From kwrobot at kitware.com Wed Feb 1 00:01:09 2017 From: kwrobot at kitware.com (Kitware Robot) Date: Wed, 1 Feb 2017 00:01:09 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1248-g1f8da86 Message-ID: <20170201050109.62BFBFA447@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 1f8da86115b6333b803feb769341fbfa171fbcc9 (commit) from 5efb8b9a5df82fef0b6abac11f590f2a655c184e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1f8da86115b6333b803feb769341fbfa171fbcc9 commit 1f8da86115b6333b803feb769341fbfa171fbcc9 Author: Kitware Robot AuthorDate: Wed Feb 1 00:01:07 2017 -0500 Commit: Kitware Robot CommitDate: Wed Feb 1 00:01:07 2017 -0500 CMake Nightly Date Stamp diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 8621bdf..6a3dae3 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 7) -set(CMake_VERSION_PATCH 20170131) +set(CMake_VERSION_PATCH 20170201) #set(CMake_VERSION_RC 1) ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 1 08:43:08 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 1 Feb 2017 08:43:08 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2461-gad55932 Message-ID: <20170201134308.A9BCFF9F29@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via ad55932e3d6ee96a52bad0e821cdbbd9672f100f (commit) via f3619bbcd648dc35ffca11b154e01eae0106d2ff (commit) from 5eb3c083401d6cf054a6841688702c0102b4aecb (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ad55932e3d6ee96a52bad0e821cdbbd9672f100f commit ad55932e3d6ee96a52bad0e821cdbbd9672f100f Merge: 5eb3c08 f3619bb Author: Brad King AuthorDate: Wed Feb 1 08:43:07 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 1 08:43:07 2017 -0500 Merge topic 'doc-cmake-packages-typo' into next f3619bbc Help: Fix typo in _NOT_FOUND_MESSAGE example in cmake-packages(7) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f3619bbcd648dc35ffca11b154e01eae0106d2ff commit f3619bbcd648dc35ffca11b154e01eae0106d2ff Author: Brad King AuthorDate: Wed Feb 1 08:40:59 2017 -0500 Commit: Brad King CommitDate: Wed Feb 1 08:40:59 2017 -0500 Help: Fix typo in _NOT_FOUND_MESSAGE example in cmake-packages(7) Fixes: #16616 diff --git a/Help/manual/cmake-packages.7.rst b/Help/manual/cmake-packages.7.rst index c27c612..c9442bc 100644 --- a/Help/manual/cmake-packages.7.rst +++ b/Help/manual/cmake-packages.7.rst @@ -449,12 +449,12 @@ be true. This can be tested with logic in the package configuration file: foreach(_comp ${ClimbingStats_FIND_COMPONENTS}) if (NOT ";${_supported_components};" MATCHES _comp) set(ClimbingStats_FOUND False) - set(ClimbingStats_NOTFOUND_MESSAGE "Unsupported component: ${_comp}") + set(ClimbingStats_NOT_FOUND_MESSAGE "Unsupported component: ${_comp}") endif() include("${CMAKE_CURRENT_LIST_DIR}/ClimbingStats${_comp}Targets.cmake") endforeach() -Here, the ``ClimbingStats_NOTFOUND_MESSAGE`` is set to a diagnosis that the package +Here, the ``ClimbingStats_NOT_FOUND_MESSAGE`` is set to a diagnosis that the package could not be found because an invalid component was specified. This message variable can be set for any case where the ``_FOUND`` variable is set to ``False``, and will be displayed to the user. ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-packages.7.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 1 08:47:37 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 1 Feb 2017 08:47:37 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2463-g915c71e Message-ID: <20170201134737.D0491FA0C3@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 915c71e3a05dc7f33ba662a9c116b090befa140b (commit) via 4136fd001052643765347c91c2ef70d146973150 (commit) from ad55932e3d6ee96a52bad0e821cdbbd9672f100f (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=915c71e3a05dc7f33ba662a9c116b090befa140b commit 915c71e3a05dc7f33ba662a9c116b090befa140b Merge: ad55932 4136fd0 Author: Brad King AuthorDate: Wed Feb 1 08:47:37 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 1 08:47:37 2017 -0500 Merge topic 'FortranCInterface-vs-intel-workaround' into next 4136fd00 fixup! FortranCInterface: Fix support for VS with Intel toolset https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4136fd001052643765347c91c2ef70d146973150 commit 4136fd001052643765347c91c2ef70d146973150 Author: Brad King AuthorDate: Wed Feb 1 08:45:18 2017 -0500 Commit: Brad King CommitDate: Wed Feb 1 08:45:18 2017 -0500 fixup! FortranCInterface: Fix support for VS with Intel toolset diff --git a/Modules/FortranCInterface.cmake b/Modules/FortranCInterface.cmake index 3899a2d..893a96f 100644 --- a/Modules/FortranCInterface.cmake +++ b/Modules/FortranCInterface.cmake @@ -348,7 +348,8 @@ function(FortranCInterface_VERIFY) try_compile(FortranCInterface_VERIFY_${lang}_COMPILED ${FortranCInterface_BINARY_DIR}/Verify${lang} ${FortranCInterface_SOURCE_DIR}/Verify - VerifyFortranC + VerifyFortranC # project name + VerifyFortranC # target name CMAKE_FLAGS -DVERIFY_CXX=${verify_cxx} -DCMAKE_VERBOSE_MAKEFILE=ON "-DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS}" ----------------------------------------------------------------------- Summary of changes: Modules/FortranCInterface.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 1 08:49:32 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 1 Feb 2017 08:49:32 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2465-g9f309d0 Message-ID: <20170201134932.5F177FA2CC@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 9f309d00e86fea6ffe1deb30384d4789d5f90e45 (commit) via c9ee05d8d9b5d2ab1539d469682a4a3974282443 (commit) from 915c71e3a05dc7f33ba662a9c116b090befa140b (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9f309d00e86fea6ffe1deb30384d4789d5f90e45 commit 9f309d00e86fea6ffe1deb30384d4789d5f90e45 Merge: 915c71e c9ee05d Author: Brad King AuthorDate: Wed Feb 1 08:49:31 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 1 08:49:31 2017 -0500 Merge topic 'FortranCInterface-vs-intel-workaround' into next c9ee05d8 FortranCInterface: Fix support for VS with Intel toolset https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c9ee05d8d9b5d2ab1539d469682a4a3974282443 commit c9ee05d8d9b5d2ab1539d469682a4a3974282443 Author: Brad King AuthorDate: Tue Jan 31 11:06:20 2017 -0500 Commit: Brad King CommitDate: Wed Feb 1 08:47:42 2017 -0500 FortranCInterface: Fix support for VS with Intel toolset When using a Visual Studio generator with an Intel toolset, such as -T "Intel C++ Compiler XE 14.0" the generated FortranCInterface mangling detection project may fail to build due to `devenv` not working with the `/project ALL_BUILD` option. This seems to be a bug in `devenv` or the Intel VS integration. Work around the problem by building with `/project FortranCInterface` instead. We only need to build this executable and its dependencies within the detection test project anyway. Fixes: #16519 diff --git a/Modules/FortranCInterface.cmake b/Modules/FortranCInterface.cmake index 3899a2d..893a96f 100644 --- a/Modules/FortranCInterface.cmake +++ b/Modules/FortranCInterface.cmake @@ -348,7 +348,8 @@ function(FortranCInterface_VERIFY) try_compile(FortranCInterface_VERIFY_${lang}_COMPILED ${FortranCInterface_BINARY_DIR}/Verify${lang} ${FortranCInterface_SOURCE_DIR}/Verify - VerifyFortranC + VerifyFortranC # project name + VerifyFortranC # target name CMAKE_FLAGS -DVERIFY_CXX=${verify_cxx} -DCMAKE_VERBOSE_MAKEFILE=ON "-DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS}" diff --git a/Modules/FortranCInterface/Detect.cmake b/Modules/FortranCInterface/Detect.cmake index 9984efd..7612890 100644 --- a/Modules/FortranCInterface/Detect.cmake +++ b/Modules/FortranCInterface/Detect.cmake @@ -30,7 +30,8 @@ set(_result) try_compile(FortranCInterface_COMPILED ${FortranCInterface_BINARY_DIR} ${FortranCInterface_SOURCE_DIR} - FortranCInterface + FortranCInterface # project name + FortranCInterface # target name CMAKE_FLAGS "-DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS}" "-DCMAKE_Fortran_FLAGS:STRING=${CMAKE_Fortran_FLAGS}" ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 1 08:56:25 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 1 Feb 2017 08:56:25 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2467-g036f34c Message-ID: <20170201135625.51F61FA561@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 036f34c7387b4e4cda45e8e2a3a7dc4e5cb6712c (commit) via 5d70894d4086b1800b31d2d51f2ac3a124d7eed0 (commit) from 9f309d00e86fea6ffe1deb30384d4789d5f90e45 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=036f34c7387b4e4cda45e8e2a3a7dc4e5cb6712c commit 036f34c7387b4e4cda45e8e2a3a7dc4e5cb6712c Merge: 9f309d0 5d70894 Author: Brad King AuthorDate: Wed Feb 1 08:56:24 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 1 08:56:24 2017 -0500 Merge topic 'intel-c11-windows' into next 5d70894d Features: Update version of Intel Compiler on Windows supporting C 11 https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=5d70894d4086b1800b31d2d51f2ac3a124d7eed0 commit 5d70894d4086b1800b31d2d51f2ac3a124d7eed0 Author: Brad King AuthorDate: Tue Jan 31 08:31:41 2017 -0500 Commit: Brad King CommitDate: Wed Feb 1 08:55:50 2017 -0500 Features: Update version of Intel Compiler on Windows supporting C 11 The Intel Compiler 15.0.0 on Windows does not support `-Qstd=c11`. Bump our version requirement to 16 to use that flag. diff --git a/Modules/Compiler/Intel-C.cmake b/Modules/Compiler/Intel-C.cmake index 6408392..9c67fbd 100644 --- a/Modules/Compiler/Intel-C.cmake +++ b/Modules/Compiler/Intel-C.cmake @@ -10,14 +10,17 @@ set(CMAKE_DEPFILE_FLAGS_C "-MD -MT -MF ") if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC") set(_std -Qstd) set(_ext c) + if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 16.0.0) + set(CMAKE_C11_STANDARD_COMPILE_OPTION "-Qstd=c11") + set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-Qstd=c11") + endif() else() set(_std -std) set(_ext gnu) -endif() - -if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 15.0.0) - set(CMAKE_C11_STANDARD_COMPILE_OPTION "${_std}=c11") - set(CMAKE_C11_EXTENSION_COMPILE_OPTION "${_std}=${_ext}11") + if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 15.0.0) + set(CMAKE_C11_STANDARD_COMPILE_OPTION "-std=c11") + set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu11") + endif() endif() if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 12.0) ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 1 09:10:09 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 1 Feb 2017 09:10:09 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2470-gda2c5c1 Message-ID: <20170201141009.85ECEEF978@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via da2c5c14ece09801e66a27d91021f1851adc2247 (commit) via 9f3e812fac4ba22a493a92f50b87a949d21e62c9 (commit) via 1f8da86115b6333b803feb769341fbfa171fbcc9 (commit) from 036f34c7387b4e4cda45e8e2a3a7dc4e5cb6712c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=da2c5c14ece09801e66a27d91021f1851adc2247 commit da2c5c14ece09801e66a27d91021f1851adc2247 Merge: 036f34c 9f3e812 Author: Brad King AuthorDate: Wed Feb 1 09:10:09 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 1 09:10:09 2017 -0500 Merge topic 'doc-cmake-developer-purpose' into next 9f3e812f Help: Extend documented purpose of cmake-developer(7) manual 1f8da861 CMake Nightly Date Stamp https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9f3e812fac4ba22a493a92f50b87a949d21e62c9 commit 9f3e812fac4ba22a493a92f50b87a949d21e62c9 Author: Brad King AuthorDate: Wed Feb 1 09:09:37 2017 -0500 Commit: Brad King CommitDate: Wed Feb 1 09:09:51 2017 -0500 Help: Extend documented purpose of cmake-developer(7) manual Issue: #16616 diff --git a/Help/manual/cmake-developer.7.rst b/Help/manual/cmake-developer.7.rst index 6557686..46b922b 100644 --- a/Help/manual/cmake-developer.7.rst +++ b/Help/manual/cmake-developer.7.rst @@ -11,7 +11,7 @@ Introduction ============ This manual is intended for reference by developers modifying the CMake -source tree itself. +source tree itself, and by those authoring externally-maintained modules. Permitted C++ Subset ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-developer.7.rst | 2 +- Source/CMakeVersion.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 1 09:16:16 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 1 Feb 2017 09:16:16 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1251-gd6113e9 Message-ID: <20170201141616.BED0DF9CF1@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via d6113e958a501af2f5c88f343fb8507710b638e5 (commit) via 3288ab0c78057e2388b247d326dc80011488a0bb (commit) via 773df0e2d7596d84a711914f1cffb4fb5a107c17 (commit) from 1f8da86115b6333b803feb769341fbfa171fbcc9 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d6113e958a501af2f5c88f343fb8507710b638e5 commit d6113e958a501af2f5c88f343fb8507710b638e5 Merge: 1f8da86 3288ab0 Author: Brad King AuthorDate: Wed Feb 1 09:16:14 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 1 09:16:14 2017 -0500 Merge topic 'developer-setup' 3288ab0c Convert local hook configuration to a Git config file format 773df0e2 Add pre-commit hook to check whether SetupForDevelopment must re-run ----------------------------------------------------------------------- Summary of changes: .hooks-config.bash => .hooks-config | 7 ++++--- Utilities/Git/pre-commit | 13 +++++++++++++ Utilities/SetupForDevelopment.sh | 4 ++++ 3 files changed, 21 insertions(+), 3 deletions(-) rename .hooks-config.bash => .hooks-config (61%) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 1 09:16:19 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 1 Feb 2017 09:16:19 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1253-g048ecde Message-ID: <20170201141619.9A5CCF9E47@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 048ecde45332995198770157c4e0a34684be03d0 (commit) via 9f3e812fac4ba22a493a92f50b87a949d21e62c9 (commit) from d6113e958a501af2f5c88f343fb8507710b638e5 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=048ecde45332995198770157c4e0a34684be03d0 commit 048ecde45332995198770157c4e0a34684be03d0 Merge: d6113e9 9f3e812 Author: Brad King AuthorDate: Wed Feb 1 09:16:17 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 1 09:16:17 2017 -0500 Merge topic 'doc-cmake-developer-purpose' 9f3e812f Help: Extend documented purpose of cmake-developer(7) manual ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-developer.7.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 1 09:16:21 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 1 Feb 2017 09:16:21 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1255-gd88ab13 Message-ID: <20170201141621.E807AF9E65@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via d88ab13750860e0f7f71e10fe21a15194214d07e (commit) via f3619bbcd648dc35ffca11b154e01eae0106d2ff (commit) from 048ecde45332995198770157c4e0a34684be03d0 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d88ab13750860e0f7f71e10fe21a15194214d07e commit d88ab13750860e0f7f71e10fe21a15194214d07e Merge: 048ecde f3619bb Author: Brad King AuthorDate: Wed Feb 1 09:16:20 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 1 09:16:20 2017 -0500 Merge topic 'doc-cmake-packages-typo' f3619bbc Help: Fix typo in _NOT_FOUND_MESSAGE example in cmake-packages(7) ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-packages.7.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 1 09:16:24 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 1 Feb 2017 09:16:24 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1257-g2dfe480 Message-ID: <20170201141624.68FB5F9F22@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 2dfe480a9c3fe40699ad85aa0355111848df870b (commit) via 5d70894d4086b1800b31d2d51f2ac3a124d7eed0 (commit) from d88ab13750860e0f7f71e10fe21a15194214d07e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=2dfe480a9c3fe40699ad85aa0355111848df870b commit 2dfe480a9c3fe40699ad85aa0355111848df870b Merge: d88ab13 5d70894 Author: Brad King AuthorDate: Wed Feb 1 09:16:22 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 1 09:16:22 2017 -0500 Merge topic 'intel-c11-windows' 5d70894d Features: Update version of Intel Compiler on Windows supporting C 11 ----------------------------------------------------------------------- Summary of changes: Modules/Compiler/Intel-C.cmake | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 1 09:16:26 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 1 Feb 2017 09:16:26 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1259-ge8f55c1 Message-ID: <20170201141626.B031EF9EAD@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via e8f55c17371ced4c6d5eb19cf40cf1141c0ef62a (commit) via c9ee05d8d9b5d2ab1539d469682a4a3974282443 (commit) from 2dfe480a9c3fe40699ad85aa0355111848df870b (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e8f55c17371ced4c6d5eb19cf40cf1141c0ef62a commit e8f55c17371ced4c6d5eb19cf40cf1141c0ef62a Merge: 2dfe480 c9ee05d Author: Brad King AuthorDate: Wed Feb 1 09:16:25 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 1 09:16:25 2017 -0500 Merge topic 'FortranCInterface-vs-intel-workaround' c9ee05d8 FortranCInterface: Fix support for VS with Intel toolset ----------------------------------------------------------------------- Summary of changes: Modules/FortranCInterface.cmake | 3 ++- Modules/FortranCInterface/Detect.cmake | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 1 09:21:46 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 1 Feb 2017 09:21:46 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1264-g6f2e2c7 Message-ID: <20170201142146.7E268FA000@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 6f2e2c74ba7f9061be8a8831195f02db5604160a (commit) via 1679fecb74ee4eb4500d591796f93fe4271b688e (commit) via 98e6d1e5e426c491e04faa746c11746002e6a69d (commit) via c8703e9d7b6c3f7ad58429317a6bf75c1e415568 (commit) via 0de9c3985004ef802aac97e20b4efde49989794c (commit) from e8f55c17371ced4c6d5eb19cf40cf1141c0ef62a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6f2e2c74ba7f9061be8a8831195f02db5604160a commit 6f2e2c74ba7f9061be8a8831195f02db5604160a Merge: e8f55c1 1679fec Author: Brad King AuthorDate: Wed Feb 1 09:21:44 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 1 09:21:44 2017 -0500 Merge topic 'WCDH_allow_unsupported' 1679fecb CompileFeatures Test: make sure the target "CompileFeatures" is always defined 98e6d1e5 Tests/Module/WCDH: make it work with only C features defined c8703e9d WCDH: optionally omit error code for unknown compilers or compiler versions 0de9c398 WCDH: add macro to write simple replacement defines ----------------------------------------------------------------------- Summary of changes: Help/release/dev/WCDH_allow_unsupported.rst | 8 ++ Modules/WriteCompilerDetectionHeader.cmake | 122 +++++++------------ Tests/CompileFeatures/CMakeLists.txt | 18 ++- .../WriteCompilerDetectionHeader/CMakeLists.txt | 128 ++++++++++++-------- 4 files changed, 137 insertions(+), 139 deletions(-) create mode 100644 Help/release/dev/WCDH_allow_unsupported.rst hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 1 09:22:05 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 1 Feb 2017 09:22:05 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2477-ga5c058a Message-ID: <20170201142205.46AF5FA005@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via a5c058ad83c469822d38f3ad5960d9cd4c2d370a (commit) via 6f2e2c74ba7f9061be8a8831195f02db5604160a (commit) via e8f55c17371ced4c6d5eb19cf40cf1141c0ef62a (commit) via 2dfe480a9c3fe40699ad85aa0355111848df870b (commit) via d88ab13750860e0f7f71e10fe21a15194214d07e (commit) via 048ecde45332995198770157c4e0a34684be03d0 (commit) via d6113e958a501af2f5c88f343fb8507710b638e5 (commit) from da2c5c14ece09801e66a27d91021f1851adc2247 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a5c058ad83c469822d38f3ad5960d9cd4c2d370a commit a5c058ad83c469822d38f3ad5960d9cd4c2d370a Merge: da2c5c1 6f2e2c7 Author: Brad King AuthorDate: Wed Feb 1 09:21:56 2017 -0500 Commit: Brad King CommitDate: Wed Feb 1 09:21:56 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 1 09:25:31 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 1 Feb 2017 09:25:31 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2479-g18e576c Message-ID: <20170201142531.3AE5EFA2F9@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 18e576c1d797645817d1e132b62f057c2328ed1c (commit) via 79f7ba3fbe67b520d7d564c7944f49c798f8c85a (commit) from a5c058ad83c469822d38f3ad5960d9cd4c2d370a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=18e576c1d797645817d1e132b62f057c2328ed1c commit 18e576c1d797645817d1e132b62f057c2328ed1c Merge: a5c058a 79f7ba3 Author: Brad King AuthorDate: Wed Feb 1 09:25:30 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 1 09:25:30 2017 -0500 Merge topic 'gcc-features' into next 79f7ba3f Revert topic 'gcc-features' https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=79f7ba3fbe67b520d7d564c7944f49c798f8c85a commit 79f7ba3fbe67b520d7d564c7944f49c798f8c85a Author: Brad King AuthorDate: Wed Feb 1 09:25:06 2017 -0500 Commit: Brad King CommitDate: Wed Feb 1 09:25:06 2017 -0500 Revert topic 'gcc-features' It will be rebased/revised/restored. diff --git a/Modules/Compiler/GNU-C-FeatureTests.cmake b/Modules/Compiler/GNU-C-FeatureTests.cmake index 0ab5265..b3fe33f 100644 --- a/Modules/Compiler/GNU-C-FeatureTests.cmake +++ b/Modules/Compiler/GNU-C-FeatureTests.cmake @@ -1,5 +1,5 @@ -set(_cmake_oldestSupported "(__GNUC__ * 100 + __GNUC_MINOR__) >= 304") +set(_cmake_oldestSupported "(__GNUC__ * 100 + __GNUC_MINOR__) >= 404") # GNU 4.7 correctly sets __STDC_VERSION__ to 201112L, but GNU 4.6 sets it # to 201000L. As the former is strictly greater than the latter, test only @@ -8,10 +8,10 @@ set(_cmake_oldestSupported "(__GNUC__ * 100 + __GNUC_MINOR__) >= 304") # to the distinction between __cplusplus and __GXX_EXPERIMENTAL_CXX0X__ tests. set(GNU46_C11 "(__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201000L") set(_cmake_feature_test_c_static_assert "${GNU46_C11}") -# Since 3.4 at least: -set(GNU34_C99 "(__GNUC__ * 100 + __GNUC_MINOR__) >= 304 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L") -set(_cmake_feature_test_c_restrict "${GNU34_C99}") -set(_cmake_feature_test_c_variadic_macros "${GNU34_C99}") +# Since 4.4 at least: +set(GNU44_C99 "(__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L") +set(_cmake_feature_test_c_restrict "${GNU44_C99}") +set(_cmake_feature_test_c_variadic_macros "${GNU44_C99}") set(GNU_C90 "${_cmake_oldestSupported}") set(_cmake_feature_test_c_function_prototypes "${GNU_C90}") diff --git a/Modules/Compiler/GNU-C.cmake b/Modules/Compiler/GNU-C.cmake index 3f02618..05c3bb2 100644 --- a/Modules/Compiler/GNU-C.cmake +++ b/Modules/Compiler/GNU-C.cmake @@ -4,12 +4,12 @@ __compiler_gnu(C) if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.5) set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c90") set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu90") -elseif (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4) +elseif (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4) set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c89") set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu89") endif() -if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4) +if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4) set(CMAKE_C99_STANDARD_COMPILE_OPTION "-std=c99") set(CMAKE_C99_EXTENSION_COMPILE_OPTION "-std=gnu99") endif() @@ -22,7 +22,7 @@ elseif (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.6) set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu1x") endif() -if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4) +if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4) if (NOT CMAKE_C_COMPILER_FORCED) if (NOT CMAKE_C_STANDARD_COMPUTED_DEFAULT) message(FATAL_ERROR "CMAKE_C_STANDARD_COMPUTED_DEFAULT should be set for ${CMAKE_C_COMPILER_ID} (${CMAKE_C_COMPILER}) version ${CMAKE_C_COMPILER_VERSION}") @@ -38,9 +38,10 @@ if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4) endif() endif() + macro(cmake_record_c_compile_features) set(_result 0) - if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4) + if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4) if(_result EQUAL 0 AND CMAKE_C11_STANDARD_COMPILE_OPTION) _record_compiler_features_c(11) endif() diff --git a/Modules/Compiler/GNU-CXX.cmake b/Modules/Compiler/GNU-CXX.cmake index c007c98..b04ea11 100644 --- a/Modules/Compiler/GNU-CXX.cmake +++ b/Modules/Compiler/GNU-CXX.cmake @@ -6,7 +6,7 @@ if (WIN32) set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fno-keep-inline-dllexport") endif() else() - if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.0) + if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.2) set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden") endif() endif() ----------------------------------------------------------------------- Summary of changes: Modules/Compiler/GNU-C-FeatureTests.cmake | 10 +++++----- Modules/Compiler/GNU-C.cmake | 9 +++++---- Modules/Compiler/GNU-CXX.cmake | 2 +- 3 files changed, 11 insertions(+), 10 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 1 13:37:03 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 1 Feb 2017 13:37:03 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1267-g2d357ea Message-ID: <20170201183703.D1347FA4C4@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 2d357ea267a5ab0f54f7b411befbadc583dd41d7 (commit) via 8cdf96d0af0f72292daa76b9a7fc7928934efbe2 (commit) via 2b1cdd85b8943059e5f2b27735df261743749342 (commit) from 6f2e2c74ba7f9061be8a8831195f02db5604160a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 1 13:37:03 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 1 Feb 2017 13:37:03 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2483-gc43228b Message-ID: <20170201183703.ECB0FFA4C5@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via c43228b1fe914035a93ceff23b91017122b5f1bc (commit) via 2d357ea267a5ab0f54f7b411befbadc583dd41d7 (commit) via 8cdf96d0af0f72292daa76b9a7fc7928934efbe2 (commit) via 2b1cdd85b8943059e5f2b27735df261743749342 (commit) from 18e576c1d797645817d1e132b62f057c2328ed1c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c43228b1fe914035a93ceff23b91017122b5f1bc commit c43228b1fe914035a93ceff23b91017122b5f1bc Merge: 18e576c 2d357ea Author: Brad King AuthorDate: Wed Feb 1 13:36:48 2017 -0500 Commit: Brad King CommitDate: Wed Feb 1 13:36:48 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 1 13:48:35 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 1 Feb 2017 13:48:35 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2485-gbef58c6 Message-ID: <20170201184835.4B687FA45C@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via bef58c63926fdb86c63525bed0ea57ed40d9e529 (commit) via 88c4576be412c85c112976dcec51b3fb7905b618 (commit) from c43228b1fe914035a93ceff23b91017122b5f1bc (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=bef58c63926fdb86c63525bed0ea57ed40d9e529 commit bef58c63926fdb86c63525bed0ea57ed40d9e529 Merge: c43228b 88c4576 Author: Brad King AuthorDate: Wed Feb 1 13:48:34 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 1 13:48:34 2017 -0500 Merge topic 'FindGSL-regex-fixup' into next 88c4576b FindGSL: Fix gl_version.h extraction regex https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=88c4576be412c85c112976dcec51b3fb7905b618 commit 88c4576be412c85c112976dcec51b3fb7905b618 Author: Igor Peschinskiy AuthorDate: Wed Feb 1 12:54:17 2017 +0300 Commit: Brad King CommitDate: Wed Feb 1 13:47:37 2017 -0500 FindGSL: Fix gl_version.h extraction regex Fix the regex to match versions with only two digits, such as `2.3`. diff --git a/Modules/FindGSL.cmake b/Modules/FindGSL.cmake index 446c3a8..76059b3 100644 --- a/Modules/FindGSL.cmake +++ b/Modules/FindGSL.cmake @@ -135,7 +135,7 @@ if( NOT GSL_VERSION ) # 2. If gsl-config is not available, try looking in gsl/gsl_version.h if( NOT GSL_VERSION AND EXISTS "${GSL_INCLUDE_DIRS}/gsl/gsl_version.h" ) file( STRINGS "${GSL_INCLUDE_DIRS}/gsl/gsl_version.h" gsl_version_h_contents REGEX "define GSL_VERSION" ) - string( REGEX REPLACE ".*([0-9].[0-9][0-9]).*" "\\1" GSL_VERSION ${gsl_version_h_contents} ) + string( REGEX REPLACE ".*([0-9]\\.[0-9][0-9]?).*" "\\1" GSL_VERSION ${gsl_version_h_contents} ) endif() # might also try scraping the directory name for a regex match "gsl-X.X" ----------------------------------------------------------------------- Summary of changes: Modules/FindGSL.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From eike at sf-mail.de Wed Feb 1 14:56:49 2017 From: eike at sf-mail.de (Rolf Eike Beer) Date: Wed, 1 Feb 2017 14:56:49 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2489-ge7bbf8c Message-ID: <20170201195649.164F5FA4E1@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via e7bbf8c3ce1362f30602b73e57feb36af14b46ac (commit) via f4de2ab585caf8a9c6773fa4507008b83a1ca2cf (commit) via 771e9f2fe79ec1a1bdf8189f88e48704e97b827e (commit) via c381c193a1ceeb79cf84ab905a0076c783b32707 (commit) from bef58c63926fdb86c63525bed0ea57ed40d9e529 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e7bbf8c3ce1362f30602b73e57feb36af14b46ac commit e7bbf8c3ce1362f30602b73e57feb36af14b46ac Merge: bef58c6 f4de2ab Author: Rolf Eike Beer AuthorDate: Wed Feb 1 14:56:48 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 1 14:56:48 2017 -0500 Merge topic 'gcc-features' into next f4de2ab5 GNU C++: record that -fvisibility-inlines-hidden is available since 4.0 771e9f2f GNU C: record that C99 is available since at least 3.4 c381c193 Tests/Module/WCDH: write multi_file_compiler_detection.h before using it https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f4de2ab585caf8a9c6773fa4507008b83a1ca2cf commit f4de2ab585caf8a9c6773fa4507008b83a1ca2cf Author: Rolf Eike Beer AuthorDate: Fri Jan 27 16:52:42 2017 +0100 Commit: Rolf Eike Beer CommitDate: Wed Feb 1 20:53:00 2017 +0100 GNU C++: record that -fvisibility-inlines-hidden is available since 4.0 See https://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Option-Summary.html diff --git a/Modules/Compiler/GNU-CXX.cmake b/Modules/Compiler/GNU-CXX.cmake index b04ea11..c007c98 100644 --- a/Modules/Compiler/GNU-CXX.cmake +++ b/Modules/Compiler/GNU-CXX.cmake @@ -6,7 +6,7 @@ if (WIN32) set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fno-keep-inline-dllexport") endif() else() - if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.2) + if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.0) set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden") endif() endif() https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=771e9f2fe79ec1a1bdf8189f88e48704e97b827e commit 771e9f2fe79ec1a1bdf8189f88e48704e97b827e Author: Rolf Eike Beer AuthorDate: Fri Jan 27 16:49:45 2017 +0100 Commit: Rolf Eike Beer CommitDate: Wed Feb 1 20:53:00 2017 +0100 GNU C: record that C99 is available since at least 3.4 diff --git a/Help/release/dev/gcc-features.rst b/Help/release/dev/gcc-features.rst new file mode 100644 index 0000000..c6959ab --- /dev/null +++ b/Help/release/dev/gcc-features.rst @@ -0,0 +1,5 @@ +gcc-features +------------ + +* The :manual:`Compile Features ` functionality + is now aware of the availability of C99 in gcc since version 3.4. diff --git a/Modules/Compiler/GNU-C-FeatureTests.cmake b/Modules/Compiler/GNU-C-FeatureTests.cmake index b3fe33f..0ab5265 100644 --- a/Modules/Compiler/GNU-C-FeatureTests.cmake +++ b/Modules/Compiler/GNU-C-FeatureTests.cmake @@ -1,5 +1,5 @@ -set(_cmake_oldestSupported "(__GNUC__ * 100 + __GNUC_MINOR__) >= 404") +set(_cmake_oldestSupported "(__GNUC__ * 100 + __GNUC_MINOR__) >= 304") # GNU 4.7 correctly sets __STDC_VERSION__ to 201112L, but GNU 4.6 sets it # to 201000L. As the former is strictly greater than the latter, test only @@ -8,10 +8,10 @@ set(_cmake_oldestSupported "(__GNUC__ * 100 + __GNUC_MINOR__) >= 404") # to the distinction between __cplusplus and __GXX_EXPERIMENTAL_CXX0X__ tests. set(GNU46_C11 "(__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201000L") set(_cmake_feature_test_c_static_assert "${GNU46_C11}") -# Since 4.4 at least: -set(GNU44_C99 "(__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L") -set(_cmake_feature_test_c_restrict "${GNU44_C99}") -set(_cmake_feature_test_c_variadic_macros "${GNU44_C99}") +# Since 3.4 at least: +set(GNU34_C99 "(__GNUC__ * 100 + __GNUC_MINOR__) >= 304 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L") +set(_cmake_feature_test_c_restrict "${GNU34_C99}") +set(_cmake_feature_test_c_variadic_macros "${GNU34_C99}") set(GNU_C90 "${_cmake_oldestSupported}") set(_cmake_feature_test_c_function_prototypes "${GNU_C90}") diff --git a/Modules/Compiler/GNU-C.cmake b/Modules/Compiler/GNU-C.cmake index 05c3bb2..3f02618 100644 --- a/Modules/Compiler/GNU-C.cmake +++ b/Modules/Compiler/GNU-C.cmake @@ -4,12 +4,12 @@ __compiler_gnu(C) if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.5) set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c90") set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu90") -elseif (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4) +elseif (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4) set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c89") set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu89") endif() -if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4) +if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4) set(CMAKE_C99_STANDARD_COMPILE_OPTION "-std=c99") set(CMAKE_C99_EXTENSION_COMPILE_OPTION "-std=gnu99") endif() @@ -22,7 +22,7 @@ elseif (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.6) set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu1x") endif() -if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4) +if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4) if (NOT CMAKE_C_COMPILER_FORCED) if (NOT CMAKE_C_STANDARD_COMPUTED_DEFAULT) message(FATAL_ERROR "CMAKE_C_STANDARD_COMPUTED_DEFAULT should be set for ${CMAKE_C_COMPILER_ID} (${CMAKE_C_COMPILER}) version ${CMAKE_C_COMPILER_VERSION}") @@ -38,10 +38,9 @@ if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4) endif() endif() - macro(cmake_record_c_compile_features) set(_result 0) - if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4) + if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4) if(_result EQUAL 0 AND CMAKE_C11_STANDARD_COMPILE_OPTION) _record_compiler_features_c(11) endif() https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c381c193a1ceeb79cf84ab905a0076c783b32707 commit c381c193a1ceeb79cf84ab905a0076c783b32707 Author: Rolf Eike Beer AuthorDate: Wed Feb 1 20:48:25 2017 +0100 Commit: Rolf Eike Beer CommitDate: Wed Feb 1 20:52:59 2017 +0100 Tests/Module/WCDH: write multi_file_compiler_detection.h before using it This was broken in commit 98e6d1e5e426c491e04faa746c11746002e6a69d (Tests/Module/WCDH: make it work with only C features defined) when all C tests were made accessible even if no C++ features are available, but the header was only created if C++ features are available. Fix it by creating the header unconditionally before any checks on the available features. diff --git a/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt b/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt index 7957ab8..a8406dd 100644 --- a/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt +++ b/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt @@ -20,6 +20,17 @@ write_compiler_detection_header( ${cxx_known_features} ${c_known_features} ) +write_compiler_detection_header( + FILE "${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files/multi_file_compiler_detection.h" + PREFIX MULTI + OUTPUT_FILES_VAR multi_files + OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files/compiler_support" + COMPILERS GNU Clang AppleClang MSVC SunPro Intel + VERSION 3.1 + FEATURES + ${cxx_known_features} ${c_known_features} +) + macro(set_defines target true_defs false_defs) set(defines) foreach(def ${true_defs}) @@ -116,17 +127,6 @@ add_executable(WriteCompilerDetectionHeader main.cpp) set_property(TARGET WriteCompilerDetectionHeader PROPERTY CXX_STANDARD 98) set_defines(WriteCompilerDetectionHeader "${true_defs}" "${false_defs}") -write_compiler_detection_header( - FILE "${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files/multi_file_compiler_detection.h" - PREFIX MULTI - OUTPUT_FILES_VAR multi_files - OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files/compiler_support" - COMPILERS GNU Clang AppleClang MSVC SunPro Intel - VERSION 3.1 - FEATURES - ${cxx_known_features} ${c_known_features} -) - add_executable(multi_files multi_files.cpp) set_property(TARGET multi_files PROPERTY CXX_STANDARD 98) target_include_directories(multi_files PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files) ----------------------------------------------------------------------- Summary of changes: Help/release/dev/gcc-features.rst | 5 +++++ Modules/Compiler/GNU-C-FeatureTests.cmake | 10 ++++----- Modules/Compiler/GNU-C.cmake | 9 ++++---- Modules/Compiler/GNU-CXX.cmake | 2 +- .../WriteCompilerDetectionHeader/CMakeLists.txt | 22 ++++++++++---------- 5 files changed, 26 insertions(+), 22 deletions(-) create mode 100644 Help/release/dev/gcc-features.rst hooks/post-receive -- CMake From eike at sf-mail.de Wed Feb 1 15:28:08 2017 From: eike at sf-mail.de (Rolf Eike Beer) Date: Wed, 1 Feb 2017 15:28:08 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2492-g45ffe4d Message-ID: <20170201202808.B75FCFA09F@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 45ffe4d2d2f45f04f9e5e5800cb374a2fc9fa18c (commit) via 42820eaedad8c6dddcf84e7a57ea102a6ca72bd4 (commit) via da1abae81303233cb78f0590f92aef75e82275f9 (commit) from e7bbf8c3ce1362f30602b73e57feb36af14b46ac (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=45ffe4d2d2f45f04f9e5e5800cb374a2fc9fa18c commit 45ffe4d2d2f45f04f9e5e5800cb374a2fc9fa18c Merge: e7bbf8c 42820ea Author: Rolf Eike Beer AuthorDate: Wed Feb 1 15:28:07 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 1 15:28:07 2017 -0500 Merge topic 'gcc-features' into next 42820eae GNU C++: record that -fvisibility-inlines-hidden is available since 4.0 da1abae8 GNU C: record that C99 is available since at least 3.4 https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=42820eaedad8c6dddcf84e7a57ea102a6ca72bd4 commit 42820eaedad8c6dddcf84e7a57ea102a6ca72bd4 Author: Rolf Eike Beer AuthorDate: Fri Jan 27 16:52:42 2017 +0100 Commit: Rolf Eike Beer CommitDate: Wed Feb 1 21:27:37 2017 +0100 GNU C++: record that -fvisibility-inlines-hidden is available since 4.0 See https://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Option-Summary.html diff --git a/Modules/Compiler/GNU-CXX.cmake b/Modules/Compiler/GNU-CXX.cmake index b04ea11..c007c98 100644 --- a/Modules/Compiler/GNU-CXX.cmake +++ b/Modules/Compiler/GNU-CXX.cmake @@ -6,7 +6,7 @@ if (WIN32) set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fno-keep-inline-dllexport") endif() else() - if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.2) + if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.0) set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden") endif() endif() https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=da1abae81303233cb78f0590f92aef75e82275f9 commit da1abae81303233cb78f0590f92aef75e82275f9 Author: Rolf Eike Beer AuthorDate: Fri Jan 27 16:49:45 2017 +0100 Commit: Rolf Eike Beer CommitDate: Wed Feb 1 21:27:37 2017 +0100 GNU C: record that C99 is available since at least 3.4 diff --git a/Help/manual/cmake-compile-features.7.rst b/Help/manual/cmake-compile-features.7.rst index d641856..078b20b 100644 --- a/Help/manual/cmake-compile-features.7.rst +++ b/Help/manual/cmake-compile-features.7.rst @@ -338,6 +338,14 @@ versions specified for each: * ``SunPro``: Oracle SolarisStudio version 12.4. * ``Intel``: Intel compiler versions 12.1 through 17.0. +CMake is currently aware of the :prop_tgt:`language standards ` +and :prop_gbl:`compile features ` available from +the following :variable:`compiler ids _COMPILER_ID>` as of the +versions specified for each: + +* all compilers and versions listed above for C++ +* ``GNU``: GNU compiler versions 3.4 through 5.0. + CMake is currently aware of the :prop_tgt:`language standards ` from the following :variable:`compiler ids _COMPILER_ID>` as of the versions specified for each: diff --git a/Help/release/dev/gcc-features.rst b/Help/release/dev/gcc-features.rst new file mode 100644 index 0000000..c6959ab --- /dev/null +++ b/Help/release/dev/gcc-features.rst @@ -0,0 +1,5 @@ +gcc-features +------------ + +* The :manual:`Compile Features ` functionality + is now aware of the availability of C99 in gcc since version 3.4. diff --git a/Modules/Compiler/GNU-C-FeatureTests.cmake b/Modules/Compiler/GNU-C-FeatureTests.cmake index b3fe33f..0ab5265 100644 --- a/Modules/Compiler/GNU-C-FeatureTests.cmake +++ b/Modules/Compiler/GNU-C-FeatureTests.cmake @@ -1,5 +1,5 @@ -set(_cmake_oldestSupported "(__GNUC__ * 100 + __GNUC_MINOR__) >= 404") +set(_cmake_oldestSupported "(__GNUC__ * 100 + __GNUC_MINOR__) >= 304") # GNU 4.7 correctly sets __STDC_VERSION__ to 201112L, but GNU 4.6 sets it # to 201000L. As the former is strictly greater than the latter, test only @@ -8,10 +8,10 @@ set(_cmake_oldestSupported "(__GNUC__ * 100 + __GNUC_MINOR__) >= 404") # to the distinction between __cplusplus and __GXX_EXPERIMENTAL_CXX0X__ tests. set(GNU46_C11 "(__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201000L") set(_cmake_feature_test_c_static_assert "${GNU46_C11}") -# Since 4.4 at least: -set(GNU44_C99 "(__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L") -set(_cmake_feature_test_c_restrict "${GNU44_C99}") -set(_cmake_feature_test_c_variadic_macros "${GNU44_C99}") +# Since 3.4 at least: +set(GNU34_C99 "(__GNUC__ * 100 + __GNUC_MINOR__) >= 304 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L") +set(_cmake_feature_test_c_restrict "${GNU34_C99}") +set(_cmake_feature_test_c_variadic_macros "${GNU34_C99}") set(GNU_C90 "${_cmake_oldestSupported}") set(_cmake_feature_test_c_function_prototypes "${GNU_C90}") diff --git a/Modules/Compiler/GNU-C.cmake b/Modules/Compiler/GNU-C.cmake index 05c3bb2..3f02618 100644 --- a/Modules/Compiler/GNU-C.cmake +++ b/Modules/Compiler/GNU-C.cmake @@ -4,12 +4,12 @@ __compiler_gnu(C) if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.5) set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c90") set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu90") -elseif (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4) +elseif (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4) set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c89") set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu89") endif() -if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4) +if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4) set(CMAKE_C99_STANDARD_COMPILE_OPTION "-std=c99") set(CMAKE_C99_EXTENSION_COMPILE_OPTION "-std=gnu99") endif() @@ -22,7 +22,7 @@ elseif (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.6) set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu1x") endif() -if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4) +if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4) if (NOT CMAKE_C_COMPILER_FORCED) if (NOT CMAKE_C_STANDARD_COMPUTED_DEFAULT) message(FATAL_ERROR "CMAKE_C_STANDARD_COMPUTED_DEFAULT should be set for ${CMAKE_C_COMPILER_ID} (${CMAKE_C_COMPILER}) version ${CMAKE_C_COMPILER_VERSION}") @@ -38,10 +38,9 @@ if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4) endif() endif() - macro(cmake_record_c_compile_features) set(_result 0) - if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4) + if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4) if(_result EQUAL 0 AND CMAKE_C11_STANDARD_COMPILE_OPTION) _record_compiler_features_c(11) endif() ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-compile-features.7.rst | 8 ++++++++ 1 file changed, 8 insertions(+) hooks/post-receive -- CMake From kwrobot at kitware.com Thu Feb 2 00:01:07 2017 From: kwrobot at kitware.com (Kitware Robot) Date: Thu, 2 Feb 2017 00:01:07 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1268-g134ffe9 Message-ID: <20170202050107.E739DFA562@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 134ffe97949125c47292797da6080e1e965ff9a8 (commit) from 2d357ea267a5ab0f54f7b411befbadc583dd41d7 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=134ffe97949125c47292797da6080e1e965ff9a8 commit 134ffe97949125c47292797da6080e1e965ff9a8 Author: Kitware Robot AuthorDate: Thu Feb 2 00:01:05 2017 -0500 Commit: Kitware Robot CommitDate: Thu Feb 2 00:01:05 2017 -0500 CMake Nightly Date Stamp diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 6a3dae3..021b939 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 7) -set(CMake_VERSION_PATCH 20170201) +set(CMake_VERSION_PATCH 20170202) #set(CMake_VERSION_RC 1) ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 2 08:39:39 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 2 Feb 2017 08:39:39 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1270-gaba66d2 Message-ID: <20170202133940.AF191A91@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via aba66d27a1d4b5364274784fce27a3c52ee2140b (commit) via 88c4576be412c85c112976dcec51b3fb7905b618 (commit) from 134ffe97949125c47292797da6080e1e965ff9a8 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=aba66d27a1d4b5364274784fce27a3c52ee2140b commit aba66d27a1d4b5364274784fce27a3c52ee2140b Merge: 134ffe9 88c4576 Author: Brad King AuthorDate: Thu Feb 2 08:39:32 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 2 08:39:32 2017 -0500 Merge topic 'FindGSL-regex-fixup' 88c4576b FindGSL: Fix gl_version.h extraction regex ----------------------------------------------------------------------- Summary of changes: Modules/FindGSL.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 2 08:40:03 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 2 Feb 2017 08:40:03 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2495-g70f45f9 Message-ID: <20170202134003.D558BC2169@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 70f45f9b647663c15df652c1d3063a53f3667a34 (commit) via aba66d27a1d4b5364274784fce27a3c52ee2140b (commit) via 134ffe97949125c47292797da6080e1e965ff9a8 (commit) from 45ffe4d2d2f45f04f9e5e5800cb374a2fc9fa18c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=70f45f9b647663c15df652c1d3063a53f3667a34 commit 70f45f9b647663c15df652c1d3063a53f3667a34 Merge: 45ffe4d aba66d2 Author: Brad King AuthorDate: Thu Feb 2 08:39:54 2017 -0500 Commit: Brad King CommitDate: Thu Feb 2 08:39:54 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 2 08:46:11 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 2 Feb 2017 08:46:11 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2497-gadb33f1 Message-ID: <20170202134611.A7F4EFA0AB@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via adb33f13eb844bb4412e76a113438727bc4ccd81 (commit) via 03d7ead1246818cd076d4d45bb5e970baf781bc9 (commit) from 70f45f9b647663c15df652c1d3063a53f3667a34 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=adb33f13eb844bb4412e76a113438727bc4ccd81 commit adb33f13eb844bb4412e76a113438727bc4ccd81 Merge: 70f45f9 03d7ead Author: Brad King AuthorDate: Thu Feb 2 08:46:09 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 2 08:46:09 2017 -0500 Merge topic 'gcc-features' into next 03d7ead1 Revert topic 'gcc-features' https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=03d7ead1246818cd076d4d45bb5e970baf781bc9 commit 03d7ead1246818cd076d4d45bb5e970baf781bc9 Author: Brad King AuthorDate: Thu Feb 2 08:45:47 2017 -0500 Commit: Brad King CommitDate: Thu Feb 2 08:45:47 2017 -0500 Revert topic 'gcc-features' It will be revised and restored. diff --git a/Help/manual/cmake-compile-features.7.rst b/Help/manual/cmake-compile-features.7.rst index 078b20b..d641856 100644 --- a/Help/manual/cmake-compile-features.7.rst +++ b/Help/manual/cmake-compile-features.7.rst @@ -338,14 +338,6 @@ versions specified for each: * ``SunPro``: Oracle SolarisStudio version 12.4. * ``Intel``: Intel compiler versions 12.1 through 17.0. -CMake is currently aware of the :prop_tgt:`language standards ` -and :prop_gbl:`compile features ` available from -the following :variable:`compiler ids _COMPILER_ID>` as of the -versions specified for each: - -* all compilers and versions listed above for C++ -* ``GNU``: GNU compiler versions 3.4 through 5.0. - CMake is currently aware of the :prop_tgt:`language standards ` from the following :variable:`compiler ids _COMPILER_ID>` as of the versions specified for each: diff --git a/Help/release/dev/gcc-features.rst b/Help/release/dev/gcc-features.rst deleted file mode 100644 index c6959ab..0000000 --- a/Help/release/dev/gcc-features.rst +++ /dev/null @@ -1,5 +0,0 @@ -gcc-features ------------- - -* The :manual:`Compile Features ` functionality - is now aware of the availability of C99 in gcc since version 3.4. diff --git a/Modules/Compiler/GNU-C-FeatureTests.cmake b/Modules/Compiler/GNU-C-FeatureTests.cmake index 0ab5265..b3fe33f 100644 --- a/Modules/Compiler/GNU-C-FeatureTests.cmake +++ b/Modules/Compiler/GNU-C-FeatureTests.cmake @@ -1,5 +1,5 @@ -set(_cmake_oldestSupported "(__GNUC__ * 100 + __GNUC_MINOR__) >= 304") +set(_cmake_oldestSupported "(__GNUC__ * 100 + __GNUC_MINOR__) >= 404") # GNU 4.7 correctly sets __STDC_VERSION__ to 201112L, but GNU 4.6 sets it # to 201000L. As the former is strictly greater than the latter, test only @@ -8,10 +8,10 @@ set(_cmake_oldestSupported "(__GNUC__ * 100 + __GNUC_MINOR__) >= 304") # to the distinction between __cplusplus and __GXX_EXPERIMENTAL_CXX0X__ tests. set(GNU46_C11 "(__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201000L") set(_cmake_feature_test_c_static_assert "${GNU46_C11}") -# Since 3.4 at least: -set(GNU34_C99 "(__GNUC__ * 100 + __GNUC_MINOR__) >= 304 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L") -set(_cmake_feature_test_c_restrict "${GNU34_C99}") -set(_cmake_feature_test_c_variadic_macros "${GNU34_C99}") +# Since 4.4 at least: +set(GNU44_C99 "(__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L") +set(_cmake_feature_test_c_restrict "${GNU44_C99}") +set(_cmake_feature_test_c_variadic_macros "${GNU44_C99}") set(GNU_C90 "${_cmake_oldestSupported}") set(_cmake_feature_test_c_function_prototypes "${GNU_C90}") diff --git a/Modules/Compiler/GNU-C.cmake b/Modules/Compiler/GNU-C.cmake index 3f02618..05c3bb2 100644 --- a/Modules/Compiler/GNU-C.cmake +++ b/Modules/Compiler/GNU-C.cmake @@ -4,12 +4,12 @@ __compiler_gnu(C) if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.5) set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c90") set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu90") -elseif (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4) +elseif (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4) set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c89") set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu89") endif() -if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4) +if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4) set(CMAKE_C99_STANDARD_COMPILE_OPTION "-std=c99") set(CMAKE_C99_EXTENSION_COMPILE_OPTION "-std=gnu99") endif() @@ -22,7 +22,7 @@ elseif (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.6) set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu1x") endif() -if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4) +if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4) if (NOT CMAKE_C_COMPILER_FORCED) if (NOT CMAKE_C_STANDARD_COMPUTED_DEFAULT) message(FATAL_ERROR "CMAKE_C_STANDARD_COMPUTED_DEFAULT should be set for ${CMAKE_C_COMPILER_ID} (${CMAKE_C_COMPILER}) version ${CMAKE_C_COMPILER_VERSION}") @@ -38,9 +38,10 @@ if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4) endif() endif() + macro(cmake_record_c_compile_features) set(_result 0) - if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4) + if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4) if(_result EQUAL 0 AND CMAKE_C11_STANDARD_COMPILE_OPTION) _record_compiler_features_c(11) endif() diff --git a/Modules/Compiler/GNU-CXX.cmake b/Modules/Compiler/GNU-CXX.cmake index c007c98..b04ea11 100644 --- a/Modules/Compiler/GNU-CXX.cmake +++ b/Modules/Compiler/GNU-CXX.cmake @@ -6,7 +6,7 @@ if (WIN32) set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fno-keep-inline-dllexport") endif() else() - if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.0) + if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.2) set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden") endif() endif() diff --git a/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt b/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt index a8406dd..7957ab8 100644 --- a/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt +++ b/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt @@ -20,17 +20,6 @@ write_compiler_detection_header( ${cxx_known_features} ${c_known_features} ) -write_compiler_detection_header( - FILE "${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files/multi_file_compiler_detection.h" - PREFIX MULTI - OUTPUT_FILES_VAR multi_files - OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files/compiler_support" - COMPILERS GNU Clang AppleClang MSVC SunPro Intel - VERSION 3.1 - FEATURES - ${cxx_known_features} ${c_known_features} -) - macro(set_defines target true_defs false_defs) set(defines) foreach(def ${true_defs}) @@ -127,6 +116,17 @@ add_executable(WriteCompilerDetectionHeader main.cpp) set_property(TARGET WriteCompilerDetectionHeader PROPERTY CXX_STANDARD 98) set_defines(WriteCompilerDetectionHeader "${true_defs}" "${false_defs}") +write_compiler_detection_header( + FILE "${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files/multi_file_compiler_detection.h" + PREFIX MULTI + OUTPUT_FILES_VAR multi_files + OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files/compiler_support" + COMPILERS GNU Clang AppleClang MSVC SunPro Intel + VERSION 3.1 + FEATURES + ${cxx_known_features} ${c_known_features} +) + add_executable(multi_files multi_files.cpp) set_property(TARGET multi_files PROPERTY CXX_STANDARD 98) target_include_directories(multi_files PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files) ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-compile-features.7.rst | 8 ------- Help/release/dev/gcc-features.rst | 5 ----- Modules/Compiler/GNU-C-FeatureTests.cmake | 10 ++++----- Modules/Compiler/GNU-C.cmake | 9 ++++---- Modules/Compiler/GNU-CXX.cmake | 2 +- .../WriteCompilerDetectionHeader/CMakeLists.txt | 22 ++++++++++---------- 6 files changed, 22 insertions(+), 34 deletions(-) delete mode 100644 Help/release/dev/gcc-features.rst hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 2 08:46:28 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 2 Feb 2017 08:46:28 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2499-g7c27b23 Message-ID: <20170202134631.457A6E1CFA@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 7c27b23602b62c9cb0b158bbcfc485ce9e30d7fc (commit) via be3727bf92a416a68f5946d2915d745c0f96740f (commit) from adb33f13eb844bb4412e76a113438727bc4ccd81 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7c27b23602b62c9cb0b158bbcfc485ce9e30d7fc commit 7c27b23602b62c9cb0b158bbcfc485ce9e30d7fc Merge: adb33f1 be3727b Author: Brad King AuthorDate: Thu Feb 2 08:46:25 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 2 08:46:25 2017 -0500 Merge topic 'doc-compile-features-fixup' into next be3727bf Help: Fix language standard link text in cmake-compile-features(7) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=be3727bf92a416a68f5946d2915d745c0f96740f commit be3727bf92a416a68f5946d2915d745c0f96740f Author: Brad King AuthorDate: Thu Feb 2 08:43:58 2017 -0500 Commit: Brad King CommitDate: Thu Feb 2 08:43:58 2017 -0500 Help: Fix language standard link text in cmake-compile-features(7) Include each language name in the text of the link to its standards property. diff --git a/Help/manual/cmake-compile-features.7.rst b/Help/manual/cmake-compile-features.7.rst index d641856..4f48ad9 100644 --- a/Help/manual/cmake-compile-features.7.rst +++ b/Help/manual/cmake-compile-features.7.rst @@ -326,7 +326,7 @@ the feature-appropriate include directory Supported Compilers =================== -CMake is currently aware of the :prop_tgt:`language standards ` +CMake is currently aware of the :prop_tgt:`C++ standards ` and :prop_gbl:`compile features ` available from the following :variable:`compiler ids _COMPILER_ID>` as of the versions specified for each: @@ -338,7 +338,7 @@ versions specified for each: * ``SunPro``: Oracle SolarisStudio version 12.4. * ``Intel``: Intel compiler versions 12.1 through 17.0. -CMake is currently aware of the :prop_tgt:`language standards ` +CMake is currently aware of the :prop_tgt:`CUDA standards ` from the following :variable:`compiler ids _COMPILER_ID>` as of the versions specified for each: ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-compile-features.7.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 2 08:46:35 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 2 Feb 2017 08:46:35 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1272-g3e34049 Message-ID: <20170202134635.A4A51FA18C@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 3e34049516f75d8545543bc68246e62ec31fabc5 (commit) via be3727bf92a416a68f5946d2915d745c0f96740f (commit) from aba66d27a1d4b5364274784fce27a3c52ee2140b (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3e34049516f75d8545543bc68246e62ec31fabc5 commit 3e34049516f75d8545543bc68246e62ec31fabc5 Merge: aba66d2 be3727b Author: Brad King AuthorDate: Thu Feb 2 08:46:33 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 2 08:46:33 2017 -0500 Merge topic 'doc-compile-features-fixup' be3727bf Help: Fix language standard link text in cmake-compile-features(7) ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-compile-features.7.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 2 08:46:52 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 2 Feb 2017 08:46:52 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2501-g84a9b25 Message-ID: <20170202134652.87F65FA0FA@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 84a9b255dbe0cf119a9f3726f36e5c4b060303cc (commit) via 3e34049516f75d8545543bc68246e62ec31fabc5 (commit) from 7c27b23602b62c9cb0b158bbcfc485ce9e30d7fc (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=84a9b255dbe0cf119a9f3726f36e5c4b060303cc commit 84a9b255dbe0cf119a9f3726f36e5c4b060303cc Merge: 7c27b23 3e34049 Author: Brad King AuthorDate: Thu Feb 2 08:46:44 2017 -0500 Commit: Brad King CommitDate: Thu Feb 2 08:46:44 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 2 08:53:10 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 2 Feb 2017 08:53:10 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2503-g16e6056 Message-ID: <20170202135311.4E822FA48C@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 16e60561ee679b1f53b08dd68ac084bdb2481473 (commit) via 645dd3ca5317852968e59a42592d8dacecc98b92 (commit) from 84a9b255dbe0cf119a9f3726f36e5c4b060303cc (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=16e60561ee679b1f53b08dd68ac084bdb2481473 commit 16e60561ee679b1f53b08dd68ac084bdb2481473 Merge: 84a9b25 645dd3c Author: Brad King AuthorDate: Thu Feb 2 08:53:08 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 2 08:53:08 2017 -0500 Merge topic 'find_cuda_fix_typo' into next 645dd3ca FindCUDA: Fix typo in CUDA_DETECT_INSTALLED_GPUS doc string https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=645dd3ca5317852968e59a42592d8dacecc98b92 commit 645dd3ca5317852968e59a42592d8dacecc98b92 Author: Pierre Moreau AuthorDate: Thu Feb 2 13:31:07 2017 +0100 Commit: Brad King CommitDate: Thu Feb 2 08:52:11 2017 -0500 FindCUDA: Fix typo in CUDA_DETECT_INSTALLED_GPUS doc string diff --git a/Modules/FindCUDA/select_compute_arch.cmake b/Modules/FindCUDA/select_compute_arch.cmake index 19fc14f..a96a8ca 100644 --- a/Modules/FindCUDA/select_compute_arch.cmake +++ b/Modules/FindCUDA/select_compute_arch.cmake @@ -71,7 +71,7 @@ function(CUDA_DETECT_INSTALLED_GPUS OUT_VARIABLE) if(run_result EQUAL 0) string(REPLACE "2.1" "2.1(2.0)" compute_capabilities "${compute_capabilities}") set(CUDA_GPU_DETECT_OUTPUT ${compute_capabilities} - CACHE INTERNAL "Returned GPU architetures from detect_gpus tool" FORCE) + CACHE INTERNAL "Returned GPU architectures from detect_gpus tool" FORCE) endif() endif() ----------------------------------------------------------------------- Summary of changes: Modules/FindCUDA/select_compute_arch.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 2 08:55:33 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 2 Feb 2017 08:55:33 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1274-g2b0256c Message-ID: <20170202135533.3C8CFFA4D2@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 2b0256c5ade94ca19467fd42075b3c22bd3856f2 (commit) via 645dd3ca5317852968e59a42592d8dacecc98b92 (commit) from 3e34049516f75d8545543bc68246e62ec31fabc5 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=2b0256c5ade94ca19467fd42075b3c22bd3856f2 commit 2b0256c5ade94ca19467fd42075b3c22bd3856f2 Merge: 3e34049 645dd3c Author: Brad King AuthorDate: Thu Feb 2 08:55:31 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 2 08:55:31 2017 -0500 Merge topic 'find_cuda_fix_typo' 645dd3ca FindCUDA: Fix typo in CUDA_DETECT_INSTALLED_GPUS doc string ----------------------------------------------------------------------- Summary of changes: Modules/FindCUDA/select_compute_arch.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 2 08:55:57 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 2 Feb 2017 08:55:57 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2505-g903c0cd Message-ID: <20170202135557.A9110FA4D3@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 903c0cda337e58c95ff947fdd4b0b21396bd6feb (commit) via 2b0256c5ade94ca19467fd42075b3c22bd3856f2 (commit) from 16e60561ee679b1f53b08dd68ac084bdb2481473 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=903c0cda337e58c95ff947fdd4b0b21396bd6feb commit 903c0cda337e58c95ff947fdd4b0b21396bd6feb Merge: 16e6056 2b0256c Author: Brad King AuthorDate: Thu Feb 2 08:55:49 2017 -0500 Commit: Brad King CommitDate: Thu Feb 2 08:55:49 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 2 10:33:47 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 2 Feb 2017 10:33:47 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2510-g9a4338d Message-ID: <20170202153347.7FEC0FA62C@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 9a4338d7f59750c2cbd61ed0a252224f102f0384 (commit) via 44fb57c9093b67bc533380b12727997f8e67efa1 (commit) via 071c3622c8954ed74e27ce7671d5de83627dfd0b (commit) via 8211f08186e67fb88296ff055d95048296482307 (commit) via 74643ffb144fc5045107fdfc2f4ebdc8e4854a37 (commit) from 903c0cda337e58c95ff947fdd4b0b21396bd6feb (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9a4338d7f59750c2cbd61ed0a252224f102f0384 commit 9a4338d7f59750c2cbd61ed0a252224f102f0384 Merge: 903c0cd 44fb57c Author: Brad King AuthorDate: Thu Feb 2 10:33:36 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 2 10:33:36 2017 -0500 Merge topic 'FindHDF5-fix-HDF5_ROOT' into next 44fb57c9 FindHDF5: Fix search with HDF5_ROOT 071c3622 FindHDF5: Use keywords in find_library calls 8211f081 FindHDF5: Initialize/finalize internal search options variable 74643ffb FindHDF5: Fix command-line parsing argument extraction order https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=44fb57c9093b67bc533380b12727997f8e67efa1 commit 44fb57c9093b67bc533380b12727997f8e67efa1 Author: Brad King AuthorDate: Thu Feb 2 09:21:21 2017 -0500 Commit: Brad King CommitDate: Thu Feb 2 10:23:19 2017 -0500 FindHDF5: Fix search with HDF5_ROOT Refactoring in commit v3.6.0-rc1~72^2 (HDF5: Rework component searching to correctly find HL for all bindings, 2016-05-12) turned off a large amount of its logic when HDF5_ROOT is set. This caused use of the hdf5 compiler wrapper to extract all needed libraries (e.g. z, dl as dependencies of hdf5 static libraries) to be skipped when using HDF5_ROOT. Fix the search logic to honor HDF5_ROOT in all code paths. Restrict the search for hdf5-specific components to this root, but allow external libraries to be found anywhere. Fixes: #16566 diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake index 84a83ba..4f79a32 100644 --- a/Modules/FindHDF5.cmake +++ b/Modules/FindHDF5.cmake @@ -383,10 +383,18 @@ endmacro() if(NOT HDF5_ROOT) set(HDF5_ROOT $ENV{HDF5_ROOT}) endif() +if(HDF5_ROOT) + set(_HDF5_SEARCH_OPTS NO_DEFAULT_PATH) +else() + set(_HDF5_SEARCH_OPTS) +endif() # Try to find HDF5 using an installed hdf5-config.cmake -if(NOT HDF5_FOUND AND NOT HDF5_ROOT) - find_package(HDF5 QUIET NO_MODULE) +if(NOT HDF5_FOUND) + find_package(HDF5 QUIET NO_MODULE + HINTS ${HDF5_ROOT} + ${_HDF5_SEARCH_OPTS} + ) if( HDF5_FOUND) set(HDF5_IS_PARALLEL ${HDF5_ENABLE_PARALLEL}) set(HDF5_INCLUDE_DIRS ${HDF5_INCLUDE_DIR}) @@ -440,7 +448,7 @@ if(NOT HDF5_FOUND AND NOT HDF5_ROOT) endif() endif() -if(NOT HDF5_FOUND AND NOT HDF5_ROOT) +if(NOT HDF5_FOUND) set(_HDF5_NEED_TO_SEARCH False) set(HDF5_COMPILER_NO_INTERROGATE True) # Only search for languages we've enabled @@ -488,8 +496,10 @@ if(NOT HDF5_FOUND AND NOT HDF5_ROOT) # search options with the wrapper find_program(HDF5_${__lang}_COMPILER_EXECUTABLE NAMES ${HDF5_${__lang}_COMPILER_NAMES} NAMES_PER_DIR + HINTS ${HDF5_ROOT} PATH_SUFFIXES bin Bin DOC "HDF5 ${__lang} Wrapper compiler. Used only to detect HDF5 compile flags." + ${_HDF5_SEARCH_OPTS} ) mark_as_advanced( HDF5_${__lang}_COMPILER_EXECUTABLE ) unset(HDF5_${__lang}_COMPILER_NAMES) @@ -516,10 +526,20 @@ if(NOT HDF5_FOUND AND NOT HDF5_ROOT) endif() foreach(L IN LISTS HDF5_${__lang}_LIBRARY_NAMES) + if(x"${L}" MATCHES "hdf5") + # hdf5 library + set(_HDF5_SEARCH_OPTS_LOCAL ${_HDF5_SEARCH_OPTS}) + else() + # external library + set(_HDF5_SEARCH_OPTS_LOCAL) + endif() find_library(HDF5_${__lang}_LIBRARY_${L} NAMES ${L} HINTS ${HDF5_${__lang}_LIBRARY_DIRS} + ${HDF5_ROOT} + ${_HDF5_SEARCH_OPTS_LOCAL} ) + unset(_HDF5_SEARCH_OPTS_LOCAL) if(HDF5_${__lang}_LIBRARY_${L}) list(APPEND HDF5_${__lang}_LIBRARIES ${HDF5_${__lang}_LIBRARY_${L}}) else() @@ -529,10 +549,20 @@ if(NOT HDF5_FOUND AND NOT HDF5_ROOT) if(FIND_HL) set(HDF5_${__lang}_HL_LIBRARIES) foreach(L IN LISTS HDF5_${__lang}_HL_LIBRARY_NAMES) + if("x${L}" MATCHES "hdf5") + # hdf5 library + set(_HDF5_SEARCH_OPTS_LOCAL ${_HDF5_SEARCH_OPTS}) + else() + # external library + set(_HDF5_SEARCH_OPTS_LOCAL) + endif() find_library(HDF5_${__lang}_LIBRARY_${L} NAMES ${L} HINTS ${HDF5_${__lang}_LIBRARY_DIRS} + ${HDF5_ROOT} + ${_HDF5_SEARCH_OPTS_LOCAL} ) + unset(_HDF5_SEARCH_OPTS_LOCAL) if(HDF5_${__lang}_LIBRARY_${L}) list(APPEND HDF5_${__lang}_HL_LIBRARIES ${HDF5_${__lang}_LIBRARY_${L}}) else() @@ -614,11 +644,6 @@ elseif(NOT HDF5_FOUND AND NOT _HDF5_NEED_TO_SEARCH) endif() endif() -if(HDF5_ROOT) - set(_HDF5_SEARCH_OPTS NO_DEFAULT_PATH) -else() - set(_HDF5_SEARCH_OPTS) -endif() find_program( HDF5_DIFF_EXECUTABLE NAMES h5diff HINTS ${HDF5_ROOT} https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=071c3622c8954ed74e27ce7671d5de83627dfd0b commit 071c3622c8954ed74e27ce7671d5de83627dfd0b Author: Brad King AuthorDate: Thu Feb 2 09:16:47 2017 -0500 Commit: Brad King CommitDate: Thu Feb 2 10:11:12 2017 -0500 FindHDF5: Use keywords in find_library calls Clarify the purpose of each argument. diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake index e982a42..84a83ba 100644 --- a/Modules/FindHDF5.cmake +++ b/Modules/FindHDF5.cmake @@ -516,7 +516,10 @@ if(NOT HDF5_FOUND AND NOT HDF5_ROOT) endif() foreach(L IN LISTS HDF5_${__lang}_LIBRARY_NAMES) - find_library(HDF5_${__lang}_LIBRARY_${L} ${L} ${HDF5_${__lang}_LIBRARY_DIRS}) + find_library(HDF5_${__lang}_LIBRARY_${L} + NAMES ${L} + HINTS ${HDF5_${__lang}_LIBRARY_DIRS} + ) if(HDF5_${__lang}_LIBRARY_${L}) list(APPEND HDF5_${__lang}_LIBRARIES ${HDF5_${__lang}_LIBRARY_${L}}) else() @@ -526,7 +529,10 @@ if(NOT HDF5_FOUND AND NOT HDF5_ROOT) if(FIND_HL) set(HDF5_${__lang}_HL_LIBRARIES) foreach(L IN LISTS HDF5_${__lang}_HL_LIBRARY_NAMES) - find_library(HDF5_${__lang}_LIBRARY_${L} ${L} ${HDF5_${__lang}_LIBRARY_DIRS}) + find_library(HDF5_${__lang}_LIBRARY_${L} + NAMES ${L} + HINTS ${HDF5_${__lang}_LIBRARY_DIRS} + ) if(HDF5_${__lang}_LIBRARY_${L}) list(APPEND HDF5_${__lang}_HL_LIBRARIES ${HDF5_${__lang}_LIBRARY_${L}}) else() https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8211f08186e67fb88296ff055d95048296482307 commit 8211f08186e67fb88296ff055d95048296482307 Author: Brad King AuthorDate: Thu Feb 2 09:13:46 2017 -0500 Commit: Brad King CommitDate: Thu Feb 2 10:10:28 2017 -0500 FindHDF5: Initialize/finalize internal search options variable While at it, use a more private name. diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake index 648b081..e982a42 100644 --- a/Modules/FindHDF5.cmake +++ b/Modules/FindHDF5.cmake @@ -609,13 +609,15 @@ elseif(NOT HDF5_FOUND AND NOT _HDF5_NEED_TO_SEARCH) endif() if(HDF5_ROOT) - set(SEARCH_OPTS NO_DEFAULT_PATH) + set(_HDF5_SEARCH_OPTS NO_DEFAULT_PATH) +else() + set(_HDF5_SEARCH_OPTS) endif() find_program( HDF5_DIFF_EXECUTABLE NAMES h5diff HINTS ${HDF5_ROOT} PATH_SUFFIXES bin Bin - ${SEARCH_OPTS} + ${_HDF5_SEARCH_OPTS} DOC "HDF5 file differencing tool." ) mark_as_advanced( HDF5_DIFF_EXECUTABLE ) @@ -644,7 +646,7 @@ if( NOT HDF5_FOUND ) HINTS ${HDF5_ROOT} PATHS $ENV{HOME}/.local/include PATH_SUFFIXES include Include - ${SEARCH_OPTS} + ${_HDF5_SEARCH_OPTS} ) mark_as_advanced(HDF5_${LANGUAGE}_INCLUDE_DIR) list(APPEND HDF5_INCLUDE_DIRS ${HDF5_${__lang}_INCLUDE_DIR}) @@ -668,12 +670,12 @@ if( NOT HDF5_FOUND ) find_library(HDF5_${LIB}_LIBRARY_DEBUG NAMES ${THIS_LIBRARY_SEARCH_DEBUG} HINTS ${HDF5_ROOT} PATH_SUFFIXES lib Lib - ${SEARCH_OPTS} + ${_HDF5_SEARCH_OPTS} ) find_library( HDF5_${LIB}_LIBRARY_RELEASE NAMES ${THIS_LIBRARY_SEARCH_RELEASE} HINTS ${HDF5_ROOT} PATH_SUFFIXES lib Lib - ${SEARCH_OPTS} + ${_HDF5_SEARCH_OPTS} ) select_library_configurations( HDF5_${LIB} ) list(APPEND HDF5_${__lang}_LIBRARIES ${HDF5_${LIB}_LIBRARY}) @@ -705,12 +707,12 @@ if( NOT HDF5_FOUND ) find_library(HDF5_${LIB}_LIBRARY_DEBUG NAMES ${THIS_LIBRARY_SEARCH_DEBUG} HINTS ${HDF5_ROOT} PATH_SUFFIXES lib Lib - ${SEARCH_OPTS} + ${_HDF5_SEARCH_OPTS} ) find_library( HDF5_${LIB}_LIBRARY_RELEASE NAMES ${THIS_LIBRARY_SEARCH_RELEASE} HINTS ${HDF5_ROOT} PATH_SUFFIXES lib Lib - ${SEARCH_OPTS} + ${_HDF5_SEARCH_OPTS} ) select_library_configurations( HDF5_${LIB} ) list(APPEND HDF5_${__lang}_HL_LIBRARIES ${HDF5_${LIB}_LIBRARY}) @@ -785,3 +787,5 @@ find_package_handle_standard_args(HDF5 VERSION_VAR HDF5_VERSION HANDLE_COMPONENTS ) + +unset(_HDF5_SEARCH_OPTS) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=74643ffb144fc5045107fdfc2f4ebdc8e4854a37 commit 74643ffb144fc5045107fdfc2f4ebdc8e4854a37 Author: Brad King AuthorDate: Thu Feb 2 10:05:51 2017 -0500 Commit: Brad King CommitDate: Thu Feb 2 10:09:49 2017 -0500 FindHDF5: Fix command-line parsing argument extraction order Re-implement our internal `_HDF5_parse_compile_line` helper to process command line arguments all at once and in order. Otherwise the libraries named by absolute path and those named by `-l` arguments are not kept in order. The new implementation will not handle separate arguments like `-I /path/to/include/dir` but I have not seen the HDF5 compiler wrappers produce this form. If necessary the parsing loop can be extended with a state variable to keep track of such pairs. diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake index 6e5a25e..648b081 100644 --- a/Modules/FindHDF5.cmake +++ b/Modules/FindHDF5.cmake @@ -340,62 +340,44 @@ macro( _HDF5_parse_compile_line libraries libraries_hl) - # Match the include paths - set( RE " -I *([^\" ]+|\"[^\"]+\")") - string( REGEX MATCHALL "${RE}" include_path_flags "${${compile_line_var}}") - foreach( IPATH IN LISTS include_path_flags ) - string( REGEX REPLACE "${RE}" "\\1" IPATH "${IPATH}" ) - list( APPEND ${include_paths} ${IPATH} ) - endforeach() - - # Match the definitions - set( RE " -D([^ ]*)") - string( REGEX MATCHALL "${RE}" definition_flags "${${compile_line_var}}" ) - foreach( DEF IN LISTS definition_flags ) - string( STRIP "${DEF}" DEF ) - list( APPEND ${definitions} ${DEF} ) - endforeach() - - # Match the library paths - set( RE " -L *([^\" ]+|\"[^\"]+\")") - string( REGEX MATCHALL "${RE}" library_path_flags "${${compile_line_var}}") - foreach( LPATH IN LISTS library_path_flags ) - string( REGEX REPLACE "${RE}" "\\1" LPATH "${LPATH}" ) - list( APPEND ${library_paths} ${LPATH} ) - endforeach() - - # now search for the lib names specified in the compile line (match -l...) - # match only -l's preceded by a space or comma - set( RE " -l *([^\" ]+|\"[^\"]+\")") - string( REGEX MATCHALL "${RE}" library_name_flags "${${compile_line_var}}") - foreach( LNAME IN LISTS library_name_flags ) - string( REGEX REPLACE "${RE}" "\\1" LNAME "${LNAME}" ) - if(LNAME MATCHES ".*hl") - list(APPEND ${libraries_hl} ${LNAME}) - else() - list(APPEND ${libraries} ${LNAME}) - endif() - endforeach() + if(UNIX) + separate_arguments(_HDF5_COMPILE_ARGS UNIX_COMMAND "${${compile_line_var}}") + else() + separate_arguments(_HDF5_COMPILE_ARGS WINDOWS_COMMAND "${${compile_line_var}}") + endif() - # now search for full library paths with no flags - set( RE " ([^\" ]+|\"[^\"]+\")") - string( REGEX MATCHALL "${RE}" library_name_noflags "${${compile_line_var}}") - foreach( LIB IN LISTS library_name_noflags ) - string( REGEX REPLACE "${RE}" "\\1" LIB "${LIB}" ) - get_filename_component(LIB "${LIB}" ABSOLUTE) - if(NOT EXISTS ${LIB} OR IS_DIRECTORY ${LIB}) - continue() - endif() - get_filename_component(LPATH ${LIB} DIRECTORY) - get_filename_component(LNAME ${LIB} NAME_WE) - string( REGEX REPLACE "^lib" "" LNAME ${LNAME} ) - list( APPEND ${library_paths} ${LPATH} ) - if(LNAME MATCHES ".*hl") - list(APPEND ${libraries_hl} ${LNAME}) - else() - list(APPEND ${libraries} ${LNAME}) - endif() - endforeach() + foreach(arg IN LISTS _HDF5_COMPILE_ARGS) + if("${arg}" MATCHES "^-I(.*)$") + # include directory + list(APPEND ${include_paths} "${CMAKE_MATCH_1}") + elseif("${arg}" MATCHES "^-D(.*)$") + # compile definition + list(APPEND ${definitions} "${CMAKE_MATCH_1}") + elseif("${arg}" MATCHES "^-L(.*)$") + # library search path + list(APPEND ${library_paths} "${CMAKE_MATCH_1}") + elseif("${arg}" MATCHES "^-l(.*)hl$") + # library name (hl) + list(APPEND ${libraries_hl} "${CMAKE_MATCH_1}") + elseif("${arg}" MATCHES "^-l(.*)$") + # library name + list(APPEND ${libraries} "${CMAKE_MATCH_1}") + elseif("${arg}" MATCHES "^(.:)?[/\\].*\\.(a|so|dylib|sl|lib)$") + # library file + if(NOT EXISTS "${arg}") + continue() + endif() + get_filename_component(_HDF5_LPATH "${arg}" DIRECTORY) + get_filename_component(_HDF5_LNAME "${arg}" NAME_WE) + string(REGEX REPLACE "^lib" "" _HDF5_LNAME "${_HDF5_LNAME}") + list(APPEND ${library_paths} "${_HDF5_LPATH}") + if(_HDF5_LNAME MATCHES ".*hl") + list(APPEND ${libraries_hl} "${_HDF5_LNAME}") + else() + list(APPEND ${libraries} "${_HDF5_LNAME}") + endif() + endif() + endforeach() endmacro() if(NOT HDF5_ROOT) ----------------------------------------------------------------------- Summary of changes: Modules/FindHDF5.cmake | 155 +++++++++++++++++++++++++++--------------------- 1 file changed, 86 insertions(+), 69 deletions(-) hooks/post-receive -- CMake From eike at sf-mail.de Thu Feb 2 15:56:16 2017 From: eike at sf-mail.de (Rolf Eike Beer) Date: Thu, 2 Feb 2017 15:56:16 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2515-g50be50f Message-ID: <20170202205616.62A94F3E81@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 50be50f8fd017a4f014aded68d81e1955382db63 (commit) via 37ed860ad1e71f347513a38432640f7dda5c07ee (commit) via 94a8ee6fd0ba487437579bb224500b9f46c2819c (commit) via 940bf6a4a427c8edfd975bf078a3ea331847f72a (commit) via f26ca5a1953e7f260bc23d30c5d35cc071a6f6ab (commit) from 9a4338d7f59750c2cbd61ed0a252224f102f0384 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=50be50f8fd017a4f014aded68d81e1955382db63 commit 50be50f8fd017a4f014aded68d81e1955382db63 Merge: 9a4338d 37ed860 Author: Rolf Eike Beer AuthorDate: Thu Feb 2 15:56:13 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 2 15:56:13 2017 -0500 Merge topic 'gcc-features' into next 37ed860a GNU C++: record that -fvisibility-inlines-hidden is available since 4.0 94a8ee6f GNU C: record that C99 is available since at least 3.4 940bf6a4 Tests/Module/WCDH: only use -Werror=undef compiler flag if actually supported f26ca5a1 Tests/Module/WCDH: write multi_file_compiler_detection.h before using it https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=37ed860ad1e71f347513a38432640f7dda5c07ee commit 37ed860ad1e71f347513a38432640f7dda5c07ee Author: Rolf Eike Beer AuthorDate: Fri Jan 27 16:52:42 2017 +0100 Commit: Rolf Eike Beer CommitDate: Thu Feb 2 18:28:56 2017 +0100 GNU C++: record that -fvisibility-inlines-hidden is available since 4.0 See https://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Option-Summary.html diff --git a/Modules/Compiler/GNU-CXX.cmake b/Modules/Compiler/GNU-CXX.cmake index b04ea11..c007c98 100644 --- a/Modules/Compiler/GNU-CXX.cmake +++ b/Modules/Compiler/GNU-CXX.cmake @@ -6,7 +6,7 @@ if (WIN32) set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fno-keep-inline-dllexport") endif() else() - if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.2) + if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.0) set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden") endif() endif() https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=94a8ee6fd0ba487437579bb224500b9f46c2819c commit 94a8ee6fd0ba487437579bb224500b9f46c2819c Author: Rolf Eike Beer AuthorDate: Fri Jan 27 16:49:45 2017 +0100 Commit: Rolf Eike Beer CommitDate: Thu Feb 2 18:28:56 2017 +0100 GNU C: record that C99 is available since at least 3.4 diff --git a/Help/manual/cmake-compile-features.7.rst b/Help/manual/cmake-compile-features.7.rst index 4f48ad9..448fe9a 100644 --- a/Help/manual/cmake-compile-features.7.rst +++ b/Help/manual/cmake-compile-features.7.rst @@ -338,6 +338,14 @@ versions specified for each: * ``SunPro``: Oracle SolarisStudio version 12.4. * ``Intel``: Intel compiler versions 12.1 through 17.0. +CMake is currently aware of the :prop_tgt:`C standards ` +and :prop_gbl:`compile features ` available from +the following :variable:`compiler ids _COMPILER_ID>` as of the +versions specified for each: + +* all compilers and versions listed above for C++ +* ``GNU``: GNU compiler versions 3.4 through 5.0. + CMake is currently aware of the :prop_tgt:`CUDA standards ` from the following :variable:`compiler ids _COMPILER_ID>` as of the versions specified for each: diff --git a/Help/release/dev/gcc-features.rst b/Help/release/dev/gcc-features.rst new file mode 100644 index 0000000..c6959ab --- /dev/null +++ b/Help/release/dev/gcc-features.rst @@ -0,0 +1,5 @@ +gcc-features +------------ + +* The :manual:`Compile Features ` functionality + is now aware of the availability of C99 in gcc since version 3.4. diff --git a/Modules/Compiler/GNU-C-FeatureTests.cmake b/Modules/Compiler/GNU-C-FeatureTests.cmake index b3fe33f..0ab5265 100644 --- a/Modules/Compiler/GNU-C-FeatureTests.cmake +++ b/Modules/Compiler/GNU-C-FeatureTests.cmake @@ -1,5 +1,5 @@ -set(_cmake_oldestSupported "(__GNUC__ * 100 + __GNUC_MINOR__) >= 404") +set(_cmake_oldestSupported "(__GNUC__ * 100 + __GNUC_MINOR__) >= 304") # GNU 4.7 correctly sets __STDC_VERSION__ to 201112L, but GNU 4.6 sets it # to 201000L. As the former is strictly greater than the latter, test only @@ -8,10 +8,10 @@ set(_cmake_oldestSupported "(__GNUC__ * 100 + __GNUC_MINOR__) >= 404") # to the distinction between __cplusplus and __GXX_EXPERIMENTAL_CXX0X__ tests. set(GNU46_C11 "(__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201000L") set(_cmake_feature_test_c_static_assert "${GNU46_C11}") -# Since 4.4 at least: -set(GNU44_C99 "(__GNUC__ * 100 + __GNUC_MINOR__) >= 404 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L") -set(_cmake_feature_test_c_restrict "${GNU44_C99}") -set(_cmake_feature_test_c_variadic_macros "${GNU44_C99}") +# Since 3.4 at least: +set(GNU34_C99 "(__GNUC__ * 100 + __GNUC_MINOR__) >= 304 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L") +set(_cmake_feature_test_c_restrict "${GNU34_C99}") +set(_cmake_feature_test_c_variadic_macros "${GNU34_C99}") set(GNU_C90 "${_cmake_oldestSupported}") set(_cmake_feature_test_c_function_prototypes "${GNU_C90}") diff --git a/Modules/Compiler/GNU-C.cmake b/Modules/Compiler/GNU-C.cmake index 05c3bb2..3f02618 100644 --- a/Modules/Compiler/GNU-C.cmake +++ b/Modules/Compiler/GNU-C.cmake @@ -4,12 +4,12 @@ __compiler_gnu(C) if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.5) set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c90") set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu90") -elseif (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4) +elseif (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4) set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c89") set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu89") endif() -if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4) +if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4) set(CMAKE_C99_STANDARD_COMPILE_OPTION "-std=c99") set(CMAKE_C99_EXTENSION_COMPILE_OPTION "-std=gnu99") endif() @@ -22,7 +22,7 @@ elseif (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.6) set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu1x") endif() -if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4) +if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4) if (NOT CMAKE_C_COMPILER_FORCED) if (NOT CMAKE_C_STANDARD_COMPUTED_DEFAULT) message(FATAL_ERROR "CMAKE_C_STANDARD_COMPUTED_DEFAULT should be set for ${CMAKE_C_COMPILER_ID} (${CMAKE_C_COMPILER}) version ${CMAKE_C_COMPILER_VERSION}") @@ -38,10 +38,9 @@ if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4) endif() endif() - macro(cmake_record_c_compile_features) set(_result 0) - if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4) + if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4) if(_result EQUAL 0 AND CMAKE_C11_STANDARD_COMPILE_OPTION) _record_compiler_features_c(11) endif() https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=940bf6a4a427c8edfd975bf078a3ea331847f72a commit 940bf6a4a427c8edfd975bf078a3ea331847f72a Author: Rolf Eike Beer AuthorDate: Thu Feb 2 18:28:24 2017 +0100 Commit: Rolf Eike Beer CommitDate: Thu Feb 2 18:28:56 2017 +0100 Tests/Module/WCDH: only use -Werror=undef compiler flag if actually supported diff --git a/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt b/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt index a8406dd..2657aeb 100644 --- a/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt +++ b/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt @@ -68,7 +68,11 @@ if (CMAKE_C_COMPILE_FEATURES) add_executable(C_undefined c_undefined.c) set_property(TARGET C_undefined PROPERTY C_STANDARD 90) - target_compile_options(C_undefined PRIVATE -Werror=undef) + include(CheckCCompilerFlag) + check_c_compiler_flag(-Werror=undef use_error_undef) + if (use_error_undef) + target_compile_options(C_undefined PRIVATE -Werror=undef) + endif() add_executable(WriteCompilerDetectionHeader_C main.c) set_property(TARGET WriteCompilerDetectionHeader_C PROPERTY C_STANDARD 90) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f26ca5a1953e7f260bc23d30c5d35cc071a6f6ab commit f26ca5a1953e7f260bc23d30c5d35cc071a6f6ab Author: Rolf Eike Beer AuthorDate: Wed Feb 1 20:48:25 2017 +0100 Commit: Rolf Eike Beer CommitDate: Thu Feb 2 18:25:28 2017 +0100 Tests/Module/WCDH: write multi_file_compiler_detection.h before using it This was broken in commit 98e6d1e5e426c491e04faa746c11746002e6a69d (Tests/Module/WCDH: make it work with only C features defined) when all C tests were made accessible even if no C++ features are available, but the header was only created if C++ features are available. Fix it by creating the header unconditionally before any checks on the available features. diff --git a/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt b/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt index 7957ab8..a8406dd 100644 --- a/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt +++ b/Tests/Module/WriteCompilerDetectionHeader/CMakeLists.txt @@ -20,6 +20,17 @@ write_compiler_detection_header( ${cxx_known_features} ${c_known_features} ) +write_compiler_detection_header( + FILE "${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files/multi_file_compiler_detection.h" + PREFIX MULTI + OUTPUT_FILES_VAR multi_files + OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files/compiler_support" + COMPILERS GNU Clang AppleClang MSVC SunPro Intel + VERSION 3.1 + FEATURES + ${cxx_known_features} ${c_known_features} +) + macro(set_defines target true_defs false_defs) set(defines) foreach(def ${true_defs}) @@ -116,17 +127,6 @@ add_executable(WriteCompilerDetectionHeader main.cpp) set_property(TARGET WriteCompilerDetectionHeader PROPERTY CXX_STANDARD 98) set_defines(WriteCompilerDetectionHeader "${true_defs}" "${false_defs}") -write_compiler_detection_header( - FILE "${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files/multi_file_compiler_detection.h" - PREFIX MULTI - OUTPUT_FILES_VAR multi_files - OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files/compiler_support" - COMPILERS GNU Clang AppleClang MSVC SunPro Intel - VERSION 3.1 - FEATURES - ${cxx_known_features} ${c_known_features} -) - add_executable(multi_files multi_files.cpp) set_property(TARGET multi_files PROPERTY CXX_STANDARD 98) target_include_directories(multi_files PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/compiler_multi_files) ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-compile-features.7.rst | 8 ++++++ Help/release/dev/gcc-features.rst | 5 ++++ Modules/Compiler/GNU-C-FeatureTests.cmake | 10 +++---- Modules/Compiler/GNU-C.cmake | 9 +++---- Modules/Compiler/GNU-CXX.cmake | 2 +- .../WriteCompilerDetectionHeader/CMakeLists.txt | 28 +++++++++++--------- 6 files changed, 39 insertions(+), 23 deletions(-) create mode 100644 Help/release/dev/gcc-features.rst hooks/post-receive -- CMake From kwrobot at kitware.com Fri Feb 3 00:01:19 2017 From: kwrobot at kitware.com (Kitware Robot) Date: Fri, 3 Feb 2017 00:01:19 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1275-g6286d26 Message-ID: <20170203050122.974AEFA744@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 6286d26ca6408cfc45031536ed54b1679e6d5ac2 (commit) from 2b0256c5ade94ca19467fd42075b3c22bd3856f2 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6286d26ca6408cfc45031536ed54b1679e6d5ac2 commit 6286d26ca6408cfc45031536ed54b1679e6d5ac2 Author: Kitware Robot AuthorDate: Fri Feb 3 00:01:05 2017 -0500 Commit: Kitware Robot CommitDate: Fri Feb 3 00:01:05 2017 -0500 CMake Nightly Date Stamp diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 021b939..fd32907 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 7) -set(CMake_VERSION_PATCH 20170202) +set(CMake_VERSION_PATCH 20170203) #set(CMake_VERSION_RC 1) ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From cmake-commits at cmake.org Fri Feb 3 06:08:47 2017 From: cmake-commits at cmake.org (cmake-commits at cmake.org) Date: Fri, 3 Feb 2017 11:08:47 +0000 (UTC) Subject: # Santander Brasil S.A - Smiles Gol - Comunicado de expiração 2017. (54397) Message-ID: <20170203110847.F2645233E1@asd-9.advogadosdobrasil2.com.br> An HTML attachment was scrubbed... URL: From brad.king at kitware.com Fri Feb 3 09:11:59 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 3 Feb 2017 09:11:59 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2518-gf50c357 Message-ID: <20170203141159.430F5F3676@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via f50c35777f571e941dcc9a5f1f1696babe885b6e (commit) via a87b7cf205dc6952be402e7caf509be6d3842383 (commit) via 812615097035bacfa405a5b87312a9385e93cccb (commit) from 50be50f8fd017a4f014aded68d81e1955382db63 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f50c35777f571e941dcc9a5f1f1696babe885b6e commit f50c35777f571e941dcc9a5f1f1696babe885b6e Merge: 50be50f a87b7cf Author: Brad King AuthorDate: Fri Feb 3 09:11:58 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 3 09:11:58 2017 -0500 Merge topic 'FindHDF5-fix-HDF5_ROOT' into next a87b7cf2 fixup! FindHDF5: Fix command-line parsing argument extraction order 81261509 FindHDF5: Restore fallback to static libraries https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a87b7cf205dc6952be402e7caf509be6d3842383 commit a87b7cf205dc6952be402e7caf509be6d3842383 Author: Brad King AuthorDate: Fri Feb 3 09:09:17 2017 -0500 Commit: Brad King CommitDate: Fri Feb 3 09:09:17 2017 -0500 fixup! FindHDF5: Fix command-line parsing argument extraction order diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake index f73abcf..b10e313 100644 --- a/Modules/FindHDF5.cmake +++ b/Modules/FindHDF5.cmake @@ -356,7 +356,7 @@ macro( _HDF5_parse_compile_line elseif("${arg}" MATCHES "^-L(.*)$") # library search path list(APPEND ${library_paths} "${CMAKE_MATCH_1}") - elseif("${arg}" MATCHES "^-l(.*)hl$") + elseif("${arg}" MATCHES "^-l(hdf5.*hl.*)$") # library name (hl) list(APPEND ${libraries_hl} "${CMAKE_MATCH_1}") elseif("${arg}" MATCHES "^-l(.*)$") @@ -371,7 +371,7 @@ macro( _HDF5_parse_compile_line get_filename_component(_HDF5_LNAME "${arg}" NAME_WE) string(REGEX REPLACE "^lib" "" _HDF5_LNAME "${_HDF5_LNAME}") list(APPEND ${library_paths} "${_HDF5_LPATH}") - if(_HDF5_LNAME MATCHES ".*hl") + if(_HDF5_LNAME MATCHES "hdf5.*hl") list(APPEND ${libraries_hl} "${_HDF5_LNAME}") else() list(APPEND ${libraries} "${_HDF5_LNAME}") https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=812615097035bacfa405a5b87312a9385e93cccb commit 812615097035bacfa405a5b87312a9385e93cccb Author: Brad King AuthorDate: Fri Feb 3 08:51:52 2017 -0500 Commit: Brad King CommitDate: Fri Feb 3 08:57:00 2017 -0500 FindHDF5: Restore fallback to static libraries Since commit v3.6.1~6^2~2 (FindHDF5: Fix h5cc arg parsing to work with homebrew on Mac, 2016-07-11) we treated `HDF5_USE_STATIC_LIBRARIES` OFF as a requirement for shared libraries. It is just supposed to be a preference. Even if `HDF5_USE_STATIC_LIBRARIES` is not set we should still fall back to finding static libraries if shared libraries are not available. Issue: #16566 diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake index 4f79a32..f73abcf 100644 --- a/Modules/FindHDF5.cmake +++ b/Modules/FindHDF5.cmake @@ -518,28 +518,26 @@ if(NOT HDF5_FOUND) ) set(HDF5_${__lang}_LIBRARIES) - set(_HDF5_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) - if(HDF5_USE_STATIC_LIBRARIES) - set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX}) - else() - set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_SHARED_LIBRARY_SUFFIX}) - endif() - foreach(L IN LISTS HDF5_${__lang}_LIBRARY_NAMES) + set(_HDF5_SEARCH_NAMES_LOCAL) if(x"${L}" MATCHES "hdf5") # hdf5 library set(_HDF5_SEARCH_OPTS_LOCAL ${_HDF5_SEARCH_OPTS}) + if(UNIX AND HDF5_USE_STATIC_LIBRARIES) + set(_HDF5_SEARCH_NAMES_LOCAL lib${L}.a) + endif() else() # external library set(_HDF5_SEARCH_OPTS_LOCAL) endif() find_library(HDF5_${__lang}_LIBRARY_${L} - NAMES ${L} + NAMES ${_HDF5_SEARCH_NAMES_LOCAL} ${L} NAMES_PER_DIR HINTS ${HDF5_${__lang}_LIBRARY_DIRS} ${HDF5_ROOT} ${_HDF5_SEARCH_OPTS_LOCAL} ) unset(_HDF5_SEARCH_OPTS_LOCAL) + unset(_HDF5_SEARCH_NAMES_LOCAL) if(HDF5_${__lang}_LIBRARY_${L}) list(APPEND HDF5_${__lang}_LIBRARIES ${HDF5_${__lang}_LIBRARY_${L}}) else() @@ -549,20 +547,25 @@ if(NOT HDF5_FOUND) if(FIND_HL) set(HDF5_${__lang}_HL_LIBRARIES) foreach(L IN LISTS HDF5_${__lang}_HL_LIBRARY_NAMES) + set(_HDF5_SEARCH_NAMES_LOCAL) if("x${L}" MATCHES "hdf5") # hdf5 library set(_HDF5_SEARCH_OPTS_LOCAL ${_HDF5_SEARCH_OPTS}) + if(UNIX AND HDF5_USE_STATIC_LIBRARIES) + set(_HDF5_SEARCH_NAMES_LOCAL lib${L}.a) + endif() else() # external library set(_HDF5_SEARCH_OPTS_LOCAL) endif() find_library(HDF5_${__lang}_LIBRARY_${L} - NAMES ${L} + NAMES ${_HDF5_SEARCH_NAMES_LOCAL} ${L} NAMES_PER_DIR HINTS ${HDF5_${__lang}_LIBRARY_DIRS} ${HDF5_ROOT} ${_HDF5_SEARCH_OPTS_LOCAL} ) unset(_HDF5_SEARCH_OPTS_LOCAL) + unset(_HDF5_SEARCH_NAMES_LOCAL) if(HDF5_${__lang}_LIBRARY_${L}) list(APPEND HDF5_${__lang}_HL_LIBRARIES ${HDF5_${__lang}_LIBRARY_${L}}) else() @@ -572,8 +575,6 @@ if(NOT HDF5_FOUND) set(HDF5_HL_FOUND True) endif() - set(CMAKE_FIND_LIBRARY_SUFFIXES ${_HDF5_CMAKE_FIND_LIBRARY_SUFFIXES}) - set(HDF5_${__lang}_FOUND True) mark_as_advanced(HDF5_${__lang}_DEFINITIONS) mark_as_advanced(HDF5_${__lang}_INCLUDE_DIRS) ----------------------------------------------------------------------- Summary of changes: Modules/FindHDF5.cmake | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 3 09:14:08 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 3 Feb 2017 09:14:08 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2524-gcac9e0b Message-ID: <20170203141408.A4444F7863@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via cac9e0b28df85225438816458ceab01ba4d534db (commit) via 5564c01703c20f992769f4e152bcc74ceddc5942 (commit) via 4908969f578ded9d87f244bd8ada65ba0c51cf28 (commit) via 77f6d22ad1f1b461297a463eb5f40fbb0d0825aa (commit) via 3d5ad7236c8ce444323fb63cd9ff50fb5f757830 (commit) via ae89967f9dc9308003630531ef34764030f98bd0 (commit) from f50c35777f571e941dcc9a5f1f1696babe885b6e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=cac9e0b28df85225438816458ceab01ba4d534db commit cac9e0b28df85225438816458ceab01ba4d534db Merge: f50c357 5564c01 Author: Brad King AuthorDate: Fri Feb 3 09:14:08 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 3 09:14:08 2017 -0500 Merge topic 'FindHDF5-fix-HDF5_ROOT' into next 5564c017 FindHDF5: Restore fallback to static libraries 4908969f FindHDF5: Fix search with HDF5_ROOT 77f6d22a FindHDF5: Use keywords in find_library calls 3d5ad723 FindHDF5: Initialize/finalize internal search options variable ae89967f FindHDF5: Fix command-line parsing argument extraction order https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=5564c01703c20f992769f4e152bcc74ceddc5942 commit 5564c01703c20f992769f4e152bcc74ceddc5942 Author: Brad King AuthorDate: Fri Feb 3 08:51:52 2017 -0500 Commit: Brad King CommitDate: Fri Feb 3 09:12:06 2017 -0500 FindHDF5: Restore fallback to static libraries Since commit v3.6.1~6^2~2 (FindHDF5: Fix h5cc arg parsing to work with homebrew on Mac, 2016-07-11) we treated `HDF5_USE_STATIC_LIBRARIES` OFF as a requirement for shared libraries. It is just supposed to be a preference. Even if `HDF5_USE_STATIC_LIBRARIES` is not set we should still fall back to finding static libraries if shared libraries are not available. Issue: #16566 diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake index 94a8729..b10e313 100644 --- a/Modules/FindHDF5.cmake +++ b/Modules/FindHDF5.cmake @@ -518,28 +518,26 @@ if(NOT HDF5_FOUND) ) set(HDF5_${__lang}_LIBRARIES) - set(_HDF5_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) - if(HDF5_USE_STATIC_LIBRARIES) - set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX}) - else() - set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_SHARED_LIBRARY_SUFFIX}) - endif() - foreach(L IN LISTS HDF5_${__lang}_LIBRARY_NAMES) + set(_HDF5_SEARCH_NAMES_LOCAL) if(x"${L}" MATCHES "hdf5") # hdf5 library set(_HDF5_SEARCH_OPTS_LOCAL ${_HDF5_SEARCH_OPTS}) + if(UNIX AND HDF5_USE_STATIC_LIBRARIES) + set(_HDF5_SEARCH_NAMES_LOCAL lib${L}.a) + endif() else() # external library set(_HDF5_SEARCH_OPTS_LOCAL) endif() find_library(HDF5_${__lang}_LIBRARY_${L} - NAMES ${L} + NAMES ${_HDF5_SEARCH_NAMES_LOCAL} ${L} NAMES_PER_DIR HINTS ${HDF5_${__lang}_LIBRARY_DIRS} ${HDF5_ROOT} ${_HDF5_SEARCH_OPTS_LOCAL} ) unset(_HDF5_SEARCH_OPTS_LOCAL) + unset(_HDF5_SEARCH_NAMES_LOCAL) if(HDF5_${__lang}_LIBRARY_${L}) list(APPEND HDF5_${__lang}_LIBRARIES ${HDF5_${__lang}_LIBRARY_${L}}) else() @@ -549,20 +547,25 @@ if(NOT HDF5_FOUND) if(FIND_HL) set(HDF5_${__lang}_HL_LIBRARIES) foreach(L IN LISTS HDF5_${__lang}_HL_LIBRARY_NAMES) + set(_HDF5_SEARCH_NAMES_LOCAL) if("x${L}" MATCHES "hdf5") # hdf5 library set(_HDF5_SEARCH_OPTS_LOCAL ${_HDF5_SEARCH_OPTS}) + if(UNIX AND HDF5_USE_STATIC_LIBRARIES) + set(_HDF5_SEARCH_NAMES_LOCAL lib${L}.a) + endif() else() # external library set(_HDF5_SEARCH_OPTS_LOCAL) endif() find_library(HDF5_${__lang}_LIBRARY_${L} - NAMES ${L} + NAMES ${_HDF5_SEARCH_NAMES_LOCAL} ${L} NAMES_PER_DIR HINTS ${HDF5_${__lang}_LIBRARY_DIRS} ${HDF5_ROOT} ${_HDF5_SEARCH_OPTS_LOCAL} ) unset(_HDF5_SEARCH_OPTS_LOCAL) + unset(_HDF5_SEARCH_NAMES_LOCAL) if(HDF5_${__lang}_LIBRARY_${L}) list(APPEND HDF5_${__lang}_HL_LIBRARIES ${HDF5_${__lang}_LIBRARY_${L}}) else() @@ -572,8 +575,6 @@ if(NOT HDF5_FOUND) set(HDF5_HL_FOUND True) endif() - set(CMAKE_FIND_LIBRARY_SUFFIXES ${_HDF5_CMAKE_FIND_LIBRARY_SUFFIXES}) - set(HDF5_${__lang}_FOUND True) mark_as_advanced(HDF5_${__lang}_DEFINITIONS) mark_as_advanced(HDF5_${__lang}_INCLUDE_DIRS) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4908969f578ded9d87f244bd8ada65ba0c51cf28 commit 4908969f578ded9d87f244bd8ada65ba0c51cf28 Author: Brad King AuthorDate: Thu Feb 2 09:21:21 2017 -0500 Commit: Brad King CommitDate: Fri Feb 3 09:12:05 2017 -0500 FindHDF5: Fix search with HDF5_ROOT Refactoring in commit v3.6.0-rc1~72^2 (HDF5: Rework component searching to correctly find HL for all bindings, 2016-05-12) turned off a large amount of its logic when HDF5_ROOT is set. This caused use of the hdf5 compiler wrapper to extract all needed libraries (e.g. z, dl as dependencies of hdf5 static libraries) to be skipped when using HDF5_ROOT. Fix the search logic to honor HDF5_ROOT in all code paths. Restrict the search for hdf5-specific components to this root, but allow external libraries to be found anywhere. Fixes: #16566 diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake index f07d0c7..94a8729 100644 --- a/Modules/FindHDF5.cmake +++ b/Modules/FindHDF5.cmake @@ -383,10 +383,18 @@ endmacro() if(NOT HDF5_ROOT) set(HDF5_ROOT $ENV{HDF5_ROOT}) endif() +if(HDF5_ROOT) + set(_HDF5_SEARCH_OPTS NO_DEFAULT_PATH) +else() + set(_HDF5_SEARCH_OPTS) +endif() # Try to find HDF5 using an installed hdf5-config.cmake -if(NOT HDF5_FOUND AND NOT HDF5_ROOT) - find_package(HDF5 QUIET NO_MODULE) +if(NOT HDF5_FOUND) + find_package(HDF5 QUIET NO_MODULE + HINTS ${HDF5_ROOT} + ${_HDF5_SEARCH_OPTS} + ) if( HDF5_FOUND) set(HDF5_IS_PARALLEL ${HDF5_ENABLE_PARALLEL}) set(HDF5_INCLUDE_DIRS ${HDF5_INCLUDE_DIR}) @@ -440,7 +448,7 @@ if(NOT HDF5_FOUND AND NOT HDF5_ROOT) endif() endif() -if(NOT HDF5_FOUND AND NOT HDF5_ROOT) +if(NOT HDF5_FOUND) set(_HDF5_NEED_TO_SEARCH False) set(HDF5_COMPILER_NO_INTERROGATE True) # Only search for languages we've enabled @@ -488,8 +496,10 @@ if(NOT HDF5_FOUND AND NOT HDF5_ROOT) # search options with the wrapper find_program(HDF5_${__lang}_COMPILER_EXECUTABLE NAMES ${HDF5_${__lang}_COMPILER_NAMES} NAMES_PER_DIR + HINTS ${HDF5_ROOT} PATH_SUFFIXES bin Bin DOC "HDF5 ${__lang} Wrapper compiler. Used only to detect HDF5 compile flags." + ${_HDF5_SEARCH_OPTS} ) mark_as_advanced( HDF5_${__lang}_COMPILER_EXECUTABLE ) unset(HDF5_${__lang}_COMPILER_NAMES) @@ -516,10 +526,20 @@ if(NOT HDF5_FOUND AND NOT HDF5_ROOT) endif() foreach(L IN LISTS HDF5_${__lang}_LIBRARY_NAMES) + if(x"${L}" MATCHES "hdf5") + # hdf5 library + set(_HDF5_SEARCH_OPTS_LOCAL ${_HDF5_SEARCH_OPTS}) + else() + # external library + set(_HDF5_SEARCH_OPTS_LOCAL) + endif() find_library(HDF5_${__lang}_LIBRARY_${L} NAMES ${L} HINTS ${HDF5_${__lang}_LIBRARY_DIRS} + ${HDF5_ROOT} + ${_HDF5_SEARCH_OPTS_LOCAL} ) + unset(_HDF5_SEARCH_OPTS_LOCAL) if(HDF5_${__lang}_LIBRARY_${L}) list(APPEND HDF5_${__lang}_LIBRARIES ${HDF5_${__lang}_LIBRARY_${L}}) else() @@ -529,10 +549,20 @@ if(NOT HDF5_FOUND AND NOT HDF5_ROOT) if(FIND_HL) set(HDF5_${__lang}_HL_LIBRARIES) foreach(L IN LISTS HDF5_${__lang}_HL_LIBRARY_NAMES) + if("x${L}" MATCHES "hdf5") + # hdf5 library + set(_HDF5_SEARCH_OPTS_LOCAL ${_HDF5_SEARCH_OPTS}) + else() + # external library + set(_HDF5_SEARCH_OPTS_LOCAL) + endif() find_library(HDF5_${__lang}_LIBRARY_${L} NAMES ${L} HINTS ${HDF5_${__lang}_LIBRARY_DIRS} + ${HDF5_ROOT} + ${_HDF5_SEARCH_OPTS_LOCAL} ) + unset(_HDF5_SEARCH_OPTS_LOCAL) if(HDF5_${__lang}_LIBRARY_${L}) list(APPEND HDF5_${__lang}_HL_LIBRARIES ${HDF5_${__lang}_LIBRARY_${L}}) else() @@ -614,11 +644,6 @@ elseif(NOT HDF5_FOUND AND NOT _HDF5_NEED_TO_SEARCH) endif() endif() -if(HDF5_ROOT) - set(_HDF5_SEARCH_OPTS NO_DEFAULT_PATH) -else() - set(_HDF5_SEARCH_OPTS) -endif() find_program( HDF5_DIFF_EXECUTABLE NAMES h5diff HINTS ${HDF5_ROOT} https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=77f6d22ad1f1b461297a463eb5f40fbb0d0825aa commit 77f6d22ad1f1b461297a463eb5f40fbb0d0825aa Author: Brad King AuthorDate: Thu Feb 2 09:16:47 2017 -0500 Commit: Brad King CommitDate: Fri Feb 3 09:12:05 2017 -0500 FindHDF5: Use keywords in find_library calls Clarify the purpose of each argument. diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake index 99b2309..f07d0c7 100644 --- a/Modules/FindHDF5.cmake +++ b/Modules/FindHDF5.cmake @@ -516,7 +516,10 @@ if(NOT HDF5_FOUND AND NOT HDF5_ROOT) endif() foreach(L IN LISTS HDF5_${__lang}_LIBRARY_NAMES) - find_library(HDF5_${__lang}_LIBRARY_${L} ${L} ${HDF5_${__lang}_LIBRARY_DIRS}) + find_library(HDF5_${__lang}_LIBRARY_${L} + NAMES ${L} + HINTS ${HDF5_${__lang}_LIBRARY_DIRS} + ) if(HDF5_${__lang}_LIBRARY_${L}) list(APPEND HDF5_${__lang}_LIBRARIES ${HDF5_${__lang}_LIBRARY_${L}}) else() @@ -526,7 +529,10 @@ if(NOT HDF5_FOUND AND NOT HDF5_ROOT) if(FIND_HL) set(HDF5_${__lang}_HL_LIBRARIES) foreach(L IN LISTS HDF5_${__lang}_HL_LIBRARY_NAMES) - find_library(HDF5_${__lang}_LIBRARY_${L} ${L} ${HDF5_${__lang}_LIBRARY_DIRS}) + find_library(HDF5_${__lang}_LIBRARY_${L} + NAMES ${L} + HINTS ${HDF5_${__lang}_LIBRARY_DIRS} + ) if(HDF5_${__lang}_LIBRARY_${L}) list(APPEND HDF5_${__lang}_HL_LIBRARIES ${HDF5_${__lang}_LIBRARY_${L}}) else() https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3d5ad7236c8ce444323fb63cd9ff50fb5f757830 commit 3d5ad7236c8ce444323fb63cd9ff50fb5f757830 Author: Brad King AuthorDate: Thu Feb 2 09:13:46 2017 -0500 Commit: Brad King CommitDate: Fri Feb 3 09:12:05 2017 -0500 FindHDF5: Initialize/finalize internal search options variable While at it, use a more private name. diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake index cf84918..99b2309 100644 --- a/Modules/FindHDF5.cmake +++ b/Modules/FindHDF5.cmake @@ -609,13 +609,15 @@ elseif(NOT HDF5_FOUND AND NOT _HDF5_NEED_TO_SEARCH) endif() if(HDF5_ROOT) - set(SEARCH_OPTS NO_DEFAULT_PATH) + set(_HDF5_SEARCH_OPTS NO_DEFAULT_PATH) +else() + set(_HDF5_SEARCH_OPTS) endif() find_program( HDF5_DIFF_EXECUTABLE NAMES h5diff HINTS ${HDF5_ROOT} PATH_SUFFIXES bin Bin - ${SEARCH_OPTS} + ${_HDF5_SEARCH_OPTS} DOC "HDF5 file differencing tool." ) mark_as_advanced( HDF5_DIFF_EXECUTABLE ) @@ -644,7 +646,7 @@ if( NOT HDF5_FOUND ) HINTS ${HDF5_ROOT} PATHS $ENV{HOME}/.local/include PATH_SUFFIXES include Include - ${SEARCH_OPTS} + ${_HDF5_SEARCH_OPTS} ) mark_as_advanced(HDF5_${LANGUAGE}_INCLUDE_DIR) list(APPEND HDF5_INCLUDE_DIRS ${HDF5_${__lang}_INCLUDE_DIR}) @@ -668,12 +670,12 @@ if( NOT HDF5_FOUND ) find_library(HDF5_${LIB}_LIBRARY_DEBUG NAMES ${THIS_LIBRARY_SEARCH_DEBUG} HINTS ${HDF5_ROOT} PATH_SUFFIXES lib Lib - ${SEARCH_OPTS} + ${_HDF5_SEARCH_OPTS} ) find_library( HDF5_${LIB}_LIBRARY_RELEASE NAMES ${THIS_LIBRARY_SEARCH_RELEASE} HINTS ${HDF5_ROOT} PATH_SUFFIXES lib Lib - ${SEARCH_OPTS} + ${_HDF5_SEARCH_OPTS} ) select_library_configurations( HDF5_${LIB} ) list(APPEND HDF5_${__lang}_LIBRARIES ${HDF5_${LIB}_LIBRARY}) @@ -705,12 +707,12 @@ if( NOT HDF5_FOUND ) find_library(HDF5_${LIB}_LIBRARY_DEBUG NAMES ${THIS_LIBRARY_SEARCH_DEBUG} HINTS ${HDF5_ROOT} PATH_SUFFIXES lib Lib - ${SEARCH_OPTS} + ${_HDF5_SEARCH_OPTS} ) find_library( HDF5_${LIB}_LIBRARY_RELEASE NAMES ${THIS_LIBRARY_SEARCH_RELEASE} HINTS ${HDF5_ROOT} PATH_SUFFIXES lib Lib - ${SEARCH_OPTS} + ${_HDF5_SEARCH_OPTS} ) select_library_configurations( HDF5_${LIB} ) list(APPEND HDF5_${__lang}_HL_LIBRARIES ${HDF5_${LIB}_LIBRARY}) @@ -785,3 +787,5 @@ find_package_handle_standard_args(HDF5 VERSION_VAR HDF5_VERSION HANDLE_COMPONENTS ) + +unset(_HDF5_SEARCH_OPTS) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ae89967f9dc9308003630531ef34764030f98bd0 commit ae89967f9dc9308003630531ef34764030f98bd0 Author: Brad King AuthorDate: Thu Feb 2 10:05:51 2017 -0500 Commit: Brad King CommitDate: Fri Feb 3 09:12:04 2017 -0500 FindHDF5: Fix command-line parsing argument extraction order Re-implement our internal `_HDF5_parse_compile_line` helper to process command line arguments all at once and in order. Otherwise the libraries named by absolute path and those named by `-l` arguments are not kept in order. The new implementation will not handle separate arguments like `-I /path/to/include/dir` but I have not seen the HDF5 compiler wrappers produce this form. If necessary the parsing loop can be extended with a state variable to keep track of such pairs. diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake index 6e5a25e..cf84918 100644 --- a/Modules/FindHDF5.cmake +++ b/Modules/FindHDF5.cmake @@ -340,62 +340,44 @@ macro( _HDF5_parse_compile_line libraries libraries_hl) - # Match the include paths - set( RE " -I *([^\" ]+|\"[^\"]+\")") - string( REGEX MATCHALL "${RE}" include_path_flags "${${compile_line_var}}") - foreach( IPATH IN LISTS include_path_flags ) - string( REGEX REPLACE "${RE}" "\\1" IPATH "${IPATH}" ) - list( APPEND ${include_paths} ${IPATH} ) - endforeach() - - # Match the definitions - set( RE " -D([^ ]*)") - string( REGEX MATCHALL "${RE}" definition_flags "${${compile_line_var}}" ) - foreach( DEF IN LISTS definition_flags ) - string( STRIP "${DEF}" DEF ) - list( APPEND ${definitions} ${DEF} ) - endforeach() - - # Match the library paths - set( RE " -L *([^\" ]+|\"[^\"]+\")") - string( REGEX MATCHALL "${RE}" library_path_flags "${${compile_line_var}}") - foreach( LPATH IN LISTS library_path_flags ) - string( REGEX REPLACE "${RE}" "\\1" LPATH "${LPATH}" ) - list( APPEND ${library_paths} ${LPATH} ) - endforeach() - - # now search for the lib names specified in the compile line (match -l...) - # match only -l's preceded by a space or comma - set( RE " -l *([^\" ]+|\"[^\"]+\")") - string( REGEX MATCHALL "${RE}" library_name_flags "${${compile_line_var}}") - foreach( LNAME IN LISTS library_name_flags ) - string( REGEX REPLACE "${RE}" "\\1" LNAME "${LNAME}" ) - if(LNAME MATCHES ".*hl") - list(APPEND ${libraries_hl} ${LNAME}) - else() - list(APPEND ${libraries} ${LNAME}) - endif() - endforeach() + if(UNIX) + separate_arguments(_HDF5_COMPILE_ARGS UNIX_COMMAND "${${compile_line_var}}") + else() + separate_arguments(_HDF5_COMPILE_ARGS WINDOWS_COMMAND "${${compile_line_var}}") + endif() - # now search for full library paths with no flags - set( RE " ([^\" ]+|\"[^\"]+\")") - string( REGEX MATCHALL "${RE}" library_name_noflags "${${compile_line_var}}") - foreach( LIB IN LISTS library_name_noflags ) - string( REGEX REPLACE "${RE}" "\\1" LIB "${LIB}" ) - get_filename_component(LIB "${LIB}" ABSOLUTE) - if(NOT EXISTS ${LIB} OR IS_DIRECTORY ${LIB}) - continue() - endif() - get_filename_component(LPATH ${LIB} DIRECTORY) - get_filename_component(LNAME ${LIB} NAME_WE) - string( REGEX REPLACE "^lib" "" LNAME ${LNAME} ) - list( APPEND ${library_paths} ${LPATH} ) - if(LNAME MATCHES ".*hl") - list(APPEND ${libraries_hl} ${LNAME}) - else() - list(APPEND ${libraries} ${LNAME}) - endif() - endforeach() + foreach(arg IN LISTS _HDF5_COMPILE_ARGS) + if("${arg}" MATCHES "^-I(.*)$") + # include directory + list(APPEND ${include_paths} "${CMAKE_MATCH_1}") + elseif("${arg}" MATCHES "^-D(.*)$") + # compile definition + list(APPEND ${definitions} "${CMAKE_MATCH_1}") + elseif("${arg}" MATCHES "^-L(.*)$") + # library search path + list(APPEND ${library_paths} "${CMAKE_MATCH_1}") + elseif("${arg}" MATCHES "^-l(hdf5.*hl.*)$") + # library name (hl) + list(APPEND ${libraries_hl} "${CMAKE_MATCH_1}") + elseif("${arg}" MATCHES "^-l(.*)$") + # library name + list(APPEND ${libraries} "${CMAKE_MATCH_1}") + elseif("${arg}" MATCHES "^(.:)?[/\\].*\\.(a|so|dylib|sl|lib)$") + # library file + if(NOT EXISTS "${arg}") + continue() + endif() + get_filename_component(_HDF5_LPATH "${arg}" DIRECTORY) + get_filename_component(_HDF5_LNAME "${arg}" NAME_WE) + string(REGEX REPLACE "^lib" "" _HDF5_LNAME "${_HDF5_LNAME}") + list(APPEND ${library_paths} "${_HDF5_LPATH}") + if(_HDF5_LNAME MATCHES "hdf5.*hl") + list(APPEND ${libraries_hl} "${_HDF5_LNAME}") + else() + list(APPEND ${libraries} "${_HDF5_LNAME}") + endif() + endif() + endforeach() endmacro() if(NOT HDF5_ROOT) ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 3 09:32:47 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 3 Feb 2017 09:32:47 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1280-gfb26fcb Message-ID: <20170203143247.8FD53FA56B@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via fb26fcb261c927687f66b556df83ff6546f9bbd9 (commit) via 37ed860ad1e71f347513a38432640f7dda5c07ee (commit) via 94a8ee6fd0ba487437579bb224500b9f46c2819c (commit) via 940bf6a4a427c8edfd975bf078a3ea331847f72a (commit) via f26ca5a1953e7f260bc23d30c5d35cc071a6f6ab (commit) from 6286d26ca6408cfc45031536ed54b1679e6d5ac2 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=fb26fcb261c927687f66b556df83ff6546f9bbd9 commit fb26fcb261c927687f66b556df83ff6546f9bbd9 Merge: 6286d26 37ed860 Author: Brad King AuthorDate: Fri Feb 3 09:32:45 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 3 09:32:45 2017 -0500 Merge topic 'gcc-features' 37ed860a GNU C++: record that -fvisibility-inlines-hidden is available since 4.0 94a8ee6f GNU C: record that C99 is available since at least 3.4 940bf6a4 Tests/Module/WCDH: only use -Werror=undef compiler flag if actually supported f26ca5a1 Tests/Module/WCDH: write multi_file_compiler_detection.h before using it ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-compile-features.7.rst | 8 ++++++ Help/release/dev/gcc-features.rst | 5 ++++ Modules/Compiler/GNU-C-FeatureTests.cmake | 10 +++---- Modules/Compiler/GNU-C.cmake | 9 +++---- Modules/Compiler/GNU-CXX.cmake | 2 +- .../WriteCompilerDetectionHeader/CMakeLists.txt | 28 +++++++++++--------- 6 files changed, 39 insertions(+), 23 deletions(-) create mode 100644 Help/release/dev/gcc-features.rst hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 3 09:33:11 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 3 Feb 2017 09:33:11 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2527-gf010bae Message-ID: <20170203143311.2E5B8FA565@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via f010baec3bc9df9a1fb23aab03128a2d203d6787 (commit) via fb26fcb261c927687f66b556df83ff6546f9bbd9 (commit) via 6286d26ca6408cfc45031536ed54b1679e6d5ac2 (commit) from cac9e0b28df85225438816458ceab01ba4d534db (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f010baec3bc9df9a1fb23aab03128a2d203d6787 commit f010baec3bc9df9a1fb23aab03128a2d203d6787 Merge: cac9e0b fb26fcb Author: Brad King AuthorDate: Fri Feb 3 09:32:54 2017 -0500 Commit: Brad King CommitDate: Fri Feb 3 09:32:54 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 3 10:58:50 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 3 Feb 2017 10:58:50 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2529-g70284f1 Message-ID: <20170203155850.4763AFA36F@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 70284f1b4c89252e2801915312e1c5acac7cb61e (commit) via cf0d8f1fd6ad5d4bc85d7788af459238df494260 (commit) from f010baec3bc9df9a1fb23aab03128a2d203d6787 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=70284f1b4c89252e2801915312e1c5acac7cb61e commit 70284f1b4c89252e2801915312e1c5acac7cb61e Merge: f010bae cf0d8f1 Author: Brad King AuthorDate: Fri Feb 3 10:58:49 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 3 10:58:49 2017 -0500 Merge topic 'FindHDF5-fix-HDF5_ROOT' into next cf0d8f1f FindHDF5: Restore HDF5_INCLUDE_DIR in all code paths https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=cf0d8f1fd6ad5d4bc85d7788af459238df494260 commit cf0d8f1fd6ad5d4bc85d7788af459238df494260 Author: Brad King AuthorDate: Fri Feb 3 10:57:10 2017 -0500 Commit: Brad King CommitDate: Fri Feb 3 10:57:10 2017 -0500 FindHDF5: Restore HDF5_INCLUDE_DIR in all code paths This compatibility variable should be set no matter which method was used to find HDF5. Even if `HDF5_INCLUDE_DIRS` was set by copying the `HDF5_INCLUDE_DIR` value from `hdf5-config.cmake` it will not hurt to copy the same value back. Issue: #16566 diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake index b10e313..e1199a7 100644 --- a/Modules/FindHDF5.cmake +++ b/Modules/FindHDF5.cmake @@ -796,17 +796,18 @@ if( NOT HDF5_FOUND ) "HDF5 library compiled with parallel IO support" ) mark_as_advanced( HDF5_IS_PARALLEL ) - # For backwards compatibility we set HDF5_INCLUDE_DIR to the value of - # HDF5_INCLUDE_DIRS - if( HDF5_INCLUDE_DIRS ) - set( HDF5_INCLUDE_DIR "${HDF5_INCLUDE_DIRS}" ) - endif() set(HDF5_REQUIRED_VARS HDF5_LIBRARIES HDF5_INCLUDE_DIRS) if(FIND_HL) list(APPEND HDF5_REQUIRED_VARS HDF5_HL_LIBRARIES) endif() endif() +# For backwards compatibility we set HDF5_INCLUDE_DIR to the value of +# HDF5_INCLUDE_DIRS +if( HDF5_INCLUDE_DIRS ) + set( HDF5_INCLUDE_DIR "${HDF5_INCLUDE_DIRS}" ) +endif() + # If HDF5_REQUIRED_VARS is empty at this point, then it's likely that # something external is trying to explicitly pass already found # locations ----------------------------------------------------------------------- Summary of changes: Modules/FindHDF5.cmake | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 3 11:47:03 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 3 Feb 2017 11:47:03 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2531-ga792ec4 Message-ID: <20170203164703.0E018F761B@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via a792ec426975260a7fe6fb87ae0972030a06d2c6 (commit) via 4bea231d1dff8063c2db37aa4344d36994ec6b46 (commit) from 70284f1b4c89252e2801915312e1c5acac7cb61e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a792ec426975260a7fe6fb87ae0972030a06d2c6 commit a792ec426975260a7fe6fb87ae0972030a06d2c6 Merge: 70284f1 4bea231 Author: Brad King AuthorDate: Fri Feb 3 11:47:02 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 3 11:47:02 2017 -0500 Merge topic 'vs-quote-rerun-paths' into next 4bea231d VS: Fix quoting of special characters in cmake re-run check commands https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4bea231d1dff8063c2db37aa4344d36994ec6b46 commit 4bea231d1dff8063c2db37aa4344d36994ec6b46 Author: Brad King AuthorDate: Fri Feb 3 10:08:37 2017 -0500 Commit: Brad King CommitDate: Fri Feb 3 10:08:37 2017 -0500 VS: Fix quoting of special characters in cmake re-run check commands Fix our calls to `AddCustomCommandToOutput` for adding cmake re-run check commands to disable old-style quoting in favor of the full quoting logic. This is necessary when paths contain special characters like `&` that old-style quoting logic does not handle. Reported-by: Steven Cook Fixes: #16585 diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index e961a3d..c4f7a33 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -310,7 +310,7 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() std::vector no_byproducts; if (cmSourceFile* file = mf->AddCustomCommandToOutput( stamps, no_byproducts, listFiles, no_main_dependency, commandLines, - "Checking Build System", no_working_directory, true)) { + "Checking Build System", no_working_directory, true, false)) { gt->AddSource(file->GetFullPath()); } else { cmSystemTools::Error("Error adding rule for ", stamps[0].c_str()); diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 49b057b..88c25b8 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -273,7 +273,7 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule() cmSystemTools::CollapseFullPath(stampName.c_str()); this->Makefile->AddCustomCommandToOutput( fullpathStampName.c_str(), listFiles, makefileIn.c_str(), commandLines, - comment.c_str(), no_working_directory, true); + comment.c_str(), no_working_directory, true, false); if (cmSourceFile* file = this->Makefile->GetSource(makefileIn.c_str())) { return file; } else { ----------------------------------------------------------------------- Summary of changes: Source/cmGlobalVisualStudio8Generator.cxx | 2 +- Source/cmLocalVisualStudio7Generator.cxx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 3 13:14:54 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 3 Feb 2017 13:14:54 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2535-gf28a0de Message-ID: <20170203181454.8125EF3841@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via f28a0de44953afab170272a04dca84432c4e0768 (commit) via fafb38bf32458bb9f7514a7c6483ca324a15fc22 (commit) via f801bf68320dc6bbccd8f420d3714f61d201b5f3 (commit) via b200010717b18854a765a9cbe2c3fc72d58fdc1c (commit) from a792ec426975260a7fe6fb87ae0972030a06d2c6 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f28a0de44953afab170272a04dca84432c4e0768 commit f28a0de44953afab170272a04dca84432c4e0768 Merge: a792ec4 fafb38b Author: Brad King AuthorDate: Fri Feb 3 13:14:53 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 3 13:14:53 2017 -0500 Merge topic 'productbuild_signing' into next fafb38bf CPackProductBuild: Fixed a possible crash if the variables aren't defined f801bf68 CPackProductBuild: Add options to sign packages b2000107 CPackProductBuild: Add options to sign packages https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=fafb38bf32458bb9f7514a7c6483ca324a15fc22 commit fafb38bf32458bb9f7514a7c6483ca324a15fc22 Author: Roman W?ger AuthorDate: Fri Feb 3 18:30:11 2017 +0100 Commit: Roman W?ger CommitDate: Fri Feb 3 18:30:11 2017 +0100 CPackProductBuild: Fixed a possible crash if the variables aren't defined diff --git a/Source/CPack/cmCPackProductBuildGenerator.cxx b/Source/CPack/cmCPackProductBuildGenerator.cxx index 833a27e..07b539d 100644 --- a/Source/CPack/cmCPackProductBuildGenerator.cxx +++ b/Source/CPack/cmCPackProductBuildGenerator.cxx @@ -75,9 +75,9 @@ int cmCPackProductBuildGenerator::PackageFiles() std::string version = this->GetOption("CPACK_PACKAGE_VERSION"); std::string productbuild = this->GetOption("CPACK_COMMAND_PRODUCTBUILD"); - std::string identityName = + const char* identityName = this->GetOption("CPACK_PRODUCTBUILD_IDENTITY_NAME"); - std::string keychainPath = + const char* keychainPath = this->GetOption("CPACK_PRODUCTBUILD_KEYCHAIN_PATH"); pkgCmd << productbuild << " --distribution \"" << packageDirFileName @@ -86,9 +86,8 @@ int cmCPackProductBuildGenerator::PackageFiles() << "\"" << " --resources \"" << resDir << "\"" << " --version \"" << version << "\"" - << (identityName.empty() ? "" : " --sign \"" + identityName + "\"") - << (keychainPath.empty() ? "" - : " --keychain \"" + keychainPath + "\"") + << (identityName ? " --sign \"" + identityName + "\"" : "") + << (keychainPath ? " --keychain \"" + keychainPath + "\"" : "") << " \"" << packageFileNames[0] << "\""; // Run ProductBuild @@ -200,17 +199,16 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage( std::string version = this->GetOption("CPACK_PACKAGE_VERSION"); std::string pkgbuild = this->GetOption("CPACK_COMMAND_PKGBUILD"); - std::string identityName = this->GetOption("CPACK_PKGBUILD_IDENTITY_NAME"); - std::string keychainPath = this->GetOption("CPACK_PKGBUILD_KEYCHAIN_PATH"); + const char* identityName = this->GetOption("CPACK_PKGBUILD_IDENTITY_NAME"); + const char* keychainPath = this->GetOption("CPACK_PKGBUILD_KEYCHAIN_PATH"); pkgCmd << pkgbuild << " --root \"" << packageDir << "\"" << " --identifier \"" << pkgId << "\"" << " --scripts \"" << scriptDir << "\"" << " --version \"" << version << "\"" << " --install-location \"/\"" - << (identityName.empty() ? "" : " --sign \"" + identityName + "\"") - << (keychainPath.empty() ? "" - : " --keychain \"" + keychainPath + "\"") + << (identityName ? " --sign \"" + identityName + "\"" : "") + << (keychainPath ? " --keychain \"" + keychainPath + "\"" : "") << " \"" << packageFile << "\""; // Run ProductBuild https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f801bf68320dc6bbccd8f420d3714f61d201b5f3 commit f801bf68320dc6bbccd8f420d3714f61d201b5f3 Author: Roman W?ger AuthorDate: Fri Feb 3 09:31:39 2017 +0100 Commit: Roman W?ger CommitDate: Fri Feb 3 09:39:32 2017 +0100 CPackProductBuild: Add options to sign packages diff --git a/Source/CPack/cmCPackProductBuildGenerator.cxx b/Source/CPack/cmCPackProductBuildGenerator.cxx index 35b2ccc..833a27e 100644 --- a/Source/CPack/cmCPackProductBuildGenerator.cxx +++ b/Source/CPack/cmCPackProductBuildGenerator.cxx @@ -85,17 +85,11 @@ int cmCPackProductBuildGenerator::PackageFiles() << " --package-path \"" << packageDirFileName << "/Contents/Packages" << "\"" << " --resources \"" << resDir << "\"" - << " --version \"" << version << "\""; - - if (!identityName.empty()) { - pkgCmd << " --sign \"" << identityName << "\""; - } - - if (!keychainPath.empty()) { - pkgCmd << " --keychain \"" << keychainPath << "\""; - } - - pkgCmd << " \"" << packageFileNames[0] << "\""; + << " --version \"" << version << "\"" + << (identityName.empty() ? "" : " --sign \"" + identityName + "\"") + << (keychainPath.empty() ? "" + : " --keychain \"" + keychainPath + "\"") + << " \"" << packageFileNames[0] << "\""; // Run ProductBuild return RunProductBuild(pkgCmd.str()); @@ -213,17 +207,11 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage( << " --identifier \"" << pkgId << "\"" << " --scripts \"" << scriptDir << "\"" << " --version \"" << version << "\"" - << " --install-location \"/\""; - - if (!identityName.empty()) { - pkgCmd << " --sign \"" << identityName << "\""; - } - - if (!keychainPath.empty()) { - pkgCmd << " --keychain \"" << keychainPath << "\""; - } - - pkgCmd << " \"" << packageFile << "\""; + << " --install-location \"/\"" + << (identityName.empty() ? "" : " --sign \"" + identityName + "\"") + << (keychainPath.empty() ? "" + : " --keychain \"" + keychainPath + "\"") + << " \"" << packageFile << "\""; // Run ProductBuild return RunProductBuild(pkgCmd.str()); https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b200010717b18854a765a9cbe2c3fc72d58fdc1c commit b200010717b18854a765a9cbe2c3fc72d58fdc1c Author: Roman W?ger AuthorDate: Sun Jan 15 01:29:34 2017 +0100 Commit: Roman W?ger CommitDate: Fri Feb 3 09:39:32 2017 +0100 CPackProductBuild: Add options to sign packages diff --git a/Help/release/dev/cpack-productbuild-signing.rst b/Help/release/dev/cpack-productbuild-signing.rst new file mode 100644 index 0000000..0b91b38 --- /dev/null +++ b/Help/release/dev/cpack-productbuild-signing.rst @@ -0,0 +1,8 @@ +cpack-productbuild-signing +-------------------------- + +* The :module:`CPackProductBuild` module gained options to sign packages. + See the variables :variable:`CPACK_PRODUCTBUILD_IDENTITY_NAME`, + :variable:`CPACK_PRODUCTBUILD_KEYCHAIN_PATH`, + :variable:`CPACK_PKGBUILD_IDENTITY_NAME`, and + :variable:`CPACK_PKGBUILD_KEYCHAIN_PATH`. diff --git a/Modules/CPackProductBuild.cmake b/Modules/CPackProductBuild.cmake index ea2fa7c..d545d3e 100644 --- a/Modules/CPackProductBuild.cmake +++ b/Modules/CPackProductBuild.cmake @@ -20,9 +20,29 @@ # the automatically detected command (or specify its location if the # auto-detection fails to find it.) # +# .. variable:: CPACK_PRODUCTBUILD_IDENTITY_NAME +# +# Adds a digital signature to the resulting package. +# +# +# .. variable:: CPACK_PRODUCTBUILD_KEYCHAIN_PATH +# +# Specify a specific keychain to search for the signing identity. +# +# # .. variable:: CPACK_COMMAND_PKGBUILD # # Path to the pkgbuild(1) command used to generate an OS X component package # on OS X. This variable can be used to override the automatically detected # command (or specify its location if the auto-detection fails to find it.) # +# +# .. variable:: CPACK_PKGBUILD_IDENTITY_NAME +# +# Adds a digital signature to the resulting package. +# +# +# .. variable:: CPACK_PKGBUILD_KEYCHAIN_PATH +# +# Specify a specific keychain to search for the signing identity. +# diff --git a/Source/CPack/cmCPackProductBuildGenerator.cxx b/Source/CPack/cmCPackProductBuildGenerator.cxx index a46e3a6..35b2ccc 100644 --- a/Source/CPack/cmCPackProductBuildGenerator.cxx +++ b/Source/CPack/cmCPackProductBuildGenerator.cxx @@ -75,14 +75,27 @@ int cmCPackProductBuildGenerator::PackageFiles() std::string version = this->GetOption("CPACK_PACKAGE_VERSION"); std::string productbuild = this->GetOption("CPACK_COMMAND_PRODUCTBUILD"); + std::string identityName = + this->GetOption("CPACK_PRODUCTBUILD_IDENTITY_NAME"); + std::string keychainPath = + this->GetOption("CPACK_PRODUCTBUILD_KEYCHAIN_PATH"); pkgCmd << productbuild << " --distribution \"" << packageDirFileName << "/Contents/distribution.dist\"" << " --package-path \"" << packageDirFileName << "/Contents/Packages" << "\"" << " --resources \"" << resDir << "\"" - << " --version \"" << version << "\"" - << " \"" << packageFileNames[0] << "\""; + << " --version \"" << version << "\""; + + if (!identityName.empty()) { + pkgCmd << " --sign \"" << identityName << "\""; + } + + if (!keychainPath.empty()) { + pkgCmd << " --keychain \"" << keychainPath << "\""; + } + + pkgCmd << " \"" << packageFileNames[0] << "\""; // Run ProductBuild return RunProductBuild(pkgCmd.str()); @@ -193,13 +206,24 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage( std::string version = this->GetOption("CPACK_PACKAGE_VERSION"); std::string pkgbuild = this->GetOption("CPACK_COMMAND_PKGBUILD"); + std::string identityName = this->GetOption("CPACK_PKGBUILD_IDENTITY_NAME"); + std::string keychainPath = this->GetOption("CPACK_PKGBUILD_KEYCHAIN_PATH"); pkgCmd << pkgbuild << " --root \"" << packageDir << "\"" << " --identifier \"" << pkgId << "\"" << " --scripts \"" << scriptDir << "\"" << " --version \"" << version << "\"" - << " --install-location \"/\"" - << " \"" << packageFile << "\""; + << " --install-location \"/\""; + + if (!identityName.empty()) { + pkgCmd << " --sign \"" << identityName << "\""; + } + + if (!keychainPath.empty()) { + pkgCmd << " --keychain \"" << keychainPath << "\""; + } + + pkgCmd << " \"" << packageFile << "\""; // Run ProductBuild return RunProductBuild(pkgCmd.str()); ----------------------------------------------------------------------- Summary of changes: Help/release/dev/cpack-productbuild-signing.rst | 8 ++++++++ Modules/CPackProductBuild.cmake | 20 ++++++++++++++++++++ Source/CPack/cmCPackProductBuildGenerator.cxx | 10 ++++++++++ 3 files changed, 38 insertions(+) create mode 100644 Help/release/dev/cpack-productbuild-signing.rst hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 3 13:18:02 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 3 Feb 2017 13:18:02 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2538-g5d57061 Message-ID: <20170203181802.CFFE9F8484@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 5d570616a4f3675260490da1604b8ad17ce98bbe (commit) via a2a73935b22444b158ec5de2916deb02d9f7928b (commit) via 93f29be2316f51f1d27fb543f92911be5b9cec9e (commit) from f28a0de44953afab170272a04dca84432c4e0768 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=5d570616a4f3675260490da1604b8ad17ce98bbe commit 5d570616a4f3675260490da1604b8ad17ce98bbe Merge: f28a0de a2a7393 Author: Brad King AuthorDate: Fri Feb 3 13:18:02 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 3 13:18:02 2017 -0500 Merge topic 'findmpi-flags-fix' into next a2a73935 FindMPI: Remove leading spaces from flags 93f29be2 FindMPI: Reset MPI_INCLUDE_PATH_WORK before use https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a2a73935b22444b158ec5de2916deb02d9f7928b commit a2a73935b22444b158ec5de2916deb02d9f7928b Author: Christian Pfeiffer AuthorDate: Thu Feb 2 11:31:22 2017 +0100 Commit: Christian Pfeiffer CommitDate: Thu Feb 2 11:31:22 2017 +0100 FindMPI: Remove leading spaces from flags diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake index 9cc7cab..dd700e3 100644 --- a/Modules/FindMPI.cmake +++ b/Modules/FindMPI.cmake @@ -313,6 +313,7 @@ function (interrogate_mpi_compiler lang try_libs) set(MPI_COMPILE_FLAGS_WORK) foreach(FLAG ${MPI_ALL_COMPILE_FLAGS}) + string(REGEX REPLACE "^ " "" FLAG ${FLAG}) if (MPI_COMPILE_FLAGS_WORK) string(APPEND MPI_COMPILE_FLAGS_WORK " ${FLAG}") else() @@ -364,6 +365,7 @@ function (interrogate_mpi_compiler lang try_libs) string(REGEX MATCHALL "(^| )(-Wl,|-Xlinker )([^\" ]+|\"[^\"]+\")" MPI_ALL_LINK_FLAGS "${MPI_LINK_CMDLINE}") set(MPI_LINK_FLAGS_WORK) foreach(FLAG ${MPI_ALL_LINK_FLAGS}) + string(REGEX REPLACE "^ " "" FLAG ${FLAG}) if (MPI_LINK_FLAGS_WORK) string(APPEND MPI_LINK_FLAGS_WORK " ${FLAG}") else() https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=93f29be2316f51f1d27fb543f92911be5b9cec9e commit 93f29be2316f51f1d27fb543f92911be5b9cec9e Author: Christian Pfeiffer AuthorDate: Wed Feb 1 18:45:13 2017 +0100 Commit: Christian Pfeiffer CommitDate: Wed Feb 1 18:45:13 2017 +0100 FindMPI: Reset MPI_INCLUDE_PATH_WORK before use diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake index 842acef..9cc7cab 100644 --- a/Modules/FindMPI.cmake +++ b/Modules/FindMPI.cmake @@ -322,6 +322,8 @@ function (interrogate_mpi_compiler lang try_libs) # Extract include paths from compile command line string(REGEX MATCHALL "(^| )-I([^\" ]+|\"[^\"]+\")" MPI_ALL_INCLUDE_PATHS "${MPI_COMPILE_CMDLINE}") + set(MPI_INCLUDE_PATH_WORK) + foreach(IPATH ${MPI_ALL_INCLUDE_PATHS}) string(REGEX REPLACE "^ ?-I" "" IPATH ${IPATH}) string(REPLACE "//" "/" IPATH ${IPATH}) ----------------------------------------------------------------------- Summary of changes: Modules/FindMPI.cmake | 4 ++++ 1 file changed, 4 insertions(+) hooks/post-receive -- CMake From kwrobot at kitware.com Sat Feb 4 00:01:07 2017 From: kwrobot at kitware.com (Kitware Robot) Date: Sat, 4 Feb 2017 00:01:07 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1281-gd5f0c69 Message-ID: <20170204050107.4E420FA3AF@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via d5f0c696116541ff4d58513d5fa2970ab70cccf7 (commit) from fb26fcb261c927687f66b556df83ff6546f9bbd9 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d5f0c696116541ff4d58513d5fa2970ab70cccf7 commit d5f0c696116541ff4d58513d5fa2970ab70cccf7 Author: Kitware Robot AuthorDate: Sat Feb 4 00:01:05 2017 -0500 Commit: Kitware Robot CommitDate: Sat Feb 4 00:01:05 2017 -0500 CMake Nightly Date Stamp diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index fd32907..5a346d4 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 7) -set(CMake_VERSION_PATCH 20170203) +set(CMake_VERSION_PATCH 20170204) #set(CMake_VERSION_RC 1) ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Sat Feb 4 07:55:49 2017 From: brad.king at kitware.com (Brad King) Date: Sat, 4 Feb 2017 07:55:49 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2540-gc5b1e19 Message-ID: <20170204125550.12A02FA27F@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via c5b1e1926e1726ce3f265464103f77e48fea9abd (commit) via 3e731810ee6fad31692baedffa9d1263f8156f76 (commit) from 5d570616a4f3675260490da1604b8ad17ce98bbe (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c5b1e1926e1726ce3f265464103f77e48fea9abd commit c5b1e1926e1726ce3f265464103f77e48fea9abd Merge: 5d57061 3e73181 Author: Brad King AuthorDate: Sat Feb 4 07:55:48 2017 -0500 Commit: CMake Topic Stage CommitDate: Sat Feb 4 07:55:48 2017 -0500 Merge topic 'vs-quote-rerun-paths' into next 3e731810 fixup! VS: Fix quoting of special characters in cmake re-run check commands https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3e731810ee6fad31692baedffa9d1263f8156f76 commit 3e731810ee6fad31692baedffa9d1263f8156f76 Author: Brad King AuthorDate: Sat Feb 4 07:54:56 2017 -0500 Commit: Brad King CommitDate: Sat Feb 4 07:54:56 2017 -0500 fixup! VS: Fix quoting of special characters in cmake re-run check commands diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index c4f7a33..bc8cc4c 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -298,7 +298,7 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() commandLine.push_back("--check-stamp-list"); commandLine.push_back(stampList.c_str()); commandLine.push_back("--vs-solution-file"); - commandLine.push_back("\"$(SolutionPath)\""); + commandLine.push_back("$(SolutionPath)"); cmCustomCommandLines commandLines; commandLines.push_back(commandLine); diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 88c25b8..38dda04 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -260,9 +260,7 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule() args += this->GetBinaryDirectory(); commandLine.push_back(args); commandLine.push_back("--check-stamp-file"); - std::string stampFilename = this->ConvertToOutputFormat( - cmSystemTools::CollapseFullPath(stampName), cmOutputConverter::SHELL); - commandLine.push_back(stampFilename.c_str()); + commandLine.push_back(stampName); std::vector const& listFiles = this->Makefile->GetListFiles(); ----------------------------------------------------------------------- Summary of changes: Source/cmGlobalVisualStudio8Generator.cxx | 2 +- Source/cmLocalVisualStudio7Generator.cxx | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Sat Feb 4 07:57:48 2017 From: brad.king at kitware.com (Brad King) Date: Sat, 4 Feb 2017 07:57:48 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2542-gbc0eaa2 Message-ID: <20170204125748.4E8A0FA2CB@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via bc0eaa247812088f98bb77230a6c334125ff7a99 (commit) via 84f6bac8afd6a7d30de829023e74b5d10225e34f (commit) from c5b1e1926e1726ce3f265464103f77e48fea9abd (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=bc0eaa247812088f98bb77230a6c334125ff7a99 commit bc0eaa247812088f98bb77230a6c334125ff7a99 Merge: c5b1e19 84f6bac Author: Brad King AuthorDate: Sat Feb 4 07:57:47 2017 -0500 Commit: CMake Topic Stage CommitDate: Sat Feb 4 07:57:47 2017 -0500 Merge topic 'vs-quote-rerun-paths' into next 84f6bac8 VS: Fix quoting of special characters in cmake re-run check commands https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=84f6bac8afd6a7d30de829023e74b5d10225e34f commit 84f6bac8afd6a7d30de829023e74b5d10225e34f Author: Brad King AuthorDate: Fri Feb 3 10:08:37 2017 -0500 Commit: Brad King CommitDate: Sat Feb 4 07:55:55 2017 -0500 VS: Fix quoting of special characters in cmake re-run check commands Fix our calls to `AddCustomCommandToOutput` for adding cmake re-run check commands to disable old-style quoting in favor of the full quoting logic. This is necessary when paths contain special characters like `&` that old-style quoting logic does not handle. Reported-by: Steven Cook Fixes: #16585 diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index e961a3d..bc8cc4c 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -298,7 +298,7 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() commandLine.push_back("--check-stamp-list"); commandLine.push_back(stampList.c_str()); commandLine.push_back("--vs-solution-file"); - commandLine.push_back("\"$(SolutionPath)\""); + commandLine.push_back("$(SolutionPath)"); cmCustomCommandLines commandLines; commandLines.push_back(commandLine); @@ -310,7 +310,7 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() std::vector no_byproducts; if (cmSourceFile* file = mf->AddCustomCommandToOutput( stamps, no_byproducts, listFiles, no_main_dependency, commandLines, - "Checking Build System", no_working_directory, true)) { + "Checking Build System", no_working_directory, true, false)) { gt->AddSource(file->GetFullPath()); } else { cmSystemTools::Error("Error adding rule for ", stamps[0].c_str()); diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 49b057b..38dda04 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -260,9 +260,7 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule() args += this->GetBinaryDirectory(); commandLine.push_back(args); commandLine.push_back("--check-stamp-file"); - std::string stampFilename = this->ConvertToOutputFormat( - cmSystemTools::CollapseFullPath(stampName), cmOutputConverter::SHELL); - commandLine.push_back(stampFilename.c_str()); + commandLine.push_back(stampName); std::vector const& listFiles = this->Makefile->GetListFiles(); @@ -273,7 +271,7 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule() cmSystemTools::CollapseFullPath(stampName.c_str()); this->Makefile->AddCustomCommandToOutput( fullpathStampName.c_str(), listFiles, makefileIn.c_str(), commandLines, - comment.c_str(), no_working_directory, true); + comment.c_str(), no_working_directory, true, false); if (cmSourceFile* file = this->Makefile->GetSource(makefileIn.c_str())) { return file; } else { ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Sat Feb 4 08:07:09 2017 From: brad.king at kitware.com (Brad King) Date: Sat, 4 Feb 2017 08:07:09 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2544-g8c3b29c Message-ID: <20170204130709.14486FA5C0@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 8c3b29c2afeb30fcf54e2c0025d4663515f904cb (commit) via 8509e8b14ead75ebcbedf0fa839bc733b1a39f4f (commit) from bc0eaa247812088f98bb77230a6c334125ff7a99 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8c3b29c2afeb30fcf54e2c0025d4663515f904cb commit 8c3b29c2afeb30fcf54e2c0025d4663515f904cb Merge: bc0eaa2 8509e8b Author: Brad King AuthorDate: Sat Feb 4 08:07:08 2017 -0500 Commit: CMake Topic Stage CommitDate: Sat Feb 4 08:07:08 2017 -0500 Merge topic 'productbuild_signing' into next 8509e8b1 CPackProductBuild: Fix compilation https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8509e8b14ead75ebcbedf0fa839bc733b1a39f4f commit 8509e8b14ead75ebcbedf0fa839bc733b1a39f4f Author: Brad King AuthorDate: Sat Feb 4 08:04:19 2017 -0500 Commit: Brad King CommitDate: Sat Feb 4 08:06:10 2017 -0500 CPackProductBuild: Fix compilation diff --git a/Source/CPack/cmCPackProductBuildGenerator.cxx b/Source/CPack/cmCPackProductBuildGenerator.cxx index 07b539d..a5a18dc 100644 --- a/Source/CPack/cmCPackProductBuildGenerator.cxx +++ b/Source/CPack/cmCPackProductBuildGenerator.cxx @@ -75,10 +75,14 @@ int cmCPackProductBuildGenerator::PackageFiles() std::string version = this->GetOption("CPACK_PACKAGE_VERSION"); std::string productbuild = this->GetOption("CPACK_COMMAND_PRODUCTBUILD"); - const char* identityName = - this->GetOption("CPACK_PRODUCTBUILD_IDENTITY_NAME"); - const char* keychainPath = - this->GetOption("CPACK_PRODUCTBUILD_KEYCHAIN_PATH"); + std::string identityName; + if (const char* n = this->GetOption("CPACK_PRODUCTBUILD_IDENTITY_NAME")) { + identityName = n; + } + std::string keychainPath; + if (const char* p = this->GetOption("CPACK_PRODUCTBUILD_KEYCHAIN_PATH")) { + keychainPath = p; + } pkgCmd << productbuild << " --distribution \"" << packageDirFileName << "/Contents/distribution.dist\"" @@ -86,8 +90,9 @@ int cmCPackProductBuildGenerator::PackageFiles() << "\"" << " --resources \"" << resDir << "\"" << " --version \"" << version << "\"" - << (identityName ? " --sign \"" + identityName + "\"" : "") - << (keychainPath ? " --keychain \"" + keychainPath + "\"" : "") + << (identityName.empty() ? "" : " --sign \"" + identityName + "\"") + << (keychainPath.empty() ? "" + : " --keychain \"" + keychainPath + "\"") << " \"" << packageFileNames[0] << "\""; // Run ProductBuild @@ -199,16 +204,23 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage( std::string version = this->GetOption("CPACK_PACKAGE_VERSION"); std::string pkgbuild = this->GetOption("CPACK_COMMAND_PKGBUILD"); - const char* identityName = this->GetOption("CPACK_PKGBUILD_IDENTITY_NAME"); - const char* keychainPath = this->GetOption("CPACK_PKGBUILD_KEYCHAIN_PATH"); + std::string identityName; + if (const char* n = this->GetOption("CPACK_PKGBUILD_IDENTITY_NAME")) { + identityName = n; + } + std::string keychainPath; + if (const char* p = this->GetOption("CPACK_PKGBUILD_KEYCHAIN_PATH")) { + keychainPath = p; + } pkgCmd << pkgbuild << " --root \"" << packageDir << "\"" << " --identifier \"" << pkgId << "\"" << " --scripts \"" << scriptDir << "\"" << " --version \"" << version << "\"" << " --install-location \"/\"" - << (identityName ? " --sign \"" + identityName + "\"" : "") - << (keychainPath ? " --keychain \"" + keychainPath + "\"" : "") + << (identityName.empty() ? "" : " --sign \"" + identityName + "\"") + << (keychainPath.empty() ? "" + : " --keychain \"" + keychainPath + "\"") << " \"" << packageFile << "\""; // Run ProductBuild ----------------------------------------------------------------------- Summary of changes: Source/CPack/cmCPackProductBuildGenerator.cxx | 32 +++++++++++++++++-------- 1 file changed, 22 insertions(+), 10 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Sat Feb 4 08:08:27 2017 From: brad.king at kitware.com (Brad King) Date: Sat, 4 Feb 2017 08:08:27 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2546-g3d4e634 Message-ID: <20170204130827.2EB13FA61C@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 3d4e6340f31d9c5b15ad0a748a7295eaea7e8943 (commit) via 48aad9cda099005f5f58a7e83d604877f6f84c6d (commit) from 8c3b29c2afeb30fcf54e2c0025d4663515f904cb (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3d4e6340f31d9c5b15ad0a748a7295eaea7e8943 commit 3d4e6340f31d9c5b15ad0a748a7295eaea7e8943 Merge: 8c3b29c 48aad9c Author: Brad King AuthorDate: Sat Feb 4 08:08:26 2017 -0500 Commit: CMake Topic Stage CommitDate: Sat Feb 4 08:08:26 2017 -0500 Merge topic 'productbuild_signing' into next 48aad9cd CPackProductBuild: Add options to sign packages https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=48aad9cda099005f5f58a7e83d604877f6f84c6d commit 48aad9cda099005f5f58a7e83d604877f6f84c6d Author: Roman W?ger AuthorDate: Sun Jan 15 01:29:34 2017 +0100 Commit: Brad King CommitDate: Sat Feb 4 08:07:48 2017 -0500 CPackProductBuild: Add options to sign packages diff --git a/Help/release/dev/cpack-productbuild-signing.rst b/Help/release/dev/cpack-productbuild-signing.rst new file mode 100644 index 0000000..0b91b38 --- /dev/null +++ b/Help/release/dev/cpack-productbuild-signing.rst @@ -0,0 +1,8 @@ +cpack-productbuild-signing +-------------------------- + +* The :module:`CPackProductBuild` module gained options to sign packages. + See the variables :variable:`CPACK_PRODUCTBUILD_IDENTITY_NAME`, + :variable:`CPACK_PRODUCTBUILD_KEYCHAIN_PATH`, + :variable:`CPACK_PKGBUILD_IDENTITY_NAME`, and + :variable:`CPACK_PKGBUILD_KEYCHAIN_PATH`. diff --git a/Modules/CPackProductBuild.cmake b/Modules/CPackProductBuild.cmake index ea2fa7c..d545d3e 100644 --- a/Modules/CPackProductBuild.cmake +++ b/Modules/CPackProductBuild.cmake @@ -20,9 +20,29 @@ # the automatically detected command (or specify its location if the # auto-detection fails to find it.) # +# .. variable:: CPACK_PRODUCTBUILD_IDENTITY_NAME +# +# Adds a digital signature to the resulting package. +# +# +# .. variable:: CPACK_PRODUCTBUILD_KEYCHAIN_PATH +# +# Specify a specific keychain to search for the signing identity. +# +# # .. variable:: CPACK_COMMAND_PKGBUILD # # Path to the pkgbuild(1) command used to generate an OS X component package # on OS X. This variable can be used to override the automatically detected # command (or specify its location if the auto-detection fails to find it.) # +# +# .. variable:: CPACK_PKGBUILD_IDENTITY_NAME +# +# Adds a digital signature to the resulting package. +# +# +# .. variable:: CPACK_PKGBUILD_KEYCHAIN_PATH +# +# Specify a specific keychain to search for the signing identity. +# diff --git a/Source/CPack/cmCPackProductBuildGenerator.cxx b/Source/CPack/cmCPackProductBuildGenerator.cxx index a46e3a6..a5a18dc 100644 --- a/Source/CPack/cmCPackProductBuildGenerator.cxx +++ b/Source/CPack/cmCPackProductBuildGenerator.cxx @@ -75,6 +75,14 @@ int cmCPackProductBuildGenerator::PackageFiles() std::string version = this->GetOption("CPACK_PACKAGE_VERSION"); std::string productbuild = this->GetOption("CPACK_COMMAND_PRODUCTBUILD"); + std::string identityName; + if (const char* n = this->GetOption("CPACK_PRODUCTBUILD_IDENTITY_NAME")) { + identityName = n; + } + std::string keychainPath; + if (const char* p = this->GetOption("CPACK_PRODUCTBUILD_KEYCHAIN_PATH")) { + keychainPath = p; + } pkgCmd << productbuild << " --distribution \"" << packageDirFileName << "/Contents/distribution.dist\"" @@ -82,6 +90,9 @@ int cmCPackProductBuildGenerator::PackageFiles() << "\"" << " --resources \"" << resDir << "\"" << " --version \"" << version << "\"" + << (identityName.empty() ? "" : " --sign \"" + identityName + "\"") + << (keychainPath.empty() ? "" + : " --keychain \"" + keychainPath + "\"") << " \"" << packageFileNames[0] << "\""; // Run ProductBuild @@ -193,12 +204,23 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage( std::string version = this->GetOption("CPACK_PACKAGE_VERSION"); std::string pkgbuild = this->GetOption("CPACK_COMMAND_PKGBUILD"); + std::string identityName; + if (const char* n = this->GetOption("CPACK_PKGBUILD_IDENTITY_NAME")) { + identityName = n; + } + std::string keychainPath; + if (const char* p = this->GetOption("CPACK_PKGBUILD_KEYCHAIN_PATH")) { + keychainPath = p; + } pkgCmd << pkgbuild << " --root \"" << packageDir << "\"" << " --identifier \"" << pkgId << "\"" << " --scripts \"" << scriptDir << "\"" << " --version \"" << version << "\"" << " --install-location \"/\"" + << (identityName.empty() ? "" : " --sign \"" + identityName + "\"") + << (keychainPath.empty() ? "" + : " --keychain \"" + keychainPath + "\"") << " \"" << packageFile << "\""; // Run ProductBuild ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Sat Feb 4 08:20:44 2017 From: brad.king at kitware.com (Brad King) Date: Sat, 4 Feb 2017 08:20:44 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2549-gc13efe3 Message-ID: <20170204132044.4A08BFA344@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via c13efe3208f32cba458eb89dde44f3fe29828a7e (commit) via 8a5cb84b0e5ef3deac4e241d0d4f3e9932daadaa (commit) via 9d34e51cdb7ccc74eaf851f1784433616bc9c31a (commit) from 3d4e6340f31d9c5b15ad0a748a7295eaea7e8943 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c13efe3208f32cba458eb89dde44f3fe29828a7e commit c13efe3208f32cba458eb89dde44f3fe29828a7e Merge: 3d4e634 8a5cb84 Author: Brad King AuthorDate: Sat Feb 4 08:20:41 2017 -0500 Commit: CMake Topic Stage CommitDate: Sat Feb 4 08:20:41 2017 -0500 Merge topic 'androidtestutilities_cleanup' into next 8a5cb84b AndroidTestUtilities: do not require ExternalData unconditionally 9d34e51c AndroidTestUtilities: ignore exit status of ls https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8a5cb84b0e5ef3deac4e241d0d4f3e9932daadaa commit 8a5cb84b0e5ef3deac4e241d0d4f3e9932daadaa Author: Zack Galbreath AuthorDate: Fri Feb 3 15:44:51 2017 -0500 Commit: Brad King CommitDate: Sat Feb 4 08:16:24 2017 -0500 AndroidTestUtilities: do not require ExternalData unconditionally Attempting to use AndroidTestUtilities to simply install some local files on device can result in the following error: Neither ExternalData_URL_TEMPLATES nor ExternalData_OBJECT_STORES is set We no longer require these ExternalData-specific variables to be set if no such remote data files are requested. Fixes: #16529 diff --git a/Modules/AndroidTestUtilities.cmake b/Modules/AndroidTestUtilities.cmake index a0a74fa..62d04f3 100644 --- a/Modules/AndroidTestUtilities.cmake +++ b/Modules/AndroidTestUtilities.cmake @@ -110,11 +110,18 @@ function(android_add_test_data test_name) endforeach() set(DATA_TARGET_NAME "${test_name}") - ExternalData_Expand_Arguments( - ${DATA_TARGET_NAME} - extern_data_output - ${AST_FILES}) - ExternalData_Add_Target(${DATA_TARGET_NAME}) + string(FIND "${AST_FILES}" "DATA{" data_files_found) + if(${data_files_found} GREATER "-1") + # Use ExternalData if any DATA{} files were found. + ExternalData_Expand_Arguments( + ${DATA_TARGET_NAME} + extern_data_output + ${AST_FILES}) + ExternalData_Add_Target(${DATA_TARGET_NAME}) + else() + add_custom_target(${DATA_TARGET_NAME} ALL) + set(extern_data_output ${AST_FILES}) + endif() # For regular files on Linux, just copy them directly. foreach(path ${AST_FILES}) diff --git a/Tests/RunCMake/AndroidTestUtilities/RunCMakeTest.cmake b/Tests/RunCMake/AndroidTestUtilities/RunCMakeTest.cmake index f0ae24b..7d031d4 100644 --- a/Tests/RunCMake/AndroidTestUtilities/RunCMakeTest.cmake +++ b/Tests/RunCMake/AndroidTestUtilities/RunCMakeTest.cmake @@ -18,3 +18,4 @@ endfunction() run_ATU(SetupTest1 "") run_ATU(SetupTest2 "tests") run_ATU(SetupTest3 "tests") +run_ATU(SetupTest4 "") diff --git a/Tests/RunCMake/AndroidTestUtilities/SetupTest4.cmake b/Tests/RunCMake/AndroidTestUtilities/SetupTest4.cmake new file mode 100644 index 0000000..9a27266 --- /dev/null +++ b/Tests/RunCMake/AndroidTestUtilities/SetupTest4.cmake @@ -0,0 +1,13 @@ +enable_testing() +include(AndroidTestUtilities) + +find_program(adb_executable adb) + +set(test_files "data/a.txt") + +set(ANDROID 1) + +android_add_test_data(setup_test + FILES ${test_files} + DEVICE_TEST_DIR "/data/local/tests/example1" + DEVICE_OBJECT_STORE "/sdcard/.ExternalData/SHA") diff --git a/Tests/RunCMake/AndroidTestUtilities/SetupTest4Build-check.cmake b/Tests/RunCMake/AndroidTestUtilities/SetupTest4Build-check.cmake new file mode 100644 index 0000000..ef7569d --- /dev/null +++ b/Tests/RunCMake/AndroidTestUtilities/SetupTest4Build-check.cmake @@ -0,0 +1,5 @@ +include(${CMAKE_CURRENT_LIST_DIR}/check.cmake) +compare_build_to_expected(FILES + "data/a.txt" + ) +check_for_setup_test() https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9d34e51cdb7ccc74eaf851f1784433616bc9c31a commit 9d34e51cdb7ccc74eaf851f1784433616bc9c31a Author: Zack Galbreath AuthorDate: Fri Feb 3 13:22:36 2017 -0500 Commit: Zack Galbreath CommitDate: Fri Feb 3 13:22:36 2017 -0500 AndroidTestUtilities: ignore exit status of ls adb used to suffer from a bug where `adb shell` would return 0 irrespective the exit status of the underlying process that it executed. This is now fixed for newer versions of Android (N+). As a result, attempting to `adb shell ls` a nonexistent file can now result in a non-zero exit status. Updating check_device_file_exists to ignore the exit status of `adb shell` fixes this bug for newer Android devices. diff --git a/Modules/AndroidTestUtilities/PushToAndroidDevice.cmake b/Modules/AndroidTestUtilities/PushToAndroidDevice.cmake index d8ca730..04529b1 100644 --- a/Modules/AndroidTestUtilities/PushToAndroidDevice.cmake +++ b/Modules/AndroidTestUtilities/PushToAndroidDevice.cmake @@ -39,7 +39,9 @@ function(android_push_test_files_to_device) # if(file_exists) will return true. macro(check_device_file_exists device_file file_exists) set(${file_exists} "") - execute_adb_command(shell ls ${device_file}) + execute_process( + COMMAND ${adb_executable} shell ls ${device_file} + OUTPUT_VARIABLE out_var ERROR_VARIABLE out_var) if(NOT out_var) # when a directory exists but is empty the output is empty set(${file_exists} "YES") else() ----------------------------------------------------------------------- Summary of changes: Modules/AndroidTestUtilities.cmake | 17 ++++++++++++----- .../AndroidTestUtilities/PushToAndroidDevice.cmake | 4 +++- .../RunCMake/AndroidTestUtilities/RunCMakeTest.cmake | 1 + .../{SetupTest1.cmake => SetupTest4.cmake} | 4 ---- ...1Build-check.cmake => SetupTest4Build-check.cmake} | 0 5 files changed, 16 insertions(+), 10 deletions(-) copy Tests/RunCMake/AndroidTestUtilities/{SetupTest1.cmake => SetupTest4.cmake} (71%) copy Tests/RunCMake/AndroidTestUtilities/{SetupTest1Build-check.cmake => SetupTest4Build-check.cmake} (100%) hooks/post-receive -- CMake From kwrobot at kitware.com Sun Feb 5 00:01:11 2017 From: kwrobot at kitware.com (Kitware Robot) Date: Sun, 5 Feb 2017 00:01:11 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1282-gc054221 Message-ID: <20170205050111.21A8BFA675@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via c054221ffd7b4643ca873ca21e96debc618d8509 (commit) from d5f0c696116541ff4d58513d5fa2970ab70cccf7 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c054221ffd7b4643ca873ca21e96debc618d8509 commit c054221ffd7b4643ca873ca21e96debc618d8509 Author: Kitware Robot AuthorDate: Sun Feb 5 00:01:05 2017 -0500 Commit: Kitware Robot CommitDate: Sun Feb 5 00:01:05 2017 -0500 CMake Nightly Date Stamp diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 5a346d4..20c14d9 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 7) -set(CMake_VERSION_PATCH 20170204) +set(CMake_VERSION_PATCH 20170205) #set(CMake_VERSION_RC 1) ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From kwrobot at kitware.com Mon Feb 6 00:01:08 2017 From: kwrobot at kitware.com (Kitware Robot) Date: Mon, 6 Feb 2017 00:01:08 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1283-ga00cca9 Message-ID: <20170206050108.C7296FA5AF@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via a00cca97b384454f8a7a1f5e665eb1eeaac98001 (commit) from c054221ffd7b4643ca873ca21e96debc618d8509 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a00cca97b384454f8a7a1f5e665eb1eeaac98001 commit a00cca97b384454f8a7a1f5e665eb1eeaac98001 Author: Kitware Robot AuthorDate: Mon Feb 6 00:01:04 2017 -0500 Commit: Kitware Robot CommitDate: Mon Feb 6 00:01:04 2017 -0500 CMake Nightly Date Stamp diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 20c14d9..8db6f58 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 7) -set(CMake_VERSION_PATCH 20170205) +set(CMake_VERSION_PATCH 20170206) #set(CMake_VERSION_RC 1) ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 6 09:52:59 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 6 Feb 2017 09:52:59 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2551-g9c24b1f Message-ID: <20170206145259.259B8FA4DF@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 9c24b1fa2b36569b6f53b9b12a1cc9ffca8146ee (commit) via d4425e65f256faf78ccaf425653e5e17b4527f0e (commit) from c13efe3208f32cba458eb89dde44f3fe29828a7e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9c24b1fa2b36569b6f53b9b12a1cc9ffca8146ee commit 9c24b1fa2b36569b6f53b9b12a1cc9ffca8146ee Merge: c13efe3 d4425e6 Author: Brad King AuthorDate: Mon Feb 6 09:52:58 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 6 09:52:58 2017 -0500 Merge topic 'vs-quote-rerun-paths' into next d4425e65 fixup! VS: Fix quoting of special characters in cmake re-run check commands https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d4425e65f256faf78ccaf425653e5e17b4527f0e commit d4425e65f256faf78ccaf425653e5e17b4527f0e Author: Brad King AuthorDate: Mon Feb 6 09:12:26 2017 -0500 Commit: Brad King CommitDate: Mon Feb 6 09:52:36 2017 -0500 fixup! VS: Fix quoting of special characters in cmake re-run check commands diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index bc8cc4c..8353a3f 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -298,7 +298,9 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() commandLine.push_back("--check-stamp-list"); commandLine.push_back(stampList.c_str()); commandLine.push_back("--vs-solution-file"); - commandLine.push_back("$(SolutionPath)"); + std::string const sln = std::string(lg->GetBinaryDirectory()) + "/" + + lg->GetProjectName() + ".sln"; + commandLine.push_back(sln); cmCustomCommandLines commandLines; commandLines.push_back(commandLine); ----------------------------------------------------------------------- Summary of changes: Source/cmGlobalVisualStudio8Generator.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 6 09:55:21 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 6 Feb 2017 09:55:21 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2553-g73f49b0 Message-ID: <20170206145522.44651FA7B3@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 73f49b01b85506fd3bf5a496a9dc5a48fc93fb6f (commit) via f8f3cb8d65d3ddbd8840814df7df884a2714b88e (commit) from 9c24b1fa2b36569b6f53b9b12a1cc9ffca8146ee (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=73f49b01b85506fd3bf5a496a9dc5a48fc93fb6f commit 73f49b01b85506fd3bf5a496a9dc5a48fc93fb6f Merge: 9c24b1f f8f3cb8 Author: Brad King AuthorDate: Mon Feb 6 09:55:20 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 6 09:55:20 2017 -0500 Merge topic 'vs-quote-rerun-paths' into next f8f3cb8d VS: Fix quoting of special characters in cmake re-run check commands https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f8f3cb8d65d3ddbd8840814df7df884a2714b88e commit f8f3cb8d65d3ddbd8840814df7df884a2714b88e Author: Brad King AuthorDate: Fri Feb 3 10:08:37 2017 -0500 Commit: Brad King CommitDate: Mon Feb 6 09:53:15 2017 -0500 VS: Fix quoting of special characters in cmake re-run check commands Fix our calls to `AddCustomCommandToOutput` for adding cmake re-run check commands to disable old-style quoting in favor of the full quoting logic. This is necessary when paths contain special characters like `&` that old-style quoting logic does not handle. This also requires us to expand the `$(SolutionPath)` placeholder explicitly because otherwise its expanded value will no longer be quoted correctly. As a side effect, this fixes the value in VS 10 and above where the placeholder may be undefined when driving the build through MSBuild without the `.sln` file. Reported-by: Steven Cook Fixes: #16585 diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index e961a3d..8353a3f 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -298,7 +298,9 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() commandLine.push_back("--check-stamp-list"); commandLine.push_back(stampList.c_str()); commandLine.push_back("--vs-solution-file"); - commandLine.push_back("\"$(SolutionPath)\""); + std::string const sln = std::string(lg->GetBinaryDirectory()) + "/" + + lg->GetProjectName() + ".sln"; + commandLine.push_back(sln); cmCustomCommandLines commandLines; commandLines.push_back(commandLine); @@ -310,7 +312,7 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() std::vector no_byproducts; if (cmSourceFile* file = mf->AddCustomCommandToOutput( stamps, no_byproducts, listFiles, no_main_dependency, commandLines, - "Checking Build System", no_working_directory, true)) { + "Checking Build System", no_working_directory, true, false)) { gt->AddSource(file->GetFullPath()); } else { cmSystemTools::Error("Error adding rule for ", stamps[0].c_str()); diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 49b057b..38dda04 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -260,9 +260,7 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule() args += this->GetBinaryDirectory(); commandLine.push_back(args); commandLine.push_back("--check-stamp-file"); - std::string stampFilename = this->ConvertToOutputFormat( - cmSystemTools::CollapseFullPath(stampName), cmOutputConverter::SHELL); - commandLine.push_back(stampFilename.c_str()); + commandLine.push_back(stampName); std::vector const& listFiles = this->Makefile->GetListFiles(); @@ -273,7 +271,7 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule() cmSystemTools::CollapseFullPath(stampName.c_str()); this->Makefile->AddCustomCommandToOutput( fullpathStampName.c_str(), listFiles, makefileIn.c_str(), commandLines, - comment.c_str(), no_working_directory, true); + comment.c_str(), no_working_directory, true, false); if (cmSourceFile* file = this->Makefile->GetSource(makefileIn.c_str())) { return file; } else { ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 6 10:29:38 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 6 Feb 2017 10:29:38 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1286-g8e8eeb7 Message-ID: <20170206152938.07641FA77C@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 8e8eeb73ab338fc6a6e2b6af9da3dc6f09cc26d1 (commit) via a2a73935b22444b158ec5de2916deb02d9f7928b (commit) via 93f29be2316f51f1d27fb543f92911be5b9cec9e (commit) from a00cca97b384454f8a7a1f5e665eb1eeaac98001 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8e8eeb73ab338fc6a6e2b6af9da3dc6f09cc26d1 commit 8e8eeb73ab338fc6a6e2b6af9da3dc6f09cc26d1 Merge: a00cca9 a2a7393 Author: Brad King AuthorDate: Mon Feb 6 10:29:35 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 6 10:29:35 2017 -0500 Merge topic 'findmpi-flags-fix' a2a73935 FindMPI: Remove leading spaces from flags 93f29be2 FindMPI: Reset MPI_INCLUDE_PATH_WORK before use ----------------------------------------------------------------------- Summary of changes: Modules/FindMPI.cmake | 4 ++++ 1 file changed, 4 insertions(+) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 6 10:29:40 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 6 Feb 2017 10:29:40 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1293-g59c50a1 Message-ID: <20170206152940.55B48FA783@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 59c50a1d3ceb0cec1690f454bb57dc63de4d621b (commit) via cf0d8f1fd6ad5d4bc85d7788af459238df494260 (commit) via 5564c01703c20f992769f4e152bcc74ceddc5942 (commit) via 4908969f578ded9d87f244bd8ada65ba0c51cf28 (commit) via 77f6d22ad1f1b461297a463eb5f40fbb0d0825aa (commit) via 3d5ad7236c8ce444323fb63cd9ff50fb5f757830 (commit) via ae89967f9dc9308003630531ef34764030f98bd0 (commit) from 8e8eeb73ab338fc6a6e2b6af9da3dc6f09cc26d1 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=59c50a1d3ceb0cec1690f454bb57dc63de4d621b commit 59c50a1d3ceb0cec1690f454bb57dc63de4d621b Merge: 8e8eeb7 cf0d8f1 Author: Brad King AuthorDate: Mon Feb 6 10:29:38 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 6 10:29:38 2017 -0500 Merge topic 'FindHDF5-fix-HDF5_ROOT' cf0d8f1f FindHDF5: Restore HDF5_INCLUDE_DIR in all code paths 5564c017 FindHDF5: Restore fallback to static libraries 4908969f FindHDF5: Fix search with HDF5_ROOT 77f6d22a FindHDF5: Use keywords in find_library calls 3d5ad723 FindHDF5: Initialize/finalize internal search options variable ae89967f FindHDF5: Fix command-line parsing argument extraction order ----------------------------------------------------------------------- Summary of changes: Modules/FindHDF5.cmake | 185 ++++++++++++++++++++++++++---------------------- 1 file changed, 102 insertions(+), 83 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 6 10:29:43 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 6 Feb 2017 10:29:43 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1296-ga4c8ad5 Message-ID: <20170206152943.67579FA782@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via a4c8ad5ed81b08e042646e132f999bebaf97a83b (commit) via 8a5cb84b0e5ef3deac4e241d0d4f3e9932daadaa (commit) via 9d34e51cdb7ccc74eaf851f1784433616bc9c31a (commit) from 59c50a1d3ceb0cec1690f454bb57dc63de4d621b (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a4c8ad5ed81b08e042646e132f999bebaf97a83b commit a4c8ad5ed81b08e042646e132f999bebaf97a83b Merge: 59c50a1 8a5cb84 Author: Brad King AuthorDate: Mon Feb 6 10:29:40 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 6 10:29:40 2017 -0500 Merge topic 'androidtestutilities_cleanup' 8a5cb84b AndroidTestUtilities: do not require ExternalData unconditionally 9d34e51c AndroidTestUtilities: ignore exit status of ls ----------------------------------------------------------------------- Summary of changes: Modules/AndroidTestUtilities.cmake | 17 ++++++++++++----- .../AndroidTestUtilities/PushToAndroidDevice.cmake | 4 +++- .../RunCMake/AndroidTestUtilities/RunCMakeTest.cmake | 1 + .../{SetupTest1.cmake => SetupTest4.cmake} | 4 ---- ...1Build-check.cmake => SetupTest4Build-check.cmake} | 0 5 files changed, 16 insertions(+), 10 deletions(-) copy Tests/RunCMake/AndroidTestUtilities/{SetupTest1.cmake => SetupTest4.cmake} (71%) copy Tests/RunCMake/AndroidTestUtilities/{SetupTest1Build-check.cmake => SetupTest4Build-check.cmake} (100%) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 6 10:29:45 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 6 Feb 2017 10:29:45 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1298-gcf1bc84 Message-ID: <20170206152945.E80C5FA78E@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via cf1bc84216ac5005301836b121d574ec90d9212a (commit) via 48aad9cda099005f5f58a7e83d604877f6f84c6d (commit) from a4c8ad5ed81b08e042646e132f999bebaf97a83b (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=cf1bc84216ac5005301836b121d574ec90d9212a commit cf1bc84216ac5005301836b121d574ec90d9212a Merge: a4c8ad5 48aad9c Author: Brad King AuthorDate: Mon Feb 6 10:29:44 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 6 10:29:44 2017 -0500 Merge topic 'productbuild_signing' 48aad9cd CPackProductBuild: Add options to sign packages ----------------------------------------------------------------------- Summary of changes: Help/release/dev/cpack-productbuild-signing.rst | 8 ++++++++ Modules/CPackProductBuild.cmake | 20 ++++++++++++++++++++ Source/CPack/cmCPackProductBuildGenerator.cxx | 22 ++++++++++++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 Help/release/dev/cpack-productbuild-signing.rst hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 6 10:29:48 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 6 Feb 2017 10:29:48 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1300-g811c854 Message-ID: <20170206152948.33947FA77D@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 811c854efffba6f97bb3038b651fed7fc1bcf2be (commit) via f8f3cb8d65d3ddbd8840814df7df884a2714b88e (commit) from cf1bc84216ac5005301836b121d574ec90d9212a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=811c854efffba6f97bb3038b651fed7fc1bcf2be commit 811c854efffba6f97bb3038b651fed7fc1bcf2be Merge: cf1bc84 f8f3cb8 Author: Brad King AuthorDate: Mon Feb 6 10:29:46 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 6 10:29:46 2017 -0500 Merge topic 'vs-quote-rerun-paths' f8f3cb8d VS: Fix quoting of special characters in cmake re-run check commands ----------------------------------------------------------------------- Summary of changes: Source/cmGlobalVisualStudio8Generator.cxx | 6 ++++-- Source/cmLocalVisualStudio7Generator.cxx | 6 ++---- 2 files changed, 6 insertions(+), 6 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 6 10:30:38 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 6 Feb 2017 10:30:38 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2562-g2d467f5 Message-ID: <20170206153038.CC5D8FA793@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 2d467f548d2d718777f12b4b947745723a82bf53 (commit) via 811c854efffba6f97bb3038b651fed7fc1bcf2be (commit) via cf1bc84216ac5005301836b121d574ec90d9212a (commit) via a4c8ad5ed81b08e042646e132f999bebaf97a83b (commit) via 59c50a1d3ceb0cec1690f454bb57dc63de4d621b (commit) via 8e8eeb73ab338fc6a6e2b6af9da3dc6f09cc26d1 (commit) via a00cca97b384454f8a7a1f5e665eb1eeaac98001 (commit) via c054221ffd7b4643ca873ca21e96debc618d8509 (commit) via d5f0c696116541ff4d58513d5fa2970ab70cccf7 (commit) from 73f49b01b85506fd3bf5a496a9dc5a48fc93fb6f (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=2d467f548d2d718777f12b4b947745723a82bf53 commit 2d467f548d2d718777f12b4b947745723a82bf53 Merge: 73f49b0 811c854 Author: Brad King AuthorDate: Mon Feb 6 10:30:10 2017 -0500 Commit: Brad King CommitDate: Mon Feb 6 10:30:10 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 6 11:15:04 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 6 Feb 2017 11:15:04 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2565-ga80bdaf Message-ID: <20170206161504.6CCB5F4B70@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via a80bdaf9e0c4f73e9a69a76f159e5c0f940ed1d7 (commit) via c2f7ef637e7e47adf89cc8ef2eea2d6f879ddc7d (commit) via 3f5e4f1957c33335d792f6edde62ca59d3b158fb (commit) from 2d467f548d2d718777f12b4b947745723a82bf53 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a80bdaf9e0c4f73e9a69a76f159e5c0f940ed1d7 commit a80bdaf9e0c4f73e9a69a76f159e5c0f940ed1d7 Merge: 2d467f5 c2f7ef6 Author: Brad King AuthorDate: Mon Feb 6 11:15:03 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 6 11:15:03 2017 -0500 Merge topic 'doc-3.8-relnotes' into next c2f7ef63 Help: Organize and revise 3.8 release notes 3f5e4f19 Help: Consolidate 3.8 release notes https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c2f7ef637e7e47adf89cc8ef2eea2d6f879ddc7d commit c2f7ef637e7e47adf89cc8ef2eea2d6f879ddc7d Author: Brad King AuthorDate: Wed Feb 1 11:38:59 2017 -0500 Commit: Brad King CommitDate: Mon Feb 6 10:35:28 2017 -0500 Help: Organize and revise 3.8 release notes Add section headers similar to the 3.7 release notes and move each individual bullet into an appropriate section. Revise a few bullets. diff --git a/Help/release/3.8.rst b/Help/release/3.8.rst index 1efafac..d427a63 100644 --- a/Help/release/3.8.rst +++ b/Help/release/3.8.rst @@ -7,51 +7,290 @@ CMake 3.8 Release Notes Changes made since CMake 3.7 include the following. -* A :variable:`CMAKE_BUILD_RPATH` variable and corresponding - :prop_tgt:`BUILD_RPATH` target property were added to support custom +New Features +============ + +Languages +--------- + +C# +^^ + +* CMake learned to support ``CSharp`` (C#) as a first-class language that + can be enabled via the :command:`project` and :command:`enable_language` + commands. It is currently supported by the :ref:`Visual Studio Generators` + for VS 2010 and above. + + C# assemblies and programs can be added just like common C++ targets using + the :command:`add_library` and :command:`add_executable` commands. + References between C# targets in the same source tree may be specified by + :command:`target_link_libraries` like for C++. References to system or + 3rd-party assemblies may be specified by the target properties + :prop_tgt:`VS_DOTNET_REFERENCE_` and + :prop_tgt:`VS_DOTNET_REFERENCES`. + +* More fine tuning of C# targets may be done using target and source + file properties. Specifically the target properties related to + Visual Studio (``VS_*``) are worth a look (for setting toolset + versions, root namespaces, assembly icons, ...). + +* Auto-linking in ``.csproj`` files: In C#/.NET development with + Visual Studio there are a number of visual editors used which + generate code. Both the generated files and the ones edited + with the UI are connected in the ``.csproj`` file using + ```` tags. If CMake finds within a C# project + any source file with extension ``.Designer.cs`` or ``.xaml.cs``, + it checks sibling files with extension ``.xaml``, ``.settings``, + ``.resx`` or ``.cs`` and establishes the dependency connection. + +CUDA +^^^^ + +* CMake learned to support ``CUDA`` as a first-class language that can be + enabled via the :command:`project` and :command:`enable_language` commands. + +* ``CUDA`` is currently supported by the :ref:`Makefile Generators` + and the :generator:`Ninja` generator on Linux, macOS, and Windows. + Support for the Visual Studio IDE is under development but not + included in this release. + +* The NVIDIA CUDA Toolkit compiler (``nvcc``) is supported. + +C & C++ +^^^^^^^ + +* The :manual:`Compile Features ` functionality + now offers meta-features that request compiler modes for specific language + standard levels (e.g. ``cxx_std_11``). See + :prop_gbl:`CMAKE_C_KNOWN_FEATURES` and :prop_gbl:`CMAKE_CXX_KNOWN_FEATURES`. + +* The :manual:`Compile Features ` functionality + is now aware of C++ 17. No specific features are yet enumerated besides + the ``cxx_std_17`` meta-feature. + +* The :manual:`Compile Features ` functionality + is now aware of the availability of C99 in gcc since version 3.4. + +Platforms +--------- + +* A new minimal platform file for ``Fuchsia`` was added. + +Generators +---------- + +* The :generator:`CodeBlocks` extra generator may now be used to + generate with :generator:`NMake Makefiles JOM`. + +* The :ref:`Visual Studio Generators` for VS 2013 and above learned to + support a ``host=x64`` option in the :variable:`CMAKE_GENERATOR_TOOLSET` + value (e.g. via the :manual:`cmake(1)` ``-T`` option) to request use + of a VS 64-bit toolchain on 64-bit hosts. + +* The :ref:`Visual Studio Generators` learned to treat files passed to + :command:`target_link_libraries` whose names end in ``.targets`` + as MSBuild "targets" files to be imported into generated project files. + +Commands +-------- + +* The :command:`add_custom_command` and :command:`add_custom_target` commands + learned the option ``COMMAND_EXPAND_LISTS`` which causes lists in the + ``COMMAND`` argument to be expanded, including lists created by generator + expressions. + +* The :command:`execute_process` command gained an ``ENCODING`` option to + specify on Windows which encoding is used for output from child process. + +* The :command:`math(EXPR)` command gained support for unary + ``+`` and ``-`` operators. + +* The :command:`source_group` command gained ``TREE`` and ``PREFIX`` + options to add groups following source tree directory structure. + +* The :command:`string(TIMESTAMP)` command learned to treat ``%%`` + as a way to encode plain ``%``. + +* The :command:`string(TIMESTAMP)` command will now honor the + ``SOURCE_DATE_EPOCH`` environment variable and use its value + instead of the current time. + +* The :command:`try_compile` command source file signature gained new options + to specify the language standard to use in the generated test project. + +* The :command:`try_compile` command source file signature now honors + language standard variables like :variable:`CMAKE_CXX_STANDARD`. + See policy :policy:`CMP0067`. + +Variables +--------- + +* A :variable:`CMAKE_CODELITE_USE_TARGETS` variable was added to tell the + :generator:`CodeLite` extra generator to change the generated project + to have target-centric organization. + The ``build``, ``rebuild``, and ``clean`` operations within ``CodeLite`` + then work on a selected target rather than the whole workspace. + (Note that the :generator:`Ninja` clean operation on a target + includes its dependencies, though.) + +* The :variable:`CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS` variable was added to + tell the :generator:`Sublime Text 2` extra generator to place specified + environment variables in the generated ``.sublime-project``. + +* The :variable:`CMAKE_SUBLIME_TEXT_2_EXCLUDE_BUILD_TREE` variable was added + to tell the :generator:`Sublime Text 2` extra generator whether to exclude + the build tree from the ``.sublime-project`` when it is inside the source + tree. + +* A :variable:`CMAKE_VS_INCLUDE_PACKAGE_TO_DEFAULT_BUILD` variable was + added to tell :ref:`Visual Studio Generators` for VS 2010 and above + to include the ``PACKAGE`` target in the default build, similar to + the existing :variable:`CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD` + variable for the ``INSTALL`` target. + +Properties +---------- + +* A :prop_tgt:`BUILD_RPATH` target property and corresponding + :variable:`CMAKE_BUILD_RPATH` variable were added to support custom ``RPATH`` locations to be added to binaries in the build tree. +* The :prop_sf:`COMPILE_FLAGS` source file property learned to support + :manual:`generator expressions `. + +* The :prop_tgt:`FRAMEWORK` target property may now also be applied to + static libraries on Apple targets. It will result in a proper + Framework but with a static library inside. + +* :ref:`Imported ` :ref:`Interface Libraries` learned new + :prop_tgt:`IMPORTED_LIBNAME` and :prop_tgt:`IMPORTED_LIBNAME_` + target properties to specify a link library name since interface libraries + do not build their own library files. + * A :prop_tgt:`_CPPLINT` target property and supporting :variable:`CMAKE__CPPLINT` variable were introduced to tell the :ref:`Makefile Generators` and the :generator:`Ninja` generator to run the ``cpplint`` style checker along with the compiler for ``C`` and ``CXX`` languages. -* CMake functionality using cryptographic hashes now supports SHA-3 algorithms. +* A :prop_tgt:`MANUALLY_ADDED_DEPENDENCIES` target property has been added. + It provides a read-only list of dependencies that have been added with + the :command:`add_dependencies` command. * The :prop_tgt:`MAP_IMPORTED_CONFIG_` target property learned to interpret empty list elements as referring to the configuration-less imported location specified by :prop_tgt:`IMPORTED_LOCATION`. -* If a command specified by the :prop_tgt:`_CLANG_TIDY` target property - returns non-zero at build time this is now treated as an error instead of - silently ignored. +* The :prop_tgt:`NO_SYSTEM_FROM_IMPORTED` target property is now supported + on :ref:`Imported ` :ref:`Interface Libraries`. -* The ``CDASH_UPLOAD`` signature of :command:`ctest_submit` was taught to honor - the ``RETRY_COUNT``, ``RETRY_DELAY``, and ``QUIET`` options. +* New source file properties :prop_sf:`SKIP_AUTOMOC`, :prop_sf:`SKIP_AUTOUIC`, + :prop_sf:`SKIP_AUTORCC`, and :prop_sf:`SKIP_AUTOGEN` were added to allow + source files to be excluded from processing by :prop_tgt:`AUTOMOC`, + :prop_tgt:`AUTOUIC`, and :prop_tgt:`AUTORCC` target properties. -* The :generator:`CodeBlocks` now can generate with - :generator:`NMake Makefiles JOM`. +* A :prop_sf:`VS_COPY_TO_OUT_DIR` source file property was added to + tell :ref:`Visual Studio Generators` for VS 2010 and above whether + or not a file should e copied to the output directory. -* The :generator:`CodeLite` extra generator gained a new option - set by the :variable:`CMAKE_CODELITE_USE_TARGETS` variable to - change the generated project to have target-centric organization. - The "build", "rebuild", and "clean" operations within CodeLite - then work on a selected target rather than the whole workspace. - (Note that the :generator:`Ninja` clean operation on a target - includes its dependencies, though.) +* A :prop_tgt:`VS_DEBUGGER_WORKING_DIRECTORY` target property was added + to tell :ref:`Visual Studio Generators` for VS 2010 and above what + debugger working directory should be set for the target. -* The :manual:`Compile Features ` functionality - now offers meta-features that request compiler modes for specific language - standard levels. See :prop_gbl:`CMAKE_C_KNOWN_FEATURES` and - :prop_gbl:`CMAKE_CXX_KNOWN_FEATURES`. +* A :prop_tgt:`VS_DOTNET_REFERENCES_COPY_LOCAL` target property was added + to specify whether to copy referenced assemblies to the output directory. + +* A :prop_tgt:`VS_DOTNET_REFERENCE_` target property was added + to tell :ref:`Visual Studio Generators` for VS 2010 and above to add + a .NET reference with a given hint path. + +* A :prop_sf:`VS_INCLUDE_IN_VSIX` source file property was added to + tell :ref:`Visual Studio Generators` for VS 2010 and above whether + to include the file in a Visual Studio extension package. + +* A :prop_sf:`VS_RESOURCE_GENERATOR` source file property was added to + give :ref:`Visual Studio Generators` for VS 2010 and above a setting + for the resource generator (``C#`` only). + +* A :prop_tgt:`VS_USER_PROPS` target property was added to tell + :ref:`Visual Studio Generators` for VS 2010 and above to use a + custom MSBuild user ``.props`` file. -* The :command:`cpack_ifw_configure_file` command was added - (in :module:`CPackIFWConfigureFile`) to configure file templates prepared - in QtIFW/SDK/Creator style. +* A :prop_gbl:`XCODE_EMIT_EFFECTIVE_PLATFORM_NAME` global property was + added to tell the :generator:`Xcode` generator whether to emit the + ``EFFECTIVE_PLATFORM_NAME`` variable. This is useful when building + with multiple SDKs like ``macosx`` and ``iphoneos`` in parallel. -* The :module:`CPackIFWConfigureFile` module was added to define - :command:`cpack_ifw_configure_file` command. +* New :prop_tgt:`XCODE_PRODUCT_TYPE` and :prop_tgt:`XCODE_EXPLICIT_FILE_TYPE` + target properties were created to tell the :generator:`Xcode` generator + to use custom values of the corresponding attributes for a target in the + generated Xcode project. + +Modules +------- + +* The :module:`ExternalData` module learned to support multiple + content links for one data file using different hashes, e.g. + ``img.png.sha256`` and ``img.png.sha1``. This allows objects + to be fetched from sources indexed by different hash algorithms. + +* The :module:`ExternalProject` module gained the ``GIT_PROGRESS`` option to + force Git to show progress when cloning repositories. + +* The :module:`ExternalProject` module gained a ``GIT_CONFIG`` option + to pass ``--config`` options to Git when cloning repositories. + +* The :module:`FeatureSummary` module :command:`feature_summary` command now + accepts a new ``QUIET_ON_EMPTY`` option that suppresses the output when + the list of packages that belong to the selected category is empty. + +* The :module:`FeatureSummary` module :command:`add_feature_info` command + now accepts lists of dependencies for deciding whether a feature is enabled + or not. + +* The package types accepted by the :module:`FeatureSummary` module can now + be tweaked by changing the :variable:`FeatureSummary_PKG_TYPES`, + :variable:`FeatureSummary_REQUIRED_PKG_TYPES` and + :variable:`FeatureSummary_DEFAULT_PKG_TYPE` global properties. + +* The :module:`FindOpenGL` module now provides imported targets + ``OpenGL::GL`` and ``OpenGL::GLU`` when the libraries are found. + +* The :module:`UseSWIG` module gained a ``swig_add_library`` command + to give more flexibility over the old ``swig_add_module`` command. + +* The :module:`UseSWIG` module ``swig_add_source_to_module`` command + learned a new ``SWIG_OUTFILE_DIR`` option to control the output + file location (``swig -o``). + +* The :module:`WriteCompilerDetectionHeader` module gained the + ``ALLOW_UNKNOWN_COMPILERS`` and ``ALLOW_UNKNOWN_COMPILER_VERSIONS`` options + that allow creation of headers that will work also with unknown or old + compilers by simply assuming they do not support any of the requested + features. + +CTest +----- + +* The :command:`ctest_memcheck` command gained a ``DEFECT_COUNT `` + option to capture the number of memory defects detected. + +* The :command:`ctest_memcheck` command learned to read the location of + suppressions files for sanitizers from the + :variable:`CTEST_MEMORYCHECK_SUPPRESSIONS_FILE` variable. + +* The :command:`ctest_memcheck` command learned to support ``LeakSanitizer`` + independently from ``AddressSanitizer``. + +* The :command:`ctest_update` command ``CDASH_UPLOAD`` signature was taught + to honor the ``RETRY_COUNT``, ``RETRY_DELAY``, and ``QUIET`` options. + +CPack +----- + +* The :module:`CPackIFWConfigureFile` module was added to define a new + :command:`cpack_ifw_configure_file` command to configure file templates + prepared in QtIFW/SDK/Creator style. * The :module:`CPackIFW` module :command:`cpack_ifw_configure_component` and :command:`cpack_ifw_configure_component_group` commands gained a new @@ -72,9 +311,14 @@ Changes made since CMake 3.7 include the following. option now is deprecated and will be removed in a future version of CMake. Please use new ``SORTING_PRIORITY`` option instead. -* The :module:`CPackIFW` module gained new :variable:`CPACK_IFW_PACKAGE_WATERMARK`, :variable:`CPACK_IFW_PACKAGE_BANNER`, - :variable:`CPACK_IFW_PACKAGE_BACKGROUND`, :variable:`CPACK_IFW_PACKAGE_WIZARD_STYLE`, :variable:`CPACK_IFW_PACKAGE_WIZARD_DEFAULT_WIDTH`, - :variable:`CPACK_IFW_PACKAGE_WIZARD_DEFAULT_HEIGHT` and :variable:`CPACK_IFW_PACKAGE_TITLE_COLOR` +* The :module:`CPackIFW` module gained new + :variable:`CPACK_IFW_PACKAGE_WATERMARK`, + :variable:`CPACK_IFW_PACKAGE_BANNER`, + :variable:`CPACK_IFW_PACKAGE_BACKGROUND`, + :variable:`CPACK_IFW_PACKAGE_WIZARD_STYLE`, + :variable:`CPACK_IFW_PACKAGE_WIZARD_DEFAULT_WIDTH`, + :variable:`CPACK_IFW_PACKAGE_WIZARD_DEFAULT_HEIGHT`, and + :variable:`CPACK_IFW_PACKAGE_TITLE_COLOR` variables to customize a QtIFW installer look. * The :module:`CPackProductBuild` module gained options to sign packages. @@ -83,130 +327,73 @@ Changes made since CMake 3.7 include the following. :variable:`CPACK_PKGBUILD_IDENTITY_NAME`, and :variable:`CPACK_PKGBUILD_KEYCHAIN_PATH`. -* The :module:`CPackRPM` module learned to omit - tags that are not supported by provided - rpmbuild tool. If unsupported tags are set - they are ignored and a developer warning is - printed out. +* The :module:`CPackRPM` module learned to omit tags that are not supported by + provided ``rpmbuild`` tool. If unsupported tags are set they are ignored + and a developer warning is printed out. * The :module:`CPackRPM` module learned to generate main component package which forces generation of a rpm for defined component without component suffix in filename and package name. See :variable:`CPACK_RPM_MAIN_COMPONENT` variable. -* The :module:`CPackRPM` module learned to generate a single debuginfo package - on demand even if components packagin is used. +* The :module:`CPackRPM` module learned to generate a single ``debuginfo`` + package on demand even if components packaging is used. See :variable:`CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE` variable. * The :module:`CPackRPM` module learned to support multiple directives per file when using :variable:`CPACK_RPM_USER_FILELIST` variable. -* The :command:`ctest_memcheck` command gained a ``DEFECT_COUNT `` - option to capture the number of memory defects detected. +Other +----- -* The :command:`ctest_memcheck` command learned to support ``LeakSanitizer`` - independently from ``AddressSanitizer``. +* CMake functionality using cryptographic hashes now supports SHA-3 algorithms. + +* A new generator expression ``$`` was added. + It resolves to the true-value if the condition is ``1`` and resolves to + the false-value if the condition is ``0``. + +Deprecated and Removed Features +=============================== + +* The :module:`FeatureSummary` module commands :command:`set_package_info`, + :command:`set_feature_info`, :command:`print_enabled_features`, and + :command:`print_disabled_features` are now deprecated. + +* The :module:`UseSWIG` module ``swig_add_module`` command is now + deprecated in favor of ``swig_add_library``. + +Other Changes +============= + +* If a command specified by the :prop_tgt:`_CLANG_TIDY` target property + returns non-zero at build time this is now treated as an error instead of + silently ignored. * The :command:`ctest_memcheck` command no longer automatically adds ``leak_check=1`` to the options used by ``AddressSanitizer``. The default behavior of ``AddressSanitizer`` is to run `LeakSanitizer` to check leaks unless ``leak_check=0``. -* The :command:`ctest_memcheck` command learned to read the location of - suppressions files for sanitizers from the - :variable:`CTEST_MEMORYCHECK_SUPPRESSIONS_FILE` variable. - * The :command:`ctest_memcheck` command was fixed to correctly append extra sanitizer options read from the :variable:`CTEST_MEMORYCHECK_SANITIZER_OPTIONS` variable to the environment variables used internally by the sanitizers. -* CMake learned to support CUDA as a first-class language. - It is supported by the :ref:`Makefile Generators` and the - :generator:`Ninja` generator. - -* The :command:`execute_process` command gained an ``ENCODING`` option to - specify on Windows which encoding is used for output from child process. - -* The commands :command:`add_custom_command` and :command:`add_custom_target` - learned the option ``COMMAND_EXPAND_LISTS`` which causes lists in the - ``COMMAND`` argument to be expanded, including lists created by generator - expressions. - -* The :module:`ExternalData` module learned to support multiple - content links for one data file using different hashes, e.g. - ``img.png.sha256`` and ``img.png.sha1``. This allows objects - to be fetched from sources indexed by different hash algorithms. - -* The :module:`ExternalProject` module gained the ``GIT_PROGRESS`` option to - force Git to show progress when cloning repositories. - -* The :module:`ExternalProject` module gained a ``GIT_CONFIG`` option - to pass ``--config`` options to Git when cloning repositories. - -* The :manual:`Compile Features ` functionality - is now aware of C++ 17. No specific features are yet enumerated besides - the ``cxx_std_17`` meta-feature. - -* The :command:`set_package_info`, :command:`set_feature_info`, - :command:`print_enabled_features` and :command:`print_disabled_features` - commands from the the :module:`FeatureSummary` module are now deprecated. - -* The :command:`set_package_properties` command no longer forces the package - type to ``OPTIONAL`` when the type is not explicitly set. - -* The :command:`feature_summary` command in the :module:`FeatureSummary` module - accepts the new ``QUIET_ON_EMPTY`` option that will suppresses the output when - the list of packages that belong to the selected category is empty. - -* The :command:`add_feature_info` in the :module:`FeatureSummary` module learned - to accept lists of dependencies for deciding whether a feature is enabled or - not. - -* The package types accepted by the the :module:`FeatureSummary` module can now - be tweaked by changing the :variable:`FeatureSummary_PKG_TYPES`, - :variable:`FeatureSummary_REQUIRED_PKG_TYPES` and - :variable:`FeatureSummary_DEFAULT_PKG_TYPE` global properties. - -* The :module:`FindOpenGL` module now provides imported targets - ``OpenGL::GL`` and ``OpenGL::GLU`` when the libraries are found. - -* A new minimal platform file for Fuchsia was added. - -* The :manual:`Compile Features ` functionality - is now aware of the availability of C99 in gcc since version 3.4. - -* A new logical generator expression for immediate-if was added: - ``$``. It takes three arguments: One - condition, a true-value, and a false-value. Resolves to the true-value if the - condition is ``1``, and resolves to the false-value if the condition is ``0``. - -* :ref:`Imported ` :ref:`Interface Libraries` learned new - :prop_tgt:`IMPORTED_LIBNAME` and :prop_tgt:`IMPORTED_LIBNAME_` - target properties to specify a link library name since interface libraries - do not build their own library files. - -* The :prop_tgt:`NO_SYSTEM_FROM_IMPORTED` target property is now supported - on :ref:`Imported ` :ref:`Interface Libraries`. +* The :module:`FeatureSummary` module :command:`set_package_properties` + command no longer forces the package type to ``OPTIONAL`` when the type + is not explicitly set. * The :manual:`Compile Features ` functionality is now aware of features supported by Intel C++ compilers versions 12.1 through 17.0 on UNIX and Windows platforms. -* The target property :prop_tgt:`MANUALLY_ADDED_DEPENDENCIES` has - been added. It is read-only and could be used to retrieve - dependencies that have been added with :command:`add_dependencies`. - -* The :command:`math(EXPR)` command gained support for unary - ``+`` and ``-`` expressions. - * Calls to the :module:`FindPkgConfig` module :command:`pkg_check_modules` command following a successful call learned to re-evaluate the cached values for a given prefix after changes to the parameters to the command for that prefix. -* When using AUTOMOC or AUTOUIC, generated +* When using :prop_tgt:`AUTOMOC` or :prop_tgt:`AUTOUIC`, generated ``moc_*``, ``*.moc`` and ``ui_*`` are placed in the ``/_autogen/include`` directory which is automatically added to the target's :prop_tgt:`INCLUDE_DIRECTORIES`. @@ -214,135 +401,14 @@ Changes made since CMake 3.7 include the following. :variable:`CMAKE_CURRENT_BINARY_DIR` in the target's :prop_tgt:`INCLUDE_DIRECTORIES`. -* The source file properties - :prop_sf:`SKIP_AUTOMOC`, - :prop_sf:`SKIP_AUTOUIC`, - :prop_sf:`SKIP_AUTORCC` and - :prop_sf:`SKIP_AUTOGEN` - allow to exclude files from - :prop_tgt:`AUTOMOC`, - :prop_tgt:`AUTOUIC` and - :prop_tgt:`AUTORCC` processing. - -* The :command:`string(TIMESTAMP)` will now honor the ``SOURCE_DATE_EPOCH`` - environment variable and use its value instead of the current time. - -* The :command:`source_group` command gained ``TREE`` and ``PREFIX`` - options to add groups following source tree directory structure. - -* The :prop_sf:`COMPILE_FLAGS` source file property learned to support - :manual:`generator expressions `. - -* The :generator:`Sublime Text 2` extra generator learned to place - environment variables in the generated ``.sublime-project``. - See the :variable:`CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS` variable. - -* The :generator:`Sublime Text 2` extra generator no longer excludes the - build tree from the ``.sublime-project`` when it is inside the source tree. - The :variable:`CMAKE_SUBLIME_TEXT_2_EXCLUDE_BUILD_TREE` variable - was added to control the behavior explicitly. - -* The :prop_tgt:`FRAMEWORK` property could now also be applied to - static libraries on Apple targets. It will result in a proper - Framework but with a static library inside. - * The :generator:`Sublime Text 2` generator no longer runs the native build command (e.g. ``ninja`` or ``make``) with verbose build output enabled. -* The :module:`UseSWIG` module gained a ``swig_add_library`` command - to give more flexibility over the old ``swig_add_module`` command. - -* The :module:`UseSWIG` module ``swig_add_module`` command is now - deprecated in favor of ``swig_add_library``. - -* The :command:`string(TIMESTAMP)` command learned to treat ``%%`` - as a way to encode plain ``%``. - * The :command:`try_compile` command source file signature now honors the :variable:`CMAKE_WARN_DEPRECATED` variable value in the generated test project. -* The :command:`try_compile` command source file signature gained new options - to specify the language standard to use in the generated test project. - -* The :command:`try_compile` command source file signature now honors - language standard variables like :variable:`CMAKE_CXX_STANDARD`. - See policy :policy:`CMP0067`. - -* The :module:`UseSWIG` module ``swig_add_source_to_module`` command - learned a new ``SWIG_OUTFILE_DIR`` option to control the output - file location (``swig -o``). - -* The :ref:`Visual Studio Generators` for VS 2010 and above - learned some more source file properties: - - - :prop_sf:`VS_RESOURCE_GENERATOR` (C# only): allows setting the resource - generator - - :prop_sf:`VS_COPY_TO_OUT_DIR`: parameter to set if file should be copied - to output directory (values: ``Never``, ``Always``, ``PreserveNewest``) - - :prop_sf:`VS_INCLUDE_IN_VSIX`: boolean property to include file include - Visual Studio extension package - -* The :ref:`Visual Studio Generators` for VS 2010 and above - learned to support the C# language. C# assemblies and - programs can be added just like common C++ targets using - the :command:`add_library` and :command:`add_executable` - commands. Referencing between several C# targets in the same - source tree is done by :command:`target_link_libraries` like - for C++. Referencing to system or 3rd party assemblies is - done by the target properties :prop_tgt:`VS_DOTNET_REFERENCE_` - and :prop_tgt:`VS_DOTNET_REFERENCES`. - -* C# as a language can be enabled using :command:`enable_language` - or :command:`project` with ``CSharp``. It is not enabled by - default. - -* Flag variables, target properties and other configuration - that specifically targets C# contains ``CSharp`` as a part of - their names. - -* More finetuning of C# targets can be done using target and source - file properties. Specifically the Visual Studio related target - properties (``VS_*``) are worth a look (for setting toolset - versions, root namespaces, assembly icons, ...). - -* **Auto-"linking"** in .csproj files: In C#/.NET development with - Visual Studio there is a number of visual editors used which - generate code. Both the generated files and the ones edited - with the UI are connected in the ``.csproj`` file using - ```` tags. If CMake finds within a C# project - any source file with extension ``.Designer.cs`` or ``.xaml.cs``, - it checks sibling files with extension ``.xaml``, ``.settings``, - ``.resx`` or ``.cs`` and establishes the dependency connection. - -* The :ref:`Visual Studio Generators` for VS 2010 and above can - now be fine tuned using custom msbuild .props files. - :prop_tgt:`VS_USER_PROPS` can be - used to change the default path of the user .props file from - ``$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props`` to - an arbitrary filename. - -* For the :ref:`Visual Studio Generators` for VS 2010 and above - the working directory for debugging can be set using a new - :prop_tgt:`VS_DEBUGGER_WORKING_DIRECTORY` target property. - -* The :ref:`Visual Studio Generators` for VS 2010 and above now support - adding the PACKAGE target to the targets which are built by default. - The behavior is similar to :variable:`CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD` - and can be toggled using :variable:`CMAKE_VS_INCLUDE_PACKAGE_TO_DEFAULT_BUILD`. - -* The :ref:`Visual Studio Generators` for VS 2010 and above can - now handle .NET references with hintpaths. For this the new - target property group :prop_tgt:`VS_DOTNET_REFERENCE_` - was introduced. The ```` part of the property name will - be the name of the reference, the value will be the actual - path to the assembly. - -* Copying of referenced assemblies to the output directory can - now be disabled using the target property - :prop_tgt:`VS_DOTNET_REFERENCES_COPY_LOCAL`. - * The :ref:`Visual Studio Generators` for VS 2010 and above now place per-source file flags after target-wide flags when they are classified as raw flags with no project file setting (``AdditionalOptions``). @@ -350,32 +416,6 @@ Changes made since CMake 3.7 include the following. by other generators, and allows flags on more-specific properties (per-source) to override those on more general ones (per-target). -* The :ref:`Visual Studio Generators` for VS 2013 and above learned to - support a ``host=x64`` option in the :variable:`CMAKE_GENERATOR_TOOLSET` - value (e.g. via the :manual:`cmake(1)` ``-T`` option) to request use - of a VS 64-bit toolchain on 64-bit hosts. - -* :ref:`Visual Studio Generators` learned to treat files passed to - :command:`target_link_libraries` whose names end in ``.targets`` - as MSBuild targets files to be imported into generated project files. - -* The :module:`WriteCompilerDetectionHeader` module gained the - ``ALLOW_UNKNOWN_COMPILERS`` and ``ALLOW_UNKNOWN_COMPILER_VERSIONS`` options - that allow creation of headers that will work also with unknown or old - compilers by simply assuming they do not support any of the requested - features. - * The precompiled Windows binary MSI package provided on ``cmake.org`` now records the installation directory in the Windows Registry under the key ``HKLM\Software\Kitware\CMake`` with a value named ``InstallDir``. - -* The Xcode generator can now control emission of the - ``EFFECTIVE_PLATFORM_NAME`` variable through the - :prop_gbl:`XCODE_EMIT_EFFECTIVE_PLATFORM_NAME` global property. - This is useful when building with multiple SDKs like macosx and - iphoneos in parallel. - -* New :prop_tgt:`XCODE_PRODUCT_TYPE` and :prop_tgt:`XCODE_EXPLICIT_FILE_TYPE` - target properties were created to tell the :generator:`Xcode` generator - to use custom values of the corresponding attributes for a target in the - generated Xcode project. https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3f5e4f1957c33335d792f6edde62ca59d3b158fb commit 3f5e4f1957c33335d792f6edde62ca59d3b158fb Author: Brad King AuthorDate: Wed Feb 1 10:13:03 2017 -0500 Commit: Brad King CommitDate: Mon Feb 6 10:34:12 2017 -0500 Help: Consolidate 3.8 release notes Move all development release notes into a new version-specific document: tail -q -n +3 Help/release/dev/* > Help/release/3.8.rst git rm -- Help/release/dev/* except the sample topic: git checkout HEAD -- Help/release/dev/0-sample-topic.rst Reference the new document from the release notes index document. Add a title and intro sentence to the new document by hand. diff --git a/Help/release/3.8.rst b/Help/release/3.8.rst new file mode 100644 index 0000000..1efafac --- /dev/null +++ b/Help/release/3.8.rst @@ -0,0 +1,381 @@ +CMake 3.8 Release Notes +*********************** + +.. only:: html + + .. contents:: + +Changes made since CMake 3.7 include the following. + +* A :variable:`CMAKE_BUILD_RPATH` variable and corresponding + :prop_tgt:`BUILD_RPATH` target property were added to support custom + ``RPATH`` locations to be added to binaries in the build tree. + +* A :prop_tgt:`_CPPLINT` target property and supporting + :variable:`CMAKE__CPPLINT` variable were introduced to tell + the :ref:`Makefile Generators` and the :generator:`Ninja` generator to + run the ``cpplint`` style checker along with the compiler for ``C`` and + ``CXX`` languages. + +* CMake functionality using cryptographic hashes now supports SHA-3 algorithms. + +* The :prop_tgt:`MAP_IMPORTED_CONFIG_` target property learned + to interpret empty list elements as referring to the configuration-less + imported location specified by :prop_tgt:`IMPORTED_LOCATION`. + +* If a command specified by the :prop_tgt:`_CLANG_TIDY` target property + returns non-zero at build time this is now treated as an error instead of + silently ignored. + +* The ``CDASH_UPLOAD`` signature of :command:`ctest_submit` was taught to honor + the ``RETRY_COUNT``, ``RETRY_DELAY``, and ``QUIET`` options. + +* The :generator:`CodeBlocks` now can generate with + :generator:`NMake Makefiles JOM`. + +* The :generator:`CodeLite` extra generator gained a new option + set by the :variable:`CMAKE_CODELITE_USE_TARGETS` variable to + change the generated project to have target-centric organization. + The "build", "rebuild", and "clean" operations within CodeLite + then work on a selected target rather than the whole workspace. + (Note that the :generator:`Ninja` clean operation on a target + includes its dependencies, though.) + +* The :manual:`Compile Features ` functionality + now offers meta-features that request compiler modes for specific language + standard levels. See :prop_gbl:`CMAKE_C_KNOWN_FEATURES` and + :prop_gbl:`CMAKE_CXX_KNOWN_FEATURES`. + +* The :command:`cpack_ifw_configure_file` command was added + (in :module:`CPackIFWConfigureFile`) to configure file templates prepared + in QtIFW/SDK/Creator style. + +* The :module:`CPackIFWConfigureFile` module was added to define + :command:`cpack_ifw_configure_file` command. + +* The :module:`CPackIFW` module :command:`cpack_ifw_configure_component` and + :command:`cpack_ifw_configure_component_group` commands gained a new + ``DEFAULT``, ``VIRTUAL``, ``FORCED_INSTALLATION``, ``REQUIRES_ADMIN_RIGHTS``, + ``DISPLAY_NAME``, ``UPDATE_TEXT``, ``DESCRIPTION``, ``RELEASE_DATE``, + ``AUTO_DEPEND_ON`` and ``TRANSLATIONS`` options to more specific + configuration. + +* The :module:`CPackIFW` module :command:`cpack_ifw_configure_component` + command gained a new ``DEPENDENCIES`` alias for ``DEPENDS`` option. + +* The :module:`CPackIFW` module :command:`cpack_ifw_configure_component_group` + command gained a new ``DEPENDS`` option. The ``DEPENDENCIES`` alias also + added. + +* The :module:`CPackIFW` module :command:`cpack_ifw_configure_component` and + :command:`cpack_ifw_configure_component_group` commands ``PRIORITY`` + option now is deprecated and will be removed in a future version of CMake. + Please use new ``SORTING_PRIORITY`` option instead. + +* The :module:`CPackIFW` module gained new :variable:`CPACK_IFW_PACKAGE_WATERMARK`, :variable:`CPACK_IFW_PACKAGE_BANNER`, + :variable:`CPACK_IFW_PACKAGE_BACKGROUND`, :variable:`CPACK_IFW_PACKAGE_WIZARD_STYLE`, :variable:`CPACK_IFW_PACKAGE_WIZARD_DEFAULT_WIDTH`, + :variable:`CPACK_IFW_PACKAGE_WIZARD_DEFAULT_HEIGHT` and :variable:`CPACK_IFW_PACKAGE_TITLE_COLOR` + variables to customize a QtIFW installer look. + +* The :module:`CPackProductBuild` module gained options to sign packages. + See the variables :variable:`CPACK_PRODUCTBUILD_IDENTITY_NAME`, + :variable:`CPACK_PRODUCTBUILD_KEYCHAIN_PATH`, + :variable:`CPACK_PKGBUILD_IDENTITY_NAME`, and + :variable:`CPACK_PKGBUILD_KEYCHAIN_PATH`. + +* The :module:`CPackRPM` module learned to omit + tags that are not supported by provided + rpmbuild tool. If unsupported tags are set + they are ignored and a developer warning is + printed out. + +* The :module:`CPackRPM` module learned to generate main component package + which forces generation of a rpm for defined component without component + suffix in filename and package name. + See :variable:`CPACK_RPM_MAIN_COMPONENT` variable. + +* The :module:`CPackRPM` module learned to generate a single debuginfo package + on demand even if components packagin is used. + See :variable:`CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE` variable. + +* The :module:`CPackRPM` module learned to support + multiple directives per file when using + :variable:`CPACK_RPM_USER_FILELIST` variable. + +* The :command:`ctest_memcheck` command gained a ``DEFECT_COUNT `` + option to capture the number of memory defects detected. + +* The :command:`ctest_memcheck` command learned to support ``LeakSanitizer`` + independently from ``AddressSanitizer``. + +* The :command:`ctest_memcheck` command no longer automatically adds + ``leak_check=1`` to the options used by ``AddressSanitizer``. The default + behavior of ``AddressSanitizer`` is to run `LeakSanitizer` to check leaks + unless ``leak_check=0``. + +* The :command:`ctest_memcheck` command learned to read the location of + suppressions files for sanitizers from the + :variable:`CTEST_MEMORYCHECK_SUPPRESSIONS_FILE` variable. + +* The :command:`ctest_memcheck` command was fixed to correctly append extra + sanitizer options read from the + :variable:`CTEST_MEMORYCHECK_SANITIZER_OPTIONS` variable to the environment + variables used internally by the sanitizers. + +* CMake learned to support CUDA as a first-class language. + It is supported by the :ref:`Makefile Generators` and the + :generator:`Ninja` generator. + +* The :command:`execute_process` command gained an ``ENCODING`` option to + specify on Windows which encoding is used for output from child process. + +* The commands :command:`add_custom_command` and :command:`add_custom_target` + learned the option ``COMMAND_EXPAND_LISTS`` which causes lists in the + ``COMMAND`` argument to be expanded, including lists created by generator + expressions. + +* The :module:`ExternalData` module learned to support multiple + content links for one data file using different hashes, e.g. + ``img.png.sha256`` and ``img.png.sha1``. This allows objects + to be fetched from sources indexed by different hash algorithms. + +* The :module:`ExternalProject` module gained the ``GIT_PROGRESS`` option to + force Git to show progress when cloning repositories. + +* The :module:`ExternalProject` module gained a ``GIT_CONFIG`` option + to pass ``--config`` options to Git when cloning repositories. + +* The :manual:`Compile Features ` functionality + is now aware of C++ 17. No specific features are yet enumerated besides + the ``cxx_std_17`` meta-feature. + +* The :command:`set_package_info`, :command:`set_feature_info`, + :command:`print_enabled_features` and :command:`print_disabled_features` + commands from the the :module:`FeatureSummary` module are now deprecated. + +* The :command:`set_package_properties` command no longer forces the package + type to ``OPTIONAL`` when the type is not explicitly set. + +* The :command:`feature_summary` command in the :module:`FeatureSummary` module + accepts the new ``QUIET_ON_EMPTY`` option that will suppresses the output when + the list of packages that belong to the selected category is empty. + +* The :command:`add_feature_info` in the :module:`FeatureSummary` module learned + to accept lists of dependencies for deciding whether a feature is enabled or + not. + +* The package types accepted by the the :module:`FeatureSummary` module can now + be tweaked by changing the :variable:`FeatureSummary_PKG_TYPES`, + :variable:`FeatureSummary_REQUIRED_PKG_TYPES` and + :variable:`FeatureSummary_DEFAULT_PKG_TYPE` global properties. + +* The :module:`FindOpenGL` module now provides imported targets + ``OpenGL::GL`` and ``OpenGL::GLU`` when the libraries are found. + +* A new minimal platform file for Fuchsia was added. + +* The :manual:`Compile Features ` functionality + is now aware of the availability of C99 in gcc since version 3.4. + +* A new logical generator expression for immediate-if was added: + ``$``. It takes three arguments: One + condition, a true-value, and a false-value. Resolves to the true-value if the + condition is ``1``, and resolves to the false-value if the condition is ``0``. + +* :ref:`Imported ` :ref:`Interface Libraries` learned new + :prop_tgt:`IMPORTED_LIBNAME` and :prop_tgt:`IMPORTED_LIBNAME_` + target properties to specify a link library name since interface libraries + do not build their own library files. + +* The :prop_tgt:`NO_SYSTEM_FROM_IMPORTED` target property is now supported + on :ref:`Imported ` :ref:`Interface Libraries`. + +* The :manual:`Compile Features ` functionality + is now aware of features supported by Intel C++ compilers versions 12.1 + through 17.0 on UNIX and Windows platforms. + +* The target property :prop_tgt:`MANUALLY_ADDED_DEPENDENCIES` has + been added. It is read-only and could be used to retrieve + dependencies that have been added with :command:`add_dependencies`. + +* The :command:`math(EXPR)` command gained support for unary + ``+`` and ``-`` expressions. + +* Calls to the :module:`FindPkgConfig` module :command:`pkg_check_modules` + command following a successful call learned to re-evaluate the cached values + for a given prefix after changes to the parameters to the command for that + prefix. + +* When using AUTOMOC or AUTOUIC, generated + ``moc_*``, ``*.moc`` and ``ui_*`` are placed in the + ``/_autogen/include`` directory which + is automatically added to the target's :prop_tgt:`INCLUDE_DIRECTORIES`. + It is therefore not necessary anymore to have + :variable:`CMAKE_CURRENT_BINARY_DIR` in the target's + :prop_tgt:`INCLUDE_DIRECTORIES`. + +* The source file properties + :prop_sf:`SKIP_AUTOMOC`, + :prop_sf:`SKIP_AUTOUIC`, + :prop_sf:`SKIP_AUTORCC` and + :prop_sf:`SKIP_AUTOGEN` + allow to exclude files from + :prop_tgt:`AUTOMOC`, + :prop_tgt:`AUTOUIC` and + :prop_tgt:`AUTORCC` processing. + +* The :command:`string(TIMESTAMP)` will now honor the ``SOURCE_DATE_EPOCH`` + environment variable and use its value instead of the current time. + +* The :command:`source_group` command gained ``TREE`` and ``PREFIX`` + options to add groups following source tree directory structure. + +* The :prop_sf:`COMPILE_FLAGS` source file property learned to support + :manual:`generator expressions `. + +* The :generator:`Sublime Text 2` extra generator learned to place + environment variables in the generated ``.sublime-project``. + See the :variable:`CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS` variable. + +* The :generator:`Sublime Text 2` extra generator no longer excludes the + build tree from the ``.sublime-project`` when it is inside the source tree. + The :variable:`CMAKE_SUBLIME_TEXT_2_EXCLUDE_BUILD_TREE` variable + was added to control the behavior explicitly. + +* The :prop_tgt:`FRAMEWORK` property could now also be applied to + static libraries on Apple targets. It will result in a proper + Framework but with a static library inside. + +* The :generator:`Sublime Text 2` generator no longer runs the native + build command (e.g. ``ninja`` or ``make``) with verbose build output + enabled. + +* The :module:`UseSWIG` module gained a ``swig_add_library`` command + to give more flexibility over the old ``swig_add_module`` command. + +* The :module:`UseSWIG` module ``swig_add_module`` command is now + deprecated in favor of ``swig_add_library``. + +* The :command:`string(TIMESTAMP)` command learned to treat ``%%`` + as a way to encode plain ``%``. + +* The :command:`try_compile` command source file signature now + honors the :variable:`CMAKE_WARN_DEPRECATED` variable value + in the generated test project. + +* The :command:`try_compile` command source file signature gained new options + to specify the language standard to use in the generated test project. + +* The :command:`try_compile` command source file signature now honors + language standard variables like :variable:`CMAKE_CXX_STANDARD`. + See policy :policy:`CMP0067`. + +* The :module:`UseSWIG` module ``swig_add_source_to_module`` command + learned a new ``SWIG_OUTFILE_DIR`` option to control the output + file location (``swig -o``). + +* The :ref:`Visual Studio Generators` for VS 2010 and above + learned some more source file properties: + + - :prop_sf:`VS_RESOURCE_GENERATOR` (C# only): allows setting the resource + generator + - :prop_sf:`VS_COPY_TO_OUT_DIR`: parameter to set if file should be copied + to output directory (values: ``Never``, ``Always``, ``PreserveNewest``) + - :prop_sf:`VS_INCLUDE_IN_VSIX`: boolean property to include file include + Visual Studio extension package + +* The :ref:`Visual Studio Generators` for VS 2010 and above + learned to support the C# language. C# assemblies and + programs can be added just like common C++ targets using + the :command:`add_library` and :command:`add_executable` + commands. Referencing between several C# targets in the same + source tree is done by :command:`target_link_libraries` like + for C++. Referencing to system or 3rd party assemblies is + done by the target properties :prop_tgt:`VS_DOTNET_REFERENCE_` + and :prop_tgt:`VS_DOTNET_REFERENCES`. + +* C# as a language can be enabled using :command:`enable_language` + or :command:`project` with ``CSharp``. It is not enabled by + default. + +* Flag variables, target properties and other configuration + that specifically targets C# contains ``CSharp`` as a part of + their names. + +* More finetuning of C# targets can be done using target and source + file properties. Specifically the Visual Studio related target + properties (``VS_*``) are worth a look (for setting toolset + versions, root namespaces, assembly icons, ...). + +* **Auto-"linking"** in .csproj files: In C#/.NET development with + Visual Studio there is a number of visual editors used which + generate code. Both the generated files and the ones edited + with the UI are connected in the ``.csproj`` file using + ```` tags. If CMake finds within a C# project + any source file with extension ``.Designer.cs`` or ``.xaml.cs``, + it checks sibling files with extension ``.xaml``, ``.settings``, + ``.resx`` or ``.cs`` and establishes the dependency connection. + +* The :ref:`Visual Studio Generators` for VS 2010 and above can + now be fine tuned using custom msbuild .props files. + :prop_tgt:`VS_USER_PROPS` can be + used to change the default path of the user .props file from + ``$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props`` to + an arbitrary filename. + +* For the :ref:`Visual Studio Generators` for VS 2010 and above + the working directory for debugging can be set using a new + :prop_tgt:`VS_DEBUGGER_WORKING_DIRECTORY` target property. + +* The :ref:`Visual Studio Generators` for VS 2010 and above now support + adding the PACKAGE target to the targets which are built by default. + The behavior is similar to :variable:`CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD` + and can be toggled using :variable:`CMAKE_VS_INCLUDE_PACKAGE_TO_DEFAULT_BUILD`. + +* The :ref:`Visual Studio Generators` for VS 2010 and above can + now handle .NET references with hintpaths. For this the new + target property group :prop_tgt:`VS_DOTNET_REFERENCE_` + was introduced. The ```` part of the property name will + be the name of the reference, the value will be the actual + path to the assembly. + +* Copying of referenced assemblies to the output directory can + now be disabled using the target property + :prop_tgt:`VS_DOTNET_REFERENCES_COPY_LOCAL`. + +* The :ref:`Visual Studio Generators` for VS 2010 and above now place + per-source file flags after target-wide flags when they are classified + as raw flags with no project file setting (``AdditionalOptions``). + This behavior is more consistent with the ordering of flags produced + by other generators, and allows flags on more-specific properties + (per-source) to override those on more general ones (per-target). + +* The :ref:`Visual Studio Generators` for VS 2013 and above learned to + support a ``host=x64`` option in the :variable:`CMAKE_GENERATOR_TOOLSET` + value (e.g. via the :manual:`cmake(1)` ``-T`` option) to request use + of a VS 64-bit toolchain on 64-bit hosts. + +* :ref:`Visual Studio Generators` learned to treat files passed to + :command:`target_link_libraries` whose names end in ``.targets`` + as MSBuild targets files to be imported into generated project files. + +* The :module:`WriteCompilerDetectionHeader` module gained the + ``ALLOW_UNKNOWN_COMPILERS`` and ``ALLOW_UNKNOWN_COMPILER_VERSIONS`` options + that allow creation of headers that will work also with unknown or old + compilers by simply assuming they do not support any of the requested + features. + +* The precompiled Windows binary MSI package provided on ``cmake.org`` now + records the installation directory in the Windows Registry under the key + ``HKLM\Software\Kitware\CMake`` with a value named ``InstallDir``. + +* The Xcode generator can now control emission of the + ``EFFECTIVE_PLATFORM_NAME`` variable through the + :prop_gbl:`XCODE_EMIT_EFFECTIVE_PLATFORM_NAME` global property. + This is useful when building with multiple SDKs like macosx and + iphoneos in parallel. + +* New :prop_tgt:`XCODE_PRODUCT_TYPE` and :prop_tgt:`XCODE_EXPLICIT_FILE_TYPE` + target properties were created to tell the :generator:`Xcode` generator + to use custom values of the corresponding attributes for a target in the + generated Xcode project. diff --git a/Help/release/dev/CUDA-language-support.rst b/Help/release/dev/CUDA-language-support.rst deleted file mode 100644 index 7df45bf..0000000 --- a/Help/release/dev/CUDA-language-support.rst +++ /dev/null @@ -1,6 +0,0 @@ -CUDA-language-support ---------------------- - -* CMake learned to support CUDA as a first-class language. - It is supported by the :ref:`Makefile Generators` and the - :generator:`Ninja` generator. diff --git a/Help/release/dev/ExternalData-multiple-hashes.rst b/Help/release/dev/ExternalData-multiple-hashes.rst deleted file mode 100644 index 608a277..0000000 --- a/Help/release/dev/ExternalData-multiple-hashes.rst +++ /dev/null @@ -1,7 +0,0 @@ -ExternalData-multiple-hashes ----------------------------- - -* The :module:`ExternalData` module learned to support multiple - content links for one data file using different hashes, e.g. - ``img.png.sha256`` and ``img.png.sha1``. This allows objects - to be fetched from sources indexed by different hash algorithms. diff --git a/Help/release/dev/ExternalProject-GIT_CONFIG.rst b/Help/release/dev/ExternalProject-GIT_CONFIG.rst deleted file mode 100644 index 2ab15e5..0000000 --- a/Help/release/dev/ExternalProject-GIT_CONFIG.rst +++ /dev/null @@ -1,5 +0,0 @@ -ExternalProject-GIT_CONFIG --------------------------- - -* The :module:`ExternalProject` module gained a ``GIT_CONFIG`` option - to pass ``--config`` options to Git when cloning repositories. diff --git a/Help/release/dev/FeatureSummary_enhancement.rst b/Help/release/dev/FeatureSummary_enhancement.rst deleted file mode 100644 index 3a5d85f..0000000 --- a/Help/release/dev/FeatureSummary_enhancement.rst +++ /dev/null @@ -1,22 +0,0 @@ -FeatureSummary_enhancement --------------------------- - -* The :command:`set_package_info`, :command:`set_feature_info`, - :command:`print_enabled_features` and :command:`print_disabled_features` - commands from the the :module:`FeatureSummary` module are now deprecated. - -* The :command:`set_package_properties` command no longer forces the package - type to ``OPTIONAL`` when the type is not explicitly set. - -* The :command:`feature_summary` command in the :module:`FeatureSummary` module - accepts the new ``QUIET_ON_EMPTY`` option that will suppresses the output when - the list of packages that belong to the selected category is empty. - -* The :command:`add_feature_info` in the :module:`FeatureSummary` module learned - to accept lists of dependencies for deciding whether a feature is enabled or - not. - -* The package types accepted by the the :module:`FeatureSummary` module can now - be tweaked by changing the :variable:`FeatureSummary_PKG_TYPES`, - :variable:`FeatureSummary_REQUIRED_PKG_TYPES` and - :variable:`FeatureSummary_DEFAULT_PKG_TYPE` global properties. diff --git a/Help/release/dev/FindOpenGL-imported-targets.rst b/Help/release/dev/FindOpenGL-imported-targets.rst deleted file mode 100644 index 79e3cb0..0000000 --- a/Help/release/dev/FindOpenGL-imported-targets.rst +++ /dev/null @@ -1,5 +0,0 @@ -FindOpenGL-imported-targets ---------------------------- - -* The :module:`FindOpenGL` module now provides imported targets - ``OpenGL::GL`` and ``OpenGL::GLU`` when the libraries are found. diff --git a/Help/release/dev/QtAutogen_Contain.rst b/Help/release/dev/QtAutogen_Contain.rst deleted file mode 100644 index 182233b..0000000 --- a/Help/release/dev/QtAutogen_Contain.rst +++ /dev/null @@ -1,10 +0,0 @@ -QtAutogen_Contain ------------------ - -* When using AUTOMOC or AUTOUIC, generated - ``moc_*``, ``*.moc`` and ``ui_*`` are placed in the - ``/_autogen/include`` directory which - is automatically added to the target's :prop_tgt:`INCLUDE_DIRECTORIES`. - It is therefore not necessary anymore to have - :variable:`CMAKE_CURRENT_BINARY_DIR` in the target's - :prop_tgt:`INCLUDE_DIRECTORIES`. diff --git a/Help/release/dev/QtAutogen_Skip.rst b/Help/release/dev/QtAutogen_Skip.rst deleted file mode 100644 index 37f795c..0000000 --- a/Help/release/dev/QtAutogen_Skip.rst +++ /dev/null @@ -1,12 +0,0 @@ -QtAutogen_Skip --------------- - -* The source file properties - :prop_sf:`SKIP_AUTOMOC`, - :prop_sf:`SKIP_AUTOUIC`, - :prop_sf:`SKIP_AUTORCC` and - :prop_sf:`SKIP_AUTOGEN` - allow to exclude files from - :prop_tgt:`AUTOMOC`, - :prop_tgt:`AUTOUIC` and - :prop_tgt:`AUTORCC` processing. diff --git a/Help/release/dev/SOURCE_DATE_EPOCH.rst b/Help/release/dev/SOURCE_DATE_EPOCH.rst deleted file mode 100644 index 576e1da..0000000 --- a/Help/release/dev/SOURCE_DATE_EPOCH.rst +++ /dev/null @@ -1,5 +0,0 @@ -SOURCE_DATE_EPOCH ------------------ - -* The :command:`string(TIMESTAMP)` will now honor the ``SOURCE_DATE_EPOCH`` - environment variable and use its value instead of the current time. diff --git a/Help/release/dev/SublimeText-no-VERBOSE.rst b/Help/release/dev/SublimeText-no-VERBOSE.rst deleted file mode 100644 index 70dfa2b..0000000 --- a/Help/release/dev/SublimeText-no-VERBOSE.rst +++ /dev/null @@ -1,6 +0,0 @@ -SublimeText-no-VERBOSE ----------------------- - -* The :generator:`Sublime Text 2` generator no longer runs the native - build command (e.g. ``ninja`` or ``make``) with verbose build output - enabled. diff --git a/Help/release/dev/UseSWIG-SWIG_OUTFILE_DIR.rst b/Help/release/dev/UseSWIG-SWIG_OUTFILE_DIR.rst deleted file mode 100644 index c001a88..0000000 --- a/Help/release/dev/UseSWIG-SWIG_OUTFILE_DIR.rst +++ /dev/null @@ -1,6 +0,0 @@ -UseSWIG-SWIG_OUTFILE_DIR ------------------------- - -* The :module:`UseSWIG` module ``swig_add_source_to_module`` command - learned a new ``SWIG_OUTFILE_DIR`` option to control the output - file location (``swig -o``). diff --git a/Help/release/dev/WCDH_allow_unsupported.rst b/Help/release/dev/WCDH_allow_unsupported.rst deleted file mode 100644 index c0b7377..0000000 --- a/Help/release/dev/WCDH_allow_unsupported.rst +++ /dev/null @@ -1,8 +0,0 @@ -WCDH_allow_unsupported ----------------------- - -* The :module:`WriteCompilerDetectionHeader` module gained the - ``ALLOW_UNKNOWN_COMPILERS`` and ``ALLOW_UNKNOWN_COMPILER_VERSIONS`` options - that allow creation of headers that will work also with unknown or old - compilers by simply assuming they do not support any of the requested - features. diff --git a/Help/release/dev/add-BUILD_RPATH.rst b/Help/release/dev/add-BUILD_RPATH.rst deleted file mode 100644 index 0d69e45..0000000 --- a/Help/release/dev/add-BUILD_RPATH.rst +++ /dev/null @@ -1,6 +0,0 @@ -add-BUILD_RPATH ---------------- - -* A :variable:`CMAKE_BUILD_RPATH` variable and corresponding - :prop_tgt:`BUILD_RPATH` target property were added to support custom - ``RPATH`` locations to be added to binaries in the build tree. diff --git a/Help/release/dev/add-LANG_CPPLINT.rst b/Help/release/dev/add-LANG_CPPLINT.rst deleted file mode 100644 index a0539cf..0000000 --- a/Help/release/dev/add-LANG_CPPLINT.rst +++ /dev/null @@ -1,8 +0,0 @@ -add-LANG_CPPLINT ----------------- - -* A :prop_tgt:`_CPPLINT` target property and supporting - :variable:`CMAKE__CPPLINT` variable were introduced to tell - the :ref:`Makefile Generators` and the :generator:`Ninja` generator to - run the ``cpplint`` style checker along with the compiler for ``C`` and - ``CXX`` languages. diff --git a/Help/release/dev/add-SHA-3.rst b/Help/release/dev/add-SHA-3.rst deleted file mode 100644 index 5743f10..0000000 --- a/Help/release/dev/add-SHA-3.rst +++ /dev/null @@ -1,4 +0,0 @@ -add-SHA-3 ---------- - -* CMake functionality using cryptographic hashes now supports SHA-3 algorithms. diff --git a/Help/release/dev/allow-fallback-config-mapping.rst b/Help/release/dev/allow-fallback-config-mapping.rst deleted file mode 100644 index 2522e10..0000000 --- a/Help/release/dev/allow-fallback-config-mapping.rst +++ /dev/null @@ -1,6 +0,0 @@ -allow-fallback-config-mapping ------------------------------ - -* The :prop_tgt:`MAP_IMPORTED_CONFIG_` target property learned - to interpret empty list elements as referring to the configuration-less - imported location specified by :prop_tgt:`IMPORTED_LOCATION`. diff --git a/Help/release/dev/capture-clang-tidy-errors.rst b/Help/release/dev/capture-clang-tidy-errors.rst deleted file mode 100644 index 14c32e6..0000000 --- a/Help/release/dev/capture-clang-tidy-errors.rst +++ /dev/null @@ -1,6 +0,0 @@ -capture-clang-tidy-errors -------------------------- - -* If a command specified by the :prop_tgt:`_CLANG_TIDY` target property - returns non-zero at build time this is now treated as an error instead of - silently ignored. diff --git a/Help/release/dev/cdash_upload_retry.rst b/Help/release/dev/cdash_upload_retry.rst deleted file mode 100644 index 2ceb42b..0000000 --- a/Help/release/dev/cdash_upload_retry.rst +++ /dev/null @@ -1,5 +0,0 @@ -cdash-upload-retry ------------------------ - -* The ``CDASH_UPLOAD`` signature of :command:`ctest_submit` was taught to honor - the ``RETRY_COUNT``, ``RETRY_DELAY``, and ``QUIET`` options. diff --git a/Help/release/dev/codeblocks-nmake-makefiles-jom.rst b/Help/release/dev/codeblocks-nmake-makefiles-jom.rst deleted file mode 100644 index f5612f0..0000000 --- a/Help/release/dev/codeblocks-nmake-makefiles-jom.rst +++ /dev/null @@ -1,5 +0,0 @@ -codeblocks-nmake-makefiles-jom ------------------------------- - -* The :generator:`CodeBlocks` now can generate with - :generator:`NMake Makefiles JOM`. diff --git a/Help/release/dev/codelite-build-and-clean-targets-enhancement.rst b/Help/release/dev/codelite-build-and-clean-targets-enhancement.rst deleted file mode 100644 index c6b78cf..0000000 --- a/Help/release/dev/codelite-build-and-clean-targets-enhancement.rst +++ /dev/null @@ -1,10 +0,0 @@ -codelite-build-and-clean-targets-enhancement --------------------------------------------- - -* The :generator:`CodeLite` extra generator gained a new option - set by the :variable:`CMAKE_CODELITE_USE_TARGETS` variable to - change the generated project to have target-centric organization. - The "build", "rebuild", and "clean" operations within CodeLite - then work on a selected target rather than the whole workspace. - (Note that the :generator:`Ninja` clean operation on a target - includes its dependencies, though.) diff --git a/Help/release/dev/compile-features-for-language-standards.rst b/Help/release/dev/compile-features-for-language-standards.rst deleted file mode 100644 index 20473b7..0000000 --- a/Help/release/dev/compile-features-for-language-standards.rst +++ /dev/null @@ -1,7 +0,0 @@ -compile-features-for-language-standards ---------------------------------------- - -* The :manual:`Compile Features ` functionality - now offers meta-features that request compiler modes for specific language - standard levels. See :prop_gbl:`CMAKE_C_KNOWN_FEATURES` and - :prop_gbl:`CMAKE_CXX_KNOWN_FEATURES`. diff --git a/Help/release/dev/cpack-ifw-configure-file.rst b/Help/release/dev/cpack-ifw-configure-file.rst deleted file mode 100644 index c9a1220..0000000 --- a/Help/release/dev/cpack-ifw-configure-file.rst +++ /dev/null @@ -1,9 +0,0 @@ -cpack-ifw-configure-file ------------------------- - -* The :command:`cpack_ifw_configure_file` command was added - (in :module:`CPackIFWConfigureFile`) to configure file templates prepared - in QtIFW/SDK/Creator style. - -* The :module:`CPackIFWConfigureFile` module was added to define - :command:`cpack_ifw_configure_file` command. diff --git a/Help/release/dev/cpack-ifw-options.rst b/Help/release/dev/cpack-ifw-options.rst deleted file mode 100644 index 9838fd4..0000000 --- a/Help/release/dev/cpack-ifw-options.rst +++ /dev/null @@ -1,21 +0,0 @@ -cpack-ifw-options ------------------ - -* The :module:`CPackIFW` module :command:`cpack_ifw_configure_component` and - :command:`cpack_ifw_configure_component_group` commands gained a new - ``DEFAULT``, ``VIRTUAL``, ``FORCED_INSTALLATION``, ``REQUIRES_ADMIN_RIGHTS``, - ``DISPLAY_NAME``, ``UPDATE_TEXT``, ``DESCRIPTION``, ``RELEASE_DATE``, - ``AUTO_DEPEND_ON`` and ``TRANSLATIONS`` options to more specific - configuration. - -* The :module:`CPackIFW` module :command:`cpack_ifw_configure_component` - command gained a new ``DEPENDENCIES`` alias for ``DEPENDS`` option. - -* The :module:`CPackIFW` module :command:`cpack_ifw_configure_component_group` - command gained a new ``DEPENDS`` option. The ``DEPENDENCIES`` alias also - added. - -* The :module:`CPackIFW` module :command:`cpack_ifw_configure_component` and - :command:`cpack_ifw_configure_component_group` commands ``PRIORITY`` - option now is deprecated and will be removed in a future version of CMake. - Please use new ``SORTING_PRIORITY`` option instead. diff --git a/Help/release/dev/cpack-ifw-package-options.rst b/Help/release/dev/cpack-ifw-package-options.rst deleted file mode 100644 index 1fec324..0000000 --- a/Help/release/dev/cpack-ifw-package-options.rst +++ /dev/null @@ -1,7 +0,0 @@ -cpack-ifw-package-options -------------------------- - -* The :module:`CPackIFW` module gained new :variable:`CPACK_IFW_PACKAGE_WATERMARK`, :variable:`CPACK_IFW_PACKAGE_BANNER`, - :variable:`CPACK_IFW_PACKAGE_BACKGROUND`, :variable:`CPACK_IFW_PACKAGE_WIZARD_STYLE`, :variable:`CPACK_IFW_PACKAGE_WIZARD_DEFAULT_WIDTH`, - :variable:`CPACK_IFW_PACKAGE_WIZARD_DEFAULT_HEIGHT` and :variable:`CPACK_IFW_PACKAGE_TITLE_COLOR` - variables to customize a QtIFW installer look. diff --git a/Help/release/dev/cpack-productbuild-signing.rst b/Help/release/dev/cpack-productbuild-signing.rst deleted file mode 100644 index 0b91b38..0000000 --- a/Help/release/dev/cpack-productbuild-signing.rst +++ /dev/null @@ -1,8 +0,0 @@ -cpack-productbuild-signing --------------------------- - -* The :module:`CPackProductBuild` module gained options to sign packages. - See the variables :variable:`CPACK_PRODUCTBUILD_IDENTITY_NAME`, - :variable:`CPACK_PRODUCTBUILD_KEYCHAIN_PATH`, - :variable:`CPACK_PKGBUILD_IDENTITY_NAME`, and - :variable:`CPACK_PKGBUILD_KEYCHAIN_PATH`. diff --git a/Help/release/dev/cpack-rpm-omit-unsupported-tags.rst b/Help/release/dev/cpack-rpm-omit-unsupported-tags.rst deleted file mode 100644 index abcb7a6..0000000 --- a/Help/release/dev/cpack-rpm-omit-unsupported-tags.rst +++ /dev/null @@ -1,8 +0,0 @@ -cpack-rpm-omit-unsupported-tags -------------------------------- - -* The :module:`CPackRPM` module learned to omit - tags that are not supported by provided - rpmbuild tool. If unsupported tags are set - they are ignored and a developer warning is - printed out. diff --git a/Help/release/dev/cpack-rpm-single-debuginfo.rst b/Help/release/dev/cpack-rpm-single-debuginfo.rst deleted file mode 100644 index 34a710d..0000000 --- a/Help/release/dev/cpack-rpm-single-debuginfo.rst +++ /dev/null @@ -1,11 +0,0 @@ -cpack-rpm-single-debuginfo --------------------------- - -* The :module:`CPackRPM` module learned to generate main component package - which forces generation of a rpm for defined component without component - suffix in filename and package name. - See :variable:`CPACK_RPM_MAIN_COMPONENT` variable. - -* The :module:`CPackRPM` module learned to generate a single debuginfo package - on demand even if components packagin is used. - See :variable:`CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE` variable. diff --git a/Help/release/dev/cpack-rpm-user-file-list-with-multiple-directives.rst b/Help/release/dev/cpack-rpm-user-file-list-with-multiple-directives.rst deleted file mode 100644 index ad0154d..0000000 --- a/Help/release/dev/cpack-rpm-user-file-list-with-multiple-directives.rst +++ /dev/null @@ -1,6 +0,0 @@ -cpack-rpm-user-file-list-with-multiple-directives -------------------------------------------------- - -* The :module:`CPackRPM` module learned to support - multiple directives per file when using - :variable:`CPACK_RPM_USER_FILELIST` variable. diff --git a/Help/release/dev/ctest_memcheck-leak_sanitizer.rst b/Help/release/dev/ctest_memcheck-leak_sanitizer.rst deleted file mode 100644 index 3fa5c49..0000000 --- a/Help/release/dev/ctest_memcheck-leak_sanitizer.rst +++ /dev/null @@ -1,19 +0,0 @@ -ctest_memcheck-leak_sanitizer -============================= - -* The :command:`ctest_memcheck` command learned to support ``LeakSanitizer`` - independently from ``AddressSanitizer``. - -* The :command:`ctest_memcheck` command no longer automatically adds - ``leak_check=1`` to the options used by ``AddressSanitizer``. The default - behavior of ``AddressSanitizer`` is to run `LeakSanitizer` to check leaks - unless ``leak_check=0``. - -* The :command:`ctest_memcheck` command learned to read the location of - suppressions files for sanitizers from the - :variable:`CTEST_MEMORYCHECK_SUPPRESSIONS_FILE` variable. - -* The :command:`ctest_memcheck` command was fixed to correctly append extra - sanitizer options read from the - :variable:`CTEST_MEMORYCHECK_SANITIZER_OPTIONS` variable to the environment - variables used internally by the sanitizers. diff --git a/Help/release/dev/ctest_memcheck_defect_count.rst b/Help/release/dev/ctest_memcheck_defect_count.rst deleted file mode 100644 index 70061c1..0000000 --- a/Help/release/dev/ctest_memcheck_defect_count.rst +++ /dev/null @@ -1,5 +0,0 @@ -ctest_memcheck_defect_count ---------------------------- - -* The :command:`ctest_memcheck` command gained a ``DEFECT_COUNT `` - option to capture the number of memory defects detected. diff --git a/Help/release/dev/execute_process-encoding.rst b/Help/release/dev/execute_process-encoding.rst deleted file mode 100644 index 1c7cd8c..0000000 --- a/Help/release/dev/execute_process-encoding.rst +++ /dev/null @@ -1,5 +0,0 @@ -execute_process-encoding ------------------------- - -* The :command:`execute_process` command gained an ``ENCODING`` option to - specify on Windows which encoding is used for output from child process. diff --git a/Help/release/dev/expand_custom_commands.rst b/Help/release/dev/expand_custom_commands.rst deleted file mode 100644 index c8cd897..0000000 --- a/Help/release/dev/expand_custom_commands.rst +++ /dev/null @@ -1,7 +0,0 @@ -expand_custom_commands ----------------------- - -* The commands :command:`add_custom_command` and :command:`add_custom_target` - learned the option ``COMMAND_EXPAND_LISTS`` which causes lists in the - ``COMMAND`` argument to be expanded, including lists created by generator - expressions. diff --git a/Help/release/dev/external-project-clone-progress.rst b/Help/release/dev/external-project-clone-progress.rst deleted file mode 100644 index 766a1a3..0000000 --- a/Help/release/dev/external-project-clone-progress.rst +++ /dev/null @@ -1,5 +0,0 @@ -external-project-clone-progress -------------------------------- - -* The :module:`ExternalProject` module gained the ``GIT_PROGRESS`` option to - force Git to show progress when cloning repositories. diff --git a/Help/release/dev/features-c++17.rst b/Help/release/dev/features-c++17.rst deleted file mode 100644 index 9c28ddf..0000000 --- a/Help/release/dev/features-c++17.rst +++ /dev/null @@ -1,6 +0,0 @@ -features-c++17 --------------- - -* The :manual:`Compile Features ` functionality - is now aware of C++ 17. No specific features are yet enumerated besides - the ``cxx_std_17`` meta-feature. diff --git a/Help/release/dev/fuchsia-platform.rst b/Help/release/dev/fuchsia-platform.rst deleted file mode 100644 index 9d5f3e8..0000000 --- a/Help/release/dev/fuchsia-platform.rst +++ /dev/null @@ -1,4 +0,0 @@ -fuchsia-platform ----------------- - -* A new minimal platform file for Fuchsia was added. diff --git a/Help/release/dev/gcc-features.rst b/Help/release/dev/gcc-features.rst deleted file mode 100644 index c6959ab..0000000 --- a/Help/release/dev/gcc-features.rst +++ /dev/null @@ -1,5 +0,0 @@ -gcc-features ------------- - -* The :manual:`Compile Features ` functionality - is now aware of the availability of C99 in gcc since version 3.4. diff --git a/Help/release/dev/if-genex.rst b/Help/release/dev/if-genex.rst deleted file mode 100644 index 62be3a7..0000000 --- a/Help/release/dev/if-genex.rst +++ /dev/null @@ -1,7 +0,0 @@ -genex-if --------- - -* A new logical generator expression for immediate-if was added: - ``$``. It takes three arguments: One - condition, a true-value, and a false-value. Resolves to the true-value if the - condition is ``1``, and resolves to the false-value if the condition is ``0``. diff --git a/Help/release/dev/imported-interface-libname.rst b/Help/release/dev/imported-interface-libname.rst deleted file mode 100644 index fdbae78..0000000 --- a/Help/release/dev/imported-interface-libname.rst +++ /dev/null @@ -1,7 +0,0 @@ -imported-interface-libname --------------------------- - -* :ref:`Imported ` :ref:`Interface Libraries` learned new - :prop_tgt:`IMPORTED_LIBNAME` and :prop_tgt:`IMPORTED_LIBNAME_` - target properties to specify a link library name since interface libraries - do not build their own library files. diff --git a/Help/release/dev/imported-interface-no-system.rst b/Help/release/dev/imported-interface-no-system.rst deleted file mode 100644 index 3a727cc..0000000 --- a/Help/release/dev/imported-interface-no-system.rst +++ /dev/null @@ -1,5 +0,0 @@ -imported-interface-no-system ----------------------------- - -* The :prop_tgt:`NO_SYSTEM_FROM_IMPORTED` target property is now supported - on :ref:`Imported ` :ref:`Interface Libraries`. diff --git a/Help/release/dev/intel-compile-features-windows.rst b/Help/release/dev/intel-compile-features-windows.rst deleted file mode 100644 index 6a2cdfe..0000000 --- a/Help/release/dev/intel-compile-features-windows.rst +++ /dev/null @@ -1,6 +0,0 @@ -intel-compile-features-windows ------------------------------- - -* The :manual:`Compile Features ` functionality - is now aware of features supported by Intel C++ compilers versions 12.1 - through 17.0 on UNIX and Windows platforms. diff --git a/Help/release/dev/manually-added-dependencies.rst b/Help/release/dev/manually-added-dependencies.rst deleted file mode 100644 index 6c486da..0000000 --- a/Help/release/dev/manually-added-dependencies.rst +++ /dev/null @@ -1,6 +0,0 @@ -manually-added-dependencies ---------------------------- - -* The target property :prop_tgt:`MANUALLY_ADDED_DEPENDENCIES` has - been added. It is read-only and could be used to retrieve - dependencies that have been added with :command:`add_dependencies`. diff --git a/Help/release/dev/math-EXPR-unary.rst b/Help/release/dev/math-EXPR-unary.rst deleted file mode 100644 index d4af15b0..0000000 --- a/Help/release/dev/math-EXPR-unary.rst +++ /dev/null @@ -1,5 +0,0 @@ -math-EXPR-unary ---------------- - -* The :command:`math(EXPR)` command gained support for unary - ``+`` and ``-`` expressions. diff --git a/Help/release/dev/pkg-config-recheck.rst b/Help/release/dev/pkg-config-recheck.rst deleted file mode 100644 index 950c3c8..0000000 --- a/Help/release/dev/pkg-config-recheck.rst +++ /dev/null @@ -1,7 +0,0 @@ -pkg-config-recheck ------------------- - -* Calls to the :module:`FindPkgConfig` module :command:`pkg_check_modules` - command following a successful call learned to re-evaluate the cached values - for a given prefix after changes to the parameters to the command for that - prefix. diff --git a/Help/release/dev/source_group-tree.rst b/Help/release/dev/source_group-tree.rst deleted file mode 100644 index c5fec1d..0000000 --- a/Help/release/dev/source_group-tree.rst +++ /dev/null @@ -1,5 +0,0 @@ -source_group-tree ------------------ - -* The :command:`source_group` command gained ``TREE`` and ``PREFIX`` - options to add groups following source tree directory structure. diff --git a/Help/release/dev/src-COMPILE_FLAGS-genex.rst b/Help/release/dev/src-COMPILE_FLAGS-genex.rst deleted file mode 100644 index 26cd3ef..0000000 --- a/Help/release/dev/src-COMPILE_FLAGS-genex.rst +++ /dev/null @@ -1,5 +0,0 @@ -src-COMPILE_FLAGS-genex ------------------------ - -* The :prop_sf:`COMPILE_FLAGS` source file property learned to support - :manual:`generator expressions `. diff --git a/Help/release/dev/st2-env-settings.rst b/Help/release/dev/st2-env-settings.rst deleted file mode 100644 index 7b36347..0000000 --- a/Help/release/dev/st2-env-settings.rst +++ /dev/null @@ -1,6 +0,0 @@ -st2-env-settings ----------------- - -* The :generator:`Sublime Text 2` extra generator learned to place - environment variables in the generated ``.sublime-project``. - See the :variable:`CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS` variable. diff --git a/Help/release/dev/st2-exclude-patterns-variable.rst b/Help/release/dev/st2-exclude-patterns-variable.rst deleted file mode 100644 index 8706c1f..0000000 --- a/Help/release/dev/st2-exclude-patterns-variable.rst +++ /dev/null @@ -1,7 +0,0 @@ -st2-exclude-patterns-variable ------------------------------ - -* The :generator:`Sublime Text 2` extra generator no longer excludes the - build tree from the ``.sublime-project`` when it is inside the source tree. - The :variable:`CMAKE_SUBLIME_TEXT_2_EXCLUDE_BUILD_TREE` variable - was added to control the behavior explicitly. diff --git a/Help/release/dev/static-frameworks.rst b/Help/release/dev/static-frameworks.rst deleted file mode 100644 index eae80bd..0000000 --- a/Help/release/dev/static-frameworks.rst +++ /dev/null @@ -1,6 +0,0 @@ -static-frameworks ------------------ - -* The :prop_tgt:`FRAMEWORK` property could now also be applied to - static libraries on Apple targets. It will result in a proper - Framework but with a static library inside. diff --git a/Help/release/dev/swig_add_library.rst b/Help/release/dev/swig_add_library.rst deleted file mode 100644 index 4b7723b..0000000 --- a/Help/release/dev/swig_add_library.rst +++ /dev/null @@ -1,8 +0,0 @@ -swig_add_library ----------------- - -* The :module:`UseSWIG` module gained a ``swig_add_library`` command - to give more flexibility over the old ``swig_add_module`` command. - -* The :module:`UseSWIG` module ``swig_add_module`` command is now - deprecated in favor of ``swig_add_library``. diff --git a/Help/release/dev/timestamp-percent.rst b/Help/release/dev/timestamp-percent.rst deleted file mode 100644 index 046d6c5..0000000 --- a/Help/release/dev/timestamp-percent.rst +++ /dev/null @@ -1,5 +0,0 @@ -timestamp-percent ------------------ - -* The :command:`string(TIMESTAMP)` command learned to treat ``%%`` - as a way to encode plain ``%``. diff --git a/Help/release/dev/try_compile-honor-CMAKE_WARN_DEPRECATED.rst b/Help/release/dev/try_compile-honor-CMAKE_WARN_DEPRECATED.rst deleted file mode 100644 index 9e13575..0000000 --- a/Help/release/dev/try_compile-honor-CMAKE_WARN_DEPRECATED.rst +++ /dev/null @@ -1,6 +0,0 @@ -try_compile-honor-CMAKE_WARN_DEPRECATED ---------------------------------------- - -* The :command:`try_compile` command source file signature now - honors the :variable:`CMAKE_WARN_DEPRECATED` variable value - in the generated test project. diff --git a/Help/release/dev/try_compile-lang-std.rst b/Help/release/dev/try_compile-lang-std.rst deleted file mode 100644 index 849cecc..0000000 --- a/Help/release/dev/try_compile-lang-std.rst +++ /dev/null @@ -1,9 +0,0 @@ -try_compile-lang-std --------------------- - -* The :command:`try_compile` command source file signature gained new options - to specify the language standard to use in the generated test project. - -* The :command:`try_compile` command source file signature now honors - language standard variables like :variable:`CMAKE_CXX_STANDARD`. - See policy :policy:`CMP0067`. diff --git a/Help/release/dev/vs-advanced-source-properties.rst b/Help/release/dev/vs-advanced-source-properties.rst deleted file mode 100644 index dd391e0..0000000 --- a/Help/release/dev/vs-advanced-source-properties.rst +++ /dev/null @@ -1,12 +0,0 @@ -vs-advanced-source-properties ------------------------------ - -* The :ref:`Visual Studio Generators` for VS 2010 and above - learned some more source file properties: - - - :prop_sf:`VS_RESOURCE_GENERATOR` (C# only): allows setting the resource - generator - - :prop_sf:`VS_COPY_TO_OUT_DIR`: parameter to set if file should be copied - to output directory (values: ``Never``, ``Always``, ``PreserveNewest``) - - :prop_sf:`VS_INCLUDE_IN_VSIX`: boolean property to include file include - Visual Studio extension package diff --git a/Help/release/dev/vs-csharp-support.rst b/Help/release/dev/vs-csharp-support.rst deleted file mode 100644 index 46b235a..0000000 --- a/Help/release/dev/vs-csharp-support.rst +++ /dev/null @@ -1,34 +0,0 @@ -vs-native-csharp-support ------------------------- - -* The :ref:`Visual Studio Generators` for VS 2010 and above - learned to support the C# language. C# assemblies and - programs can be added just like common C++ targets using - the :command:`add_library` and :command:`add_executable` - commands. Referencing between several C# targets in the same - source tree is done by :command:`target_link_libraries` like - for C++. Referencing to system or 3rd party assemblies is - done by the target properties :prop_tgt:`VS_DOTNET_REFERENCE_` - and :prop_tgt:`VS_DOTNET_REFERENCES`. - -* C# as a language can be enabled using :command:`enable_language` - or :command:`project` with ``CSharp``. It is not enabled by - default. - -* Flag variables, target properties and other configuration - that specifically targets C# contains ``CSharp`` as a part of - their names. - -* More finetuning of C# targets can be done using target and source - file properties. Specifically the Visual Studio related target - properties (``VS_*``) are worth a look (for setting toolset - versions, root namespaces, assembly icons, ...). - -* **Auto-"linking"** in .csproj files: In C#/.NET development with - Visual Studio there is a number of visual editors used which - generate code. Both the generated files and the ones edited - with the UI are connected in the ``.csproj`` file using - ```` tags. If CMake finds within a C# project - any source file with extension ``.Designer.cs`` or ``.xaml.cs``, - it checks sibling files with extension ``.xaml``, ``.settings``, - ``.resx`` or ``.cs`` and establishes the dependency connection. diff --git a/Help/release/dev/vs-custom-msbuild-props.rst b/Help/release/dev/vs-custom-msbuild-props.rst deleted file mode 100644 index 68dae42..0000000 --- a/Help/release/dev/vs-custom-msbuild-props.rst +++ /dev/null @@ -1,9 +0,0 @@ -vs-custom-msbuild-props ------------------------ - -* The :ref:`Visual Studio Generators` for VS 2010 and above can - now be fine tuned using custom msbuild .props files. - :prop_tgt:`VS_USER_PROPS` can be - used to change the default path of the user .props file from - ``$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props`` to - an arbitrary filename. diff --git a/Help/release/dev/vs-debugger-config.rst b/Help/release/dev/vs-debugger-config.rst deleted file mode 100644 index 58873a5..0000000 --- a/Help/release/dev/vs-debugger-config.rst +++ /dev/null @@ -1,6 +0,0 @@ -vs-debugger-configuration -------------------------- - -* For the :ref:`Visual Studio Generators` for VS 2010 and above - the working directory for debugging can be set using a new - :prop_tgt:`VS_DEBUGGER_WORKING_DIRECTORY` target property. diff --git a/Help/release/dev/vs-default-build-package.rst b/Help/release/dev/vs-default-build-package.rst deleted file mode 100644 index 62c66e0..0000000 --- a/Help/release/dev/vs-default-build-package.rst +++ /dev/null @@ -1,7 +0,0 @@ -vs-default-build-package ------------------------- - -* The :ref:`Visual Studio Generators` for VS 2010 and above now support - adding the PACKAGE target to the targets which are built by default. - The behavior is similar to :variable:`CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD` - and can be toggled using :variable:`CMAKE_VS_INCLUDE_PACKAGE_TO_DEFAULT_BUILD`. diff --git a/Help/release/dev/vs-dotnet-references.rst b/Help/release/dev/vs-dotnet-references.rst deleted file mode 100644 index 8998afb..0000000 --- a/Help/release/dev/vs-dotnet-references.rst +++ /dev/null @@ -1,13 +0,0 @@ -vs-dotnet-references --------------------- - -* The :ref:`Visual Studio Generators` for VS 2010 and above can - now handle .NET references with hintpaths. For this the new - target property group :prop_tgt:`VS_DOTNET_REFERENCE_` - was introduced. The ```` part of the property name will - be the name of the reference, the value will be the actual - path to the assembly. - -* Copying of referenced assemblies to the output directory can - now be disabled using the target property - :prop_tgt:`VS_DOTNET_REFERENCES_COPY_LOCAL`. diff --git a/Help/release/dev/vs-flag-order.rst b/Help/release/dev/vs-flag-order.rst deleted file mode 100644 index 21cea37..0000000 --- a/Help/release/dev/vs-flag-order.rst +++ /dev/null @@ -1,9 +0,0 @@ -vs-flag-order -------------- - -* The :ref:`Visual Studio Generators` for VS 2010 and above now place - per-source file flags after target-wide flags when they are classified - as raw flags with no project file setting (``AdditionalOptions``). - This behavior is more consistent with the ordering of flags produced - by other generators, and allows flags on more-specific properties - (per-source) to override those on more general ones (per-target). diff --git a/Help/release/dev/vs-host-x64-tools.rst b/Help/release/dev/vs-host-x64-tools.rst deleted file mode 100644 index e42881a..0000000 --- a/Help/release/dev/vs-host-x64-tools.rst +++ /dev/null @@ -1,7 +0,0 @@ -vs-host-x64-tools ------------------ - -* The :ref:`Visual Studio Generators` for VS 2013 and above learned to - support a ``host=x64`` option in the :variable:`CMAKE_GENERATOR_TOOLSET` - value (e.g. via the :manual:`cmake(1)` ``-T`` option) to request use - of a VS 64-bit toolchain on 64-bit hosts. diff --git a/Help/release/dev/vs_targets_file_as_library.rst b/Help/release/dev/vs_targets_file_as_library.rst deleted file mode 100644 index 9c923fa..0000000 --- a/Help/release/dev/vs_targets_file_as_library.rst +++ /dev/null @@ -1,6 +0,0 @@ -vs_targets_file_as_library --------------------------- - -* :ref:`Visual Studio Generators` learned to treat files passed to - :command:`target_link_libraries` whose names end in ``.targets`` - as MSBuild targets files to be imported into generated project files. diff --git a/Help/release/dev/wix-reg-install-dir.rst b/Help/release/dev/wix-reg-install-dir.rst deleted file mode 100644 index 961fad2..0000000 --- a/Help/release/dev/wix-reg-install-dir.rst +++ /dev/null @@ -1,6 +0,0 @@ -wix-reg-install-dir -------------------- - -* The precompiled Windows binary MSI package provided on ``cmake.org`` now - records the installation directory in the Windows Registry under the key - ``HKLM\Software\Kitware\CMake`` with a value named ``InstallDir``. diff --git a/Help/release/dev/xcode-effective-platform-name.rst b/Help/release/dev/xcode-effective-platform-name.rst deleted file mode 100644 index e337ca0..0000000 --- a/Help/release/dev/xcode-effective-platform-name.rst +++ /dev/null @@ -1,8 +0,0 @@ -xcode-effective-platform-name ------------------------------ - -* The Xcode generator can now control emission of the - ``EFFECTIVE_PLATFORM_NAME`` variable through the - :prop_gbl:`XCODE_EMIT_EFFECTIVE_PLATFORM_NAME` global property. - This is useful when building with multiple SDKs like macosx and - iphoneos in parallel. diff --git a/Help/release/dev/xcode-message-extension.rst b/Help/release/dev/xcode-message-extension.rst deleted file mode 100644 index 11c0702..0000000 --- a/Help/release/dev/xcode-message-extension.rst +++ /dev/null @@ -1,7 +0,0 @@ -xcode-message-extension ------------------------ - -* New :prop_tgt:`XCODE_PRODUCT_TYPE` and :prop_tgt:`XCODE_EXPLICIT_FILE_TYPE` - target properties were created to tell the :generator:`Xcode` generator - to use custom values of the corresponding attributes for a target in the - generated Xcode project. diff --git a/Help/release/index.rst b/Help/release/index.rst index 30decd5..292c9a8 100644 --- a/Help/release/index.rst +++ b/Help/release/index.rst @@ -13,6 +13,7 @@ Releases .. toctree:: :maxdepth: 1 + 3.8 <3.8> 3.7 <3.7> 3.6 <3.6> 3.5 <3.5> ----------------------------------------------------------------------- Summary of changes: Help/release/3.8.rst | 421 ++++++++++++++++++++ Help/release/dev/CUDA-language-support.rst | 6 - Help/release/dev/ExternalData-multiple-hashes.rst | 7 - Help/release/dev/ExternalProject-GIT_CONFIG.rst | 5 - Help/release/dev/FeatureSummary_enhancement.rst | 22 - Help/release/dev/FindOpenGL-imported-targets.rst | 5 - Help/release/dev/QtAutogen_Contain.rst | 10 - Help/release/dev/QtAutogen_Skip.rst | 12 - Help/release/dev/SOURCE_DATE_EPOCH.rst | 5 - Help/release/dev/SublimeText-no-VERBOSE.rst | 6 - Help/release/dev/UseSWIG-SWIG_OUTFILE_DIR.rst | 6 - Help/release/dev/WCDH_allow_unsupported.rst | 8 - Help/release/dev/add-BUILD_RPATH.rst | 6 - Help/release/dev/add-LANG_CPPLINT.rst | 8 - Help/release/dev/add-SHA-3.rst | 4 - Help/release/dev/allow-fallback-config-mapping.rst | 6 - Help/release/dev/capture-clang-tidy-errors.rst | 6 - Help/release/dev/cdash_upload_retry.rst | 5 - .../release/dev/codeblocks-nmake-makefiles-jom.rst | 5 - ...odelite-build-and-clean-targets-enhancement.rst | 10 - .../compile-features-for-language-standards.rst | 7 - Help/release/dev/cpack-ifw-configure-file.rst | 9 - Help/release/dev/cpack-ifw-options.rst | 21 - Help/release/dev/cpack-ifw-package-options.rst | 7 - Help/release/dev/cpack-productbuild-signing.rst | 8 - .../dev/cpack-rpm-omit-unsupported-tags.rst | 8 - Help/release/dev/cpack-rpm-single-debuginfo.rst | 11 - ...rpm-user-file-list-with-multiple-directives.rst | 6 - Help/release/dev/ctest_memcheck-leak_sanitizer.rst | 19 - Help/release/dev/ctest_memcheck_defect_count.rst | 5 - Help/release/dev/execute_process-encoding.rst | 5 - Help/release/dev/expand_custom_commands.rst | 7 - .../dev/external-project-clone-progress.rst | 5 - Help/release/dev/features-c++17.rst | 6 - Help/release/dev/fuchsia-platform.rst | 4 - Help/release/dev/gcc-features.rst | 5 - Help/release/dev/if-genex.rst | 7 - Help/release/dev/imported-interface-libname.rst | 7 - Help/release/dev/imported-interface-no-system.rst | 5 - .../release/dev/intel-compile-features-windows.rst | 6 - Help/release/dev/manually-added-dependencies.rst | 6 - Help/release/dev/math-EXPR-unary.rst | 5 - Help/release/dev/pkg-config-recheck.rst | 7 - Help/release/dev/source_group-tree.rst | 5 - Help/release/dev/src-COMPILE_FLAGS-genex.rst | 5 - Help/release/dev/st2-env-settings.rst | 6 - Help/release/dev/st2-exclude-patterns-variable.rst | 7 - Help/release/dev/static-frameworks.rst | 6 - Help/release/dev/swig_add_library.rst | 8 - Help/release/dev/timestamp-percent.rst | 5 - .../try_compile-honor-CMAKE_WARN_DEPRECATED.rst | 6 - Help/release/dev/try_compile-lang-std.rst | 9 - Help/release/dev/vs-advanced-source-properties.rst | 12 - Help/release/dev/vs-csharp-support.rst | 34 -- Help/release/dev/vs-custom-msbuild-props.rst | 9 - Help/release/dev/vs-debugger-config.rst | 6 - Help/release/dev/vs-default-build-package.rst | 7 - Help/release/dev/vs-dotnet-references.rst | 13 - Help/release/dev/vs-flag-order.rst | 9 - Help/release/dev/vs-host-x64-tools.rst | 7 - Help/release/dev/vs_targets_file_as_library.rst | 6 - Help/release/dev/wix-reg-install-dir.rst | 6 - Help/release/dev/xcode-effective-platform-name.rst | 8 - Help/release/dev/xcode-message-extension.rst | 7 - Help/release/index.rst | 1 + 65 files changed, 422 insertions(+), 499 deletions(-) create mode 100644 Help/release/3.8.rst delete mode 100644 Help/release/dev/CUDA-language-support.rst delete mode 100644 Help/release/dev/ExternalData-multiple-hashes.rst delete mode 100644 Help/release/dev/ExternalProject-GIT_CONFIG.rst delete mode 100644 Help/release/dev/FeatureSummary_enhancement.rst delete mode 100644 Help/release/dev/FindOpenGL-imported-targets.rst delete mode 100644 Help/release/dev/QtAutogen_Contain.rst delete mode 100644 Help/release/dev/QtAutogen_Skip.rst delete mode 100644 Help/release/dev/SOURCE_DATE_EPOCH.rst delete mode 100644 Help/release/dev/SublimeText-no-VERBOSE.rst delete mode 100644 Help/release/dev/UseSWIG-SWIG_OUTFILE_DIR.rst delete mode 100644 Help/release/dev/WCDH_allow_unsupported.rst delete mode 100644 Help/release/dev/add-BUILD_RPATH.rst delete mode 100644 Help/release/dev/add-LANG_CPPLINT.rst delete mode 100644 Help/release/dev/add-SHA-3.rst delete mode 100644 Help/release/dev/allow-fallback-config-mapping.rst delete mode 100644 Help/release/dev/capture-clang-tidy-errors.rst delete mode 100644 Help/release/dev/cdash_upload_retry.rst delete mode 100644 Help/release/dev/codeblocks-nmake-makefiles-jom.rst delete mode 100644 Help/release/dev/codelite-build-and-clean-targets-enhancement.rst delete mode 100644 Help/release/dev/compile-features-for-language-standards.rst delete mode 100644 Help/release/dev/cpack-ifw-configure-file.rst delete mode 100644 Help/release/dev/cpack-ifw-options.rst delete mode 100644 Help/release/dev/cpack-ifw-package-options.rst delete mode 100644 Help/release/dev/cpack-productbuild-signing.rst delete mode 100644 Help/release/dev/cpack-rpm-omit-unsupported-tags.rst delete mode 100644 Help/release/dev/cpack-rpm-single-debuginfo.rst delete mode 100644 Help/release/dev/cpack-rpm-user-file-list-with-multiple-directives.rst delete mode 100644 Help/release/dev/ctest_memcheck-leak_sanitizer.rst delete mode 100644 Help/release/dev/ctest_memcheck_defect_count.rst delete mode 100644 Help/release/dev/execute_process-encoding.rst delete mode 100644 Help/release/dev/expand_custom_commands.rst delete mode 100644 Help/release/dev/external-project-clone-progress.rst delete mode 100644 Help/release/dev/features-c++17.rst delete mode 100644 Help/release/dev/fuchsia-platform.rst delete mode 100644 Help/release/dev/gcc-features.rst delete mode 100644 Help/release/dev/if-genex.rst delete mode 100644 Help/release/dev/imported-interface-libname.rst delete mode 100644 Help/release/dev/imported-interface-no-system.rst delete mode 100644 Help/release/dev/intel-compile-features-windows.rst delete mode 100644 Help/release/dev/manually-added-dependencies.rst delete mode 100644 Help/release/dev/math-EXPR-unary.rst delete mode 100644 Help/release/dev/pkg-config-recheck.rst delete mode 100644 Help/release/dev/source_group-tree.rst delete mode 100644 Help/release/dev/src-COMPILE_FLAGS-genex.rst delete mode 100644 Help/release/dev/st2-env-settings.rst delete mode 100644 Help/release/dev/st2-exclude-patterns-variable.rst delete mode 100644 Help/release/dev/static-frameworks.rst delete mode 100644 Help/release/dev/swig_add_library.rst delete mode 100644 Help/release/dev/timestamp-percent.rst delete mode 100644 Help/release/dev/try_compile-honor-CMAKE_WARN_DEPRECATED.rst delete mode 100644 Help/release/dev/try_compile-lang-std.rst delete mode 100644 Help/release/dev/vs-advanced-source-properties.rst delete mode 100644 Help/release/dev/vs-csharp-support.rst delete mode 100644 Help/release/dev/vs-custom-msbuild-props.rst delete mode 100644 Help/release/dev/vs-debugger-config.rst delete mode 100644 Help/release/dev/vs-default-build-package.rst delete mode 100644 Help/release/dev/vs-dotnet-references.rst delete mode 100644 Help/release/dev/vs-flag-order.rst delete mode 100644 Help/release/dev/vs-host-x64-tools.rst delete mode 100644 Help/release/dev/vs_targets_file_as_library.rst delete mode 100644 Help/release/dev/wix-reg-install-dir.rst delete mode 100644 Help/release/dev/xcode-effective-platform-name.rst delete mode 100644 Help/release/dev/xcode-message-extension.rst hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 6 11:16:07 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 6 Feb 2017 11:16:07 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1303-g92be2fb Message-ID: <20170206161607.E43DAF5ACC@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 92be2fb392d694dffc80e635f4ac10212cfd7ef9 (commit) via c2f7ef637e7e47adf89cc8ef2eea2d6f879ddc7d (commit) via 3f5e4f1957c33335d792f6edde62ca59d3b158fb (commit) from 811c854efffba6f97bb3038b651fed7fc1bcf2be (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=92be2fb392d694dffc80e635f4ac10212cfd7ef9 commit 92be2fb392d694dffc80e635f4ac10212cfd7ef9 Merge: 811c854 c2f7ef6 Author: Brad King AuthorDate: Mon Feb 6 11:16:06 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 6 11:16:06 2017 -0500 Merge topic 'doc-3.8-relnotes' c2f7ef63 Help: Organize and revise 3.8 release notes 3f5e4f19 Help: Consolidate 3.8 release notes ----------------------------------------------------------------------- Summary of changes: Help/release/3.8.rst | 421 ++++++++++++++++++++ Help/release/dev/CUDA-language-support.rst | 6 - Help/release/dev/ExternalData-multiple-hashes.rst | 7 - Help/release/dev/ExternalProject-GIT_CONFIG.rst | 5 - Help/release/dev/FeatureSummary_enhancement.rst | 22 - Help/release/dev/FindOpenGL-imported-targets.rst | 5 - Help/release/dev/QtAutogen_Contain.rst | 10 - Help/release/dev/QtAutogen_Skip.rst | 12 - Help/release/dev/SOURCE_DATE_EPOCH.rst | 5 - Help/release/dev/SublimeText-no-VERBOSE.rst | 6 - Help/release/dev/UseSWIG-SWIG_OUTFILE_DIR.rst | 6 - Help/release/dev/WCDH_allow_unsupported.rst | 8 - Help/release/dev/add-BUILD_RPATH.rst | 6 - Help/release/dev/add-LANG_CPPLINT.rst | 8 - Help/release/dev/add-SHA-3.rst | 4 - Help/release/dev/allow-fallback-config-mapping.rst | 6 - Help/release/dev/capture-clang-tidy-errors.rst | 6 - Help/release/dev/cdash_upload_retry.rst | 5 - .../release/dev/codeblocks-nmake-makefiles-jom.rst | 5 - ...odelite-build-and-clean-targets-enhancement.rst | 10 - .../compile-features-for-language-standards.rst | 7 - Help/release/dev/cpack-ifw-configure-file.rst | 9 - Help/release/dev/cpack-ifw-options.rst | 21 - Help/release/dev/cpack-ifw-package-options.rst | 7 - Help/release/dev/cpack-productbuild-signing.rst | 8 - .../dev/cpack-rpm-omit-unsupported-tags.rst | 8 - Help/release/dev/cpack-rpm-single-debuginfo.rst | 11 - ...rpm-user-file-list-with-multiple-directives.rst | 6 - Help/release/dev/ctest_memcheck-leak_sanitizer.rst | 19 - Help/release/dev/ctest_memcheck_defect_count.rst | 5 - Help/release/dev/execute_process-encoding.rst | 5 - Help/release/dev/expand_custom_commands.rst | 7 - .../dev/external-project-clone-progress.rst | 5 - Help/release/dev/features-c++17.rst | 6 - Help/release/dev/fuchsia-platform.rst | 4 - Help/release/dev/gcc-features.rst | 5 - Help/release/dev/if-genex.rst | 7 - Help/release/dev/imported-interface-libname.rst | 7 - Help/release/dev/imported-interface-no-system.rst | 5 - .../release/dev/intel-compile-features-windows.rst | 6 - Help/release/dev/manually-added-dependencies.rst | 6 - Help/release/dev/math-EXPR-unary.rst | 5 - Help/release/dev/pkg-config-recheck.rst | 7 - Help/release/dev/source_group-tree.rst | 5 - Help/release/dev/src-COMPILE_FLAGS-genex.rst | 5 - Help/release/dev/st2-env-settings.rst | 6 - Help/release/dev/st2-exclude-patterns-variable.rst | 7 - Help/release/dev/static-frameworks.rst | 6 - Help/release/dev/swig_add_library.rst | 8 - Help/release/dev/timestamp-percent.rst | 5 - .../try_compile-honor-CMAKE_WARN_DEPRECATED.rst | 6 - Help/release/dev/try_compile-lang-std.rst | 9 - Help/release/dev/vs-advanced-source-properties.rst | 12 - Help/release/dev/vs-csharp-support.rst | 34 -- Help/release/dev/vs-custom-msbuild-props.rst | 9 - Help/release/dev/vs-debugger-config.rst | 6 - Help/release/dev/vs-default-build-package.rst | 7 - Help/release/dev/vs-dotnet-references.rst | 13 - Help/release/dev/vs-flag-order.rst | 9 - Help/release/dev/vs-host-x64-tools.rst | 7 - Help/release/dev/vs_targets_file_as_library.rst | 6 - Help/release/dev/wix-reg-install-dir.rst | 6 - Help/release/dev/xcode-effective-platform-name.rst | 8 - Help/release/dev/xcode-message-extension.rst | 7 - Help/release/index.rst | 1 + 65 files changed, 422 insertions(+), 499 deletions(-) create mode 100644 Help/release/3.8.rst delete mode 100644 Help/release/dev/CUDA-language-support.rst delete mode 100644 Help/release/dev/ExternalData-multiple-hashes.rst delete mode 100644 Help/release/dev/ExternalProject-GIT_CONFIG.rst delete mode 100644 Help/release/dev/FeatureSummary_enhancement.rst delete mode 100644 Help/release/dev/FindOpenGL-imported-targets.rst delete mode 100644 Help/release/dev/QtAutogen_Contain.rst delete mode 100644 Help/release/dev/QtAutogen_Skip.rst delete mode 100644 Help/release/dev/SOURCE_DATE_EPOCH.rst delete mode 100644 Help/release/dev/SublimeText-no-VERBOSE.rst delete mode 100644 Help/release/dev/UseSWIG-SWIG_OUTFILE_DIR.rst delete mode 100644 Help/release/dev/WCDH_allow_unsupported.rst delete mode 100644 Help/release/dev/add-BUILD_RPATH.rst delete mode 100644 Help/release/dev/add-LANG_CPPLINT.rst delete mode 100644 Help/release/dev/add-SHA-3.rst delete mode 100644 Help/release/dev/allow-fallback-config-mapping.rst delete mode 100644 Help/release/dev/capture-clang-tidy-errors.rst delete mode 100644 Help/release/dev/cdash_upload_retry.rst delete mode 100644 Help/release/dev/codeblocks-nmake-makefiles-jom.rst delete mode 100644 Help/release/dev/codelite-build-and-clean-targets-enhancement.rst delete mode 100644 Help/release/dev/compile-features-for-language-standards.rst delete mode 100644 Help/release/dev/cpack-ifw-configure-file.rst delete mode 100644 Help/release/dev/cpack-ifw-options.rst delete mode 100644 Help/release/dev/cpack-ifw-package-options.rst delete mode 100644 Help/release/dev/cpack-productbuild-signing.rst delete mode 100644 Help/release/dev/cpack-rpm-omit-unsupported-tags.rst delete mode 100644 Help/release/dev/cpack-rpm-single-debuginfo.rst delete mode 100644 Help/release/dev/cpack-rpm-user-file-list-with-multiple-directives.rst delete mode 100644 Help/release/dev/ctest_memcheck-leak_sanitizer.rst delete mode 100644 Help/release/dev/ctest_memcheck_defect_count.rst delete mode 100644 Help/release/dev/execute_process-encoding.rst delete mode 100644 Help/release/dev/expand_custom_commands.rst delete mode 100644 Help/release/dev/external-project-clone-progress.rst delete mode 100644 Help/release/dev/features-c++17.rst delete mode 100644 Help/release/dev/fuchsia-platform.rst delete mode 100644 Help/release/dev/gcc-features.rst delete mode 100644 Help/release/dev/if-genex.rst delete mode 100644 Help/release/dev/imported-interface-libname.rst delete mode 100644 Help/release/dev/imported-interface-no-system.rst delete mode 100644 Help/release/dev/intel-compile-features-windows.rst delete mode 100644 Help/release/dev/manually-added-dependencies.rst delete mode 100644 Help/release/dev/math-EXPR-unary.rst delete mode 100644 Help/release/dev/pkg-config-recheck.rst delete mode 100644 Help/release/dev/source_group-tree.rst delete mode 100644 Help/release/dev/src-COMPILE_FLAGS-genex.rst delete mode 100644 Help/release/dev/st2-env-settings.rst delete mode 100644 Help/release/dev/st2-exclude-patterns-variable.rst delete mode 100644 Help/release/dev/static-frameworks.rst delete mode 100644 Help/release/dev/swig_add_library.rst delete mode 100644 Help/release/dev/timestamp-percent.rst delete mode 100644 Help/release/dev/try_compile-honor-CMAKE_WARN_DEPRECATED.rst delete mode 100644 Help/release/dev/try_compile-lang-std.rst delete mode 100644 Help/release/dev/vs-advanced-source-properties.rst delete mode 100644 Help/release/dev/vs-csharp-support.rst delete mode 100644 Help/release/dev/vs-custom-msbuild-props.rst delete mode 100644 Help/release/dev/vs-debugger-config.rst delete mode 100644 Help/release/dev/vs-default-build-package.rst delete mode 100644 Help/release/dev/vs-dotnet-references.rst delete mode 100644 Help/release/dev/vs-flag-order.rst delete mode 100644 Help/release/dev/vs-host-x64-tools.rst delete mode 100644 Help/release/dev/vs_targets_file_as_library.rst delete mode 100644 Help/release/dev/wix-reg-install-dir.rst delete mode 100644 Help/release/dev/xcode-effective-platform-name.rst delete mode 100644 Help/release/dev/xcode-message-extension.rst hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 6 11:16:32 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 6 Feb 2017 11:16:32 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-2567-g12b6adf Message-ID: <20170206161632.15E1FF59DA@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 12b6adf4bd562ddd1b4dccb9a2888e1c854a6b6e (commit) via 92be2fb392d694dffc80e635f4ac10212cfd7ef9 (commit) from a80bdaf9e0c4f73e9a69a76f159e5c0f940ed1d7 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=12b6adf4bd562ddd1b4dccb9a2888e1c854a6b6e commit 12b6adf4bd562ddd1b4dccb9a2888e1c854a6b6e Merge: a80bdaf 92be2fb Author: Brad King AuthorDate: Mon Feb 6 11:16:23 2017 -0500 Commit: Brad King CommitDate: Mon Feb 6 11:16:23 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From cmake-commits at cmake.org Mon Feb 6 11:34:19 2017 From: cmake-commits at cmake.org (cmake-commits at cmake.org) Date: Mon, 6 Feb 2017 11:34:19 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1307-g0f4dae0 Message-ID: <20170206163419.716ECFA496@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 0f4dae0a4da92af5079eb730443ec188b3b46f8e (commit) via c9bb3530dc6117b495237113d38dc7d812b23b72 (commit) via 566d20771f82492081c55c9da6f1768941eee40a (commit) via 1d25e8a7c9000a2261dfb42337a2cd7456fc81d5 (commit) from 92be2fb392d694dffc80e635f4ac10212cfd7ef9 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- Utilities/Release/upload_release.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- CMake From cmake-commits at cmake.org Mon Feb 6 11:34:21 2017 From: cmake-commits at cmake.org (cmake-commits at cmake.org) Date: Mon, 6 Feb 2017 11:34:21 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-1308-g4d50525 Message-ID: <20170206163423.8D443FA4D9@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated discards 12b6adf4bd562ddd1b4dccb9a2888e1c854a6b6e (commit) discards a80bdaf9e0c4f73e9a69a76f159e5c0f940ed1d7 (commit) discards 2d467f548d2d718777f12b4b947745723a82bf53 (commit) discards 73f49b01b85506fd3bf5a496a9dc5a48fc93fb6f (commit) discards 9c24b1fa2b36569b6f53b9b12a1cc9ffca8146ee (commit) discards d4425e65f256faf78ccaf425653e5e17b4527f0e (commit) discards c13efe3208f32cba458eb89dde44f3fe29828a7e (commit) discards 3d4e6340f31d9c5b15ad0a748a7295eaea7e8943 (commit) discards 8c3b29c2afeb30fcf54e2c0025d4663515f904cb (commit) discards 8509e8b14ead75ebcbedf0fa839bc733b1a39f4f (commit) discards bc0eaa247812088f98bb77230a6c334125ff7a99 (commit) discards 84f6bac8afd6a7d30de829023e74b5d10225e34f (commit) discards c5b1e1926e1726ce3f265464103f77e48fea9abd (commit) discards 3e731810ee6fad31692baedffa9d1263f8156f76 (commit) discards 5d570616a4f3675260490da1604b8ad17ce98bbe (commit) discards f28a0de44953afab170272a04dca84432c4e0768 (commit) discards fafb38bf32458bb9f7514a7c6483ca324a15fc22 (commit) discards a792ec426975260a7fe6fb87ae0972030a06d2c6 (commit) discards 70284f1b4c89252e2801915312e1c5acac7cb61e (commit) discards 4bea231d1dff8063c2db37aa4344d36994ec6b46 (commit) discards f010baec3bc9df9a1fb23aab03128a2d203d6787 (commit) discards cac9e0b28df85225438816458ceab01ba4d534db (commit) discards f50c35777f571e941dcc9a5f1f1696babe885b6e (commit) discards a87b7cf205dc6952be402e7caf509be6d3842383 (commit) discards 812615097035bacfa405a5b87312a9385e93cccb (commit) discards f801bf68320dc6bbccd8f420d3714f61d201b5f3 (commit) discards b200010717b18854a765a9cbe2c3fc72d58fdc1c (commit) discards 50be50f8fd017a4f014aded68d81e1955382db63 (commit) discards 9a4338d7f59750c2cbd61ed0a252224f102f0384 (commit) discards 44fb57c9093b67bc533380b12727997f8e67efa1 (commit) discards 071c3622c8954ed74e27ce7671d5de83627dfd0b (commit) discards 8211f08186e67fb88296ff055d95048296482307 (commit) discards 74643ffb144fc5045107fdfc2f4ebdc8e4854a37 (commit) discards 903c0cda337e58c95ff947fdd4b0b21396bd6feb (commit) discards 16e60561ee679b1f53b08dd68ac084bdb2481473 (commit) discards 84a9b255dbe0cf119a9f3726f36e5c4b060303cc (commit) discards 7c27b23602b62c9cb0b158bbcfc485ce9e30d7fc (commit) discards adb33f13eb844bb4412e76a113438727bc4ccd81 (commit) discards 03d7ead1246818cd076d4d45bb5e970baf781bc9 (commit) discards 70f45f9b647663c15df652c1d3063a53f3667a34 (commit) discards 45ffe4d2d2f45f04f9e5e5800cb374a2fc9fa18c (commit) discards 42820eaedad8c6dddcf84e7a57ea102a6ca72bd4 (commit) discards da1abae81303233cb78f0590f92aef75e82275f9 (commit) discards e7bbf8c3ce1362f30602b73e57feb36af14b46ac (commit) discards f4de2ab585caf8a9c6773fa4507008b83a1ca2cf (commit) discards 771e9f2fe79ec1a1bdf8189f88e48704e97b827e (commit) discards c381c193a1ceeb79cf84ab905a0076c783b32707 (commit) discards bef58c63926fdb86c63525bed0ea57ed40d9e529 (commit) discards c43228b1fe914035a93ceff23b91017122b5f1bc (commit) discards 18e576c1d797645817d1e132b62f057c2328ed1c (commit) discards 79f7ba3fbe67b520d7d564c7944f49c798f8c85a (commit) discards a5c058ad83c469822d38f3ad5960d9cd4c2d370a (commit) discards da2c5c14ece09801e66a27d91021f1851adc2247 (commit) discards 036f34c7387b4e4cda45e8e2a3a7dc4e5cb6712c (commit) discards 9f309d00e86fea6ffe1deb30384d4789d5f90e45 (commit) discards 915c71e3a05dc7f33ba662a9c116b090befa140b (commit) discards 4136fd001052643765347c91c2ef70d146973150 (commit) discards ad55932e3d6ee96a52bad0e821cdbbd9672f100f (commit) discards 5eb3c083401d6cf054a6841688702c0102b4aecb (commit) discards 17e5230ea6f68587ee2eda1145ef086d564e1229 (commit) discards 2a99491734ddf8a879ab7ca6492373cf072031d4 (commit) discards 372e87197b07d1b5d68712b609f5184d1d974f73 (commit) discards 6de43c42ad12bd8bc92845cfcdbaf7d623e44ca3 (commit) discards 3a61f7e8e2ec578a9512dd3599088d8d24f158dd (commit) discards e93b76ec1e916a4546dee8f8735b4115f16b201c (commit) discards 3c97335df6f03f4c9737f75eaff65e9ba2e718ec (commit) discards 4407ab5ece0abb662b86a53bc651651141c4b162 (commit) discards 086a1ec7889b14375c628cc58be721011de41abc (commit) discards 0440b8fa4e8475e062c23aa1729984659028bd0b (commit) discards 06a5bb57c31fa588e939ba5fdd66a2337da73035 (commit) discards 6f899744ad89c07185b4ab89c0d14f5289369ea4 (commit) discards 7d4c722add9f1e799fc278d164fa4fb0916f3aa4 (commit) discards 698f5243cde7238cb289f1750e56a01d571591e7 (commit) discards ef372b3a0a6b1d6c915ba404ec0acb83e6d89925 (commit) discards e2025bcc8ba13eef8f2e8f6709128f845dc3ff2b (commit) discards 9c7eecc64a484482e55f584ec97f582288faadf5 (commit) discards abb20e3234f49fe6d40bf3506b1d8f28277198c3 (commit) discards 48381a9899894532e40e6ecaa4f2e83b0b35b171 (commit) discards 91751d6491c7fad048a5fa62fe52c9db043c4801 (commit) discards 6ccabce2cd5736f076ebf079cd05e0ac6ff28209 (commit) discards 784fe97dbf81cb1dcf81f213de1843a5351a94c7 (commit) discards 498ac510f97da1932b7cf01ada26dd6401db00f0 (commit) discards a38022e786f751fea0785f45df9a611cbf863b34 (commit) discards a3faf127a169cad512f9d6c67adfa1d8cc781f11 (commit) discards e715efbedea5ef980aee816f6a398ce8752e5877 (commit) discards 6d2ebf57d7ad7e9772ef2cbc2321329b03e50770 (commit) discards 6932f8466cae72e4d231bb2ce4929d38a306e00a (commit) discards 2903e108bde5d4e493a0fbbef1eebba0e49e49da (commit) discards fb28d942cb449a91356f5da31033b312993740ba (commit) discards ced346efc67dbfa23f76cb13622485d07c8e9f5f (commit) discards 2086b6a344ba7dbf235a5d161035aea9fb966628 (commit) discards 0fbe7569ce673f75d61e01cf644006df8e1d0432 (commit) discards 597fe23b9bdeff2276adc1c6204c7d45eee7f7bd (commit) discards 22e81072b78eeca40e4a68f79b2bb0d19e059c85 (commit) discards 9ee77262c3485d0079698ce52ec163a9971ca6d1 (commit) discards 0fabbf1027a5872b8c9228bdcc548133bb08005b (commit) discards c610be3c4f698e4fdb3e3272305e381121c8103b (commit) discards 51c1863936254a27fb1fe756f2c5c2bcef718422 (commit) discards 75650c68024ad5d9d3374e197d5fdec5ae9406aa (commit) discards ad64b91c25208a5b27f49cef201ae155aae3cd9e (commit) discards 0758c659996640f6558d09ee9835ad325c60c25d (commit) discards 266fe3bd760dcd93d51c556baff7dfcf5bfc66f4 (commit) discards 4b9e085f77ac2500d2a3bbd2253acbc6b1c84c0e (commit) discards 7c51e930146249c1220275a030af5b557b0a4799 (commit) discards 63bba4d2b9d729ffb852e93df4b04c6635f04c21 (commit) discards 1325cfc3a76387a327b5758adcf8ef42f2e19af3 (commit) discards 67c2364394141cecc3aa1f3c065ff25ce71a4efe (commit) discards 2a1a1cd66b63cac5cf2aff533bec4c35984a115c (commit) discards 46177cceae13afa80baa87e6d84c17ed45ecb298 (commit) discards e2dadb0802b1e329d6b1df771ce6bfbe84b08a4b (commit) discards c6db87387ee1e5c30b9bc873ad2438db5bd6e43a (commit) discards 610e3cfb8b490ddd154f3a47d676e03e82dc714a (commit) discards 1d0ed3063e2e9cc918b9fdcf45bbdb3aa6b0ce09 (commit) discards ffd0a359ca89ce397cd2603166b3370cbcfb25ff (commit) discards fc0d4d17232df6f2f2e7a130f25398db37ac4dcb (commit) discards 203112a512053157b7931ba0d92573e1a1bf86ba (commit) discards b022eb947f75b36ddaf3ec4aeffac56025e19ed0 (commit) discards 7b9ff037836da0342d173be8d74ecc44e31640db (commit) discards 3fcca6156371952688785ac354d0d4f6276400ed (commit) discards f9f1d9f2333ca6f76b816c303187abd2ae976e93 (commit) discards 842491d93681faa0d874bbaf0d31ace78df0ac1f (commit) discards 972dd56913054eedfc1f8cf39bf47c7132b973c6 (commit) discards cfa206ce421fe093b95aeb3ff14cce38d0005f28 (commit) discards 8708542da2b794a08b11c3ccae91dc927504ae50 (commit) discards 0256ba65a806b9e9aefa03acec4f39cdcf71f2e4 (commit) discards 368845459f43438e239663171cb38125915d5080 (commit) discards 8ccf48b37ada48d940e7a525cab2354ded7f3794 (commit) discards 90a3dd6f7cbb1263ea92537fc780678aa6c01999 (commit) discards fea7e6f3ce3d24510a883e8dd2c92ca38fa34acd (commit) discards 474151cfc6545eb0938e45fe5885c2ae569098ec (commit) discards df0c2c01ada32e63420fcaa4cfdb1e6acd3137d5 (commit) discards ca3a4fee2db8946a5ba46498959027a5cdf84b9a (commit) discards 893423e9c9f4563dcd33e6472c8be85ec1aca88c (commit) discards 69cd1ce190268342cc570569afbba1fc6038822e (commit) discards f6bdf63b18766c59d8ffca0e0383ad7ee14f0ce9 (commit) discards 613019294497177018550dc4969e3c2b9b603f1b (commit) discards 0d5d02923532b736915bcfbbb9677c4c2c8638a1 (commit) discards c66720d15dcf9bc8fd478e2bd3ec6cd0aed9fef4 (commit) discards 639429cb85ed679c38223c7be1c4a0dfd3b3de39 (commit) discards 82eb1702d16723c4f997ded593cbe7cb0ca75999 (commit) discards bb234a4b50ecca06c00ab4f4cebdd44261f25653 (commit) discards 1fe432a4a94ef20f8fad1b516a04541ba00e2610 (commit) discards 72c29b28286a37cde40e1b231d915f2b1fd249f8 (commit) discards 28fe71051162e95fe5eb116c11cf36eacc3b1d7d (commit) discards b278af8e08066537fa4eab38b3001e1c0df9f8d8 (commit) discards 21de0cc48524e171b19df5f39eaf16543c34c2ae (commit) discards 33fbedfbf2858051489c4d5d7cbc04f7cfb8d81e (commit) discards 64aeddeb1274793b8f3ec2a1369398620ebd5ef0 (commit) discards b65393034d79702fcb5b97a8ac1bb2abb7065553 (commit) discards de9eee5f4cc05ef6dc161044d68b7400c60e2772 (commit) discards b92afa6fb2d19eb8006bd2893f179953644b5439 (commit) discards 52edbfcac86c6156e95cbdb1947e71216e8b8a40 (commit) discards 7f6d4227d57b9e5deb0aae0e1caee7ff86b7533b (commit) discards e0cee4632ec08a8eb2f73b33b2a702b3add0fc33 (commit) discards da9be2c4764f2557e4a7b44a11ce6cb8412a100e (commit) discards 54963f7c1c30622a4d4ca7afb3bd3c2d44257754 (commit) discards fa8f3ada662e9cbf3f92e9b60989dd25d623b23a (commit) discards a2ee4ce131ae24160c9825aa67f7f38e7eef48ad (commit) discards d9fc72a88c0b400a34619379c002c34cc9ed7117 (commit) discards 956e20ea5b043a207449000020dd0dda62c3bd64 (commit) discards e78ff350cf2228579077211aab5ed994183235a3 (commit) discards d3742568c8597a7e5050e1607ed4e6f91f29bd09 (commit) discards 4dcd4a5da431df5f9fa225b5d264b3c61572ace3 (commit) discards e9ae0adbfc45c716d5bafdd9fb8d5d41f8a52983 (commit) discards a802ddd628292cf772674d2ee02772ec832d0422 (commit) discards 5a2d9200aa246b25dfa66a2c4cafe82f6c6c51fc (commit) discards cba760da8de27c311918f2d33ff7f27193f6e6af (commit) discards f38f5c7b2003bd0865d395e07f015d5d8c1580a7 (commit) discards 8c1cfb945a4fe63caa4f5d9fc33fbe2c3731a3ca (commit) discards 211bd24ab3388d44d018f0e4773f9db80c9eb9e0 (commit) discards 9d16616b45a62a9b398cff89d9801a7e9af264b0 (commit) discards 073b55ff67c0057b49b94c9ee3d89f6c79db7664 (commit) discards 9764f958cca5dd910ad7b49ccb804afe69d0f30a (commit) discards 28b332f1f1aceec9b5c2b598f432454d72711246 (commit) discards 37dff4b95a8846939d0294434bc0e0b16e006d09 (commit) discards af15867d4af1cb9526e136fc67d9fefff6f9e2ea (commit) discards 1ac8030d4853e05fb7905f21ee4a3f5ea611369f (commit) discards 6821858d0eef4898b42cea91be7a736b5658a990 (commit) discards d38b13d289dd67249d3d307562ff2a7a27d5785a (commit) discards 4934381161c51afb5a3c0cb88f100e147c52759a (commit) discards a19123906c75f70d8f8289c57bd6e8bf4a24ae8b (commit) discards 2af02e78b771682ddfe50f4a0cd7a16fc021ff56 (commit) discards 4ca4583536da2da644e77805a638b52c4bee38d6 (commit) discards c25aaec199ba4cf231341864f38287d843555c21 (commit) discards 7c8abe92cada5c27ec31a8289a53cfcefb85eb08 (commit) discards 51f53df171a577f879bcceaf823522220932f46c (commit) discards fcfd09c471c3091dea2955933f22876fec749a9a (commit) discards df116254f60064601fd6075a3385e6fce6a104cd (commit) discards bf84865411f11faec1e16d3e202ce69c9ecaf56b (commit) discards 53c9f27fb81714007495ea29ed6f7172181278da (commit) discards e0c88bb22dc43180f6e101eccf99d01f6da9ae28 (commit) discards 7cb0a515267709852e4553f742c10edf10e46474 (commit) discards d302561cf4715cf26095fa734bbdd81d66aa2251 (commit) discards 4b20cb2c133792a8f6435a7bda7e585c3dcd20dc (commit) discards 412a4c64d8fcc06f69c2bc4ed53813c07111aecd (commit) discards 6467c32f052d977cfc7bc93c02c20103954225f7 (commit) discards 50f0a478f0af759cf8107f3dd7aa8d811579c4c3 (commit) discards 2650902e29becd6442d99ec47b9e8f76ecb3d59f (commit) discards 6a935bd4adac8521da3988ff7b1202ed31ee2411 (commit) discards 971b392e59105b7c76a98628c3054c54b1a252e2 (commit) discards fff9c79d71279e95d6ccf8535f3c6ecf125847b8 (commit) discards 905d58d9927224f4907d42179842ef90d95c625f (commit) discards 14dac313ccf9212200f48878e3e44f2579523ee3 (commit) discards 6f5c375741ac1e2174f7213f94aa1587e04fe5c7 (commit) discards 60a120f1fb48fada4cf3a50413b729b4db9694d3 (commit) discards c2dd8d68cb817791ce86488da1539cbdf5167ebb (commit) discards a3de35d1b09f4798603aa33ae92f648607952225 (commit) discards 840933e925b3ed0f83ab688ee93758577b704504 (commit) discards 0cd3edc01a87750ab414acb63bd817f6aa148768 (commit) discards 664858e81eff9eb60278c3810638ce72a258e088 (commit) discards 21d0df2c519548c8fe752002e37bc2958f99f4b9 (commit) discards e568e03e024719c1e119fb5e3ee35f491ca1b757 (commit) discards c52c3679f3653ad0e34b35f08b9ccf780f3e5473 (commit) discards 927c6bf2a8f640f4a60bf3acc97af8d838a29969 (commit) discards 7508f58de59e532dd011edc3c0281ff60aaad7b8 (commit) discards 040148125575371543ea890762da9f4467b9529e (commit) discards 973ae1be388c84b11b3ad57e4971f9be92f03bd8 (commit) discards 5a1cd30ba35674baad81b42970528fb6e2c83f14 (commit) discards 1730f191089a5f5399635abd2fb6397809468e64 (commit) discards 6800c29b1417421710719a176860e3ae6be99bb9 (commit) discards 3dd0616af3c5928e5c880186d5cfd241506a4369 (commit) discards a37e6e27efa5729c6136105f6bd702986050d58c (commit) discards aedbd25e061fc348bd2b88862956d972a955059b (commit) discards d3c7c8008643475c656562837bf3c072e57ef799 (commit) discards e80f026bd36fbfe70b0d88caa81bed429ca81b11 (commit) discards 6ec6ac205967a40297e8d3b9c0ca9d27863ef8c5 (commit) discards ef155cf6403be058f878d046045e111a1bff41d8 (commit) discards 5c6d51bdf072a8fb6e683636321e57430c0268ac (commit) discards ee14e5aaa12451d93a0cc3787d2f73b2841ec950 (commit) discards e2210140b158c7f8edffe4875722165928566fc0 (commit) discards afd1fd49695b0dad9cca6f00749384568c214a9e (commit) discards 6a7f9c025da31eff3cd63dd85c16dc5aad0534fe (commit) discards 74a03183ffc0982cd948bf76ce84f7891b585d1e (commit) discards c16ab966d519e8d8cb7bb073cc9b3e8d507b5cca (commit) discards 374e984b7e143008d38b7d148b1700cadbccbb59 (commit) discards 097ac761334e18758e7f81ec46486ea200317eec (commit) discards cdd559eab5df6972ce89dbc6e24b6ab1b6081254 (commit) discards 7f3e96623e6d1bc22e447926926409c2836e7d6a (commit) discards 5fddbf1382f9eca0354404ad062343da61cfc84a (commit) discards 016ec962653d5f2060ebf05d09ecddc13deb0cab (commit) discards 3f697a732c4d737fa319020e435f43d973a29901 (commit) discards 2e8f576a9d8b320f420aca2aaf0ac51bf1f8a5c3 (commit) discards 6ae52ce4a16a65338c3e6ef44d4f4891667e07d7 (commit) discards 69d0bac3bb25152fa0b3c4b23139b2bddb96eed2 (commit) discards cae7d6db19197200455de775d457d0cbd4bb655d (commit) discards 0655d616d6e11b6e490b4cea2f1367caec36c4e2 (commit) discards 0c59007843491c178b89ec6b4d318d9a478e6b76 (commit) discards 55f86ceb1f2e5e925a678e9decf181141bb301dc (commit) discards ff1602f864a282a7eece0dce6612e33a6a37b265 (commit) discards 19e5a8a29816e5f9a61b53a444a127b87c55c12e (commit) discards 25b5e76e15b3b5fe6e0aacd5345ecd1f3d360e5b (commit) discards b526e70725cc58b1bc51c0d5c4f3f9c00a908387 (commit) discards f1926db39ba43c3ba8d3397425fd93de71d6bbf1 (commit) discards 2ad86c4232bec1eb5205f67a350084cc77018f27 (commit) discards 202c24a3e137558723f8d781ccbdd3665daa8b2e (commit) discards b4636f780f83e0da8431a5cfd6725878baf65aab (commit) discards deefc1319b83543ff4ffe65feded4ddc290b6a54 (commit) discards 6ad05df8bafd62b7ecb70d68cb395b72caf5fd8b (commit) discards 0287d41c435914431fee29ce064a480c5eb59174 (commit) discards 44c85ae38a4401379c411a1e3fefce8aefce0eed (commit) discards 014c446aeeecb24be2a0494f1031cd992fd3d045 (commit) discards d954016868c66aa78b66bd94c2d744b8cc42738a (commit) discards 14f8a662df08f79471f199ff40444593933e509d (commit) discards 31e1ebf7015852bae9dbc5204e37534ae29c8548 (commit) discards 63a8770f08d0bcb239ceaaa18f5a6ee99af38be2 (commit) discards da90f247541d7a3e3cd8ae32fe74450e8ffb46b8 (commit) discards f79c8a9fa000f7e3b4cdb984cd91a709cb42bce6 (commit) discards 3ae275f4f8a4dcf6721c0112b7d4cfcb9366a35e (commit) discards ae4b031f2bcd15bb06edb97a217d8461926cc950 (commit) discards 29234c055a20494f76f9653fa11df5bc7d901ebd (commit) discards 4b74150218a9c0ab28070d10c87f4391b724bba6 (commit) discards 89a350e455008070ec9c4c6ed55e1e4fb681921b (commit) discards b641f2b873d55f8ba7b99db906fe6a780a910369 (commit) discards b393e63bc9b98b429dc1bbaf21a4e2d481dfec4b (commit) discards 331eb74b795cae914ec88e58f2c0bec69c17a853 (commit) discards f14f4875429bcc4445ec06328f42d3243bd36892 (commit) discards 8dc707a2ffd830f95271275808b645a372e7cebd (commit) discards 1f2f6e07bb430fb36bba3acef474b2ce8e1ceaa2 (commit) discards 23435daa22f650a1a6509025fb2d38e8714f8ceb (commit) discards 9a0bf4d558cfd16917d2cb5c41a754740f159c98 (commit) discards d9775228dabb1424d2f8d1a250c5a0e6ffad47b1 (commit) discards 18e54de628127ac7dd948f473db3977c350c4bca (commit) discards 2d08b225f78c13781887dc26ff3a3ce621394262 (commit) discards c6c976f2c2a3e6503fff3bc77c9f7b8c61cd7e0b (commit) discards 73b458473d4bf8001037b9605543b03099d0c481 (commit) discards a2773b1709e7c853512981039144ed53e3ef802f (commit) discards 0e1c33dcb83294825f0f1785895684721f99875b (commit) discards 12663fc8718aa156afdf43697193747b35348988 (commit) discards c354e6695678ce81925ff73327bdfb4f7b5f9b7b (commit) discards 73677b9fab31d1f68cf0d5dfe2bb68f4b9887d81 (commit) discards cfbc407faab422db01e4a7d2c4e5a7c3acdc9951 (commit) discards 8be34d3d4c4669793f8a400dfa111230d92af701 (commit) discards 07d64808b353bb14faa959596f0489a17f5f85f6 (commit) discards 567a4fe9b1984d5c770afab8bd677bcee3841659 (commit) discards d497b25dcc2d84a7222b32182586ecc4995221ec (commit) discards 6681122a8fd8d93bb49c79d8ba448fc870fd6747 (commit) discards 2a9429bbd2b67c9c639492bafc645ddd1eeee7c7 (commit) discards 699ce812f43553bb6b6732141d62e77716ad8726 (commit) discards 4ce8a4d0a18702cf228beaa6a9ecc7b38e355751 (commit) discards e0bfd3f4f565ea936f665a461380079573521916 (commit) discards d0868c9866d1bec94285c51bf2c6258e1c835223 (commit) discards 040e28be7c196697a103e19725d1c9ef392d2471 (commit) discards fd466d3fd3070b36aadbd7457ddb644b33d40a61 (commit) discards f090b7818791116d3bd273403a91531e9a14d3fc (commit) discards 4d7002fe4045e32dc3e5eefaff9ab2f20c878297 (commit) discards 2969f55026a2bb77f063c6c119a9c9e3afc35854 (commit) discards 8263a78cab321419a6d8839e78317673cd2779a2 (commit) discards 3c5549e5d6d8b3651f7696e5f9daade18ffab621 (commit) discards b0c31f93c84207b3c3a8ba31241ff2ee22886acf (commit) discards 54fd0836989e2a4bb8711265499e09e6ffd5c3d8 (commit) discards bf5b0b18cb543bd25e43fe27373851fa70befe26 (commit) discards 3738245c7b170b3d16ac54b53bbfa08d8d321fff (commit) discards df364bf8e78f533dc2267ae281cf4a67c040813e (commit) discards f96cd09de6efbf13d9662eb99fe5911c36fd0ebb (commit) discards 4c3b6121f4cd46550db6f2e00359b779ba54735e (commit) discards fb55dc9d5b7a7e70770a783f41ec21c734f1fce7 (commit) discards 1890504c1220777f247462f00d9889a6d242e4bd (commit) discards 6d47003d339c0be17efe467fe06bc97294479e73 (commit) discards 4227f29a67b30f2512af767c785559ce14cabe70 (commit) discards 26265218e2ca78135f128e80e5ff71adaf5677a8 (commit) discards 6bfcb004e409915032522b831124b758b1ba5403 (commit) discards 01100b9e899c0a8392f3f1c2d29bcde93a29132f (commit) discards 37debbdfda006617a0e83f171d617bb3bfdf44f2 (commit) discards 803e1735e6bbd394e19e051ca81ee416c6921034 (commit) discards 78c5db6a0ad90eec54958e06e7b9dcac9b6cc8ab (commit) discards 451fea216b47ccd5be8e699e1b08536f573e62b4 (commit) discards fb4a45ee9daddfc982e3e85f6f914be93dc51138 (commit) discards e2747bb4fca04ea829223496b39036c2b4627e7b (commit) discards 04f8752d1d46ecc1d55f50fb5dae195390e345b3 (commit) discards a1d713f219bab2475c540af474d80c4949234da0 (commit) discards b8e990fade3ad1e8b4b533ada1e86411a7abf39e (commit) discards b195005741d7ec9f766fd2bd0c3d0287fed7ef78 (commit) discards f7301e6e5f64cb42573ea7128eef3e7ba91a7779 (commit) discards ebb7ff5b9ba490a8645de7092c729f211b8cd464 (commit) discards 7ac84052c4f6a22349fde7b43b8b073a22bf30f1 (commit) discards b55c0379eeab76a40a0a8291d1e5ab53b0014689 (commit) discards 799e55a6a525e255c7b3c49e1afa9a62f463ca96 (commit) discards 934289dd5dce80d4f8e53b5dfdb3c300e3dbf5b2 (commit) discards f3b3644c4fed7915bb6774929af5766ed1809054 (commit) discards 7a9b109e598b5beea2f5d370a8ed60bf28ec29ba (commit) discards 0fdba25baabb8f32141a6ebc854ad8cd9f4a646c (commit) discards 7c8a07a306894bec95b465411759c6fff76a35be (commit) discards 65aadbed2e3361519eec9a32a3250976c0ae04ed (commit) discards 5b5bdb2638ccd83dfe7127444121907c11769b25 (commit) discards 674aaf80bda5254cd7c16377f93fda577a06bedc (commit) discards 08f31611996f8c7878f6267bd3698056cb016f61 (commit) discards d1cdeeedc18387660759f09958b8e47b9162b83a (commit) discards 9220290194fffec111890c28ff17ff0b79947a5b (commit) discards 78b6017c86c7367bf7ef217e026c71435df491e2 (commit) discards e9d1ae8c8e19d9a53933334311488c319ba7b783 (commit) discards b5b7a7107955aaa704230378393745f1dffeddc1 (commit) discards 682a8d17ce83d04b867e7197cc7e34734d4990f9 (commit) discards c52e556f1324662f168daf8e32366e3144e523d0 (commit) discards 372f25218eaecf27916760990c39ffdf376494e3 (commit) discards eabef10641eb8c995a5e1f732b4d2c2caea1b655 (commit) discards 0db926e9ea39c71cf8caa15bfaebc1a1474613be (commit) discards eb0d73faea66a440ff5594752de1d251e81dbbd4 (commit) discards a899d1f02d75de80161dcd6544ddacd45d231c84 (commit) discards cf394dbe507c5bcd076c02c9654eb44174682ad7 (commit) discards 5443e3966190b3e4aaad445e2a406d6ac9d0d9fa (commit) discards d17683e7dfee0bc7b12afbd62e57c7d512cbc73a (commit) discards 306c30e6007215ff4adfa9c5be28284ba8ac05ad (commit) discards bc5d62e4f7e190b567fd5e9f5364fa78da076ff5 (commit) discards 35ca0a30dcc2048ccac57e1dec7756416abd3468 (commit) discards d415b3cffa0beec9f7d174400f6850ad68972e28 (commit) discards 8f2af4b18e340ea50a716199e27e8af27b929aca (commit) discards 369bfc70d8548baaad751c11d36b88f7c2678f78 (commit) discards b59ed27ea731244fad7276182467b1076704a10a (commit) discards 6bb3ebd485cd92c3c9760432dd4db716ec831723 (commit) discards 8c6f5311aea01e3d8dd597c6f5c847bb55420471 (commit) discards 5d2b217e602966c0dc25ee70181bb47c97f6ed08 (commit) discards eb64b2e2b41fe619e643045056a24bd6d6b81b87 (commit) discards f1297c25f0edd121295893950b501acc3905715f (commit) discards 52a9fd5a28163f02091b81d343ac897df5f6fc37 (commit) discards 30ef584bd16398ed4736175c965872172107d92a (commit) discards 048f528573587cb310456dc8b28833bc44cbe6d1 (commit) discards 0045e4ba1b8b8fe57651f1ce5411f2061d79bdd4 (commit) discards a22263ea280290e0255b9b6e73dd0e9b45f799e4 (commit) discards 378ac83b75d0e4b00eaf7e792cba01b2836aa33d (commit) discards 211b66d781ba2ebb690d4f24fd4d5327fd720ef5 (commit) discards e58beda22fce3afeea59b5e4c01f4fb039794dfc (commit) discards ba41887aaf0d36f696c67b06ff9965b74728ff30 (commit) discards da7df841c1bfd82d9b21592f708ce4a090cf7d75 (commit) discards 7b249311422b8d4c9edd76a12ba0e287b4cd245e (commit) discards 6df91bf6f7f3d9cce662606889585ad41eb85cba (commit) discards e5af11d4d1daa7079c2635700fbcd50f0cb3ac01 (commit) discards 5d67e5457f9eac7cd1be20f11b4a2331d7b56337 (commit) discards 9814bfd0bd343bb141b9de0f6d622f92201715a9 (commit) discards ec493ce9986aa3e56abb8b7bc59693add4f1579d (commit) discards f0e277d8651b17ef28e17499e5972112af1efb52 (commit) discards 94fcf65d4e5efc9d77d944cf4c52ff16ebb3bad5 (commit) discards 98192941e80255650764d30b2da701f9c596890f (commit) discards 31df3da507b0ff4ef8a7e41b85e7967bf1c1019e (commit) discards 08aac8319d907b36b1ae65803adf5079109168e6 (commit) discards 211f798e466bc225dccd2aad89c3c24d02b66bdc (commit) discards 402bb3c1f1762f03d29e735a129ab9f6419e4d66 (commit) discards 0c61ea6263aac5c8d98eb72a1478c2032b65b014 (commit) discards 656cd0267a76d871ff469bd1d0777294d1168047 (commit) discards 21eecae3d33670082ba19e6380adee9bfff0ba18 (commit) discards 84276519414640af8f635ebf36f2e47519caac40 (commit) discards 4bf498e9618c6d70e642a5a58c49f222f8f2b575 (commit) discards 820267ff71a81546c420e1257bbdc4d72dad8a46 (commit) discards 6a262ae56f4b5522836cde5a5f00baacf05aec56 (commit) discards d3046264ae8f48af0e0f8ae8a21722a64d354fd2 (commit) discards 45dc7662d8d9ebf0538be9b17459466eb5d744ae (commit) discards 1129ebfc65e412e760a7cb53d07729a8e320b679 (commit) discards 790ed0f91d04f86963dd20a46edb3f5ff74eb586 (commit) discards 5326c02b669c5f7953bbb287f6b0882ed592e40c (commit) discards 942132b500c26d91e557a6cf127d28209480e42a (commit) discards 7554a08895ec9d2754bf159450126be6f5d5ac15 (commit) discards 6881448971ff63c32dd7d380872369afdec9b7b4 (commit) discards aaa775916df2d1dbe5e09c91d0238f8271978c7c (commit) discards b046f1f16171e79d4877e96dedd2176a682529f2 (commit) discards 19cdfe464bf366f900aea1d6b60b506b96bd850f (commit) discards bfd06cc1b32a386690f6aa071f921947533da03c (commit) discards 15fd34c75455508eb1d7cc95c2ed475b6cc503a1 (commit) discards 1d8f0dd7836889944fd491c639e4010e97bc5e84 (commit) discards 0cfcc2e3e5b7eb312b82ceddeabf1e696feea2d4 (commit) discards a6e932533da73b906508e42840c665b89955fb00 (commit) discards 22492e41fbc949999575cf126d9f3bde083da9b8 (commit) discards 172e77380b8b4b012069eadb43b6156c4201e6a0 (commit) discards 2e29d71c33f54eb84b1fae5bbb3c362b4f994f29 (commit) discards 3ab7ed32396004ac7534e466657bbfb7f95b8a76 (commit) discards ded57be08ac19c9e8c06796d9da6c5386cb16de7 (commit) discards 977cfef6f69e51639b9d7206667adff4b1154095 (commit) discards fa07c5135990639b2cb4f382c085d0cb89592e70 (commit) discards a1a00f9f5553d9fca6b99de6679a961f9538a45d (commit) discards 3557e49685fb5b58f05c25d13ffcca5f4a2eff47 (commit) discards 38041d5268571762738be3e99da5c1fd13e27cde (commit) discards 65f5d303534c4705accc0a3f38cf845ee6b7823f (commit) discards 3e6039ec93e6ba5d8d311b5480dd075bf110908b (commit) discards 50cd2d8567409ac6bf371c245eae6bd0b904ed12 (commit) discards 308f37c6da621016d9cb5da49c50fa6c1ff9005c (commit) discards 09752e9d1a58132bf439eb5e82df125ad8d60c0e (commit) discards 471e3ff8ee3854dc6f2b507cb09f9dc7f088284e (commit) discards 6573bc3cfb0a24e091c9fc544a43d51064bb78b1 (commit) discards 3d840e4da4fcd1b57036d0906b014643d4cbcbf7 (commit) discards 8ea54462c97909a798b406b0eebb6cd1a703004f (commit) discards 99ba42de4a90b1ec468cf55a80eccb3f828776b9 (commit) discards 111b81958eb3d1350c430805b7a54e74bfa7350c (commit) discards a432a54e6f64d2519c5eda520d17e137af8371af (commit) discards 147b8fdfcacd3e56cc0703c560e2073cb60a3277 (commit) discards f4a9406513d4c0f1bdc825325e3691ab83fc6b7b (commit) discards 5f457173b1c2fce6a6a8cb2c41ee34c750b07216 (commit) discards 2170072ec502d612f62746e9ed1c960dec5fd714 (commit) discards 5d4b0c52b5fb2fad86b746e05ff7de91dd26952b (commit) discards 0d5a8f0895395eb5de14ff3678ba208f59e6ee96 (commit) discards b1776fc2a2dd1e7d4166ff713bf328ebf2e98a6a (commit) discards a46d43ca7cd96e722220b45664f5ecd52ae79e5d (commit) discards 3defab1f56082a7fbf51cca39d51ae9a3d232f86 (commit) discards 4bba79ad0ceb753c87c268eb1b66dc3d818223f0 (commit) discards 09219634e58399eef76e06afd2a74caeb93cf905 (commit) discards a43fa8ec70b589cb1794850cdeb147c271f88066 (commit) discards bfb872f8252d25833824e062e396a0f0c7df1b10 (commit) discards b4e97ca94a4b549785be67de0c95d6aa54d59cc6 (commit) discards ca59b4beca14ce465fc68cedeb3ab83c279de8fe (commit) discards 8d67c7badf1233ca22e8b1d5ea20da137dba440e (commit) discards a1e1320a5090c52a65ec1592c283efd062645f83 (commit) discards 0c8e9841b6660516b56e27589a02569c4c71e0d1 (commit) discards 2a3becdbc9ba4bea59a5fd720be504dce2e88705 (commit) discards 78c53899db3fdf4d680ba78f50f37312cc2383eb (commit) discards f0f7cd4861749984392a3247faba705303755f01 (commit) discards 9eee8a966e39ee55e7bee6b321e0382ddaf7806a (commit) discards 95e6a82d1e640b2faafa99e2b359ad68bbfe0f43 (commit) discards d3934925a02995e97af78199d9ff04a57aa737d6 (commit) discards 5ff45960beaf4bc6a59d44fe1d0ab247e6db39dd (commit) discards aa1fb2f40605bb2cc359a04875126cb1c274ee63 (commit) discards 581a2808db8d2df705b57d99bd4f023499a2a564 (commit) discards 6b6df66568567851dca227c6892d5774fd0198cf (commit) discards 37ac89d01093efaaec26ddba6a1452d70ad3efca (commit) discards 07488d68e7e23a6ebd7ecf6f56afd946577b424e (commit) discards f2305cd6ec1da6060e866c3d7fd82e09fdb6beb6 (commit) discards 9508a3ad5d7c85e1e0e2f984144badc5c9d3410e (commit) discards bfa853191d45137d73337063366dda963defcd2b (commit) discards fa29a5ef43f35f411bac78786a98e214e82bd188 (commit) discards 402d16512adb6d4cd7926bc8c3426a5a5b3d5c3d (commit) discards d77a0bcc65f1056543c780923ea3e7cb8984911a (commit) discards 09595bf87be18dedadf9ffcabfd230f835c36466 (commit) discards de51425e8e78a56dcb0a8737c301171b494a6118 (commit) discards 3566a76f8fd67e1f1e2f6807aa5c9ed5262b8d37 (commit) discards a84c119dcda402fdee1046330d9bf3785cdb8e62 (commit) discards d2982298ba8821b53bc8c278d55a27aefc64043d (commit) discards 1e82c51485f745d4659f3f731134e62a43249381 (commit) discards 66f6eb6bc62b5d89c7440d896243a89edc167a2b (commit) discards 58d36c8041dc2e2e2932b570b5e4d658f1a25ebc (commit) discards 88d2cd0c798ca2c1eb2070520879731518db906c (commit) discards a75211647fa4acf4c1c847958fc9ff7d05351d84 (commit) discards a24901c82eeef253079aefa4d2a6f86bc8ba80b6 (commit) discards fda1290d0a06cff77af86b6e6d81677ca7ce82e0 (commit) discards 9d0ef0ea14f76ca4b58db0bdcecdc2250d9a35a7 (commit) discards 7201cc232e32a4aa9b9825c0ded5b4fcefbd4106 (commit) discards bfeaa0d02ebf9ea44b03f378729728e95965308a (commit) discards 2c556b40f22295f2bcf69ec979f5f467bbe17387 (commit) discards 38cd817b719dcc6fd1750e1863ae6ac7fb923faa (commit) discards ba973d446764631b14c369f9ddc773e27ccfb12f (commit) discards ddfd827c449a8ded9043dbf700950202e0d2ae2a (commit) discards 6e8ac679a9a647101654da5b490f2b30a93f5f60 (commit) discards 637c24bf527c7cf0ffc753a8fbe858e6b9a6fb35 (commit) discards a966ea50fcd6425f74e3e6982b9548490a4acb8d (commit) discards 7f9e152943a1494fa784a86d7708dc6403a9a3d6 (commit) discards 258901cd19d9bee049e65ae347536255b00fbe9d (commit) discards b8d9541aead07ddca4152d232c20924fd906a1f2 (commit) discards 860ad8e96ac20c8fb77ee853b7c18b15db1747f1 (commit) discards 3b96df21e3d3ca0b3be6403263a6d0b33ddf20b4 (commit) discards d59b3bc8381162d6406006f47c39fc6e3dc05947 (commit) discards 1f00b504a7a64bca286071db0ca95e67f61ddce8 (commit) discards 4a0ae3f3f73c366f7b816daa4807f7a009680636 (commit) discards 058d2e992e37946469ca7559c4d1188ec7018eba (commit) discards 37911fe54ee6e9e566edde7539d619905f9a0c66 (commit) discards b4ed74e89e9d1fb7325573b6ac07fb355580c13b (commit) discards a0df705f16b844da0c8285c2885c75ef4872bf5e (commit) discards 1301e17efbcf1a286e96240a0aa4082d134f1ea2 (commit) discards 3bd5d24975e984b7df2c55855aacaaa291ca35d1 (commit) discards a5c6b771aa45f23cca8ef51c165475fc88cd60c2 (commit) discards f4d8b9d6db329e27d4bdcf07859649bb43fe7214 (commit) discards e2dae6b0f987e47f7bcdd5c0d7e4f5e97ad51703 (commit) discards 9325f3f9a892fc6b66ee82225758dac67566f187 (commit) discards 10bda09161db81ff54a24698503d0a0596281d7a (commit) discards 1eb9514b34b5636ee372dae0d06944768432b0f6 (commit) discards 70616dc970a34f4a088862ebcda5ad73da065945 (commit) discards 99e521434de759bb68f6885a7f199c3af5cc620c (commit) discards 2d8121bca63806095114992ecfef43de15596e95 (commit) discards 0097782dc54c90cade92bc7448510b523b982345 (commit) discards bec52e5115f2a5598b8d997f18dc1232e0a74f07 (commit) discards bd7c0fa734c662df43cd287ea37b7b84f5251601 (commit) discards 6ce78700e32851f4562d8064f479b6ab6bca4a0b (commit) discards b2113840b329b1a399a31c8d71c9c9c1cb0e8a90 (commit) discards f813fd224221ca71c15c79fd9542be515de21e88 (commit) discards 4768c3daa26a9fa3bf24b915b30646fd5422b35e (commit) discards 255c3f38b91779c9704efafc22c6da95e7c4a04c (commit) discards b8d01567d81f482e0be6d3d0b5344700c841b22f (commit) discards ca76a7cdf1899a211096f5a3a89ac8133558b6b3 (commit) discards dc5eda62eefbd75d9c34fae23a111e04630c9c9a (commit) discards cdb9f8fa7b9c1d519526c2282a4eb149c408b4fb (commit) discards 1dadfde95ca57497dbcf2bd6679e52d167837c06 (commit) discards 5ae1cea2ba711a22e0b7ebadeb71e5347b8547ef (commit) discards 7080e8b39714568a81f8bd80e5ae79d00ee3eb23 (commit) discards b98f80e22e4625e339121eea3cf766346bd7c96f (commit) discards 39ee174ab11263a519a86a17e423d3bb927d8dfd (commit) discards 093053c0972b492b2ac3dd78b4a86047ac54a2b5 (commit) discards e2bc5a3721de77f33e767b6b93ce5374b54b3f83 (commit) discards 0182855fffbc438a453a9deada0b488be550978f (commit) discards bc8c145792a6657eff665105573464ddda95aa4a (commit) discards 44b706e16176d04f9a0ef66dc22cd1de86d8ab53 (commit) discards e40624fb07af6e0678610f79719cfeed751c47eb (commit) discards 7b67436769861b22c431c10c13d40351c4acd08e (commit) discards 36406b4b5d7f62fc0e781001ca6681ce72141fc6 (commit) discards c974715fbd90bafcc7c639545e748d5a5dca7886 (commit) discards 6fc28b4e5a902faba2cac49158c003d67c3ca1c4 (commit) discards 25be059cb83743a37db09b72ccf33862983bb416 (commit) discards 57b72acd65db3dc86d326967ec0b1a304c57b6fe (commit) discards d1565ff672b87389f023fdd1932f407428709e54 (commit) discards 04b111b971f3e8d6f8c891d8f52943a2dca73496 (commit) discards 841e09299d5dbd91e2915117cbffabe80b29bcb1 (commit) discards 8b4edc40e64ee1b32d4ebed18dd799ee63a6f785 (commit) discards 58f56ee84fbb17c75eabff3410b8f5b3e56721cb (commit) discards 1059d4176862fd8fac8ecc66c1b56eeadf4cd07c (commit) discards 67a24b8fd162e4715e95fa0952d6f08c10338de1 (commit) discards 614f1938b1e50a1e74e9252ec6282ab38faebe37 (commit) discards 45db27654cf20ced2b6f2936b6b93e91534b82ec (commit) discards 51c964511ee52c89370e15fd7968d54368e7cb3e (commit) discards aafa5e76c80c4850a7767d47fb8026d70b4b9a52 (commit) discards 35edbdb02c0566eb56c3b649450caf68607b5216 (commit) discards cc653bea23a94e8c494203954954efd319d31cda (commit) discards 23e8657e5854ff3fef364ec490a14fb06556f04d (commit) discards 0235eda8011ac6f8bdafa2a2e2ae8044c47556dc (commit) discards dd84d713d8bc75aef40564320afecea2ea8165fd (commit) discards 03ed0e9279261bc7967d77b19ab9d71d3a929512 (commit) discards f86efd538055a50001396eed9648f151a0a54088 (commit) discards d98f7178adc3cb8ea3f46302e3efaf2f58088a8f (commit) discards 398ab66bf2da85aa50a5fa9638a4cff14ec6d024 (commit) discards 70bd7d16c57b3929f06b7faa5141efd4e4b6c031 (commit) discards e442a1fcb60c15d270116bc45755217b47b40359 (commit) discards 250c3b994e4057baaa713288697cb29eda59de25 (commit) discards 52834ffc22f87b634c194f75966b52793696e825 (commit) discards 39707fbe51f914b538aabfa6f02852009f24d370 (commit) discards 153be68ff49b80eef0558c3cde89e3cd7e4d9856 (commit) discards 807a2e02ca64ddd34788d9724867e38df5d8e701 (commit) discards 9527fc332a8a74d5dd27d16af122b89cc3a394ef (commit) discards 86d0d04211c1102be5449a18825aec645c7b6942 (commit) discards 82564914ff697b04cbc1f4978f9569ba14b33203 (commit) discards 6e51a624401016e1df34a70e273574ba0ab1bcf5 (commit) discards dba69241e3a7fdc160e6eae727dd5ccec8eaaf26 (commit) discards 5b04ef2a793c50b18e258c2236778fd0ae9f1d2c (commit) discards a90b109787bd7e62dd478149992fea0a3bb00b5c (commit) discards 2a46ccf4a510d719956769de05e6df2f160005b5 (commit) discards 17a67400ee5eee12577e446a029adb65bd16c394 (commit) discards 08a3cf513b5807195c8382540fd820dd35a59d8c (commit) discards 2f1cb23aa2499bcdac6d7c5fd3c5666d21e0aa4c (commit) discards d8e5290d4f670f6dd06666dc0778683f0dc18778 (commit) discards db4aafaf5a636e66fb317c4127f3e07d788adac1 (commit) discards 2377ddfdaddffcb8695299dba28843be882dd149 (commit) discards b3046a315b7f145246b9635d8810fdae492802e5 (commit) discards fba84dd91556a927daa13c853b37597f32e93bb4 (commit) discards 26c891b10f1edf10ca62f1d5d329d42fab03899d (commit) discards cad287b27b573001d39b7ff5364a3136973ff92e (commit) discards 6eff71859a8bb013c788c0645642232fe678b6ce (commit) discards 760f2bfc6dc3f0d21460f1f85a6b2f7b50244639 (commit) discards dc97bfc8af0895adadcce4ccd6f2099d70c44e5a (commit) discards 18fdff2efc3abf56166d6cd716677c115e5c02ac (commit) discards b38ffa4addb71b12e00a5b09052b0e24b59f6544 (commit) discards 6eb9ea1c74ff1bc39a6c5d9a77bb6bf3c7b03bbb (commit) discards 81e1cb2159aad135d603c5aaac4d62ef6f6dd2a1 (commit) discards a1034851bb36621dd91206b4060476db522fa7b3 (commit) discards f19677825d06e7671f82b4f50ee31880d1dc1652 (commit) discards 00e76959930c590e8e6f2ad6ee09f33eb51c4fb3 (commit) discards 723b9b35bf191161abb4179c7a10c65dedecfb46 (commit) discards d85e8a9b2e012a0339d0c0e9cd55bb146b81a9ce (commit) discards 4545da9029b0882f36722197ea80a81f32f8c219 (commit) discards d94e9ed19aa2c5b2e1a78c737aa5c0887c975c2c (commit) discards ceb6a9f243c54ce3772188ea971d5fd6c66ff6fb (commit) discards a3fb155f636bbe567353b34b62c766ee19c43dae (commit) discards 077c70d310c18d7f93ca926e166316d645d30e7e (commit) discards f31f22974fb00b2a63998947117ce7170afebbd6 (commit) discards 073b3aef7631cff92db311c7df53dbf69b7d2100 (commit) discards af3ae22aaa5397fe0b904b7de138740da402ad9e (commit) discards f5065d58f331268f22d3a433a60a60dbbecac0d4 (commit) discards d9ed2bbdfb2addfc64cd36c78453b945aa73815a (commit) discards 420225ada23d2a72e16cc8ded6b2f21189eee3b3 (commit) discards db1ee8ada8a5c3e4dc286772663b2b6d2da190b1 (commit) discards aa6407263676127da94b4f5517410709fb47a2cc (commit) discards db48adff5a6075554e2cd681bb0d4a5414af6e38 (commit) discards a5749ae9dc21d58857ac856bcde421c6bb3e98b6 (commit) discards 2446a2d281221cb10b2ab218151e2139e05efae4 (commit) discards 8bf737196b333e36b64246d1771a143d0d9ed4b8 (commit) discards 0ee52e4e935b7d55446ead2242b8f0231e11dda6 (commit) discards ef2e192b88cab13285409db5e3335296e319747f (commit) discards c372a7468cb25fbbdf731391d9a8a7cff0a6e914 (commit) discards 76e1fe8b655674669cf23452291c59cae1d99f8e (commit) discards 977d4b3fbb9eb109496c33a8093103a5b45cad4a (commit) discards 027c414ab53ad6d204cff4473827652439b785a5 (commit) discards e909a7d71cc39698e2613722cc43122d33b0472a (commit) discards e5f9144f30f14da9fdd5f2a3e12e57c0e5cfa5ad (commit) discards fb950253ad84e4dd25418b3f51d20df240487a0b (commit) discards ee3724f107844c57ca144171debe17be6674127e (commit) discards 7bfcbf73fa4356f5f9506c48b6ed8aeef1cbfaaf (commit) discards cdf609ab48e9af52cfb2c5f3d3f00d0734258436 (commit) discards 7f07081e9144cadfe7e1e15f28f43ac8b4cd6382 (commit) discards 33eadfabaf1a91a0800d9be79104b208023ebda0 (commit) discards 0114d0c0ec0e8b4b1b7eab94ea8b7a5cefbecf99 (commit) discards e330f155745e6c102a598015a6ba36a4882658b9 (commit) discards b9b815a782e55055ea1dbbda25cb9aa2f1fae222 (commit) discards bded33556f7b3680021b3db6f0757a8a71566a95 (commit) discards 797bc54afe2a84b232d3886b1c977cd3b876057e (commit) discards e10b5d73603644a63da6877474dc0dc939b27438 (commit) discards cbeb29833dd044b386c765abdb5aee57e6c2f7ec (commit) discards 904ac9e3410573ffd91a5b96f6892e08d3c110c5 (commit) discards 496e09ee2452ce9eca8f185181e013301dd4b5d4 (commit) discards 647c3cd2a114dd3c28cddc6b8e2b0ebd7b0b7431 (commit) discards 27c2222bf0c76a37656eb8a755fbe02e4c6a58e8 (commit) discards aef8218ab7e063d209ef236c3caa9d6cc5ec9dbb (commit) discards 3c0ece3d42f9251457ff3358aa2626d99fb32532 (commit) discards 9b8450a4a95777151048b769a2fd8cd79fd0bd92 (commit) discards 5f795781b8b2594c17fe6fe4385d0b2b8db97278 (commit) discards e2ebe9d929c61f16cc0847a53b32b4d4475f8244 (commit) discards 7ea9805db8ae5017a26448d65048986ef2d10568 (commit) discards eb936525a239daceef1fb6c607e540046cf09f92 (commit) discards 08580775f0cd1443db623def952be35f9995f18a (commit) discards 4f83efc02275a14eb47243b9d7ebb47b1e7b5797 (commit) discards 2efa764c16f7a0b89e7c688513f98846ffc8bcc7 (commit) discards 4a90a79f157764c13d1efc3f94ec59212d225bba (commit) discards dfa7535878a1f1b584139a7f3c245890cce0b2e2 (commit) discards ff245351f35f241ea98d9a979da1abd27460f800 (commit) discards 702b37e052350b3b998d4c3b99dd50b99eda7a17 (commit) discards c68e7a95a6fd7ea0697175bce40a50d52458fb43 (commit) discards 2f292f702cfe325553352dfc743c8efb6bd797f7 (commit) discards 36f99ed048cf700a8768162348f157ed67459ee1 (commit) discards 0be3e5c248049e896972fe7156df53fa8ac7223c (commit) discards 9a1b054c082affa1d38d87d0a41255554c73c374 (commit) discards 1a465ce162d8b976017d5a27081b67caef3d882c (commit) discards 7d6b24abcb2813082fe38b07dc7c2e66a027a6fc (commit) discards 9de900a14aa9348f012c83f2dabee7c6e9aedaba (commit) discards 89e8dd3c8d9b5876378b4175487689b14073ea36 (commit) discards 7b0fcddff33f5b9bbb43bb3243a9930c31e90284 (commit) discards 5c14795cf0a199ec39bd9b69185346a2fee54a8d (commit) discards 9d9eb4368626cf058782e541898e5908c4698e4b (commit) discards 1a7d314ffa458eb33be199d0f18b3ef145e85cf9 (commit) discards d54b5572bf91c0be866b1049421209d2a0320336 (commit) discards eb88b91ae35aecb639a3614a308d4e042798e4d9 (commit) discards ed2429ea47b45f76680143f6218109b4c77b61c9 (commit) discards ea67c43cc186b6645e4b7101a72382f1695f1852 (commit) discards 8299eea9fc762414338c5e1b9079e9c8059d82b9 (commit) discards d2bb979f043dc2a86e4953e5b6336004e7183163 (commit) discards 15fb77871ef8e4617817bdbd6bb3189f7406b551 (commit) discards e6a2ab33febc5bf7054776fabbbdb44f716335d5 (commit) discards 9cd8c198b79646bf9a1f36570ab3b09bc277dc8e (commit) discards 19ac97e80295663db6f356ba2125196f3de2656d (commit) discards bb155d82d8759e56ac07fb64bb89aebfdf761471 (commit) discards 49edf4705c7e1fda9430a2a686290cd2f48dd72d (commit) discards 5c5893fcc28264c6bca1c933e30058d28d2aac50 (commit) discards b77e3b106e9c3cf3bd429995d613ccf65b3b82ad (commit) discards 81a47eb463c980dcd8cc165650a743caeb8bc911 (commit) discards 652117690392f128d5d1ab9bfadd836fe6c6fbc7 (commit) discards 861c152add2b73e97739afe6f4524f99104d3b5d (commit) discards 11548a092d0c4d85482b8395294df1708612b2e3 (commit) discards 8d3f8512d1b8df0f9f0cf0f27b87d2ff5e769158 (commit) discards fefc91b1244d4040795245a1d16e6acfaebef016 (commit) discards 92a710b7b6aa05f74f1813a2d93ecb97ef3d8381 (commit) discards 87cffe87f286e8ea9d7628560b3a00451eb95760 (commit) discards d70a7f9bb3ac95a232ee1bbf6af7ae66b5781f06 (commit) discards 472707aa7b07aa43b9621fc85d43071eaea5c4a9 (commit) discards 1675d19fc07ddd299f9a7fbe2448e409181c3825 (commit) discards f1b00359d9f1fd5716f8a26cf2dadddf37196d55 (commit) discards 3e542118fa2d164f1e3a014f352ac8e829f1ee25 (commit) discards 6159f10e306b3d568379e42a3d9510d4e0c5e931 (commit) discards 31a6509201cba1bfa16813ad69697f04bc427ec3 (commit) discards ebe648fc05be37b9925c93973b6c4d6ab293e1db (commit) discards 1e6da51ef8c5764f413e7a66f86a64cbb20f3ff3 (commit) discards 4de59e2427c678ecb551ef891affba3205725bdd (commit) discards 40e0ae0effc7e487d172ca3b3516370588af74d8 (commit) discards b5b9f8d52061572c19ece7afe252bc8521f2c4ea (commit) discards 6a9214d5644183b287656571bee295c40c132d72 (commit) discards 54c19ba2a26509d4c849c948688954b5a259bca1 (commit) discards 96aea22d0a9176710bfd308b2bd376e409e0c72f (commit) discards a9265d88b5cef056256d7370698bb3de169e9001 (commit) discards d9b0a0b3f5b8f6b23372380822bad4392f2d3f5a (commit) discards 5826e3378bd5c5bb18186ba350065262d416a7b3 (commit) discards 47b8396446aafb0c8d5347ebfb36514e14b21711 (commit) discards 55537e71f3ba1b5f6b212ad0540243d6a9fe923c (commit) discards 7bb6a33b7cd26e80a1ad9d8a7fd10f406fb15195 (commit) discards 404e3ebc4f512d912a07d12de897931463c9df3c (commit) discards 96d23ca9a55e112c167e39535d5e132e046954a0 (commit) discards 7a941d91d3a7b864008d0e15b8a2ace1c6b88b85 (commit) discards db87aa33be07ed5234f948316a1483f716e3ecb7 (commit) discards 7d34c8eb67d557a6eefe1ca7980ff00906bd0f9f (commit) discards 327c10aef394d0d4ed08c681f742196360709cb7 (commit) discards 257e6ad4e1ce5d6735ae7cb7bdce1defc7abf2d7 (commit) discards 32d0a8a1ac3254ea029bee283358d782f0609414 (commit) discards d2c565f6f707e94cf0e77261033e72ffbd3b2109 (commit) discards 966a7e290c81308ef6185d18de6bcc11e43643d3 (commit) discards 807ac5d9a3ab9ea13f8b918347cff1c18aebe66c (commit) discards 8037cc12f59a607a6bbc7a65ede915bc31bf61b5 (commit) discards 5b83bdc894c0501feed78ea1b86ff299ed8274a6 (commit) discards c4b0f64b1317656a916162e90621da6d255ab8f1 (commit) discards 9b7016eea420f6eec2e016d2f694c58eea3e4bbd (commit) discards e9636dafb2e11b0df9da1841981514578e2659ca (commit) discards 3cc9809f374ea224a24d145b85a3af8cffb4c2fd (commit) discards c807a70ac156634225b91300a0b1038229edeab4 (commit) discards 0f1eae2d3d7bed2bcfde648e99150676c4cebe5b (commit) discards 4e34731f14736e112ab6a0e40550d4ea9c6a3e80 (commit) discards 814a5d1548cf99dbb8ab4a40c3c7d05efac9bd1f (commit) discards 4f9f9b5f079987385cf25fd2d51cb5d64d8f558c (commit) discards 6b37f52ef8f55b687246c10e7eb72a894b429422 (commit) discards 35c6358a002e1efed815b31a1985851590e1608b (commit) discards 6e3e7ddeafe2924a44d8965c6651b385537be876 (commit) discards 3f7b09c95ee2efff892b5699fdc03a8ffc1423ac (commit) discards 38ec4b15d232f45124fe290accc773284b99a679 (commit) discards 25cd3e21e86cefa0da6eac0ab54a3adc2d01fb72 (commit) discards edca8b6c81cee13aeb8bb2b14d4d3c4e79f11342 (commit) discards b40c0bb7fa48d84edf00c1468b1ae17031d9e716 (commit) discards a5b31cdac6050fa034285a7aab63c1534c9b003e (commit) discards ddb04ebae16819485e7c4150250bb17c47fd0358 (commit) discards 36bf6fd1d42550c4c42e23d4816b1b1031efcf03 (commit) discards c8a128147963eea8bf40125873c722370ab54b0c (commit) discards 2a71480fa93b4c8bdb6485c1a78a9cd01f050791 (commit) discards 7719d01d2925429be2ee4f742cbce81c5c5e1044 (commit) discards f2f7d5af951cdca95bd245838d5f24fea85a92cf (commit) discards 6086ab4f5cdfc87fa2bdac95ecf83c6d3677e5f2 (commit) discards 0c32230ce5fd27d4a2515c7194df00b3c36b532d (commit) discards 0721d07ec934eb7a6049c2fd9d3b7f5e25707772 (commit) discards 998cbca769bb7cedf28bd1d77c51b0de63f1913c (commit) discards 2c62af2d4bc7c5f1d66869b49da138f76586c155 (commit) discards 6dacf55a79b849ccefb468166d012686b1ed3a18 (commit) discards 0ee7b4132a7ef9c2eca46a7268a718132fa31cb2 (commit) discards 166cd2c80d14149698a3b9f39d2973defaa8af8f (commit) discards 7e58067e3820cb79780adb0847bc90fb081e8206 (commit) discards 838fd5c3ecc961323affd2a890ff3421edc82f08 (commit) discards 996e95b07cd311e88c77d245d5f532d1b6c7fbd4 (commit) discards d1de38461085cf6405f76130753d9f12bbeb9519 (commit) discards 16df58045f9cc1b553fe1607177f91e23fb45b43 (commit) discards 471d00b9b946082724d2d7b1b8ed29d54275adb2 (commit) discards 13750d275c73e83b2e6a0535127305a51fc478ea (commit) discards 044d08aa2544ddc072071de5004ffabdef6f771d (commit) discards 8ce68d9ca0d35c45af6a349facd589b3e68f70ed (commit) discards ff3b05d41b6bbbba0b32697a8bd6096dacc8aed4 (commit) discards 906934fae85a07ae489a636d2681082a2face69f (commit) discards 33e25b1dedcda14fbcccd14281edb412a0c14cac (commit) discards c4cd1d2f5b8ab579c620ff7eb24ceab2b7830644 (commit) discards dfff0d5c4af796e2e5869bc2bb65d7d23cfbdd78 (commit) discards 032312e95d5f799d77789faa57c657b6be409f6a (commit) discards 72b9bf5cf8e2df6fb5290afb7c2825ec54c59640 (commit) discards 56481623c6e615b2c90482dd8b6f880cd571561c (commit) discards 956d93a5f04bebe404b228771c87059fa1efe261 (commit) discards 5aebc4aa1bab731194948721301a3ed69daeaa1f (commit) discards 77a96b0cb74c0d040be232370356fea0a1257578 (commit) discards b5ae698e7aea15321ee94436cdbec9747e422209 (commit) discards cec11d1d4731389dda229442da834dddf5bdb56c (commit) discards 0e78a19123015e727c82b06f84859194a7ee7571 (commit) discards 6db1846a898e7651720ac03f5d4c869f95729f0c (commit) discards f4570ad0d275896fa14d09bfa871b938b4a3b894 (commit) discards 54eed9ada656ea5f43d55d4e7b03945889365689 (commit) discards a279f9378ad9b8692230ddb9d74d8825d19c2a27 (commit) discards 5b24b80fd4b77b5078d2a6f49c988ba6c937c901 (commit) discards 17c1cb103036976fed9b4b476654821629c177a0 (commit) discards efb416046626b3c9332dde3a2e20ace755d58b9a (commit) discards 47392375887e09e6e69ce178f870f9ca9e639298 (commit) discards d44f19273550c193ef643db5fc9ac6aff13ce85b (commit) discards 39ec090ac4c4389a761fda0ff913e3267c2839e3 (commit) discards 77b88ee5b8fa9560310b6b4c6975639809caf451 (commit) discards fa635edaa121cfa688615ca7c07432f5c3e686d7 (commit) discards 612bb575cbaf3ed9f6acad58a25e54bad09edd18 (commit) discards 6b74669d508572429314e9522c53374faa0666b8 (commit) discards 88ee8733112b16d9ab122f25fd4c67eecee7b07e (commit) discards bc583514658b81631b6d345c25cfb5d1531a44b1 (commit) discards 619df3f7c867fceea05c7a7957090627d528b8e8 (commit) discards cd060d3aa1a0d2f5bf86301251d2e64650b9f50d (commit) discards c7d27ed8ffa6d486b0e91654c1a6b14de73ab673 (commit) discards 66b673c375019df62a1bbbd1a4e8c068fbae9449 (commit) discards 3b3b59681cfeea332fb0f48f796f222586e2ee99 (commit) discards 7cb0f785fcffb32141a4e643fd354d2f86596534 (commit) discards 0fb4869a78bad0c529bbf8d59ef91d47ac19384f (commit) discards 4008f1f1d1ee1ae9f1f16d555aee3ea40b4f7cc8 (commit) discards 64f718b310bbf299959b5b91949ade424e68ee1b (commit) discards 23378e88aca447aacce995fb6433cb25ba958c9a (commit) discards ecc74c41abd21ef2c0c8d34124a29f9201f06927 (commit) discards e0af67b4fc05970cea3007f0ae4b97d5e3f512d4 (commit) discards ee0ce4c1dc907edd93716ff21b631c544680dca2 (commit) discards bbfdde3378281d2764025aef0ee965b1806397ae (commit) discards 2b40bc240e51585f5184d057146d2e4da2fbed84 (commit) discards 97599787929fd197241dc3e4adcbf852bdf9f76d (commit) discards 3a0b88c121e39bf66e55c5e0e5f126fd0290ab4f (commit) discards 15da528a4f90e497d8ecd3592e0c19e6aed4307f (commit) discards 95f5bf3a71a6fdb1e516e1a6e5a0cadf968337f3 (commit) discards 1d3c41f925db306c60c390be89e32ddcfc81d62b (commit) discards d3c45a83f489137874715c4a7d0c4f6f50a9cc13 (commit) discards 32737a1de163185236e867e10a276e60334a0836 (commit) discards e52e454f2cf9c8c6c9ab86afd4ce0c58df9e16ff (commit) discards 4b4bebc7e19687ff9d1d28374555e647e5b1a634 (commit) discards b45687a47df2c5bd075f0316eb753c1a786c08b3 (commit) discards 7d270027fec3938cdbf68e8e0f8df9741cf07c0c (commit) discards 2d2bec4b3d42deff6f8a9b529967fb80fc1465a8 (commit) discards 940627da617082b135d09ee3712970fc42f00aa2 (commit) discards e7f14657496e3ff5ef5824a95d7ddb1eb533120f (commit) discards bb290d80b397e2eba99982548b790c127bbcf4f5 (commit) discards 468f1d46ea0b184c13589dbddd2c48709696fa51 (commit) discards f2e4518a2794b278c8a3308a0f708f3977564589 (commit) discards 79d1906aefd527c10e488523aaf5a7ebc38463f4 (commit) discards 916c507c53546f4bacb236749934d2f53d85e48d (commit) discards ab0693126ee1cf32aaef440b778f8a0a62e127dc (commit) discards 6dc7f3cd015c7ffae07e391f102dafa211c475b9 (commit) discards db98cfbdaa2eae996d46a0d21f195dbb2e030c9d (commit) discards fd04f8cf253bfea097ba9e3021fa6a55c2fbc718 (commit) discards d79b8e85700981667f30e1b35ee9ba1b3c323ce5 (commit) discards 3837a64f0f4956aefb08c4ce4cd838607492503b (commit) discards 3accc2823c60bc93c779d5911bfd7d9c3fc9d091 (commit) discards 1aaa28a5cc18cd0a8f80e7ce84ab233bc38a023f (commit) discards 0a4028759c12de9846d3ffe9cce74523353bf0bc (commit) discards 0a18af8b167218e096b1411ee39dc025707c959a (commit) discards a69d7a4ee0eff002f0ab4a4b19164a33b7157333 (commit) discards 246b82be53e8e68e92c06ddfe261cde92b1d04fa (commit) discards afb0f66f0f47813de8c9a77659326a8923a6e1c2 (commit) discards a3dab54134c6bd015edcc55d88a74204836649ca (commit) discards 0ab2c473c7c04905a0a791e0c2897ed74c51eb4b (commit) discards 6738d19b2c8a64709fac9544f9df28be6531ac88 (commit) discards 1563b936fd11bb6512d7365a070a6185ffc9fbaf (commit) discards 85f893c0535538991218b8caaafe3ff871017b29 (commit) discards bf111520211ec74ab847b7fa11637b702af2e8ca (commit) discards 5521217d66f57464ac4ecf715527682f5148f356 (commit) discards c98c12731a987cf83d7aabc3b8127c51ceb8d741 (commit) discards 331a9929897ad4ba864320e12bee96db86ffd8fe (commit) discards 24e5bff0eb7e82d34775a029296858b8142ff02f (commit) discards a5f7a59bbb86a7cfb7792765270722f07a9a679f (commit) discards 7d6e8599e87ee212861488f62f726afe0fd927db (commit) discards 06f7f9f2fac3ff31f8ea909c0a5cd647e8912059 (commit) discards cc04b2272954e90e97af212ab76ba8322bf225d4 (commit) discards 1529102dab129c3d2e1010f1e37544fd4a698f5d (commit) discards 2b3a600e8570df998247ed89da75522cb97e8563 (commit) discards 08714bc5fcc28cc8e66faa6bd6f06c9a1c1b7cc2 (commit) discards 818f49597debd3636bbb96e6aecc4c4f648c0320 (commit) discards ccf17096071718ea9d7ed75d37fd1e7c8fdad196 (commit) discards fddee52d5bdf90d806834411062b3af37a6332bc (commit) discards 2d4e1942743e5d150076e57b2cc5efef7f9ab115 (commit) discards dc8b205f50d910eabbd0ef5b75873045aa862ea8 (commit) discards 74e42fbdb1619cc2d68f08910aaae96a78142058 (commit) discards 94b9567e93acf6740f78acb49b6efec097ad56dd (commit) discards 1732d1498b32e173dcf9642964fd7128f04397d0 (commit) discards c9c61385c9710e273c2287a0d5ced8080e5bc908 (commit) discards 82876f13bc5d093e450895ee72d4ac4f38988f71 (commit) discards 4ce2ab4db04cb2278c451b03a039caa00e4381f6 (commit) discards 4f8633666382e9b518a5af001146c9f8abfb9844 (commit) discards 9af394a2ce6f0815323e9213784494b225bc2a6f (commit) discards be38bde9b8cbabd2b2fd629fc336c04ada52c38d (commit) discards 4df5915b50c57b3f028cb3fb7555c42384bd34e8 (commit) discards 50c3bb901aad305cb7bfa1971d0ee1aeac226389 (commit) discards b3b41d113196e5cd8bf8263f08c0ace03faa3ed6 (commit) discards e6402444f1f837efb452c50c106a738a66b59d48 (commit) discards 645186c0b7e46cf99882616ef2a00f07a472825c (commit) discards bbc1ed0b6f8669912dbf7151d3c46fa806e04a67 (commit) discards 3aa68a0197e510372c26152d4bbf9a1066b082d3 (commit) discards 797b4d3a176c01c91b040ac4fc1e787796e62deb (commit) discards f01ee88d0040b4905844af32d10a689d8ccfc672 (commit) discards dcb8b0fb35e74749d07b8aec837b41564691f0c7 (commit) discards a8102f933066923c47ed35e0125a5c2e0940a4e8 (commit) discards 719a9e8f89a9b6f9bfd78638b62907062a84d535 (commit) discards 1a8f42e50f1435c05479ad3039e27d6c842a69fd (commit) discards 32040cd3aefa07524d64f65340bdc2b7e1cca513 (commit) discards 35e25ada0edbcd6a36204ea13a4da8309dab3cfc (commit) discards 5b23ea48ac45f2b08ec1941c291608737ec16555 (commit) discards 174057f9e157e570a83cf7cd55a7e121d0f4c63c (commit) discards dfa9c54353b329a73f09314bd119224818a947fa (commit) discards 4cfeac87fe0170b09b7c6a21a2f2dd0ff420d111 (commit) discards 14f1a9d044504d831fe34e711f4e54da4d3f2d08 (commit) discards 2b7eb72ebdd57a7c61075cad0fa6c7f3947f6e54 (commit) discards 4bb235357a363646685f6595b6ea501becb74813 (commit) discards b500bd327a4565bb85c0ef3585ad7c36aac5d8c5 (commit) discards 3e330d8805c29f00ff550b37f50add3d009c93d7 (commit) discards 75fbf9008092484c869d6e075d9c8a056ad8c331 (commit) discards 98cc166c5565c2a57ff5e41c68d15dbb39e16aea (commit) discards f85bd200f947b6d4c89e9475a6a424b5b2270a16 (commit) discards 1a54dc7196caedf938ef32655d13b05feb87e984 (commit) discards a93f28e4c0794fdfc1226d774a8ddce57aeef452 (commit) discards 9f2c6ee4d0a389aa89f94754f50a59674ab06e67 (commit) discards dfe2e256cdfdec77894e0fb7832279c996b3d81e (commit) discards b4f95726130a6241e65be94083866176d8c431e1 (commit) discards 81885619e30455a26655c604901160dfc7455c34 (commit) discards 032d3b4030b97fefcf4a808c541344405efbdeda (commit) discards 9745fcfa79993a2524c2bb40c126d338cfa78899 (commit) discards 299c411444e7c833adcf58248b30ebec56ff2f30 (commit) discards 0ef81f9de3026aadafd68ab5b1b000bbfe57338e (commit) discards 65c4caedf049d34effbadfae449c00974ebf11c2 (commit) discards 01c002450510e33e7f66da1af4b7d14de97156ca (commit) discards 437d9ffa10541a43c9af08e0d8da52728506d536 (commit) discards ec25bfbe1a2623245fb3b7bc047b5243d3916dfd (commit) discards d2080ff950d88d91f80affce596171862c0fcd59 (commit) discards 307cb3c1f24857f4ff93747c14fb268d6b20fdb4 (commit) discards c6eb6f124e422969b4d4b7a64dd86122bbc058be (commit) discards e80c272bcd8e6bf2f1549218f7b3cc2a03087482 (commit) discards 2811bf8d21c1441b3846621b31b62a4bc634fcd4 (commit) discards 773fa853f2c6bc5d108b47a536f6cb43658771ac (commit) discards 24b4801a660b64f6736a0fcc6f8f4c0f2b5d72ed (commit) discards 075a06080ff86467dcc70bb2d4f467b8bc87eddf (commit) discards 2e2ba95cb9d7806219c76773e81f91056e83077f (commit) discards eb5c141897404324d13c7cf568f9c92e80cb4609 (commit) discards 042ce68948fde096fc99d0658994646f9651be6f (commit) discards c3dd900c57b891066529c66675e042c7dc611c13 (commit) discards 93b60614f97cb7cb0a181a10c2f56ae624f31448 (commit) discards e48bbaf7bb46d7bfaaae9e645e0ef854d9016d6c (commit) discards 4e8a9caf166117cffa1fe0d8b5715d3449125369 (commit) discards 50eb6cf42322dafb0b9f53ac02f956e69a4be188 (commit) discards bd4f7bd88af4dd062f953b8f102e55aca098edc1 (commit) discards 5618f7123d9ed3667d5cb53a05779d10ae6438ff (commit) discards db659b69cddd639e4c44bdb4e4d53a06e424fc8b (commit) discards 8554cb72c124ac87e63e3da1d23f9795c7b42f2e (commit) discards f05a7d0668b7d1f6e540e9478332eeff04090c23 (commit) discards fe5e4f05abf1b557c226395271a0e4eff61631ab (commit) discards 3b67ffe4ab6e876ec8cda1b4e1298b73ea022e28 (commit) discards 0bbc70a7015b0ce837172f324fbe09f0f82efe57 (commit) discards 461687855df695039f4ba6714dea62fa7a51315e (commit) discards aecd35b5432da7c2b205ecec60140b2ce6e319d5 (commit) discards 47d8092dbe61cf8e4ab98c5ffcb787370789b801 (commit) discards 9bc24ade20c57abca95789940d4b1ddae1528be4 (commit) discards d494d534858f0189f208f6e5d21cfd9c59412a30 (commit) discards ebcca02a091192f881e106e4ec7c879b343a1ae3 (commit) discards 799756410ceb775b28dbd28ea464a6dbd794c44e (commit) discards da76011790b2cda7159d82db3ff5971699869239 (commit) discards b23b251ae262ba2e8e1ce7851648942a16e74c73 (commit) discards 14f71f8c9d06c0f51156dce1f13db2d26f6f6bc5 (commit) discards 92040fa48189e503e587b383cd12ffe16443c257 (commit) discards 6fb87e0913d808518125f3e6c4ad901e9817a570 (commit) discards c44804bd2c49cfc5ae2d588c2f9e81a8515e35c9 (commit) discards 0febfc1a32ee964f6e32d4d123d28b56b80709f4 (commit) discards b59659da1784db4997e7def4ea322a06672f15f7 (commit) discards 8c0bc67bed33fb53816b478fbbfae809720cbdfa (commit) discards 3881d58885ad322596ceb98a66631b0f9a65bc3c (commit) discards 387e43639e56691356a9c5617b24ff7ff7e25e92 (commit) discards 212e620fcb657ec83b8ba3f469dccf6a0b693102 (commit) discards d3b3fa3a26b0295e4a0d767c3e1be1a5807de6a5 (commit) discards be056652c6100f7dc6833396a6b5b2345948750c (commit) discards 2eed8794522852d9f1f4aa55b0829ad567c3779a (commit) discards 6dfa79dbb5e08614f0d64dc0be8be3c5fcd7a7a6 (commit) discards 237866b8bdb6d39992e3f77cd56e82e4181d5947 (commit) discards f923940b7c9c93179b7ea6356c32c8a7beedebe2 (commit) discards 2f779b24d65321dc05974c46a69cc3150f3d09cd (commit) discards 6b400f503118e894685bb88f7b18ade37bca5dfe (commit) discards a9540002c5101e533e1896a4150462f20ceac68f (commit) discards c7f69a3ee6d693e6fb6d563d7914afb12abdca82 (commit) discards b09b42069ca7cfe9510fafbf8e5282a49bb45e93 (commit) discards fddd06191565ba067f82b0baa6f33beabe78ccab (commit) discards e6ec80ae7c193b318b02c30f7a8f0355635ee170 (commit) discards f014b3408a942ed1be8e0bbe7767ec8e6f092f5f (commit) discards a23f4f0666fdbfb7ab75635f62e216b5d5d158d0 (commit) discards 9ce8fbf522e84f3f596e90453b4c652514a00099 (commit) discards 54379cab91d6b2d6940d65fa8dd31530bd30ae52 (commit) discards 25dbc485565649f54d64b57f6a35b651b8a15165 (commit) discards 1ebf57341d671befa62b4065b7565a01f1fe06aa (commit) discards 0e69f517951fefc4f4917d3101259c8a7a7fbc66 (commit) discards 75ace0a67d0b57eecaf1862e8a5dc68efa0a724b (commit) discards d1f0e3064827cbaa929e8d55ae69ec40fda43a45 (commit) discards d94460ce3ff089c7746d24378f899008a2e5385d (commit) discards 4b9292a9458d25a9394190de5ac9d9d056768070 (commit) discards a89dc5374b8798e6dbe699b7a074ec7cd9be36e8 (commit) discards 0fde927b36aa8972da15fefa3e0f01ee22c6bcef (commit) discards d1e7a46ad99e411a20740ffa651f9affee9ae427 (commit) discards 2c0f3a34e5bd163b5194da61c9d1c0d89dc4f68d (commit) discards 590f2a365ed4ee2cc3a7fd93f55b2ab869fc3004 (commit) discards a5dfe2391b8d60fc2f6b5778687a9a338b6ed561 (commit) discards a365ab39a149ee2d71804e8dfd9a8c4636db9fac (commit) discards d409cb7bb7724b742efaa289d9183f5f5a840638 (commit) discards 749587d10ed558c20e8f45d2190999ebdda6c9c9 (commit) discards 2af5a4054363955c94feeb26d6b33bdcc2dc5736 (commit) discards 3823ed3ab7a4ae1b0663ae89608386d03cc6709a (commit) discards c7a826a42d0d31dc494da0c07ba23af24b152554 (commit) discards e0a44b614ced7559f596649ac159f35bc65aa35d (commit) discards ee304e8a3b7e3eae55cbf7ef06589f27441c1bf8 (commit) discards 1ed28ad0edd0e85f7d4a03be5c0d38bf36203437 (commit) discards ed05c2d38e4a9224b0d2978c7f6eea8278598dd3 (commit) discards fd1f119877d70c15ff420b7ae63d6a518386aeaf (commit) discards 7490ae768d8e709a7778ae25a13484e8fd09871c (commit) discards 2b1e5125bb08ba16a8c9a18a48adc67a4df0b8d7 (commit) discards 14ab1e900306331d66ab6ef384cf1cc2f85dab1b (commit) discards 3f9274f610a957bf9186365a212a50a6785acbed (commit) discards 750906500d08cff001762412c2f307022836a879 (commit) discards 2ef26ebebf2a405f342ed8623a185ec1bd4b4b38 (commit) discards 0be1721b533ae213fc255aeb5063f3dee204c8d2 (commit) discards 70184a7716b16cef891d80d57c506571aa6d2744 (commit) discards 4edd6e2a616a192b207268dc6bf2d9d3bf7a3031 (commit) discards ec4d7d2ff0b8442ed1f735376f22ea2ece1a9f8c (commit) discards b0ab3549ef8113079c1f2957977b389a3858ab3a (commit) discards 4551b1ae134a3d1f6c7a30a9b941000a466a11ef (commit) discards 49fe82b52d6dd1c034b130ff17dd6c9f9511ce63 (commit) discards c942de4483d282f22af403b71965ae3abdcf1a9b (commit) discards 1ae7aa2924d658d9f0afe3b839038ea13f284d14 (commit) discards b446295d63fc481a66569fd363b02779009311a3 (commit) discards c481462afca694c44b0405042195bfc4ba032e79 (commit) discards ff9ecb35546cab4421e66493156f14dba345236f (commit) discards 605a85bd1cfb5601c9ec77cf9e45019f9faf23a2 (commit) discards 48e27d6151459a671aa7611d298813eb9c2fedc3 (commit) discards 0fb7df0c9ee9d269daaeae76c6bd840eb114be3d (commit) discards ba0bb60882068d0581254e0c3dd99dfda44fedf8 (commit) discards 5ee591dbad84c38eb03e8d6d7f3c35ad9f010d87 (commit) discards 6f3a8f0febae0753d0114b2d4dc53a788ce4637e (commit) discards e00cdcdd433824b1692856231c7e9791164f0ab3 (commit) discards 7151a2f464b03bf024dca0165678299ca35e8c6c (commit) discards 3a087b7b57b8d3625655930b086588cfc14c3829 (commit) discards 86d03c32678c016cbd70d911d38439125d08e207 (commit) discards f30fb4d5a450e287ea34667f42efa10e3426ac1f (commit) discards 1c6b43d80fe151145e68ed1f718b31705abb1537 (commit) discards 67c528c03d2c598e4922f932c5598d5da91bc408 (commit) discards 6f0cee13fdadd4573e9dd57c1713d9a674abb713 (commit) discards a60ea0a957978495bd8a2dacb17447ef9e0bc694 (commit) discards 8b3af6a7ca2d4938568df8dc70c9d44c62ba9fe1 (commit) discards 49afda6b4e94d7747058bf5174bda6c333c921c6 (commit) discards 91bc8ec9b8941f15c9adca532afa2dea9d1c1fa1 (commit) discards 3743af8aa6db573370b5f4d10b06d35ab507b894 (commit) discards 780b5ea7c5b416e17f469235c08679fa3417262b (commit) discards b9badf851e865ef7076abb49904785b026909a49 (commit) discards b2c6630c566344c4289cf312adfa45f939820f54 (commit) discards 17bef2cd6780731f77be1383f74ddb5d9c44bffc (commit) discards 9dcfa5f09b2b6345c3a83612a69d3e94bc43aac9 (commit) discards 885c6f5f348a45174cf5e3a799dc8c0f13c37e67 (commit) discards ca40503553b08255ae8a67168ee840b9e7487011 (commit) discards e5c68d04f4eb28ab4f967fe1f127be6b28c0ec92 (commit) discards 8bb3d57e7eaa89fb394e33aa29849ee559f29915 (commit) discards 881c15b360a11f4951ba185e54fbaf8ec028b237 (commit) discards 0cd57caf76abd5560cf09b12c4e894e505980948 (commit) discards 7c4ce8062620e6d1375316a5c8966690c475fc2a (commit) discards fd5440694f9dd2d9d1d70d6bcd58a928c8d2e912 (commit) discards beac5cbd01a48e0d53114ee0156f79108a6ab6ac (commit) discards adee2f4b870ad5aa27437feaf7360ae984afcf27 (commit) discards b2fa025ce3d264d9f3313a83ef77a0ded398d07f (commit) discards 3855acab5f925de761e384007592f54b471eeacd (commit) discards 4bc4312ca064a82b3ac157ef0b67235e5cb02afc (commit) discards 331e584c686e3a20708287d807f18a60d64568b0 (commit) discards d7f6a6164e7775eeabec0aa5d66c81a365b3d1f1 (commit) discards 76624fb8470bdc63b3844f84edc3c941bc524f41 (commit) discards 5e5c1c9224b7b10df29732ab16d7fbc052faba40 (commit) discards 6cb01ac244b6476c2677cf2b2114e9044886c747 (commit) discards 275217f7c9a7b0252643b50f0431001802499daa (commit) discards f62d2c869f7ebbb418bde71bff2ecbfc7a3993b2 (commit) discards dd75faf01aecc93c32cbc5941d29033e33af0521 (commit) discards 1b79da2c9939c0674970d36ca282f0e4f62fa8c5 (commit) discards 92810dc819dc45bad1a7aff6bb10b82c9d2451f7 (commit) discards 3826f1c832b071df8bb7163d44ad1981724ad70b (commit) discards 14252b2d864c26a9331421c600744464c9c3c08f (commit) discards d3f418e5be2c94933abfccf13e3aea031472c949 (commit) discards 479b0e2175da23aa995c19cc03d2abbfae1ea551 (commit) discards a27be19f9c4990e97310c1fbf0005aaaf9bbf40e (commit) discards c2382855e6a9706c9f71beb1f57bfafc75587f65 (commit) discards 7f13f7a99d4fefc39aafc6efe0582fa5ece4f8c9 (commit) discards 6b05e33c95b2bb392f6c6602da4677747613e35d (commit) discards 5de760147f83b507f5b5dda7051eb1f6386e052b (commit) discards 95ac050958f063223a4a3f660aa5d8521b089c3f (commit) discards 6e3b88962c6762ab384ef73c9a77444ace4b0738 (commit) discards 2f5c30a55bdabcf606b26abb89395608170f9ae2 (commit) discards 65ca5dfc857fd295495941a65ce3862675f50d59 (commit) discards 9ba2a76c8636156de00496f62a4d9d2be85b1b56 (commit) discards 8d9daade39b9ebb190f32597469910a70a8131d0 (commit) discards 0428c729ec5203a1887bbb078940a4fc0ad20be0 (commit) discards ae6ee87520349c432aad6f1dfa987a1cc630eacd (commit) discards 742fcc25999fa30d348dc6df35cd07ecbdcb6fe9 (commit) discards b57b7870f6e188136ec0bae6ebc555c882feee90 (commit) discards 076d39926f899f88e30b4128c2c835ab35091a31 (commit) discards b06615050293a04b7e7ef8ccf97ec706351d761e (commit) discards 7a7a02193745d52183cdd203deb1a93d49f797e7 (commit) discards 639cbcdaf9e7dc5ae9e4156ec2f21ad1c8634acf (commit) discards 62e5fc1dbf477bb2628dee9d2e9bf143609f441b (commit) discards 37cab7eb17b505a18f534408307797a5e126663e (commit) discards 0e16f8f8067ae721d23e842b83e0e24d4e5d2b49 (commit) discards 47e6e46fcf85e73b65b0f93be4e1d9aeb72b9579 (commit) discards 2f81fb21790dac9f6036d804d68f108bb498b720 (commit) discards cc911145ee8a4a8bb1fcea6fecf77cba37fcf261 (commit) discards 2bfda685be5c8138d5b5d5c2366dc41665ef7064 (commit) discards ac5daf964a49edc00dc23c621cb5fbc6b9deca4e (commit) discards 61d7cc52ebd5bcaf9676a285268e1dc8c1131908 (commit) discards c5800af1919ce735267f1dca4e0d9c5234ca9ce3 (commit) discards dffcc796ef7759fcb6bdfad7c576adc88e60a7ca (commit) discards c12c7f35633c1b75e4ed2c84e021065fce82716d (commit) discards 1991df2f67e587f01de2836f09015fc1983d1a45 (commit) discards e0f428248c51aacfc2b9e53cca5b88aa15042013 (commit) discards cfcf11093df6477b04e19dad4c4fa56f1032faa5 (commit) discards e8ce84727ed59d55c37adbf06cde0e2f114c46e1 (commit) discards 1035d0e0d270301d266f2d20b39bf09fa3448972 (commit) discards 3984b09071ebad215d71203603c5913830ae335a (commit) discards d808f0fdad129f19f1607aa5585a5642fcecf01a (commit) discards f17210aec9bf7db8272ab7ce7eea7addd07587fd (commit) discards 61e69451ace821aaa94a9ba2b2f4e15140222736 (commit) discards f4458e9fd0120198fab3b862f1e12552fd9d9c4b (commit) discards da3c79a376774a27792e349381ea727bc91e1eef (commit) discards d8633d344b2393a38746898963f7fdd5c997098a (commit) discards 4d832fc7f94e7af9ab4ddec8dd0c8086d757bf66 (commit) discards 9f667ee9f52f436a3d43121d43c8efe4e05709e1 (commit) discards befbf7ad51059b6077de1fa34a59bde28284731a (commit) discards cb56b773baeb123f22a8d4409c1a68bce0d3e45c (commit) discards 409a2a800115fb55aadf78e23deb85a57b8ffcbe (commit) discards 0a291271fdbd530a38722bc554e7bbb49cc7245d (commit) discards 4eb2c4dcaf55ea08c633871fc54dba411803832d (commit) discards c12a24cefaebc06d825578270473bf4537568ffb (commit) discards cf39fd0f40c77a3a05fd921e66ee814a572e4086 (commit) discards 87bde938fe3c66fc6298108c7594578005bbb2a6 (commit) discards 9723f4ddb9cc0767b7b963aa31def62c11b05c50 (commit) discards cd04ce0a7f6317169f6d8738f56b46c658314bd0 (commit) discards 4b64d265ee79a39aabe6241f3e0811f38c0c2177 (commit) discards d89821cdd61896d7500f8ca2378294d9cf7aa27e (commit) discards c207eccdf8224900f5d44ead6f8ee2fb89c9bfc1 (commit) discards 0076f00d2d174da03b50ad5b06fa820ee47264c6 (commit) discards 284bc42262d70e849e5ebab15cf930f220a41f7c (commit) discards 92d6775f6bb2443adaab7f85a645ed01e8a5cf15 (commit) discards e8de7c1650c21199e2ac867b7e1751a2178184b8 (commit) discards b3310831a55d40848cb76dfbccf44c5179e916e0 (commit) discards f724cf9c8d03d8e14a109bc99de497328936e992 (commit) discards e9b966cea5838d928a1b67af26e693d77e3f259e (commit) discards 5ac03f5aa179b96f3f849d584caba3e4fb7a0c13 (commit) discards f7a8a5a9753c488bb59418dff0d8f6a0f4e036a4 (commit) discards 082efba39a822c3affb8e3ebf0899d45751357e1 (commit) discards 856628d05cef2d84b3c5c33ff13ff016c2244022 (commit) discards 1e663d26f306bbfda333aa57e7664865596f1878 (commit) discards 7c8ee666ec64e2429a4e68ae397fa0ec38ba6a1a (commit) discards eb4e40a70597ae444a3a753f50099bea24b80ae8 (commit) discards 643a7dab9df5cb3fff55a9caaf2e1837f9acd753 (commit) discards e74e07ffd1826be46539aa5c7cd864e10aca5f80 (commit) discards 650d0c63e50ff502e9f5fcbf08f885ebb32b6101 (commit) discards 2c93d6ca7f77e1f657c8df3019fd8a95f74db7a6 (commit) discards 4fbed291a99c5e1fd1c51abbbfbe430ad716e091 (commit) discards af6f3004dcf83123b3d12cf7446edb51bbec1b14 (commit) discards 2c7bc60834cde0c0e5eff03db092c341dfac78b7 (commit) discards ae975013067b228e3bb712c479ece54813c4a34f (commit) discards ab65a1e18599219c644889c4d4cb1b45c0dc8383 (commit) discards d96271d9e14354ffb93f80a5ba85fb337767a6c5 (commit) discards f90c7ba54f1a9a61e930292207d3387df40b2dad (commit) discards c8a45332313cac5acc6661f8bcf4993d1fb81b49 (commit) discards 78a3604d252b6f42d192807b9bac84f46e6ec76f (commit) discards 0d83b5464de903900cbe02e9bc484c30b37bca2b (commit) discards d9718500fa01d3045ca86e85be68ab9dfee4cbed (commit) discards bf023b1933deae89f90de611dca8cc6b249f2d8c (commit) discards 23d732fa83e7e0ae07aad810e1867238900a51f0 (commit) discards 8f612e2aa4496e3ef88ee80c2ed33e7ba4d6ea64 (commit) discards f6a0ca3e63547e728d2eea19803d24ed9825d467 (commit) discards d27726cf694036fe22622ce93736a9d0f9896fd6 (commit) discards 1a973ccfd069fb9300d2a6078cf8cf3f25c3b5a2 (commit) discards 6334f0e256eb8c89660f41ac9eee68035b78902d (commit) discards a2683d3cccd196764d24f9cd6eab4ab64f239819 (commit) discards ac67d12cef8f91be025c9b5491d79419970c4684 (commit) discards 859b341859ac13aa8e872101240fc8c47c766e23 (commit) discards f9bde4d2941bf65df78d22dbb713f6f79a7133fa (commit) discards 0e81268978550f0573845b7e626e47de85d67279 (commit) discards 4dfbdc908600a3fc98de34b765ba255646b6e648 (commit) discards 88be3514f5d7a1187880bb89481954b6da26ebb6 (commit) discards 0fb47ff836af7fbd74998bfeb3067708b9f7db68 (commit) discards eea5dbab2e1db3b265035346d52a2b2c6df53a5c (commit) discards f5c9da0999ca2edfa337796a1e2da9726198c9bf (commit) discards f38d2ed7d391c788baec7e215ee0c1b1d95982d1 (commit) discards c8c24d8dd52fd3e79f6019f605161024d35082b8 (commit) discards 52fa6aab809c470d2bbc248da1367c1fdba53454 (commit) discards 1d156cd3cc0318b6cd251198ae671d4ff03c1c2a (commit) discards df16bb48b8dd6a4dc68cf8485d8b07e7bdc0e6a7 (commit) discards 6a0843d3b684ff3dd57f9e29aaf9947dcc81c253 (commit) discards f7f6ddb5cbe58a594970b8700bef3ea2cabe8554 (commit) discards fb2b59432d9764694fb51dd9e80b73d8c87442f9 (commit) discards e5abe1865909ed63e14069fa418b01f20a6ca01e (commit) discards ace79e42fd521f9b6f35ae6e985441ef14b6d03b (commit) discards a01b5490594eb98063d8354acdd52a03fb46232f (commit) discards 7f15429cc574f90fdd68ee254c28833a4843e2aa (commit) discards 9d2cb3f668dd79def44829c8bd5791e7c242e026 (commit) discards b39bd548f9f1f96a2285e5aff638085352c21f29 (commit) discards bf7d0168bfdfbe1b91bae83dd0091af54e7c4e8a (commit) discards 003dceb9f5b416a41ba9ca38c51f24f82e867091 (commit) discards 1c165e6148dda9e40fe17b6f39bf4c96e3c2fc96 (commit) discards 7a68e30bdc4baa0542cecd57fd963c18442d3719 (commit) discards 69ba48d32de541c7d6b73bbd1dd3ed25f6ff0015 (commit) discards 785ebd8a0b1ba20a45a5f29816e5742702955a10 (commit) discards ab1addb73d03889525a3c948501866bc2ffaacae (commit) discards 6537189a8dfd967ad3541b0eac4351ba4e1ac4d5 (commit) discards 5ec8861390616565e543ca00f596753a016959a5 (commit) discards d834454b0ba5292e78b4ba8a68b2988619861bfb (commit) discards 7937b4518b0b908d1fb6cb0c1da33234782e3358 (commit) discards d426ee7ca4a036e97420eedeaf5abbfd24d4af4d (commit) discards 495f92446a6e663be39a742721bb18e7fb1d9c14 (commit) discards d1c1db6360cacdcce9fc48c51fb7809f2711e62b (commit) discards 7adaccf028973818e04182298fe1ec2902c1878f (commit) discards 19043bbf24eec581b506990ed1aea680b598e262 (commit) discards 44a0a9aac4193a647842da6c4298677f9753e7c3 (commit) discards eff4fa9738cfaaf5fe7d7cdd3d4983bf0cfbee10 (commit) discards d7806c45a0bf7e765cb76229fa5f8be47c10701b (commit) discards ca4f6938620160242f24f612a5495d40bf5cf933 (commit) discards 280cf7aa4e2cad24440039f4b7105c5096caf437 (commit) discards 62e83877c58a9e81d68a30553f54f18a3ed8eb0b (commit) discards fae02d5e5126fba375e26ec66f216a1d16f29413 (commit) discards 866e4d53ea3a1084e8ba1dd672af83ff3d62c697 (commit) discards 74adf4e543d506a44500d0aa9bf1203c2270b217 (commit) discards dfa27f07b492d1aaa94b32a11b4e24ca73d5e420 (commit) discards 511ed264e1b2816d519fb45bd1a86f650d35dbed (commit) discards 6e77e10712d852322e28a9283e7b1385fed01da0 (commit) discards e5f9caf1260a17aea799487aa7abb2950d3252ce (commit) discards abb1e1d227f3f5e61fa22c57c7f6f0fdca745ace (commit) discards ee661eb0e937bbb683f1deb24faf927add5f060a (commit) discards ec5115eab84226573a8d6903db68d432c1fe147a (commit) discards 44aa69e750a730fde6610acecfef09663d42098f (commit) discards 4bd19454ed652c54d278546992f9c3606e1de966 (commit) discards 8081600219bc8638dd8ce99e6d25a7f35c0cc8f0 (commit) discards fb932b367e1678c3d4395d7af422fa9627666f1a (commit) discards 608e6fe5f24bc6cbf8f4296994fa3878b49a4557 (commit) discards 5dcf248bc167a04886fb5388c42d1d11aae61cec (commit) discards 3288481c22337a8bdd785d0cd8b725d5abc1351d (commit) discards c7926fe8890a80bb3e9072e903dcadcf4faac4cf (commit) discards a41cf74b1836899ad9e3c80a8013446e849049ed (commit) discards 41aa789e0b1d498e0a160bc2848c9a16fea9d2b5 (commit) discards cc7832e9bcfea870de73911f1017bdef6a9ff956 (commit) discards aa1ab4c0c975ca81ca7005e0359573836e930530 (commit) discards 1704cd340e9851e0041d275be54bb7be21b40288 (commit) discards 8de218ceaf8bd1c6a122f245228aa885c82985a7 (commit) discards 986d8c78d428c6d7ac5d3a8e4ada86e65901ad99 (commit) discards 21b23658deecb8a8ae0b0be1c7dbd53adb694fe2 (commit) discards 94af779a19c7ed4227a396fd26f1bc22ee26699a (commit) discards 06455f35cf076326134621cc44a446681e6c90e4 (commit) discards ca5ef925eb1ae2a1e63ae1b0762ddbbef19e49a2 (commit) discards 490b2d6ee5146c7f097ba8a2759bf720d528abce (commit) discards 1d6b62aa619dd4eba44c77587fc51349b73c9ce5 (commit) discards 5d4fbacad99dcfdc6dad8b56965e79b61a9df68d (commit) discards 21e9e419770ffd41884772439dbfda28cee623de (commit) discards 5fc1dba0efe29c6e551593154f516f65075aa798 (commit) discards 25ea96c017ab81f958f26221155d95f7880fbf79 (commit) discards 1db6826ae803e9e1c63a1a19bf953fdc1360002e (commit) discards 0f847e7042105fe1456dbf23eff9477a3dd254fc (commit) discards 9f041e9f37d8228670eabfcc8132d1c3819a1423 (commit) discards ae55ba6c866b3b5ea76b3edaefa4226c1815b11d (commit) discards f3f0ad74f30e540b6ab60840e63f33e1edd97508 (commit) discards 86aeeb1a3f61a56e9a864ff3be8cba47ca76ef45 (commit) discards 6dd39afe104b89baf051e803ff22551a74176bda (commit) discards e6cd89b6b31760c5aee1aa0ae354014cd4b498e8 (commit) discards 886a61ae304afd7c28362c19ea5c539e686d6760 (commit) discards 6051f76a0f28c91d36d51d132dc723778577d053 (commit) discards 4bad5480535f93ec1b3fec9527994ba83146dc3c (commit) discards debeea6b152d6ecadebf9dfa98cc8181280e88cd (commit) discards 66805932ee04c275c2f9fce35be66d4d8c6c3a08 (commit) via 4d505256b3e3b787f701e84717d1076a0e87ae22 (commit) via 0f4dae0a4da92af5079eb730443ec188b3b46f8e (commit) via c9bb3530dc6117b495237113d38dc7d812b23b72 (commit) via 566d20771f82492081c55c9da6f1768941eee40a (commit) via 1d25e8a7c9000a2261dfb42337a2cd7456fc81d5 (commit) This update added new revisions after undoing existing revisions. That is to say, the old revision is not a strict subset of the new revision. This situation occurs when you --force push a change and generate a repository containing something like this: * -- * -- B -- O -- O -- O (12b6adf4bd562ddd1b4dccb9a2888e1c854a6b6e) \ N -- N -- N (4d505256b3e3b787f701e84717d1076a0e87ae22) When this happens we assume that you've already had alert emails for all of the O revisions, and so we here report only the revisions in the N branch from the common base, B. Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4d505256b3e3b787f701e84717d1076a0e87ae22 commit 4d505256b3e3b787f701e84717d1076a0e87ae22 Merge: c9bb353 0f4dae0 Author: Brad King AuthorDate: Mon Feb 6 11:33:35 2017 -0500 Commit: Brad King CommitDate: Mon Feb 6 11:33:35 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- Utilities/Release/upload_release.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- CMake From cmake-commits at cmake.org Mon Feb 6 11:34:26 2017 From: cmake-commits at cmake.org (cmake-commits at cmake.org) Date: Mon, 6 Feb 2017 11:34:26 -0500 (EST) Subject: [Cmake-commits] CMake branch, release, updated. v3.7.2-1305-g566d207 Message-ID: <20170206163426.76C3BFA565@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, release has been updated via 566d20771f82492081c55c9da6f1768941eee40a (commit) via 1d25e8a7c9000a2261dfb42337a2cd7456fc81d5 (commit) via 92be2fb392d694dffc80e635f4ac10212cfd7ef9 (commit) via c2f7ef637e7e47adf89cc8ef2eea2d6f879ddc7d (commit) via 3f5e4f1957c33335d792f6edde62ca59d3b158fb (commit) via 811c854efffba6f97bb3038b651fed7fc1bcf2be (commit) via cf1bc84216ac5005301836b121d574ec90d9212a (commit) via a4c8ad5ed81b08e042646e132f999bebaf97a83b (commit) via 59c50a1d3ceb0cec1690f454bb57dc63de4d621b (commit) via 8e8eeb73ab338fc6a6e2b6af9da3dc6f09cc26d1 (commit) via f8f3cb8d65d3ddbd8840814df7df884a2714b88e (commit) via a00cca97b384454f8a7a1f5e665eb1eeaac98001 (commit) via c054221ffd7b4643ca873ca21e96debc618d8509 (commit) via 8a5cb84b0e5ef3deac4e241d0d4f3e9932daadaa (commit) via 48aad9cda099005f5f58a7e83d604877f6f84c6d (commit) via d5f0c696116541ff4d58513d5fa2970ab70cccf7 (commit) via 9d34e51cdb7ccc74eaf851f1784433616bc9c31a (commit) via cf0d8f1fd6ad5d4bc85d7788af459238df494260 (commit) via fb26fcb261c927687f66b556df83ff6546f9bbd9 (commit) via 5564c01703c20f992769f4e152bcc74ceddc5942 (commit) via 4908969f578ded9d87f244bd8ada65ba0c51cf28 (commit) via 77f6d22ad1f1b461297a463eb5f40fbb0d0825aa (commit) via 3d5ad7236c8ce444323fb63cd9ff50fb5f757830 (commit) via ae89967f9dc9308003630531ef34764030f98bd0 (commit) via 6286d26ca6408cfc45031536ed54b1679e6d5ac2 (commit) via 37ed860ad1e71f347513a38432640f7dda5c07ee (commit) via 94a8ee6fd0ba487437579bb224500b9f46c2819c (commit) via 940bf6a4a427c8edfd975bf078a3ea331847f72a (commit) via f26ca5a1953e7f260bc23d30c5d35cc071a6f6ab (commit) via 2b0256c5ade94ca19467fd42075b3c22bd3856f2 (commit) via 645dd3ca5317852968e59a42592d8dacecc98b92 (commit) via 3e34049516f75d8545543bc68246e62ec31fabc5 (commit) via be3727bf92a416a68f5946d2915d745c0f96740f (commit) via aba66d27a1d4b5364274784fce27a3c52ee2140b (commit) via a2a73935b22444b158ec5de2916deb02d9f7928b (commit) via 134ffe97949125c47292797da6080e1e965ff9a8 (commit) via 88c4576be412c85c112976dcec51b3fb7905b618 (commit) via 2d357ea267a5ab0f54f7b411befbadc583dd41d7 (commit) via 8cdf96d0af0f72292daa76b9a7fc7928934efbe2 (commit) via 93f29be2316f51f1d27fb543f92911be5b9cec9e (commit) via 6f2e2c74ba7f9061be8a8831195f02db5604160a (commit) via e8f55c17371ced4c6d5eb19cf40cf1141c0ef62a (commit) via 2dfe480a9c3fe40699ad85aa0355111848df870b (commit) via d88ab13750860e0f7f71e10fe21a15194214d07e (commit) via 048ecde45332995198770157c4e0a34684be03d0 (commit) via d6113e958a501af2f5c88f343fb8507710b638e5 (commit) via 9f3e812fac4ba22a493a92f50b87a949d21e62c9 (commit) via 5d70894d4086b1800b31d2d51f2ac3a124d7eed0 (commit) via c9ee05d8d9b5d2ab1539d469682a4a3974282443 (commit) via f3619bbcd648dc35ffca11b154e01eae0106d2ff (commit) via 1f8da86115b6333b803feb769341fbfa171fbcc9 (commit) via 3288ab0c78057e2388b247d326dc80011488a0bb (commit) via 773df0e2d7596d84a711914f1cffb4fb5a107c17 (commit) via 5efb8b9a5df82fef0b6abac11f590f2a655c184e (commit) via 2e2c92edb03a28ccc6b0755410e58125a472aa52 (commit) via 6ec0c09a7a1f148f747db97228fc3bf1f63e3ed1 (commit) via 5accbaccbcc5f876a444c26987b66bf6d023880d (commit) via f012a95836e14e12f5a445abd72fa79599736641 (commit) via 8a76536e78e9084fb9636b2f0c57121522cfbbaf (commit) via 435cebaaa1663274cbe43c19cb8244011b6d1384 (commit) via 071f8e78dda152d8759539fa390b25c7f58d3cc5 (commit) via 07d3695e75d1bbeaa571901708350efc3f936e0e (commit) via 050bb41ca71d2cd9d4a229cdae19c97f77753273 (commit) via d6108c87afb03a326b14bc6feafeb14e99316e5f (commit) via 3642d657b153f212eb119f1003e11c3079494630 (commit) via 7e5ef9ca78f67c2f4def64408ce4c7ecc03917a7 (commit) via a6fda7bf4010051c2232d4ba6c64f310862a6471 (commit) via a2d393d648d0f64010a4b34b84ab7985a284e294 (commit) via c7b846edaa7cee549ca08cbfbab2843daf106a01 (commit) via 1679fecb74ee4eb4500d591796f93fe4271b688e (commit) via 98e6d1e5e426c491e04faa746c11746002e6a69d (commit) via c8703e9d7b6c3f7ad58429317a6bf75c1e415568 (commit) via 0de9c3985004ef802aac97e20b4efde49989794c (commit) via 97d61562d064af4e79ed51cfe4ef4ea95f780b23 (commit) via 5181f1f86a4d4c2ac09a540285c938fe2c2fa262 (commit) via 4dde0bc8ef1d953b8e4b13a2e465d756b5274933 (commit) via 8df12fc9d4b52cdd18d4fa9408325be7d0c28ed2 (commit) via 5c6c766da1b30f2d886ba369a4c407e575ee1ccf (commit) via e6659f6323c75331f15fe93bb8d060ec03729738 (commit) via cbabde81f26db615411aafc788b9a0db35a87267 (commit) via 84963f429a74c251accfcbd1d4923e1e8ced6bcf (commit) via b30ac988d02d00f7423870799d59272a553ab9e9 (commit) via 6c54f7b3655737406c53fa1e4fc1d8f4cc22f9f9 (commit) via f01045ea36621fbc66a87bb041cd403d47304211 (commit) via 325c6153088c673569971958f107f6cb97b67c50 (commit) via 0ea578b498059340d575be263f5b6a91581f5ce5 (commit) via 86ec0aca050f2568cea691a0ec965f6a95e06d2b (commit) via fa9c12933f0fc51ee577a43b51381b4d8e4a127b (commit) via 560574b0c03f2cd8f34cf4a90f6f41648b08a1e9 (commit) via 83596d4ba133014b6ed1ab993f61476634e2bfdb (commit) via d525754eabef7a9f6e6696ae323a8ed965e12f2e (commit) via 45405f00d27031fb9641408c56673532a3ee3bde (commit) via 50e1c1056ea82690474dc186d7a4103b33547fa6 (commit) via 8643ca75c705568bc9bb084a5182baef04865d2d (commit) via 895f7f16a79428689a263ba5cd9a72647dc8e912 (commit) via b8db2ed79675930421ac96256d63af515e624d38 (commit) via 90ee3bd3b0b22c62cbb96334ba6620b89ea3d6be (commit) via 4ab35eb661f92686cc3ed3a1b52f7c2ef49bf8a1 (commit) via 09cad3090415fbe59474232675e8124c8332116a (commit) via 6ee9efa883c19c7c1ebfba660c76d42551bbaee8 (commit) via 243aed525a2fd8e5fe32139fd0f8d0cc0e40cc33 (commit) via c3a22518f83dfe8e1787e93f05398a5263cc781a (commit) via d491172445dcd32547fbeb3598510455e8e44132 (commit) via 1a2a9b0d08c7ba2af168856b1220d42ff9a80921 (commit) via 3cfde818354a8f8e26a9b0b6589f3cc38b50e48d (commit) via f0165eb624403c26989d1039c076d61536cc3074 (commit) via 9da7bf082513952c47ffb738b722df49a2fd7152 (commit) via 4cf4acebe347bfd55e051354b9748a5b0c25b58a (commit) via 614a97a57b65454a14231ed60346884bab2399be (commit) via 65a0bfd83cc47e60b9f42262f762c676fb210aa2 (commit) via 4da3cae9ffb3202d9c447e9f497f8a2758538b06 (commit) via a45de72cc437a13179e933509d524d2088a86002 (commit) via 24d73fa0eb2e9f7cdc8fb8192445ce3ee04cf7d3 (commit) via ef47272b075a2ad8018481d3fdfb6f2beb514056 (commit) via c1f3086de70793ee5552986347291d814b796232 (commit) via 014365ea97848654cc9493225399528f8b7b15b7 (commit) via b4efd34d798317930d2e9af907fb3123999c450b (commit) via c0ca687a1b8c27f767dd32ad7660a3fde84bbc82 (commit) via 54790e77d7401cc50fd6dce584aa00985aa94ac5 (commit) via 4f37987e3fd72b957d45e741e6ee70ccf42b167d (commit) via 9006ec1d9b7d738f690c32d673443b8851887f16 (commit) via 4bc2c16b5d01a66c00100171ad083e9ab5a6506c (commit) via 9702b3eefd2baccd24eea9779e17da8fc143fa4c (commit) via a007f15344007a6261209a409c6988b0e4c4b7e0 (commit) via 796dea67a68be432f98e2fef50059c93106557a2 (commit) via eb86b4cec14df4a51cca9f178e8e758b97be11b7 (commit) via 178c897374718c2b7cfa76f5c016f23658d5d2b2 (commit) via 3bb4a798268669ca1364040abb3cfdf4a44c2f92 (commit) via 60b68304f25088db12112c47a4599e4fef405429 (commit) via 1731b90cd0b8c1c0da2f485a9b43006bb2174150 (commit) via df3353d1f9b4cebc46018fd8fb6c601d038747c1 (commit) via 2759e22575b9c63f3162a9629c2d8aa6b9d7effa (commit) via 3270f763b28195de83c8b762dba5fb366b714b30 (commit) via c59d381065b14076f47246f21ecd730cfdbae7a1 (commit) via 38bb96386cdc331d6fd080166318ff8272fc19eb (commit) via 6122fc54a9275caf3054a12bbc813be2c8036863 (commit) via 6c99ec5bfdc9710355e3318cb9884638ea2ce925 (commit) via 0e990a01f15dfcddebc24ca018d4695209226132 (commit) via f6e4602fe7467fe149f3843a3263a986ea1d804d (commit) via 114ac7d005d262f6fa13a87111303938e66cec3f (commit) via e5089c562cdb516bb2a502754788864390c429be (commit) via 269b1db914698a94cfb53998d8811ab03885418c (commit) via 0618ddf6b1da3a886f12b6ad2b19da49b2f87e28 (commit) via e6eaf25c3a74c6d075178e309cb0eea8d894698a (commit) via 39bf93c897626130177d57e6813cbe46b35c4972 (commit) via e116f2a5de330ca4dd413e29db62ed39805b2c06 (commit) via 522e1588ec7bfdbc86199cc1991e706ebafc02fd (commit) via 7b4514fb33cf256ef165b2b28ba4affd1930a957 (commit) via 624709c824a2d7a75a36dc23551377bdc2aee648 (commit) via 1c93eb683b182b1f0bbdcbd39fc50ad48cc57739 (commit) via 8ea12a8b80c4c3153cc602f1d0735b3db8581ae8 (commit) via ae629a0dc9fa775230f4ce0157f13fde99381c9c (commit) via 1ee0ffab819d632d7570bee23a83807facbb45a2 (commit) via 1806e011cb2608c7ef62f345661dd35a899eb81c (commit) via 10c9c73d58b481a212d1ed87ceeb227a7654bc56 (commit) via 8f1bce12d2f8ae2eb3771b173b28b8405b059923 (commit) via 1c2ac0b8baebcf2496d701ab316f8f5666b470be (commit) via 6b4b8e6a600e177d6bbe41848e7de58e7392c81a (commit) via d9d41d332d91abf0da7aa531b64bdecad5b6e9b9 (commit) via 0f891007a902a79acf746479f6bfe19b96899cef (commit) via 395f01ef728b3c41b2cab020aff381814244ebe1 (commit) via 910ef6d0a3eab5d483759ee23f10e91f1c4da8c2 (commit) via 22d240184cfe5afda325551b68610bf7160afa8b (commit) via 2b1cdd85b8943059e5f2b27735df261743749342 (commit) via adc04afe34791a90a552fcaefaf30e24b937e1b3 (commit) via 05ed82b1d2175410e8cf4d7f8b4b7ba0514d2589 (commit) via 0ce7643a84eabfc1c1083d2f3ecccfae6d04836a (commit) via 5614a5cd1f7f8fe34f6b31c572476a2ddfd6d9ae (commit) via 45dea920ab4e96f84f43eab906dca3c51bd12c31 (commit) via f5fae345e4a0f9f54b69424552f7d85aa85ba907 (commit) via 7f0a21a51eb483c523a2c8880ce4e0466251ec74 (commit) via 4bfb1249ede1b86dcd53b34ec885f17460edc8f6 (commit) via 90cb40832375fa880b792ca9bf5cdd3071912f9d (commit) via fe8e00f6b91d7e8614af5a5ffb2ab68775b06e1c (commit) via 0ed885f742088b0e68103b87ee36837c37575628 (commit) via cab8f26211051a24ceb0e512660f022c9960f241 (commit) via c9e76c3e04ad2dc4f50297451f2c38fdef7ae6b6 (commit) via 524c56431859cfc8a96a8dad752f131804982166 (commit) via f63096a68c692f1098380cc84e729ab79c67e59b (commit) via 6e4eb083d64a0e562e4fb8d2663cd895aa75c500 (commit) via 65124233da4b3e53643c896d38602318fcc549f0 (commit) via aa63ab6d3e7bf320f17a5364a596355e3ab976e0 (commit) via 3fc4a2b71a25ba4045a8b80e66ecffba54bd0d54 (commit) via 020cba316bb3a4d33da5108ab10d2c06b4712427 (commit) via d9f836e9567dbcce85b917300e8de9086aa1f1f7 (commit) via ee77941a1fdf3a617207b00a7f2e9315eaef7b31 (commit) via 219c7bdcb16cd1dfe2e72befa4334c5b8147e1d7 (commit) via f38644527cee6d99b48930bf88e84de15d98007b (commit) via 298b5b31caaa613259d0a1c56a299e8e523fd61a (commit) via cdf7e5d8661c5035e42d251d009b5ef49a11af98 (commit) via 5201a3065b1c49ee2628d95c860b667e9e2b182e (commit) via 35ad12f99e71515f9cc65b1219160b88095a5f6b (commit) via 47d391d71d611c5129c6914ad77b34dc4bb79d75 (commit) via a67baf0af0f5c94eeab400a163b8b2f6824d7bab (commit) via 9aa2ec7787968528a6612aeedcf0485700ef8445 (commit) via 4433be6bce6f69d26dee1e2a4213e409bde66a21 (commit) via 743085a5795ae666a56a3eeea59c5467a0b714a8 (commit) via 94332a3ed8398202e4d8f985bcfba31ea0fa71e6 (commit) via 8a8aff612c77e03358601a9c5d8941e518f82d1c (commit) via 4680e469f6a6f5cd1a0791d200dfe48c0324f38f (commit) via 034e1723dbb29082eed3f1df9d0cb846a89b4b91 (commit) via 0f3bb10dbe253ddeabe1b7006b46d813de61dd01 (commit) via 2ad405202e811affb9961f96a90d319d49a88b11 (commit) via b42330be21c0d3046aa0e6fdf046a492bddef520 (commit) via 2bba0bfc2c113a1ec94802ecfb8a836a385f919b (commit) via 7bd1d53505045bfa97f573f7b587514012618913 (commit) via be5b310cca242dfba9203ae07ed1d76a1b240d48 (commit) via b3d675f1cbd60a41936b517356e657e826434555 (commit) via 7c8ab7ddc8944152a1344c43acbb8c57fa2d398a (commit) via 85a8939e2fc7eb2715a9264fd40c009c3a98cb8b (commit) via 63e550e54f577b081d1ccd742ed1bbd02622a671 (commit) via 1b63ce865e86596ad7df3cf39df827434c986f22 (commit) via 397b854620fc1ab3d8427ebeb5b7e4659c4f9128 (commit) via a7dd8e669289e7b78ebc05b5d337052f32582038 (commit) via 6fda6005b306cc4a1e9e9e66d9cd4525fc623f73 (commit) via 7f5842d7d943403fca02a5345e9d6f779eb7bf9a (commit) via bb670d9625e670a0e87ec048e44db39b9d2b336f (commit) via 3f86032bdab94e219d053c10b7e55eba9c06e562 (commit) via f24e1d37cef95145927d14d186e1615fca23a75b (commit) via f27c5852b0d1e37fb27bd1da1e7295b5f1fc963d (commit) via d7d2cb48c69e2a9da72a8baf188f02b81ec9c34f (commit) via 721997a7a23f0cfa5c9e096cc3768625a51f359d (commit) via 9f47d32697686265bc2c5a708d2b53e2337f3f10 (commit) via 597124ba8e409edc28cbf8f2a55150d2913a50e3 (commit) via 2b400b242101fd8b7a46073412830278aa3cc9ec (commit) via edf0b8a52bd4db8557adaf11d7096f7982c373aa (commit) via 06430919f4b903ba256ce158caf223f515faa8a4 (commit) via ca179f2afc6d8ab5e0df3e35255155c21a61b5f6 (commit) via 119791ae528aace81f6c209e05798c80d8926b3d (commit) via 95e4cfc5947fb5a324f6dad50cff8d71f928aba8 (commit) via 6c55755bdd54c2d474e2c8fe4c9d078e10404f26 (commit) via 1491ab1c6626ed6a3b67e74b94fd18230e1bb4d4 (commit) via 29112c9a695a8dce6486203d0415f17ac41d3a0b (commit) via 6d333be14d23b9aaf4452189199134bd674ad395 (commit) via 52688bf7453cdb767e231f5fdc7d80ce79ae239d (commit) via 4ae2dcb1b965efac7c088cbf97fa66c4d3c41858 (commit) via 8d1f9e5b850e02d304e4c209e720f06e25837470 (commit) via dc5051f1c1b7604b9c05e04bdccdff222b69efa0 (commit) via 05dbc940b7e19cdccd7ec73ea173719be66244e1 (commit) via 47ffa0ea5d6cf08bd891d889ce67bee8008ebd8c (commit) via 0362c60fe5f4e7e4011f14dc2519ffb1bc6c8ce8 (commit) via 4971799360b5ec7c99f94810f2fa5cb9f80dcebf (commit) via 577f721fb70bbf6c29c40d5f10d4319370ccb1f8 (commit) via 9fe399e3894dccce158b445c9ec4f2253035eaa0 (commit) via 728820f3ea0faf55ffe1236a44a35e9197fc6291 (commit) via f9a810f7b39406e00998c6e74e5a7d7d218d5aba (commit) via 5599d858c7881b4331c449ba5c59d255ed50bd11 (commit) via 1155170230ebd096df06ebf108908d6c99242d6d (commit) via 5365421e84e6133f0e038995e3a8232ec46d6a91 (commit) via 522b913f437b04aa10b84cb5807ab43181377d7e (commit) via 02582b91ad92969d8fbbd845a5d48b3fbd762966 (commit) via d470cb70077acf2216afe097b5abe379f1828239 (commit) via a2e80cb0853b3b8306069b833ec8c2128a77b072 (commit) via 65c1e012ffc17ab77e5aaa84b22241a81de4c2ce (commit) via 945dd207b6ca6ca38e3b87247836eb1b3d5f8a77 (commit) via 95420cea5e12d21957a50dae20f90c2e83571758 (commit) via 9f3eff6f5675851c81f093d16310d17e3754cd5f (commit) via 889fe63b510b9669e42af31600c2c887abe0bb34 (commit) via 51255a7c7ade4b591b38ef6d61ce0f6a6ed96699 (commit) via e31986b90058a46071f7fe4a52788de6b42cb96c (commit) via bc09abd7d07064ed046cdc8e959b443d69f77596 (commit) via b4f7ce5c79bf06292deaad8097da7889eddc2886 (commit) via 5e76ded22c8900a8aea3dbc76f2401f5d832298e (commit) via 2e550e36d29332adda29f85fbf79e1610286ab9b (commit) via 88a816c6b9b4f5cb11b40410935d47fa61b39858 (commit) via e15106b2f1825fb42bb82a47b1ee5e9299212fa6 (commit) via 097b47b972d04c0546f5799dc901f971b471c2b3 (commit) via ec09e91a653fb5d2df2d4fe5c3bc76a453ac5e39 (commit) via 592c8cfd93b8fd2ceb579b09b9b6f4c157adea3b (commit) via 082456e5a3ded411c6cbbdf9c3d3f6fb39fbc9c5 (commit) via c9a0b14153b87de34a651b1136971f9404fc362c (commit) via a10586377232b28be13c2bf90c98d002067eb5fc (commit) via 053adc60ee80e55f2a8c09fadadc5db6e789412d (commit) via efff7086c66d63c62d9474eca5a3b2d21d725bfe (commit) via e0ed1de4fb5e9d18c2d00775229496079d6e077a (commit) via 17a0703d205d26048247e22174a1eda36498d341 (commit) via a7c5d5fb0e8d096dfc9b6e82e93f1e0d6225fe1f (commit) via 1ce39a1e73d6a38ec53679113ba643ac6a51781c (commit) via e0cc40ed58a16f63a26cf25c56f6e8471401fbfe (commit) via eb728d266e171987616c71a63f3f772eab45ebf3 (commit) via 12d5ccd10a451301bf3cbdefe8fde744bf6c9467 (commit) via 9a670222758bff23645df36a5cb9d98cb1bafa8e (commit) via bc2cc80255c64bc2b2fa4c9dbb54f5cd90150982 (commit) via 474edf75f6234a9ed3b59b7e11c53d57f9bd2f78 (commit) via 039588e335fbf559f66719aff2a3c8920a078261 (commit) via 2eb5596503ab8cf2f5ded140d45aa013c9705436 (commit) via d1682a8514f9ecbe91f59e651be917afec044907 (commit) via 445ab80c444b1f5d2800784f85601976867df411 (commit) via 34745595c3b87279b92ea402fd2ccb6351344307 (commit) via 0884c9e46a108e8d7b52f6d96242f147ab12d001 (commit) via ff6a034e0bb7731c97a90afec849d8c80e2a783d (commit) via 396e9378a820cc5216aecce6bff42f526f4f7c26 (commit) via a8b576244f729e543795750eb6c9e188c0e1fe66 (commit) via 1406408e61a001728eded5a7f28f3c392ff31c38 (commit) via 22dfda11121c2b0c2374a5eb29fd3a2f140ff92c (commit) via 3a97a3713a498c9a89a1733131196f7fcd03552c (commit) via 6e6253ea88542e9a3c8afc9560f131bc7073ead7 (commit) via 7db05f426e2c3a5b4d1a29ae97f5a75692bc03ac (commit) via 6eabac26f5c8167481be9c872210a8142ead4b99 (commit) via d6877e6c405eb67f0e3e9eae783de02d1d8be659 (commit) via 0315ab7a31091eda95caac319d42409c24fc6fac (commit) via 6310f7c3a06cf56ddfda7fd5d2a36decb6802e57 (commit) via 3e5fbbd6cdc472cdf7823cf81c0e527c79653188 (commit) via ff91b1514be75dee07e8009a60ad39284e8844b4 (commit) via 524f5ee186f95a0dc0dc449e437910a72b175893 (commit) via 4b0c13a87ffb799334669f77978cc4d5e83f950a (commit) via 696339a9d571ff7d37222296164dd738a6a2b042 (commit) via 8deb913d983eee5ad1439ccb98244817d8912602 (commit) via eadd395a1396ed78a3ecea7740f8f4735ab84453 (commit) via 513ef514e51702bf7775f79119f8e3e39ccbb784 (commit) via b8968b4b3984b425497324c302948a197b2badbd (commit) via af77368ed3d81c877fc19a64831aff380cf4646e (commit) via 3462118c6d700754e243492c3a65ef4ff26923f5 (commit) via b1dc4ddbdd651e8bdd30878fa9afc840d97c9114 (commit) via 154def305e7a95d9280573b053170b17539c9f69 (commit) via 914728f8d724e834a402619d05309ad8154ba59d (commit) via c43cf158d74460440dc5a3d0aec984c754f57958 (commit) via 2c8eb2696a8f3505d45ed5accfa94b3e5541e169 (commit) via 039a7df9bada6d061f34728a0bb57fdcb9e277c1 (commit) via ea62999f457a4263702a7f01e2c9bd8070da1e01 (commit) via 9239141e954c6b9eaba53fcad46fa2de24d8ba44 (commit) via 4164078c8540bbf75b47afd5c1bee0acbbd5b253 (commit) via cbc07d331d1d5429dc1e0b7c6c7949ff8d9efdf1 (commit) via c17e0a3ad58f06fcb0827910af520405670b3d51 (commit) via 53787bf8de2d3981f650e9036bb89cb6ed884a75 (commit) via 8dbdd3e726ead25c179e6eb4ffab212a1db3aba8 (commit) via 0699760d5c8b644242ddd4ac6d07d8c4c68f2b94 (commit) via a84f0bb726ebcc8e9bf3db0b99e5b6fd8a720045 (commit) via 7b766b83952ec4c431a55d2f6e589a5f806834c9 (commit) via 2964b8cca4155fa318722f6ef17f0d4d56ee2f29 (commit) via d58b6bf31c18cfedd4a2f15e009b8e5cbdc21b6e (commit) via 94c319f93309ff4cddd0280cdcbd48b50492db36 (commit) via 966be439e07131c3ff84175c1a9e3b6336908d8e (commit) via de531432887487943dbe4ae5a1bde762d5582e06 (commit) via d8e45536fb3637454cf17a638dcd9fc236e94660 (commit) via d9313a82906ced0ff3c76828e86d9d7a248a5e49 (commit) via 32d3540e090c4a24d55b99c49c094a9cb574c9b3 (commit) via e7280a7f1743d73cdab41ed709a9e1d0f99b6342 (commit) via 63d3ca4c1cab0c7b9c71d6c051c3b4c053eb7627 (commit) via 6ae19bf32e232beb59a0c427d82c0761e8248ab8 (commit) via 9986da4f0f2f49c0d7d260f9d21deaa906708376 (commit) via d51cc88e844c78c01c1616e6a2fb102c0682dd00 (commit) via cf1d5a9cdba49a2e9f08879d756ae118b22bfc6a (commit) via f962275987e17cf94da663a919f52b6d0c8f44f4 (commit) via c736c41ad192c89e1c74751a8f401c75955f5f3b (commit) via cbd650c2642e40369eaa53d20dafee6cdccae4af (commit) via 0b1527ff3d1781380756ee72a9641b7c5c7c87cc (commit) via 2b9d795e63acf723a6abd79f3195ec70476442a5 (commit) via 2cfcdf757d032cdea8b980792007a6f9d749e6fb (commit) via 2f67aef23d4192fadb222dc79311fb5ffbbc36ce (commit) via 794fdf40a1bc85dded519d7c737f73690e3a6e42 (commit) via a1e49bb155132606ed9f590c0b62e68f2e288d0b (commit) via adbf72280d1eb823402c4cc7f2c27ec0ef16062a (commit) via 574c81e28cef6737adc1619ce3b44b43bdcf308b (commit) via aff368bb8456694e2550e2f69451456728ab31eb (commit) via 0471d13ecd2ff4d4a0e824a1b1d0d850ea070d05 (commit) via c0bd1eb6d0da40d429120e925aa755a1f5a754e8 (commit) via eee51e24d2290771ad3dded566ef897243f21331 (commit) via 4ce6cd2bcfa847fe2e9926d97f27be1d89fe1c4b (commit) via cda3a69b1bcc2e83806f7423c6970a794be8261f (commit) via 0dabeb6024b352bc7d5f9e1dce63ad87186ce36f (commit) via a0ed39ac2207edbda08b1459096d2c1bf757cc71 (commit) via 8f9e0884d4f948526c08c35dde345a142352d549 (commit) via 98f2143305b8b8c5ce08dfa38ee79750696865a6 (commit) via cda9a904b5ef76d923a072a45c0c15fd1d87d6be (commit) via e537bd91129fc1616f787b64024f1b08d0f7ae45 (commit) via 0a2e588585a951b1f26cfa9094e0709f1d026b1e (commit) via cdacfbd255dcf640be7dd4971a1be616d015b3fd (commit) via cf590c1236e40eaff9fe76ec918fad33df4f6be4 (commit) via 976574b01009e11326c7894edf35a4f315b216d4 (commit) via 9cad0ec691f3d019a8737c4a6bb61c11573e6062 (commit) via 0d8874e49374fda8513f1f3c5fa1797aa86d90ed (commit) via 737350526234269b79c52f9dc567e0f1d93b13f2 (commit) via 5df77fba5327ce78d297587be1a29fe7688b6b42 (commit) via c628fd2fab273999e959aad00834369924dd9d06 (commit) via bd9b53ab33bb2185d526e8897cbd8f95c680b2c7 (commit) via c8084b3020b51150ecb5b1dc3b91758b171c93f4 (commit) via ea0db79e65fb943381c8a3358fd18ba2516e29bd (commit) via fbf0f0b3b6a2a6c7cfd8bc7eca2cfbd0263670f9 (commit) via da04b68f3937ae2d4497068b41e7cd69d449320a (commit) via 2da3ae3bf76def94d3177f963703e3672ee27f1c (commit) via 58a09969f84eadd0f06adee33d3aaba09da26229 (commit) via 88f07fb417a25f98662da2abf09a9db03f48eb7f (commit) via 65fb0fa63279b96035a144fd2f6413d1b2def47f (commit) via 2b301e11e2402690c43a7535656cba487559bd1f (commit) via 36bc7e4c3f91c560df8051afedddea3f49474264 (commit) via 8b623e8a4af7451c718f448c8e27ce2b82347f76 (commit) via df00ed13107ecb5e5b61ec07bb4190de0aaeb6b0 (commit) via 6daa2d384ef7f6f9edd5fed18c830168f7496881 (commit) via 05c14ea0a97f3e8a7287f3e0bbc57f91e2a6e490 (commit) via 5b0a64ebc5d03a4dd0022b87e8e6cb77c3db013b (commit) via e8e9034596e15dee3c8febe860c2429df512dc10 (commit) via 65c18b2141fb2553911104e0c10fe74d8daf5b9d (commit) via b7f0b1240f9c251d059fafcde878168f2b9a6664 (commit) via ba8bb32162ae7bc42c4a3a521a4e4b98274d9d8e (commit) via 6154a2cddcdb297b1aef20f501fec9af7d7b5262 (commit) via 2f4e5ed66dc34a5f4ecb80d38d291d1e78ac12f7 (commit) via 4918cd8c98938ab245d7fea74ba6e20f3ec8ef8b (commit) via 3657ac9fbb6bf6cd82bf9a0119fd989ab3f4f704 (commit) via 77468c751f62c4dfa64fb60c5f4336a8534aec85 (commit) via 9639b2f7e7fadee1c160b915183dc2aa30a0408e (commit) via 3578e86272b16b303edd640f29781dd316a857a4 (commit) via c93e85d87e683e4c20e5f29726889279aea9d921 (commit) via 18c8278b622e4cb9b155c5dc4ceac93322bed85f (commit) via d47bda00b2e46b3fd6f9e050f3f21b5337ac244b (commit) via efdfc26e14b5a4d8b52a1021ffe85418cdfc802f (commit) via ad5b702c0914e0912693b9e5a84d9fe4bb53d720 (commit) via def7395f6278c096ab8f4f418cd5db5059c8c314 (commit) via 8e4d286e7b105407d523ccf745198d0400b5fdb3 (commit) via 4087d0ae85cd9835296a82e0d5a63db0feabcb93 (commit) via 0a9e4e08b5d275fa20190509d6b1448f360461a8 (commit) via b5c7835e27dc4bb009d508a5b280ebd01b2fcd71 (commit) via 58dc3745ec925923713f16c0e77bc9277b29eb7d (commit) via ed8a9cb7de9323709b125eb4af97cc6a8c444a66 (commit) via 4a06479874e583181f86fb64bf795e1eb1ee0de2 (commit) via 5c616c1089ea351336a7eefbf53ffb6e5bd8e97d (commit) via 25d7b8836d8a073d13c384a14bae05d5c1d244eb (commit) via 6271df8ff5ce5552929bb76440fa432641498800 (commit) via c59811a233267a21fdea14af4bc6583af0f8d9b0 (commit) via 40e5614923db52a31b5e46a3bbc5e70105fcbf5a (commit) via caeb6d1dfb7ec9ab471d24e71244d7899f044c27 (commit) via 59461c2696e46f5d3eaf5753ee4f7d2ee6eb71a6 (commit) via 9fdad82c48fe28af73e07c2f91749c50fa5a131f (commit) via a12d8a03af8430d0a570c97deb200e16830568eb (commit) via 94c6040b730e5b77e72c39dda10a0df3228ce279 (commit) via a9fee0667ee6396a6a0b7e5d33b542e49e3054c9 (commit) via a20edeebd2c93ce1d1549d79b525ba5260d7faa5 (commit) via 5c6c0344d32f9282059d46b6fe6f9925ac1f1202 (commit) via 517c7cca8c856546a93454cf0cf98fe6bad3f856 (commit) via da03e2d6c60f70f6dfe581e130067b2dde4517fc (commit) via a9ea66bd66db0f0ad9b0b59d617739ad6a04cebf (commit) via 2413075765228001a205017c670abbefdf3b7f61 (commit) via 58f02aaa4df6dcdac917ff7af7db2a7a1eb040f9 (commit) via f17394185558d6adc4e09c19937c798580fbf1f3 (commit) via 858081c2f9c8066396982cf7e7277514c8cce6e4 (commit) via 788581883fef05820f3f83ec5d1456490bc2397f (commit) via 60e5f61917815289c80c31880e5c90bdf81eefb8 (commit) via 2674818ee16b3f8882b785bda1120d474ff58c16 (commit) via 062645ca6788491c4f63acc83782b87ffbe26043 (commit) via c5df1f165c7f8f1e31e3144d326c6836af2e678d (commit) via 61001557d44fef7b98a4bab463bf66797f927197 (commit) via 23a35edf4d685826e2380bb90e36027000f69971 (commit) via 55da7e501ef114a3eac835396dae2187b7af96e8 (commit) via e3f404fe29d85c068641309c1bfbfab1e34cc6e3 (commit) via 10ca398b4481b92a2cb0baa57f764443230fe4c3 (commit) via c241679956520ff5293c959b37ded827c49096d5 (commit) via e3a93c66cc9f1d578f880f19e17ad31cc731fa86 (commit) via 53b5d6345dd9216e5110a9645a0aa194926d5688 (commit) via c968213d2e43945e69ebe4ad12ca933b8f4c4e6f (commit) via 1371eec4c38b0a3b83f1416774c6c213ad0db6fc (commit) via 1d1f29f435cd9854ec6b6075bf3e7dd810d19ec8 (commit) via 3d3d3f94703e23d3d2cbff67537057474e3e0ff1 (commit) via 7b47ce5a3a9bf9b92c4f8f2590b788da444a6f94 (commit) via d1d11f73a1a7d2d2ad949e9a4ad1c65f155f3cfa (commit) via 55ff3c78b3d0d08cdbc6dea700e2add6a64c988b (commit) via ce71bd9505a46d7350c0e256f2d8f4f183d1c9fa (commit) via 9ac0c3936e612ec4780ea96d298095e2ad907fef (commit) via b932cd429800bb24d71e1d60f954fe4df2d1eb5c (commit) via 88da3d68c2d205688762fd6a7e84fd730533e844 (commit) via 58c66393cfb999f23bfb6ff72122ecbc531434c0 (commit) via 85bfdddaf75905a2c075d2a94d85f4bcfa1feea9 (commit) via 2988abd9390c1d6876610436883d1f7bcd405d8f (commit) via a74e6893480e491959e9165106f199a8cd0edd57 (commit) via cac529dd495f05dcd24d33dd5fa595ff28eb7a60 (commit) via 7c9db8f8139b945d4c55d9061e4ef122351b210d (commit) via 3874843f0f5be9d53001517b3697e0d092f0e845 (commit) via cf2d33305fb233042ca880216bc83108b55785dc (commit) via b88843d651dc2c500af13c1fe882b389c4949b04 (commit) via 44ddd889af8c9934b2c73411e0aea7e323300abd (commit) via c7cd379179b42cc3ef3bd49e23f8ff264bbcd041 (commit) via c1a55079177c256c83ba5ab4bd72555537ba69bf (commit) via 7552d16d1a9ccfc86490b1052ed4719a704ae358 (commit) via 4505411982aae1d5c79bd80c43b8cba5b3a462cf (commit) via db61cd5d72f78aaf720f60f8e3a573fc36599bf9 (commit) via b7771078ad1ade95a4ae310815be7971017e10e1 (commit) via c58a5198e5eb8878ad111be2eafcfef75e94b54b (commit) via 0c38000393aef700b22a596e35c7975c7a7b1ad4 (commit) via 1dd3e21a54f684df876da6d778ed04535ebf10ee (commit) via 8acf5b78efe995662a832952e514fce09ace03fa (commit) via e9286c9e0f7b059cd2ba3da1bf392ab5cc70e4e3 (commit) via ba9fcedf6a66e524416d8822fe8873e88fac5ab6 (commit) via c46145c61b9e2bfb8c8ea893f95f31e2b480c0d3 (commit) via e326d8cf3eb2ac3f98fe5b4783b35c6141c006a9 (commit) via e438693e953b77ca12339f664518e28283c7ec64 (commit) via d42d3780ac1d62c7733affb9fd168a4e803634a2 (commit) via a0d64ecf8b9eac29cbfeb7461cf3bcb1688f7aa7 (commit) via 0478314e13e6d04a0100cc3be4ab84540a8beaa5 (commit) via c8a4147a34d38ec6a96c51e750f70f76a90ff1dc (commit) via e1f571a98371ec99467502234671fb52f8f6cce9 (commit) via e324d70409b8f56c0d870916f81d8b848233c4e1 (commit) via c2211703d35de8fc24e818680c033503b96167ff (commit) via 2da0875f3a8cc91a8355298cc8da0a34f98acf09 (commit) via 5961db41436081f0ff936ba56a7053f51551afc1 (commit) via 6d0a8af3687c66f95d7f787402f7aa82c8fae73a (commit) via 6731025211bb300f762ac4d4984de124dc38c95a (commit) via 43d77e1dadab06f9b49ebb6cbfdaffcc4b708f1a (commit) via 98665c35199fffb66ff92f5f15da0e1580625cc0 (commit) via df74f3ff834cacdd46aff7366a479d8317315a7c (commit) via bafbeaf19076f9ae94be2b8cdb845617674aaf99 (commit) via 8f437f3c35ae13c147e0d022a84774750d4a0a7a (commit) via 360c3427117312548358fddce906a346f17b8f5f (commit) via b5409d04f1c1309deb7e45163a106c8cb4daf38c (commit) via d9996aab74836bb830e106bea0b0064a4c74cb1c (commit) via b770b85d6c05fd36462172e33c8b700b22b801e9 (commit) via 5c3dc7460ea6644bd658131ec474e6ddce825b1a (commit) via 8c9358386b0b2826ffc3da4385474a4227477eef (commit) via 8f47a5f16aa685e15e6b49c0b90a58b18ea38d0a (commit) via 057ac11bfbc5501c8037b173a73a55466163774d (commit) via d3afe4070b9c5ba08a11ce3b4b30d2c1ad4c591d (commit) via 6f53b1ab642ca1e5977121ec60779f248cf8ee88 (commit) via 39e07d7a175d5da0c1a2ebc905689705571d2084 (commit) via 8c6f990fb600d042ebb7a21996280ef31798bc79 (commit) via 49f8687e1601bacd3386d8393dc831124691715e (commit) via 7731121d66dc2212c67eb9d49840ac846bd00ce7 (commit) via 00750ece6a5dbfd51a8dd789c4d7dc1246f63ec3 (commit) via 708e44af5d445d25cc39e83da800ccc57f90a79a (commit) via 1c97d1df20bbf771568321020e84718b82788272 (commit) via b620772b11fe396194148ec4768bd59ad89fb91f (commit) via 69871e67e3b0612d7df8cc3ecf4a631850935e48 (commit) via 9360e288168b850223285d1fbd695abd33cf26eb (commit) via 8548caa3ee9914f7bd25dba4dadbb1c3a6338253 (commit) via 9d9c68e21a09646816232fa849536ceaca106fc5 (commit) via bb8c96689fe692196e8f77df6d071656b161b47c (commit) via 48180401d321e7fba19ac45e9e2e8a718c20d0b8 (commit) via 4fa858ecb1b40e63c733047f07cc5049f7e2366a (commit) via 273e481e48c855905bde4d91a986c06713df0183 (commit) via 6f024008ce2bdf11bec1ff1174ee68f9a6da6fcb (commit) via ff1a01b743dc70e555fb0fc61eb4d019eb25df76 (commit) via f448364de8cd2cd97933020fe0607d2fef3e1bcd (commit) via 4eadf2ce3f90431fa3ae8a791fde432c6c60b5a1 (commit) via 2e18801a1bf4e313fc2ec25d9a8842312728e1be (commit) via 048aac2cf99061c5fc13a67fb707b064db5c8660 (commit) via c9e220827810d693eefc7a2053bdb7b7de09ccf0 (commit) via 26505dfcb7afd993d0e0622c0904d355f9b2da3f (commit) via fc055c04e1ebab4b3e1f8209f8e4697ccee5a58f (commit) via 9eba41479bc9f60cd810fa1786cb3baf3d570266 (commit) via 693d85f8d62d63ddf860637c69b8b239e7f22ad8 (commit) via 43747ee8b345481d3f669e3df68010dabc15d014 (commit) via 8de8d3b191b020c499fdfdd8df237af95da946cd (commit) via d0283dc1859d61dc2cbdec0c8ee0b00214976c06 (commit) via 2c9667e897f0342c40afa5db5947d87f89e557b1 (commit) via 0f37cd228e9668d981ff75f3e1c63d4f716b7e57 (commit) via 0290bfc35dee73fb534556700554536f1164caaf (commit) via 22f05b1d8c8c52babe62ab44e6f1864aa73164a0 (commit) via 9cf5fe22d0ac51a45d99823820a100ea02ab4305 (commit) via 4beaa926b3f290c10824b2d04cd94fd44a9489d1 (commit) via f72ba42b7c643b1b217d1b8f6684cec3289e7201 (commit) via 45aa03b97aeeb512264ac2bfbb2028330be254d1 (commit) via 3bb2051eef5c3a07f99e9e6549187211758317d6 (commit) via df7fa47c1b42a360158f0b8596d177998fd4fa2d (commit) via d6a1e2b90b40b8947141a1ab6ea4e7c5051d78c5 (commit) via f8a1ba202f51e70510f12f46fe0633ea908d5144 (commit) via 93cc249f3dd7ecd621cd063e4c08bbdb54d971e8 (commit) via 25d7b1ca9d3a160850ad1f147ff96ac7c55f7d9f (commit) via 41f11259317668d53c9712afbb6cbc1580c45681 (commit) via 1b91e010bccaf1c93574c04197fb1e8b75b6c50a (commit) via 7f307d9ea6e77ee6fd7081d464314a64cbf64f32 (commit) via 1b50bd3f5c1f608a84df89c2f5e187a53f0be31d (commit) via d59010e47fa953afb7f638fbab1a65195478d3fa (commit) via 76444957c1978deea8d15b906e733d5e1e33e7db (commit) via f6f42b25c841d807536ec533a5a738d7dd6f02dd (commit) via 8ababa140c13c8a38ac46b2d5feb089b0b3ee25d (commit) via a0adef2bed84b77e81856d75399c913fbc6789dc (commit) via 46609588759e3d84069e3f350feb8ca42560141b (commit) via 0ae4632119ba5300995ec5ddd5513a44bfd2a198 (commit) via 7ecac703cec8bde71f8d11c1a8fa34bfa077edee (commit) via 4e4b786e33cb67250a026efc1bbba6bba8575a07 (commit) via a5a6f61be37bd7fa6997e40ed43b3450834b265e (commit) via 1af67b199a048ed8f02f3b7090ad7d9fdae3e558 (commit) via c45b767a8c2120ba61b9fafa31d8db37a919d62a (commit) via 027ce359ff7454ac0aca4d9a9208759ef4b9c8b7 (commit) via 97c1e569245f655b5701c0b5b38bc1daa19f1750 (commit) via 85c8e652b10f35969dee9ada0784ca70c0f8719c (commit) via 8084f7a6c9d5ed6059d37abde2c5e4a68cb01157 (commit) via 24e29d4190e5ec87021cc11e7bc787b7245bb50b (commit) via ae1a6815b6e2c0a45df51e994b75f9005e1794fe (commit) via 684e4d205d64ff8b98c00a1d6a358bffbf509c62 (commit) via 5dec0a232843d6408ed1a73292126c47a85bd5af (commit) via dd153de4f0c737f75b545b503b330880001135fe (commit) via 738a182a90dd29ce16376ab03a08c718b8068867 (commit) via 6d979ecf266b47796779173c4635a2f0deb38d41 (commit) via 46ff507e4193eca0bd02b9d0835491c99a082788 (commit) via e9bd298a23412bf8110b29ef54cb9fd980ad385a (commit) via f7425c2177e3368ec83e2731cc092dcd2a999d82 (commit) via bd6a269e1acf7f5634d05bb085d9e12cf51e9e35 (commit) via ba946930dd6e1de5aa99123084a5506f7542e3b4 (commit) via dde72ee9439e0f2b77b097b7e49851ce4cd52d11 (commit) via 9b06c22648e992dc135b648ab4039b1b24861be9 (commit) via 66bd8a3cf2f401f5d37bb8eff6da711824adea91 (commit) via debeb07a4005dfe4ea506041f2b2b11ee9bb2d09 (commit) via a178a0d7a6d4783716f485c3ad7eacadff78152e (commit) via 7108d4b73d130d7717f1af5bbaa52b1ea3c43b0f (commit) via 36588f7b162e74130ac2530f57acca263f1141ca (commit) via 5e36feebd4bcf4e7a6025a092fc257a33bbe6dc1 (commit) via 23a63d202417f3d31273041a04b16af2ff361e54 (commit) via 75f2a1e4598c0ecb16537e1b1344b63d69c6b0f6 (commit) via 7b6f6d9e67431cdcdd9a8f1de92c66651768814c (commit) via 6eb78af2bab552523a0c7ec29c632ffd1d145bfe (commit) via 571721c562786ee0996367b590693f82a643fbfb (commit) via 163e8018098699b15f7aef9ded444aa72de49701 (commit) via f2035cbd0d631698ec911e72d0d857fd32d2db7a (commit) via d07d24b8a3c5a8e2cd3898fdd0344c0a1bd095b7 (commit) via a4da6fa71dc0e0e6102d4b72f7abee00ac4e4110 (commit) via 2ed473b3b8e28485e6a14a49c7e0e4133eb02eee (commit) via afe7d5f26d16a76d26ac361d7a41a5119d20dd11 (commit) via 12823faa72f7da8b462e77b0a3fb66ae0e1d8c6e (commit) via 29b37dd97538371ceffb2e1904437e44c46dcbb8 (commit) via a53a2f1e7e786a74c51796fcc6b94937f21ab45d (commit) via 2036639b55fe5a1baaa36145368e7229834d6387 (commit) via 8cdf566bc00da2b1a839a74bdbc99cfbc305bfee (commit) via 32e95a7b24b057e410f0d49fa10a3d05452be264 (commit) via d5ab04f065b85a300c348236519b4c024dd19377 (commit) via 8224545b1db801d6ffeac6424eaf5757416082aa (commit) via 4288708cbad644b26468769e287dfd06b974ced9 (commit) via 996e5237cad257b94c55cb788e8175e474b6696f (commit) via 076aef8e45a91e83f9a7d879712fd70778d67c92 (commit) via 67303794f0bd36912cd9e7e7d0402c3c6fc85a11 (commit) via d23a0196844f066047aa6942b69c6e591462df38 (commit) via 1afbe7d2cca61ecf483f7697b0141a233508603d (commit) via 6938772a114099df406bc72cbc98a3c8d57cd458 (commit) via 8bced8b18de592b572eb5766c7d36d76ea789d09 (commit) via cd5cff13370f6953497484f6e4b04f957fe9c9a7 (commit) via c4d4becf8b79f68534eb8320ccd63218afa4ca31 (commit) via 2599f5d64b6d81967de9ba6f11420ec7815f618d (commit) via 7052af9d4a4e71f52e98a24969c38e8eb86f317b (commit) via d675004dbac12a938cf60fac39e5b9b81bbb6a99 (commit) via cb4bc19ae1b2f61165543ef926037936b179414d (commit) via 59dbd3f891ed79d56df468235c47be3538be734d (commit) via 31e013ae6066067433676c21b8698256404d64f1 (commit) via 62c4cb4b6f0cdb2be2729362133f850d6fe96c20 (commit) via f7c2a803a80d41de41f6b4838d49be2f8bae4afc (commit) via e390991846825799e619e072a28f1da58b7c89ba (commit) via 44c978a2dab96b44ed2dd7470f532c4aa4c7da7c (commit) via 325e452ea2d9b3224ade47eda24e44bf00a8306d (commit) via 9e8f74fbb0148f6aa0a026b8610da6d84bbf0366 (commit) via 2ee5eac3668ebdcb6dc19c95eaadf3a4b120202b (commit) via 839cd16396eec521f0112e4f542fcf347d029620 (commit) via 2f7bafd6dacbe83b881866c0c7a00847ef266382 (commit) via 4838ca14dfe9ee17b2c788b91227d8f7bf733f06 (commit) via a0af10e42371b17daa51646a3123ec5d8a6d0291 (commit) via dd4e25a5a6ed6b6a7019e46d56e6f4c098c61618 (commit) via 9e3164dfa2747bd15c3d3e780875a9b286b765c6 (commit) via 9e07ffa4e4211ca165f24c1f45744fbe7984a43f (commit) via 2f7e05fbc20150377668a4ea1b114fd1b4d92df6 (commit) via 745b56f58c8147aa6015a918f3bfd19abc807b48 (commit) via 0ab9cb4699dbbba808f243c4dc32aebe23a69a34 (commit) via 703d194338039e0231638b1f690748025ecca505 (commit) via 7abb12c826cad6e5847c32d4769c076732581901 (commit) via d3f9f5120c05e4756d7ee1ed81917f74583455a2 (commit) via cbccebbac970e37a772ee06ab766b6cbc085532f (commit) via 4093bd4025e65bdc75254bc7d08a675b10808a22 (commit) via 56c5c8e17aab80fe006d3de064d322dc31e8f25b (commit) via 8a975efc94518c93124d66a7a6626d8ab13f9561 (commit) via d0c14dfb3694d076b8115d64dc317fd686b90aa2 (commit) via 66a709999349b5a7964c2647c41f4759fe2141ee (commit) via 7b4244aceb44aad117dfaccfb2287fbddbe9eca7 (commit) via 9db0dfd75861aeb40433ad8a566c2a5900976659 (commit) via 1b22cb0a07be25bf6b8bf3afc8ffae7c928a90c9 (commit) via 50c3ebb90309d3165b30c243b4047a71eba34f73 (commit) via a8a47098082a57a5b22cac546f030b551e1b9c32 (commit) via 48456535f3c59e19572857d7071d9551783e06d6 (commit) via d040d1647d2192ab97db9b041599c9e224c93553 (commit) via 2cc479bdac84843d0284573cf801ee526e798c54 (commit) via 181e9bb6128c9ad4043c41ef270c79318146e1ad (commit) via b687d2ba093b1b79e9faf09e45d11567b0ec9ac1 (commit) via ed8858edb7c5100e1928c5a94f85485f0e322aa7 (commit) via 8575affa4c72e1c0d07f964d2f28eb6ddbadb291 (commit) via 79443e1b8b604de00d269e73a977f449bc3fcef2 (commit) via 6d51bea4e6ff058383e63c215ec5fb7fcab9870c (commit) via 0f15aee799a0af9fe1999d5c071483c9660ccf5b (commit) via a0ad6fc4dc55541f66534abcf050aaf63c65033f (commit) via 46b6a25adaa3ce4326247263de426399be409a29 (commit) via 53a69c7dd47f693efec85e031b89251dd7bdef2f (commit) via 70b52a7113664b8b74b231d62ff798952d29ae1f (commit) via 7763bd72076357b986daa7e21e4bfe163f58c84a (commit) via 70a2bfe97c1b024bff5fa6b6537528457ca5a7f4 (commit) via a15f51620ba0142e05cfa6aebd346a5cf76ca302 (commit) via 9e57dafd7462c568e0fdce9bd69b61e8700529df (commit) via 6eb654c06e7efbbf27d3be220078561b3e9da968 (commit) via 04029ab47d81eef428b0d2589bf873ea6ffac865 (commit) via 88ecfd8ba122133777bb71b027df3684689d4e3a (commit) via 129c21d260af045b0a9ef16921303c5b37885192 (commit) via 8288d16126193e86bb6880a7d7b749649ad83e2c (commit) via aeff60e44c203dd67b316a6c6eab1454a408e1f7 (commit) via a6fe714eaa6e25c2a661c3ec57f7eb8b8dbadede (commit) via 6d604c4972d744defe783e7a5f9fbf478eee2dfe (commit) via 74a0359ee6ef2aee60a9f9300817e6d9ef87bd57 (commit) via 2420ce88f1cab64b9801b58f3c0c8abf7d615a2b (commit) via de758cfaa1c70e8cfb5666b356e8df96d80ebd18 (commit) via 0ffc4e735a2f954201e0e59c2e14c8dd28cd5985 (commit) via f84a3acd71d4aacd2c553279ab0943d09d83eced (commit) via 460052516fdd06a2c0c765359f4d92006e67283b (commit) via acde2c4a5389bfe5b1af697a02c160060db7d6e8 (commit) via b3193996bd4c87ece760f5f53f2236451605f00a (commit) via 95cfb5457959cb221af60a63a39bc152bb024e58 (commit) via 45d74e9ad32592856852f92471c658256b619e6a (commit) via 1528831bb1330cc539004f9fb3068e871f109d34 (commit) via 029b2096129aeb96bd6352522bca88489fc76352 (commit) via 1748b60a47ec80036c28f874333a5d8ae89ca73e (commit) via 22de879289356ecc68449daa4498a70272a191d4 (commit) via 5562d678a9b11830910a48ca367c9d29684c4f55 (commit) via cdad11c7347c8426f1440ca9a370e1e93e3bf0c8 (commit) via 43f292ab34ea403b3f354b8e2c6fa04b2ff9da7d (commit) via 78db709062e83f862d97db960f5840404f48266e (commit) via 8ee3909ea67e507cfac8bd070e49f98ac3624735 (commit) via e3cd5599a21a122f58787bf56b1f98e7722bae65 (commit) via 5c2100e5c0be11a8dda8694be214a59e15766857 (commit) via 790c0a89de5a06e52a5f71b372e70ed0b36194cd (commit) via 80ebc55a7ce934ee357c30713bcb96b209e97963 (commit) via ce1abfa4149ae0b3920626bef2dd15e8ee8b1940 (commit) via 44de61578130cbd6e0f23057f9cf86f884078a4e (commit) via 4775a99f61ff7982a37432625e37869e436cd1bd (commit) via 0a56e6fe35b89778a7e08a0341d3b08450aebd19 (commit) via c9d142c4e96ad7fbbb7a98c0a9c22f088877519a (commit) via 2469cb5aae79f2ab409744f0ab1ef54d6fac7c2a (commit) via 6e72c8d491afb85cb6cbdea88c4bcbea8e293494 (commit) via 8f5a442408cedb7c60c63f33e1bfeea61fa2d985 (commit) via 17254772215ed3b565c4e1e13059099459bc52df (commit) via 706d05e71ad183b0e07f5f33feda498f04f52fa0 (commit) via c0e223cd2ad78abc698c517004101a3eb48214c4 (commit) via 2dafeacb75e54cfe6c5dc17f253ebdcc61a99e47 (commit) via 427b6da9e5aa2e1a8570259573b1faa15e4169df (commit) via 024451383827969c30f71c5335c66f348193a2d7 (commit) via 25b6e7b710d7739cca44ed19bf45a190e72a6b82 (commit) via 0e9634d2c90fd748774f9238219cb1661550f233 (commit) via e67a59b00d08b426272c86771690782e5cc7f97f (commit) via 8dd3c319c9baa60459df6b368440d8a7f0857580 (commit) via 837d1359ee4d227476154d81de41f4af5ecf2c7c (commit) via f0d50957b9c75963222c084c09295e63a45f08f5 (commit) via ab4a9a98266fb29008cecc9649a91fc844c541f5 (commit) via 451e9f93be4a19f18c4a2ac0a1bd6776ba67c327 (commit) via 572ac897733f0b6fe7baf67006db0e8f182db59c (commit) via 095279bc94c81c4076de20474f1d3dd186764388 (commit) via 338e681c761a77bcaf997844607cca13f11ac0b6 (commit) via 7849424173870379bde31903c0ee644e50f64582 (commit) via e1c410dea3f6062300d59c3343518013b53a18be (commit) via e57ee41370196fbedffe57f878d701d302df9e5d (commit) via 2a663ebce10fb9d393594e28f8ecc870488f6eba (commit) via b6da714af79578bfdcbfe990addc557448b51eea (commit) via af46484bc4d1c928453d10d2daa89b43313484ff (commit) via da0e3f90967bccfa31be347f703d637c52621a64 (commit) via 5ca4abb27f314ce03fc337514c489e67bfcf0ee5 (commit) via a9562eac3ee74b3ed396f2900dfae322186e2ebe (commit) via c9560a9a7b4ff56233008a9622683738765edfa5 (commit) via 7c8f7737fd28d209cb871ac62bbd08ad738e2751 (commit) via 6d0b5ff60d288c7847001c1cb01bd55c78cfe4e6 (commit) via ae4cfa8b12d127d7673c6278eb67acdae6239b4e (commit) via f55fcdc8598be03d0622dd5a7b96d33a6613a296 (commit) via 4790842612b445bc49ee7af4d44f71718e292d48 (commit) via b6f1b1741d3a998deb374609133482daf8c26993 (commit) via 2b7cc7644063778b26e60ab4f07bbfe06b539157 (commit) via 06209c4ce2d75d2e7eff16312d570b7f411e413e (commit) via dadccc752e5e78944af89999112c9a7f8444ffbf (commit) via fcfddc67edbea6f4d2deadfc16e0d2510eee8f63 (commit) via 06ee14f5be17189f920a5fbd5af634f47f80b632 (commit) via 4deaa25f46bbe021648d837a936be64117922157 (commit) via 1d9934a56a36707a9366043042c3aa3e5ae7d86d (commit) via 40bd42dfbcafd572ccd3541f1f84177453c9c255 (commit) via 4cc601f2c5c0fe76fa76f7e4a47d112df7a1c032 (commit) via 7b9131da64b4b569e10ec145fab0c8e22fa69761 (commit) via 9cf5b98d54497b425fe341e4ad5bc188d9fa5445 (commit) via a5e806b3f51d91814d8a39a4bb84363d530874bb (commit) via d038559e49b0d0dd65124370f48a92ba3de9006c (commit) via 43ce4414c479af6b04e93decaf7f69938c92a323 (commit) via 4b316097103e0f30220fd579bce28163d38458bf (commit) via ae05fcc63f37b71cd9b07a2aade03a2a84fa22c4 (commit) via f7c5e970a0b9697ecdb443aecdee87b51e0a5457 (commit) via d95e6dff3cb869d45b27836dc0967ab27872bcdc (commit) via 3d42a72bd5827ea875bbba830ecff90b3aaf54d6 (commit) via 595feb323479ce6e8f8e8a3a863f9286d9f7bd64 (commit) via 96103972ea1c478a2845fb68aee70a3395c148e0 (commit) via 92c865b8f5f0aef1af3ecd33692ce490467c0e70 (commit) via d5b56dd15cd351ce678dc0edf63c72a49ffc5ae3 (commit) via d608cfb6bf6b93add793c64b40787307be10059a (commit) via de7083f3c0bdc9c0af0d35c44afde86aab6d6622 (commit) via 115269a86c3116198f4de7c690fef21ec38767ac (commit) via 5dec403103990f766f458ff79987234e3b945787 (commit) via 5b20d0abfad057d3d6ae7cbae62f564ddb31dd0f (commit) via 489c52ce680df6439f9c1e553cd2925ca8944cb1 (commit) via bbaf24341026cdacd1e313dd3f8e3501e9c4070e (commit) via a92f8d96162b9e6c29ad0bd81b8fd05b387d94a9 (commit) via ec6ce623351ea3fda95dda49a72fc279a63aee87 (commit) via 4f5155f6aba7cb7cd8c0e5b75e43b38a70568eb1 (commit) via aaeee1ca72d4f8b09ebf98c3e3bd73d50c09c0d8 (commit) via bf326ebb7694d2e86fbcfef4cb827c70531c3255 (commit) via ce4ec876ceb73f52055b617374c04dbbbfd2a98d (commit) via f8aac21947f43a0e886a3cc3655514abb95bb260 (commit) via 4a4be0301bd9c6062738e87892cbe5bd8d900a49 (commit) via bfa8831f0219d7c01ff3f434882e2ad941206e96 (commit) via 0120e474a3ff3067faabc6c1e370f8b4f0a733d2 (commit) via f02b67787d89ac5b430558d62b74483eaa03c1b8 (commit) via f636d1e74a5a9d39d2f25b72b26c3d24813a5565 (commit) via cb5dba8eb12eb75a8e66bf9326bfec22f90fda9a (commit) via a9fa60997a0e6438399e2e6e4a9c02f2935b386a (commit) via b4ffd26fd8750989a8aadd626242c314068ba987 (commit) via a57e76301baf95bc4acf9a1ed50e349220b45579 (commit) via 8b33507aba37f7aa8dc1c0d961ba49ef10679449 (commit) via a0b159685ea4383255e46de5456d6a9204457c1f (commit) via 5733d3fbb96a0f48b58b44e5b256ec1978cbbf61 (commit) via 6338652a87c3985188ba94d7eedc84a05563750d (commit) via 8715157c73b243d2e4f7a0dc83a3a91d780a7a0b (commit) via 68a9fc1bca0dab0804d0ca411f933d8e9ec88093 (commit) via 3bb73a051d490f1bc07ef01733b75e260e0dc944 (commit) via f82c2d63ec8e3f5b3650424e19e53bb453b15d8d (commit) via 013193d0b00f5a9db5440b2306548b44cbcfc21c (commit) via ec1d585c43b60a8f9c7b3cb1636e831915b37eb0 (commit) via 4c5b3c1ceaec319163fa26a8e55eb669f11ee8a5 (commit) via d0a9d8bbe60edfb7cf7569fe8162b17bba294182 (commit) via a21f74767c61c36308ede4b35f69a342cb60c129 (commit) via 60939702e1071385ada5d1082b88763cbd1bab56 (commit) via 92f95aede99c76af2ccff09d5b9cc895539332d0 (commit) via c326209fa351ca236778c462bcb0b85f6fa392f7 (commit) via 979e8ba6c6c6ed538b1dd9d60d89d863e7c4273c (commit) via 7a79f7e3c13d3f1c87db40c3230716dcb79d0df9 (commit) via 87584b5e9d4bb3147de4ad2adac2d337be456a62 (commit) via 7fcbd47e955d7e318f1f6dd96cc26d6737525c86 (commit) via c50c32a30f434613a0a46b1c7dbb7eb03d29896d (commit) via 5e428389615da64208c40be256a30f8c9e988523 (commit) via 1f8480312e41b281eccad13a4afcb7c1ef49f22a (commit) via be73273952974e15ed12cf41180162bbbda70da3 (commit) via fd8e6b1edaf451b1a695939fea5548f599eacccb (commit) via de53eb18ab48acbc6db6580473d1e83c73d59bc9 (commit) via 25a76df17f72dcec494b88d2b59a54acbdee9798 (commit) via cd8a57ae9b4e7f811d30e1c5b225d36c7a049429 (commit) via 71180fc8aa1db84260552f494578401e3ddb6a84 (commit) via 3216e94cef3cd4afa558d9adef29921a9330935d (commit) via 5420278dc884c0382f271872b67c33978f3fe6b8 (commit) via d0ff3e701c63caab5a44c48ac70e3ab75af9ee88 (commit) via 9a596b33bbfdb274ccf7f678c78cb8826c7c363b (commit) via 47f91a6183a6bb65a423d5acb1b75c4b39c17a87 (commit) via 465a85fb4615f4cfa20058c534bf3bfe71df1732 (commit) via fc2cb74feedf2637e4b2cc153ede7b0726b9a7d3 (commit) via 0bd333bc2eb6590f939ccabb7caf102f13443600 (commit) via 7189d62c32e6f53dab5637f928917e59055f5e41 (commit) via af7ebf8ad3b2b773dfe636a189a82998b1dc63e1 (commit) via bb01f20e993bbd19b00e07ff0094b155aa0859de (commit) via 31bb727f3b239b541e1ff5679b3c461e9a05f227 (commit) via 53048afa8dc24327d82a1ff0f78801e1f344a4b6 (commit) via 7c09bcfee81ab651e04505d29eb1c5e35fb673ce (commit) via 3cfad71c775e648a8cc9e20726bf4d5ea2f52202 (commit) via 883bd34a1fa31273929c7baf2f43b3c6f5ec0c01 (commit) via 2be9d85af8caddb26936279a2ed9b226e97ea410 (commit) via 3a523eec7814dfbed2361da298849a5b5964318a (commit) via 88f38a2bb42599561e685dfba956866d857fe518 (commit) via 64b5b06dc61db74ef2f994ec4d0f4277113fb49e (commit) via e2565be52c7d80a4993c749282210e5b599cbc32 (commit) via 72190b923bd19bc9f9bddc6958ebb0cec28a5b98 (commit) via 453df662bafe52ec87e0972323cf87ec737f3437 (commit) via 09cda9d5e7bb31f05177bdaf11d24aeaf85a8dd3 (commit) via 95a97a40e48a0db2b206c4560d6962be3666812c (commit) via 773b36e5d4af3ac040625e0ea16bcfd30fcdeb6d (commit) via 25085f41b20f7f5a5fb25e8ab683f77476f917a2 (commit) via d3633731ab423b0627f86f94e6ff5fb932bbe76e (commit) via f725b20be36482f46364f17d18e528b5738d0e6a (commit) via 36f9f0f8a3e7640c12034fff8871b779cba9f0ce (commit) via f18b18b72b8f7f8dc21e350f4dd1c6931cdb389f (commit) via 666bb0e3fa0d212c03f785bd9f6bc05d29925e1f (commit) via 4ec359bd6256e870d9b233fd5cd105e452a62300 (commit) via 049b10e2f621800f0b8da1918784dad7a049d6a8 (commit) via 69bb9f37f9b71a109ef9547af25144e207f116e4 (commit) via 2e620f0b3834e5a612a38d61b7e50a561d7f11e8 (commit) via 48910cf0968a4c5b4ffd9093972498920404685f (commit) via 9df1cb0fa68869f8125025f20fa8c64467aab2e8 (commit) via d568cecf38a6a4b399c925fd3553dd4a273d0af1 (commit) via 0cd654c8e23b19311bae876ada4ad5b432c1ad1b (commit) via bac93dcf192d8680cd72570682d6593da9818088 (commit) via 1e994985d83b09d71b4928a61a75d1cf3861aaec (commit) via 5ae3966d75593b05a9658af8d2fdd47c2bf48a4d (commit) via 443180fb9915eefe0b232875505632ffb9fabb95 (commit) via b34c045736384fc3ba8574b33211bd75082bc07b (commit) via cd0423300bea21a5c0747a6aeaefbae24c10ecd8 (commit) via 228280d8334f2bcac346e5f0d3ea802af7f22862 (commit) via d8e83ab979b0ccfc4887dbf48c088a72dffb2e96 (commit) via f52bcc2ac1b3dddeca2320d8320a9406101c732d (commit) via 80e477239dc3a57f87f9efb7b1d78eb0f0e2b6a3 (commit) via 800a11dc3633b3ec91223c4b53bcc7817e63ad02 (commit) via 7c0e67ee220a5fb7806cb5ef4c80df31f3e34a13 (commit) via 926a22b8b8131347a61681252f9b27644607cb89 (commit) via 28a9e71c527dd4d9159af2a1e83bdd4ff0925cdc (commit) via d6ef59f5a39f9748f44abdba80f596c16b6984a3 (commit) via 1d1f1eeb6a52d464d476eb0a46eb75c452e3dfbc (commit) via 479932fa32115b666be1deea42862673a0c4b608 (commit) via 925e4270fdc5c731c123cb8037607840008f4713 (commit) via 5cb1b345d932d3e0dc34a2d423894a59a6c8db35 (commit) via 1367fccc330b0ff314845aeb3547bbc38486913a (commit) via 798b0adc628ab16dbb4d04ef444b8e7db4f5cffa (commit) via 60d80bca4afcfb3a38b588a5a2060cc275b4afbc (commit) via dec0cfcef012ca762a731d6e096012fa1c072f14 (commit) via a12e148b8a7611d097158bc2acf4ae19ed2c9d18 (commit) via acc2e03d798eeebdecd8198ae8eba495f8ccc5e7 (commit) via 3dd99758d1f912d0edc2df05b6d2cfabd5005efe (commit) via e106a6eafb42dd3c6557e964e04339dcd5787ad4 (commit) via 90e09fb958e761b416863052ca5408ed4280443b (commit) via b902f2a98a6764857f74608250219186f262a207 (commit) via ffe78961ada28f3777066228b4e5870889b42f70 (commit) via 4cb5d3353f488ee7bf3943619e67a5664dbae8df (commit) via 9c507c13a0cffb163a1d56f34c020b5474a3e100 (commit) via 967e9aafda9054a3e963923d14514075225f7792 (commit) via de25d988bccc2d81ce137d763246aadafda336ea (commit) via baead1e2a8ff7938f6be9c5fc01762edddd2ace9 (commit) via 9a8d758c3a27833dccf21102ae753de314684b0d (commit) via df252db15a0e539be255536417f36045301db02c (commit) via 6d5fb0e0d0464d50ae58673bf5543b0d052dc681 (commit) via a34b98a834bf6ac044e8590c3fe644c9307124e9 (commit) via b0996a3fa223370edcdb40a1d8b66d1a3a734daf (commit) via 8b6cc2518a8019314af43a32702a09bff318b777 (commit) via 2d23f7b206c908e55999143487548e2d6a92bc79 (commit) via ab2ae4823c3b60347825da4b851cd4e676f8bed1 (commit) via 316206e2678b64a2c986bcc889e5fbf2fcefad18 (commit) via cea26782c9f626dfe24ef8eed0a65d31d461301b (commit) via b5ad094e3b4496b84b6326b09521c86e9b753385 (commit) via 13bc31aab5c51667369acce3a5ca9d1df57a1611 (commit) via f6b93fbf3ae00a9157af2f6497bed074d585cea9 (commit) via 6a65f0534b7f62ba6fece4b422eaffcdeb3cc535 (commit) via 93f025118d3ecb132658502625707307135535e8 (commit) via ff957bc1e11278b3152c4f4b0732fc9667dc42e3 (commit) via 713424ad207aa0f5e01f8c16b2ee1c442a91893a (commit) via ff11989cc3f11ebaf0584ac4fba44c67222ffbcc (commit) via c88a078d690f72caea53b0723e8393b83f1b0b6f (commit) via 2fb83cc8710898e1fc802b68c9d55c456913719a (commit) via 8444b984a29392c32a13521cc0e3d40788cc9530 (commit) via cfbf857b22540059e6d5a6c271af4aa0314aad7e (commit) via 4c7de5d3940cdf7b648d89642968c95168949182 (commit) via 505f56dc91a94446b907620881f9156c9a9dfc92 (commit) via 357305953600b0de49f0373888c8fe5eb1e7eef4 (commit) via b8c5258b005f5dd677dc324164dbda1be4e403db (commit) via fa4b2e7dc3293510427fa9f9fd96c98209ebfea5 (commit) via 01567fd74f1426ebab2499e5e08d33eff5435f99 (commit) via 9c6cf7fcac1f4f23ec21aeb322026d4f422760cc (commit) via ba28e0405e4a41158395323ace1dd0075934233e (commit) via 9ceef25ee2ebf6315e4c13dfc7102850c2807228 (commit) via e27716bd420679e2958602f43a21be26eb94ffcb (commit) via 311d0376e2312d3539bd997160f880cf58743834 (commit) via 77e78af1a2f10d5ec349d0a46118cddd8ec7a539 (commit) via b9fcd348a703a0fb60d9b2443cd55f96956a5765 (commit) via 098a18c476b5e60b3bacc0e47f23359fc4a3ea2c (commit) via 5214bb354b508cafc859b4a05b4e5f8ed44767e0 (commit) via 602b78aa79f6d99e775fa0a84fb441156d192833 (commit) via c58c739da7287a1cb33558f4e121ecdb23cfadd9 (commit) via 6b90e2850c1bd5df0aab0f1a93ea12f21bb9213f (commit) via cc9987f1ae6319e6641fcfa4cf5997dc7c907948 (commit) via 353f6362baffbcc8750b9ff9649552bf9d555a63 (commit) via f648b9be6347046583ee795f42e39713f248a608 (commit) via e7480d670b9a20bc5d8b17db5a9427fafb212e85 (commit) via 9a58517df4168a5d928b715fcaa96fc24df9b40c (commit) via 1e4bb358946a100ea04bbc97f8195b90b44a5e9c (commit) via ee0f2d23fcf3cd7a67ad8d7bd132a475ed78405f (commit) via 18a966c80feb7459aadbda1e34f2c0a63beb7044 (commit) via f2ff94958f22e36976854ebf97029614e4c460bf (commit) via 891711aaffb150456d83f0698d401f61463d5ced (commit) via 95805d725d49af665c2254f97effbe8b812239ea (commit) via 369d580937b49c1c5672ba3512c2a736581d545c (commit) via a5a3642f9292bb697176aaf1077fc98302f286b7 (commit) via d34ac22fec975a9f5b6b6b37134e1722ffa06025 (commit) via 967dcf36d07ba9b7e40383834906fe1d657456b3 (commit) via c6c8c24908e108b7b3c5c76e29197323ac3a4287 (commit) via 402b133d7b13c691a3d3f3a354bd10eea1ff24f1 (commit) via 8f6fd091b8b2faac52082a5dc854966e70ab3447 (commit) via 6613434376740218fc74950ae5fc2e32baa5fa89 (commit) via fe03a86eb392b5c9a0f551e40b625cefa972e04b (commit) via 0caca40fccead726db6c4d5f5b4ea990958914df (commit) via 5448f0068cc4e228a7481905412fc956e239a827 (commit) via 05e05cd2aae9d00d2ed89a4f0cb9ef2f2976ae80 (commit) via 335a29cb07a8d014a9ed4d4dbf25e49da3a78b33 (commit) via fdd0ce915c0ab7e5a9f3b95612b35d845a7a5213 (commit) via fa15858a7eee3a6feb84bd39b01478c2116ab21e (commit) via 1c8b99ce0b8e3a7a78b029a0cf18dc7256be6aee (commit) via e81c323da9c020c91c967184ecf98f806eb95867 (commit) via 9d203c0051bbec48dfbee90940e6faff87a2bdeb (commit) via 68e7250a9facbe7b82cff17af3bf2a831e481f3c (commit) via 69fc7bf87db33d88af02602fba811b5c5e740a70 (commit) via 584ab5285b51945e0dd523caf77342985ac97ce4 (commit) via e2ed9a70929092ab7b32e036886859e53fbff897 (commit) via 51cfba8c219a923c924349cd255a523eb797e104 (commit) via 53862f04a0002894c0ef5aeb23d52495e5abe60d (commit) via 2a567c68ce6605071f3e21638560493b71ed2841 (commit) via c9108c7b81fecb26924596d55a84fc849125507c (commit) via bdc88646c1336a209d16de14bd23eb436565363d (commit) via 61758bf4b9b5d28cec11d2ea68b9e53ad2769ca6 (commit) via 3062b8a046b24e4c28b374b5c4235bb0da0a2a2c (commit) via 644ff572f736ff04f927661fa5bd2283cd3ee3e1 (commit) via 9430125511865b65e2fa897c59c70414238fbf91 (commit) via 9a399c27a8c6e9a264cbabf9bb3b091b2e74a71f (commit) via c1a520513d4c7504fc9e9e4d9e56acc24569f490 (commit) via c15dc1972839e175afaa9011f74376dadf08277f (commit) via 15aa814b85a90fb8e8798eb99617d27957c28f36 (commit) via 9f1429e274df81344d260c8e42b3387a402940f1 (commit) via 87cc9bfc3c6892c93e10f73421e2b0fdba06b8e9 (commit) via e983bd326a9e3b7902d8f7cf0d891030ad3bd4c1 (commit) via f660832999e086f02a9f3552c028aed900cd7249 (commit) via 92be048b7f40f4ca352bc0ef85c8e1bf4dfc0702 (commit) via c401f95888938562881cd5d7c21ccea5974fe130 (commit) via 21f449214d9bf4c8fa99b3a90029cff2171e3fac (commit) via c1b96fddf835d5faf27698d5a1637bd1507274e0 (commit) via b899c0a92f6833c4996276d86d9e0fb3d42df77c (commit) via 3d5ec790eea47a91c6f70d172c42839db02b8467 (commit) via 1ae2c232b652b69bb7605eae765a86c3bb520b8f (commit) via 1a74e719068c97518d6f9521c86862a17166f32e (commit) via 9a901dc78de32519dae234719370b5330d5564b4 (commit) via aae5a9feb1b07bfae6968f2dfb3b3057a04b3c89 (commit) via 2214011f7b3b13fe7ae0f68f0f9d49af11e12edd (commit) via 7f9a8d53aa8a3595f4f1f2f81607f8df3627642d (commit) via fb0b087c4dc65f18aef431e41de3aa9b91e35371 (commit) via 2169b0faa40a20cd9aae25f9170cca074579a023 (commit) via 9855ebf11a1556bd0b73a1eaec39232842871528 (commit) via af782d021345506bb4e0d1e832a7b77fb8a0b12a (commit) via 569509f4bfbf44c67e237a01f957fdfe52223cfa (commit) via e3770c56a8ef6b20f473556a1ca29ea6e0f51f7f (commit) via 6c9b3b5c03b41842d3d79c1bd80691be7e5c6f89 (commit) via 8483dab8e16b9734ac7d2b90b95d474ce8502e40 (commit) via 4fb70919a57582e4ca7c2a9f6bc4f72b38f9af86 (commit) via 608afd4f62f57fe3f9dcac1e9cc94b8bd1adf9c6 (commit) via 64f9c282f3337335c05a062f341fd5155cade51c (commit) via f69e768d94ff5e0238cbb924836737c4ce11a930 (commit) via 1e555a44aa4e3d40bca2f88915c9f957098e5a55 (commit) via dd7f9d8393b4dfd470335e662bfb94aaf57f93e1 (commit) via e094c8fa0aa3827b0e81660ad5e29d85b216d60f (commit) via 97670dbf2fa567998c26686caa4f03b6f4e78967 (commit) via ac394fddab4c4407c08059eb70f6f2363b3c45fc (commit) via ced77d2bbd07d195f563217bea1930e29472fd4d (commit) via 587ab3221300f04a4de0756dc1a44fa0eac9c0d2 (commit) via 149d49ea7c009f9965d9be91cdac8ee6cd2cfb91 (commit) via 60d73393a50944c1e81472d7e80a458bcb898554 (commit) via 010560be6674def3ce02d05dcf2331230d0c4e91 (commit) via 2d3aa94225e259c9bc1c0d469e6326b476d225c1 (commit) via 7aa9961939f99c915485d86e460b9941f949d59c (commit) via fc7ecd6b0570d91a31221203e4bbaf7e48006662 (commit) via 72dac5365e97f2223037e6d3c37de78328883f32 (commit) via 090c8712435f19d3cb7e23a7ca67ba21313ee0c8 (commit) via a5f4463eedc31f6f552b7f7837212661349898df (commit) via 92c3cab223845ca83533bba7b6d73f6180223935 (commit) via effa6c8343fb871574cb5471de5eb4c1705dd334 (commit) via e10439121e9602f77f80531dd60acc781fba5e79 (commit) via f27492a4db2c56f334b2ca5c746b01b8e9a04995 (commit) via 4f78b9ff2df89d5b4104f92251feb0a7f0976d7f (commit) via 0de6a404aafb497074980eba5144d243b6868d68 (commit) via e6eecec761afd9c1b275d4adebfd08c2e96412fd (commit) via e3587ee01ddf834805e317c21dc87198f443c00e (commit) via e0a84904eb38e145c3a4d4e4ef5d7aceb3c2d196 (commit) via a91eaf387287a201d421e90d78bcae8836cc6042 (commit) via 27be1d815298ebf343823ff99baa35484da92a85 (commit) via 34433c88e259493a22c59558e1ee052251f2c149 (commit) via cde6eb6249cd3211cb3391860221ec32f985e53b (commit) via a9bf981a4c0ee3aece0b162ba7ebc76ad99330eb (commit) via 17d27893e6fdc70a39a35cad468f332f968e44e7 (commit) via 34bcec39c68b82148635cec94a2f7d49d40edf75 (commit) via 2fe3e55d53989c909be595b00a4749b75886accf (commit) via a49751fb2eed0ca6415b243c35b23201b8060597 (commit) via 63d215dfa8373899d0d35f2c28ea0aa7a672be8c (commit) via aa105725152defd75b11a96e27db8b28b9e884a5 (commit) via a08a48c2da1ad0aa760c127511fb96c92d7890af (commit) via c61b6f7f37386eb06bb50d9fc25cb40efe44c9cc (commit) via 1745733809ebb31640b4f9205f2eee96e932e995 (commit) via 050ef26061b6b73cc7c48dd8e7180ee0e7d5c073 (commit) via 674d76538e4f51f89a7a1a3746b32e6d7519568a (commit) via e89fbfaf6626b0693cc597ce4e705d87b8faf996 (commit) via fb461cacba5afe98fd9871d4b8ab0500d825ad5a (commit) via 3a9e92bce1c10e0082d431a61e100485fd6cf270 (commit) via 0060391dffe824526b1f359db79c66c55e53d0c5 (commit) via 5bc964eddbee7936f05ab758c7ac417fffbe4a3e (commit) via 2dc409964858c96125948082a2c488bd573b8269 (commit) via cb40af5d6fa65dae9421280c05934eafc8a66165 (commit) via 1205f75e3bd9e5ff7051459cac4594ea7c3a9bf9 (commit) via 163991dd83cac6afa0f6dfeec41d885e8b880fc8 (commit) via 51f89932c0adccdc28bc3cb6ccf0248a16d897a2 (commit) via 64aa29b7d682c333653ee4720e07914396ec3da7 (commit) via 33a9aaa89b437da29a70f27d25b267242b6f982c (commit) via 96f6fe6b5737494fc560e126b7c797d232d9307e (commit) via a5f0e629887055085eec40da4ad4d147c6887a33 (commit) via 99177a2029fd30d37d49ad2026fb5438f1d07c8f (commit) via cff5112385342fde6dd4fc643265789c3616e414 (commit) via 9519d79b63af5912ecb620ea28079a2341ee0253 (commit) via 086f356f6c83537aeee3ca06ff8db335eee03560 (commit) via e46350ffd98c39cb788aa2fdfbef9753d6089af6 (commit) via 909842fff98983bff8b61c37b11a99d89dcc4d36 (commit) via 19beee46cc6e9b7a05694b29420ad49487648501 (commit) via 188c762f8a5f690708109a3cb8d44693e599adb1 (commit) via 9a2048f1ea6687530e209992c3f5eafcbc02b2a9 (commit) via 248527ed930ea69f9d6953a47b708044c48d5921 (commit) via 274ff520925deea9bf9532673c15b96616521615 (commit) via 69be82394dcd9044c9aa392e0aa078a6e09ec460 (commit) via 5fdee6d402798545280f8dc2955b21d4fe61605c (commit) via 6f7c02ab0ac83fcb23f147a41902d5ac97d4a299 (commit) via 3b6f1587bed536e3d31e6665aff35aa27f5e79bc (commit) via 0cbe2edb23d581233c518beafe92a2c9d4f529ac (commit) via cef59bb8bac6b6d38025cc492235953c5ff7654b (commit) via 0d57b07ad99cefc5df9e65d6c14aeaddf5d64b88 (commit) via c3fb0d95ad114c9f9680e885c4c2263b43c437dc (commit) via 5ebba228823ffc96e82f4b6cc1103c2f2ed8cfa7 (commit) via b59b6dd9d27de7839c7b23a3094db33298038896 (commit) via bdddd4234e977f65ee7df8adcd3888706dfd0dda (commit) via f796e1b6f6984b200453a13e6b8640353ff9488b (commit) via c75a9d660169ddd1e7be57486d3813ca73886b55 (commit) via 46ad0d2183230d1af93242efbdcce20d55514efb (commit) via 2628dec12cb22546d2a21032f53fb0ef096faec8 (commit) via 315b9a31895ca6bb26eba12bff3a0fe9cd37568a (commit) via d5feb5b34cd9f595bf42aa934738b918785e3e87 (commit) via efba22e1deebcfc3924d5f14c026104eb4b62d28 (commit) via b29425f7aafe07eff526f3c7defb317856b72984 (commit) via f009d8f5e2e4007b93494c5d22ba25b41a4872a1 (commit) via 6cd27a853a1c77e5da0a9a14140284a7674cf18c (commit) via 8b0e4795687a2ea289d1313db24d75bcf3cd13bc (commit) via 88016e2e9f13d60c4a0b88fb64ffd802a2d9e534 (commit) via be87cb0c444595fa1970e257031252669c201d3e (commit) via 425cd1670fdd40b752af71e5f28952ae4fcec4ac (commit) via fa9dbc56a15aec71ac2eda7890efd0116797f373 (commit) via 848ae2a663ef83e059561d94b33d551154642231 (commit) via a0a720e6a70133e361762101ce69a0b3f1ab244d (commit) via 637e3f3ee131cf30f7337db06314f4a1af22c245 (commit) via 05251e6d80b03ae14d6a89765f14c2eb10979bd4 (commit) via fbf1721c94b40ea86eeb183a1916f2066eb64bdc (commit) via 390a7d8647c13570dc6416fceb884dc51c8ef6f9 (commit) via e32a6bdd990571bafb8537110128d28a593150b7 (commit) via 7863fba1f6f37db2f75834d0d6a3fbbc680e731c (commit) via 8096682e4edb542a48bbf66c085911db5f00be02 (commit) via 7d57c1a2c926011bc2e4c7a65b802763ec4efbcb (commit) via a55cac4ba475ff61da4146272246512a52247323 (commit) via 705fcf522be16eee03b1757274b23ada6547e6bd (commit) via 1fb6f672bd2bd041edb772b0627278383a00fb62 (commit) via 60b3f216c18aa317656433bcc0b724e6abd8d02f (commit) via aaa5dbbf64392dad518668ac1d046d624dac41f3 (commit) via ac5b80e76c102d43749555c9bc888f9ac9b7436e (commit) via 4bc17345c01ea467099e28c7df30c23ace9e7811 (commit) via 2810e561829b0db36961442f0332939e1b74ccdf (commit) via 834f52a6f41ec5ae8429afa2d374f96458963cf3 (commit) via 7aaed265ade4c3b38967e83095497280a7a55153 (commit) via 0d818632978a450f1afaf687c867e62e885457f7 (commit) via 70e268da3e5f8e00bdf065786cd685a9660fe1c4 (commit) via 47092d3e809be971264a8d5416ff3cb9255f6565 (commit) via 7db671a14374fdbfb8ae87ab9618bca111f4e8a5 (commit) via a8513d8a80dbf654915a3176673e7f7ef544a957 (commit) via d079e71c290c3c55a2db5180953daf014a964c25 (commit) via eb923da2c41ab811a6adec44ef87f3aa8bd26849 (commit) via 02946e0b956061092c2406ed94ab3d9a0beeaffb (commit) via 8b496672fe0ae641bcb45aec04094db9987732bb (commit) via dabd17792215535bdbc0fc5ad032e2a59e7505d2 (commit) via 03622ee2d0947b01a56527ea34cbe43fb9c8eba6 (commit) via f0579e2fda1922f32efbf3e2b160cc004aafd99a (commit) via 4c921e5c7b8170b95ba13c33e0f8ae21dd78055e (commit) via 2f79b22ce049a15e4d4190bbe5e80a3bad9492e8 (commit) via 33cb0173d5ebcde2a8621edaa66f8401133d5cc9 (commit) via 08b9a0fdfa02f50e6ae2aeca1963e8f47d041dd2 (commit) via ca4029fa9aada8e5d86eb81cc5ef9c7e9efe7715 (commit) via 2e242b5c1e6b24e4ed59692b9338e295b792f70e (commit) via 6699d46a2a7f12d35926def3e4db3c7a0a5f7449 (commit) via 39b08858f676f0251898ffc7601ad216bb87ae21 (commit) via ac5c49239051d0caeb57b6a2f66eca5993309f0c (commit) via d61bfcbf47361c2b8d04b56fe189ca33e299aa16 (commit) via 9273eed4040986aef97e73812bb418b946a82fe9 (commit) via 779939a00ebc21419404737f2fc2b34e7775f086 (commit) via 1b592b6458ce033b04ba2aa0ee4cf5ace0fd042c (commit) via 30fe9f024353dcb9799680e1da73d21745a53b3d (commit) via bd74517325fddc0592973f26634c5985490e9d21 (commit) via 2be36b0ab5efe5775aaaa47d659ec984ed014b8d (commit) via 9d0e556904e476d550b6cacfb4e927d63f1b5a37 (commit) via 3b07c58dbdb7fb02b7a61ea4bc3ea78d1bdbea9c (commit) via 0123500309d293103c79ba7485b46152bbe6afbb (commit) via 429cc18fca163a90c7f6c85d932925ea6aef2667 (commit) via ccdc3d300f3f0f3e8492e580a21513b9664c9aca (commit) via 19ffc0729fdc12b8c0874db7ae1c5e576b48ba10 (commit) via 632326a7c762aa039d245a506553c9f06d23cd10 (commit) via 8eb6038d0d98da7f7e04462a72bd2e7529a7baff (commit) via 5380948faec94270f9b799fba6f8b0e7c9ad0899 (commit) via 1aee54ed87f94ceb91fb6c9693160fa41313b7ca (commit) via 24c86e1c3ff5b507815e081f2173bc5b77358e78 (commit) via 6db64ad43202af66270d996775e1504ba676b63d (commit) via d3df00ae5330de935eafd0f315017ae0f89a6968 (commit) via 10160f691c5fa6849a02383d727b30da648aa878 (commit) via 0838d20e506ed6bf064b51f7ef2d026c76b4af3d (commit) via 8f33de92ba4fc152b0e2b63008732ce0ad4ba18c (commit) via 2fb8e5b1c46ea586233b19e612ba174aa74d004c (commit) via d9190f3308fb67f01f061038a06006af73a77da1 (commit) via 656ebaca3be50e92edca3d9628b784f5ff1e6a99 (commit) via 4134030434ea88024ef46f9f00b19513fc3cec4c (commit) via f03d446e967af91460ff31eb52d840983b3d8cec (commit) via 3444105f9fe4fcee390c8d616e1a211a078a630b (commit) via 77c4202edc242c96087295585a85a20700bdb26f (commit) via 09b6cc66b09b9689ca01faee5e33ef101b46f972 (commit) via 0c978063259fb013856b617d680cebcdee51ab1a (commit) via 0152a01f11fc46f645fd765cc7b1be76cc07b52a (commit) via 011e6870e4a7f19476c162a8c011fd018d9a7e9c (commit) via cbca80f3516d7e5b2def6105a1b26b44bad7b6fe (commit) via d48f69d0f5f265d1c091a614098cae3ff4325fbe (commit) via ff8e321c6ade784b3f1b3b19a7783788872e44a9 (commit) via 80f57e67eefc905a726f2f35bd1672a188ea4c99 (commit) via 7ef834682547df5e0ccdcd503558dcbf1206a638 (commit) via 69295812065a5d07c07347add2fdcf8f36f993ba (commit) via 5b361fdda0f2808f0368b746a880981ebda0ade0 (commit) via 2e5d1990f382aa42e8a0ad34117ee1e5a9187153 (commit) via b3701f9a5213f2ff5b2bc197e9af5d1f2ff68a9c (commit) via 06b71ff9fb41369e6dce0c2b9760d2d546d47dec (commit) via 1e6aaefdeebbf09eaf7fa0e9dbc6a7faa2f9132a (commit) via ea533eb71516a92e1528e358ffa374b16864eac6 (commit) via 8fe948c54cd0a7a06b5c56e8a40dab945c5a08e7 (commit) via 9c7fc00a45b6f0891c95fba707b0e2ce9d2e2dbf (commit) via 211e3223a6f96800b5c7187a58715a8e1e081869 (commit) via e8cdbec45e757352580476a329f4998074d1b10a (commit) via d3f1fcf6d19d4f4384861b4f342b632d249e1449 (commit) via 19d4f942fe5fe2d84e9fc1f6abe9c237f6dceeec (commit) via ce002921344cceb42801d088ab82fcf8f21964da (commit) via c637e0c53b5b81d6605018bd64ea2769f356662a (commit) via fbc1b75c2692d82f729359b0aeec7ad959662d54 (commit) via 3d0e95f64c996d3d54b387f7688f988dd843ac6a (commit) via e3c5aed6ae1b0dcdde51f5baea7f150395d21d9f (commit) via 326d5fa74781d807b9ecc2feed1b433657c3a92b (commit) via 7d45db99563c83a1a85722b1ee0f1fe10f8967d3 (commit) via a28b8f95bca8ac99c811fe24cd1e291330a1cd28 (commit) via 66c6144cdafcae83fe4c36a4355a67aa69198809 (commit) via b6a174d2bcd5d64cff7a54a4744fe2b5811d6f9e (commit) via d0faa58a51114a97f3af6a951b6c4052ca19c9ee (commit) via 2a49d86d5dec66f7696bd7063459f504cc336a5e (commit) via b0301db23b12351720993a351fedf081ca0fa444 (commit) via 267e02097e90d05a16ffd1aa53fb7910b79aa0ec (commit) via 009019f2596de08c488588fd2c67a423f9fe92bf (commit) via 378849f41e574e72c577b549dfc2d5333ca8f9b5 (commit) via 4a3c49b4698f0e8c20c345770f551142088a3037 (commit) via 785bfae867de0ad18463d618d45b4ae8c2712934 (commit) via cc5e6b82c2ae8293a400b604e0366578f9097d94 (commit) via 8312fd5c1f82d5acc600c9d796ff99620cbbd3e1 (commit) via a1cfc4fe3deed4d642773d0ae63dd524c3f2eba1 (commit) via 4079ba20d9d9c8d15fd28d9440d56c907dda811c (commit) via 17ab8e33f005aab3e493ac4535f63b6f229aacab (commit) via d9fde87d1a3a4de382d664bd121af957af6eaaea (commit) via d92c160db333bf65e52da1cb73a068b5d3f1db4f (commit) via 7edfcd0e834a4dc8d3da9cada6ad6b9b46dfb4dd (commit) via 6c8dc7f1df6d3492d11ad994a35ee2f0b8a4e60b (commit) via 1efca9f427a5c537afc034aadf0c29073bfdfa22 (commit) via d9b5f0a301c23c2c0e56ad3fcb696de71c3d6365 (commit) via 1c70c6cc09f0f8be087db2aeae5ee6a3f1b47bda (commit) via 2b7baed719e4a6eb918ed6f22ee6031a40b7f316 (commit) via 7ba954925a876f4c753a4296236bc7d2f18eb0b8 (commit) via 6d98b15fc8b9a065325e3683afe94efce17dd162 (commit) via 869037ee86d1c0ab757840adf499ea270d4301e1 (commit) via 2f6462a634726d9d0ea8d8552454839d67183016 (commit) via 148b83a12185d7611ff7576464087430c3f2719c (commit) via 4457a9f181663701961dc209740974f48213e6e7 (commit) via 4d039c5b46e3cac29ff1d9ce3e768af1bca6b69a (commit) via c8ec8d6a7ec6c176bc14e7026dc755a9be8689cb (commit) via 3e8d47d18b4db6b4621ee5e4864dde234ad8a282 (commit) via 3b4895fa35e4a96022abd99b07002a7d2ab3a968 (commit) via 2232e97a6ed4a338b814d1ba3d62a7ffa9ef6e7f (commit) via 9a1d4e4ba170f4ac34c80593bd2fe8e1481a1181 (commit) via 8391b3015a82909828b7ada98e76d45aa11b892b (commit) via 7f90d5e5ccfa862ebd99bd79632cc9351fe2ee19 (commit) via 7a1e542ed7065ab300af11f5cb4cfe465de2e5e6 (commit) via b4fab15fc75e4ad62ece05dc9a37bd87e807ba9b (commit) via cb5cadf3c79bf2d80dbd1e2f5602ed709fe25ef5 (commit) via bb8cf5215680efe76f8197d52aa2620a8e939895 (commit) via 758f58b4a18fbb512edd1baf520017e816fee20b (commit) via 9c4d105680c99e194c6d6063315ee2affd2a7b63 (commit) via 89b03498ef0005778260f4734e3102e8a5463ff0 (commit) via f7fc93281b81d0ae824f0ef4dbaae3ea5e9fb6a0 (commit) via 9e7f9bbf56b5d9201da0cc5b360555101c6c6a36 (commit) via fadb812a52bbf14c7b4850e6a5fdd81405d8b5f5 (commit) via ea563a27a2042cfb3be33d0f74efecc7687b86bb (commit) via 36e07e10176866c2ad07a58fd3ac30de81e0909d (commit) via 5553e330dc2015ec5b9f8e6573d9b58928bcb9e3 (commit) via 0f1fedbd6a298cf9af2f36577cc66c4ee167be3d (commit) via 15762b72b456998ac0f87ceec750a20e9872f325 (commit) via cd4f573ae9f4ded1cb386698f90c7ccf1504f094 (commit) via b8b1d15186b33ec598b1126169856184805b3e6f (commit) via 8c61544bb7ea017158e37e78cbbdbc943931824d (commit) via 7f1cd3280cf484b5d565a12ae57022de018faa57 (commit) via 2597bcf831dae6a0a7a212607ea4b926ec6b10e0 (commit) via 20e62f74c5a030a25fe1c3a6c835d67eea152d8f (commit) via fd93b3605bc931b5ce2386816973e106fa1ec646 (commit) via 1365e18b9b5ddfb5bc13da5bcdefeb566be12f08 (commit) via 1ed5f6b39b80ab337551f1fa9601b3257ddd4be7 (commit) via 8377d9e00b7a00f1687b947aaf3c9e10b6779df4 (commit) via 00173b71d97f81cc9db9b573998bd4359aa2c25b (commit) via d5911ef014fcffd14d397759ca638519733a48ad (commit) via c3264f48c2960325b9141d3ec58c6b49afe120c9 (commit) via 52168f3210ca07a8d80991958d588789c2693d63 (commit) via 5213f8936fd5a70e1f38939e5d1894e7fabb9e02 (commit) via b61c268bd04425597e2e9c5f213dea3cdad3cb19 (commit) via e278f5a84806a2b228182dc4a2cc98a1eaa19f8c (commit) via 51bc6bddb91283da25d098492c9cc1b50e3008fc (commit) via 8e0c1599a1015cf80c4db35d108509986236b756 (commit) via 72eb6a374ed12cfa0dee0ce1930a4dcd8473c700 (commit) via 66c4d0820ca86b0b119303859f3dae0f7c560969 (commit) via c666f8cbc6cb81b0729e116890c70096fd2101ac (commit) via f00214aa4f8036951a926efd7dc3891d47abce49 (commit) via bb1d3370cedceec48c82a523cf35df2207c7db17 (commit) via b2cf1cba07633a242d5d13f694609a505c6a6235 (commit) via 6e634e387fd3a31e19fb6af48a1f09999a2ddd64 (commit) via 45e13c8be8266789d2dfbf002f5282d86465d493 (commit) via 1aaace3e54e5da05b68f246899e125e4ba1ce29e (commit) via b12affd78578247678ca25e1b9711625c6c60268 (commit) via 22605f1e230a187658c57df22b66e1b1ade09a4a (commit) via aa57f35ff539a1d43d93e373048f70ce7fd04852 (commit) via 38642f4fb78be70e84390947b1052994b8debd98 (commit) via 62e33fcd08a08bf4a1835ab7bd98650150800978 (commit) via 730ba30726c8dd36cd48fa3259385587a4aa48f8 (commit) via 4376e47a2fdcf5d0c966df983a4205dce8147ff1 (commit) via 9203691f09341077365da6386ab8561a4ee51a8b (commit) via 241858c5e6750dfdc8cc9dfcbc82a39735ba04af (commit) via 4787330730a222103f40c65e5cae4cba28bca204 (commit) via 5385817762e636ae27717891892786294749aee2 (commit) via 834efe12bf6bf8059e545ac496eeb390c08e4220 (commit) via 05d802a77ef94452e8b89c1bf3412c78f0e86c97 (commit) via dc6d8066607435a0d4b6338bc53e0b1ac746bd35 (commit) via 484dc1e5d85f4f468e27816eab0fccc9c7d6ec11 (commit) via 63d19ec83f5f66dbb4aedc037d433aedd9d034bb (commit) via 0c09a6ab1dc8cc5556aa3ccb852d5146ed8e2424 (commit) via 7e6b88fc2f8549ebc75006603a4add98125af7b2 (commit) from 35413bf2c1b33980afd418030af27f184872af6b (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- Summary of changes: .hooks-config | 10 + .hooks-config.bash | 9 - Auxiliary/CMakeLists.txt | 2 +- Auxiliary/vim/syntax/cmake.vim | 6 +- CMakeCPack.cmake | 392 +- CMakeCPackOptions.cmake.in | 60 +- CMakeLists.txt | 115 +- CTestCustom.cmake.in | 6 +- Copyright.txt | 4 +- Help/command/add_custom_command.rst | 11 +- Help/command/add_custom_target.rst | 9 + Help/command/add_library.rst | 2 +- Help/command/ctest_memcheck.rst | 8 +- Help/command/ctest_submit.rst | 8 +- Help/command/execute_process.rst | 16 +- Help/command/file.rst | 13 +- Help/command/install.rst | 6 +- Help/command/source_group.rst | 18 +- Help/command/string.rst | 34 +- Help/command/target_link_libraries.rst | 5 + Help/command/try_compile.rst | 36 +- Help/generator/CodeBlocks.rst | 3 + Help/generator/VS_TOOLSET_HOST_ARCH.txt | 10 + Help/generator/Visual Studio 10 2010.rst | 7 + Help/generator/Visual Studio 11 2012.rst | 7 + Help/generator/Visual Studio 12 2013.rst | 9 + Help/generator/Visual Studio 14 2015.rst | 9 + Help/generator/Visual Studio 15 2017.rst | 9 + Help/generator/Xcode.rst | 7 + Help/manual/OPTIONS_BUILD.txt | 11 +- Help/manual/cmake-buildsystem.7.rst | 2 + Help/manual/cmake-compile-features.7.rst | 45 +- Help/manual/cmake-developer.7.rst | 2 +- Help/manual/cmake-generator-expressions.7.rst | 2 + Help/manual/cmake-modules.7.rst | 1 + Help/manual/cmake-packages.7.rst | 4 +- Help/manual/cmake-policies.7.rst | 8 + Help/manual/cmake-properties.7.rst | 23 + Help/manual/cmake-qt.7.rst | 32 +- Help/manual/cmake-variables.7.rst | 9 + Help/module/CPackIFWConfigureFile.rst | 1 + Help/policy/CMP0067.rst | 37 + Help/prop_gbl/AUTOGEN_TARGETS_FOLDER.rst | 2 +- Help/prop_gbl/AUTOMOC_TARGETS_FOLDER.rst | 2 +- Help/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.rst | 12 + Help/prop_gbl/CMAKE_C_KNOWN_FEATURES.rst | 9 + .../XCODE_EMIT_EFFECTIVE_PLATFORM_NAME.rst | 24 + Help/prop_sf/COMPILE_FLAGS.rst | 7 + Help/prop_sf/SKIP_AUTOGEN.rst | 8 + Help/prop_sf/SKIP_AUTOMOC.rst | 6 + Help/prop_sf/SKIP_AUTORCC.rst | 6 + Help/prop_sf/SKIP_AUTOUIC.rst | 6 + Help/prop_sf/VS_COPY_TO_OUT_DIR.rst | 6 + Help/prop_sf/VS_INCLUDE_IN_VSIX.rst | 6 + Help/prop_sf/VS_RESOURCE_GENERATOR.rst | 8 + Help/prop_test/TIMEOUT_AFTER_MATCH.rst | 4 +- Help/prop_tgt/AUTOGEN_TARGET_DEPENDS.rst | 8 +- Help/prop_tgt/AUTOMOC.rst | 16 +- Help/prop_tgt/AUTORCC.rst | 3 + Help/prop_tgt/AUTOUIC.rst | 3 + Help/prop_tgt/BUILD_RPATH.rst | 10 + Help/prop_tgt/CUDA_EXTENSIONS.rst | 17 + Help/prop_tgt/CUDA_SEPARABLE_COMPILATION.rst | 13 + Help/prop_tgt/CUDA_STANDARD.rst | 32 + Help/prop_tgt/CUDA_STANDARD_REQUIRED.rst | 18 + Help/prop_tgt/CXX_STANDARD.rst | 2 +- Help/prop_tgt/FRAMEWORK.rst | 4 +- Help/prop_tgt/IMPORTED_LIBNAME.rst | 23 + Help/prop_tgt/IMPORTED_LIBNAME_CONFIG.rst | 7 + Help/prop_tgt/LANG_CPPLINT.rst | 13 + Help/prop_tgt/MANUALLY_ADDED_DEPENDENCIES.rst | 8 + Help/prop_tgt/MAP_IMPORTED_CONFIG_CONFIG.rst | 22 +- Help/prop_tgt/VS_DEBUGGER_WORKING_DIRECTORY.rst | 6 + Help/prop_tgt/VS_DOTNET_REFERENCES_COPY_LOCAL.rst | 7 + Help/prop_tgt/VS_DOTNET_REFERENCE_refname.rst | 12 + Help/prop_tgt/VS_USER_PROPS.rst | 12 + Help/prop_tgt/XCODE_EXPLICIT_FILE_TYPE.rst | 8 + Help/prop_tgt/XCODE_PRODUCT_TYPE.rst | 8 + Help/release/3.8.rst | 421 ++ Help/release/index.rst | 1 + Help/variable/CMAKE_BUILD_RPATH.rst | 10 + Help/variable/CMAKE_CL_64.rst | 5 +- Help/variable/CMAKE_CUDA_EXTENSIONS.rst | 11 + Help/variable/CMAKE_CUDA_STANDARD.rst | 11 + Help/variable/CMAKE_CUDA_STANDARD_REQUIRED.rst | 11 + Help/variable/CMAKE_DL_LIBS.rst | 2 +- Help/variable/CMAKE_LANG_COMPILER_ID.rst | 1 + Help/variable/CMAKE_LANG_CPPLINT.rst | 6 + Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst | 2 + .../variable/CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS.rst | 25 + .../CMAKE_SUBLIME_TEXT_2_EXCLUDE_BUILD_TREE.rst | 7 + .../CMAKE_VS_INCLUDE_PACKAGE_TO_DEFAULT_BUILD.rst | 8 + ...CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE.rst | 10 + Help/variable/CTEST_MEMORYCHECK_TYPE.rst | 2 +- Modules/AndroidTestUtilities.cmake | 17 +- .../AndroidTestUtilities/PushToAndroidDevice.cmake | 6 +- Modules/AutogenInfo.cmake.in | 18 +- Modules/BundleUtilities.cmake | 58 +- Modules/CMakeAddFortranSubdirectory.cmake | 1 - Modules/CMakeCSharpCompiler.cmake.in | 9 + Modules/CMakeCSharpCompilerId.cs.in | 63 + Modules/CMakeCSharpInformation.cmake | 119 + Modules/CMakeCUDACompiler.cmake.in | 25 + Modules/CMakeCUDACompilerABI.cu | 16 + Modules/CMakeCUDACompilerId.cu.in | 50 + Modules/CMakeCUDAInformation.cmake | 200 + Modules/CMakeCXXCompiler.cmake.in | 1 + Modules/CMakeCXXCompilerId.cpp.in | 4 +- Modules/CMakeCompilerIdDetection.cmake | 9 +- Modules/CMakeDetermineASMCompiler.cmake | 8 +- Modules/CMakeDetermineCSharpCompiler.cmake | 43 + Modules/CMakeDetermineCUDACompiler.cmake | 162 + Modules/CMakeDetermineCompileFeatures.cmake | 6 + Modules/CMakeDetermineCompilerId.cmake | 22 +- Modules/CMakeExpandImportedTargets.cmake | 3 - Modules/CMakeFindBinUtils.cmake | 1 + Modules/CMakeGraphVizOptions.cmake | 13 +- Modules/CMakePackageConfigHelpers.cmake | 3 - Modules/CMakeParseImplicitLinkInfo.cmake | 15 + Modules/CMakePrintHelpers.cmake | 2 - Modules/CMakeTestCSharpCompiler.cmake | 64 + Modules/CMakeTestCUDACompiler.cmake | 76 + Modules/CPack.STGZ_Header.sh.in | 5 +- Modules/CPack.cmake | 4 +- Modules/CPackDeb.cmake | 15 +- Modules/CPackIFW.cmake | 179 +- Modules/CPackIFWConfigureFile.cmake | 65 + Modules/CPackProductBuild.cmake | 20 + Modules/CPackRPM.cmake | 361 +- Modules/CTestCoverageCollectGCOV.cmake | 1 - Modules/CTestUseLaunchers.cmake | 4 +- Modules/CheckFunctionExists.c | 2 +- Modules/CheckFunctionExists.cmake | 30 +- Modules/Compiler/AppleClang-C.cmake | 12 +- Modules/Compiler/AppleClang-CXX.cmake | 21 +- Modules/Compiler/Clang-C.cmake | 12 +- Modules/Compiler/Clang-CXX-FeatureTests.cmake | 3 +- Modules/Compiler/Clang-CXX.cmake | 26 +- ...ompiler.cmake => GNU-C-DetermineCompiler.cmake} | 0 Modules/Compiler/GNU-C-FeatureTests.cmake | 10 +- Modules/Compiler/GNU-C.cmake | 23 +- Modules/Compiler/GNU-CXX-DetermineCompiler.cmake | 15 + Modules/Compiler/GNU-CXX.cmake | 24 +- Modules/Compiler/Intel-C-FeatureTests.cmake | 9 +- Modules/Compiler/Intel-C.cmake | 28 +- Modules/Compiler/Intel-CXX-FeatureTests.cmake | 67 +- Modules/Compiler/Intel-CXX.cmake | 51 +- Modules/Compiler/MSVC-CXX.cmake | 10 +- Modules/Compiler/NVIDIA-CUDA.cmake | 28 + Modules/Compiler/NVIDIA-DetermineCompiler.cmake | 17 + Modules/Compiler/PGI-Fortran.cmake | 3 + Modules/Compiler/SunPro-CXX.cmake | 12 +- Modules/CompilerId/VS-10.csproj.in | 55 + Modules/CompilerId/VS-10.vcxproj.in | 3 + Modules/ExternalData.cmake | 119 +- Modules/ExternalProject.cmake | 215 +- Modules/FeatureSummary.cmake | 331 +- Modules/FindALSA.cmake | 2 - Modules/FindASPELL.cmake | 2 - Modules/FindAVIFile.cmake | 2 - Modules/FindArmadillo.cmake | 7 - Modules/FindBISON.cmake | 4 - Modules/FindBZip2.cmake | 2 - Modules/FindBoost.cmake | 48 +- Modules/FindBullet.cmake | 2 - Modules/FindCUDA/select_compute_arch.cmake | 20 +- Modules/FindCURL.cmake | 2 - Modules/FindCoin3D.cmake | 4 - Modules/FindCurses.cmake | 2 - Modules/FindDart.cmake | 2 - Modules/FindDevIL.cmake | 4 +- Modules/FindEXPAT.cmake | 2 - Modules/FindFLEX.cmake | 4 - Modules/FindFreetype.cmake | 3 - Modules/FindGIF.cmake | 2 - Modules/FindGSL.cmake | 3 +- Modules/FindGTK2.cmake | 84 +- Modules/FindGTest.cmake | 14 +- Modules/FindGettext.cmake | 2 - Modules/FindGit.cmake | 5 +- Modules/FindGnuTLS.cmake | 3 - Modules/FindGnuplot.cmake | 3 - Modules/FindHDF5.cmake | 193 +- Modules/FindHSPELL.cmake | 3 - Modules/FindHg.cmake | 2 - Modules/FindICU.cmake | 1 + Modules/FindIcotool.cmake | 2 - Modules/FindJPEG.cmake | 2 - Modules/FindJasper.cmake | 2 - Modules/FindJava.cmake | 9 +- Modules/FindLATEX.cmake | 1 - Modules/FindLTTngUST.cmake | 2 - Modules/FindLibArchive.cmake | 8 +- Modules/FindLibXml2.cmake | 2 - Modules/FindLua.cmake | 23 +- Modules/FindMPEG.cmake | 2 - Modules/FindMPEG2.cmake | 3 - Modules/FindMPI.cmake | 18 +- Modules/FindMotif.cmake | 3 - Modules/FindOpenAL.cmake | 2 - Modules/FindOpenGL.cmake | 61 +- Modules/FindOpenSSL.cmake | 13 +- Modules/FindOpenSceneGraph.cmake | 1 - Modules/FindPNG.cmake | 4 +- Modules/FindPackageHandleStandardArgs.cmake | 1 - Modules/FindPerl.cmake | 2 - Modules/FindPerlLibs.cmake | 2 - Modules/FindPhysFS.cmake | 3 - Modules/FindPkgConfig.cmake | 8 +- Modules/FindProtobuf.cmake | 2 +- Modules/FindPythonInterp.cmake | 2 - Modules/FindPythonLibs.cmake | 27 +- Modules/FindQuickTime.cmake | 2 - Modules/FindSDL.cmake | 14 +- Modules/FindSDL_sound.cmake | 7 +- Modules/FindSquish.cmake | 3 - Modules/FindTCL.cmake | 2 - Modules/FindTIFF.cmake | 2 - Modules/FindTclsh.cmake | 2 - Modules/FindWget.cmake | 4 +- Modules/FindZLIB.cmake | 2 - Modules/FortranCInterface.cmake | 3 +- Modules/FortranCInterface/CMakeLists.txt | 3 + Modules/FortranCInterface/Detect.cmake | 3 +- Modules/GNUInstallDirs.cmake | 130 +- Modules/GenerateExportHeader.cmake | 1 - Modules/GetPrerequisites.cmake | 20 +- Modules/InstallRequiredSystemLibraries.cmake | 32 +- Modules/Internal/FeatureTesting.cmake | 12 +- Modules/Platform/Android-Clang-ASM.cmake | 2 + Modules/Platform/Android-Clang.cmake | 4 +- Modules/Platform/Android-Common.cmake | 9 + Modules/Platform/Android/ndk-stl-c++.cmake | 5 +- Modules/Platform/Darwin-PGI-C.cmake | 2 + Modules/Platform/Darwin-PGI-CXX.cmake | 2 + Modules/Platform/Darwin-PGI-Fortran.cmake | 2 + Modules/Platform/Darwin-PGI.cmake | 14 + Modules/Platform/Darwin.cmake | 2 - Modules/Platform/Fuchsia.cmake | 25 + Modules/Platform/Windows-MSVC.cmake | 6 +- Modules/Platform/Windows-NVIDIA-CUDA.cmake | 42 + Modules/Platform/Windows.cmake | 1 + Modules/Qt4Macros.cmake | 2 +- Modules/UseJava.cmake | 2 - Modules/UseSWIG.cmake | 81 +- Modules/WriteBasicConfigVersionFile.cmake | 2 - Modules/WriteCompilerDetectionHeader.cmake | 130 +- Packaging/QtSDK/ToolsCMakeXX.cmake | 45 + Packaging/QtSDK/qt.tools.cmake.xx.qs.in | 48 + Source/.gitattributes | 15 +- Source/CMakeInstallDestinations.cmake | 8 +- Source/CMakeLists.txt | 317 +- Source/CMakeVersion.cmake | 6 +- Source/CPack/IFW/cmCPackIFWGenerator.h | 1 - Source/CPack/IFW/cmCPackIFWInstaller.cxx | 137 +- Source/CPack/IFW/cmCPackIFWInstaller.h | 25 + Source/CPack/IFW/cmCPackIFWPackage.cxx | 256 +- Source/CPack/IFW/cmCPackIFWPackage.h | 14 + Source/CPack/IFW/cmCPackIFWRepository.cxx | 2 +- Source/CPack/OSXScriptLauncher.cxx | 4 +- Source/CPack/WiX/cmCPackWIXGenerator.cxx | 8 +- Source/CPack/WiX/cmWIXRichTextFormatWriter.h | 3 +- Source/CPack/WiX/cmWIXSourceWriter.cxx | 41 +- Source/CPack/WiX/cmWIXSourceWriter.h | 2 - Source/CPack/cmCPack7zGenerator.h | 1 - Source/CPack/cmCPackArchiveGenerator.h | 3 +- Source/CPack/cmCPackBundleGenerator.cxx | 5 +- Source/CPack/cmCPackBundleGenerator.h | 4 + Source/CPack/cmCPackDebGenerator.cxx | 6 +- Source/CPack/cmCPackDebGenerator.h | 1 - Source/CPack/cmCPackDragNDropGenerator.cxx | 4 +- Source/CPack/cmCPackDragNDropGenerator.h | 6 + Source/CPack/cmCPackGenerator.cxx | 34 +- Source/CPack/cmCPackGenerator.h | 32 +- Source/CPack/cmCPackGeneratorFactory.cxx | 12 +- Source/CPack/cmCPackGeneratorFactory.h | 11 +- Source/CPack/cmCPackLog.cxx | 7 +- Source/CPack/cmCPackLog.h | 23 +- Source/CPack/cmCPackNSISGenerator.cxx | 12 +- Source/CPack/cmCPackNSISGenerator.h | 1 - Source/CPack/cmCPackOSXX11Generator.cxx | 11 +- Source/CPack/cmCPackOSXX11Generator.h | 3 + Source/CPack/cmCPackPKGGenerator.cxx | 11 +- Source/CPack/cmCPackPKGGenerator.h | 7 +- Source/CPack/cmCPackPackageMakerGenerator.cxx | 18 +- Source/CPack/cmCPackPackageMakerGenerator.h | 3 + Source/CPack/cmCPackProductBuildGenerator.cxx | 33 +- Source/CPack/cmCPackProductBuildGenerator.h | 4 + Source/CPack/cmCPackRPMGenerator.cxx | 256 +- Source/CPack/cmCPackRPMGenerator.h | 1 - Source/CPack/cmCPackSTGZGenerator.cxx | 8 +- Source/CPack/cmCPackSTGZGenerator.h | 1 - Source/CPack/cmCPackTGZGenerator.h | 1 - Source/CPack/cmCPackTXZGenerator.h | 1 - Source/CPack/cmCPackTarBZip2Generator.h | 1 - Source/CPack/cmCPackTarCompressGenerator.h | 1 - Source/CPack/cmCPackZIPGenerator.h | 1 - Source/CPack/cpack.cxx | 35 +- Source/CTest/cmCTestBuildAndTestHandler.h | 3 +- Source/CTest/cmCTestBuildCommand.h | 3 - Source/CTest/cmCTestBuildHandler.cxx | 27 +- Source/CTest/cmCTestBuildHandler.h | 10 +- Source/CTest/cmCTestCommand.h | 2 - Source/CTest/cmCTestConfigureCommand.cxx | 4 + Source/CTest/cmCTestConfigureCommand.h | 3 - Source/CTest/cmCTestConfigureHandler.h | 3 +- Source/CTest/cmCTestCoverageCommand.h | 3 +- Source/CTest/cmCTestCoverageHandler.cxx | 12 +- Source/CTest/cmCTestCoverageHandler.h | 3 +- Source/CTest/cmCTestCurl.cxx | 46 +- Source/CTest/cmCTestCurl.h | 2 + Source/CTest/cmCTestEmptyBinaryDirectoryCommand.h | 3 - Source/CTest/cmCTestGIT.cxx | 30 +- Source/CTest/cmCTestGenericHandler.cxx | 7 +- Source/CTest/cmCTestGenericHandler.h | 13 +- Source/CTest/cmCTestHandlerCommand.cxx | 5 + Source/CTest/cmCTestHandlerCommand.h | 5 +- Source/CTest/cmCTestLaunch.cxx | 56 +- Source/CTest/cmCTestMemCheckCommand.cxx | 23 + Source/CTest/cmCTestMemCheckCommand.h | 13 +- Source/CTest/cmCTestMemCheckHandler.cxx | 90 +- Source/CTest/cmCTestMemCheckHandler.h | 7 +- Source/CTest/cmCTestMultiProcessHandler.cxx | 2 +- Source/CTest/cmCTestReadCustomFilesCommand.h | 3 - Source/CTest/cmCTestRunScriptCommand.h | 3 - Source/CTest/cmCTestRunTest.cxx | 9 +- Source/CTest/cmCTestRunTest.h | 4 +- Source/CTest/cmCTestScriptHandler.cxx | 22 +- Source/CTest/cmCTestScriptHandler.h | 3 +- Source/CTest/cmCTestSleepCommand.h | 3 - Source/CTest/cmCTestStartCommand.h | 3 - Source/CTest/cmCTestSubmitCommand.cxx | 29 +- Source/CTest/cmCTestSubmitCommand.h | 3 +- Source/CTest/cmCTestSubmitHandler.cxx | 181 +- Source/CTest/cmCTestSubmitHandler.h | 3 +- Source/CTest/cmCTestTestCommand.h | 3 - Source/CTest/cmCTestTestHandler.cxx | 170 +- Source/CTest/cmCTestTestHandler.h | 3 +- Source/CTest/cmCTestUpdateCommand.h | 3 - Source/CTest/cmCTestUpdateHandler.h | 3 +- Source/CTest/cmCTestUploadCommand.cxx | 5 +- Source/CTest/cmCTestUploadCommand.h | 3 +- Source/CTest/cmCTestUploadHandler.h | 3 +- Source/CTest/cmCTestVC.cxx | 9 +- Source/CTest/cmCTestVC.h | 11 +- Source/CTest/cmParseCoberturaCoverage.cxx | 2 +- Source/CTest/cmProcess.cxx | 11 +- Source/CursesDialog/ccmake.cxx | 6 +- Source/CursesDialog/cmCursesBoolWidget.cxx | 4 +- .../CursesDialog/cmCursesCacheEntryComposite.cxx | 11 +- Source/CursesDialog/cmCursesDummyWidget.cxx | 4 +- Source/CursesDialog/cmCursesFilePathWidget.cxx | 4 +- Source/CursesDialog/cmCursesMainForm.cxx | 129 +- Source/CursesDialog/cmCursesMainForm.h | 4 +- Source/CursesDialog/cmCursesOptionsWidget.cxx | 4 +- Source/CursesDialog/cmCursesPathWidget.cxx | 6 +- Source/CursesDialog/cmCursesStringWidget.cxx | 8 +- Source/CursesDialog/cmCursesWidget.cxx | 4 +- Source/CursesDialog/cmCursesWidget.h | 6 +- Source/Modules/FindLibRHash.cmake | 73 + Source/QtDialog/AddCacheEntry.cxx | 2 +- Source/QtDialog/CMakeSetup.cxx | 4 +- Source/QtDialog/FirstConfigure.cxx | 2 +- Source/QtDialog/QCMake.cxx | 26 +- Source/QtDialog/RegexExplorer.cxx | 34 +- Source/QtDialog/RegexExplorer.h | 1 + Source/QtDialog/RegexExplorer.ui | 37 +- Source/QtIFW/CMake.DeveloperReference.HTML.qs.in | 4 +- Source/QtIFW/CMake.Dialogs.QtGUI.qs | 21 - Source/QtIFW/CMake.Dialogs.QtGUI.qs.in | 21 + Source/QtIFW/CMake.Documentation.SphinxHTML.qs.in | 4 +- Source/QtIFW/CMake.qs.in | 10 +- Source/QtIFW/installscript.qs.in | 12 +- Source/bindexplib.cxx | 3 +- Source/bindexplib.h | 5 +- Source/cmAddCompileOptionsCommand.cxx | 4 + Source/cmAddCompileOptionsCommand.h | 8 +- Source/cmAddCustomCommandCommand.cxx | 21 +- Source/cmAddCustomCommandCommand.h | 8 +- Source/cmAddCustomTargetCommand.cxx | 25 +- Source/cmAddCustomTargetCommand.h | 8 +- Source/cmAddDefinitionsCommand.cxx | 4 + Source/cmAddDefinitionsCommand.h | 8 +- Source/cmAddDependenciesCommand.cxx | 8 +- Source/cmAddDependenciesCommand.h | 8 +- Source/cmAddExecutableCommand.cxx | 20 +- Source/cmAddExecutableCommand.h | 8 +- Source/cmAddLibraryCommand.cxx | 80 +- Source/cmAddLibraryCommand.h | 8 +- Source/cmAddSubDirectoryCommand.cxx | 8 + Source/cmAddSubDirectoryCommand.h | 8 +- Source/cmAddTestCommand.cxx | 6 +- Source/cmAddTestCommand.h | 8 +- Source/cmAlgorithms.h | 22 +- Source/cmAuxSourceDirectoryCommand.cxx | 14 +- Source/cmAuxSourceDirectoryCommand.h | 8 +- Source/cmBootstrapCommands1.cxx | 87 - Source/cmBootstrapCommands2.cxx | 94 - Source/cmBreakCommand.cxx | 5 + Source/cmBreakCommand.h | 8 +- Source/cmBuildCommand.cxx | 13 +- Source/cmBuildCommand.h | 8 +- Source/cmBuildNameCommand.cxx | 12 +- Source/cmBuildNameCommand.h | 7 +- Source/cmCMakeHostSystemInformationCommand.cxx | 7 + Source/cmCMakeHostSystemInformationCommand.h | 12 +- Source/cmCMakeMinimumRequired.cxx | 8 + Source/cmCMakeMinimumRequired.h | 8 +- Source/cmCMakePolicyCommand.cxx | 12 +- Source/cmCMakePolicyCommand.h | 8 +- Source/cmCPluginAPI.cxx | 75 +- Source/cmCTest.cxx | 171 +- Source/cmCTest.h | 26 +- Source/cmCacheManager.cxx | 45 +- Source/cmCacheManager.h | 25 +- Source/cmCallVisualStudioMacro.cxx | 2 + Source/cmCallVisualStudioMacro.h | 2 +- Source/cmCommand.cxx | 54 + Source/cmCommand.h | 95 +- Source/cmCommandArgumentLexer.cxx | 1783 ++++---- Source/cmCommandArgumentLexer.h | 144 +- Source/cmCommandArgumentLexer.in.l | 36 +- Source/cmCommandArgumentsHelper.h | 6 +- Source/cmCommands.cxx | 241 ++ Source/cmCommands.cxx.in | 10 - Source/cmCommands.h | 10 +- Source/cmCommandsForBootstrap.cxx | 7 - Source/cmCommonTargetGenerator.cxx | 45 +- Source/cmCommonTargetGenerator.h | 8 +- Source/cmComputeLinkDepends.cxx | 6 +- Source/cmComputeLinkInformation.cxx | 58 +- Source/cmComputeLinkInformation.h | 1 + Source/cmComputeTargetDepends.cxx | 21 +- Source/cmConditionEvaluator.cxx | 26 +- Source/cmConditionEvaluator.h | 12 +- Source/cmConfigure.cmake.h.in | 1 - Source/cmConfigureFileCommand.cxx | 8 +- Source/cmConfigureFileCommand.h | 9 +- Source/cmContinueCommand.cxx | 5 + Source/cmContinueCommand.h | 8 +- Source/cmConvertMSBuildXMLToJSON.py | 453 ++ Source/cmCoreTryCompile.cxx | 367 +- Source/cmCoreTryCompile.h | 14 +- Source/cmCreateTestSourceList.cxx | 6 + Source/cmCreateTestSourceList.h | 9 +- Source/cmCryptoHash.cxx | 113 +- Source/cmCryptoHash.h | 74 +- Source/cmCustomCommand.cxx | 12 + Source/cmCustomCommand.h | 5 + Source/cmCustomCommandGenerator.cxx | 77 +- Source/cmCustomCommandGenerator.h | 6 +- Source/cmDefinePropertyCommand.cxx | 7 +- Source/cmDefinePropertyCommand.h | 8 +- Source/cmDefinitions.cxx | 1 + Source/cmDefinitions.h | 25 +- Source/cmDependsC.cxx | 11 +- Source/cmDependsFortran.cxx | 61 +- Source/cmDependsFortran.h | 3 + Source/cmDependsJavaLexer.cxx | 2255 +++++----- Source/cmDependsJavaLexer.h | 201 +- Source/cmDependsJavaLexer.in.l | 30 +- Source/cmDependsJavaParserHelper.cxx | 4 +- Source/cmDependsJavaParserHelper.h | 2 + Source/cmDocumentationFormatter.cxx | 2 +- Source/cmELF.cxx | 224 +- Source/cmELF.h | 23 +- Source/cmElseCommand.cxx | 12 - Source/cmElseCommand.h | 41 - Source/cmElseIfCommand.cxx | 11 - Source/cmElseIfCommand.h | 41 - Source/cmEnableLanguageCommand.cxx | 4 + Source/cmEnableLanguageCommand.h | 8 +- Source/cmEnableTestingCommand.cxx | 4 + Source/cmEnableTestingCommand.h | 8 +- Source/cmEndForEachCommand.cxx | 12 - Source/cmEndForEachCommand.h | 51 - Source/cmEndFunctionCommand.cxx | 12 - Source/cmEndFunctionCommand.h | 51 - Source/cmEndIfCommand.cxx | 19 - Source/cmEndIfCommand.h | 41 - Source/cmEndMacroCommand.cxx | 12 - Source/cmEndMacroCommand.h | 51 - Source/cmEndWhileCommand.cxx | 18 - Source/cmEndWhileCommand.h | 51 - Source/cmExecProgramCommand.cxx | 22 +- Source/cmExecProgramCommand.h | 13 +- Source/cmExecuteProcessCommand.cxx | 42 +- Source/cmExecuteProcessCommand.h | 8 +- Source/cmExecutionStatus.h | 4 - Source/cmExpandedCommandArgument.h | 4 +- Source/cmExportBuildAndroidMKGenerator.cxx | 44 +- Source/cmExportBuildAndroidMKGenerator.h | 10 +- Source/cmExportBuildFileGenerator.cxx | 10 +- Source/cmExportCommand.cxx | 22 +- Source/cmExportCommand.h | 9 +- Source/cmExportFileGenerator.cxx | 20 +- Source/cmExportInstallAndroidMKGenerator.cxx | 19 +- Source/cmExportInstallAndroidMKGenerator.h | 10 +- Source/cmExportInstallFileGenerator.cxx | 8 +- Source/cmExportLibraryDependenciesCommand.cxx | 20 +- Source/cmExportLibraryDependenciesCommand.h | 7 +- Source/cmExportTryCompileFileGenerator.cxx | 4 +- Source/cmExprLexer.cxx | 1976 ++++----- Source/cmExprLexer.h | 193 +- Source/cmExprLexer.in.l | 24 +- Source/cmExprParser.cxx | 1768 ++++---- Source/cmExprParser.y | 157 +- Source/cmExprParserTokens.h | 94 +- Source/cmExtraCodeBlocksGenerator.cxx | 59 +- Source/cmExtraCodeLiteGenerator.cxx | 103 +- Source/cmExtraCodeLiteGenerator.h | 12 +- Source/cmExtraEclipseCDT4Generator.cxx | 61 +- Source/cmExtraKateGenerator.cxx | 16 +- Source/cmExtraSublimeTextGenerator.cxx | 99 +- Source/cmExtraSublimeTextGenerator.h | 3 + Source/cmFLTKWrapUICommand.cxx | 14 +- Source/cmFLTKWrapUICommand.h | 9 +- Source/cmFileCommand.cxx | 142 +- Source/cmFileCommand.h | 8 +- Source/cmFileMonitor.cxx | 11 +- Source/cmFileMonitor.h | 2 +- Source/cmFilePathChecksum.cxx | 88 + Source/cmFilePathChecksum.h | 65 + Source/cmFilePathUuid.cxx | 118 - Source/cmFilePathUuid.h | 69 - Source/cmFileTimeComparison.cxx | 35 +- Source/cmFindBase.cxx | 13 +- Source/cmFindBase.h | 6 +- Source/cmFindCommon.cxx | 6 +- Source/cmFindCommon.h | 10 +- Source/cmFindFileCommand.cxx | 2 - Source/cmFindFileCommand.h | 7 +- Source/cmFindLibraryCommand.cxx | 20 +- Source/cmFindLibraryCommand.h | 9 +- Source/cmFindPackageCommand.cxx | 51 +- Source/cmFindPackageCommand.h | 13 +- Source/cmFindPathCommand.cxx | 17 +- Source/cmFindPathCommand.h | 8 +- Source/cmFindProgramCommand.cxx | 16 +- Source/cmFindProgramCommand.h | 9 +- Source/cmForEachCommand.cxx | 10 +- Source/cmForEachCommand.h | 10 +- Source/cmFortranLexer.cxx | 183 +- Source/cmFortranLexer.h | 13 +- Source/cmFortranLexer.in.l | 10 +- Source/cmFortranParserImpl.cxx | 10 +- Source/cmFunctionBlocker.h | 7 +- Source/cmFunctionCommand.cxx | 18 +- Source/cmFunctionCommand.h | 11 +- Source/cmGeneratedFileStream.cxx | 24 +- Source/cmGeneratedFileStream.h | 7 +- Source/cmGeneratorExpression.cxx | 10 +- Source/cmGeneratorExpressionDAGChecker.cxx | 5 +- Source/cmGeneratorExpressionEvaluationFile.cxx | 11 +- Source/cmGeneratorExpressionEvaluationFile.h | 13 +- Source/cmGeneratorExpressionEvaluator.h | 6 +- Source/cmGeneratorExpressionNode.cxx | 50 +- Source/cmGeneratorExpressionParser.cxx | 4 +- Source/cmGeneratorTarget.cxx | 384 +- Source/cmGeneratorTarget.h | 23 +- Source/cmGetCMakePropertyCommand.cxx | 6 +- Source/cmGetCMakePropertyCommand.h | 8 +- Source/cmGetDirectoryPropertyCommand.cxx | 6 + Source/cmGetDirectoryPropertyCommand.h | 8 +- Source/cmGetFilenameComponentCommand.cxx | 16 +- Source/cmGetFilenameComponentCommand.h | 8 +- Source/cmGetPropertyCommand.cxx | 27 +- Source/cmGetPropertyCommand.h | 8 +- Source/cmGetSourceFilePropertyCommand.cxx | 3 + Source/cmGetSourceFilePropertyCommand.h | 8 +- Source/cmGetTargetPropertyCommand.cxx | 23 +- Source/cmGetTargetPropertyCommand.h | 8 +- Source/cmGetTestPropertyCommand.cxx | 4 +- Source/cmGetTestPropertyCommand.h | 8 +- Source/cmGhsMultiGpj.h | 2 - Source/cmGhsMultiTargetGenerator.cxx | 25 +- Source/cmGlobalBorlandMakefileGenerator.cxx | 2 + Source/cmGlobalGenerator.cxx | 135 +- Source/cmGlobalGenerator.h | 70 +- Source/cmGlobalGeneratorFactory.h | 7 +- Source/cmGlobalGhsMultiGenerator.cxx | 15 +- Source/cmGlobalGhsMultiGenerator.h | 2 +- Source/cmGlobalJOMMakefileGenerator.cxx | 2 + Source/cmGlobalKdevelopGenerator.cxx | 4 +- Source/cmGlobalMSYSMakefileGenerator.cxx | 5 +- Source/cmGlobalMinGWMakefileGenerator.cxx | 2 + Source/cmGlobalNMakeMakefileGenerator.cxx | 2 + Source/cmGlobalNMakeMakefileGenerator.h | 6 + Source/cmGlobalNinjaGenerator.cxx | 125 +- Source/cmGlobalNinjaGenerator.h | 38 +- Source/cmGlobalUnixMakefileGenerator3.cxx | 102 +- Source/cmGlobalUnixMakefileGenerator3.h | 14 +- Source/cmGlobalVisualStudio10Generator.cxx | 139 +- Source/cmGlobalVisualStudio10Generator.h | 23 +- Source/cmGlobalVisualStudio11Generator.cxx | 18 +- Source/cmGlobalVisualStudio11Generator.h | 13 +- Source/cmGlobalVisualStudio12Generator.cxx | 28 + Source/cmGlobalVisualStudio12Generator.h | 12 + Source/cmGlobalVisualStudio14Generator.cxx | 13 + Source/cmGlobalVisualStudio14Generator.h | 9 + Source/cmGlobalVisualStudio15Generator.cxx | 61 +- Source/cmGlobalVisualStudio15Generator.h | 13 + Source/cmGlobalVisualStudio71Generator.cxx | 9 +- Source/cmGlobalVisualStudio71Generator.h | 2 +- Source/cmGlobalVisualStudio7Generator.cxx | 69 +- Source/cmGlobalVisualStudio7Generator.h | 4 +- Source/cmGlobalVisualStudio8Generator.cxx | 26 +- Source/cmGlobalVisualStudio8Generator.h | 7 +- Source/cmGlobalVisualStudio9Generator.cxx | 3 +- Source/cmGlobalVisualStudioGenerator.cxx | 58 +- Source/cmGlobalVisualStudioGenerator.h | 20 +- Source/cmGlobalXCodeGenerator.cxx | 272 +- Source/cmGlobalXCodeGenerator.h | 74 +- Source/cmGraphAdjacencyList.h | 4 +- Source/cmGraphVizWriter.cxx | 29 +- Source/cmGraphVizWriter.h | 4 +- Source/cmHexFileConverter.cxx | 5 +- Source/cmHexFileConverter.h | 4 - Source/cmIDEOptions.cxx | 7 +- Source/cmIDEOptions.h | 6 +- Source/cmIfCommand.cxx | 14 +- Source/cmIfCommand.h | 12 +- Source/cmIncludeCommand.cxx | 14 +- Source/cmIncludeCommand.h | 8 +- Source/cmIncludeDirectoryCommand.cxx | 8 + Source/cmIncludeDirectoryCommand.h | 8 +- Source/cmIncludeExternalMSProjectCommand.cxx | 15 +- Source/cmIncludeExternalMSProjectCommand.h | 8 +- Source/cmIncludeRegularExpressionCommand.cxx | 4 + Source/cmIncludeRegularExpressionCommand.h | 8 +- Source/cmInstallCommand.cxx | 88 +- Source/cmInstallCommand.h | 8 +- Source/cmInstallCommandArguments.cxx | 2 + Source/cmInstallCommandArguments.h | 5 +- Source/cmInstallFilesCommand.cxx | 7 + Source/cmInstallFilesCommand.h | 8 +- Source/cmInstallProgramsCommand.cxx | 8 + Source/cmInstallProgramsCommand.h | 8 +- Source/cmInstallTargetGenerator.cxx | 62 +- Source/cmInstallTargetsCommand.cxx | 9 + Source/cmInstallTargetsCommand.h | 8 +- Source/cmLinkDirectoriesCommand.cxx | 9 + Source/cmLinkDirectoriesCommand.h | 8 +- Source/cmLinkItem.h | 8 + Source/cmLinkLibrariesCommand.cxx | 11 +- Source/cmLinkLibrariesCommand.h | 8 +- Source/cmLinkLineComputer.cxx | 192 + Source/cmLinkLineComputer.h | 58 + Source/cmLinkLineDeviceComputer.cxx | 80 + Source/cmLinkLineDeviceComputer.h | 39 + Source/cmLinkedTree.h | 4 +- Source/cmListCommand.cxx | 18 +- Source/cmListCommand.h | 8 +- Source/cmListFileCache.cxx | 7 +- Source/cmListFileCache.h | 12 +- Source/cmListFileLexer.c | 203 +- Source/cmListFileLexer.h | 2 +- Source/cmListFileLexer.in.l | 15 +- Source/cmLoadCacheCommand.cxx | 10 +- Source/cmLoadCacheCommand.h | 9 +- Source/cmLoadCommandCommand.cxx | 23 +- Source/cmLoadCommandCommand.h | 7 +- Source/cmLocalCommonGenerator.cxx | 5 +- Source/cmLocalCommonGenerator.h | 5 +- Source/cmLocalGenerator.cxx | 733 +--- Source/cmLocalGenerator.h | 104 +- Source/cmLocalGhsMultiGenerator.cxx | 2 +- Source/cmLocalNinjaGenerator.cxx | 70 +- Source/cmLocalNinjaGenerator.h | 22 +- Source/cmLocalUnixMakefileGenerator3.cxx | 120 +- Source/cmLocalUnixMakefileGenerator3.h | 3 + Source/cmLocalVisualStudio10Generator.cxx | 4 +- Source/cmLocalVisualStudio10Generator.h | 7 + Source/cmLocalVisualStudio7Generator.cxx | 89 +- Source/cmLocalVisualStudio7Generator.h | 17 +- Source/cmLocalVisualStudioGenerator.cxx | 4 +- Source/cmLocalVisualStudioGenerator.h | 16 +- Source/cmLocalXCodeGenerator.cxx | 5 +- Source/cmLocalXCodeGenerator.h | 9 + Source/cmLocale.h | 7 +- Source/cmMSVC60LinkLineComputer.cxx | 42 + Source/cmMSVC60LinkLineComputer.h | 26 + Source/cmMachO.cxx | 6 +- Source/cmMachO.h | 5 + Source/cmMacroCommand.cxx | 18 +- Source/cmMacroCommand.h | 11 +- Source/cmMakeDirectoryCommand.cxx | 5 + Source/cmMakeDirectoryCommand.h | 8 +- Source/cmMakefile.cxx | 333 +- Source/cmMakefile.h | 105 +- Source/cmMakefileExecutableTargetGenerator.cxx | 314 +- Source/cmMakefileExecutableTargetGenerator.h | 4 + Source/cmMakefileLibraryTargetGenerator.cxx | 422 +- Source/cmMakefileLibraryTargetGenerator.h | 6 + Source/cmMakefileTargetGenerator.cxx | 301 +- Source/cmMakefileTargetGenerator.h | 23 +- Source/cmMakefileUtilityTargetGenerator.cxx | 12 +- Source/cmMarkAsAdvancedCommand.cxx | 10 +- Source/cmMarkAsAdvancedCommand.h | 8 +- Source/cmMathCommand.cxx | 5 + Source/cmMathCommand.h | 8 +- Source/cmMessageCommand.cxx | 6 + Source/cmMessageCommand.h | 8 +- Source/cmNinjaLinkLineComputer.cxx | 23 + Source/cmNinjaLinkLineComputer.h | 31 + Source/cmNinjaNormalTargetGenerator.cxx | 481 ++- Source/cmNinjaNormalTargetGenerator.h | 10 + Source/cmNinjaTargetGenerator.cxx | 146 +- Source/cmNinjaTypes.h | 6 +- Source/cmNinjaUtilityTargetGenerator.cxx | 4 +- Source/cmObject.h | 41 - Source/cmOptionCommand.cxx | 12 +- Source/cmOptionCommand.h | 8 +- Source/cmOutputConverter.cxx | 111 +- Source/cmOutputConverter.h | 48 +- Source/cmOutputRequiredFilesCommand.cxx | 34 +- Source/cmOutputRequiredFilesCommand.h | 8 +- Source/cmParseArgumentsCommand.cxx | 11 + Source/cmParseArgumentsCommand.h | 8 +- Source/cmPathLabel.cxx | 2 + Source/cmPathLabel.h | 4 +- Source/cmPolicies.cxx | 3 +- Source/cmPolicies.h | 5 +- Source/cmProcessOutput.cxx | 173 + Source/cmProcessOutput.h | 88 + Source/cmProcessTools.cxx | 23 +- Source/cmProcessTools.h | 5 +- Source/cmProjectCommand.cxx | 18 +- Source/cmProjectCommand.h | 8 +- Source/cmQTWrapCPPCommand.cxx | 9 +- Source/cmQTWrapCPPCommand.h | 8 +- Source/cmQTWrapUICommand.cxx | 9 +- Source/cmQTWrapUICommand.h | 7 +- Source/cmQtAutoGeneratorInitializer.cxx | 528 +-- Source/cmQtAutoGenerators.cxx | 1700 ++++---- Source/cmQtAutoGenerators.h | 152 +- Source/cmRemoveCommand.cxx | 5 + Source/cmRemoveCommand.h | 8 +- Source/cmRemoveDefinitionsCommand.cxx | 4 + Source/cmRemoveDefinitionsCommand.h | 8 +- Source/cmReturnCommand.cxx | 2 + Source/cmReturnCommand.h | 8 +- Source/cmRulePlaceholderExpander.cxx | 308 ++ Source/cmRulePlaceholderExpander.h | 81 + Source/cmSearchPath.cxx | 6 + Source/cmSearchPath.h | 4 +- Source/cmSeparateArgumentsCommand.cxx | 8 + Source/cmSeparateArgumentsCommand.h | 8 +- Source/cmServer.cxx | 1 + Source/cmServerConnection.cxx | 1 + Source/cmServerProtocol.cxx | 67 +- Source/cmSetCommand.cxx | 19 +- Source/cmSetCommand.h | 8 +- Source/cmSetDirectoryPropertiesCommand.cxx | 4 +- Source/cmSetDirectoryPropertiesCommand.h | 9 +- Source/cmSetPropertyCommand.cxx | 19 +- Source/cmSetPropertyCommand.h | 13 +- Source/cmSetSourceFilesPropertiesCommand.cxx | 4 + Source/cmSetSourceFilesPropertiesCommand.h | 9 +- Source/cmSetTargetPropertiesCommand.cxx | 7 +- Source/cmSetTargetPropertiesCommand.h | 9 +- Source/cmSetTestsPropertiesCommand.cxx | 6 +- Source/cmSetTestsPropertiesCommand.h | 9 +- Source/cmSiteNameCommand.cxx | 9 +- Source/cmSiteNameCommand.h | 8 +- Source/cmSourceFile.cxx | 4 +- Source/cmSourceGroupCommand.cxx | 175 +- Source/cmSourceGroupCommand.h | 12 +- Source/cmStandardIncludes.h | 1 - Source/cmStandardLexer.h | 26 +- Source/cmState.cxx | 1147 +----- Source/cmState.h | 245 +- Source/cmStateDirectory.cxx | 528 +++ Source/cmStateDirectory.h | 83 + Source/cmStatePrivate.h | 101 + Source/cmStateSnapshot.cxx | 427 ++ Source/cmStateSnapshot.h | 88 + Source/cmStateTypes.h | 55 + Source/cmStringCommand.cxx | 29 +- Source/cmStringCommand.h | 11 +- Source/cmSubdirCommand.cxx | 11 +- Source/cmSubdirCommand.h | 8 +- Source/cmSubdirDependsCommand.cxx | 4 + Source/cmSubdirDependsCommand.h | 7 +- Source/cmSystemTools.cxx | 129 +- Source/cmSystemTools.h | 11 +- Source/cmTarget.cxx | 741 ++-- Source/cmTarget.h | 70 +- Source/cmTargetCompileDefinitionsCommand.cxx | 7 + Source/cmTargetCompileDefinitionsCommand.h | 10 +- Source/cmTargetCompileFeaturesCommand.cxx | 7 + Source/cmTargetCompileFeaturesCommand.h | 10 +- Source/cmTargetCompileOptionsCommand.cxx | 8 + Source/cmTargetCompileOptionsCommand.h | 10 +- Source/cmTargetDepend.h | 4 +- Source/cmTargetExport.h | 6 +- Source/cmTargetIncludeDirectoriesCommand.cxx | 10 + Source/cmTargetIncludeDirectoriesCommand.h | 10 +- Source/cmTargetLinkLibrariesCommand.cxx | 53 +- Source/cmTargetLinkLibrariesCommand.h | 10 +- Source/cmTargetPropCommandBase.cxx | 18 +- Source/cmTargetPropCommandBase.h | 7 +- Source/cmTargetPropertyComputer.cxx | 92 + Source/cmTargetPropertyComputer.h | 110 + Source/cmTargetSourcesCommand.cxx | 9 +- Source/cmTargetSourcesCommand.h | 10 +- Source/cmTestGenerator.cxx | 13 +- Source/cmTimestamp.cxx | 20 +- Source/cmTimestamp.h | 4 +- Source/cmTryCompileCommand.cxx | 5 + Source/cmTryCompileCommand.h | 9 +- Source/cmTryRunCommand.cxx | 27 +- Source/cmTryRunCommand.h | 9 +- Source/cmTypeMacro.h | 31 - Source/cmUnexpectedCommand.cxx | 22 + Source/cmUnexpectedCommand.h | 40 + Source/cmUnsetCommand.cxx | 8 + Source/cmUnsetCommand.h | 8 +- Source/cmUseMangledMesaCommand.cxx | 9 +- Source/cmUseMangledMesaCommand.h | 7 +- Source/cmUtilitySourceCommand.cxx | 14 +- Source/cmUtilitySourceCommand.h | 7 +- Source/cmUuid.cxx | 31 +- Source/cmVS10CSharpFlagTable.h | 120 + Source/cmVS11CSharpFlagTable.h | 120 + Source/cmVS12CSharpFlagTable.h | 120 + Source/cmVS140CSharpFlagTable.h | 120 + Source/cmVS141CSharpFlagTable.h | 120 + Source/cmVSSetupHelper.cxx | 366 ++ Source/cmVSSetupHelper.h | 154 + Source/cmVariableRequiresCommand.cxx | 5 + Source/cmVariableRequiresCommand.h | 7 +- Source/cmVariableWatchCommand.cxx | 7 + Source/cmVariableWatchCommand.h | 9 +- Source/cmVisualStudio10TargetGenerator.cxx | 1148 ++++-- Source/cmVisualStudio10TargetGenerator.h | 52 +- Source/cmVisualStudio10ToolsetOptions.cxx | 159 + Source/cmVisualStudio10ToolsetOptions.h | 37 + Source/cmVisualStudioGeneratorOptions.cxx | 23 +- Source/cmVisualStudioGeneratorOptions.h | 14 +- Source/cmVisualStudioSlnData.h | 4 +- Source/cmVisualStudioSlnParser.h | 6 +- Source/cmVisualStudioWCEPlatformParser.h | 5 +- Source/cmWhileCommand.cxx | 6 + Source/cmWhileCommand.h | 10 +- Source/cmWriteFileCommand.cxx | 7 +- Source/cmWriteFileCommand.h | 8 +- Source/cmXCode21Object.cxx | 3 + Source/cmXCode21Object.h | 5 + Source/cmXCodeObject.cxx | 5 +- Source/cmXCodeObject.h | 9 +- Source/cm_codecvt.cxx | 215 + Source/cm_codecvt.hxx | 58 + Source/cm_sha2.c | 1613 -------- Source/cm_sha2.h | 140 - Source/cm_sha2_mangle.h | 42 - Source/cm_unordered_map.hxx | 25 + Source/cm_unordered_set.hxx | 25 + Source/cmake.cxx | 260 +- Source/cmake.h | 32 +- Source/cmakemain.cxx | 19 +- Source/cmakexbuild.cxx | 9 +- Source/cmcldeps.cxx | 11 +- Source/cmcmd.cxx | 179 +- Source/ctest.cxx | 14 +- Source/kwsys/.gitattributes | 4 +- Source/kwsys/Base64.c | 218 +- Source/kwsys/Base64.h.in | 82 +- Source/kwsys/CMakeLists.txt | 44 +- Source/kwsys/CONTRIBUTING.rst | 38 +- Source/kwsys/CTestConfig.cmake | 14 +- Source/kwsys/CommandLineArguments.cxx | 786 ++-- Source/kwsys/CommandLineArguments.hxx.in | 133 +- Source/kwsys/Configure.h.in | 167 +- Source/kwsys/Configure.hxx.in | 29 +- Source/kwsys/ConsoleBuf.hxx.in | 650 +-- Source/kwsys/Copyright.txt | 17 +- Source/kwsys/Directory.cxx | 140 +- Source/kwsys/Directory.hxx.in | 23 +- Source/kwsys/DynamicLoader.cxx | 363 +- Source/kwsys/DynamicLoader.hxx.in | 43 +- Source/kwsys/Encoding.h.in | 58 +- Source/kwsys/Encoding.hxx.in | 72 +- Source/kwsys/EncodingC.c | 53 +- Source/kwsys/EncodingCXX.cxx | 170 +- Source/kwsys/FStream.cxx | 67 +- Source/kwsys/FStream.hxx.in | 428 +- Source/kwsys/Glob.cxx | 416 +- Source/kwsys/Glob.hxx.in | 64 +- Source/kwsys/IOStream.cxx | 245 +- Source/kwsys/IOStream.hxx.in | 136 +- Source/kwsys/MD5.c | 523 ++- Source/kwsys/MD5.h.in | 64 +- Source/kwsys/Process.h.in | 260 +- Source/kwsys/ProcessUNIX.c | 2078 +++++----- Source/kwsys/ProcessWin32.c | 1837 ++++----- Source/kwsys/README.rst | 37 + Source/kwsys/README.txt | 12 - Source/kwsys/RegularExpression.cxx | 1666 ++++---- Source/kwsys/RegularExpression.hxx.in | 148 +- Source/kwsys/SharedForward.h.in | 604 ++- Source/kwsys/String.c | 97 +- Source/kwsys/String.h.in | 36 +- Source/kwsys/String.hxx.in | 62 +- Source/kwsys/System.c | 221 +- Source/kwsys/System.h.in | 32 +- Source/kwsys/SystemInformation.cxx | 4308 ++++++++++---------- Source/kwsys/SystemInformation.hxx.in | 61 +- Source/kwsys/SystemTools.cxx | 3908 ++++++++---------- Source/kwsys/SystemTools.hxx.in | 294 +- Source/kwsys/Terminal.c | 317 +- Source/kwsys/Terminal.h.in | 191 +- Source/kwsys/hash_fun.hxx.in | 89 +- Source/kwsys/hash_map.hxx.in | 246 +- Source/kwsys/hash_set.hxx.in | 217 +- Source/kwsys/hashtable.hxx.in | 486 ++- Source/kwsys/kwsysHeaderDump.pl | 13 +- Source/kwsys/kwsysPlatformTests.cmake | 14 +- Source/kwsys/kwsysPlatformTestsC.c | 52 +- Source/kwsys/kwsysPlatformTestsCXX.cxx | 147 +- Source/kwsys/kwsysPrivate.h | 19 +- Source/kwsys/testCommandLineArguments.cxx | 201 +- Source/kwsys/testCommandLineArguments1.cxx | 83 +- Source/kwsys/testConsoleBuf.cxx | 443 +- Source/kwsys/testConsoleBuf.hxx | 20 +- Source/kwsys/testConsoleBufChild.cxx | 21 +- Source/kwsys/testDynamicLoader.cxx | 89 +- Source/kwsys/testDynload.c | 15 +- Source/kwsys/testEncode.c | 31 +- Source/kwsys/testEncoding.cxx | 161 +- Source/kwsys/testFStream.cxx | 114 +- Source/kwsys/testFail.c | 31 +- Source/kwsys/testHashSTL.cxx | 37 +- Source/kwsys/testIOS.cxx | 153 +- Source/kwsys/testProcess.c | 454 +-- Source/kwsys/testSharedForward.c.in | 27 +- Source/kwsys/testSystemInformation.cxx | 67 +- Source/kwsys/testSystemTools.cxx | 1181 +++--- Source/kwsys/testSystemTools.h.in | 13 +- Source/kwsys/testTerminal.c | 19 +- Templates/TestDriver.cxx.in | 146 +- Tests/BootstrapTest.cmake | 9 +- .../target_compile_features/CMakeLists.txt | 2 +- Tests/CMakeLib/CMakeLists.txt | 3 + Tests/CMakeLib/run_compile_commands.cxx | 4 +- Tests/CMakeLib/testEncoding.cxx | 49 + Tests/CMakeLib/testFindPackageCommand.cxx | 6 +- Tests/CMakeLib/testSystemTools.cxx | 7 +- Tests/CMakeLib/testXMLSafe.cxx | 5 +- Tests/CMakeLists.txt | 38 +- Tests/CMakeOnly/CMakeLists.txt | 3 + Tests/CMakeOnly/CompilerIdCSharp/CMakeLists.txt | 21 + Tests/CMakeTests/File-SHA3_224-Works.cmake | 2 + Tests/CMakeTests/File-SHA3_256-Works.cmake | 2 + Tests/CMakeTests/File-SHA3_384-Works.cmake | 2 + Tests/CMakeTests/File-SHA3_512-Works.cmake | 2 + Tests/CMakeTests/File-TIMESTAMP-NotBogus.cmake | 1 + Tests/CMakeTests/FileTest.cmake.in | 12 + Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in | 7 + Tests/CMakeTests/String-SHA3_224-Works.cmake | 2 + Tests/CMakeTests/String-SHA3_256-Works.cmake | 2 + Tests/CMakeTests/String-SHA3_384-Works.cmake | 2 + Tests/CMakeTests/String-SHA3_512-Works.cmake | 2 + Tests/CMakeTests/StringTest.cmake.in | 12 + Tests/CSharpOnly/CMakeLists.txt | 10 + Tests/CSharpOnly/csharponly.cs | 15 + Tests/CSharpOnly/lib1.cs | 10 + Tests/CSharpOnly/lib2.cs | 10 + .../launcher_compiler_test_project/CMakeLists.txt | 7 + .../CTestConfig.cmake | 0 .../launcher_compiler_test_project/build_error.cxx | 5 + .../CMakeLists.txt | 19 + .../CTestConfig.cmake | 0 .../command.cmake | 0 .../launcher_linker_test_project/CMakeLists.txt | 7 + .../CTestConfig.cmake | 0 .../launcher_linker_test_project/link_error.cxx | 6 + .../launcher_test_project/CMakeLists.txt | 19 - Tests/CTestTestLaunchers/test.cmake.in | 80 +- Tests/CTestTestStopTime/GetDate.cmake | 1 + Tests/CompileFeatures/CMakeLists.txt | 37 +- Tests/CompileFeatures/cxx_right_angle_brackets.cpp | 4 +- Tests/CompileFeatures/default_dialect.cpp | 6 +- Tests/Cuda/CMakeLists.txt | 5 + Tests/Cuda/Complex/CMakeLists.txt | 40 + Tests/Cuda/Complex/dynamic.cpp | 11 + Tests/Cuda/Complex/dynamic.cu | 33 + Tests/Cuda/Complex/file1.cu | 10 + Tests/Cuda/Complex/file1.h | 7 + Tests/Cuda/Complex/file2.cu | 20 + Tests/Cuda/Complex/file2.h | 10 + Tests/Cuda/Complex/file3.cu | 29 + Tests/Cuda/Complex/main.cpp | 20 + Tests/Cuda/Complex/mixed.cpp | 22 + Tests/Cuda/Complex/mixed.cu | 35 + Tests/Cuda/ConsumeCompileFeatures/CMakeLists.txt | 17 + Tests/Cuda/ConsumeCompileFeatures/main.cu | 18 + Tests/Cuda/ConsumeCompileFeatures/static.cpp | 10 + Tests/Cuda/ConsumeCompileFeatures/static.cu | 9 + Tests/Cuda/ObjectLibrary/CMakeLists.txt | 12 + Tests/Cuda/ObjectLibrary/main.cpp | 20 + Tests/Cuda/ObjectLibrary/static.cpp | 6 + Tests/Cuda/ObjectLibrary/static.cu | 21 + Tests/Cuda/ProperLinkFlags/CMakeLists.txt | 20 + Tests/Cuda/ProperLinkFlags/file1.cu | 11 + Tests/Cuda/ProperLinkFlags/file1.h | 7 + Tests/Cuda/ProperLinkFlags/main.cxx | 9 + Tests/CudaOnly/CMakeLists.txt | 4 + Tests/CudaOnly/EnableStandard/CMakeLists.txt | 15 + Tests/CudaOnly/EnableStandard/main.cu | 23 + Tests/CudaOnly/EnableStandard/shared.cu | 15 + Tests/CudaOnly/EnableStandard/static.cu | 9 + Tests/CudaOnly/SeparateCompilation/CMakeLists.txt | 33 + Tests/CudaOnly/SeparateCompilation/file1.cu | 10 + Tests/CudaOnly/SeparateCompilation/file1.h | 7 + Tests/CudaOnly/SeparateCompilation/file2.cu | 20 + Tests/CudaOnly/SeparateCompilation/file2.h | 10 + Tests/CudaOnly/SeparateCompilation/file3.cu | 25 + Tests/CudaOnly/SeparateCompilation/file4.cu | 25 + Tests/CudaOnly/SeparateCompilation/file5.cu | 25 + Tests/CudaOnly/SeparateCompilation/main.cu | 15 + Tests/CudaOnly/WithDefs/CMakeLists.txt | 36 + Tests/CudaOnly/WithDefs/main.notcu | 59 + Tests/CustomCommand/CMakeLists.txt | 21 + Tests/CustomCommand/compare_options.cmake | 14 + Tests/ExternalProject/CMakeLists.txt | 17 + Tests/ExternalProjectLocal/CMakeLists.txt | 1 + Tests/FindLibRHash/CMakeLists.txt | 10 + Tests/FindLibRHash/Test/CMakeLists.txt | 17 + Tests/FindLibRHash/Test/main.c | 7 + Tests/FindOpenGL/CMakeLists.txt | 10 + Tests/FindOpenGL/Test/CMakeLists.txt | 14 + Tests/FindOpenGL/Test/main.c | 17 + Tests/FindPackageModeMakefileTest/CMakeLists.txt | 13 +- Tests/Framework/CMakeLists.txt | 47 +- Tests/GeneratorExpression/CMakeLists.txt | 26 +- Tests/GeneratorExpression/check-part3.cmake | 21 +- Tests/GeneratorExpression/check-part4.cmake | 5 + Tests/GeneratorExpression/echo.c | 3 + Tests/IncludeDirectories/CMakeLists.txt | 4 +- .../SystemIncludeDirectories/CMakeLists.txt | 15 +- Tests/InterfaceLibrary/CMakeLists.txt | 20 +- Tests/InterfaceLibrary/definetestexe.cpp | 3 +- Tests/InterfaceLibrary/item.cpp | 4 + Tests/InterfaceLibrary/item_fake.cpp | 5 + Tests/MacRuntimePath/A/CMakeLists.txt | 15 +- Tests/MathTest/CMakeLists.txt | 3 + Tests/Module/ExternalData/CMakeLists.txt | 2 + .../ExternalData/MultipleAlgorithmNoMD5.dat.md5 | 1 + ....2.dat.sha1 => MultipleAlgorithmNoMD5.dat.sha1} | 0 ...Top.dat.md5 => MultipleAlgorithmNoSHA1.dat.md5} | 0 .../ExternalData/MultipleAlgorithmNoSHA1.dat.sha1 | 1 + .../ExternalData/{MD5 => SHA3_256}/.gitattributes | 0 ...c7b45493750a3612ecc483095eb1366f9f46b179550e231 | 1 + .../Module/ExternalData/SeriesMixed.5.dat.sha3-256 | 1 + .../WriteCompilerDetectionHeader/CMakeLists.txt | 154 +- Tests/Preprocess/CMakeLists.txt | 14 +- Tests/QtAutoUicInterface/CMakeLists.txt | 7 +- Tests/QtAutoUicInterface/libwidget.cpp | 5 + Tests/QtAutoUicInterface/libwidget.h | 3 +- Tests/QtAutoUicInterface/mywidget.cpp | 5 + Tests/QtAutoUicInterface/mywidget.h | 3 +- Tests/QtAutogen/Bdir/CMakeLists.txt | 10 - Tests/QtAutogen/CMakeLists.txt | 192 +- Tests/QtAutogen/automoc_rerun/CMakeLists.txt | 2 +- Tests/QtAutogen/autorcc_depends/CMakeLists.txt | 2 +- Tests/QtAutogen/{ => complex}/Adir/CMakeLists.txt | 0 Tests/QtAutogen/{ => complex}/Adir/libA.cpp | 0 Tests/QtAutogen/{ => complex}/Adir/libA.h | 0 Tests/QtAutogen/complex/Bdir/CMakeLists.txt | 9 + Tests/QtAutogen/{ => complex}/Bdir/libB.cpp | 0 Tests/QtAutogen/{ => complex}/Bdir/libB.h | 0 Tests/QtAutogen/complex/CMakeLists.txt | 82 + Tests/QtAutogen/{ => complex}/abc.cpp | 0 Tests/QtAutogen/{ => complex}/abc.h | 0 Tests/QtAutogen/{ => complex}/abc_p.h | 0 Tests/QtAutogen/{ => complex}/bar.cpp | 0 Tests/QtAutogen/{ => complex}/blub.cpp | 0 Tests/QtAutogen/{ => complex}/blub.h | 0 Tests/QtAutogen/{ => complex}/calwidget.cpp | 0 Tests/QtAutogen/{ => complex}/calwidget.h | 0 Tests/QtAutogen/{ => complex}/calwidget.ui | 0 Tests/QtAutogen/{ => complex}/codeeditor.cpp | 0 Tests/QtAutogen/{ => complex}/codeeditor.h | 0 Tests/QtAutogen/{ => complex}/debug_class.cpp | 0 Tests/QtAutogen/{ => complex}/debug_class.h | 0 Tests/QtAutogen/{ => complex}/debug_class.ui | 0 Tests/QtAutogen/{ => complex}/debug_resource.qrc | 0 Tests/QtAutogen/{ => complex}/foo.cpp | 0 Tests/QtAutogen/{ => complex}/foo.h | 0 Tests/QtAutogen/{ => complex}/gadget.cpp | 0 Tests/QtAutogen/{ => complex}/gadget.h | 0 Tests/QtAutogen/{ => complex}/generated.cpp | 0 Tests/QtAutogen/{ => complex}/generated.h | 0 Tests/QtAutogen/{ => complex}/generated.txt.in | 0 .../{ => complex}/generated_resource.qrc.in | 0 Tests/QtAutogen/{ => complex}/libC.cpp | 0 Tests/QtAutogen/{ => complex}/libC.h | 0 Tests/QtAutogen/{ => complex}/main.cpp | 0 Tests/QtAutogen/{ => complex}/multiplewidgets.cpp | 0 Tests/QtAutogen/{ => complex}/multiplewidgets.h | 0 Tests/QtAutogen/{ => complex}/myinterface.h.in | 0 .../QtAutogen/{ => complex}/myotherinterface.h.in | 0 Tests/QtAutogen/{ => complex}/private_slot.cpp | 0 Tests/QtAutogen/{ => complex}/private_slot.h | 0 Tests/QtAutogen/{ => complex}/resourcetester.cpp | 0 Tests/QtAutogen/{ => complex}/resourcetester.h | 0 Tests/QtAutogen/{ => complex}/second_resource.qrc | 0 Tests/QtAutogen/{ => complex}/second_widget.cpp | 0 Tests/QtAutogen/{ => complex}/second_widget.h | 0 Tests/QtAutogen/{ => complex}/second_widget.ui | 0 Tests/QtAutogen/{ => complex}/sub/bar.h | 0 .../QtAutogen/{ => complex}/targetObjectsTest.cpp | 0 Tests/QtAutogen/{ => complex}/test.qrc | 0 Tests/QtAutogen/{ => complex}/widget1.ui | 0 Tests/QtAutogen/{ => complex}/widget2.ui | 0 Tests/QtAutogen/{ => complex}/xyz.cpp | 0 Tests/QtAutogen/{ => complex}/xyz.h | 0 Tests/QtAutogen/{ => complex}/yaf.cpp | 0 Tests/QtAutogen/{ => complex}/yaf.h | 0 Tests/QtAutogen/{ => complex}/yaf_p.h | 0 Tests/QtAutogen/defines_test/CMakeLists.txt | 2 - Tests/QtAutogen/rccEmpty.cpp | 9 + .../{rcc_empty_resource.qrc => rccEmptyRes.qrc} | 0 Tests/QtAutogen/rccOnly.cpp | 9 + Tests/QtAutogen/rccOnlyRes.qrc | 5 + Tests/QtAutogen/rcc_empty.cpp | 9 - Tests/QtAutogen/rcconly.cpp | 9 - Tests/QtAutogen/sameName/CMakeLists.txt | 3 +- Tests/QtAutogen/skipMoc.cpp | 14 + Tests/QtAutogen/skipRcc.cpp | 9 + Tests/QtAutogen/skipSource/qItemA.cpp | 5 + Tests/QtAutogen/skipSource/qItemA.hpp | 13 + Tests/QtAutogen/skipSource/qItemB.cpp | 5 + Tests/QtAutogen/skipSource/qItemB.hpp | 13 + Tests/QtAutogen/skipSource/qItemC.cpp | 5 + Tests/QtAutogen/skipSource/qItemC.hpp | 13 + Tests/QtAutogen/skipSource/skipRccBad1.qrc | 5 + Tests/QtAutogen/skipSource/skipRccBad2.qrc | 5 + Tests/QtAutogen/skipSource/skipRccGood.qrc | 6 + Tests/QtAutogen/skipSource/skipUicGen.cpp | 7 + Tests/QtAutogen/skipSource/skipUicGen.hpp | 8 + Tests/QtAutogen/skipSource/skipUicNoGen1.cpp | 7 + Tests/QtAutogen/skipSource/skipUicNoGen1.hpp | 8 + Tests/QtAutogen/skipSource/skipUicNoGen2.cpp | 7 + Tests/QtAutogen/skipSource/skipUicNoGen2.hpp | 8 + Tests/QtAutogen/skipSource/ui_nogen1.h | 6 + Tests/QtAutogen/skipSource/ui_nogen2.h | 6 + Tests/QtAutogen/skipSource/uigen1.ui | 24 + Tests/QtAutogen/skipSource/uigen2.ui | 24 + Tests/QtAutogen/skipUic.cpp | 22 + Tests/QtAutogen/sub/uiconly.cpp | 13 - Tests/QtAutogen/sub/uiconly.h | 20 - Tests/QtAutogen/uicOnlySource/uiconly.cpp | 18 + Tests/QtAutogen/uicOnlySource/uiconly.h | 20 + Tests/QtAutogen/{sub => uicOnlySource}/uiconly.ui | 0 .../AndroidTestUtilities/RunCMakeTest.cmake | 1 + .../RunCMake/AndroidTestUtilities/SetupTest4.cmake | 13 + ...ild-check.cmake => SetupTest4Build-check.cmake} | 0 Tests/RunCMake/CMakeLists.txt | 28 +- Tests/RunCMake/CPack/7Z/Helpers.cmake | 3 + .../CPack/{TGZ => 7Z}/Prerequirements.cmake | 0 .../packaging_COMPONENT_default.cmake} | 0 .../CPack/ArchiveCommon/common_helpers.cmake | 62 + Tests/RunCMake/CPack/CMakeLists.txt | 13 +- Tests/RunCMake/CPack/COMPONENTS_EMPTY_DIR.cmake | 5 - Tests/RunCMake/CPack/CPackTestHelpers.cmake | 51 +- Tests/RunCMake/CPack/CUSTOM_NAMES.cmake | 7 - .../DEB/COMPONENTS_EMPTY_DIR-ExpectedFiles.cmake | 5 - .../CPack/DEB/COMPONENTS_EMPTY_DIR-specifics.cmake | 3 - .../CPack/DEB/CUSTOM_NAMES-ExpectedFiles.cmake | 9 - .../CPack/DEB/CUSTOM_NAMES-specifics.cmake | 6 - .../CPack/DEB/DEB_EXTRA-ExpectedFiles.cmake | 9 - .../DEB/DEB_GENERATE_SHLIBS-ExpectedFiles.cmake | 6 - .../DEB/DEB_GENERATE_SHLIBS-Prerequirements.cmake | 7 - ...EB_GENERATE_SHLIBS_LDCONFIG-ExpectedFiles.cmake | 6 - ..._GENERATE_SHLIBS_LDCONFIG-Prerequirements.cmake | 7 - .../CPack/DEB/DEPENDENCIES-ExpectedFiles.cmake | 14 - .../CPack/DEB/DEPENDENCIES-VerifyResult.cmake | 34 - .../CPack/DEB/DEPENDENCIES-specifics.cmake | 23 - .../CPack/DEB/EMPTY_DIR-ExpectedFiles.cmake | 5 - Tests/RunCMake/CPack/DEB/EMPTY_DIR-specifics.cmake | 2 - Tests/RunCMake/CPack/DEB/Helpers.cmake | 43 +- .../CPack/DEB/LONG_FILENAMES-ExpectedFiles.cmake | 5 - .../CPack/DEB/LONG_FILENAMES-Prerequirements.cmake | 7 - .../CPack/DEB/LONG_FILENAMES-specifics.cmake | 3 - .../RunCMake/CPack/DEB/MINIMAL-ExpectedFiles.cmake | 5 - Tests/RunCMake/CPack/DEB/MINIMAL-specifics.cmake | 2 - .../DEB/PER_COMPONENT_FIELDS-ExpectedFiles.cmake | 9 - .../DEB/PER_COMPONENT_FIELDS-VerifyResult.cmake | 18 - .../CPack/DEB/PER_COMPONENT_FIELDS-specifics.cmake | 7 - Tests/RunCMake/CPack/DEB/Prerequirements.cmake | 7 + .../CPack/DEB/packaging_COMPONENT_default.cmake | 2 + .../CPack/DEB/packaging_MONOLITHIC_default.cmake | 1 + Tests/RunCMake/CPack/DEBUGINFO.cmake | 34 - Tests/RunCMake/CPack/DEB_EXTRA.cmake | 39 - Tests/RunCMake/CPack/DEB_GENERATE_SHLIBS.cmake | 18 - .../CPack/DEB_GENERATE_SHLIBS_LDCONFIG.cmake | 19 - Tests/RunCMake/CPack/DEPENDENCIES.cmake | 20 - Tests/RunCMake/CPack/EMPTY_DIR.cmake | 4 - Tests/RunCMake/CPack/INSTALL_SCRIPTS.cmake | 26 - Tests/RunCMake/CPack/LONG_FILENAMES.cmake | 10 - Tests/RunCMake/CPack/MINIMAL.cmake | 3 - Tests/RunCMake/CPack/PACKAGE_CHECKSUM.cmake | 4 - .../CPack/PARTIALLY_RELOCATABLE_WARNING.cmake | 6 - Tests/RunCMake/CPack/PER_COMPONENT_FIELDS.cmake | 5 - Tests/RunCMake/CPack/README.txt | 179 +- .../RPM/COMPONENTS_EMPTY_DIR-ExpectedFiles.cmake | 5 - .../CPack/RPM/COMPONENTS_EMPTY_DIR-stderr.txt | 1 - .../CPack/RPM/CUSTOM_NAMES-ExpectedFiles.cmake | 9 - .../CPack/RPM/CUSTOM_NAMES-specifics.cmake | 5 - Tests/RunCMake/CPack/RPM/CUSTOM_NAMES-stderr.txt | 3 - .../CPack/RPM/DEBUGINFO-ExpectedFiles.cmake | 14 - Tests/RunCMake/CPack/RPM/DEBUGINFO-stderr.txt | 3 - .../CPack/RPM/DEPENDENCIES-ExpectedFiles.cmake | 13 - .../CPack/RPM/DEPENDENCIES-VerifyResult.cmake | 45 - .../CPack/RPM/DEPENDENCIES-specifics.cmake | 22 - .../CPack/RPM/EMPTY_DIR-ExpectedFiles.cmake | 5 - Tests/RunCMake/CPack/RPM/EMPTY_DIR-stderr.txt | 1 - Tests/RunCMake/CPack/RPM/Helpers.cmake | 53 + .../CPack/RPM/INSTALL_SCRIPTS-ExpectedFiles.cmake | 7 - .../CPack/RPM/INSTALL_SCRIPTS-specifics.cmake | 19 - .../RunCMake/CPack/RPM/MINIMAL-ExpectedFiles.cmake | 5 - Tests/RunCMake/CPack/RPM/MINIMAL-stderr.txt | 1 - ...RTIALLY_RELOCATABLE_WARNING-ExpectedFiles.cmake | 5 - .../RPM/PER_COMPONENT_FIELDS-ExpectedFiles.cmake | 9 - .../RPM/PER_COMPONENT_FIELDS-VerifyResult.cmake | 18 - .../CPack/RPM/PER_COMPONENT_FIELDS-specifics.cmake | 5 - .../CPack/RPM/RPM_DIST-ExpectedFiles.cmake | 5 - .../CPack/RPM/SOURCE_PACKAGE-ExpectedFiles.cmake | 5 - .../CPack/RPM/SOURCE_PACKAGE-VerifyResult.cmake | 63 - .../RunCMake/CPack/RPM/default_expected_stderr.txt | 1 + .../CPack/RPM/packaging_COMPONENT_default.cmake | 1 + Tests/RunCMake/CPack/RPM_DIST.cmake | 4 - Tests/RunCMake/CPack/RunCMakeTest.cmake | 39 +- Tests/RunCMake/CPack/SOURCE_PACKAGE.cmake | 9 - Tests/RunCMake/CPack/STGZ/Helpers.cmake | 64 + Tests/RunCMake/CPack/STGZ/Prerequirements.cmake | 11 + .../packaging_COMPONENT_default.cmake} | 0 Tests/RunCMake/CPack/TBZ2/Helpers.cmake | 3 + .../CPack/{TGZ => TBZ2}/Prerequirements.cmake | 0 .../packaging_COMPONENT_default.cmake} | 0 .../TGZ/COMPONENTS_EMPTY_DIR-ExpectedFiles.cmake | 3 - .../CPack/TGZ/EMPTY_DIR-ExpectedFiles.cmake | 3 - Tests/RunCMake/CPack/TGZ/Helpers.cmake | 11 +- .../RunCMake/CPack/TGZ/MINIMAL-ExpectedFiles.cmake | 5 - .../CPack/TGZ/PACKAGE_CHECKSUM-ExpectedFiles.cmake | 9 - .../CPack/TGZ/PACKAGE_CHECKSUM-VerifyResult.cmake | 14 - ...ics.cmake => packaging_COMPONENT_default.cmake} | 0 Tests/RunCMake/CPack/TXZ/Helpers.cmake | 3 + .../CPack/{TGZ => TXZ}/Prerequirements.cmake | 0 .../packaging_COMPONENT_default.cmake} | 0 Tests/RunCMake/CPack/TZ/Helpers.cmake | 3 + .../CPack/{TGZ => TZ}/Prerequirements.cmake | 0 .../packaging_COMPONENT_default.cmake} | 0 Tests/RunCMake/CPack/VerifyResult.cmake | 71 +- Tests/RunCMake/CPack/ZIP/Helpers.cmake | 3 + .../CPack/{TGZ => ZIP}/Prerequirements.cmake | 0 .../packaging_COMPONENT_default.cmake} | 0 .../CUSTOM_BINARY_SPEC_FILE/ExpectedFiles.cmake | 9 + .../RPM-COMPONENT-stderr.txt | 2 + .../RPM-MONOLITHIC-stderr.txt | 1 + .../tests/CUSTOM_BINARY_SPEC_FILE/custom.spec.in | 80 + .../CPack/tests/CUSTOM_BINARY_SPEC_FILE/test.cmake | 9 + .../CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake | 12 + Tests/RunCMake/CPack/tests/CUSTOM_NAMES/test.cmake | 14 + .../CPack/tests/DEBUGINFO/ExpectedFiles.cmake | 16 + Tests/RunCMake/CPack/tests/DEBUGINFO/test.cmake | 30 + .../CPack/tests/DEPENDENCIES/DEB-stderr.txt | 1 + .../CPack/tests/DEPENDENCIES/ExpectedFiles.cmake | 18 + .../CPack/tests/DEPENDENCIES/VerifyResult.cmake | 82 + Tests/RunCMake/CPack/tests/DEPENDENCIES/test.cmake | 60 + .../RunCMake/CPack/tests/DIST/ExpectedFiles.cmake | 2 + .../DIST/VerifyResult.cmake} | 0 Tests/RunCMake/CPack/tests/DIST/test.cmake | 3 + .../CPack/tests/EMPTY_DIR/ExpectedFiles.cmake | 7 + Tests/RunCMake/CPack/tests/EMPTY_DIR/test.cmake | 14 + .../RunCMake/CPack/tests/EXTRA/ExpectedFiles.cmake | 8 + .../EXTRA/VerifyResult.cmake} | 0 Tests/RunCMake/CPack/tests/EXTRA/test.cmake | 35 + .../GENERATE_SHLIBS/DEB-Prerequirements.cmake | 7 + .../tests/GENERATE_SHLIBS/ExpectedFiles.cmake | 6 + .../GENERATE_SHLIBS/VerifyResult.cmake} | 0 .../CPack/tests/GENERATE_SHLIBS/test.cmake | 14 + .../DEB-Prerequirements.cmake | 7 + .../GENERATE_SHLIBS_LDCONFIG/ExpectedFiles.cmake | 6 + .../GENERATE_SHLIBS_LDCONFIG/VerifyResult.cmake} | 0 .../tests/GENERATE_SHLIBS_LDCONFIG/test.cmake | 15 + .../tests/INSTALL_SCRIPTS/ExpectedFiles.cmake | 5 + .../INSTALL_SCRIPTS/VerifyResult.cmake} | 0 .../CPack/tests/INSTALL_SCRIPTS/test.cmake | 44 + .../tests/LONG_FILENAMES/DEB-Prerequirements.cmake | 7 + .../CPack/tests/LONG_FILENAMES/ExpectedFiles.cmake | 3 + .../LONG_FILENAMES/VerifyResult.cmake} | 0 .../RunCMake/CPack/tests/LONG_FILENAMES/test.cmake | 13 + .../CPack/tests/MAIN_COMPONENT/ExpectedFiles.cmake | 11 + .../tests/MAIN_COMPONENT/RPM-invalid-stderr.txt | 1 + .../RunCMake/CPack/tests/MAIN_COMPONENT/test.cmake | 10 + .../CPack/tests/MD5SUMS/ExpectedFiles.cmake | 2 + .../CPack/tests/MD5SUMS/VerifyResult.cmake | 3 + Tests/RunCMake/CPack/tests/MD5SUMS/test.cmake | 5 + .../CPack/tests/MINIMAL/ExpectedFiles.cmake | 2 + Tests/RunCMake/CPack/tests/MINIMAL/test.cmake | 5 + .../tests/PACKAGE_CHECKSUM/ExpectedFiles.cmake | 6 + .../PACKAGE_CHECKSUM/TGZ-invalid-stderr.txt} | 0 .../tests/PACKAGE_CHECKSUM/VerifyResult.cmake | 12 + .../CPack/tests/PACKAGE_CHECKSUM/test.cmake | 3 + .../ExpectedFiles.cmake | 2 + .../PARTIALLY_RELOCATABLE_WARNING/RPM-stderr.txt} | 0 .../tests/PARTIALLY_RELOCATABLE_WARNING/test.cmake | 4 + .../tests/PER_COMPONENT_FIELDS/ExpectedFiles.cmake | 8 + .../tests/PER_COMPONENT_FIELDS/VerifyResult.cmake | 26 + .../CPack/tests/PER_COMPONENT_FIELDS/test.cmake | 18 + .../tests/SINGLE_DEBUGINFO/ExpectedFiles.cmake | 30 + .../RPM-no_main_component-stderr.txt | 1 + .../CPack/tests/SINGLE_DEBUGINFO/test.cmake | 54 + .../CPack/tests/SOURCE_PACKAGE/ExpectedFiles.cmake | 2 + .../CPack/tests/SOURCE_PACKAGE/VerifyResult.cmake | 65 + .../RunCMake/CPack/tests/SOURCE_PACKAGE/test.cmake | 7 + .../CPack/tests/SUGGESTS/ExpectedFiles.cmake | 2 + Tests/RunCMake/CPack/tests/SUGGESTS/RPM-stderr.txt | 1 + .../CPack/tests/SUGGESTS/VerifyResult.cmake | 31 + Tests/RunCMake/CPack/tests/SUGGESTS/test.cmake | 3 + .../CPack/tests/USER_FILELIST/ExpectedFiles.cmake | 2 + .../CPack/tests/USER_FILELIST/VerifyResult.cmake | 12 + .../RunCMake/CPack/tests/USER_FILELIST/test.cmake | 13 + Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake | 1 + .../CTestCommandLine/repeat-until-fail-cmake.cmake | 2 + .../C-bad-Build-result.txt} | 0 Tests/RunCMake/ClangTidy/C-bad-Build-stdout.txt | 2 + Tests/RunCMake/ClangTidy/C-bad.cmake | 3 + Tests/RunCMake/ClangTidy/RunCMakeTest.cmake | 1 + .../CommandLine/E___run_iwyu-no-iwyu-stderr.txt | 2 +- .../LinkImplementationFeatureCycle.cmake | 4 +- .../LinkImplementationFeatureCycleSolved.cmake | 2 +- Tests/RunCMake/Configure/RemoveCache-stdout.txt | 1 + Tests/RunCMake/Configure/RemoveCache.cmake | 17 + Tests/RunCMake/Configure/RunCMakeTest.cmake | 9 + Tests/RunCMake/Cpplint/C-Build-stdout.txt | 1 + .../C-error-Build-result.txt} | 0 Tests/RunCMake/Cpplint/C-error-Build-stdout.txt | 1 + .../C-error-launch-Build-result.txt} | 0 .../Cpplint/C-error-launch-Build-stdout.txt | 1 + Tests/RunCMake/Cpplint/C-error-launch.cmake | 3 + Tests/RunCMake/Cpplint/C-error.cmake | 3 + Tests/RunCMake/Cpplint/C-launch-Build-stdout.txt | 1 + .../RunCMake/{ClangTidy => Cpplint}/C-launch.cmake | 0 Tests/RunCMake/Cpplint/C.cmake | 3 + Tests/RunCMake/Cpplint/CMakeLists.txt | 3 + Tests/RunCMake/Cpplint/CXX-Build-stdout.txt | 1 + .../CXX-error-Build-result.txt} | 0 Tests/RunCMake/Cpplint/CXX-error-Build-stdout.txt | 1 + .../CXX-error-launch-Build-result.txt} | 0 .../Cpplint/CXX-error-launch-Build-stdout.txt | 1 + Tests/RunCMake/Cpplint/CXX-error-launch.cmake | 3 + Tests/RunCMake/Cpplint/CXX-error.cmake | 3 + Tests/RunCMake/Cpplint/CXX-launch-Build-stdout.txt | 1 + .../{ClangTidy => Cpplint}/CXX-launch.cmake | 0 Tests/RunCMake/Cpplint/CXX.cmake | 3 + Tests/RunCMake/Cpplint/RunCMakeTest.cmake | 26 + .../LinkInterfaceLoop => RunCMake/Cpplint}/main.c | 0 Tests/RunCMake/{ClangTidy => Cpplint}/main.cxx | 0 .../CrosscompilingEmulator/AddCustomCommand.cmake | 17 +- .../CrosscompilingEmulator/AddCustomTarget.cmake | 16 +- .../generated_exe_emulator_unexpected.cxx | 9 + .../simple_src_exitsuccess.cxx | 4 - .../FeatureSummaryCustomBadDefault-result.txt} | 0 .../FeatureSummaryCustomBadDefault-stderr.txt | 9 + .../FeatureSummaryCustomBadDefault.cmake | 8 + .../FeatureSummaryCustomRequired-result.txt} | 0 .../FeatureSummaryCustomRequired-stderr.txt | 6 + .../FeatureSummaryCustomRequired-stdout.txt | 17 + .../FeatureSummaryCustomRequired.cmake | 16 + .../FeatureSummaryCustomRequiredListA-result.txt} | 0 .../FeatureSummaryCustomRequiredListA-stderr.txt | 6 + .../FeatureSummaryCustomRequiredListA-stdout.txt | 17 + .../FeatureSummaryCustomRequiredListA.cmake | 16 + .../FeatureSummaryCustomRequiredListB-result.txt} | 0 .../FeatureSummaryCustomRequiredListB-stderr.txt | 6 + .../FeatureSummaryCustomRequiredListB-stdout.txt | 17 + .../FeatureSummaryCustomRequiredListB.cmake | 16 + .../FeatureSummaryCustomTypes-stdout.txt | 29 + .../FeatureSummary/FeatureSummaryCustomTypes.cmake | 36 + ...mmaryFatalOnMissingRequiredPackages-result.txt} | 0 ...ummaryFatalOnMissingRequiredPackages-stderr.txt | 6 + ...ummaryFatalOnMissingRequiredPackages-stdout.txt | 17 + ...tureSummaryFatalOnMissingRequiredPackages.cmake | 12 + .../FeatureSummaryIncludeQuietPackages-stdout.txt | 14 + .../FeatureSummaryIncludeQuietPackages.cmake | 11 + .../FeatureSummaryMultipleDepends-stdout.txt | 10 + .../FeatureSummaryMultipleDepends.cmake | 12 + .../FeatureSummaryPurpose-stdout.txt | 16 + .../FeatureSummary/FeatureSummaryPurpose.cmake | 16 + .../FeatureSummaryQuietOnEmpty-stdout.txt | 5 + .../FeatureSummaryQuietOnEmpty.cmake | 14 + .../FeatureSummary/FeatureSummaryTypes-stdout.txt | 45 + .../FeatureSummary/FeatureSummaryTypes.cmake | 48 + .../FeatureSummaryURLDescription-stdout.txt | 32 + .../FeatureSummaryURLDescription.cmake | 28 + .../FeatureSummaryWhatAll-stdout.txt | 4 +- .../FeatureSummaryWhatList-stdout.txt | 4 +- .../FeatureSummaryWhatOnce-stdout.txt | 2 +- .../FeatureSummary/FeatureSummaryWhatOnce.cmake | 4 +- .../FeatureSummaryWhatSingle-stdout.txt | 2 +- Tests/RunCMake/FeatureSummary/FindBar.cmake | 2 + Tests/RunCMake/FeatureSummary/FindBaz.cmake | 2 + Tests/RunCMake/FeatureSummary/FindFoo.cmake | 4 + Tests/RunCMake/FeatureSummary/RunCMakeTest.cmake | 12 + .../{ClangTidy => FindGTK2}/CMakeLists.txt | 0 Tests/RunCMake/FindGTK2/FindGTK2RunTwice.cmake | 21 + Tests/RunCMake/FindGTK2/RunCMakeTest.cmake | 3 + Tests/RunCMake/Framework/FrameworkLayout.cmake | 5 +- .../Framework/FrameworkTypeSHARED-build-stdout.txt | 1 + .../Framework/FrameworkTypeSTATIC-build-stdout.txt | 1 + Tests/RunCMake/Framework/RunCMakeTest.cmake | 69 +- .../BadIF-result.txt} | 0 .../RunCMake/GeneratorExpression/BadIF-stderr.txt | 15 + Tests/RunCMake/GeneratorExpression/BadIF.cmake | 5 + .../GeneratorExpression/RunCMakeTest.cmake | 1 + .../TARGET_PROPERTY-LOCATION-stderr.txt | 4 +- .../BadToolsetHostArch-result.txt} | 0 .../GeneratorToolset/BadToolsetHostArch-stderr.txt | 10 + .../BadToolsetHostArch.cmake} | 0 Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake | 15 + .../TestToolsetHostArchBoth-stdout.txt | 2 + .../GeneratorToolset/TestToolsetHostArchBoth.cmake | 2 + .../TestToolsetHostArchNone-stdout.txt | 2 + .../GeneratorToolset/TestToolsetHostArchNone.cmake | 2 + .../TestToolsetHostArchOnly-stdout.txt | 2 + .../GeneratorToolset/TestToolsetHostArchOnly.cmake | 2 + .../NinjaToolMissing-result.txt} | 0 Tests/RunCMake/Ninja/NinjaToolMissing-stderr.txt | 6 + .../RunCMake/Ninja/NinjaToolMissing.cmake | 0 Tests/RunCMake/Ninja/RunCMakeTest.cmake | 6 + Tests/RunCMake/RunCMake.cmake | 4 +- Tests/RunCMake/RunCTest.cmake | 1 + Tests/RunCMake/VS10Project/RunCMakeTest.cmake | 3 + .../RunCMake/VS10Project/VsCustomProps-check.cmake | 25 + Tests/RunCMake/VS10Project/VsCustomProps.cmake | 7 + .../VS10Project/VsDebuggerWorkingDir-check.cmake | 22 + .../VS10Project/VsDebuggerWorkingDir.cmake | 5 + .../VsTargetsFileReferences-check.cmake | 45 + .../VS10Project/VsTargetsFileReferences.cmake | 9 + .../bar.c => RunCMake/VS10Project/bar.cpp} | 0 Tests/RunCMake/VS10Project/baz.cpp | 3 + Tests/RunCMake/VS10Project/my.props | 5 + .../VSSolution/AddPackageToDefault-check.cmake | 29 + .../RunCMake/VSSolution/AddPackageToDefault.cmake | 2 + Tests/RunCMake/VSSolution/RunCMakeTest.cmake | 1 + .../PerConfigPerSourceFlags-result.txt} | 0 .../PerConfigPerSourceFlags-stderr.txt | 8 + .../XcodeProject/PerConfigPerSourceFlags.cmake | 3 + Tests/RunCMake/XcodeProject/RunCMakeTest.cmake | 23 + Tests/RunCMake/XcodeProject/XcodeBundles.cmake | 52 +- .../RunCMake/XcodeProject/XcodeMultiplatform.cmake | 14 + .../ReadOnlyProperty-result.txt} | 0 .../add_dependencies/ReadOnlyProperty-stderr.txt | 1 + .../add_dependencies/ReadOnlyProperty.cmake | 6 + .../add_dependencies/RetrieveDependencies.cmake | 16 + Tests/RunCMake/add_dependencies/RunCMakeTest.cmake | 2 + Tests/RunCMake/add_dependencies/a.c | 3 + Tests/RunCMake/add_dependencies/b.c | 3 + Tests/RunCMake/add_dependencies/c.c | 3 + Tests/RunCMake/ctest_build/CMakeLists.txt.in | 1 + Tests/RunCMake/ctest_build/RunCMakeTest.cmake | 5 + Tests/RunCMake/ctest_build/test.cmake.in | 1 + Tests/RunCMake/ctest_fixtures/CMakeLists.txt.in | 6 + Tests/RunCMake/ctest_fixtures/RunCMakeTest.cmake | 1 + Tests/RunCMake/ctest_fixtures/unused-stdout.txt | 9 + .../DummyAddressLeakSanitizer-result.txt} | 0 .../DummyAddressLeakSanitizer-stderr.txt | 1 + ...ut.txt => DummyAddressLeakSanitizer-stdout.txt} | 0 .../DummyLeakSanitizerPrintDefects-result.txt} | 0 .../DummyLeakSanitizerPrintDefects-stderr.txt | 1 + ...t => DummyLeakSanitizerPrintDefects-stdout.txt} | 0 .../RunCMake/ctest_memcheck/DummyPurify-stdout.txt | 4 +- .../ctest_memcheck/DummyValgrind-stdout.txt | 4 +- .../DummyValgrindCustomOptions-stdout.txt | 4 +- .../DummyValgrindFailPost-stdout.txt | 4 +- .../DummyValgrindIgnoreMemcheck-stdout.txt | 4 +- .../DummyValgrindNoDefects-result.txt} | 0 .../DummyValgrindNoDefects-stderr.txt | 1 + .../DummyValgrindNoDefects-stdout.txt | 8 + .../ctest_memcheck/DummyValgrindPrePost-stdout.txt | 4 +- Tests/RunCMake/ctest_memcheck/RunCMakeTest.cmake | 56 +- Tests/RunCMake/ctest_memcheck/test.cmake.in | 4 +- .../ctest_memcheck/testAddressLeakSanitizer.cmake | 47 + .../ctest_memcheck/testAddressSanitizer.cmake | 2 +- .../ctest_memcheck/testLeakSanitizer.cmake | 20 +- .../ctest_memcheck/testMemorySanitizer.cmake | 4 +- .../ctest_memcheck/testThreadSanitizer.cmake | 4 +- .../testUndefinedBehaviorSanitizer.cmake | 6 +- .../CDashUploadMissingFile-result.txt} | 0 .../ctest_submit/CDashUploadMissingFile-stderr.txt | 1 + .../ctest_submit/CDashUploadRETRY_COUNT-stderr.txt | 2 - .../ctest_submit/CDashUploadRETRY_DELAY-stderr.txt | 2 - .../CDashUploadRetry-result.txt} | 0 .../ctest_submit/CDashUploadRetry-stderr.txt | 1 + .../ctest_submit/CDashUploadRetry-stdout.txt | 4 + Tests/RunCMake/ctest_submit/RunCMakeTest.cmake | 4 +- Tests/RunCMake/execute_process/CMakeLists.txt | 3 + Tests/RunCMake/execute_process/Encoding.cmake | 6 + .../EncodingMissing-result.txt} | 0 .../execute_process/EncodingMissing-stderr.txt | 4 + .../RunCMake/execute_process/EncodingMissing.cmake | 1 + .../execute_process/EncodingUTF8-stderr.txt | 1 + Tests/RunCMake/execute_process/RunCMakeTest.cmake | 5 + .../file/GLOB-noexp-LIST_DIRECTORIES.cmake | 1 + Tests/RunCMake/file/RunCMakeTest.cmake | 1 + .../IMPORTED_LIBNAME-bad-value-result.txt} | 0 .../IMPORTED_LIBNAME-bad-value-stderr.txt | 44 + .../IMPORTED_LIBNAME-bad-value.cmake | 6 + .../IMPORTED_LIBNAME-non-iface-result.txt} | 0 .../IMPORTED_LIBNAME-non-iface-stderr.txt | 45 + .../IMPORTED_LIBNAME-non-iface.cmake | 17 + .../IMPORTED_LIBNAME-non-imported-result.txt} | 0 .../IMPORTED_LIBNAME-non-imported-stderr.txt | 21 + .../IMPORTED_LIBNAME-non-imported.cmake | 5 + .../RunCMake/interface_library/RunCMakeTest.cmake | 3 + Tests/RunCMake/pseudo_cpplint.c | 21 + Tests/RunCMake/pseudo_emulator_custom_command.c | 3 +- Tests/RunCMake/pseudo_iwyu.c | 3 +- Tests/RunCMake/pseudo_tidy.c | 6 + Tests/RunCMake/set_property/RunCMakeTest.cmake | 1 + .../TYPE-result.txt} | 0 Tests/RunCMake/set_property/TYPE-stderr.txt | 1 + Tests/RunCMake/set_property/TYPE.cmake | 2 + Tests/RunCMake/string/RunCMakeTest.cmake | 5 + .../Timestamp-result.txt} | 0 Tests/RunCMake/string/Timestamp-stderr.txt | 1 + Tests/RunCMake/string/Timestamp.cmake | 3 + .../TimestampEmpty-result.txt} | 0 Tests/RunCMake/string/TimestampEmpty-stderr.txt | 1 + Tests/RunCMake/string/TimestampEmpty.cmake | 3 + Tests/RunCMake/string/TimestampInvalid-result.txt | 1 + Tests/RunCMake/string/TimestampInvalid-stderr.txt | 1 + Tests/RunCMake/string/TimestampInvalid.cmake | 3 + Tests/RunCMake/string/TimestampInvalid2-result.txt | 1 + Tests/RunCMake/string/TimestampInvalid2-stderr.txt | 1 + Tests/RunCMake/string/TimestampInvalid2.cmake | 3 + Tests/RunCMake/try_compile/CMP0067-stderr.txt | 25 + Tests/RunCMake/try_compile/CMP0067.cmake | 40 + .../CStandard-result.txt} | 0 Tests/RunCMake/try_compile/CStandard-stderr.txt | 7 + Tests/RunCMake/try_compile/CStandard.cmake | 7 + Tests/RunCMake/try_compile/CStandardGNU.c | 10 + Tests/RunCMake/try_compile/CStandardGNU.cmake | 23 + .../RunCMake/try_compile/CStandardNoDefault.cmake | 9 + .../CudaStandard-result.txt} | 0 Tests/RunCMake/try_compile/CudaStandard-stderr.txt | 7 + Tests/RunCMake/try_compile/CudaStandard.cmake | 7 + .../try_compile/CudaStandardNoDefault.cmake | 9 + .../CxxStandard-result.txt} | 0 Tests/RunCMake/try_compile/CxxStandard-stderr.txt | 7 + Tests/RunCMake/try_compile/CxxStandard.cmake | 7 + Tests/RunCMake/try_compile/CxxStandardGNU.cmake | 23 + Tests/RunCMake/try_compile/CxxStandardGNU.cxx | 11 + .../try_compile/CxxStandardNoDefault.cmake | 9 + Tests/RunCMake/try_compile/RunCMakeTest.cmake | 26 + Tests/RunCMake/try_compile/WarnDeprecated.cmake | 19 + .../RunCMake/try_compile/src.cu | 0 .../RunCMake/try_compile/src.cxx | 0 Tests/RunCMake/while/EndAlone-stderr.txt | 2 +- Tests/SourceGroups/CMakeLists.txt | 13 +- Tests/SourceGroups/main.c | 7 + Tests/SourceGroups/sub1/tree_bar.c | 4 + Tests/SourceGroups/sub1/tree_baz.c | 4 + Tests/SourceGroups/sub1/tree_subdir/tree_foobar.c | 4 + Tests/SourceGroups/tree_foo.c | 4 + Tests/SwigTest/CMakeLists.txt | 13 +- Utilities/.gitattributes | 1 + Utilities/CMakeLists.txt | 2 +- Utilities/Git/pre-commit | 15 +- Utilities/GitSetup/.gitattributes | 5 +- Utilities/GitSetup/README | 7 + Utilities/GitSetup/config | 2 +- Utilities/GitSetup/config.sample | 10 + Utilities/GitSetup/git-gerrit-push | 74 + Utilities/GitSetup/git-gitlab-push | 177 + Utilities/GitSetup/setup-gerrit | 15 +- Utilities/GitSetup/setup-gitlab | 140 + Utilities/GitSetup/setup-hooks | 1 + Utilities/GitSetup/setup-stage | 9 +- Utilities/GitSetup/setup-upstream | 104 + Utilities/KWStyle/CMake.kws.xml.in | 11 - Utilities/KWStyle/CMakeFiles.txt.in | 15 - Utilities/KWStyle/CMakeLists.txt | 69 - Utilities/KWStyle/CMakeMoreChecks.kws.xml.in | 30 - Utilities/Release/README | 2 +- Utilities/Release/WiX/WIX.template.in | 13 +- Utilities/Release/linux64_release.cmake | 7 +- Utilities/Release/osx_release.cmake | 2 +- Utilities/Release/upload_release.cmake | 2 +- Utilities/Scripts/clang-format.bash | 3 +- Utilities/Scripts/update-curl.bash | 2 +- Utilities/Scripts/update-gitsetup.bash | 20 + Utilities/Scripts/update-kwsys.bash | 2 +- Utilities/Scripts/update-librhash.bash | 45 + Utilities/SetupForDevelopment.sh | 4 + Utilities/cmThirdParty.h.in | 1 + Utilities/cm_rhash.h | 14 + Utilities/cmcurl/CMake/CurlSymbolHiding.cmake | 61 + Utilities/cmcurl/CMake/FindNGHTTP2.cmake | 18 + Utilities/cmcurl/CMakeLists.txt | 100 +- Utilities/cmcurl/include/curl/curl.h | 11 +- Utilities/cmcurl/include/curl/curlver.h | 8 +- Utilities/cmcurl/lib/CMakeLists.txt | 5 + Utilities/cmcurl/lib/Makefile.inc | 8 +- Utilities/cmcurl/lib/amigaos.c | 2 +- Utilities/cmcurl/lib/base64.c | 5 + Utilities/cmcurl/lib/conncache.c | 1 - Utilities/cmcurl/lib/connect.c | 33 +- Utilities/cmcurl/lib/connect.h | 40 +- Utilities/cmcurl/lib/cookie.c | 128 +- Utilities/cmcurl/lib/cookie.h | 4 +- Utilities/cmcurl/lib/curl_config.h.cmake | 8 +- Utilities/cmcurl/lib/curl_ntlm_core.c | 37 +- Utilities/cmcurl/lib/curl_sasl.c | 12 +- Utilities/cmcurl/lib/curl_setup.h | 24 +- Utilities/cmcurl/lib/curl_sspi.c | 20 +- Utilities/cmcurl/lib/curlx.h | 13 +- Utilities/cmcurl/lib/dict.c | 25 +- Utilities/cmcurl/lib/easy.c | 40 +- Utilities/cmcurl/lib/escape.c | 34 +- Utilities/cmcurl/lib/file.c | 11 +- Utilities/cmcurl/lib/formdata.c | 62 +- Utilities/cmcurl/lib/formdata.h | 1 + Utilities/cmcurl/lib/ftp.c | 107 +- Utilities/cmcurl/lib/ftp.h | 4 +- Utilities/cmcurl/lib/ftplistparser.c | 3 +- Utilities/cmcurl/lib/getenv.c | 3 +- Utilities/cmcurl/lib/getinfo.c | 19 +- Utilities/cmcurl/lib/gopher.c | 37 +- Utilities/cmcurl/lib/hostcheck.c | 14 +- Utilities/cmcurl/lib/hostip.c | 7 +- Utilities/cmcurl/lib/http.c | 282 +- Utilities/cmcurl/lib/http.h | 1 + Utilities/cmcurl/lib/http2.c | 172 +- Utilities/cmcurl/lib/http2.h | 6 +- Utilities/cmcurl/lib/http_digest.c | 2 +- Utilities/cmcurl/lib/http_negotiate.c | 1 - Utilities/cmcurl/lib/http_ntlm.c | 2 +- Utilities/cmcurl/lib/http_proxy.c | 18 +- Utilities/cmcurl/lib/if2ip.c | 8 +- Utilities/cmcurl/lib/imap.c | 25 +- Utilities/cmcurl/lib/krb5.c | 12 +- Utilities/cmcurl/lib/ldap.c | 59 +- Utilities/cmcurl/lib/libcurl.rc | 6 +- Utilities/cmcurl/lib/md5.c | 2 +- Utilities/cmcurl/lib/mprintf.c | 26 +- Utilities/cmcurl/lib/multi.c | 281 +- Utilities/cmcurl/lib/multiif.h | 1 + Utilities/cmcurl/lib/netrc.c | 18 +- Utilities/cmcurl/lib/parsedate.c | 20 +- Utilities/cmcurl/lib/pingpong.c | 3 +- Utilities/cmcurl/lib/pipeline.c | 12 +- Utilities/cmcurl/lib/pop3.c | 10 +- Utilities/cmcurl/lib/progress.c | 75 + Utilities/cmcurl/lib/progress.h | 6 +- Utilities/cmcurl/lib/rawstr.c | 148 - Utilities/cmcurl/lib/rawstr.h | 47 - Utilities/cmcurl/lib/rtsp.c | 22 +- Utilities/cmcurl/lib/security.c | 13 +- Utilities/cmcurl/lib/select.c | 35 +- Utilities/cmcurl/lib/select.h | 9 +- Utilities/cmcurl/lib/smb.c | 10 +- Utilities/cmcurl/lib/smtp.c | 8 +- Utilities/cmcurl/lib/socks.c | 132 +- Utilities/cmcurl/lib/ssh.c | 55 +- Utilities/cmcurl/lib/strcase.c | 166 + Utilities/cmcurl/lib/strcase.h | 50 + Utilities/cmcurl/lib/strdup.c | 4 +- Utilities/cmcurl/lib/strdup.h | 4 +- Utilities/cmcurl/lib/strequal.c | 79 - Utilities/cmcurl/lib/strequal.h | 31 - Utilities/cmcurl/lib/strerror.c | 87 +- Utilities/cmcurl/lib/strerror.h | 4 +- Utilities/cmcurl/lib/system_win32.c | 39 +- Utilities/cmcurl/lib/telnet.c | 13 +- Utilities/cmcurl/lib/tftp.c | 31 +- Utilities/cmcurl/lib/transfer.c | 103 +- Utilities/cmcurl/lib/transfer.h | 8 +- Utilities/cmcurl/lib/url.c | 243 +- Utilities/cmcurl/lib/urldata.h | 15 +- Utilities/cmcurl/lib/vauth/cleartext.c | 2 - Utilities/cmcurl/lib/vauth/digest.c | 48 +- Utilities/cmcurl/lib/vauth/digest_sspi.c | 25 +- Utilities/cmcurl/lib/vauth/krb5_gssapi.c | 14 + Utilities/cmcurl/lib/vauth/krb5_sspi.c | 22 + Utilities/cmcurl/lib/vauth/ntlm.c | 14 + Utilities/cmcurl/lib/vauth/ntlm_sspi.c | 21 + Utilities/cmcurl/lib/vauth/spnego_gssapi.c | 14 + Utilities/cmcurl/lib/vauth/spnego_sspi.c | 26 +- Utilities/cmcurl/lib/vauth/vauth.c | 41 + Utilities/cmcurl/lib/vauth/vauth.h | 15 + Utilities/cmcurl/lib/version.c | 14 +- Utilities/cmcurl/lib/vtls/axtls.c | 3 +- Utilities/cmcurl/lib/vtls/cyassl.c | 9 +- Utilities/cmcurl/lib/vtls/darwinssl.c | 24 +- Utilities/cmcurl/lib/vtls/gskit.c | 10 +- Utilities/cmcurl/lib/vtls/gtls.c | 12 +- Utilities/cmcurl/lib/vtls/mbedtls.c | 14 +- Utilities/cmcurl/lib/vtls/nss.c | 68 +- Utilities/cmcurl/lib/vtls/openssl.c | 108 +- Utilities/cmcurl/lib/vtls/polarssl.c | 80 +- Utilities/cmcurl/lib/vtls/polarssl_threadlock.c | 4 +- Utilities/cmcurl/lib/vtls/schannel.c | 40 +- Utilities/cmcurl/lib/vtls/vtls.c | 18 +- Utilities/cmcurl/lib/x509asn1.c | 12 +- Utilities/{cmcurl => cmlibrhash}/.gitattributes | 0 Utilities/cmlibrhash/CMakeLists.txt | 40 + Utilities/cmlibrhash/COPYING | 15 + Utilities/cmlibrhash/README | 7 + Utilities/cmlibrhash/librhash/algorithms.c | 220 + Utilities/cmlibrhash/librhash/algorithms.h | 120 + Utilities/cmlibrhash/librhash/byte_order.c | 150 + Utilities/cmlibrhash/librhash/byte_order.h | 156 + Utilities/cmlibrhash/librhash/hex.c | 188 + Utilities/cmlibrhash/librhash/hex.h | 25 + Utilities/cmlibrhash/librhash/md5.c | 236 ++ Utilities/cmlibrhash/librhash/md5.h | 31 + Utilities/cmlibrhash/librhash/rhash.c | 872 ++++ Utilities/cmlibrhash/librhash/rhash.h | 288 ++ Utilities/cmlibrhash/librhash/sha1.c | 196 + Utilities/cmlibrhash/librhash/sha1.h | 31 + Utilities/cmlibrhash/librhash/sha256.c | 241 ++ Utilities/cmlibrhash/librhash/sha256.h | 32 + Utilities/cmlibrhash/librhash/sha3.c | 356 ++ Utilities/cmlibrhash/librhash/sha3.h | 54 + Utilities/cmlibrhash/librhash/sha512.c | 255 ++ Utilities/cmlibrhash/librhash/sha512.h | 32 + Utilities/cmlibrhash/librhash/ustd.h | 39 + Utilities/cmlibrhash/librhash/util.h | 31 + Utilities/cmlibuv/CMakeLists.txt | 10 +- Utilities/{cmcurl => cmvssetup}/.gitattributes | 0 Utilities/cmvssetup/Setup.Configuration.h | 991 +++++ bootstrap | 196 +- 1737 files changed, 51555 insertions(+), 33136 deletions(-) create mode 100644 .hooks-config delete mode 100644 .hooks-config.bash create mode 100644 Help/generator/VS_TOOLSET_HOST_ARCH.txt create mode 100644 Help/module/CPackIFWConfigureFile.rst create mode 100644 Help/policy/CMP0067.rst create mode 100644 Help/prop_gbl/XCODE_EMIT_EFFECTIVE_PLATFORM_NAME.rst create mode 100644 Help/prop_sf/SKIP_AUTOGEN.rst create mode 100644 Help/prop_sf/SKIP_AUTOMOC.rst create mode 100644 Help/prop_sf/SKIP_AUTORCC.rst create mode 100644 Help/prop_sf/SKIP_AUTOUIC.rst create mode 100644 Help/prop_sf/VS_COPY_TO_OUT_DIR.rst create mode 100644 Help/prop_sf/VS_INCLUDE_IN_VSIX.rst create mode 100644 Help/prop_sf/VS_RESOURCE_GENERATOR.rst create mode 100644 Help/prop_tgt/BUILD_RPATH.rst create mode 100644 Help/prop_tgt/CUDA_EXTENSIONS.rst create mode 100644 Help/prop_tgt/CUDA_SEPARABLE_COMPILATION.rst create mode 100644 Help/prop_tgt/CUDA_STANDARD.rst create mode 100644 Help/prop_tgt/CUDA_STANDARD_REQUIRED.rst create mode 100644 Help/prop_tgt/IMPORTED_LIBNAME.rst create mode 100644 Help/prop_tgt/IMPORTED_LIBNAME_CONFIG.rst create mode 100644 Help/prop_tgt/LANG_CPPLINT.rst create mode 100644 Help/prop_tgt/MANUALLY_ADDED_DEPENDENCIES.rst create mode 100644 Help/prop_tgt/VS_DEBUGGER_WORKING_DIRECTORY.rst create mode 100644 Help/prop_tgt/VS_DOTNET_REFERENCES_COPY_LOCAL.rst create mode 100644 Help/prop_tgt/VS_DOTNET_REFERENCE_refname.rst create mode 100644 Help/prop_tgt/VS_USER_PROPS.rst create mode 100644 Help/prop_tgt/XCODE_EXPLICIT_FILE_TYPE.rst create mode 100644 Help/prop_tgt/XCODE_PRODUCT_TYPE.rst create mode 100644 Help/release/3.8.rst create mode 100644 Help/variable/CMAKE_BUILD_RPATH.rst create mode 100644 Help/variable/CMAKE_CUDA_EXTENSIONS.rst create mode 100644 Help/variable/CMAKE_CUDA_STANDARD.rst create mode 100644 Help/variable/CMAKE_CUDA_STANDARD_REQUIRED.rst create mode 100644 Help/variable/CMAKE_LANG_CPPLINT.rst create mode 100644 Help/variable/CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS.rst create mode 100644 Help/variable/CMAKE_SUBLIME_TEXT_2_EXCLUDE_BUILD_TREE.rst create mode 100644 Help/variable/CMAKE_VS_INCLUDE_PACKAGE_TO_DEFAULT_BUILD.rst create mode 100644 Help/variable/CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE.rst create mode 100644 Modules/CMakeCSharpCompiler.cmake.in create mode 100644 Modules/CMakeCSharpCompilerId.cs.in create mode 100644 Modules/CMakeCSharpInformation.cmake create mode 100644 Modules/CMakeCUDACompiler.cmake.in create mode 100644 Modules/CMakeCUDACompilerABI.cu create mode 100644 Modules/CMakeCUDACompilerId.cu.in create mode 100644 Modules/CMakeCUDAInformation.cmake create mode 100644 Modules/CMakeDetermineCSharpCompiler.cmake create mode 100644 Modules/CMakeDetermineCUDACompiler.cmake create mode 100644 Modules/CMakeTestCSharpCompiler.cmake create mode 100644 Modules/CMakeTestCUDACompiler.cmake create mode 100644 Modules/CPackIFWConfigureFile.cmake rename Modules/Compiler/{GNU-DetermineCompiler.cmake => GNU-C-DetermineCompiler.cmake} (100%) create mode 100644 Modules/Compiler/GNU-CXX-DetermineCompiler.cmake create mode 100644 Modules/Compiler/NVIDIA-CUDA.cmake create mode 100644 Modules/Compiler/NVIDIA-DetermineCompiler.cmake create mode 100644 Modules/CompilerId/VS-10.csproj.in create mode 100644 Modules/Platform/Android-Clang-ASM.cmake create mode 100644 Modules/Platform/Darwin-PGI-C.cmake create mode 100644 Modules/Platform/Darwin-PGI-CXX.cmake create mode 100644 Modules/Platform/Darwin-PGI-Fortran.cmake create mode 100644 Modules/Platform/Darwin-PGI.cmake create mode 100644 Modules/Platform/Fuchsia.cmake create mode 100644 Modules/Platform/Windows-NVIDIA-CUDA.cmake create mode 100644 Packaging/QtSDK/ToolsCMakeXX.cmake create mode 100644 Packaging/QtSDK/qt.tools.cmake.xx.qs.in create mode 100644 Source/Modules/FindLibRHash.cmake delete mode 100644 Source/QtIFW/CMake.Dialogs.QtGUI.qs create mode 100644 Source/QtIFW/CMake.Dialogs.QtGUI.qs.in delete mode 100644 Source/cmBootstrapCommands1.cxx delete mode 100644 Source/cmBootstrapCommands2.cxx create mode 100644 Source/cmCommand.cxx create mode 100644 Source/cmCommands.cxx delete mode 100644 Source/cmCommands.cxx.in delete mode 100644 Source/cmCommandsForBootstrap.cxx create mode 100644 Source/cmConvertMSBuildXMLToJSON.py delete mode 100644 Source/cmElseCommand.cxx delete mode 100644 Source/cmElseCommand.h delete mode 100644 Source/cmElseIfCommand.cxx delete mode 100644 Source/cmElseIfCommand.h delete mode 100644 Source/cmEndForEachCommand.cxx delete mode 100644 Source/cmEndForEachCommand.h delete mode 100644 Source/cmEndFunctionCommand.cxx delete mode 100644 Source/cmEndFunctionCommand.h delete mode 100644 Source/cmEndIfCommand.cxx delete mode 100644 Source/cmEndIfCommand.h delete mode 100644 Source/cmEndMacroCommand.cxx delete mode 100644 Source/cmEndMacroCommand.h delete mode 100644 Source/cmEndWhileCommand.cxx delete mode 100644 Source/cmEndWhileCommand.h create mode 100644 Source/cmFilePathChecksum.cxx create mode 100644 Source/cmFilePathChecksum.h delete mode 100644 Source/cmFilePathUuid.cxx delete mode 100644 Source/cmFilePathUuid.h create mode 100644 Source/cmLinkLineComputer.cxx create mode 100644 Source/cmLinkLineComputer.h create mode 100644 Source/cmLinkLineDeviceComputer.cxx create mode 100644 Source/cmLinkLineDeviceComputer.h create mode 100644 Source/cmMSVC60LinkLineComputer.cxx create mode 100644 Source/cmMSVC60LinkLineComputer.h create mode 100644 Source/cmNinjaLinkLineComputer.cxx create mode 100644 Source/cmNinjaLinkLineComputer.h delete mode 100644 Source/cmObject.h create mode 100644 Source/cmProcessOutput.cxx create mode 100644 Source/cmProcessOutput.h create mode 100644 Source/cmRulePlaceholderExpander.cxx create mode 100644 Source/cmRulePlaceholderExpander.h create mode 100644 Source/cmStateDirectory.cxx create mode 100644 Source/cmStateDirectory.h create mode 100644 Source/cmStatePrivate.h create mode 100644 Source/cmStateSnapshot.cxx create mode 100644 Source/cmStateSnapshot.h create mode 100644 Source/cmStateTypes.h create mode 100644 Source/cmTargetPropertyComputer.cxx create mode 100644 Source/cmTargetPropertyComputer.h delete mode 100644 Source/cmTypeMacro.h create mode 100644 Source/cmUnexpectedCommand.cxx create mode 100644 Source/cmUnexpectedCommand.h create mode 100644 Source/cmVS10CSharpFlagTable.h create mode 100644 Source/cmVS11CSharpFlagTable.h create mode 100644 Source/cmVS12CSharpFlagTable.h create mode 100644 Source/cmVS140CSharpFlagTable.h create mode 100644 Source/cmVS141CSharpFlagTable.h create mode 100644 Source/cmVSSetupHelper.cxx create mode 100644 Source/cmVSSetupHelper.h create mode 100644 Source/cmVisualStudio10ToolsetOptions.cxx create mode 100644 Source/cmVisualStudio10ToolsetOptions.h create mode 100644 Source/cm_codecvt.cxx create mode 100644 Source/cm_codecvt.hxx delete mode 100644 Source/cm_sha2.c delete mode 100644 Source/cm_sha2.h delete mode 100644 Source/cm_sha2_mangle.h create mode 100644 Source/cm_unordered_map.hxx create mode 100644 Source/cm_unordered_set.hxx create mode 100644 Source/kwsys/README.rst delete mode 100644 Source/kwsys/README.txt create mode 100644 Tests/CMakeLib/testEncoding.cxx create mode 100644 Tests/CMakeOnly/CompilerIdCSharp/CMakeLists.txt create mode 100644 Tests/CMakeTests/File-SHA3_224-Works.cmake create mode 100644 Tests/CMakeTests/File-SHA3_256-Works.cmake create mode 100644 Tests/CMakeTests/File-SHA3_384-Works.cmake create mode 100644 Tests/CMakeTests/File-SHA3_512-Works.cmake create mode 100644 Tests/CMakeTests/String-SHA3_224-Works.cmake create mode 100644 Tests/CMakeTests/String-SHA3_256-Works.cmake create mode 100644 Tests/CMakeTests/String-SHA3_384-Works.cmake create mode 100644 Tests/CMakeTests/String-SHA3_512-Works.cmake create mode 100644 Tests/CSharpOnly/CMakeLists.txt create mode 100644 Tests/CSharpOnly/csharponly.cs create mode 100644 Tests/CSharpOnly/lib1.cs create mode 100644 Tests/CSharpOnly/lib2.cs create mode 100644 Tests/CTestTestLaunchers/launcher_compiler_test_project/CMakeLists.txt copy Tests/CTestTestLaunchers/{launcher_test_project => launcher_compiler_test_project}/CTestConfig.cmake (100%) create mode 100644 Tests/CTestTestLaunchers/launcher_compiler_test_project/build_error.cxx create mode 100644 Tests/CTestTestLaunchers/launcher_custom_command_test_project/CMakeLists.txt copy Tests/CTestTestLaunchers/{launcher_test_project => launcher_custom_command_test_project}/CTestConfig.cmake (100%) rename Tests/CTestTestLaunchers/{launcher_test_project => launcher_custom_command_test_project}/command.cmake (100%) create mode 100644 Tests/CTestTestLaunchers/launcher_linker_test_project/CMakeLists.txt rename Tests/CTestTestLaunchers/{launcher_test_project => launcher_linker_test_project}/CTestConfig.cmake (100%) create mode 100644 Tests/CTestTestLaunchers/launcher_linker_test_project/link_error.cxx delete mode 100644 Tests/CTestTestLaunchers/launcher_test_project/CMakeLists.txt create mode 100644 Tests/Cuda/CMakeLists.txt create mode 100644 Tests/Cuda/Complex/CMakeLists.txt create mode 100644 Tests/Cuda/Complex/dynamic.cpp create mode 100644 Tests/Cuda/Complex/dynamic.cu create mode 100644 Tests/Cuda/Complex/file1.cu create mode 100644 Tests/Cuda/Complex/file1.h create mode 100644 Tests/Cuda/Complex/file2.cu create mode 100644 Tests/Cuda/Complex/file2.h create mode 100644 Tests/Cuda/Complex/file3.cu create mode 100644 Tests/Cuda/Complex/main.cpp create mode 100644 Tests/Cuda/Complex/mixed.cpp create mode 100644 Tests/Cuda/Complex/mixed.cu create mode 100644 Tests/Cuda/ConsumeCompileFeatures/CMakeLists.txt create mode 100644 Tests/Cuda/ConsumeCompileFeatures/main.cu create mode 100644 Tests/Cuda/ConsumeCompileFeatures/static.cpp create mode 100644 Tests/Cuda/ConsumeCompileFeatures/static.cu create mode 100644 Tests/Cuda/ObjectLibrary/CMakeLists.txt create mode 100644 Tests/Cuda/ObjectLibrary/main.cpp create mode 100644 Tests/Cuda/ObjectLibrary/static.cpp create mode 100644 Tests/Cuda/ObjectLibrary/static.cu create mode 100644 Tests/Cuda/ProperLinkFlags/CMakeLists.txt create mode 100644 Tests/Cuda/ProperLinkFlags/file1.cu create mode 100644 Tests/Cuda/ProperLinkFlags/file1.h create mode 100644 Tests/Cuda/ProperLinkFlags/main.cxx create mode 100644 Tests/CudaOnly/CMakeLists.txt create mode 100644 Tests/CudaOnly/EnableStandard/CMakeLists.txt create mode 100644 Tests/CudaOnly/EnableStandard/main.cu create mode 100644 Tests/CudaOnly/EnableStandard/shared.cu create mode 100644 Tests/CudaOnly/EnableStandard/static.cu create mode 100644 Tests/CudaOnly/SeparateCompilation/CMakeLists.txt create mode 100644 Tests/CudaOnly/SeparateCompilation/file1.cu create mode 100644 Tests/CudaOnly/SeparateCompilation/file1.h create mode 100644 Tests/CudaOnly/SeparateCompilation/file2.cu create mode 100644 Tests/CudaOnly/SeparateCompilation/file2.h create mode 100644 Tests/CudaOnly/SeparateCompilation/file3.cu create mode 100644 Tests/CudaOnly/SeparateCompilation/file4.cu create mode 100644 Tests/CudaOnly/SeparateCompilation/file5.cu create mode 100644 Tests/CudaOnly/SeparateCompilation/main.cu create mode 100644 Tests/CudaOnly/WithDefs/CMakeLists.txt create mode 100644 Tests/CudaOnly/WithDefs/main.notcu create mode 100644 Tests/CustomCommand/compare_options.cmake create mode 100644 Tests/FindLibRHash/CMakeLists.txt create mode 100644 Tests/FindLibRHash/Test/CMakeLists.txt create mode 100644 Tests/FindLibRHash/Test/main.c create mode 100644 Tests/FindOpenGL/CMakeLists.txt create mode 100644 Tests/FindOpenGL/Test/CMakeLists.txt create mode 100644 Tests/FindOpenGL/Test/main.c create mode 100644 Tests/InterfaceLibrary/item.cpp create mode 100644 Tests/InterfaceLibrary/item_fake.cpp create mode 100644 Tests/Module/ExternalData/MultipleAlgorithmNoMD5.dat.md5 copy Tests/Module/ExternalData/{SeriesMixed.2.dat.sha1 => MultipleAlgorithmNoMD5.dat.sha1} (100%) copy Tests/Module/ExternalData/{MetaTop.dat.md5 => MultipleAlgorithmNoSHA1.dat.md5} (100%) create mode 100644 Tests/Module/ExternalData/MultipleAlgorithmNoSHA1.dat.sha1 copy Tests/Module/ExternalData/{MD5 => SHA3_256}/.gitattributes (100%) create mode 100644 Tests/Module/ExternalData/SHA3_256/c01b0bfd51ece4295c7b45493750a3612ecc483095eb1366f9f46b179550e231 create mode 100644 Tests/Module/ExternalData/SeriesMixed.5.dat.sha3-256 delete mode 100644 Tests/QtAutogen/Bdir/CMakeLists.txt rename Tests/QtAutogen/{ => complex}/Adir/CMakeLists.txt (100%) rename Tests/QtAutogen/{ => complex}/Adir/libA.cpp (100%) rename Tests/QtAutogen/{ => complex}/Adir/libA.h (100%) create mode 100644 Tests/QtAutogen/complex/Bdir/CMakeLists.txt rename Tests/QtAutogen/{ => complex}/Bdir/libB.cpp (100%) rename Tests/QtAutogen/{ => complex}/Bdir/libB.h (100%) create mode 100644 Tests/QtAutogen/complex/CMakeLists.txt rename Tests/QtAutogen/{ => complex}/abc.cpp (100%) rename Tests/QtAutogen/{ => complex}/abc.h (100%) rename Tests/QtAutogen/{ => complex}/abc_p.h (100%) rename Tests/QtAutogen/{ => complex}/bar.cpp (100%) rename Tests/QtAutogen/{ => complex}/blub.cpp (100%) rename Tests/QtAutogen/{ => complex}/blub.h (100%) rename Tests/QtAutogen/{ => complex}/calwidget.cpp (100%) rename Tests/QtAutogen/{ => complex}/calwidget.h (100%) rename Tests/QtAutogen/{ => complex}/calwidget.ui (100%) rename Tests/QtAutogen/{ => complex}/codeeditor.cpp (100%) rename Tests/QtAutogen/{ => complex}/codeeditor.h (100%) rename Tests/QtAutogen/{ => complex}/debug_class.cpp (100%) rename Tests/QtAutogen/{ => complex}/debug_class.h (100%) rename Tests/QtAutogen/{ => complex}/debug_class.ui (100%) rename Tests/QtAutogen/{ => complex}/debug_resource.qrc (100%) rename Tests/QtAutogen/{ => complex}/foo.cpp (100%) rename Tests/QtAutogen/{ => complex}/foo.h (100%) rename Tests/QtAutogen/{ => complex}/gadget.cpp (100%) rename Tests/QtAutogen/{ => complex}/gadget.h (100%) rename Tests/QtAutogen/{ => complex}/generated.cpp (100%) rename Tests/QtAutogen/{ => complex}/generated.h (100%) rename Tests/QtAutogen/{ => complex}/generated.txt.in (100%) rename Tests/QtAutogen/{ => complex}/generated_resource.qrc.in (100%) rename Tests/QtAutogen/{ => complex}/libC.cpp (100%) rename Tests/QtAutogen/{ => complex}/libC.h (100%) rename Tests/QtAutogen/{ => complex}/main.cpp (100%) rename Tests/QtAutogen/{ => complex}/multiplewidgets.cpp (100%) rename Tests/QtAutogen/{ => complex}/multiplewidgets.h (100%) rename Tests/QtAutogen/{ => complex}/myinterface.h.in (100%) rename Tests/QtAutogen/{ => complex}/myotherinterface.h.in (100%) rename Tests/QtAutogen/{ => complex}/private_slot.cpp (100%) rename Tests/QtAutogen/{ => complex}/private_slot.h (100%) rename Tests/QtAutogen/{ => complex}/resourcetester.cpp (100%) rename Tests/QtAutogen/{ => complex}/resourcetester.h (100%) rename Tests/QtAutogen/{ => complex}/second_resource.qrc (100%) rename Tests/QtAutogen/{ => complex}/second_widget.cpp (100%) rename Tests/QtAutogen/{ => complex}/second_widget.h (100%) rename Tests/QtAutogen/{ => complex}/second_widget.ui (100%) rename Tests/QtAutogen/{ => complex}/sub/bar.h (100%) rename Tests/QtAutogen/{ => complex}/targetObjectsTest.cpp (100%) rename Tests/QtAutogen/{ => complex}/test.qrc (100%) rename Tests/QtAutogen/{ => complex}/widget1.ui (100%) rename Tests/QtAutogen/{ => complex}/widget2.ui (100%) rename Tests/QtAutogen/{ => complex}/xyz.cpp (100%) rename Tests/QtAutogen/{ => complex}/xyz.h (100%) rename Tests/QtAutogen/{ => complex}/yaf.cpp (100%) rename Tests/QtAutogen/{ => complex}/yaf.h (100%) rename Tests/QtAutogen/{ => complex}/yaf_p.h (100%) create mode 100644 Tests/QtAutogen/rccEmpty.cpp rename Tests/QtAutogen/{rcc_empty_resource.qrc => rccEmptyRes.qrc} (100%) create mode 100644 Tests/QtAutogen/rccOnly.cpp create mode 100644 Tests/QtAutogen/rccOnlyRes.qrc delete mode 100644 Tests/QtAutogen/rcc_empty.cpp delete mode 100644 Tests/QtAutogen/rcconly.cpp create mode 100644 Tests/QtAutogen/skipMoc.cpp create mode 100644 Tests/QtAutogen/skipRcc.cpp create mode 100644 Tests/QtAutogen/skipSource/qItemA.cpp create mode 100644 Tests/QtAutogen/skipSource/qItemA.hpp create mode 100644 Tests/QtAutogen/skipSource/qItemB.cpp create mode 100644 Tests/QtAutogen/skipSource/qItemB.hpp create mode 100644 Tests/QtAutogen/skipSource/qItemC.cpp create mode 100644 Tests/QtAutogen/skipSource/qItemC.hpp create mode 100644 Tests/QtAutogen/skipSource/skipRccBad1.qrc create mode 100644 Tests/QtAutogen/skipSource/skipRccBad2.qrc create mode 100644 Tests/QtAutogen/skipSource/skipRccGood.qrc create mode 100644 Tests/QtAutogen/skipSource/skipUicGen.cpp create mode 100644 Tests/QtAutogen/skipSource/skipUicGen.hpp create mode 100644 Tests/QtAutogen/skipSource/skipUicNoGen1.cpp create mode 100644 Tests/QtAutogen/skipSource/skipUicNoGen1.hpp create mode 100644 Tests/QtAutogen/skipSource/skipUicNoGen2.cpp create mode 100644 Tests/QtAutogen/skipSource/skipUicNoGen2.hpp create mode 100644 Tests/QtAutogen/skipSource/ui_nogen1.h create mode 100644 Tests/QtAutogen/skipSource/ui_nogen2.h create mode 100644 Tests/QtAutogen/skipSource/uigen1.ui create mode 100644 Tests/QtAutogen/skipSource/uigen2.ui create mode 100644 Tests/QtAutogen/skipUic.cpp delete mode 100644 Tests/QtAutogen/sub/uiconly.cpp delete mode 100644 Tests/QtAutogen/sub/uiconly.h create mode 100644 Tests/QtAutogen/uicOnlySource/uiconly.cpp create mode 100644 Tests/QtAutogen/uicOnlySource/uiconly.h rename Tests/QtAutogen/{sub => uicOnlySource}/uiconly.ui (100%) create mode 100644 Tests/RunCMake/AndroidTestUtilities/SetupTest4.cmake copy Tests/RunCMake/AndroidTestUtilities/{SetupTest1Build-check.cmake => SetupTest4Build-check.cmake} (100%) create mode 100644 Tests/RunCMake/CPack/7Z/Helpers.cmake copy Tests/RunCMake/CPack/{TGZ => 7Z}/Prerequirements.cmake (100%) copy Tests/RunCMake/CPack/{TGZ/COMPONENTS_EMPTY_DIR-specifics.cmake => 7Z/packaging_COMPONENT_default.cmake} (100%) create mode 100644 Tests/RunCMake/CPack/ArchiveCommon/common_helpers.cmake delete mode 100644 Tests/RunCMake/CPack/COMPONENTS_EMPTY_DIR.cmake delete mode 100644 Tests/RunCMake/CPack/CUSTOM_NAMES.cmake delete mode 100644 Tests/RunCMake/CPack/DEB/COMPONENTS_EMPTY_DIR-ExpectedFiles.cmake delete mode 100644 Tests/RunCMake/CPack/DEB/COMPONENTS_EMPTY_DIR-specifics.cmake delete mode 100644 Tests/RunCMake/CPack/DEB/CUSTOM_NAMES-ExpectedFiles.cmake delete mode 100644 Tests/RunCMake/CPack/DEB/CUSTOM_NAMES-specifics.cmake delete mode 100644 Tests/RunCMake/CPack/DEB/DEB_EXTRA-ExpectedFiles.cmake delete mode 100644 Tests/RunCMake/CPack/DEB/DEB_GENERATE_SHLIBS-ExpectedFiles.cmake delete mode 100644 Tests/RunCMake/CPack/DEB/DEB_GENERATE_SHLIBS-Prerequirements.cmake delete mode 100644 Tests/RunCMake/CPack/DEB/DEB_GENERATE_SHLIBS_LDCONFIG-ExpectedFiles.cmake delete mode 100644 Tests/RunCMake/CPack/DEB/DEB_GENERATE_SHLIBS_LDCONFIG-Prerequirements.cmake delete mode 100644 Tests/RunCMake/CPack/DEB/DEPENDENCIES-ExpectedFiles.cmake delete mode 100644 Tests/RunCMake/CPack/DEB/DEPENDENCIES-VerifyResult.cmake delete mode 100644 Tests/RunCMake/CPack/DEB/DEPENDENCIES-specifics.cmake delete mode 100644 Tests/RunCMake/CPack/DEB/EMPTY_DIR-ExpectedFiles.cmake delete mode 100644 Tests/RunCMake/CPack/DEB/EMPTY_DIR-specifics.cmake delete mode 100644 Tests/RunCMake/CPack/DEB/LONG_FILENAMES-ExpectedFiles.cmake delete mode 100644 Tests/RunCMake/CPack/DEB/LONG_FILENAMES-Prerequirements.cmake delete mode 100644 Tests/RunCMake/CPack/DEB/LONG_FILENAMES-specifics.cmake delete mode 100644 Tests/RunCMake/CPack/DEB/MINIMAL-ExpectedFiles.cmake delete mode 100644 Tests/RunCMake/CPack/DEB/MINIMAL-specifics.cmake delete mode 100644 Tests/RunCMake/CPack/DEB/PER_COMPONENT_FIELDS-ExpectedFiles.cmake delete mode 100644 Tests/RunCMake/CPack/DEB/PER_COMPONENT_FIELDS-VerifyResult.cmake delete mode 100644 Tests/RunCMake/CPack/DEB/PER_COMPONENT_FIELDS-specifics.cmake create mode 100644 Tests/RunCMake/CPack/DEB/packaging_COMPONENT_default.cmake create mode 100644 Tests/RunCMake/CPack/DEB/packaging_MONOLITHIC_default.cmake delete mode 100644 Tests/RunCMake/CPack/DEBUGINFO.cmake delete mode 100644 Tests/RunCMake/CPack/DEB_EXTRA.cmake delete mode 100644 Tests/RunCMake/CPack/DEB_GENERATE_SHLIBS.cmake delete mode 100644 Tests/RunCMake/CPack/DEB_GENERATE_SHLIBS_LDCONFIG.cmake delete mode 100644 Tests/RunCMake/CPack/DEPENDENCIES.cmake delete mode 100644 Tests/RunCMake/CPack/EMPTY_DIR.cmake delete mode 100644 Tests/RunCMake/CPack/INSTALL_SCRIPTS.cmake delete mode 100644 Tests/RunCMake/CPack/LONG_FILENAMES.cmake delete mode 100644 Tests/RunCMake/CPack/MINIMAL.cmake delete mode 100644 Tests/RunCMake/CPack/PACKAGE_CHECKSUM.cmake delete mode 100644 Tests/RunCMake/CPack/PARTIALLY_RELOCATABLE_WARNING.cmake delete mode 100644 Tests/RunCMake/CPack/PER_COMPONENT_FIELDS.cmake delete mode 100644 Tests/RunCMake/CPack/RPM/COMPONENTS_EMPTY_DIR-ExpectedFiles.cmake delete mode 100644 Tests/RunCMake/CPack/RPM/COMPONENTS_EMPTY_DIR-stderr.txt delete mode 100644 Tests/RunCMake/CPack/RPM/CUSTOM_NAMES-ExpectedFiles.cmake delete mode 100644 Tests/RunCMake/CPack/RPM/CUSTOM_NAMES-specifics.cmake delete mode 100644 Tests/RunCMake/CPack/RPM/CUSTOM_NAMES-stderr.txt delete mode 100644 Tests/RunCMake/CPack/RPM/DEBUGINFO-ExpectedFiles.cmake delete mode 100644 Tests/RunCMake/CPack/RPM/DEBUGINFO-stderr.txt delete mode 100644 Tests/RunCMake/CPack/RPM/DEPENDENCIES-ExpectedFiles.cmake delete mode 100644 Tests/RunCMake/CPack/RPM/DEPENDENCIES-VerifyResult.cmake delete mode 100644 Tests/RunCMake/CPack/RPM/DEPENDENCIES-specifics.cmake delete mode 100644 Tests/RunCMake/CPack/RPM/EMPTY_DIR-ExpectedFiles.cmake delete mode 100644 Tests/RunCMake/CPack/RPM/EMPTY_DIR-stderr.txt delete mode 100644 Tests/RunCMake/CPack/RPM/INSTALL_SCRIPTS-ExpectedFiles.cmake delete mode 100644 Tests/RunCMake/CPack/RPM/INSTALL_SCRIPTS-specifics.cmake delete mode 100644 Tests/RunCMake/CPack/RPM/MINIMAL-ExpectedFiles.cmake delete mode 100644 Tests/RunCMake/CPack/RPM/MINIMAL-stderr.txt delete mode 100644 Tests/RunCMake/CPack/RPM/PARTIALLY_RELOCATABLE_WARNING-ExpectedFiles.cmake delete mode 100644 Tests/RunCMake/CPack/RPM/PER_COMPONENT_FIELDS-ExpectedFiles.cmake delete mode 100644 Tests/RunCMake/CPack/RPM/PER_COMPONENT_FIELDS-VerifyResult.cmake delete mode 100644 Tests/RunCMake/CPack/RPM/PER_COMPONENT_FIELDS-specifics.cmake delete mode 100644 Tests/RunCMake/CPack/RPM/RPM_DIST-ExpectedFiles.cmake delete mode 100644 Tests/RunCMake/CPack/RPM/SOURCE_PACKAGE-ExpectedFiles.cmake delete mode 100644 Tests/RunCMake/CPack/RPM/SOURCE_PACKAGE-VerifyResult.cmake create mode 100644 Tests/RunCMake/CPack/RPM/default_expected_stderr.txt create mode 100644 Tests/RunCMake/CPack/RPM/packaging_COMPONENT_default.cmake delete mode 100644 Tests/RunCMake/CPack/RPM_DIST.cmake delete mode 100644 Tests/RunCMake/CPack/SOURCE_PACKAGE.cmake create mode 100644 Tests/RunCMake/CPack/STGZ/Helpers.cmake create mode 100644 Tests/RunCMake/CPack/STGZ/Prerequirements.cmake copy Tests/RunCMake/CPack/{TGZ/COMPONENTS_EMPTY_DIR-specifics.cmake => STGZ/packaging_COMPONENT_default.cmake} (100%) create mode 100644 Tests/RunCMake/CPack/TBZ2/Helpers.cmake copy Tests/RunCMake/CPack/{TGZ => TBZ2}/Prerequirements.cmake (100%) copy Tests/RunCMake/CPack/{TGZ/COMPONENTS_EMPTY_DIR-specifics.cmake => TBZ2/packaging_COMPONENT_default.cmake} (100%) delete mode 100644 Tests/RunCMake/CPack/TGZ/COMPONENTS_EMPTY_DIR-ExpectedFiles.cmake delete mode 100644 Tests/RunCMake/CPack/TGZ/EMPTY_DIR-ExpectedFiles.cmake delete mode 100644 Tests/RunCMake/CPack/TGZ/MINIMAL-ExpectedFiles.cmake delete mode 100644 Tests/RunCMake/CPack/TGZ/PACKAGE_CHECKSUM-ExpectedFiles.cmake delete mode 100644 Tests/RunCMake/CPack/TGZ/PACKAGE_CHECKSUM-VerifyResult.cmake copy Tests/RunCMake/CPack/TGZ/{COMPONENTS_EMPTY_DIR-specifics.cmake => packaging_COMPONENT_default.cmake} (100%) create mode 100644 Tests/RunCMake/CPack/TXZ/Helpers.cmake copy Tests/RunCMake/CPack/{TGZ => TXZ}/Prerequirements.cmake (100%) copy Tests/RunCMake/CPack/{TGZ/COMPONENTS_EMPTY_DIR-specifics.cmake => TXZ/packaging_COMPONENT_default.cmake} (100%) create mode 100644 Tests/RunCMake/CPack/TZ/Helpers.cmake copy Tests/RunCMake/CPack/{TGZ => TZ}/Prerequirements.cmake (100%) copy Tests/RunCMake/CPack/{TGZ/COMPONENTS_EMPTY_DIR-specifics.cmake => TZ/packaging_COMPONENT_default.cmake} (100%) create mode 100644 Tests/RunCMake/CPack/ZIP/Helpers.cmake copy Tests/RunCMake/CPack/{TGZ => ZIP}/Prerequirements.cmake (100%) rename Tests/RunCMake/CPack/{TGZ/COMPONENTS_EMPTY_DIR-specifics.cmake => ZIP/packaging_COMPONENT_default.cmake} (100%) create mode 100644 Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/ExpectedFiles.cmake create mode 100644 Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/RPM-COMPONENT-stderr.txt create mode 100644 Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/RPM-MONOLITHIC-stderr.txt create mode 100644 Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/custom.spec.in create mode 100644 Tests/RunCMake/CPack/tests/CUSTOM_BINARY_SPEC_FILE/test.cmake create mode 100644 Tests/RunCMake/CPack/tests/CUSTOM_NAMES/ExpectedFiles.cmake create mode 100644 Tests/RunCMake/CPack/tests/CUSTOM_NAMES/test.cmake create mode 100644 Tests/RunCMake/CPack/tests/DEBUGINFO/ExpectedFiles.cmake create mode 100644 Tests/RunCMake/CPack/tests/DEBUGINFO/test.cmake create mode 100644 Tests/RunCMake/CPack/tests/DEPENDENCIES/DEB-stderr.txt create mode 100644 Tests/RunCMake/CPack/tests/DEPENDENCIES/ExpectedFiles.cmake create mode 100644 Tests/RunCMake/CPack/tests/DEPENDENCIES/VerifyResult.cmake create mode 100644 Tests/RunCMake/CPack/tests/DEPENDENCIES/test.cmake create mode 100644 Tests/RunCMake/CPack/tests/DIST/ExpectedFiles.cmake rename Tests/RunCMake/CPack/{RPM/RPM_DIST-VerifyResult.cmake => tests/DIST/VerifyResult.cmake} (100%) create mode 100644 Tests/RunCMake/CPack/tests/DIST/test.cmake create mode 100644 Tests/RunCMake/CPack/tests/EMPTY_DIR/ExpectedFiles.cmake create mode 100644 Tests/RunCMake/CPack/tests/EMPTY_DIR/test.cmake create mode 100644 Tests/RunCMake/CPack/tests/EXTRA/ExpectedFiles.cmake rename Tests/RunCMake/CPack/{DEB/DEB_EXTRA-VerifyResult.cmake => tests/EXTRA/VerifyResult.cmake} (100%) create mode 100644 Tests/RunCMake/CPack/tests/EXTRA/test.cmake create mode 100644 Tests/RunCMake/CPack/tests/GENERATE_SHLIBS/DEB-Prerequirements.cmake create mode 100644 Tests/RunCMake/CPack/tests/GENERATE_SHLIBS/ExpectedFiles.cmake rename Tests/RunCMake/CPack/{DEB/DEB_GENERATE_SHLIBS-VerifyResult.cmake => tests/GENERATE_SHLIBS/VerifyResult.cmake} (100%) create mode 100644 Tests/RunCMake/CPack/tests/GENERATE_SHLIBS/test.cmake create mode 100644 Tests/RunCMake/CPack/tests/GENERATE_SHLIBS_LDCONFIG/DEB-Prerequirements.cmake create mode 100644 Tests/RunCMake/CPack/tests/GENERATE_SHLIBS_LDCONFIG/ExpectedFiles.cmake rename Tests/RunCMake/CPack/{DEB/DEB_GENERATE_SHLIBS_LDCONFIG-VerifyResult.cmake => tests/GENERATE_SHLIBS_LDCONFIG/VerifyResult.cmake} (100%) create mode 100644 Tests/RunCMake/CPack/tests/GENERATE_SHLIBS_LDCONFIG/test.cmake create mode 100644 Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/ExpectedFiles.cmake rename Tests/RunCMake/CPack/{RPM/INSTALL_SCRIPTS-VerifyResult.cmake => tests/INSTALL_SCRIPTS/VerifyResult.cmake} (100%) create mode 100644 Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/test.cmake create mode 100644 Tests/RunCMake/CPack/tests/LONG_FILENAMES/DEB-Prerequirements.cmake create mode 100644 Tests/RunCMake/CPack/tests/LONG_FILENAMES/ExpectedFiles.cmake rename Tests/RunCMake/CPack/{DEB/LONG_FILENAMES-VerifyResult.cmake => tests/LONG_FILENAMES/VerifyResult.cmake} (100%) create mode 100644 Tests/RunCMake/CPack/tests/LONG_FILENAMES/test.cmake create mode 100644 Tests/RunCMake/CPack/tests/MAIN_COMPONENT/ExpectedFiles.cmake create mode 100644 Tests/RunCMake/CPack/tests/MAIN_COMPONENT/RPM-invalid-stderr.txt create mode 100644 Tests/RunCMake/CPack/tests/MAIN_COMPONENT/test.cmake create mode 100644 Tests/RunCMake/CPack/tests/MD5SUMS/ExpectedFiles.cmake create mode 100644 Tests/RunCMake/CPack/tests/MD5SUMS/VerifyResult.cmake create mode 100644 Tests/RunCMake/CPack/tests/MD5SUMS/test.cmake create mode 100644 Tests/RunCMake/CPack/tests/MINIMAL/ExpectedFiles.cmake create mode 100644 Tests/RunCMake/CPack/tests/MINIMAL/test.cmake create mode 100644 Tests/RunCMake/CPack/tests/PACKAGE_CHECKSUM/ExpectedFiles.cmake rename Tests/RunCMake/CPack/{TGZ/PACKAGE_CHECKSUM-invalid-stderr.txt => tests/PACKAGE_CHECKSUM/TGZ-invalid-stderr.txt} (100%) create mode 100644 Tests/RunCMake/CPack/tests/PACKAGE_CHECKSUM/VerifyResult.cmake create mode 100644 Tests/RunCMake/CPack/tests/PACKAGE_CHECKSUM/test.cmake create mode 100644 Tests/RunCMake/CPack/tests/PARTIALLY_RELOCATABLE_WARNING/ExpectedFiles.cmake rename Tests/RunCMake/CPack/{RPM/PARTIALLY_RELOCATABLE_WARNING-stderr.txt => tests/PARTIALLY_RELOCATABLE_WARNING/RPM-stderr.txt} (100%) create mode 100644 Tests/RunCMake/CPack/tests/PARTIALLY_RELOCATABLE_WARNING/test.cmake create mode 100644 Tests/RunCMake/CPack/tests/PER_COMPONENT_FIELDS/ExpectedFiles.cmake create mode 100644 Tests/RunCMake/CPack/tests/PER_COMPONENT_FIELDS/VerifyResult.cmake create mode 100644 Tests/RunCMake/CPack/tests/PER_COMPONENT_FIELDS/test.cmake create mode 100644 Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/ExpectedFiles.cmake create mode 100644 Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/RPM-no_main_component-stderr.txt create mode 100644 Tests/RunCMake/CPack/tests/SINGLE_DEBUGINFO/test.cmake create mode 100644 Tests/RunCMake/CPack/tests/SOURCE_PACKAGE/ExpectedFiles.cmake create mode 100644 Tests/RunCMake/CPack/tests/SOURCE_PACKAGE/VerifyResult.cmake create mode 100644 Tests/RunCMake/CPack/tests/SOURCE_PACKAGE/test.cmake create mode 100644 Tests/RunCMake/CPack/tests/SUGGESTS/ExpectedFiles.cmake create mode 100644 Tests/RunCMake/CPack/tests/SUGGESTS/RPM-stderr.txt create mode 100644 Tests/RunCMake/CPack/tests/SUGGESTS/VerifyResult.cmake create mode 100644 Tests/RunCMake/CPack/tests/SUGGESTS/test.cmake create mode 100644 Tests/RunCMake/CPack/tests/USER_FILELIST/ExpectedFiles.cmake create mode 100644 Tests/RunCMake/CPack/tests/USER_FILELIST/VerifyResult.cmake create mode 100644 Tests/RunCMake/CPack/tests/USER_FILELIST/test.cmake copy Tests/RunCMake/{CMP0060/CMP0060-OLD-Build-result.txt => ClangTidy/C-bad-Build-result.txt} (100%) create mode 100644 Tests/RunCMake/ClangTidy/C-bad-Build-stdout.txt create mode 100644 Tests/RunCMake/ClangTidy/C-bad.cmake create mode 100644 Tests/RunCMake/Configure/RemoveCache-stdout.txt create mode 100644 Tests/RunCMake/Configure/RemoveCache.cmake create mode 100644 Tests/RunCMake/Cpplint/C-Build-stdout.txt copy Tests/RunCMake/{CMP0060/CMP0060-OLD-Build-result.txt => Cpplint/C-error-Build-result.txt} (100%) create mode 100644 Tests/RunCMake/Cpplint/C-error-Build-stdout.txt copy Tests/RunCMake/{CMP0060/CMP0060-OLD-Build-result.txt => Cpplint/C-error-launch-Build-result.txt} (100%) create mode 100644 Tests/RunCMake/Cpplint/C-error-launch-Build-stdout.txt create mode 100644 Tests/RunCMake/Cpplint/C-error-launch.cmake create mode 100644 Tests/RunCMake/Cpplint/C-error.cmake create mode 100644 Tests/RunCMake/Cpplint/C-launch-Build-stdout.txt copy Tests/RunCMake/{ClangTidy => Cpplint}/C-launch.cmake (100%) create mode 100644 Tests/RunCMake/Cpplint/C.cmake create mode 100644 Tests/RunCMake/Cpplint/CMakeLists.txt create mode 100644 Tests/RunCMake/Cpplint/CXX-Build-stdout.txt copy Tests/RunCMake/{CMP0060/CMP0060-OLD-Build-result.txt => Cpplint/CXX-error-Build-result.txt} (100%) create mode 100644 Tests/RunCMake/Cpplint/CXX-error-Build-stdout.txt copy Tests/RunCMake/{CMP0060/CMP0060-OLD-Build-result.txt => Cpplint/CXX-error-launch-Build-result.txt} (100%) create mode 100644 Tests/RunCMake/Cpplint/CXX-error-launch-Build-stdout.txt create mode 100644 Tests/RunCMake/Cpplint/CXX-error-launch.cmake create mode 100644 Tests/RunCMake/Cpplint/CXX-error.cmake create mode 100644 Tests/RunCMake/Cpplint/CXX-launch-Build-stdout.txt copy Tests/RunCMake/{ClangTidy => Cpplint}/CXX-launch.cmake (100%) create mode 100644 Tests/RunCMake/Cpplint/CXX.cmake create mode 100644 Tests/RunCMake/Cpplint/RunCMakeTest.cmake copy Tests/{CMakeOnly/LinkInterfaceLoop => RunCMake/Cpplint}/main.c (100%) copy Tests/RunCMake/{ClangTidy => Cpplint}/main.cxx (100%) create mode 100644 Tests/RunCMake/CrosscompilingEmulator/generated_exe_emulator_unexpected.cxx delete mode 100644 Tests/RunCMake/CrosscompilingEmulator/simple_src_exitsuccess.cxx copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => FeatureSummary/FeatureSummaryCustomBadDefault-result.txt} (100%) create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryCustomBadDefault-stderr.txt create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryCustomBadDefault.cmake copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => FeatureSummary/FeatureSummaryCustomRequired-result.txt} (100%) create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryCustomRequired-stderr.txt create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryCustomRequired-stdout.txt create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryCustomRequired.cmake copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => FeatureSummary/FeatureSummaryCustomRequiredListA-result.txt} (100%) create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryCustomRequiredListA-stderr.txt create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryCustomRequiredListA-stdout.txt create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryCustomRequiredListA.cmake copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => FeatureSummary/FeatureSummaryCustomRequiredListB-result.txt} (100%) create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryCustomRequiredListB-stderr.txt create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryCustomRequiredListB-stdout.txt create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryCustomRequiredListB.cmake create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryCustomTypes-stdout.txt create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryCustomTypes.cmake copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => FeatureSummary/FeatureSummaryFatalOnMissingRequiredPackages-result.txt} (100%) create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryFatalOnMissingRequiredPackages-stderr.txt create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryFatalOnMissingRequiredPackages-stdout.txt create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryFatalOnMissingRequiredPackages.cmake create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryIncludeQuietPackages-stdout.txt create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryIncludeQuietPackages.cmake create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryMultipleDepends-stdout.txt create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryMultipleDepends.cmake create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryPurpose-stdout.txt create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryPurpose.cmake create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryQuietOnEmpty-stdout.txt create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryQuietOnEmpty.cmake create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryTypes-stdout.txt create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryTypes.cmake create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryURLDescription-stdout.txt create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryURLDescription.cmake create mode 100644 Tests/RunCMake/FeatureSummary/FindBar.cmake create mode 100644 Tests/RunCMake/FeatureSummary/FindBaz.cmake create mode 100644 Tests/RunCMake/FeatureSummary/FindFoo.cmake copy Tests/RunCMake/{ClangTidy => FindGTK2}/CMakeLists.txt (100%) create mode 100644 Tests/RunCMake/FindGTK2/FindGTK2RunTwice.cmake create mode 100644 Tests/RunCMake/FindGTK2/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/Framework/FrameworkTypeSHARED-build-stdout.txt create mode 100644 Tests/RunCMake/Framework/FrameworkTypeSTATIC-build-stdout.txt copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => GeneratorExpression/BadIF-result.txt} (100%) create mode 100644 Tests/RunCMake/GeneratorExpression/BadIF-stderr.txt create mode 100644 Tests/RunCMake/GeneratorExpression/BadIF.cmake copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => GeneratorToolset/BadToolsetHostArch-result.txt} (100%) create mode 100644 Tests/RunCMake/GeneratorToolset/BadToolsetHostArch-stderr.txt copy Tests/RunCMake/{GeneratorPlatform/BadPlatform.cmake => GeneratorToolset/BadToolsetHostArch.cmake} (100%) create mode 100644 Tests/RunCMake/GeneratorToolset/TestToolsetHostArchBoth-stdout.txt create mode 100644 Tests/RunCMake/GeneratorToolset/TestToolsetHostArchBoth.cmake create mode 100644 Tests/RunCMake/GeneratorToolset/TestToolsetHostArchNone-stdout.txt create mode 100644 Tests/RunCMake/GeneratorToolset/TestToolsetHostArchNone.cmake create mode 100644 Tests/RunCMake/GeneratorToolset/TestToolsetHostArchOnly-stdout.txt create mode 100644 Tests/RunCMake/GeneratorToolset/TestToolsetHostArchOnly.cmake copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => Ninja/NinjaToolMissing-result.txt} (100%) create mode 100644 Tests/RunCMake/Ninja/NinjaToolMissing-stderr.txt copy Modules/IntelVSImplicitPath/hello.f => Tests/RunCMake/Ninja/NinjaToolMissing.cmake (100%) create mode 100644 Tests/RunCMake/VS10Project/VsCustomProps-check.cmake create mode 100644 Tests/RunCMake/VS10Project/VsCustomProps.cmake create mode 100644 Tests/RunCMake/VS10Project/VsDebuggerWorkingDir-check.cmake create mode 100644 Tests/RunCMake/VS10Project/VsDebuggerWorkingDir.cmake create mode 100644 Tests/RunCMake/VS10Project/VsTargetsFileReferences-check.cmake create mode 100644 Tests/RunCMake/VS10Project/VsTargetsFileReferences.cmake copy Tests/{Visibility/bar.c => RunCMake/VS10Project/bar.cpp} (100%) create mode 100644 Tests/RunCMake/VS10Project/baz.cpp create mode 100644 Tests/RunCMake/VS10Project/my.props create mode 100644 Tests/RunCMake/VSSolution/AddPackageToDefault-check.cmake create mode 100644 Tests/RunCMake/VSSolution/AddPackageToDefault.cmake copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => XcodeProject/PerConfigPerSourceFlags-result.txt} (100%) create mode 100644 Tests/RunCMake/XcodeProject/PerConfigPerSourceFlags-stderr.txt create mode 100644 Tests/RunCMake/XcodeProject/PerConfigPerSourceFlags.cmake create mode 100644 Tests/RunCMake/XcodeProject/XcodeMultiplatform.cmake copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => add_dependencies/ReadOnlyProperty-result.txt} (100%) create mode 100644 Tests/RunCMake/add_dependencies/ReadOnlyProperty-stderr.txt create mode 100644 Tests/RunCMake/add_dependencies/ReadOnlyProperty.cmake create mode 100644 Tests/RunCMake/add_dependencies/RetrieveDependencies.cmake create mode 100644 Tests/RunCMake/add_dependencies/a.c create mode 100644 Tests/RunCMake/add_dependencies/b.c create mode 100644 Tests/RunCMake/add_dependencies/c.c create mode 100644 Tests/RunCMake/ctest_fixtures/unused-stdout.txt rename Tests/RunCMake/{ctest_submit/CDashUploadRETRY_COUNT-result.txt => ctest_memcheck/DummyAddressLeakSanitizer-result.txt} (100%) create mode 100644 Tests/RunCMake/ctest_memcheck/DummyAddressLeakSanitizer-stderr.txt copy Tests/RunCMake/ctest_memcheck/{DummyLeakSanitizer-stdout.txt => DummyAddressLeakSanitizer-stdout.txt} (100%) rename Tests/RunCMake/{ctest_submit/CDashUploadRETRY_DELAY-result.txt => ctest_memcheck/DummyLeakSanitizerPrintDefects-result.txt} (100%) create mode 100644 Tests/RunCMake/ctest_memcheck/DummyLeakSanitizerPrintDefects-stderr.txt copy Tests/RunCMake/ctest_memcheck/{DummyLeakSanitizer-stdout.txt => DummyLeakSanitizerPrintDefects-stdout.txt} (100%) copy Tests/RunCMake/{CMP0022/CMP0022-WARN-empty-old-result.txt => ctest_memcheck/DummyValgrindNoDefects-result.txt} (100%) create mode 100644 Tests/RunCMake/ctest_memcheck/DummyValgrindNoDefects-stderr.txt create mode 100644 Tests/RunCMake/ctest_memcheck/DummyValgrindNoDefects-stdout.txt create mode 100644 Tests/RunCMake/ctest_memcheck/testAddressLeakSanitizer.cmake copy Tests/RunCMake/{ctest_build/BuildFailure-result.txt => ctest_submit/CDashUploadMissingFile-result.txt} (100%) create mode 100644 Tests/RunCMake/ctest_submit/CDashUploadMissingFile-stderr.txt delete mode 100644 Tests/RunCMake/ctest_submit/CDashUploadRETRY_COUNT-stderr.txt delete mode 100644 Tests/RunCMake/ctest_submit/CDashUploadRETRY_DELAY-stderr.txt copy Tests/RunCMake/{ctest_build/BuildFailure-result.txt => ctest_submit/CDashUploadRetry-result.txt} (100%) create mode 100644 Tests/RunCMake/ctest_submit/CDashUploadRetry-stderr.txt create mode 100644 Tests/RunCMake/ctest_submit/CDashUploadRetry-stdout.txt create mode 100644 Tests/RunCMake/execute_process/CMakeLists.txt create mode 100644 Tests/RunCMake/execute_process/Encoding.cmake copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => execute_process/EncodingMissing-result.txt} (100%) create mode 100644 Tests/RunCMake/execute_process/EncodingMissing-stderr.txt create mode 100644 Tests/RunCMake/execute_process/EncodingMissing.cmake create mode 100644 Tests/RunCMake/execute_process/EncodingUTF8-stderr.txt create mode 100644 Tests/RunCMake/file/GLOB-noexp-LIST_DIRECTORIES.cmake copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => interface_library/IMPORTED_LIBNAME-bad-value-result.txt} (100%) create mode 100644 Tests/RunCMake/interface_library/IMPORTED_LIBNAME-bad-value-stderr.txt create mode 100644 Tests/RunCMake/interface_library/IMPORTED_LIBNAME-bad-value.cmake copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => interface_library/IMPORTED_LIBNAME-non-iface-result.txt} (100%) create mode 100644 Tests/RunCMake/interface_library/IMPORTED_LIBNAME-non-iface-stderr.txt create mode 100644 Tests/RunCMake/interface_library/IMPORTED_LIBNAME-non-iface.cmake copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => interface_library/IMPORTED_LIBNAME-non-imported-result.txt} (100%) create mode 100644 Tests/RunCMake/interface_library/IMPORTED_LIBNAME-non-imported-stderr.txt create mode 100644 Tests/RunCMake/interface_library/IMPORTED_LIBNAME-non-imported.cmake create mode 100644 Tests/RunCMake/pseudo_cpplint.c copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => set_property/TYPE-result.txt} (100%) create mode 100644 Tests/RunCMake/set_property/TYPE-stderr.txt create mode 100644 Tests/RunCMake/set_property/TYPE.cmake copy Tests/RunCMake/{CMP0022/CMP0022-WARN-empty-old-result.txt => string/Timestamp-result.txt} (100%) create mode 100644 Tests/RunCMake/string/Timestamp-stderr.txt create mode 100644 Tests/RunCMake/string/Timestamp.cmake copy Tests/RunCMake/{CMP0022/CMP0022-WARN-empty-old-result.txt => string/TimestampEmpty-result.txt} (100%) create mode 100644 Tests/RunCMake/string/TimestampEmpty-stderr.txt create mode 100644 Tests/RunCMake/string/TimestampEmpty.cmake create mode 100644 Tests/RunCMake/string/TimestampInvalid-result.txt create mode 100644 Tests/RunCMake/string/TimestampInvalid-stderr.txt create mode 100644 Tests/RunCMake/string/TimestampInvalid.cmake create mode 100644 Tests/RunCMake/string/TimestampInvalid2-result.txt create mode 100644 Tests/RunCMake/string/TimestampInvalid2-stderr.txt create mode 100644 Tests/RunCMake/string/TimestampInvalid2.cmake create mode 100644 Tests/RunCMake/try_compile/CMP0067-stderr.txt create mode 100644 Tests/RunCMake/try_compile/CMP0067.cmake copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => try_compile/CStandard-result.txt} (100%) create mode 100644 Tests/RunCMake/try_compile/CStandard-stderr.txt create mode 100644 Tests/RunCMake/try_compile/CStandard.cmake create mode 100644 Tests/RunCMake/try_compile/CStandardGNU.c create mode 100644 Tests/RunCMake/try_compile/CStandardGNU.cmake create mode 100644 Tests/RunCMake/try_compile/CStandardNoDefault.cmake copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => try_compile/CudaStandard-result.txt} (100%) create mode 100644 Tests/RunCMake/try_compile/CudaStandard-stderr.txt create mode 100644 Tests/RunCMake/try_compile/CudaStandard.cmake create mode 100644 Tests/RunCMake/try_compile/CudaStandardNoDefault.cmake copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => try_compile/CxxStandard-result.txt} (100%) create mode 100644 Tests/RunCMake/try_compile/CxxStandard-stderr.txt create mode 100644 Tests/RunCMake/try_compile/CxxStandard.cmake create mode 100644 Tests/RunCMake/try_compile/CxxStandardGNU.cmake create mode 100644 Tests/RunCMake/try_compile/CxxStandardGNU.cxx create mode 100644 Tests/RunCMake/try_compile/CxxStandardNoDefault.cmake create mode 100644 Tests/RunCMake/try_compile/WarnDeprecated.cmake copy Modules/DummyCXXFile.cxx => Tests/RunCMake/try_compile/src.cu (100%) copy Modules/DummyCXXFile.cxx => Tests/RunCMake/try_compile/src.cxx (100%) create mode 100644 Tests/SourceGroups/sub1/tree_bar.c create mode 100644 Tests/SourceGroups/sub1/tree_baz.c create mode 100644 Tests/SourceGroups/sub1/tree_subdir/tree_foobar.c create mode 100644 Tests/SourceGroups/tree_foo.c create mode 100755 Utilities/GitSetup/git-gerrit-push create mode 100755 Utilities/GitSetup/git-gitlab-push create mode 100755 Utilities/GitSetup/setup-gitlab create mode 100755 Utilities/GitSetup/setup-upstream delete mode 100644 Utilities/KWStyle/CMake.kws.xml.in delete mode 100644 Utilities/KWStyle/CMakeFiles.txt.in delete mode 100644 Utilities/KWStyle/CMakeLists.txt delete mode 100644 Utilities/KWStyle/CMakeMoreChecks.kws.xml.in delete mode 100644 Utilities/KWStyle/CMakeOverwrite.txt create mode 100755 Utilities/Scripts/update-gitsetup.bash create mode 100755 Utilities/Scripts/update-librhash.bash create mode 100644 Utilities/cm_rhash.h create mode 100644 Utilities/cmcurl/CMake/CurlSymbolHiding.cmake create mode 100644 Utilities/cmcurl/CMake/FindNGHTTP2.cmake delete mode 100644 Utilities/cmcurl/lib/rawstr.c delete mode 100644 Utilities/cmcurl/lib/rawstr.h create mode 100644 Utilities/cmcurl/lib/strcase.c create mode 100644 Utilities/cmcurl/lib/strcase.h delete mode 100644 Utilities/cmcurl/lib/strequal.c delete mode 100644 Utilities/cmcurl/lib/strequal.h copy Utilities/{cmcurl => cmlibrhash}/.gitattributes (100%) create mode 100644 Utilities/cmlibrhash/CMakeLists.txt create mode 100644 Utilities/cmlibrhash/COPYING create mode 100644 Utilities/cmlibrhash/README create mode 100644 Utilities/cmlibrhash/librhash/algorithms.c create mode 100644 Utilities/cmlibrhash/librhash/algorithms.h create mode 100644 Utilities/cmlibrhash/librhash/byte_order.c create mode 100644 Utilities/cmlibrhash/librhash/byte_order.h create mode 100644 Utilities/cmlibrhash/librhash/hex.c create mode 100644 Utilities/cmlibrhash/librhash/hex.h create mode 100644 Utilities/cmlibrhash/librhash/md5.c create mode 100644 Utilities/cmlibrhash/librhash/md5.h create mode 100644 Utilities/cmlibrhash/librhash/rhash.c create mode 100644 Utilities/cmlibrhash/librhash/rhash.h create mode 100644 Utilities/cmlibrhash/librhash/sha1.c create mode 100644 Utilities/cmlibrhash/librhash/sha1.h create mode 100644 Utilities/cmlibrhash/librhash/sha256.c create mode 100644 Utilities/cmlibrhash/librhash/sha256.h create mode 100644 Utilities/cmlibrhash/librhash/sha3.c create mode 100644 Utilities/cmlibrhash/librhash/sha3.h create mode 100644 Utilities/cmlibrhash/librhash/sha512.c create mode 100644 Utilities/cmlibrhash/librhash/sha512.h create mode 100644 Utilities/cmlibrhash/librhash/ustd.h create mode 100644 Utilities/cmlibrhash/librhash/util.h copy Utilities/{cmcurl => cmvssetup}/.gitattributes (100%) create mode 100644 Utilities/cmvssetup/Setup.Configuration.h hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 6 13:10:26 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 6 Feb 2017 13:10:26 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-1311-g5e08acc Message-ID: <20170206181026.8BBE314DA@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 5e08acc89b9b28ffdab4eadc379aa9a346bd841d (commit) via c2645e1979f83b1550d977cee0cdb80122daf8e0 (commit) via 95983ed8453f9167077821aea347ba1a87e92eac (commit) from 4d505256b3e3b787f701e84717d1076a0e87ae22 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=5e08acc89b9b28ffdab4eadc379aa9a346bd841d commit 5e08acc89b9b28ffdab4eadc379aa9a346bd841d Merge: 4d50525 c2645e1 Author: Brad King AuthorDate: Mon Feb 6 13:10:20 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 6 13:10:20 2017 -0500 Merge topic 'update-kwsys' into next c2645e19 Merge branch 'upstream-KWSys' into update-kwsys 95983ed8 KWSys 2017-02-06 (ef673998) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c2645e1979f83b1550d977cee0cdb80122daf8e0 commit c2645e1979f83b1550d977cee0cdb80122daf8e0 Merge: 0f4dae0 95983ed Author: Brad King AuthorDate: Mon Feb 6 13:01:40 2017 -0500 Commit: Brad King CommitDate: Mon Feb 6 13:01:40 2017 -0500 Merge branch 'upstream-KWSys' into update-kwsys * upstream-KWSys: KWSys 2017-02-06 (ef673998) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=95983ed8453f9167077821aea347ba1a87e92eac commit 95983ed8453f9167077821aea347ba1a87e92eac Author: KWSys Upstream AuthorDate: Mon Feb 6 10:00:05 2017 -0500 Commit: Brad King CommitDate: Mon Feb 6 13:01:39 2017 -0500 KWSys 2017-02-06 (ef673998) Code extracted from: https://gitlab.kitware.com/utils/kwsys.git at commit ef6739982f686648ef5ae6902aaf5fbaad891bce (master). Upstream Shortlog ----------------- Ben Boeckel (1): 8d8c86b5 testConsoleBuf: tighten the check for the /utf-8 flag Gregor Jasny (1): d6b87625 SystemTools: Add helper function to check for FIFO file type diff --git a/CMakeLists.txt b/CMakeLists.txt index d4fe8a7..de68118 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -946,7 +946,7 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) testConsoleBuf ) IF("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC" AND - NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "19.0") + CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "19.0.23506") set_property(SOURCE testConsoleBuf.cxx testConsoleBufChild.cxx PROPERTY COMPILE_FLAGS /utf-8) ENDIF() SET_PROPERTY(SOURCE testConsoleBuf.cxx APPEND PROPERTY COMPILE_DEFINITIONS diff --git a/SystemTools.cxx b/SystemTools.cxx index 97dd4ae..8c82ec1 100644 --- a/SystemTools.cxx +++ b/SystemTools.cxx @@ -3067,6 +3067,28 @@ bool SystemTools::FileIsSymlink(const std::string& name) #endif } +bool SystemTools::FileIsFIFO(const std::string& name) +{ +#if defined(_WIN32) + HANDLE hFile = + CreateFileW(Encoding::ToWide(name).c_str(), GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + return false; + } + const DWORD type = GetFileType(hFile); + CloseHandle(hFile); + return type == FILE_TYPE_PIPE; +#else + struct stat fs; + if (lstat(name.c_str(), &fs) == 0) { + return S_ISFIFO(fs.st_mode); + } else { + return false; + } +#endif +} + #if defined(_WIN32) && !defined(__CYGWIN__) bool SystemTools::CreateSymlink(const std::string&, const std::string&) { diff --git a/SystemTools.hxx.in b/SystemTools.hxx.in index f3d06fe..7a5256b 100644 --- a/SystemTools.hxx.in +++ b/SystemTools.hxx.in @@ -654,6 +654,11 @@ public: static bool FileIsSymlink(const std::string& name); /** + * Return true if the file is a FIFO + */ + static bool FileIsFIFO(const std::string& name); + + /** * Return true if the file has a given signature (first set of bytes) */ static bool FileHasSignature(const char* filename, const char* signature, ----------------------------------------------------------------------- Summary of changes: Source/kwsys/CMakeLists.txt | 2 +- Source/kwsys/SystemTools.cxx | 22 ++++++++++++++++++++++ Source/kwsys/SystemTools.hxx.in | 5 +++++ 3 files changed, 28 insertions(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 6 13:13:17 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 6 Feb 2017 13:13:17 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-1313-g97528f3 Message-ID: <20170206181317.509ECE71D9@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 97528f337a23106f8475fa7bd2d2345b8358fee5 (commit) via 72ed051b12d983d298b9447d3464a38f5e0f918c (commit) from 5e08acc89b9b28ffdab4eadc379aa9a346bd841d (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=97528f337a23106f8475fa7bd2d2345b8358fee5 commit 97528f337a23106f8475fa7bd2d2345b8358fee5 Merge: 5e08acc 72ed051 Author: Brad King AuthorDate: Mon Feb 6 13:13:16 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 6 13:13:16 2017 -0500 Merge topic 'determine_id_without_user_specified_flags' into next 72ed051b CMakeDetermineCompilerId: check with and without user-specified flags https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=72ed051b12d983d298b9447d3464a38f5e0f918c commit 72ed051b12d983d298b9447d3464a38f5e0f918c Author: Michael Maltese AuthorDate: Mon Jan 23 18:58:18 2017 -0800 Commit: Brad King CommitDate: Mon Feb 6 13:12:06 2017 -0500 CMakeDetermineCompilerId: check with and without user-specified flags Clang may raise an error when passed a `-march=` option that doesn't correspond to the current target triple. CMake cannot pass the target triple when determining the compiler id because it doesn't know how yet, but it does pass along user-specified flags. This breaks when those user-specified flags include `-march=`. Fix this use case by also trying to find the compiler id without the user-specified flags. Fixes: #16587 diff --git a/Modules/CMakeDetermineASMCompiler.cmake b/Modules/CMakeDetermineASMCompiler.cmake index 4162726..3f18a8c 100644 --- a/Modules/CMakeDetermineASMCompiler.cmake +++ b/Modules/CMakeDetermineASMCompiler.cmake @@ -93,8 +93,8 @@ if(NOT CMAKE_ASM${ASM_DIALECT}_COMPILER_ID) set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_ARMCC "(ARM Compiler)|(ARM Assembler)") include(CMakeDetermineCompilerId) - CMAKE_DETERMINE_COMPILER_ID_VENDOR(ASM${ASM_DIALECT}) - + set(userflags) + CMAKE_DETERMINE_COMPILER_ID_VENDOR(ASM${ASM_DIALECT} "${userflags}") endif() if(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID) diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index bb34de5..ae485bf 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -24,16 +24,21 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src) # Try building with no extra flags and then try each set # of helper flags. Stop when the compiler is identified. - foreach(flags ${CMAKE_${lang}_COMPILER_ID_TEST_FLAGS_FIRST} - "" - ${CMAKE_${lang}_COMPILER_ID_TEST_FLAGS}) - CMAKE_DETERMINE_COMPILER_ID_BUILD("${lang}" "${flags}" "${src}") - CMAKE_DETERMINE_COMPILER_ID_MATCH_VENDOR("${lang}" "${COMPILER_${lang}_PRODUCED_OUTPUT}") - if(CMAKE_${lang}_COMPILER_ID) - break() - endif() - foreach(file ${COMPILER_${lang}_PRODUCED_FILES}) - CMAKE_DETERMINE_COMPILER_ID_CHECK("${lang}" "${CMAKE_${lang}_COMPILER_ID_DIR}/${file}" "${src}") + foreach(userflags "${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}" "") + foreach(testflags ${CMAKE_${lang}_COMPILER_ID_TEST_FLAGS_FIRST} + "" + ${CMAKE_${lang}_COMPILER_ID_TEST_FLAGS}) + CMAKE_DETERMINE_COMPILER_ID_BUILD("${lang}" "${testflags}" "${userflags}" "${src}") + CMAKE_DETERMINE_COMPILER_ID_MATCH_VENDOR("${lang}" "${COMPILER_${lang}_PRODUCED_OUTPUT}") + if(CMAKE_${lang}_COMPILER_ID) + break() + endif() + foreach(file ${COMPILER_${lang}_PRODUCED_FILES}) + CMAKE_DETERMINE_COMPILER_ID_CHECK("${lang}" "${CMAKE_${lang}_COMPILER_ID_DIR}/${file}" "${src}") + endforeach() + if(CMAKE_${lang}_COMPILER_ID) + break() + endif() endforeach() if(CMAKE_${lang}_COMPILER_ID) break() @@ -42,7 +47,9 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src) # If the compiler is still unknown, try to query its vendor. if(CMAKE_${lang}_COMPILER AND NOT CMAKE_${lang}_COMPILER_ID) - CMAKE_DETERMINE_COMPILER_ID_VENDOR(${lang}) + foreach(userflags "${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}" "") + CMAKE_DETERMINE_COMPILER_ID_VENDOR(${lang} "${userflags}") + endforeach() endif() if (COMPILER_QNXNTO AND CMAKE_${lang}_COMPILER_ID STREQUAL "GNU") @@ -66,7 +73,9 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src) endif() if(CMAKE_GENERATOR STREQUAL "Ninja" AND MSVC_${lang}_ARCHITECTURE_ID) - CMAKE_DETERMINE_MSVC_SHOWINCLUDES_PREFIX(${lang}) + foreach(userflags "${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}" "") + CMAKE_DETERMINE_MSVC_SHOWINCLUDES_PREFIX(${lang} "${userflags}") + endforeach() else() set(CMAKE_${lang}_CL_SHOWINCLUDES_PREFIX "") endif() @@ -127,7 +136,7 @@ endfunction() #----------------------------------------------------------------------------- # Function to build the compiler id source file and look for output # files. -function(CMAKE_DETERMINE_COMPILER_ID_BUILD lang testflags src) +function(CMAKE_DETERMINE_COMPILER_ID_BUILD lang testflags userflags src) # Create a clean working directory. file(REMOVE_RECURSE ${CMAKE_${lang}_COMPILER_ID_DIR}) file(MAKE_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR}) @@ -137,7 +146,7 @@ function(CMAKE_DETERMINE_COMPILER_ID_BUILD lang testflags src) # Construct a description of this test case. set(COMPILER_DESCRIPTION "Compiler: ${CMAKE_${lang}_COMPILER} ${CMAKE_${lang}_COMPILER_ID_ARG1} -Build flags: ${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST} +Build flags: ${userflags} Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} ") @@ -327,7 +336,7 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} execute_process( COMMAND "${CMAKE_${lang}_COMPILER}" ${CMAKE_${lang}_COMPILER_ID_ARG1} - ${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST} + ${userflags} ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} "${src}" @@ -615,7 +624,7 @@ endfunction() # set(CMAKE_${lang}_COMPILER_ID_VENDOR_REGEX_${vendor} "Some Vendor Output") # We try running the compiler with the flag for each vendor and # matching its regular expression in the output. -function(CMAKE_DETERMINE_COMPILER_ID_VENDOR lang) +function(CMAKE_DETERMINE_COMPILER_ID_VENDOR lang userflags) if(NOT CMAKE_${lang}_COMPILER_ID_DIR) # We get here when this function is called not from within CMAKE_DETERMINE_COMPILER_ID() @@ -633,7 +642,7 @@ function(CMAKE_DETERMINE_COMPILER_ID_VENDOR lang) execute_process( COMMAND "${CMAKE_${lang}_COMPILER}" ${CMAKE_${lang}_COMPILER_ID_ARG1} - ${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST} + ${userflags} ${flags} WORKING_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR} OUTPUT_VARIABLE output ERROR_VARIABLE output @@ -661,7 +670,7 @@ function(CMAKE_DETERMINE_COMPILER_ID_VENDOR lang) endforeach() endfunction() -function(CMAKE_DETERMINE_MSVC_SHOWINCLUDES_PREFIX lang) +function(CMAKE_DETERMINE_MSVC_SHOWINCLUDES_PREFIX lang userflags) # Run this MSVC-compatible compiler to detect what the /showIncludes # option displays. We can use a C source even with the C++ compiler # because MSVC-compatible compilers handle both and show the same output. @@ -671,7 +680,7 @@ function(CMAKE_DETERMINE_MSVC_SHOWINCLUDES_PREFIX lang) execute_process( COMMAND "${CMAKE_${lang}_COMPILER}" ${CMAKE_${lang}_COMPILER_ID_ARG1} - ${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST} + ${userflags} /nologo /showIncludes /c main.c WORKING_DIRECTORY ${showdir} OUTPUT_VARIABLE out diff --git a/Tests/CMakeTests/CompilerIdVendorTest.cmake.in b/Tests/CMakeTests/CompilerIdVendorTest.cmake.in index 68f6462..9cf5321 100644 --- a/Tests/CMakeTests/CompilerIdVendorTest.cmake.in +++ b/Tests/CMakeTests/CompilerIdVendorTest.cmake.in @@ -8,7 +8,6 @@ file(MAKE_DIRECTORY ${MY_BINARY_DIR}) set(CMAKE_MyLang_COMPILER ${CMAKE_COMMAND}) set(CMAKE_MyLang_COMPILER_ID_ARG1) -set(CMAKE_MyLang_COMPILER_ID_FLAGS_LIST) set(CMAKE_MyLang_COMPILER_ID_DIR ${MY_BINARY_DIR}) file(WRITE "${MY_BINARY_DIR}/BogusVendor.cmake" "message(\"This is a BogusVendor compiler\")") @@ -22,7 +21,8 @@ set(CMAKE_MyLang_COMPILER_ID_VENDOR_FLAGS_MyVendor -P MyVendor.cmake) set(CMAKE_MyLang_COMPILER_ID_VENDOR_REGEX_MyVendor MyVendor) set(CMAKE_BINARY_DIR ${MY_BINARY_DIR}) -cmake_determine_compiler_id_vendor(MyLang) +set(userflags) +cmake_determine_compiler_id_vendor(MyLang "${userflags}") if("${CMAKE_MyLang_COMPILER_ID}" STREQUAL "MyVendor") message(STATUS "Found MyVendor compiler id!") ----------------------------------------------------------------------- Summary of changes: Modules/CMakeDetermineASMCompiler.cmake | 4 +- Modules/CMakeDetermineCompilerId.cmake | 47 ++++++++++++++---------- Tests/CMakeTests/CompilerIdVendorTest.cmake.in | 4 +- 3 files changed, 32 insertions(+), 23 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 6 14:36:05 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 6 Feb 2017 14:36:05 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-1315-gdf2ae6c Message-ID: <20170206193612.DBD76FA62B@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via df2ae6c84e8917c77cdf66182944e7b85fdce651 (commit) via 6cffc98ca0625d0f5db1c34e59b9271416bc212e (commit) from 97528f337a23106f8475fa7bd2d2345b8358fee5 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=df2ae6c84e8917c77cdf66182944e7b85fdce651 commit df2ae6c84e8917c77cdf66182944e7b85fdce651 Merge: 97528f3 6cffc98 Author: Brad King AuthorDate: Mon Feb 6 14:36:04 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 6 14:36:04 2017 -0500 Merge topic 'FeatureSummary-doc-cleanup' into next 6cffc98c FeatureSummary: Fix documentation https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6cffc98ca0625d0f5db1c34e59b9271416bc212e commit 6cffc98ca0625d0f5db1c34e59b9271416bc212e Author: Daniele E. Domenichelli AuthorDate: Fri Feb 3 15:29:08 2017 +0100 Commit: Brad King CommitDate: Mon Feb 6 14:35:30 2017 -0500 FeatureSummary: Fix documentation diff --git a/Modules/FeatureSummary.cmake b/Modules/FeatureSummary.cmake index 8910be7..f29a5f0 100644 --- a/Modules/FeatureSummary.cmake +++ b/Modules/FeatureSummary.cmake @@ -44,7 +44,7 @@ The global property :variable:`FeatureSummary_REQUIRED_PKG_TYPES` defines which package types are required. If one or more package in this categories has not been found, CMake will abort -when calling :cmd;`feature_summary` with the +when calling :command:`feature_summary` with the 'FATAL_ON_MISSING_REQUIRED_PACKAGES' option enabled. The default value for this global property is ``REQUIRED``. @@ -54,7 +54,7 @@ The default value for this global property is ``REQUIRED``. The global property :variable:`FeatureSummary_DEFAULT_PKG_TYPE` defines which package type is the default one. -When calling :cmd;`feature_summary`, if the user did not set the package type +When calling :command:`feature_summary`, if the user did not set the package type explicitly, the package will be assigned to this category. This value must be one of the types defined in the @@ -196,9 +196,11 @@ endfunction() [VAR ] [INCLUDE_QUIET_PACKAGES] [FATAL_ON_MISSING_REQUIRED_PACKAGES] - [DESCRIPTION "Found packages:"] + [DESCRIPTION ""] [QUIET_ON_EMPTY] - WHAT (ALL | PACKAGES_FOUND | PACKAGES_NOT_FOUND + WHAT (ALL + | PACKAGES_FOUND | PACKAGES_NOT_FOUND + | _PACKAGES_FOUND | _PACKAGES_NOT_FOUND | ENABLED_FEATURES | DISABLED_FEATURES) ) @@ -245,10 +247,10 @@ endfunction() information is "printed" into the specified variable. If ``FILENAME`` is not used, the information is printed to the terminal. Using the ``DESCRIPTION`` option a description or headline can be set which will be - printed above the actual content. If ``INCLUDE_QUIET_PACKAGES`` is given, - packages which have been searched with ``find_package(... QUIET)`` will - also be listed. By default they are skipped. If - ``FATAL_ON_MISSING_REQUIRED_PACKAGES`` is given, CMake will abort if a + printed above the actual content. + If ``INCLUDE_QUIET_PACKAGES`` is given, packages which have been searched with + ``find_package(... QUIET)`` will also be listed. By default they are skipped. + If ``FATAL_ON_MISSING_REQUIRED_PACKAGES`` is given, CMake will abort if a package which is marked as one of the package types listed in the :variable:`FeatureSummary_REQUIRED_PKG_TYPES` global property has not been found. ----------------------------------------------------------------------- Summary of changes: Modules/FeatureSummary.cmake | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 6 14:36:44 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 6 Feb 2017 14:36:44 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1309-g370e20c Message-ID: <20170206193644.BF23CFA61C@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 370e20c90ee8382bbf8ab6d629072c3e84011ae0 (commit) via 6cffc98ca0625d0f5db1c34e59b9271416bc212e (commit) from 0f4dae0a4da92af5079eb730443ec188b3b46f8e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=370e20c90ee8382bbf8ab6d629072c3e84011ae0 commit 370e20c90ee8382bbf8ab6d629072c3e84011ae0 Merge: 0f4dae0 6cffc98 Author: Brad King AuthorDate: Mon Feb 6 14:36:42 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 6 14:36:42 2017 -0500 Merge topic 'FeatureSummary-doc-cleanup' 6cffc98c FeatureSummary: Fix documentation ----------------------------------------------------------------------- Summary of changes: Modules/FeatureSummary.cmake | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 6 14:38:28 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 6 Feb 2017 14:38:28 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1311-gfddc01b Message-ID: <20170206193828.5F1FDFA650@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via fddc01bab3352d12c0eba1ff781b359a7dec529c (commit) via 84df4a49500e51ac6e2a19a77e385e66234386f7 (commit) from 370e20c90ee8382bbf8ab6d629072c3e84011ae0 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 6 14:38:28 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 6 Feb 2017 14:38:28 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-1319-geb9bdad Message-ID: <20170206193828.AD93FFA64E@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via eb9bdadb1ab2103d9febf6ada6c3fcf5165d81af (commit) via fddc01bab3352d12c0eba1ff781b359a7dec529c (commit) via 84df4a49500e51ac6e2a19a77e385e66234386f7 (commit) via 370e20c90ee8382bbf8ab6d629072c3e84011ae0 (commit) from df2ae6c84e8917c77cdf66182944e7b85fdce651 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=eb9bdadb1ab2103d9febf6ada6c3fcf5165d81af commit eb9bdadb1ab2103d9febf6ada6c3fcf5165d81af Merge: df2ae6c fddc01b Author: Brad King AuthorDate: Mon Feb 6 14:38:11 2017 -0500 Commit: Brad King CommitDate: Mon Feb 6 14:38:11 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 6 14:38:28 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 6 Feb 2017 14:38:28 -0500 (EST) Subject: [Cmake-commits] CMake branch, release, updated. v3.7.2-1307-g84df4a4 Message-ID: <20170206193828.CADFCFA650@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, release has been updated via 84df4a49500e51ac6e2a19a77e385e66234386f7 (commit) via 6cffc98ca0625d0f5db1c34e59b9271416bc212e (commit) from 566d20771f82492081c55c9da6f1768941eee40a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- Summary of changes: Modules/FeatureSummary.cmake | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 6 14:50:58 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 6 Feb 2017 14:50:58 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-1323-g86c5373 Message-ID: <20170206195059.1597CFA071@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 86c53732c151f94749f375fe371e5db6f1f469e8 (commit) via 28e87033a3f3f997334c45b19b2292ed3821f59e (commit) via 6f62c66b2c5f0595ff0a51ca97f3b5e1d0924523 (commit) via f9bc8cfeeb956a5abbf293d8a26fb5b15aeec1d7 (commit) from eb9bdadb1ab2103d9febf6ada6c3fcf5165d81af (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=86c53732c151f94749f375fe371e5db6f1f469e8 commit 86c53732c151f94749f375fe371e5db6f1f469e8 Merge: eb9bdad 28e8703 Author: Brad King AuthorDate: Mon Feb 6 14:50:52 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 6 14:50:52 2017 -0500 Merge topic 'FeatureSummary_description' into next 28e87033 FeatureSummary: Update release notes 6f62c66b FeatureSummary: Add FeatureSummary__DESCRIPTION global properties f9bc8cfe FeatureSummary: Add DEFAULT_DESCRIPTION option to feature_summary https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=28e87033a3f3f997334c45b19b2292ed3821f59e commit 28e87033a3f3f997334c45b19b2292ed3821f59e Author: Daniele E. Domenichelli AuthorDate: Fri Feb 3 15:45:05 2017 +0100 Commit: Brad King CommitDate: Mon Feb 6 14:44:24 2017 -0500 FeatureSummary: Update release notes diff --git a/Help/release/dev/FeatureSummary_description.rst b/Help/release/dev/FeatureSummary_description.rst new file mode 100644 index 0000000..c56e4ce --- /dev/null +++ b/Help/release/dev/FeatureSummary_description.rst @@ -0,0 +1,11 @@ +FeatureSummary_description +-------------------------- + +* The :command:`feature_summary` command in the :module:`FeatureSummary` module + accepts the new ``DEFAULT_DESCRIPTION`` option that will print the default + title for the selected package type. + +* The global property :variable:`FeatureSummary__DESCRIPTION` can be + defined for each ```` to replace the type name with the specified string + whenever the package type is used in an output string by the + :module:`FeatureSummary` module. https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6f62c66b2c5f0595ff0a51ca97f3b5e1d0924523 commit 6f62c66b2c5f0595ff0a51ca97f3b5e1d0924523 Author: Daniele E. Domenichelli AuthorDate: Fri Feb 3 15:42:11 2017 +0100 Commit: Brad King CommitDate: Mon Feb 6 14:44:24 2017 -0500 FeatureSummary: Add FeatureSummary__DESCRIPTION global properties The global property FeatureSummary__DESCRIPTION can be defined for each type to replace the type name with the specified string whenever the package type is used in an output string. diff --git a/Modules/FeatureSummary.cmake b/Modules/FeatureSummary.cmake index 2913753..1b93304 100644 --- a/Modules/FeatureSummary.cmake +++ b/Modules/FeatureSummary.cmake @@ -63,6 +63,16 @@ is set for all the packages. The default value for this global property is ``OPTIONAL``. + +.. variable:: FeatureSummary__DESCRIPTION + +The global property :variable:`FeatureSummary__DESCRIPTION` can be defined +for each type to replace the type name with the specified string whenever the +package type is used in an output string. + +If not set, the string "```` packages" is used. + + #]=======================================================================] get_property(_fsPkgTypeIsSet GLOBAL PROPERTY FeatureSummary_PKG_TYPES SET) @@ -351,8 +361,13 @@ function(FEATURE_SUMMARY) set(title_PACKAGES_FOUND "The following packages have been found:") set(title_PACKAGES_NOT_FOUND "The following packages have not been found:") foreach(_fsPkgType ${_fsPkgTypes}) - set(title_${_fsPkgType}_PACKAGES_FOUND "The following ${_fsPkgType} packages have been found:") - set(title_${_fsPkgType}_PACKAGES_NOT_FOUND "The following ${_fsPkgType} packages have not been found:") + set(_fsPkgTypeDescription "${_fsPkgType} packages") + get_property(_fsPkgTypeDescriptionIsSet GLOBAL PROPERTY FeatureSummary_${_fsPkgType}_DESCRIPTION SET) + if(_fsPkgTypeDescriptionIsSet) + get_property(_fsPkgTypeDescription GLOBAL PROPERTY FeatureSummary_${_fsPkgType}_DESCRIPTION ) + endif() + set(title_${_fsPkgType}_PACKAGES_FOUND "The following ${_fsPkgTypeDescription} have been found:") + set(title_${_fsPkgType}_PACKAGES_NOT_FOUND "The following ${_fsPkgTypeDescription} have not been found:") endforeach() list(FIND validWhatParts "${_FS_WHAT}" indexInList) diff --git a/Tests/RunCMake/FeatureSummary/FeatureSummaryCustomDescription-stdout.txt b/Tests/RunCMake/FeatureSummary/FeatureSummaryCustomDescription-stdout.txt new file mode 100644 index 0000000..723c467 --- /dev/null +++ b/Tests/RunCMake/FeatureSummary/FeatureSummaryCustomDescription-stdout.txt @@ -0,0 +1,91 @@ +-- The following TYPE1 packages have been found: + + \* Foo, The Foo package, + +-- The following TYPE2 packages have not been found: + + \* Bar + +-- The following TYPE3 packages have not been found: + + \* Baz + +--[ ] + \* Foo, The Foo package, + +--[ ] + \* Bar + +--[ ] + \* Baz + +-- TYPE1 pkgs found + + \* Foo, The Foo package, + +-- TYPE2 pkgs not found + + \* Bar + +-- TYPE3 pkgs not found + + \* Baz + +-- The following TYPE1 packages have been found: + + \* Foo, The Foo package, + +-- The following TYPE2 packages have not been found: + + \* Bar + +-- The following TYPE3 packages have not been found: + + \* Baz + +-- The following first type packages have been found: + + \* Foo, The Foo package, + +-- The following second type packages have not been found: + + \* Bar + +-- The following third type packages have not been found: + + \* Baz + +--[ ] + \* Foo, The Foo package, + +--[ ] + \* Bar + +--[ ] + \* Baz + +-- TYPE1 pkgs found + + \* Foo, The Foo package, + +-- TYPE2 pkgs not found + + \* Bar + +-- TYPE3 pkgs not found + + \* Baz + +-- The following first type packages have been found: + + \* Foo, The Foo package, + +-- The following second type packages have not been found: + + \* Bar + +-- The following third type packages have not been found: + + \* Baz + +-- Configuring done diff --git a/Tests/RunCMake/FeatureSummary/FeatureSummaryCustomDescription.cmake b/Tests/RunCMake/FeatureSummary/FeatureSummaryCustomDescription.cmake new file mode 100644 index 0000000..e61b652 --- /dev/null +++ b/Tests/RunCMake/FeatureSummary/FeatureSummaryCustomDescription.cmake @@ -0,0 +1,158 @@ +include(FeatureSummary) +set_property(GLOBAL PROPERTY FeatureSummary_PKG_TYPES TYPE1 TYPE2 TYPE3) + +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) + +find_package(Foo) +find_package(Bar) +find_package(Baz) + +set_package_properties(Foo PROPERTIES TYPE TYPE1) +set_package_properties(Bar PROPERTIES TYPE TYPE2) +set_package_properties(Baz PROPERTIES TYPE TYPE3) + +feature_summary(WHAT ALL) + +feature_summary(WHAT TYPE1_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) +feature_summary(WHAT TYPE1_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) +feature_summary(WHAT TYPE2_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) +feature_summary(WHAT TYPE2_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) +feature_summary(WHAT TYPE3_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) +feature_summary(WHAT TYPE3_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) + +feature_summary(WHAT TYPE1_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "TYPE1 pkgs found\n") +feature_summary(WHAT TYPE1_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "TYPE1 pkgs not found\n") +feature_summary(WHAT TYPE2_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "TYPE2 pkgs found\n") +feature_summary(WHAT TYPE2_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "TYPE2 pkgs not found\n") +feature_summary(WHAT TYPE3_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "TYPE3 pkgs found\n") +feature_summary(WHAT TYPE3_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "TYPE3 pkgs not found\n") + +feature_summary(WHAT TYPE1_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) +feature_summary(WHAT TYPE1_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) +feature_summary(WHAT TYPE2_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) +feature_summary(WHAT TYPE2_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) +feature_summary(WHAT TYPE3_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) +feature_summary(WHAT TYPE3_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) + +set_property(GLOBAL PROPERTY FeatureSummary_TYPE1_DESCRIPTION "first type packages") +set_property(GLOBAL PROPERTY FeatureSummary_TYPE2_DESCRIPTION "second type packages") +set_property(GLOBAL PROPERTY FeatureSummary_TYPE3_DESCRIPTION "third type packages") + +feature_summary(WHAT ALL) + +feature_summary(WHAT TYPE1_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) +feature_summary(WHAT TYPE1_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) +feature_summary(WHAT TYPE2_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) +feature_summary(WHAT TYPE2_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) +feature_summary(WHAT TYPE3_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) +feature_summary(WHAT TYPE3_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) + +feature_summary(WHAT TYPE1_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "TYPE1 pkgs found\n") +feature_summary(WHAT TYPE1_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "TYPE1 pkgs not found\n") +feature_summary(WHAT TYPE2_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "TYPE2 pkgs found\n") +feature_summary(WHAT TYPE2_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "TYPE2 pkgs not found\n") +feature_summary(WHAT TYPE3_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "TYPE3 pkgs found\n") +feature_summary(WHAT TYPE3_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "TYPE3 pkgs not found\n") + +feature_summary(WHAT TYPE1_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) +feature_summary(WHAT TYPE1_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) +feature_summary(WHAT TYPE2_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) +feature_summary(WHAT TYPE2_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) +feature_summary(WHAT TYPE3_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) +feature_summary(WHAT TYPE3_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) diff --git a/Tests/RunCMake/FeatureSummary/RunCMakeTest.cmake b/Tests/RunCMake/FeatureSummary/RunCMakeTest.cmake index 8486487..c672c16 100644 --- a/Tests/RunCMake/FeatureSummary/RunCMakeTest.cmake +++ b/Tests/RunCMake/FeatureSummary/RunCMakeTest.cmake @@ -20,3 +20,4 @@ run_cmake(FeatureSummaryCustomBadDefault) run_cmake(FeatureSummaryCustomRequired) run_cmake(FeatureSummaryCustomRequiredListA) run_cmake(FeatureSummaryCustomRequiredListB) +run_cmake(FeatureSummaryCustomDescription) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f9bc8cfeeb956a5abbf293d8a26fb5b15aeec1d7 commit f9bc8cfeeb956a5abbf293d8a26fb5b15aeec1d7 Author: Daniele E. Domenichelli AuthorDate: Fri Feb 3 15:32:34 2017 +0100 Commit: Brad King CommitDate: Mon Feb 6 14:44:23 2017 -0500 FeatureSummary: Add DEFAULT_DESCRIPTION option to feature_summary If enabled and only one package type is selected, it will print the default title for the selected package type. diff --git a/Modules/FeatureSummary.cmake b/Modules/FeatureSummary.cmake index f29a5f0..2913753 100644 --- a/Modules/FeatureSummary.cmake +++ b/Modules/FeatureSummary.cmake @@ -196,7 +196,7 @@ endfunction() [VAR ] [INCLUDE_QUIET_PACKAGES] [FATAL_ON_MISSING_REQUIRED_PACKAGES] - [DESCRIPTION ""] + [DESCRIPTION "" | DEFAULT_DESCRIPTION] [QUIET_ON_EMPTY] WHAT (ALL | PACKAGES_FOUND | PACKAGES_NOT_FOUND @@ -247,7 +247,10 @@ endfunction() information is "printed" into the specified variable. If ``FILENAME`` is not used, the information is printed to the terminal. Using the ``DESCRIPTION`` option a description or headline can be set which will be - printed above the actual content. + printed above the actual content. If only one type of + package was requested, no title is printed, unless it is explicitly set using + either ``DESCRIPTION`` to use a custom string, or ``DEFAULT_DESCRIPTION`` to + use a default title for the requested type. If ``INCLUDE_QUIET_PACKAGES`` is given, packages which have been searched with ``find_package(... QUIET)`` will also be listed. By default they are skipped. If ``FATAL_ON_MISSING_REQUIRED_PACKAGES`` is given, CMake will abort if a @@ -306,8 +309,14 @@ endfunction() function(FEATURE_SUMMARY) # CMAKE_PARSE_ARGUMENTS( args...) - set(options APPEND INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES QUIET_ON_EMPTY) - set(oneValueArgs FILENAME VAR DESCRIPTION) + set(options APPEND + INCLUDE_QUIET_PACKAGES + FATAL_ON_MISSING_REQUIRED_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) + set(oneValueArgs FILENAME + VAR + DESCRIPTION) set(multiValueArgs WHAT) CMAKE_PARSE_ARGUMENTS(_FS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${_FIRST_ARG} ${ARGN}) @@ -320,6 +329,11 @@ function(FEATURE_SUMMARY) message(FATAL_ERROR "The call to FEATURE_SUMMARY() doesn't set the required WHAT argument.") endif() + if(_FS_DEFAULT_DESCRIPTION AND DEFINED _FS_DESCRIPTION) + message(WARNING "DEFAULT_DESCRIPTION option discarded since DESCRIPTION is set.") + set(_FS_DEFAULT_DESCRIPTION 0) + endif() + set(validWhatParts "ENABLED_FEATURES" "DISABLED_FEATURES" "PACKAGES_FOUND" @@ -332,11 +346,24 @@ function(FEATURE_SUMMARY) "${_fsPkgType}_PACKAGES_NOT_FOUND") endforeach() + set(title_ENABLED_FEATURES "The following features have been enabled:") + set(title_DISABLED_FEATURES "The following features have been disabled:") + set(title_PACKAGES_FOUND "The following packages have been found:") + set(title_PACKAGES_NOT_FOUND "The following packages have not been found:") + foreach(_fsPkgType ${_fsPkgTypes}) + set(title_${_fsPkgType}_PACKAGES_FOUND "The following ${_fsPkgType} packages have been found:") + set(title_${_fsPkgType}_PACKAGES_NOT_FOUND "The following ${_fsPkgType} packages have not been found:") + endforeach() + list(FIND validWhatParts "${_FS_WHAT}" indexInList) if(NOT "${indexInList}" STREQUAL "-1") _FS_GET_FEATURE_SUMMARY( ${_FS_WHAT} _featureSummary ${_FS_INCLUDE_QUIET_PACKAGES} ) if(_featureSummary OR NOT _FS_QUIET_ON_EMPTY) - set(_fullText "${_FS_DESCRIPTION}${_featureSummary}\n") + if(_FS_DEFAULT_DESCRIPTION) + set(_fullText "${title_${_FS_WHAT}}\n${_featureSummary}\n") + else() + set(_fullText "${_FS_DESCRIPTION}${_featureSummary}\n") + endif() endif() if(_featureSummary) @@ -375,15 +402,6 @@ function(FEATURE_SUMMARY) endforeach() endif() - set(title_ENABLED_FEATURES "The following features have been enabled:") - set(title_DISABLED_FEATURES "The following features have been disabled:") - set(title_PACKAGES_FOUND "The following packages have been found:") - set(title_PACKAGES_NOT_FOUND "The following packages have not been found:") - foreach(_fsPkgType ${_fsPkgTypes}) - set(title_${_fsPkgType}_PACKAGES_FOUND "The following ${_fsPkgType} packages have been found:") - set(title_${_fsPkgType}_PACKAGES_NOT_FOUND "The following ${_fsPkgType} packages have not been found:") - endforeach() - set(_fullText "${_FS_DESCRIPTION}") foreach(part ${allWhatParts}) set(_tmp) diff --git a/Tests/RunCMake/FeatureSummary/FeatureSummaryDefaultDescription-stdout.txt b/Tests/RunCMake/FeatureSummary/FeatureSummaryDefaultDescription-stdout.txt new file mode 100644 index 0000000..47bdee3 --- /dev/null +++ b/Tests/RunCMake/FeatureSummary/FeatureSummaryDefaultDescription-stdout.txt @@ -0,0 +1,46 @@ +-- The following RUNTIME packages have been found: + + \* Foo, The Foo package, + +-- The following OPTIONAL packages have not been found: + + \* Bar + +-- The following REQUIRED packages have not been found: + + \* Baz + +--[ ] + \* Foo, The Foo package, + +--[ ] + \* Bar + +--[ ] + \* Baz + +-- RUNTIME pkgs found + + \* Foo, The Foo package, + +-- OPTIONAL pkgs not found + + \* Bar + +-- REQUIRED pkgs not found + + \* Baz + +-- The following RUNTIME packages have been found: + + \* Foo, The Foo package, + +-- The following OPTIONAL packages have not been found: + + \* Bar + +-- The following REQUIRED packages have not been found: + + \* Baz + +-- Configuring done diff --git a/Tests/RunCMake/FeatureSummary/FeatureSummaryDefaultDescription.cmake b/Tests/RunCMake/FeatureSummary/FeatureSummaryDefaultDescription.cmake new file mode 100644 index 0000000..536fe72 --- /dev/null +++ b/Tests/RunCMake/FeatureSummary/FeatureSummaryDefaultDescription.cmake @@ -0,0 +1,82 @@ +include(FeatureSummary) + +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) + +find_package(Foo) +find_package(Bar) +find_package(Baz) + +set_package_properties(Foo PROPERTIES TYPE RUNTIME) +set_package_properties(Bar PROPERTIES TYPE OPTIONAL) +set_package_properties(Baz PROPERTIES TYPE REQUIRED) + +feature_summary(WHAT ALL) + +feature_summary(WHAT RUNTIME_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) +feature_summary(WHAT RUNTIME_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) +feature_summary(WHAT OPTIONAL_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) +feature_summary(WHAT OPTIONAL_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) +feature_summary(WHAT REQUIRED_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) +feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY) + +feature_summary(WHAT RUNTIME_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "RUNTIME pkgs found\n") +feature_summary(WHAT RUNTIME_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "RUNTIME pkgs not found\n") +feature_summary(WHAT OPTIONAL_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "OPTIONAL pkgs found\n") +feature_summary(WHAT OPTIONAL_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "OPTIONAL pkgs not found\n") +feature_summary(WHAT REQUIRED_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "REQUIRED pkgs found\n") +feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DESCRIPTION "REQUIRED pkgs not found\n") + +feature_summary(WHAT RUNTIME_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) +feature_summary(WHAT RUNTIME_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) +feature_summary(WHAT OPTIONAL_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) +feature_summary(WHAT OPTIONAL_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) +feature_summary(WHAT REQUIRED_PACKAGES_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) +feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND + INCLUDE_QUIET_PACKAGES + QUIET_ON_EMPTY + DEFAULT_DESCRIPTION) diff --git a/Tests/RunCMake/FeatureSummary/RunCMakeTest.cmake b/Tests/RunCMake/FeatureSummary/RunCMakeTest.cmake index 9caee4c..8486487 100644 --- a/Tests/RunCMake/FeatureSummary/RunCMakeTest.cmake +++ b/Tests/RunCMake/FeatureSummary/RunCMakeTest.cmake @@ -14,6 +14,7 @@ run_cmake(FeatureSummaryFatalOnMissingRequiredPackages) run_cmake(FeatureSummaryIncludeQuietPackages) run_cmake(FeatureSummaryQuietOnEmpty) run_cmake(FeatureSummaryMultipleDepends) +run_cmake(FeatureSummaryDefaultDescription) run_cmake(FeatureSummaryCustomTypes) run_cmake(FeatureSummaryCustomBadDefault) run_cmake(FeatureSummaryCustomRequired) ----------------------------------------------------------------------- Summary of changes: Help/release/dev/FeatureSummary_description.rst | 11 ++ Modules/FeatureSummary.cmake | 61 ++++++-- .../FeatureSummaryCustomDescription-stdout.txt | 91 +++++++++++ .../FeatureSummaryCustomDescription.cmake | 158 ++++++++++++++++++++ .../FeatureSummaryDefaultDescription-stdout.txt | 46 ++++++ .../FeatureSummaryDefaultDescription.cmake | 82 ++++++++++ Tests/RunCMake/FeatureSummary/RunCMakeTest.cmake | 2 + 7 files changed, 437 insertions(+), 14 deletions(-) create mode 100644 Help/release/dev/FeatureSummary_description.rst create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryCustomDescription-stdout.txt create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryCustomDescription.cmake create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryDefaultDescription-stdout.txt create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryDefaultDescription.cmake hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 6 14:54:47 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 6 Feb 2017 14:54:47 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-1325-g30c8c9b Message-ID: <20170206195448.62EBAFA157@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 30c8c9bc75b387b1432a9c1cb5d4399bae163a71 (commit) via 558a69fc90b5037c13c8335af41bbc9ec03b004e (commit) from 86c53732c151f94749f375fe371e5db6f1f469e8 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=30c8c9bc75b387b1432a9c1cb5d4399bae163a71 commit 30c8c9bc75b387b1432a9c1cb5d4399bae163a71 Merge: 86c5373 558a69f Author: Brad King AuthorDate: Mon Feb 6 14:54:46 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 6 14:54:46 2017 -0500 Merge topic 'wix-custom-root-id' into next 558a69fc CPackWIX: Introduce new CPACK_WIX_ROOT_FOLDER_ID variable https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=558a69fc90b5037c13c8335af41bbc9ec03b004e commit 558a69fc90b5037c13c8335af41bbc9ec03b004e Author: Nils Gladitz AuthorDate: Fri Feb 3 09:02:31 2017 +0100 Commit: Brad King CommitDate: Mon Feb 6 14:53:16 2017 -0500 CPackWIX: Introduce new CPACK_WIX_ROOT_FOLDER_ID variable The new variable allows specification of a custom root folder ID. The implicit default is "ProgramFiles<64>Folder". The "<64>" token is replaced by "" for 32-bit and "64" for 64-bit builds. Inspired-By: Eric Backus Fixes: #16573 diff --git a/Help/release/dev/wix-custom-root-id.rst b/Help/release/dev/wix-custom-root-id.rst new file mode 100644 index 0000000..3e10fdd --- /dev/null +++ b/Help/release/dev/wix-custom-root-id.rst @@ -0,0 +1,7 @@ +wix-custom-root-id +------------------ + +* The CPack WIX generator implemented a new + :variable:`CPACK_WIX_ROOT_FOLDER_ID` variable which allows + using a custom root folder ID instead of the default + ``ProgramFilesFolder`` / ``ProgramFiles64Folder``. diff --git a/Modules/CPackWIX.cmake b/Modules/CPackWIX.cmake index 0f2278f..5a36e4c 100644 --- a/Modules/CPackWIX.cmake +++ b/Modules/CPackWIX.cmake @@ -268,6 +268,17 @@ # follow the localization or convention of the system on which the # installation is performed. # +# .. variable:: CPACK_WIX_ROOT_FOLDER_ID +# +# This variable allows specification of a custom root folder ID. +# The generator specific ``<64>`` token can be used for +# folder IDs that come in 32-bit and 64-bit variants. +# In 32-bit builds the token will expand empty while in 64-bit builds +# it will expand to ``64``. +# +# When unset generated installers will default installing to +# ``ProgramFiles<64>Folder``. +# if(NOT CPACK_WIX_ROOT) file(TO_CMAKE_PATH "$ENV{WIX}" CPACK_WIX_ROOT) diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx index 2bccf2e..39586de 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx +++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx @@ -437,8 +437,8 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() directoryDefinitions.AddAttribute("Name", "SourceDir"); size_t installRootSize = - directoryDefinitions.BeginInstallationPrefixDirectory( - GetProgramFilesFolderId(), installRoot); + directoryDefinitions.BeginInstallationPrefixDirectory(GetRootFolderId(), + installRoot); std::string fileDefinitionsFilename = this->CPackTopLevel + "/files.wxs"; @@ -570,16 +570,26 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() return this->Patch->CheckForUnappliedFragments(); } -std::string cmCPackWIXGenerator::GetProgramFilesFolderId() const +std::string cmCPackWIXGenerator::GetRootFolderId() const { if (cmSystemTools::IsOn(GetOption("CPACK_WIX_SKIP_PROGRAM_FOLDER"))) { return ""; } + + std::string result = "ProgramFiles<64>Folder"; + + const char* rootFolderId = GetOption("CPACK_WIX_ROOT_FOLDER_ID"); + if (rootFolderId) { + result = rootFolderId; + } + if (GetArchitecture() == "x86") { - return "ProgramFilesFolder"; + cmSystemTools::ReplaceString(result, "<64>", ""); } else { - return "ProgramFiles64Folder"; + cmSystemTools::ReplaceString(result, "<64>", "64"); } + + return result; } bool cmCPackWIXGenerator::GenerateMainSourceFileFromTemplate() diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.h b/Source/CPack/WiX/cmCPackWIXGenerator.h index fc0994c..36647d8 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.h +++ b/Source/CPack/WiX/cmCPackWIXGenerator.h @@ -65,7 +65,7 @@ private: bool CreateWiXSourceFiles(); - std::string GetProgramFilesFolderId() const; + std::string GetRootFolderId() const; bool GenerateMainSourceFileFromTemplate(); ----------------------------------------------------------------------- Summary of changes: Help/release/dev/wix-custom-root-id.rst | 7 +++++++ Modules/CPackWIX.cmake | 11 +++++++++++ Source/CPack/WiX/cmCPackWIXGenerator.cxx | 20 +++++++++++++++----- Source/CPack/WiX/cmCPackWIXGenerator.h | 2 +- 4 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 Help/release/dev/wix-custom-root-id.rst hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 6 16:14:12 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 6 Feb 2017 16:14:12 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-1327-g01d6480 Message-ID: <20170206211413.84358E667F@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 01d648002dd3d669c4612e8174671c27bd637702 (commit) via a3f71349deaf533201d3cb2e8076bb4e7edfbbf6 (commit) from 30c8c9bc75b387b1432a9c1cb5d4399bae163a71 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=01d648002dd3d669c4612e8174671c27bd637702 commit 01d648002dd3d669c4612e8174671c27bd637702 Merge: 30c8c9b a3f7134 Author: Brad King AuthorDate: Mon Feb 6 16:14:08 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 6 16:14:08 2017 -0500 Merge topic 'FindProtobuf-static-libs' into next a3f71349 FindProtobuf: Add option to find static libraries on UNIX https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a3f71349deaf533201d3cb2e8076bb4e7edfbbf6 commit a3f71349deaf533201d3cb2e8076bb4e7edfbbf6 Author: S?bastien GALLOU AuthorDate: Mon Feb 6 17:39:59 2017 +0100 Commit: Brad King CommitDate: Mon Feb 6 16:12:39 2017 -0500 FindProtobuf: Add option to find static libraries on UNIX Add a `Protobuf_USE_STATIC_LIBS` input variable to optionally restrict searches to static library names. This follows the approach of `FindBoost`. diff --git a/Help/release/dev/FindProtobuf-static-libs.rst b/Help/release/dev/FindProtobuf-static-libs.rst new file mode 100644 index 0000000..fcc0678 --- /dev/null +++ b/Help/release/dev/FindProtobuf-static-libs.rst @@ -0,0 +1,5 @@ +FindProtobuf-static-libs +------------------------ + +* The :module:`FindProtobuf` module now supports usage of static libraries + for Unix via a new ``Protobuf_USE_STATIC_LIBS`` input variable. diff --git a/Modules/FindProtobuf.cmake b/Modules/FindProtobuf.cmake index 3ffd5a7..102ed42 100644 --- a/Modules/FindProtobuf.cmake +++ b/Modules/FindProtobuf.cmake @@ -20,6 +20,9 @@ # imported .proto files. # ``Protobuf_DEBUG`` # Show debug messages. +# ``Protobuf_USE_STATIC_LIBS`` +# Set to ON to force the use of the static libraries. +# Default is OFF. # # Defines the following variables: # @@ -218,6 +221,14 @@ function(PROTOBUF_GENERATE_PYTHON SRCS) set(${SRCS} ${${SRCS}} PARENT_SCOPE) endfunction() + +if(Protobuf_DEBUG) + # Output some of their choices + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "Protobuf_USE_STATIC_LIBS = ${Protobuf_USE_STATIC_LIBS}") +endif() + + # Backwards compatibility # Define camel case versions of input variables foreach(UPPER @@ -245,6 +256,17 @@ if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(_PROTOBUF_ARCH_DIR x64/) endif() + +# Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES +if( Protobuf_USE_STATIC_LIBS ) + set( _protobuf_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) + if(WIN32) + set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) + else() + set(CMAKE_FIND_LIBRARY_SUFFIXES .a ) + endif() +endif() + include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake) # Internal function: search for normal library as well as a debug one @@ -399,6 +421,11 @@ if(Protobuf_FOUND) set(Protobuf_INCLUDE_DIRS ${Protobuf_INCLUDE_DIR}) endif() +# Restore the original find library ordering +if( Protobuf_USE_STATIC_LIBS ) + set(CMAKE_FIND_LIBRARY_SUFFIXES ${_protobuf_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) +endif() + # Backwards compatibility # Define upper case versions of output variables foreach(Camel ----------------------------------------------------------------------- Summary of changes: Help/release/dev/FindProtobuf-static-libs.rst | 5 +++++ Modules/FindProtobuf.cmake | 27 +++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 Help/release/dev/FindProtobuf-static-libs.rst hooks/post-receive -- CMake From kwrobot at kitware.com Tue Feb 7 00:01:14 2017 From: kwrobot at kitware.com (Kitware Robot) Date: Tue, 7 Feb 2017 00:01:14 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1312-g0a09717 Message-ID: <20170207050114.7CAA3FA0BE@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 0a09717ea3171bf9dda97e22e796c4cdbeed717b (commit) from fddc01bab3352d12c0eba1ff781b359a7dec529c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0a09717ea3171bf9dda97e22e796c4cdbeed717b commit 0a09717ea3171bf9dda97e22e796c4cdbeed717b Author: Kitware Robot AuthorDate: Tue Feb 7 00:01:12 2017 -0500 Commit: Kitware Robot CommitDate: Tue Feb 7 00:01:12 2017 -0500 CMake Nightly Date Stamp diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 0577039..5b779bc 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 8) -set(CMake_VERSION_PATCH 20170206) +set(CMake_VERSION_PATCH 20170207) #set(CMake_VERSION_RC 1) ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 7 09:59:38 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 7 Feb 2017 09:59:38 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1315-g7642ca2 Message-ID: <20170207145938.C533DFA50F@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 7642ca21b7d21f41b41703a6d1bef1d6f3c1e564 (commit) via c2645e1979f83b1550d977cee0cdb80122daf8e0 (commit) via 95983ed8453f9167077821aea347ba1a87e92eac (commit) from 0a09717ea3171bf9dda97e22e796c4cdbeed717b (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7642ca21b7d21f41b41703a6d1bef1d6f3c1e564 commit 7642ca21b7d21f41b41703a6d1bef1d6f3c1e564 Merge: 0a09717 c2645e1 Author: Brad King AuthorDate: Tue Feb 7 09:59:36 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 7 09:59:36 2017 -0500 Merge topic 'update-kwsys' c2645e19 Merge branch 'upstream-KWSys' into update-kwsys 95983ed8 KWSys 2017-02-06 (ef673998) ----------------------------------------------------------------------- Summary of changes: Source/kwsys/CMakeLists.txt | 2 +- Source/kwsys/SystemTools.cxx | 22 ++++++++++++++++++++++ Source/kwsys/SystemTools.hxx.in | 5 +++++ 3 files changed, 28 insertions(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 7 09:59:41 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 7 Feb 2017 09:59:41 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1317-g4dbd03f Message-ID: <20170207145941.443B3FA43A@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 4dbd03f6ef60a88e76b4a716782fb186c19fd6d6 (commit) via 558a69fc90b5037c13c8335af41bbc9ec03b004e (commit) from 7642ca21b7d21f41b41703a6d1bef1d6f3c1e564 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4dbd03f6ef60a88e76b4a716782fb186c19fd6d6 commit 4dbd03f6ef60a88e76b4a716782fb186c19fd6d6 Merge: 7642ca2 558a69f Author: Brad King AuthorDate: Tue Feb 7 09:59:39 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 7 09:59:39 2017 -0500 Merge topic 'wix-custom-root-id' 558a69fc CPackWIX: Introduce new CPACK_WIX_ROOT_FOLDER_ID variable ----------------------------------------------------------------------- Summary of changes: Help/release/dev/wix-custom-root-id.rst | 7 +++++++ Modules/CPackWIX.cmake | 11 +++++++++++ Source/CPack/WiX/cmCPackWIXGenerator.cxx | 20 +++++++++++++++----- Source/CPack/WiX/cmCPackWIXGenerator.h | 2 +- 4 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 Help/release/dev/wix-custom-root-id.rst hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 7 09:59:44 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 7 Feb 2017 09:59:44 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1321-gc756ad9 Message-ID: <20170207145944.0C4A5FA54D@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via c756ad9e73e1432d8596caf7dd6ade298ce84946 (commit) via 28e87033a3f3f997334c45b19b2292ed3821f59e (commit) via 6f62c66b2c5f0595ff0a51ca97f3b5e1d0924523 (commit) via f9bc8cfeeb956a5abbf293d8a26fb5b15aeec1d7 (commit) from 4dbd03f6ef60a88e76b4a716782fb186c19fd6d6 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c756ad9e73e1432d8596caf7dd6ade298ce84946 commit c756ad9e73e1432d8596caf7dd6ade298ce84946 Merge: 4dbd03f 28e8703 Author: Brad King AuthorDate: Tue Feb 7 09:59:41 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 7 09:59:41 2017 -0500 Merge topic 'FeatureSummary_description' 28e87033 FeatureSummary: Update release notes 6f62c66b FeatureSummary: Add FeatureSummary__DESCRIPTION global properties f9bc8cfe FeatureSummary: Add DEFAULT_DESCRIPTION option to feature_summary ----------------------------------------------------------------------- Summary of changes: Help/release/dev/FeatureSummary_description.rst | 11 ++ Modules/FeatureSummary.cmake | 61 ++++++-- .../FeatureSummaryCustomDescription-stdout.txt | 91 +++++++++++ .../FeatureSummaryCustomDescription.cmake | 158 ++++++++++++++++++++ .../FeatureSummaryDefaultDescription-stdout.txt | 46 ++++++ .../FeatureSummaryDefaultDescription.cmake | 82 ++++++++++ Tests/RunCMake/FeatureSummary/RunCMakeTest.cmake | 2 + 7 files changed, 437 insertions(+), 14 deletions(-) create mode 100644 Help/release/dev/FeatureSummary_description.rst create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryCustomDescription-stdout.txt create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryCustomDescription.cmake create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryDefaultDescription-stdout.txt create mode 100644 Tests/RunCMake/FeatureSummary/FeatureSummaryDefaultDescription.cmake hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 7 09:59:46 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 7 Feb 2017 09:59:46 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1323-g6dec5d5 Message-ID: <20170207145946.8DBD7FA532@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 6dec5d5fb83a02f534d681d39c9caba87f3cf9c7 (commit) via a3f71349deaf533201d3cb2e8076bb4e7edfbbf6 (commit) from c756ad9e73e1432d8596caf7dd6ade298ce84946 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6dec5d5fb83a02f534d681d39c9caba87f3cf9c7 commit 6dec5d5fb83a02f534d681d39c9caba87f3cf9c7 Merge: c756ad9 a3f7134 Author: Brad King AuthorDate: Tue Feb 7 09:59:44 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 7 09:59:44 2017 -0500 Merge topic 'FindProtobuf-static-libs' a3f71349 FindProtobuf: Add option to find static libraries on UNIX ----------------------------------------------------------------------- Summary of changes: Help/release/dev/FindProtobuf-static-libs.rst | 5 +++++ Modules/FindProtobuf.cmake | 27 +++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 Help/release/dev/FindProtobuf-static-libs.rst hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 7 09:59:48 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 7 Feb 2017 09:59:48 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.7.2-1325-g9bd017d Message-ID: <20170207145948.D3C55FA564@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 9bd017d20ec4a2f9f4ceb2a39aa764b584026026 (commit) via 72ed051b12d983d298b9447d3464a38f5e0f918c (commit) from 6dec5d5fb83a02f534d681d39c9caba87f3cf9c7 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9bd017d20ec4a2f9f4ceb2a39aa764b584026026 commit 9bd017d20ec4a2f9f4ceb2a39aa764b584026026 Merge: 6dec5d5 72ed051 Author: Brad King AuthorDate: Tue Feb 7 09:59:47 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 7 09:59:47 2017 -0500 Merge topic 'determine_id_without_user_specified_flags' 72ed051b CMakeDetermineCompilerId: check with and without user-specified flags ----------------------------------------------------------------------- Summary of changes: Modules/CMakeDetermineASMCompiler.cmake | 4 +- Modules/CMakeDetermineCompilerId.cmake | 47 ++++++++++++++---------- Tests/CMakeTests/CompilerIdVendorTest.cmake.in | 4 +- 3 files changed, 32 insertions(+), 23 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 7 10:00:02 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 7 Feb 2017 10:00:02 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-1334-g2848407 Message-ID: <20170207150002.DBADEFA50F@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 2848407ff801cad7cf0cb86391dcecdc8343542a (commit) via 9bd017d20ec4a2f9f4ceb2a39aa764b584026026 (commit) via 6dec5d5fb83a02f534d681d39c9caba87f3cf9c7 (commit) via c756ad9e73e1432d8596caf7dd6ade298ce84946 (commit) via 4dbd03f6ef60a88e76b4a716782fb186c19fd6d6 (commit) via 7642ca21b7d21f41b41703a6d1bef1d6f3c1e564 (commit) via 0a09717ea3171bf9dda97e22e796c4cdbeed717b (commit) from 01d648002dd3d669c4612e8174671c27bd637702 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=2848407ff801cad7cf0cb86391dcecdc8343542a commit 2848407ff801cad7cf0cb86391dcecdc8343542a Merge: 01d6480 9bd017d Author: Brad King AuthorDate: Tue Feb 7 09:59:54 2017 -0500 Commit: Brad King CommitDate: Tue Feb 7 09:59:54 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 7 11:25:05 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 7 Feb 2017 11:25:05 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.7.2-1336-g7a6d61f Message-ID: <20170207162505.D65BAFA110@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 7a6d61fe67383038e2874e0508d78778fabc7183 (commit) via 9837ed96992a0a5e151c4cb5d4cbe6c7890d7db4 (commit) from 2848407ff801cad7cf0cb86391dcecdc8343542a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7a6d61fe67383038e2874e0508d78778fabc7183 commit 7a6d61fe67383038e2874e0508d78778fabc7183 Merge: 2848407 9837ed9 Author: Brad King AuthorDate: Tue Feb 7 11:25:04 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 7 11:25:04 2017 -0500 Merge topic 'ExtractGTestMacro' into next 9837ed96 GoogleTest: Add module to contain gtest_add_tests independently https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9837ed96992a0a5e151c4cb5d4cbe6c7890d7db4 commit 9837ed96992a0a5e151c4cb5d4cbe6c7890d7db4 Author: Bradley Lowekamp AuthorDate: Mon Feb 6 11:14:16 2017 -0500 Commit: Brad King CommitDate: Tue Feb 7 11:24:18 2017 -0500 GoogleTest: Add module to contain gtest_add_tests independently Extract the `gtest_add_tests` macro from `FindGTest` into a separate module. GTest or GoogleTest can be used by a project in a several different ways, including installed libraries in the system, from an ExternalProject, or adding the GTest source directory as a sub directory of the project. As not all of these uses are supported by the FindGTest module the useful `gtest_add_tests` macro is separated to easily enable reuse. Issue: #14151 diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst index d4712ba..2dd56c7 100644 --- a/Help/manual/cmake-modules.7.rst +++ b/Help/manual/cmake-modules.7.rst @@ -228,6 +228,7 @@ All Modules /module/GenerateExportHeader /module/GetPrerequisites /module/GNUInstallDirs + /module/GoogleTest /module/InstallRequiredSystemLibraries /module/MacroAddFileDependencies /module/ProcessorCount diff --git a/Help/module/GoogleTest.rst b/Help/module/GoogleTest.rst new file mode 100644 index 0000000..3d4cc97 --- /dev/null +++ b/Help/module/GoogleTest.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../Modules/GoogleTest.cmake diff --git a/Help/release/dev/ExtractGTestMacro.rst b/Help/release/dev/ExtractGTestMacro.rst new file mode 100644 index 0000000..574982c --- /dev/null +++ b/Help/release/dev/ExtractGTestMacro.rst @@ -0,0 +1,5 @@ +ExtractGTestMacro +----------------- + +* A new :module:`GoogleTest` module was added to provide the + ``gtest_add_tests`` macro independently of the :module:`FindGTest` module. diff --git a/Modules/FindGTest.cmake b/Modules/FindGTest.cmake index 6540171..c4b4535 100644 --- a/Modules/FindGTest.cmake +++ b/Modules/FindGTest.cmake @@ -70,64 +70,10 @@ # Deeper integration with CTest # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ # -# If you would like each Google test to show up in CTest as a test you -# may use the following macro:: -# -# GTEST_ADD_TESTS(executable extra_args files...) -# -# ``executable`` -# the path to the test executable -# ``extra_args`` -# a list of extra arguments to be passed to executable enclosed in -# quotes (or ``""`` for none) -# ``files...`` -# a list of source files to search for tests and test fixtures. Or -# ``AUTO`` to find them from executable target -# -# However, note that this macro will slow down your tests by running -# an executable for each test and test fixture. -# -# Example usage:: -# -# set(FooTestArgs --foo 1 --bar 2) -# add_executable(FooTest FooUnitTest.cc) -# GTEST_ADD_TESTS(FooTest "${FooTestArgs}" AUTO) - -# -# Thanks to Daniel Blezek for the GTEST_ADD_TESTS code - -function(GTEST_ADD_TESTS executable extra_args) - if(NOT ARGN) - message(FATAL_ERROR "Missing ARGN: Read the documentation for GTEST_ADD_TESTS") - endif() - if(ARGN STREQUAL "AUTO") - # obtain sources used for building that executable - get_property(ARGN TARGET ${executable} PROPERTY SOURCES) - endif() - set(gtest_case_name_regex ".*\\( *([A-Za-z_0-9]+) *, *([A-Za-z_0-9]+) *\\).*") - set(gtest_test_type_regex "(TYPED_TEST|TEST_?[FP]?)") - foreach(source ${ARGN}) - set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${source}) - file(READ "${source}" contents) - string(REGEX MATCHALL "${gtest_test_type_regex} *\\(([A-Za-z_0-9 ,]+)\\)" found_tests ${contents}) - foreach(hit ${found_tests}) - string(REGEX MATCH "${gtest_test_type_regex}" test_type ${hit}) +# See :module:`GoogleTest` for information on the :command:`gtest_add_tests` +# command. - # Parameterized tests have a different signature for the filter - if("x${test_type}" STREQUAL "xTEST_P") - string(REGEX REPLACE ${gtest_case_name_regex} "*/\\1.\\2/*" test_name ${hit}) - elseif("x${test_type}" STREQUAL "xTEST_F" OR "x${test_type}" STREQUAL "xTEST") - string(REGEX REPLACE ${gtest_case_name_regex} "\\1.\\2" test_name ${hit}) - elseif("x${test_type}" STREQUAL "xTYPED_TEST") - string(REGEX REPLACE ${gtest_case_name_regex} "\\1/*.\\2" test_name ${hit}) - else() - message(WARNING "Could not parse GTest ${hit} for adding to CTest.") - continue() - endif() - add_test(NAME ${test_name} COMMAND ${executable} --gtest_filter=${test_name} ${extra_args}) - endforeach() - endforeach() -endfunction() +include(${CMAKE_CURRENT_LIST_DIR}/GoogleTest.cmake) function(_gtest_append_debugs _endvar _library) if(${_library} AND ${_library}_DEBUG) diff --git a/Modules/GoogleTest.cmake b/Modules/GoogleTest.cmake new file mode 100644 index 0000000..91a3a25 --- /dev/null +++ b/Modules/GoogleTest.cmake @@ -0,0 +1,73 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +GoogleTest +---------- + +This module defines functions to help use the Google Test infrastructure. + +.. command:: gtest_add_tests + + Automatically add tests with CTest by scanning source code for Google test + macros. + + :: + + gtest_add_tests( ...) + + ```` + The path to the test executable. + ```` + A ;-list of extra arguments to be passed to executable. The entire + list must be passed as a single argument. Enclose it in quotes, + or pass ``""`` for no arguments. + ``...`` + A list of source files to search for tests and test fixtures. + Alternatively, use ``AUTO`` to specify that ```` is the name + of a CMake executable target whose sources should be scanned. + +Example +^^^^^^^ + +.. code-block:: cmake + + include(GoogleTest) + set(FooTestArgs --foo 1 --bar 2) + add_executable(FooTest FooUnitTest.cc) + gtest_add_tests(FooTest "${FooTestArgs}" AUTO) + +#]=======================================================================] + +function(gtest_add_tests executable extra_args) + if(NOT ARGN) + message(FATAL_ERROR "Missing ARGN: Read the documentation for GTEST_ADD_TESTS") + endif() + if(ARGN STREQUAL "AUTO") + # obtain sources used for building that executable + get_property(ARGN TARGET ${executable} PROPERTY SOURCES) + endif() + set(gtest_case_name_regex ".*\\( *([A-Za-z_0-9]+) *, *([A-Za-z_0-9]+) *\\).*") + set(gtest_test_type_regex "(TYPED_TEST|TEST_?[FP]?)") + foreach(source ${ARGN}) + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${source}) + file(READ "${source}" contents) + string(REGEX MATCHALL "${gtest_test_type_regex} *\\(([A-Za-z_0-9 ,]+)\\)" found_tests ${contents}) + foreach(hit ${found_tests}) + string(REGEX MATCH "${gtest_test_type_regex}" test_type ${hit}) + + # Parameterized tests have a different signature for the filter + if("x${test_type}" STREQUAL "xTEST_P") + string(REGEX REPLACE ${gtest_case_name_regex} "*/\\1.\\2/*" test_name ${hit}) + elseif("x${test_type}" STREQUAL "xTEST_F" OR "x${test_type}" STREQUAL "xTEST") + string(REGEX REPLACE ${gtest_case_name_regex} "\\1.\\2" test_name ${hit}) + elseif("x${test_type}" STREQUAL "xTYPED_TEST") + string(REGEX REPLACE ${gtest_case_name_regex} "\\1/*.\\2" test_name ${hit}) + else() + message(WARNING "Could not parse GTest ${hit} for adding to CTest.") + continue() + endif() + add_test(NAME ${test_name} COMMAND ${executable} --gtest_filter=${test_name} ${extra_args}) + endforeach() + endforeach() +endfunction() ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-modules.7.rst | 1 + Help/module/GoogleTest.rst | 1 + Help/release/dev/ExtractGTestMacro.rst | 5 +++ Modules/FindGTest.cmake | 60 ++------------------------ Modules/GoogleTest.cmake | 73 ++++++++++++++++++++++++++++++++ 5 files changed, 83 insertions(+), 57 deletions(-) create mode 100644 Help/module/GoogleTest.rst create mode 100644 Help/release/dev/ExtractGTestMacro.rst create mode 100644 Modules/GoogleTest.cmake hooks/post-receive -- CMake From robert.maynard at kitware.com Tue Feb 7 13:11:46 2017 From: robert.maynard at kitware.com (Robert Maynard) Date: Tue, 7 Feb 2017 13:11:46 -0500 (EST) Subject: [Cmake-commits] CMake annotated tag, v3.8.0-rc1, created. v3.8.0-rc1 Message-ID: <20170207181146.89FD8F1F69@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The annotated tag, v3.8.0-rc1 has been created at b47338086e2c434b4d7958ef114f24abe9541316 (tag) tagging 84df4a49500e51ac6e2a19a77e385e66234386f7 (commit) replaces v3.7.2 tagged by Brad King on Tue Feb 7 09:22:18 2017 -0500 - Log ----------------------------------------------------------------- CMake 3.8.0-rc1 -----BEGIN PGP SIGNATURE----- iQJKBAABCAA0FiEExsJlMku+vcNQtRPQLSzvEDSSFoQFAliZ2BoWHGJyYWQua2lu Z0BraXR3YXJlLmNvbQAKCRAtLO8QNJIWhE25EAClV46/njUVlLQrvPj25cIvjPX3 rAkET+THc5sc7sWueW/bUzSO4RFqTYLaXPrEYvE8pACa28HDPX4UHSaitO80MAo4 UVKyS4upOPGHF3lhLFi4CfaqqY9qdx3uTh7C70ZurZub8cPX1ahA6/v4ONct5eRk N/6qAArnS5+zteXOYzGriUknnkj9KztTEm1iZzjxIHtSCrlKgCL/id+9UReiwddr X3ZOPKIZvg8f8gAUz7GGzQJIPLiDcPcAr21AGGUW0jwmGkxDetUofunXZa4E6Chd iaRYa1MtXf3yFftISH4Vwo2pxuwNY59CX7xRE9sfUiYuq02QKJfRHP4WMw/Tx6k+ AwgWYU97L9ywJA1H6+7ZupIXBXkPq/eepBN4ZRnAqKvPoSbd4YZM0PttoL110GoW 1lZLXg3lfsfhWHPCdHjTegLGbO0tNiEbkFjHfIr4+h+k469IxYiNtjkZZGc42JiY hy7QOsMMEDy8OgWHqp/M5DrqrY1syyFFynfYII9EPmhVbR7f2JOsKDu1wv3jCp+k /BYlwSzq+sapHojhkPpiS8ptVsNfZimYT7GXZcIzeD2Rm0LPY2rGc+hsoF7NV8BQ GW85TUp4BWntjwVLtPY99kM7GRo8ABZ0J/Lc7i4Tt8rDOmLTAWO5jkLJ1/DJUsAR f7xRjVWV8xFnnn9RHQ== =HMVM -----END PGP SIGNATURE----- Adam Martin (1): FindProtobuf: Search for debug library named with `d` suffix Adam Weisi (1): Eclipse: Fix indexer for subprojects Alex Turbov (5): FindBoost: Use string(APPEND) in more cases FindBoost: Use list(INSERT) to simplify suffix list generation FindBoost: Minor style updates FindBoost: Simplify library dir detection with cascading if/elseif/else FindBoost: Search official location of prebuilt binaries on Windows Alex Wang (1): Features: Fix cxx_right_angle_brackets compiler feature test Alexander Adam (2): CPack/RPM omit unsupported tags CPack/RPM test for Suggests tag Alexander Voitenko (1): QtIFW: Added new options to QtIFW cpack generator for modifying wizard style Alexey Sokolov (1): UseSWIG: Automatically scan dependencies of SWIG files for Makefiles Alexis Murzeau (1): Ninja: Use binary dir for `$subdir/all` targets Andre McCurdy (1): CheckFunctionExists.c: avoid gcc warnings with -Wstrict-prototypes Ben Boeckel (8): cmcldeps: search for single-byte strings as characters cmcldeps: append strings as strings cmcldeps: prefer the /TC flag ExternalProject: fix typo ExternalProject: support GIT_PROGRESS argument ExternalProject: support extracting the configure command FindHDF5: use the target rather than the path cmSystemTools: use the actual case for root detection Bernhard M. Wiedemann (3): cmTimestamp: Support SOURCE_DATE_EPOCH to override current time string: Teach TIMESTAMP to treat %% as % Tests: make tests pass with SOURCE_DATE_EPOCH set Betsy McPhail (1): ctest_memcheck: Add DEFECT_COUNT option to capture defect count Bill Hoffman (2): ctest_configure: Propagate CTEST_USE_LAUNCHERS from caller to project ctest: Improve output for `-T memcheck` Bjoern Thiel (2): InstallRequiredSystemLibraries: Distinguish UCRT install configurations FindCUDA: Enable CUDA_SELECT_NVCC_ARCH_FLAGS Auto for MSVC Brad King (590): Merge branch 'release' Begin post-3.7 development Merge topic 'fix-doc-3.7-relnotes' Merge branch 'release' Merge topic 'add-BUILD_RPATH' Do not define cout/cerr preprocessor symbols Utilities/Release: Drop macOS .tar.Z binary Utilities/Release: Drop Linux .tar.Z binary Merge topic 'no-tar.Z-binaries' Utilities/GitSetup: Fetch local hooks via https Utilities/Release: Update README to reference https URL Merge topic 'utils-https-cmake.org' Merge topic 'qtifw-https-cmake.org' Merge topic 'no-define-cout-cerr' Merge topic 'fix-VS-resources-pri-path' Merge topic 'cmake-server-improve-shutdown' Merge topic 'FindMatlab-fix-simulink-cache' Merge topic 'FindMatlab-documentation' Merge topic 'check-libuv-minimum-version' Merge topic 'cpack-rpm-debuginfo-fixes' Merge topic 'mips-rld-map-rel' Merge topic 'vs-15-preview-5' Merge topic 'android-ndk-r13' Merge topic 'codelite-global-setting' Merge topic 'CMP0065-LINK_FLAGS' Merge topic 'cleanup-Convert' Merge topic 'cpack-rpm-single-debuginfo' Merge topic 'nmake-encoding' Merge branch 'release' Tests: Improve RunCMake.CPack_* failure message formatting Merge topic 'FindProtobuf-fix-subdirs' Merge topic 'android-cxxabi' Merge topic 'android-export-has-cpp' Merge topic 'update-kwsys' Merge topic 'test-cpack-improve-failure-messages' Merge topic 'cmake-cleanup' Merge topic 'minor-cleanups' Merge topic 'ninja-cleanups' Merge topic 'clean-up-link-configuration' Merge branch 'release' Merge topic 'extract-cmLinkLineComputer' cmake: Factor out default generator selection into helper cmake: Simplify VS registry entry lookup cmake: Rename default generator selection internal variable cmake: Rename default generator selection list variable cmake: Use array iteration for default generator list cmake: Use array iteration for default generator VS variants cmake: Simplify default generator search by switching direction cmake: Fix default VS generator selection for Microsoft Build Tools Merge topic 'cmake-gui-fix-extra-generator-names' Merge topic 'vs15-separate-flag-table' Merge topic 'ExternalProject-fix-CMAKE_CACHE_ARGS-list' Merge topic 'remove-obsolete' Merge topic 'FindProtobuf-debug-suffix' Merge topic 'FindSDL-mingw-mwindows' Merge topic 'vs-default-generator' Help: Document VS and Xcode toolset selection Merge topic 'msbuild-json' Merge topic 'ice-3.6.3' Merge branch 'release' Merge branch 'backport-LINK_WHAT_YOU_USE-allow-OFF' into LINK_WHAT_YOU_USE-allow-OFF Merge topic 'LINK_WHAT_YOU_USE-allow-OFF' Merge topic 'ninja-rc-regression' Merge topic 'ninja-framework-POST_BUILD' Merge topic 'st2-exclude-patterns-variable' Merge topic 'FindBoost-minor-cleanup' Merge topic 'flush-archive-list' VS: Provide an option to use x64 host tools Merge topic 'vs-host-x64-tools' Merge branch 'release' cmExprParser: Port to bison 3 cmExprParser: Revise indentation style to match rest of CMake math(EXPR): Add support for unary `+` and `-` expressions Merge topic 'doc-clarify-ctest-APPEND' Merge topic 'doc-math-EXPR' Merge topic 'osx-no-deployment-target-on-cross-compile' Merge topic 'cmcldeps-more-safety' Merge topic 'refactor-folder-name-retrieval' Merge topic 'extract-cmRulePlaceholderExpander' Merge topic 'extract-computed-target-properties' Merge topic 'FindwxWidgets-unversioned-library-path' Merge topic 'math-EXPR-unary' Merge topic 'CheckFunctionExists-prototype' Merge topic 'propagate_ctest_use_launchers' Merge topic 'timeout_after_match_testtime' Merge branch 'release' Ninja: Add compile rules only for languages that are actually compiled Merge topic 'cmake-server-pipe-mode-fix' Merge topic 'fix-Android-NsightTegra' Merge topic 'ExternalData-multiple-hashes' Merge topic 'external-project-source-subdir-usage' Merge branch 'release' Merge branch 'release' Merge topic 'split-cmState' Merge topic 'clang-tidy' Merge topic 'ninja-only-object-rules' Merge topic 'external-project-configure-command-extraction' Merge topic 'external-project-clone-progress' Merge topic 'vs-csharp-prep' cmGlobalGenerator: Allow FindMakeProgram to fail Ninja: Fail early on when ninja build tool does not run Help: Format MAP_IMPORTED_CONFIG_ documentation Tests: Add test for MAP_IMPORTED_CONFIG_ empty fallback Merge topic 'android-armeabi-c++_static' Merge topic 'ninja-diagnose-missing-tool' Merge topic 'allow-fallback-config-mapping' Merge topic 'ninja-encoding' Merge topic 'cm_unordered_map' Merge topic 'android-link-exe' Merge topic 'separate-compilation' Merge topic 'remove-cmobject-uses' Merge topic 'parallel-boostrap-test' Merge topic 'cmcommand-no-disable' Merge topic 'doc-cmake-server-typos' Merge branch 'backport-ninja-subdir-binary-dir' into ninja-subdir-binary-dir Merge topic 'cmake-server-message-quoting' Merge topic 'ninja-subdir-binary-dir' Merge topic 'android-pic' Merge topic 'st2-fix-regex' Merge topic 'intel-compile-features-windows' Merge topic 'remove-cmobject' Merge topic 'cm_unordered_set' Merge branch 'release' Merge branch 'upstream-KWSys' into update-kwsys VS: Add internal API to get platform toolset as string Merge topic 'fix-right-angle-bracket-feature-test' Merge topic 'update-kwsys' Merge topic 'vs-toolset-options' Intel: Fix compiler C++98 standard flag on Windows VS: Fix use of `Windows7.1SDK` 64-bit toolset with VS 2010 Express Merge topic 'vs-fix-no-toolset' Merge topic 'intel-17-features' Merge topic 'intel-compiler-windows-c++98' Merge topic 'consoleBuf' Merge topic 'include-what-you-use' Intel: Remove incorrect C++98 standard compiler flag on Windows Features: Unset Intel CXX feature temporaries Features: Port Intel CXX features to test macros where possible Features: Record features for Intel Compiler on Windows FindSDL_sound: Fix SDL_SOUND_LIBRARIES result value Merge topic 'cmake-server-handshake-improvements' Merge branch 'release' Tests: Add case for Xcode per-config per-source COMPILE_FLAGS diagnostic Fix custom command target substitution with CROSSCOMPILING_EMULATOR Tests: Check that CROSSCOMPILING_EMULATOR is not used on imported targets Ninja: Fix POST_BUILD noop on Windows Merge topic 'ninja-windows-POST_BUILD-noop' Merge topic 'intel-compile-features-windows' Merge topic 'clang-tidy' Merge topic 'st2-env-vars-variable' Merge topic 'src-COMPILE_FLAGS-genex' Merge topic 'FindMatlab-9.1' Merge topic 'FindMatlab-fix-typo' Merge topic 'FindSDL-sound-fix' Merge topic 'custom-command-CROSSCOMPILING_EMULATOR' Merge branch 'release' Merge topic 'CPackDeb-doc-typos' Merge topic 'doc-tweaks' Merge topic 'find-qt5-docs' Merge topic 'UseSWIG-SWIG_OUTFILE_DIR' Merge topic 'fix-macos-sysroot' Merge topic 'fix_compiler_arg1' Merge topic 'cpack-doc-typos' Merge topic 'doc-cmake-qt-missing-dbus' Merge topic 'doc-cmake-qt-fixes' Merge branch 'release' Features: Do not record features on MSVC < 2010 Features: Centralize per-compiler recording macros Features: Add meta-features requesting awareness of a particular standard WCDH: Ignore language standard meta-features Features: Test feature propagation with language standard meta-feature Features: Test cycle diagnostic with language standard meta-feature Help: Document language standard meta-features Merge branch 'qtdialog-lib-paths' into release-3.6 Merge branch 'FindHDF5-restore-default-C' into release-3.6 CMake 3.6.3 VS: Place source-specific AdditionalOptions after target-wide flags Features: Fix Intel cxx_attributes existence condition Merge topic 'intel-compile-features-windows' Merge topic 'compile-features-for-language-standards' Merge topic 'remove-utf8-option' Merge topic 'FindHDF5-restore-default-C' Merge branch 'release-3.6' Merge branch 'release' Merge branch 'release-3.6' Add script to update librhash from upstream Merge branch 'upstream-librhash' into import-librhash cmTarget: Clarify comments in GetMappedConfig cmTarget: Add comment clarifying interface library special case cmTarget: Refactor GetMappedConfig to choose location property up front Merge topic 'cpackifw-search-algorithm' Merge topic 'vs-flag-order' Merge branch 'release' Merge branch 'release' FortranCInterface: Make mangling detection robust to PIC Fortran Merge topic 'FortranCInterface-pic' Merge topic 'cpack-rpm-omit-unsupported-tags' Merge topic 'clang-tidy' Merge topic 'include-what-you-use' Drop KWStyle checks in favor of clang-format and Git hooks Merge branch 'upstream-KWSys' into update-kwsys Allow imported INTERFACE libraries to specify a link library name Merge topic 'imported-interface-libname' Merge topic 'pkgconfig_imported_target' Merge topic 'FindSDL_preventGrowingCacheVar' Merge topic 'drop-kwstyle' Merge topic 'update-kwsys' librhash: Remove source fragments not needed for CMake librhash: Build the library within CMake librhash: Disable warnings to avoid changing 3rd party code librhash: Install COPYING file with CMake documentation librhash: Use __builtin_bswap{32,64} on Clang librhash: Implement bswap_64 even in strict C90 mode librhash: Implement bswap_32 as a function even in strict C90 mode librhash: Avoid signed left-shift overflow cmCryptoHash: Avoid using subclasses at client sites cmCryptoHash: Re-implement in terms of librhash librhash: Port to KWIML for ABI and integer type information Port hash computation to cmCryptoHash Remove unused cm_sha2 infrastructure FindLibRHash: Add module to find the librhash package Add option to build CMake against a system librhash Merge topic 'autorcc-only-no-rebuild' Merge topic 'import-librhash' Merge branch 'release' Features: Fix standards and features for Intel 15 on Windows Features: Suppress c_static_assert test coverage on Intel <= 15 Features: Detect Intel C++14 mode more reliably librhash: Update import script to add SHA-3 implementation Merge branch 'upstream-librhash' into add-SHA-3 librhash: Activate SHA-3 implementation Help: De-duplicate and spell out supported hash algorithms cmCryptoHash: Add support for SHA-3 algorithms string: Add support for SHA-3 algorithms file: Add support for SHA-3 algorithms Merge branch 'release' Merge topic 'intel-compile-features-windows-15' Merge topic 'intel-compile-features' Merge topic 'ExternalProject-GIT_CONFIG' Merge topic 'ctest_memcheck_defect_count' Merge topic 'fuchsia-platform' Merge topic 'vs_targets_file_as_library' Merge topic 'cdash_version_check' Help: Add notes for topic 'swig_add_library' ExternalData: Add support for SHA-3 algorithms ExternalProject: Add support for SHA-3 algorithms Tests: Add SHA-3 algorithm coverage to CPack checksum test Help: Add notes for topic 'add-SHA-3' Merge topic 'swig_add_library' Merge topic 'ninja-comment-ComputeLinkCmd' cmCTestBuildHandler: Use size_t in ProcessBuffer length argument Android: Always set CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION Android: Add CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG variable Android: Add CMAKE__ANDROID_TOOLCHAIN_MACHINE Help: Add release note for CUDA support ExternalProject: Fix UPDATE_DISCONNECTED with empty update steps Merge topic 'FindBISON-fix-rebuild' Merge topic 'cmake-server-fix-16422' Merge topic 'cmake-server-fix-16423' Merge topic 'ExternalProject-fix-UPDATE_DISCONNECTED' Merge topic 'UseSWIG_USE_BUILD_SHARED_LIBS' Merge topic 'add-SHA-3' Merge branch 'release' MSVC: Do not define _DEBUG explicitly when using /MDd Merge topic 'armcc-response-file-flag' Merge topic 'childEncoding' Merge topic 'Empty_CTestTestfile_on_BUILD_TESTING_OFF' Merge topic 'msvc-no-explicit-_DEBUG' Merge topic 'vs-suppress-upgrade-prompt' Merge topic 'test_vs_targets_file_reference' Merge topic 'ccmake_fix_print_keys' Merge branch 'upstream-KWSys' into update-kwsys Merge topic 'update-kwsys' Merge topic 'improve_ctest_memcheck_output' Merge topic 'cmake-m4-destination' Merge topic 'android-info-variables' Tolerate removed/replaced CMakeCache.txt with old CMakeFiles/ Utilities/Release: Update to openssl-1.0.2j Merge topic 'xcode-add-override-keyword' Merge topic 'update-prebuilt-openssl' Merge topic 'ExternalProject-cmd-poisoning' Merge topic 'tolerate-removed-cache' Merge topic 'auto_project_regeneration' Merge branch 'upstream-KWSys' into update-kwsys cmake: Comment why we ignore the include-what-you-use return code cmake: If ldd for LINK_WHAT_YOU_USE fails to run then report why cmake: Report if the _CLANG_TIDY tool exits with non-zero Android: Always set CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION Android: Add CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG variable Android: Add CMAKE__ANDROID_TOOLCHAIN_MACHINE Merge topic 'backport-android-info-variables' Help: Drop release notes for backported Android variables Merge topic 'backport-android-info-variables' Merge topic 'backport-android-info-variables' Merge branch 'release' Merge branch 'release' Merge topic 'update-kwsys' Merge topic 'capture-clang-tidy-errors' Help: Mention IMPORTED_LIBNAME_* in interface library property whitelist Merge topic 'doc-imported-interface-libname' Allow NO_SYSTEM_FROM_IMPORTED on imported INTERFACE libraries Merge topic 'doc-CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT' Merge topic 'imported-interface-no-system' Merge topic 'eclipse-subprojects' try_compile: Honor CMAKE_WARN_DEPRECATED in test project Merge branch 'release' FindPythonLibs: Tolerate a non-absolute PYTHON_EXECUTABLE Merge topic '16449-revert-xcode-system-includes' Merge topic 'cpack-tests-framework-updates' Merge topic 'include-what-you-use' librhash: Avoid signed left-shift overflow in sha256 Merge topic 'libarchive-openssl-1.1' Merge topic 'librhash-left-shift-unsigned' Merge topic 'initial_cuda_language_support' Merge topic 'try_compile-honor-CMAKE_WARN_DEPRECATED' Merge topic 'vs-default-build-package' Merge topic 'FindPkgConfig-fix-print-errors' Merge topic 'FindDevIL-updates' Merge topic 'find-module-cleanup-sweep' Merge branch 'release' Merge branch 'vs15-rename-generator' into vs15-rename-generator-for-master Merge branch 'upstream-KWSys' into update-kwsys Merge topic 'vs15-rename-generator-for-master' Merge topic 'update-kwsys' Merge topic 'UseSWIG-java-outputs' Merge topic 'end-commands' Merge topic 'QtAutogen_tests_update_v2' Merge topic 'cpack-ifw-options' Merge topic 'FindPythonLibs-tolerate-relative-exe' Merge topic 'msbuild-customization' Merge topic 'CMakeGraphVizOptions-docs' Merge branch 'release' Ninja,Makefile: Name static library compile PDB files as VS does Merge branch 'release' PGI: Pass macOS-specific link flags directly to linker Merge topic 'VS_DEBUGGER_WORKING_DIRECTORY' Merge topic 'cmake-server-pad-arguments' Merge topic 'vs-Zc-inline' Merge topic 'pgi-macos-flags' Merge topic 'compile-pdb-default' Merge topic 'cmake-ifw-root-component' Merge branch 'release' cmake-gui: Clarify help string on toolset selection field Merge topic 'utf8pipe' Merge topic 'execute_process-encoding' Merge topic 'target_project_type' Merge topic 'csharp_compiler_flag_tables' Merge topic 'packaging-qtsdk' Merge topic 'cmake-gui-T-help' Features: Make feature recording conditions more consistent Features: Add infrastructure for C++ 17 language standard Features: Activate C++ 17 support for GNU 5.1+ Features: Activate C++ 17 support for Clang 3.5+ Features: Activate C++ 17 support for AppleClang 6.1+ Help: Add release note for C++ 17 support FindOpenGL: Provide imported targets for GL and GLU Merge topic 'asm-splitting' Merge topic 'src-COMPILE_FLAGS-genex' Merge topic 'cpack-rpm-user-file-list-with-multiple-directives' Merge topic 'test-handler-multimap' Merge branch 'upstream-KWSys' into update-kwsys Merge topic 'features-c++17' curl: Update script to get curl 7.51.0 Merge branch 'upstream-curl' into update-curl curl: Disable symbol hiding logic in build for CMake try_compile: Stop processing when test build system fails to generate try_compile: Add options to specify language standards try_compile: Add policy CMP0067 to honor language standards Help: Add notes for topic 'wix-reg-install-dir' Merge topic 'wix-reg-install-dir' Merge topic 'update-kwsys' Merge topic 'update-curl' Merge topic 'FindOpenGL-imported-targets' Merge topic 'QtAutogen_Contain' Merge topic 'try_compile-lang-std' Merge branch 'vs-fix-standalone-Windows7.1SDK-toolset' into vs-fix-standalone-Windows7.1SDK-toolset-for-master Merge topic 'vs-fix-standalone-Windows7.1SDK-toolset-for-master' Merge topic 'cpack-deb-missing-file-utility-error' Merge topic 'csharp_support_options_isdebug' Merge branch 'release' Makefile: Restore RULE_LAUNCH_COMPILE generation on compilation rules Comment ExpandRuleVariables calls not preceded by launcher insertion cmRulePlaceholderExpander: Remove unused member RuleLauncher CUDA: Fix default compiler flag initialization CUDA: Fix Cuda.Complex test case extern function signatures Merge topic 'FindBoost-vs15' Merge branch 'release' Help: Add notes for topic 'xcode-message-extension' Merge topic 'fix-ctest-launchers' Merge topic 'xcode-message-extension' Merge topic 'clang-tidy' Merge topic 'document_cuda_standard_property' Merge topic 'cuda-fixups' Merge topic 'GetPrerequisites-fix-find_program-call' Merge topic 'try_compile-lang-std-cuda' CUDA: Implement nvcc implicit link line extraction more robustly pre-commit: Update KWSys rejection message for new upstream location Merge topic 'update-kwsys-upstream-link' Merge topic 'GNUInstallDirs-cache-type' Merge topic 'dotnet_hint_references' Merge topic 'rebuild-lexers' Merge topic 'cuda-implicit-libs' Help: Clarify meaning of CMAKE_CL_64 update-kwsys: Update repository URL Merge branch 'upstream-KWSys' into update-kwsys Merge topic 'update-kwsys' Merge topic 'doc-clarify-CMAKE_CL_64' Merge topic 'codelite-build-and-clean-targets-enhancement' Merge topic 'FindPNG-typo' Copyright.txt: Update year range to end in 2017 Makefile,Ninja: De-duplicate MSVC compiler PDB path selection Merge topic 'copyright-year' Merge topic 'csharp_support_compiler_detection' Merge topic 'refactor-compile-pdb-path' Merge topic 'FindPythonLibs-tolerate-components' Merge topic 'cuda_tests_now_explain_why_they_fail' Merge topic 'FindGit-fix-cross-compile' Fix typo in error message on missing required variable Merge topic 'pgi-ninja-fortran' Merge topic 'mr-reset-error-flag-on-configure' Merge topic 'fix-required-var-error-typo' Merge topic 'read-only-type-target-property' Merge topic '15687-revisit-xcode-system-include' Merge topic 'cpack-deb-package-version-override-fix' Merge branch 'cmake-server-do-not-crash-on-interface-lib' into cmake-server-do-not-crash-on-interface-lib-for-master Merge topic 'cmake-server-do-not-crash-on-interface-lib-for-master' Merge topic 'cpack-rpm-user-binary-spec-file-fix' Merge topic 'cpack-test-extra-std-out-err-file-overloads' Merge topic 'cpack-deb-md5sums-paths-fix' Merge topic 'cpack-new-tests' Merge topic '16204-regex-explorer-match-all' cmListFileLexer: Fix signature of cmListFileLexer_New VS: Port Visual Studio Setup third-party header to older VS versions Merge topic 'FindBoost-find-default' Merge topic 'FindGTest-fixups' Merge topic 'FindBoost-1.63' Merge topic 'pgsql-yum' Merge topic 'FindOpenSSL-check-both' Merge topic 'SublimeText-no-VERBOSE' Merge topic 'issue-16513-concrt140-dll' Merge topic 'AndroidTestUtilities-fix-cleanup' Merge topic 'android_clang_asm' Merge topic 'Autogen_Simplify' Merge topic 'cpack-rpm-user-binary-spec-file-test' Merge topic 'BundleUtilities-symlink-structure' Merge topic 'solaris-build-fixes' Merge topic 'UseSWIG-implicit-depends' Merge topic 'ctest_memcheck-leak_sanitizer' Merge branch 'release' Merge topic 'cmFileMonitor-skip-empty-names' Merge topic 'codeblocks-nmake-makefiles-jom' Merge topic 'add-cpack-ifw-configure-file' Merge topic 'cmake-install-infix' Merge topic 'dont-include-CMakeParseArguments' Merge topic 'cmListFileLexer-warning-fix' Merge topic 'vs15-detect-from-installer' Merge topic 'FindJava-jre-hints' Merge topic 'cuda_compile_features_test_use_widely_supported_feature' Merge topic 'fix_get_prerequisites' Merge topic 'get_prerequisites_delayload' Merge topic 'InstallRequiredSystemLibraries-UCRT-configs' Merge topic 'asan_overriding_user_options' Merge topic 'launcher-tests' Merge branch 'release' CMakeParseImplicitLinkInfo: Add support for MSVC invoked by CUDA nvcc CUDA: Allow platform files to set device linking rules CUDA: Detect use of MSVC host compiler CUDA: Detect MSVC architecture id CUDA: Use `.obj` object file extension on Windows CUDA: Populate compiler PDB placeholder during device linking CUDA: Find MSVC binutils on Windows CUDA: Detect implicit link information on Windows CUDA: Populate NVIDIA compiler information on Windows CUDA: Port test cases to Windows with MSVC host compiler CUDA: Enable CudaOnly.SeparateCompilation test runtime calls Merge topic 'cuda-windows' VS: Fix detection of VS 2017 installation with WindowsStore cmVSSetupHelper: Simplify use of EnumerateAndChooseVSInstance Ninja: Do not use module definition `.def` files for static libraries Merge branch 'release' Merge topic 'docs-function-exists' file: Fix crash on GLOB with no expressions after LIST_DIRECTORIES Merge topic 'sparc-libatomic' Merge topic 'fix_repeat_until_fail_duplicated_output' Merge topic 'clang-3.1-3.3-cpp11' Merge topic 'usage-cpack-ifw-configure-file' Merge topic 'vs15-detect-from-installer' Merge topic 'ninja-no-static-lib-def-file' Merge topic 'cuda_propagate_flags_when_dlink_on_executables' Merge topic 'cuda-no-def-file-for-device' Merge topic 'fast-local-and-strip-install' Merge topic 'Autogen_Config' Merge topic 'csharp_simple' Merge topic 'source_group-tree' cmCTestBuildHandler: Fix warning in FragmentCompare signature Merge branch 'upstream-KWSys' into update-kwsys Merge topic 'expand_custom_commands' Merge topic 'file-GLOB-empty-no-crash' Merge topic 'fixtureUnusedOrdering' Merge topic 'findhdf5-libraries-targets' Merge topic 'FindICU-include-dirs' Merge topic 'update-kwsys' Merge topic 'cmCTestBuildHandler-fix-warning' ExternalProject: Restore case-insensitive download hash check Merge branch 'case-insensitive-bindir-detection' into release Merge topic 'cdash_upload_retry' Merge topic '16165-manually-added-dependencies' Merge topic 'cpack-ifw-new-installer-options' Merge topic 'case-insensitive-bindir-detection' Merge topic 'ExternalProject-restore-case-insensitive-hash' Merge topic 'add-dl-to-lua-static-linking' Android: Fix c++_{static,shared} support include directory order Android: Pass sysroot include directory explicitly Merge topic 'csproj-improvements' Merge topic 'qt4-lupdate-cmp0058' Merge topic 'qtdialog-trim-new-varname' Merge topic '16253-xcode-effective-platform-name' Merge topic 'android-include-api' Merge topic 'cpack-stgz-minimal-test' Merge topic 'dl-libs-typo' FindLua: try to find library according to version from header Merge topic 'cuda_linker_preference' Merge topic 'lang_lint' Merge topic 'sanitizer-options' Merge topic 'cpack-ifw-options' Merge topic 'intel-mpi-windows-fix' Merge topic 'testdriver-cleanup' Tests: Simplify GeneratorExpression imported include directory check Tests: Teach GeneratorExpression to cover spaces in include dirs Tests: Extend GeneratorExpression to work with more configurations Merge topic 'FindLua-versioned-lib' Merge topic 'FindGTK2_RunTwice' Merge topic 'pkg-config-recheck' Merge topic 'FindCUDA-select-flags-auto-msvc' Merge topic 'tests_auto_type' Merge topic 'test-GeneratorExpression-update' Merge topic 'topic-reproducible-build' Merge topic 'GNUG_define' Merge topic 'genex-if' Merge topic 'test-preprocess-configs' Merge topic 'timestamp-percent' Merge topic 'FeatureSummary_enhancement' Add script to update GitSetup from upstream Merge branch 'upstream-GitSetup' into developer-setup Merge branch 'upstream-GitSetup' into developer-setup GitSetup: Tell Git not to export .gitattributes Tell Git not to export the GitSetup directory Merge topic 'developer-setup' Merge topic '16432-static-frameworks' Merge topic 'vs-export-external-objects' Merge topic 'topic-reproducible-build' Merge topic 'FindBoost-cache-unset-on-change' Merge topic 'CSharpVS2017' Add pre-commit hook to check whether SetupForDevelopment must re-run Convert local hook configuration to a Git config file format Help: Fix typo in _NOT_FOUND_MESSAGE example in cmake-packages(7) FortranCInterface: Fix support for VS with Intel toolset Features: Update version of Intel Compiler on Windows supporting C 11 Help: Extend documented purpose of cmake-developer(7) manual Merge topic 'developer-setup' Merge topic 'doc-cmake-developer-purpose' Merge topic 'doc-cmake-packages-typo' Merge topic 'intel-c11-windows' Merge topic 'FortranCInterface-vs-intel-workaround' Merge topic 'WCDH_allow_unsupported' Merge branch 'release-3.7' Merge branch 'release-3.7' Merge topic 'FindGSL-regex-fixup' Help: Fix language standard link text in cmake-compile-features(7) Merge topic 'doc-compile-features-fixup' Merge topic 'find_cuda_fix_typo' FindHDF5: Fix command-line parsing argument extraction order FindHDF5: Initialize/finalize internal search options variable FindHDF5: Use keywords in find_library calls FindHDF5: Fix search with HDF5_ROOT FindHDF5: Restore fallback to static libraries Merge topic 'gcc-features' FindHDF5: Restore HDF5_INCLUDE_DIR in all code paths VS: Fix quoting of special characters in cmake re-run check commands Merge topic 'findmpi-flags-fix' Merge topic 'FindHDF5-fix-HDF5_ROOT' Merge topic 'androidtestutilities_cleanup' Merge topic 'productbuild_signing' Merge topic 'vs-quote-rerun-paths' Help: Consolidate 3.8 release notes Help: Organize and revise 3.8 release notes Merge topic 'doc-3.8-relnotes' Help: Drop development topic notes to prepare release CMake 3.8.0-rc1 version update Merge branch 'FeatureSummary-doc-cleanup' into release Bruno Pedrosa (3): Sublime: Exclude build tree from source tree project only optionally Sublime: Update generated diagnostic matching expression for MSVC Sublime: Add option to specify env vars for the .sublime-project Christian Fetzer (3): Help: Clarify how to run sequential commands in execute_process Help: Document error behavior of file(REMOVE/REMOVE_RECURSE) ExternalProject: Allow passing config flags to git clone Christian Pfeiffer (4): FindMPI: Add Intel MPI wrapper names on Windows FindMPI: Strip quotes from include path and convert to CMake path format FindMPI: Reset MPI_INCLUDE_PATH_WORK before use FindMPI: Remove leading spaces from flags Clinton Stimpson (3): Encoding: Remove option to use ANSI code page internally Qt4: Only change timestamp on generated .pro files if content changes cmake-gui: trim spaces from user-created variable names Colby Pike (1): Genex: Add `IF` generator expression Cong Zhang (1): UseSWIG: Add option to specify swig output file directory Craig Scott (2): FindSDL: Prevent unbounded growth of SDL_LIBRARY_TEMP variable CTest: Ensure setup/cleanup ordering even when fixture not required Curl Upstream (1): curl 2016-11-02 (3c561c65) Daniel Carrera (1): PGI: Add support for Fortran with the Ninja generator Daniel Pfeifer (58): cmOutputConverter: remove unused code CMakeCPack: remove obsolete conditions Don't require libbz2 when using system libarchive Don't require liblzma when using system libarchive Allow custom built libarchive to use custom built expat. silence selected clang-tidy violations fix more issues reported by clang-tidy Separate compilation for commands included in cmCommands Separate compilation for commands included in cmBootstrapCommands1 Separate compilation for commands included in cmBootstrapCommands2 Create all commands from a single function bootstrap: Sort source files lexicographically cmCommand: implement functions in cxx file BootstrapTest: Use --parallel=... argument. Fix newly discovered clang-tidy issues Make cmCommand not inherit from cmObject Make cmCPackLog not inherit from cmObject Make cmCTestGenericHandler not inherit from cmObject Make cmCPackGeneratorFactory not inherit from cmObject Make cmCPackGenerator not inherit from cmObject Introduce CM_UNORDERED_MAP Remove cmCommand::Enabled and all related accessors Remove cmObject.h and cmTypeMacro.h Introduce CM_UNORDERED_SET Include necessary headers in commands Use the empty method to check for emptiness Remove redundant c_str() calls Avoid some copies cmCPluginAPI: Fix clang-tidy findings cmCTestSubmitHandler: Remove redundant c_str() cmGlobalNinjaGenerator: Suppress clang-tidy warning cmGeneratorTarget: Don't assing a bool to a string cmGeneratorTarget: Correctly set FortranModuleDirectoryCreated Fix several include-what-you-use findings iwyu: Fix OSX specific issues iwyu: Fix more findings iwyu: Fix VisualStudio specific issues avoid including cmStandardIncludes.h Make error message of standalone endwhile command consistent Set the error after argument expansion in end commands Combine all unexpected commands to a single class cmCTestTestHandler: use multimap clang-tidy: apply performance-unnecessary-value-param fixes clang-tidy: apply performance-faster-string-find fixes clang-tidy: apply readability-redundant-string-init fixes clang-tidy: apply modernize-use-bool-literals fixes clang-tidy: apply readability-redundant-control-flow fixes clang-tidy: apply readability-static-definition-in-anonymous-namespace fixes clang-tidy: apply misc-suspicious-string-compare fixes clang-tidy: apply misc-redundant-expression fixes Regenerate lexer source code CPackDeb: use CPACK_DEBIAN_PACKAGE_VERSION Don't include CMakeParseArguments TestDriver: Revise C++ coding style using clang-format TestDriver: abstract CM_CAST macro TestDriver: use for loop TestDriver: calc NumTests at compile time TestDriver: fix/silence clang-tidy warnings Daniele E. Domenichelli (16): UseSWIG: Add swig_add_library macro. UseSWIG: Do not set NO_SONAME property for SHARED and STATIC libraries UseSWIG: Do not set PREFIX property for SHARED and STATIC lua libraries SwigTest: Update for swig_add_library and add lua example UseSWIG: Add USE_BUILD_SHARED_LIBS to accepted values for the TYPE arg FindGTK2: Fix GTK2_LIBRARIES and GTK2_TARGETS when called twice FindGTK2: Add unit test to check variables when run twice FeatureSummary: Clean printed output FeatureSummary: Add deprecation warnings to deprecated commands FeatureSummary: Do not force OPTIONAL type in SET_PACKAGE_PROPERTIES FeatureSummary: Add unit tests FeatureSummary: Add QUIET_ON_EMPTY option to feature_summary FeatureSummary: Allow lists of dependencies in ADD_FEATURE_INFO FeatureSummary: Refactor to use global properties for package types FeatureSummary: Update release notes FeatureSummary: Fix documentation Domen Vrankar (33): CPack/RPM learned defining main component CPack/RPM single debuginfo packaging CPack/RPM prevent special tags from being removed Release text for omitting unsupported tags topic Tests: CPack fix for invalid config file path Tests: fix CPack test source packages missing generator type Tests: CPack/RPM test introduction of default stderr test output Tests: CPack test should use default package name Tests: CPack move tests to separate dir Tests: CPack test move std error files to test files Tests: CPack test should always check test output Tests: CPack test move ExpectedFiles script Tests: CPack test merge generator specifics Tests: CPack test move per test prerequirements Tests: CPack test move and merge VerifyResult Tests: CPack test unify expected file naming Tests: CPack test use same content list Tests: CPack test long_filenames prerequirements Tests: remove generator prefix from CPack test name Tests: CPack test set packaging type Tests: source CPack tests don't require build stage Tests: CPack/DEB test change prerequirements check Tests: CPack test documentation facelift CPack/RPM CPACK_RPM_USER_FILELIST change release note CPack/Archive minimal tests for more formats RunCMake.CPack_* add COMPONENT to minimal test CPack/Deb invalid md5sums file fix store old locale to a temporary variable CPack/RPM fix - custom binary spec file handling CPack test additional std out/err regex file overloads CPack/RPM test for using custom binary spec file CPack/STGZ prefer pax for extraction CPack/STGZ: minimalistic packages test Don Olmstead (3): Add a script to convert from MSBuild XML to a JSON format VS: Move toolset flag table lookup to global generator VS: Choose flag map based on the toolset name Dong XiaoC (2): FindGTest: Fix documented GTEST_MSVC_SEARCH default value FindGTest: add lib search path for MSVC x64 platform D?vis Mos?ns (12): codecvt: Add class for encoding conversion cmGeneratedFileStream: Add optional encoding support NMake: Use ANSI encoding for NMake Makefiles cmSystemTools: Flush output buffer for list_item_verbose Ninja: Use ANSI encoding for Ninja build files on Windows Enable Unicode output to Windows consoles Add cmProcessOutput class to be used for decoding text data Windows: Encode child process output to internally-used encoding Add Encoding option for RunChild, RunMakeCommand and RunProcess CTest: Use UTF-8 encoding for output from Git Windows: Use UTF-8 for pipes in CMake, CTest and CPack execute_process: Add ENCODING option for Windows child process output Ed Branch (1): add_custom_{command,target}: Add COMMAND_EXPAND_LISTS option Emil Laine (1): FindSDL: Add -mwindows to link flags for MinGW, correct wording Eric Berge (2): Disable libuv on Solaris 10 libuv requires _XOPEN_SOURCE 600 on Solaris 11 Erik Christensen (1): VS: Disable project upgrade prompt on VS 2013 and above Florent Castelli (2): Android: Set compiler target platform when compiling ASM with Clang FindICU: Add 'include' to the path suffixes Francois Budin (1): FindPythonLibs: Tolerate call with PYTHON_LIBRARY already a list Gautier Pelloux-Prayer (1): FindPkgConfig: Fix missing error text when library version is specified Giel van Schijndel (1): Features: activate C++11 support for Clang 3.1+ Gilles Khouzam (2): Tests: Make Preprocess test work in RelWithDebInfo and MinSizeRel VS: Fix CSharp compiler identification for VS 2017 GitSetup Upstream (2): GitSetup 2012-04-26 (b7daff9b) GitSetup 2016-12-13 (cd5ada6d) Gregor Jasny (14): Factor IDE folder name retrieval out into helper method Xcode: Add override keyword to suppress warnings Xcode: Add target property to override productType Xcode: Add target property to override explicitFileType Xcode: Properly mark SYSTEM includes as such cmTarget: Enforce TYPE being a read-only property cmake-gui: Add MATCHALL option to Regex Explorer Add a getter for manually added target dependencies Xcode: Control emission of EFFECTIVE_PLATFORM_NAME Makefile: Re-order list of files to clean Makefile: For static libraries remove only the "real" lib before creating Xcode: Ignore Xcode project warning until issue is fixed Xcode: Refactor RunCMake.Framework test to prepare for static frameworks Apple: Add support for static frameworks Harry Mallon (3): CMakeGraphVizOptions: Minor improvements to docs. CPackRPM now supports multiple directives in CPACK_RPM_USER_FILELIST FindOpenSSL: Check that both CRYPTO and SSL libraries are present Henning Meyer (1): CPack/DEB shlibdep options depend on file utility Igor Peschinskiy (1): FindGSL: Fix gl_version.h extraction regex Iyyappa Murugandi (6): VS: Add Visual Studio Setup third-party header VS: Port Visual Studio Setup third-party header to MinGW VS: Drop check for VS 15 Express Edition VS: Fix VS 2017 Windows Store toolset selection VS: Add helper class to interact with Visual Studio Installer VS: Use Visual Studio Installer to locate VS 2017 James Cowgill (5): elf: remove tag switch from ELF_Dyn ByteSwap function elf: add DynamicEntryList methods and rpath tag constants cmSystemTools: rewrite RemoveRPath using DyanmicEntryList methods cmSystemTools, elf: handle DT_MIPS_RLD_REL_MAP in RemoveRPath elf: Remove GetDynamicEntryCount and ReadBytes methods Jamie Snape (8): Honor LINK_WHAT_YOU_USE when set to OFF ctest_memcheck: add support for standalone LeakSanitizer MEMORYCHECK_SUPPRESSIONS_FILE: add support for sanitizers ctest_memcheck: join *SAN_OPTIONS with : ctest_memcheck: do not add detect_leaks=1 to ASAN_OPTIONS Tests: Use CTEST_MEMORYCHECK_SANITIZER_OPTIONS where appropriate ctest_memcheck: Fix sanitizers when MemoryCheckSanitizerOptions is empty Add properties to run the cpplint style checker with the compiler Jens Weggemann (1): Teach MAP_IMPORTED_CONFIG_ to support configuration-less import Jos? Sim?es (1): FindGit: Fix check for Windows host KWSys Upstream (8): KWSys 2016-10-23 (b630d2f5) KWSys 2016-11-09 (18c65411) KWSys 2016-11-16 (a0c60eec) KWSys 2016-11-18 (2a3f6f6b) KWSys 2016-11-28 (1c7c2139) KWSys 2016-12-02 (4967ccc0) KWSys 2016-12-14 (95a7e234) KWSys 2017-01-16 (a423d829) Karsten Sperling (1): ExternalProject: Do not trip over pre-existing 'cmd' variable Kitware Robot (126): CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp CMake Nightly Date Stamp Konstantin Podsvirov (9): install: Configurable DESTINATION for the cmake.m4 file CPackIFW: Add some options QtIFW: Configurable root component QtIFW: Packaging as part of the QtSDK Allow CodeBlocks for NMake Makefiles JOM Add cpack_ifw_configure_file command Add installation infix (empty by default) QtIFW: Improved packaging CPackIFW: Add some options Marcus D. Hanwell (1): Help: Update example Qt 5 find_package call to use COMPONENTS Martin Koegler (3): GetPrerequisites: Fix call to find_program for `ri` tool BundleUtilities: Maintain symlink structure GetPrerequisites: Do not fail on files we cannot find Mateusz Janek (1): source_group: Add options create groups matching directory tree Matt McCormick (1): ExternalData: Add support for multiple hash algorithms Matthew Hanna (1): FindPkgConfig: Recheck pkg-config on parameter change. Matthew Woehlke (1): Tests: Add additional launcher tests Maxime Morel (1): FindPNG: Fix small typo fix in module help Michael Krasnyk (1): FindLua: Add dl library to Lua static library linking Michael St?rmer (15): VS: Add CSharp project uuid and file extension VS: Add internal API for detecting "managed" projects VS: Add option to place `PACKAGE` target in solution default build VS: Add option to customize vcxproj user props file VS: Add target property VS_DEBUGGER_WORKING_DIRECTORY cmVisualStudio10TargetGenerator: Prepare to handle C# projects VS: Add flag tables for C# VS: Teach option map IsDebug() method about C# projects VS: add support for .NET references with hint paths C# support: add compiler detection for MSVC VS: renamed target property VS_USER_PROPS_CXX to VS_USER_PROPS VS: added support for C# (for Visual Studio 2010, 2012, 2013, 2015) VS: added documentation for C# support VS: improve handling of source files with special extensions in .csproj VS: removed usage of relative paths for C# targets in in-source builds Micha? G?rny (1): CMakeDetermineASMCompiler: arg-split ASM* env var like CC Mike Gelfand (1): Makefiles: Make fast local and strip install truly fast Minze Zwerver (1): CodeLite: Make build/clean/rebuild operations optionally target-centric Nils Gladitz (1): Utilities/Release: Store WiX CMake install location in Windows registry Pascal Thomet (1): GetPrerequisites: Exclude delay load dependencies on Windows Petr Hosek (1): Add Fuchsia platform module Pierre Moreau (1): FindCUDA: Fix typo in CUDA_DETECT_INSTALLED_GPUS doc string Rechi Rechi (1): FindJava: add hints for jre Richard Collins (1): Sublime: Do not build with verbose output Robert Maynard (28): CUDA: Add basic CUDA language support for *NIX systems. CUDA: Add support language levels (98/11) CUDA: Explicitly state all source files are cuda sources. CUDA: CompilerId now errors out properly when passed a non CUDA compiler. CUDA: We now properly perform CUDA compiler identification. CUDA: State that cuda has preprocessor output and can generate assembly. CUDA: Enable header dependency scanning. CUDA: add support for specifying an explicit host compiler. CUDA: Use the host compiler for linking CUDA executables and shared libs. CUDA: C++ compile features now enable cuda c++11 support. CUDA: Refactor CMakeCUDAInformation to prepare for separable compilation. CUDA: Refactor cmLinkLineComputer to allow for better derived children. Ninja: Document why ComputeLinkCmd is structured the way it is. CUDA: Add LinkLineComputer that computes cuda dlink lines. CUDA: Add support for the CUDA_SEPARABLE_COMPILATION target property CUDA: Add separable compilation support to the ninja generator. CUDA: Add separable compilation support to the makefile generator. CUDA: Add support for CMAKE_CUDA_COMPILE_OPTIONS_VISIBILITY CUDA: Prefer environment variables CUDACXX and CUDAHOSTCXX. CUDA: Add tests to verify CUDA compiler works properly. Help: Document CUDA_STANDARD and related properties try_compile: extend CMP0067 to honor language standards for CUDA. CUDA: Tests now state why they are failing when no CUDA card is found. CUDA: ConsumeCompileFeatures use cxx_nullptr for wider compiler support CUDA: Don't use module definition `.def` files for device linking CUDA: Test that CUDA flags are used when device linking executables. CUDA: Now pass correct FLAGS when device link cuda executables. CUDA: set linker preference between C and C++ Roger Leigh (2): GNUInstallDirs: Unify path logic into helper macros GNUInstallDirs: Set UNINITALIZED cache properties to type PATH Rolf Eike Beer (14): FindLibArchive: use CMAKE_CURRENT_LIST_DIR to find FPHSA FindLibArchive: do not set LibArchive_FOUND explicitly Find*.cmake: drop the comments before including FPHSA Explicitly link against libatomic on Linux/sparc for `__atomic_fetch_add_4` Tests: use cxx_auto_type only if actually available GNUC: also check __GNUG__ define when checking for g++ WCDH: add macro to write simple replacement defines WCDH: optionally omit error code for unknown compilers or compiler versions Tests/Module/WCDH: make it work with only C features defined CompileFeatures Test: make sure the target "CompileFeatures" is always defined Tests/Module/WCDH: write multi_file_compiler_detection.h before using it Tests/Module/WCDH: only use -Werror=undef compiler flag if actually supported GNU C: record that C99 is available since at least 3.4 GNU C++: record that -fvisibility-inlines-hidden is available since 4.0 Roman W?ger (1): CPackProductBuild: Add options to sign packages Ruslan Baratov (2): Add a BUILD_RPATH target property specifying build-tree RPATH entries AndroidTestUtilities: fix cleanup operation Sebastian Holtermann (111): QtAutogen tests: Rename rcconly target to camel case rccOnly. QtAutogen tests: Rename rcc_empty target to camel case rccEmpty QtAutogen tests: Rename uiconly target to camel case uicOnly QtAutogen tests: Move independent sameName test to top list of CMakeLists.txt QtAutogen tests: Extend test description in CMakeLists.txt QtAutogen tests: Move the complex test case to a subdirectory QtAutogen tests: Pass Qt compiler features to library targets QtAutogen: Use util prefix for static function name QtAutogen: Use shorter name for static function QtAutogen: Remove and inline ReadAll function QtAutogen: Rcc related setup function rename QtAutogen: Rcc related list function rename QtAutogen: Rcc related function rename QtAutogen: Rcc related function rename QtAutogen: Uic related setup function rename QtAutogen: Uic related function rename QtAutogen: Moc related setup function rename QtAutogen: Move util functions to file begin QtAutogen: Target directory name function rename QtAutogen: Moc related variable renamed QtAutogen: Moc related variable renamed QtAutogen: Remove unused intermediate definition in makefile QtAutogen: Inline single use variable QtAutogen: Change config file permissions only on demand QtAutogen: Rename config AM_RELAXED_MODE to AM_MOC_RELAXED_MODE QtAutogen: Make strings const QtAutogen: Rename variable templates in config template QtAutogen: Variable scope optimizations QtAutogen: For loop feature test optimization QtAutogen: Comments QtAutogen: Improved error recognition on config load QtAutogen: Improved error recognition QtAutogen: Error and warning log method tweaks QtAutogen: Improved error handling QtAutogen: Make sure parent directory exists before writing files QtAutogen: New common bold logging method QtAutogen: Use upper case for MOC, UIC and RCC in messages QtAutogen: Generate moc compilation in _automoc.dir/moc_compilation.cpp QtAutogen: Remove .dir suffix from automoc build directory QtAutogen: Use checksum based subdirectories to avoid name collisions cmGeneratorTarget: Add AddIncludeDirectory method (experimental) QtAutogen: Generate included ui_ and moc_ files in _automoc/includes QtAutogen: Clean removes autogen build directory QtAutogen: Determine the Qt major version in only one way QtAutogen: Inline single use variable definitions QtAutogen: Rename autogen target to *_autogen from *_automoc QtAutogen: Reconfigure when .qrc file changes QtAutogen: Add moc compilation file to autogen target byproducts QtAutogen: Add rcc output files to autogen target byproducts QtAutogen: Generate rcc output file names in one place only QtAutogen: Rename and sort variables QtAutogen: Don't use std::i/ofstream::is_open() QtAutogen: Tests: Don't include CMAKE_CURRENT_BINARY_DIR QtAutogen: Tests: Don't use std::auto_ptr QtAutogen: Tests: Increase minimum required CMake version QtAutogen: Tests: Update ui_ include lookup directory QtAutogen: Tests: Don't use std::auto_ptr QtAutogen: AUTOMOC documentation update QtAutogen: CMake-Qt documentation update QtAutogen: Release notes for the Contain branch AUTOGEN: Generators: rename makeParentDirectory to MakeParentDirectory AUTOGEN: Generators: Cleanup variable initialization AUTOGEN: Generators: Cleanup and optimize ParseForUic method AUTOGEN: Generators: Variable rename AUTOGEN: Generators: Comments AUTOGEN: Generators: Introduce unified ParseSourceFile AUTOGEN: Generators: Use unified ParseSourceFile and drop old methods AUTOGEN: Generators: Use precompiled regular expressions AUTOGEN: Generators: Group static function definitions AUTOGEN: Generators: Rename ParseForUic method AUTOGEN: Generators: Split config headers/sources into vector AUTOGEN: Generators: Split config SKIP_MOC and SKIP_UIC into vectors AUTOGEN: Generators: Add dedicated method for moc content parsing AUTOGEN: Make skipMoc and skipUic blacklists behave the same way AUTOGEN: Rename config variables AUTOGEN: Initializer: Introduce SKIP_AUTOGEN checks AUTOGEN: Initializer: Enable SKIP_AUTOGEN on all AUTOGEN generated sources AUTOGEN: Initializer: Always remember skipped files AUTOGEN: Generators: Remove unused variable AUTOGEN: Generators: Be verbose about skipping files AUTOGEN: Generators: Use separate header lists for MOC and UIC AUTOGEN: Generators: Moc/UicSkipTest methods AUTOGEN: Generators: Use AUTOMOC/UIC/RCC instead of AUTOGEN in messages AUTOGEN: Generators: Use single moc/uic skip test method only AUTOGEN: Generators: Message upper/lower case unification AUTOGEN: Generators: Do moc/uic skip test during file list generation AUTOGEN: Tests: AUTOMOC SKIP_AUTOMOC and SKIP_AUTOGEN test AUTOGEN: Tests: AUTOUIC SKIP_AUTOUIC and SKIP_AUTOGEN test AUTOGEN: Tests: AUTORCC SKIP_AUTORCC and SKIP_AUTOGEN test AUTOGEN: Documentation for SKIP_AUTOX source file properties AUTOGEN: Documentation update: cmake-qt, AUTOMOC, AUTOUIC, AUTORCC AUTOGEN: Release notes for SKIP_AUTOX Autogen: Generators: Sort methods by task Autogen: Generators: Static function upper case rename Autogen: Generators: Static function upper case rename Autogen: Generators: Make class static method a source static function Autogen: Generators: Make class static method a source static function Autogen: Generators: Simplify (and fix) JoinExts function Autogen: Generators: Introduce FileAbsentOrOlder function Autogen: Generators: Use FileAbsentOrOlder for MOC tests Autogen: Generators: Use FileAbsentOrOlder for UIC tests Autogen: Generators: Rename GenerateFoo methods to FooGenerate Autogen: Generators: Move moc/uic/rcc executable test to generate method Autogen: Generators: Add function to read makefile definitions config aware Autogen: Generators: Save the MOC settings that were actually used Autogen: Generators: Dedicated generateAll variables for MOC/UIC/RCC Autogen: Generators: Save the UIC/RCC settings that were actually used Autogen: Initializer: Add old settings file to clean files Autogen: Generators: Fix clang-tidy readability-else-after-return Autogen: Generators: Rename requiresMocing method Autogen: Generators: Remove space Soji Yamakawa (2): VS: Treat libraries ending in `.targets` as msbuild imports Tests: Extend VS10Project to cover `.targets` file linking Stephen Kelly (123): Xcode: Inline ConvertToRelativePath calls Convert: Extract local variables Convert: Extract local variables for readability Convert: Remove early return check Convert: Remove asserts which are duplicated in delegate method Convert: Extract method to determine if paths are in directory Makefiles: Hardcode the relative location of the CMakeCache file Fortran: Wrap path convert in a call with a more-suitable name Fortran: Inline conversion to relative path Makefiles: Introduce local RelativePath method Convert: Inline platform-specific methods cmOutputConverter: Add a flag for IsUnix cmLocalGenerator: Simplify ConvertToLinkReference cmLocalGenerator: Extract policy handling into a method cmLocalGenerator: Rename local variable to be more appropriate CMP0065: Put computed flags into LINK_FLAGS not LINK_LIBRARIES cmTarget: Add assert about link data cmTarget: Remove addition of zero when merging link libraries cmTarget: Remove useless link library state cmTarget: Inline MergeLinkLibraries into only caller cmMakefile: Remove useless link directory container cmMakefile: Remove superfluous overload cmMakefile: Invert handling of error condition cmMakefile: Return after error and remove else condition cmMakefile: DeMorgan-invert condition cmMakefile: Collapse two consecutive if()s into one cmMakefile: Remove ALIAS check cmMakefile: Invert if() condition to remove else cmMakefile: Use public API to find a target cmMakefile: Inline method into only caller cmMakefile: Use public API to find a target cmTarget: Remove target name from parameter list cmMakefile: Remove obsolete parameter cmake: Simplify find-package mode library addition cmMakefile: Inline method into caller Ninja: Separate two coupled calls Ninja: Replace array access with local variable cmMakefile: Inline method into only remaining caller cmMakefile: Implement LinkLibraries as an internal property cmMakefile: Simplify programmer error to an assert Ninja: Extract identical code from condition Makefiles: Separate two coupled calls Makefiles: Replace array access with local variable Makefiles: Extract identical code from condition cmMakefile: Remove pointless condition Makefiles: Make helper class independent of cmLocalGenerator Makefiles: Inline only use of method Makefiles: Remove forbidden flag logic Makefiles: Remove query for CMAKE_OBJECT_NAME cmLocalGenerator: Extract definition retrieval out of loop Test: Remove condition for CMake version no longer supported cmMakefile: Return a string from GetDefineFlags cmLocalGenerator: Inline conversion into link computation Ninja: Constify cmLinkLineComputer: Extract from cmLocalGenerator Makefiles: Port CreateLinkLibs to cmLinkLineComputer cmLocalGenerator: Pass link library info to OutputLinkLibraries cmLocalGenerator: Separate rpath content from library stream cmLocalGenerator: Separate stdlib content from library stream cmLocalGenerator: Move flag determination up in the function cmLocalGenerator: Move stringstream to where it is used cmLocalGenerator: Use a std::string instead of char* cmLocalGenerator: Move variable to where it is used cmLinkLineComputer: Move ComputeLinkLibs from cmLocalGenerator cmLinkLineComputer: Move LinkPath computation from cmLocalGenerator cmLinkLineComputer: Move RPath computation from cmLocalGenerator cmLocalGenerator: Inline last use of local variable cmLinkLineComputer: Move FrameworkPath computation from cmLocalGenerator cmLinkLineComputer: Extract link libraries computation from cmLocalGenerator cmTarget: Use static storage for computed properties cmTarget: Remove mutable marker from properties cmTarget: Move SOURCES property computation before the rest cmTarget: Move IMPORTED check to callers cmTarget: Split property computation into separate class cmTarget: Extract location computation methods cmTarget: Extract GetSources method cmTarget: Extract GetLocation method cmListFileBacktrace: Add a method to retrieve the Bottom of a snapshot cmTargetPropertyComputer: Implement GetProperty without cmMakefile cmTargetPropertyComputer: Extract into new files cmTargetPropertyComputer: Move whitelist check from cmTarget cmTargetPropertyComputer: Unify whitelist handling from cmTarget cm{,Generator}Target: Add global generator accessors cmTargetPropertyComputer: Template some methods on the Target cmGeneratorTarget: Implement cmTargetPropertyComputer interface cmLocalGenerator: Remove the launcher from RuleVariables cmLocalGenerator: Simplify loop with range algorithm cmLocalGenerator: Introduce a container of compiler names cmLocalGenerator: Use the language from the compiler container cmLocalGenerator: Move variable to where it can be used easily cmLocalGenerator: Move compiler option handling to be more direct cmLocalGenerator: Populate a container of mappings for replacements cmLocalGenerator: Extract compiler option replacement from loop cmLocalGenerator: Populate variable mapping for all replacements cmLocalGenerator: Merge loops which populate mapping cmLocalGenerator: Store variable replacements as state cmLocalGenerator: Use a converter in rule replacement API cmLocalGenerator: Use strings instead of a Target in rule replacement cmLocalGenerator: Move memset to cxx file cmRulePlaceholderExpander: Extract from cmLocalGenerator cmRulePlaceholderExpander: Port clients to direct-use cmTarget: Move sanity checks and computed property access to callers cmTarget: Group code for checking written properties together cmTarget: Implement GetProperty in terms of cmState::Snapshot cmCommandArgumentParserHelper: Remove unused header cmServerProtocol: Remove unused header cmState: Move nested struct into separate top-level namespace cmState: Move SnapshotDataType to separate namespace cmState: Move PolicyStackEntry to separate namespace cmState: Move PositionType to separate namespace cmState: Move SnapshotType enum to separate namespace cmState: Move TargetType enum to separate namespace cmState: Move CacheEntryType enum to separate namespace cmState: Move Directory class to separate namespace cmState: Port dependent code to new cmStateDirectory name cmState: Move Snapshot type to separate namespace cmState: Port dependent code to new cmStateSnapshot name cmState: Remove compatibility typedefs cmState: Move extracted declarations to a separate file cmState: Port dependents to new cmStateTypes header cmState: Split auxiliary classes into separate files cmTargetPropertyComputer: Add missing include cmListFileCache: Remove cmState header include Stephen Sorley (1): CheckFunctionExists: Document suggestion to use CheckSymbolExists instead. Sylvain Joubert (5): Remove CTestTestfile.cmake when BUILD_TESTING is OFF ccmake: Add missing spaces to match the previous text length ccmake: Correctly display edit mode and associated keys ctest_memcheck: Append sanitizers user options at the end to allow overriding CTest: Properly reset output to avoid duplication with --repeat-until-fail Taylor Braun-Jones (1): InstallRequiredSystemLibraries: Add concrt*.dll for VC >= 14.0 Thiago M. de C. Marques (1): Help: Update example Qt 5 find_package call to add missing component Thiago Perrotta (1): Help: Fix typo in CMAKE_DL_LIBS docs Tobias Hunger (2): server-mode: Fix per-source COMPILE_FLAGS genex evaluation server-mode: Do not crash when running into INTERFACE_LIBRARY Vladim?r Vondru? (2): FindDevIL: fail properly when library is not found. FindDevIL: Make the ILUT library optional Yves Frederix (2): VS: Teach `cmake --build` to reconfigure if needed before building FindBoost: unset cache variables if the lib dir changes Zack Galbreath (9): CTest: report time spent after matching output cmRulePlaceholderExpander: Fix CMAKE__COMPILER_ARG1 replacement Update tests that expect uncompressed output Do not query CDash for version ctest_submit: Allow RETRY_COUNT for CDASH_UPLOAD ctest_submit: improve handling of QUIET option ctest_submit: Update documentation for CDash upload retries AndroidTestUtilities: ignore exit status of ls AndroidTestUtilities: do not require ExternalData unconditionally Zsolt Parragi (2): Add generator expression support to per-source COMPILE_FLAGS VS: Fix WINDOWS_EXPORT_ALL_SYMBOLS for external objects caryoscelus (1): UseSWIG: Record generated java files as custom command outputs librhash upstream (2): librhash 2016-11-01 (d839a1a8) librhash 2016-11-06 (de79828d) ----------------------------------------------------------------------- hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 7 13:25:04 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 7 Feb 2017 13:25:04 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-31-gb44b3df Message-ID: <20170207182504.20566FA223@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via b44b3df4e1f9ee55734c2e02f37459e2bea5dc1d (commit) via 5ba2c9e5e08cb391c366065210a95a46ac74f310 (commit) from 7a6d61fe67383038e2874e0508d78778fabc7183 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b44b3df4e1f9ee55734c2e02f37459e2bea5dc1d commit b44b3df4e1f9ee55734c2e02f37459e2bea5dc1d Merge: 7a6d61f 5ba2c9e Author: Brad King AuthorDate: Tue Feb 7 13:25:02 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 7 13:25:02 2017 -0500 Merge topic 'vs-nasm' into next 5ba2c9e5 VS: Add support for ASM_NASM language diff --cc Modules/CMakeDetermineASMCompiler.cmake index 3f18a8c,66bf14b..7d5e2b2 --- a/Modules/CMakeDetermineASMCompiler.cmake +++ b/Modules/CMakeDetermineASMCompiler.cmake @@@ -92,9 -92,17 +92,17 @@@ if(NOT CMAKE_ASM${ASM_DIALECT}_COMPILER set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_FLAGS_ARMCC ) set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_ARMCC "(ARM Compiler)|(ARM Assembler)") + list(APPEND CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDORS NASM) + set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_FLAGS_NASM "-v") + set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_NASM "(NASM version)") + + list(APPEND CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDORS YASM) + set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_FLAGS_YASM "--version") + set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_YASM "(yasm)") + include(CMakeDetermineCompilerId) - CMAKE_DETERMINE_COMPILER_ID_VENDOR(ASM${ASM_DIALECT}) - + set(userflags) + CMAKE_DETERMINE_COMPILER_ID_VENDOR(ASM${ASM_DIALECT} "${userflags}") endif() if(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=5ba2c9e5e08cb391c366065210a95a46ac74f310 commit 5ba2c9e5e08cb391c366065210a95a46ac74f310 Author: Evgeny Fimochkin AuthorDate: Fri Jan 27 19:31:50 2017 +0700 Commit: Brad King CommitDate: Tue Feb 7 13:20:52 2017 -0500 VS: Add support for ASM_NASM language Fixes: #16469 diff --git a/Help/release/dev/vs-nasm.rst b/Help/release/dev/vs-nasm.rst new file mode 100644 index 0000000..bb082a4 --- /dev/null +++ b/Help/release/dev/vs-nasm.rst @@ -0,0 +1,5 @@ +vs-nasm +------- + +* :ref:`Visual Studio Generators` for VS 2010 and above learned to support + the ``ASM_NASM`` language when ``nasm`` is installed. diff --git a/Modules/CMakeDetermineASMCompiler.cmake b/Modules/CMakeDetermineASMCompiler.cmake index 4162726..66bf14b 100644 --- a/Modules/CMakeDetermineASMCompiler.cmake +++ b/Modules/CMakeDetermineASMCompiler.cmake @@ -92,6 +92,14 @@ if(NOT CMAKE_ASM${ASM_DIALECT}_COMPILER_ID) set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_FLAGS_ARMCC ) set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_ARMCC "(ARM Compiler)|(ARM Assembler)") + list(APPEND CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDORS NASM) + set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_FLAGS_NASM "-v") + set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_NASM "(NASM version)") + + list(APPEND CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDORS YASM) + set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_FLAGS_YASM "--version") + set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_YASM "(yasm)") + include(CMakeDetermineCompilerId) CMAKE_DETERMINE_COMPILER_ID_VENDOR(ASM${ASM_DIALECT}) diff --git a/Modules/CMakeDetermineASM_NASMCompiler.cmake b/Modules/CMakeDetermineASM_NASMCompiler.cmake index 4c8e422..dd75310 100644 --- a/Modules/CMakeDetermineASM_NASMCompiler.cmake +++ b/Modules/CMakeDetermineASM_NASMCompiler.cmake @@ -7,8 +7,21 @@ set(CMAKE_ASM_NASM_COMPILER_LIST nasm yasm) if(NOT CMAKE_ASM_NASM_COMPILER) - find_program(CMAKE_ASM_NASM_COMPILER nasm - "$ENV{ProgramFiles}/NASM") + set(_CMAKE_ENV_VARX86 "ProgramFiles(x86)") + set(_CMAKE_ASM_NASM_COMPILER_PATHS + "[HKEY_CURRENT_USER\\SOFTWARE\\nasm]" + "$ENV{ProgramFiles}/NASM" + "$ENV{${ENV_VARX86}}/NASM" + "$ENV{LOCALAPPDATA}/NASM" + ) + find_program(CMAKE_ASM_NASM_COMPILER + NAMES ${CMAKE_ASM_NASM_COMPILER_LIST} + PATHS ${_CMAKE_ASM_NASM_COMPILER_PATHS} + NO_DEFAULT_PATH + DOC "NASM compiler" + ) + unset(_CMAKE_ENV_VARX86) + unset(_CMAKE_ASM_NASM_COMPILER_PATHS) endif() # Load the generic DetermineASM compiler file with the DIALECT set properly: diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index e27615a..b64ae26 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -13,6 +13,7 @@ #include "cmVS10LibFlagTable.h" #include "cmVS10LinkFlagTable.h" #include "cmVS10MASMFlagTable.h" +#include "cmVS10NASMFlagTable.h" #include "cmVS10RCFlagTable.h" #include "cmVisualStudioSlnData.h" #include "cmVisualStudioSlnParser.h" @@ -113,6 +114,7 @@ cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator( this->DefaultLibFlagTable = cmVS10LibFlagTable; this->DefaultLinkFlagTable = cmVS10LinkFlagTable; this->DefaultMasmFlagTable = cmVS10MASMFlagTable; + this->DefaultNasmFlagTable = cmVS10NASMFlagTable; this->DefaultRcFlagTable = cmVS10RCFlagTable; this->Version = VS10; } @@ -354,6 +356,13 @@ void cmGlobalVisualStudio10Generator::Generate() void cmGlobalVisualStudio10Generator::EnableLanguage( std::vector const& lang, cmMakefile* mf, bool optional) { + for (std::vector::const_iterator it = lang.begin(); + it != lang.end(); ++it) { + if (*it == "ASM_NASM") { + this->NasmEnabled = true; + } + } + this->AddPlatformDefinitions(mf); cmGlobalVisualStudio8Generator::EnableLanguage(lang, mf, optional); } @@ -663,3 +672,8 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetMasmFlagTable() const return (table != CM_NULLPTR) ? table : this->DefaultMasmFlagTable; } + +cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetNasmFlagTable() const +{ + return this->DefaultNasmFlagTable; +} diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 5bfaf38..3fc62ec 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -96,6 +96,7 @@ public: cmIDEFlagTable const* GetLibFlagTable() const; cmIDEFlagTable const* GetLinkFlagTable() const; cmIDEFlagTable const* GetMasmFlagTable() const; + cmIDEFlagTable const* GetNasmFlagTable() const; protected: virtual void Generate(); @@ -125,6 +126,7 @@ protected: cmIDEFlagTable const* DefaultLibFlagTable; cmIDEFlagTable const* DefaultLinkFlagTable; cmIDEFlagTable const* DefaultMasmFlagTable; + cmIDEFlagTable const* DefaultNasmFlagTable; cmIDEFlagTable const* DefaultRcFlagTable; bool SystemIsWindowsCE; bool SystemIsWindowsPhone; diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 602666e..65a0bde 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -47,6 +47,7 @@ cmGlobalVisualStudio7Generator::cmGlobalVisualStudio7Generator( this->IntelProjectVersion = 0; this->DevEnvCommandInitialized = false; this->MasmEnabled = false; + this->NasmEnabled = false; if (platformName.empty()) { this->DefaultPlatformName = "Win32"; diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h index 62194c3..1f96cc6 100644 --- a/Source/cmGlobalVisualStudio7Generator.h +++ b/Source/cmGlobalVisualStudio7Generator.h @@ -95,6 +95,7 @@ public: /** Is the Microsoft Assembler enabled? */ bool IsMasmEnabled() const { return this->MasmEnabled; } + bool IsNasmEnabled() const { return this->NasmEnabled; } // Encoding for Visual Studio files virtual std::string Encoding(); @@ -163,6 +164,7 @@ protected: std::string GeneratorPlatform; std::string DefaultPlatformName; bool MasmEnabled; + bool NasmEnabled; private: char* IntelProjectVersion; diff --git a/Source/cmVS10NASMFlagTable.h b/Source/cmVS10NASMFlagTable.h new file mode 100644 index 0000000..b91af92 --- /dev/null +++ b/Source/cmVS10NASMFlagTable.h @@ -0,0 +1,50 @@ +static cmVS7FlagTable cmVS10NASMFlagTable[] = { + + // Enum Properties + { "Outputswitch", "fwin32", "", "0", 0 }, + { "Outputswitch", "fwin", "", "0", 0 }, + { "Outputswitch", "fwin64", "", "1", 0 }, + { "Outputswitch", "felf", "", "2", 0 }, + { "Outputswitch", "felf32", "", "2", 0 }, + { "Outputswitch", "felf64", "", "3", 0 }, + + { "ErrorReportingFormat", "Xgnu", "", "-Xgnu GNU format: Default format", + 0 }, + { "ErrorReportingFormat", "Xvc", "", + "-Xvc Style used by Microsoft Visual C++", 0 }, + + // Bool Properties + { "TreatWarningsAsErrors", "Werror", "", "true", 0 }, + { "GenerateDebugInformation", "g", "", "true", 0 }, + { "floatunderflow", "w+float-underflow", "", "true", 0 }, + { "macrodefaults", "w-macro-defaults", "", "true", 0 }, + { "user", "w-user", "%warning directives (default on)", "true", 0 }, + { "floatoverflow", "w-float-overflow", "", "true", 0 }, + { "floatdenorm", "w+float-denorm", "", "true", 0 }, + { "numberoverflow", "w-number-overflow", "", "true", 0 }, + { "macroselfref", "w+macro-selfref", "", "true", 0 }, + { "floattoolong", "w-float-toolong", "", "true", 0 }, + { "orphanlabels", "w-orphan-labels", "", "true", 0 }, + { "tasmmode", "t", "", "true", 0 }, + + // Bool Properties With Argument + + // String List Properties + { "PreprocessorDefinitions", "D", "Preprocessor Definitions", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + { "UndefinePreprocessorDefinitions", "U", + "Undefine Preprocessor Definitions", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + { "IncludePaths", "I", "Include Paths", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + { "AssembledCodeListingFile", "l", + "Generates an assembled code listing file.", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + + // String Properties + // Skip [Inputs] - no command line Switch. + // Skip [CommandLineTemplate] - no command line Switch. + // Skip [ExecutionDescription] - no command line Switch. + // Skip [AdditionalOptions] - no command line Switch. + { 0, 0, 0, 0, 0 } +}; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 2e6c19b..a7edc95 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -10,6 +10,7 @@ #include "cmLocalVisualStudio7Generator.h" #include "cmMakefile.h" #include "cmSourceFile.h" +#include "cmSystemTools.h" #include "cmVisualStudioGeneratorOptions.h" #include "windows.h" @@ -207,6 +208,9 @@ void cmVisualStudio10TargetGenerator::Generate() if (!this->ComputeMasmOptions()) { return; } + if (!this->ComputeNasmOptions()) { + return; + } if (!this->ComputeLinkOptions()) { return; } @@ -454,6 +458,21 @@ void cmVisualStudio10TargetGenerator::Generate() "BuildCustomizations\\masm.props\" />\n", 2); } + if (this->GlobalGenerator->IsNasmEnabled()) { + // Always search in the standard modules location. + std::string propsTemplate = + GetCMakeFilePath("Templates/MSBuild/nasm.props.in"); + + std::string propsLocal; + propsLocal += this->DefaultArtifactDir; + propsLocal += "\\nasm.props"; + this->ConvertToWindowsSlash(propsLocal); + this->Makefile->ConfigureFile(propsTemplate.c_str(), propsLocal.c_str(), + false, true, true); + std::string import = std::string("\n"; + this->WriteString(import.c_str(), 2); + } this->WriteString("\n", 1); this->WriteString("\n", 1); { @@ -509,6 +528,13 @@ void cmVisualStudio10TargetGenerator::Generate() "BuildCustomizations\\masm.targets\" />\n", 2); } + if (this->GlobalGenerator->IsNasmEnabled()) { + std::string nasmTargets = + GetCMakeFilePath("Templates/MSBuild/nasm.targets"); + std::string import = "\n"; + this->WriteString(import.c_str(), 2); + } this->WriteString("\n", 1); if (csproj == this->ProjectType) { for (std::vector::const_iterator i = @@ -1719,6 +1745,8 @@ void cmVisualStudio10TargetGenerator::WriteAllSources() tool = "ClCompile"; } else if (lang == "ASM_MASM" && this->GlobalGenerator->IsMasmEnabled()) { tool = "MASM"; + } else if (lang == "ASM_NASM" && this->GlobalGenerator->IsNasmEnabled()) { + tool = "NASM"; } else if (lang == "RC") { tool = "ResourceCompile"; } else if (lang == "CSharp") { @@ -2431,6 +2459,71 @@ void cmVisualStudio10TargetGenerator::WriteMasmOptions( this->WriteString("\n", 2); } +bool cmVisualStudio10TargetGenerator::ComputeNasmOptions() +{ + if (!this->GlobalGenerator->IsNasmEnabled()) { + return true; + } + for (std::vector::const_iterator i = + this->Configurations.begin(); + i != this->Configurations.end(); ++i) { + if (!this->ComputeNasmOptions(*i)) { + return false; + } + } + return true; +} + +bool cmVisualStudio10TargetGenerator::ComputeNasmOptions( + std::string const& configName) +{ + cmGlobalVisualStudio10Generator* gg = + static_cast(this->GlobalGenerator); + CM_AUTO_PTR pOptions(new Options( + this->LocalGenerator, Options::NasmCompiler, gg->GetNasmFlagTable())); + Options& nasmOptions = *pOptions; + + std::string CONFIG = cmSystemTools::UpperCase(configName); + std::string configFlagsVar = std::string("CMAKE_ASM_NASM_FLAGS_") + CONFIG; + std::string flags = + std::string(this->Makefile->GetSafeDefinition("CMAKE_ASM_NASM_FLAGS")) + + std::string(" -f") + std::string(this->Makefile->GetSafeDefinition( + "CMAKE_ASM_NASM_OBJECT_FORMAT")) + + std::string(" ") + + std::string(this->Makefile->GetSafeDefinition(configFlagsVar)); + nasmOptions.Parse(flags.c_str()); + this->NasmOptions[configName] = pOptions.release(); + return true; +} + +void cmVisualStudio10TargetGenerator::WriteNasmOptions( + std::string const& configName, std::vector includes) +{ + if (!this->GlobalGenerator->IsNasmEnabled()) { + return; + } + this->WriteString("\n", 2); + + Options& nasmOptions = *(this->NasmOptions[configName]); + for (size_t i = 0; i < includes.size(); i++) { + includes[i] += "\\"; + } + + nasmOptions.AppendFlag("IncludePaths", includes); + nasmOptions.AppendFlag("IncludePaths", "%(IncludePaths)"); + nasmOptions.OutputFlagMap(*this->BuildFileStream, " "); + nasmOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", ""); + nasmOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ", + "\n", "ASM_NASM"); + + // Preprocessor definitions and includes are shared with clOptions. + Options& clOptions = *(this->ClOptions[configName]); + clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ", + "\n", "ASM_NASM"); + + this->WriteString("\n", 2); +} + void cmVisualStudio10TargetGenerator::WriteLibOptions( std::string const& config) { @@ -3062,6 +3155,7 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups() // output rc compile flags this->WriteRCOptions(*i, includes); this->WriteMasmOptions(*i, includes); + this->WriteNasmOptions(*i, includes); } // output midl flags this->WriteMidlOptions(*i, includes); @@ -3988,3 +4082,14 @@ bool cmVisualStudio10TargetGenerator::ForceOld(const std::string& source) const CloseHandle(h); return true; } + +std::string cmVisualStudio10TargetGenerator::GetCMakeFilePath( + const char* relativeFilePath) const +{ + // Always search in the standard modules location. + std::string path = cmSystemTools::GetCMakeRoot() + "/"; + path += relativeFilePath; + this->ConvertToWindowsSlash(path); + + return path; +} diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index 45464c0..0ebb4e4 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -51,7 +51,7 @@ private: }; std::string ConvertPath(std::string const& path, bool forceRelative); - void ConvertToWindowsSlash(std::string& s); + static void ConvertToWindowsSlash(std::string& s); void WriteString(const char* line, int indentLevel); void WriteProjectConfigurations(); void WriteProjectConfigurationValues(); @@ -102,6 +102,11 @@ private: bool ComputeMasmOptions(std::string const& config); void WriteMasmOptions(std::string const& config, std::vector const& includes); + bool ComputeNasmOptions(); + bool ComputeNasmOptions(std::string const& config); + void WriteNasmOptions(std::string const& config, + std::vector includes); + bool ComputeLinkOptions(); bool ComputeLinkOptions(std::string const& config); bool ComputeLibOptions(); @@ -146,6 +151,7 @@ private: OptionsMap ClOptions; OptionsMap RcOptions; OptionsMap MasmOptions; + OptionsMap NasmOptions; OptionsMap LinkOptions; std::string PathToProjectFile; std::string ProjectFileExtension; @@ -177,6 +183,7 @@ private: typedef std::map ToolSourceMap; ToolSourceMap Tools; + std::string GetCMakeFilePath(const char* name) const; }; #endif diff --git a/Source/cmVisualStudio10ToolsetOptions.cxx b/Source/cmVisualStudio10ToolsetOptions.cxx index afca216..0f15ec4 100644 --- a/Source/cmVisualStudio10ToolsetOptions.cxx +++ b/Source/cmVisualStudio10ToolsetOptions.cxx @@ -11,6 +11,7 @@ #include "cmVS10LibFlagTable.h" #include "cmVS10LinkFlagTable.h" #include "cmVS10MASMFlagTable.h" +#include "cmVS10NASMFlagTable.h" #include "cmVS10RCFlagTable.h" #include "cmVS11CLFlagTable.h" #include "cmVS11CSharpFlagTable.h" diff --git a/Source/cmVisualStudioGeneratorOptions.h b/Source/cmVisualStudioGeneratorOptions.h index ab6b8cc..3a53ff5 100644 --- a/Source/cmVisualStudioGeneratorOptions.h +++ b/Source/cmVisualStudioGeneratorOptions.h @@ -27,6 +27,7 @@ public: Compiler, ResourceCompiler, MasmCompiler, + NasmCompiler, Linker, FortranCompiler, CSharpCompiler diff --git a/Templates/MSBuild/nasm.props.in b/Templates/MSBuild/nasm.props.in new file mode 100644 index 0000000..3443108 --- /dev/null +++ b/Templates/MSBuild/nasm.props.in @@ -0,0 +1,17 @@ + + + + Midl + CustomBuild + + + + $(IntDir)%(FileName).obj + 0 + @CMAKE_ASM_NASM_COMPILER@ + 0 + "%(CompilerNasm)" [AllOptions] [AdditionalOptions] "%(FullPath)" + Assembling %(Filename)%(Extension) + + + diff --git a/Templates/MSBuild/nasm.targets b/Templates/MSBuild/nasm.targets new file mode 100644 index 0000000..eeeb613 --- /dev/null +++ b/Templates/MSBuild/nasm.targets @@ -0,0 +1,41 @@ + + + + + + _NASM + + + + + $(ComputeLinkInputsTargets); + ComputeNASMOutput; + + + $(ComputeLibInputsTargets); + ComputeNASMOutput; + + + + $(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml + + + + + + + + @(NASM, '|') + + + + + + + + + + + + + diff --git a/Templates/MSBuild/nasm.xml b/Templates/MSBuild/nasm.xml new file mode 100644 index 0000000..92f8548 --- /dev/null +++ b/Templates/MSBuild/nasm.xml @@ -0,0 +1,110 @@ + + + + + + + + + + General + + + + + Preprocessing Options + + + + + Assembler Options + + + + + Advanced + + + + + Command Line + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Execute Before + + + Specifies the targets for the build customization to run before. + + + + + + + + + + + Execute After + + + Specifies the targets for the build customization to run after. + + + + + + + + + + + + + Additional Options + + + Additional Options + + + + + + + diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 4945b31..910ff39 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -2043,7 +2043,8 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release set(reg_wp81 "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\WindowsPhone\\v8.1;InstallationFolder]") select_wince_sdk(reg_wince wince_sdk) set(reg_tegra "[HKEY_LOCAL_MACHINE\\SOFTWARE\\NVIDIA Corporation\\Nsight Tegra;sdkRoot]") - foreach(reg vs10 vs11 vs12 vs14 ws80 ws81 ws10_0 wp80 wp81 wince tegra) + set(reg_nasm "[HKEY_CURRENT_USER\\SOFTWARE\\nasm]") + foreach(reg vs10 vs11 vs12 vs14 ws80 ws81 ws10_0 wp80 wp81 wince tegra nasm) get_filename_component(r "${reg_${reg}}" ABSOLUTE) if(IS_DIRECTORY "${r}") set(${reg} 1) @@ -2134,6 +2135,10 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release endif() endif() + if(CMAKE_GENERATOR MATCHES "Visual Studio ([^789]|[789][0-9])" AND nasm) + ADD_TEST_MACRO(VSNASM VSNASM) + endif() + if (CMake_TEST_GreenHillsMULTI) macro(add_test_GhsMulti name primaryTarget bspName) add_test(NAME GhsMulti.${name} COMMAND ${CMAKE_CTEST_COMMAND} diff --git a/Tests/VSNASM/CMakeLists.txt b/Tests/VSNASM/CMakeLists.txt new file mode 100644 index 0000000..c2e29df --- /dev/null +++ b/Tests/VSNASM/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 2.8.12) +project(VSNASM C ASM_NASM) +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + add_definitions(-DTESTx64) + string(APPEND CMAKE_ASM_NASM_FLAGS " -DTEST2x64") +else() + add_definitions(-DTESTi386) +endif() +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) +add_executable(VSNASM main.c foo.asm) diff --git a/Tests/VSNASM/foo.asm b/Tests/VSNASM/foo.asm new file mode 100644 index 0000000..aba0673 --- /dev/null +++ b/Tests/VSNASM/foo.asm @@ -0,0 +1,7 @@ +section .text +%ifdef TEST2x64 +global foo +%else +global _foo +%endif +%include "foo-proc.asm" diff --git a/Tests/VSNASM/include/foo-proc.asm b/Tests/VSNASM/include/foo-proc.asm new file mode 100644 index 0000000..450a791 --- /dev/null +++ b/Tests/VSNASM/include/foo-proc.asm @@ -0,0 +1,7 @@ +%ifdef TESTx64 +foo: +%else +_foo: +%endif + mov eax, 0 + ret diff --git a/Tests/VSNASM/main.c b/Tests/VSNASM/main.c new file mode 100644 index 0000000..18ddb78 --- /dev/null +++ b/Tests/VSNASM/main.c @@ -0,0 +1,5 @@ +extern int foo(void); +int main(void) +{ + return foo(); +} ----------------------------------------------------------------------- Summary of changes: Help/release/dev/vs-nasm.rst | 5 ++ Modules/CMakeDetermineASMCompiler.cmake | 8 ++ Modules/CMakeDetermineASM_NASMCompiler.cmake | 17 +++- Source/cmGlobalVisualStudio10Generator.cxx | 14 ++++ Source/cmGlobalVisualStudio10Generator.h | 2 + Source/cmGlobalVisualStudio7Generator.cxx | 1 + Source/cmGlobalVisualStudio7Generator.h | 2 + Source/cmVS10NASMFlagTable.h | 50 ++++++++++++ Source/cmVisualStudio10TargetGenerator.cxx | 105 ++++++++++++++++++++++++ Source/cmVisualStudio10TargetGenerator.h | 9 ++- Source/cmVisualStudio10ToolsetOptions.cxx | 1 + Source/cmVisualStudioGeneratorOptions.h | 1 + Templates/MSBuild/nasm.props.in | 17 ++++ Templates/MSBuild/nasm.targets | 41 ++++++++++ Templates/MSBuild/nasm.xml | 110 ++++++++++++++++++++++++++ Tests/CMakeLists.txt | 7 +- Tests/{VSMASM => VSNASM}/CMakeLists.txt | 6 +- Tests/VSNASM/foo.asm | 7 ++ Tests/VSNASM/include/foo-proc.asm | 7 ++ Tests/{VSMASM => VSNASM}/main.c | 0 20 files changed, 403 insertions(+), 7 deletions(-) create mode 100644 Help/release/dev/vs-nasm.rst create mode 100644 Source/cmVS10NASMFlagTable.h create mode 100644 Templates/MSBuild/nasm.props.in create mode 100644 Templates/MSBuild/nasm.targets create mode 100644 Templates/MSBuild/nasm.xml copy Tests/{VSMASM => VSNASM}/CMakeLists.txt (63%) create mode 100644 Tests/VSNASM/foo.asm create mode 100644 Tests/VSNASM/include/foo-proc.asm copy Tests/{VSMASM => VSNASM}/main.c (100%) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 7 14:40:39 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 7 Feb 2017 14:40:39 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-33-g6a98f43 Message-ID: <20170207194039.D9B09C0F66@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 6a98f43c2894bbf324ae31311e5e0ef021a2c3b3 (commit) via b99d0e064557f6d59da35da34a7d5ae39cd44644 (commit) from b44b3df4e1f9ee55734c2e02f37459e2bea5dc1d (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6a98f43c2894bbf324ae31311e5e0ef021a2c3b3 commit 6a98f43c2894bbf324ae31311e5e0ef021a2c3b3 Merge: b44b3df b99d0e0 Author: Brad King AuthorDate: Tue Feb 7 14:40:38 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 7 14:40:38 2017 -0500 Merge topic 'lang-flag-order' into next b99d0e06 Move language standard options to the beginning of compiler flags https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b99d0e064557f6d59da35da34a7d5ae39cd44644 commit b99d0e064557f6d59da35da34a7d5ae39cd44644 Author: Brad King AuthorDate: Mon Feb 6 13:10:54 2017 -0500 Commit: Brad King CommitDate: Mon Feb 6 13:10:54 2017 -0500 Move language standard options to the beginning of compiler flags Through `CXX_STANDARD` and `COMPILE_FEATURES` target properties CMake determines what `-std=` flag to pass to the compiler. Move this flag to the beginning of the command line so that flags provided by users can override it (e.g. to use a standard flag newer than CMake knows). Fixes: #16608 diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx index ba623d5..5ed5817 100644 --- a/Source/cmGhsMultiTargetGenerator.cxx +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -231,6 +231,9 @@ void cmGhsMultiTargetGenerator::SetCompilerFlags(std::string const& config, std::string flags; const char* lang = language.c_str(); + this->LocalGenerator->AddLanguageStandardOptions( + flags, this->GeneratorTarget, lang, config); + if (notKernel) { this->LocalGenerator->AddLanguageFlags(flags, lang, config); } else { diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 8627cf2..de716e6 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -1643,6 +1643,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, li != languages.end(); ++li) { std::string const& lang = *li; std::string& flags = cflags[lang]; + this->CurrentLocalGenerator->AddLanguageStandardOptions(flags, gtgt, lang, + configName); // Add language-specific flags. this->CurrentLocalGenerator->AddLanguageFlags(flags, lang, configName); diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 44c390c..6e4eeeb 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -746,6 +746,13 @@ void cmLocalGenerator::AddCompileOptions(std::string& flags, this->AppendFlagEscape(flags, *i); } } +} + +void cmLocalGenerator::AddLanguageStandardOptions(std::string& flags, + cmGeneratorTarget* target, + const std::string& lang, + const std::string& config) +{ std::vector features; target->GetCompileFeatures(features, config); for (std::vector::const_iterator it = features.begin(); @@ -1053,6 +1060,8 @@ void cmLocalGenerator::GetTargetCompileFlags(cmGeneratorTarget* target, { cmMakefile* mf = this->GetMakefile(); + this->AddLanguageStandardOptions(flags, target, lang, config); + // Add language-specific flags. this->AddLanguageFlags(flags, lang, config); diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 901ca35..689ec70 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -98,6 +98,10 @@ public: const std::string& lang, const std::string& config); + void AddLanguageStandardOptions(std::string& flags, + cmGeneratorTarget* target, + const std::string& lang, + const std::string& config); void AddLanguageFlags(std::string& flags, const std::string& lang, const std::string& config); void AddCMP0018Flags(std::string& flags, cmGeneratorTarget const* target, diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 38dda04..04ec110 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -648,6 +648,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration( target->GetName().c_str()); return; } + this->AddLanguageStandardOptions(flags, target, linkLanguage, configName); if (linkLanguage == "C" || linkLanguage == "CXX" || linkLanguage == "Fortran") { std::string baseFlagVar = "CMAKE_"; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 2e6c19b..1317c57 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -2158,6 +2158,8 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( this->Name.c_str()); return false; } + this->LocalGenerator->AddLanguageStandardOptions( + flags, this->GeneratorTarget, linkLanguage, configName); if (linkLanguage == "C" || linkLanguage == "CXX" || linkLanguage == "Fortran" || linkLanguage == "CSharp") { std::string baseFlagVar = "CMAKE_"; ----------------------------------------------------------------------- Summary of changes: Source/cmGhsMultiTargetGenerator.cxx | 3 +++ Source/cmGlobalXCodeGenerator.cxx | 2 ++ Source/cmLocalGenerator.cxx | 9 +++++++++ Source/cmLocalGenerator.h | 4 ++++ Source/cmLocalVisualStudio7Generator.cxx | 1 + Source/cmVisualStudio10TargetGenerator.cxx | 2 ++ 6 files changed, 21 insertions(+) hooks/post-receive -- CMake From kwrobot at kitware.com Wed Feb 8 00:01:09 2017 From: kwrobot at kitware.com (Kitware Robot) Date: Wed, 8 Feb 2017 00:01:09 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-19-g7e42a43 Message-ID: <20170208050110.008C9FA177@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 7e42a43c1413e46e43d657a025dae726735dfcda (commit) from 9bd017d20ec4a2f9f4ceb2a39aa764b584026026 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7e42a43c1413e46e43d657a025dae726735dfcda commit 7e42a43c1413e46e43d657a025dae726735dfcda Author: Kitware Robot AuthorDate: Wed Feb 8 00:01:07 2017 -0500 Commit: Kitware Robot CommitDate: Wed Feb 8 00:01:07 2017 -0500 CMake Nightly Date Stamp diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 5b779bc..7d63f1a 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 8) -set(CMake_VERSION_PATCH 20170207) +set(CMake_VERSION_PATCH 20170208) #set(CMake_VERSION_RC 1) ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 8 08:25:30 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 8 Feb 2017 08:25:30 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-35-gca0b192 Message-ID: <20170208132531.8D6DDFA2EF@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via ca0b192713a2a4694394fa7b2dfbfaa96cb6f6b1 (commit) via 82e5ab9e14b81e0d21ef61f503a2b4c8638776e8 (commit) from 6a98f43c2894bbf324ae31311e5e0ef021a2c3b3 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ca0b192713a2a4694394fa7b2dfbfaa96cb6f6b1 commit ca0b192713a2a4694394fa7b2dfbfaa96cb6f6b1 Merge: 6a98f43 82e5ab9 Author: Brad King AuthorDate: Wed Feb 8 08:25:27 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 8 08:25:27 2017 -0500 Merge topic 'doc-cmake.org-version-switch' into next 82e5ab9e Utilities/Sphinx: Add option for cmake.org version switch to html https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=82e5ab9e14b81e0d21ef61f503a2b4c8638776e8 commit 82e5ab9e14b81e0d21ef61f503a2b4c8638776e8 Author: Brad King AuthorDate: Wed Feb 8 08:13:43 2017 -0500 Commit: Brad King CommitDate: Wed Feb 8 08:19:10 2017 -0500 Utilities/Sphinx: Add option for cmake.org version switch to html Leave the option undocumented since it is not for general use. We can simply pass it through `SPHINX_FLAGS` when building for publication on `cmake.org`. diff --git a/Utilities/Sphinx/templates/layout.html b/Utilities/Sphinx/templates/layout.html index 177e044..be2660c 100644 --- a/Utilities/Sphinx/templates/layout.html +++ b/Utilities/Sphinx/templates/layout.html @@ -8,10 +8,22 @@ CMake{{ reldelim1 }}
  • + {%- if versionswitch is defined %} + {{ release }} + {% trans %}Documentation{% endtrans %}{{ reldelim1 }} + {%- else %} {{ shorttitle|e }}{{ reldelim1 }} + {%- endif %}
  • {% endblock %} +{% block extrahead %} + {% if versionswitch is defined %} + + {% endif %} +{{ super() }} +{% endblock %} + {# Put some context in the html title element. Workaround for #} {# https://bitbucket.org/birkenfeld/sphinx/issue/1492/qthelp-generate-html-title-element-should #} {% block htmltitle %} ----------------------------------------------------------------------- Summary of changes: Utilities/Sphinx/templates/layout.html | 12 ++++++++++++ 1 file changed, 12 insertions(+) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 8 08:46:53 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 8 Feb 2017 08:46:53 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-37-gfb71eaf Message-ID: <20170208134655.46A47F7866@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via fb71eaf6b4b53ced12e208ee5905c5909deddf36 (commit) via 86d2bb68b573a1d71bc6eb6c88287ff29baa3909 (commit) from ca0b192713a2a4694394fa7b2dfbfaa96cb6f6b1 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=fb71eaf6b4b53ced12e208ee5905c5909deddf36 commit fb71eaf6b4b53ced12e208ee5905c5909deddf36 Merge: ca0b192 86d2bb6 Author: Brad King AuthorDate: Wed Feb 8 08:46:50 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 8 08:46:50 2017 -0500 Merge topic 'lang-flag-order' into next 86d2bb68 Revert "Move language standard options to the beginning of compiler flags" https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=86d2bb68b573a1d71bc6eb6c88287ff29baa3909 commit 86d2bb68b573a1d71bc6eb6c88287ff29baa3909 Author: Brad King AuthorDate: Wed Feb 8 08:46:28 2017 -0500 Commit: Brad King CommitDate: Wed Feb 8 08:46:28 2017 -0500 Revert "Move language standard options to the beginning of compiler flags" This reverts commit b99d0e064557f6d59da35da34a7d5ae39cd44644. diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx index 5ed5817..ba623d5 100644 --- a/Source/cmGhsMultiTargetGenerator.cxx +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -231,9 +231,6 @@ void cmGhsMultiTargetGenerator::SetCompilerFlags(std::string const& config, std::string flags; const char* lang = language.c_str(); - this->LocalGenerator->AddLanguageStandardOptions( - flags, this->GeneratorTarget, lang, config); - if (notKernel) { this->LocalGenerator->AddLanguageFlags(flags, lang, config); } else { diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index de716e6..8627cf2 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -1643,8 +1643,6 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, li != languages.end(); ++li) { std::string const& lang = *li; std::string& flags = cflags[lang]; - this->CurrentLocalGenerator->AddLanguageStandardOptions(flags, gtgt, lang, - configName); // Add language-specific flags. this->CurrentLocalGenerator->AddLanguageFlags(flags, lang, configName); diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 6e4eeeb..44c390c 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -746,13 +746,6 @@ void cmLocalGenerator::AddCompileOptions(std::string& flags, this->AppendFlagEscape(flags, *i); } } -} - -void cmLocalGenerator::AddLanguageStandardOptions(std::string& flags, - cmGeneratorTarget* target, - const std::string& lang, - const std::string& config) -{ std::vector features; target->GetCompileFeatures(features, config); for (std::vector::const_iterator it = features.begin(); @@ -1060,8 +1053,6 @@ void cmLocalGenerator::GetTargetCompileFlags(cmGeneratorTarget* target, { cmMakefile* mf = this->GetMakefile(); - this->AddLanguageStandardOptions(flags, target, lang, config); - // Add language-specific flags. this->AddLanguageFlags(flags, lang, config); diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 689ec70..901ca35 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -98,10 +98,6 @@ public: const std::string& lang, const std::string& config); - void AddLanguageStandardOptions(std::string& flags, - cmGeneratorTarget* target, - const std::string& lang, - const std::string& config); void AddLanguageFlags(std::string& flags, const std::string& lang, const std::string& config); void AddCMP0018Flags(std::string& flags, cmGeneratorTarget const* target, diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 04ec110..38dda04 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -648,7 +648,6 @@ void cmLocalVisualStudio7Generator::WriteConfiguration( target->GetName().c_str()); return; } - this->AddLanguageStandardOptions(flags, target, linkLanguage, configName); if (linkLanguage == "C" || linkLanguage == "CXX" || linkLanguage == "Fortran") { std::string baseFlagVar = "CMAKE_"; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 1317c57..2e6c19b 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -2158,8 +2158,6 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( this->Name.c_str()); return false; } - this->LocalGenerator->AddLanguageStandardOptions( - flags, this->GeneratorTarget, linkLanguage, configName); if (linkLanguage == "C" || linkLanguage == "CXX" || linkLanguage == "Fortran" || linkLanguage == "CSharp") { std::string baseFlagVar = "CMAKE_"; ----------------------------------------------------------------------- Summary of changes: Source/cmGhsMultiTargetGenerator.cxx | 3 --- Source/cmGlobalXCodeGenerator.cxx | 2 -- Source/cmLocalGenerator.cxx | 9 --------- Source/cmLocalGenerator.h | 4 ---- Source/cmLocalVisualStudio7Generator.cxx | 1 - Source/cmVisualStudio10TargetGenerator.cxx | 2 -- 6 files changed, 21 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 8 09:17:55 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 8 Feb 2017 09:17:55 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-21-g787c5f3 Message-ID: <20170208141758.77719FA1F9@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 787c5f37dde5982dea71b34339b9f546907bb368 (commit) via 82e5ab9e14b81e0d21ef61f503a2b4c8638776e8 (commit) from 7e42a43c1413e46e43d657a025dae726735dfcda (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=787c5f37dde5982dea71b34339b9f546907bb368 commit 787c5f37dde5982dea71b34339b9f546907bb368 Merge: 7e42a43 82e5ab9 Author: Brad King AuthorDate: Wed Feb 8 09:17:43 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 8 09:17:43 2017 -0500 Merge topic 'doc-cmake.org-version-switch' 82e5ab9e Utilities/Sphinx: Add option for cmake.org version switch to html ----------------------------------------------------------------------- Summary of changes: Utilities/Sphinx/templates/layout.html | 12 ++++++++++++ 1 file changed, 12 insertions(+) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 8 09:18:22 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 8 Feb 2017 09:18:22 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-40-gdb47cc7 Message-ID: <20170208141822.AE5F9FA246@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via db47cc7584e076fa6ebfbf9cf71317c15fc4e691 (commit) via 787c5f37dde5982dea71b34339b9f546907bb368 (commit) via 7e42a43c1413e46e43d657a025dae726735dfcda (commit) from fb71eaf6b4b53ced12e208ee5905c5909deddf36 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=db47cc7584e076fa6ebfbf9cf71317c15fc4e691 commit db47cc7584e076fa6ebfbf9cf71317c15fc4e691 Merge: fb71eaf 787c5f3 Author: Brad King AuthorDate: Wed Feb 8 09:18:15 2017 -0500 Commit: Brad King CommitDate: Wed Feb 8 09:18:15 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 8 10:49:36 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 8 Feb 2017 10:49:36 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-47-g3373f1e Message-ID: <20170208154936.3FCECF9FD4@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 3373f1efa71ea5cc3cb98238b25c5dd08420748c (commit) via 4ed9498bbdc13344a7f81b2c213a175bb719121d (commit) via 37d47b4375fd8c15f90bd1b03f6a2c1a0ac58636 (commit) via 73ae67006c952b8804f2566e868bc3acf7539857 (commit) via 1df9d5f91944e0b5ba00815d55bb7dc545053b4c (commit) via 4cc2908fdaaf1ab8afe5c2ae5dbb3401859a9aab (commit) via f4a3290ae7ae096f8b92f7adfba7088e6918bc0b (commit) from db47cc7584e076fa6ebfbf9cf71317c15fc4e691 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3373f1efa71ea5cc3cb98238b25c5dd08420748c commit 3373f1efa71ea5cc3cb98238b25c5dd08420748c Merge: db47cc7 4ed9498 Author: Brad King AuthorDate: Wed Feb 8 10:49:29 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 8 10:49:29 2017 -0500 Merge topic 'update-curl' into next 4ed9498b Help: Add notes for topic 'update-curl' 37d47b43 Tests: Fix `file://` URLs given to curl 73ae6700 curl: Fix passing _WINSOCKAPI_ macro to compiler 1df9d5f9 Merge branch 'upstream-curl' into update-curl 4cc2908f curl 2016-12-22 (44b9b4d4) f4a3290a curl: Update script to get curl 7.52.1 https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4ed9498bbdc13344a7f81b2c213a175bb719121d commit 4ed9498bbdc13344a7f81b2c213a175bb719121d Author: Brad King AuthorDate: Tue Feb 7 14:36:49 2017 -0500 Commit: Brad King CommitDate: Tue Feb 7 14:37:42 2017 -0500 Help: Add notes for topic 'update-curl' diff --git a/Help/release/dev/update-curl.rst b/Help/release/dev/update-curl.rst new file mode 100644 index 0000000..852ad5a --- /dev/null +++ b/Help/release/dev/update-curl.rst @@ -0,0 +1,6 @@ +update-curl +----------- + +* The version of curl bundled with CMake no longer accepts URLs of the form + ``file://c:/...`` on Windows due to a change in upstream curl 7.52. Use + the form ``file:///c:/...`` instead to work on all versions. https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=37d47b4375fd8c15f90bd1b03f6a2c1a0ac58636 commit 37d47b4375fd8c15f90bd1b03f6a2c1a0ac58636 Author: Brad King AuthorDate: Tue Feb 7 14:25:49 2017 -0500 Commit: Brad King CommitDate: Tue Feb 7 14:28:48 2017 -0500 Tests: Fix `file://` URLs given to curl Since upstream curl commit curl-7_52_0~131 (URL-parser: for file://[host]/ URLs, the [host] must be localhost, 2016-11-11) we can no longer use URLs of the form `file://c:/...` on Windows. These worked only accidentally before. Use `file:///c:/...` instead. diff --git a/Tests/CMakeTests/FileDownloadBadHashTest.cmake.in b/Tests/CMakeTests/FileDownloadBadHashTest.cmake.in index 4a47c06..82280dd 100644 --- a/Tests/CMakeTests/FileDownloadBadHashTest.cmake.in +++ b/Tests/CMakeTests/FileDownloadBadHashTest.cmake.in @@ -1,4 +1,4 @@ -set(url "file://@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png") +set(url "file:///@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png") set(dir "@CMAKE_CURRENT_BINARY_DIR@/downloads") file(DOWNLOAD diff --git a/Tests/CMakeTests/FileDownloadTest.cmake.in b/Tests/CMakeTests/FileDownloadTest.cmake.in index 83ade2b..48b4afe 100644 --- a/Tests/CMakeTests/FileDownloadTest.cmake.in +++ b/Tests/CMakeTests/FileDownloadTest.cmake.in @@ -1,4 +1,4 @@ -set(url "file://@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png") +set(url "file:///@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png") set(dir "@CMAKE_CURRENT_BINARY_DIR@/downloads") message(STATUS "FileDownload:1") diff --git a/Tests/CMakeTests/FileUploadTest.cmake.in b/Tests/CMakeTests/FileUploadTest.cmake.in index 8577aef..452090f 100644 --- a/Tests/CMakeTests/FileUploadTest.cmake.in +++ b/Tests/CMakeTests/FileUploadTest.cmake.in @@ -10,7 +10,7 @@ endif() file(MAKE_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@/uploads") set(filename "@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png") -set(urlbase "file://@CMAKE_CURRENT_BINARY_DIR@/uploads") +set(urlbase "file:///@CMAKE_CURRENT_BINARY_DIR@/uploads") message(STATUS "FileUpload:1") file(UPLOAD diff --git a/Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake b/Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake index ca72692..02e67dc 100644 --- a/Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake +++ b/Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake @@ -1,5 +1,5 @@ file(DOWNLOAD - "file://${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-hash-mismatch.txt" + "file:///${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-hash-mismatch.txt" ${CMAKE_CURRENT_BINARY_DIR}/hash-mismatch.txt EXPECTED_HASH SHA1=0123456789abcdef0123456789abcdef01234567 STATUS status diff --git a/Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake b/Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake index 2e3fbe1..862d833 100644 --- a/Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake +++ b/Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake @@ -1,5 +1,5 @@ file(DOWNLOAD - "file://${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-unused-argument.txt" + "file:///${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-unused-argument.txt" "${CMAKE_CURRENT_BINARY_DIR}/unused-argument.txt" JUNK ) diff --git a/Tests/RunCMake/file/UPLOAD-unused-argument.cmake b/Tests/RunCMake/file/UPLOAD-unused-argument.cmake index 94ac9ac..408da0e 100644 --- a/Tests/RunCMake/file/UPLOAD-unused-argument.cmake +++ b/Tests/RunCMake/file/UPLOAD-unused-argument.cmake @@ -1,5 +1,5 @@ file(UPLOAD "${CMAKE_CURRENT_SOURCE_DIR}/UPLOAD-unused-argument.txt" - "file://${CMAKE_CURRENT_BINARY_DIR}/unused-argument.txt" + "file:///${CMAKE_CURRENT_BINARY_DIR}/unused-argument.txt" JUNK ) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=73ae67006c952b8804f2566e868bc3acf7539857 commit 73ae67006c952b8804f2566e868bc3acf7539857 Author: Brad King AuthorDate: Tue Feb 7 11:39:49 2017 -0500 Commit: Brad King CommitDate: Tue Feb 7 11:39:49 2017 -0500 curl: Fix passing _WINSOCKAPI_ macro to compiler Define `_WINSOCKAPI_` blank rather than to 1 in order to match the value used by Microsoft's winsock header files. Backported from upstream curl commit 192466e0 (cmake: Fix passing _WINSOCKAPI_ macro to compiler, 2017-01-09). Fixes: #16545 diff --git a/Utilities/cmcurl/CMakeLists.txt b/Utilities/cmcurl/CMakeLists.txt index 5cef59f..6a34e8d 100644 --- a/Utilities/cmcurl/CMakeLists.txt +++ b/Utilities/cmcurl/CMakeLists.txt @@ -316,7 +316,7 @@ include (CheckCSourceCompiles) # On windows preload settings if(WIN32) - set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WINSOCKAPI_") + set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WINSOCKAPI_=") include(${CMAKE_CURRENT_SOURCE_DIR}/CMake/Platforms/WindowsCache.cmake) endif(WIN32) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1df9d5f91944e0b5ba00815d55bb7dc545053b4c commit 1df9d5f91944e0b5ba00815d55bb7dc545053b4c Merge: f4a3290 4cc2908 Author: Brad King AuthorDate: Tue Feb 7 11:38:00 2017 -0500 Commit: Brad King CommitDate: Tue Feb 7 11:38:00 2017 -0500 Merge branch 'upstream-curl' into update-curl * upstream-curl: curl 2016-12-22 (44b9b4d4) diff --cc Utilities/cmcurl/CMakeLists.txt index 262554d,0000000..5cef59f mode 100644,000000..100644 --- a/Utilities/cmcurl/CMakeLists.txt +++ b/Utilities/cmcurl/CMakeLists.txt @@@ -1,1279 -1,0 +1,1283 @@@ +# Set curl options as needed for CMake build +set(BUILD_CURL_EXE OFF CACHE INTERNAL "No curl exe") +set(BUILD_DASHBOARD_REPORTS OFF CACHE INTERNAL "No curl dashboard reports") +set(BUILD_RELEASE_DEBUG_DIRS OFF CACHE INTERNAL "No curl release/debug dirs") +set(CMAKE_USE_GSSAPI OFF CACHE INTERNAL "Disable curl gssapi") +set(CMAKE_USE_LIBSSH2 OFF CACHE INTERNAL "Disable curl libssh2") +set(CMAKE_USE_OPENLDAP OFF CACHE INTERNAL "No curl OpenLDAP") +set(CURL_DISABLE_COOKIES OFF CACHE INTERNAL "Do not disable curl cookie support") +set(CURL_DISABLE_CRYPTO_AUTH OFF CACHE INTERNAL "Do not disable curl crypto auth") +set(CURL_DISABLE_DICT ON CACHE INTERNAL "Disable curl dict protocol?") +set(CURL_DISABLE_FILE OFF CACHE INTERNAL "Disable curl file protocol?") +set(CURL_DISABLE_FTP OFF CACHE INTERNAL "Disable curl ftp protocol?") +set(CURL_DISABLE_GOPHER ON CACHE INTERNAL "Disable curl gopher protocol?") +set(CURL_DISABLE_HTTP OFF CACHE INTERNAL "Disable curl http protocol?") +set(CURL_DISABLE_IMAP ON CACHE INTERNAL "Disable curl imap protocol?") +set(CURL_DISABLE_LDAP ON CACHE INTERNAL "Disable curl ldap protocol?") +set(CURL_DISABLE_LDAPS ON CACHE INTERNAL "Disable curl ldaps protocol?") +set(CURL_DISABLE_POP3 ON CACHE INTERNAL "Disable curl pop3 protocol?") +set(CURL_DISABLE_PROXY OFF CACHE INTERNAL "Do not disable curl proxy") +set(CURL_DISABLE_RTSP ON CACHE INTERNAL "Disable curl rtsp protocol?") +set(CURL_DISABLE_SMTP ON CACHE INTERNAL "Disable curl smtp protocol?") +set(CURL_DISABLE_TELNET ON CACHE INTERNAL "Disable curl telnet protocol?") +set(CURL_DISABLE_TFTP ON CACHE INTERNAL "Disable curl tftp protocol?") +set(CURL_DISABLE_VERBOSE_STRINGS OFF CACHE INTERNAL "Do not disable curl verbosity") +set(CURL_HIDDEN_SYMBOLS OFF CACHE INTERNAL "No curl hidden symbols") +set(CURL_STATICLIB ON CACHE INTERNAL "Static curl") +set(DISABLED_THREADSAFE OFF CACHE INTERNAL "Curl can use thread-safe functions") +set(ENABLE_ARES OFF CACHE INTERNAL "No curl c-ares support") +set(ENABLE_CURLDEBUG OFF CACHE INTERNAL "No curl TrackMemory features") +set(ENABLE_DEBUG OFF CACHE INTERNAL "No curl debug features") +set(ENABLE_IPV6 OFF CACHE INTERNAL "No curl IPv6 support") +set(ENABLE_MANUAL OFF CACHE INTERNAL "No curl built-in manual") +set(ENABLE_THREADED_RESOLVER OFF CACHE INTERNAL "No curl POSIX threaded DNS lookup") +set(ENABLE_UNIX_SOCKETS OFF CACHE INTERNAL "No curl Unix domain sockets support") +set(HTTP_ONLY OFF CACHE INTERNAL "Curl is not http-only") +set(USE_WIN32_LDAP OFF CACHE INTERNAL "No curl Windows LDAP") + +# Windows Vista and above have inet_pton, but this will link on +# older versions and then the executable will fail to launch at +# runtime on older versions because no DLL provides the symbol. +if(WIN32) + set(HAVE_INET_PTON 0 CACHE INTERNAL "Do not use inet_pton") +endif() + +# Starting with OSX 10.11 there is an unrelated libnetwork library which will +# be picked up during curl configuration. Linking against this library is +# unnecessary and breaks backward compatibility of the resulting binaries +# because libnetwork is unavailable on older OSX versions. +if(APPLE) + set(HAVE_LIBNETWORK 0 CACHE INTERNAL "Do not use libnetwork") +endif(APPLE) + +# Disable warnings to avoid changing 3rd party code. +if(CMAKE_C_COMPILER_ID MATCHES + "^(GNU|Clang|AppleClang|XL|VisualAge|SunPro|MIPSpro|HP|Intel)$") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w") +elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall") +endif() + +#*************************************************************************** +# _ _ ____ _ +# Project ___| | | | _ \| | +# / __| | | | |_) | | +# | (__| |_| | _ <| |___ +# \___|\___/|_| \_\_____| +# +# Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at https://curl.haxx.se/docs/copyright.html. +# +# You may opt to use, copy, modify, merge, publish, distribute and/or sell +# copies of the Software, and permit persons to whom the Software is +# furnished to do so, under the terms of the COPYING file. +# +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# KIND, either express or implied. +# +########################################################################### +# curl/libcurl CMake script +# by Tetetest and Sukender (Benoit Neil) + +# TODO: +# The output .so file lacks the soname number which we currently have within the lib/Makefile.am file +# Add full (4 or 5 libs) SSL support +# Add INSTALL target (EXTRA_DIST variables in Makefile.am may be moved to Makefile.inc so that CMake/CPack is aware of what's to include). +# Add CTests(?) +# Check on all possible platforms +# Test with as many configurations possible (With or without any option) +# Create scripts that help keeping the CMake build system up to date (to reduce maintenance). According to Tetetest: +# - lists of headers that 'configure' checks for; +# - curl-specific tests (the ones that are in m4/curl-*.m4 files); +# - (most obvious thing:) curl version numbers. +# Add documentation subproject +# +# To check: +# (From Daniel Stenberg) The cmake build selected to run gcc with -fPIC on my box while the plain configure script did not. +# (From Daniel Stenberg) The gcc command line use neither -g nor any -O options. As a developer, I also treasure our configure scripts's --enable-debug option that sets a long range of "picky" compiler options. +cmake_minimum_required(VERSION 2.8 FATAL_ERROR) +set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}") +include(Utilities) +include(Macros) +include(CMakeDependentOption) + +project( CURL C ) + +if(0) # This code not needed for building within CMake. +message(WARNING "the curl cmake build system is poorly maintained. Be aware") +endif() + +file (READ ${CURL_SOURCE_DIR}/include/curl/curlver.h CURL_VERSION_H_CONTENTS) +string (REGEX MATCH "#define LIBCURL_VERSION \"[^\"]*" + CURL_VERSION ${CURL_VERSION_H_CONTENTS}) +string (REGEX REPLACE "[^\"]+\"" "" CURL_VERSION ${CURL_VERSION}) +string (REGEX MATCH "#define LIBCURL_VERSION_NUM 0x[0-9a-fA-F]+" + CURL_VERSION_NUM ${CURL_VERSION_H_CONTENTS}) +string (REGEX REPLACE "[^0]+0x" "" CURL_VERSION_NUM ${CURL_VERSION_NUM}) + +include_regular_expression("^.*$") # Sukender: Is it necessary? + +# Setup package meta-data +# SET(PACKAGE "curl") +if(0) # This code not needed for building within CMake. +message(STATUS "curl version=[${CURL_VERSION}]") +endif() +# SET(PACKAGE_TARNAME "curl") +# SET(PACKAGE_NAME "curl") +# SET(PACKAGE_VERSION "-") +# SET(PACKAGE_STRING "curl-") +# SET(PACKAGE_BUGREPORT "a suitable curl mailing list => https://curl.haxx.se/mail/") +set(OPERATING_SYSTEM "${CMAKE_SYSTEM_NAME}") +set(OS "\"${CMAKE_SYSTEM_NAME}\"") + +include_directories(${PROJECT_BINARY_DIR}/include/curl) +include_directories( ${CURL_SOURCE_DIR}/include ) + +option(BUILD_CURL_EXE "Set to ON to build curl executable." ON) +option(CURL_STATICLIB "Set to ON to build libcurl with static linking." OFF) +option(ENABLE_ARES "Set to ON to enable c-ares support" OFF) +if(WIN32) + CMAKE_DEPENDENT_OPTION(ENABLE_THREADED_RESOLVER + "Set to ON to enable threaded DNS lookup" + ON "NOT ENABLE_ARES" + OFF) +else() + option(ENABLE_THREADED_RESOLVER "Set to ON to enable POSIX threaded DNS lookup" OFF) +endif() +option(ENABLE_DEBUG "Set to ON to enable curl debug features" OFF) +option(ENABLE_CURLDEBUG "Set to ON to build with TrackMemory feature enabled" OFF) + +if (ENABLE_DEBUG) + # DEBUGBUILD will be defined only for Debug builds + if(NOT CMAKE_VERSION VERSION_LESS 3.0) + set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS $<$:DEBUGBUILD>) + else() + set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_DEBUG DEBUGBUILD) + endif() + set(ENABLE_CURLDEBUG ON) +endif() + +if (ENABLE_CURLDEBUG) + set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS CURLDEBUG) +endif() + +# initialize CURL_LIBS +set(CURL_LIBS "") + +if(ENABLE_THREADED_RESOLVER AND ENABLE_ARES) + message(FATAL_ERROR "Options ENABLE_THREADED_RESOLVER and ENABLE_ARES are mutually exclusive") +endif() + +if(ENABLE_ARES) + set(USE_ARES 1) + find_package(CARES REQUIRED) + list(APPEND CURL_LIBS ${CARES_LIBRARY} ) + set(CURL_LIBS ${CURL_LIBS} ${CARES_LIBRARY}) +endif() + +if(MSVC) + option(BUILD_RELEASE_DEBUG_DIRS "Set OFF to build each configuration to a separate directory" OFF) + mark_as_advanced(BUILD_RELEASE_DEBUG_DIRS) +endif() + +if(0) # This code not needed for building within CMake. +include(CurlSymbolHiding) +endif() + +option(HTTP_ONLY "disables all protocols except HTTP (This overrides all CURL_DISABLE_* options)" OFF) +mark_as_advanced(HTTP_ONLY) +option(CURL_DISABLE_FTP "disables FTP" OFF) +mark_as_advanced(CURL_DISABLE_FTP) +option(CURL_DISABLE_LDAP "disables LDAP" OFF) +mark_as_advanced(CURL_DISABLE_LDAP) +option(CURL_DISABLE_TELNET "disables Telnet" OFF) +mark_as_advanced(CURL_DISABLE_TELNET) +option(CURL_DISABLE_DICT "disables DICT" OFF) +mark_as_advanced(CURL_DISABLE_DICT) +option(CURL_DISABLE_FILE "disables FILE" OFF) +mark_as_advanced(CURL_DISABLE_FILE) +option(CURL_DISABLE_TFTP "disables TFTP" OFF) +mark_as_advanced(CURL_DISABLE_TFTP) +option(CURL_DISABLE_HTTP "disables HTTP" OFF) +mark_as_advanced(CURL_DISABLE_HTTP) + +option(CURL_DISABLE_LDAPS "to disable LDAPS" OFF) +mark_as_advanced(CURL_DISABLE_LDAPS) + +option(CURL_DISABLE_RTSP "to disable RTSP" OFF) +mark_as_advanced(CURL_DISABLE_RTSP) +option(CURL_DISABLE_PROXY "to disable proxy" OFF) +mark_as_advanced(CURL_DISABLE_PROXY) +option(CURL_DISABLE_POP3 "to disable POP3" OFF) +mark_as_advanced(CURL_DISABLE_POP3) +option(CURL_DISABLE_IMAP "to disable IMAP" OFF) +mark_as_advanced(CURL_DISABLE_IMAP) +option(CURL_DISABLE_SMTP "to disable SMTP" OFF) +mark_as_advanced(CURL_DISABLE_SMTP) +option(CURL_DISABLE_GOPHER "to disable Gopher" OFF) +mark_as_advanced(CURL_DISABLE_GOPHER) + +if(HTTP_ONLY) + set(CURL_DISABLE_FTP ON) + set(CURL_DISABLE_LDAP ON) + set(CURL_DISABLE_LDAPS ON) + set(CURL_DISABLE_TELNET ON) + set(CURL_DISABLE_DICT ON) + set(CURL_DISABLE_FILE ON) + set(CURL_DISABLE_TFTP ON) + set(CURL_DISABLE_RTSP ON) + set(CURL_DISABLE_POP3 ON) + set(CURL_DISABLE_IMAP ON) + set(CURL_DISABLE_SMTP ON) + set(CURL_DISABLE_GOPHER ON) +endif() + +option(CURL_DISABLE_COOKIES "to disable cookies support" OFF) +mark_as_advanced(CURL_DISABLE_COOKIES) + +option(CURL_DISABLE_CRYPTO_AUTH "to disable cryptographic authentication" OFF) +mark_as_advanced(CURL_DISABLE_CRYPTO_AUTH) +option(CURL_DISABLE_VERBOSE_STRINGS "to disable verbose strings" OFF) +mark_as_advanced(CURL_DISABLE_VERBOSE_STRINGS) +option(DISABLED_THREADSAFE "Set to explicitly specify we don't want to use thread-safe functions" OFF) +mark_as_advanced(DISABLED_THREADSAFE) +option(ENABLE_IPV6 "Define if you want to enable IPv6 support" ON) +mark_as_advanced(ENABLE_IPV6) +if(ENABLE_IPV6 AND NOT WIN32) + include(CheckStructHasMember) + check_struct_has_member("struct sockaddr_in6" sin6_addr "netinet/in.h" + HAVE_SOCKADDR_IN6_SIN6_ADDR) + check_struct_has_member("struct sockaddr_in6" sin6_scope_id "netinet/in.h" + HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) + if(NOT HAVE_SOCKADDR_IN6_SIN6_ADDR) + message(WARNING "struct sockaddr_in6 not available, disabling IPv6 support") + # Force the feature off as this name is used as guard macro... + set(ENABLE_IPV6 OFF + CACHE BOOL "Define if you want to enable IPv6 support" FORCE) + endif() +endif() + +option(ENABLE_MANUAL "to provide the built-in manual" ON) +unset(USE_MANUAL CACHE) # TODO: cache NROFF/NROFF_MANOPT/USE_MANUAL vars? +if(ENABLE_MANUAL) + find_program(NROFF NAMES gnroff nroff) + if(NROFF) + # Need a way to write to stdin, this will do + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/nroff-input.txt" "test") + # Tests for a valid nroff option to generate a manpage + foreach(_MANOPT "-man" "-mandoc") + execute_process(COMMAND "${NROFF}" ${_MANOPT} + OUTPUT_VARIABLE NROFF_MANOPT_OUTPUT + INPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/nroff-input.txt" + ERROR_QUIET) + # Save the option if it was valid + if(NROFF_MANOPT_OUTPUT) + message("Found *nroff option: -- ${_MANOPT}") + set(NROFF_MANOPT ${_MANOPT}) + set(USE_MANUAL 1) + break() + endif() + endforeach() + # No need for the temporary file + file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/nroff-input.txt") + if(NOT USE_MANUAL) + message(WARNING "Found no *nroff option to get plaintext from man pages") + endif() + else() + message(WARNING "Found no *nroff program") + endif() +endif() + +# We need ansi c-flags, especially on HP +set(CMAKE_C_FLAGS "${CMAKE_ANSI_CFLAGS} ${CMAKE_C_FLAGS}") +set(CMAKE_REQUIRED_FLAGS ${CMAKE_ANSI_CFLAGS}) + +# Disable warnings on Borland to avoid changing 3rd party code. +if(BORLAND) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w-") +endif(BORLAND) + +# If we are on AIX, do the _ALL_SOURCE magic +if(${CMAKE_SYSTEM_NAME} MATCHES AIX) + set(_ALL_SOURCE 1) +endif(${CMAKE_SYSTEM_NAME} MATCHES AIX) + +# Include all the necessary files for macros +include (CheckFunctionExists) +include (CheckIncludeFile) +include (CheckIncludeFiles) +include (CheckLibraryExists) +include (CheckSymbolExists) +include (CheckTypeSize) +include (CheckCSourceCompiles) + +# On windows preload settings +if(WIN32) + set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WINSOCKAPI_") + include(${CMAKE_CURRENT_SOURCE_DIR}/CMake/Platforms/WindowsCache.cmake) +endif(WIN32) + +if(ENABLE_THREADED_RESOLVER) + if(WIN32) + set(USE_THREADS_WIN32 ON) + else() + check_include_file_concat("pthread.h" HAVE_PTHREAD_H) + if(HAVE_PTHREAD_H) + set(CMAKE_THREAD_PREFER_PTHREAD 1) + find_package(Threads) + if(CMAKE_USE_PTHREADS_INIT) + set(CURL_LIBS ${CURL_LIBS} ${CMAKE_THREAD_LIBS_INIT}) + set(USE_THREADS_POSIX 1) + endif() + endif() + endif() +endif() + +# Check for all needed libraries +if(0) # This code not needed for building within CMake. +check_library_exists_concat("dl" dlopen HAVE_LIBDL) +else() + # Use the cmake-defined dl libs as dl is should not be used + # on HPUX, but rather dld this avoids a warning + list(APPEND CURL_LIBS ${CMAKE_DL_LIBS}) +endif() +check_library_exists_concat("socket" connect HAVE_LIBSOCKET) +check_library_exists("c" gethostbyname "" NOT_NEED_LIBNSL) + +# Yellowtab Zeta needs different libraries than BeOS 5. +if(BEOS) + set(NOT_NEED_LIBNSL 1) + check_library_exists_concat("bind" gethostbyname HAVE_LIBBIND) + check_library_exists_concat("bnetapi" closesocket HAVE_LIBBNETAPI) +endif(BEOS) + +check_library_exists_concat("network" recv HAVE_LIBNETWORK) + +if(NOT NOT_NEED_LIBNSL) + check_library_exists_concat("nsl" gethostbyname HAVE_LIBNSL) +endif(NOT NOT_NEED_LIBNSL) + +check_function_exists(gethostname HAVE_GETHOSTNAME) + +if(WIN32) + check_library_exists_concat("ws2_32" getch HAVE_LIBWS2_32) + check_library_exists_concat("winmm" getch HAVE_LIBWINMM) +endif() + +set(USE_OPENSSL OFF) +set(HAVE_LIBCRYPTO OFF) +set(HAVE_LIBSSL OFF) + +if(CMAKE_USE_OPENSSL) + find_package(OpenSSL) + if(OPENSSL_FOUND) + list(APPEND CURL_LIBS ${OPENSSL_LIBRARIES}) + set(USE_OPENSSL ON) + set(HAVE_LIBCRYPTO ON) + set(HAVE_LIBSSL ON) + include_directories(${OPENSSL_INCLUDE_DIR}) + set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) + check_include_file("openssl/crypto.h" HAVE_OPENSSL_CRYPTO_H) + check_include_file("openssl/engine.h" HAVE_OPENSSL_ENGINE_H) + check_include_file("openssl/err.h" HAVE_OPENSSL_ERR_H) + check_include_file("openssl/pem.h" HAVE_OPENSSL_PEM_H) + check_include_file("openssl/pkcs12.h" HAVE_OPENSSL_PKCS12_H) + check_include_file("openssl/rsa.h" HAVE_OPENSSL_RSA_H) + check_include_file("openssl/ssl.h" HAVE_OPENSSL_SSL_H) + check_include_file("openssl/x509.h" HAVE_OPENSSL_X509_H) + check_include_file("openssl/rand.h" HAVE_OPENSSL_RAND_H) + + # Optionally build with a specific CA cert bundle. + if(CURL_CA_BUNDLE) + add_definitions(-DCURL_CA_BUNDLE="${CURL_CA_BUNDLE}") + endif() + # Optionally build with a specific CA cert dir. + if(CURL_CA_PATH) + add_definitions(-DCURL_CA_PATH="${CURL_CA_PATH}") + endif() + endif() +elseif(WIN32) + # Use Windows SSL/TLS native implementation. + set(CURL_WINDOWS_SSPI ON) +elseif(APPLE) + # Use OS X SSL/TLS native implementation if available on target version. + if(CMAKE_OSX_DEPLOYMENT_TARGET) + set(OSX_VERSION ${CMAKE_OSX_DEPLOYMENT_TARGET}) + else() + execute_process( + COMMAND sw_vers -productVersion + OUTPUT_VARIABLE OSX_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + endif() + if(NOT OSX_VERSION VERSION_LESS 10.6 AND + CMAKE_C_COMPILER_ID MATCHES "GNU|Clang|AppleClang") + add_definitions(-DUSE_DARWINSSL) + list(APPEND CURL_LIBS + "-framework CoreFoundation" + "-framework Security" + ) + endif() +endif() + +option(USE_NGHTTP2 "Use Nghttp2 library" OFF) +if(USE_NGHTTP2) + find_package(NGHTTP2 REQUIRED) + include_directories(${NGHTTP2_INCLUDE_DIRS}) + list(APPEND CURL_LIBS ${NGHTTP2_LIBRARIES}) +endif() + +if(NOT CURL_DISABLE_LDAP) + if(WIN32) + option(USE_WIN32_LDAP "Use Windows LDAP implementation" ON) + if(USE_WIN32_LDAP) + check_library_exists_concat("wldap32" cldap_open HAVE_WLDAP32) + if(NOT HAVE_WLDAP32) + set(USE_WIN32_LDAP OFF) + endif() + endif() + endif() + + option(CMAKE_USE_OPENLDAP "Use OpenLDAP code." OFF) + mark_as_advanced(CMAKE_USE_OPENLDAP) + set(CMAKE_LDAP_LIB "ldap" CACHE STRING "Name or full path to ldap library") + set(CMAKE_LBER_LIB "lber" CACHE STRING "Name or full path to lber library") + + if(CMAKE_USE_OPENLDAP AND USE_WIN32_LDAP) + message(FATAL_ERROR "Cannot use USE_WIN32_LDAP and CMAKE_USE_OPENLDAP at the same time") + endif() + + # Now that we know, we're not using windows LDAP... + if(USE_WIN32_LDAP) + check_include_file_concat("winldap.h" HAVE_WINLDAP_H) + check_include_file_concat("winber.h" HAVE_WINBER_H) + else() + # Check for LDAP + set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_LIBRARIES}) + check_library_exists_concat(${CMAKE_LDAP_LIB} ldap_init HAVE_LIBLDAP) + check_library_exists_concat(${CMAKE_LBER_LIB} ber_init HAVE_LIBLBER) + + set(CMAKE_REQUIRED_INCLUDES_BAK ${CMAKE_REQUIRED_INCLUDES}) + set(CMAKE_LDAP_INCLUDE_DIR "" CACHE STRING "Path to LDAP include directory") + if(CMAKE_LDAP_INCLUDE_DIR) + list(APPEND CMAKE_REQUIRED_INCLUDES ${CMAKE_LDAP_INCLUDE_DIR}) + endif() + check_include_file_concat("ldap.h" HAVE_LDAP_H) + check_include_file_concat("lber.h" HAVE_LBER_H) + + if(NOT HAVE_LDAP_H) + message(STATUS "LDAP_H not found CURL_DISABLE_LDAP set ON") + set(CURL_DISABLE_LDAP ON CACHE BOOL "" FORCE) + set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES_BAK}) #LDAP includes won't be used + elseif(NOT HAVE_LIBLDAP) + message(STATUS "LDAP library '${CMAKE_LDAP_LIB}' not found CURL_DISABLE_LDAP set ON") + set(CURL_DISABLE_LDAP ON CACHE BOOL "" FORCE) + set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES_BAK}) #LDAP includes won't be used + else() + if(CMAKE_USE_OPENLDAP) + set(USE_OPENLDAP ON) + endif() + if(CMAKE_LDAP_INCLUDE_DIR) + include_directories(${CMAKE_LDAP_INCLUDE_DIR}) + endif() + set(NEED_LBER_H ON) + set(_HEADER_LIST) + if(HAVE_WINDOWS_H) + list(APPEND _HEADER_LIST "windows.h") + endif() + if(HAVE_SYS_TYPES_H) + list(APPEND _HEADER_LIST "sys/types.h") + endif() + list(APPEND _HEADER_LIST "ldap.h") + + set(_SRC_STRING "") + foreach(_HEADER ${_HEADER_LIST}) + set(_INCLUDE_STRING "${_INCLUDE_STRING}#include <${_HEADER}>\n") + endforeach() + + set(_SRC_STRING + " + ${_INCLUDE_STRING} + int main(int argc, char ** argv) + { + BerValue *bvp = NULL; + BerElement *bep = ber_init(bvp); + ber_free(bep, 1); + return 0; + }" + ) + set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -DLDAP_DEPRECATED=1") + list(APPEND CMAKE_REQUIRED_LIBRARIES ${CMAKE_LDAP_LIB}) + if(HAVE_LIBLBER) + list(APPEND CMAKE_REQUIRED_LIBRARIES ${CMAKE_LBER_LIB}) + endif() + check_c_source_compiles("${_SRC_STRING}" NOT_NEED_LBER_H) + + if(NOT_NEED_LBER_H) + set(NEED_LBER_H OFF) + else() + set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -DNEED_LBER_H") + endif() + endif() + endif() + +endif() + +# No ldap, no ldaps. +if(CURL_DISABLE_LDAP) + if(NOT CURL_DISABLE_LDAPS) + message(STATUS "LDAP needs to be enabled to support LDAPS") + set(CURL_DISABLE_LDAPS ON CACHE BOOL "" FORCE) + endif() +endif() + +if(NOT CURL_DISABLE_LDAPS) + check_include_file_concat("ldap_ssl.h" HAVE_LDAP_SSL_H) + check_include_file_concat("ldapssl.h" HAVE_LDAPSSL_H) +endif() + +# Check for idn +check_library_exists_concat("idn2" idn2_lookup_ul HAVE_LIBIDN2) + +# Check for symbol dlopen (same as HAVE_LIBDL) +check_library_exists("${CURL_LIBS}" dlopen "" HAVE_DLOPEN) + +if(0) # This code not needed for building within CMake. +option(CURL_ZLIB "Set to ON to enable building curl with zlib support." ON) +set(HAVE_LIBZ OFF) +set(HAVE_ZLIB_H OFF) +set(HAVE_ZLIB OFF) +if(CURL_ZLIB) + find_package(ZLIB QUIET) + if(ZLIB_FOUND) + set(HAVE_ZLIB_H ON) + set(HAVE_ZLIB ON) + set(HAVE_LIBZ ON) + list(APPEND CURL_LIBS ${ZLIB_LIBRARIES}) + include_directories(${ZLIB_INCLUDE_DIRS}) + list(APPEND CMAKE_REQUIRED_INCLUDES ${ZLIB_INCLUDE_DIRS}) + endif() +endif() +endif() + +#----------------------------------------------------------------------------- +# CMake-specific curl code. + +if(CURL_SPECIAL_LIBZ) + set(CURL_LIBS ${CURL_LIBS} "${CURL_SPECIAL_LIBZ}") + include_directories(${CURL_SPECIAL_LIBZ_INCLUDES}) + set(HAVE_LIBZ 0) + set(HAVE_ZLIB_H 0) +endif() + +#libSSH2 +option(CMAKE_USE_LIBSSH2 "Use libSSH2" ON) +mark_as_advanced(CMAKE_USE_LIBSSH2) +set(USE_LIBSSH2 OFF) +set(HAVE_LIBSSH2 OFF) +set(HAVE_LIBSSH2_H OFF) + +if(CMAKE_USE_LIBSSH2) + find_package(LibSSH2) + if(LIBSSH2_FOUND) + list(APPEND CURL_LIBS ${LIBSSH2_LIBRARY}) + set(CMAKE_REQUIRED_LIBRARIES ${LIBSSH2_LIBRARY}) + list(APPEND CMAKE_REQUIRED_INCLUDES "${LIBSSH2_INCLUDE_DIR}") + include_directories("${LIBSSH2_INCLUDE_DIR}") + set(HAVE_LIBSSH2 ON) + set(USE_LIBSSH2 ON) + + # find_package has already found the headers + set(HAVE_LIBSSH2_H ON) + set(CURL_INCLUDES ${CURL_INCLUDES} "${LIBSSH2_INCLUDE_DIR}/libssh2.h") + set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -DHAVE_LIBSSH2_H") + + # now check for specific libssh2 symbols as they were added in different versions + set(CMAKE_EXTRA_INCLUDE_FILES "libssh2.h") + check_function_exists(libssh2_version HAVE_LIBSSH2_VERSION) + check_function_exists(libssh2_init HAVE_LIBSSH2_INIT) + check_function_exists(libssh2_exit HAVE_LIBSSH2_EXIT) + check_function_exists(libssh2_scp_send64 HAVE_LIBSSH2_SCP_SEND64) + check_function_exists(libssh2_session_handshake HAVE_LIBSSH2_SESSION_HANDSHAKE) + set(CMAKE_EXTRA_INCLUDE_FILES "") + + endif(LIBSSH2_FOUND) +endif(CMAKE_USE_LIBSSH2) + +option(CMAKE_USE_GSSAPI "Use GSSAPI implementation (right now only Heimdal is supported with CMake build)" OFF) +mark_as_advanced(CMAKE_USE_GSSAPI) + +if(CMAKE_USE_GSSAPI) + find_package(GSS) + + set(HAVE_GSSAPI ${GSS_FOUND}) + if(GSS_FOUND) + + message(STATUS "Found ${GSS_FLAVOUR} GSSAPI version: \"${GSS_VERSION}\"") + + list(APPEND CMAKE_REQUIRED_INCLUDES ${GSS_INCLUDE_DIRECTORIES}) + check_include_file_concat("gssapi/gssapi.h" HAVE_GSSAPI_GSSAPI_H) + check_include_file_concat("gssapi/gssapi_generic.h" HAVE_GSSAPI_GSSAPI_GENERIC_H) + check_include_file_concat("gssapi/gssapi_krb5.h" HAVE_GSSAPI_GSSAPI_KRB5_H) + + if(GSS_FLAVOUR STREQUAL "Heimdal") + set(HAVE_GSSHEIMDAL ON) + else() # MIT + set(HAVE_GSSMIT ON) + set(_INCLUDE_LIST "") + if(HAVE_GSSAPI_GSSAPI_H) + list(APPEND _INCLUDE_LIST "gssapi/gssapi.h") + endif() + if(HAVE_GSSAPI_GSSAPI_GENERIC_H) + list(APPEND _INCLUDE_LIST "gssapi/gssapi_generic.h") + endif() + if(HAVE_GSSAPI_GSSAPI_KRB5_H) + list(APPEND _INCLUDE_LIST "gssapi/gssapi_krb5.h") + endif() + + string(REPLACE ";" " " _COMPILER_FLAGS_STR "${GSS_COMPILER_FLAGS}") + string(REPLACE ";" " " _LINKER_FLAGS_STR "${GSS_LINKER_FLAGS}") + + foreach(_dir ${GSS_LINK_DIRECTORIES}) + set(_LINKER_FLAGS_STR "${_LINKER_FLAGS_STR} -L\"${_dir}\"") + endforeach() + + set(CMAKE_REQUIRED_FLAGS "${_COMPILER_FLAGS_STR} ${_LINKER_FLAGS_STR}") + set(CMAKE_REQUIRED_LIBRARIES ${GSS_LIBRARIES}) + check_symbol_exists("GSS_C_NT_HOSTBASED_SERVICE" ${_INCLUDE_LIST} HAVE_GSS_C_NT_HOSTBASED_SERVICE) + if(NOT HAVE_GSS_C_NT_HOSTBASED_SERVICE) + set(HAVE_OLD_GSSMIT ON) + endif() + + endif() + + include_directories(${GSS_INCLUDE_DIRECTORIES}) + link_directories(${GSS_LINK_DIRECTORIES}) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GSS_COMPILER_FLAGS}") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${GSS_LINKER_FLAGS}") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GSS_LINKER_FLAGS}") + list(APPEND CURL_LIBS ${GSS_LIBRARIES}) + + else() + message(WARNING "GSSAPI support has been requested but no supporting libraries found. Skipping.") + endif() +endif() + +option(ENABLE_UNIX_SOCKETS "Define if you want Unix domain sockets support" ON) +if(ENABLE_UNIX_SOCKETS) + include(CheckStructHasMember) + check_struct_has_member("struct sockaddr_un" sun_path "sys/un.h" USE_UNIX_SOCKETS) +else() + unset(USE_UNIX_SOCKETS CACHE) +endif() + + +# Check for header files +if(NOT UNIX) + check_include_file_concat("windows.h" HAVE_WINDOWS_H) + check_include_file_concat("winsock.h" HAVE_WINSOCK_H) + check_include_file_concat("ws2tcpip.h" HAVE_WS2TCPIP_H) + check_include_file_concat("winsock2.h" HAVE_WINSOCK2_H) + if(CURL_WINDOWS_SSPI) + set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -DSECURITY_WIN32") + check_include_file_concat("sspi.h" HAVE_SSPI_H) + if(HAVE_SSPI_H) + check_include_file_concat("schannel.h" HAVE_SCHANNEL_H) + set(USE_WINDOWS_SSPI ON) + if(HAVE_SCHANNEL_H) + set(USE_SCHANNEL ON) + set(SSL_ENABLED ON) + set(CURL_LIBS ${CURL_LIBS} "crypt32") + endif() + endif() + endif() +else() + set(HAVE_WINDOWS_H 0) + set(HAVE_WINSOCK_H 0) + set(HAVE_WS2TCPIP_H 0) + set(HAVE_WINSOCK2_H 0) +endif() + +check_include_file_concat("stdio.h" HAVE_STDIO_H) +check_include_file_concat("inttypes.h" HAVE_INTTYPES_H) +check_include_file_concat("sys/filio.h" HAVE_SYS_FILIO_H) +check_include_file_concat("sys/ioctl.h" HAVE_SYS_IOCTL_H) +check_include_file_concat("sys/param.h" HAVE_SYS_PARAM_H) +check_include_file_concat("sys/poll.h" HAVE_SYS_POLL_H) +check_include_file_concat("sys/resource.h" HAVE_SYS_RESOURCE_H) +check_include_file_concat("sys/select.h" HAVE_SYS_SELECT_H) +check_include_file_concat("sys/socket.h" HAVE_SYS_SOCKET_H) +check_include_file_concat("sys/sockio.h" HAVE_SYS_SOCKIO_H) +check_include_file_concat("sys/stat.h" HAVE_SYS_STAT_H) +check_include_file_concat("sys/time.h" HAVE_SYS_TIME_H) +check_include_file_concat("sys/types.h" HAVE_SYS_TYPES_H) +check_include_file_concat("sys/uio.h" HAVE_SYS_UIO_H) +check_include_file_concat("sys/un.h" HAVE_SYS_UN_H) +check_include_file_concat("sys/utime.h" HAVE_SYS_UTIME_H) +check_include_file_concat("alloca.h" HAVE_ALLOCA_H) +check_include_file_concat("arpa/inet.h" HAVE_ARPA_INET_H) +check_include_file_concat("arpa/tftp.h" HAVE_ARPA_TFTP_H) +check_include_file_concat("assert.h" HAVE_ASSERT_H) +check_include_file_concat("crypto.h" HAVE_CRYPTO_H) +check_include_file_concat("des.h" HAVE_DES_H) +check_include_file_concat("err.h" HAVE_ERR_H) +check_include_file_concat("errno.h" HAVE_ERRNO_H) +check_include_file_concat("fcntl.h" HAVE_FCNTL_H) +check_include_file_concat("idn2.h" HAVE_IDN2_H) +check_include_file_concat("ifaddrs.h" HAVE_IFADDRS_H) +check_include_file_concat("io.h" HAVE_IO_H) +check_include_file_concat("krb.h" HAVE_KRB_H) +check_include_file_concat("libgen.h" HAVE_LIBGEN_H) +check_include_file_concat("limits.h" HAVE_LIMITS_H) +check_include_file_concat("locale.h" HAVE_LOCALE_H) +check_include_file_concat("net/if.h" HAVE_NET_IF_H) +check_include_file_concat("netdb.h" HAVE_NETDB_H) +check_include_file_concat("netinet/in.h" HAVE_NETINET_IN_H) +check_include_file_concat("netinet/tcp.h" HAVE_NETINET_TCP_H) + +check_include_file_concat("pem.h" HAVE_PEM_H) +check_include_file_concat("poll.h" HAVE_POLL_H) +check_include_file_concat("pwd.h" HAVE_PWD_H) +check_include_file_concat("rsa.h" HAVE_RSA_H) +check_include_file_concat("setjmp.h" HAVE_SETJMP_H) +check_include_file_concat("sgtty.h" HAVE_SGTTY_H) +check_include_file_concat("signal.h" HAVE_SIGNAL_H) +check_include_file_concat("ssl.h" HAVE_SSL_H) +check_include_file_concat("stdbool.h" HAVE_STDBOOL_H) +check_include_file_concat("stdint.h" HAVE_STDINT_H) +check_include_file_concat("stdio.h" HAVE_STDIO_H) +check_include_file_concat("stdlib.h" HAVE_STDLIB_H) +check_include_file_concat("string.h" HAVE_STRING_H) +check_include_file_concat("strings.h" HAVE_STRINGS_H) +check_include_file_concat("stropts.h" HAVE_STROPTS_H) +check_include_file_concat("termio.h" HAVE_TERMIO_H) +check_include_file_concat("termios.h" HAVE_TERMIOS_H) +check_include_file_concat("time.h" HAVE_TIME_H) +check_include_file_concat("unistd.h" HAVE_UNISTD_H) +check_include_file_concat("utime.h" HAVE_UTIME_H) +check_include_file_concat("x509.h" HAVE_X509_H) + +check_include_file_concat("process.h" HAVE_PROCESS_H) +check_include_file_concat("stddef.h" HAVE_STDDEF_H) +check_include_file_concat("dlfcn.h" HAVE_DLFCN_H) +check_include_file_concat("malloc.h" HAVE_MALLOC_H) +check_include_file_concat("memory.h" HAVE_MEMORY_H) +check_include_file_concat("netinet/if_ether.h" HAVE_NETINET_IF_ETHER_H) +check_include_file_concat("stdint.h" HAVE_STDINT_H) +check_include_file_concat("sockio.h" HAVE_SOCKIO_H) +check_include_file_concat("sys/utsname.h" HAVE_SYS_UTSNAME_H) + +check_type_size(size_t SIZEOF_SIZE_T) +check_type_size(ssize_t SIZEOF_SSIZE_T) +check_type_size("long long" SIZEOF_LONG_LONG) +check_type_size("long" SIZEOF_LONG) +check_type_size("short" SIZEOF_SHORT) +check_type_size("int" SIZEOF_INT) +check_type_size("__int64" SIZEOF___INT64) +check_type_size("time_t" SIZEOF_TIME_T) + +# Make public versions of some type sizes for curlbuild.h. +foreach(t INT LONG LONG_LONG SSIZE_T) + string(REPLACE "SIZEOF_" "CURL_SIZEOF_" CURL_SIZEOF_${t}_CODE "${SIZEOF_${t}_CODE}") +endforeach() + +if(HAVE_SIZEOF_LONG_LONG) + set(HAVE_LONGLONG 1) + set(HAVE_LL 1) +endif(HAVE_SIZEOF_LONG_LONG) + +find_file(RANDOM_FILE urandom /dev) +mark_as_advanced(RANDOM_FILE) + +# Check for some functions that are used +if(HAVE_LIBWS2_32) + set(CMAKE_REQUIRED_LIBRARIES ws2_32) +elseif(HAVE_LIBSOCKET) + set(CMAKE_REQUIRED_LIBRARIES socket) +endif() + +check_symbol_exists(basename "${CURL_INCLUDES}" HAVE_BASENAME) +check_symbol_exists(socket "${CURL_INCLUDES}" HAVE_SOCKET) - check_symbol_exists(poll "${CURL_INCLUDES}" HAVE_POLL) ++# poll on macOS is unreliable, it first did not exist, then was broken until ++# fixed in 10.9 only to break again in 10.12. ++if(NOT APPLE) ++ check_symbol_exists(poll "${CURL_INCLUDES}" HAVE_POLL) ++endif() +check_symbol_exists(select "${CURL_INCLUDES}" HAVE_SELECT) +check_symbol_exists(strdup "${CURL_INCLUDES}" HAVE_STRDUP) +check_symbol_exists(strstr "${CURL_INCLUDES}" HAVE_STRSTR) +check_symbol_exists(strtok_r "${CURL_INCLUDES}" HAVE_STRTOK_R) +check_symbol_exists(strftime "${CURL_INCLUDES}" HAVE_STRFTIME) +check_symbol_exists(uname "${CURL_INCLUDES}" HAVE_UNAME) +check_symbol_exists(strcasecmp "${CURL_INCLUDES}" HAVE_STRCASECMP) +check_symbol_exists(stricmp "${CURL_INCLUDES}" HAVE_STRICMP) +check_symbol_exists(strcmpi "${CURL_INCLUDES}" HAVE_STRCMPI) +check_symbol_exists(strncmpi "${CURL_INCLUDES}" HAVE_STRNCMPI) +check_symbol_exists(alarm "${CURL_INCLUDES}" HAVE_ALARM) +if(NOT HAVE_STRNCMPI) + set(HAVE_STRCMPI) +endif(NOT HAVE_STRNCMPI) +check_symbol_exists(gethostbyaddr "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR) +check_symbol_exists(gethostbyaddr_r "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR_R) +check_symbol_exists(gettimeofday "${CURL_INCLUDES}" HAVE_GETTIMEOFDAY) +check_symbol_exists(inet_addr "${CURL_INCLUDES}" HAVE_INET_ADDR) +check_symbol_exists(inet_ntoa "${CURL_INCLUDES}" HAVE_INET_NTOA) +check_symbol_exists(inet_ntoa_r "${CURL_INCLUDES}" HAVE_INET_NTOA_R) +check_symbol_exists(tcsetattr "${CURL_INCLUDES}" HAVE_TCSETATTR) +check_symbol_exists(tcgetattr "${CURL_INCLUDES}" HAVE_TCGETATTR) +check_symbol_exists(perror "${CURL_INCLUDES}" HAVE_PERROR) +check_symbol_exists(closesocket "${CURL_INCLUDES}" HAVE_CLOSESOCKET) +check_symbol_exists(setvbuf "${CURL_INCLUDES}" HAVE_SETVBUF) +check_symbol_exists(sigsetjmp "${CURL_INCLUDES}" HAVE_SIGSETJMP) +check_symbol_exists(getpass_r "${CURL_INCLUDES}" HAVE_GETPASS_R) +check_symbol_exists(strlcat "${CURL_INCLUDES}" HAVE_STRLCAT) +check_symbol_exists(getpwuid "${CURL_INCLUDES}" HAVE_GETPWUID) +check_symbol_exists(geteuid "${CURL_INCLUDES}" HAVE_GETEUID) +check_symbol_exists(utime "${CURL_INCLUDES}" HAVE_UTIME) +if(CMAKE_USE_OPENSSL) + check_symbol_exists(RAND_status "${CURL_INCLUDES}" HAVE_RAND_STATUS) + check_symbol_exists(RAND_screen "${CURL_INCLUDES}" HAVE_RAND_SCREEN) + check_symbol_exists(RAND_egd "${CURL_INCLUDES}" HAVE_RAND_EGD) + if(HAVE_LIBCRYPTO AND HAVE_LIBSSL) + set(USE_OPENSSL 1) + endif(HAVE_LIBCRYPTO AND HAVE_LIBSSL) +endif(CMAKE_USE_OPENSSL) +check_symbol_exists(gmtime_r "${CURL_INCLUDES}" HAVE_GMTIME_R) +check_symbol_exists(localtime_r "${CURL_INCLUDES}" HAVE_LOCALTIME_R) + +check_symbol_exists(gethostbyname "${CURL_INCLUDES}" HAVE_GETHOSTBYNAME) +check_symbol_exists(gethostbyname_r "${CURL_INCLUDES}" HAVE_GETHOSTBYNAME_R) + +check_symbol_exists(signal "${CURL_INCLUDES}" HAVE_SIGNAL_FUNC) +check_symbol_exists(SIGALRM "${CURL_INCLUDES}" HAVE_SIGNAL_MACRO) +if(HAVE_SIGNAL_FUNC AND HAVE_SIGNAL_MACRO) + set(HAVE_SIGNAL 1) +endif(HAVE_SIGNAL_FUNC AND HAVE_SIGNAL_MACRO) +check_symbol_exists(uname "${CURL_INCLUDES}" HAVE_UNAME) +check_symbol_exists(strtoll "${CURL_INCLUDES}" HAVE_STRTOLL) +check_symbol_exists(_strtoi64 "${CURL_INCLUDES}" HAVE__STRTOI64) +check_symbol_exists(strerror_r "${CURL_INCLUDES}" HAVE_STRERROR_R) +check_symbol_exists(siginterrupt "${CURL_INCLUDES}" HAVE_SIGINTERRUPT) +check_symbol_exists(perror "${CURL_INCLUDES}" HAVE_PERROR) +check_symbol_exists(fork "${CURL_INCLUDES}" HAVE_FORK) +check_symbol_exists(getaddrinfo "${CURL_INCLUDES}" HAVE_GETADDRINFO) +check_symbol_exists(freeaddrinfo "${CURL_INCLUDES}" HAVE_FREEADDRINFO) +check_symbol_exists(freeifaddrs "${CURL_INCLUDES}" HAVE_FREEIFADDRS) +check_symbol_exists(pipe "${CURL_INCLUDES}" HAVE_PIPE) +check_symbol_exists(ftruncate "${CURL_INCLUDES}" HAVE_FTRUNCATE) +check_symbol_exists(getprotobyname "${CURL_INCLUDES}" HAVE_GETPROTOBYNAME) +check_symbol_exists(getrlimit "${CURL_INCLUDES}" HAVE_GETRLIMIT) +check_symbol_exists(setlocale "${CURL_INCLUDES}" HAVE_SETLOCALE) +check_symbol_exists(setrlimit "${CURL_INCLUDES}" HAVE_SETRLIMIT) +check_symbol_exists(fcntl "${CURL_INCLUDES}" HAVE_FCNTL) +check_symbol_exists(ioctl "${CURL_INCLUDES}" HAVE_IOCTL) +check_symbol_exists(setsockopt "${CURL_INCLUDES}" HAVE_SETSOCKOPT) + +# symbol exists in win32, but function does not. +check_function_exists(inet_pton HAVE_INET_PTON) + +# sigaction and sigsetjmp are special. Use special mechanism for +# detecting those, but only if previous attempt failed. +if(HAVE_SIGNAL_H) + check_symbol_exists(sigaction "signal.h" HAVE_SIGACTION) +endif(HAVE_SIGNAL_H) + +if(NOT HAVE_SIGSETJMP) + if(HAVE_SETJMP_H) + check_symbol_exists(sigsetjmp "setjmp.h" HAVE_MACRO_SIGSETJMP) + if(HAVE_MACRO_SIGSETJMP) + set(HAVE_SIGSETJMP 1) + endif(HAVE_MACRO_SIGSETJMP) + endif(HAVE_SETJMP_H) +endif(NOT HAVE_SIGSETJMP) + +# If there is no stricmp(), do not allow LDAP to parse URLs +if(NOT HAVE_STRICMP) + set(HAVE_LDAP_URL_PARSE 1) +endif(NOT HAVE_STRICMP) + +# Do curl specific tests +foreach(CURL_TEST + HAVE_FCNTL_O_NONBLOCK + HAVE_IOCTLSOCKET + HAVE_IOCTLSOCKET_CAMEL + HAVE_IOCTLSOCKET_CAMEL_FIONBIO + HAVE_IOCTLSOCKET_FIONBIO + HAVE_IOCTL_FIONBIO + HAVE_IOCTL_SIOCGIFADDR + HAVE_SETSOCKOPT_SO_NONBLOCK + HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID + TIME_WITH_SYS_TIME + HAVE_O_NONBLOCK + HAVE_GETHOSTBYADDR_R_5 + HAVE_GETHOSTBYADDR_R_7 + HAVE_GETHOSTBYADDR_R_8 + HAVE_GETHOSTBYADDR_R_5_REENTRANT + HAVE_GETHOSTBYADDR_R_7_REENTRANT + HAVE_GETHOSTBYADDR_R_8_REENTRANT + HAVE_GETHOSTBYNAME_R_3 + HAVE_GETHOSTBYNAME_R_5 + HAVE_GETHOSTBYNAME_R_6 + HAVE_GETHOSTBYNAME_R_3_REENTRANT + HAVE_GETHOSTBYNAME_R_5_REENTRANT + HAVE_GETHOSTBYNAME_R_6_REENTRANT + HAVE_SOCKLEN_T + HAVE_IN_ADDR_T + HAVE_BOOL_T + STDC_HEADERS + RETSIGTYPE_TEST + HAVE_INET_NTOA_R_DECL + HAVE_INET_NTOA_R_DECL_REENTRANT + HAVE_GETADDRINFO + HAVE_FILE_OFFSET_BITS + ) + curl_internal_test(${CURL_TEST}) +endforeach(CURL_TEST) + +if(HAVE_FILE_OFFSET_BITS) + set(_FILE_OFFSET_BITS 64) + set(CMAKE_REQUIRED_FLAGS "-D_FILE_OFFSET_BITS=64") +endif(HAVE_FILE_OFFSET_BITS) +check_type_size("off_t" SIZEOF_OFF_T) +set(CMAKE_REQUIRED_FLAGS) + +foreach(CURL_TEST + HAVE_GLIBC_STRERROR_R + HAVE_POSIX_STRERROR_R + ) + curl_internal_test_run(${CURL_TEST}) +endforeach(CURL_TEST) + +# Check for reentrant +foreach(CURL_TEST + HAVE_GETHOSTBYADDR_R_5 + HAVE_GETHOSTBYADDR_R_7 + HAVE_GETHOSTBYADDR_R_8 + HAVE_GETHOSTBYNAME_R_3 + HAVE_GETHOSTBYNAME_R_5 + HAVE_GETHOSTBYNAME_R_6 + HAVE_INET_NTOA_R_DECL_REENTRANT) + if(NOT ${CURL_TEST}) + if(${CURL_TEST}_REENTRANT) + set(NEED_REENTRANT 1) + endif(${CURL_TEST}_REENTRANT) + endif(NOT ${CURL_TEST}) +endforeach(CURL_TEST) + +if(NEED_REENTRANT) + foreach(CURL_TEST + HAVE_GETHOSTBYADDR_R_5 + HAVE_GETHOSTBYADDR_R_7 + HAVE_GETHOSTBYADDR_R_8 + HAVE_GETHOSTBYNAME_R_3 + HAVE_GETHOSTBYNAME_R_5 + HAVE_GETHOSTBYNAME_R_6) + set(${CURL_TEST} 0) + if(${CURL_TEST}_REENTRANT) + set(${CURL_TEST} 1) + endif(${CURL_TEST}_REENTRANT) + endforeach(CURL_TEST) +endif(NEED_REENTRANT) + +if(HAVE_INET_NTOA_R_DECL_REENTRANT) + set(HAVE_INET_NTOA_R_DECL 1) + set(NEED_REENTRANT 1) +endif(HAVE_INET_NTOA_R_DECL_REENTRANT) + +# Some other minor tests + +if(NOT HAVE_IN_ADDR_T) + set(in_addr_t "unsigned long") +endif(NOT HAVE_IN_ADDR_T) + +# Fix libz / zlib.h + +if(NOT CURL_SPECIAL_LIBZ) + if(NOT HAVE_LIBZ) + set(HAVE_ZLIB_H 0) + endif(NOT HAVE_LIBZ) + + if(NOT HAVE_ZLIB_H) + set(HAVE_LIBZ 0) + endif(NOT HAVE_ZLIB_H) +endif(NOT CURL_SPECIAL_LIBZ) + +# Check for nonblocking +set(HAVE_DISABLED_NONBLOCKING 1) +if(HAVE_FIONBIO OR + HAVE_IOCTLSOCKET OR + HAVE_IOCTLSOCKET_CASE OR + HAVE_O_NONBLOCK) + set(HAVE_DISABLED_NONBLOCKING) +endif(HAVE_FIONBIO OR + HAVE_IOCTLSOCKET OR + HAVE_IOCTLSOCKET_CASE OR + HAVE_O_NONBLOCK) + +if(RETSIGTYPE_TEST) + set(RETSIGTYPE void) +else(RETSIGTYPE_TEST) + set(RETSIGTYPE int) +endif(RETSIGTYPE_TEST) + +if(CMAKE_COMPILER_IS_GNUCC AND APPLE) + include(CheckCCompilerFlag) + check_c_compiler_flag(-Wno-long-double HAVE_C_FLAG_Wno_long_double) + if(HAVE_C_FLAG_Wno_long_double) + # The Mac version of GCC warns about use of long double. Disable it. + get_source_file_property(MPRINTF_COMPILE_FLAGS mprintf.c COMPILE_FLAGS) + if(MPRINTF_COMPILE_FLAGS) + set(MPRINTF_COMPILE_FLAGS "${MPRINTF_COMPILE_FLAGS} -Wno-long-double") + else(MPRINTF_COMPILE_FLAGS) + set(MPRINTF_COMPILE_FLAGS "-Wno-long-double") + endif(MPRINTF_COMPILE_FLAGS) + set_source_files_properties(mprintf.c PROPERTIES + COMPILE_FLAGS ${MPRINTF_COMPILE_FLAGS}) + endif(HAVE_C_FLAG_Wno_long_double) +endif(CMAKE_COMPILER_IS_GNUCC AND APPLE) + +if(HAVE_SOCKLEN_T) + set(CURL_HAVE_SOCKLEN_T 1) + set(CURL_TYPEOF_CURL_SOCKLEN_T "socklen_t") + if(WIN32) + set(CMAKE_EXTRA_INCLUDE_FILES "winsock2.h;ws2tcpip.h") + elseif(HAVE_SYS_SOCKET_H) + set(CMAKE_EXTRA_INCLUDE_FILES "sys/socket.h") + endif() + check_type_size("socklen_t" CURL_SIZEOF_CURL_SOCKLEN_T) + set(CMAKE_EXTRA_INCLUDE_FILES) + if(NOT HAVE_CURL_SIZEOF_CURL_SOCKLEN_T) + message(FATAL_ERROR + "Check for sizeof socklen_t failed, see CMakeFiles/CMakerror.log") + endif() +else() + set(CURL_HAVE_SOCKLEN_T 0) +endif() + +# TODO test which of these headers are required for the typedefs used in curlbuild.h +if(WIN32) + set(CURL_PULL_WS2TCPIP_H ${HAVE_WS2TCPIP_H}) +else() + set(CURL_PULL_SYS_TYPES_H ${HAVE_SYS_TYPES_H}) + set(CURL_PULL_SYS_SOCKET_H ${HAVE_SYS_SOCKET_H}) + set(CURL_PULL_SYS_POLL_H ${HAVE_SYS_POLL_H}) +endif() +set(CURL_PULL_STDINT_H ${HAVE_STDINT_H}) +set(CURL_PULL_INTTYPES_H ${HAVE_INTTYPES_H}) + +include(CMake/OtherTests.cmake) + +add_definitions(-DHAVE_CONFIG_H) + +# For windows, do not allow the compiler to use default target (Vista). +if(WIN32) + add_definitions(-D_WIN32_WINNT=0x0501) +endif(WIN32) + +# For windows, all compilers used by cmake should support large files +if(WIN32) + set(USE_WIN32_LARGE_FILES ON) +endif(WIN32) + +if(MSVC) + add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE) +endif(MSVC) + +# Ugly (but functional) way to include "Makefile.inc" by transforming it (= regenerate it). +function(TRANSFORM_MAKEFILE_INC INPUT_FILE OUTPUT_FILE) + file(READ ${INPUT_FILE} MAKEFILE_INC_TEXT) + string(REPLACE "$(top_srcdir)" "\${CURL_SOURCE_DIR}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) + string(REPLACE "$(top_builddir)" "\${CURL_BINARY_DIR}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) + + string(REGEX REPLACE "\\\\\n" "?!?" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) + string(REGEX REPLACE "([a-zA-Z_][a-zA-Z0-9_]*)[\t ]*=[\t ]*([^\n]*)" "SET(\\1 \\2)" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) + string(REPLACE "?!?" "\n" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) + + string(REGEX REPLACE "\\$\\(([a-zA-Z_][a-zA-Z0-9_]*)\\)" "\${\\1}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) # Replace $() with ${} + string(REGEX REPLACE "@([a-zA-Z_][a-zA-Z0-9_]*)@" "\${\\1}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) # Replace @@ with ${}, even if that may not be read by CMake scripts. + file(WRITE ${OUTPUT_FILE} ${MAKEFILE_INC_TEXT}) + +endfunction() + +add_subdirectory(lib) +if(BUILD_CURL_EXE) + add_subdirectory(src) +endif() + +#----------------------------------------------------------------------------- +# CMake-specific curl code. +add_executable(LIBCURL curltest.c) +target_link_libraries(LIBCURL cmcurl) + +if(CMAKE_CURL_TEST_URL) + add_test(curl LIBCURL ${CMAKE_CURL_TEST_URL}) +endif() + +install(FILES COPYING DESTINATION ${CMAKE_DOC_DIR}/cmcurl) +#----------------------------------------------------------------------------- + +if(0) # This code not needed for building within CMake. +include(CTest) +if(BUILD_TESTING) + add_subdirectory(tests) +endif() + +# TODO support GNUTLS, NSS, POLARSSL, AXTLS, CYASSL, WINSSL, DARWINSSL +if(USE_OPENSSL) + set(SSL_ENABLED 1) +endif() + +# Helper to populate a list (_items) with a label when conditions (the remaining +# args) are satisfied +function(_add_if label) + # TODO need to disable policy CMP0054 (CMake 3.1) to allow this indirection + if(${ARGN}) + set(_items ${_items} "${label}" PARENT_SCOPE) + endif() +endfunction() + +# Clear list and try to detect available features +set(_items) +_add_if("WinSSL" SSL_ENABLED AND USE_WINDOWS_SSPI) +_add_if("OpenSSL" SSL_ENABLED AND USE_OPENSSL) +_add_if("IPv6" ENABLE_IPV6) +_add_if("unix-sockets" USE_UNIX_SOCKETS) +_add_if("libz" HAVE_LIBZ) +_add_if("AsynchDNS" USE_ARES OR USE_THREADS_POSIX OR USE_THREADS_WIN32) +_add_if("IDN" HAVE_LIBIDN2) +_add_if("Largefile" (CURL_SIZEOF_CURL_OFF_T GREATER 4) AND + ((SIZEOF_OFF_T GREATER 4) OR USE_WIN32_LARGE_FILES)) +# TODO SSP1 (WinSSL) check is missing +_add_if("SSPI" USE_WINDOWS_SSPI) +_add_if("GSS-API" HAVE_GSSAPI) +# TODO SSP1 missing for SPNEGO +_add_if("SPNEGO" NOT CURL_DISABLE_CRYPTO_AUTH AND + (HAVE_GSSAPI OR USE_WINDOWS_SSPI)) +_add_if("Kerberos" NOT CURL_DISABLE_CRYPTO_AUTH AND + (HAVE_GSSAPI OR USE_WINDOWS_SSPI)) +# NTLM support requires crypto function adaptions from various SSL libs +# TODO alternative SSL libs tests for SSP1, GNUTLS, NSS, DARWINSSL +if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR + USE_WINDOWS_SSPI OR GNUTLS_ENABLED OR NSS_ENABLED OR DARWINSSL_ENABLED)) + _add_if("NTLM" 1) + # TODO missing option (autoconf: --enable-ntlm-wb) + _add_if("NTLM_WB" NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED) +endif() +# TODO missing option (--enable-tls-srp), depends on GNUTLS_SRP/OPENSSL_SRP +_add_if("TLS-SRP" USE_TLS_SRP) +# TODO option --with-nghttp2 tests for nghttp2 lib and nghttp2/nghttp2.h header +_add_if("HTTP2" USE_NGHTTP2) +string(REPLACE ";" " " SUPPORT_FEATURES "${_items}") +message(STATUS "Enabled features: ${SUPPORT_FEATURES}") + +# Clear list and try to detect available protocols +set(_items) +_add_if("HTTP" NOT CURL_DISABLE_HTTP) +_add_if("HTTPS" NOT CURL_DISABLE_HTTP AND SSL_ENABLED) +_add_if("FTP" NOT CURL_DISABLE_FTP) +_add_if("FTPS" NOT CURL_DISABLE_FTP AND SSL_ENABLED) +_add_if("FILE" NOT CURL_DISABLE_FILE) +_add_if("TELNET" NOT CURL_DISABLE_TELNET) +_add_if("LDAP" NOT CURL_DISABLE_LDAP) +# CURL_DISABLE_LDAP implies CURL_DISABLE_LDAPS +# TODO check HAVE_LDAP_SSL (in autoconf this is enabled with --enable-ldaps) +_add_if("LDAPS" NOT CURL_DISABLE_LDAPS AND + ((USE_OPENLDAP AND SSL_ENABLED) OR + (NOT USE_OPENLDAP AND HAVE_LDAP_SSL))) +_add_if("DICT" NOT CURL_DISABLE_DICT) +_add_if("TFTP" NOT CURL_DISABLE_TFTP) +_add_if("GOPHER" NOT CURL_DISABLE_GOPHER) +_add_if("POP3" NOT CURL_DISABLE_POP3) +_add_if("POP3S" NOT CURL_DISABLE_POP3 AND SSL_ENABLED) +_add_if("IMAP" NOT CURL_DISABLE_IMAP) +_add_if("IMAPS" NOT CURL_DISABLE_IMAP AND SSL_ENABLED) +_add_if("SMTP" NOT CURL_DISABLE_SMTP) +_add_if("SMTPS" NOT CURL_DISABLE_SMTP AND SSL_ENABLED) +_add_if("SCP" USE_LIBSSH2) +_add_if("SFTP" USE_LIBSSH2) +_add_if("RTSP" NOT CURL_DISABLE_RTSP) +_add_if("RTMP" USE_LIBRTMP) +list(SORT _items) +string(REPLACE ";" " " SUPPORT_PROTOCOLS "${_items}") +message(STATUS "Enabled protocols: ${SUPPORT_PROTOCOLS}") + +# curl-config needs the following options to be set. +set(CC "${CMAKE_C_COMPILER}") +# TODO probably put a -D... options here? +set(CONFIGURE_OPTIONS "") +# TODO when to set "-DCURL_STATICLIB" for CPPFLAG_CURL_STATICLIB? +set(CPPFLAG_CURL_STATICLIB "") +# TODO need to set this (see CURL_CHECK_CA_BUNDLE in acinclude.m4) +set(CURL_CA_BUNDLE "") +set(CURLVERSION "${CURL_VERSION}") +set(ENABLE_SHARED "yes") +if(CURL_STATICLIB) + set(ENABLE_STATIC "yes") +else() + set(ENABLE_STATIC "no") +endif() +set(exec_prefix "\${prefix}") +set(includedir "\${prefix}/include") +set(LDFLAGS "${CMAKE_SHARED_LINKER_FLAGS}") +set(LIBCURL_LIBS "") +set(libdir "${CMAKE_INSTALL_PREFIX}/lib") +foreach(_lib ${CMAKE_C_IMPLICIT_LINK_LIBRARIES} ${CURL_LIBS}) + if(_lib MATCHES ".*/.*") + set(LIBCURL_LIBS "${LIBCURL_LIBS} ${_lib}") + else() + set(LIBCURL_LIBS "${LIBCURL_LIBS} -l${_lib}") + endif() +endforeach() +# "a" (Linux) or "lib" (Windows) +string(REPLACE "." "" libext "${CMAKE_STATIC_LIBRARY_SUFFIX}") +set(prefix "${CMAKE_INSTALL_PREFIX}") +# Set this to "yes" to append all libraries on which -lcurl is dependent +set(REQUIRE_LIB_DEPS "no") +# SUPPORT_FEATURES +# SUPPORT_PROTOCOLS +set(VERSIONNUM "${CURL_VERSION_NUM}") + +# Finally generate a "curl-config" matching this config +configure_file("${CURL_SOURCE_DIR}/curl-config.in" + "${CURL_BINARY_DIR}/curl-config" @ONLY) +install(FILES "${CURL_BINARY_DIR}/curl-config" + DESTINATION bin + PERMISSIONS + OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE + WORLD_READ WORLD_EXECUTE) + +# Finally generate a pkg-config file matching this config +configure_file("${CURL_SOURCE_DIR}/libcurl.pc.in" + "${CURL_BINARY_DIR}/libcurl.pc" @ONLY) +install(FILES "${CURL_BINARY_DIR}/libcurl.pc" + DESTINATION lib/pkgconfig) + +# This needs to be run very last so other parts of the scripts can take advantage of this. +if(NOT CURL_CONFIG_HAS_BEEN_RUN_BEFORE) + set(CURL_CONFIG_HAS_BEEN_RUN_BEFORE 1 CACHE INTERNAL "Flag to track whether this is the first time running CMake or if CMake has been configured before") +endif() + +# Installation. +# First, install generated curlbuild.h +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/include/curl/curlbuild.h" + DESTINATION include/curl ) +# Next, install other headers excluding curlbuild.h +install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/curl" + DESTINATION include + FILES_MATCHING PATTERN "*.h" + PATTERN "curlbuild.h" EXCLUDE) + + +# Workaround for MSVS10 to avoid the Dialog Hell +# FIXME: This could be removed with future version of CMake. +if(MSVC_VERSION EQUAL 1600) + set(CURL_SLN_FILENAME "${CMAKE_CURRENT_BINARY_DIR}/CURL.sln") + if(EXISTS "${CURL_SLN_FILENAME}") + file(APPEND "${CURL_SLN_FILENAME}" "\n# This should be regenerated!\n") + endif() +endif() +endif() diff --cc Utilities/cmcurl/include/curl/curl.h index aa1034b,0000000..daca8d1 mode 100644,000000..100644 --- a/Utilities/cmcurl/include/curl/curl.h +++ b/Utilities/cmcurl/include/curl/curl.h @@@ -1,2456 -1,0 +1,2530 @@@ +#ifndef __CURL_CURL_H +#define __CURL_CURL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * If you have libcurl problems, all docs and details are found here: + * https://curl.haxx.se/libcurl/ + * + * curl-library mailing list subscription and unsubscription web interface: + * https://cool.haxx.se/mailman/listinfo/curl-library/ + */ + +#ifdef CURL_NO_OLDIES +#define CURL_STRICTER +#endif + +#include "curlver.h" /* libcurl version defines */ +#include "cmcurl/include/curl/curlbuild.h" /* libcurl build definitions */ +#include "curlrules.h" /* libcurl rules enforcement */ + +/* + * Define WIN32 when build target is Win32 API + */ + +#if (defined(_WIN32) || defined(__WIN32__)) && \ + !defined(WIN32) && !defined(__SYMBIAN32__) +#define WIN32 +#endif + +#include +#include + +#if defined(__FreeBSD__) && (__FreeBSD__ >= 2) +/* Needed for __FreeBSD_version symbol definition */ +#include +#endif + +/* The include stuff here below is mainly for time_t! */ +#include +#include + +#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__) +#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H) || \ + defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H)) +/* The check above prevents the winsock2 inclusion if winsock.h already was + included, since they can't co-exist without problems */ +#include +#include +#endif +#endif + +/* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish + libc5-based Linux systems. Only include it on systems that are known to + require it! */ +#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \ + defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \ + defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \ + (defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) +#include +#endif + +#if !defined(WIN32) && !defined(_WIN32_WCE) +#include +#endif + +#if !defined(WIN32) && !defined(__WATCOMC__) && !defined(__VXWORKS__) +#include +#endif + +#if defined __BEOS__ || defined __HAIKU__ +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER) +typedef struct Curl_easy CURL; +typedef struct Curl_share CURLSH; +#else +typedef void CURL; +typedef void CURLSH; +#endif + +/* + * libcurl external API function linkage decorations. + */ + +#ifdef CURL_STATICLIB +# define CURL_EXTERN +#elif defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__) +# if defined(BUILDING_LIBCURL) +# define CURL_EXTERN __declspec(dllexport) +# else +# define CURL_EXTERN __declspec(dllimport) +# endif +#elif defined(BUILDING_LIBCURL) && defined(CURL_HIDDEN_SYMBOLS) +# define CURL_EXTERN CURL_EXTERN_SYMBOL +#else +# define CURL_EXTERN +#endif + +#ifndef curl_socket_typedef +/* socket typedef */ +#if defined(WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H) +typedef SOCKET curl_socket_t; +#define CURL_SOCKET_BAD INVALID_SOCKET +#else +typedef int curl_socket_t; +#define CURL_SOCKET_BAD -1 +#endif +#define curl_socket_typedef +#endif /* curl_socket_typedef */ + +struct curl_httppost { + struct curl_httppost *next; /* next entry in the list */ + char *name; /* pointer to allocated name */ + long namelength; /* length of name length */ + char *contents; /* pointer to allocated data contents */ + long contentslength; /* length of contents field, see also + CURL_HTTPPOST_LARGE */ + char *buffer; /* pointer to allocated buffer contents */ + long bufferlength; /* length of buffer field */ + char *contenttype; /* Content-Type */ - struct curl_slist* contentheader; /* list of extra headers for this form */ ++ struct curl_slist *contentheader; /* list of extra headers for this form */ + struct curl_httppost *more; /* if one field name has more than one + file, this link should link to following + files */ + long flags; /* as defined below */ + +/* specified content is a file name */ +#define CURL_HTTPPOST_FILENAME (1<<0) +/* specified content is a file name */ +#define CURL_HTTPPOST_READFILE (1<<1) +/* name is only stored pointer do not free in formfree */ +#define CURL_HTTPPOST_PTRNAME (1<<2) +/* contents is only stored pointer do not free in formfree */ +#define CURL_HTTPPOST_PTRCONTENTS (1<<3) +/* upload file from buffer */ +#define CURL_HTTPPOST_BUFFER (1<<4) +/* upload file from pointer contents */ +#define CURL_HTTPPOST_PTRBUFFER (1<<5) +/* upload file contents by using the regular read callback to get the data and + pass the given pointer as custom pointer */ +#define CURL_HTTPPOST_CALLBACK (1<<6) +/* use size in 'contentlen', added in 7.46.0 */ +#define CURL_HTTPPOST_LARGE (1<<7) + + char *showfilename; /* The file name to show. If not set, the + actual file name will be used (if this + is a file part) */ + void *userp; /* custom pointer used for + HTTPPOST_CALLBACK posts */ + curl_off_t contentlen; /* alternative length of contents + field. Used if CURL_HTTPPOST_LARGE is + set. Added in 7.46.0 */ +}; + +/* This is the CURLOPT_PROGRESSFUNCTION callback proto. It is now considered + deprecated but was the only choice up until 7.31.0 */ +typedef int (*curl_progress_callback)(void *clientp, + double dltotal, + double dlnow, + double ultotal, + double ulnow); + +/* This is the CURLOPT_XFERINFOFUNCTION callback proto. It was introduced in + 7.32.0, it avoids floating point and provides more detailed information. */ +typedef int (*curl_xferinfo_callback)(void *clientp, + curl_off_t dltotal, + curl_off_t dlnow, + curl_off_t ultotal, + curl_off_t ulnow); + +#ifndef CURL_MAX_WRITE_SIZE + /* Tests have proven that 20K is a very bad buffer size for uploads on + Windows, while 16K for some odd reason performed a lot better. + We do the ifndef check to allow this value to easier be changed at build + time for those who feel adventurous. The practical minimum is about + 400 bytes since libcurl uses a buffer of this size as a scratch area + (unrelated to network send operations). */ +#define CURL_MAX_WRITE_SIZE 16384 +#endif + +#ifndef CURL_MAX_HTTP_HEADER +/* The only reason to have a max limit for this is to avoid the risk of a bad + server feeding libcurl with a never-ending header that will cause reallocs + infinitely */ +#define CURL_MAX_HTTP_HEADER (100*1024) +#endif + +/* This is a magic return code for the write callback that, when returned, + will signal libcurl to pause receiving on the current transfer. */ +#define CURL_WRITEFUNC_PAUSE 0x10000001 + +typedef size_t (*curl_write_callback)(char *buffer, + size_t size, + size_t nitems, + void *outstream); + + + +/* enumeration of file types */ +typedef enum { + CURLFILETYPE_FILE = 0, + CURLFILETYPE_DIRECTORY, + CURLFILETYPE_SYMLINK, + CURLFILETYPE_DEVICE_BLOCK, + CURLFILETYPE_DEVICE_CHAR, + CURLFILETYPE_NAMEDPIPE, + CURLFILETYPE_SOCKET, + CURLFILETYPE_DOOR, /* is possible only on Sun Solaris now */ + + CURLFILETYPE_UNKNOWN /* should never occur */ +} curlfiletype; + +#define CURLFINFOFLAG_KNOWN_FILENAME (1<<0) +#define CURLFINFOFLAG_KNOWN_FILETYPE (1<<1) +#define CURLFINFOFLAG_KNOWN_TIME (1<<2) +#define CURLFINFOFLAG_KNOWN_PERM (1<<3) +#define CURLFINFOFLAG_KNOWN_UID (1<<4) +#define CURLFINFOFLAG_KNOWN_GID (1<<5) +#define CURLFINFOFLAG_KNOWN_SIZE (1<<6) +#define CURLFINFOFLAG_KNOWN_HLINKCOUNT (1<<7) + +/* Content of this structure depends on information which is known and is + achievable (e.g. by FTP LIST parsing). Please see the url_easy_setopt(3) man + page for callbacks returning this structure -- some fields are mandatory, + some others are optional. The FLAG field has special meaning. */ +struct curl_fileinfo { + char *filename; + curlfiletype filetype; + time_t time; + unsigned int perm; + int uid; + int gid; + curl_off_t size; + long int hardlinks; + + struct { + /* If some of these fields is not NULL, it is a pointer to b_data. */ + char *time; + char *perm; + char *user; + char *group; + char *target; /* pointer to the target filename of a symlink */ + } strings; + + unsigned int flags; + + /* used internally */ - char * b_data; ++ char *b_data; + size_t b_size; + size_t b_used; +}; + +/* return codes for CURLOPT_CHUNK_BGN_FUNCTION */ +#define CURL_CHUNK_BGN_FUNC_OK 0 +#define CURL_CHUNK_BGN_FUNC_FAIL 1 /* tell the lib to end the task */ +#define CURL_CHUNK_BGN_FUNC_SKIP 2 /* skip this chunk over */ + +/* if splitting of data transfer is enabled, this callback is called before + download of an individual chunk started. Note that parameter "remains" works + only for FTP wildcard downloading (for now), otherwise is not used */ +typedef long (*curl_chunk_bgn_callback)(const void *transfer_info, + void *ptr, + int remains); + +/* return codes for CURLOPT_CHUNK_END_FUNCTION */ +#define CURL_CHUNK_END_FUNC_OK 0 +#define CURL_CHUNK_END_FUNC_FAIL 1 /* tell the lib to end the task */ + +/* If splitting of data transfer is enabled this callback is called after + download of an individual chunk finished. + Note! After this callback was set then it have to be called FOR ALL chunks. + Even if downloading of this chunk was skipped in CHUNK_BGN_FUNC. + This is the reason why we don't need "transfer_info" parameter in this + callback and we are not interested in "remains" parameter too. */ +typedef long (*curl_chunk_end_callback)(void *ptr); + +/* return codes for FNMATCHFUNCTION */ +#define CURL_FNMATCHFUNC_MATCH 0 /* string corresponds to the pattern */ +#define CURL_FNMATCHFUNC_NOMATCH 1 /* pattern doesn't match the string */ +#define CURL_FNMATCHFUNC_FAIL 2 /* an error occurred */ + +/* callback type for wildcard downloading pattern matching. If the + string matches the pattern, return CURL_FNMATCHFUNC_MATCH value, etc. */ +typedef int (*curl_fnmatch_callback)(void *ptr, + const char *pattern, + const char *string); + +/* These are the return codes for the seek callbacks */ +#define CURL_SEEKFUNC_OK 0 +#define CURL_SEEKFUNC_FAIL 1 /* fail the entire transfer */ +#define CURL_SEEKFUNC_CANTSEEK 2 /* tell libcurl seeking can't be done, so + libcurl might try other means instead */ +typedef int (*curl_seek_callback)(void *instream, + curl_off_t offset, + int origin); /* 'whence' */ + +/* This is a return code for the read callback that, when returned, will + signal libcurl to immediately abort the current transfer. */ +#define CURL_READFUNC_ABORT 0x10000000 +/* This is a return code for the read callback that, when returned, will + signal libcurl to pause sending data on the current transfer. */ +#define CURL_READFUNC_PAUSE 0x10000001 + +typedef size_t (*curl_read_callback)(char *buffer, + size_t size, + size_t nitems, + void *instream); + +typedef enum { + CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */ + CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */ + CURLSOCKTYPE_LAST /* never use */ +} curlsocktype; + +/* The return code from the sockopt_callback can signal information back + to libcurl: */ +#define CURL_SOCKOPT_OK 0 +#define CURL_SOCKOPT_ERROR 1 /* causes libcurl to abort and return + CURLE_ABORTED_BY_CALLBACK */ +#define CURL_SOCKOPT_ALREADY_CONNECTED 2 + +typedef int (*curl_sockopt_callback)(void *clientp, + curl_socket_t curlfd, + curlsocktype purpose); + +struct curl_sockaddr { + int family; + int socktype; + int protocol; + unsigned int addrlen; /* addrlen was a socklen_t type before 7.18.0 but it + turned really ugly and painful on the systems that + lack this type */ + struct sockaddr addr; +}; + +typedef curl_socket_t +(*curl_opensocket_callback)(void *clientp, + curlsocktype purpose, + struct curl_sockaddr *address); + +typedef int +(*curl_closesocket_callback)(void *clientp, curl_socket_t item); + +typedef enum { + CURLIOE_OK, /* I/O operation successful */ + CURLIOE_UNKNOWNCMD, /* command was unknown to callback */ + CURLIOE_FAILRESTART, /* failed to restart the read */ + CURLIOE_LAST /* never use */ +} curlioerr; + +typedef enum { + CURLIOCMD_NOP, /* no operation */ + CURLIOCMD_RESTARTREAD, /* restart the read stream from start */ + CURLIOCMD_LAST /* never use */ +} curliocmd; + +typedef curlioerr (*curl_ioctl_callback)(CURL *handle, + int cmd, + void *clientp); + +#ifndef CURL_DID_MEMORY_FUNC_TYPEDEFS +/* + * The following typedef's are signatures of malloc, free, realloc, strdup and + * calloc respectively. Function pointers of these types can be passed to the + * curl_global_init_mem() function to set user defined memory management + * callback routines. + */ +typedef void *(*curl_malloc_callback)(size_t size); +typedef void (*curl_free_callback)(void *ptr); +typedef void *(*curl_realloc_callback)(void *ptr, size_t size); +typedef char *(*curl_strdup_callback)(const char *str); +typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size); + +#define CURL_DID_MEMORY_FUNC_TYPEDEFS +#endif + +/* the kind of data that is passed to information_callback*/ +typedef enum { + CURLINFO_TEXT = 0, + CURLINFO_HEADER_IN, /* 1 */ + CURLINFO_HEADER_OUT, /* 2 */ + CURLINFO_DATA_IN, /* 3 */ + CURLINFO_DATA_OUT, /* 4 */ + CURLINFO_SSL_DATA_IN, /* 5 */ + CURLINFO_SSL_DATA_OUT, /* 6 */ + CURLINFO_END +} curl_infotype; + +typedef int (*curl_debug_callback) + (CURL *handle, /* the handle/transfer this concerns */ + curl_infotype type, /* what kind of data */ + char *data, /* points to the data */ + size_t size, /* size of the data pointed to */ + void *userptr); /* whatever the user please */ + +/* All possible error codes from all sorts of curl functions. Future versions + may return other values, stay prepared. + + Always add new return codes last. Never *EVER* remove any. The return + codes must remain the same! + */ + +typedef enum { + CURLE_OK = 0, + CURLE_UNSUPPORTED_PROTOCOL, /* 1 */ + CURLE_FAILED_INIT, /* 2 */ + CURLE_URL_MALFORMAT, /* 3 */ + CURLE_NOT_BUILT_IN, /* 4 - [was obsoleted in August 2007 for + 7.17.0, reused in April 2011 for 7.21.5] */ + CURLE_COULDNT_RESOLVE_PROXY, /* 5 */ + CURLE_COULDNT_RESOLVE_HOST, /* 6 */ + CURLE_COULDNT_CONNECT, /* 7 */ + CURLE_WEIRD_SERVER_REPLY, /* 8 */ + CURLE_REMOTE_ACCESS_DENIED, /* 9 a service was denied by the server + due to lack of access - when login fails + this is not returned. */ + CURLE_FTP_ACCEPT_FAILED, /* 10 - [was obsoleted in April 2006 for + 7.15.4, reused in Dec 2011 for 7.24.0]*/ + CURLE_FTP_WEIRD_PASS_REPLY, /* 11 */ + CURLE_FTP_ACCEPT_TIMEOUT, /* 12 - timeout occurred accepting server + [was obsoleted in August 2007 for 7.17.0, + reused in Dec 2011 for 7.24.0]*/ + CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */ + CURLE_FTP_WEIRD_227_FORMAT, /* 14 */ + CURLE_FTP_CANT_GET_HOST, /* 15 */ + CURLE_HTTP2, /* 16 - A problem in the http2 framing layer. + [was obsoleted in August 2007 for 7.17.0, + reused in July 2014 for 7.38.0] */ + CURLE_FTP_COULDNT_SET_TYPE, /* 17 */ + CURLE_PARTIAL_FILE, /* 18 */ + CURLE_FTP_COULDNT_RETR_FILE, /* 19 */ + CURLE_OBSOLETE20, /* 20 - NOT USED */ + CURLE_QUOTE_ERROR, /* 21 - quote command failure */ + CURLE_HTTP_RETURNED_ERROR, /* 22 */ + CURLE_WRITE_ERROR, /* 23 */ + CURLE_OBSOLETE24, /* 24 - NOT USED */ + CURLE_UPLOAD_FAILED, /* 25 - failed upload "command" */ + CURLE_READ_ERROR, /* 26 - couldn't open/read from file */ + CURLE_OUT_OF_MEMORY, /* 27 */ + /* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error + instead of a memory allocation error if CURL_DOES_CONVERSIONS + is defined + */ + CURLE_OPERATION_TIMEDOUT, /* 28 - the timeout time was reached */ + CURLE_OBSOLETE29, /* 29 - NOT USED */ + CURLE_FTP_PORT_FAILED, /* 30 - FTP PORT operation failed */ + CURLE_FTP_COULDNT_USE_REST, /* 31 - the REST command failed */ + CURLE_OBSOLETE32, /* 32 - NOT USED */ + CURLE_RANGE_ERROR, /* 33 - RANGE "command" didn't work */ + CURLE_HTTP_POST_ERROR, /* 34 */ + CURLE_SSL_CONNECT_ERROR, /* 35 - wrong when connecting with SSL */ + CURLE_BAD_DOWNLOAD_RESUME, /* 36 - couldn't resume download */ + CURLE_FILE_COULDNT_READ_FILE, /* 37 */ + CURLE_LDAP_CANNOT_BIND, /* 38 */ + CURLE_LDAP_SEARCH_FAILED, /* 39 */ + CURLE_OBSOLETE40, /* 40 - NOT USED */ + CURLE_FUNCTION_NOT_FOUND, /* 41 */ + CURLE_ABORTED_BY_CALLBACK, /* 42 */ + CURLE_BAD_FUNCTION_ARGUMENT, /* 43 */ + CURLE_OBSOLETE44, /* 44 - NOT USED */ + CURLE_INTERFACE_FAILED, /* 45 - CURLOPT_INTERFACE failed */ + CURLE_OBSOLETE46, /* 46 - NOT USED */ + CURLE_TOO_MANY_REDIRECTS, /* 47 - catch endless re-direct loops */ + CURLE_UNKNOWN_OPTION, /* 48 - User specified an unknown option */ + CURLE_TELNET_OPTION_SYNTAX, /* 49 - Malformed telnet option */ + CURLE_OBSOLETE50, /* 50 - NOT USED */ + CURLE_PEER_FAILED_VERIFICATION, /* 51 - peer's certificate or fingerprint + wasn't verified fine */ + CURLE_GOT_NOTHING, /* 52 - when this is a specific error */ + CURLE_SSL_ENGINE_NOTFOUND, /* 53 - SSL crypto engine not found */ + CURLE_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as + default */ + CURLE_SEND_ERROR, /* 55 - failed sending network data */ + CURLE_RECV_ERROR, /* 56 - failure in receiving network data */ + CURLE_OBSOLETE57, /* 57 - NOT IN USE */ + CURLE_SSL_CERTPROBLEM, /* 58 - problem with the local certificate */ + CURLE_SSL_CIPHER, /* 59 - couldn't use specified cipher */ + CURLE_SSL_CACERT, /* 60 - problem with the CA cert (path?) */ + CURLE_BAD_CONTENT_ENCODING, /* 61 - Unrecognized/bad encoding */ + CURLE_LDAP_INVALID_URL, /* 62 - Invalid LDAP URL */ + CURLE_FILESIZE_EXCEEDED, /* 63 - Maximum file size exceeded */ + CURLE_USE_SSL_FAILED, /* 64 - Requested FTP SSL level failed */ + CURLE_SEND_FAIL_REWIND, /* 65 - Sending the data requires a rewind + that failed */ + CURLE_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */ + CURLE_LOGIN_DENIED, /* 67 - user, password or similar was not + accepted and we failed to login */ + CURLE_TFTP_NOTFOUND, /* 68 - file not found on server */ + CURLE_TFTP_PERM, /* 69 - permission problem on server */ + CURLE_REMOTE_DISK_FULL, /* 70 - out of disk space on server */ + CURLE_TFTP_ILLEGAL, /* 71 - Illegal TFTP operation */ + CURLE_TFTP_UNKNOWNID, /* 72 - Unknown transfer ID */ + CURLE_REMOTE_FILE_EXISTS, /* 73 - File already exists */ + CURLE_TFTP_NOSUCHUSER, /* 74 - No such user */ + CURLE_CONV_FAILED, /* 75 - conversion failed */ + CURLE_CONV_REQD, /* 76 - caller must register conversion + callbacks using curl_easy_setopt options + CURLOPT_CONV_FROM_NETWORK_FUNCTION, + CURLOPT_CONV_TO_NETWORK_FUNCTION, and + CURLOPT_CONV_FROM_UTF8_FUNCTION */ + CURLE_SSL_CACERT_BADFILE, /* 77 - could not load CACERT file, missing + or wrong format */ + CURLE_REMOTE_FILE_NOT_FOUND, /* 78 - remote file not found */ + CURLE_SSH, /* 79 - error from the SSH layer, somewhat + generic so the error message will be of + interest when this has happened */ + + CURLE_SSL_SHUTDOWN_FAILED, /* 80 - Failed to shut down the SSL + connection */ + CURLE_AGAIN, /* 81 - socket is not ready for send/recv, + wait till it's ready and try again (Added + in 7.18.2) */ + CURLE_SSL_CRL_BADFILE, /* 82 - could not load CRL file, missing or + wrong format (Added in 7.19.0) */ + CURLE_SSL_ISSUER_ERROR, /* 83 - Issuer check failed. (Added in + 7.19.0) */ + CURLE_FTP_PRET_FAILED, /* 84 - a PRET command failed */ + CURLE_RTSP_CSEQ_ERROR, /* 85 - mismatch of RTSP CSeq numbers */ + CURLE_RTSP_SESSION_ERROR, /* 86 - mismatch of RTSP Session Ids */ + CURLE_FTP_BAD_FILE_LIST, /* 87 - unable to parse FTP file list */ + CURLE_CHUNK_FAILED, /* 88 - chunk callback reported error */ + CURLE_NO_CONNECTION_AVAILABLE, /* 89 - No connection available, the + session will be queued */ + CURLE_SSL_PINNEDPUBKEYNOTMATCH, /* 90 - specified pinned public key did not + match */ + CURLE_SSL_INVALIDCERTSTATUS, /* 91 - invalid certificate status */ + CURLE_HTTP2_STREAM, /* 92 - stream error in HTTP/2 framing layer + */ + CURL_LAST /* never use! */ +} CURLcode; + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Previously obsolete error code re-used in 7.38.0 */ +#define CURLE_OBSOLETE16 CURLE_HTTP2 + +/* Previously obsolete error codes re-used in 7.24.0 */ +#define CURLE_OBSOLETE10 CURLE_FTP_ACCEPT_FAILED +#define CURLE_OBSOLETE12 CURLE_FTP_ACCEPT_TIMEOUT + +/* compatibility with older names */ +#define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING +#define CURLE_FTP_WEIRD_SERVER_REPLY CURLE_WEIRD_SERVER_REPLY + +/* The following were added in 7.21.5, April 2011 */ +#define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION + +/* The following were added in 7.17.1 */ +/* These are scheduled to disappear by 2009 */ +#define CURLE_SSL_PEER_CERTIFICATE CURLE_PEER_FAILED_VERIFICATION + +/* The following were added in 7.17.0 */ +/* These are scheduled to disappear by 2009 */ +#define CURLE_OBSOLETE CURLE_OBSOLETE50 /* no one should be using this! */ +#define CURLE_BAD_PASSWORD_ENTERED CURLE_OBSOLETE46 +#define CURLE_BAD_CALLING_ORDER CURLE_OBSOLETE44 +#define CURLE_FTP_USER_PASSWORD_INCORRECT CURLE_OBSOLETE10 +#define CURLE_FTP_CANT_RECONNECT CURLE_OBSOLETE16 +#define CURLE_FTP_COULDNT_GET_SIZE CURLE_OBSOLETE32 +#define CURLE_FTP_COULDNT_SET_ASCII CURLE_OBSOLETE29 +#define CURLE_FTP_WEIRD_USER_REPLY CURLE_OBSOLETE12 +#define CURLE_FTP_WRITE_ERROR CURLE_OBSOLETE20 +#define CURLE_LIBRARY_NOT_FOUND CURLE_OBSOLETE40 +#define CURLE_MALFORMAT_USER CURLE_OBSOLETE24 +#define CURLE_SHARE_IN_USE CURLE_OBSOLETE57 +#define CURLE_URL_MALFORMAT_USER CURLE_NOT_BUILT_IN + +#define CURLE_FTP_ACCESS_DENIED CURLE_REMOTE_ACCESS_DENIED +#define CURLE_FTP_COULDNT_SET_BINARY CURLE_FTP_COULDNT_SET_TYPE +#define CURLE_FTP_QUOTE_ERROR CURLE_QUOTE_ERROR +#define CURLE_TFTP_DISKFULL CURLE_REMOTE_DISK_FULL +#define CURLE_TFTP_EXISTS CURLE_REMOTE_FILE_EXISTS +#define CURLE_HTTP_RANGE_ERROR CURLE_RANGE_ERROR +#define CURLE_FTP_SSL_FAILED CURLE_USE_SSL_FAILED + +/* The following were added earlier */ + +#define CURLE_OPERATION_TIMEOUTED CURLE_OPERATION_TIMEDOUT + +#define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR +#define CURLE_HTTP_PORT_FAILED CURLE_INTERFACE_FAILED +#define CURLE_FTP_COULDNT_STOR_FILE CURLE_UPLOAD_FAILED + +#define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE +#define CURLE_FTP_BAD_DOWNLOAD_RESUME CURLE_BAD_DOWNLOAD_RESUME + +/* This was the error code 50 in 7.7.3 and a few earlier versions, this + is no longer used by libcurl but is instead #defined here only to not + make programs break */ +#define CURLE_ALREADY_COMPLETE 99999 + +/* Provide defines for really old option names */ +#define CURLOPT_FILE CURLOPT_WRITEDATA /* name changed in 7.9.7 */ +#define CURLOPT_INFILE CURLOPT_READDATA /* name changed in 7.9.7 */ +#define CURLOPT_WRITEHEADER CURLOPT_HEADERDATA + +/* Since long deprecated options with no code in the lib that does anything + with them. */ +#define CURLOPT_WRITEINFO CURLOPT_OBSOLETE40 +#define CURLOPT_CLOSEPOLICY CURLOPT_OBSOLETE72 + +#endif /*!CURL_NO_OLDIES*/ + +/* This prototype applies to all conversion callbacks */ +typedef CURLcode (*curl_conv_callback)(char *buffer, size_t length); + +typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl, /* easy handle */ + void *ssl_ctx, /* actually an + OpenSSL SSL_CTX */ + void *userptr); + +typedef enum { + CURLPROXY_HTTP = 0, /* added in 7.10, new in 7.19.4 default is to use + CONNECT HTTP/1.1 */ + CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT + HTTP/1.0 */ ++ CURLPROXY_HTTPS = 2, /* added in 7.52.0 */ + CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already + in 7.10 */ + CURLPROXY_SOCKS5 = 5, /* added in 7.10 */ + CURLPROXY_SOCKS4A = 6, /* added in 7.18.0 */ + CURLPROXY_SOCKS5_HOSTNAME = 7 /* Use the SOCKS5 protocol but pass along the + host name rather than the IP address. added + in 7.18.0 */ +} curl_proxytype; /* this enum was added in 7.10 */ + +/* + * Bitmasks for CURLOPT_HTTPAUTH and CURLOPT_PROXYAUTH options: + * + * CURLAUTH_NONE - No HTTP authentication + * CURLAUTH_BASIC - HTTP Basic authentication (default) + * CURLAUTH_DIGEST - HTTP Digest authentication + * CURLAUTH_NEGOTIATE - HTTP Negotiate (SPNEGO) authentication + * CURLAUTH_GSSNEGOTIATE - Alias for CURLAUTH_NEGOTIATE (deprecated) + * CURLAUTH_NTLM - HTTP NTLM authentication + * CURLAUTH_DIGEST_IE - HTTP Digest authentication with IE flavour + * CURLAUTH_NTLM_WB - HTTP NTLM authentication delegated to winbind helper + * CURLAUTH_ONLY - Use together with a single other type to force no + * authentication or just that single type + * CURLAUTH_ANY - All fine types set + * CURLAUTH_ANYSAFE - All fine types except Basic + */ + +#define CURLAUTH_NONE ((unsigned long)0) +#define CURLAUTH_BASIC (((unsigned long)1)<<0) +#define CURLAUTH_DIGEST (((unsigned long)1)<<1) +#define CURLAUTH_NEGOTIATE (((unsigned long)1)<<2) +/* Deprecated since the advent of CURLAUTH_NEGOTIATE */ +#define CURLAUTH_GSSNEGOTIATE CURLAUTH_NEGOTIATE +#define CURLAUTH_NTLM (((unsigned long)1)<<3) +#define CURLAUTH_DIGEST_IE (((unsigned long)1)<<4) +#define CURLAUTH_NTLM_WB (((unsigned long)1)<<5) +#define CURLAUTH_ONLY (((unsigned long)1)<<31) +#define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE) +#define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE)) + +#define CURLSSH_AUTH_ANY ~0 /* all types supported by the server */ +#define CURLSSH_AUTH_NONE 0 /* none allowed, silly but complete */ +#define CURLSSH_AUTH_PUBLICKEY (1<<0) /* public/private key files */ +#define CURLSSH_AUTH_PASSWORD (1<<1) /* password */ +#define CURLSSH_AUTH_HOST (1<<2) /* host key files */ +#define CURLSSH_AUTH_KEYBOARD (1<<3) /* keyboard interactive */ +#define CURLSSH_AUTH_AGENT (1<<4) /* agent (ssh-agent, pageant...) */ +#define CURLSSH_AUTH_DEFAULT CURLSSH_AUTH_ANY + +#define CURLGSSAPI_DELEGATION_NONE 0 /* no delegation (default) */ +#define CURLGSSAPI_DELEGATION_POLICY_FLAG (1<<0) /* if permitted by policy */ +#define CURLGSSAPI_DELEGATION_FLAG (1<<1) /* delegate always */ + +#define CURL_ERROR_SIZE 256 + +enum curl_khtype { + CURLKHTYPE_UNKNOWN, + CURLKHTYPE_RSA1, + CURLKHTYPE_RSA, + CURLKHTYPE_DSS +}; + +struct curl_khkey { + const char *key; /* points to a zero-terminated string encoded with base64 + if len is zero, otherwise to the "raw" data */ + size_t len; + enum curl_khtype keytype; +}; + +/* this is the set of return values expected from the curl_sshkeycallback + callback */ +enum curl_khstat { + CURLKHSTAT_FINE_ADD_TO_FILE, + CURLKHSTAT_FINE, + CURLKHSTAT_REJECT, /* reject the connection, return an error */ + CURLKHSTAT_DEFER, /* do not accept it, but we can't answer right now so + this causes a CURLE_DEFER error but otherwise the + connection will be left intact etc */ + CURLKHSTAT_LAST /* not for use, only a marker for last-in-list */ +}; + +/* this is the set of status codes pass in to the callback */ +enum curl_khmatch { + CURLKHMATCH_OK, /* match */ + CURLKHMATCH_MISMATCH, /* host found, key mismatch! */ + CURLKHMATCH_MISSING, /* no matching host/key found */ + CURLKHMATCH_LAST /* not for use, only a marker for last-in-list */ +}; + +typedef int + (*curl_sshkeycallback) (CURL *easy, /* easy handle */ + const struct curl_khkey *knownkey, /* known */ + const struct curl_khkey *foundkey, /* found */ + enum curl_khmatch, /* libcurl's view on the keys */ + void *clientp); /* custom pointer passed from app */ + +/* parameter for the CURLOPT_USE_SSL option */ +typedef enum { + CURLUSESSL_NONE, /* do not attempt to use SSL */ + CURLUSESSL_TRY, /* try using SSL, proceed anyway otherwise */ + CURLUSESSL_CONTROL, /* SSL for the control connection or fail */ + CURLUSESSL_ALL, /* SSL for all communication or fail */ + CURLUSESSL_LAST /* not an option, never use */ +} curl_usessl; + +/* Definition of bits for the CURLOPT_SSL_OPTIONS argument: */ + +/* - ALLOW_BEAST tells libcurl to allow the BEAST SSL vulnerability in the + name of improving interoperability with older servers. Some SSL libraries + have introduced work-arounds for this flaw but those work-arounds sometimes + make the SSL communication fail. To regain functionality with those broken + servers, a user can this way allow the vulnerability back. */ +#define CURLSSLOPT_ALLOW_BEAST (1<<0) + +/* - NO_REVOKE tells libcurl to disable certificate revocation checks for those + SSL backends where such behavior is present. */ +#define CURLSSLOPT_NO_REVOKE (1<<1) + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Backwards compatibility with older names */ +/* These are scheduled to disappear by 2009 */ + +#define CURLFTPSSL_NONE CURLUSESSL_NONE +#define CURLFTPSSL_TRY CURLUSESSL_TRY +#define CURLFTPSSL_CONTROL CURLUSESSL_CONTROL +#define CURLFTPSSL_ALL CURLUSESSL_ALL +#define CURLFTPSSL_LAST CURLUSESSL_LAST +#define curl_ftpssl curl_usessl +#endif /*!CURL_NO_OLDIES*/ + +/* parameter for the CURLOPT_FTP_SSL_CCC option */ +typedef enum { + CURLFTPSSL_CCC_NONE, /* do not send CCC */ + CURLFTPSSL_CCC_PASSIVE, /* Let the server initiate the shutdown */ + CURLFTPSSL_CCC_ACTIVE, /* Initiate the shutdown */ + CURLFTPSSL_CCC_LAST /* not an option, never use */ +} curl_ftpccc; + +/* parameter for the CURLOPT_FTPSSLAUTH option */ +typedef enum { + CURLFTPAUTH_DEFAULT, /* let libcurl decide */ + CURLFTPAUTH_SSL, /* use "AUTH SSL" */ + CURLFTPAUTH_TLS, /* use "AUTH TLS" */ + CURLFTPAUTH_LAST /* not an option, never use */ +} curl_ftpauth; + +/* parameter for the CURLOPT_FTP_CREATE_MISSING_DIRS option */ +typedef enum { + CURLFTP_CREATE_DIR_NONE, /* do NOT create missing dirs! */ + CURLFTP_CREATE_DIR, /* (FTP/SFTP) if CWD fails, try MKD and then CWD + again if MKD succeeded, for SFTP this does + similar magic */ + CURLFTP_CREATE_DIR_RETRY, /* (FTP only) if CWD fails, try MKD and then CWD + again even if MKD failed! */ + CURLFTP_CREATE_DIR_LAST /* not an option, never use */ +} curl_ftpcreatedir; + +/* parameter for the CURLOPT_FTP_FILEMETHOD option */ +typedef enum { + CURLFTPMETHOD_DEFAULT, /* let libcurl pick */ + CURLFTPMETHOD_MULTICWD, /* single CWD operation for each path part */ + CURLFTPMETHOD_NOCWD, /* no CWD at all */ + CURLFTPMETHOD_SINGLECWD, /* one CWD to full dir, then work on file */ + CURLFTPMETHOD_LAST /* not an option, never use */ +} curl_ftpmethod; + +/* bitmask defines for CURLOPT_HEADEROPT */ +#define CURLHEADER_UNIFIED 0 +#define CURLHEADER_SEPARATE (1<<0) + +/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */ +#define CURLPROTO_HTTP (1<<0) +#define CURLPROTO_HTTPS (1<<1) +#define CURLPROTO_FTP (1<<2) +#define CURLPROTO_FTPS (1<<3) +#define CURLPROTO_SCP (1<<4) +#define CURLPROTO_SFTP (1<<5) +#define CURLPROTO_TELNET (1<<6) +#define CURLPROTO_LDAP (1<<7) +#define CURLPROTO_LDAPS (1<<8) +#define CURLPROTO_DICT (1<<9) +#define CURLPROTO_FILE (1<<10) +#define CURLPROTO_TFTP (1<<11) +#define CURLPROTO_IMAP (1<<12) +#define CURLPROTO_IMAPS (1<<13) +#define CURLPROTO_POP3 (1<<14) +#define CURLPROTO_POP3S (1<<15) +#define CURLPROTO_SMTP (1<<16) +#define CURLPROTO_SMTPS (1<<17) +#define CURLPROTO_RTSP (1<<18) +#define CURLPROTO_RTMP (1<<19) +#define CURLPROTO_RTMPT (1<<20) +#define CURLPROTO_RTMPE (1<<21) +#define CURLPROTO_RTMPTE (1<<22) +#define CURLPROTO_RTMPS (1<<23) +#define CURLPROTO_RTMPTS (1<<24) +#define CURLPROTO_GOPHER (1<<25) +#define CURLPROTO_SMB (1<<26) +#define CURLPROTO_SMBS (1<<27) +#define CURLPROTO_ALL (~0) /* enable everything */ + +/* long may be 32 or 64 bits, but we should never depend on anything else + but 32 */ +#define CURLOPTTYPE_LONG 0 +#define CURLOPTTYPE_OBJECTPOINT 10000 +#define CURLOPTTYPE_STRINGPOINT 10000 +#define CURLOPTTYPE_FUNCTIONPOINT 20000 +#define CURLOPTTYPE_OFF_T 30000 + +/* *STRINGPOINT is an alias for OBJECTPOINT to allow tools to extract the + string options from the header file */ + +/* name is uppercase CURLOPT_, + type is one of the defined CURLOPTTYPE_ + number is unique identifier */ +#ifdef CINIT +#undef CINIT +#endif + +#ifdef CURL_ISOCPP +#define CINIT(na,t,nu) CURLOPT_ ## na = CURLOPTTYPE_ ## t + nu +#else +/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */ +#define LONG CURLOPTTYPE_LONG +#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT +#define STRINGPOINT CURLOPTTYPE_OBJECTPOINT +#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT +#define OFF_T CURLOPTTYPE_OFF_T +#define CINIT(name,type,number) CURLOPT_/**/name = type + number +#endif + +/* + * This macro-mania below setups the CURLOPT_[what] enum, to be used with + * curl_easy_setopt(). The first argument in the CINIT() macro is the [what] + * word. + */ + +typedef enum { + /* This is the FILE * or void * the regular output should be written to. */ + CINIT(WRITEDATA, OBJECTPOINT, 1), + + /* The full URL to get/put */ + CINIT(URL, STRINGPOINT, 2), + + /* Port number to connect to, if other than default. */ + CINIT(PORT, LONG, 3), + + /* Name of proxy to use. */ + CINIT(PROXY, STRINGPOINT, 4), + + /* "user:password;options" to use when fetching. */ + CINIT(USERPWD, STRINGPOINT, 5), + + /* "user:password" to use with proxy. */ + CINIT(PROXYUSERPWD, STRINGPOINT, 6), + + /* Range to get, specified as an ASCII string. */ + CINIT(RANGE, STRINGPOINT, 7), + + /* not used */ + + /* Specified file stream to upload from (use as input): */ + CINIT(READDATA, OBJECTPOINT, 9), + + /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE + * bytes big. If this is not used, error messages go to stderr instead: */ + CINIT(ERRORBUFFER, OBJECTPOINT, 10), + + /* Function that will be called to store the output (instead of fwrite). The + * parameters will use fwrite() syntax, make sure to follow them. */ + CINIT(WRITEFUNCTION, FUNCTIONPOINT, 11), + + /* Function that will be called to read the input (instead of fread). The + * parameters will use fread() syntax, make sure to follow them. */ + CINIT(READFUNCTION, FUNCTIONPOINT, 12), + + /* Time-out the read operation after this amount of seconds */ + CINIT(TIMEOUT, LONG, 13), + + /* If the CURLOPT_INFILE is used, this can be used to inform libcurl about + * how large the file being sent really is. That allows better error + * checking and better verifies that the upload was successful. -1 means + * unknown size. + * + * For large file support, there is also a _LARGE version of the key + * which takes an off_t type, allowing platforms with larger off_t + * sizes to handle larger files. See below for INFILESIZE_LARGE. + */ + CINIT(INFILESIZE, LONG, 14), + + /* POST static input fields. */ + CINIT(POSTFIELDS, OBJECTPOINT, 15), + + /* Set the referrer page (needed by some CGIs) */ + CINIT(REFERER, STRINGPOINT, 16), + + /* Set the FTP PORT string (interface name, named or numerical IP address) + Use i.e '-' to use default address. */ + CINIT(FTPPORT, STRINGPOINT, 17), + + /* Set the User-Agent string (examined by some CGIs) */ + CINIT(USERAGENT, STRINGPOINT, 18), + + /* If the download receives less than "low speed limit" bytes/second + * during "low speed time" seconds, the operations is aborted. + * You could i.e if you have a pretty high speed connection, abort if + * it is less than 2000 bytes/sec during 20 seconds. + */ + + /* Set the "low speed limit" */ + CINIT(LOW_SPEED_LIMIT, LONG, 19), + + /* Set the "low speed time" */ + CINIT(LOW_SPEED_TIME, LONG, 20), + + /* Set the continuation offset. + * + * Note there is also a _LARGE version of this key which uses + * off_t types, allowing for large file offsets on platforms which + * use larger-than-32-bit off_t's. Look below for RESUME_FROM_LARGE. + */ + CINIT(RESUME_FROM, LONG, 21), + + /* Set cookie in request: */ + CINIT(COOKIE, STRINGPOINT, 22), + + /* This points to a linked list of headers, struct curl_slist kind. This + list is also used for RTSP (in spite of its name) */ + CINIT(HTTPHEADER, OBJECTPOINT, 23), + + /* This points to a linked list of post entries, struct curl_httppost */ + CINIT(HTTPPOST, OBJECTPOINT, 24), + + /* name of the file keeping your private SSL-certificate */ + CINIT(SSLCERT, STRINGPOINT, 25), + + /* password for the SSL or SSH private key */ + CINIT(KEYPASSWD, STRINGPOINT, 26), + + /* send TYPE parameter? */ + CINIT(CRLF, LONG, 27), + + /* send linked-list of QUOTE commands */ + CINIT(QUOTE, OBJECTPOINT, 28), + + /* send FILE * or void * to store headers to, if you use a callback it + is simply passed to the callback unmodified */ + CINIT(HEADERDATA, OBJECTPOINT, 29), + + /* point to a file to read the initial cookies from, also enables + "cookie awareness" */ + CINIT(COOKIEFILE, STRINGPOINT, 31), + + /* What version to specifically try to use. + See CURL_SSLVERSION defines below. */ + CINIT(SSLVERSION, LONG, 32), + + /* What kind of HTTP time condition to use, see defines */ + CINIT(TIMECONDITION, LONG, 33), + + /* Time to use with the above condition. Specified in number of seconds + since 1 Jan 1970 */ + CINIT(TIMEVALUE, LONG, 34), + + /* 35 = OBSOLETE */ + + /* Custom request, for customizing the get command like + HTTP: DELETE, TRACE and others + FTP: to use a different list command + */ + CINIT(CUSTOMREQUEST, STRINGPOINT, 36), + + /* FILE handle to use instead of stderr */ + CINIT(STDERR, OBJECTPOINT, 37), + + /* 38 is not used */ + + /* send linked-list of post-transfer QUOTE commands */ + CINIT(POSTQUOTE, OBJECTPOINT, 39), + + CINIT(OBSOLETE40, OBJECTPOINT, 40), /* OBSOLETE, do not use! */ + + CINIT(VERBOSE, LONG, 41), /* talk a lot */ + CINIT(HEADER, LONG, 42), /* throw the header out too */ + CINIT(NOPROGRESS, LONG, 43), /* shut off the progress meter */ + CINIT(NOBODY, LONG, 44), /* use HEAD to get http document */ + CINIT(FAILONERROR, LONG, 45), /* no output on http error codes >= 400 */ + CINIT(UPLOAD, LONG, 46), /* this is an upload */ + CINIT(POST, LONG, 47), /* HTTP POST method */ + CINIT(DIRLISTONLY, LONG, 48), /* bare names when listing directories */ + + CINIT(APPEND, LONG, 50), /* Append instead of overwrite on upload! */ + + /* Specify whether to read the user+password from the .netrc or the URL. + * This must be one of the CURL_NETRC_* enums below. */ + CINIT(NETRC, LONG, 51), + + CINIT(FOLLOWLOCATION, LONG, 52), /* use Location: Luke! */ + + CINIT(TRANSFERTEXT, LONG, 53), /* transfer data in text/ASCII format */ + CINIT(PUT, LONG, 54), /* HTTP PUT */ + + /* 55 = OBSOLETE */ + + /* DEPRECATED + * Function that will be called instead of the internal progress display + * function. This function should be defined as the curl_progress_callback + * prototype defines. */ + CINIT(PROGRESSFUNCTION, FUNCTIONPOINT, 56), + + /* Data passed to the CURLOPT_PROGRESSFUNCTION and CURLOPT_XFERINFOFUNCTION + callbacks */ + CINIT(PROGRESSDATA, OBJECTPOINT, 57), +#define CURLOPT_XFERINFODATA CURLOPT_PROGRESSDATA + + /* We want the referrer field set automatically when following locations */ + CINIT(AUTOREFERER, LONG, 58), + + /* Port of the proxy, can be set in the proxy string as well with: + "[host]:[port]" */ + CINIT(PROXYPORT, LONG, 59), + + /* size of the POST input data, if strlen() is not good to use */ + CINIT(POSTFIELDSIZE, LONG, 60), + + /* tunnel non-http operations through a HTTP proxy */ + CINIT(HTTPPROXYTUNNEL, LONG, 61), + + /* Set the interface string to use as outgoing network interface */ + CINIT(INTERFACE, STRINGPOINT, 62), + + /* Set the krb4/5 security level, this also enables krb4/5 awareness. This + * is a string, 'clear', 'safe', 'confidential' or 'private'. If the string + * is set but doesn't match one of these, 'private' will be used. */ + CINIT(KRBLEVEL, STRINGPOINT, 63), + + /* Set if we should verify the peer in ssl handshake, set 1 to verify. */ + CINIT(SSL_VERIFYPEER, LONG, 64), + + /* The CApath or CAfile used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CINIT(CAINFO, STRINGPOINT, 65), + + /* 66 = OBSOLETE */ + /* 67 = OBSOLETE */ + + /* Maximum number of http redirects to follow */ + CINIT(MAXREDIRS, LONG, 68), + + /* Pass a long set to 1 to get the date of the requested document (if + possible)! Pass a zero to shut it off. */ + CINIT(FILETIME, LONG, 69), + + /* This points to a linked list of telnet options */ + CINIT(TELNETOPTIONS, OBJECTPOINT, 70), + + /* Max amount of cached alive connections */ + CINIT(MAXCONNECTS, LONG, 71), + + CINIT(OBSOLETE72, LONG, 72), /* OBSOLETE, do not use! */ + + /* 73 = OBSOLETE */ + + /* Set to explicitly use a new connection for the upcoming transfer. + Do not use this unless you're absolutely sure of this, as it makes the + operation slower and is less friendly for the network. */ + CINIT(FRESH_CONNECT, LONG, 74), + + /* Set to explicitly forbid the upcoming transfer's connection to be re-used + when done. Do not use this unless you're absolutely sure of this, as it + makes the operation slower and is less friendly for the network. */ + CINIT(FORBID_REUSE, LONG, 75), + + /* Set to a file name that contains random data for libcurl to use to + seed the random engine when doing SSL connects. */ + CINIT(RANDOM_FILE, STRINGPOINT, 76), + + /* Set to the Entropy Gathering Daemon socket pathname */ + CINIT(EGDSOCKET, STRINGPOINT, 77), + + /* Time-out connect operations after this amount of seconds, if connects are + OK within this time, then fine... This only aborts the connect phase. */ + CINIT(CONNECTTIMEOUT, LONG, 78), + + /* Function that will be called to store headers (instead of fwrite). The + * parameters will use fwrite() syntax, make sure to follow them. */ + CINIT(HEADERFUNCTION, FUNCTIONPOINT, 79), + + /* Set this to force the HTTP request to get back to GET. Only really usable + if POST, PUT or a custom request have been used first. + */ + CINIT(HTTPGET, LONG, 80), + + /* Set if we should verify the Common name from the peer certificate in ssl + * handshake, set 1 to check existence, 2 to ensure that it matches the + * provided hostname. */ + CINIT(SSL_VERIFYHOST, LONG, 81), + + /* Specify which file name to write all known cookies in after completed + operation. Set file name to "-" (dash) to make it go to stdout. */ + CINIT(COOKIEJAR, STRINGPOINT, 82), + + /* Specify which SSL ciphers to use */ + CINIT(SSL_CIPHER_LIST, STRINGPOINT, 83), + + /* Specify which HTTP version to use! This must be set to one of the + CURL_HTTP_VERSION* enums set below. */ + CINIT(HTTP_VERSION, LONG, 84), + + /* Specifically switch on or off the FTP engine's use of the EPSV command. By + default, that one will always be attempted before the more traditional + PASV command. */ + CINIT(FTP_USE_EPSV, LONG, 85), + + /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */ + CINIT(SSLCERTTYPE, STRINGPOINT, 86), + + /* name of the file keeping your private SSL-key */ + CINIT(SSLKEY, STRINGPOINT, 87), + + /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */ + CINIT(SSLKEYTYPE, STRINGPOINT, 88), + + /* crypto engine for the SSL-sub system */ + CINIT(SSLENGINE, STRINGPOINT, 89), + + /* set the crypto engine for the SSL-sub system as default + the param has no meaning... + */ + CINIT(SSLENGINE_DEFAULT, LONG, 90), + + /* Non-zero value means to use the global dns cache */ + CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91), /* DEPRECATED, do not use! */ + + /* DNS cache timeout */ + CINIT(DNS_CACHE_TIMEOUT, LONG, 92), + + /* send linked-list of pre-transfer QUOTE commands */ + CINIT(PREQUOTE, OBJECTPOINT, 93), + + /* set the debug function */ + CINIT(DEBUGFUNCTION, FUNCTIONPOINT, 94), + + /* set the data for the debug function */ + CINIT(DEBUGDATA, OBJECTPOINT, 95), + + /* mark this as start of a cookie session */ + CINIT(COOKIESESSION, LONG, 96), + + /* The CApath directory used to validate the peer certificate + this option is used only if SSL_VERIFYPEER is true */ + CINIT(CAPATH, STRINGPOINT, 97), + + /* Instruct libcurl to use a smaller receive buffer */ + CINIT(BUFFERSIZE, LONG, 98), + + /* Instruct libcurl to not use any signal/alarm handlers, even when using + timeouts. This option is useful for multi-threaded applications. + See libcurl-the-guide for more background information. */ + CINIT(NOSIGNAL, LONG, 99), + + /* Provide a CURLShare for mutexing non-ts data */ + CINIT(SHARE, OBJECTPOINT, 100), + + /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default), - CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and CURLPROXY_SOCKS5. */ ++ CURLPROXY_HTTPS, CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and ++ CURLPROXY_SOCKS5. */ + CINIT(PROXYTYPE, LONG, 101), + + /* Set the Accept-Encoding string. Use this to tell a server you would like + the response to be compressed. Before 7.21.6, this was known as + CURLOPT_ENCODING */ + CINIT(ACCEPT_ENCODING, STRINGPOINT, 102), + + /* Set pointer to private data */ + CINIT(PRIVATE, OBJECTPOINT, 103), + + /* Set aliases for HTTP 200 in the HTTP Response header */ + CINIT(HTTP200ALIASES, OBJECTPOINT, 104), + + /* Continue to send authentication (user+password) when following locations, + even when hostname changed. This can potentially send off the name + and password to whatever host the server decides. */ + CINIT(UNRESTRICTED_AUTH, LONG, 105), + + /* Specifically switch on or off the FTP engine's use of the EPRT command ( + it also disables the LPRT attempt). By default, those ones will always be + attempted before the good old traditional PORT command. */ + CINIT(FTP_USE_EPRT, LONG, 106), + + /* Set this to a bitmask value to enable the particular authentications + methods you like. Use this in combination with CURLOPT_USERPWD. + Note that setting multiple bits may cause extra network round-trips. */ + CINIT(HTTPAUTH, LONG, 107), + + /* Set the ssl context callback function, currently only for OpenSSL ssl_ctx + in second argument. The function must be matching the + curl_ssl_ctx_callback proto. */ + CINIT(SSL_CTX_FUNCTION, FUNCTIONPOINT, 108), + + /* Set the userdata for the ssl context callback function's third + argument */ + CINIT(SSL_CTX_DATA, OBJECTPOINT, 109), + + /* FTP Option that causes missing dirs to be created on the remote server. + In 7.19.4 we introduced the convenience enums for this option using the + CURLFTP_CREATE_DIR prefix. + */ + CINIT(FTP_CREATE_MISSING_DIRS, LONG, 110), + + /* Set this to a bitmask value to enable the particular authentications + methods you like. Use this in combination with CURLOPT_PROXYUSERPWD. + Note that setting multiple bits may cause extra network round-trips. */ + CINIT(PROXYAUTH, LONG, 111), + + /* FTP option that changes the timeout, in seconds, associated with + getting a response. This is different from transfer timeout time and + essentially places a demand on the FTP server to acknowledge commands + in a timely manner. */ + CINIT(FTP_RESPONSE_TIMEOUT, LONG, 112), +#define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT + + /* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to + tell libcurl to resolve names to those IP versions only. This only has + affect on systems with support for more than one, i.e IPv4 _and_ IPv6. */ + CINIT(IPRESOLVE, LONG, 113), + + /* Set this option to limit the size of a file that will be downloaded from + an HTTP or FTP server. + + Note there is also _LARGE version which adds large file support for + platforms which have larger off_t sizes. See MAXFILESIZE_LARGE below. */ + CINIT(MAXFILESIZE, LONG, 114), + + /* See the comment for INFILESIZE above, but in short, specifies + * the size of the file being uploaded. -1 means unknown. + */ + CINIT(INFILESIZE_LARGE, OFF_T, 115), + + /* Sets the continuation offset. There is also a LONG version of this; + * look above for RESUME_FROM. + */ + CINIT(RESUME_FROM_LARGE, OFF_T, 116), + + /* Sets the maximum size of data that will be downloaded from + * an HTTP or FTP server. See MAXFILESIZE above for the LONG version. + */ + CINIT(MAXFILESIZE_LARGE, OFF_T, 117), + + /* Set this option to the file name of your .netrc file you want libcurl + to parse (using the CURLOPT_NETRC option). If not set, libcurl will do + a poor attempt to find the user's home directory and check for a .netrc + file in there. */ + CINIT(NETRC_FILE, STRINGPOINT, 118), + + /* Enable SSL/TLS for FTP, pick one of: + CURLUSESSL_TRY - try using SSL, proceed anyway otherwise + CURLUSESSL_CONTROL - SSL for the control connection or fail + CURLUSESSL_ALL - SSL for all communication or fail + */ + CINIT(USE_SSL, LONG, 119), + + /* The _LARGE version of the standard POSTFIELDSIZE option */ + CINIT(POSTFIELDSIZE_LARGE, OFF_T, 120), + + /* Enable/disable the TCP Nagle algorithm */ + CINIT(TCP_NODELAY, LONG, 121), + + /* 122 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 123 OBSOLETE. Gone in 7.16.0 */ + /* 124 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 125 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 126 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ + /* 127 OBSOLETE. Gone in 7.16.0 */ + /* 128 OBSOLETE. Gone in 7.16.0 */ + + /* When FTP over SSL/TLS is selected (with CURLOPT_USE_SSL), this option + can be used to change libcurl's default action which is to first try + "AUTH SSL" and then "AUTH TLS" in this order, and proceed when a OK + response has been received. + + Available parameters are: + CURLFTPAUTH_DEFAULT - let libcurl decide + CURLFTPAUTH_SSL - try "AUTH SSL" first, then TLS + CURLFTPAUTH_TLS - try "AUTH TLS" first, then SSL + */ + CINIT(FTPSSLAUTH, LONG, 129), + + CINIT(IOCTLFUNCTION, FUNCTIONPOINT, 130), + CINIT(IOCTLDATA, OBJECTPOINT, 131), + + /* 132 OBSOLETE. Gone in 7.16.0 */ + /* 133 OBSOLETE. Gone in 7.16.0 */ + + /* zero terminated string for pass on to the FTP server when asked for + "account" info */ + CINIT(FTP_ACCOUNT, STRINGPOINT, 134), + + /* feed cookie into cookie engine */ + CINIT(COOKIELIST, STRINGPOINT, 135), + + /* ignore Content-Length */ + CINIT(IGNORE_CONTENT_LENGTH, LONG, 136), + + /* Set to non-zero to skip the IP address received in a 227 PASV FTP server + response. Typically used for FTP-SSL purposes but is not restricted to + that. libcurl will then instead use the same IP address it used for the + control connection. */ + CINIT(FTP_SKIP_PASV_IP, LONG, 137), + + /* Select "file method" to use when doing FTP, see the curl_ftpmethod + above. */ + CINIT(FTP_FILEMETHOD, LONG, 138), + + /* Local port number to bind the socket to */ + CINIT(LOCALPORT, LONG, 139), + + /* Number of ports to try, including the first one set with LOCALPORT. + Thus, setting it to 1 will make no additional attempts but the first. + */ + CINIT(LOCALPORTRANGE, LONG, 140), + + /* no transfer, set up connection and let application use the socket by + extracting it with CURLINFO_LASTSOCKET */ + CINIT(CONNECT_ONLY, LONG, 141), + + /* Function that will be called to convert from the + network encoding (instead of using the iconv calls in libcurl) */ + CINIT(CONV_FROM_NETWORK_FUNCTION, FUNCTIONPOINT, 142), + + /* Function that will be called to convert to the + network encoding (instead of using the iconv calls in libcurl) */ + CINIT(CONV_TO_NETWORK_FUNCTION, FUNCTIONPOINT, 143), + + /* Function that will be called to convert from UTF8 + (instead of using the iconv calls in libcurl) + Note that this is used only for SSL certificate processing */ + CINIT(CONV_FROM_UTF8_FUNCTION, FUNCTIONPOINT, 144), + + /* if the connection proceeds too quickly then need to slow it down */ + /* limit-rate: maximum number of bytes per second to send or receive */ + CINIT(MAX_SEND_SPEED_LARGE, OFF_T, 145), + CINIT(MAX_RECV_SPEED_LARGE, OFF_T, 146), + + /* Pointer to command string to send if USER/PASS fails. */ + CINIT(FTP_ALTERNATIVE_TO_USER, STRINGPOINT, 147), + + /* callback function for setting socket options */ + CINIT(SOCKOPTFUNCTION, FUNCTIONPOINT, 148), + CINIT(SOCKOPTDATA, OBJECTPOINT, 149), + + /* set to 0 to disable session ID re-use for this transfer, default is + enabled (== 1) */ + CINIT(SSL_SESSIONID_CACHE, LONG, 150), + + /* allowed SSH authentication methods */ + CINIT(SSH_AUTH_TYPES, LONG, 151), + + /* Used by scp/sftp to do public/private key authentication */ + CINIT(SSH_PUBLIC_KEYFILE, STRINGPOINT, 152), + CINIT(SSH_PRIVATE_KEYFILE, STRINGPOINT, 153), + + /* Send CCC (Clear Command Channel) after authentication */ + CINIT(FTP_SSL_CCC, LONG, 154), + + /* Same as TIMEOUT and CONNECTTIMEOUT, but with ms resolution */ + CINIT(TIMEOUT_MS, LONG, 155), + CINIT(CONNECTTIMEOUT_MS, LONG, 156), + + /* set to zero to disable the libcurl's decoding and thus pass the raw body + data to the application even when it is encoded/compressed */ + CINIT(HTTP_TRANSFER_DECODING, LONG, 157), + CINIT(HTTP_CONTENT_DECODING, LONG, 158), + + /* Permission used when creating new files and directories on the remote + server for protocols that support it, SFTP/SCP/FILE */ + CINIT(NEW_FILE_PERMS, LONG, 159), + CINIT(NEW_DIRECTORY_PERMS, LONG, 160), + + /* Set the behaviour of POST when redirecting. Values must be set to one + of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */ + CINIT(POSTREDIR, LONG, 161), + + /* used by scp/sftp to verify the host's public key */ + CINIT(SSH_HOST_PUBLIC_KEY_MD5, STRINGPOINT, 162), + + /* Callback function for opening socket (instead of socket(2)). Optionally, + callback is able change the address or refuse to connect returning + CURL_SOCKET_BAD. The callback should have type + curl_opensocket_callback */ + CINIT(OPENSOCKETFUNCTION, FUNCTIONPOINT, 163), + CINIT(OPENSOCKETDATA, OBJECTPOINT, 164), + + /* POST volatile input fields. */ + CINIT(COPYPOSTFIELDS, OBJECTPOINT, 165), + + /* set transfer mode (;type=) when doing FTP via an HTTP proxy */ + CINIT(PROXY_TRANSFER_MODE, LONG, 166), + + /* Callback function for seeking in the input stream */ + CINIT(SEEKFUNCTION, FUNCTIONPOINT, 167), + CINIT(SEEKDATA, OBJECTPOINT, 168), + + /* CRL file */ + CINIT(CRLFILE, STRINGPOINT, 169), + + /* Issuer certificate */ + CINIT(ISSUERCERT, STRINGPOINT, 170), + + /* (IPv6) Address scope */ + CINIT(ADDRESS_SCOPE, LONG, 171), + + /* Collect certificate chain info and allow it to get retrievable with + CURLINFO_CERTINFO after the transfer is complete. */ + CINIT(CERTINFO, LONG, 172), + + /* "name" and "pwd" to use when fetching. */ + CINIT(USERNAME, STRINGPOINT, 173), + CINIT(PASSWORD, STRINGPOINT, 174), + + /* "name" and "pwd" to use with Proxy when fetching. */ + CINIT(PROXYUSERNAME, STRINGPOINT, 175), + CINIT(PROXYPASSWORD, STRINGPOINT, 176), + + /* Comma separated list of hostnames defining no-proxy zones. These should + match both hostnames directly, and hostnames within a domain. For + example, local.com will match local.com and www.local.com, but NOT + notlocal.com or www.notlocal.com. For compatibility with other + implementations of this, .local.com will be considered to be the same as + local.com. A single * is the only valid wildcard, and effectively + disables the use of proxy. */ + CINIT(NOPROXY, STRINGPOINT, 177), + + /* block size for TFTP transfers */ + CINIT(TFTP_BLKSIZE, LONG, 178), + + /* Socks Service */ + CINIT(SOCKS5_GSSAPI_SERVICE, STRINGPOINT, 179), /* DEPRECATED, do not use! */ + + /* Socks Service */ + CINIT(SOCKS5_GSSAPI_NEC, LONG, 180), + + /* set the bitmask for the protocols that are allowed to be used for the + transfer, which thus helps the app which takes URLs from users or other + external inputs and want to restrict what protocol(s) to deal + with. Defaults to CURLPROTO_ALL. */ + CINIT(PROTOCOLS, LONG, 181), + + /* set the bitmask for the protocols that libcurl is allowed to follow to, + as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs + to be set in both bitmasks to be allowed to get redirected to. Defaults + to all protocols except FILE and SCP. */ + CINIT(REDIR_PROTOCOLS, LONG, 182), + + /* set the SSH knownhost file name to use */ + CINIT(SSH_KNOWNHOSTS, STRINGPOINT, 183), + + /* set the SSH host key callback, must point to a curl_sshkeycallback + function */ + CINIT(SSH_KEYFUNCTION, FUNCTIONPOINT, 184), + + /* set the SSH host key callback custom pointer */ + CINIT(SSH_KEYDATA, OBJECTPOINT, 185), + + /* set the SMTP mail originator */ + CINIT(MAIL_FROM, STRINGPOINT, 186), + + /* set the list of SMTP mail receiver(s) */ + CINIT(MAIL_RCPT, OBJECTPOINT, 187), + + /* FTP: send PRET before PASV */ + CINIT(FTP_USE_PRET, LONG, 188), + + /* RTSP request method (OPTIONS, SETUP, PLAY, etc...) */ + CINIT(RTSP_REQUEST, LONG, 189), + + /* The RTSP session identifier */ + CINIT(RTSP_SESSION_ID, STRINGPOINT, 190), + + /* The RTSP stream URI */ + CINIT(RTSP_STREAM_URI, STRINGPOINT, 191), + + /* The Transport: header to use in RTSP requests */ + CINIT(RTSP_TRANSPORT, STRINGPOINT, 192), + + /* Manually initialize the client RTSP CSeq for this handle */ + CINIT(RTSP_CLIENT_CSEQ, LONG, 193), + + /* Manually initialize the server RTSP CSeq for this handle */ + CINIT(RTSP_SERVER_CSEQ, LONG, 194), + + /* The stream to pass to INTERLEAVEFUNCTION. */ + CINIT(INTERLEAVEDATA, OBJECTPOINT, 195), + + /* Let the application define a custom write method for RTP data */ + CINIT(INTERLEAVEFUNCTION, FUNCTIONPOINT, 196), + + /* Turn on wildcard matching */ + CINIT(WILDCARDMATCH, LONG, 197), + + /* Directory matching callback called before downloading of an + individual file (chunk) started */ + CINIT(CHUNK_BGN_FUNCTION, FUNCTIONPOINT, 198), + + /* Directory matching callback called after the file (chunk) + was downloaded, or skipped */ + CINIT(CHUNK_END_FUNCTION, FUNCTIONPOINT, 199), + + /* Change match (fnmatch-like) callback for wildcard matching */ + CINIT(FNMATCH_FUNCTION, FUNCTIONPOINT, 200), + + /* Let the application define custom chunk data pointer */ + CINIT(CHUNK_DATA, OBJECTPOINT, 201), + + /* FNMATCH_FUNCTION user pointer */ + CINIT(FNMATCH_DATA, OBJECTPOINT, 202), + + /* send linked-list of name:port:address sets */ + CINIT(RESOLVE, OBJECTPOINT, 203), + + /* Set a username for authenticated TLS */ + CINIT(TLSAUTH_USERNAME, STRINGPOINT, 204), + + /* Set a password for authenticated TLS */ + CINIT(TLSAUTH_PASSWORD, STRINGPOINT, 205), + + /* Set authentication type for authenticated TLS */ + CINIT(TLSAUTH_TYPE, STRINGPOINT, 206), + + /* Set to 1 to enable the "TE:" header in HTTP requests to ask for + compressed transfer-encoded responses. Set to 0 to disable the use of TE: + in outgoing requests. The current default is 0, but it might change in a + future libcurl release. + + libcurl will ask for the compressed methods it knows of, and if that + isn't any, it will not ask for transfer-encoding at all even if this + option is set to 1. + + */ + CINIT(TRANSFER_ENCODING, LONG, 207), + + /* Callback function for closing socket (instead of close(2)). The callback + should have type curl_closesocket_callback */ + CINIT(CLOSESOCKETFUNCTION, FUNCTIONPOINT, 208), + CINIT(CLOSESOCKETDATA, OBJECTPOINT, 209), + + /* allow GSSAPI credential delegation */ + CINIT(GSSAPI_DELEGATION, LONG, 210), + + /* Set the name servers to use for DNS resolution */ + CINIT(DNS_SERVERS, STRINGPOINT, 211), + + /* Time-out accept operations (currently for FTP only) after this amount + of miliseconds. */ + CINIT(ACCEPTTIMEOUT_MS, LONG, 212), + + /* Set TCP keepalive */ + CINIT(TCP_KEEPALIVE, LONG, 213), + + /* non-universal keepalive knobs (Linux, AIX, HP-UX, more) */ + CINIT(TCP_KEEPIDLE, LONG, 214), + CINIT(TCP_KEEPINTVL, LONG, 215), + + /* Enable/disable specific SSL features with a bitmask, see CURLSSLOPT_* */ + CINIT(SSL_OPTIONS, LONG, 216), + + /* Set the SMTP auth originator */ + CINIT(MAIL_AUTH, STRINGPOINT, 217), + + /* Enable/disable SASL initial response */ + CINIT(SASL_IR, LONG, 218), + + /* Function that will be called instead of the internal progress display + * function. This function should be defined as the curl_xferinfo_callback + * prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */ + CINIT(XFERINFOFUNCTION, FUNCTIONPOINT, 219), + + /* The XOAUTH2 bearer token */ + CINIT(XOAUTH2_BEARER, STRINGPOINT, 220), + + /* Set the interface string to use as outgoing network + * interface for DNS requests. + * Only supported by the c-ares DNS backend */ + CINIT(DNS_INTERFACE, STRINGPOINT, 221), + + /* Set the local IPv4 address to use for outgoing DNS requests. + * Only supported by the c-ares DNS backend */ + CINIT(DNS_LOCAL_IP4, STRINGPOINT, 222), + + /* Set the local IPv4 address to use for outgoing DNS requests. + * Only supported by the c-ares DNS backend */ + CINIT(DNS_LOCAL_IP6, STRINGPOINT, 223), + + /* Set authentication options directly */ + CINIT(LOGIN_OPTIONS, STRINGPOINT, 224), + + /* Enable/disable TLS NPN extension (http2 over ssl might fail without) */ + CINIT(SSL_ENABLE_NPN, LONG, 225), + + /* Enable/disable TLS ALPN extension (http2 over ssl might fail without) */ + CINIT(SSL_ENABLE_ALPN, LONG, 226), + + /* Time to wait for a response to a HTTP request containing an + * Expect: 100-continue header before sending the data anyway. */ + CINIT(EXPECT_100_TIMEOUT_MS, LONG, 227), + + /* This points to a linked list of headers used for proxy requests only, + struct curl_slist kind */ + CINIT(PROXYHEADER, OBJECTPOINT, 228), + + /* Pass in a bitmask of "header options" */ + CINIT(HEADEROPT, LONG, 229), + + /* The public key in DER form used to validate the peer public key + this option is used only if SSL_VERIFYPEER is true */ + CINIT(PINNEDPUBLICKEY, STRINGPOINT, 230), + + /* Path to Unix domain socket */ + CINIT(UNIX_SOCKET_PATH, STRINGPOINT, 231), + + /* Set if we should verify the certificate status. */ + CINIT(SSL_VERIFYSTATUS, LONG, 232), + + /* Set if we should enable TLS false start. */ + CINIT(SSL_FALSESTART, LONG, 233), + + /* Do not squash dot-dot sequences */ + CINIT(PATH_AS_IS, LONG, 234), + + /* Proxy Service Name */ + CINIT(PROXY_SERVICE_NAME, STRINGPOINT, 235), + + /* Service Name */ + CINIT(SERVICE_NAME, STRINGPOINT, 236), + + /* Wait/don't wait for pipe/mutex to clarify */ + CINIT(PIPEWAIT, LONG, 237), + + /* Set the protocol used when curl is given a URL without a protocol */ + CINIT(DEFAULT_PROTOCOL, STRINGPOINT, 238), + + /* Set stream weight, 1 - 256 (default is 16) */ + CINIT(STREAM_WEIGHT, LONG, 239), + + /* Set stream dependency on another CURL handle */ + CINIT(STREAM_DEPENDS, OBJECTPOINT, 240), + + /* Set E-xclusive stream dependency on another CURL handle */ + CINIT(STREAM_DEPENDS_E, OBJECTPOINT, 241), + + /* Do not send any tftp option requests to the server */ + CINIT(TFTP_NO_OPTIONS, LONG, 242), + + /* Linked-list of host:port:connect-to-host:connect-to-port, + overrides the URL's host:port (only for the network layer) */ + CINIT(CONNECT_TO, OBJECTPOINT, 243), + + /* Set TCP Fast Open */ + CINIT(TCP_FASTOPEN, LONG, 244), + + /* Continue to send data if the server responds early with an + * HTTP status code >= 300 */ + CINIT(KEEP_SENDING_ON_ERROR, LONG, 245), + ++ /* The CApath or CAfile used to validate the proxy certificate ++ this option is used only if PROXY_SSL_VERIFYPEER is true */ ++ CINIT(PROXY_CAINFO, STRINGPOINT, 246), ++ ++ /* The CApath directory used to validate the proxy certificate ++ this option is used only if PROXY_SSL_VERIFYPEER is true */ ++ CINIT(PROXY_CAPATH, STRINGPOINT, 247), ++ ++ /* Set if we should verify the proxy in ssl handshake, ++ set 1 to verify. */ ++ CINIT(PROXY_SSL_VERIFYPEER, LONG, 248), ++ ++ /* Set if we should verify the Common name from the proxy certificate in ssl ++ * handshake, set 1 to check existence, 2 to ensure that it matches ++ * the provided hostname. */ ++ CINIT(PROXY_SSL_VERIFYHOST, LONG, 249), ++ ++ /* What version to specifically try to use for proxy. ++ See CURL_SSLVERSION defines below. */ ++ CINIT(PROXY_SSLVERSION, LONG, 250), ++ ++ /* Set a username for authenticated TLS for proxy */ ++ CINIT(PROXY_TLSAUTH_USERNAME, STRINGPOINT, 251), ++ ++ /* Set a password for authenticated TLS for proxy */ ++ CINIT(PROXY_TLSAUTH_PASSWORD, STRINGPOINT, 252), ++ ++ /* Set authentication type for authenticated TLS for proxy */ ++ CINIT(PROXY_TLSAUTH_TYPE, STRINGPOINT, 253), ++ ++ /* name of the file keeping your private SSL-certificate for proxy */ ++ CINIT(PROXY_SSLCERT, STRINGPOINT, 254), ++ ++ /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") for ++ proxy */ ++ CINIT(PROXY_SSLCERTTYPE, STRINGPOINT, 255), ++ ++ /* name of the file keeping your private SSL-key for proxy */ ++ CINIT(PROXY_SSLKEY, STRINGPOINT, 256), ++ ++ /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") for ++ proxy */ ++ CINIT(PROXY_SSLKEYTYPE, STRINGPOINT, 257), ++ ++ /* password for the SSL private key for proxy */ ++ CINIT(PROXY_KEYPASSWD, STRINGPOINT, 258), ++ ++ /* Specify which SSL ciphers to use for proxy */ ++ CINIT(PROXY_SSL_CIPHER_LIST, STRINGPOINT, 259), ++ ++ /* CRL file for proxy */ ++ CINIT(PROXY_CRLFILE, STRINGPOINT, 260), ++ ++ /* Enable/disable specific SSL features with a bitmask for proxy, see ++ CURLSSLOPT_* */ ++ CINIT(PROXY_SSL_OPTIONS, LONG, 261), ++ ++ /* Name of pre proxy to use. */ ++ CINIT(PRE_PROXY, STRINGPOINT, 262), ++ ++ /* The public key in DER form used to validate the proxy public key ++ this option is used only if PROXY_SSL_VERIFYPEER is true */ ++ CINIT(PROXY_PINNEDPUBLICKEY, STRINGPOINT, 263), ++ + CURLOPT_LASTENTRY /* the last unused */ +} CURLoption; + +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all + the obsolete stuff removed! */ + +/* Backwards compatibility with older names */ +/* These are scheduled to disappear by 2011 */ + +/* This was added in version 7.19.1 */ +#define CURLOPT_POST301 CURLOPT_POSTREDIR + +/* These are scheduled to disappear by 2009 */ + +/* The following were added in 7.17.0 */ +#define CURLOPT_SSLKEYPASSWD CURLOPT_KEYPASSWD +#define CURLOPT_FTPAPPEND CURLOPT_APPEND +#define CURLOPT_FTPLISTONLY CURLOPT_DIRLISTONLY +#define CURLOPT_FTP_SSL CURLOPT_USE_SSL + +/* The following were added earlier */ + +#define CURLOPT_SSLCERTPASSWD CURLOPT_KEYPASSWD +#define CURLOPT_KRB4LEVEL CURLOPT_KRBLEVEL + +#else +/* This is set if CURL_NO_OLDIES is defined at compile-time */ +#undef CURLOPT_DNS_USE_GLOBAL_CACHE /* soon obsolete */ +#endif + + + /* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host + name resolves addresses using more than one IP protocol version, this + option might be handy to force libcurl to use a specific IP version. */ +#define CURL_IPRESOLVE_WHATEVER 0 /* default, resolves addresses to all IP + versions that your system allows */ +#define CURL_IPRESOLVE_V4 1 /* resolve to IPv4 addresses */ +#define CURL_IPRESOLVE_V6 2 /* resolve to IPv6 addresses */ + + /* three convenient "aliases" that follow the name scheme better */ +#define CURLOPT_RTSPHEADER CURLOPT_HTTPHEADER + + /* These enums are for use with the CURLOPT_HTTP_VERSION option. */ +enum { + CURL_HTTP_VERSION_NONE, /* setting this means we don't care, and that we'd + like the library to choose the best possible + for us! */ + CURL_HTTP_VERSION_1_0, /* please use HTTP 1.0 in the request */ + CURL_HTTP_VERSION_1_1, /* please use HTTP 1.1 in the request */ + CURL_HTTP_VERSION_2_0, /* please use HTTP 2 in the request */ + CURL_HTTP_VERSION_2TLS, /* use version 2 for HTTPS, version 1.1 for HTTP */ + CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE, /* please use HTTP 2 without HTTP/1.1 + Upgrade */ + + CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */ +}; + +/* Convenience definition simple because the name of the version is HTTP/2 and + not 2.0. The 2_0 version of the enum name was set while the version was + still planned to be 2.0 and we stick to it for compatibility. */ +#define CURL_HTTP_VERSION_2 CURL_HTTP_VERSION_2_0 + +/* + * Public API enums for RTSP requests + */ +enum { + CURL_RTSPREQ_NONE, /* first in list */ + CURL_RTSPREQ_OPTIONS, + CURL_RTSPREQ_DESCRIBE, + CURL_RTSPREQ_ANNOUNCE, + CURL_RTSPREQ_SETUP, + CURL_RTSPREQ_PLAY, + CURL_RTSPREQ_PAUSE, + CURL_RTSPREQ_TEARDOWN, + CURL_RTSPREQ_GET_PARAMETER, + CURL_RTSPREQ_SET_PARAMETER, + CURL_RTSPREQ_RECORD, + CURL_RTSPREQ_RECEIVE, + CURL_RTSPREQ_LAST /* last in list */ +}; + + /* These enums are for use with the CURLOPT_NETRC option. */ +enum CURL_NETRC_OPTION { + CURL_NETRC_IGNORED, /* The .netrc will never be read. + * This is the default. */ + CURL_NETRC_OPTIONAL, /* A user:password in the URL will be preferred + * to one in the .netrc. */ + CURL_NETRC_REQUIRED, /* A user:password in the URL will be ignored. + * Unless one is set programmatically, the .netrc + * will be queried. */ + CURL_NETRC_LAST +}; + +enum { + CURL_SSLVERSION_DEFAULT, + CURL_SSLVERSION_TLSv1, /* TLS 1.x */ + CURL_SSLVERSION_SSLv2, + CURL_SSLVERSION_SSLv3, + CURL_SSLVERSION_TLSv1_0, + CURL_SSLVERSION_TLSv1_1, + CURL_SSLVERSION_TLSv1_2, ++ CURL_SSLVERSION_TLSv1_3, + + CURL_SSLVERSION_LAST /* never use, keep last */ +}; + +enum CURL_TLSAUTH { + CURL_TLSAUTH_NONE, + CURL_TLSAUTH_SRP, + CURL_TLSAUTH_LAST /* never use, keep last */ +}; + +/* symbols to use with CURLOPT_POSTREDIR. + CURL_REDIR_POST_301, CURL_REDIR_POST_302 and CURL_REDIR_POST_303 + can be bitwise ORed so that CURL_REDIR_POST_301 | CURL_REDIR_POST_302 + | CURL_REDIR_POST_303 == CURL_REDIR_POST_ALL */ + +#define CURL_REDIR_GET_ALL 0 +#define CURL_REDIR_POST_301 1 +#define CURL_REDIR_POST_302 2 +#define CURL_REDIR_POST_303 4 +#define CURL_REDIR_POST_ALL \ + (CURL_REDIR_POST_301|CURL_REDIR_POST_302|CURL_REDIR_POST_303) + +typedef enum { + CURL_TIMECOND_NONE, + + CURL_TIMECOND_IFMODSINCE, + CURL_TIMECOND_IFUNMODSINCE, + CURL_TIMECOND_LASTMOD, + + CURL_TIMECOND_LAST +} curl_TimeCond; + + +/* curl_strequal() and curl_strnequal() are subject for removal in a future - libcurl, see lib/README.curlx for details */ ++ libcurl, see lib/README.curlx for details ++ ++ !checksrc! disable SPACEBEFOREPAREN 2 ++*/ +CURL_EXTERN int (curl_strequal)(const char *s1, const char *s2); +CURL_EXTERN int (curl_strnequal)(const char *s1, const char *s2, size_t n); + +/* name is uppercase CURLFORM_ */ +#ifdef CFINIT +#undef CFINIT +#endif + +#ifdef CURL_ISOCPP +#define CFINIT(name) CURLFORM_ ## name +#else +/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */ +#define CFINIT(name) CURLFORM_/**/name +#endif + +typedef enum { + CFINIT(NOTHING), /********* the first one is unused ************/ + + /* */ + CFINIT(COPYNAME), + CFINIT(PTRNAME), + CFINIT(NAMELENGTH), + CFINIT(COPYCONTENTS), + CFINIT(PTRCONTENTS), + CFINIT(CONTENTSLENGTH), + CFINIT(FILECONTENT), + CFINIT(ARRAY), + CFINIT(OBSOLETE), + CFINIT(FILE), + + CFINIT(BUFFER), + CFINIT(BUFFERPTR), + CFINIT(BUFFERLENGTH), + + CFINIT(CONTENTTYPE), + CFINIT(CONTENTHEADER), + CFINIT(FILENAME), + CFINIT(END), + CFINIT(OBSOLETE2), + + CFINIT(STREAM), + CFINIT(CONTENTLEN), /* added in 7.46.0, provide a curl_off_t length */ + + CURLFORM_LASTENTRY /* the last unused */ +} CURLformoption; + +#undef CFINIT /* done */ + +/* structure to be used as parameter for CURLFORM_ARRAY */ +struct curl_forms { + CURLformoption option; + const char *value; +}; + +/* use this for multipart formpost building */ +/* Returns code for curl_formadd() + * + * Returns: + * CURL_FORMADD_OK on success + * CURL_FORMADD_MEMORY if the FormInfo allocation fails + * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form + * CURL_FORMADD_NULL if a null pointer was given for a char + * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed + * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used + * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error) + * CURL_FORMADD_MEMORY if a curl_httppost struct cannot be allocated + * CURL_FORMADD_MEMORY if some allocation for string copying failed. + * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array + * + ***************************************************************************/ +typedef enum { + CURL_FORMADD_OK, /* first, no error */ + + CURL_FORMADD_MEMORY, + CURL_FORMADD_OPTION_TWICE, + CURL_FORMADD_NULL, + CURL_FORMADD_UNKNOWN_OPTION, + CURL_FORMADD_INCOMPLETE, + CURL_FORMADD_ILLEGAL_ARRAY, + CURL_FORMADD_DISABLED, /* libcurl was built with this disabled */ + + CURL_FORMADD_LAST /* last */ +} CURLFORMcode; + +/* + * NAME curl_formadd() + * + * DESCRIPTION + * + * Pretty advanced function for building multi-part formposts. Each invoke + * adds one part that together construct a full post. Then use + * CURLOPT_HTTPPOST to send it off to libcurl. + */ +CURL_EXTERN CURLFORMcode curl_formadd(struct curl_httppost **httppost, + struct curl_httppost **last_post, + ...); + +/* + * callback function for curl_formget() + * The void *arg pointer will be the one passed as second argument to + * curl_formget(). + * The character buffer passed to it must not be freed. + * Should return the buffer length passed to it as the argument "len" on + * success. + */ +typedef size_t (*curl_formget_callback)(void *arg, const char *buf, + size_t len); + +/* + * NAME curl_formget() + * + * DESCRIPTION + * + * Serialize a curl_httppost struct built with curl_formadd(). + * Accepts a void pointer as second argument which will be passed to + * the curl_formget_callback function. + * Returns 0 on success. + */ +CURL_EXTERN int curl_formget(struct curl_httppost *form, void *arg, + curl_formget_callback append); +/* + * NAME curl_formfree() + * + * DESCRIPTION + * + * Free a multipart formpost previously built with curl_formadd(). + */ +CURL_EXTERN void curl_formfree(struct curl_httppost *form); + +/* + * NAME curl_getenv() + * + * DESCRIPTION + * + * Returns a malloc()'ed string that MUST be curl_free()ed after usage is + * complete. DEPRECATED - see lib/README.curlx + */ +CURL_EXTERN char *curl_getenv(const char *variable); + +/* + * NAME curl_version() + * + * DESCRIPTION + * + * Returns a static ascii string of the libcurl version. + */ +CURL_EXTERN char *curl_version(void); + +/* + * NAME curl_easy_escape() + * + * DESCRIPTION + * + * Escapes URL strings (converts all letters consider illegal in URLs to their + * %XX versions). This function returns a new allocated string or NULL if an + * error occurred. + */ +CURL_EXTERN char *curl_easy_escape(CURL *handle, + const char *string, + int length); + +/* the previous version: */ +CURL_EXTERN char *curl_escape(const char *string, + int length); + + +/* + * NAME curl_easy_unescape() + * + * DESCRIPTION + * + * Unescapes URL encoding in strings (converts all %XX codes to their 8bit + * versions). This function returns a new allocated string or NULL if an error + * occurred. + * Conversion Note: On non-ASCII platforms the ASCII %XX codes are + * converted into the host encoding. + */ +CURL_EXTERN char *curl_easy_unescape(CURL *handle, + const char *string, + int length, + int *outlength); + +/* the previous version */ +CURL_EXTERN char *curl_unescape(const char *string, + int length); + +/* + * NAME curl_free() + * + * DESCRIPTION + * + * Provided for de-allocation in the same translation unit that did the + * allocation. Added in libcurl 7.10 + */ +CURL_EXTERN void curl_free(void *p); + +/* + * NAME curl_global_init() + * + * DESCRIPTION + * + * curl_global_init() should be invoked exactly once for each application that + * uses libcurl and before any call of other libcurl functions. + * + * This function is not thread-safe! + */ +CURL_EXTERN CURLcode curl_global_init(long flags); + +/* + * NAME curl_global_init_mem() + * + * DESCRIPTION + * + * curl_global_init() or curl_global_init_mem() should be invoked exactly once + * for each application that uses libcurl. This function can be used to + * initialize libcurl and set user defined memory management callback + * functions. Users can implement memory management routines to check for + * memory leaks, check for mis-use of the curl library etc. User registered + * callback routines with be invoked by this library instead of the system + * memory management routines like malloc, free etc. + */ +CURL_EXTERN CURLcode curl_global_init_mem(long flags, + curl_malloc_callback m, + curl_free_callback f, + curl_realloc_callback r, + curl_strdup_callback s, + curl_calloc_callback c); + +/* + * NAME curl_global_cleanup() + * + * DESCRIPTION + * + * curl_global_cleanup() should be invoked exactly once for each application + * that uses libcurl + */ +CURL_EXTERN void curl_global_cleanup(void); + +/* linked-list structure for the CURLOPT_QUOTE option (and other) */ +struct curl_slist { + char *data; + struct curl_slist *next; +}; + +/* + * NAME curl_slist_append() + * + * DESCRIPTION + * + * Appends a string to a linked list. If no list exists, it will be created + * first. Returns the new list, after appending. + */ +CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *, + const char *); + +/* + * NAME curl_slist_free_all() + * + * DESCRIPTION + * + * free a previously built curl_slist. + */ +CURL_EXTERN void curl_slist_free_all(struct curl_slist *); + +/* + * NAME curl_getdate() + * + * DESCRIPTION + * + * Returns the time, in seconds since 1 Jan 1970 of the time string given in + * the first argument. The time argument in the second parameter is unused + * and should be set to NULL. + */ +CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused); + +/* info about the certificate chain, only for OpenSSL builds. Asked + for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */ +struct curl_certinfo { + int num_of_certs; /* number of certificates with information */ + struct curl_slist **certinfo; /* for each index in this array, there's a + linked list with textual information in the + format "name: value" */ +}; + +/* enum for the different supported SSL backends */ +typedef enum { + CURLSSLBACKEND_NONE = 0, + CURLSSLBACKEND_OPENSSL = 1, + CURLSSLBACKEND_GNUTLS = 2, + CURLSSLBACKEND_NSS = 3, + CURLSSLBACKEND_OBSOLETE4 = 4, /* Was QSOSSL. */ + CURLSSLBACKEND_GSKIT = 5, + CURLSSLBACKEND_POLARSSL = 6, + CURLSSLBACKEND_CYASSL = 7, + CURLSSLBACKEND_SCHANNEL = 8, + CURLSSLBACKEND_DARWINSSL = 9, + CURLSSLBACKEND_AXTLS = 10, + CURLSSLBACKEND_MBEDTLS = 11 +} curl_sslbackend; + +/* aliases for library clones and renames */ +#define CURLSSLBACKEND_LIBRESSL 1 +#define CURLSSLBACKEND_BORINGSSL 1 +#define CURLSSLBACKEND_WOLFSSL 6 + +/* Information about the SSL library used and the respective internal SSL + handle, which can be used to obtain further information regarding the + connection. Asked for with CURLINFO_TLS_SSL_PTR or CURLINFO_TLS_SESSION. */ +struct curl_tlssessioninfo { + curl_sslbackend backend; + void *internals; +}; + +#define CURLINFO_STRING 0x100000 +#define CURLINFO_LONG 0x200000 +#define CURLINFO_DOUBLE 0x300000 +#define CURLINFO_SLIST 0x400000 +#define CURLINFO_SOCKET 0x500000 +#define CURLINFO_MASK 0x0fffff +#define CURLINFO_TYPEMASK 0xf00000 + +typedef enum { + CURLINFO_NONE, /* first, never use this */ + CURLINFO_EFFECTIVE_URL = CURLINFO_STRING + 1, + CURLINFO_RESPONSE_CODE = CURLINFO_LONG + 2, + CURLINFO_TOTAL_TIME = CURLINFO_DOUBLE + 3, + CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE + 4, + CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE + 5, + CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE + 6, + CURLINFO_SIZE_UPLOAD = CURLINFO_DOUBLE + 7, + CURLINFO_SIZE_DOWNLOAD = CURLINFO_DOUBLE + 8, + CURLINFO_SPEED_DOWNLOAD = CURLINFO_DOUBLE + 9, + CURLINFO_SPEED_UPLOAD = CURLINFO_DOUBLE + 10, + CURLINFO_HEADER_SIZE = CURLINFO_LONG + 11, + CURLINFO_REQUEST_SIZE = CURLINFO_LONG + 12, + CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13, + CURLINFO_FILETIME = CURLINFO_LONG + 14, + CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE + 15, + CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE + 16, + CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17, + CURLINFO_CONTENT_TYPE = CURLINFO_STRING + 18, + CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE + 19, + CURLINFO_REDIRECT_COUNT = CURLINFO_LONG + 20, + CURLINFO_PRIVATE = CURLINFO_STRING + 21, + CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG + 22, + CURLINFO_HTTPAUTH_AVAIL = CURLINFO_LONG + 23, + CURLINFO_PROXYAUTH_AVAIL = CURLINFO_LONG + 24, + CURLINFO_OS_ERRNO = CURLINFO_LONG + 25, + CURLINFO_NUM_CONNECTS = CURLINFO_LONG + 26, + CURLINFO_SSL_ENGINES = CURLINFO_SLIST + 27, + CURLINFO_COOKIELIST = CURLINFO_SLIST + 28, + CURLINFO_LASTSOCKET = CURLINFO_LONG + 29, + CURLINFO_FTP_ENTRY_PATH = CURLINFO_STRING + 30, + CURLINFO_REDIRECT_URL = CURLINFO_STRING + 31, + CURLINFO_PRIMARY_IP = CURLINFO_STRING + 32, + CURLINFO_APPCONNECT_TIME = CURLINFO_DOUBLE + 33, + CURLINFO_CERTINFO = CURLINFO_SLIST + 34, + CURLINFO_CONDITION_UNMET = CURLINFO_LONG + 35, + CURLINFO_RTSP_SESSION_ID = CURLINFO_STRING + 36, + CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG + 37, + CURLINFO_RTSP_SERVER_CSEQ = CURLINFO_LONG + 38, + CURLINFO_RTSP_CSEQ_RECV = CURLINFO_LONG + 39, + CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40, + CURLINFO_LOCAL_IP = CURLINFO_STRING + 41, + CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42, + CURLINFO_TLS_SESSION = CURLINFO_SLIST + 43, + CURLINFO_ACTIVESOCKET = CURLINFO_SOCKET + 44, + CURLINFO_TLS_SSL_PTR = CURLINFO_SLIST + 45, + CURLINFO_HTTP_VERSION = CURLINFO_LONG + 46, ++ CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 47, ++ CURLINFO_PROTOCOL = CURLINFO_LONG + 48, ++ CURLINFO_SCHEME = CURLINFO_STRING + 49, + /* Fill in new entries below here! */ + - CURLINFO_LASTONE = 46 ++ CURLINFO_LASTONE = 49 +} CURLINFO; + +/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as + CURLINFO_HTTP_CODE */ +#define CURLINFO_HTTP_CODE CURLINFO_RESPONSE_CODE + +typedef enum { + CURLCLOSEPOLICY_NONE, /* first, never use this */ + + CURLCLOSEPOLICY_OLDEST, + CURLCLOSEPOLICY_LEAST_RECENTLY_USED, + CURLCLOSEPOLICY_LEAST_TRAFFIC, + CURLCLOSEPOLICY_SLOWEST, + CURLCLOSEPOLICY_CALLBACK, + + CURLCLOSEPOLICY_LAST /* last, never use this */ +} curl_closepolicy; + +#define CURL_GLOBAL_SSL (1<<0) +#define CURL_GLOBAL_WIN32 (1<<1) +#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32) +#define CURL_GLOBAL_NOTHING 0 +#define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL +#define CURL_GLOBAL_ACK_EINTR (1<<2) + + +/***************************************************************************** + * Setup defines, protos etc for the sharing stuff. + */ + +/* Different data locks for a single share */ +typedef enum { + CURL_LOCK_DATA_NONE = 0, + /* CURL_LOCK_DATA_SHARE is used internally to say that + * the locking is just made to change the internal state of the share + * itself. + */ + CURL_LOCK_DATA_SHARE, + CURL_LOCK_DATA_COOKIE, + CURL_LOCK_DATA_DNS, + CURL_LOCK_DATA_SSL_SESSION, + CURL_LOCK_DATA_CONNECT, + CURL_LOCK_DATA_LAST +} curl_lock_data; + +/* Different lock access types */ +typedef enum { + CURL_LOCK_ACCESS_NONE = 0, /* unspecified action */ + CURL_LOCK_ACCESS_SHARED = 1, /* for read perhaps */ + CURL_LOCK_ACCESS_SINGLE = 2, /* for write perhaps */ + CURL_LOCK_ACCESS_LAST /* never use */ +} curl_lock_access; + +typedef void (*curl_lock_function)(CURL *handle, + curl_lock_data data, + curl_lock_access locktype, + void *userptr); +typedef void (*curl_unlock_function)(CURL *handle, + curl_lock_data data, + void *userptr); + + +typedef enum { + CURLSHE_OK, /* all is fine */ + CURLSHE_BAD_OPTION, /* 1 */ + CURLSHE_IN_USE, /* 2 */ + CURLSHE_INVALID, /* 3 */ + CURLSHE_NOMEM, /* 4 out of memory */ + CURLSHE_NOT_BUILT_IN, /* 5 feature not present in lib */ + CURLSHE_LAST /* never use */ +} CURLSHcode; + +typedef enum { + CURLSHOPT_NONE, /* don't use */ + CURLSHOPT_SHARE, /* specify a data type to share */ + CURLSHOPT_UNSHARE, /* specify which data type to stop sharing */ + CURLSHOPT_LOCKFUNC, /* pass in a 'curl_lock_function' pointer */ + CURLSHOPT_UNLOCKFUNC, /* pass in a 'curl_unlock_function' pointer */ + CURLSHOPT_USERDATA, /* pass in a user data pointer used in the lock/unlock + callback functions */ + CURLSHOPT_LAST /* never use */ +} CURLSHoption; + +CURL_EXTERN CURLSH *curl_share_init(void); +CURL_EXTERN CURLSHcode curl_share_setopt(CURLSH *, CURLSHoption option, ...); +CURL_EXTERN CURLSHcode curl_share_cleanup(CURLSH *); + +/**************************************************************************** + * Structures for querying information about the curl library at runtime. + */ + +typedef enum { + CURLVERSION_FIRST, + CURLVERSION_SECOND, + CURLVERSION_THIRD, + CURLVERSION_FOURTH, + CURLVERSION_LAST /* never actually use this */ +} CURLversion; + +/* The 'CURLVERSION_NOW' is the symbolic name meant to be used by + basically all programs ever that want to get version information. It is + meant to be a built-in version number for what kind of struct the caller + expects. If the struct ever changes, we redefine the NOW to another enum + from above. */ +#define CURLVERSION_NOW CURLVERSION_FOURTH + +typedef struct { + CURLversion age; /* age of the returned struct */ + const char *version; /* LIBCURL_VERSION */ + unsigned int version_num; /* LIBCURL_VERSION_NUM */ + const char *host; /* OS/host/cpu/machine when configured */ + int features; /* bitmask, see defines below */ + const char *ssl_version; /* human readable string */ + long ssl_version_num; /* not used anymore, always 0 */ + const char *libz_version; /* human readable string */ + /* protocols is terminated by an entry with a NULL protoname */ + const char * const *protocols; + + /* The fields below this were added in CURLVERSION_SECOND */ + const char *ares; + int ares_num; + + /* This field was added in CURLVERSION_THIRD */ + const char *libidn; + + /* These field were added in CURLVERSION_FOURTH */ + + /* Same as '_libiconv_version' if built with HAVE_ICONV */ + int iconv_ver_num; + + const char *libssh_version; /* human readable string */ + +} curl_version_info_data; + +#define CURL_VERSION_IPV6 (1<<0) /* IPv6-enabled */ +#define CURL_VERSION_KERBEROS4 (1<<1) /* Kerberos V4 auth is supported + (deprecated) */ +#define CURL_VERSION_SSL (1<<2) /* SSL options are present */ +#define CURL_VERSION_LIBZ (1<<3) /* libz features are present */ +#define CURL_VERSION_NTLM (1<<4) /* NTLM auth is supported */ +#define CURL_VERSION_GSSNEGOTIATE (1<<5) /* Negotiate auth is supported + (deprecated) */ +#define CURL_VERSION_DEBUG (1<<6) /* Built with debug capabilities */ +#define CURL_VERSION_ASYNCHDNS (1<<7) /* Asynchronous DNS resolves */ +#define CURL_VERSION_SPNEGO (1<<8) /* SPNEGO auth is supported */ +#define CURL_VERSION_LARGEFILE (1<<9) /* Supports files larger than 2GB */ +#define CURL_VERSION_IDN (1<<10) /* Internationized Domain Names are + supported */ +#define CURL_VERSION_SSPI (1<<11) /* Built against Windows SSPI */ +#define CURL_VERSION_CONV (1<<12) /* Character conversions supported */ +#define CURL_VERSION_CURLDEBUG (1<<13) /* Debug memory tracking supported */ +#define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */ +#define CURL_VERSION_NTLM_WB (1<<15) /* NTLM delegation to winbind helper + is suported */ +#define CURL_VERSION_HTTP2 (1<<16) /* HTTP2 support built-in */ +#define CURL_VERSION_GSSAPI (1<<17) /* Built against a GSS-API library */ +#define CURL_VERSION_KERBEROS5 (1<<18) /* Kerberos V5 auth is supported */ +#define CURL_VERSION_UNIX_SOCKETS (1<<19) /* Unix domain sockets support */ +#define CURL_VERSION_PSL (1<<20) /* Mozilla's Public Suffix List, used + for cookie domain verification */ ++#define CURL_VERSION_HTTPS_PROXY (1<<21) /* HTTPS-proxy support built-in */ + + /* + * NAME curl_version_info() + * + * DESCRIPTION + * + * This function returns a pointer to a static copy of the version info + * struct. See above. + */ +CURL_EXTERN curl_version_info_data *curl_version_info(CURLversion); + +/* + * NAME curl_easy_strerror() + * + * DESCRIPTION + * + * The curl_easy_strerror function may be used to turn a CURLcode value + * into the equivalent human readable error string. This is useful + * for printing meaningful error messages. + */ +CURL_EXTERN const char *curl_easy_strerror(CURLcode); + +/* + * NAME curl_share_strerror() + * + * DESCRIPTION + * + * The curl_share_strerror function may be used to turn a CURLSHcode value + * into the equivalent human readable error string. This is useful + * for printing meaningful error messages. + */ +CURL_EXTERN const char *curl_share_strerror(CURLSHcode); + +/* + * NAME curl_easy_pause() + * + * DESCRIPTION + * + * The curl_easy_pause function pauses or unpauses transfers. Select the new + * state by setting the bitmask, use the convenience defines below. + * + */ +CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask); + +#define CURLPAUSE_RECV (1<<0) +#define CURLPAUSE_RECV_CONT (0) + +#define CURLPAUSE_SEND (1<<2) +#define CURLPAUSE_SEND_CONT (0) + +#define CURLPAUSE_ALL (CURLPAUSE_RECV|CURLPAUSE_SEND) +#define CURLPAUSE_CONT (CURLPAUSE_RECV_CONT|CURLPAUSE_SEND_CONT) + +#ifdef __cplusplus +} +#endif + +/* unfortunately, the easy.h and multi.h include files need options and info + stuff before they can be included! */ +#include "easy.h" /* nothing in curl is fun without the easy stuff */ +#include "multi.h" + +/* the typechecker doesn't work in C++ (yet) */ +#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \ + ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && \ + !defined(__cplusplus) && !defined(CURL_DISABLE_TYPECHECK) +#include "typecheck-gcc.h" +#else +#if defined(__STDC__) && (__STDC__ >= 1) +#if 0 /* Triggers clang -Wdisabled-macro-expansion, skip for CMake. */ +/* This preprocessor magic that replaces a call with the exact same call is + only done to make sure application authors pass exactly three arguments + to these functions. */ +#define curl_easy_setopt(handle,opt,param) curl_easy_setopt(handle,opt,param) +#define curl_easy_getinfo(handle,info,arg) curl_easy_getinfo(handle,info,arg) +#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param) +#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param) +#endif +#endif /* __STDC__ >= 1 */ +#endif /* gcc >= 4.3 && !__cplusplus */ + +#endif /* __CURL_CURL_H */ diff --cc Utilities/cmcurl/include/curl/curlver.h index 2415d1a,0000000..3967ad2 mode 100644,000000..100644 --- a/Utilities/cmcurl/include/curl/curlver.h +++ b/Utilities/cmcurl/include/curl/curlver.h @@@ -1,77 -1,0 +1,77 @@@ +#ifndef __CURL_CURLVER_H +#define __CURL_CURLVER_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* This header file contains nothing but libcurl version info, generated by + a script at release-time. This was made its own header file in 7.11.2 */ + +/* This is the global package copyright */ +#define LIBCURL_COPYRIGHT "1996 - 2016 Daniel Stenberg, ." + +/* This is the version number of the libcurl package from which this header + file origins: */ - #define LIBCURL_VERSION "7.51.0" ++#define LIBCURL_VERSION "7.52.1" + +/* The numeric version number is also available "in parts" by using these + defines: */ +#define LIBCURL_VERSION_MAJOR 7 - #define LIBCURL_VERSION_MINOR 51 - #define LIBCURL_VERSION_PATCH 0 ++#define LIBCURL_VERSION_MINOR 52 ++#define LIBCURL_VERSION_PATCH 1 + +/* This is the numeric version of the libcurl version number, meant for easier + parsing and comparions by programs. The LIBCURL_VERSION_NUM define will + always follow this syntax: + + 0xXXYYZZ + + Where XX, YY and ZZ are the main version, release and patch numbers in + hexadecimal (using 8 bits each). All three numbers are always represented + using two digits. 1.2 would appear as "0x010200" while version 9.11.7 + appears as "0x090b07". + + This 6-digit (24 bits) hexadecimal number does not show pre-release number, + and it is always a greater number in a more recent release. It makes + comparisons with greater than and less than work. + + Note: This define is the full hex number and _does not_ use the + CURL_VERSION_BITS() macro since curl's own configure script greps for it + and needs it to contain the full number. +*/ - #define LIBCURL_VERSION_NUM 0x073300 ++#define LIBCURL_VERSION_NUM 0x073401 + +/* + * This is the date and time when the full source package was created. The + * timestamp is not stored in git, as the timestamp is properly set in the + * tarballs by the maketgz script. + * + * The format of the date should follow this template: + * + * "Mon Feb 12 11:35:33 UTC 2007" + */ +#define LIBCURL_TIMESTAMP "DEV" + +#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|z) +#define CURL_AT_LEAST_VERSION(x,y,z) \ + (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z)) + +#endif /* __CURL_CURLVER_H */ diff --cc Utilities/cmcurl/lib/curl_setup.h index 4eb17a1,0000000..c861e97 mode 100644,000000..100644 --- a/Utilities/cmcurl/lib/curl_setup.h +++ b/Utilities/cmcurl/lib/curl_setup.h @@@ -1,780 -1,0 +1,780 @@@ +#ifndef HEADER_CURL_SETUP_H +#define HEADER_CURL_SETUP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Define WIN32 when build target is Win32 API + */ + +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) && \ + !defined(__SYMBIAN32__) +#define WIN32 +#endif + +/* + * Include configuration script results or hand-crafted + * configuration file for platforms which lack config tool. + */ + +#ifdef HAVE_CONFIG_H + +#include "curl_config.h" + +#else /* HAVE_CONFIG_H */ + +#ifdef _WIN32_WCE +# include "config-win32ce.h" +#else +# ifdef WIN32 +# include "config-win32.h" +# endif +#endif + +#if defined(macintosh) && defined(__MRC__) +# include "config-mac.h" +#endif + +#ifdef __riscos__ +# include "config-riscos.h" +#endif + +#ifdef __AMIGA__ +# include "config-amigaos.h" +#endif + +#ifdef __SYMBIAN32__ +# include "config-symbian.h" +#endif + +#ifdef __OS400__ +# include "config-os400.h" +#endif + +#ifdef TPF +# include "config-tpf.h" +#endif + +#ifdef __VXWORKS__ +# include "config-vxworks.h" +#endif + +#endif /* HAVE_CONFIG_H */ + +#if defined(_MSC_VER) +# pragma warning(push,1) +#endif + +/* ================================================================ */ +/* Definition of preprocessor macros/symbols which modify compiler */ +/* behavior or generated code characteristics must be done here, */ +/* as appropriate, before any system header file is included. It is */ +/* also possible to have them defined in the config file included */ +/* before this point. As a result of all this we frown inclusion of */ +/* system header files in our config files, avoid this at any cost. */ +/* ================================================================ */ + +/* + * AIX 4.3 and newer needs _THREAD_SAFE defined to build + * proper reentrant code. Others may also need it. + */ + +#ifdef NEED_THREAD_SAFE +# ifndef _THREAD_SAFE +# define _THREAD_SAFE +# endif +#endif + +/* + * Tru64 needs _REENTRANT set for a few function prototypes and + * things to appear in the system header files. Unixware needs it + * to build proper reentrant code. Others may also need it. + */ + +#ifdef NEED_REENTRANT +# ifndef _REENTRANT +# define _REENTRANT +# endif +#endif + +/* Solaris needs this to get a POSIX-conformant getpwuid_r */ +#if defined(sun) || defined(__sun) +# ifndef _POSIX_PTHREAD_SEMANTICS +# define _POSIX_PTHREAD_SEMANTICS 1 +# endif +#endif + +/* ================================================================ */ +/* If you need to include a system header file for your platform, */ +/* please, do it beyond the point further indicated in this file. */ +/* ================================================================ */ + +/* + * libcurl's external interface definitions are also used internally, + * and might also include required system header files to define them. + */ + +#include + +/* + * Compile time sanity checks must also be done when building the library. + */ + +#include + +/* + * Ensure that no one is using the old SIZEOF_CURL_OFF_T macro + */ + +#ifdef SIZEOF_CURL_OFF_T +# error "SIZEOF_CURL_OFF_T shall not be defined!" + Error Compilation_aborted_SIZEOF_CURL_OFF_T_shall_not_be_defined +#endif + +/* + * Disable other protocols when http is the only one desired. + */ + +#ifdef HTTP_ONLY +# ifndef CURL_DISABLE_TFTP +# define CURL_DISABLE_TFTP +# endif +# ifndef CURL_DISABLE_FTP +# define CURL_DISABLE_FTP +# endif +# ifndef CURL_DISABLE_LDAP +# define CURL_DISABLE_LDAP +# endif +# ifndef CURL_DISABLE_TELNET +# define CURL_DISABLE_TELNET +# endif +# ifndef CURL_DISABLE_DICT +# define CURL_DISABLE_DICT +# endif +# ifndef CURL_DISABLE_FILE +# define CURL_DISABLE_FILE +# endif +# ifndef CURL_DISABLE_RTSP +# define CURL_DISABLE_RTSP +# endif +# ifndef CURL_DISABLE_POP3 +# define CURL_DISABLE_POP3 +# endif +# ifndef CURL_DISABLE_IMAP +# define CURL_DISABLE_IMAP +# endif +# ifndef CURL_DISABLE_SMTP +# define CURL_DISABLE_SMTP +# endif +# ifndef CURL_DISABLE_RTMP +# define CURL_DISABLE_RTMP +# endif +# ifndef CURL_DISABLE_GOPHER +# define CURL_DISABLE_GOPHER +# endif +# ifndef CURL_DISABLE_SMB +# define CURL_DISABLE_SMB +# endif +#endif + +/* + * When http is disabled rtsp is not supported. + */ + +#if defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_RTSP) +# define CURL_DISABLE_RTSP +#endif + +/* ================================================================ */ +/* No system header file shall be included in this file before this */ +/* point. The only allowed ones are those included from curlbuild.h */ +/* ================================================================ */ + +/* + * OS/400 setup file includes some system headers. + */ + +#ifdef __OS400__ +# include "setup-os400.h" +#endif + +/* + * VMS setup file includes some system headers. + */ + +#ifdef __VMS +# include "setup-vms.h" +#endif + +/* + * Use getaddrinfo to resolve the IPv4 address literal. If the current network + * interface doesn???t support IPv4, but supports IPv6, NAT64, and DNS64, + * performing this task will result in a synthesized IPv6 address. + */ +#ifdef __APPLE__ +#define USE_RESOLVE_ON_IPS 1 +#endif + +/* + * Include header files for windows builds before redefining anything. + * Use this preprocessor block only to include or exclude windows.h, + * winsock2.h, ws2tcpip.h or winsock.h. Any other windows thing belongs + * to any other further and independent block. Under Cygwin things work + * just as under linux (e.g. ) and the winsock headers should + * never be included when __CYGWIN__ is defined. configure script takes + * care of this, not defining HAVE_WINDOWS_H, HAVE_WINSOCK_H, HAVE_WINSOCK2_H, + * neither HAVE_WS2TCPIP_H when __CYGWIN__ is defined. + */ + +#ifdef HAVE_WINDOWS_H +# if defined(UNICODE) && !defined(_UNICODE) +# define _UNICODE +# endif +# if defined(_UNICODE) && !defined(UNICODE) +# define UNICODE +# endif +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include +# ifdef HAVE_WINSOCK2_H +# include +# ifdef HAVE_WS2TCPIP_H +# include +# endif +# else +# ifdef HAVE_WINSOCK_H +# include +# endif +# endif +# include +# ifdef UNICODE + typedef wchar_t *(*curl_wcsdup_callback)(const wchar_t *str); +# endif +#endif + +/* + * Define USE_WINSOCK to 2 if we have and use WINSOCK2 API, else + * define USE_WINSOCK to 1 if we have and use WINSOCK API, else + * undefine USE_WINSOCK. + */ + +#undef USE_WINSOCK + +#ifdef HAVE_WINSOCK2_H +# define USE_WINSOCK 2 +#else +# ifdef HAVE_WINSOCK_H +# define USE_WINSOCK 1 +# endif +#endif + +#ifdef USE_LWIPSOCK +# include +# include +# include +#endif + +#ifdef HAVE_EXTRA_STRICMP_H +# include +#endif + +#ifdef HAVE_EXTRA_STRDUP_H +# include +#endif + +#ifdef TPF +# include /* for bzero, strcasecmp, and strncasecmp */ +# include /* for strcpy and strlen */ +# include /* for rand and srand */ +# include /* for select and ioctl*/ +# include /* for in_addr_t definition */ +# include /* for tpf_process_signals */ + /* change which select is used for libcurl */ +# define select(a,b,c,d,e) tpf_select_libcurl(a,b,c,d,e) +#endif + +#ifdef __VXWORKS__ +# include /* for generic BSD socket functions */ +# include /* for basic I/O interface functions */ +#endif + +#ifdef __AMIGA__ +# ifndef __ixemul__ +# include +# include +# include +# include +# define select(a,b,c,d,e) WaitSelect(a,b,c,d,e,0) +# endif +#endif + +#include +#ifdef HAVE_ASSERT_H +#include +#endif + +#ifdef __TANDEM /* for nsr-tandem-nsk systems */ +#include +#endif + +#ifndef STDC_HEADERS /* no standard C headers! */ +#include +#endif + +#ifdef __POCC__ +# include +# include +# define sys_nerr EILSEQ +#endif + +/* + * Salford-C kludge section (mostly borrowed from wxWidgets). + */ +#ifdef __SALFORDC__ + #pragma suppress 353 /* Possible nested comments */ + #pragma suppress 593 /* Define not used */ + #pragma suppress 61 /* enum has no name */ + #pragma suppress 106 /* unnamed, unused parameter */ + #include +#endif + +/* Default Windows file API selection. */ +#ifdef _WIN32 +# if defined(_MSC_VER) && (_INTEGRAL_MAX_BITS >= 64) +# define USE_WIN32_LARGE_FILES +# elif defined(__MINGW32__) +# define USE_WIN32_LARGE_FILES +# else +# define USE_WIN32_SMALL_FILES +# endif +#endif + +/* + * Large file (>2Gb) support using WIN32 functions. + */ + +#ifdef USE_WIN32_LARGE_FILES +# include +# include +# include +# undef lseek +# define lseek(fdes,offset,whence) _lseeki64(fdes, offset, whence) +# undef fstat +# define fstat(fdes,stp) _fstati64(fdes, stp) +# undef stat +# define stat(fname,stp) _stati64(fname, stp) +# define struct_stat struct _stati64 +# define LSEEK_ERROR (__int64)-1 +#endif + +/* + * Small file (<2Gb) support using WIN32 functions. + */ + +#ifdef USE_WIN32_SMALL_FILES +# include +# include +# include +# ifndef _WIN32_WCE +# undef lseek +# define lseek(fdes,offset,whence) _lseek(fdes, (long)offset, whence) +# define fstat(fdes,stp) _fstat(fdes, stp) +# define stat(fname,stp) _stat(fname, stp) +# define struct_stat struct _stat +# endif +# define LSEEK_ERROR (long)-1 +#endif + +#ifndef struct_stat +# define struct_stat struct stat +#endif + +#ifndef LSEEK_ERROR +# define LSEEK_ERROR (off_t)-1 +#endif + +/* + * Default sizeof(off_t) in case it hasn't been defined in config file. + */ + +#ifndef SIZEOF_OFF_T +# if defined(__VMS) && !defined(__VAX) +# if defined(_LARGEFILE) +# define SIZEOF_OFF_T 8 +# endif +# elif defined(__OS400__) && defined(__ILEC400__) +# if defined(_LARGE_FILES) +# define SIZEOF_OFF_T 8 +# endif +# elif defined(__MVS__) && defined(__IBMC__) +# if defined(_LP64) || defined(_LARGE_FILES) +# define SIZEOF_OFF_T 8 +# endif +# elif defined(__370__) && defined(__IBMC__) +# if defined(_LP64) || defined(_LARGE_FILES) +# define SIZEOF_OFF_T 8 +# endif +# endif +# ifndef SIZEOF_OFF_T +# define SIZEOF_OFF_T 4 +# endif +#endif + +/* + * Arg 2 type for gethostname in case it hasn't been defined in config file. + */ + +#ifndef GETHOSTNAME_TYPE_ARG2 +# ifdef USE_WINSOCK +# define GETHOSTNAME_TYPE_ARG2 int +# else +# define GETHOSTNAME_TYPE_ARG2 size_t +# endif +#endif + +/* Below we define some functions. They should + + 4. set the SIGALRM signal timeout + 5. set dir/file naming defines + */ + +#ifdef WIN32 + +# define DIR_CHAR "\\" +# define DOT_CHAR "_" + +#else /* WIN32 */ + +# ifdef MSDOS /* Watt-32 */ + +# include +# define select(n,r,w,x,t) select_s(n,r,w,x,t) +# define ioctl(x,y,z) ioctlsocket(x,y,(char *)(z)) +# include +# ifdef word +# undef word +# endif +# ifdef byte +# undef byte +# endif + +# endif /* MSDOS */ + +# ifdef __minix + /* Minix 3 versions up to at least 3.1.3 are missing these prototypes */ - extern char * strtok_r(char *s, const char *delim, char **last); - extern struct tm * gmtime_r(const time_t * const timep, struct tm *tmp); ++ extern char *strtok_r(char *s, const char *delim, char **last); ++ extern struct tm *gmtime_r(const time_t * const timep, struct tm *tmp); +# endif + +# define DIR_CHAR "/" +# ifndef DOT_CHAR +# define DOT_CHAR "." +# endif + +# ifdef MSDOS +# undef DOT_CHAR +# define DOT_CHAR "_" +# endif + +# ifndef fileno /* sunos 4 have this as a macro! */ + int fileno(FILE *stream); +# endif + +#endif /* WIN32 */ + +/* + * msvc 6.0 requires PSDK in order to have INET6_ADDRSTRLEN + * defined in ws2tcpip.h as well as to provide IPv6 support. + * Does not apply if lwIP is used. + */ + +#if defined(_MSC_VER) && !defined(__POCC__) && !defined(USE_LWIPSOCK) +# if !defined(HAVE_WS2TCPIP_H) || \ + ((_MSC_VER < 1300) && !defined(INET6_ADDRSTRLEN)) +# undef HAVE_GETADDRINFO_THREADSAFE +# undef HAVE_FREEADDRINFO +# undef HAVE_GETADDRINFO +# undef HAVE_GETNAMEINFO +# undef ENABLE_IPV6 +# endif +#endif + +/* ---------------------------------------------------------------- */ +/* resolver specialty compile-time defines */ +/* CURLRES_* defines to use in the host*.c sources */ +/* ---------------------------------------------------------------- */ + +/* + * lcc-win32 doesn't have _beginthreadex(), lacks threads support. + */ + +#if defined(__LCC__) && defined(WIN32) +# undef USE_THREADS_POSIX +# undef USE_THREADS_WIN32 +#endif + +/* + * MSVC threads support requires a multi-threaded runtime library. + * _beginthreadex() is not available in single-threaded ones. + */ + +#if defined(_MSC_VER) && !defined(__POCC__) && !defined(_MT) +# undef USE_THREADS_POSIX +# undef USE_THREADS_WIN32 +#endif + +/* + * Mutually exclusive CURLRES_* definitions. + */ + +#ifdef USE_ARES +# define CURLRES_ASYNCH +# define CURLRES_ARES +/* now undef the stock libc functions just to avoid them being used */ +# undef HAVE_GETADDRINFO +# undef HAVE_FREEADDRINFO +# undef HAVE_GETHOSTBYNAME +#elif defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) +# define CURLRES_ASYNCH +# define CURLRES_THREADED +#else +# define CURLRES_SYNCH +#endif + +#ifdef ENABLE_IPV6 +# define CURLRES_IPV6 +#else +# define CURLRES_IPV4 +#endif + +/* ---------------------------------------------------------------- */ + +/* + * When using WINSOCK, TELNET protocol requires WINSOCK2 API. + */ + +#if defined(USE_WINSOCK) && (USE_WINSOCK != 2) +# define CURL_DISABLE_TELNET 1 +#endif + +/* + * msvc 6.0 does not have struct sockaddr_storage and + * does not define IPPROTO_ESP in winsock2.h. But both + * are available if PSDK is properly installed. + */ + +#if defined(_MSC_VER) && !defined(__POCC__) +# if !defined(HAVE_WINSOCK2_H) || ((_MSC_VER < 1300) && !defined(IPPROTO_ESP)) +# undef HAVE_STRUCT_SOCKADDR_STORAGE +# endif +#endif + +/* + * Intentionally fail to build when using msvc 6.0 without PSDK installed. + * The brave of heart can circumvent this, defining ALLOW_MSVC6_WITHOUT_PSDK + * in lib/config-win32.h although absolutely discouraged and unsupported. + */ + +#if defined(_MSC_VER) && !defined(__POCC__) +# if !defined(HAVE_WINDOWS_H) || ((_MSC_VER < 1300) && !defined(_FILETIME_)) +# if !defined(ALLOW_MSVC6_WITHOUT_PSDK) +# error MSVC 6.0 requires "February 2003 Platform SDK" a.k.a. \ + "Windows Server 2003 PSDK" +# else +# define CURL_DISABLE_LDAP 1 +# endif +# endif +#endif + +#ifdef NETWARE +int netware_init(void); +#ifndef __NOVELL_LIBC__ +#include +#include +#endif +#endif + +#if defined(HAVE_LIBIDN2) && defined(HAVE_IDN2_H) +/* The lib and header are present */ +#define USE_LIBIDN2 +#endif + +#ifndef SIZEOF_TIME_T +/* assume default size of time_t to be 32 bit */ +#define SIZEOF_TIME_T 4 +#endif + +#define LIBIDN_REQUIRED_VERSION "0.4.1" + +#if defined(USE_GNUTLS) || defined(USE_OPENSSL) || defined(USE_NSS) || \ + defined(USE_POLARSSL) || defined(USE_AXTLS) || defined(USE_MBEDTLS) || \ + defined(USE_CYASSL) || defined(USE_SCHANNEL) || \ + defined(USE_DARWINSSL) || defined(USE_GSKIT) +#define USE_SSL /* SSL support has been enabled */ +#endif + +/* Single point where USE_SPNEGO definition might be defined */ +#if !defined(CURL_DISABLE_CRYPTO_AUTH) && \ + (defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)) +#define USE_SPNEGO +#endif + +/* Single point where USE_KERBEROS5 definition might be defined */ +#if !defined(CURL_DISABLE_CRYPTO_AUTH) && \ + (defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)) +#define USE_KERBEROS5 +#endif + +/* Single point where USE_NTLM definition might be defined */ +#if !defined(CURL_DISABLE_NTLM) && !defined(CURL_DISABLE_CRYPTO_AUTH) +#if defined(USE_OPENSSL) || defined(USE_WINDOWS_SSPI) || \ + defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_DARWINSSL) || \ + defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) + +#define USE_NTLM + +#elif defined(USE_MBEDTLS) +# include +# if defined(MBEDTLS_MD4_C) +#define USE_NTLM +# endif + +#endif +#endif + +/* non-configure builds may define CURL_WANTS_CA_BUNDLE_ENV */ +#if defined(CURL_WANTS_CA_BUNDLE_ENV) && !defined(CURL_CA_BUNDLE) +#define CURL_CA_BUNDLE getenv("CURL_CA_BUNDLE") +#endif + +/* + * Provide a mechanism to silence picky compilers, such as gcc 4.6+. + * Parameters should of course normally not be unused, but for example when + * we have multiple implementations of the same interface it may happen. + */ + +#if defined(__GNUC__) && ((__GNUC__ >= 3) || \ + ((__GNUC__ == 2) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 7))) +# define UNUSED_PARAM __attribute__((__unused__)) +# define WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +#else +# define UNUSED_PARAM /*NOTHING*/ +# define WARN_UNUSED_RESULT +#endif + +/* + * Include macros and defines that should only be processed once. + */ + +#ifndef HEADER_CURL_SETUP_ONCE_H +#include "curl_setup_once.h" +#endif + +/* + * Definition of our NOP statement Object-like macro + */ + +#ifndef Curl_nop_stmt +# define Curl_nop_stmt do { } WHILE_FALSE +#endif + +/* + * Ensure that Winsock and lwIP TCP/IP stacks are not mixed. + */ + +#if defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H) +# if defined(SOCKET) || \ + defined(USE_WINSOCK) || \ + defined(HAVE_WINSOCK_H) || \ + defined(HAVE_WINSOCK2_H) || \ + defined(HAVE_WS2TCPIP_H) +# error "Winsock and lwIP TCP/IP stack definitions shall not coexist!" +# endif +#endif + +/* + * Portable symbolic names for Winsock shutdown() mode flags. + */ + +#ifdef USE_WINSOCK +# define SHUT_RD 0x00 +# define SHUT_WR 0x01 +# define SHUT_RDWR 0x02 +#endif + +/* Define S_ISREG if not defined by system headers, f.e. MSVC */ +#if !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG) +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#endif + +/* Define S_ISDIR if not defined by system headers, f.e. MSVC */ +#if !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#endif + +/* In Windows the default file mode is text but an application can override it. +Therefore we specify it explicitly. https://github.com/curl/curl/pull/258 +*/ +#if defined(WIN32) || defined(MSDOS) +#define FOPEN_READTEXT "rt" +#define FOPEN_WRITETEXT "wt" +#elif defined(__CYGWIN__) +/* Cygwin has specific behavior we need to address when WIN32 is not defined. +https://cygwin.com/cygwin-ug-net/using-textbinary.html +For write we want our output to have line endings of LF and be compatible with +other Cygwin utilities. For read we want to handle input that may have line +endings either CRLF or LF so 't' is appropriate. +*/ +#define FOPEN_READTEXT "rt" +#define FOPEN_WRITETEXT "w" +#else +#define FOPEN_READTEXT "r" +#define FOPEN_WRITETEXT "w" +#endif + +/* WinSock destroys recv() buffer when send() failed. + * Enabled automatically for Windows and for Cygwin as Cygwin sockets are + * wrappers for WinSock sockets. https://github.com/curl/curl/issues/657 + * Define DONT_USE_RECV_BEFORE_SEND_WORKAROUND to force disable workaround. + */ +#if !defined(DONT_USE_RECV_BEFORE_SEND_WORKAROUND) +# if defined(WIN32) || defined(__CYGWIN__) +# define USE_RECV_BEFORE_SEND_WORKAROUND +# endif +#else /* DONT_USE_RECV_BEFORE_SEND_WORKAROUNDS */ +# ifdef USE_RECV_BEFORE_SEND_WORKAROUND +# undef USE_RECV_BEFORE_SEND_WORKAROUND +# endif +#endif /* DONT_USE_RECV_BEFORE_SEND_WORKAROUNDS */ + +/* Detect Windows App environment which has a restricted access + * to the Win32 APIs. */ +# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602) +# include +# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \ + !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +# define CURL_WINDOWS_APP +# endif +# endif + +#endif /* HEADER_CURL_SETUP_H */ diff --cc Utilities/cmcurl/lib/ftp.c index 9d0a03c,0000000..89c7e40 mode 100644,000000..100644 --- a/Utilities/cmcurl/lib/ftp.c +++ b/Utilities/cmcurl/lib/ftp.c @@@ -1,4609 -1,0 +1,4549 @@@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifndef CURL_DISABLE_FTP + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_UTSNAME_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef __VMS +#include +#include +#endif + +#if (defined(NETWARE) && defined(__NOVELL_LIBC__)) +#undef in_addr_t +#define in_addr_t unsigned long +#endif + +#include +#include "urldata.h" +#include "sendf.h" +#include "if2ip.h" +#include "hostip.h" +#include "progress.h" +#include "transfer.h" +#include "escape.h" +#include "http.h" /* for HTTP proxy tunnel stuff */ +#include "socks.h" +#include "ftp.h" +#include "fileinfo.h" +#include "ftplistparser.h" +#include "curl_sec.h" +#include "strtoofft.h" +#include "strcase.h" +#include "vtls/vtls.h" +#include "connect.h" +#include "strerror.h" +#include "inet_ntop.h" +#include "inet_pton.h" +#include "select.h" +#include "parsedate.h" /* for the week day and month names */ +#include "sockaddr.h" /* required for Curl_sockaddr_storage */ +#include "multiif.h" +#include "url.h" +#include "strcase.h" +#include "speedcheck.h" +#include "warnless.h" +#include "http_proxy.h" +#include "non-ascii.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#ifndef NI_MAXHOST +#define NI_MAXHOST 1025 +#endif +#ifndef INET_ADDRSTRLEN +#define INET_ADDRSTRLEN 16 +#endif + +#ifdef CURL_DISABLE_VERBOSE_STRINGS +#define ftp_pasv_verbose(a,b,c,d) Curl_nop_stmt +#endif + +/* Local API functions */ +#ifndef DEBUGBUILD +static void _state(struct connectdata *conn, + ftpstate newstate); +#define state(x,y) _state(x,y) +#else +static void _state(struct connectdata *conn, + ftpstate newstate, + int lineno); +#define state(x,y) _state(x,y,__LINE__) +#endif + +static CURLcode ftp_sendquote(struct connectdata *conn, + struct curl_slist *quote); +static CURLcode ftp_quit(struct connectdata *conn); +static CURLcode ftp_parse_url_path(struct connectdata *conn); +static CURLcode ftp_regular_transfer(struct connectdata *conn, bool *done); +#ifndef CURL_DISABLE_VERBOSE_STRINGS +static void ftp_pasv_verbose(struct connectdata *conn, + Curl_addrinfo *ai, + char *newhost, /* ascii version */ + int port); +#endif +static CURLcode ftp_state_prepare_transfer(struct connectdata *conn); +static CURLcode ftp_state_mdtm(struct connectdata *conn); +static CURLcode ftp_state_quote(struct connectdata *conn, + bool init, ftpstate instate); +static CURLcode ftp_nb_type(struct connectdata *conn, + bool ascii, ftpstate newstate); +static int ftp_need_type(struct connectdata *conn, + bool ascii); +static CURLcode ftp_do(struct connectdata *conn, bool *done); +static CURLcode ftp_done(struct connectdata *conn, + CURLcode, bool premature); +static CURLcode ftp_connect(struct connectdata *conn, bool *done); +static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection); +static CURLcode ftp_do_more(struct connectdata *conn, int *completed); +static CURLcode ftp_multi_statemach(struct connectdata *conn, bool *done); +static int ftp_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); +static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); +static CURLcode ftp_doing(struct connectdata *conn, + bool *dophase_done); +static CURLcode ftp_setup_connection(struct connectdata * conn); + +static CURLcode init_wc_data(struct connectdata *conn); +static CURLcode wc_statemach(struct connectdata *conn); + +static void wc_data_dtor(void *ptr); + +static CURLcode ftp_state_retr(struct connectdata *conn, curl_off_t filesize); + +static CURLcode ftp_readresp(curl_socket_t sockfd, + struct pingpong *pp, + int *ftpcode, + size_t *size); +static CURLcode ftp_dophase_done(struct connectdata *conn, + bool connected); + +/* easy-to-use macro: */ +#define PPSENDF(x,y,z) result = Curl_pp_sendf(x,y,z); \ + if(result) \ + return result + + +/* + * FTP protocol handler. + */ + +const struct Curl_handler Curl_handler_ftp = { + "FTP", /* scheme */ + ftp_setup_connection, /* setup_connection */ + ftp_do, /* do_it */ + ftp_done, /* done */ + ftp_do_more, /* do_more */ + ftp_connect, /* connect_it */ + ftp_multi_statemach, /* connecting */ + ftp_doing, /* doing */ + ftp_getsock, /* proto_getsock */ + ftp_getsock, /* doing_getsock */ + ftp_domore_getsock, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ftp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_FTP, /* defport */ + CURLPROTO_FTP, /* protocol */ + PROTOPT_DUAL | PROTOPT_CLOSEACTION | PROTOPT_NEEDSPWD + | PROTOPT_NOURLQUERY /* flags */ +}; + + +#ifdef USE_SSL +/* + * FTPS protocol handler. + */ + +const struct Curl_handler Curl_handler_ftps = { + "FTPS", /* scheme */ + ftp_setup_connection, /* setup_connection */ + ftp_do, /* do_it */ + ftp_done, /* done */ + ftp_do_more, /* do_more */ + ftp_connect, /* connect_it */ + ftp_multi_statemach, /* connecting */ + ftp_doing, /* doing */ + ftp_getsock, /* proto_getsock */ + ftp_getsock, /* doing_getsock */ + ftp_domore_getsock, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ftp_disconnect, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_FTPS, /* defport */ + CURLPROTO_FTPS, /* protocol */ + PROTOPT_SSL | PROTOPT_DUAL | PROTOPT_CLOSEACTION | + PROTOPT_NEEDSPWD | PROTOPT_NOURLQUERY /* flags */ +}; +#endif + +#ifndef CURL_DISABLE_HTTP +/* + * HTTP-proxyed FTP protocol handler. + */ + +static const struct Curl_handler Curl_handler_ftp_proxy = { + "FTP", /* scheme */ + Curl_http_setup_conn, /* setup_connection */ + Curl_http, /* do_it */ + Curl_http_done, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_FTP, /* defport */ + CURLPROTO_HTTP, /* protocol */ + PROTOPT_NONE /* flags */ +}; + + +#ifdef USE_SSL +/* + * HTTP-proxyed FTPS protocol handler. + */ + +static const struct Curl_handler Curl_handler_ftps_proxy = { + "FTPS", /* scheme */ + Curl_http_setup_conn, /* setup_connection */ + Curl_http, /* do_it */ + Curl_http_done, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_getsock */ + ZERO_NULL, /* doing_getsock */ + ZERO_NULL, /* domore_getsock */ + ZERO_NULL, /* perform_getsock */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* readwrite */ + PORT_FTPS, /* defport */ + CURLPROTO_HTTP, /* protocol */ + PROTOPT_NONE /* flags */ +}; +#endif +#endif + +static void close_secondarysocket(struct connectdata *conn) +{ + if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) { + Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]); + conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; + } + conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE; + conn->tunnel_state[SECONDARYSOCKET] = TUNNEL_INIT; +} + +/* + * NOTE: back in the old days, we added code in the FTP code that made NOBODY + * requests on files respond with headers passed to the client/stdout that + * looked like HTTP ones. + * + * This approach is not very elegant, it causes confusion and is error-prone. + * It is subject for removal at the next (or at least a future) soname bump. + * Until then you can test the effects of the removal by undefining the + * following define named CURL_FTP_HTTPSTYLE_HEAD. + */ +#define CURL_FTP_HTTPSTYLE_HEAD 1 + +static void freedirs(struct ftp_conn *ftpc) +{ + int i; + if(ftpc->dirs) { + for(i=0; i < ftpc->dirdepth; i++) { + free(ftpc->dirs[i]); + ftpc->dirs[i]=NULL; + } + free(ftpc->dirs); + ftpc->dirs = NULL; + ftpc->dirdepth = 0; + } + Curl_safefree(ftpc->file); + + /* no longer of any use */ + Curl_safefree(ftpc->newhost); +} + +/* Returns non-zero if the given string contains CR (\r) or LF (\n), + which are not allowed within RFC 959 . + Note: The input string is in the client's encoding which might + not be ASCII, so escape sequences \r & \n must be used instead + of hex values 0x0d & 0x0a. +*/ +static bool isBadFtpString(const char *string) +{ + return ((NULL != strchr(string, '\r')) || + (NULL != strchr(string, '\n'))) ? TRUE : FALSE; +} + +/*********************************************************************** + * + * AcceptServerConnect() + * + * After connection request is received from the server this function is + * called to accept the connection and close the listening socket + * + */ +static CURLcode AcceptServerConnect(struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + curl_socket_t sock = conn->sock[SECONDARYSOCKET]; + curl_socket_t s = CURL_SOCKET_BAD; +#ifdef ENABLE_IPV6 + struct Curl_sockaddr_storage add; +#else + struct sockaddr_in add; +#endif + curl_socklen_t size = (curl_socklen_t) sizeof(add); + + if(0 == getsockname(sock, (struct sockaddr *) &add, &size)) { + size = sizeof(add); + + s=accept(sock, (struct sockaddr *) &add, &size); + } + Curl_closesocket(conn, sock); /* close the first socket */ + + if(CURL_SOCKET_BAD == s) { + failf(data, "Error accept()ing server connect"); + return CURLE_FTP_PORT_FAILED; + } + infof(data, "Connection accepted from server\n"); + /* when this happens within the DO state it is important that we mark us as + not needing DO_MORE anymore */ + conn->bits.do_more = FALSE; + + conn->sock[SECONDARYSOCKET] = s; + (void)curlx_nonblock(s, TRUE); /* enable non-blocking */ + conn->sock_accepted[SECONDARYSOCKET] = TRUE; + + if(data->set.fsockopt) { + int error = 0; + + /* activate callback for setting socket options */ + error = data->set.fsockopt(data->set.sockopt_client, + s, + CURLSOCKTYPE_ACCEPT); + + if(error) { + close_secondarysocket(conn); + return CURLE_ABORTED_BY_CALLBACK; + } + } + + return CURLE_OK; + +} + +/* + * ftp_timeleft_accept() returns the amount of milliseconds left allowed for + * waiting server to connect. If the value is negative, the timeout time has + * already elapsed. + * + * The start time is stored in progress.t_acceptdata - as set with + * Curl_pgrsTime(..., TIMER_STARTACCEPT); + * + */ - static long ftp_timeleft_accept(struct Curl_easy *data) ++static time_t ftp_timeleft_accept(struct Curl_easy *data) +{ - long timeout_ms = DEFAULT_ACCEPT_TIMEOUT; - long other; ++ time_t timeout_ms = DEFAULT_ACCEPT_TIMEOUT; ++ time_t other; + struct timeval now; + + if(data->set.accepttimeout > 0) + timeout_ms = data->set.accepttimeout; + + now = Curl_tvnow(); + + /* check if the generic timeout possibly is set shorter */ + other = Curl_timeleft(data, &now, FALSE); + if(other && (other < timeout_ms)) + /* note that this also works fine for when other happens to be negative + due to it already having elapsed */ + timeout_ms = other; + else { + /* subtract elapsed time */ + timeout_ms -= Curl_tvdiff(now, data->progress.t_acceptdata); + if(!timeout_ms) + /* avoid returning 0 as that means no timeout! */ + return -1; + } + + return timeout_ms; +} + + +/*********************************************************************** + * + * ReceivedServerConnect() + * + * After allowing server to connect to us from data port, this function + * checks both data connection for connection establishment and ctrl + * connection for a negative response regarding a failure in connecting + * + */ +static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received) +{ + struct Curl_easy *data = conn->data; + curl_socket_t ctrl_sock = conn->sock[FIRSTSOCKET]; + curl_socket_t data_sock = conn->sock[SECONDARYSOCKET]; + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + int result; - long timeout_ms; ++ time_t timeout_ms; + ssize_t nread; + int ftpcode; + + *received = FALSE; + + timeout_ms = ftp_timeleft_accept(data); + infof(data, "Checking for server connect\n"); + if(timeout_ms < 0) { + /* if a timeout was already reached, bail out */ + failf(data, "Accept timeout occurred while waiting server connect"); + return CURLE_FTP_ACCEPT_TIMEOUT; + } + + /* First check whether there is a cached response from server */ + if(pp->cache_size && pp->cache && pp->cache[0] > '3') { + /* Data connection could not be established, let's return */ + infof(data, "There is negative response in cache while serv connect\n"); + Curl_GetFTPResponse(&nread, conn, &ftpcode); + return CURLE_FTP_ACCEPT_FAILED; + } + + result = Curl_socket_check(ctrl_sock, data_sock, CURL_SOCKET_BAD, 0); + + /* see if the connection request is already here */ - switch (result) { ++ switch(result) { + case -1: /* error */ + /* let's die here */ + failf(data, "Error while waiting for server connect"); + return CURLE_FTP_ACCEPT_FAILED; + case 0: /* Server connect is not received yet */ + break; /* loop */ + default: + + if(result & CURL_CSELECT_IN2) { + infof(data, "Ready to accept data connection from server\n"); + *received = TRUE; + } + else if(result & CURL_CSELECT_IN) { + infof(data, "Ctrl conn has data while waiting for data conn\n"); + Curl_GetFTPResponse(&nread, conn, &ftpcode); + + if(ftpcode/100 > 3) + return CURLE_FTP_ACCEPT_FAILED; + + return CURLE_WEIRD_SERVER_REPLY; + } + + break; + } /* switch() */ + + return CURLE_OK; +} + + +/*********************************************************************** + * + * InitiateTransfer() + * + * After connection from server is accepted this function is called to + * setup transfer parameters and initiate the data transfer. + * + */ +static CURLcode InitiateTransfer(struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + struct FTP *ftp = data->req.protop; + CURLcode result = CURLE_OK; + - if(conn->ssl[SECONDARYSOCKET].use) { ++ if(conn->bits.ftp_use_data_ssl) { + /* since we only have a plaintext TCP connection here, we must now + * do the TLS stuff */ + infof(data, "Doing the SSL/TLS handshake on the data stream\n"); + result = Curl_ssl_connect(conn, SECONDARYSOCKET); + if(result) + return result; + } + + if(conn->proto.ftpc.state_saved == FTP_STOR) { + *(ftp->bytecountp)=0; + + /* When we know we're uploading a specified file, we can get the file + size prior to the actual upload. */ + + Curl_pgrsSetUploadSize(data, data->state.infilesize); + + /* set the SO_SNDBUF for the secondary socket for those who need it */ + Curl_sndbufset(conn->sock[SECONDARYSOCKET]); + + Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */ + SECONDARYSOCKET, ftp->bytecountp); + } + else { + /* FTP download: */ + Curl_setup_transfer(conn, SECONDARYSOCKET, + conn->proto.ftpc.retr_size_saved, FALSE, + ftp->bytecountp, -1, NULL); /* no upload here */ + } + + conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */ + state(conn, FTP_STOP); + + return CURLE_OK; +} + +/*********************************************************************** + * + * AllowServerConnect() + * + * When we've issue the PORT command, we have told the server to connect to + * us. This function checks whether data connection is established if so it is + * accepted. + * + */ +static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected) +{ + struct Curl_easy *data = conn->data; - long timeout_ms; ++ time_t timeout_ms; + CURLcode result = CURLE_OK; + + *connected = FALSE; + infof(data, "Preparing for accepting server on data port\n"); + + /* Save the time we start accepting server connect */ + Curl_pgrsTime(data, TIMER_STARTACCEPT); + + timeout_ms = ftp_timeleft_accept(data); + if(timeout_ms < 0) { + /* if a timeout was already reached, bail out */ + failf(data, "Accept timeout occurred while waiting server connect"); + return CURLE_FTP_ACCEPT_TIMEOUT; + } + + /* see if the connection request is already here */ + result = ReceivedServerConnect(conn, connected); + if(result) + return result; + + if(*connected) { + result = AcceptServerConnect(conn); + if(result) + return result; + + result = InitiateTransfer(conn); + if(result) + return result; + } + else { + /* Add timeout to multi handle and break out of the loop */ + if(!result && *connected == FALSE) { + if(data->set.accepttimeout > 0) + Curl_expire(data, data->set.accepttimeout); + else + Curl_expire(data, DEFAULT_ACCEPT_TIMEOUT); + } + } + + return result; +} + +/* macro to check for a three-digit ftp status code at the start of the + given string */ +#define STATUSCODE(line) (ISDIGIT(line[0]) && ISDIGIT(line[1]) && \ + ISDIGIT(line[2])) + +/* macro to check for the last line in an FTP server response */ +#define LASTLINE(line) (STATUSCODE(line) && (' ' == line[3])) + +static bool ftp_endofresp(struct connectdata *conn, char *line, size_t len, + int *code) +{ + (void)conn; + + if((len > 3) && LASTLINE(line)) { + *code = curlx_sltosi(strtol(line, NULL, 10)); + return TRUE; + } + + return FALSE; +} + +static CURLcode ftp_readresp(curl_socket_t sockfd, + struct pingpong *pp, + int *ftpcode, /* return the ftp-code if done */ + size_t *size) /* size of the response */ +{ + struct connectdata *conn = pp->conn; + struct Curl_easy *data = conn->data; +#ifdef HAVE_GSSAPI + char * const buf = data->state.buffer; +#endif + CURLcode result = CURLE_OK; + int code; + + result = Curl_pp_readresp(sockfd, pp, &code, size); + +#if defined(HAVE_GSSAPI) + /* handle the security-oriented responses 6xx ***/ + /* FIXME: some errorchecking perhaps... ***/ + switch(code) { + case 631: + code = Curl_sec_read_msg(conn, buf, PROT_SAFE); + break; + case 632: + code = Curl_sec_read_msg(conn, buf, PROT_PRIVATE); + break; + case 633: + code = Curl_sec_read_msg(conn, buf, PROT_CONFIDENTIAL); + break; + default: + /* normal ftp stuff we pass through! */ + break; + } +#endif + + /* store the latest code for later retrieval */ + data->info.httpcode=code; + + if(ftpcode) + *ftpcode = code; + + if(421 == code) { + /* 421 means "Service not available, closing control connection." and FTP + * servers use it to signal that idle session timeout has been exceeded. + * If we ignored the response, it could end up hanging in some cases. + * + * This response code can come at any point so having it treated + * generically is a good idea. + */ + infof(data, "We got a 421 - timeout!\n"); + state(conn, FTP_STOP); + return CURLE_OPERATION_TIMEDOUT; + } + + return result; +} + +/* --- parse FTP server responses --- */ + +/* + * Curl_GetFTPResponse() is a BLOCKING function to read the full response + * from a server after a command. + * + */ + +CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */ + struct connectdata *conn, + int *ftpcode) /* return the ftp-code */ +{ + /* + * We cannot read just one byte per read() and then go back to select() as + * the OpenSSL read() doesn't grok that properly. + * + * Alas, read as much as possible, split up into lines, use the ending + * line in a response or continue reading. */ + + curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; - long timeout; /* timeout in milliseconds */ - long interval_ms; ++ time_t timeout; /* timeout in milliseconds */ ++ time_t interval_ms; + struct Curl_easy *data = conn->data; + CURLcode result = CURLE_OK; + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + size_t nread; + int cache_skip=0; + int value_to_be_ignored=0; + + if(ftpcode) + *ftpcode = 0; /* 0 for errors */ + else + /* make the pointer point to something for the rest of this function */ + ftpcode = &value_to_be_ignored; + + *nreadp=0; + + while(!*ftpcode && !result) { + /* check and reset timeout value every lap */ + timeout = Curl_pp_state_timeout(pp); + + if(timeout <=0) { + failf(data, "FTP response timeout"); + return CURLE_OPERATION_TIMEDOUT; /* already too little time */ + } + + interval_ms = 1000; /* use 1 second timeout intervals */ + if(timeout < interval_ms) + interval_ms = timeout; + + /* + * Since this function is blocking, we need to wait here for input on the + * connection and only then we call the response reading function. We do + * timeout at least every second to make the timeout check run. + * + * A caution here is that the ftp_readresp() function has a cache that may + * contain pieces of a response from the previous invoke and we need to + * make sure we don't just wait for input while there is unhandled data in + * that cache. But also, if the cache is there, we call ftp_readresp() and + * the cache wasn't good enough to continue we must not just busy-loop + * around this function. + * + */ + + if(pp->cache && (cache_skip < 2)) { + /* + * There's a cache left since before. We then skipping the wait for + * socket action, unless this is the same cache like the previous round + * as then the cache was deemed not enough to act on and we then need to + * wait for more data anyway. + */ + } - else { - switch (SOCKET_READABLE(sockfd, interval_ms)) { ++ else if(!Curl_conn_data_pending(conn, FIRSTSOCKET)) { ++ switch(SOCKET_READABLE(sockfd, interval_ms)) { + case -1: /* select() error, stop reading */ + failf(data, "FTP response aborted due to select/poll error: %d", + SOCKERRNO); + return CURLE_RECV_ERROR; + + case 0: /* timeout */ + if(Curl_pgrsUpdate(conn)) + return CURLE_ABORTED_BY_CALLBACK; + continue; /* just continue in our loop for the timeout duration */ + + default: /* for clarity */ + break; + } + } + result = ftp_readresp(sockfd, pp, ftpcode, &nread); + if(result) + break; + + if(!nread && pp->cache) + /* bump cache skip counter as on repeated skips we must wait for more + data */ + cache_skip++; + else + /* when we got data or there is no cache left, we reset the cache skip + counter */ + cache_skip=0; + + *nreadp += nread; + + } /* while there's buffer left and loop is requested */ + + pp->pending_resp = FALSE; + + return result; +} + +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + /* for debug purposes */ +static const char * const ftp_state_names[]={ + "STOP", + "WAIT220", + "AUTH", + "USER", + "PASS", + "ACCT", + "PBSZ", + "PROT", + "CCC", + "PWD", + "SYST", + "NAMEFMT", + "QUOTE", + "RETR_PREQUOTE", + "STOR_PREQUOTE", + "POSTQUOTE", + "CWD", + "MKD", + "MDTM", + "TYPE", + "LIST_TYPE", + "RETR_TYPE", + "STOR_TYPE", + "SIZE", + "RETR_SIZE", + "STOR_SIZE", + "REST", + "RETR_REST", + "PORT", + "PRET", + "PASV", + "LIST", + "RETR", + "STOR", + "QUIT" +}; +#endif + +/* This is the ONLY way to change FTP state! */ +static void _state(struct connectdata *conn, + ftpstate newstate +#ifdef DEBUGBUILD + , int lineno +#endif + ) +{ + struct ftp_conn *ftpc = &conn->proto.ftpc; + +#if defined(DEBUGBUILD) + +#if defined(CURL_DISABLE_VERBOSE_STRINGS) + (void) lineno; +#else + if(ftpc->state != newstate) + infof(conn->data, "FTP %p (line %d) state change from %s to %s\n", + (void *)ftpc, lineno, ftp_state_names[ftpc->state], + ftp_state_names[newstate]); +#endif +#endif + + ftpc->state = newstate; +} + +static CURLcode ftp_state_user(struct connectdata *conn) +{ + CURLcode result; + struct FTP *ftp = conn->data->req.protop; + /* send USER */ + PPSENDF(&conn->proto.ftpc.pp, "USER %s", ftp->user?ftp->user:""); + + state(conn, FTP_USER); + conn->data->state.ftp_trying_alternative = FALSE; + + return CURLE_OK; +} + +static CURLcode ftp_state_pwd(struct connectdata *conn) +{ + CURLcode result; + + /* send PWD to discover our entry point */ + PPSENDF(&conn->proto.ftpc.pp, "%s", "PWD"); + state(conn, FTP_PWD); + + return CURLE_OK; +} + +/* For the FTP "protocol connect" and "doing" phases only */ +static int ftp_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks); +} + +/* For the FTP "DO_MORE" phase only */ +static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks) +{ + struct ftp_conn *ftpc = &conn->proto.ftpc; + + if(!numsocks) + return GETSOCK_BLANK; + + /* When in DO_MORE state, we could be either waiting for us to connect to a + * remote site, or we could wait for that site to connect to us. Or just + * handle ordinary commands. + */ + + if(FTP_STOP == ftpc->state) { + int bits = GETSOCK_READSOCK(0); + + /* if stopped and still in this state, then we're also waiting for a + connect on the secondary connection */ + socks[0] = conn->sock[FIRSTSOCKET]; + + if(!conn->data->set.ftp_use_port) { + int s; + int i; + /* PORT is used to tell the server to connect to us, and during that we + don't do happy eyeballs, but we do if we connect to the server */ + for(s=1, i=0; i<2; i++) { + if(conn->tempsock[i] != CURL_SOCKET_BAD) { + socks[s] = conn->tempsock[i]; + bits |= GETSOCK_WRITESOCK(s++); + } + } + } + else { + socks[1] = conn->sock[SECONDARYSOCKET]; + bits |= GETSOCK_WRITESOCK(1) | GETSOCK_READSOCK(1); + } + + return bits; + } + else + return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks); +} + +/* This is called after the FTP_QUOTE state is passed. + + ftp_state_cwd() sends the range of CWD commands to the server to change to + the correct directory. It may also need to send MKD commands to create + missing ones, if that option is enabled. +*/ +static CURLcode ftp_state_cwd(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + if(ftpc->cwddone) + /* already done and fine */ + result = ftp_state_mdtm(conn); + else { + ftpc->count2 = 0; /* count2 counts failed CWDs */ + + /* count3 is set to allow a MKD to fail once. In the case when first CWD + fails and then MKD fails (due to another session raced it to create the + dir) this then allows for a second try to CWD to it */ + ftpc->count3 = (conn->data->set.ftp_create_missing_dirs==2)?1:0; + + if(conn->bits.reuse && ftpc->entrypath) { + /* This is a re-used connection. Since we change directory to where the + transfer is taking place, we must first get back to the original dir + where we ended up after login: */ + ftpc->count1 = 0; /* we count this as the first path, then we add one + for all upcoming ones in the ftp->dirs[] array */ + PPSENDF(&conn->proto.ftpc.pp, "CWD %s", ftpc->entrypath); + state(conn, FTP_CWD); + } + else { + if(ftpc->dirdepth) { + ftpc->count1 = 1; + /* issue the first CWD, the rest is sent when the CWD responses are + received... */ + PPSENDF(&conn->proto.ftpc.pp, "CWD %s", ftpc->dirs[ftpc->count1 -1]); + state(conn, FTP_CWD); + } + else { + /* No CWD necessary */ + result = ftp_state_mdtm(conn); + } + } + } + return result; +} + +typedef enum { + EPRT, + PORT, + DONE +} ftpport; + +static CURLcode ftp_state_use_port(struct connectdata *conn, + ftpport fcmd) /* start with this */ + +{ + CURLcode result = CURLE_OK; + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct Curl_easy *data=conn->data; + curl_socket_t portsock= CURL_SOCKET_BAD; + char myhost[256] = ""; + + struct Curl_sockaddr_storage ss; + Curl_addrinfo *res, *ai; + curl_socklen_t sslen; + char hbuf[NI_MAXHOST]; + struct sockaddr *sa=(struct sockaddr *)&ss; + struct sockaddr_in * const sa4 = (void *)sa; +#ifdef ENABLE_IPV6 + struct sockaddr_in6 * const sa6 = (void *)sa; +#endif + char tmp[1024]; + static const char mode[][5] = { "EPRT", "PORT" }; + int rc; + int error; + char *host = NULL; + char *string_ftpport = data->set.str[STRING_FTPPORT]; + struct Curl_dns_entry *h=NULL; + unsigned short port_min = 0; + unsigned short port_max = 0; + unsigned short port; + bool possibly_non_local = TRUE; + + char *addr = NULL; + + /* Step 1, figure out what is requested, + * accepted format : + * (ipv4|ipv6|domain|interface)?(:port(-range)?)? + */ + + if(data->set.str[STRING_FTPPORT] && + (strlen(data->set.str[STRING_FTPPORT]) > 1)) { + +#ifdef ENABLE_IPV6 + size_t addrlen = INET6_ADDRSTRLEN > strlen(string_ftpport) ? + INET6_ADDRSTRLEN : strlen(string_ftpport); +#else + size_t addrlen = INET_ADDRSTRLEN > strlen(string_ftpport) ? + INET_ADDRSTRLEN : strlen(string_ftpport); +#endif + char *ip_start = string_ftpport; + char *ip_end = NULL; + char *port_start = NULL; + char *port_sep = NULL; + + addr = calloc(addrlen+1, 1); + if(!addr) + return CURLE_OUT_OF_MEMORY; + +#ifdef ENABLE_IPV6 + if(*string_ftpport == '[') { + /* [ipv6]:port(-range) */ + ip_start = string_ftpport + 1; - if((ip_end = strchr(string_ftpport, ']')) != NULL) ++ ip_end = strchr(string_ftpport, ']'); ++ if(ip_end) + strncpy(addr, ip_start, ip_end - ip_start); + } + else +#endif + if(*string_ftpport == ':') { + /* :port */ + ip_end = string_ftpport; - } - else if((ip_end = strchr(string_ftpport, ':')) != NULL) { - /* either ipv6 or (ipv4|domain|interface):port(-range) */ - #ifdef ENABLE_IPV6 - if(Curl_inet_pton(AF_INET6, string_ftpport, sa6) == 1) { - /* ipv6 */ - port_min = port_max = 0; - strcpy(addr, string_ftpport); - ip_end = NULL; /* this got no port ! */ + } - else ++ else { ++ ip_end = strchr(string_ftpport, ':'); ++ if(ip_end) { ++ /* either ipv6 or (ipv4|domain|interface):port(-range) */ ++#ifdef ENABLE_IPV6 ++ if(Curl_inet_pton(AF_INET6, string_ftpport, sa6) == 1) { ++ /* ipv6 */ ++ port_min = port_max = 0; ++ strcpy(addr, string_ftpport); ++ ip_end = NULL; /* this got no port ! */ ++ } ++ else +#endif - /* (ipv4|domain|interface):port(-range) */ - strncpy(addr, string_ftpport, ip_end - ip_start); - } - else - /* ipv4|interface */ - strcpy(addr, string_ftpport); ++ /* (ipv4|domain|interface):port(-range) */ ++ strncpy(addr, string_ftpport, ip_end - ip_start); ++ } ++ else ++ /* ipv4|interface */ ++ strcpy(addr, string_ftpport); ++ } + + /* parse the port */ + if(ip_end != NULL) { - if((port_start = strchr(ip_end, ':')) != NULL) { ++ port_start = strchr(ip_end, ':'); ++ if(port_start) { + port_min = curlx_ultous(strtoul(port_start+1, NULL, 10)); - if((port_sep = strchr(port_start, '-')) != NULL) { ++ port_sep = strchr(port_start, '-'); ++ if(port_sep) { + port_max = curlx_ultous(strtoul(port_sep + 1, NULL, 10)); + } + else + port_max = port_min; + } + } + + /* correct errors like: + * :1234-1230 + * :-4711, in this case port_min is (unsigned)-1, + * therefore port_min > port_max for all cases + * but port_max = (unsigned)-1 + */ + if(port_min > port_max) + port_min = port_max = 0; + + + if(*addr != '\0') { + /* attempt to get the address of the given interface name */ + switch(Curl_if2ip(conn->ip_addr->ai_family, + Curl_ipv6_scope(conn->ip_addr->ai_addr), + conn->scope_id, addr, hbuf, sizeof(hbuf))) { + case IF2IP_NOT_FOUND: + /* not an interface, use the given string as host name instead */ + host = addr; + break; + case IF2IP_AF_NOT_SUPPORTED: + return CURLE_FTP_PORT_FAILED; + case IF2IP_FOUND: + host = hbuf; /* use the hbuf for host name */ + } + } + else + /* there was only a port(-range) given, default the host */ + host = NULL; + } /* data->set.ftpport */ + + if(!host) { + /* not an interface and not a host name, get default by extracting + the IP from the control connection */ + + sslen = sizeof(ss); + if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) { + failf(data, "getsockname() failed: %s", + Curl_strerror(conn, SOCKERRNO) ); + free(addr); + return CURLE_FTP_PORT_FAILED; + } + switch(sa->sa_family) { +#ifdef ENABLE_IPV6 + case AF_INET6: + Curl_inet_ntop(sa->sa_family, &sa6->sin6_addr, hbuf, sizeof(hbuf)); + break; +#endif + default: + Curl_inet_ntop(sa->sa_family, &sa4->sin_addr, hbuf, sizeof(hbuf)); + break; + } + host = hbuf; /* use this host name */ + possibly_non_local = FALSE; /* we know it is local now */ + } + + /* resolv ip/host to ip */ + rc = Curl_resolv(conn, host, 0, &h); + if(rc == CURLRESOLV_PENDING) + (void)Curl_resolver_wait_resolv(conn, &h); + if(h) { + res = h->addr; + /* when we return from this function, we can forget about this entry + to we can unlock it now already */ + Curl_resolv_unlock(data, h); + } /* (h) */ + else + res = NULL; /* failure! */ + + if(res == NULL) { + failf(data, "failed to resolve the address provided to PORT: %s", host); + free(addr); + return CURLE_FTP_PORT_FAILED; + } + + free(addr); + host = NULL; + + /* step 2, create a socket for the requested address */ + + portsock = CURL_SOCKET_BAD; + error = 0; + for(ai = res; ai; ai = ai->ai_next) { + result = Curl_socket(conn, ai, NULL, &portsock); + if(result) { + error = SOCKERRNO; + continue; + } + break; + } + if(!ai) { + failf(data, "socket failure: %s", Curl_strerror(conn, error)); + return CURLE_FTP_PORT_FAILED; + } + + /* step 3, bind to a suitable local address */ + + memcpy(sa, ai->ai_addr, ai->ai_addrlen); + sslen = ai->ai_addrlen; + + for(port = port_min; port <= port_max;) { + if(sa->sa_family == AF_INET) + sa4->sin_port = htons(port); +#ifdef ENABLE_IPV6 + else + sa6->sin6_port = htons(port); +#endif + /* Try binding the given address. */ + if(bind(portsock, sa, sslen) ) { + /* It failed. */ + error = SOCKERRNO; + if(possibly_non_local && (error == EADDRNOTAVAIL)) { + /* The requested bind address is not local. Use the address used for + * the control connection instead and restart the port loop + */ + + infof(data, "bind(port=%hu) on non-local address failed: %s\n", port, + Curl_strerror(conn, error) ); + + sslen = sizeof(ss); + if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) { + failf(data, "getsockname() failed: %s", + Curl_strerror(conn, SOCKERRNO) ); + Curl_closesocket(conn, portsock); + return CURLE_FTP_PORT_FAILED; + } + port = port_min; + possibly_non_local = FALSE; /* don't try this again */ + continue; + } + else if(error != EADDRINUSE && error != EACCES) { + failf(data, "bind(port=%hu) failed: %s", port, + Curl_strerror(conn, error) ); + Curl_closesocket(conn, portsock); + return CURLE_FTP_PORT_FAILED; + } + } + else + break; + + port++; + } + + /* maybe all ports were in use already*/ + if(port > port_max) { + failf(data, "bind() failed, we ran out of ports!"); + Curl_closesocket(conn, portsock); + return CURLE_FTP_PORT_FAILED; + } + + /* get the name again after the bind() so that we can extract the + port number it uses now */ + sslen = sizeof(ss); + if(getsockname(portsock, (struct sockaddr *)sa, &sslen)) { + failf(data, "getsockname() failed: %s", + Curl_strerror(conn, SOCKERRNO) ); + Curl_closesocket(conn, portsock); + return CURLE_FTP_PORT_FAILED; + } + + /* step 4, listen on the socket */ + + if(listen(portsock, 1)) { + failf(data, "socket failure: %s", Curl_strerror(conn, SOCKERRNO)); + Curl_closesocket(conn, portsock); + return CURLE_FTP_PORT_FAILED; + } + + /* step 5, send the proper FTP command */ + + /* get a plain printable version of the numerical address to work with + below */ + Curl_printable_address(ai, myhost, sizeof(myhost)); + +#ifdef ENABLE_IPV6 + if(!conn->bits.ftp_use_eprt && conn->bits.ipv6) + /* EPRT is disabled but we are connected to a IPv6 host, so we ignore the + request and enable EPRT again! */ + conn->bits.ftp_use_eprt = TRUE; +#endif + + for(; fcmd != DONE; fcmd++) { + + if(!conn->bits.ftp_use_eprt && (EPRT == fcmd)) + /* if disabled, goto next */ + continue; + + if((PORT == fcmd) && sa->sa_family != AF_INET) + /* PORT is IPv4 only */ + continue; + + switch(sa->sa_family) { + case AF_INET: + port = ntohs(sa4->sin_port); + break; +#ifdef ENABLE_IPV6 + case AF_INET6: + port = ntohs(sa6->sin6_port); + break; +#endif + default: + continue; /* might as well skip this */ + } + + if(EPRT == fcmd) { + /* + * Two fine examples from RFC2428; + * + * EPRT |1|132.235.1.2|6275| + * + * EPRT |2|1080::8:800:200C:417A|5282| + */ + + result = Curl_pp_sendf(&ftpc->pp, "%s |%d|%s|%hu|", mode[fcmd], + sa->sa_family == AF_INET?1:2, + myhost, port); + if(result) { + failf(data, "Failure sending EPRT command: %s", + curl_easy_strerror(result)); + Curl_closesocket(conn, portsock); + /* don't retry using PORT */ + ftpc->count1 = PORT; + /* bail out */ + state(conn, FTP_STOP); + return result; + } + break; + } + else if(PORT == fcmd) { + char *source = myhost; + char *dest = tmp; + + /* translate x.x.x.x to x,x,x,x */ + while(source && *source) { + if(*source == '.') + *dest=','; + else + *dest = *source; + dest++; + source++; + } + *dest = 0; + snprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff)); + + result = Curl_pp_sendf(&ftpc->pp, "%s %s", mode[fcmd], tmp); + if(result) { + failf(data, "Failure sending PORT command: %s", + curl_easy_strerror(result)); + Curl_closesocket(conn, portsock); + /* bail out */ + state(conn, FTP_STOP); + return result; + } + break; + } + } + + /* store which command was sent */ + ftpc->count1 = fcmd; + + close_secondarysocket(conn); + + /* we set the secondary socket variable to this for now, it is only so that + the cleanup function will close it in case we fail before the true + secondary stuff is made */ + conn->sock[SECONDARYSOCKET] = portsock; + + /* this tcpconnect assignment below is a hackish work-around to make the + multi interface with active FTP work - as it will not wait for a + (passive) connect in Curl_is_connected(). + + The *proper* fix is to make sure that the active connection from the + server is done in a non-blocking way. Currently, it is still BLOCKING. + */ + conn->bits.tcpconnect[SECONDARYSOCKET] = TRUE; + + state(conn, FTP_PORT); + return result; +} + +static CURLcode ftp_state_use_pasv(struct connectdata *conn) +{ + struct ftp_conn *ftpc = &conn->proto.ftpc; + CURLcode result = CURLE_OK; + /* + Here's the excecutive summary on what to do: + + PASV is RFC959, expect: + 227 Entering Passive Mode (a1,a2,a3,a4,p1,p2) + + LPSV is RFC1639, expect: + 228 Entering Long Passive Mode (4,4,a1,a2,a3,a4,2,p1,p2) + + EPSV is RFC2428, expect: + 229 Entering Extended Passive Mode (|||port|) + + */ + + static const char mode[][5] = { "EPSV", "PASV" }; + int modeoff; + +#ifdef PF_INET6 + if(!conn->bits.ftp_use_epsv && conn->bits.ipv6) + /* EPSV is disabled but we are connected to a IPv6 host, so we ignore the + request and enable EPSV again! */ + conn->bits.ftp_use_epsv = TRUE; +#endif + + modeoff = conn->bits.ftp_use_epsv?0:1; + + PPSENDF(&ftpc->pp, "%s", mode[modeoff]); + + ftpc->count1 = modeoff; + state(conn, FTP_PASV); + infof(conn->data, "Connect data stream passively\n"); + + return result; +} + +/* + * ftp_state_prepare_transfer() starts PORT, PASV or PRET etc. + * + * REST is the last command in the chain of commands when a "head"-like + * request is made. Thus, if an actual transfer is to be made this is where we + * take off for real. + */ +static CURLcode ftp_state_prepare_transfer(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct FTP *ftp = conn->data->req.protop; + struct Curl_easy *data = conn->data; + + if(ftp->transfer != FTPTRANSFER_BODY) { + /* doesn't transfer any data */ + + /* still possibly do PRE QUOTE jobs */ + state(conn, FTP_RETR_PREQUOTE); + result = ftp_state_quote(conn, TRUE, FTP_RETR_PREQUOTE); + } + else if(data->set.ftp_use_port) { + /* We have chosen to use the PORT (or similar) command */ + result = ftp_state_use_port(conn, EPRT); + } + else { + /* We have chosen (this is default) to use the PASV (or similar) command */ + if(data->set.ftp_use_pret) { + /* The user has requested that we send a PRET command + to prepare the server for the upcoming PASV */ + if(!conn->proto.ftpc.file) { + PPSENDF(&conn->proto.ftpc.pp, "PRET %s", + data->set.str[STRING_CUSTOMREQUEST]? + data->set.str[STRING_CUSTOMREQUEST]: + (data->set.ftp_list_only?"NLST":"LIST")); + } + else if(data->set.upload) { + PPSENDF(&conn->proto.ftpc.pp, "PRET STOR %s", conn->proto.ftpc.file); + } + else { + PPSENDF(&conn->proto.ftpc.pp, "PRET RETR %s", conn->proto.ftpc.file); + } + state(conn, FTP_PRET); + } + else { + result = ftp_state_use_pasv(conn); + } + } + return result; +} + +static CURLcode ftp_state_rest(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct FTP *ftp = conn->data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + if((ftp->transfer != FTPTRANSFER_BODY) && ftpc->file) { + /* if a "head"-like request is being made (on a file) */ + + /* Determine if server can respond to REST command and therefore + whether it supports range */ + PPSENDF(&conn->proto.ftpc.pp, "REST %d", 0); + + state(conn, FTP_REST); + } + else + result = ftp_state_prepare_transfer(conn); + + return result; +} + +static CURLcode ftp_state_size(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct FTP *ftp = conn->data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + if((ftp->transfer == FTPTRANSFER_INFO) && ftpc->file) { + /* if a "head"-like request is being made (on a file) */ + + /* we know ftpc->file is a valid pointer to a file name */ + PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file); + + state(conn, FTP_SIZE); + } + else + result = ftp_state_rest(conn); + + return result; +} + +static CURLcode ftp_state_list(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + /* If this output is to be machine-parsed, the NLST command might be better + to use, since the LIST command output is not specified or standard in any + way. It has turned out that the NLST list output is not the same on all + servers either... */ + + /* + if FTPFILE_NOCWD was specified, we are currently in + the user's home directory, so we should add the path + as argument for the LIST / NLST / or custom command. + Whether the server will support this, is uncertain. + + The other ftp_filemethods will CWD into dir/dir/ first and + then just do LIST (in that case: nothing to do here) + */ + char *cmd, *lstArg, *slashPos; + + lstArg = NULL; + if((data->set.ftp_filemethod == FTPFILE_NOCWD) && + data->state.path && + data->state.path[0] && + strchr(data->state.path, '/')) { + + lstArg = strdup(data->state.path); + if(!lstArg) + return CURLE_OUT_OF_MEMORY; + + /* Check if path does not end with /, as then we cut off the file part */ + if(lstArg[strlen(lstArg) - 1] != '/') { + + /* chop off the file part if format is dir/dir/file */ + slashPos = strrchr(lstArg, '/'); + if(slashPos) + *(slashPos+1) = '\0'; + } + } + + cmd = aprintf("%s%s%s", + data->set.str[STRING_CUSTOMREQUEST]? + data->set.str[STRING_CUSTOMREQUEST]: + (data->set.ftp_list_only?"NLST":"LIST"), + lstArg? " ": "", + lstArg? lstArg: ""); + + if(!cmd) { + free(lstArg); + return CURLE_OUT_OF_MEMORY; + } + + result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", cmd); + + free(lstArg); + free(cmd); + + if(result) + return result; + + state(conn, FTP_LIST); + + return result; +} + +static CURLcode ftp_state_retr_prequote(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + /* We've sent the TYPE, now we must send the list of prequote strings */ + + result = ftp_state_quote(conn, TRUE, FTP_RETR_PREQUOTE); + + return result; +} + +static CURLcode ftp_state_stor_prequote(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + /* We've sent the TYPE, now we must send the list of prequote strings */ + + result = ftp_state_quote(conn, TRUE, FTP_STOR_PREQUOTE); + + return result; +} + +static CURLcode ftp_state_type(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct FTP *ftp = conn->data->req.protop; + struct Curl_easy *data = conn->data; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + /* If we have selected NOBODY and HEADER, it means that we only want file + information. Which in FTP can't be much more than the file size and + date. */ + if(data->set.opt_no_body && ftpc->file && + ftp_need_type(conn, data->set.prefer_ascii)) { + /* The SIZE command is _not_ RFC 959 specified, and therefor many servers + may not support it! It is however the only way we have to get a file's + size! */ + + ftp->transfer = FTPTRANSFER_INFO; + /* this means no actual transfer will be made */ + + /* Some servers return different sizes for different modes, and thus we + must set the proper type before we check the size */ + result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_TYPE); + if(result) + return result; + } + else + result = ftp_state_size(conn); + + return result; +} + +/* This is called after the CWD commands have been done in the beginning of + the DO phase */ +static CURLcode ftp_state_mdtm(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + /* Requested time of file or time-depended transfer? */ + if((data->set.get_filetime || data->set.timecondition) && ftpc->file) { + + /* we have requested to get the modified-time of the file, this is a white + spot as the MDTM is not mentioned in RFC959 */ + PPSENDF(&ftpc->pp, "MDTM %s", ftpc->file); + + state(conn, FTP_MDTM); + } + else + result = ftp_state_type(conn); + + return result; +} + + +/* This is called after the TYPE and possible quote commands have been sent */ +static CURLcode ftp_state_ul_setup(struct connectdata *conn, + bool sizechecked) +{ + CURLcode result = CURLE_OK; + struct FTP *ftp = conn->data->req.protop; + struct Curl_easy *data = conn->data; + struct ftp_conn *ftpc = &conn->proto.ftpc; + int seekerr = CURL_SEEKFUNC_OK; + + if((data->state.resume_from && !sizechecked) || + ((data->state.resume_from > 0) && sizechecked)) { + /* we're about to continue the uploading of a file */ + /* 1. get already existing file's size. We use the SIZE command for this + which may not exist in the server! The SIZE command is not in + RFC959. */ + + /* 2. This used to set REST. But since we can do append, we + don't another ftp command. We just skip the source file + offset and then we APPEND the rest on the file instead */ + + /* 3. pass file-size number of bytes in the source file */ + /* 4. lower the infilesize counter */ + /* => transfer as usual */ + + if(data->state.resume_from < 0) { + /* Got no given size to start from, figure it out */ + PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file); + state(conn, FTP_STOR_SIZE); + return result; + } + + /* enable append */ + data->set.ftp_append = TRUE; + + /* Let's read off the proper amount of bytes from the input. */ + if(conn->seek_func) { + seekerr = conn->seek_func(conn->seek_client, data->state.resume_from, + SEEK_SET); + } + + if(seekerr != CURL_SEEKFUNC_OK) { + if(seekerr != CURL_SEEKFUNC_CANTSEEK) { + failf(data, "Could not seek stream"); + return CURLE_FTP_COULDNT_USE_REST; + } + /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */ + else { + curl_off_t passed=0; + do { + size_t readthisamountnow = + (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ? + BUFSIZE : curlx_sotouz(data->state.resume_from - passed); + + size_t actuallyread = + data->state.fread_func(data->state.buffer, 1, readthisamountnow, + data->state.in); + + passed += actuallyread; + if((actuallyread == 0) || (actuallyread > readthisamountnow)) { + /* this checks for greater-than only to make sure that the + CURL_READFUNC_ABORT return code still aborts */ + failf(data, "Failed to read data"); + return CURLE_FTP_COULDNT_USE_REST; + } + } while(passed < data->state.resume_from); + } + } + /* now, decrease the size of the read */ + if(data->state.infilesize>0) { + data->state.infilesize -= data->state.resume_from; + + if(data->state.infilesize <= 0) { + infof(data, "File already completely uploaded\n"); + + /* no data to transfer */ + Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + + /* Set ->transfer so that we won't get any error in + * ftp_done() because we didn't transfer anything! */ + ftp->transfer = FTPTRANSFER_NONE; + + state(conn, FTP_STOP); + return CURLE_OK; + } + } + /* we've passed, proceed as normal */ + } /* resume_from */ + + PPSENDF(&ftpc->pp, data->set.ftp_append?"APPE %s":"STOR %s", + ftpc->file); + + state(conn, FTP_STOR); + + return result; +} + +static CURLcode ftp_state_quote(struct connectdata *conn, + bool init, + ftpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct FTP *ftp = data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + bool quote=FALSE; + struct curl_slist *item; + + switch(instate) { + case FTP_QUOTE: + default: + item = data->set.quote; + break; + case FTP_RETR_PREQUOTE: + case FTP_STOR_PREQUOTE: + item = data->set.prequote; + break; + case FTP_POSTQUOTE: + item = data->set.postquote; + break; + } + + /* + * This state uses: + * 'count1' to iterate over the commands to send + * 'count2' to store wether to allow commands to fail + */ + + if(init) + ftpc->count1 = 0; + else + ftpc->count1++; + + if(item) { + int i = 0; + + /* Skip count1 items in the linked list */ + while((i< ftpc->count1) && item) { + item = item->next; + i++; + } + if(item) { + char *cmd = item->data; + if(cmd[0] == '*') { + cmd++; + ftpc->count2 = 1; /* the sent command is allowed to fail */ + } + else + ftpc->count2 = 0; /* failure means cancel operation */ + + PPSENDF(&ftpc->pp, "%s", cmd); + state(conn, instate); + quote = TRUE; + } + } + + if(!quote) { + /* No more quote to send, continue to ... */ + switch(instate) { + case FTP_QUOTE: + default: + result = ftp_state_cwd(conn); + break; + case FTP_RETR_PREQUOTE: + if(ftp->transfer != FTPTRANSFER_BODY) + state(conn, FTP_STOP); + else { + if(ftpc->known_filesize != -1) { + Curl_pgrsSetDownloadSize(data, ftpc->known_filesize); + result = ftp_state_retr(conn, ftpc->known_filesize); + } + else { + if(data->set.ignorecl) { + /* This code is to support download of growing files. It prevents + the state machine from requesting the file size from the + server. With an unknown file size the download continues until + the server terminates it, otherwise the client stops if the + received byte count exceeds the reported file size. Set option + CURLOPT_IGNORE_CONTENT_LENGTH to 1 to enable this behavior.*/ + PPSENDF(&ftpc->pp, "RETR %s", ftpc->file); + state(conn, FTP_RETR); + } + else { + PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file); + state(conn, FTP_RETR_SIZE); + } + } + } + break; + case FTP_STOR_PREQUOTE: + result = ftp_state_ul_setup(conn, FALSE); + break; + case FTP_POSTQUOTE: + break; + } + } + + return result; +} + +/* called from ftp_state_pasv_resp to switch to PASV in case of EPSV + problems */ +static CURLcode ftp_epsv_disable(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + if(conn->bits.ipv6) { + /* We can't disable EPSV when doing IPv6, so this is instead a fail */ + failf(conn->data, "Failed EPSV attempt, exiting\n"); + return CURLE_WEIRD_SERVER_REPLY; + } + + infof(conn->data, "Failed EPSV attempt. Disabling EPSV\n"); + /* disable it for next transfer */ + conn->bits.ftp_use_epsv = FALSE; + conn->data->state.errorbuf = FALSE; /* allow error message to get + rewritten */ + PPSENDF(&conn->proto.ftpc.pp, "%s", "PASV"); + conn->proto.ftpc.count1++; + /* remain in/go to the FTP_PASV state */ + state(conn, FTP_PASV); + return result; +} + - /* - * Perform the necessary magic that needs to be done once the TCP connection - * to the proxy has completed. - */ - static CURLcode proxy_magic(struct connectdata *conn, - char *newhost, unsigned short newport, - bool *magicdone) - { - CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; - - #if defined(CURL_DISABLE_PROXY) - (void) newhost; - (void) newport; - #endif - - *magicdone = FALSE; - - switch(conn->proxytype) { - case CURLPROXY_SOCKS5: - case CURLPROXY_SOCKS5_HOSTNAME: - result = Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, newhost, - newport, SECONDARYSOCKET, conn); - *magicdone = TRUE; - break; - case CURLPROXY_SOCKS4: - result = Curl_SOCKS4(conn->proxyuser, newhost, newport, - SECONDARYSOCKET, conn, FALSE); - *magicdone = TRUE; - break; - case CURLPROXY_SOCKS4A: - result = Curl_SOCKS4(conn->proxyuser, newhost, newport, - SECONDARYSOCKET, conn, TRUE); - *magicdone = TRUE; - break; - case CURLPROXY_HTTP: - case CURLPROXY_HTTP_1_0: - /* do nothing here. handled later. */ - break; - default: - failf(data, "unknown proxytype option given"); - result = CURLE_COULDNT_CONNECT; - break; - } - - if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { - /* BLOCKING */ - /* We want "seamless" FTP operations through HTTP proxy tunnel */ - - /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the - * member conn->proto.http; we want FTP through HTTP and we have to - * change the member temporarily for connecting to the HTTP proxy. After - * Curl_proxyCONNECT we have to set back the member to the original - * struct FTP pointer - */ - struct HTTP http_proxy; - struct FTP *ftp_save = data->req.protop; - memset(&http_proxy, 0, sizeof(http_proxy)); - data->req.protop = &http_proxy; - - result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport, TRUE); - - data->req.protop = ftp_save; - - if(result) - return result; - - if(conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE) { - /* the CONNECT procedure is not complete, the tunnel is not yet up */ - state(conn, FTP_STOP); /* this phase is completed */ - return result; - } - else - *magicdone = TRUE; - } - - return result; - } + +static char *control_address(struct connectdata *conn) +{ + /* Returns the control connection IP address. + If a proxy tunnel is used, returns the original host name instead, because + the effective control connection address is the proxy address, + not the ftp host. */ - if(conn->bits.tunnel_proxy || - conn->proxytype == CURLPROXY_SOCKS5 || - conn->proxytype == CURLPROXY_SOCKS5_HOSTNAME || - conn->proxytype == CURLPROXY_SOCKS4 || - conn->proxytype == CURLPROXY_SOCKS4A) ++ if(conn->bits.tunnel_proxy || conn->bits.socksproxy) + return conn->host.name; + + return conn->ip_addr_str; +} + +static CURLcode ftp_state_pasv_resp(struct connectdata *conn, + int ftpcode) +{ + struct ftp_conn *ftpc = &conn->proto.ftpc; + CURLcode result; + struct Curl_easy *data=conn->data; + struct Curl_dns_entry *addr=NULL; + int rc; + unsigned short connectport; /* the local port connect() should use! */ + char *str=&data->state.buffer[4]; /* start on the first letter */ + + /* if we come here again, make sure the former name is cleared */ + Curl_safefree(ftpc->newhost); + + if((ftpc->count1 == 0) && + (ftpcode == 229)) { + /* positive EPSV response */ + char *ptr = strchr(str, '('); + if(ptr) { + unsigned int num; + char separator[4]; + ptr++; + if(5 == sscanf(ptr, "%c%c%c%u%c", + &separator[0], + &separator[1], + &separator[2], + &num, + &separator[3])) { + const char sep1 = separator[0]; + int i; + + /* The four separators should be identical, or else this is an oddly + formatted reply and we bail out immediately. */ + for(i=1; i<4; i++) { + if(separator[i] != sep1) { + ptr=NULL; /* set to NULL to signal error */ + break; + } + } + if(num > 0xffff) { + failf(data, "Illegal port number in EPSV reply"); + return CURLE_FTP_WEIRD_PASV_REPLY; + } + if(ptr) { + ftpc->newport = (unsigned short)(num & 0xffff); + ftpc->newhost = strdup(control_address(conn)); + if(!ftpc->newhost) + return CURLE_OUT_OF_MEMORY; + } + } + else + ptr=NULL; + } + if(!ptr) { + failf(data, "Weirdly formatted EPSV reply"); + return CURLE_FTP_WEIRD_PASV_REPLY; + } + } + else if((ftpc->count1 == 1) && + (ftpcode == 227)) { + /* positive PASV response */ + int ip[4]; + int port[2]; + + /* + * Scan for a sequence of six comma-separated numbers and use them as + * IP+port indicators. + * + * Found reply-strings include: + * "227 Entering Passive Mode (127,0,0,1,4,51)" + * "227 Data transfer will passively listen to 127,0,0,1,4,51" + * "227 Entering passive mode. 127,0,0,1,4,51" + */ + while(*str) { + if(6 == sscanf(str, "%d,%d,%d,%d,%d,%d", + &ip[0], &ip[1], &ip[2], &ip[3], + &port[0], &port[1])) + break; + str++; + } + + if(!*str) { + failf(data, "Couldn't interpret the 227-response"); + return CURLE_FTP_WEIRD_227_FORMAT; + } + + /* we got OK from server */ + if(data->set.ftp_skip_ip) { + /* told to ignore the remotely given IP but instead use the host we used + for the control connection */ + infof(data, "Skip %d.%d.%d.%d for data connection, re-use %s instead\n", + ip[0], ip[1], ip[2], ip[3], + conn->host.name); + ftpc->newhost = strdup(control_address(conn)); + } + else + ftpc->newhost = aprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); + + if(!ftpc->newhost) + return CURLE_OUT_OF_MEMORY; + + ftpc->newport = (unsigned short)(((port[0]<<8) + port[1]) & 0xffff); + } + else if(ftpc->count1 == 0) { + /* EPSV failed, move on to PASV */ + return ftp_epsv_disable(conn); + } + else { + failf(data, "Bad PASV/EPSV response: %03d", ftpcode); + return CURLE_FTP_WEIRD_PASV_REPLY; + } + + if(conn->bits.proxy) { + /* + * This connection uses a proxy and we need to connect to the proxy again + * here. We don't want to rely on a former host lookup that might've + * expired now, instead we remake the lookup here and now! + */ - rc = Curl_resolv(conn, conn->proxy.name, (int)conn->port, &addr); ++ const char * const host_name = conn->bits.socksproxy ? ++ conn->socks_proxy.host.name : conn->http_proxy.host.name; ++ rc = Curl_resolv(conn, host_name, (int)conn->port, &addr); + if(rc == CURLRESOLV_PENDING) + /* BLOCKING, ignores the return code but 'addr' will be NULL in + case of failure */ + (void)Curl_resolver_wait_resolv(conn, &addr); + + connectport = + (unsigned short)conn->port; /* we connect to the proxy's port */ + + if(!addr) { - failf(data, "Can't resolve proxy host %s:%hu", - conn->proxy.name, connectport); ++ failf(data, "Can't resolve proxy host %s:%hu", host_name, connectport); + return CURLE_FTP_CANT_GET_HOST; + } + } + else { + /* normal, direct, ftp connection */ + rc = Curl_resolv(conn, ftpc->newhost, ftpc->newport, &addr); + if(rc == CURLRESOLV_PENDING) + /* BLOCKING */ + (void)Curl_resolver_wait_resolv(conn, &addr); + + connectport = ftpc->newport; /* we connect to the remote port */ + + if(!addr) { + failf(data, "Can't resolve new host %s:%hu", ftpc->newhost, connectport); + return CURLE_FTP_CANT_GET_HOST; + } + } + + conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE; + result = Curl_connecthost(conn, addr); + + if(result) { + Curl_resolv_unlock(data, addr); /* we're done using this address */ + if(ftpc->count1 == 0 && ftpcode == 229) + return ftp_epsv_disable(conn); + + return result; + } + + + /* + * When this is used from the multi interface, this might've returned with + * the 'connected' set to FALSE and thus we are now awaiting a non-blocking + * connect to connect. + */ + + if(data->set.verbose) + /* this just dumps information about this second connection */ + ftp_pasv_verbose(conn, addr->addr, ftpc->newhost, connectport); + ++ Curl_safefree(conn->secondaryhostname); ++ conn->secondaryhostname = strdup(ftpc->newhost); ++ conn->secondary_port = ftpc->newport; ++ + Curl_resolv_unlock(data, addr); /* we're done using this address */ + conn->bits.do_more = TRUE; + state(conn, FTP_STOP); /* this phase is completed */ + + return result; +} + +static CURLcode ftp_state_port_resp(struct connectdata *conn, + int ftpcode) +{ + struct Curl_easy *data = conn->data; + struct ftp_conn *ftpc = &conn->proto.ftpc; + ftpport fcmd = (ftpport)ftpc->count1; + CURLcode result = CURLE_OK; + + /* The FTP spec tells a positive response should have code 200. + Be more permissive here to tolerate deviant servers. */ + if(ftpcode / 100 != 2) { + /* the command failed */ + + if(EPRT == fcmd) { + infof(data, "disabling EPRT usage\n"); + conn->bits.ftp_use_eprt = FALSE; + } + fcmd++; + + if(fcmd == DONE) { + failf(data, "Failed to do PORT"); + result = CURLE_FTP_PORT_FAILED; + } + else + /* try next */ + result = ftp_state_use_port(conn, fcmd); + } + else { + infof(data, "Connect data stream actively\n"); + state(conn, FTP_STOP); /* end of DO phase */ + result = ftp_dophase_done(conn, FALSE); + } + + return result; +} + +static CURLcode ftp_state_mdtm_resp(struct connectdata *conn, + int ftpcode) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data=conn->data; + struct FTP *ftp = data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + switch(ftpcode) { + case 213: + { + /* we got a time. Format should be: "YYYYMMDDHHMMSS[.sss]" where the + last .sss part is optional and means fractions of a second */ + int year, month, day, hour, minute, second; + char *buf = data->state.buffer; + if(6 == sscanf(buf+4, "%04d%02d%02d%02d%02d%02d", + &year, &month, &day, &hour, &minute, &second)) { + /* we have a time, reformat it */ + time_t secs=time(NULL); + /* using the good old yacc/bison yuck */ + snprintf(buf, sizeof(conn->data->state.buffer), + "%04d%02d%02d %02d:%02d:%02d GMT", + year, month, day, hour, minute, second); + /* now, convert this into a time() value: */ + data->info.filetime = (long)curl_getdate(buf, &secs); + } + +#ifdef CURL_FTP_HTTPSTYLE_HEAD + /* If we asked for a time of the file and we actually got one as well, + we "emulate" a HTTP-style header in our output. */ + + if(data->set.opt_no_body && + ftpc->file && + data->set.get_filetime && + (data->info.filetime>=0) ) { + time_t filetime = (time_t)data->info.filetime; + struct tm buffer; + const struct tm *tm = &buffer; + + result = Curl_gmtime(filetime, &buffer); + if(result) + return result; + + /* format: "Tue, 15 Nov 1994 12:45:26" */ + snprintf(buf, BUFSIZE-1, + "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n", + Curl_wkday[tm->tm_wday?tm->tm_wday-1:6], + tm->tm_mday, + Curl_month[tm->tm_mon], + tm->tm_year + 1900, + tm->tm_hour, + tm->tm_min, + tm->tm_sec); + result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0); + if(result) + return result; + } /* end of a ridiculous amount of conditionals */ +#endif + } + break; + default: + infof(data, "unsupported MDTM reply format\n"); + break; + case 550: /* "No such file or directory" */ + failf(data, "Given file does not exist"); + result = CURLE_FTP_COULDNT_RETR_FILE; + break; + } + + if(data->set.timecondition) { + if((data->info.filetime > 0) && (data->set.timevalue > 0)) { + switch(data->set.timecondition) { + case CURL_TIMECOND_IFMODSINCE: + default: + if(data->info.filetime <= data->set.timevalue) { + infof(data, "The requested document is not new enough\n"); + ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */ + data->info.timecond = TRUE; + state(conn, FTP_STOP); + return CURLE_OK; + } + break; + case CURL_TIMECOND_IFUNMODSINCE: + if(data->info.filetime > data->set.timevalue) { + infof(data, "The requested document is not old enough\n"); + ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */ + data->info.timecond = TRUE; + state(conn, FTP_STOP); + return CURLE_OK; + } + break; + } /* switch */ + } + else { + infof(data, "Skipping time comparison\n"); + } + } + + if(!result) + result = ftp_state_type(conn); + + return result; +} + +static CURLcode ftp_state_type_resp(struct connectdata *conn, + int ftpcode, + ftpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data=conn->data; + + if(ftpcode/100 != 2) { + /* "sasserftpd" and "(u)r(x)bot ftpd" both responds with 226 after a + successful 'TYPE I'. While that is not as RFC959 says, it is still a + positive response code and we allow that. */ + failf(data, "Couldn't set desired mode"); + return CURLE_FTP_COULDNT_SET_TYPE; + } + if(ftpcode != 200) + infof(data, "Got a %03d response code instead of the assumed 200\n", + ftpcode); + + if(instate == FTP_TYPE) + result = ftp_state_size(conn); + else if(instate == FTP_LIST_TYPE) + result = ftp_state_list(conn); + else if(instate == FTP_RETR_TYPE) + result = ftp_state_retr_prequote(conn); + else if(instate == FTP_STOR_TYPE) + result = ftp_state_stor_prequote(conn); + + return result; +} + +static CURLcode ftp_state_retr(struct connectdata *conn, + curl_off_t filesize) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data=conn->data; + struct FTP *ftp = data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + if(data->set.max_filesize && (filesize > data->set.max_filesize)) { + failf(data, "Maximum file size exceeded"); + return CURLE_FILESIZE_EXCEEDED; + } + ftp->downloadsize = filesize; + + if(data->state.resume_from) { + /* We always (attempt to) get the size of downloads, so it is done before + this even when not doing resumes. */ + if(filesize == -1) { + infof(data, "ftp server doesn't support SIZE\n"); + /* We couldn't get the size and therefore we can't know if there really + is a part of the file left to get, although the server will just + close the connection when we start the connection so it won't cause + us any harm, just not make us exit as nicely. */ + } + else { + /* We got a file size report, so we check that there actually is a + part of the file left to get, or else we go home. */ + if(data->state.resume_from< 0) { + /* We're supposed to download the last abs(from) bytes */ + if(filesize < -data->state.resume_from) { + failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T + ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")", + data->state.resume_from, filesize); + return CURLE_BAD_DOWNLOAD_RESUME; + } + /* convert to size to download */ + ftp->downloadsize = -data->state.resume_from; + /* download from where? */ + data->state.resume_from = filesize - ftp->downloadsize; + } + else { + if(filesize < data->state.resume_from) { + failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T + ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")", + data->state.resume_from, filesize); + return CURLE_BAD_DOWNLOAD_RESUME; + } + /* Now store the number of bytes we are expected to download */ + ftp->downloadsize = filesize-data->state.resume_from; + } + } + + if(ftp->downloadsize == 0) { + /* no data to transfer */ + Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + infof(data, "File already completely downloaded\n"); + + /* Set ->transfer so that we won't get any error in ftp_done() + * because we didn't transfer the any file */ + ftp->transfer = FTPTRANSFER_NONE; + state(conn, FTP_STOP); + return CURLE_OK; + } + + /* Set resume file transfer offset */ + infof(data, "Instructs server to resume from offset %" + CURL_FORMAT_CURL_OFF_T "\n", data->state.resume_from); + + PPSENDF(&ftpc->pp, "REST %" CURL_FORMAT_CURL_OFF_T, + data->state.resume_from); + + state(conn, FTP_RETR_REST); + } + else { + /* no resume */ + PPSENDF(&ftpc->pp, "RETR %s", ftpc->file); + state(conn, FTP_RETR); + } + + return result; +} + +static CURLcode ftp_state_size_resp(struct connectdata *conn, + int ftpcode, + ftpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data=conn->data; + curl_off_t filesize; + char *buf = data->state.buffer; + + /* get the size from the ascii string: */ + filesize = (ftpcode == 213)?curlx_strtoofft(buf+4, NULL, 0):-1; + + if(instate == FTP_SIZE) { +#ifdef CURL_FTP_HTTPSTYLE_HEAD + if(-1 != filesize) { + snprintf(buf, sizeof(data->state.buffer), + "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize); + result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0); + if(result) + return result; + } +#endif + Curl_pgrsSetDownloadSize(data, filesize); + result = ftp_state_rest(conn); + } + else if(instate == FTP_RETR_SIZE) { + Curl_pgrsSetDownloadSize(data, filesize); + result = ftp_state_retr(conn, filesize); + } + else if(instate == FTP_STOR_SIZE) { + data->state.resume_from = filesize; + result = ftp_state_ul_setup(conn, TRUE); + } + + return result; +} + +static CURLcode ftp_state_rest_resp(struct connectdata *conn, + int ftpcode, + ftpstate instate) +{ + CURLcode result = CURLE_OK; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + switch(instate) { + case FTP_REST: + default: +#ifdef CURL_FTP_HTTPSTYLE_HEAD + if(ftpcode == 350) { + char buffer[24]= { "Accept-ranges: bytes\r\n" }; + result = Curl_client_write(conn, CLIENTWRITE_BOTH, buffer, 0); + if(result) + return result; + } +#endif + result = ftp_state_prepare_transfer(conn); + break; + + case FTP_RETR_REST: + if(ftpcode != 350) { + failf(conn->data, "Couldn't use REST"); + result = CURLE_FTP_COULDNT_USE_REST; + } + else { + PPSENDF(&ftpc->pp, "RETR %s", ftpc->file); + state(conn, FTP_RETR); + } + break; + } + + return result; +} + +static CURLcode ftp_state_stor_resp(struct connectdata *conn, + int ftpcode, ftpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + + if(ftpcode>=400) { + failf(data, "Failed FTP upload: %0d", ftpcode); + state(conn, FTP_STOP); + /* oops, we never close the sockets! */ + return CURLE_UPLOAD_FAILED; + } + + conn->proto.ftpc.state_saved = instate; + + /* PORT means we are now awaiting the server to connect to us. */ + if(data->set.ftp_use_port) { + bool connected; + + state(conn, FTP_STOP); /* no longer in STOR state */ + + result = AllowServerConnect(conn, &connected); + if(result) + return result; + + if(!connected) { + struct ftp_conn *ftpc = &conn->proto.ftpc; + infof(data, "Data conn was not available immediately\n"); + ftpc->wait_data_conn = TRUE; + } + + return CURLE_OK; + } + else + return InitiateTransfer(conn); +} + +/* for LIST and RETR responses */ +static CURLcode ftp_state_get_resp(struct connectdata *conn, + int ftpcode, + ftpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct FTP *ftp = data->req.protop; + char *buf = data->state.buffer; + + if((ftpcode == 150) || (ftpcode == 125)) { + + /* + A; + 150 Opening BINARY mode data connection for /etc/passwd (2241 + bytes). (ok, the file is being transferred) + + B: + 150 Opening ASCII mode data connection for /bin/ls + + C: + 150 ASCII data connection for /bin/ls (137.167.104.91,37445) (0 bytes). + + D: + 150 Opening ASCII mode data connection for [file] (0.0.0.0,0) (545 bytes) + + E: + 125 Data connection already open; Transfer starting. */ + + curl_off_t size=-1; /* default unknown size */ + + + /* + * It appears that there are FTP-servers that return size 0 for files when + * SIZE is used on the file while being in BINARY mode. To work around + * that (stupid) behavior, we attempt to parse the RETR response even if + * the SIZE returned size zero. + * + * Debugging help from Salvatore Sorrentino on February 26, 2003. + */ + + if((instate != FTP_LIST) && + !data->set.prefer_ascii && + (ftp->downloadsize < 1)) { + /* + * It seems directory listings either don't show the size or very + * often uses size 0 anyway. ASCII transfers may very well turn out + * that the transferred amount of data is not the same as this line + * tells, why using this number in those cases only confuses us. + * + * Example D above makes this parsing a little tricky */ + char *bytes; + bytes=strstr(buf, " bytes"); + if(bytes--) { + long in=(long)(bytes-buf); + /* this is a hint there is size information in there! ;-) */ + while(--in) { + /* scan for the left parenthesis and break there */ + if('(' == *bytes) + break; + /* skip only digits */ + if(!ISDIGIT(*bytes)) { + bytes=NULL; + break; + } + /* one more estep backwards */ + bytes--; + } + /* if we have nothing but digits: */ + if(bytes++) { + /* get the number! */ + size = curlx_strtoofft(bytes, NULL, 0); + } + } + } + else if(ftp->downloadsize > -1) + size = ftp->downloadsize; + + if(size > data->req.maxdownload && data->req.maxdownload > 0) + size = data->req.size = data->req.maxdownload; + else if((instate != FTP_LIST) && (data->set.prefer_ascii)) + size = -1; /* kludge for servers that understate ASCII mode file size */ + + infof(data, "Maxdownload = %" CURL_FORMAT_CURL_OFF_T "\n", + data->req.maxdownload); + + if(instate != FTP_LIST) + infof(data, "Getting file with size: %" CURL_FORMAT_CURL_OFF_T "\n", + size); + + /* FTP download: */ + conn->proto.ftpc.state_saved = instate; + conn->proto.ftpc.retr_size_saved = size; + + if(data->set.ftp_use_port) { + bool connected; + + result = AllowServerConnect(conn, &connected); + if(result) + return result; + + if(!connected) { + struct ftp_conn *ftpc = &conn->proto.ftpc; + infof(data, "Data conn was not available immediately\n"); + state(conn, FTP_STOP); + ftpc->wait_data_conn = TRUE; + } + } + else + return InitiateTransfer(conn); + } + else { + if((instate == FTP_LIST) && (ftpcode == 450)) { + /* simply no matching files in the dir listing */ + ftp->transfer = FTPTRANSFER_NONE; /* don't download anything */ + state(conn, FTP_STOP); /* this phase is over */ + } + else { + failf(data, "RETR response: %03d", ftpcode); + return instate == FTP_RETR && ftpcode == 550? + CURLE_REMOTE_FILE_NOT_FOUND: + CURLE_FTP_COULDNT_RETR_FILE; + } + } + + return result; +} + +/* after USER, PASS and ACCT */ +static CURLcode ftp_state_loggedin(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + if(conn->ssl[FIRSTSOCKET].use) { + /* PBSZ = PROTECTION BUFFER SIZE. + + The 'draft-murray-auth-ftp-ssl' (draft 12, page 7) says: + + Specifically, the PROT command MUST be preceded by a PBSZ + command and a PBSZ command MUST be preceded by a successful + security data exchange (the TLS negotiation in this case) + + ... (and on page 8): + + Thus the PBSZ command must still be issued, but must have a + parameter of '0' to indicate that no buffering is taking place + and the data connection should not be encapsulated. + */ + PPSENDF(&conn->proto.ftpc.pp, "PBSZ %d", 0); + state(conn, FTP_PBSZ); + } + else { + result = ftp_state_pwd(conn); + } + return result; +} + +/* for USER and PASS responses */ +static CURLcode ftp_state_user_resp(struct connectdata *conn, + int ftpcode, + ftpstate instate) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + struct FTP *ftp = data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + (void)instate; /* no use for this yet */ + + /* some need password anyway, and others just return 2xx ignored */ + if((ftpcode == 331) && (ftpc->state == FTP_USER)) { + /* 331 Password required for ... + (the server requires to send the user's password too) */ + PPSENDF(&ftpc->pp, "PASS %s", ftp->passwd?ftp->passwd:""); + state(conn, FTP_PASS); + } + else if(ftpcode/100 == 2) { + /* 230 User ... logged in. + (the user logged in with or without password) */ + result = ftp_state_loggedin(conn); + } + else if(ftpcode == 332) { + if(data->set.str[STRING_FTP_ACCOUNT]) { + PPSENDF(&ftpc->pp, "ACCT %s", data->set.str[STRING_FTP_ACCOUNT]); + state(conn, FTP_ACCT); + } + else { + failf(data, "ACCT requested but none available"); + result = CURLE_LOGIN_DENIED; + } + } + else { + /* All other response codes, like: + + 530 User ... access denied + (the server denies to log the specified user) */ + + if(conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER] && + !conn->data->state.ftp_trying_alternative) { + /* Ok, USER failed. Let's try the supplied command. */ + PPSENDF(&conn->proto.ftpc.pp, "%s", + conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]); + conn->data->state.ftp_trying_alternative = TRUE; + state(conn, FTP_USER); + result = CURLE_OK; + } + else { + failf(data, "Access denied: %03d", ftpcode); + result = CURLE_LOGIN_DENIED; + } + } + return result; +} + +/* for ACCT response */ +static CURLcode ftp_state_acct_resp(struct connectdata *conn, + int ftpcode) +{ + CURLcode result = CURLE_OK; + struct Curl_easy *data = conn->data; + if(ftpcode != 230) { + failf(data, "ACCT rejected by server: %03d", ftpcode); + result = CURLE_FTP_WEIRD_PASS_REPLY; /* FIX */ + } + else + result = ftp_state_loggedin(conn); + + return result; +} + + +static CURLcode ftp_statemach_act(struct connectdata *conn) +{ + CURLcode result; + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + struct Curl_easy *data=conn->data; + int ftpcode; + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + static const char ftpauth[][4] = { "SSL", "TLS" }; + size_t nread = 0; + + if(pp->sendleft) + return Curl_pp_flushsend(pp); + + result = ftp_readresp(sock, pp, &ftpcode, &nread); + if(result) + return result; + + if(ftpcode) { + /* we have now received a full FTP server response */ + switch(ftpc->state) { + case FTP_WAIT220: + if(ftpcode == 230) + /* 230 User logged in - already! */ + return ftp_state_user_resp(conn, ftpcode, ftpc->state); + else if(ftpcode != 220) { + failf(data, "Got a %03d ftp-server response when 220 was expected", + ftpcode); + return CURLE_WEIRD_SERVER_REPLY; + } + + /* We have received a 220 response fine, now we proceed. */ +#ifdef HAVE_GSSAPI + if(data->set.krb) { + /* If not anonymous login, try a secure login. Note that this + procedure is still BLOCKING. */ + + Curl_sec_request_prot(conn, "private"); + /* We set private first as default, in case the line below fails to + set a valid level */ + Curl_sec_request_prot(conn, data->set.str[STRING_KRB_LEVEL]); + + if(Curl_sec_login(conn)) + infof(data, "Logging in with password in cleartext!\n"); + else + infof(data, "Authentication successful\n"); + } +#endif + - if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) { ++ if(data->set.use_ssl && ++ (!conn->ssl[FIRSTSOCKET].use || ++ (conn->bits.proxy_ssl_connected[FIRSTSOCKET] && ++ !conn->proxy_ssl[FIRSTSOCKET].use))) { + /* We don't have a SSL/TLS connection yet, but FTPS is + requested. Try a FTPS connection now */ + + ftpc->count3=0; + switch(data->set.ftpsslauth) { + case CURLFTPAUTH_DEFAULT: + case CURLFTPAUTH_SSL: + ftpc->count2 = 1; /* add one to get next */ + ftpc->count1 = 0; + break; + case CURLFTPAUTH_TLS: + ftpc->count2 = -1; /* subtract one to get next */ + ftpc->count1 = 1; + break; + default: + failf(data, "unsupported parameter to CURLOPT_FTPSSLAUTH: %d", + (int)data->set.ftpsslauth); + return CURLE_UNKNOWN_OPTION; /* we don't know what to do */ + } + PPSENDF(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]); + state(conn, FTP_AUTH); + } + else { + result = ftp_state_user(conn); + if(result) + return result; + } + + break; + + case FTP_AUTH: + /* we have gotten the response to a previous AUTH command */ + + /* RFC2228 (page 5) says: + * + * If the server is willing to accept the named security mechanism, + * and does not require any security data, it must respond with + * reply code 234/334. + */ + + if((ftpcode == 234) || (ftpcode == 334)) { + /* Curl_ssl_connect is BLOCKING */ + result = Curl_ssl_connect(conn, FIRSTSOCKET); + if(!result) { - conn->ssl[SECONDARYSOCKET].use = FALSE; /* clear-text data */ ++ conn->bits.ftp_use_data_ssl = FALSE; /* clear-text data */ + result = ftp_state_user(conn); + } + } + else if(ftpc->count3 < 1) { + ftpc->count3++; + ftpc->count1 += ftpc->count2; /* get next attempt */ + result = Curl_pp_sendf(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]); + /* remain in this same state */ + } + else { + if(data->set.use_ssl > CURLUSESSL_TRY) + /* we failed and CURLUSESSL_CONTROL or CURLUSESSL_ALL is set */ + result = CURLE_USE_SSL_FAILED; + else + /* ignore the failure and continue */ + result = ftp_state_user(conn); + } + + if(result) + return result; + break; + + case FTP_USER: + case FTP_PASS: + result = ftp_state_user_resp(conn, ftpcode, ftpc->state); + break; + + case FTP_ACCT: + result = ftp_state_acct_resp(conn, ftpcode); + break; + + case FTP_PBSZ: + PPSENDF(&ftpc->pp, "PROT %c", + data->set.use_ssl == CURLUSESSL_CONTROL ? 'C' : 'P'); + state(conn, FTP_PROT); + + break; + + case FTP_PROT: + if(ftpcode/100 == 2) + /* We have enabled SSL for the data connection! */ - conn->ssl[SECONDARYSOCKET].use = ++ conn->bits.ftp_use_data_ssl = + (data->set.use_ssl != CURLUSESSL_CONTROL) ? TRUE : FALSE; + /* FTP servers typically responds with 500 if they decide to reject + our 'P' request */ + else if(data->set.use_ssl > CURLUSESSL_CONTROL) + /* we failed and bails out */ + return CURLE_USE_SSL_FAILED; + + if(data->set.ftp_ccc) { + /* CCC - Clear Command Channel + */ + PPSENDF(&ftpc->pp, "%s", "CCC"); + state(conn, FTP_CCC); + } + else { + result = ftp_state_pwd(conn); + if(result) + return result; + } + break; + + case FTP_CCC: + if(ftpcode < 500) { + /* First shut down the SSL layer (note: this call will block) */ + result = Curl_ssl_shutdown(conn, FIRSTSOCKET); + + if(result) { + failf(conn->data, "Failed to clear the command channel (CCC)"); + return result; + } + } + + /* Then continue as normal */ + result = ftp_state_pwd(conn); + if(result) + return result; + break; + + case FTP_PWD: + if(ftpcode == 257) { + char *ptr=&data->state.buffer[4]; /* start on the first letter */ + char *dir; + char *store; + + dir = malloc(nread + 1); + if(!dir) + return CURLE_OUT_OF_MEMORY; + + /* Reply format is like + 257[rubbish]"" and the + RFC959 says + + The directory name can contain any character; embedded + double-quotes should be escaped by double-quotes (the + "quote-doubling" convention). + */ + + /* scan for the first double-quote for non-standard responses */ + while(ptr < &data->state.buffer[sizeof(data->state.buffer)] + && *ptr != '\n' && *ptr != '\0' && *ptr != '"') + ptr++; + + if('\"' == *ptr) { + /* it started good */ + ptr++; + for(store = dir; *ptr;) { + if('\"' == *ptr) { + if('\"' == ptr[1]) { + /* "quote-doubling" */ + *store = ptr[1]; + ptr++; + } + else { + /* end of path */ + *store = '\0'; /* zero terminate */ + break; /* get out of this loop */ + } + } + else + *store = *ptr; + store++; + ptr++; + } + + /* If the path name does not look like an absolute path (i.e.: it + does not start with a '/'), we probably need some server-dependent + adjustments. For example, this is the case when connecting to + an OS400 FTP server: this server supports two name syntaxes, + the default one being incompatible with standard pathes. In + addition, this server switches automatically to the regular path + syntax when one is encountered in a command: this results in + having an entrypath in the wrong syntax when later used in CWD. + The method used here is to check the server OS: we do it only + if the path name looks strange to minimize overhead on other + systems. */ + + if(!ftpc->server_os && dir[0] != '/') { + + result = Curl_pp_sendf(&ftpc->pp, "%s", "SYST"); + if(result) { + free(dir); + return result; + } + Curl_safefree(ftpc->entrypath); + ftpc->entrypath = dir; /* remember this */ + infof(data, "Entry path is '%s'\n", ftpc->entrypath); + /* also save it where getinfo can access it: */ + data->state.most_recent_ftp_entrypath = ftpc->entrypath; + state(conn, FTP_SYST); + break; + } + + Curl_safefree(ftpc->entrypath); + ftpc->entrypath = dir; /* remember this */ + infof(data, "Entry path is '%s'\n", ftpc->entrypath); + /* also save it where getinfo can access it: */ + data->state.most_recent_ftp_entrypath = ftpc->entrypath; + } + else { + /* couldn't get the path */ + free(dir); + infof(data, "Failed to figure out path\n"); + } + } + state(conn, FTP_STOP); /* we are done with the CONNECT phase! */ + DEBUGF(infof(data, "protocol connect phase DONE\n")); + break; + + case FTP_SYST: + if(ftpcode == 215) { + char *ptr=&data->state.buffer[4]; /* start on the first letter */ + char *os; + char *store; + + os = malloc(nread + 1); + if(!os) + return CURLE_OUT_OF_MEMORY; + + /* Reply format is like + 215 + */ + while(*ptr == ' ') + ptr++; + for(store = os; *ptr && *ptr != ' ';) + *store++ = *ptr++; + *store = '\0'; /* zero terminate */ + + /* Check for special servers here. */ + + if(strcasecompare(os, "OS/400")) { + /* Force OS400 name format 1. */ + result = Curl_pp_sendf(&ftpc->pp, "%s", "SITE NAMEFMT 1"); + if(result) { + free(os); + return result; + } + /* remember target server OS */ + Curl_safefree(ftpc->server_os); + ftpc->server_os = os; + state(conn, FTP_NAMEFMT); + break; + } + else { + /* Nothing special for the target server. */ + /* remember target server OS */ + Curl_safefree(ftpc->server_os); + ftpc->server_os = os; + } + } + else { + /* Cannot identify server OS. Continue anyway and cross fingers. */ + } + + state(conn, FTP_STOP); /* we are done with the CONNECT phase! */ + DEBUGF(infof(data, "protocol connect phase DONE\n")); + break; + + case FTP_NAMEFMT: + if(ftpcode == 250) { + /* Name format change successful: reload initial path. */ + ftp_state_pwd(conn); + break; + } + + state(conn, FTP_STOP); /* we are done with the CONNECT phase! */ + DEBUGF(infof(data, "protocol connect phase DONE\n")); + break; + + case FTP_QUOTE: + case FTP_POSTQUOTE: + case FTP_RETR_PREQUOTE: + case FTP_STOR_PREQUOTE: + if((ftpcode >= 400) && !ftpc->count2) { + /* failure response code, and not allowed to fail */ + failf(conn->data, "QUOT command failed with %03d", ftpcode); + return CURLE_QUOTE_ERROR; + } + result = ftp_state_quote(conn, FALSE, ftpc->state); + if(result) + return result; + + break; + + case FTP_CWD: + if(ftpcode/100 != 2) { + /* failure to CWD there */ + if(conn->data->set.ftp_create_missing_dirs && + ftpc->count1 && !ftpc->count2) { + /* try making it */ + ftpc->count2++; /* counter to prevent CWD-MKD loops */ + PPSENDF(&ftpc->pp, "MKD %s", ftpc->dirs[ftpc->count1 - 1]); + state(conn, FTP_MKD); + } + else { + /* return failure */ + failf(data, "Server denied you to change to the given directory"); + ftpc->cwdfail = TRUE; /* don't remember this path as we failed + to enter it */ + return CURLE_REMOTE_ACCESS_DENIED; + } + } + else { + /* success */ + ftpc->count2=0; + if(++ftpc->count1 <= ftpc->dirdepth) { + /* send next CWD */ + PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->count1 - 1]); + } + else { + result = ftp_state_mdtm(conn); + if(result) + return result; + } + } + break; + + case FTP_MKD: + if((ftpcode/100 != 2) && !ftpc->count3--) { + /* failure to MKD the dir */ + failf(data, "Failed to MKD dir: %03d", ftpcode); + return CURLE_REMOTE_ACCESS_DENIED; + } + state(conn, FTP_CWD); + /* send CWD */ + PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->count1 - 1]); + break; + + case FTP_MDTM: + result = ftp_state_mdtm_resp(conn, ftpcode); + break; + + case FTP_TYPE: + case FTP_LIST_TYPE: + case FTP_RETR_TYPE: + case FTP_STOR_TYPE: + result = ftp_state_type_resp(conn, ftpcode, ftpc->state); + break; + + case FTP_SIZE: + case FTP_RETR_SIZE: + case FTP_STOR_SIZE: + result = ftp_state_size_resp(conn, ftpcode, ftpc->state); + break; + + case FTP_REST: + case FTP_RETR_REST: + result = ftp_state_rest_resp(conn, ftpcode, ftpc->state); + break; + + case FTP_PRET: + if(ftpcode != 200) { + /* there only is this one standard OK return code. */ + failf(data, "PRET command not accepted: %03d", ftpcode); + return CURLE_FTP_PRET_FAILED; + } + result = ftp_state_use_pasv(conn); + break; + + case FTP_PASV: + result = ftp_state_pasv_resp(conn, ftpcode); + break; + + case FTP_PORT: + result = ftp_state_port_resp(conn, ftpcode); + break; + + case FTP_LIST: + case FTP_RETR: + result = ftp_state_get_resp(conn, ftpcode, ftpc->state); + break; + + case FTP_STOR: + result = ftp_state_stor_resp(conn, ftpcode, ftpc->state); + break; + + case FTP_QUIT: + /* fallthrough, just stop! */ + default: + /* internal error */ + state(conn, FTP_STOP); + break; + } + } /* if(ftpcode) */ + + return result; +} + + +/* called repeatedly until done from multi.c */ +static CURLcode ftp_multi_statemach(struct connectdata *conn, + bool *done) +{ + struct ftp_conn *ftpc = &conn->proto.ftpc; + CURLcode result = Curl_pp_statemach(&ftpc->pp, FALSE); + + /* Check for the state outside of the Curl_socket_check() return code checks + since at times we are in fact already in this state when this function + gets called. */ + *done = (ftpc->state == FTP_STOP) ? TRUE : FALSE; + + return result; +} + +static CURLcode ftp_block_statemach(struct connectdata *conn) +{ + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + CURLcode result = CURLE_OK; + + while(ftpc->state != FTP_STOP) { + result = Curl_pp_statemach(pp, TRUE); + if(result) + break; + } + + return result; +} + +/* + * ftp_connect() should do everything that is to be considered a part of + * the connection phase. + * + * The variable 'done' points to will be TRUE if the protocol-layer connect + * phase is done when this function returns, or FALSE if not. + * + */ +static CURLcode ftp_connect(struct connectdata *conn, + bool *done) /* see description above */ +{ + CURLcode result; + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + + *done = FALSE; /* default to not done yet */ + + /* We always support persistent connections on ftp */ + connkeep(conn, "FTP default"); + + pp->response_time = RESP_TIMEOUT; /* set default response time-out */ + pp->statemach_act = ftp_statemach_act; + pp->endofresp = ftp_endofresp; + pp->conn = conn; + + if(conn->handler->flags & PROTOPT_SSL) { + /* BLOCKING */ + result = Curl_ssl_connect(conn, FIRSTSOCKET); + if(result) + return result; + } + + Curl_pp_init(pp); /* init the generic pingpong data */ + + /* When we connect, we start in the state where we await the 220 + response */ + state(conn, FTP_WAIT220); + + result = ftp_multi_statemach(conn, done); + + return result; +} + +/*********************************************************************** + * + * ftp_done() + * + * The DONE function. This does what needs to be done after a single DO has + * performed. + * + * Input argument is already checked for validity. + */ +static CURLcode ftp_done(struct connectdata *conn, CURLcode status, + bool premature) +{ + struct Curl_easy *data = conn->data; + struct FTP *ftp = data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + ssize_t nread; + int ftpcode; + CURLcode result = CURLE_OK; - char *path; ++ char *path = NULL; + const char *path_to_use = data->state.path; + + if(!ftp) + return CURLE_OK; + + switch(status) { + case CURLE_BAD_DOWNLOAD_RESUME: + case CURLE_FTP_WEIRD_PASV_REPLY: + case CURLE_FTP_PORT_FAILED: + case CURLE_FTP_ACCEPT_FAILED: + case CURLE_FTP_ACCEPT_TIMEOUT: + case CURLE_FTP_COULDNT_SET_TYPE: + case CURLE_FTP_COULDNT_RETR_FILE: + case CURLE_PARTIAL_FILE: + case CURLE_UPLOAD_FAILED: + case CURLE_REMOTE_ACCESS_DENIED: + case CURLE_FILESIZE_EXCEEDED: + case CURLE_REMOTE_FILE_NOT_FOUND: + case CURLE_WRITE_ERROR: + /* the connection stays alive fine even though this happened */ + /* fall-through */ + case CURLE_OK: /* doesn't affect the control connection's status */ + if(!premature) + break; + + /* until we cope better with prematurely ended requests, let them + * fallback as if in complete failure */ + default: /* by default, an error means the control connection is + wedged and should not be used anymore */ + ftpc->ctl_valid = FALSE; + ftpc->cwdfail = TRUE; /* set this TRUE to prevent us to remember the + current path, as this connection is going */ + connclose(conn, "FTP ended with bad error code"); + result = status; /* use the already set error code */ + break; + } + + /* now store a copy of the directory we are in */ + free(ftpc->prevpath); + + if(data->set.wildcardmatch) { + if(data->set.chunk_end && ftpc->file) { + data->set.chunk_end(data->wildcard.customptr); + } + ftpc->known_filesize = -1; + } + + if(!result) + /* get the "raw" path */ + result = Curl_urldecode(data, path_to_use, 0, &path, NULL, FALSE); + if(result) { + /* We can limp along anyway (and should try to since we may already be in + * the error path) */ + ftpc->ctl_valid = FALSE; /* mark control connection as bad */ + connclose(conn, "FTP: out of memory!"); /* mark for connection closure */ + ftpc->prevpath = NULL; /* no path remembering */ + } + else { + size_t flen = ftpc->file?strlen(ftpc->file):0; /* file is "raw" already */ + size_t dlen = strlen(path)-flen; + if(!ftpc->cwdfail) { + if(dlen && (data->set.ftp_filemethod != FTPFILE_NOCWD)) { + ftpc->prevpath = path; + if(flen) + /* if 'path' is not the whole string */ + ftpc->prevpath[dlen]=0; /* terminate */ + } + else { + /* we never changed dir */ + ftpc->prevpath=strdup(""); + free(path); + } + if(ftpc->prevpath) + infof(data, "Remembering we are in dir \"%s\"\n", ftpc->prevpath); + } + else { + ftpc->prevpath = NULL; /* no path */ + free(path); + } + } + /* free the dir tree and file parts */ + freedirs(ftpc); + + /* shut down the socket to inform the server we're done */ + +#ifdef _WIN32_WCE + shutdown(conn->sock[SECONDARYSOCKET], 2); /* SD_BOTH */ +#endif + + if(conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) { + if(!result && ftpc->dont_check && data->req.maxdownload > 0) { + /* partial download completed */ + result = Curl_pp_sendf(pp, "%s", "ABOR"); + if(result) { + failf(data, "Failure sending ABOR command: %s", + curl_easy_strerror(result)); + ftpc->ctl_valid = FALSE; /* mark control connection as bad */ + connclose(conn, "ABOR command failed"); /* connection closure */ + } + } + + if(conn->ssl[SECONDARYSOCKET].use) { + /* The secondary socket is using SSL so we must close down that part + first before we close the socket for real */ + Curl_ssl_close(conn, SECONDARYSOCKET); + + /* Note that we keep "use" set to TRUE since that (next) connection is + still requested to use SSL */ + } + close_secondarysocket(conn); + } + + if(!result && (ftp->transfer == FTPTRANSFER_BODY) && ftpc->ctl_valid && + pp->pending_resp && !premature) { + /* + * Let's see what the server says about the transfer we just performed, + * but lower the timeout as sometimes this connection has died while the + * data has been transferred. This happens when doing through NATs etc that + * abandon old silent connections. + */ + long old_time = pp->response_time; + + pp->response_time = 60*1000; /* give it only a minute for now */ + pp->response = Curl_tvnow(); /* timeout relative now */ + + result = Curl_GetFTPResponse(&nread, conn, &ftpcode); + + pp->response_time = old_time; /* set this back to previous value */ + + if(!nread && (CURLE_OPERATION_TIMEDOUT == result)) { + failf(data, "control connection looks dead"); + ftpc->ctl_valid = FALSE; /* mark control connection as bad */ + connclose(conn, "Timeout or similar in FTP DONE operation"); /* close */ + } + + if(result) + return result; + + if(ftpc->dont_check && data->req.maxdownload > 0) { + /* we have just sent ABOR and there is no reliable way to check if it was + * successful or not; we have to close the connection now */ + infof(data, "partial download completed, closing connection\n"); + connclose(conn, "Partial download with no ability to check"); + return result; + } + + if(!ftpc->dont_check) { + /* 226 Transfer complete, 250 Requested file action okay, completed. */ + if((ftpcode != 226) && (ftpcode != 250)) { + failf(data, "server did not report OK, got %d", ftpcode); + result = CURLE_PARTIAL_FILE; + } + } + } + + if(result || premature) + /* the response code from the transfer showed an error already so no + use checking further */ + ; + else if(data->set.upload) { + if((-1 != data->state.infilesize) && + (data->state.infilesize != *ftp->bytecountp) && + !data->set.crlf && + (ftp->transfer == FTPTRANSFER_BODY)) { + failf(data, "Uploaded unaligned file size (%" CURL_FORMAT_CURL_OFF_T + " out of %" CURL_FORMAT_CURL_OFF_T " bytes)", + *ftp->bytecountp, data->state.infilesize); + result = CURLE_PARTIAL_FILE; + } + } + else { + if((-1 != data->req.size) && + (data->req.size != *ftp->bytecountp) && +#ifdef CURL_DO_LINEEND_CONV + /* Most FTP servers don't adjust their file SIZE response for CRLFs, so + * we'll check to see if the discrepancy can be explained by the number + * of CRLFs we've changed to LFs. + */ + ((data->req.size + data->state.crlf_conversions) != + *ftp->bytecountp) && +#endif /* CURL_DO_LINEEND_CONV */ + (data->req.maxdownload != *ftp->bytecountp)) { + failf(data, "Received only partial file: %" CURL_FORMAT_CURL_OFF_T + " bytes", *ftp->bytecountp); + result = CURLE_PARTIAL_FILE; + } + else if(!ftpc->dont_check && + !*ftp->bytecountp && + (data->req.size>0)) { + failf(data, "No data was received!"); + result = CURLE_FTP_COULDNT_RETR_FILE; + } + } + + /* clear these for next connection */ + ftp->transfer = FTPTRANSFER_BODY; + ftpc->dont_check = FALSE; + + /* Send any post-transfer QUOTE strings? */ + if(!status && !result && !premature && data->set.postquote) + result = ftp_sendquote(conn, data->set.postquote); + + return result; +} + +/*********************************************************************** + * + * ftp_sendquote() + * + * Where a 'quote' means a list of custom commands to send to the server. + * The quote list is passed as an argument. + * + * BLOCKING + */ + +static +CURLcode ftp_sendquote(struct connectdata *conn, struct curl_slist *quote) +{ + struct curl_slist *item; + ssize_t nread; + int ftpcode; + CURLcode result; + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + + item = quote; + while(item) { + if(item->data) { + char *cmd = item->data; + bool acceptfail = FALSE; + + /* if a command starts with an asterisk, which a legal FTP command never + can, the command will be allowed to fail without it causing any + aborts or cancels etc. It will cause libcurl to act as if the command + is successful, whatever the server reponds. */ + + if(cmd[0] == '*') { + cmd++; + acceptfail = TRUE; + } + + PPSENDF(&conn->proto.ftpc.pp, "%s", cmd); + + pp->response = Curl_tvnow(); /* timeout relative now */ + + result = Curl_GetFTPResponse(&nread, conn, &ftpcode); + if(result) + return result; + + if(!acceptfail && (ftpcode >= 400)) { + failf(conn->data, "QUOT string not accepted: %s", cmd); + return CURLE_QUOTE_ERROR; + } + } + + item = item->next; + } + + return CURLE_OK; +} + +/*********************************************************************** + * + * ftp_need_type() + * + * Returns TRUE if we in the current situation should send TYPE + */ +static int ftp_need_type(struct connectdata *conn, + bool ascii_wanted) +{ + return conn->proto.ftpc.transfertype != (ascii_wanted?'A':'I'); +} + +/*********************************************************************** + * + * ftp_nb_type() + * + * Set TYPE. We only deal with ASCII or BINARY so this function + * sets one of them. + * If the transfer type is not sent, simulate on OK response in newstate + */ +static CURLcode ftp_nb_type(struct connectdata *conn, + bool ascii, ftpstate newstate) +{ + struct ftp_conn *ftpc = &conn->proto.ftpc; + CURLcode result; + char want = (char)(ascii?'A':'I'); + + if(ftpc->transfertype == want) { + state(conn, newstate); + return ftp_state_type_resp(conn, 200, newstate); + } + + PPSENDF(&ftpc->pp, "TYPE %c", want); + state(conn, newstate); + + /* keep track of our current transfer type */ + ftpc->transfertype = want; + return CURLE_OK; +} + +/*************************************************************************** + * + * ftp_pasv_verbose() + * + * This function only outputs some informationals about this second connection + * when we've issued a PASV command before and thus we have connected to a + * possibly new IP address. + * + */ +#ifndef CURL_DISABLE_VERBOSE_STRINGS +static void +ftp_pasv_verbose(struct connectdata *conn, + Curl_addrinfo *ai, + char *newhost, /* ascii version */ + int port) +{ + char buf[256]; + Curl_printable_address(ai, buf, sizeof(buf)); + infof(conn->data, "Connecting to %s (%s) port %d\n", newhost, buf, port); +} +#endif + +/* + Check if this is a range download, and if so, set the internal variables + properly. + */ + +static CURLcode ftp_range(struct connectdata *conn) +{ + curl_off_t from, to; + char *ptr; + char *ptr2; + struct Curl_easy *data = conn->data; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + if(data->state.use_range && data->state.range) { + from=curlx_strtoofft(data->state.range, &ptr, 0); + while(*ptr && (ISSPACE(*ptr) || (*ptr=='-'))) + ptr++; + to=curlx_strtoofft(ptr, &ptr2, 0); + if(ptr == ptr2) { + /* we didn't get any digit */ + to=-1; + } + if((-1 == to) && (from>=0)) { + /* X - */ + data->state.resume_from = from; + DEBUGF(infof(conn->data, "FTP RANGE %" CURL_FORMAT_CURL_OFF_T + " to end of file\n", from)); + } + else if(from < 0) { + /* -Y */ + data->req.maxdownload = -from; + data->state.resume_from = from; + DEBUGF(infof(conn->data, "FTP RANGE the last %" CURL_FORMAT_CURL_OFF_T + " bytes\n", -from)); + } + else { + /* X-Y */ + data->req.maxdownload = (to-from)+1; /* include last byte */ + data->state.resume_from = from; + DEBUGF(infof(conn->data, "FTP RANGE from %" CURL_FORMAT_CURL_OFF_T + " getting %" CURL_FORMAT_CURL_OFF_T " bytes\n", + from, data->req.maxdownload)); + } + DEBUGF(infof(conn->data, "range-download from %" CURL_FORMAT_CURL_OFF_T + " to %" CURL_FORMAT_CURL_OFF_T ", totally %" + CURL_FORMAT_CURL_OFF_T " bytes\n", + from, to, data->req.maxdownload)); + ftpc->dont_check = TRUE; /* dont check for successful transfer */ + } + else + data->req.maxdownload = -1; + return CURLE_OK; +} + + +/* + * ftp_do_more() + * + * This function shall be called when the second FTP (data) connection is + * connected. + * + * 'complete' can return 0 for incomplete, 1 for done and -1 for go back + * (which basically is only for when PASV is being sent to retry a failed + * EPSV). + */ + +static CURLcode ftp_do_more(struct connectdata *conn, int *completep) +{ + struct Curl_easy *data=conn->data; + struct ftp_conn *ftpc = &conn->proto.ftpc; + CURLcode result = CURLE_OK; + bool connected = FALSE; + bool complete = FALSE; + + /* the ftp struct is inited in ftp_connect() */ + struct FTP *ftp = data->req.protop; + + /* if the second connection isn't done yet, wait for it */ + if(!conn->bits.tcpconnect[SECONDARYSOCKET]) { + if(conn->tunnel_state[SECONDARYSOCKET] == TUNNEL_CONNECT) { + /* As we're in TUNNEL_CONNECT state now, we know the proxy name and port + aren't used so we blank their arguments. TODO: make this nicer */ + result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0, FALSE); + + return result; + } + + result = Curl_is_connected(conn, SECONDARYSOCKET, &connected); + + /* Ready to do more? */ + if(connected) { + DEBUGF(infof(data, "DO-MORE connected phase starts\n")); - if(conn->bits.proxy) { - infof(data, "Connection to proxy confirmed\n"); - result = proxy_magic(conn, ftpc->newhost, ftpc->newport, &connected); - } + } + else { + if(result && (ftpc->count1 == 0)) { + *completep = -1; /* go back to DOING please */ + /* this is a EPSV connect failing, try PASV instead */ + return ftp_epsv_disable(conn); + } + return result; + } + } + ++ result = Curl_proxy_connect(conn, SECONDARYSOCKET); ++ if(result) ++ return result; ++ ++ if(CONNECT_SECONDARYSOCKET_PROXY_SSL()) ++ return result; ++ ++ if(conn->bits.tunnel_proxy && conn->bits.httpproxy && ++ conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE) ++ return result; ++ ++ + if(ftpc->state) { + /* already in a state so skip the initial commands. + They are only done to kickstart the do_more state */ + result = ftp_multi_statemach(conn, &complete); + + *completep = (int)complete; + + /* if we got an error or if we don't wait for a data connection return + immediately */ + if(result || (ftpc->wait_data_conn != TRUE)) + return result; + + if(ftpc->wait_data_conn) + /* if we reach the end of the FTP state machine here, *complete will be + TRUE but so is ftpc->wait_data_conn, which says we need to wait for + the data connection and therefore we're not actually complete */ + *completep = 0; + } + + if(ftp->transfer <= FTPTRANSFER_INFO) { + /* a transfer is about to take place, or if not a file name was given + so we'll do a SIZE on it later and then we need the right TYPE first */ + + if(ftpc->wait_data_conn == TRUE) { + bool serv_conned; + + result = ReceivedServerConnect(conn, &serv_conned); + if(result) + return result; /* Failed to accept data connection */ + + if(serv_conned) { + /* It looks data connection is established */ + result = AcceptServerConnect(conn); + ftpc->wait_data_conn = FALSE; + if(!result) + result = InitiateTransfer(conn); + + if(result) + return result; + + *completep = 1; /* this state is now complete when the server has + connected back to us */ + } + } + else if(data->set.upload) { + result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_STOR_TYPE); + if(result) + return result; + + result = ftp_multi_statemach(conn, &complete); + if(ftpc->wait_data_conn) + /* if we reach the end of the FTP state machine here, *complete will be + TRUE but so is ftpc->wait_data_conn, which says we need to wait for + the data connection and therefore we're not actually complete */ + *completep = 0; + else + *completep = (int)complete; + } + else { + /* download */ + ftp->downloadsize = -1; /* unknown as of yet */ + + result = ftp_range(conn); + if(result) + ; + else if(data->set.ftp_list_only || !ftpc->file) { + /* The specified path ends with a slash, and therefore we think this + is a directory that is requested, use LIST. But before that we + need to set ASCII transfer mode. */ + + /* But only if a body transfer was requested. */ + if(ftp->transfer == FTPTRANSFER_BODY) { + result = ftp_nb_type(conn, TRUE, FTP_LIST_TYPE); + if(result) + return result; + } + /* otherwise just fall through */ + } + else { + result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_RETR_TYPE); + if(result) + return result; + } + + result = ftp_multi_statemach(conn, &complete); + *completep = (int)complete; + } + return result; + } + + if(!result && (ftp->transfer != FTPTRANSFER_BODY)) + /* no data to transfer. FIX: it feels like a kludge to have this here + too! */ + Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + + if(!ftpc->wait_data_conn) { + /* no waiting for the data connection so this is now complete */ + *completep = 1; + DEBUGF(infof(data, "DO-MORE phase ends with %d\n", (int)result)); + } + + return result; +} + + + +/*********************************************************************** + * + * ftp_perform() + * + * This is the actual DO function for FTP. Get a file/directory according to + * the options previously setup. + */ + +static +CURLcode ftp_perform(struct connectdata *conn, + bool *connected, /* connect status after PASV / PORT */ + bool *dophase_done) +{ + /* this is FTP and no proxy */ + CURLcode result=CURLE_OK; + + DEBUGF(infof(conn->data, "DO phase starts\n")); + + if(conn->data->set.opt_no_body) { + /* requested no body means no transfer... */ + struct FTP *ftp = conn->data->req.protop; + ftp->transfer = FTPTRANSFER_INFO; + } + + *dophase_done = FALSE; /* not done yet */ + + /* start the first command in the DO phase */ + result = ftp_state_quote(conn, TRUE, FTP_QUOTE); + if(result) + return result; + + /* run the state-machine */ + result = ftp_multi_statemach(conn, dophase_done); + + *connected = conn->bits.tcpconnect[SECONDARYSOCKET]; + + infof(conn->data, "ftp_perform ends with SECONDARY: %d\n", *connected); + + if(*dophase_done) { + DEBUGF(infof(conn->data, "DO phase is complete1\n")); + } + + return result; +} + +static void wc_data_dtor(void *ptr) +{ + struct ftp_wc_tmpdata *tmp = ptr; + if(tmp) + Curl_ftp_parselist_data_free(&tmp->parser); + free(tmp); +} + +static CURLcode init_wc_data(struct connectdata *conn) +{ + char *last_slash; + char *path = conn->data->state.path; + struct WildcardData *wildcard = &(conn->data->wildcard); + CURLcode result = CURLE_OK; + struct ftp_wc_tmpdata *ftp_tmp; + + last_slash = strrchr(conn->data->state.path, '/'); + if(last_slash) { + last_slash++; + if(last_slash[0] == '\0') { + wildcard->state = CURLWC_CLEAN; + result = ftp_parse_url_path(conn); + return result; + } + else { + wildcard->pattern = strdup(last_slash); + if(!wildcard->pattern) + return CURLE_OUT_OF_MEMORY; + last_slash[0] = '\0'; /* cut file from path */ + } + } + else { /* there is only 'wildcard pattern' or nothing */ + if(path[0]) { + wildcard->pattern = strdup(path); + if(!wildcard->pattern) + return CURLE_OUT_OF_MEMORY; + path[0] = '\0'; + } + else { /* only list */ + wildcard->state = CURLWC_CLEAN; + result = ftp_parse_url_path(conn); + return result; + } + } + + /* program continues only if URL is not ending with slash, allocate needed + resources for wildcard transfer */ + + /* allocate ftp protocol specific temporary wildcard data */ + ftp_tmp = calloc(1, sizeof(struct ftp_wc_tmpdata)); + if(!ftp_tmp) { + Curl_safefree(wildcard->pattern); + return CURLE_OUT_OF_MEMORY; + } + + /* INITIALIZE parselist structure */ + ftp_tmp->parser = Curl_ftp_parselist_data_alloc(); + if(!ftp_tmp->parser) { + Curl_safefree(wildcard->pattern); + free(ftp_tmp); + return CURLE_OUT_OF_MEMORY; + } + + wildcard->tmp = ftp_tmp; /* put it to the WildcardData tmp pointer */ + wildcard->tmp_dtor = wc_data_dtor; + + /* wildcard does not support NOCWD option (assert it?) */ + if(conn->data->set.ftp_filemethod == FTPFILE_NOCWD) + conn->data->set.ftp_filemethod = FTPFILE_MULTICWD; + + /* try to parse ftp url */ + result = ftp_parse_url_path(conn); + if(result) { + Curl_safefree(wildcard->pattern); + wildcard->tmp_dtor(wildcard->tmp); + wildcard->tmp_dtor = ZERO_NULL; + wildcard->tmp = NULL; + return result; + } + + wildcard->path = strdup(conn->data->state.path); + if(!wildcard->path) { + Curl_safefree(wildcard->pattern); + wildcard->tmp_dtor(wildcard->tmp); + wildcard->tmp_dtor = ZERO_NULL; + wildcard->tmp = NULL; + return CURLE_OUT_OF_MEMORY; + } + + /* backup old write_function */ + ftp_tmp->backup.write_function = conn->data->set.fwrite_func; + /* parsing write function */ + conn->data->set.fwrite_func = Curl_ftp_parselist; + /* backup old file descriptor */ + ftp_tmp->backup.file_descriptor = conn->data->set.out; + /* let the writefunc callback know what curl pointer is working with */ + conn->data->set.out = conn; + + infof(conn->data, "Wildcard - Parsing started\n"); + return CURLE_OK; +} + +/* This is called recursively */ +static CURLcode wc_statemach(struct connectdata *conn) +{ + struct WildcardData * const wildcard = &(conn->data->wildcard); + CURLcode result = CURLE_OK; + - switch (wildcard->state) { ++ switch(wildcard->state) { + case CURLWC_INIT: + result = init_wc_data(conn); + if(wildcard->state == CURLWC_CLEAN) + /* only listing! */ + break; + else + wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING; + break; + + case CURLWC_MATCHING: { + /* In this state is LIST response successfully parsed, so lets restore + previous WRITEFUNCTION callback and WRITEDATA pointer */ + struct ftp_wc_tmpdata *ftp_tmp = wildcard->tmp; + conn->data->set.fwrite_func = ftp_tmp->backup.write_function; + conn->data->set.out = ftp_tmp->backup.file_descriptor; + ftp_tmp->backup.write_function = ZERO_NULL; + ftp_tmp->backup.file_descriptor = NULL; + wildcard->state = CURLWC_DOWNLOADING; + + if(Curl_ftp_parselist_geterror(ftp_tmp->parser)) { + /* error found in LIST parsing */ + wildcard->state = CURLWC_CLEAN; + return wc_statemach(conn); + } + else if(wildcard->filelist->size == 0) { + /* no corresponding file */ + wildcard->state = CURLWC_CLEAN; + return CURLE_REMOTE_FILE_NOT_FOUND; + } + return wc_statemach(conn); + } + + case CURLWC_DOWNLOADING: { + /* filelist has at least one file, lets get first one */ + struct ftp_conn *ftpc = &conn->proto.ftpc; + struct curl_fileinfo *finfo = wildcard->filelist->head->ptr; + + char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename); + if(!tmp_path) + return CURLE_OUT_OF_MEMORY; + + /* switch default "state.pathbuffer" and tmp_path, good to see + ftp_parse_url_path function to understand this trick */ + Curl_safefree(conn->data->state.pathbuffer); + conn->data->state.pathbuffer = tmp_path; + conn->data->state.path = tmp_path; + + infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename); + if(conn->data->set.chunk_bgn) { + long userresponse = conn->data->set.chunk_bgn( + finfo, wildcard->customptr, (int)wildcard->filelist->size); + switch(userresponse) { + case CURL_CHUNK_BGN_FUNC_SKIP: + infof(conn->data, "Wildcard - \"%s\" skipped by user\n", + finfo->filename); + wildcard->state = CURLWC_SKIP; + return wc_statemach(conn); + case CURL_CHUNK_BGN_FUNC_FAIL: + return CURLE_CHUNK_FAILED; + } + } + + if(finfo->filetype != CURLFILETYPE_FILE) { + wildcard->state = CURLWC_SKIP; + return wc_statemach(conn); + } + + if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE) + ftpc->known_filesize = finfo->size; + + result = ftp_parse_url_path(conn); + if(result) + return result; + + /* we don't need the Curl_fileinfo of first file anymore */ + Curl_llist_remove(wildcard->filelist, wildcard->filelist->head, NULL); + + if(wildcard->filelist->size == 0) { /* remains only one file to down. */ + wildcard->state = CURLWC_CLEAN; + /* after that will be ftp_do called once again and no transfer + will be done because of CURLWC_CLEAN state */ + return CURLE_OK; + } + } break; + + case CURLWC_SKIP: { + if(conn->data->set.chunk_end) + conn->data->set.chunk_end(conn->data->wildcard.customptr); + Curl_llist_remove(wildcard->filelist, wildcard->filelist->head, NULL); + wildcard->state = (wildcard->filelist->size == 0) ? + CURLWC_CLEAN : CURLWC_DOWNLOADING; + return wc_statemach(conn); + } + + case CURLWC_CLEAN: { + struct ftp_wc_tmpdata *ftp_tmp = wildcard->tmp; + result = CURLE_OK; + if(ftp_tmp) + result = Curl_ftp_parselist_geterror(ftp_tmp->parser); + + wildcard->state = result ? CURLWC_ERROR : CURLWC_DONE; + } break; + + case CURLWC_DONE: + case CURLWC_ERROR: + break; + } + + return result; +} + +/*********************************************************************** + * + * ftp_do() + * + * This function is registered as 'curl_do' function. It decodes the path + * parts etc as a wrapper to the actual DO function (ftp_perform). + * + * The input argument is already checked for validity. + */ +static CURLcode ftp_do(struct connectdata *conn, bool *done) +{ + CURLcode result = CURLE_OK; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + *done = FALSE; /* default to false */ + ftpc->wait_data_conn = FALSE; /* default to no such wait */ + + if(conn->data->set.wildcardmatch) { + result = wc_statemach(conn); + if(conn->data->wildcard.state == CURLWC_SKIP || + conn->data->wildcard.state == CURLWC_DONE) { + /* do not call ftp_regular_transfer */ + return CURLE_OK; + } + if(result) /* error, loop or skipping the file */ + return result; + } + else { /* no wildcard FSM needed */ + result = ftp_parse_url_path(conn); + if(result) + return result; + } + + result = ftp_regular_transfer(conn, done); + + return result; +} + + +CURLcode Curl_ftpsend(struct connectdata *conn, const char *cmd) +{ + ssize_t bytes_written; +#define SBUF_SIZE 1024 + char s[SBUF_SIZE]; + size_t write_len; + char *sptr=s; + CURLcode result = CURLE_OK; +#ifdef HAVE_GSSAPI + enum protection_level data_sec = conn->data_prot; +#endif + + write_len = strlen(cmd); + if(write_len > (sizeof(s) -3)) + return CURLE_BAD_FUNCTION_ARGUMENT; + + strcpy(&s[write_len], "\r\n"); /* append a trailing CRLF */ + write_len +=2; + + bytes_written=0; + + result = Curl_convert_to_network(conn->data, s, write_len); + /* Curl_convert_to_network calls failf if unsuccessful */ + if(result) + return result; + + for(;;) { +#ifdef HAVE_GSSAPI + conn->data_prot = PROT_CMD; +#endif + result = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len, + &bytes_written); +#ifdef HAVE_GSSAPI + DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST); + conn->data_prot = data_sec; +#endif + + if(result) + break; + + if(conn->data->set.verbose) + Curl_debug(conn->data, CURLINFO_HEADER_OUT, + sptr, (size_t)bytes_written, conn); + + if(bytes_written != (ssize_t)write_len) { + write_len -= bytes_written; + sptr += bytes_written; + } + else + break; + } + + return result; +} + +/*********************************************************************** + * + * ftp_quit() + * + * This should be called before calling sclose() on an ftp control connection + * (not data connections). We should then wait for the response from the + * server before returning. The calling code should then try to close the + * connection. + * + */ +static CURLcode ftp_quit(struct connectdata *conn) +{ + CURLcode result = CURLE_OK; + + if(conn->proto.ftpc.ctl_valid) { + result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", "QUIT"); + if(result) { + failf(conn->data, "Failure sending QUIT command: %s", + curl_easy_strerror(result)); + conn->proto.ftpc.ctl_valid = FALSE; /* mark control connection as bad */ + connclose(conn, "QUIT command failed"); /* mark for connection closure */ + state(conn, FTP_STOP); + return result; + } + + state(conn, FTP_QUIT); + + result = ftp_block_statemach(conn); + } + + return result; +} + +/*********************************************************************** + * + * ftp_disconnect() + * + * Disconnect from an FTP server. Cleanup protocol-specific per-connection + * resources. BLOCKING. + */ +static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection) +{ + struct ftp_conn *ftpc= &conn->proto.ftpc; + struct pingpong *pp = &ftpc->pp; + + /* We cannot send quit unconditionally. If this connection is stale or + bad in any way, sending quit and waiting around here will make the + disconnect wait in vain and cause more problems than we need to. + + ftp_quit() will check the state of ftp->ctl_valid. If it's ok it + will try to send the QUIT command, otherwise it will just return. + */ + if(dead_connection) + ftpc->ctl_valid = FALSE; + + /* The FTP session may or may not have been allocated/setup at this point! */ + (void)ftp_quit(conn); /* ignore errors on the QUIT */ + + if(ftpc->entrypath) { + struct Curl_easy *data = conn->data; + if(data->state.most_recent_ftp_entrypath == ftpc->entrypath) { + data->state.most_recent_ftp_entrypath = NULL; + } + free(ftpc->entrypath); + ftpc->entrypath = NULL; + } + + freedirs(ftpc); + free(ftpc->prevpath); + ftpc->prevpath = NULL; + free(ftpc->server_os); + ftpc->server_os = NULL; + + Curl_pp_disconnect(pp); + +#ifdef HAVE_GSSAPI + Curl_sec_end(conn); +#endif + + return CURLE_OK; +} + +/*********************************************************************** + * + * ftp_parse_url_path() + * + * Parse the URL path into separate path components. + * + */ +static +CURLcode ftp_parse_url_path(struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + /* the ftp struct is already inited in ftp_connect() */ + struct FTP *ftp = data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + const char *slash_pos; /* position of the first '/' char in curpos */ + const char *path_to_use = data->state.path; + const char *cur_pos; + const char *filename = NULL; + - cur_pos = path_to_use; /* current position in path. point at the begin - of next path component */ ++ cur_pos = path_to_use; /* current position in path. point at the begin of ++ next path component */ + + ftpc->ctl_valid = FALSE; + ftpc->cwdfail = FALSE; + + switch(data->set.ftp_filemethod) { + case FTPFILE_NOCWD: + /* fastest, but less standard-compliant */ + + /* + The best time to check whether the path is a file or directory is right + here. so: + + the first condition in the if() right here, is there just in case + someone decides to set path to NULL one day + */ + if(path_to_use[0] && + (path_to_use[strlen(path_to_use) - 1] != '/') ) + filename = path_to_use; /* this is a full file path */ + /* + else { + ftpc->file is not used anywhere other than for operations on a file. + In other words, never for directory operations. + So we can safely leave filename as NULL here and use it as a + argument in dir/file decisions. + } + */ + break; + + case FTPFILE_SINGLECWD: + /* get the last slash */ + if(!path_to_use[0]) { + /* no dir, no file */ + ftpc->dirdepth = 0; + break; + } + slash_pos=strrchr(cur_pos, '/'); + if(slash_pos || !*cur_pos) { + size_t dirlen = slash_pos-cur_pos; + CURLcode result; + + ftpc->dirs = calloc(1, sizeof(ftpc->dirs[0])); + if(!ftpc->dirs) + return CURLE_OUT_OF_MEMORY; + + if(!dirlen) + dirlen++; + + result = Curl_urldecode(conn->data, slash_pos ? cur_pos : "/", + slash_pos ? dirlen : 1, + &ftpc->dirs[0], NULL, + FALSE); + if(result) { + freedirs(ftpc); + return result; + } + ftpc->dirdepth = 1; /* we consider it to be a single dir */ + filename = slash_pos ? slash_pos+1 : cur_pos; /* rest is file name */ + } + else + filename = cur_pos; /* this is a file name only */ + break; + + default: /* allow pretty much anything */ + case FTPFILE_MULTICWD: + ftpc->dirdepth = 0; + ftpc->diralloc = 5; /* default dir depth to allocate */ + ftpc->dirs = calloc(ftpc->diralloc, sizeof(ftpc->dirs[0])); + if(!ftpc->dirs) + return CURLE_OUT_OF_MEMORY; + + /* we have a special case for listing the root dir only */ + if(!strcmp(path_to_use, "/")) { + cur_pos++; /* make it point to the zero byte */ + ftpc->dirs[0] = strdup("/"); + ftpc->dirdepth++; + } + else { + /* parse the URL path into separate path components */ + while((slash_pos = strchr(cur_pos, '/')) != NULL) { + /* 1 or 0 pointer offset to indicate absolute directory */ + ssize_t absolute_dir = ((cur_pos - data->state.path > 0) && + (ftpc->dirdepth == 0))?1:0; + + /* seek out the next path component */ + if(slash_pos-cur_pos) { + /* we skip empty path components, like "x//y" since the FTP command + CWD requires a parameter and a non-existent parameter a) doesn't + work on many servers and b) has no effect on the others. */ + size_t len = slash_pos - cur_pos + absolute_dir; + CURLcode result = + Curl_urldecode(conn->data, cur_pos - absolute_dir, len, + &ftpc->dirs[ftpc->dirdepth], NULL, + TRUE); + if(result) { + free(ftpc->dirs[ftpc->dirdepth]); + freedirs(ftpc); + return result; + } + } + else { + cur_pos = slash_pos + 1; /* jump to the rest of the string */ + if(!ftpc->dirdepth) { + /* path starts with a slash, add that as a directory */ + ftpc->dirs[ftpc->dirdepth] = strdup("/"); + if(!ftpc->dirs[ftpc->dirdepth++]) { /* run out of memory ... */ + failf(data, "no memory"); + freedirs(ftpc); + return CURLE_OUT_OF_MEMORY; + } + } + continue; + } + + cur_pos = slash_pos + 1; /* jump to the rest of the string */ + if(++ftpc->dirdepth >= ftpc->diralloc) { + /* enlarge array */ + char **bigger; + ftpc->diralloc *= 2; /* double the size each time */ + bigger = realloc(ftpc->dirs, ftpc->diralloc * sizeof(ftpc->dirs[0])); + if(!bigger) { + freedirs(ftpc); + return CURLE_OUT_OF_MEMORY; + } + ftpc->dirs = bigger; + } + } + } + filename = cur_pos; /* the rest is the file name */ + break; + } /* switch */ + + if(filename && *filename) { + CURLcode result = + Curl_urldecode(conn->data, filename, 0, &ftpc->file, NULL, TRUE); + + if(result) { + freedirs(ftpc); + return result; + } + } + else + ftpc->file=NULL; /* instead of point to a zero byte, we make it a NULL + pointer */ + + if(data->set.upload && !ftpc->file && (ftp->transfer == FTPTRANSFER_BODY)) { + /* We need a file name when uploading. Return error! */ + failf(data, "Uploading to a URL without a file name!"); + return CURLE_URL_MALFORMAT; + } + + ftpc->cwddone = FALSE; /* default to not done */ + + if(ftpc->prevpath) { + /* prevpath is "raw" so we convert the input path before we compare the + strings */ + size_t dlen; + char *path; + CURLcode result = + Curl_urldecode(conn->data, data->state.path, 0, &path, &dlen, FALSE); + if(result) { + freedirs(ftpc); + return result; + } + + dlen -= ftpc->file?strlen(ftpc->file):0; + if((dlen == strlen(ftpc->prevpath)) && + !strncmp(path, ftpc->prevpath, dlen)) { + infof(data, "Request has same path as previous transfer\n"); + ftpc->cwddone = TRUE; + } + free(path); + } + + return CURLE_OK; +} + +/* call this when the DO phase has completed */ +static CURLcode ftp_dophase_done(struct connectdata *conn, + bool connected) +{ + struct FTP *ftp = conn->data->req.protop; + struct ftp_conn *ftpc = &conn->proto.ftpc; + + if(connected) { + int completed; + CURLcode result = ftp_do_more(conn, &completed); + + if(result) { + close_secondarysocket(conn); + return result; + } + } + + if(ftp->transfer != FTPTRANSFER_BODY) + /* no data to transfer */ + Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); + else if(!connected) + /* since we didn't connect now, we want do_more to get called */ + conn->bits.do_more = TRUE; + + ftpc->ctl_valid = TRUE; /* seems good */ + + return CURLE_OK; +} + +/* called from multi.c while DOing */ +static CURLcode ftp_doing(struct connectdata *conn, + bool *dophase_done) +{ + CURLcode result = ftp_multi_statemach(conn, dophase_done); + + if(result) + DEBUGF(infof(conn->data, "DO phase failed\n")); + else if(*dophase_done) { + result = ftp_dophase_done(conn, FALSE /* not connected */); + + DEBUGF(infof(conn->data, "DO phase is complete2\n")); + } + return result; +} + +/*********************************************************************** + * + * ftp_regular_transfer() + * + * The input argument is already checked for validity. + * + * Performs all commands done before a regular transfer between a local and a + * remote host. + * + * ftp->ctl_valid starts out as FALSE, and gets set to TRUE if we reach the + * ftp_done() function without finding any major problem. + */ +static +CURLcode ftp_regular_transfer(struct connectdata *conn, + bool *dophase_done) +{ + CURLcode result=CURLE_OK; + bool connected=FALSE; + struct Curl_easy *data = conn->data; + struct ftp_conn *ftpc = &conn->proto.ftpc; + data->req.size = -1; /* make sure this is unknown at this point */ + + Curl_pgrsSetUploadCounter(data, 0); + Curl_pgrsSetDownloadCounter(data, 0); + Curl_pgrsSetUploadSize(data, -1); + Curl_pgrsSetDownloadSize(data, -1); + + ftpc->ctl_valid = TRUE; /* starts good */ + + result = ftp_perform(conn, + &connected, /* have we connected after PASV/PORT */ + dophase_done); /* all commands in the DO-phase done? */ + + if(!result) { + + if(!*dophase_done) + /* the DO phase has not completed yet */ + return CURLE_OK; + + result = ftp_dophase_done(conn, connected); + + if(result) + return result; + } + else + freedirs(ftpc); + + return result; +} + +static CURLcode ftp_setup_connection(struct connectdata *conn) +{ + struct Curl_easy *data = conn->data; + char *type; + char command; + struct FTP *ftp; + + if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) { + /* Unless we have asked to tunnel ftp operations through the proxy, we + switch and use HTTP operations only */ +#ifndef CURL_DISABLE_HTTP + if(conn->handler == &Curl_handler_ftp) + conn->handler = &Curl_handler_ftp_proxy; + else { +#ifdef USE_SSL + conn->handler = &Curl_handler_ftps_proxy; +#else + failf(data, "FTPS not supported!"); + return CURLE_UNSUPPORTED_PROTOCOL; +#endif + } + /* set it up as a HTTP connection instead */ + return conn->handler->setup_connection(conn); +#else + failf(data, "FTP over http proxy requires HTTP support built-in!"); + return CURLE_UNSUPPORTED_PROTOCOL; +#endif + } + + conn->data->req.protop = ftp = malloc(sizeof(struct FTP)); + if(NULL == ftp) + return CURLE_OUT_OF_MEMORY; + + data->state.path++; /* don't include the initial slash */ + data->state.slash_removed = TRUE; /* we've skipped the slash */ + + /* FTP URLs support an extension like ";type=" that + * we'll try to get now! */ + type = strstr(data->state.path, ";type="); + + if(!type) + type = strstr(conn->host.rawalloc, ";type="); + + if(type) { + *type = 0; /* it was in the middle of the hostname */ + command = Curl_raw_toupper(type[6]); + conn->bits.type_set = TRUE; + - switch (command) { ++ switch(command) { + case 'A': /* ASCII mode */ + data->set.prefer_ascii = TRUE; + break; + + case 'D': /* directory mode */ + data->set.ftp_list_only = TRUE; + break; + + case 'I': /* binary mode */ + default: + /* switch off ASCII */ + data->set.prefer_ascii = FALSE; + break; + } + } + + /* get some initial data into the ftp struct */ + ftp->bytecountp = &conn->data->req.bytecount; + ftp->transfer = FTPTRANSFER_BODY; + ftp->downloadsize = 0; + + /* No need to duplicate user+password, the connectdata struct won't change + during a session, but we re-init them here since on subsequent inits + since the conn struct may have changed or been replaced. + */ + ftp->user = conn->user; + ftp->passwd = conn->passwd; + if(isBadFtpString(ftp->user)) + return CURLE_URL_MALFORMAT; + if(isBadFtpString(ftp->passwd)) + return CURLE_URL_MALFORMAT; + + conn->proto.ftpc.known_filesize = -1; /* unknown size for now */ + + return CURLE_OK; +} + +#endif /* CURL_DISABLE_FTP */ diff --cc Utilities/cmcurl/lib/mprintf.c index 3cdd41a,0000000..4baa1cc mode 100644,000000..100644 --- a/Utilities/cmcurl/lib/mprintf.c +++ b/Utilities/cmcurl/lib/mprintf.c @@@ -1,1166 -1,0 +1,1181 @@@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1999 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * + * Purpose: + * A merge of Bjorn Reese's format() function and Daniel's dsprintf() + * 1.0. A full blooded printf() clone with full support for $ + * everywhere (parameters, widths and precisions) including variabled + * sized parameters (like doubles, long longs, long doubles and even + * void * in 64-bit architectures). + * + * Current restrictions: + * - Max 128 parameters + * - No 'long double' support. + * + * If you ever want truly portable and good *printf() clones, the project that + * took on from here is named 'Trio' and you find more details on the trio web + * page at https://daniel.haxx.se/projects/trio/ + */ + +#include "curl_setup.h" +#include + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + +/* + * If SIZEOF_SIZE_T has not been defined, default to the size of long. + */ + +#ifndef SIZEOF_SIZE_T +# define SIZEOF_SIZE_T CURL_SIZEOF_LONG +#endif + +#ifdef HAVE_LONGLONG +# define LONG_LONG_TYPE long long +# define HAVE_LONG_LONG_TYPE +#else +# if defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64) +# define LONG_LONG_TYPE __int64 +# define HAVE_LONG_LONG_TYPE +# else +# undef LONG_LONG_TYPE +# undef HAVE_LONG_LONG_TYPE +# endif +#endif + +/* + * Non-ANSI integer extensions + */ + +#if (defined(__BORLANDC__) && (__BORLANDC__ >= 0x520)) || \ + (defined(__WATCOMC__) && defined(__386__)) || \ + (defined(__POCC__) && defined(_MSC_VER)) || \ + (defined(_WIN32_WCE)) || \ + (defined(__MINGW32__)) || \ + (defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)) +# define MP_HAVE_INT_EXTENSIONS +#endif + +/* + * Max integer data types that mprintf.c is capable + */ + +#ifdef HAVE_LONG_LONG_TYPE +# define mp_intmax_t LONG_LONG_TYPE +# define mp_uintmax_t unsigned LONG_LONG_TYPE +#else +# define mp_intmax_t long +# define mp_uintmax_t unsigned long +#endif + - #define BUFFSIZE 256 /* buffer for long-to-str and float-to-str calcs */ ++#define BUFFSIZE 326 /* buffer for long-to-str and float-to-str calcs, should ++ fit negative DBL_MAX (317 letters) */ +#define MAX_PARAMETERS 128 /* lame static limit */ + +#ifdef __AMIGA__ +# undef FORMAT_INT +#endif + +/* Lower-case digits. */ +static const char lower_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; + +/* Upper-case digits. */ +static const char upper_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + +#define OUTCHAR(x) \ + do{ \ + if(stream((unsigned char)(x), (FILE *)data) != -1) \ + done++; \ + else \ + return done; /* return immediately on failure */ \ + } WHILE_FALSE + +/* Data type to read from the arglist */ +typedef enum { + FORMAT_UNKNOWN = 0, + FORMAT_STRING, + FORMAT_PTR, + FORMAT_INT, + FORMAT_INTPTR, + FORMAT_LONG, + FORMAT_LONGLONG, + FORMAT_DOUBLE, + FORMAT_LONGDOUBLE, + FORMAT_WIDTH /* For internal use */ +} FormatType; + +/* conversion and display flags */ +enum { + FLAGS_NEW = 0, + FLAGS_SPACE = 1<<0, + FLAGS_SHOWSIGN = 1<<1, + FLAGS_LEFT = 1<<2, + FLAGS_ALT = 1<<3, + FLAGS_SHORT = 1<<4, + FLAGS_LONG = 1<<5, + FLAGS_LONGLONG = 1<<6, + FLAGS_LONGDOUBLE = 1<<7, + FLAGS_PAD_NIL = 1<<8, + FLAGS_UNSIGNED = 1<<9, + FLAGS_OCTAL = 1<<10, + FLAGS_HEX = 1<<11, + FLAGS_UPPER = 1<<12, + FLAGS_WIDTH = 1<<13, /* '*' or '*$' used */ + FLAGS_WIDTHPARAM = 1<<14, /* width PARAMETER was specified */ + FLAGS_PREC = 1<<15, /* precision was specified */ + FLAGS_PRECPARAM = 1<<16, /* precision PARAMETER was specified */ + FLAGS_CHAR = 1<<17, /* %c story */ + FLAGS_FLOATE = 1<<18, /* %e or %E */ + FLAGS_FLOATG = 1<<19 /* %g or %G */ +}; + +typedef struct { + FormatType type; + int flags; + long width; /* width OR width parameter number */ + long precision; /* precision OR precision parameter number */ + union { + char *str; + void *ptr; + union { + mp_intmax_t as_signed; + mp_uintmax_t as_unsigned; + } num; + double dnum; + } data; +} va_stack_t; + +struct nsprintf { + char *buffer; + size_t length; + size_t max; +}; + +struct asprintf { + char *buffer; /* allocated buffer */ + size_t len; /* length of string */ + size_t alloc; /* length of alloc */ + int fail; /* (!= 0) if an alloc has failed and thus + the output is not the complete data */ +}; + +static long dprintf_DollarString(char *input, char **end) +{ + int number=0; + while(ISDIGIT(*input)) { + number *= 10; + number += *input-'0'; + input++; + } + if(number && ('$'==*input++)) { + *end = input; + return number; + } + return 0; +} + +static bool dprintf_IsQualifierNoDollar(const char *fmt) +{ +#if defined(MP_HAVE_INT_EXTENSIONS) + if(!strncmp(fmt, "I32", 3) || !strncmp(fmt, "I64", 3)) { + return TRUE; + } +#endif + + switch(*fmt) { + case '-': case '+': case ' ': case '#': case '.': + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case 'h': case 'l': case 'L': case 'z': case 'q': + case '*': case 'O': +#if defined(MP_HAVE_INT_EXTENSIONS) + case 'I': +#endif + return TRUE; + + default: + return FALSE; + } +} + +/****************************************************************** + * + * Pass 1: + * Create an index with the type of each parameter entry and its + * value (may vary in size) + * + * Returns zero on success. + * + ******************************************************************/ + +static int dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos, + va_list arglist) +{ + char *fmt = (char *)format; + int param_num = 0; + long this_param; + long width; + long precision; + int flags; + long max_param=0; + long i; + + while(*fmt) { + if(*fmt++ == '%') { + if(*fmt == '%') { + fmt++; + continue; /* while */ + } + + flags = FLAGS_NEW; + + /* Handle the positional case (N$) */ + + param_num++; + + this_param = dprintf_DollarString(fmt, &fmt); + if(0 == this_param) + /* we got no positional, get the next counter */ + this_param = param_num; + + if(this_param > max_param) + max_param = this_param; + + /* + * The parameter with number 'i' should be used. Next, we need + * to get SIZE and TYPE of the parameter. Add the information + * to our array. + */ + + width = 0; + precision = 0; + + /* Handle the flags */ + + while(dprintf_IsQualifierNoDollar(fmt)) { +#if defined(MP_HAVE_INT_EXTENSIONS) + if(!strncmp(fmt, "I32", 3)) { + flags |= FLAGS_LONG; + fmt += 3; + } + else if(!strncmp(fmt, "I64", 3)) { + flags |= FLAGS_LONGLONG; + fmt += 3; + } + else +#endif + + switch(*fmt++) { + case ' ': + flags |= FLAGS_SPACE; + break; + case '+': + flags |= FLAGS_SHOWSIGN; + break; + case '-': + flags |= FLAGS_LEFT; + flags &= ~FLAGS_PAD_NIL; + break; + case '#': + flags |= FLAGS_ALT; + break; + case '.': - flags |= FLAGS_PREC; + if('*' == *fmt) { + /* The precision is picked from a specified parameter */ + + flags |= FLAGS_PRECPARAM; + fmt++; + param_num++; + + i = dprintf_DollarString(fmt, &fmt); + if(i) + precision = i; + else + precision = param_num; + + if(precision > max_param) + max_param = precision; + } + else { + flags |= FLAGS_PREC; + precision = strtol(fmt, &fmt, 10); + } + break; + case 'h': + flags |= FLAGS_SHORT; + break; +#if defined(MP_HAVE_INT_EXTENSIONS) + case 'I': +#if (CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG) + flags |= FLAGS_LONGLONG; +#else + flags |= FLAGS_LONG; +#endif + break; +#endif + case 'l': + if(flags & FLAGS_LONG) + flags |= FLAGS_LONGLONG; + else + flags |= FLAGS_LONG; + break; + case 'L': + flags |= FLAGS_LONGDOUBLE; + break; + case 'q': + flags |= FLAGS_LONGLONG; + break; + case 'z': + /* the code below generates a warning if -Wunreachable-code is + used */ +#if (SIZEOF_SIZE_T > CURL_SIZEOF_LONG) + flags |= FLAGS_LONGLONG; +#else + flags |= FLAGS_LONG; +#endif + break; + case 'O': +#if (CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG) + flags |= FLAGS_LONGLONG; +#else + flags |= FLAGS_LONG; +#endif + break; + case '0': + if(!(flags & FLAGS_LEFT)) + flags |= FLAGS_PAD_NIL; + /* FALLTHROUGH */ + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + flags |= FLAGS_WIDTH; + width = strtol(fmt-1, &fmt, 10); + break; + case '*': /* Special case */ + flags |= FLAGS_WIDTHPARAM; + param_num++; + + i = dprintf_DollarString(fmt, &fmt); + if(i) + width = i; + else + width = param_num; + if(width > max_param) + max_param=width; + break; + default: + break; + } + } /* switch */ + + /* Handle the specifier */ + + i = this_param - 1; + + if((i < 0) || (i >= MAX_PARAMETERS)) + /* out of allowed range */ + return 1; + + switch (*fmt) { + case 'S': + flags |= FLAGS_ALT; + /* FALLTHROUGH */ + case 's': + vto[i].type = FORMAT_STRING; + break; + case 'n': + vto[i].type = FORMAT_INTPTR; + break; + case 'p': + vto[i].type = FORMAT_PTR; + break; + case 'd': case 'i': + vto[i].type = FORMAT_INT; + break; + case 'u': + vto[i].type = FORMAT_INT; + flags |= FLAGS_UNSIGNED; + break; + case 'o': + vto[i].type = FORMAT_INT; + flags |= FLAGS_OCTAL; + break; + case 'x': + vto[i].type = FORMAT_INT; + flags |= FLAGS_HEX|FLAGS_UNSIGNED; + break; + case 'X': + vto[i].type = FORMAT_INT; + flags |= FLAGS_HEX|FLAGS_UPPER|FLAGS_UNSIGNED; + break; + case 'c': + vto[i].type = FORMAT_INT; + flags |= FLAGS_CHAR; + break; + case 'f': + vto[i].type = FORMAT_DOUBLE; + break; + case 'e': + vto[i].type = FORMAT_DOUBLE; + flags |= FLAGS_FLOATE; + break; + case 'E': + vto[i].type = FORMAT_DOUBLE; + flags |= FLAGS_FLOATE|FLAGS_UPPER; + break; + case 'g': + vto[i].type = FORMAT_DOUBLE; + flags |= FLAGS_FLOATG; + break; + case 'G': + vto[i].type = FORMAT_DOUBLE; + flags |= FLAGS_FLOATG|FLAGS_UPPER; + break; + default: + vto[i].type = FORMAT_UNKNOWN; + break; + } /* switch */ + + vto[i].flags = flags; + vto[i].width = width; + vto[i].precision = precision; + + if(flags & FLAGS_WIDTHPARAM) { + /* we have the width specified from a parameter, so we make that + parameter's info setup properly */ + long k = width - 1; + vto[i].width = k; + vto[k].type = FORMAT_WIDTH; + vto[k].flags = FLAGS_NEW; + /* can't use width or precision of width! */ + vto[k].width = 0; + vto[k].precision = 0; + } + if(flags & FLAGS_PRECPARAM) { + /* we have the precision specified from a parameter, so we make that + parameter's info setup properly */ + long k = precision - 1; + vto[i].precision = k; + vto[k].type = FORMAT_WIDTH; + vto[k].flags = FLAGS_NEW; + /* can't use width or precision of width! */ + vto[k].width = 0; + vto[k].precision = 0; + } + *endpos++ = fmt + 1; /* end of this sequence */ + } + } + + /* Read the arg list parameters into our data list */ + for(i=0; i$ sequence */ + param=dprintf_DollarString(f, &f); + + if(!param) + param = param_num; + else + --param; + + param_num++; /* increase this always to allow "%2$s %1$s %s" and then the + third %s will pick the 3rd argument */ + + p = &vto[param]; + + /* pick up the specified width */ + if(p->flags & FLAGS_WIDTHPARAM) { + width = (long)vto[p->width].data.num.as_signed; + param_num++; /* since the width is extracted from a parameter, we + must skip that to get to the next one properly */ + if(width < 0) { + /* "A negative field width is taken as a '-' flag followed by a + positive field width." */ + width = -width; + p->flags |= FLAGS_LEFT; + p->flags &= ~FLAGS_PAD_NIL; + } + } + else + width = p->width; + + /* pick up the specified precision */ + if(p->flags & FLAGS_PRECPARAM) { + prec = (long)vto[p->precision].data.num.as_signed; + param_num++; /* since the precision is extracted from a parameter, we + must skip that to get to the next one properly */ + if(prec < 0) + /* "A negative precision is taken as if the precision were + omitted." */ + prec = -1; + } + else if(p->flags & FLAGS_PREC) + prec = p->precision; + else + prec = -1; + + is_alt = (p->flags & FLAGS_ALT) ? 1 : 0; + - switch (p->type) { ++ switch(p->type) { + case FORMAT_INT: + num = p->data.num.as_unsigned; + if(p->flags & FLAGS_CHAR) { + /* Character. */ + if(!(p->flags & FLAGS_LEFT)) + while(--width > 0) + OUTCHAR(' '); + OUTCHAR((char) num); + if(p->flags & FLAGS_LEFT) + while(--width > 0) + OUTCHAR(' '); + break; + } + if(p->flags & FLAGS_OCTAL) { + /* Octal unsigned integer. */ + base = 8; + goto unsigned_number; + } + else if(p->flags & FLAGS_HEX) { + /* Hexadecimal unsigned integer. */ + + digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits; + base = 16; + goto unsigned_number; + } + else if(p->flags & FLAGS_UNSIGNED) { + /* Decimal unsigned integer. */ + base = 10; + goto unsigned_number; + } + + /* Decimal integer. */ + base = 10; + + is_neg = (p->data.num.as_signed < (mp_intmax_t)0) ? 1 : 0; + if(is_neg) { + /* signed_num might fail to hold absolute negative minimum by 1 */ + signed_num = p->data.num.as_signed + (mp_intmax_t)1; + signed_num = -signed_num; + num = (mp_uintmax_t)signed_num; + num += (mp_uintmax_t)1; + } + + goto number; + + unsigned_number: + /* Unsigned number of base BASE. */ + is_neg = 0; + + number: + /* Number of base BASE. */ + + /* Supply a default precision if none was given. */ + if(prec == -1) + prec = 1; + + /* Put the number in WORK. */ + w = workend; + while(num > 0) { + *w-- = digits[num % base]; + num /= base; + } + width -= (long)(workend - w); + prec -= (long)(workend - w); + + if(is_alt && base == 8 && prec <= 0) { + *w-- = '0'; + --width; + } + + if(prec > 0) { + width -= prec; + while(prec-- > 0) + *w-- = '0'; + } + + if(is_alt && base == 16) + width -= 2; + + if(is_neg || (p->flags & FLAGS_SHOWSIGN) || (p->flags & FLAGS_SPACE)) + --width; + + if(!(p->flags & FLAGS_LEFT) && !(p->flags & FLAGS_PAD_NIL)) + while(width-- > 0) + OUTCHAR(' '); + + if(is_neg) + OUTCHAR('-'); + else if(p->flags & FLAGS_SHOWSIGN) + OUTCHAR('+'); + else if(p->flags & FLAGS_SPACE) + OUTCHAR(' '); + + if(is_alt && base == 16) { + OUTCHAR('0'); + if(p->flags & FLAGS_UPPER) + OUTCHAR('X'); + else + OUTCHAR('x'); + } + + if(!(p->flags & FLAGS_LEFT) && (p->flags & FLAGS_PAD_NIL)) + while(width-- > 0) + OUTCHAR('0'); + + /* Write the number. */ + while(++w <= workend) { + OUTCHAR(*w); + } + + if(p->flags & FLAGS_LEFT) + while(width-- > 0) + OUTCHAR(' '); + break; + + case FORMAT_STRING: + /* String. */ + { + static const char null[] = "(nil)"; + const char *str; + size_t len; + + str = (char *) p->data.str; + if(str == NULL) { + /* Write null[] if there's space. */ + if(prec == -1 || prec >= (long) sizeof(null) - 1) { + str = null; + len = sizeof(null) - 1; + /* Disable quotes around (nil) */ + p->flags &= (~FLAGS_ALT); + } + else { + str = ""; + len = 0; + } + } + else if(prec != -1) + len = (size_t)prec; + else + len = strlen(str); + + width -= (len > LONG_MAX) ? LONG_MAX : (long)len; + + if(p->flags & FLAGS_ALT) + OUTCHAR('"'); + + if(!(p->flags&FLAGS_LEFT)) + while(width-- > 0) + OUTCHAR(' '); + + while((len-- > 0) && *str) + OUTCHAR(*str++); + if(p->flags&FLAGS_LEFT) + while(width-- > 0) + OUTCHAR(' '); + + if(p->flags & FLAGS_ALT) + OUTCHAR('"'); + } + break; + + case FORMAT_PTR: + /* Generic pointer. */ + { + void *ptr; + ptr = (void *) p->data.ptr; + if(ptr != NULL) { + /* If the pointer is not NULL, write it as a %#x spec. */ + base = 16; + digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits; + is_alt = 1; + num = (size_t) ptr; + is_neg = 0; + goto number; + } + else { + /* Write "(nil)" for a nil pointer. */ + static const char strnil[] = "(nil)"; + const char *point; + + width -= (long)(sizeof(strnil) - 1); + if(p->flags & FLAGS_LEFT) + while(width-- > 0) + OUTCHAR(' '); + for(point = strnil; *point != '\0'; ++point) + OUTCHAR(*point); + if(! (p->flags & FLAGS_LEFT)) + while(width-- > 0) + OUTCHAR(' '); + } + } + break; + + case FORMAT_DOUBLE: + { + char formatbuf[32]="%"; + char *fptr = &formatbuf[1]; + size_t left = sizeof(formatbuf)-strlen(formatbuf); + int len; + + width = -1; + if(p->flags & FLAGS_WIDTH) + width = p->width; + else if(p->flags & FLAGS_WIDTHPARAM) + width = (long)vto[p->width].data.num.as_signed; + + prec = -1; + if(p->flags & FLAGS_PREC) + prec = p->precision; + else if(p->flags & FLAGS_PRECPARAM) + prec = (long)vto[p->precision].data.num.as_signed; + + if(p->flags & FLAGS_LEFT) + *fptr++ = '-'; + if(p->flags & FLAGS_SHOWSIGN) + *fptr++ = '+'; + if(p->flags & FLAGS_SPACE) + *fptr++ = ' '; + if(p->flags & FLAGS_ALT) + *fptr++ = '#'; + + *fptr = 0; + + if(width >= 0) { ++ if(width >= (long)sizeof(work)) ++ width = sizeof(work)-1; + /* RECURSIVE USAGE */ + len = curl_msnprintf(fptr, left, "%ld", width); + fptr += len; + left -= len; + } + if(prec >= 0) { ++ /* for each digit in the integer part, we can have one less ++ precision */ ++ size_t maxprec = sizeof(work) - 2; ++ double val = p->data.dnum; ++ while(val >= 10.0) { ++ val /= 10; ++ maxprec--; ++ } ++ ++ if(prec > (long)maxprec) ++ prec = (long)maxprec-1; + /* RECURSIVE USAGE */ + len = curl_msnprintf(fptr, left, ".%ld", prec); + fptr += len; + } + if(p->flags & FLAGS_LONG) + *fptr++ = 'l'; + + if(p->flags & FLAGS_FLOATE) + *fptr++ = (char)((p->flags & FLAGS_UPPER) ? 'E':'e'); + else if(p->flags & FLAGS_FLOATG) + *fptr++ = (char)((p->flags & FLAGS_UPPER) ? 'G' : 'g'); + else + *fptr++ = 'f'; + + *fptr = 0; /* and a final zero termination */ + + /* NOTE NOTE NOTE!! Not all sprintf implementations return number of + output characters */ + (sprintf)(work, formatbuf, p->data.dnum); - ++#ifdef CURLDEBUG ++ assert(strlen(work) <= sizeof(work)); ++#endif + for(fptr=work; *fptr; fptr++) + OUTCHAR(*fptr); + } + break; + + case FORMAT_INTPTR: + /* Answer the count of characters written. */ +#ifdef HAVE_LONG_LONG_TYPE + if(p->flags & FLAGS_LONGLONG) + *(LONG_LONG_TYPE *) p->data.ptr = (LONG_LONG_TYPE)done; + else +#endif + if(p->flags & FLAGS_LONG) + *(long *) p->data.ptr = (long)done; + else if(!(p->flags & FLAGS_SHORT)) + *(int *) p->data.ptr = (int)done; + else + *(short *) p->data.ptr = (short)done; + break; + + default: + break; + } + f = *end++; /* goto end of %-code */ + + } + return done; +} + +/* fputc() look-alike */ +static int addbyter(int output, FILE *data) +{ + struct nsprintf *infop=(struct nsprintf *)data; + unsigned char outc = (unsigned char)output; + + if(infop->length < infop->max) { + /* only do this if we haven't reached max length yet */ + infop->buffer[0] = outc; /* store */ + infop->buffer++; /* increase pointer */ + infop->length++; /* we are now one byte larger */ + return outc; /* fputc() returns like this on success */ + } + return -1; +} + +int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format, + va_list ap_save) +{ + int retcode; + struct nsprintf info; + + info.buffer = buffer; + info.length = 0; + info.max = maxlength; + + retcode = dprintf_formatf(&info, addbyter, format, ap_save); + if((retcode != -1) && info.max) { + /* we terminate this with a zero byte */ + if(info.max == info.length) + /* we're at maximum, scrap the last letter */ + info.buffer[-1] = 0; + else + info.buffer[0] = 0; + } + return retcode; +} + +int curl_msnprintf(char *buffer, size_t maxlength, const char *format, ...) +{ + int retcode; + va_list ap_save; /* argument pointer */ + va_start(ap_save, format); + retcode = curl_mvsnprintf(buffer, maxlength, format, ap_save); + va_end(ap_save); + return retcode; +} + +/* fputc() look-alike */ +static int alloc_addbyter(int output, FILE *data) +{ + struct asprintf *infop=(struct asprintf *)data; + unsigned char outc = (unsigned char)output; + + if(!infop->buffer) { + infop->buffer = malloc(32); + if(!infop->buffer) { + infop->fail = 1; + return -1; /* fail */ + } + infop->alloc = 32; + infop->len =0; + } + else if(infop->len+1 >= infop->alloc) { + char *newptr = NULL; + size_t newsize = infop->alloc*2; + + /* detect wrap-around or other overflow problems */ + if(newsize > infop->alloc) + newptr = realloc(infop->buffer, newsize); + + if(!newptr) { + infop->fail = 1; + return -1; /* fail */ + } + infop->buffer = newptr; + infop->alloc = newsize; + } + + infop->buffer[ infop->len ] = outc; + + infop->len++; + + return outc; /* fputc() returns like this on success */ +} + +char *curl_maprintf(const char *format, ...) +{ + va_list ap_save; /* argument pointer */ + int retcode; + struct asprintf info; + + info.buffer = NULL; + info.len = 0; + info.alloc = 0; + info.fail = 0; + + va_start(ap_save, format); + retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save); + va_end(ap_save); + if((-1 == retcode) || info.fail) { + if(info.alloc) + free(info.buffer); + return NULL; + } + if(info.alloc) { + info.buffer[info.len] = 0; /* we terminate this with a zero byte */ + return info.buffer; + } + else + return strdup(""); +} + +char *curl_mvaprintf(const char *format, va_list ap_save) +{ + int retcode; + struct asprintf info; + + info.buffer = NULL; + info.len = 0; + info.alloc = 0; + info.fail = 0; + + retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save); + if((-1 == retcode) || info.fail) { + if(info.alloc) + free(info.buffer); + return NULL; + } + + if(info.alloc) { + info.buffer[info.len] = 0; /* we terminate this with a zero byte */ + return info.buffer; + } + else + return strdup(""); +} + +static int storebuffer(int output, FILE *data) +{ + char **buffer = (char **)data; + unsigned char outc = (unsigned char)output; + **buffer = outc; + (*buffer)++; + return outc; /* act like fputc() ! */ +} + +int curl_msprintf(char *buffer, const char *format, ...) +{ + va_list ap_save; /* argument pointer */ + int retcode; + va_start(ap_save, format); + retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save); + va_end(ap_save); + *buffer=0; /* we terminate this with a zero byte */ + return retcode; +} + +int curl_mprintf(const char *format, ...) +{ + int retcode; + va_list ap_save; /* argument pointer */ + va_start(ap_save, format); + + retcode = dprintf_formatf(stdout, fputc, format, ap_save); + va_end(ap_save); + return retcode; +} + +int curl_mfprintf(FILE *whereto, const char *format, ...) +{ + int retcode; + va_list ap_save; /* argument pointer */ + va_start(ap_save, format); + retcode = dprintf_formatf(whereto, fputc, format, ap_save); + va_end(ap_save); + return retcode; +} + +int curl_mvsprintf(char *buffer, const char *format, va_list ap_save) +{ + int retcode; + retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save); + *buffer=0; /* we terminate this with a zero byte */ + return retcode; +} + +int curl_mvprintf(const char *format, va_list ap_save) +{ + return dprintf_formatf(stdout, fputc, format, ap_save); +} + +int curl_mvfprintf(FILE *whereto, const char *format, va_list ap_save) +{ + return dprintf_formatf(whereto, fputc, format, ap_save); +} diff --cc Utilities/cmcurl/lib/rand.c index 0000000,a51951c..a51951c mode 000000,100644..100644 --- a/Utilities/cmcurl/lib/rand.c +++ b/Utilities/cmcurl/lib/rand.c diff --cc Utilities/cmcurl/lib/select.c index d5caa70,0000000..6bb0ab1 mode 100644,000000..100644 --- a/Utilities/cmcurl/lib/select.c +++ b/Utilities/cmcurl/lib/select.c @@@ -1,583 -1,0 +1,583 @@@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_SYS_SELECT_H +#include +#endif + +#if !defined(HAVE_SELECT) && !defined(HAVE_POLL_FINE) +#error "We can't compile without select() or poll() support." +#endif + +#if defined(__BEOS__) +/* BeOS has FD_SET defined in socket.h */ +#include +#endif + +#ifdef MSDOS +#include /* delay() */ +#endif + +#ifdef __VXWORKS__ +#include /* bzero() in FD_SET */ +#endif + +#include + +#include "urldata.h" +#include "connect.h" +#include "select.h" +#include "warnless.h" + +/* Convenience local macros */ +#define ELAPSED_MS() (int)curlx_tvdiff(curlx_tvnow(), initial_tv) + +int Curl_ack_eintr = 0; +#define ERROR_NOT_EINTR(error) (Curl_ack_eintr || error != EINTR) + +/* + * Internal function used for waiting a specific amount of ms + * in Curl_socket_check() and Curl_poll() when no file descriptor + * is provided to wait on, just being used to delay execution. + * WinSock select() and poll() timeout mechanisms need a valid + * socket descriptor in a not null file descriptor set to work. + * Waiting indefinitely with this function is not allowed, a + * zero or negative timeout value will return immediately. + * Timeout resolution, accuracy, as well as maximum supported + * value is system dependent, neither factor is a citical issue + * for the intended use of this function in the library. + * + * Return values: + * -1 = system call error, invalid timeout value, or interrupted + * 0 = specified timeout has elapsed + */ +int Curl_wait_ms(int timeout_ms) +{ +#if !defined(MSDOS) && !defined(USE_WINSOCK) +#ifndef HAVE_POLL_FINE + struct timeval pending_tv; +#endif + struct timeval initial_tv; + int pending_ms; + int error; +#endif + int r = 0; + + if(!timeout_ms) + return 0; + if(timeout_ms < 0) { + SET_SOCKERRNO(EINVAL); + return -1; + } +#if defined(MSDOS) + delay(timeout_ms); +#elif defined(USE_WINSOCK) + Sleep(timeout_ms); +#else + pending_ms = timeout_ms; + initial_tv = curlx_tvnow(); + do { +#if defined(HAVE_POLL_FINE) + r = poll(NULL, 0, pending_ms); +#else + pending_tv.tv_sec = pending_ms / 1000; + pending_tv.tv_usec = (pending_ms % 1000) * 1000; + r = select(0, NULL, NULL, NULL, &pending_tv); +#endif /* HAVE_POLL_FINE */ + if(r != -1) + break; + error = SOCKERRNO; + if(error && ERROR_NOT_EINTR(error)) + break; + pending_ms = timeout_ms - ELAPSED_MS(); + if(pending_ms <= 0) { + r = 0; /* Simulate a "call timed out" case */ + break; + } + } while(r == -1); +#endif /* USE_WINSOCK */ + if(r) + r = -1; + return r; +} + +/* + * Wait for read or write events on a set of file descriptors. It uses poll() + * when a fine poll() is available, in order to avoid limits with FD_SETSIZE, + * otherwise select() is used. An error is returned if select() is being used + * and a file descriptor is too large for FD_SETSIZE. + * + * A negative timeout value makes this function wait indefinitely, + * unles no valid file descriptor is given, when this happens the + * negative timeout is ignored and the function times out immediately. + * + * Return values: + * -1 = system call error or fd >= FD_SETSIZE + * 0 = timeout + * [bitmask] = action as described below + * + * CURL_CSELECT_IN - first socket is readable + * CURL_CSELECT_IN2 - second socket is readable + * CURL_CSELECT_OUT - write socket is writable + * CURL_CSELECT_ERR - an error condition occurred + */ +int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */ + curl_socket_t readfd1, + curl_socket_t writefd, /* socket to write to */ - long timeout_ms) /* milliseconds to wait */ ++ time_t timeout_ms) /* milliseconds to wait */ +{ +#ifdef HAVE_POLL_FINE + struct pollfd pfd[3]; + int num; +#else + struct timeval pending_tv; + struct timeval *ptimeout; + fd_set fds_read; + fd_set fds_write; + fd_set fds_err; + curl_socket_t maxfd; +#endif + struct timeval initial_tv = {0, 0}; + int pending_ms = 0; + int error; + int r; + int ret; + +#if SIZEOF_LONG != SIZEOF_INT + /* wrap-around precaution */ + if(timeout_ms >= INT_MAX) + timeout_ms = INT_MAX; +#endif + + if((readfd0 == CURL_SOCKET_BAD) && (readfd1 == CURL_SOCKET_BAD) && + (writefd == CURL_SOCKET_BAD)) { + /* no sockets, just wait */ + r = Curl_wait_ms((int)timeout_ms); + return r; + } + + /* Avoid initial timestamp, avoid curlx_tvnow() call, when elapsed + time in this function does not need to be measured. This happens + when function is called with a zero timeout or a negative timeout + value indicating a blocking call should be performed. */ + + if(timeout_ms > 0) { + pending_ms = (int)timeout_ms; + initial_tv = curlx_tvnow(); + } + +#ifdef HAVE_POLL_FINE + + num = 0; + if(readfd0 != CURL_SOCKET_BAD) { + pfd[num].fd = readfd0; + pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI; + pfd[num].revents = 0; + num++; + } + if(readfd1 != CURL_SOCKET_BAD) { + pfd[num].fd = readfd1; + pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI; + pfd[num].revents = 0; + num++; + } + if(writefd != CURL_SOCKET_BAD) { + pfd[num].fd = writefd; + pfd[num].events = POLLWRNORM|POLLOUT; + pfd[num].revents = 0; + num++; + } + + do { + if(timeout_ms < 0) + pending_ms = -1; + else if(!timeout_ms) + pending_ms = 0; + r = poll(pfd, num, pending_ms); + if(r != -1) + break; + error = SOCKERRNO; + if(error && ERROR_NOT_EINTR(error)) + break; + if(timeout_ms > 0) { + pending_ms = (int)(timeout_ms - ELAPSED_MS()); + if(pending_ms <= 0) { + r = 0; /* Simulate a "call timed out" case */ + break; + } + } + } while(r == -1); + + if(r < 0) + return -1; + if(r == 0) + return 0; + + ret = 0; + num = 0; + if(readfd0 != CURL_SOCKET_BAD) { + if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP)) + ret |= CURL_CSELECT_IN; + if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL)) + ret |= CURL_CSELECT_ERR; + num++; + } + if(readfd1 != CURL_SOCKET_BAD) { + if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP)) + ret |= CURL_CSELECT_IN2; + if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL)) + ret |= CURL_CSELECT_ERR; + num++; + } + if(writefd != CURL_SOCKET_BAD) { + if(pfd[num].revents & (POLLWRNORM|POLLOUT)) + ret |= CURL_CSELECT_OUT; + if(pfd[num].revents & (POLLERR|POLLHUP|POLLNVAL)) + ret |= CURL_CSELECT_ERR; + } + + return ret; + +#else /* HAVE_POLL_FINE */ + + FD_ZERO(&fds_err); + maxfd = (curl_socket_t)-1; + + FD_ZERO(&fds_read); + if(readfd0 != CURL_SOCKET_BAD) { + VERIFY_SOCK(readfd0); + FD_SET(readfd0, &fds_read); + FD_SET(readfd0, &fds_err); + maxfd = readfd0; + } + if(readfd1 != CURL_SOCKET_BAD) { + VERIFY_SOCK(readfd1); + FD_SET(readfd1, &fds_read); + FD_SET(readfd1, &fds_err); + if(readfd1 > maxfd) + maxfd = readfd1; + } + + FD_ZERO(&fds_write); + if(writefd != CURL_SOCKET_BAD) { + VERIFY_SOCK(writefd); + FD_SET(writefd, &fds_write); + FD_SET(writefd, &fds_err); + if(writefd > maxfd) + maxfd = writefd; + } + + ptimeout = (timeout_ms < 0) ? NULL : &pending_tv; + + do { + if(timeout_ms > 0) { + pending_tv.tv_sec = pending_ms / 1000; + pending_tv.tv_usec = (pending_ms % 1000) * 1000; + } + else if(!timeout_ms) { + pending_tv.tv_sec = 0; + pending_tv.tv_usec = 0; + } + + /* WinSock select() must not be called with an fd_set that contains zero + fd flags, or it will return WSAEINVAL. But, it also can't be called + with no fd_sets at all! From the documentation: + + Any two of the parameters, readfds, writefds, or exceptfds, can be + given as null. At least one must be non-null, and any non-null + descriptor set must contain at least one handle to a socket. + + We know that we have at least one bit set in at least two fd_sets in + this case, but we may have no bits set in either fds_read or fd_write, + so check for that and handle it. Luckily, with WinSock, we can _also_ + ask how many bits are set on an fd_set. + + It is unclear why WinSock doesn't just handle this for us instead of + calling this an error. + + Note also that WinSock ignores the first argument, so we don't worry + about the fact that maxfd is computed incorrectly with WinSock (since + curl_socket_t is unsigned in such cases and thus -1 is the largest + value). + */ +#ifdef USE_WINSOCK + r = select((int)maxfd + 1, + fds_read.fd_count ? &fds_read : NULL, + fds_write.fd_count ? &fds_write : NULL, + &fds_err, ptimeout); +#else + r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout); +#endif + + if(r != -1) + break; + error = SOCKERRNO; + if(error && ERROR_NOT_EINTR(error)) + break; + if(timeout_ms > 0) { + pending_ms = (int)(timeout_ms - ELAPSED_MS()); + if(pending_ms <= 0) { + r = 0; /* Simulate a "call timed out" case */ + break; + } + } + } while(r == -1); + + if(r < 0) + return -1; + if(r == 0) + return 0; + + ret = 0; + if(readfd0 != CURL_SOCKET_BAD) { + if(FD_ISSET(readfd0, &fds_read)) + ret |= CURL_CSELECT_IN; + if(FD_ISSET(readfd0, &fds_err)) + ret |= CURL_CSELECT_ERR; + } + if(readfd1 != CURL_SOCKET_BAD) { + if(FD_ISSET(readfd1, &fds_read)) + ret |= CURL_CSELECT_IN2; + if(FD_ISSET(readfd1, &fds_err)) + ret |= CURL_CSELECT_ERR; + } + if(writefd != CURL_SOCKET_BAD) { + if(FD_ISSET(writefd, &fds_write)) + ret |= CURL_CSELECT_OUT; + if(FD_ISSET(writefd, &fds_err)) + ret |= CURL_CSELECT_ERR; + } + + return ret; + +#endif /* HAVE_POLL_FINE */ + +} + +/* + * This is a wrapper around poll(). If poll() does not exist, then + * select() is used instead. An error is returned if select() is + * being used and a file descriptor is too large for FD_SETSIZE. + * A negative timeout value makes this function wait indefinitely, + * unles no valid file descriptor is given, when this happens the + * negative timeout is ignored and the function times out immediately. + * + * Return values: + * -1 = system call error or fd >= FD_SETSIZE + * 0 = timeout + * N = number of structures with non zero revent fields + */ +int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms) +{ +#ifndef HAVE_POLL_FINE + struct timeval pending_tv; + struct timeval *ptimeout; + fd_set fds_read; + fd_set fds_write; + fd_set fds_err; + curl_socket_t maxfd; +#endif + struct timeval initial_tv = {0, 0}; + bool fds_none = TRUE; + unsigned int i; + int pending_ms = 0; + int error; + int r; + + if(ufds) { + for(i = 0; i < nfds; i++) { + if(ufds[i].fd != CURL_SOCKET_BAD) { + fds_none = FALSE; + break; + } + } + } + if(fds_none) { + r = Curl_wait_ms(timeout_ms); + return r; + } + + /* Avoid initial timestamp, avoid curlx_tvnow() call, when elapsed + time in this function does not need to be measured. This happens + when function is called with a zero timeout or a negative timeout + value indicating a blocking call should be performed. */ + + if(timeout_ms > 0) { + pending_ms = timeout_ms; + initial_tv = curlx_tvnow(); + } + +#ifdef HAVE_POLL_FINE + + do { + if(timeout_ms < 0) + pending_ms = -1; + else if(!timeout_ms) + pending_ms = 0; + r = poll(ufds, nfds, pending_ms); + if(r != -1) + break; + error = SOCKERRNO; + if(error && ERROR_NOT_EINTR(error)) + break; + if(timeout_ms > 0) { + pending_ms = (int)(timeout_ms - ELAPSED_MS()); + if(pending_ms <= 0) { + r = 0; /* Simulate a "call timed out" case */ + break; + } + } + } while(r == -1); + + if(r < 0) + return -1; + if(r == 0) + return 0; + + for(i = 0; i < nfds; i++) { + if(ufds[i].fd == CURL_SOCKET_BAD) + continue; + if(ufds[i].revents & POLLHUP) + ufds[i].revents |= POLLIN; + if(ufds[i].revents & POLLERR) + ufds[i].revents |= (POLLIN|POLLOUT); + } + +#else /* HAVE_POLL_FINE */ + + FD_ZERO(&fds_read); + FD_ZERO(&fds_write); + FD_ZERO(&fds_err); + maxfd = (curl_socket_t)-1; + + for(i = 0; i < nfds; i++) { + ufds[i].revents = 0; + if(ufds[i].fd == CURL_SOCKET_BAD) + continue; + VERIFY_SOCK(ufds[i].fd); + if(ufds[i].events & (POLLIN|POLLOUT|POLLPRI| + POLLRDNORM|POLLWRNORM|POLLRDBAND)) { + if(ufds[i].fd > maxfd) + maxfd = ufds[i].fd; + if(ufds[i].events & (POLLRDNORM|POLLIN)) + FD_SET(ufds[i].fd, &fds_read); + if(ufds[i].events & (POLLWRNORM|POLLOUT)) + FD_SET(ufds[i].fd, &fds_write); + if(ufds[i].events & (POLLRDBAND|POLLPRI)) + FD_SET(ufds[i].fd, &fds_err); + } + } + +#ifdef USE_WINSOCK + /* WinSock select() can't handle zero events. See the comment about this in + Curl_check_socket(). */ + if(fds_read.fd_count == 0 && fds_write.fd_count == 0 + && fds_err.fd_count == 0) { + r = Curl_wait_ms(timeout_ms); + return r; + } +#endif + + ptimeout = (timeout_ms < 0) ? NULL : &pending_tv; + + do { + if(timeout_ms > 0) { + pending_tv.tv_sec = pending_ms / 1000; + pending_tv.tv_usec = (pending_ms % 1000) * 1000; + } + else if(!timeout_ms) { + pending_tv.tv_sec = 0; + pending_tv.tv_usec = 0; + } + +#ifdef USE_WINSOCK + r = select((int)maxfd + 1, + /* WinSock select() can't handle fd_sets with zero bits set, so + don't give it such arguments. See the comment about this in + Curl_check_socket(). + */ + fds_read.fd_count ? &fds_read : NULL, + fds_write.fd_count ? &fds_write : NULL, + fds_err.fd_count ? &fds_err : NULL, ptimeout); +#else + r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout); +#endif + if(r != -1) + break; + error = SOCKERRNO; + if(error && ERROR_NOT_EINTR(error)) + break; + if(timeout_ms > 0) { + pending_ms = timeout_ms - ELAPSED_MS(); + if(pending_ms <= 0) { + r = 0; /* Simulate a "call timed out" case */ + break; + } + } + } while(r == -1); + + if(r < 0) + return -1; + if(r == 0) + return 0; + + r = 0; + for(i = 0; i < nfds; i++) { + ufds[i].revents = 0; + if(ufds[i].fd == CURL_SOCKET_BAD) + continue; + if(FD_ISSET(ufds[i].fd, &fds_read)) + ufds[i].revents |= POLLIN; + if(FD_ISSET(ufds[i].fd, &fds_write)) + ufds[i].revents |= POLLOUT; + if(FD_ISSET(ufds[i].fd, &fds_err)) + ufds[i].revents |= POLLPRI; + if(ufds[i].revents != 0) + r++; + } + +#endif /* HAVE_POLL_FINE */ + + return r; +} + +#ifdef TPF +/* + * This is a replacement for select() on the TPF platform. + * It is used whenever libcurl calls select(). + * The call below to tpf_process_signals() is required because + * TPF's select calls are not signal interruptible. + * + * Return values are the same as select's. + */ +int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes, + fd_set* excepts, struct timeval* tv) +{ + int rc; + + rc = tpf_select_bsd(maxfds, reads, writes, excepts, tv); + tpf_process_signals(); + return rc; +} +#endif /* TPF */ https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4cc2908fdaaf1ab8afe5c2ae5dbb3401859a9aab commit 4cc2908fdaaf1ab8afe5c2ae5dbb3401859a9aab Author: Curl Upstream AuthorDate: Thu Dec 22 16:41:14 2016 +0100 Commit: Brad King CommitDate: Tue Feb 7 11:37:30 2017 -0500 curl 2016-12-22 (44b9b4d4) Code extracted from: https://github.com/curl/curl.git at commit 44b9b4d4f56d6f6de92c89636994c03984e9cd01 (curl-7_52_1). diff --git a/CMake/OtherTests.cmake b/CMake/OtherTests.cmake index d599498..3b203c5 100644 --- a/CMake/OtherTests.cmake +++ b/CMake/OtherTests.cmake @@ -179,17 +179,20 @@ int main(void) { include(CheckCSourceRuns) -set(CMAKE_REQUIRED_FLAGS) -if(HAVE_SYS_POLL_H) - set(CMAKE_REQUIRED_FLAGS "-DHAVE_SYS_POLL_H") -endif(HAVE_SYS_POLL_H) -check_c_source_runs(" - #ifdef HAVE_SYS_POLL_H - # include - #endif - int main(void) { - return poll((void *)0, 0, 10 /*ms*/); - }" HAVE_POLL_FINE) +# See HAVE_POLL in CMakeLists.txt for why poll is disabled on macOS +if(NOT APPLE) + set(CMAKE_REQUIRED_FLAGS) + if(HAVE_SYS_POLL_H) + set(CMAKE_REQUIRED_FLAGS "-DHAVE_SYS_POLL_H") + endif(HAVE_SYS_POLL_H) + check_c_source_runs(" + #ifdef HAVE_SYS_POLL_H + # include + #endif + int main(void) { + return poll((void *)0, 0, 10 /*ms*/); + }" HAVE_POLL_FINE) +endif() set(HAVE_SIG_ATOMIC_T 1) set(CMAKE_REQUIRED_FLAGS) diff --git a/CMakeLists.txt b/CMakeLists.txt index ed3f38a..a6a7368 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -742,7 +742,11 @@ endif() check_symbol_exists(basename "${CURL_INCLUDES}" HAVE_BASENAME) check_symbol_exists(socket "${CURL_INCLUDES}" HAVE_SOCKET) -check_symbol_exists(poll "${CURL_INCLUDES}" HAVE_POLL) +# poll on macOS is unreliable, it first did not exist, then was broken until +# fixed in 10.9 only to break again in 10.12. +if(NOT APPLE) + check_symbol_exists(poll "${CURL_INCLUDES}" HAVE_POLL) +endif() check_symbol_exists(select "${CURL_INCLUDES}" HAVE_SELECT) check_symbol_exists(strdup "${CURL_INCLUDES}" HAVE_STRDUP) check_symbol_exists(strstr "${CURL_INCLUDES}" HAVE_STRSTR) diff --git a/include/curl/curl.h b/include/curl/curl.h index 9c09cb9..5b4ae46 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -143,7 +143,7 @@ struct curl_httppost { char *buffer; /* pointer to allocated buffer contents */ long bufferlength; /* length of buffer field */ char *contenttype; /* Content-Type */ - struct curl_slist* contentheader; /* list of extra headers for this form */ + struct curl_slist *contentheader; /* list of extra headers for this form */ struct curl_httppost *more; /* if one field name has more than one file, this link should link to following files */ @@ -270,7 +270,7 @@ struct curl_fileinfo { unsigned int flags; /* used internally */ - char * b_data; + char *b_data; size_t b_size; size_t b_used; }; @@ -640,6 +640,7 @@ typedef enum { CONNECT HTTP/1.1 */ CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT HTTP/1.0 */ + CURLPROXY_HTTPS = 2, /* added in 7.52.0 */ CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already in 7.10 */ CURLPROXY_SOCKS5 = 5, /* added in 7.10 */ @@ -1206,7 +1207,8 @@ typedef enum { CINIT(SHARE, OBJECTPOINT, 100), /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default), - CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and CURLPROXY_SOCKS5. */ + CURLPROXY_HTTPS, CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and + CURLPROXY_SOCKS5. */ CINIT(PROXYTYPE, LONG, 101), /* Set the Accept-Encoding string. Use this to tell a server you would like @@ -1704,6 +1706,70 @@ typedef enum { * HTTP status code >= 300 */ CINIT(KEEP_SENDING_ON_ERROR, LONG, 245), + /* The CApath or CAfile used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CINIT(PROXY_CAINFO, STRINGPOINT, 246), + + /* The CApath directory used to validate the proxy certificate + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CINIT(PROXY_CAPATH, STRINGPOINT, 247), + + /* Set if we should verify the proxy in ssl handshake, + set 1 to verify. */ + CINIT(PROXY_SSL_VERIFYPEER, LONG, 248), + + /* Set if we should verify the Common name from the proxy certificate in ssl + * handshake, set 1 to check existence, 2 to ensure that it matches + * the provided hostname. */ + CINIT(PROXY_SSL_VERIFYHOST, LONG, 249), + + /* What version to specifically try to use for proxy. + See CURL_SSLVERSION defines below. */ + CINIT(PROXY_SSLVERSION, LONG, 250), + + /* Set a username for authenticated TLS for proxy */ + CINIT(PROXY_TLSAUTH_USERNAME, STRINGPOINT, 251), + + /* Set a password for authenticated TLS for proxy */ + CINIT(PROXY_TLSAUTH_PASSWORD, STRINGPOINT, 252), + + /* Set authentication type for authenticated TLS for proxy */ + CINIT(PROXY_TLSAUTH_TYPE, STRINGPOINT, 253), + + /* name of the file keeping your private SSL-certificate for proxy */ + CINIT(PROXY_SSLCERT, STRINGPOINT, 254), + + /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") for + proxy */ + CINIT(PROXY_SSLCERTTYPE, STRINGPOINT, 255), + + /* name of the file keeping your private SSL-key for proxy */ + CINIT(PROXY_SSLKEY, STRINGPOINT, 256), + + /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") for + proxy */ + CINIT(PROXY_SSLKEYTYPE, STRINGPOINT, 257), + + /* password for the SSL private key for proxy */ + CINIT(PROXY_KEYPASSWD, STRINGPOINT, 258), + + /* Specify which SSL ciphers to use for proxy */ + CINIT(PROXY_SSL_CIPHER_LIST, STRINGPOINT, 259), + + /* CRL file for proxy */ + CINIT(PROXY_CRLFILE, STRINGPOINT, 260), + + /* Enable/disable specific SSL features with a bitmask for proxy, see + CURLSSLOPT_* */ + CINIT(PROXY_SSL_OPTIONS, LONG, 261), + + /* Name of pre proxy to use. */ + CINIT(PRE_PROXY, STRINGPOINT, 262), + + /* The public key in DER form used to validate the proxy public key + this option is used only if PROXY_SSL_VERIFYPEER is true */ + CINIT(PROXY_PINNEDPUBLICKEY, STRINGPOINT, 263), + CURLOPT_LASTENTRY /* the last unused */ } CURLoption; @@ -1805,6 +1871,7 @@ enum { CURL_SSLVERSION_TLSv1_0, CURL_SSLVERSION_TLSv1_1, CURL_SSLVERSION_TLSv1_2, + CURL_SSLVERSION_TLSv1_3, CURL_SSLVERSION_LAST /* never use, keep last */ }; @@ -1839,7 +1906,10 @@ typedef enum { /* curl_strequal() and curl_strnequal() are subject for removal in a future - libcurl, see lib/README.curlx for details */ + libcurl, see lib/README.curlx for details + + !checksrc! disable SPACEBEFOREPAREN 2 +*/ CURL_EXTERN int (curl_strequal)(const char *s1, const char *s2); CURL_EXTERN int (curl_strnequal)(const char *s1, const char *s2, size_t n); @@ -2209,9 +2279,12 @@ typedef enum { CURLINFO_ACTIVESOCKET = CURLINFO_SOCKET + 44, CURLINFO_TLS_SSL_PTR = CURLINFO_SLIST + 45, CURLINFO_HTTP_VERSION = CURLINFO_LONG + 46, + CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 47, + CURLINFO_PROTOCOL = CURLINFO_LONG + 48, + CURLINFO_SCHEME = CURLINFO_STRING + 49, /* Fill in new entries below here! */ - CURLINFO_LASTONE = 46 + CURLINFO_LASTONE = 49 } CURLINFO; /* CURLINFO_RESPONSE_CODE is the new name for the option previously known as @@ -2372,6 +2445,7 @@ typedef struct { #define CURL_VERSION_UNIX_SOCKETS (1<<19) /* Unix domain sockets support */ #define CURL_VERSION_PSL (1<<20) /* Mozilla's Public Suffix List, used for cookie domain verification */ +#define CURL_VERSION_HTTPS_PROXY (1<<21) /* HTTPS-proxy support built-in */ /* * NAME curl_version_info() diff --git a/include/curl/curlver.h b/include/curl/curlver.h index 3bb0235..9126641 100644 --- a/include/curl/curlver.h +++ b/include/curl/curlver.h @@ -30,13 +30,13 @@ /* This is the version number of the libcurl package from which this header file origins: */ -#define LIBCURL_VERSION "7.51.0-DEV" +#define LIBCURL_VERSION "7.52.1-DEV" /* The numeric version number is also available "in parts" by using these defines: */ #define LIBCURL_VERSION_MAJOR 7 -#define LIBCURL_VERSION_MINOR 51 -#define LIBCURL_VERSION_PATCH 0 +#define LIBCURL_VERSION_MINOR 52 +#define LIBCURL_VERSION_PATCH 1 /* This is the numeric version of the libcurl version number, meant for easier parsing and comparions by programs. The LIBCURL_VERSION_NUM define will @@ -57,7 +57,7 @@ CURL_VERSION_BITS() macro since curl's own configure script greps for it and needs it to contain the full number. */ -#define LIBCURL_VERSION_NUM 0x073300 +#define LIBCURL_VERSION_NUM 0x073401 /* * This is the date and time when the full source package was created. The diff --git a/include/curl/easy.h b/include/curl/easy.h index afc766c..752c504 100644 --- a/include/curl/easy.h +++ b/include/curl/easy.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2008, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -58,7 +58,7 @@ CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...); * curl_easy_duphandle() for each new thread to avoid a series of identical * curl_easy_setopt() invokes in every thread. */ -CURL_EXTERN CURL* curl_easy_duphandle(CURL *curl); +CURL_EXTERN CURL *curl_easy_duphandle(CURL *curl); /* * NAME curl_easy_reset() diff --git a/include/curl/stdcheaders.h b/include/curl/stdcheaders.h index 6f0f7f3..027b6f4 100644 --- a/include/curl/stdcheaders.h +++ b/include/curl/stdcheaders.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -24,8 +24,8 @@ #include -size_t fread (void *, size_t, size_t, FILE *); -size_t fwrite (const void *, size_t, size_t, FILE *); +size_t fread(void *, size_t, size_t, FILE *); +size_t fwrite(const void *, size_t, size_t, FILE *); int strcasecmp(const char *, const char *); int strncasecmp(const char *, const char *, size_t); diff --git a/include/curl/typecheck-gcc.h b/include/curl/typecheck-gcc.h index 6ec8bcf..4eb896e 100644 --- a/include/curl/typecheck-gcc.h +++ b/include/curl/typecheck-gcc.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -40,7 +40,7 @@ */ #define curl_easy_setopt(handle, option, value) \ __extension__ ({ \ - __typeof__ (option) _curl_opt = option; \ + __typeof__(option) _curl_opt = option; \ if(__builtin_constant_p(_curl_opt)) { \ if(_curl_is_long_option(_curl_opt)) \ if(!_curl_is_long(value)) \ @@ -110,7 +110,7 @@ __extension__ ({ \ /* FIXME: don't allow const pointers */ #define curl_easy_getinfo(handle, info, arg) \ __extension__ ({ \ - __typeof__ (info) _curl_info = info; \ + __typeof__(info) _curl_info = info; \ if(__builtin_constant_p(_curl_info)) { \ if(_curl_is_string_info(_curl_info)) \ if(!_curl_is_arr((arg), char *)) \ @@ -151,7 +151,7 @@ _CURL_WARNING(_curl_easy_setopt_err_curl_off_t, "curl_easy_setopt expects a curl_off_t argument for this option") _CURL_WARNING(_curl_easy_setopt_err_string, "curl_easy_setopt expects a " - "string (char* or char[]) argument for this option" + "string ('char *' or char[]) argument for this option" ) _CURL_WARNING(_curl_easy_setopt_err_write_callback, "curl_easy_setopt expects a curl_write_callback argument for this option") @@ -182,24 +182,25 @@ _CURL_WARNING(_curl_easy_setopt_err_error_buffer, "curl_easy_setopt expects a " "char buffer of CURL_ERROR_SIZE as argument for this option") _CURL_WARNING(_curl_easy_setopt_err_FILE, - "curl_easy_setopt expects a FILE* argument for this option") + "curl_easy_setopt expects a 'FILE *' argument for this option") _CURL_WARNING(_curl_easy_setopt_err_postfields, - "curl_easy_setopt expects a void* or char* argument for this option") + "curl_easy_setopt expects a 'void *' or 'char *' argument for this option") _CURL_WARNING(_curl_easy_setopt_err_curl_httpost, - "curl_easy_setopt expects a struct curl_httppost* argument for this option") + "curl_easy_setopt expects a 'struct curl_httppost *' " + "argument for this option") _CURL_WARNING(_curl_easy_setopt_err_curl_slist, - "curl_easy_setopt expects a struct curl_slist* argument for this option") + "curl_easy_setopt expects a 'struct curl_slist *' argument for this option") _CURL_WARNING(_curl_easy_setopt_err_CURLSH, "curl_easy_setopt expects a CURLSH* argument for this option") _CURL_WARNING(_curl_easy_getinfo_err_string, - "curl_easy_getinfo expects a pointer to char * for this info") + "curl_easy_getinfo expects a pointer to 'char *' for this info") _CURL_WARNING(_curl_easy_getinfo_err_long, "curl_easy_getinfo expects a pointer to long for this info") _CURL_WARNING(_curl_easy_getinfo_err_double, "curl_easy_getinfo expects a pointer to double for this info") _CURL_WARNING(_curl_easy_getinfo_err_curl_slist, - "curl_easy_getinfo expects a pointer to struct curl_slist * for this info") + "curl_easy_getinfo expects a pointer to 'struct curl_slist *' for this info") /* groups of curl_easy_setops options that take the same type of argument */ @@ -363,7 +364,7 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist, /* XXX: should evaluate to true iff expr is a pointer */ #define _curl_is_any_ptr(expr) \ - (sizeof(expr) == sizeof(void*)) + (sizeof(expr) == sizeof(void *)) /* evaluates to true if expr is NULL */ /* XXX: must not evaluate expr, so this check is not accurate */ @@ -455,12 +456,12 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist, _curl_callback_compatible((expr), _curl_read_callback4) || \ _curl_callback_compatible((expr), _curl_read_callback5) || \ _curl_callback_compatible((expr), _curl_read_callback6)) -typedef size_t (_curl_read_callback1)(char *, size_t, size_t, void*); -typedef size_t (_curl_read_callback2)(char *, size_t, size_t, const void*); -typedef size_t (_curl_read_callback3)(char *, size_t, size_t, FILE*); -typedef size_t (_curl_read_callback4)(void *, size_t, size_t, void*); -typedef size_t (_curl_read_callback5)(void *, size_t, size_t, const void*); -typedef size_t (_curl_read_callback6)(void *, size_t, size_t, FILE*); +typedef size_t (_curl_read_callback1)(char *, size_t, size_t, void *); +typedef size_t (_curl_read_callback2)(char *, size_t, size_t, const void *); +typedef size_t (_curl_read_callback3)(char *, size_t, size_t, FILE *); +typedef size_t (_curl_read_callback4)(void *, size_t, size_t, void *); +typedef size_t (_curl_read_callback5)(void *, size_t, size_t, const void *); +typedef size_t (_curl_read_callback6)(void *, size_t, size_t, FILE *); /* evaluates to true if expr is of type curl_write_callback or "similar" */ #define _curl_is_write_cb(expr) \ @@ -473,14 +474,14 @@ typedef size_t (_curl_read_callback6)(void *, size_t, size_t, FILE*); _curl_callback_compatible((expr), _curl_write_callback4) || \ _curl_callback_compatible((expr), _curl_write_callback5) || \ _curl_callback_compatible((expr), _curl_write_callback6)) -typedef size_t (_curl_write_callback1)(const char *, size_t, size_t, void*); +typedef size_t (_curl_write_callback1)(const char *, size_t, size_t, void *); typedef size_t (_curl_write_callback2)(const char *, size_t, size_t, - const void*); -typedef size_t (_curl_write_callback3)(const char *, size_t, size_t, FILE*); -typedef size_t (_curl_write_callback4)(const void *, size_t, size_t, void*); + const void *); +typedef size_t (_curl_write_callback3)(const char *, size_t, size_t, FILE *); +typedef size_t (_curl_write_callback4)(const void *, size_t, size_t, void *); typedef size_t (_curl_write_callback5)(const void *, size_t, size_t, - const void*); -typedef size_t (_curl_write_callback6)(const void *, size_t, size_t, FILE*); + const void *); +typedef size_t (_curl_write_callback6)(const void *, size_t, size_t, FILE *); /* evaluates to true if expr is of type curl_ioctl_callback or "similar" */ #define _curl_is_ioctl_cb(expr) \ @@ -490,10 +491,10 @@ typedef size_t (_curl_write_callback6)(const void *, size_t, size_t, FILE*); _curl_callback_compatible((expr), _curl_ioctl_callback2) || \ _curl_callback_compatible((expr), _curl_ioctl_callback3) || \ _curl_callback_compatible((expr), _curl_ioctl_callback4)) -typedef curlioerr (_curl_ioctl_callback1)(CURL *, int, void*); -typedef curlioerr (_curl_ioctl_callback2)(CURL *, int, const void*); -typedef curlioerr (_curl_ioctl_callback3)(CURL *, curliocmd, void*); -typedef curlioerr (_curl_ioctl_callback4)(CURL *, curliocmd, const void*); +typedef curlioerr (_curl_ioctl_callback1)(CURL *, int, void *); +typedef curlioerr (_curl_ioctl_callback2)(CURL *, int, const void *); +typedef curlioerr (_curl_ioctl_callback3)(CURL *, curliocmd, void *); +typedef curlioerr (_curl_ioctl_callback4)(CURL *, curliocmd, const void *); /* evaluates to true if expr is of type curl_sockopt_callback or "similar" */ #define _curl_is_sockopt_cb(expr) \ diff --git a/lib/Makefile.inc b/lib/Makefile.inc index 1328cad..19f5800 100644 --- a/lib/Makefile.inc +++ b/lib/Makefile.inc @@ -51,7 +51,7 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \ pingpong.c rtsp.c curl_threads.c warnless.c hmac.c curl_rtmp.c \ openldap.c curl_gethostname.c gopher.c idn_win32.c \ http_proxy.c non-ascii.c asyn-ares.c asyn-thread.c curl_gssapi.c \ - http_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_sasl.c \ + http_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_sasl.c rand.c \ curl_multibyte.c hostcheck.c conncache.c pipeline.c dotdot.c \ x509asn1.c http2.c smb.c curl_endian.c curl_des.c system_win32.c @@ -72,7 +72,7 @@ LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \ curl_sasl.h curl_multibyte.h hostcheck.h conncache.h \ curl_setup_once.h multihandle.h setup-vms.h pipeline.h dotdot.h \ x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.h \ - curl_printf.h system_win32.h + curl_printf.h system_win32.h rand.h LIB_RCFILES = libcurl.rc diff --git a/lib/asyn-ares.c b/lib/asyn-ares.c index 2aed94f..c038c2a 100644 --- a/lib/asyn-ares.c +++ b/lib/asyn-ares.c @@ -169,7 +169,7 @@ int Curl_resolver_duphandle(void **to, void *from) return CURLE_OK; } -static void destroy_async_data (struct Curl_async *async); +static void destroy_async_data(struct Curl_async *async); /* * Cancel all possibly still on-going resolves for this connection. @@ -184,7 +184,7 @@ void Curl_resolver_cancel(struct connectdata *conn) /* * destroy_async_data() cleans up async resolver data. */ -static void destroy_async_data (struct Curl_async *async) +static void destroy_async_data(struct Curl_async *async) { free(async->hostname); diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c index 7cce01a..26a15b1 100644 --- a/lib/asyn-thread.c +++ b/lib/asyn-thread.c @@ -155,8 +155,8 @@ struct thread_sync_data { curl_mutex_t * mtx; int done; - char * hostname; /* hostname to resolve, Curl_async.hostname - duplicate */ + char *hostname; /* hostname to resolve, Curl_async.hostname + duplicate */ int port; int sock_error; Curl_addrinfo *res; @@ -169,7 +169,7 @@ struct thread_sync_data { struct thread_data { curl_thread_t thread_hnd; unsigned int poll_interval; - long interval_end; + time_t interval_end; struct thread_sync_data tsd; }; @@ -200,7 +200,7 @@ void destroy_thread_sync_data(struct thread_sync_data * tsd) /* Initialize resolver thread synchronization data */ static int init_thread_sync_data(struct thread_data * td, - const char * hostname, + const char *hostname, int port, const struct addrinfo *hints) { @@ -263,7 +263,7 @@ static int getaddrinfo_complete(struct connectdata *conn) * For builds without ARES, but with ENABLE_IPV6, create a resolver thread * and wait on it. */ -static unsigned int CURL_STDCALL getaddrinfo_thread (void *arg) +static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg) { struct thread_sync_data *tsd = (struct thread_sync_data*)arg; struct thread_data *td = tsd->td; @@ -303,7 +303,7 @@ static unsigned int CURL_STDCALL getaddrinfo_thread (void *arg) /* * gethostbyname_thread() resolves a name and then exits. */ -static unsigned int CURL_STDCALL gethostbyname_thread (void *arg) +static unsigned int CURL_STDCALL gethostbyname_thread(void *arg) { struct thread_sync_data *tsd = (struct thread_sync_data *)arg; struct thread_data *td = tsd->td; @@ -336,7 +336,7 @@ static unsigned int CURL_STDCALL gethostbyname_thread (void *arg) /* * destroy_async_data() cleans up async resolver data and thread handle. */ -static void destroy_async_data (struct Curl_async *async) +static void destroy_async_data(struct Curl_async *async) { if(async->os_specific) { struct thread_data *td = (struct thread_data*) async->os_specific; @@ -375,14 +375,14 @@ static void destroy_async_data (struct Curl_async *async) * * Returns FALSE in case of failure, otherwise TRUE. */ -static bool init_resolve_thread (struct connectdata *conn, - const char *hostname, int port, - const struct addrinfo *hints) +static bool init_resolve_thread(struct connectdata *conn, + const char *hostname, int port, + const struct addrinfo *hints) { struct thread_data *td = calloc(1, sizeof(struct thread_data)); int err = RESOLVER_ENOMEM; - conn->async.os_specific = (void*) td; + conn->async.os_specific = (void *)td; if(!td) goto err_exit; @@ -525,7 +525,7 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn, } else { /* poll for name lookup done with exponential backoff up to 250ms */ - long elapsed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle); + time_t elapsed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle); if(elapsed < 0) elapsed = 0; diff --git a/lib/conncache.c b/lib/conncache.c index 01b1b44..d8ef9a5 100644 --- a/lib/conncache.c +++ b/lib/conncache.c @@ -132,8 +132,10 @@ static char *hashkey(struct connectdata *conn) { const char *hostname; - if(conn->bits.proxy) - hostname = conn->proxy.name; + if(conn->bits.socksproxy) + hostname = conn->socks_proxy.host.name; + else if(conn->bits.httpproxy) + hostname = conn->http_proxy.host.name; else if(conn->bits.conn_to_host) hostname = conn->conn_to_host.name; else diff --git a/lib/connect.c b/lib/connect.c index 3df34d9..524d885 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -179,12 +179,12 @@ singleipconnect(struct connectdata *conn, * * @unittest: 1303 */ -long Curl_timeleft(struct Curl_easy *data, - struct timeval *nowp, - bool duringconnect) +time_t Curl_timeleft(struct Curl_easy *data, + struct timeval *nowp, + bool duringconnect) { int timeout_set = 0; - long timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0; + time_t timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0; struct timeval now; /* if a timeout is set, use the most restrictive one */ @@ -194,7 +194,7 @@ long Curl_timeleft(struct Curl_easy *data, if(duringconnect && (data->set.connecttimeout > 0)) timeout_set |= 2; - switch (timeout_set) { + switch(timeout_set) { case 1: timeout_ms = data->set.timeout; break; @@ -601,26 +601,28 @@ void Curl_persistconninfo(struct connectdata *conn) { memcpy(conn->data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN); memcpy(conn->data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN); + conn->data->info.conn_scheme = conn->handler->scheme; + conn->data->info.conn_protocol = conn->handler->protocol; conn->data->info.conn_primary_port = conn->primary_port; conn->data->info.conn_local_port = conn->local_port; } /* retrieves ip address and port from a sockaddr structure */ -static bool getaddressinfo(struct sockaddr* sa, char* addr, - long* port) +static bool getaddressinfo(struct sockaddr *sa, char *addr, + long *port) { unsigned short us_port; - struct sockaddr_in* si = NULL; + struct sockaddr_in *si = NULL; #ifdef ENABLE_IPV6 - struct sockaddr_in6* si6 = NULL; + struct sockaddr_in6 *si6 = NULL; #endif #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX) - struct sockaddr_un* su = NULL; + struct sockaddr_un *su = NULL; #endif - switch (sa->sa_family) { + switch(sa->sa_family) { case AF_INET: - si = (struct sockaddr_in*)(void*) sa; + si = (struct sockaddr_in *)(void *) sa; if(Curl_inet_ntop(sa->sa_family, &si->sin_addr, addr, MAX_IPADR_LEN)) { us_port = ntohs(si->sin_port); @@ -630,7 +632,7 @@ static bool getaddressinfo(struct sockaddr* sa, char* addr, break; #ifdef ENABLE_IPV6 case AF_INET6: - si6 = (struct sockaddr_in6*)(void*) sa; + si6 = (struct sockaddr_in6 *)(void *) sa; if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr, addr, MAX_IPADR_LEN)) { us_port = ntohs(si6->sin6_port); @@ -722,7 +724,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, { struct Curl_easy *data = conn->data; CURLcode result = CURLE_OK; - long allow; + time_t allow; int error = 0; struct timeval now; int rc; @@ -843,7 +845,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, if(result) { /* no more addresses to try */ - const char* hostname; + const char *hostname; /* if the first address family runs out of addresses to try before the happy eyeball timeout, go ahead and try the next family now */ @@ -853,8 +855,10 @@ CURLcode Curl_is_connected(struct connectdata *conn, return result; } - if(conn->bits.proxy) - hostname = conn->proxy.name; + if(conn->bits.socksproxy) + hostname = conn->socks_proxy.host.name; + else if(conn->bits.httpproxy) + hostname = conn->http_proxy.host.name; else if(conn->bits.conn_to_host) hostname = conn->conn_to_host.name; else @@ -1153,7 +1157,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ struct timeval before = Curl_tvnow(); CURLcode result = CURLE_COULDNT_CONNECT; - long timeout_ms = Curl_timeleft(data, &before, TRUE); + time_t timeout_ms = Curl_timeleft(data, &before, TRUE); if(timeout_ms < 0) { /* a precaution, no need to continue if time already is up */ @@ -1243,24 +1247,6 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data, /* only store this if the caller cares for it */ *connp = c; sockfd = c->sock[FIRSTSOCKET]; - /* we have a socket connected, let's determine if the server shut down */ - /* determine if ssl */ - if(c->ssl[FIRSTSOCKET].use) { - /* use the SSL context */ - if(!Curl_ssl_check_cxn(c)) - return CURL_SOCKET_BAD; /* FIN received */ - } -/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */ -#ifdef MSG_PEEK - else if(sockfd != CURL_SOCKET_BAD) { - /* use the socket */ - char buf; - if(recv((RECV_TYPE_ARG1)sockfd, (RECV_TYPE_ARG2)&buf, - (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) { - return CURL_SOCKET_BAD; /* FIN received */ - } - } -#endif } else return CURL_SOCKET_BAD; @@ -1269,6 +1255,33 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data, } /* + * Check if a connection seems to be alive. + */ +bool Curl_connalive(struct connectdata *conn) +{ + /* First determine if ssl */ + if(conn->ssl[FIRSTSOCKET].use) { + /* use the SSL context */ + if(!Curl_ssl_check_cxn(conn)) + return false; /* FIN received */ + } +/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */ +#ifdef MSG_PEEK + else if(conn->sock[FIRSTSOCKET] == CURL_SOCKET_BAD) + return false; + else { + /* use the socket */ + char buf; + if(recv((RECV_TYPE_ARG1)conn->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf, + (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) { + return false; /* FIN received */ + } + } +#endif + return true; +} + +/* * Close a socket. * * 'conn' can be NULL, beware! @@ -1391,3 +1404,16 @@ void Curl_conncontrol(struct connectdata *conn, should assign this bit */ } } + +/* Data received can be cached at various levels, so check them all here. */ +bool Curl_conn_data_pending(struct connectdata *conn, int sockindex) +{ + int readable; + + if(Curl_ssl_data_pending(conn, sockindex) || + Curl_recv_has_postponed_data(conn, sockindex)) + return true; + + readable = SOCKET_READABLE(conn->sock[sockindex], 0); + return (readable > 0 && (readable & CURL_CSELECT_IN)); +} diff --git a/lib/connect.h b/lib/connect.h index a7cbc9b..5653cb4 100644 --- a/lib/connect.h +++ b/lib/connect.h @@ -35,9 +35,9 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* generic function that returns how much time there's left to run, according to the timeouts set */ -long Curl_timeleft(struct Curl_easy *data, - struct timeval *nowp, - bool duringconnect); +time_t Curl_timeleft(struct Curl_easy *data, + struct timeval *nowp, + bool duringconnect); #define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */ #define HAPPY_EYEBALLS_TIMEOUT 200 /* milliseconds to wait between @@ -52,6 +52,11 @@ long Curl_timeleft(struct Curl_easy *data, curl_socket_t Curl_getconnectinfo(struct Curl_easy *data, struct connectdata **connp); +/* + * Check if a connection seems to be alive. + */ +bool Curl_connalive(struct connectdata *conn); + #ifdef USE_WINSOCK /* When you run a program that uses the Windows Sockets API, you may experience slow performance when you copy data to a TCP server. @@ -137,4 +142,6 @@ void Curl_conncontrol(struct connectdata *conn, #define connkeep(x,y) Curl_conncontrol(x, CONNCTRL_KEEP) #endif +bool Curl_conn_data_pending(struct connectdata *conn, int sockindex); + #endif /* HEADER_CURL_CONNECT_H */ diff --git a/lib/content_encoding.c b/lib/content_encoding.c index fa36aca..5385058 100644 --- a/lib/content_encoding.c +++ b/lib/content_encoding.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -28,8 +28,8 @@ #include #include "sendf.h" #include "content_encoding.h" +#include "strdup.h" #include "curl_memory.h" - #include "memdebug.h" /* Comment this out if zlib is always going to be at least ver. 1.2.0.4 @@ -69,11 +69,11 @@ process_zlib_error(struct connectdata *conn, z_stream *z) { struct Curl_easy *data = conn->data; if(z->msg) - failf (data, "Error while processing content unencoding: %s", - z->msg); + failf(data, "Error while processing content unencoding: %s", + z->msg); else - failf (data, "Error while processing content unencoding: " - "Unknown failure within decompression software."); + failf(data, "Error while processing content unencoding: " + "Unknown failure within decompression software."); return CURLE_BAD_CONTENT_ENCODING; } @@ -327,14 +327,14 @@ Curl_unencode_gzip_write(struct connectdata *conn, * can handle the gzip header themselves. */ - switch (k->zlib_init) { + switch(k->zlib_init) { /* Skip over gzip header? */ case ZLIB_INIT: { /* Initial call state */ ssize_t hlen; - switch (check_gzip_header((unsigned char *)k->str, nread, &hlen)) { + switch(check_gzip_header((unsigned char *)k->str, nread, &hlen)) { case GZIP_OK: z->next_in = (Bytef *)k->str + hlen; z->avail_in = (uInt)(nread - hlen); @@ -371,18 +371,15 @@ Curl_unencode_gzip_write(struct connectdata *conn, { /* Need more gzip header data state */ ssize_t hlen; - unsigned char *oldblock = z->next_in; - z->avail_in += (uInt)nread; - z->next_in = realloc(z->next_in, z->avail_in); + z->next_in = Curl_saferealloc(z->next_in, z->avail_in); if(z->next_in == NULL) { - free(oldblock); return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY); } /* Append the new block of data to the previous one */ memcpy(z->next_in + z->avail_in - nread, k->str, nread); - switch (check_gzip_header(z->next_in, z->avail_in, &hlen)) { + switch(check_gzip_header(z->next_in, z->avail_in, &hlen)) { case GZIP_OK: /* This is the zlib stream data */ free(z->next_in); diff --git a/lib/cookie.c b/lib/cookie.c index 1b3e645..092a226 100644 --- a/lib/cookie.c +++ b/lib/cookie.c @@ -146,12 +146,12 @@ static bool tailmatch(const char *cooke_domain, const char *hostname) * matching cookie path and url path * RFC6265 5.1.4 Paths and Path-Match */ -static bool pathmatch(const char* cookie_path, const char* request_uri) +static bool pathmatch(const char *cookie_path, const char *request_uri) { size_t cookie_path_len; size_t uri_path_len; - char* uri_path = NULL; - char* pos; + char *uri_path = NULL; + char *pos; bool ret = FALSE; /* cookie_path must not have last '/' separator. ex: /sample */ @@ -798,8 +798,8 @@ Curl_cookie_add(struct Curl_easy *data, /* Check if the domain is a Public Suffix and if yes, ignore the cookie. This needs a libpsl compiled with builtin data. */ if(domain && co->domain && !isip(co->domain)) { - if(((psl = psl_builtin()) != NULL) - && !psl_is_cookie_domain_acceptable(psl, domain, co->domain)) { + psl = psl_builtin(); + if(psl && !psl_is_cookie_domain_acceptable(psl, domain, co->domain)) { infof(data, "cookie '%s' dropped, domain '%s' must not set cookies for '%s'\n", co->name, domain, co->domain); diff --git a/lib/curl_addrinfo.c b/lib/curl_addrinfo.c index 35eb2dd..61cdadd 100644 --- a/lib/curl_addrinfo.c +++ b/lib/curl_addrinfo.c @@ -146,7 +146,8 @@ Curl_getaddrinfo_ex(const char *nodename, if((size_t)ai->ai_addrlen < ss_size) continue; - if((ca = malloc(sizeof(Curl_addrinfo))) == NULL) { + ca = malloc(sizeof(Curl_addrinfo)); + if(!ca) { error = EAI_MEMORY; break; } @@ -163,7 +164,8 @@ Curl_getaddrinfo_ex(const char *nodename, ca->ai_canonname = NULL; ca->ai_next = NULL; - if((ca->ai_addr = malloc(ss_size)) == NULL) { + ca->ai_addr = malloc(ss_size); + if(!ca->ai_addr) { error = EAI_MEMORY; free(ca); break; @@ -171,7 +173,8 @@ Curl_getaddrinfo_ex(const char *nodename, memcpy(ca->ai_addr, ai->ai_addr, ss_size); if(ai->ai_canonname != NULL) { - if((ca->ai_canonname = strdup(ai->ai_canonname)) == NULL) { + ca->ai_canonname = strdup(ai->ai_canonname); + if(!ca->ai_canonname) { error = EAI_MEMORY; free(ca->ai_addr); free(ca); @@ -286,21 +289,24 @@ Curl_he2ai(const struct hostent *he, int port) size_t ss_size; #ifdef ENABLE_IPV6 if(he->h_addrtype == AF_INET6) - ss_size = sizeof (struct sockaddr_in6); + ss_size = sizeof(struct sockaddr_in6); else #endif - ss_size = sizeof (struct sockaddr_in); + ss_size = sizeof(struct sockaddr_in); - if((ai = calloc(1, sizeof(Curl_addrinfo))) == NULL) { + ai = calloc(1, sizeof(Curl_addrinfo)); + if(!ai) { result = CURLE_OUT_OF_MEMORY; break; } - if((ai->ai_canonname = strdup(he->h_name)) == NULL) { + ai->ai_canonname = strdup(he->h_name); + if(!ai->ai_canonname) { result = CURLE_OUT_OF_MEMORY; free(ai); break; } - if((ai->ai_addr = calloc(1, ss_size)) == NULL) { + ai->ai_addr = calloc(1, ss_size); + if(!ai->ai_addr) { result = CURLE_OUT_OF_MEMORY; free(ai->ai_canonname); free(ai); @@ -325,7 +331,7 @@ Curl_he2ai(const struct hostent *he, int port) /* leave the rest of the struct filled with zero */ - switch (ai->ai_family) { + switch(ai->ai_family) { case AF_INET: addr = (void *)ai->ai_addr; /* storage area for this info */ @@ -475,8 +481,9 @@ Curl_addrinfo *Curl_str2addr(char *address, int port) /** * Given a path to a Unix domain socket, return a newly allocated Curl_addrinfo * struct initialized with this path. + * Set '*longpath' to TRUE if the error is a too long path. */ -Curl_addrinfo *Curl_unix2addr(const char *path) +Curl_addrinfo *Curl_unix2addr(const char *path, int *longpath) { Curl_addrinfo *ai; struct sockaddr_un *sa_un; @@ -485,8 +492,10 @@ Curl_addrinfo *Curl_unix2addr(const char *path) ai = calloc(1, sizeof(Curl_addrinfo)); if(!ai) return NULL; - if((ai->ai_addr = calloc(1, sizeof(struct sockaddr_un))) == NULL) { + ai->ai_addr = calloc(1, sizeof(struct sockaddr_un)); + if(!ai->ai_addr) { free(ai); + *longpath = FALSE; return NULL; } /* sun_path must be able to store the NUL-terminated path */ @@ -494,6 +503,7 @@ Curl_addrinfo *Curl_unix2addr(const char *path) if(path_len >= sizeof(sa_un->sun_path)) { free(ai->ai_addr); free(ai); + *longpath = TRUE; return NULL; } @@ -576,7 +586,7 @@ void Curl_addrinfo_set_port(Curl_addrinfo *addrinfo, int port) struct sockaddr_in6 *addr6; #endif for(ca = addrinfo; ca != NULL; ca = ca->ai_next) { - switch (ca->ai_family) { + switch(ca->ai_family) { case AF_INET: addr = (void *)ca->ai_addr; /* storage area for this info */ addr->sin_port = htons((unsigned short)port); diff --git a/lib/curl_addrinfo.h b/lib/curl_addrinfo.h index 1a681e6..4f24730 100644 --- a/lib/curl_addrinfo.h +++ b/lib/curl_addrinfo.h @@ -80,7 +80,7 @@ Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port); Curl_addrinfo *Curl_str2addr(char *dotted, int port); #ifdef USE_UNIX_SOCKETS -Curl_addrinfo *Curl_unix2addr(const char *path); +Curl_addrinfo *Curl_unix2addr(const char *path, int *longpath); #endif #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \ diff --git a/lib/curl_endian.c b/lib/curl_endian.c index 76deca6..c2d21de 100644 --- a/lib/curl_endian.c +++ b/lib/curl_endian.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -37,7 +37,7 @@ * * Returns the integer. */ -unsigned short Curl_read16_le(unsigned char *buf) +unsigned short Curl_read16_le(const unsigned char *buf) { return (unsigned short)(((unsigned short)buf[0]) | ((unsigned short)buf[1] << 8)); @@ -56,7 +56,7 @@ unsigned short Curl_read16_le(unsigned char *buf) * * Returns the integer. */ -unsigned int Curl_read32_le(unsigned char *buf) +unsigned int Curl_read32_le(const unsigned char *buf) { return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8) | ((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24); @@ -77,7 +77,7 @@ unsigned int Curl_read32_le(unsigned char *buf) * Returns the integer. */ #if defined(HAVE_LONGLONG) -unsigned long long Curl_read64_le(unsigned char *buf) +unsigned long long Curl_read64_le(const unsigned char *buf) { return ((unsigned long long)buf[0]) | ((unsigned long long)buf[1] << 8) | @@ -89,7 +89,7 @@ unsigned long long Curl_read64_le(unsigned char *buf) ((unsigned long long)buf[7] << 56); } #else -unsigned __int64 Curl_read64_le(unsigned char *buf) +unsigned __int64 Curl_read64_le(const unsigned char *buf) { return ((unsigned __int64)buf[0]) | ((unsigned __int64)buf[1] << 8) | ((unsigned __int64)buf[2] << 16) | ((unsigned __int64)buf[3] << 24) | @@ -113,7 +113,7 @@ unsigned __int64 Curl_read64_le(unsigned char *buf) * * Returns the integer. */ -unsigned short Curl_read16_be(unsigned char *buf) +unsigned short Curl_read16_be(const unsigned char *buf) { return (unsigned short)(((unsigned short)buf[0] << 8) | ((unsigned short)buf[1])); @@ -132,7 +132,7 @@ unsigned short Curl_read16_be(unsigned char *buf) * * Returns the integer. */ -unsigned int Curl_read32_be(unsigned char *buf) +unsigned int Curl_read32_be(const unsigned char *buf) { return ((unsigned int)buf[0] << 24) | ((unsigned int)buf[1] << 16) | ((unsigned int)buf[2] << 8) | ((unsigned int)buf[3]); @@ -153,7 +153,7 @@ unsigned int Curl_read32_be(unsigned char *buf) * Returns the integer. */ #if defined(HAVE_LONGLONG) -unsigned long long Curl_read64_be(unsigned char *buf) +unsigned long long Curl_read64_be(const unsigned char *buf) { return ((unsigned long long)buf[0] << 56) | ((unsigned long long)buf[1] << 48) | @@ -165,7 +165,7 @@ unsigned long long Curl_read64_be(unsigned char *buf) ((unsigned long long)buf[7]); } #else -unsigned __int64 Curl_read64_be(unsigned char *buf) +unsigned __int64 Curl_read64_be(const unsigned char *buf) { return ((unsigned __int64)buf[0] << 56) | ((unsigned __int64)buf[1] << 48) | ((unsigned __int64)buf[2] << 40) | ((unsigned __int64)buf[3] << 32) | diff --git a/lib/curl_endian.h b/lib/curl_endian.h index df8398c..8a2b07a 100644 --- a/lib/curl_endian.h +++ b/lib/curl_endian.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -23,32 +23,32 @@ ***************************************************************************/ /* Converts a 16-bit integer from little endian */ -unsigned short Curl_read16_le(unsigned char *buf); +unsigned short Curl_read16_le(const unsigned char *buf); /* Converts a 32-bit integer from little endian */ -unsigned int Curl_read32_le(unsigned char *buf); +unsigned int Curl_read32_le(const unsigned char *buf); #if (CURL_SIZEOF_CURL_OFF_T > 4) /* Converts a 64-bit integer from little endian */ #if defined(HAVE_LONGLONG) -unsigned long long Curl_read64_le(unsigned char *buf); +unsigned long long Curl_read64_le(const unsigned char *buf); #else -unsigned __int64 Curl_read64_le(unsigned char *buf); +unsigned __int64 Curl_read64_le(const unsigned char *buf); #endif #endif /* Converts a 16-bit integer from big endian */ -unsigned short Curl_read16_be(unsigned char *buf); +unsigned short Curl_read16_be(const unsigned char *buf); /* Converts a 32-bit integer from big endian */ -unsigned int Curl_read32_be(unsigned char *buf); +unsigned int Curl_read32_be(const unsigned char *buf); #if (CURL_SIZEOF_CURL_OFF_T > 4) /* Converts a 64-bit integer from big endian */ #if defined(HAVE_LONGLONG) -unsigned long long Curl_read64_be(unsigned char *buf); +unsigned long long Curl_read64_be(const unsigned char *buf); #else -unsigned __int64 Curl_read64_be(unsigned char *buf); +unsigned __int64 Curl_read64_be(const unsigned char *buf); #endif #endif diff --git a/lib/curl_gethostname.c b/lib/curl_gethostname.c index 2591fd8..8337c72 100644 --- a/lib/curl_gethostname.c +++ b/lib/curl_gethostname.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -48,8 +48,8 @@ * For libcurl static library release builds no overriding takes place. */ -int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen) { - +int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen) +{ #ifndef HAVE_GETHOSTNAME /* Allow compilation and return failure when unavailable */ @@ -59,7 +59,7 @@ int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen) { #else int err; - char* dot; + char *dot; #ifdef DEBUGBUILD diff --git a/lib/curl_gssapi.c b/lib/curl_gssapi.c index bf7c766..83f3fa0 100644 --- a/lib/curl_gssapi.c +++ b/lib/curl_gssapi.c @@ -94,7 +94,7 @@ static size_t display_gss_error(OM_uint32 status, int type, if(GSS_LOG_BUFFER_LEN > len + status_string.length + 3) { len += snprintf(buf + len, GSS_LOG_BUFFER_LEN - len, "%.*s. ", (int)status_string.length, - (char*)status_string.value); + (char *)status_string.value); } gss_release_buffer(&min_stat, &status_string); } while(!GSS_ERROR(maj_stat) && msg_ctx != 0); diff --git a/lib/curl_hmac.h b/lib/curl_hmac.h index 41703b4..756dc9e 100644 --- a/lib/curl_hmac.h +++ b/lib/curl_hmac.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -24,11 +24,11 @@ #ifndef CURL_DISABLE_CRYPTO_AUTH -typedef void (* HMAC_hinit_func)(void * context); -typedef void (* HMAC_hupdate_func)(void * context, - const unsigned char * data, +typedef void (* HMAC_hinit_func)(void *context); +typedef void (* HMAC_hupdate_func)(void *context, + const unsigned char *data, unsigned int len); -typedef void (* HMAC_hfinal_func)(unsigned char * result, void * context); +typedef void (* HMAC_hfinal_func)(unsigned char *result, void *context); /* Per-hash function HMAC parameters. */ @@ -46,21 +46,21 @@ typedef struct { /* HMAC computation context. */ typedef struct { - const HMAC_params * hmac_hash; /* Hash function definition. */ - void * hmac_hashctxt1; /* Hash function context 1. */ - void * hmac_hashctxt2; /* Hash function context 2. */ + const HMAC_params *hmac_hash; /* Hash function definition. */ + void *hmac_hashctxt1; /* Hash function context 1. */ + void *hmac_hashctxt2; /* Hash function context 2. */ } HMAC_context; /* Prototypes. */ -HMAC_context * Curl_HMAC_init(const HMAC_params * hashparams, - const unsigned char * key, +HMAC_context * Curl_HMAC_init(const HMAC_params *hashparams, + const unsigned char *key, unsigned int keylen); -int Curl_HMAC_update(HMAC_context * context, - const unsigned char * data, +int Curl_HMAC_update(HMAC_context *context, + const unsigned char *data, unsigned int len); -int Curl_HMAC_final(HMAC_context * context, unsigned char * result); +int Curl_HMAC_final(HMAC_context *context, unsigned char *result); #endif diff --git a/lib/curl_ntlm_core.c b/lib/curl_ntlm_core.c index 812a073..73d983c 100644 --- a/lib/curl_ntlm_core.c +++ b/lib/curl_ntlm_core.c @@ -566,7 +566,7 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data, gcry_md_hd_t MD4pw; gcry_md_open(&MD4pw, GCRY_MD_MD4, 0); gcry_md_write(MD4pw, pw, 2 * len); - memcpy (ntbuffer, gcry_md_read (MD4pw, 0), MD4_DIGEST_LENGTH); + memcpy(ntbuffer, gcry_md_read(MD4pw, 0), MD4_DIGEST_LENGTH); gcry_md_close(MD4pw); #elif defined(USE_MBEDTLS) mbedtls_md4(pw, 2 * len, ntbuffer); diff --git a/lib/curl_ntlm_wb.c b/lib/curl_ntlm_wb.c index afdea16..6a90e62 100644 --- a/lib/curl_ntlm_wb.c +++ b/lib/curl_ntlm_wb.c @@ -51,6 +51,7 @@ #include "curl_ntlm_wb.h" #include "url.h" #include "strerror.h" +#include "strdup.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" @@ -156,7 +157,8 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp) } slash = strpbrk(username, "\\/"); if(slash) { - if((domain = strdup(username)) == NULL) + domain = strdup(username); + if(!domain) return CURLE_OUT_OF_MEMORY; slash = domain + (slash - username); *slash = '\0'; @@ -293,11 +295,10 @@ static CURLcode ntlm_wb_response(struct connectdata *conn, buf[len_out - 1] = '\0'; break; } - newbuf = realloc(buf, len_out + NTLM_BUFSIZE); - if(!newbuf) { - free(buf); + newbuf = Curl_saferealloc(buf, len_out + NTLM_BUFSIZE); + if(!newbuf) return CURLE_OUT_OF_MEMORY; - } + buf = newbuf; } @@ -349,7 +350,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, if(proxy) { allocuserpwd = &conn->allocptr.proxyuserpwd; - userp = conn->proxyuser; + userp = conn->http_proxy.user; ntlm = &conn->proxyntlm; authp = &conn->data->state.authproxy; } diff --git a/lib/curl_sasl.c b/lib/curl_sasl.c index 6b86962..807f5de 100644 --- a/lib/curl_sasl.c +++ b/lib/curl_sasl.c @@ -262,10 +262,13 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn, size_t len = 0; saslstate state1 = SASL_STOP; saslstate state2 = SASL_FINAL; + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; #if defined(USE_KERBEROS5) - const char* service = data->set.str[STRING_SERVICE_NAME] ? - data->set.str[STRING_SERVICE_NAME] : - sasl->params->service; + const char *service = data->set.str[STRING_SERVICE_NAME] ? + data->set.str[STRING_SERVICE_NAME] : + sasl->params->service; #endif sasl->force_ir = force_ir; /* Latch for future use */ @@ -341,8 +344,8 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn, if(force_ir || data->set.sasl_ir) result = Curl_auth_create_oauth_bearer_message(data, conn->user, - conn->host.name, - conn->port, + hostname, + port, conn->oauth_bearer, &resp, &len); } @@ -408,6 +411,9 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn, struct Curl_easy *data = conn->data; saslstate newstate = SASL_FINAL; char *resp = NULL; + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; #if !defined(CURL_DISABLE_CRYPTO_AUTH) char *serverdata; char *chlg = NULL; @@ -542,8 +548,8 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn, /* Create the authorisation message */ if(sasl->authused == SASL_MECH_OAUTHBEARER) { result = Curl_auth_create_oauth_bearer_message(data, conn->user, - conn->host.name, - conn->port, + hostname, + port, conn->oauth_bearer, &resp, &len); diff --git a/lib/curl_sec.h b/lib/curl_sec.h index 3f94e14..7bdde26 100644 --- a/lib/curl_sec.h +++ b/lib/curl_sec.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -30,8 +30,8 @@ struct Curl_sec_client_mech { void (*end)(void *); int (*check_prot)(void *, int); int (*overhead)(void *, int, int); - int (*encode)(void *, const void*, int, int, void**); - int (*decode)(void *, void*, int, int, struct connectdata *); + int (*encode)(void *, const void *, int, int, void **); + int (*decode)(void *, void *, int, int, struct connectdata *); }; #define AUTH_OK 0 @@ -39,11 +39,11 @@ struct Curl_sec_client_mech { #define AUTH_ERROR 2 #ifdef HAVE_GSSAPI -int Curl_sec_read_msg (struct connectdata *conn, char *, - enum protection_level); -void Curl_sec_end (struct connectdata *); -CURLcode Curl_sec_login (struct connectdata *); -int Curl_sec_request_prot (struct connectdata *conn, const char *level); +int Curl_sec_read_msg(struct connectdata *conn, char *, + enum protection_level); +void Curl_sec_end(struct connectdata *); +CURLcode Curl_sec_login(struct connectdata *); +int Curl_sec_request_prot(struct connectdata *conn, const char *level); extern struct Curl_sec_client_mech Curl_krb5_client_mech; #endif diff --git a/lib/curl_setup.h b/lib/curl_setup.h index 9619a1e..0fe3633 100644 --- a/lib/curl_setup.h +++ b/lib/curl_setup.h @@ -467,8 +467,8 @@ # ifdef __minix /* Minix 3 versions up to at least 3.1.3 are missing these prototypes */ - extern char * strtok_r(char *s, const char *delim, char **last); - extern struct tm * gmtime_r(const time_t * const timep, struct tm *tmp); + extern char *strtok_r(char *s, const char *delim, char **last); + extern struct tm *gmtime_r(const time_t * const timep, struct tm *tmp); # endif # define DIR_CHAR "/" diff --git a/lib/curl_threads.c b/lib/curl_threads.c index c98d8bb..a78eff5 100644 --- a/lib/curl_threads.c +++ b/lib/curl_threads.c @@ -59,7 +59,7 @@ static void *curl_thread_create_thunk(void *arg) return 0; } -curl_thread_t Curl_thread_create(unsigned int (*func) (void*), void *arg) +curl_thread_t Curl_thread_create(unsigned int (*func) (void *), void *arg) { curl_thread_t t = malloc(sizeof(pthread_t)); struct curl_actual_call *ac = malloc(sizeof(struct curl_actual_call)); @@ -100,7 +100,8 @@ int Curl_thread_join(curl_thread_t *hnd) #elif defined(USE_THREADS_WIN32) -curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void*), +/* !checksrc! disable SPACEBEFOREPAREN 1 */ +curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void *), void *arg) { #ifdef _WIN32_WCE diff --git a/lib/curl_threads.h b/lib/curl_threads.h index 8cbac63..9e0d14a 100644 --- a/lib/curl_threads.h +++ b/lib/curl_threads.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -50,7 +50,8 @@ #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) -curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void*), +/* !checksrc! disable SPACEBEFOREPAREN 1 */ +curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void *), void *arg); void Curl_thread_destroy(curl_thread_t hnd); diff --git a/lib/easy.c b/lib/easy.c index eee1061..1242369 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -927,6 +927,8 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) Curl_convert_setup(outcurl); + Curl_initinfo(outcurl); + outcurl->magic = CURLEASY_MAGIC_NUMBER; /* we reach this point and thus we are OK */ diff --git a/lib/escape.c b/lib/escape.c index 6657007..9c811b8 100644 --- a/lib/escape.c +++ b/lib/escape.c @@ -31,6 +31,7 @@ #include "warnless.h" #include "non-ascii.h" #include "escape.h" +#include "strdup.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" @@ -42,7 +43,7 @@ */ static bool Curl_isunreserved(unsigned char in) { - switch (in) { + switch(in) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'a': case 'b': case 'c': case 'd': case 'e': @@ -109,11 +110,9 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string, newlen += 2; /* the size grows with two, since this'll become a %XX */ if(newlen > alloc) { alloc *= 2; - testing_ptr = realloc(ns, alloc); - if(!testing_ptr) { - free(ns); + testing_ptr = Curl_saferealloc(ns, alloc); + if(!testing_ptr) return NULL; - } else { ns = testing_ptr; } diff --git a/lib/file.c b/lib/file.c index 272289e..3dbc0f2 100644 --- a/lib/file.c +++ b/lib/file.c @@ -313,7 +313,7 @@ static CURLcode file_upload(struct connectdata *conn) curl_off_t bytecount = 0; struct timeval now = Curl_tvnow(); struct_stat file_stat; - const char* buf2; + const char *buf2; /* * Since FILE: doesn't do the full init, we need to provide some extra diff --git a/lib/formdata.c b/lib/formdata.c index 785f1a6..abd2da0 100644 --- a/lib/formdata.c +++ b/lib/formdata.c @@ -36,6 +36,7 @@ #include "strcase.h" #include "sendf.h" #include "strdup.h" +#include "rand.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" @@ -80,7 +81,7 @@ AddHttpPost(char *name, size_t namelength, char *buffer, size_t bufferlength, char *contenttype, long flags, - struct curl_slist* contentHeader, + struct curl_slist *contentHeader, char *showfilename, char *userp, struct curl_httppost *parent_post, struct curl_httppost **httppost, @@ -315,7 +316,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, break; } - switch (option) { + switch(option) { case CURLFORM_ARRAY: if(array_state) /* we don't support an array from within an array */ @@ -547,9 +548,9 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, { /* this "cast increases required alignment of target type" but we consider it OK anyway */ - struct curl_slist* list = array_state? - (struct curl_slist*)(void*)array_value: - va_arg(params, struct curl_slist*); + struct curl_slist *list = array_state? + (struct curl_slist *)(void *)array_value: + va_arg(params, struct curl_slist *); if(current_form->contentheader) return_value = CURL_FORMADD_OPTION_TWICE; @@ -761,8 +762,8 @@ CURLFORMcode curl_formadd(struct curl_httppost **httppost, * and CD/DVD images should be either a STREAM_LF format or a fixed format. * */ -curl_off_t VmsRealFileSize(const char * name, - const struct_stat * stat_buf) +curl_off_t VmsRealFileSize(const char *name, + const struct_stat *stat_buf) { char buffer[8192]; curl_off_t count; @@ -791,8 +792,8 @@ curl_off_t VmsRealFileSize(const char * name, * if not to call a routine to get the correct size. * */ -static curl_off_t VmsSpecialSize(const char * name, - const struct_stat * stat_buf) +static curl_off_t VmsSpecialSize(const char *name, + const struct_stat *stat_buf) { switch(stat_buf->st_fab_rfm) { case FAB$C_VAR: @@ -948,8 +949,8 @@ void Curl_formclean(struct FormData **form_ptr) if(form->type <= FORM_CONTENT) free(form->line); /* free the line */ free(form); /* free the struct */ - - } while((form = next) != NULL); /* continue */ + form = next; + } while(form); /* continue */ *form_ptr = NULL; } @@ -1030,8 +1031,8 @@ void curl_formfree(struct curl_httppost *form) free(form->contenttype); /* free the content type */ free(form->showfilename); /* free the faked file name */ free(form); /* free the struct */ - - } while((form = next) != NULL); /* continue */ + form = next; + } while(form); /* continue */ } #ifndef HAVE_BASENAME @@ -1166,7 +1167,7 @@ CURLcode Curl_getformdata(struct Curl_easy *data, curl_off_t size = 0; /* support potentially ENORMOUS formposts */ char *boundary; char *fileboundary = NULL; - struct curl_slist* curList; + struct curl_slist *curList; *finalform = NULL; /* default form is empty */ @@ -1373,8 +1374,8 @@ CURLcode Curl_getformdata(struct Curl_easy *data, if(result) break; } - - } while((post = post->next) != NULL); /* for each field */ + post = post->next; + } while(post); /* for each field */ /* end-boundary for everything */ if(!result) @@ -1426,13 +1427,14 @@ int Curl_FormInit(struct Form *form, struct FormData *formdata) * */ # define fopen_read vmsfopenread -static FILE * vmsfopenread(const char *file, const char *mode) { +static FILE * vmsfopenread(const char *file, const char *mode) +{ struct_stat statbuf; int result; result = stat(file, &statbuf); - switch (statbuf.st_fab_rfm) { + switch(statbuf.st_fab_rfm) { case FAB$C_VAR: case FAB$C_VFC: case FAB$C_STMCR: @@ -1569,8 +1571,12 @@ static char *formboundary(struct Curl_easy *data) { /* 24 dashes and 16 hexadecimal digits makes 64 bit (18446744073709551615) combinations */ - return aprintf("------------------------%08x%08x", - Curl_rand(data), Curl_rand(data)); + unsigned int rnd[2]; + CURLcode result = Curl_rand(data, &rnd[0], 2); + if(result) + return NULL; + + return aprintf("------------------------%08x%08x", rnd[0], rnd[1]); } #else /* CURL_DISABLE_HTTP */ diff --git a/lib/formdata.h b/lib/formdata.h index 200470b..69629f6 100644 --- a/lib/formdata.h +++ b/lib/formdata.h @@ -65,7 +65,7 @@ typedef struct FormInfo { file name will be used */ bool showfilename_alloc; char *userp; /* pointer for the read callback */ - struct curl_slist* contentheader; + struct curl_slist *contentheader; struct FormInfo *more; } FormInfo; diff --git a/lib/ftp.c b/lib/ftp.c index b231731..fd77a5a 100644 --- a/lib/ftp.c +++ b/lib/ftp.c @@ -384,10 +384,10 @@ static CURLcode AcceptServerConnect(struct connectdata *conn) * Curl_pgrsTime(..., TIMER_STARTACCEPT); * */ -static long ftp_timeleft_accept(struct Curl_easy *data) +static time_t ftp_timeleft_accept(struct Curl_easy *data) { - long timeout_ms = DEFAULT_ACCEPT_TIMEOUT; - long other; + time_t timeout_ms = DEFAULT_ACCEPT_TIMEOUT; + time_t other; struct timeval now; if(data->set.accepttimeout > 0) @@ -430,7 +430,7 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received) struct ftp_conn *ftpc = &conn->proto.ftpc; struct pingpong *pp = &ftpc->pp; int result; - long timeout_ms; + time_t timeout_ms; ssize_t nread; int ftpcode; @@ -455,7 +455,7 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received) result = Curl_socket_check(ctrl_sock, data_sock, CURL_SOCKET_BAD, 0); /* see if the connection request is already here */ - switch (result) { + switch(result) { case -1: /* error */ /* let's die here */ failf(data, "Error while waiting for server connect"); @@ -499,7 +499,7 @@ static CURLcode InitiateTransfer(struct connectdata *conn) struct FTP *ftp = data->req.protop; CURLcode result = CURLE_OK; - if(conn->ssl[SECONDARYSOCKET].use) { + if(conn->bits.ftp_use_data_ssl) { /* since we only have a plaintext TCP connection here, we must now * do the TLS stuff */ infof(data, "Doing the SSL/TLS handshake on the data stream\n"); @@ -547,7 +547,7 @@ static CURLcode InitiateTransfer(struct connectdata *conn) static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected) { struct Curl_easy *data = conn->data; - long timeout_ms; + time_t timeout_ms; CURLcode result = CURLE_OK; *connected = FALSE; @@ -687,8 +687,8 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */ * line in a response or continue reading. */ curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; - long timeout; /* timeout in milliseconds */ - long interval_ms; + time_t timeout; /* timeout in milliseconds */ + time_t interval_ms; struct Curl_easy *data = conn->data; CURLcode result = CURLE_OK; struct ftp_conn *ftpc = &conn->proto.ftpc; @@ -740,8 +740,8 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */ * wait for more data anyway. */ } - else { - switch (SOCKET_READABLE(sockfd, interval_ms)) { + else if(!Curl_conn_data_pending(conn, FIRSTSOCKET)) { + switch(SOCKET_READABLE(sockfd, interval_ms)) { case -1: /* select() error, stop reading */ failf(data, "FTP response aborted due to select/poll error: %d", SOCKERRNO); @@ -1035,7 +1035,8 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, if(*string_ftpport == '[') { /* [ipv6]:port(-range) */ ip_start = string_ftpport + 1; - if((ip_end = strchr(string_ftpport, ']')) != NULL) + ip_end = strchr(string_ftpport, ']'); + if(ip_end) strncpy(addr, ip_start, ip_end - ip_start); } else @@ -1043,30 +1044,35 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, if(*string_ftpport == ':') { /* :port */ ip_end = string_ftpport; - } - else if((ip_end = strchr(string_ftpport, ':')) != NULL) { - /* either ipv6 or (ipv4|domain|interface):port(-range) */ -#ifdef ENABLE_IPV6 - if(Curl_inet_pton(AF_INET6, string_ftpport, sa6) == 1) { - /* ipv6 */ - port_min = port_max = 0; - strcpy(addr, string_ftpport); - ip_end = NULL; /* this got no port ! */ } - else + else { + ip_end = strchr(string_ftpport, ':'); + if(ip_end) { + /* either ipv6 or (ipv4|domain|interface):port(-range) */ +#ifdef ENABLE_IPV6 + if(Curl_inet_pton(AF_INET6, string_ftpport, sa6) == 1) { + /* ipv6 */ + port_min = port_max = 0; + strcpy(addr, string_ftpport); + ip_end = NULL; /* this got no port ! */ + } + else #endif - /* (ipv4|domain|interface):port(-range) */ - strncpy(addr, string_ftpport, ip_end - ip_start); - } - else - /* ipv4|interface */ - strcpy(addr, string_ftpport); + /* (ipv4|domain|interface):port(-range) */ + strncpy(addr, string_ftpport, ip_end - ip_start); + } + else + /* ipv4|interface */ + strcpy(addr, string_ftpport); + } /* parse the port */ if(ip_end != NULL) { - if((port_start = strchr(ip_end, ':')) != NULL) { + port_start = strchr(ip_end, ':'); + if(port_start) { port_min = curlx_ultous(strtoul(port_start+1, NULL, 10)); - if((port_sep = strchr(port_start, '-')) != NULL) { + port_sep = strchr(port_start, '-'); + if(port_sep) { port_max = curlx_ultous(strtoul(port_sep + 1, NULL, 10)); } else @@ -1850,84 +1856,6 @@ static CURLcode ftp_epsv_disable(struct connectdata *conn) return result; } -/* - * Perform the necessary magic that needs to be done once the TCP connection - * to the proxy has completed. - */ -static CURLcode proxy_magic(struct connectdata *conn, - char *newhost, unsigned short newport, - bool *magicdone) -{ - CURLcode result = CURLE_OK; - struct Curl_easy *data = conn->data; - -#if defined(CURL_DISABLE_PROXY) - (void) newhost; - (void) newport; -#endif - - *magicdone = FALSE; - - switch(conn->proxytype) { - case CURLPROXY_SOCKS5: - case CURLPROXY_SOCKS5_HOSTNAME: - result = Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, newhost, - newport, SECONDARYSOCKET, conn); - *magicdone = TRUE; - break; - case CURLPROXY_SOCKS4: - result = Curl_SOCKS4(conn->proxyuser, newhost, newport, - SECONDARYSOCKET, conn, FALSE); - *magicdone = TRUE; - break; - case CURLPROXY_SOCKS4A: - result = Curl_SOCKS4(conn->proxyuser, newhost, newport, - SECONDARYSOCKET, conn, TRUE); - *magicdone = TRUE; - break; - case CURLPROXY_HTTP: - case CURLPROXY_HTTP_1_0: - /* do nothing here. handled later. */ - break; - default: - failf(data, "unknown proxytype option given"); - result = CURLE_COULDNT_CONNECT; - break; - } - - if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { - /* BLOCKING */ - /* We want "seamless" FTP operations through HTTP proxy tunnel */ - - /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the - * member conn->proto.http; we want FTP through HTTP and we have to - * change the member temporarily for connecting to the HTTP proxy. After - * Curl_proxyCONNECT we have to set back the member to the original - * struct FTP pointer - */ - struct HTTP http_proxy; - struct FTP *ftp_save = data->req.protop; - memset(&http_proxy, 0, sizeof(http_proxy)); - data->req.protop = &http_proxy; - - result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport, TRUE); - - data->req.protop = ftp_save; - - if(result) - return result; - - if(conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE) { - /* the CONNECT procedure is not complete, the tunnel is not yet up */ - state(conn, FTP_STOP); /* this phase is completed */ - return result; - } - else - *magicdone = TRUE; - } - - return result; -} static char *control_address(struct connectdata *conn) { @@ -1935,11 +1863,7 @@ static char *control_address(struct connectdata *conn) If a proxy tunnel is used, returns the original host name instead, because the effective control connection address is the proxy address, not the ftp host. */ - if(conn->bits.tunnel_proxy || - conn->proxytype == CURLPROXY_SOCKS5 || - conn->proxytype == CURLPROXY_SOCKS5_HOSTNAME || - conn->proxytype == CURLPROXY_SOCKS4 || - conn->proxytype == CURLPROXY_SOCKS4A) + if(conn->bits.tunnel_proxy || conn->bits.socksproxy) return conn->host.name; return conn->ip_addr_str; @@ -2063,7 +1987,9 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, * here. We don't want to rely on a former host lookup that might've * expired now, instead we remake the lookup here and now! */ - rc = Curl_resolv(conn, conn->proxy.name, (int)conn->port, &addr); + const char * const host_name = conn->bits.socksproxy ? + conn->socks_proxy.host.name : conn->http_proxy.host.name; + rc = Curl_resolv(conn, host_name, (int)conn->port, &addr); if(rc == CURLRESOLV_PENDING) /* BLOCKING, ignores the return code but 'addr' will be NULL in case of failure */ @@ -2073,8 +1999,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, (unsigned short)conn->port; /* we connect to the proxy's port */ if(!addr) { - failf(data, "Can't resolve proxy host %s:%hu", - conn->proxy.name, connectport); + failf(data, "Can't resolve proxy host %s:%hu", host_name, connectport); return CURLE_FTP_CANT_GET_HOST; } } @@ -2115,6 +2040,10 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, /* this just dumps information about this second connection */ ftp_pasv_verbose(conn, addr->addr, ftpc->newhost, connectport); + Curl_safefree(conn->secondaryhostname); + conn->secondaryhostname = strdup(ftpc->newhost); + conn->secondary_port = ftpc->newport; + Curl_resolv_unlock(data, addr); /* we're done using this address */ conn->bits.do_more = TRUE; state(conn, FTP_STOP); /* this phase is completed */ @@ -2763,7 +2692,10 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) } #endif - if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) { + if(data->set.use_ssl && + (!conn->ssl[FIRSTSOCKET].use || + (conn->bits.proxy_ssl_connected[FIRSTSOCKET] && + !conn->proxy_ssl[FIRSTSOCKET].use))) { /* We don't have a SSL/TLS connection yet, but FTPS is requested. Try a FTPS connection now */ @@ -2808,7 +2740,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) /* Curl_ssl_connect is BLOCKING */ result = Curl_ssl_connect(conn, FIRSTSOCKET); if(!result) { - conn->ssl[SECONDARYSOCKET].use = FALSE; /* clear-text data */ + conn->bits.ftp_use_data_ssl = FALSE; /* clear-text data */ result = ftp_state_user(conn); } } @@ -2850,7 +2782,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) case FTP_PROT: if(ftpcode/100 == 2) /* We have enabled SSL for the data connection! */ - conn->ssl[SECONDARYSOCKET].use = + conn->bits.ftp_use_data_ssl = (data->set.use_ssl != CURLUSESSL_CONTROL) ? TRUE : FALSE; /* FTP servers typically responds with 500 if they decide to reject our 'P' request */ @@ -3250,7 +3182,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status, ssize_t nread; int ftpcode; CURLcode result = CURLE_OK; - char *path; + char *path = NULL; const char *path_to_use = data->state.path; if(!ftp) @@ -3666,10 +3598,6 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep) /* Ready to do more? */ if(connected) { DEBUGF(infof(data, "DO-MORE connected phase starts\n")); - if(conn->bits.proxy) { - infof(data, "Connection to proxy confirmed\n"); - result = proxy_magic(conn, ftpc->newhost, ftpc->newport, &connected); - } } else { if(result && (ftpc->count1 == 0)) { @@ -3681,6 +3609,18 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep) } } + result = Curl_proxy_connect(conn, SECONDARYSOCKET); + if(result) + return result; + + if(CONNECT_SECONDARYSOCKET_PROXY_SSL()) + return result; + + if(conn->bits.tunnel_proxy && conn->bits.httpproxy && + conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE) + return result; + + if(ftpc->state) { /* already in a state so skip the intial commands. They are only done to kickstart the do_more state */ @@ -3939,7 +3879,7 @@ static CURLcode wc_statemach(struct connectdata *conn) struct WildcardData * const wildcard = &(conn->data->wildcard); CURLcode result = CURLE_OK; - switch (wildcard->state) { + switch(wildcard->state) { case CURLWC_INIT: result = init_wc_data(conn); if(wildcard->state == CURLWC_CLEAN) @@ -4246,8 +4186,8 @@ CURLcode ftp_parse_url_path(struct connectdata *conn) const char *cur_pos; const char *filename = NULL; - cur_pos = path_to_use; /* current position in path. point at the begin - of next path component */ + cur_pos = path_to_use; /* current position in path. point at the begin of + next path component */ ftpc->ctl_valid = FALSE; ftpc->cwdfail = FALSE; @@ -4567,7 +4507,7 @@ static CURLcode ftp_setup_connection(struct connectdata *conn) command = Curl_raw_toupper(type[6]); conn->bits.type_set = TRUE; - switch (command) { + switch(command) { case 'A': /* ASCII mode */ data->set.prefer_ascii = TRUE; break; diff --git a/lib/ftp.h b/lib/ftp.h index dbd8567..3bbf262 100644 --- a/lib/ftp.h +++ b/lib/ftp.h @@ -143,7 +143,7 @@ struct ftp_conn { ftpstate state_saved; /* transfer type saved to be reloaded after data connection is established */ curl_off_t retr_size_saved; /* Size of retrieved file saved */ - char * server_os; /* The target server operating system. */ + char *server_os; /* The target server operating system. */ curl_off_t known_filesize; /* file size is different from -1, if wildcard LIST parsing was done and wc_statemach set it */ diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c index 747dbba..f94b31b 100644 --- a/lib/ftplistparser.c +++ b/lib/ftplistparser.c @@ -396,9 +396,9 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, } } - switch (parser->os_type) { + switch(parser->os_type) { case OS_TYPE_UNIX: - switch (parser->state.UNIX.main) { + switch(parser->state.UNIX.main) { case PL_UNIX_TOTALSIZE: switch(parser->state.UNIX.sub.total_dirsize) { case PL_UNIX_TOTALSIZE_INIT: @@ -447,7 +447,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, } break; case PL_UNIX_FILETYPE: - switch (c) { + switch(c) { case '-': finfo->filetype = CURLFILETYPE_FILE; break; @@ -967,7 +967,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, } break; case PL_WINNT_FILENAME: - switch (parser->state.NT.sub.filename) { + switch(parser->state.NT.sub.filename) { case PL_WINNT_FILENAME_PRESPACE: if(c != ' ') { parser->item_offset = finfo->b_used -1; diff --git a/lib/getinfo.c b/lib/getinfo.c index 9641d79..a1ce505 100644 --- a/lib/getinfo.c +++ b/lib/getinfo.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -36,8 +36,11 @@ #include "memdebug.h" /* - * This is supposed to be called in the beginning of a perform() session and - * in curl_easy_reset() and should reset all session-info variables. + * Initialize statistical and informational data. + * + * This function is called in curl_easy_reset, curl_easy_duphandle and at the + * beginning of a perform session. It must reset the session-info variables, + * in particular all variables in struct PureInfo. */ CURLcode Curl_initinfo(struct Curl_easy *data) { @@ -75,6 +78,9 @@ CURLcode Curl_initinfo(struct Curl_easy *data) info->conn_primary_port = 0; info->conn_local_port = 0; + info->conn_scheme = 0; + info->conn_protocol = 0; + #ifdef USE_SSL Curl_ssl_free_certinfo(data); #endif @@ -83,7 +89,7 @@ CURLcode Curl_initinfo(struct Curl_easy *data) } static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info, - char **param_charp) + const char **param_charp) { switch(info) { case CURLINFO_EFFECTIVE_URL: @@ -120,6 +126,9 @@ static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info, case CURLINFO_RTSP_SESSION_ID: *param_charp = data->set.str[STRING_RTSP_SESSION_ID]; break; + case CURLINFO_SCHEME: + *param_charp = data->info.conn_scheme; + break; default: return CURLE_UNKNOWN_OPTION; @@ -157,6 +166,9 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info, case CURLINFO_SSL_VERIFYRESULT: *param_longp = data->set.ssl.certverifyresult; break; + case CURLINFO_PROXY_SSL_VERIFYRESULT: + *param_longp = data->set.proxy_ssl.certverifyresult; + break; case CURLINFO_REDIRECT_COUNT: *param_longp = data->set.followlocation; break; @@ -208,7 +220,7 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info, *param_longp = data->state.rtsp_CSeq_recv; break; case CURLINFO_HTTP_VERSION: - switch (data->info.httpversion) { + switch(data->info.httpversion) { case 10: *param_longp = CURL_HTTP_VERSION_1_0; break; @@ -223,6 +235,9 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info, break; } break; + case CURLINFO_PROTOCOL: + *param_longp = data->info.conn_protocol; + break; default: return CURLE_UNKNOWN_OPTION; @@ -379,7 +394,7 @@ CURLcode Curl_getinfo(struct Curl_easy *data, CURLINFO info, ...) va_list arg; long *param_longp = NULL; double *param_doublep = NULL; - char **param_charp = NULL; + const char **param_charp = NULL; struct curl_slist **param_slistp = NULL; curl_socket_t *param_socketp = NULL; int type; @@ -393,7 +408,7 @@ CURLcode Curl_getinfo(struct Curl_easy *data, CURLINFO info, ...) type = CURLINFO_TYPEMASK & (int)info; switch(type) { case CURLINFO_STRING: - param_charp = va_arg(arg, char **); + param_charp = va_arg(arg, const char **); if(param_charp) result = getinfo_char(data, info, param_charp); break; diff --git a/lib/hash.c b/lib/hash.c index 937381b..0655042 100644 --- a/lib/hash.c +++ b/lib/hash.c @@ -135,7 +135,7 @@ Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p) { struct curl_hash_element *he; struct curl_llist_element *le; - struct curl_llist *l = FETCH_LIST (h, key, key_len); + struct curl_llist *l = FETCH_LIST(h, key, key_len); for(le = l->head; le; le = le->next) { he = (struct curl_hash_element *) le->ptr; @@ -291,9 +291,9 @@ Curl_hash_clean_with_criterium(struct curl_hash *h, void *user, } } -size_t Curl_hash_str(void* key, size_t key_length, size_t slots_num) +size_t Curl_hash_str(void *key, size_t key_length, size_t slots_num) { - const char* key_str = (const char *) key; + const char *key_str = (const char *) key; const char *end = key_str + key_length; unsigned long h = 5381; diff --git a/lib/hash.h b/lib/hash.h index 57a17f0..a5a6cac 100644 --- a/lib/hash.h +++ b/lib/hash.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -29,16 +29,16 @@ #include "llist.h" /* Hash function prototype */ -typedef size_t (*hash_function) (void* key, +typedef size_t (*hash_function) (void *key, size_t key_length, size_t slots_num); /* Comparator function prototype. Compares two keys. */ -typedef size_t (*comp_function) (void* key1, +typedef size_t (*comp_function) (void *key1, size_t key1_len, - void*key2, + void *key2, size_t key2_len); typedef void (*curl_hash_dtor)(void *); @@ -76,7 +76,7 @@ int Curl_hash_init(struct curl_hash *h, void *Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p); int Curl_hash_delete(struct curl_hash *h, void *key, size_t key_len); -void *Curl_hash_pick(struct curl_hash *, void * key, size_t key_len); +void *Curl_hash_pick(struct curl_hash *, void *key, size_t key_len); void Curl_hash_apply(struct curl_hash *h, void *user, void (*cb)(void *user, void *ptr)); int Curl_hash_count(struct curl_hash *h); @@ -84,10 +84,9 @@ void Curl_hash_destroy(struct curl_hash *h); void Curl_hash_clean(struct curl_hash *h); void Curl_hash_clean_with_criterium(struct curl_hash *h, void *user, int (*comp)(void *, void *)); -size_t Curl_hash_str(void* key, size_t key_length, size_t slots_num); -size_t Curl_str_key_compare(void*k1, size_t key1_len, void*k2, +size_t Curl_hash_str(void *key, size_t key_length, size_t slots_num); +size_t Curl_str_key_compare(void *k1, size_t key1_len, void *k2, size_t key2_len); - void Curl_hash_start_iterate(struct curl_hash *hash, struct curl_hash_iterator *iter); struct curl_hash_element * diff --git a/lib/hmac.c b/lib/hmac.c index 3df4715..dae9505 100644 --- a/lib/hmac.c +++ b/lib/hmac.c @@ -49,12 +49,12 @@ static const unsigned char hmac_opad = 0x5C; HMAC_context * Curl_HMAC_init(const HMAC_params * hashparams, - const unsigned char * key, + const unsigned char *key, unsigned int keylen) { size_t i; - HMAC_context * ctxt; - unsigned char * hkey; + HMAC_context *ctxt; + unsigned char *hkey; unsigned char b; /* Create HMAC context. */ @@ -101,7 +101,7 @@ Curl_HMAC_init(const HMAC_params * hashparams, } int Curl_HMAC_update(HMAC_context * ctxt, - const unsigned char * data, + const unsigned char *data, unsigned int len) { /* Update first hash calculation. */ @@ -110,7 +110,7 @@ int Curl_HMAC_update(HMAC_context * ctxt, } -int Curl_HMAC_final(HMAC_context * ctxt, unsigned char * result) +int Curl_HMAC_final(HMAC_context *ctxt, unsigned char *result) { const HMAC_params * hashparams = ctxt->hmac_hash; diff --git a/lib/hostcheck.c b/lib/hostcheck.c index f545254..cbd0893 100644 --- a/lib/hostcheck.c +++ b/lib/hostcheck.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -22,7 +22,10 @@ #include "curl_setup.h" -#if defined(USE_OPENSSL) || defined(USE_AXTLS) || defined(USE_GSKIT) +#if defined(USE_OPENSSL) \ + || defined(USE_AXTLS) \ + || defined(USE_GSKIT) \ + || (defined(USE_SCHANNEL) && defined(_WIN32_WCE)) /* these backends use functions from this file */ #ifdef HAVE_NETINET_IN_H @@ -144,4 +147,4 @@ int Curl_cert_hostcheck(const char *match_pattern, const char *hostname) return res; } -#endif /* OPENSSL or AXTLS or GSKIT */ +#endif /* OPENSSL, AXTLS, GSKIT or schannel+wince */ diff --git a/lib/hostip.c b/lib/hostip.c index 24a922e..fa4bad9 100644 --- a/lib/hostip.c +++ b/lib/hostip.c @@ -172,7 +172,7 @@ Curl_printable_address(const Curl_addrinfo *ai, char *buf, size_t bufsize) const struct in6_addr *ipaddr6; #endif - switch (ai->ai_family) { + switch(ai->ai_family) { case AF_INET: sa4 = (const void *)ai->ai_addr; ipaddr4 = &sa4->sin_addr; @@ -568,7 +568,7 @@ int Curl_resolv_timeout(struct connectdata *conn, const char *hostname, int port, struct Curl_dns_entry **entry, - long timeoutms) + time_t timeoutms) { #ifdef USE_ALARM_TIMEOUT #ifdef HAVE_SIGACTION diff --git a/lib/hostip.h b/lib/hostip.h index 9098ee3..1dc4079 100644 --- a/lib/hostip.h +++ b/lib/hostip.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -87,7 +87,7 @@ int Curl_resolv(struct connectdata *conn, const char *hostname, int port, struct Curl_dns_entry **dnsentry); int Curl_resolv_timeout(struct connectdata *conn, const char *hostname, int port, struct Curl_dns_entry **dnsentry, - long timeoutms); + time_t timeoutms); #ifdef CURLRES_IPV6 /* @@ -131,7 +131,7 @@ int Curl_mk_dnscache(struct curl_hash *hash); void Curl_hostcache_prune(struct Curl_easy *data); /* Return # of adresses in a Curl_addrinfo struct */ -int Curl_num_addresses (const Curl_addrinfo *addr); +int Curl_num_addresses(const Curl_addrinfo *addr); #if defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO) int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa, @@ -143,7 +143,7 @@ int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa, #endif /* IPv4 threadsafe resolve function used for synch and asynch builds */ -Curl_addrinfo *Curl_ipv4_resolve_r(const char * hostname, int port); +Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port); CURLcode Curl_async_resolved(struct connectdata *conn, bool *protocol_connect); diff --git a/lib/hostip4.c b/lib/hostip4.c index 15895d7..e459328 100644 --- a/lib/hostip4.c +++ b/lib/hostip4.c @@ -291,7 +291,7 @@ Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, * gethostbyname() is the preferred one. */ else { - h = gethostbyname((void*)hostname); + h = gethostbyname((void *)hostname); #endif /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */ } diff --git a/lib/http.c b/lib/http.c index e7788e7..4c1c07f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -76,6 +76,7 @@ #include "pipeline.h" #include "http2.h" #include "connect.h" +#include "strdup.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -287,8 +288,8 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy) if(proxy) { userp = &conn->allocptr.proxyuserpwd; - user = conn->proxyuser; - pwd = conn->proxypasswd; + user = conn->http_proxy.user; + pwd = conn->http_proxy.passwd; } else { userp = &conn->allocptr.userpwd; @@ -544,8 +545,8 @@ CURLcode Curl_http_auth_act(struct connectdata *conn) } } if(http_should_fail(conn)) { - failf (data, "The requested URL returned error: %d", - data->req.httpcode); + failf(data, "The requested URL returned error: %d", + data->req.httpcode); result = CURLE_HTTP_RETURNED_ERROR; } @@ -641,7 +642,7 @@ output_auth_headers(struct connectdata *conn, if(auth) { infof(data, "%s auth using %s with user '%s'\n", proxy ? "Proxy" : "Server", auth, - proxy ? (conn->proxyuser ? conn->proxyuser : "") : + proxy ? (conn->http_proxy.user ? conn->http_proxy.user : "") : (conn->user ? conn->user : "")); authstatus->multi = (!authstatus->done) ? TRUE : FALSE; } @@ -839,9 +840,11 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy, auth += strlen("NTLM"); while(*auth && ISSPACE(*auth)) auth++; - if(*auth) - if((conn->challenge_header = strdup(auth)) == NULL) + if(*auth) { + conn->challenge_header = strdup(auth); + if(!conn->challenge_header) return CURLE_OUT_OF_MEMORY; + } } } #endif @@ -1098,7 +1101,9 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in, return result; } - if((conn->handler->flags & PROTOPT_SSL) && conn->httpversion != 20) { + if((conn->handler->flags & PROTOPT_SSL || + conn->http_proxy.proxytype == CURLPROXY_HTTPS) + && conn->httpversion != 20) { /* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk when we speak HTTPS, as if only a fraction of it is sent now, this data needs to fit into the normal read-callback buffer later on and that @@ -1255,14 +1260,13 @@ CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size) if(in->buffer) /* we have a buffer, enlarge the existing one */ - new_rb = realloc(in->buffer, new_size); + new_rb = Curl_saferealloc(in->buffer, new_size); else /* create a new buffer */ new_rb = malloc(new_size); if(!new_rb) { /* If we failed, we cleanup the whole buffer and return error */ - Curl_safefree(in->buffer); free(in); return CURLE_OUT_OF_MEMORY; } @@ -1350,10 +1354,13 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) connkeep(conn, "HTTP default"); /* the CONNECT procedure might not have been completed */ - result = Curl_proxy_connect(conn); + result = Curl_proxy_connect(conn, FIRSTSOCKET); if(result) return result; + if(CONNECT_FIRSTSOCKET_PROXY_SSL()) + return CURLE_OK; /* wait for HTTPS proxy SSL initialization to complete */ + if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT) /* nothing else to do except wait right now - we're not done here. */ return CURLE_OK; @@ -1396,50 +1403,16 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done) return result; } -#endif -#if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \ - defined(USE_DARWINSSL) || defined(USE_POLARSSL) || defined(USE_NSS) || \ - defined(USE_MBEDTLS) -/* This function is for OpenSSL, GnuTLS, darwinssl, schannel and polarssl only. - It should be made to query the generic SSL layer instead. */ static int https_getsock(struct connectdata *conn, curl_socket_t *socks, int numsocks) { - if(conn->handler->flags & PROTOPT_SSL) { - struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; - - if(!numsocks) - return GETSOCK_BLANK; - - if(connssl->connecting_state == ssl_connect_2_writing) { - /* write mode */ - socks[0] = conn->sock[FIRSTSOCKET]; - return GETSOCK_WRITESOCK(0); - } - else if(connssl->connecting_state == ssl_connect_2_reading) { - /* read mode */ - socks[0] = conn->sock[FIRSTSOCKET]; - return GETSOCK_READSOCK(0); - } - } - - return CURLE_OK; -} -#else -#ifdef USE_SSL -static int https_getsock(struct connectdata *conn, - curl_socket_t *socks, - int numsocks) -{ - (void)conn; - (void)socks; - (void)numsocks; + if(conn->handler->flags & PROTOPT_SSL) + return Curl_ssl_getsock(conn, socks, numsocks); return GETSOCK_BLANK; } #endif /* USE_SSL */ -#endif /* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL */ /* * Curl_http_done() gets called after a single HTTP request has been @@ -2092,7 +2065,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) /* when doing ftp, append ;type= if not present */ char *type = strstr(ppath, ";type="); if(type && type[6] && type[7] == 0) { - switch (Curl_raw_toupper(type[6])) { + switch(Curl_raw_toupper(type[6])) { case 'A': case 'D': case 'I': @@ -2328,7 +2301,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done) * Free proxyuserpwd for Negotiate/NTLM. Cannot reuse as it is associated * with the connection and shouldn't be repeated over it either. */ - switch (data->state.authproxy.picked) { + switch(data->state.authproxy.picked) { case CURLAUTH_NEGOTIATE: case CURLAUTH_NTLM: case CURLAUTH_NTLM_WB: @@ -2782,7 +2755,7 @@ checkhttpprefix(struct Curl_easy *data, /* convert from the network encoding using a scratch area */ char *scratch = strdup(s); if(NULL == scratch) { - failf (data, "Failed to allocate memory for conversion!"); + failf(data, "Failed to allocate memory for conversion!"); return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */ } if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) { @@ -2820,7 +2793,7 @@ checkrtspprefix(struct Curl_easy *data, /* convert from the network encoding using a scratch area */ char *scratch = strdup(s); if(NULL == scratch) { - failf (data, "Failed to allocate memory for conversion!"); + failf(data, "Failed to allocate memory for conversion!"); return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */ } if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) { @@ -2872,8 +2845,8 @@ static CURLcode header_append(struct Curl_easy *data, /* The reason to have a max limit for this is to avoid the risk of a bad server feeding libcurl with a never-ending header that will cause reallocs infinitely */ - failf (data, "Avoided giant realloc for header (max is %d)!", - CURL_MAX_HTTP_HEADER); + failf(data, "Avoided giant realloc for header (max is %d)!", + CURL_MAX_HTTP_HEADER); return CURLE_OUT_OF_MEMORY; } @@ -2881,7 +2854,7 @@ static CURLcode header_append(struct Curl_easy *data, hbufp_index = k->hbufp - data->state.headerbuff; newbuff = realloc(data->state.headerbuff, newsize); if(!newbuff) { - failf (data, "Failed to alloc memory for big header!"); + failf(data, "Failed to alloc memory for big header!"); return CURLE_OUT_OF_MEMORY; } data->state.headersize=newsize; @@ -3122,8 +3095,8 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, * up and return an error. */ if(http_should_fail(conn)) { - failf (data, "The requested URL returned error: %d", - k->httpcode); + failf(data, "The requested URL returned error: %d", + k->httpcode); return CURLE_HTTP_RETURNED_ERROR; } diff --git a/lib/http2.c b/lib/http2.c index cfdb327..4cc17ba 100644 --- a/lib/http2.c +++ b/lib/http2.c @@ -35,7 +35,7 @@ #include "url.h" #include "connect.h" #include "strtoofft.h" - +#include "strdup.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" @@ -59,6 +59,12 @@ #define nghttp2_session_callbacks_set_error_callback(x,y) #endif +#if (NGHTTP2_VERSION_NUM >= 0x010c00) +#define NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE 1 +#endif + +#define HTTP2_HUGE_WINDOW_SIZE (1 << 30) + /* * Curl_http2_init_state() is called when the easy handle is created and * allows for HTTP/2 specific init of state. @@ -223,7 +229,8 @@ int Curl_http2_ver(char *p, size_t len) https://tools.ietf.org/html/rfc7540#page-77 nghttp2_error_code enums are identical. */ -const char *Curl_http2_strerror(uint32_t err) { +const char *Curl_http2_strerror(uint32_t err) +{ #ifndef NGHTTP2_HAS_HTTP2_STRERROR const char *str[] = { "NO_ERROR", /* 0x0 */ @@ -841,10 +848,9 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, stream->push_headers_alloc) { char **headp; stream->push_headers_alloc *= 2; - headp = realloc(stream->push_headers, - stream->push_headers_alloc * sizeof(char *)); + headp = Curl_saferealloc(stream->push_headers, + stream->push_headers_alloc * sizeof(char *)); if(!headp) { - free(stream->push_headers); stream->push_headers = NULL; return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; } @@ -966,7 +972,7 @@ static ssize_t data_source_read_callback(nghttp2_session *session, */ static nghttp2_settings_entry settings[] = { { NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100 }, - { NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, NGHTTP2_INITIAL_WINDOW_SIZE }, + { NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, HTTP2_HUGE_WINDOW_SIZE }, }; #define H2_BUFSIZE 32768 @@ -1572,6 +1578,72 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex, #define HEADER_OVERFLOW(x) \ (x.namelen > (uint16_t)-1 || x.valuelen > (uint16_t)-1 - x.namelen) +/* + * Check header memory for the token "trailers". + * Parse the tokens as separated by comma and surrounded by whitespace. + * Returns TRUE if found or FALSE if not. + */ +static bool contains_trailers(const char *p, size_t len) +{ + const char *end = p + len; + for(;;) { + for(; p != end && (*p == ' ' || *p == '\t'); ++p) + ; + if(p == end || (size_t)(end - p) < sizeof("trailers") - 1) + return FALSE; + if(strncasecompare("trailers", p, sizeof("trailers") - 1)) { + p += sizeof("trailers") - 1; + for(; p != end && (*p == ' ' || *p == '\t'); ++p) + ; + if(p == end || *p == ',') + return TRUE; + } + /* skip to next token */ + for(; p != end && *p != ','; ++p) + ; + if(p == end) + return FALSE; + ++p; + } +} + +typedef enum { + /* Send header to server */ + HEADERINST_FORWARD, + /* Don't send header to server */ + HEADERINST_IGNORE, + /* Discard header, and replace it with "te: trailers" */ + HEADERINST_TE_TRAILERS +} header_instruction; + +/* Decides how to treat given header field. */ +static header_instruction inspect_header(const char *name, size_t namelen, + const char *value, size_t valuelen) { + switch(namelen) { + case 2: + if(!strncasecompare("te", name, namelen)) + return HEADERINST_FORWARD; + + return contains_trailers(value, valuelen) ? + HEADERINST_TE_TRAILERS : HEADERINST_IGNORE; + case 7: + return strncasecompare("upgrade", name, namelen) ? + HEADERINST_IGNORE : HEADERINST_FORWARD; + case 10: + return (strncasecompare("connection", name, namelen) || + strncasecompare("keep-alive", name, namelen)) ? + HEADERINST_IGNORE : HEADERINST_FORWARD; + case 16: + return strncasecompare("proxy-connection", name, namelen) ? + HEADERINST_IGNORE : HEADERINST_FORWARD; + case 17: + return strncasecompare("transfer-encoding", name, namelen) ? + HEADERINST_IGNORE : HEADERINST_FORWARD; + default: + return HEADERINST_FORWARD; + } +} + static ssize_t http2_send(struct connectdata *conn, int sockindex, const void *mem, size_t len, CURLcode *err) { @@ -1587,7 +1659,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, size_t nheader; size_t i; size_t authority_idx; - char *hdbuf = (char*)mem; + char *hdbuf = (char *)mem; char *end, *line_end; nghttp2_data_provider data_prd; int32_t stream_id; @@ -1725,7 +1797,6 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, i = 3; while(i < nheader) { size_t hlen; - int skip = 0; hdbuf = line_end + 2; @@ -1743,12 +1814,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, goto fail; hlen = end - hdbuf; - if(hlen == 10 && strncasecompare("connection", hdbuf, 10)) { - /* skip Connection: headers! */ - skip = 1; - --nheader; - } - else if(hlen == 4 && strncasecompare("host", hdbuf, 4)) { + if(hlen == 4 && strncasecompare("host", hdbuf, 4)) { authority_idx = i; nva[i].name = (unsigned char *)":authority"; nva[i].namelen = strlen((char *)nva[i].name); @@ -1761,16 +1827,28 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex, while(*hdbuf == ' ' || *hdbuf == '\t') ++hdbuf; end = line_end; - if(!skip) { + + switch(inspect_header((const char *)nva[i].name, nva[i].namelen, hdbuf, + end - hdbuf)) { + case HEADERINST_IGNORE: + /* skip header fields prohibited by HTTP/2 specification. */ + --nheader; + continue; + case HEADERINST_TE_TRAILERS: + nva[i].value = (uint8_t*)"trailers"; + nva[i].valuelen = sizeof("trailers") - 1; + break; + default: nva[i].value = (unsigned char *)hdbuf; nva[i].valuelen = (size_t)(end - hdbuf); - nva[i].flags = NGHTTP2_NV_FLAG_NONE; - if(HEADER_OVERFLOW(nva[i])) { - failf(conn->data, "Failed sending HTTP request: Header overflow"); - goto fail; - } - ++i; } + + nva[i].flags = NGHTTP2_NV_FLAG_NONE; + if(HEADER_OVERFLOW(nva[i])) { + failf(conn->data, "Failed sending HTTP request: Header overflow"); + goto fail; + } + ++i; } /* :authority must come before non-pseudo header fields */ @@ -1961,7 +2039,8 @@ CURLcode Curl_http2_switched(struct connectdata *conn, else { /* stream ID is unknown at this point */ stream->stream_id = -1; - rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE, NULL, 0); + rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE, settings, + sizeof(settings) / sizeof(settings[0])); if(rv != 0) { failf(data, "nghttp2_submit_settings() failed: %s(%d)", nghttp2_strerror(rv), rv); @@ -1969,6 +2048,16 @@ CURLcode Curl_http2_switched(struct connectdata *conn, } } +#ifdef NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE + rv = nghttp2_session_set_local_window_size(httpc->h2, NGHTTP2_FLAG_NONE, 0, + HTTP2_HUGE_WINDOW_SIZE); + if(rv != 0) { + failf(data, "nghttp2_session_set_local_window_size() failed: %s(%d)", + nghttp2_strerror(rv), rv); + return CURLE_HTTP2; + } +#endif + /* we are going to copy mem to httpc->inbuf. This is required since mem is part of buffer pointed by stream->mem, and callbacks called by nghttp2_session_mem_recv() will write stream specific @@ -1984,7 +2073,8 @@ CURLcode Curl_http2_switched(struct connectdata *conn, " after upgrade: len=%zu\n", nread); - memcpy(httpc->inbuf, mem, nread); + if(nread) + memcpy(httpc->inbuf, mem, nread); httpc->inbuflen = nread; nproc = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)httpc->inbuf, @@ -2024,6 +2114,82 @@ CURLcode Curl_http2_switched(struct connectdata *conn, return CURLE_OK; } +void Curl_http2_add_child(struct Curl_easy *parent, struct Curl_easy *child, + bool exclusive) +{ + struct Curl_http2_dep **tail; + struct Curl_http2_dep *dep = calloc(1, sizeof(struct Curl_http2_dep)); + dep->data = child; + + if(parent->set.stream_dependents && exclusive) { + struct Curl_http2_dep *node = parent->set.stream_dependents; + while(node) { + node->data->set.stream_depends_on = child; + node = node->next; + } + + tail = &child->set.stream_dependents; + while(*tail) + tail = &(*tail)->next; + + DEBUGASSERT(!*tail); + *tail = parent->set.stream_dependents; + parent->set.stream_dependents = 0; + } + + tail = &parent->set.stream_dependents; + while(*tail) { + (*tail)->data->set.stream_depends_e = FALSE; + tail = &(*tail)->next; + } + + DEBUGASSERT(!*tail); + *tail = dep; + + child->set.stream_depends_on = parent; + child->set.stream_depends_e = exclusive; +} + +void Curl_http2_remove_child(struct Curl_easy *parent, struct Curl_easy *child) +{ + struct Curl_http2_dep *last = 0; + struct Curl_http2_dep *data = parent->set.stream_dependents; + DEBUGASSERT(child->set.stream_depends_on == parent); + + while(data && data->data != child) { + last = data; + data = data->next; + } + + DEBUGASSERT(data); + + if(data) { + if(last) { + last->next = data->next; + } + else { + parent->set.stream_dependents = data->next; + } + free(data); + } + + child->set.stream_depends_on = 0; + child->set.stream_depends_e = FALSE; +} + +void Curl_http2_cleanup_dependencies(struct Curl_easy *data) +{ + while(data->set.stream_dependents) { + struct Curl_easy *tmp = data->set.stream_dependents->data; + Curl_http2_remove_child(data, tmp); + if(data->set.stream_depends_on) + Curl_http2_add_child(data->set.stream_depends_on, tmp, FALSE); + } + + if(data->set.stream_depends_on) + Curl_http2_remove_child(data->set.stream_depends_on, data); +} + #else /* !USE_NGHTTP2 */ /* Satisfy external references even if http2 is not compiled in. */ diff --git a/lib/http2.h b/lib/http2.h index 8917535..f405b3a 100644 --- a/lib/http2.h +++ b/lib/http2.h @@ -53,6 +53,11 @@ void Curl_http2_setup_conn(struct connectdata *conn); void Curl_http2_setup_req(struct Curl_easy *data); void Curl_http2_done(struct connectdata *conn, bool premature); CURLcode Curl_http2_done_sending(struct connectdata *conn); +void Curl_http2_add_child(struct Curl_easy *parent, struct Curl_easy *child, + bool exclusive); +void Curl_http2_remove_child(struct Curl_easy *parent, + struct Curl_easy *child); +void Curl_http2_cleanup_dependencies(struct Curl_easy *data); #else /* USE_NGHTTP2 */ #define Curl_http2_init(x) CURLE_UNSUPPORTED_PROTOCOL #define Curl_http2_send_request(x) CURLE_UNSUPPORTED_PROTOCOL @@ -65,6 +70,9 @@ CURLcode Curl_http2_done_sending(struct connectdata *conn); #define Curl_http2_init_userset(x) #define Curl_http2_done(x,y) #define Curl_http2_done_sending(x) +#define Curl_http2_add_child(x, y, z) +#define Curl_http2_remove_child(x, y) +#define Curl_http2_cleanup_dependencies(x) #endif #endif /* HEADER_CURL_HTTP2_H */ diff --git a/lib/http_chunks.c b/lib/http_chunks.c index ea17109..1bdf697 100644 --- a/lib/http_chunks.c +++ b/lib/http_chunks.c @@ -190,8 +190,8 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, /* Write the data portion available */ #ifdef HAVE_LIBZ - switch (conn->data->set.http_ce_skip? - IDENTITY : data->req.auto_decoding) { + switch(conn->data->set.http_ce_skip? + IDENTITY : data->req.auto_decoding) { case IDENTITY: #endif if(!k->ignorebody) { @@ -219,10 +219,10 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, break; default: - failf (conn->data, - "Unrecognized content encoding type. " - "libcurl understands `identity', `deflate' and `gzip' " - "content encodings."); + failf(conn->data, + "Unrecognized content encoding type. " + "libcurl understands `identity', `deflate' and `gzip' " + "content encodings."); return CHUNKE_BAD_ENCODING; } #endif @@ -360,7 +360,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, const char *Curl_chunked_strerror(CHUNKcode code) { - switch (code) { + switch(code) { default: return "OK"; case CHUNKE_TOO_LONG_HEX: diff --git a/lib/http_digest.c b/lib/http_digest.c index 184d00b..e2d865b 100644 --- a/lib/http_digest.c +++ b/lib/http_digest.c @@ -74,8 +74,8 @@ CURLcode Curl_output_digest(struct connectdata *conn, { CURLcode result; struct Curl_easy *data = conn->data; - unsigned char *path; - char *tmp; + unsigned char *path = NULL; + char *tmp = NULL; char *response; size_t len; bool have_chlg; @@ -95,8 +95,8 @@ CURLcode Curl_output_digest(struct connectdata *conn, if(proxy) { digest = &data->state.proxydigest; allocuserpwd = &conn->allocptr.proxyuserpwd; - userp = conn->proxyuser; - passwdp = conn->proxypasswd; + userp = conn->http_proxy.user; + passwdp = conn->http_proxy.passwd; authp = &data->state.authproxy; } else { @@ -140,12 +140,14 @@ CURLcode Curl_output_digest(struct connectdata *conn, http://www.fngtps.com/2006/09/http-authentication */ - if(authp->iestyle && ((tmp = strchr((char *)uripath, '?')) != NULL)) { - size_t urilen = tmp - (char *)uripath; - - path = (unsigned char *) aprintf("%.*s", urilen, uripath); + if(authp->iestyle) { + tmp = strchr((char *)uripath, '?'); + if(tmp) { + size_t urilen = tmp - (char *)uripath; + path = (unsigned char *) aprintf("%.*s", urilen, uripath); + } } - else + if(!tmp) path = (unsigned char *) strdup((char *) uripath); if(!path) diff --git a/lib/http_negotiate.c b/lib/http_negotiate.c index eb17ed4..51375e8 100644 --- a/lib/http_negotiate.c +++ b/lib/http_negotiate.c @@ -37,6 +37,7 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, const char *header) { + CURLcode result; struct Curl_easy *data = conn->data; size_t len; @@ -50,11 +51,11 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, struct negotiatedata *neg_ctx; if(proxy) { - userp = conn->proxyuser; - passwdp = conn->proxypasswd; + userp = conn->http_proxy.user; + passwdp = conn->http_proxy.passwd; service = data->set.str[STRING_PROXY_SERVICE_NAME] ? data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP"; - host = conn->proxy.name; + host = conn->http_proxy.host.name; neg_ctx = &data->state.proxyneg; } else { @@ -89,8 +90,13 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, } /* Initilise the security context and decode our challenge */ - return Curl_auth_decode_spnego_message(data, userp, passwdp, service, host, - header, neg_ctx); + result = Curl_auth_decode_spnego_message(data, userp, passwdp, service, + host, header, neg_ctx); + + if(result) + Curl_auth_spnego_cleanup(neg_ctx); + + return result; } CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy) diff --git a/lib/http_ntlm.c b/lib/http_ntlm.c index e424040..21c77cd 100644 --- a/lib/http_ntlm.c +++ b/lib/http_ntlm.c @@ -136,8 +136,8 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy) if(proxy) { allocuserpwd = &conn->allocptr.proxyuserpwd; - userp = conn->proxyuser; - passwdp = conn->proxypasswd; + userp = conn->http_proxy.user; + passwdp = conn->http_proxy.passwd; ntlm = &conn->proxyntlm; authp = &conn->data->state.authproxy; } diff --git a/lib/http_proxy.c b/lib/http_proxy.c index 8f5e9b4..e0213f3 100644 --- a/lib/http_proxy.c +++ b/lib/http_proxy.c @@ -35,14 +35,50 @@ #include "non-ascii.h" #include "connect.h" #include "curlx.h" +#include "vtls/vtls.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" #include "memdebug.h" -CURLcode Curl_proxy_connect(struct connectdata *conn) +/* + * Perform SSL initialization for HTTPS proxy. Sets + * proxy_ssl_connected connection bit when complete. Can be + * called multiple times. + */ +static CURLcode https_proxy_connect(struct connectdata *conn, int sockindex) +{ +#ifdef USE_SSL + CURLcode result = CURLE_OK; + DEBUGASSERT(conn->http_proxy.proxytype == CURLPROXY_HTTPS); + if(!conn->bits.proxy_ssl_connected[sockindex]) { + /* perform SSL initialization for this socket */ + result = + Curl_ssl_connect_nonblocking(conn, sockindex, + &conn->bits.proxy_ssl_connected[sockindex]); + if(result) + conn->bits.close = TRUE; /* a failed connection is marked for closure to + prevent (bad) re-use or similar */ + } + return result; +#else + (void) conn; + (void) sockindex; + return CURLE_NOT_BUILT_IN; +#endif +} + +CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex) { + if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) { + const CURLcode result = https_proxy_connect(conn, sockindex); + if(result) + return result; + if(!conn->bits.proxy_ssl_connected[sockindex]) + return result; /* wait for HTTPS proxy SSL initialization to complete */ + } + if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { #ifndef CURL_DISABLE_PROXY /* for [protocol] tunneled through HTTP proxy */ @@ -68,15 +104,20 @@ CURLcode Curl_proxy_connect(struct connectdata *conn) memset(&http_proxy, 0, sizeof(http_proxy)); conn->data->req.protop = &http_proxy; connkeep(conn, "HTTP proxy CONNECT"); - if(conn->bits.conn_to_host) + if(sockindex == SECONDARYSOCKET) + hostname = conn->secondaryhostname; + else if(conn->bits.conn_to_host) hostname = conn->conn_to_host.name; else hostname = conn->host.name; - if(conn->bits.conn_to_port) + + if(sockindex == SECONDARYSOCKET) + remote_port = conn->secondary_port; + else if(conn->bits.conn_to_port) remote_port = conn->conn_to_port; else remote_port = conn->remote_port; - result = Curl_proxyCONNECT(conn, FIRSTSOCKET, hostname, + result = Curl_proxyCONNECT(conn, sockindex, hostname, remote_port, FALSE); conn->data->req.protop = prot_save; if(CURLE_OK != result) @@ -113,7 +154,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, curl_off_t cl=0; bool closeConnection = FALSE; bool chunked_encoding = FALSE; - long check; + time_t check; #define SELECT_OK 0 #define SELECT_ERROR 1 @@ -161,7 +202,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, char *host=(char *)""; const char *proxyconn=""; const char *useragent=""; - const char *http = (conn->proxytype == CURLPROXY_HTTP_1_0) ? + const char *http = (conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ? "1.0" : "1.1"; bool ipv6_ip = conn->bits.ipv6_ip; char *hostheader; @@ -244,7 +285,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, } if(!blocking) { - if(0 == SOCKET_READABLE(tunnelsocket, 0)) + if(!Curl_conn_data_pending(conn, sockindex)) /* return so we'll be called again polling-style */ return CURLE_OK; else { @@ -263,13 +304,22 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, char *ptr; char *line_start; - ptr=data->state.buffer; + ptr = data->state.buffer; line_start = ptr; - nread=0; - perline=0; + nread = 0; + perline = 0; + + while(nread < BUFSIZE && keepon && !error) { + int writetype; - while((nread= &data->state.buffer[BUFSIZE]) { + failf(data, "CONNECT response too large!"); + return CURLE_RECV_ERROR; + } check = Curl_timeleft(data, NULL, TRUE); if(check <= 0) { @@ -278,253 +328,233 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, break; } - /* loop every second at least, less if the timeout is near */ - switch (SOCKET_READABLE(tunnelsocket, check<1000L?check:1000)) { - case -1: /* select() error, stop reading */ - error = SELECT_ERROR; - failf(data, "Proxy CONNECT aborted due to select/poll error"); + /* Read one byte at a time to avoid a race condition. Wait at most one + second before looping to ensure continuous pgrsUpdates. */ + result = Curl_read(conn, tunnelsocket, ptr, 1, &gotbytes); + if(result == CURLE_AGAIN) { + if(SOCKET_READABLE(tunnelsocket, check<1000L?check:1000) == -1) { + error = SELECT_ERROR; + failf(data, "Proxy CONNECT aborted due to select/poll error"); + break; + } + continue; + } + else if(result) { + keepon = FALSE; break; - case 0: /* timeout */ + } + else if(gotbytes <= 0) { + if(data->set.proxyauth && data->state.authproxy.avail) { + /* proxy auth was requested and there was proxy auth available, + then deem this as "mere" proxy disconnect */ + conn->bits.proxy_connect_closed = TRUE; + infof(data, "Proxy CONNECT connection closed\n"); + } + else { + error = SELECT_ERROR; + failf(data, "Proxy CONNECT aborted"); + } + keepon = FALSE; break; - default: - DEBUGASSERT(ptr+BUFSIZE-nread <= data->state.buffer+BUFSIZE+1); - result = Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread, - &gotbytes); - if(result==CURLE_AGAIN) - continue; /* go loop yourself */ - else if(result) - keepon = FALSE; - else if(gotbytes <= 0) { - keepon = FALSE; - if(data->set.proxyauth && data->state.authproxy.avail) { - /* proxy auth was requested and there was proxy auth available, - then deem this as "mere" proxy disconnect */ - conn->bits.proxy_connect_closed = TRUE; - infof(data, "Proxy CONNECT connection closed\n"); - } - else { - error = SELECT_ERROR; - failf(data, "Proxy CONNECT aborted"); + } + + /* We got a byte of data */ + nread++; + + if(keepon > TRUE) { + /* This means we are currently ignoring a response-body */ + + nread = 0; /* make next read start over in the read buffer */ + ptr = data->state.buffer; + if(cl) { + /* A Content-Length based body: simply count down the counter + and make sure to break out of the loop when we're done! */ + cl--; + if(cl <= 0) { + keepon = FALSE; + break; } } else { - /* - * We got a whole chunk of data, which can be anything from one - * byte to a set of lines and possibly just a piece of the last - * line. - */ - int i; - - nread += gotbytes; - - if(keepon > TRUE) { - /* This means we are currently ignoring a response-body */ - - nread = 0; /* make next read start over in the read buffer */ - ptr=data->state.buffer; - if(cl) { - /* A Content-Length based body: simply count down the counter - and make sure to break out of the loop when we're done! */ - cl -= gotbytes; - if(cl<=0) { - keepon = FALSE; - break; - } + /* chunked-encoded body, so we need to do the chunked dance + properly to know when the end of the body is reached */ + CHUNKcode r; + ssize_t tookcareof = 0; + + /* now parse the chunked piece of data so that we can + properly tell when the stream ends */ + r = Curl_httpchunk_read(conn, ptr, 1, &tookcareof); + if(r == CHUNKE_STOP) { + /* we're done reading chunks! */ + infof(data, "chunk reading DONE\n"); + keepon = FALSE; + /* we did the full CONNECT treatment, go COMPLETE */ + conn->tunnel_state[sockindex] = TUNNEL_COMPLETE; + } + } + continue; + } + + perline++; /* amount of bytes in this line so far */ + + /* if this is not the end of a header line then continue */ + if(*ptr != 0x0a) { + ptr++; + continue; + } + + /* convert from the network encoding */ + result = Curl_convert_from_network(data, line_start, perline); + /* Curl_convert_from_network calls failf if unsuccessful */ + if(result) + return result; + + /* output debug if that is requested */ + if(data->set.verbose) + Curl_debug(data, CURLINFO_HEADER_IN, + line_start, (size_t)perline, conn); + + /* send the header to the callback */ + writetype = CLIENTWRITE_HEADER; + if(data->set.include_header) + writetype |= CLIENTWRITE_BODY; + + result = Curl_client_write(conn, writetype, line_start, perline); + + data->info.header_size += (long)perline; + data->req.headerbytecount += (long)perline; + + if(result) + return result; + + /* Newlines are CRLF, so the CR is ignored as the line isn't + really terminated until the LF comes. Treat a following CR + as end-of-headers as well.*/ + + if(('\r' == line_start[0]) || + ('\n' == line_start[0])) { + /* end of response-headers from the proxy */ + nread = 0; /* make next read start over in the read + buffer */ + ptr = data->state.buffer; + if((407 == k->httpcode) && !data->state.authproblem) { + /* If we get a 407 response code with content length + when we have no auth problem, we must ignore the + whole response-body */ + keepon = 2; + + if(cl) { + infof(data, "Ignore %" CURL_FORMAT_CURL_OFF_T + " bytes of response-body\n", cl); + } + else if(chunked_encoding) { + CHUNKcode r; + + infof(data, "Ignore chunked response-body\n"); + + /* We set ignorebody true here since the chunked + decoder function will acknowledge that. Pay + attention so that this is cleared again when this + function returns! */ + k->ignorebody = TRUE; + + if(line_start[1] == '\n') { + /* this can only be a LF if the letter at index 0 + was a CR */ + line_start++; } - else { - /* chunked-encoded body, so we need to do the chunked dance - properly to know when the end of the body is reached */ - CHUNKcode r; - ssize_t tookcareof=0; - - /* now parse the chunked piece of data so that we can - properly tell when the stream ends */ - r = Curl_httpchunk_read(conn, ptr, gotbytes, &tookcareof); - if(r == CHUNKE_STOP) { - /* we're done reading chunks! */ - infof(data, "chunk reading DONE\n"); - keepon = FALSE; - /* we did the full CONNECT treatment, go COMPLETE */ - conn->tunnel_state[sockindex] = TUNNEL_COMPLETE; - } - else - infof(data, "Read %zd bytes of chunk, continue\n", - tookcareof); + + /* now parse the chunked piece of data so that we can + properly tell when the stream ends */ + r = Curl_httpchunk_read(conn, line_start + 1, 1, &gotbytes); + if(r == CHUNKE_STOP) { + /* we're done reading chunks! */ + infof(data, "chunk reading DONE\n"); + keepon = FALSE; + /* we did the full CONNECT treatment, go to + COMPLETE */ + conn->tunnel_state[sockindex] = TUNNEL_COMPLETE; } } - else - for(i = 0; i < gotbytes; ptr++, i++) { - perline++; /* amount of bytes in this line so far */ - if(*ptr == 0x0a) { - char letter; - int writetype; - - /* convert from the network encoding */ - result = Curl_convert_from_network(data, line_start, - perline); - /* Curl_convert_from_network calls failf if unsuccessful */ - if(result) - return result; - - /* output debug if that is requested */ - if(data->set.verbose) - Curl_debug(data, CURLINFO_HEADER_IN, - line_start, (size_t)perline, conn); - - /* send the header to the callback */ - writetype = CLIENTWRITE_HEADER; - if(data->set.include_header) - writetype |= CLIENTWRITE_BODY; - - result = Curl_client_write(conn, writetype, line_start, - perline); - - data->info.header_size += (long)perline; - data->req.headerbytecount += (long)perline; - - if(result) - return result; - - /* Newlines are CRLF, so the CR is ignored as the line isn't - really terminated until the LF comes. Treat a following CR - as end-of-headers as well.*/ - - if(('\r' == line_start[0]) || - ('\n' == line_start[0])) { - /* end of response-headers from the proxy */ - nread = 0; /* make next read start over in the read - buffer */ - ptr=data->state.buffer; - if((407 == k->httpcode) && !data->state.authproblem) { - /* If we get a 407 response code with content length - when we have no auth problem, we must ignore the - whole response-body */ - keepon = 2; - - if(cl) { - infof(data, "Ignore %" CURL_FORMAT_CURL_OFF_T - " bytes of response-body\n", cl); - - /* remove the remaining chunk of what we already - read */ - cl -= (gotbytes - i); - - if(cl<=0) - /* if the whole thing was already read, we are done! - */ - keepon=FALSE; - } - else if(chunked_encoding) { - CHUNKcode r; - /* We set ignorebody true here since the chunked - decoder function will acknowledge that. Pay - attention so that this is cleared again when this - function returns! */ - k->ignorebody = TRUE; - infof(data, "%zd bytes of chunk left\n", gotbytes-i); - - if(line_start[1] == '\n') { - /* this can only be a LF if the letter at index 0 - was a CR */ - line_start++; - i++; - } - - /* now parse the chunked piece of data so that we can - properly tell when the stream ends */ - r = Curl_httpchunk_read(conn, line_start+1, - gotbytes -i, &gotbytes); - if(r == CHUNKE_STOP) { - /* we're done reading chunks! */ - infof(data, "chunk reading DONE\n"); - keepon = FALSE; - /* we did the full CONNECT treatment, go to - COMPLETE */ - conn->tunnel_state[sockindex] = TUNNEL_COMPLETE; - } - else - infof(data, "Read %zd bytes of chunk, continue\n", - gotbytes); - } - else { - /* without content-length or chunked encoding, we - can't keep the connection alive since the close is - the end signal so we bail out at once instead */ - keepon=FALSE; - } - } - else { - keepon = FALSE; - if(200 == data->info.httpproxycode) { - if(gotbytes - (i+1)) - failf(data, "Proxy CONNECT followed by %zd bytes " - "of opaque data. Data ignored (known bug #39)", - gotbytes - (i+1)); - } - } - /* we did the full CONNECT treatment, go to COMPLETE */ - conn->tunnel_state[sockindex] = TUNNEL_COMPLETE; - break; /* breaks out of for-loop, not switch() */ - } - - /* keep a backup of the position we are about to blank */ - letter = line_start[perline]; - line_start[perline]=0; /* zero terminate the buffer */ - if((checkprefix("WWW-Authenticate:", line_start) && - (401 == k->httpcode)) || - (checkprefix("Proxy-authenticate:", line_start) && - (407 == k->httpcode))) { - - bool proxy = (k->httpcode == 407) ? TRUE : FALSE; - char *auth = Curl_copy_header_value(line_start); - if(!auth) - return CURLE_OUT_OF_MEMORY; - - result = Curl_http_input_auth(conn, proxy, auth); - - free(auth); - - if(result) - return result; - } - else if(checkprefix("Content-Length:", line_start)) { - cl = curlx_strtoofft(line_start + - strlen("Content-Length:"), NULL, 10); - } - else if(Curl_compareheader(line_start, - "Connection:", "close")) - closeConnection = TRUE; - else if(Curl_compareheader(line_start, - "Transfer-Encoding:", - "chunked")) { - infof(data, "CONNECT responded chunked\n"); - chunked_encoding = TRUE; - /* init our chunky engine */ - Curl_httpchunk_init(conn); - } - else if(Curl_compareheader(line_start, - "Proxy-Connection:", "close")) - closeConnection = TRUE; - else if(2 == sscanf(line_start, "HTTP/1.%d %d", - &subversion, - &k->httpcode)) { - /* store the HTTP code from the proxy */ - data->info.httpproxycode = k->httpcode; - } - /* put back the letter we blanked out before */ - line_start[perline]= letter; - - perline=0; /* line starts over here */ - line_start = ptr+1; /* this skips the zero byte we wrote */ - } - } + else { + /* without content-length or chunked encoding, we + can't keep the connection alive since the close is + the end signal so we bail out at once instead */ + keepon = FALSE; + } } - break; - } /* switch */ - if(Curl_pgrsUpdate(conn)) - return CURLE_ABORTED_BY_CALLBACK; + else + keepon = FALSE; + /* we did the full CONNECT treatment, go to COMPLETE */ + conn->tunnel_state[sockindex] = TUNNEL_COMPLETE; + continue; + } + + line_start[perline] = 0; /* zero terminate the buffer */ + if((checkprefix("WWW-Authenticate:", line_start) && + (401 == k->httpcode)) || + (checkprefix("Proxy-authenticate:", line_start) && + (407 == k->httpcode))) { + + bool proxy = (k->httpcode == 407) ? TRUE : FALSE; + char *auth = Curl_copy_header_value(line_start); + if(!auth) + return CURLE_OUT_OF_MEMORY; + + result = Curl_http_input_auth(conn, proxy, auth); + + free(auth); + + if(result) + return result; + } + else if(checkprefix("Content-Length:", line_start)) { + if(k->httpcode/100 == 2) { + /* A server MUST NOT send any Transfer-Encoding or + Content-Length header fields in a 2xx (Successful) + response to CONNECT. (RFC 7231 section 4.3.6) */ + failf(data, "Content-Length: in %03d response", + k->httpcode); + return CURLE_RECV_ERROR; + } + + cl = curlx_strtoofft(line_start + + strlen("Content-Length:"), NULL, 10); + } + else if(Curl_compareheader(line_start, "Connection:", "close")) + closeConnection = TRUE; + else if(Curl_compareheader(line_start, + "Transfer-Encoding:", + "chunked")) { + if(k->httpcode/100 == 2) { + /* A server MUST NOT send any Transfer-Encoding or + Content-Length header fields in a 2xx (Successful) + response to CONNECT. (RFC 7231 section 4.3.6) */ + failf(data, "Transfer-Encoding: in %03d response", k->httpcode); + return CURLE_RECV_ERROR; + } + infof(data, "CONNECT responded chunked\n"); + chunked_encoding = TRUE; + /* init our chunky engine */ + Curl_httpchunk_init(conn); + } + else if(Curl_compareheader(line_start, "Proxy-Connection:", "close")) + closeConnection = TRUE; + else if(2 == sscanf(line_start, "HTTP/1.%d %d", + &subversion, + &k->httpcode)) { + /* store the HTTP code from the proxy */ + data->info.httpproxycode = k->httpcode; + } + + perline = 0; /* line starts over here */ + ptr = data->state.buffer; + line_start = ptr; } /* while there's buffer left and loop is requested */ + if(Curl_pgrsUpdate(conn)) + return CURLE_ABORTED_BY_CALLBACK; + if(error) return CURLE_RECV_ERROR; @@ -538,8 +568,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, if(conn->bits.close) /* the connection has been marked for closure, most likely in the Curl_http_auth_act() function and thus we can kill it at once - below - */ + below */ closeConnection = TRUE; } @@ -600,7 +629,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, data->state.authproxy.done = TRUE; - infof (data, "Proxy replied OK to CONNECT request\n"); + infof(data, "Proxy replied OK to CONNECT request\n"); data->req.ignorebody = FALSE; /* put it (back) to non-ignore state */ conn->bits.rewindaftersend = FALSE; /* make sure this isn't set for the document request */ diff --git a/lib/http_proxy.h b/lib/http_proxy.h index fd04330..d1f5a7c 100644 --- a/lib/http_proxy.h +++ b/lib/http_proxy.h @@ -32,11 +32,11 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, /* Default proxy timeout in milliseconds */ #define PROXY_TIMEOUT (3600*1000) -CURLcode Curl_proxy_connect(struct connectdata *conn); +CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex); #else #define Curl_proxyCONNECT(x,y,z,w,v) CURLE_NOT_BUILT_IN -#define Curl_proxy_connect(x) CURLE_OK +#define Curl_proxy_connect(x,y) CURLE_OK #endif #endif /* HEADER_CURL_HTTP_PROXY_H */ diff --git a/lib/if2ip.c b/lib/if2ip.c index e6faa4b..d876615 100644 --- a/lib/if2ip.c +++ b/lib/if2ip.c @@ -68,7 +68,7 @@ unsigned int Curl_ipv6_scope(const struct sockaddr *sa) #else if(sa->sa_family == AF_INET6) { const struct sockaddr_in6 * sa6 = (const struct sockaddr_in6 *)(void *) sa; - const unsigned char * b = sa6->sin6_addr.s6_addr; + const unsigned char *b = sa6->sin6_addr.s6_addr; unsigned short w = (unsigned short) ((b[0] << 8) | b[1]); switch(w & 0xFFC0) { diff --git a/lib/imap.c b/lib/imap.c index 4aa7dcc..78dc6fa 100644 --- a/lib/imap.c +++ b/lib/imap.c @@ -107,7 +107,7 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn, const char *initresp); static CURLcode imap_continue_authenticate(struct connectdata *conn, const char *resp); -static void imap_get_message(char *buffer, char** outptr); +static void imap_get_message(char *buffer, char **outptr); /* * IMAP protocol handler. @@ -390,10 +390,10 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len, * * Gets the authentication message from the response buffer. */ -static void imap_get_message(char *buffer, char** outptr) +static void imap_get_message(char *buffer, char **outptr) { size_t len = 0; - char* message = NULL; + char *message = NULL; /* Find the start of the message */ for(message = buffer + 2; *message == ' ' || *message == '\t'; message++) diff --git a/lib/inet_ntop.c b/lib/inet_ntop.c index 416005c..9afbdbb 100644 --- a/lib/inet_ntop.c +++ b/lib/inet_ntop.c @@ -182,12 +182,12 @@ static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size) */ char *Curl_inet_ntop(int af, const void *src, char *buf, size_t size) { - switch (af) { + switch(af) { case AF_INET: - return inet_ntop4((const unsigned char*)src, buf, size); + return inet_ntop4((const unsigned char *)src, buf, size); #ifdef ENABLE_IPV6 case AF_INET6: - return inet_ntop6((const unsigned char*)src, buf, size); + return inet_ntop6((const unsigned char *)src, buf, size); #endif default: SET_ERRNO(EAFNOSUPPORT); diff --git a/lib/inet_pton.c b/lib/inet_pton.c index cf8b88a..475f44a 100644 --- a/lib/inet_pton.c +++ b/lib/inet_pton.c @@ -65,7 +65,7 @@ static int inet_pton6(const char *src, unsigned char *dst); int Curl_inet_pton(int af, const char *src, void *dst) { - switch (af) { + switch(af) { case AF_INET: return (inet_pton4(src, (unsigned char *)dst)); #ifdef ENABLE_IPV6 @@ -103,7 +103,8 @@ inet_pton4(const char *src, unsigned char *dst) while((ch = *src++) != '\0') { const char *pch; - if((pch = strchr(digits, ch)) != NULL) { + pch = strchr(digits, ch); + if(pch) { unsigned int val = *tp * 10 + (unsigned int)(pch - digits); if(saw_digit && *tp == 0) @@ -169,7 +170,8 @@ inet_pton6(const char *src, unsigned char *dst) while((ch = *src++) != '\0') { const char *pch; - if((pch = strchr((xdigits = xdigits_l), ch)) == NULL) + pch = strchr((xdigits = xdigits_l), ch); + if(!pch) pch = strchr((xdigits = xdigits_u), ch); if(pch != NULL) { val <<= 4; diff --git a/lib/krb5.c b/lib/krb5.c index 5d5c003..067b0a5 100644 --- a/lib/krb5.c +++ b/lib/krb5.c @@ -121,7 +121,7 @@ krb5_encode(void *app_data, const void *from, int length, int level, void **to) /* NOTE that the cast is safe, neither of the krb5, gnu gss and heimdal * libraries modify the input buffer in gss_seal() */ - dec.value = (void*)from; + dec.value = (void *)from; dec.length = length; maj = gss_seal(&min, *context, level == PROT_PRIVATE, diff --git a/lib/ldap.c b/lib/ldap.c index 7dbc1b0..979ce7d 100644 --- a/lib/ldap.c +++ b/lib/ldap.c @@ -109,9 +109,9 @@ typedef struct { #undef LDAPURLDesc #define LDAPURLDesc CURL_LDAPURLDesc -static int _ldap_url_parse (const struct connectdata *conn, - LDAPURLDesc **ludp); -static void _ldap_free_urldesc (LDAPURLDesc *ludp); +static int _ldap_url_parse(const struct connectdata *conn, + LDAPURLDesc **ludp); +static void _ldap_free_urldesc(LDAPURLDesc *ludp); #undef ldap_free_urldesc #define ldap_free_urldesc _ldap_free_urldesc @@ -119,11 +119,11 @@ static void _ldap_free_urldesc (LDAPURLDesc *ludp); #ifdef DEBUG_LDAP #define LDAP_TRACE(x) do { \ - _ldap_trace ("%u: ", __LINE__); \ + _ldap_trace("%u: ", __LINE__); \ _ldap_trace x; \ } WHILE_FALSE - static void _ldap_trace (const char *fmt, ...); + static void _ldap_trace(const char *fmt, ...); #else #define LDAP_TRACE(x) Curl_nop_stmt #endif @@ -271,7 +271,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) ldap_set_option(server, LDAP_OPT_SSL, LDAP_OPT_ON); #else int ldap_option; - char* ldap_ca = data->set.str[STRING_SSL_CAFILE]; + char *ldap_ca = conn->ssl_config.CAfile; #if defined(CURL_HAS_NOVELL_LDAPSDK) rc = ldapssl_client_init(NULL, NULL); if(rc != LDAP_SUCCESS) { @@ -279,11 +279,11 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) result = CURLE_SSL_CERTPROBLEM; goto quit; } - if(data->set.ssl.verifypeer) { + if(conn->ssl_config.verifypeer) { /* Novell SDK supports DER or BASE64 files. */ int cert_type = LDAPSSL_CERT_FILETYPE_B64; - if((data->set.str[STRING_CERT_TYPE]) && - (strcasecompare(data->set.str[STRING_CERT_TYPE], "DER"))) + if((data->set.ssl.cert_type) && + (strcasecompare(data->set.ssl.cert_type, "DER"))) cert_type = LDAPSSL_CERT_FILETYPE_DER; if(!ldap_ca) { failf(data, "LDAP local: ERROR %s CA cert not set!", @@ -321,10 +321,10 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) goto quit; } #elif defined(LDAP_OPT_X_TLS) - if(data->set.ssl.verifypeer) { + if(conn->ssl_config.verifypeer) { /* OpenLDAP SDK supports BASE64 files. */ - if((data->set.str[STRING_CERT_TYPE]) && - (!strcasecompare(data->set.str[STRING_CERT_TYPE], "PEM"))) { + if((data->set.ssl.cert_type) && + (!strcasecompare(data->set.ssl.cert_type, "PEM"))) { failf(data, "LDAP local: ERROR OpenLDAP only supports PEM cert-type!"); result = CURLE_SSL_CERTPROBLEM; goto quit; @@ -655,7 +655,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done) quit: if(ldapmsg) { ldap_msgfree(ldapmsg); - LDAP_TRACE (("Received %d entries\n", num)); + LDAP_TRACE(("Received %d entries\n", num)); } if(rc == LDAP_SIZELIMIT_EXCEEDED) infof(data, "There are more than %d entries\n", num); @@ -682,7 +682,7 @@ quit: } #ifdef DEBUG_LDAP -static void _ldap_trace (const char *fmt, ...) +static void _ldap_trace(const char *fmt, ...) { static int do_trace = -1; va_list args; @@ -694,9 +694,9 @@ static void _ldap_trace (const char *fmt, ...) if(!do_trace) return; - va_start (args, fmt); - vfprintf (stderr, fmt, args); - va_end (args); + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); } #endif @@ -705,7 +705,7 @@ static void _ldap_trace (const char *fmt, ...) /* * Return scope-value for a scope-string. */ -static int str2scope (const char *p) +static int str2scope(const char *p) { if(strcasecompare(p, "one")) return LDAP_SCOPE_ONELEVEL; @@ -799,7 +799,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp) char *unescaped; CURLcode result; - LDAP_TRACE (("DN '%s'\n", dn)); + LDAP_TRACE(("DN '%s'\n", dn)); /* Unescape the DN */ result = Curl_urldecode(conn->data, dn, 0, &unescaped, NULL, FALSE); @@ -864,7 +864,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp) char *unescaped; CURLcode result; - LDAP_TRACE (("attr[%d] '%s'\n", i, attributes[i])); + LDAP_TRACE(("attr[%d] '%s'\n", i, attributes[i])); /* Unescape the attribute */ result = Curl_urldecode(conn->data, attributes[i], 0, &unescaped, NULL, @@ -917,7 +917,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp) goto quit; } - LDAP_TRACE (("scope %d\n", ludp->lud_scope)); + LDAP_TRACE(("scope %d\n", ludp->lud_scope)); } p = q; @@ -934,7 +934,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp) char *unescaped; CURLcode result; - LDAP_TRACE (("filter '%s'\n", filter)); + LDAP_TRACE(("filter '%s'\n", filter)); /* Unescape the filter */ result = Curl_urldecode(conn->data, filter, 0, &unescaped, NULL, FALSE); @@ -1009,7 +1009,7 @@ static void _ldap_free_urldesc(LDAPURLDesc *ludp) free(ludp->lud_attrs); } - free (ludp); + free(ludp); } #endif /* !HAVE_LDAP_URL_PARSE */ #endif /* !CURL_DISABLE_LDAP && !USE_OPENLDAP */ diff --git a/lib/md4.c b/lib/md4.c index 60f73a2..1bdc9f3 100644 --- a/lib/md4.c +++ b/lib/md4.c @@ -213,7 +213,8 @@ static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size) unsigned long used, available; saved_lo = ctx->lo; - if((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) + ctx->lo = (saved_lo + size) & 0x1fffffff; + if(ctx->lo < saved_lo) ctx->hi++; ctx->hi += (MD4_u32plus)size >> 29; diff --git a/lib/md5.c b/lib/md5.c index f818d32..f2dc16c 100644 --- a/lib/md5.c +++ b/lib/md5.c @@ -45,7 +45,7 @@ static void MD5_Init(MD5_CTX * ctx) } static void MD5_Update(MD5_CTX * ctx, - const unsigned char * input, + const unsigned char *input, unsigned int inputLen) { md5_update(ctx, inputLen, input); @@ -71,7 +71,7 @@ static void MD5_Init(MD5_CTX * ctx) } static void MD5_Update(MD5_CTX * ctx, - const unsigned char * input, + const unsigned char *input, unsigned int inputLen) { gcry_md_write(*ctx, input, inputLen); @@ -402,7 +402,8 @@ static void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size) unsigned long used, available; saved_lo = ctx->lo; - if((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) + ctx->lo = (saved_lo + size) & 0x1fffffff; + if(ctx->lo < saved_lo) ctx->hi++; ctx->hi += (MD5_u32plus)size >> 29; diff --git a/lib/memdebug.c b/lib/memdebug.c index ccbf461..15e8661 100644 --- a/lib/memdebug.c +++ b/lib/memdebug.c @@ -90,7 +90,7 @@ struct memdebug { union { curl_off_t o; double d; - void * p; + void *p; } mem[1]; /* I'm hoping this is the thing with the strictest alignment * requirements. That also means we waste some space :-( */ diff --git a/lib/mprintf.c b/lib/mprintf.c index 2c88aa8..e4270ab 100644 --- a/lib/mprintf.c +++ b/lib/mprintf.c @@ -92,7 +92,8 @@ # define mp_uintmax_t unsigned long #endif -#define BUFFSIZE 256 /* buffer for long-to-str and float-to-str calcs */ +#define BUFFSIZE 326 /* buffer for long-to-str and float-to-str calcs, should + fit negative DBL_MAX (317 letters) */ #define MAX_PARAMETERS 128 /* lame static limit */ #ifdef __AMIGA__ @@ -303,7 +304,6 @@ static int dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos, flags |= FLAGS_ALT; break; case '.': - flags |= FLAGS_PREC; if('*' == *fmt) { /* The precision is picked from a specified parameter */ @@ -502,7 +502,7 @@ static int dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos, (mp_intmax_t)va_arg(arglist, int); } - switch (vto[i].type) { + switch(vto[i].type) { case FORMAT_STRING: vto[i].data.str = va_arg(arglist, char *); break; @@ -692,7 +692,7 @@ static int dprintf_formatf( is_alt = (p->flags & FLAGS_ALT) ? 1 : 0; - switch (p->type) { + switch(p->type) { case FORMAT_INT: num = p->data.num.as_unsigned; if(p->flags & FLAGS_CHAR) { @@ -917,12 +917,25 @@ static int dprintf_formatf( *fptr = 0; if(width >= 0) { + if(width >= (long)sizeof(work)) + width = sizeof(work)-1; /* RECURSIVE USAGE */ len = curl_msnprintf(fptr, left, "%ld", width); fptr += len; left -= len; } if(prec >= 0) { + /* for each digit in the integer part, we can have one less + precision */ + size_t maxprec = sizeof(work) - 2; + double val = p->data.dnum; + while(val >= 10.0) { + val /= 10; + maxprec--; + } + + if(prec > (long)maxprec) + prec = (long)maxprec-1; /* RECURSIVE USAGE */ len = curl_msnprintf(fptr, left, ".%ld", prec); fptr += len; @@ -942,7 +955,9 @@ static int dprintf_formatf( /* NOTE NOTE NOTE!! Not all sprintf implementations return number of output characters */ (sprintf)(work, formatbuf, p->data.dnum); - +#ifdef CURLDEBUG + assert(strlen(work) <= sizeof(work)); +#endif for(fptr=work; *fptr; fptr++) OUTCHAR(*fptr); } diff --git a/lib/multi.c b/lib/multi.c index 2432b15..950b600 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -42,6 +42,7 @@ #include "multihandle.h" #include "pipeline.h" #include "sigpipe.h" +#include "vtls/vtls.h" #include "connect.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -812,6 +813,11 @@ static int waitconnect_getsock(struct connectdata *conn, if(!numsocks) return GETSOCK_BLANK; +#ifdef USE_SSL + if(CONNECT_FIRSTSOCKET_PROXY_SSL()) + return Curl_ssl_getsock(conn, sock, numsocks); +#endif + for(i=0; i<2; i++) { if(conn->tempsock[i] != CURL_SOCKET_BAD) { sock[s] = conn->tempsock[i]; @@ -1300,7 +1306,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, CURLMcode rc; CURLcode result = CURLE_OK; struct SingleRequest *k; - long timeout_ms; + time_t timeout_ms; int control; if(!GOOD_EASY_HANDLE(data)) @@ -1548,7 +1554,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, multistate(data, CURLM_STATE_CONNECT); } else if(!result) { - if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_COMPLETE) { + if((data->easy_conn->http_proxy.proxytype != CURLPROXY_HTTPS || + data->easy_conn->bits.proxy_ssl_connected[FIRSTSOCKET]) && + (data->easy_conn->tunnel_state[FIRSTSOCKET] != TUNNEL_CONNECT)) { rc = CURLM_CALL_MULTI_PERFORM; /* initiate protocol connect phase */ multistate(data, CURLM_STATE_SENDPROTOCONNECT); @@ -1561,6 +1569,14 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, /* awaiting a completion of an asynch TCP connect */ result = Curl_is_connected(data->easy_conn, FIRSTSOCKET, &connected); if(connected && !result) { +#ifndef CURL_DISABLE_HTTP + if((data->easy_conn->http_proxy.proxytype == CURLPROXY_HTTPS && + !data->easy_conn->bits.proxy_ssl_connected[FIRSTSOCKET]) || + (data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)) { + multistate(data, CURLM_STATE_WAITPROXYCONNECT); + break; + } +#endif rc = CURLM_CALL_MULTI_PERFORM; multistate(data, data->easy_conn->bits.tunnel_proxy? CURLM_STATE_WAITPROXYCONNECT: @@ -2486,7 +2502,7 @@ static CURLMcode add_next_timeout(struct timeval now, timeout in *tv */ for(e = list->head; e;) { struct curl_llist_element *n = e->next; - long diff = curlx_tvdiff(*(struct timeval *)e->ptr, now); + time_t diff = curlx_tvdiff(*(struct timeval *)e->ptr, now); if(diff <= 0) /* remove outdated entry */ Curl_llist_remove(list, e, NULL); @@ -2764,7 +2780,7 @@ static CURLMcode multi_timeout(struct Curl_multi *multi, if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) { /* some time left before expiration */ - *timeout_ms = curlx_tvdiff(multi->timetree->key, now); + *timeout_ms = (long)curlx_tvdiff(multi->timetree->key, now); if(!*timeout_ms) /* * Since we only provide millisecond resolution on the returned value @@ -2871,7 +2887,7 @@ multi_addtimeout(struct curl_llist *timeoutlist, /* find the correct spot in the list */ for(e = timeoutlist->head; e; e = e->next) { struct timeval *checktime = e->ptr; - long diff = curlx_tvdiff(*checktime, *timedup); + time_t diff = curlx_tvdiff(*checktime, *timedup); if(diff > 0) break; prev = e; @@ -2898,7 +2914,7 @@ multi_addtimeout(struct curl_llist *timeoutlist, * The timeout will be added to a queue of timeouts if it defines a moment in * time that is later than the current head of queue. */ -void Curl_expire(struct Curl_easy *data, long milli) +void Curl_expire(struct Curl_easy *data, time_t milli) { struct Curl_multi *multi = data->multi; struct timeval *nowp = &data->state.expiretime; @@ -2911,7 +2927,7 @@ void Curl_expire(struct Curl_easy *data, long milli) return; set = Curl_tvnow(); - set.tv_sec += milli/1000; + set.tv_sec += (long)(milli/1000); set.tv_usec += (milli%1000)*1000; if(set.tv_usec >= 1000000) { @@ -2923,7 +2939,7 @@ void Curl_expire(struct Curl_easy *data, long milli) /* This means that the struct is added as a node in the splay tree. Compare if the new time is earlier, and only remove-old/add-new if it is. */ - long diff = curlx_tvdiff(set, *nowp); + time_t diff = curlx_tvdiff(set, *nowp); if(diff > 0) { /* the new expire time was later so just add it to the queue and get out */ @@ -2961,14 +2977,14 @@ void Curl_expire(struct Curl_easy *data, long milli) * time-out period to expire. * */ -void Curl_expire_latest(struct Curl_easy *data, long milli) +void Curl_expire_latest(struct Curl_easy *data, time_t milli) { struct timeval *expire = &data->state.expiretime; struct timeval set; set = Curl_tvnow(); - set.tv_sec += milli / 1000; + set.tv_sec += (long)(milli / 1000); set.tv_usec += (milli % 1000) * 1000; if(set.tv_usec >= 1000000) { @@ -2980,7 +2996,7 @@ void Curl_expire_latest(struct Curl_easy *data, long milli) /* This means that the struct is added as a node in the splay tree. Compare if the new time is earlier, and only remove-old/add-new if it is. */ - long diff = curlx_tvdiff(set, *expire); + time_t diff = curlx_tvdiff(set, *expire); if(diff > 0) /* the new expire time was later than the top time, so just skip this */ return; diff --git a/lib/multihandle.h b/lib/multihandle.h index c56b6ae..0b78de9 100644 --- a/lib/multihandle.h +++ b/lib/multihandle.h @@ -38,7 +38,9 @@ typedef enum { CURLM_STATE_CONNECT, /* 2 - resolve/connect has been sent off */ CURLM_STATE_WAITRESOLVE, /* 3 - awaiting the resolve to finalize */ CURLM_STATE_WAITCONNECT, /* 4 - awaiting the TCP connect to finalize */ - CURLM_STATE_WAITPROXYCONNECT, /* 5 - awaiting proxy CONNECT to finalize */ + CURLM_STATE_WAITPROXYCONNECT, /* 5 - awaiting HTTPS proxy SSL initialization + to complete and/or proxy CONNECT to + finalize */ CURLM_STATE_SENDPROTOCONNECT, /* 6 - initiate protocol connect procedure */ CURLM_STATE_PROTOCONNECT, /* 7 - completing the protocol-specific connect phase */ diff --git a/lib/multiif.h b/lib/multiif.h index eaff496..e5de1fc 100644 --- a/lib/multiif.h +++ b/lib/multiif.h @@ -25,9 +25,9 @@ /* * Prototypes for library-wide functions provided by multi.c */ -void Curl_expire(struct Curl_easy *data, long milli); +void Curl_expire(struct Curl_easy *data, time_t milli); void Curl_expire_clear(struct Curl_easy *data); -void Curl_expire_latest(struct Curl_easy *data, long milli); +void Curl_expire_latest(struct Curl_easy *data, time_t milli); bool Curl_pipeline_wanted(const struct Curl_multi* multi, int bits); void Curl_multi_handlePipeBreak(struct Curl_easy *data); diff --git a/lib/non-ascii.c b/lib/non-ascii.c index ed14618..2f5de4c 100644 --- a/lib/non-ascii.c +++ b/lib/non-ascii.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -117,7 +117,7 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data, /* call iconv */ input_ptr = output_ptr = buffer; in_bytes = out_bytes = length; - rc = iconv(data->outbound_cd, (const char**)&input_ptr, &in_bytes, + rc = iconv(data->outbound_cd, (const char **)&input_ptr, &in_bytes, &output_ptr, &out_bytes); if((rc == ICONV_ERROR) || (in_bytes != 0)) { error = ERRNO; diff --git a/lib/nwlib.c b/lib/nwlib.c index 42b6aa0..290cbe3 100644 --- a/lib/nwlib.c +++ b/lib/nwlib.c @@ -184,7 +184,8 @@ int GetOrSetUpData(int id, libdata_t **appData, */ NXLock(gLibLock); - if(!(app_data = (libdata_t *) get_app_data(id))) { + app_data = (libdata_t *) get_app_data(id); + if(!app_data) { app_data = malloc(sizeof(libdata_t)); if(app_data) { @@ -259,7 +260,8 @@ int GetOrSetUpData(int id, libdata_t **appData, err = ENOMEM; } - if((err = NXKeySetValue(key, thread_data))) { + err = NXKeySetValue(key, thread_data); + if(err) { free(thread_data->twentybytes); free(thread_data); thread_data = (libthreaddata_t *) NULL; @@ -303,14 +305,14 @@ void DisposeThreadData(void *data) /* For native CLib-based NLM seems we can do a bit more simple. */ #include -int main (void) +int main(void) { /* initialize any globals here... */ /* do this if any global initializing was done SynchronizeStart(); */ - ExitThread (TSR_THREAD, 0); + ExitThread(TSR_THREAD, 0); return 0; } diff --git a/lib/nwos.c b/lib/nwos.c index 385f9c8..c6c22cc 100644 --- a/lib/nwos.c +++ b/lib/nwos.c @@ -26,7 +26,7 @@ #ifdef __NOVELL_LIBC__ /* For native LibC-based NLM we need to do nothing. */ -int netware_init (void) +int netware_init(void) { return 0; } @@ -45,7 +45,7 @@ NETDB_DEFINE_CONTEXT #include NETINET_DEFINE_CONTEXT -int netware_init (void) +int netware_init(void) { int rc = 0; unsigned int myHandle = GetNLMHandle(); @@ -72,13 +72,13 @@ int netware_init (void) } /* dummy function to satisfy newer prelude */ -int __init_environment (void) +int __init_environment(void) { return 0; } /* dummy function to satisfy newer prelude */ -int __deinit_environment (void) +int __deinit_environment(void) { return 0; } diff --git a/lib/pingpong.c b/lib/pingpong.c index bf2c8fd..7a99357 100644 --- a/lib/pingpong.c +++ b/lib/pingpong.c @@ -44,12 +44,12 @@ /* Returns timeout in ms. 0 or negative number means the timeout has already triggered */ -long Curl_pp_state_timeout(struct pingpong *pp) +time_t Curl_pp_state_timeout(struct pingpong *pp) { struct connectdata *conn = pp->conn; struct Curl_easy *data=conn->data; - long timeout_ms; /* in milliseconds */ - long timeout2_ms; /* in milliseconds */ + time_t timeout_ms; /* in milliseconds */ + time_t timeout2_ms; /* in milliseconds */ long response_time= (data->set.server_response_timeout)? data->set.server_response_timeout: pp->response_time; @@ -83,8 +83,8 @@ CURLcode Curl_pp_statemach(struct pingpong *pp, bool block) struct connectdata *conn = pp->conn; curl_socket_t sock = conn->sock[FIRSTSOCKET]; int rc; - long interval_ms; - long timeout_ms = Curl_pp_state_timeout(pp); + time_t interval_ms; + time_t timeout_ms = Curl_pp_state_timeout(pp); struct Curl_easy *data=conn->data; CURLcode result = CURLE_OK; @@ -101,7 +101,9 @@ CURLcode Curl_pp_statemach(struct pingpong *pp, bool block) else interval_ms = 0; /* immediate */ - if(Curl_pp_moredata(pp)) + if(Curl_ssl_data_pending(conn, FIRSTSOCKET)) + rc = 1; + else if(Curl_pp_moredata(pp)) /* We are receiving and there is data in the cache so just read it */ rc = 1; else if(!pp->sendleft && Curl_ssl_data_pending(conn, FIRSTSOCKET)) diff --git a/lib/pingpong.h b/lib/pingpong.h index 2f649d5..500100a 100644 --- a/lib/pingpong.h +++ b/lib/pingpong.h @@ -88,7 +88,7 @@ void Curl_pp_init(struct pingpong *pp); /* Returns timeout in ms. 0 or negative number means the timeout has already triggered */ -long Curl_pp_state_timeout(struct pingpong *pp); +time_t Curl_pp_state_timeout(struct pingpong *pp); /*********************************************************************** diff --git a/lib/pop3.c b/lib/pop3.c index 8486519..9bb691c 100644 --- a/lib/pop3.c +++ b/lib/pop3.c @@ -104,7 +104,7 @@ static CURLcode pop3_parse_custom_request(struct connectdata *conn); static CURLcode pop3_perform_auth(struct connectdata *conn, const char *mech, const char *initresp); static CURLcode pop3_continue_auth(struct connectdata *conn, const char *resp); -static void pop3_get_message(char *buffer, char** outptr); +static void pop3_get_message(char *buffer, char **outptr); /* * POP3 protocol handler. @@ -290,10 +290,10 @@ static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len, * * Gets the authentication message from the response buffer. */ -static void pop3_get_message(char *buffer, char** outptr) +static void pop3_get_message(char *buffer, char **outptr) { size_t len = 0; - char* message = NULL; + char *message = NULL; /* Find the start of the message */ for(message = buffer + 2; *message == ' ' || *message == '\t'; message++) @@ -1572,7 +1572,7 @@ CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread) if(prev) { /* If the partial match was the CRLF and dot then only write the CRLF as the server would have inserted the dot */ - result = Curl_client_write(conn, CLIENTWRITE_BODY, (char*)POP3_EOB, + result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)POP3_EOB, strip_dot ? prev - 1 : prev); if(result) diff --git a/lib/progress.c b/lib/progress.c index 0f67ef2..60627b2 100644 --- a/lib/progress.c +++ b/lib/progress.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -249,24 +249,26 @@ long Curl_pgrsLimitWaitTime(curl_off_t cursize, struct timeval start, struct timeval now) { - curl_off_t size = cursize - startsize; - long minimum, actual; + curl_off_t size = cursize - startsize; + time_t minimum; + time_t actual; - /* we don't have a starting point yet -- return 0 so it gets (re)set */ - if(start.tv_sec == 0 && start.tv_usec == 0) - return 0; + /* we don't have a starting point yet -- return 0 so it gets (re)set */ + if(start.tv_sec == 0 && start.tv_usec == 0) + return 0; - /* not enough data yet */ - if(size < limit) - return -1; + /* not enough data yet */ + if(size < limit) + return -1; - minimum = (long) (CURL_OFF_T_C(1000) * size / limit); - actual = Curl_tvdiff(now, start); + minimum = (time_t) (CURL_OFF_T_C(1000) * size / limit); + actual = Curl_tvdiff(now, start); - if(actual < minimum) - return minimum - actual; - else - return 0; + if(actual < minimum) + /* this is a conversion on some systems (64bit time_t => 32bit long) */ + return (long)(minimum - actual); + else + return 0; } void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size) @@ -359,9 +361,7 @@ int Curl_pgrsUpdate(struct connectdata *conn) now = Curl_tvnow(); /* what time is it */ /* The time spent so far (from the start) */ - data->progress.timespent = - (double)(now.tv_sec - data->progress.start.tv_sec) + - (double)(now.tv_usec - data->progress.start.tv_usec)/1000000.0; + data->progress.timespent = curlx_tvdiff_secs(now, data->progress.start); timespent = (curl_off_t)data->progress.timespent; /* The average download speed this far */ @@ -375,7 +375,7 @@ int Curl_pgrsUpdate(struct connectdata *conn) (data->progress.timespent>0?data->progress.timespent:1)); /* Calculations done at most once a second, unless end is reached */ - if(data->progress.lastshow != (long)now.tv_sec) { + if(data->progress.lastshow != now.tv_sec) { shownow = TRUE; data->progress.lastshow = now.tv_sec; @@ -402,7 +402,7 @@ int Curl_pgrsUpdate(struct connectdata *conn) /* first of all, we don't do this if there's no counted seconds yet */ if(countindex) { - long span_ms; + time_t span_ms; /* Get the index position to compare with the 'nowindex' position. Get the oldest entry possible. While we have less than CURR_TIME diff --git a/lib/rand.c b/lib/rand.c new file mode 100644 index 0000000..a51951c --- /dev/null +++ b/lib/rand.c @@ -0,0 +1,130 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include +#include "vtls/vtls.h" +#include "sendf.h" +#include "rand.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +static CURLcode randit(struct Curl_easy *data, unsigned int *rnd) +{ + unsigned int r; + CURLcode result = CURLE_OK; + static unsigned int randseed; + static bool seeded = FALSE; + +#ifdef CURLDEBUG + char *force_entropy = getenv("CURL_ENTROPY"); + if(force_entropy) { + if(!seeded) { + size_t elen = strlen(force_entropy); + size_t clen = sizeof(randseed); + size_t min = elen < clen ? elen : clen; + memcpy((char *)&randseed, force_entropy, min); + seeded = TRUE; + } + else + randseed++; + *rnd = randseed; + return CURLE_OK; + } +#endif + + /* data may be NULL! */ + result = Curl_ssl_random(data, (unsigned char *)rnd, sizeof(*rnd)); + if(result != CURLE_NOT_BUILT_IN) + /* only if there is no random funtion in the TLS backend do the non crypto + version, otherwise return result */ + return result; + + /* ---- non-cryptographic version following ---- */ + +#ifdef RANDOM_FILE + if(!seeded) { + /* if there's a random file to read a seed from, use it */ + int fd = open(RANDOM_FILE, O_RDONLY); + if(fd > -1) { + /* read random data into the randseed variable */ + ssize_t nread = read(fd, &randseed, sizeof(randseed)); + if(nread == sizeof(randseed)) + seeded = TRUE; + close(fd); + } + } +#endif + + if(!seeded) { + struct timeval now = curlx_tvnow(); + infof(data, "WARNING: Using weak random seed\n"); + randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec; + randseed = randseed * 1103515245 + 12345; + randseed = randseed * 1103515245 + 12345; + randseed = randseed * 1103515245 + 12345; + seeded = TRUE; + } + + /* Return an unsigned 32-bit pseudo-random number. */ + r = randseed = randseed * 1103515245 + 12345; + *rnd = (r << 16) | ((r >> 16) & 0xFFFF); + return CURLE_OK; +} + +/* + * Curl_rand() stores 'num' number of random unsigned integers in the buffer + * 'rndptr' points to. + * + * If libcurl is built without TLS support or with a TLS backend that lacks a + * proper random API (Gskit, PolarSSL or mbedTLS), this function will use + * "weak" random. + * + * When built *with* TLS support and a backend that offers strong random, it + * will return error if it cannot provide strong random values. + * + * NOTE: 'data' may be passed in as NULL when coming from external API without + * easy handle! + * + */ + +CURLcode Curl_rand(struct Curl_easy *data, unsigned int *rndptr, + unsigned int num) +{ + CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT; + unsigned int i; + + assert(num > 0); + + for(i = 0; i < num; i++) { + result = randit(data, rndptr++); + if(result) + return result; + } + return result; +} diff --git a/lib/strdup.h b/lib/rand.h similarity index 59% copy from lib/strdup.h copy to lib/rand.h index c74a3b7..0f89861 100644 --- a/lib/strdup.h +++ b/lib/rand.h @@ -1,5 +1,5 @@ -#ifndef HEADER_CURL_STRDUP_H -#define HEADER_CURL_STRDUP_H +#ifndef HEADER_CURL_RAND_H +#define HEADER_CURL_RAND_H /*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | @@ -21,11 +21,23 @@ * KIND, either express or implied. * ***************************************************************************/ -#include "curl_setup.h" -#ifndef HAVE_STRDUP -extern char *curlx_strdup(const char *str); -#endif -void *Curl_memdup(const void *src, size_t buffer_length); +/* + * Curl_rand() stores 'num' number of random unsigned integers in the buffer + * 'rnd' points to. + * + * If libcurl is built without TLS support or with a TLS backend that lacks a + * proper random API (Gskit, PolarSSL or mbedTLS), this function will use + * "weak" random. + * + * When built *with* TLS support and a backend that offers strong random, it + * will return error if it cannot provide strong random values. + * + * NOTE: 'data' may be passed in as NULL when coming from external API without + * easy handle! + * + */ +CURLcode Curl_rand(struct Curl_easy *data, unsigned int *rnd, + unsigned int num); -#endif /* HEADER_CURL_STRDUP_H */ +#endif /* HEADER_CURL_RAND_H */ diff --git a/lib/rtsp.c b/lib/rtsp.c index d1bad19..65c6c3b 100644 --- a/lib/rtsp.c +++ b/lib/rtsp.c @@ -36,6 +36,7 @@ #include "strcase.h" #include "select.h" #include "connect.h" +#include "strdup.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" #include "curl_memory.h" @@ -139,7 +140,7 @@ static CURLcode rtsp_setup_connection(struct connectdata *conn) * want to block the application forever while receiving a stream. Therefore, * we cannot assume that an RTSP socket is dead just because it is readable. * - * Instead, if it is readable, run Curl_getconnectinfo() to peek at the socket + * Instead, if it is readable, run Curl_connalive() to peek at the socket * and distinguish between closed and data. */ bool Curl_rtsp_connisdead(struct connectdata *check) @@ -156,12 +157,9 @@ bool Curl_rtsp_connisdead(struct connectdata *check) /* socket is in an error state */ ret_val = TRUE; } - else if((sval & CURL_CSELECT_IN) && check->data) { - /* readable with no error. could be closed or could be alive but we can - only check if we have a proper Curl_easy for the connection */ - curl_socket_t connectinfo = Curl_getconnectinfo(check->data, &check); - if(connectinfo != CURL_SOCKET_BAD) - ret_val = FALSE; + else if(sval & CURL_CSELECT_IN) { + /* readable with no error. could still be closed */ + ret_val = !Curl_connalive(check); } return ret_val; @@ -488,7 +486,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done) * Free userpwd now --- cannot reuse this for Negotiate and possibly NTLM * with basic and digest, it will be freed anyway by the next request */ - Curl_safefree (conn->allocptr.userpwd); + Curl_safefree(conn->allocptr.userpwd); conn->allocptr.userpwd = NULL; if(result) @@ -614,9 +612,9 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data, if(rtspc->rtp_buf) { /* There was some leftover data the last time. Merge buffers */ - char *newptr = realloc(rtspc->rtp_buf, rtspc->rtp_bufsize + *nread); + char *newptr = Curl_saferealloc(rtspc->rtp_buf, + rtspc->rtp_bufsize + *nread); if(!newptr) { - Curl_safefree(rtspc->rtp_buf); rtspc->rtp_buf = NULL; rtspc->rtp_bufsize = 0; return CURLE_OUT_OF_MEMORY; @@ -736,7 +734,7 @@ CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len) curl_write_callback writeit; if(len == 0) { - failf (data, "Cannot write a 0 size RTP packet."); + failf(data, "Cannot write a 0 size RTP packet."); return CURLE_WRITE_ERROR; } @@ -744,12 +742,12 @@ CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len) wrote = writeit(ptr, 1, len, data->set.rtp_out); if(CURL_WRITEFUNC_PAUSE == wrote) { - failf (data, "Cannot pause RTP"); + failf(data, "Cannot pause RTP"); return CURLE_WRITE_ERROR; } if(wrote != len) { - failf (data, "Failed writing RTP data"); + failf(data, "Failed writing RTP data"); return CURLE_WRITE_ERROR; } diff --git a/lib/security.c b/lib/security.c index ff26066..4a8f444 100644 --- a/lib/security.c +++ b/lib/security.c @@ -62,7 +62,7 @@ #include "sendf.h" #include "strcase.h" #include "warnless.h" - +#include "strdup.h" /* The last #include file should be: */ #include "memdebug.h" @@ -88,7 +88,8 @@ name_to_level(const char *name) /* Convert a protocol |level| to its char representation. We take an int to catch programming mistakes. */ -static char level_to_char(int level) { +static char level_to_char(int level) +{ switch(level) { case PROT_CLEAR: return 'C'; @@ -202,7 +203,7 @@ static CURLcode read_data(struct connectdata *conn, if(len) { /* only realloc if there was a length */ len = ntohl(len); - tmp = realloc(buf->data, len); + tmp = Curl_saferealloc(buf->data, len); } if(tmp == NULL) return CURLE_OUT_OF_MEMORY; @@ -222,7 +223,7 @@ buffer_read(struct krb5buffer *buf, void *data, size_t len) { if(buf->size - buf->index < len) len = buf->size - buf->index; - memcpy(data, (char*)buf->data + buf->index, len); + memcpy(data, (char *)buf->data + buf->index, len); buf->index += len; return len; } @@ -291,7 +292,7 @@ static void do_sec_send(struct connectdata *conn, curl_socket_t fd, prot_level = conn->command_prot; } bytes = conn->mech->encode(conn->app_data, from, length, prot_level, - (void**)&buffer); + (void **)&buffer); if(!buffer || bytes <= 0) return; /* error */ @@ -411,7 +412,7 @@ int Curl_sec_read_msg(struct connectdata *conn, char *buffer, static int sec_set_protection_level(struct connectdata *conn) { int code; - char* pbsz; + char *pbsz; static unsigned int buffer_size = 1 << 20; /* 1048576 */ enum protection_level level = conn->request_data_prot; diff --git a/lib/select.c b/lib/select.c index 26302d9..03af645 100644 --- a/lib/select.c +++ b/lib/select.c @@ -145,7 +145,7 @@ int Curl_wait_ms(int timeout_ms) int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */ curl_socket_t readfd1, curl_socket_t writefd, /* socket to write to */ - long timeout_ms) /* milliseconds to wait */ + time_t timeout_ms) /* milliseconds to wait */ { #ifdef HAVE_POLL_FINE struct pollfd pfd[3]; diff --git a/lib/select.h b/lib/select.h index 1d26f49..e247bd9 100644 --- a/lib/select.h +++ b/lib/select.h @@ -73,7 +73,7 @@ struct pollfd int Curl_socket_check(curl_socket_t readfd, curl_socket_t readfd2, curl_socket_t writefd, - long timeout_ms); + time_t timeout_ms); #define SOCKET_READABLE(x,z) \ Curl_socket_check(x, CURL_SOCKET_BAD, CURL_SOCKET_BAD, z) diff --git a/lib/sendf.c b/lib/sendf.c index 2101797..7601697 100644 --- a/lib/sendf.c +++ b/lib/sendf.c @@ -122,6 +122,13 @@ static size_t convert_lineends(struct Curl_easy *data, #endif /* CURL_DO_LINEEND_CONV */ #ifdef USE_RECV_BEFORE_SEND_WORKAROUND +bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex) +{ + struct postponed_data * const psnd = &(conn->postponed[sockindex]); + return psnd->buffer && psnd->allocated_size && + psnd->recv_size > psnd->recv_processed; +} + static void pre_receive_plain(struct connectdata *conn, int num) { const curl_socket_t sockfd = conn->sock[num]; @@ -201,6 +208,12 @@ static ssize_t get_pre_recved(struct connectdata *conn, int num, char *buf, } #else /* ! USE_RECV_BEFORE_SEND_WORKAROUND */ /* Use "do-nothing" macros instead of functions when workaround not used */ +bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex) +{ + (void)conn; + (void)sockindex; + return false; +} #define pre_receive_plain(c,n) do {} WHILE_FALSE #define get_pre_recved(c,n,b,l) 0 #endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */ @@ -488,7 +501,7 @@ static CURLcode pausewrite(struct Curl_easy *data, */ CURLcode Curl_client_chop_write(struct connectdata *conn, int type, - char * ptr, + char *ptr, size_t len) { struct Curl_easy *data = conn->data; @@ -571,7 +584,7 @@ CURLcode Curl_client_chop_write(struct connectdata *conn, return pausewrite(data, CLIENTWRITE_HEADER, ptr, len); if(wrote != chunklen) { - failf (data, "Failed writing header"); + failf(data, "Failed writing header"); return CURLE_WRITE_ERROR; } } @@ -692,7 +705,7 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */ } /* If we come here, it means that there is no data to read from the buffer, * so we read from the socket */ - bytesfromsocket = CURLMIN(sizerequested, BUFSIZE * sizeof (char)); + bytesfromsocket = CURLMIN(sizerequested, BUFSIZE * sizeof(char)); buffertofill = conn->master_buffer; } else { @@ -796,7 +809,7 @@ int Curl_debug(struct Curl_easy *data, curl_infotype type, char buffer[160]; const char *t=NULL; const char *w="Data"; - switch (type) { + switch(type) { case CURLINFO_HEADER_IN: w = "Header"; /* FALLTHROUGH */ diff --git a/lib/sendf.h b/lib/sendf.h index a951a0b..fbe4f99 100644 --- a/lib/sendf.h +++ b/lib/sendf.h @@ -56,6 +56,8 @@ CURLcode Curl_client_chop_write(struct connectdata *conn, int type, char *ptr, CURLcode Curl_client_write(struct connectdata *conn, int type, char *ptr, size_t len) WARN_UNUSED_RESULT; +bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex); + /* internal read-function, does plain socket only */ CURLcode Curl_read_plain(curl_socket_t sockfd, char *buf, diff --git a/lib/setup-os400.h b/lib/setup-os400.h index e32b72f..a3c2a7b 100644 --- a/lib/setup-os400.h +++ b/lib/setup-os400.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -41,18 +41,18 @@ typedef unsigned long u_int32_t; #include #include -extern int Curl_getaddrinfo_a(const char * nodename, - const char * servname, - const struct addrinfo * hints, - struct addrinfo * * res); +extern int Curl_getaddrinfo_a(const char *nodename, + const char *servname, + const struct addrinfo *hints, + struct addrinfo **res); #define getaddrinfo Curl_getaddrinfo_a -extern int Curl_getnameinfo_a(const struct sockaddr * sa, - curl_socklen_t salen, - char * nodename, curl_socklen_t nodenamelen, - char * servname, curl_socklen_t servnamelen, - int flags); +extern int Curl_getnameinfo_a(const struct sockaddr *sa, + curl_socklen_t salen, + char *nodename, curl_socklen_t nodenamelen, + char *servname, curl_socklen_t servnamelen, + int flags); #define getnameinfo Curl_getnameinfo_a @@ -79,7 +79,7 @@ extern int Curl_gsk_secure_soc_init(gsk_handle my_session_handle); extern int Curl_gsk_attribute_set_buffer_a(gsk_handle my_gsk_handle, GSK_BUF_ID bufID, - const char * buffer, + const char *buffer, int bufSize); #define gsk_attribute_set_buffer Curl_gsk_attribute_set_buffer_a @@ -95,29 +95,29 @@ extern int Curl_gsk_attribute_set_numeric_value(gsk_handle my_gsk_handle, extern int Curl_gsk_attribute_set_callback(gsk_handle my_gsk_handle, GSK_CALLBACK_ID callBackID, - void * callBackAreaPtr); + void *callBackAreaPtr); #define gsk_attribute_set_callback Curl_gsk_attribute_set_callback extern int Curl_gsk_attribute_get_buffer_a(gsk_handle my_gsk_handle, GSK_BUF_ID bufID, - const char * * buffer, - int * bufSize); + const char **buffer, + int *bufSize); #define gsk_attribute_get_buffer Curl_gsk_attribute_get_buffer_a extern int Curl_gsk_attribute_get_enum(gsk_handle my_gsk_handle, GSK_ENUM_ID enumID, - GSK_ENUM_VALUE * enumValue); + GSK_ENUM_VALUE *enumValue); #define gsk_attribute_get_enum Curl_gsk_attribute_get_enum extern int Curl_gsk_attribute_get_numeric_value(gsk_handle my_gsk_handle, GSK_NUM_ID numID, - int * numValue); + int *numValue); #define gsk_attribute_get_numeric_value Curl_gsk_attribute_get_numeric_value extern int Curl_gsk_attribute_get_cert_info(gsk_handle my_gsk_handle, GSK_CERT_ID certID, - const gsk_cert_data_elem * * certDataElem, - int * certDataElementCount); + const gsk_cert_data_elem **certDataElem, + int *certDataElementCount); #define gsk_attribute_get_cert_info Curl_gsk_attribute_get_cert_info extern int Curl_gsk_secure_soc_misc(gsk_handle my_session_handle, @@ -125,13 +125,13 @@ extern int Curl_gsk_secure_soc_misc(gsk_handle my_session_handle, #define gsk_secure_soc_misc Curl_gsk_secure_soc_misc extern int Curl_gsk_secure_soc_read(gsk_handle my_session_handle, - char * readBuffer, - int readBufSize, int * amtRead); + char *readBuffer, + int readBufSize, int *amtRead); #define gsk_secure_soc_read Curl_gsk_secure_soc_read extern int Curl_gsk_secure_soc_write(gsk_handle my_session_handle, - char * writeBuffer, - int writeBufSize, int * amtWritten); + char *writeBuffer, + int writeBufSize, int *amtWritten); #define gsk_secure_soc_write Curl_gsk_secure_soc_write extern const char * Curl_gsk_strerror_a(int gsk_return_value); @@ -202,10 +202,10 @@ extern OM_uint32 Curl_gss_delete_sec_context_a(OM_uint32 * minor_status, extern int Curl_os400_connect(int sd, struct sockaddr * destaddr, int addrlen); extern int Curl_os400_bind(int sd, struct sockaddr * localaddr, int addrlen); -extern int Curl_os400_sendto(int sd, char * buffer, int buflen, int flags, - struct sockaddr * dstaddr, int addrlen); -extern int Curl_os400_recvfrom(int sd, char * buffer, int buflen, int flags, - struct sockaddr * fromaddr, int * addrlen); +extern int Curl_os400_sendto(int sd, char *buffer, int buflen, int flags, + struct sockaddr * dstaddr, int addrlen); +extern int Curl_os400_recvfrom(int sd, char *buffer, int buflen, int flags, + struct sockaddr *fromaddr, int *addrlen); #define connect Curl_os400_connect #define bind Curl_os400_bind diff --git a/lib/setup-vms.h b/lib/setup-vms.h index 4b78e0b..6c454ae 100644 --- a/lib/setup-vms.h +++ b/lib/setup-vms.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -41,7 +41,7 @@ # endif #endif #include - char * decc$getenv(const char * __name); +char *decc$getenv(const char *__name); #include #include @@ -79,23 +79,24 @@ # if __INITIAL_POINTER_SIZE == 32 /* Translate the path, but only if the path is a VMS file specification */ /* The translation is usually only needed for older versions of VMS */ -static char * vms_translate_path(const char * path) { -char * unix_path; -char * test_str; - - /* See if the result is in VMS format, if not, we are done */ - /* Assume that this is a PATH, not just some data */ - test_str = strpbrk(path, ":[<^"); - if(test_str == NULL) { - return (char *)path; - } - - unix_path = decc$translate_vms(path); - - if((int)unix_path <= 0) { - /* We can not translate it, so return the original string */ - return (char *)path; - } +static char *vms_translate_path(const char *path) +{ + char *unix_path; + char *test_str; + + /* See if the result is in VMS format, if not, we are done */ + /* Assume that this is a PATH, not just some data */ + test_str = strpbrk(path, ":[<^"); + if(test_str == NULL) { + return (char *)path; + } + + unix_path = decc$translate_vms(path); + + if((int)unix_path <= 0) { + /* We can not translate it, so return the original string */ + return (char *)path; + } } # else /* VMS translate path is actually not needed on the current 64 bit */ @@ -111,74 +112,74 @@ char * test_str; # endif #endif -static char * vms_getenv(const char * envvar) { +static char *vms_getenv(const char *envvar) +{ + char *result; + char *vms_path; -char * result; -char * vms_path; - - /* first use the DECC getenv() function */ - result = decc$getenv(envvar); - if(result == NULL) { - return result; - } + /* first use the DECC getenv() function */ + result = decc$getenv(envvar); + if(result == NULL) { + return result; + } - vms_path = result; - result = vms_translate_path(vms_path); + vms_path = result; + result = vms_translate_path(vms_path); - /* note that if you backport this to use VAX C RTL, that the VAX C RTL */ - /* may do a malloc(2048) for each call to getenv(), so you will need */ - /* to add a free(vms_path) */ - /* Do not do a free() for DEC C RTL builds, which should be used for */ - /* VMS 5.5-2 and later, even if using GCC */ + /* note that if you backport this to use VAX C RTL, that the VAX C RTL */ + /* may do a malloc(2048) for each call to getenv(), so you will need */ + /* to add a free(vms_path) */ + /* Do not do a free() for DEC C RTL builds, which should be used for */ + /* VMS 5.5-2 and later, even if using GCC */ - return result; + return result; } static struct passwd vms_passwd_cache; -static struct passwd * vms_getpwuid(uid_t uid) { - -struct passwd * my_passwd; +static struct passwd * vms_getpwuid(uid_t uid) +{ + struct passwd * my_passwd; /* Hack needed to support 64 bit builds, decc_getpwnam is 32 bit only */ #ifdef __DECC # if __INITIAL_POINTER_SIZE -__char_ptr32 unix_path; + __char_ptr32 unix_path; # else -char * unix_path; + char *unix_path; # endif #else -char * unix_path; + char *unix_path; #endif - my_passwd = decc_getpwuid(uid); - if(my_passwd == NULL) { - return my_passwd; - } - - unix_path = vms_translate_path(my_passwd->pw_dir); - - if((long)unix_path <= 0) { - /* We can not translate it, so return the original string */ - return my_passwd; - } - - /* If no changes needed just return it */ - if(unix_path == my_passwd->pw_dir) { - return my_passwd; - } - - /* Need to copy the structure returned */ - /* Since curl is only using pw_dir, no need to fix up * - /* the pw_shell when running under Bash */ - vms_passwd_cache.pw_name = my_passwd->pw_name; - vms_passwd_cache.pw_uid = my_passwd->pw_uid; - vms_passwd_cache.pw_gid = my_passwd->pw_uid; - vms_passwd_cache.pw_dir = unix_path; - vms_passwd_cache.pw_shell = my_passwd->pw_shell; - - return &vms_passwd_cache; + my_passwd = decc_getpwuid(uid); + if(my_passwd == NULL) { + return my_passwd; + } + + unix_path = vms_translate_path(my_passwd->pw_dir); + + if((long)unix_path <= 0) { + /* We can not translate it, so return the original string */ + return my_passwd; + } + + /* If no changes needed just return it */ + if(unix_path == my_passwd->pw_dir) { + return my_passwd; + } + + /* Need to copy the structure returned */ + /* Since curl is only using pw_dir, no need to fix up */ + /* the pw_shell when running under Bash */ + vms_passwd_cache.pw_name = my_passwd->pw_name; + vms_passwd_cache.pw_uid = my_passwd->pw_uid; + vms_passwd_cache.pw_gid = my_passwd->pw_uid; + vms_passwd_cache.pw_dir = unix_path; + vms_passwd_cache.pw_shell = my_passwd->pw_shell; + + return &vms_passwd_cache; } #ifdef __DECC diff --git a/lib/share.h b/lib/share.h index e689ff2..c039a16 100644 --- a/lib/share.h +++ b/lib/share.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -54,8 +54,8 @@ struct Curl_share { long sessionage; }; -CURLSHcode Curl_share_lock (struct Curl_easy *, curl_lock_data, - curl_lock_access); -CURLSHcode Curl_share_unlock (struct Curl_easy *, curl_lock_data); +CURLSHcode Curl_share_lock(struct Curl_easy *, curl_lock_data, + curl_lock_access); +CURLSHcode Curl_share_unlock(struct Curl_easy *, curl_lock_data); #endif /* HEADER_CURL_SHARE_H */ diff --git a/lib/smb.c b/lib/smb.c index 7cb0c96..f197fe1 100644 --- a/lib/smb.c +++ b/lib/smb.c @@ -6,7 +6,7 @@ * \___|\___/|_| \_\_____| * * Copyright (C) 2014, Bill Nagel , Exacq Technologies - * Copyright (C) 2015, Daniel Stenberg, , et al. + * Copyright (C) 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -308,8 +308,8 @@ static CURLcode smb_recv_message(struct connectdata *conn, void **msg) if(smbc->got < sizeof(unsigned int)) return CURLE_OK; - nbt_size = Curl_read16_be((unsigned char *)(buf + sizeof(unsigned short))) + - sizeof(unsigned int); + nbt_size = Curl_read16_be((const unsigned char *)(buf + + sizeof(unsigned short))) + sizeof(unsigned int); if(smbc->got < nbt_size) return CURLE_OK; @@ -320,7 +320,7 @@ static CURLcode smb_recv_message(struct connectdata *conn, void **msg) if(nbt_size >= msg_size + sizeof(unsigned short)) { /* Add the byte count */ msg_size += sizeof(unsigned short) + - Curl_read16_le((unsigned char *)&buf[msg_size]); + Curl_read16_le((const unsigned char *)&buf[msg_size]); if(nbt_size < msg_size) return CURLE_READ_ERROR; } @@ -781,9 +781,9 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done) next_state = SMB_CLOSE; break; } - len = Curl_read16_le(((unsigned char *) msg) + + len = Curl_read16_le(((const unsigned char *) msg) + sizeof(struct smb_header) + 11); - off = Curl_read16_le(((unsigned char *) msg) + + off = Curl_read16_le(((const unsigned char *) msg) + sizeof(struct smb_header) + 13); if(len > 0) { if(off + sizeof(unsigned int) + len > smbc->got) { @@ -812,7 +812,7 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done) next_state = SMB_CLOSE; break; } - len = Curl_read16_le(((unsigned char *) msg) + + len = Curl_read16_le(((const unsigned char *) msg) + sizeof(struct smb_header) + 5); conn->data->req.bytecount += len; conn->data->req.offset += len; diff --git a/lib/smtp.c b/lib/smtp.c index a4fc2c2..ff8e80d 100644 --- a/lib/smtp.c +++ b/lib/smtp.c @@ -103,7 +103,7 @@ static CURLcode smtp_parse_custom_request(struct connectdata *conn); static CURLcode smtp_perform_auth(struct connectdata *conn, const char *mech, const char *initresp); static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp); -static void smtp_get_message(char *buffer, char** outptr); +static void smtp_get_message(char *buffer, char **outptr); /* * SMTP protocol handler. @@ -278,10 +278,10 @@ static bool smtp_endofresp(struct connectdata *conn, char *line, size_t len, * * Gets the authentication message from the response buffer. */ -static void smtp_get_message(char *buffer, char** outptr) +static void smtp_get_message(char *buffer, char **outptr) { size_t len = 0; - char* message = NULL; + char *message = NULL; /* Find the start of the message */ for(message = buffer + 4; *message == ' ' || *message == '\t'; message++) diff --git a/lib/socks.c b/lib/socks.c index 742d411..774fb20 100644 --- a/lib/socks.c +++ b/lib/socks.c @@ -57,7 +57,7 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */ ssize_t nread; ssize_t allread = 0; int result; - long timeleft; + time_t timeleft; *n = 0; for(;;) { timeleft = Curl_timeleft(conn->data, NULL, TRUE); @@ -109,9 +109,10 @@ CURLcode Curl_SOCKS4(const char *proxy_name, const char *hostname, int remote_port, int sockindex, - struct connectdata *conn, - bool protocol4a) + struct connectdata *conn) { + const bool protocol4a = + (conn->socks_proxy.proxytype == CURLPROXY_SOCKS4A) ? TRUE : FALSE; #define SOCKS4REQLEN 262 unsigned char socksreq[SOCKS4REQLEN]; /* room for SOCKS4 request incl. user id */ @@ -126,6 +127,10 @@ CURLcode Curl_SOCKS4(const char *proxy_name, return CURLE_OPERATION_TIMEDOUT; } + if(conn->bits.httpproxy) + infof(conn->data, "SOCKS4%s: connecting to HTTP proxy %s port %d\n", + protocol4a ? "a" : "", hostname, remote_port); + (void)curlx_nonblock(sock, FALSE); infof(data, "SOCKS4 communication to %s:%d\n", hostname, remote_port); @@ -174,11 +179,11 @@ CURLcode Curl_SOCKS4(const char *proxy_name, if(hp->ai_family == AF_INET) { struct sockaddr_in *saddr_in; - saddr_in = (struct sockaddr_in*)(void*)hp->ai_addr; - socksreq[4] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[0]; - socksreq[5] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[1]; - socksreq[6] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[2]; - socksreq[7] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[3]; + saddr_in = (struct sockaddr_in *)(void *)hp->ai_addr; + socksreq[4] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[0]; + socksreq[5] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[1]; + socksreq[6] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[2]; + socksreq[7] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[3]; infof(data, "SOCKS4 connect to IPv4 %s (locally resolved)\n", buf); } @@ -219,7 +224,7 @@ CURLcode Curl_SOCKS4(const char *proxy_name, ssize_t written; ssize_t hostnamelen = 0; int packetsize = 9 + - (int)strlen((char*)socksreq + 8); /* size including NUL */ + (int)strlen((char *)socksreq + 8); /* size including NUL */ /* If SOCKS4a, set special invalid IP address 0.0.0.x */ if(protocol4a) { @@ -230,7 +235,7 @@ CURLcode Curl_SOCKS4(const char *proxy_name, /* If still enough room in buffer, also append hostname */ hostnamelen = (ssize_t)strlen(hostname) + 1; /* length including NUL */ if(packetsize + hostnamelen <= SOCKS4REQLEN) - strcpy((char*)socksreq + packetsize, hostname); + strcpy((char *)socksreq + packetsize, hostname); else hostnamelen = 0; /* Flag: hostname did not fit in buffer */ } @@ -376,11 +381,16 @@ CURLcode Curl_SOCKS5(const char *proxy_name, CURLcode code; curl_socket_t sock = conn->sock[sockindex]; struct Curl_easy *data = conn->data; - long timeout; - bool socks5_resolve_local = (conn->proxytype == CURLPROXY_SOCKS5)?TRUE:FALSE; + time_t timeout; + bool socks5_resolve_local = + (conn->socks_proxy.proxytype == CURLPROXY_SOCKS5) ? TRUE : FALSE; const size_t hostname_len = strlen(hostname); ssize_t len = 0; + if(conn->bits.httpproxy) + infof(conn->data, "SOCKS5: connecting to HTTP proxy %s port %d\n", + hostname, remote_port); + /* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */ if(!socks5_resolve_local && hostname_len > 255) { infof(conn->data, "SOCKS5: server resolving disabled for hostnames of " @@ -605,9 +615,9 @@ CURLcode Curl_SOCKS5(const char *proxy_name, struct sockaddr_in *saddr_in; socksreq[len++] = 1; /* ATYP: IPv4 = 1 */ - saddr_in = (struct sockaddr_in*)(void*)hp->ai_addr; + saddr_in = (struct sockaddr_in *)(void *)hp->ai_addr; for(i = 0; i < 4; i++) { - socksreq[len++] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[i]; + socksreq[len++] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[i]; } infof(data, "SOCKS5 connect to IPv4 %s (locally resolved)\n", buf); @@ -617,9 +627,10 @@ CURLcode Curl_SOCKS5(const char *proxy_name, struct sockaddr_in6 *saddr_in6; socksreq[len++] = 4; /* ATYP: IPv6 = 4 */ - saddr_in6 = (struct sockaddr_in6*)(void*)hp->ai_addr; + saddr_in6 = (struct sockaddr_in6 *)(void *)hp->ai_addr; for(i = 0; i < 16; i++) { - socksreq[len++] = ((unsigned char*)&saddr_in6->sin6_addr.s6_addr)[i]; + socksreq[len++] = + ((unsigned char *)&saddr_in6->sin6_addr.s6_addr)[i]; } infof(data, "SOCKS5 connect to IPv6 %s (locally resolved)\n", buf); diff --git a/lib/socks.h b/lib/socks.h index a44ada6..348707e 100644 --- a/lib/socks.h +++ b/lib/socks.h @@ -25,7 +25,7 @@ #include "curl_setup.h" #ifdef CURL_DISABLE_PROXY -#define Curl_SOCKS4(a,b,c,d,e,f) CURLE_NOT_BUILT_IN +#define Curl_SOCKS4(a,b,c,d,e) CURLE_NOT_BUILT_IN #define Curl_SOCKS5(a,b,c,d,e,f) CURLE_NOT_BUILT_IN #else /* @@ -49,8 +49,7 @@ CURLcode Curl_SOCKS4(const char *proxy_name, const char *hostname, int remote_port, int sockindex, - struct connectdata *conn, - bool protocol4a); + struct connectdata *conn); /* * This function logs in to a SOCKS5 proxy and sends the specifics to the diff --git a/lib/socks_gssapi.c b/lib/socks_gssapi.c index 369245a..54d0635 100644 --- a/lib/socks_gssapi.c +++ b/lib/socks_gssapi.c @@ -46,7 +46,7 @@ static gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT; static int check_gss_err(struct Curl_easy *data, OM_uint32 major_status, OM_uint32 minor_status, - const char* function) + const char *function) { if(GSS_ERROR(major_status)) { OM_uint32 maj_stat, min_stat; @@ -65,7 +65,7 @@ static int check_gss_err(struct Curl_easy *data, &msg_ctx, &status_string); if(maj_stat == GSS_S_COMPLETE) { if(sizeof(buf) > len + status_string.length + 1) { - strcpy(buf+len, (char*) status_string.value); + strcpy(buf+len, (char *) status_string.value); len += status_string.length; } gss_release_buffer(&min_stat, &status_string); @@ -86,7 +86,7 @@ static int check_gss_err(struct Curl_easy *data, &msg_ctx, &status_string); if(maj_stat == GSS_S_COMPLETE) { if(sizeof(buf) > len + status_string.length) - strcpy(buf+len, (char*) status_string.value); + strcpy(buf+len, (char *) status_string.value); gss_release_buffer(&min_stat, &status_string); break; } @@ -123,6 +123,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, unsigned char socksreq[4]; /* room for GSS-API exchange header only */ const char *serviceptr = data->set.str[STRING_PROXY_SERVICE_NAME] ? data->set.str[STRING_PROXY_SERVICE_NAME] : "rcmd"; + const size_t serviceptr_length = strlen(serviceptr); /* GSS-API request looks like * +----+------+-----+----------------+ @@ -134,22 +135,23 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, /* prepare service name */ if(strchr(serviceptr, '/')) { - service.value = malloc(strlen(serviceptr)); + service.length = serviceptr_length; + service.value = malloc(service.length); if(!service.value) return CURLE_OUT_OF_MEMORY; - service.length = strlen(serviceptr); memcpy(service.value, serviceptr, service.length); gss_major_status = gss_import_name(&gss_minor_status, &service, (gss_OID) GSS_C_NULL_OID, &server); } else { - service.value = malloc(strlen(serviceptr) +strlen(conn->proxy.name)+2); + service.value = malloc(serviceptr_length + + strlen(conn->socks_proxy.host.name)+2); if(!service.value) return CURLE_OUT_OF_MEMORY; - service.length = strlen(serviceptr) +strlen(conn->proxy.name)+1; + service.length = serviceptr_length + strlen(conn->socks_proxy.host.name)+1; snprintf(service.value, service.length+1, "%s@%s", - serviceptr, conn->proxy.name); + serviceptr, conn->socks_proxy.host.name); gss_major_status = gss_import_name(&gss_minor_status, &service, GSS_C_NT_HOSTBASED_SERVICE, &server); @@ -290,9 +292,9 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, gss_release_name(&gss_status, &server); /* Everything is good so far, user was authenticated! */ - gss_major_status = gss_inquire_context (&gss_minor_status, gss_context, - &gss_client_name, NULL, NULL, NULL, - NULL, NULL, NULL); + gss_major_status = gss_inquire_context(&gss_minor_status, gss_context, + &gss_client_name, NULL, NULL, NULL, + NULL, NULL, NULL); if(check_gss_err(data, gss_major_status, gss_minor_status, "gss_inquire_context")) { gss_delete_sec_context(&gss_status, &gss_context, NULL); diff --git a/lib/socks_sspi.c b/lib/socks_sspi.c index 6053490..edc73ad 100644 --- a/lib/socks_sspi.c +++ b/lib/socks_sspi.c @@ -45,7 +45,7 @@ */ static int check_sspi_err(struct connectdata *conn, SECURITY_STATUS status, - const char* function) + const char *function) { if(status != SEC_E_OK && status != SEC_I_COMPLETE_AND_CONTINUE && @@ -86,6 +86,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, unsigned char socksreq[4]; /* room for GSS-API exchange header only */ const char *service = data->set.str[STRING_PROXY_SERVICE_NAME] ? data->set.str[STRING_PROXY_SERVICE_NAME] : "rcmd"; + const size_t service_length = strlen(service); /* GSS-API request looks like * +----+------+-----+----------------+ @@ -102,11 +103,13 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, return CURLE_OUT_OF_MEMORY; } else { - service_name = malloc(strlen(service) + strlen(conn->proxy.name) + 2); + service_name = malloc(service_length + + strlen(conn->socks_proxy.host.name) + 2); if(!service_name) return CURLE_OUT_OF_MEMORY; - snprintf(service_name, strlen(service) +strlen(conn->proxy.name)+2, - "%s/%s", service, conn->proxy.name); + snprintf(service_name, service_length + + strlen(conn->socks_proxy.host.name)+2, "%s/%s", + service, conn->socks_proxy.host.name); } input_desc.cBuffers = 1; diff --git a/lib/speedcheck.c b/lib/speedcheck.c index 13c34af..bc15d97 100644 --- a/lib/speedcheck.c +++ b/lib/speedcheck.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -40,8 +40,8 @@ CURLcode Curl_speedcheck(struct Curl_easy *data, data->set.low_speed_time && (Curl_tvlong(data->state.keeps_speed) != 0) && (data->progress.current_speed < data->set.low_speed_limit)) { - long howlong = Curl_tvdiff(now, data->state.keeps_speed); - long nextcheck = (data->set.low_speed_time * 1000) - howlong; + time_t howlong = Curl_tvdiff(now, data->state.keeps_speed); + time_t nextcheck = (data->set.low_speed_time * 1000) - howlong; /* We are now below the "low speed limit". If we are below it for "low speed time" seconds we consider that enough reason diff --git a/lib/ssh.c b/lib/ssh.c index 43c8283..5ed036a 100644 --- a/lib/ssh.c +++ b/lib/ssh.c @@ -71,7 +71,7 @@ #include "url.h" #include "speedcheck.h" #include "getinfo.h" - +#include "strdup.h" #include "strcase.h" #include "vtls/vtls.h" #include "connect.h" @@ -239,7 +239,7 @@ kbd_callback(const char *name, int name_len, const char *instruction, static CURLcode sftp_libssh2_error_to_CURLE(int err) { - switch (err) { + switch(err) { case LIBSSH2_FX_OK: return CURLE_OK; @@ -271,7 +271,7 @@ static CURLcode sftp_libssh2_error_to_CURLE(int err) static CURLcode libssh2_session_error_to_CURLE(int err) { - switch (err) { + switch(err) { /* Ordered by order of appearance in libssh2.h */ case LIBSSH2_ERROR_NONE: return CURLE_OK; @@ -676,7 +676,7 @@ static CURLcode ssh_check_fingerprint(struct connectdata *conn) * against a known fingerprint, if available. */ if(pubkey_md5 && strlen(pubkey_md5) == 32) { - if(!fingerprint || strcmp(md5buffer, pubkey_md5)) { + if(!fingerprint || !strcasecompare(md5buffer, pubkey_md5)) { if(fingerprint) failf(data, "Denied establishing ssh session: mismatch md5 fingerprint. " @@ -782,14 +782,14 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) state(conn, SSH_AUTH_DONE); break; } - else if((err = libssh2_session_last_errno(sshc->ssh_session)) == - LIBSSH2_ERROR_EAGAIN) { - rc = LIBSSH2_ERROR_EAGAIN; - break; - } else { - state(conn, SSH_SESSION_FREE); - sshc->actualcode = libssh2_session_error_to_CURLE(err); + err = libssh2_session_last_errno(sshc->ssh_session); + if(err == LIBSSH2_ERROR_EAGAIN) + rc = LIBSSH2_ERROR_EAGAIN; + else { + state(conn, SSH_SESSION_FREE); + sshc->actualcode = libssh2_session_error_to_CURLE(err); + } break; } } @@ -874,7 +874,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) break; } - sshc->passphrase = data->set.str[STRING_KEY_PASSWD]; + sshc->passphrase = data->set.ssl.key_passwd; if(!sshc->passphrase) sshc->passphrase = ""; @@ -1987,12 +1987,14 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) break; } } - if((sshc->readdir_filename = malloc(PATH_MAX+1)) == NULL) { + sshc->readdir_filename = malloc(PATH_MAX+1); + if(!sshc->readdir_filename) { state(conn, SSH_SFTP_CLOSE); sshc->actualcode = CURLE_OUT_OF_MEMORY; break; } - if((sshc->readdir_longentry = malloc(PATH_MAX+1)) == NULL) { + sshc->readdir_longentry = malloc(PATH_MAX+1); + if(!sshc->readdir_longentry) { Curl_safefree(sshc->readdir_filename); state(conn, SSH_SFTP_CLOSE); sshc->actualcode = CURLE_OUT_OF_MEMORY; @@ -2112,9 +2114,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) /* get room for the filename and extra output */ sshc->readdir_totalLen += 4 + sshc->readdir_len; - new_readdir_line = realloc(sshc->readdir_line, sshc->readdir_totalLen); + new_readdir_line = Curl_saferealloc(sshc->readdir_line, + sshc->readdir_totalLen); if(!new_readdir_line) { - Curl_safefree(sshc->readdir_line); + sshc->readdir_line = NULL; Curl_safefree(sshc->readdir_filename); Curl_safefree(sshc->readdir_longentry); state(conn, SSH_SFTP_CLOSE); @@ -2651,7 +2654,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) else if(rc < 0) { infof(data, "Failed to disconnect from libssh2 agent\n"); } - libssh2_agent_free (sshc->ssh_agent); + libssh2_agent_free(sshc->ssh_agent); sshc->ssh_agent = NULL; /* NB: there is no need to free identities, they are part of internal @@ -2788,13 +2791,16 @@ static int ssh_getsock(struct connectdata *conn, static void ssh_block2waitfor(struct connectdata *conn, bool block) { struct ssh_conn *sshc = &conn->proto.sshc; - int dir; - if(block && (dir = libssh2_session_block_directions(sshc->ssh_session))) { - /* translate the libssh2 define bits into our own bit defines */ - conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) | - ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0); + int dir = 0; + if(block) { + dir = libssh2_session_block_directions(sshc->ssh_session); + if(dir) { + /* translate the libssh2 define bits into our own bit defines */ + conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) | + ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0); + } } - else + if(!dir) /* It didn't block or libssh2 didn't reveal in which direction, put back the original set */ conn->waitfor = sshc->orig_waitfor; @@ -2860,8 +2866,8 @@ static CURLcode ssh_block_statemach(struct connectdata *conn, if(LIBSSH2_SESSION_BLOCK_OUTBOUND & dir) fd_write = sock; /* wait for the socket to become ready */ - Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write, - left>1000?1000:left); /* ignore result */ + (void)Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write, + left>1000?1000:left); /* ignore result */ } #endif @@ -3383,7 +3389,7 @@ get_pathname(const char **cpp, char **path) static const char *sftp_libssh2_strerror(int err) { - switch (err) { + switch(err) { case LIBSSH2_FX_NO_SUCH_FILE: return "No such file or directory"; diff --git a/lib/strcase.c b/lib/strcase.c index 807689e..a750f7b 100644 --- a/lib/strcase.c +++ b/lib/strcase.c @@ -34,7 +34,7 @@ char Curl_raw_toupper(char in) if(in >= 'a' && in <= 'z') return (char)('A' + in - 'a'); #else - switch (in) { + switch(in) { case 'a': return 'A'; case 'b': @@ -120,6 +120,16 @@ int Curl_strcasecompare(const char *first, const char *second) return (Curl_raw_toupper(*first) == Curl_raw_toupper(*second)); } +int Curl_safe_strcasecompare(const char *first, const char *second) +{ + if(first && second) + /* both pointers point to something then compare them */ + return Curl_strcasecompare(first, second); + else + /* if both pointers are NULL then treat them as equal */ + return (NULL == first && NULL == second); +} + /* * @unittest: 1301 */ diff --git a/lib/strcase.h b/lib/strcase.h index bf057b1..ea2abc8 100644 --- a/lib/strcase.h +++ b/lib/strcase.h @@ -36,6 +36,7 @@ #define strncasecompare(a,b,c) Curl_strncasecompare(a,b,c) int Curl_strcasecompare(const char *first, const char *second); +int Curl_safe_strcasecompare(const char *first, const char *second); int Curl_strncasecompare(const char *first, const char *second, size_t max); char Curl_raw_toupper(char in); diff --git a/lib/strdup.c b/lib/strdup.c index 5a15c2b..136b693 100644 --- a/lib/strdup.c +++ b/lib/strdup.c @@ -75,3 +75,26 @@ void *Curl_memdup(const void *src, size_t length) return buffer; } + +/*************************************************************************** + * + * Curl_saferealloc(ptr, size) + * + * Does a normal realloc(), but will free the data pointer if the realloc + * fails. If 'size' is zero, it will free the data and return a failure. + * + * This convenience function is provided and used to help us avoid a common + * mistake pattern when we could pass in a zero, catch the NULL return and end + * up free'ing the memory twice. + * + * Returns the new pointer or NULL on failure. + * + ***************************************************************************/ +void *Curl_saferealloc(void *ptr, size_t size) +{ + void *datap = realloc(ptr, size); + if(size && !datap) + /* only free 'ptr' if size was non-zero */ + free(ptr); + return datap; +} diff --git a/lib/strdup.h b/lib/strdup.h index c74a3b7..ae3d5d0 100644 --- a/lib/strdup.h +++ b/lib/strdup.h @@ -27,5 +27,6 @@ extern char *curlx_strdup(const char *str); #endif void *Curl_memdup(const void *src, size_t buffer_length); +void *Curl_saferealloc(void *ptr, size_t size); #endif /* HEADER_CURL_STRDUP_H */ diff --git a/lib/strerror.c b/lib/strerror.c index db50c7d..7e5cde4 100644 --- a/lib/strerror.c +++ b/lib/strerror.c @@ -53,7 +53,7 @@ const char * curl_easy_strerror(CURLcode error) { #ifndef CURL_DISABLE_VERBOSE_STRINGS - switch (error) { + switch(error) { case CURLE_OK: return "No error"; @@ -348,7 +348,7 @@ const char * curl_multi_strerror(CURLMcode error) { #ifndef CURL_DISABLE_VERBOSE_STRINGS - switch (error) { + switch(error) { case CURLM_CALL_MULTI_PERFORM: return "Please call curl_multi_perform() soon"; @@ -393,7 +393,7 @@ const char * curl_share_strerror(CURLSHcode error) { #ifndef CURL_DISABLE_VERBOSE_STRINGS - switch (error) { + switch(error) { case CURLSHE_OK: return "No error"; @@ -435,7 +435,7 @@ get_winsock_error (int err, char *buf, size_t len) const char *p; #ifndef CURL_DISABLE_VERBOSE_STRINGS - switch (err) { + switch(err) { case WSAEINTR: p = "Call interrupted"; break; @@ -609,7 +609,7 @@ get_winsock_error (int err, char *buf, size_t len) else p = "error"; #endif - strncpy (buf, p, len); + strncpy(buf, p, len); buf [len-1] = '\0'; return buf; } @@ -715,10 +715,12 @@ const char *Curl_strerror(struct connectdata *conn, int err) buf[max] = '\0'; /* make sure the string is zero terminated */ /* strip trailing '\r\n' or '\n'. */ - if((p = strrchr(buf, '\n')) != NULL && (p - buf) >= 2) - *p = '\0'; - if((p = strrchr(buf, '\r')) != NULL && (p - buf) >= 1) - *p = '\0'; + p = strrchr(buf, '\n'); + if(p && (p - buf) >= 2) + *p = '\0'; + p = strrchr(buf, '\r'); + if(p && (p - buf) >= 1) + *p = '\0'; if(old_errno != ERRNO) SET_ERRNO(old_errno); @@ -750,7 +752,7 @@ const char *Curl_sspi_strerror (struct connectdata *conn, int err) old_errno = ERRNO; - switch (err) { + switch(err) { case SEC_E_OK: txt = "No error"; break; @@ -1035,10 +1037,12 @@ const char *Curl_sspi_strerror (struct connectdata *conn, int err) if(msg_formatted) { msgbuf[sizeof(msgbuf)-1] = '\0'; /* strip trailing '\r\n' or '\n' */ - if((p = strrchr(msgbuf, '\n')) != NULL && (p - msgbuf) >= 2) - *p = '\0'; - if((p = strrchr(msgbuf, '\r')) != NULL && (p - msgbuf) >= 1) - *p = '\0'; + p = strrchr(msgbuf, '\n'); + if(p && (p - msgbuf) >= 2) + *p = '\0'; + p = strrchr(msgbuf, '\r'); + if(p && (p - msgbuf) >= 1) + *p = '\0'; msg = msgbuf; } if(msg) diff --git a/lib/strtoofft.c b/lib/strtoofft.c index 6d5d2d5..b854bf4 100644 --- a/lib/strtoofft.c +++ b/lib/strtoofft.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -165,7 +165,7 @@ static int get_char(char c, int base) value = c - 'a' + 10; } #else - const char * cp; + const char *cp; int value; cp = memchr(valchars, c, 10 + 26 + 26); diff --git a/lib/telnet.c b/lib/telnet.c index c37242d..551af60 100644 --- a/lib/telnet.c +++ b/lib/telnet.c @@ -91,7 +91,7 @@ #ifdef USE_WINSOCK typedef FARPROC WSOCK2_FUNC; -static CURLcode check_wsock2 (struct Curl_easy *data); +static CURLcode check_wsock2(struct Curl_easy *data); #endif static @@ -935,7 +935,7 @@ static void suboption(struct connectdata *conn) struct TELNET *tn = (struct TELNET *)data->req.protop; printsub(data, '<', (unsigned char *)tn->subbuffer, CURL_SB_LEN(tn)+2); - switch (CURL_SB_GET(tn)) { + switch(CURL_SB_GET(tn)) { case CURL_TELOPT_TTYPE: len = strlen(tn->subopt_ttype) + 4 + 2; snprintf((char *)temp, sizeof(temp), @@ -1004,12 +1004,12 @@ static void sendsuboption(struct connectdata *conn, int option) ssize_t bytes_written; int err; unsigned short x, y; - unsigned char*uc1, *uc2; + unsigned char *uc1, *uc2; struct Curl_easy *data = conn->data; struct TELNET *tn = (struct TELNET *)data->req.protop; - switch (option) { + switch(option) { case CURL_TELOPT_NAWS: /* We prepare data to be sent */ CURL_SB_CLEAR(tn); @@ -1020,8 +1020,8 @@ static void sendsuboption(struct connectdata *conn, int option) /* Window size must be sent according to the 'network order' */ x=htons(tn->subopt_wsx); y=htons(tn->subopt_wsy); - uc1 = (unsigned char*)&x; - uc2 = (unsigned char*)&y; + uc1 = (unsigned char *)&x; + uc2 = (unsigned char *)&y; CURL_SB_ACCUM(tn, uc1[0]); CURL_SB_ACCUM(tn, uc1[1]); CURL_SB_ACCUM(tn, uc2[0]); @@ -1087,7 +1087,7 @@ CURLcode telrcv(struct connectdata *conn, while(count--) { c = inbuf[in]; - switch (tn->telrcv_state) { + switch(tn->telrcv_state) { case CURL_TS_CR: tn->telrcv_state = CURL_TS_DATA; if(c == '\0') { @@ -1111,7 +1111,7 @@ CURLcode telrcv(struct connectdata *conn, case CURL_TS_IAC: process_iac: DEBUGASSERT(startwrite < 0); - switch (c) { + switch(c) { case CURL_WILL: tn->telrcv_state = CURL_TS_WILL; break; @@ -1241,7 +1241,7 @@ static CURLcode send_telnet_data(struct connectdata *conn, struct pollfd pfd[1]; pfd[0].fd = conn->sock[FIRSTSOCKET]; pfd[0].events = POLLOUT; - switch (Curl_poll(pfd, 1, -1)) { + switch(Curl_poll(pfd, 1, -1)) { case -1: /* error, abort writing */ case 0: /* timeout (will never happen) */ result = CURLE_SEND_ERROR; @@ -1489,7 +1489,8 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) events.lNetworkEvents = 0; if(SOCKET_ERROR == enum_netevents_func(sockfd, event_handle, &events)) { - if((err = SOCKERRNO) != EINPROGRESS) { + err = SOCKERRNO; + if(err != EINPROGRESS) { infof(data, "WSAEnumNetworkEvents failed (%d)", err); keepon = FALSE; result = CURLE_READ_ERROR; @@ -1576,7 +1577,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done) } while(keepon) { - switch (Curl_poll(pfd, poll_cnt, interval_ms)) { + switch(Curl_poll(pfd, poll_cnt, interval_ms)) { case -1: /* error, stop reading */ keepon = FALSE; continue; diff --git a/lib/tftp.c b/lib/tftp.c index deee394..f2f8347 100644 --- a/lib/tftp.c +++ b/lib/tftp.c @@ -199,7 +199,7 @@ const struct Curl_handler Curl_handler_tftp = { static CURLcode tftp_set_timeouts(tftp_state_data_t *state) { time_t maxtime, timeout; - long timeout_ms; + time_t timeout_ms; bool start = (state->state == TFTP_STATE_START) ? TRUE : FALSE; time(&state->start_time); @@ -304,7 +304,7 @@ static unsigned short getrpacketblock(const tftp_packet_t *packet) static size_t Curl_strnlen(const char *string, size_t maxlen) { - const char *end = memchr (string, '\0', maxlen); + const char *end = memchr(string, '\0', maxlen); return end ? (size_t) (end - string) : maxlen; } @@ -1356,7 +1356,7 @@ static CURLcode tftp_do(struct connectdata *conn, bool *done) static CURLcode tftp_setup_connection(struct connectdata * conn) { struct Curl_easy *data = conn->data; - char * type; + char *type; char command; conn->socktype = SOCK_DGRAM; /* UDP datagram based */ @@ -1372,7 +1372,7 @@ static CURLcode tftp_setup_connection(struct connectdata * conn) *type = 0; /* it was in the middle of the hostname */ command = Curl_raw_toupper(type[6]); - switch (command) { + switch(command) { case 'A': /* ASCII mode */ case 'N': /* NETASCII mode */ data->set.prefer_ascii = TRUE; diff --git a/lib/timeval.c b/lib/timeval.c index 629f1c8..f3b207a 100644 --- a/lib/timeval.c +++ b/lib/timeval.c @@ -116,7 +116,7 @@ struct timeval curlx_tvnow(void) * Returns: the time difference in number of milliseconds. For large diffs it * returns 0x7fffffff on 32bit time_t systems. */ -long curlx_tvdiff(struct timeval newer, struct timeval older) +time_t curlx_tvdiff(struct timeval newer, struct timeval older) { #if SIZEOF_TIME_T < 8 /* for 32bit time_t systems, add a precaution to avoid overflow for really @@ -126,7 +126,7 @@ long curlx_tvdiff(struct timeval newer, struct timeval older) return 0x7fffffff; #endif return (newer.tv_sec-older.tv_sec)*1000+ - (long)(newer.tv_usec-older.tv_usec)/1000; + (time_t)(newer.tv_usec-older.tv_usec)/1000; } /* @@ -144,7 +144,7 @@ double curlx_tvdiff_secs(struct timeval newer, struct timeval older) } /* return the number of seconds in the given input timeval struct */ -long Curl_tvlong(struct timeval t1) +time_t Curl_tvlong(struct timeval t1) { return t1.tv_sec; } diff --git a/lib/timeval.h b/lib/timeval.h index 50c31a2..09f8b3a 100644 --- a/lib/timeval.h +++ b/lib/timeval.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -37,7 +37,7 @@ struct timeval curlx_tvnow(void); * * Returns: the time difference in number of milliseconds. */ -long curlx_tvdiff(struct timeval t1, struct timeval t2); +time_t curlx_tvdiff(struct timeval t1, struct timeval t2); /* * Same as curlx_tvdiff but with full usec resolution. @@ -46,7 +46,7 @@ long curlx_tvdiff(struct timeval t1, struct timeval t2); */ double curlx_tvdiff_secs(struct timeval t1, struct timeval t2); -long Curl_tvlong(struct timeval t1); +time_t Curl_tvlong(struct timeval t1); /* These two defines below exist to provide the older API for library internals only. */ diff --git a/lib/transfer.c b/lib/transfer.c index 6245ee4..750fb04 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -741,8 +741,8 @@ static CURLcode readwrite_data(struct Curl_easy *data, Make sure that ALL_CONTENT_ENCODINGS contains all the encodings handled here. */ #ifdef HAVE_LIBZ - switch (conn->data->set.http_ce_skip ? - IDENTITY : k->auto_decoding) { + switch(conn->data->set.http_ce_skip ? + IDENTITY : k->auto_decoding) { case IDENTITY: #endif /* This is the default when the server sends no @@ -775,9 +775,9 @@ static CURLcode readwrite_data(struct Curl_easy *data, break; default: - failf (data, "Unrecognized content encoding type. " - "libcurl understands `identity', `deflate' and `gzip' " - "content encodings."); + failf(data, "Unrecognized content encoding type. " + "libcurl understands `identity', `deflate' and `gzip' " + "content encodings."); result = CURLE_BAD_CONTENT_ENCODING; break; } @@ -1137,7 +1137,7 @@ CURLcode Curl_readwrite(struct connectdata *conn, */ - long ms = Curl_tvdiff(k->now, k->start100); + time_t ms = Curl_tvdiff(k->now, k->start100); if(ms >= data->set.expect_100_timeout) { /* we've waited long enough, continue anyway */ k->exp100 = EXP100_SEND_DATA; @@ -1296,7 +1296,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) /* Init the SSL session ID cache here. We do it here since we want to do it after the *_setopt() calls (that could specify the size of the cache) but before any transfer takes place. */ - result = Curl_ssl_initsessions(data, data->set.ssl.max_ssl_sessions); + result = Curl_ssl_initsessions(data, data->set.general_ssl.max_ssl_sessions); if(result) return result; diff --git a/lib/url.c b/lib/url.c index b997f41..7944d7b 100644 --- a/lib/url.c +++ b/lib/url.c @@ -92,6 +92,7 @@ bool curl_win32_idn_to_ascii(const char *in, char **out); #include "warnless.h" #include "non-ascii.h" #include "inet_pton.h" +#include "getinfo.h" /* And now for the protocols */ #include "ftp.h" @@ -463,6 +464,7 @@ CURLcode Curl_close(struct Curl_easy *data) /* this destroys the channel and we cannot use it anymore after this */ Curl_resolver_cleanup(data->state.resolver); + Curl_http2_cleanup_dependencies(data); Curl_convert_close(data); /* No longer a dirty share, if it exists */ @@ -525,9 +527,9 @@ CURLcode Curl_init_userdefined(struct UserDefined *set) set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */ /* Set the default size of the SSL session ID cache */ - set->ssl.max_ssl_sessions = 5; + set->general_ssl.max_ssl_sessions = 5; - set->proxyport = CURL_DEFAULT_PROXY_PORT; /* from url.h */ + set->proxyport = 0; set->proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */ set->httpauth = CURLAUTH_BASIC; /* defaults to basic */ set->proxyauth = CURLAUTH_BASIC; /* defaults to basic */ @@ -539,14 +541,16 @@ CURLcode Curl_init_userdefined(struct UserDefined *set) * libcurl 7.10 introduced SSL verification *by default*! This needs to be * switched off unless wanted. */ - set->ssl.verifypeer = TRUE; - set->ssl.verifyhost = TRUE; + set->ssl.primary.verifypeer = TRUE; + set->ssl.primary.verifyhost = TRUE; #ifdef USE_TLS_SRP set->ssl.authtype = CURL_TLSAUTH_NONE; #endif set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth type */ - set->ssl.sessionid = TRUE; /* session ID caching enabled by default */ + set->general_ssl.sessionid = TRUE; /* session ID caching enabled by + default */ + set->proxy_ssl = set->ssl; set->new_file_perms = 0644; /* Default permissions */ set->new_directory_perms = 0755; /* Default permissions */ @@ -569,14 +573,17 @@ CURLcode Curl_init_userdefined(struct UserDefined *set) /* This is our preferred CA cert bundle/path since install time */ #if defined(CURL_CA_BUNDLE) - result = setstropt(&set->str[STRING_SSL_CAFILE], CURL_CA_BUNDLE); + result = setstropt(&set->str[STRING_SSL_CAFILE_ORIG], CURL_CA_BUNDLE); if(result) return result; #endif #if defined(CURL_CA_PATH) - result = setstropt(&set->str[STRING_SSL_CAPATH], CURL_CA_PATH); + result = setstropt(&set->str[STRING_SSL_CAPATH_ORIG], CURL_CA_PATH); if(result) return result; + + result = setstropt(&set->str[STRING_SSL_CAPATH_PROXY], + (char *) CURL_CA_PATH); #endif set->wildcardmatch = FALSE; @@ -646,6 +653,8 @@ CURLcode Curl_open(struct Curl_easy **curl) Curl_convert_init(data); + Curl_initinfo(data); + /* most recent connection is not yet defined */ data->state.lastconnect = NULL; @@ -694,7 +703,12 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, break; case CURLOPT_SSL_CIPHER_LIST: /* set a list of cipher we want to use in the SSL connection */ - result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST], + result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_ORIG], + va_arg(param, char *)); + break; + case CURLOPT_PROXY_SSL_CIPHER_LIST: + /* set a list of cipher we want to use in the SSL connection for proxy */ + result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_PROXY], va_arg(param, char *)); break; @@ -900,7 +914,18 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, * implementations are lame. */ #ifdef USE_SSL - data->set.ssl.version = va_arg(param, long); + data->set.ssl.primary.version = va_arg(param, long); +#else + result = CURLE_UNKNOWN_OPTION; +#endif + break; + case CURLOPT_PROXY_SSLVERSION: + /* + * Set explicit SSL version to try to connect with for proxy, as some SSL + * implementations are lame. + */ +#ifdef USE_SSL + data->set.proxy_ssl.primary.version = va_arg(param, long); #else result = CURLE_UNKNOWN_OPTION; #endif @@ -1007,7 +1032,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, (data->set.postfieldsize > (curl_off_t)((size_t)-1)))) result = CURLE_OUT_OF_MEMORY; else { - char * p; + char *p; (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL); @@ -1434,18 +1459,30 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, case CURLOPT_PROXY: /* - * Set proxy server:port to use as HTTP proxy. + * Set proxy server:port to use as proxy. * - * If the proxy is set to "" we explicitly say that we don't want to use a - * proxy (even though there might be environment variables saying so). + * If the proxy is set to "" (and CURLOPT_SOCKS_PROXY is set to "" or NULL) + * we explicitly say that we don't want to use a proxy + * (even though there might be environment variables saying so). * * Setting it to NULL, means no proxy but allows the environment variables - * to decide for us. + * to decide for us (if CURLOPT_SOCKS_PROXY setting it to NULL). */ result = setstropt(&data->set.str[STRING_PROXY], va_arg(param, char *)); break; + case CURLOPT_PRE_PROXY: + /* + * Set proxy server:port to use as SOCKS proxy. + * + * If the proxy is set to "" or NULL we explicitly say that we don't want + * to use the socks proxy. + */ + result = setstropt(&data->set.str[STRING_PRE_PROXY], + va_arg(param, char *)); + break; + case CURLOPT_PROXYTYPE: /* * Set proxy type. HTTP/HTTP_1_0/SOCKS4/SOCKS4a/SOCKS5/SOCKS5_HOSTNAME @@ -1457,7 +1494,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, /* * set transfer mode (;type=) when doing FTP via an HTTP proxy */ - switch (va_arg(param, long)) { + switch(va_arg(param, long)) { case 0: data->set.proxy_transfer_mode = FALSE; break; @@ -1910,35 +1947,70 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, /* * String that holds file name of the SSL certificate to use */ - result = setstropt(&data->set.str[STRING_CERT], + result = setstropt(&data->set.str[STRING_CERT_ORIG], + va_arg(param, char *)); + break; + case CURLOPT_PROXY_SSLCERT: + /* + * String that holds file name of the SSL certificate to use for proxy + */ + result = setstropt(&data->set.str[STRING_CERT_PROXY], va_arg(param, char *)); break; case CURLOPT_SSLCERTTYPE: /* * String that holds file type of the SSL certificate to use */ - result = setstropt(&data->set.str[STRING_CERT_TYPE], + result = setstropt(&data->set.str[STRING_CERT_TYPE_ORIG], + va_arg(param, char *)); + break; + case CURLOPT_PROXY_SSLCERTTYPE: + /* + * String that holds file type of the SSL certificate to use for proxy + */ + result = setstropt(&data->set.str[STRING_CERT_TYPE_PROXY], va_arg(param, char *)); break; case CURLOPT_SSLKEY: /* * String that holds file name of the SSL key to use */ - result = setstropt(&data->set.str[STRING_KEY], + result = setstropt(&data->set.str[STRING_KEY_ORIG], + va_arg(param, char *)); + break; + case CURLOPT_PROXY_SSLKEY: + /* + * String that holds file name of the SSL key to use for proxy + */ + result = setstropt(&data->set.str[STRING_KEY_PROXY], va_arg(param, char *)); break; case CURLOPT_SSLKEYTYPE: /* * String that holds file type of the SSL key to use */ - result = setstropt(&data->set.str[STRING_KEY_TYPE], + result = setstropt(&data->set.str[STRING_KEY_TYPE_ORIG], + va_arg(param, char *)); + break; + case CURLOPT_PROXY_SSLKEYTYPE: + /* + * String that holds file type of the SSL key to use for proxy + */ + result = setstropt(&data->set.str[STRING_KEY_TYPE_PROXY], va_arg(param, char *)); break; case CURLOPT_KEYPASSWD: /* * String that holds the SSL or SSH private key password. */ - result = setstropt(&data->set.str[STRING_KEY_PASSWD], + result = setstropt(&data->set.str[STRING_KEY_PASSWD_ORIG], + va_arg(param, char *)); + break; + case CURLOPT_PROXY_KEYPASSWD: + /* + * String that holds the SSL private key password for proxy. + */ + result = setstropt(&data->set.str[STRING_KEY_PASSWD_PROXY], va_arg(param, char *)); break; case CURLOPT_SSLENGINE: @@ -2001,7 +2073,15 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, /* * Enable peer SSL verifying. */ - data->set.ssl.verifypeer = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.ssl.primary.verifypeer = (0 != va_arg(param, long)) ? + TRUE : FALSE; + break; + case CURLOPT_PROXY_SSL_VERIFYPEER: + /* + * Enable peer SSL verifying for proxy. + */ + data->set.proxy_ssl.primary.verifypeer = + (0 != va_arg(param, long))?TRUE:FALSE; break; case CURLOPT_SSL_VERIFYHOST: /* @@ -2019,7 +2099,25 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, return CURLE_BAD_FUNCTION_ARGUMENT; } - data->set.ssl.verifyhost = (0 != arg) ? TRUE : FALSE; + data->set.ssl.primary.verifyhost = (0 != arg) ? TRUE : FALSE; + break; + case CURLOPT_PROXY_SSL_VERIFYHOST: + /* + * Enable verification of the host name in the peer certificate for proxy + */ + arg = va_arg(param, long); + + /* Obviously people are not reading documentation and too many thought + this argument took a boolean when it wasn't and misused it. We thus ban + 1 as a sensible input and we warn about its use. Then we only have the + 2 action internally stored as TRUE. */ + + if(1 == arg) { + failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!"); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + + data->set.proxy_ssl.primary.verifyhost = (0 != arg)?TRUE:FALSE; break; case CURLOPT_SSL_VERIFYSTATUS: /* @@ -2030,7 +2128,8 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, break; } - data->set.ssl.verifystatus = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.ssl.primary.verifystatus = (0 != va_arg(param, long)) ? + TRUE : FALSE; break; case CURLOPT_SSL_CTX_FUNCTION: #ifdef have_curlssl_ssl_ctx @@ -2076,7 +2175,19 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, * Set pinned public key for SSL connection. * Specify file name of the public key in DER format. */ - result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY], + result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG], + va_arg(param, char *)); +#else + result = CURLE_NOT_BUILT_IN; +#endif + break; + case CURLOPT_PROXY_PINNEDPUBLICKEY: +#ifdef have_curlssl_pinnedpubkey /* only by supported backends */ + /* + * Set pinned public key for SSL connection. + * Specify file name of the public key in DER format. + */ + result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY], va_arg(param, char *)); #else result = CURLE_NOT_BUILT_IN; @@ -2086,7 +2197,15 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, /* * Set CA info for SSL connection. Specify file name of the CA certificate */ - result = setstropt(&data->set.str[STRING_SSL_CAFILE], + result = setstropt(&data->set.str[STRING_SSL_CAFILE_ORIG], + va_arg(param, char *)); + break; + case CURLOPT_PROXY_CAINFO: + /* + * Set CA info SSL connection for proxy. Specify file name of the + * CA certificate + */ + result = setstropt(&data->set.str[STRING_SSL_CAFILE_PROXY], va_arg(param, char *)); break; case CURLOPT_CAPATH: @@ -2096,7 +2215,16 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, * certificates which have been prepared using openssl c_rehash utility. */ /* This does not work on windows. */ - result = setstropt(&data->set.str[STRING_SSL_CAPATH], + result = setstropt(&data->set.str[STRING_SSL_CAPATH_ORIG], + va_arg(param, char *)); + break; + case CURLOPT_PROXY_CAPATH: + /* + * Set CA path info for SSL connection proxy. Specify directory name of the + * CA certificates which have been prepared using openssl c_rehash utility. + */ + /* This does not work on windows. */ + result = setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY], va_arg(param, char *)); #else result = CURLE_NOT_BUILT_IN; @@ -2107,7 +2235,15 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, * Set CRL file info for SSL connection. Specify file name of the CRL * to check certificates revocation */ - result = setstropt(&data->set.str[STRING_SSL_CRLFILE], + result = setstropt(&data->set.str[STRING_SSL_CRLFILE_ORIG], + va_arg(param, char *)); + break; + case CURLOPT_PROXY_CRLFILE: + /* + * Set CRL file info for SSL connection for proxy. Specify file name of the + * CRL to check certificates revocation + */ + result = setstropt(&data->set.str[STRING_SSL_CRLFILE_PROXY], va_arg(param, char *)); break; case CURLOPT_ISSUERCERT: @@ -2115,7 +2251,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, * Set Issuer certificate file * to check certificates issuer */ - result = setstropt(&data->set.str[STRING_SSL_ISSUERCERT], + result = setstropt(&data->set.str[STRING_SSL_ISSUERCERT_ORIG], va_arg(param, char *)); break; case CURLOPT_TELNETOPTIONS: @@ -2196,7 +2332,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, } #endif /* CURL_DISABLE_HTTP */ if(data->share->sslsession) { - data->set.ssl.max_ssl_sessions = data->share->max_ssl_sessions; + data->set.general_ssl.max_ssl_sessions = data->share->max_ssl_sessions; data->state.session = data->share->sslsession; } Curl_share_unlock(data, CURL_LOCK_DATA_SHARE); @@ -2231,8 +2367,14 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, case CURLOPT_SSL_OPTIONS: arg = va_arg(param, long); - data->set.ssl_enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST); - data->set.ssl_no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE); + data->set.ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE; + data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE); + break; + + case CURLOPT_PROXY_SSL_OPTIONS: + arg = va_arg(param, long); + data->set.proxy_ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE; + data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE); break; #endif @@ -2328,7 +2470,8 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, break; case CURLOPT_SSL_SESSIONID_CACHE: - data->set.ssl.sessionid = (0 != va_arg(param, long)) ? TRUE : FALSE; + data->set.general_ssl.sessionid = (0 != va_arg(param, long)) ? + TRUE : FALSE; break; #ifdef USE_LIBSSH2 @@ -2595,23 +2738,43 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, break; #ifdef USE_TLS_SRP case CURLOPT_TLSAUTH_USERNAME: - result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME], + result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_ORIG], va_arg(param, char *)); - if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype) + if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype) data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ break; + case CURLOPT_PROXY_TLSAUTH_USERNAME: + result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY], + va_arg(param, char *)); + if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] && + !data->set.proxy_ssl.authtype) + data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ + break; case CURLOPT_TLSAUTH_PASSWORD: - result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD], + result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_ORIG], va_arg(param, char *)); - if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype) + if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype) data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ break; + case CURLOPT_PROXY_TLSAUTH_PASSWORD: + result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY], + va_arg(param, char *)); + if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] && + !data->set.proxy_ssl.authtype) + data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ + break; case CURLOPT_TLSAUTH_TYPE: if(strncasecompare((char *)va_arg(param, char *), "SRP", strlen("SRP"))) data->set.ssl.authtype = CURL_TLSAUTH_SRP; else data->set.ssl.authtype = CURL_TLSAUTH_NONE; break; + case CURLOPT_PROXY_TLSAUTH_TYPE: + if(strncasecompare((char *)va_arg(param, char *), "SRP", strlen("SRP"))) + data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; + else + data->set.proxy_ssl.authtype = CURL_TLSAUTH_NONE; + break; #endif case CURLOPT_DNS_SERVERS: result = Curl_set_dns_servers(data, va_arg(param, char *)); @@ -2678,9 +2841,11 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, return CURLE_NOT_BUILT_IN; #else struct Curl_easy *dep = va_arg(param, struct Curl_easy *); - if(dep && GOOD_EASY_HANDLE(dep)) { - data->set.stream_depends_on = dep; - data->set.stream_depends_e = (option == CURLOPT_STREAM_DEPENDS_E); + if(!dep || GOOD_EASY_HANDLE(dep)) { + if(data->set.stream_depends_on) { + Curl_http2_remove_child(data->set.stream_depends_on, data); + } + Curl_http2_add_child(dep, data, (option == CURLOPT_STREAM_DEPENDS_E)); } break; #endif @@ -2718,10 +2883,10 @@ static void conn_reset_postponed_data(struct connectdata *conn, int num) #endif /* DEBUGBUILD */ } else { - DEBUGASSERT (psnd->allocated_size == 0); - DEBUGASSERT (psnd->recv_size == 0); - DEBUGASSERT (psnd->recv_processed == 0); - DEBUGASSERT (psnd->bindsock == CURL_SOCKET_BAD); + DEBUGASSERT(psnd->allocated_size == 0); + DEBUGASSERT(psnd->recv_size == 0); + DEBUGASSERT(psnd->recv_processed == 0); + DEBUGASSERT(psnd->bindsock == CURL_SOCKET_BAD); } } @@ -2768,8 +2933,10 @@ static void conn_free(struct connectdata *conn) Curl_safefree(conn->passwd); Curl_safefree(conn->oauth_bearer); Curl_safefree(conn->options); - Curl_safefree(conn->proxyuser); - Curl_safefree(conn->proxypasswd); + Curl_safefree(conn->http_proxy.user); + Curl_safefree(conn->socks_proxy.user); + Curl_safefree(conn->http_proxy.passwd); + Curl_safefree(conn->socks_proxy.passwd); Curl_safefree(conn->allocptr.proxyuserpwd); Curl_safefree(conn->allocptr.uagent); Curl_safefree(conn->allocptr.userpwd); @@ -2783,7 +2950,9 @@ static void conn_free(struct connectdata *conn) Curl_safefree(conn->trailer); Curl_safefree(conn->host.rawalloc); /* host name buffer */ Curl_safefree(conn->conn_to_host.rawalloc); /* host name buffer */ - Curl_safefree(conn->proxy.rawalloc); /* proxy name buffer */ + Curl_safefree(conn->secondaryhostname); + Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */ + Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */ Curl_safefree(conn->master_buffer); conn_reset_all_postponed_data(conn); @@ -2795,7 +2964,12 @@ static void conn_free(struct connectdata *conn) conn->recv_pipe = NULL; Curl_safefree(conn->localdev); - Curl_free_ssl_config(&conn->ssl_config); + Curl_free_primary_ssl_config(&conn->ssl_config); + Curl_free_primary_ssl_config(&conn->proxy_ssl_config); + +#ifdef USE_UNIX_SOCKETS + Curl_safefree(conn->unix_domain_socket); +#endif free(conn); /* free all the connection oriented data */ } @@ -2856,6 +3030,8 @@ CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection) free_fixed_hostname(&conn->host); free_fixed_hostname(&conn->conn_to_host); free_fixed_hostname(&conn->proxy); + free_fixed_hostname(&conn->http_proxy.host); + free_fixed_hostname(&conn->socks_proxy.host); Curl_ssl_close(conn, FIRSTSOCKET); @@ -3014,8 +3190,8 @@ Curl_oldest_idle_connection(struct Curl_easy *data) struct curl_hash_iterator iter; struct curl_llist_element *curr; struct curl_hash_element *he; - long highscore=-1; - long score; + time_t highscore=-1; + time_t score; struct timeval now; struct connectdata *conn_candidate = NULL; struct connectbundle *bundle; @@ -3052,6 +3228,21 @@ Curl_oldest_idle_connection(struct Curl_easy *data) return conn_candidate; } +static bool +proxy_info_matches(const struct proxy_info* data, + const struct proxy_info* needle) +{ + if((data->proxytype == needle->proxytype) && + (data->port == needle->port) && + Curl_safe_strcasecompare(data->host.name, needle->host.name) && + Curl_safe_strcasecompare(data->user, needle->user) && + Curl_safe_strcasecompare(data->passwd, needle->passwd)) + return TRUE; + + return FALSE; +} + + /* * This function finds the connection in the connection * bundle that has been unused for the longest time. @@ -3064,8 +3255,8 @@ find_oldest_idle_connection_in_bundle(struct Curl_easy *data, struct connectbundle *bundle) { struct curl_llist_element *curr; - long highscore=-1; - long score; + time_t highscore=-1; + time_t score; struct timeval now; struct connectdata *conn_candidate = NULL; struct connectdata *conn; @@ -3147,7 +3338,7 @@ static int call_disconnect_if_dead(struct connectdata *conn, static void prune_dead_connections(struct Curl_easy *data) { struct timeval now = Curl_tvnow(); - long elapsed = Curl_tvdiff(now, data->state.conn_cache->last_cleanup); + time_t elapsed = Curl_tvdiff(now, data->state.conn_cache->last_cleanup); if(elapsed >= 1000L) { Curl_conncache_foreach(data->state.conn_cache, data, @@ -3326,6 +3517,17 @@ ConnectionExists(struct Curl_easy *data, } } +#ifdef USE_UNIX_SOCKETS + if(needle->unix_domain_socket) { + if(!check->unix_domain_socket) + continue; + if(strcmp(needle->unix_domain_socket, check->unix_domain_socket)) + continue; + } + else if(check->unix_domain_socket) + continue; +#endif + if((needle->handler->flags&PROTOPT_SSL) != (check->handler->flags&PROTOPT_SSL)) /* don't do mixed SSL and non-SSL connections */ @@ -3334,23 +3536,12 @@ ConnectionExists(struct Curl_easy *data, /* except protocols that have been upgraded via TLS */ continue; - if(needle->handler->flags&PROTOPT_SSL) { - if((data->set.ssl.verifypeer != check->verifypeer) || - (data->set.ssl.verifyhost != check->verifyhost)) - continue; - } - - if(needle->bits.proxy != check->bits.proxy) - /* don't do mixed proxy and non-proxy connections */ + if(needle->bits.httpproxy != check->bits.httpproxy || + needle->bits.socksproxy != check->bits.socksproxy) continue; - if(needle->bits.proxy && - (needle->proxytype != check->proxytype || - needle->bits.httpproxy != check->bits.httpproxy || - needle->bits.tunnel_proxy != check->bits.tunnel_proxy || - !strcasecompare(needle->proxy.name, check->proxy.name) || - needle->port != check->port)) - /* don't mix connections that use different proxies */ + if(needle->bits.socksproxy && !proxy_info_matches(&needle->socks_proxy, + &check->socks_proxy)) continue; if(needle->bits.conn_to_host != check->bits.conn_to_host) @@ -3363,6 +3554,33 @@ ConnectionExists(struct Curl_easy *data, * connections that don't use this feature */ continue; + if(needle->bits.httpproxy) { + if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy)) + continue; + + if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy) + continue; + + if(needle->http_proxy.proxytype == CURLPROXY_HTTPS) { + /* use https proxy */ + if(needle->handler->flags&PROTOPT_SSL) { + /* use double layer ssl */ + if(!Curl_ssl_config_matches(&needle->proxy_ssl_config, + &check->proxy_ssl_config)) + continue; + if(check->proxy_ssl[FIRSTSOCKET].state != ssl_connection_complete) + continue; + } + else { + if(!Curl_ssl_config_matches(&needle->ssl_config, + &check->ssl_config)) + continue; + if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete) + continue; + } + } + } + if(!canPipeline && check->inuse) /* this request can't be pipelined but the checked connection is already in use so we skip it */ @@ -3382,9 +3600,8 @@ ConnectionExists(struct Curl_easy *data, */ if((check->localport != needle->localport) || (check->localportrange != needle->localportrange) || - !check->localdev || - !needle->localdev || - strcmp(check->localdev, needle->localdev)) + (needle->localdev && + (!check->localdev || strcmp(check->localdev, needle->localdev)))) continue; } @@ -3399,10 +3616,11 @@ ConnectionExists(struct Curl_easy *data, } if(!needle->bits.httpproxy || (needle->handler->flags&PROTOPT_SSL) || - (needle->bits.httpproxy && needle->bits.tunnel_proxy)) { + needle->bits.tunnel_proxy) { /* The requested connection does not use a HTTP proxy or it uses SSL or - it is a non-SSL protocol tunneled over the same HTTP proxy name and - port number */ + it is a non-SSL protocol tunneled or it is a non-SSL protocol which + is allowed to be upgraded via TLS */ + if((strcasecompare(needle->handler->scheme, check->handler->scheme) || (get_protocol_family(check->handler->protocol) == needle->handler->protocol && check->tls_upgraded)) && @@ -3463,12 +3681,13 @@ ConnectionExists(struct Curl_easy *data, /* Same for Proxy NTLM authentication */ if(wantProxyNTLMhttp) { - /* Both check->proxyuser and check->proxypasswd can be NULL */ - if(!check->proxyuser || !check->proxypasswd) + /* Both check->http_proxy.user and check->http_proxy.passwd can be + * NULL */ + if(!check->http_proxy.user || !check->http_proxy.passwd) continue; - if(strcmp(needle->proxyuser, check->proxyuser) || - strcmp(needle->proxypasswd, check->proxypasswd)) + if(strcmp(needle->http_proxy.user, check->http_proxy.user) || + strcmp(needle->http_proxy.passwd, check->http_proxy.passwd)) continue; } else if(check->proxyntlm.state != NTLMSTATE_NONE) { @@ -3572,51 +3791,48 @@ ConnectionExists(struct Curl_easy *data, Note: this function's sub-functions call failf() */ -CURLcode Curl_connected_proxy(struct connectdata *conn, - int sockindex) +CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex) { - if(!conn->bits.proxy || sockindex) - /* this magic only works for the primary socket as the secondary is used - for FTP only and it has FTP specific magic in ftp.c */ - return CURLE_OK; + CURLcode result = CURLE_OK; - switch(conn->proxytype) { + if(conn->bits.socksproxy) { #ifndef CURL_DISABLE_PROXY - case CURLPROXY_SOCKS5: - case CURLPROXY_SOCKS5_HOSTNAME: - return Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, - conn->bits.conn_to_host ? conn->conn_to_host.name : - conn->host.name, - conn->bits.conn_to_port ? conn->conn_to_port : - conn->remote_port, - FIRSTSOCKET, conn); - - case CURLPROXY_SOCKS4: - return Curl_SOCKS4(conn->proxyuser, - conn->bits.conn_to_host ? conn->conn_to_host.name : - conn->host.name, - conn->bits.conn_to_port ? conn->conn_to_port : - conn->remote_port, - FIRSTSOCKET, conn, FALSE); - - case CURLPROXY_SOCKS4A: - return Curl_SOCKS4(conn->proxyuser, - conn->bits.conn_to_host ? conn->conn_to_host.name : - conn->host.name, - conn->bits.conn_to_port ? conn->conn_to_port : - conn->remote_port, - FIRSTSOCKET, conn, TRUE); + const char * const host = conn->bits.conn_to_host ? + conn->conn_to_host.name : + conn->bits.httpproxy ? + conn->http_proxy.host.name : + sockindex == SECONDARYSOCKET ? + conn->secondaryhostname : conn->host.name; + const int port = conn->bits.conn_to_port ? conn->conn_to_port : + conn->bits.httpproxy ? + (int)conn->http_proxy.port : + sockindex == SECONDARYSOCKET ? + conn->secondary_port : conn->remote_port; + conn->bits.socksproxy_connecting = TRUE; + switch(conn->socks_proxy.proxytype) { + case CURLPROXY_SOCKS5: + case CURLPROXY_SOCKS5_HOSTNAME: + result = Curl_SOCKS5(conn->socks_proxy.user, conn->socks_proxy.passwd, + host, port, sockindex, conn); + break; + case CURLPROXY_SOCKS4: + case CURLPROXY_SOCKS4A: + result = Curl_SOCKS4(conn->socks_proxy.user, host, port, sockindex, + conn); + break; + + default: + failf(conn->data, "unknown proxytype option given"); + result = CURLE_COULDNT_CONNECT; + } /* switch proxytype */ + conn->bits.socksproxy_connecting = FALSE; +#else + (void)sockindex; #endif /* CURL_DISABLE_PROXY */ - case CURLPROXY_HTTP: - case CURLPROXY_HTTP_1_0: - /* do nothing here. handled later. */ - break; - default: - break; - } /* switch proxytype */ + } - return CURLE_OK; + return result; } /* @@ -3627,7 +3843,9 @@ void Curl_verboseconnect(struct connectdata *conn) { if(conn->data->set.verbose) infof(conn->data, "Connected to %s (%s) port %ld (#%ld)\n", - conn->bits.proxy ? conn->proxy.dispname : conn->host.dispname, + conn->bits.socksproxy ? conn->socks_proxy.host.dispname : + conn->bits.httpproxy ? conn->http_proxy.host.dispname : + conn->host.dispname, conn->ip_addr_str, conn->port, conn->connection_id); } #endif @@ -3717,10 +3935,14 @@ CURLcode Curl_protocol_connect(struct connectdata *conn, if(!conn->bits.protoconnstart) { - result = Curl_proxy_connect(conn); + result = Curl_proxy_connect(conn, FIRSTSOCKET); if(result) return result; + if(CONNECT_FIRSTSOCKET_PROXY_SSL()) + /* wait for HTTPS proxy SSL initialization to complete */ + return CURLE_OK; + if(conn->bits.tunnel_proxy && conn->bits.httpproxy && (conn->tunnel_state[FIRSTSOCKET] != TUNNEL_COMPLETE)) /* when using an HTTP tunnel proxy, await complete tunnel establishment @@ -3750,7 +3972,7 @@ CURLcode Curl_protocol_connect(struct connectdata *conn, */ static bool is_ASCII_name(const char *hostname) { - const unsigned char *ch = (const unsigned char*)hostname; + const unsigned char *ch = (const unsigned char *)hostname; while(*ch) { if(*ch++ & 0x80) @@ -3879,12 +4101,14 @@ static struct connectdata *allocate_conn(struct Curl_easy *data) conn->data = data; /* Setup the association between this connection and the Curl_easy */ - conn->proxytype = data->set.proxytype; /* type */ + conn->http_proxy.proxytype = data->set.proxytype; + conn->socks_proxy.proxytype = CURLPROXY_SOCKS4; #ifdef CURL_DISABLE_PROXY conn->bits.proxy = FALSE; conn->bits.httpproxy = FALSE; + conn->bits.socksproxy = FALSE; conn->bits.proxy_user_passwd = FALSE; conn->bits.tunnel_proxy = FALSE; @@ -3895,11 +4119,20 @@ static struct connectdata *allocate_conn(struct Curl_easy *data) conn->bits.proxy = (data->set.str[STRING_PROXY] && *data->set.str[STRING_PROXY]) ? TRUE : FALSE; conn->bits.httpproxy = (conn->bits.proxy && - (conn->proxytype == CURLPROXY_HTTP || - conn->proxytype == CURLPROXY_HTTP_1_0)) ? - TRUE : FALSE; - conn->bits.proxy_user_passwd = (data->set.str[STRING_PROXYUSERNAME]) ? - TRUE : FALSE; + (conn->http_proxy.proxytype == CURLPROXY_HTTP || + conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0 || + conn->http_proxy.proxytype == CURLPROXY_HTTPS)) ? + TRUE : FALSE; + conn->bits.socksproxy = (conn->bits.proxy && + !conn->bits.httpproxy) ? TRUE : FALSE; + + if(data->set.str[STRING_PRE_PROXY] && *data->set.str[STRING_PRE_PROXY]) { + conn->bits.proxy = TRUE; + conn->bits.socksproxy = TRUE; + } + + conn->bits.proxy_user_passwd = + (data->set.str[STRING_PROXYUSERNAME]) ? TRUE : FALSE; conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy; #endif /* CURL_DISABLE_PROXY */ @@ -3908,8 +4141,10 @@ static struct connectdata *allocate_conn(struct Curl_easy *data) conn->bits.ftp_use_epsv = data->set.ftp_use_epsv; conn->bits.ftp_use_eprt = data->set.ftp_use_eprt; - conn->verifypeer = data->set.ssl.verifypeer; - conn->verifyhost = data->set.ssl.verifyhost; + conn->ssl_config.verifypeer = data->set.ssl.primary.verifypeer; + conn->ssl_config.verifyhost = data->set.ssl.primary.verifyhost; + conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer; + conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost; conn->ip_version = data->set.ipver; @@ -3924,7 +4159,7 @@ static struct connectdata *allocate_conn(struct Curl_easy *data) if(Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1) && !conn->master_buffer) { /* Allocate master_buffer to be used for HTTP/1 pipelining */ - conn->master_buffer = calloc(BUFSIZE, sizeof (char)); + conn->master_buffer = calloc(BUFSIZE, sizeof(char)); if(!conn->master_buffer) goto error; } @@ -4065,33 +4300,38 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, * the URL protocols specified in RFC 1738 */ if(path[0] != '/') { - /* the URL included a host name, we ignore host names in file:// URLs - as the standards don't define what to do with them */ - char *ptr=strchr(path, '/'); - if(ptr) { - /* there was a slash present - - RFC1738 (section 3.1, page 5) says: - - The rest of the locator consists of data specific to the scheme, - and is known as the "url-path". It supplies the details of how the - specified resource can be accessed. Note that the "/" between the - host (or port) and the url-path is NOT part of the url-path. - - As most agents use file://localhost/foo to get '/foo' although the - slash preceding foo is a separator and not a slash for the path, - a URL as file://localhost//foo must be valid as well, to refer to - the same file with an absolute path. - */ + /* the URL includes a host name, it must match "localhost" or + "127.0.0.1" to be valid */ + char *ptr; + if(!checkprefix("localhost/", path) && + !checkprefix("127.0.0.1/", path)) { + failf(data, "Valid host name with slash missing in URL"); + return CURLE_URL_MALFORMAT; + } + ptr = &path[9]; /* now points to the slash after the host */ - if(ptr[1] && ('/' == ptr[1])) - /* if there was two slashes, we skip the first one as that is then - used truly as a separator */ - ptr++; + /* there was a host name and slash present - /* This cannot be made with strcpy, as the memory chunks overlap! */ - memmove(path, ptr, strlen(ptr)+1); - } + RFC1738 (section 3.1, page 5) says: + + The rest of the locator consists of data specific to the scheme, + and is known as the "url-path". It supplies the details of how the + specified resource can be accessed. Note that the "/" between the + host (or port) and the url-path is NOT part of the url-path. + + As most agents use file://localhost/foo to get '/foo' although the + slash preceding foo is a separator and not a slash for the path, + a URL as file://localhost//foo must be valid as well, to refer to + the same file with an absolute path. + */ + + if('/' == ptr[1]) + /* if there was two slashes, we skip the first one as that is then + used truly as a separator */ + ptr++; + + /* This cannot be made with strcpy, as the memory chunks overlap! */ + memmove(path, ptr, strlen(ptr)+1); } protop = "file"; /* protocol string */ @@ -4473,7 +4713,7 @@ void Curl_free_request_state(struct Curl_easy *data) * Checks if the host is in the noproxy list. returns true if it matches * and therefore the proxy should NOT be used. ****************************************************************/ -static bool check_noproxy(const char* name, const char* no_proxy) +static bool check_noproxy(const char *name, const char *no_proxy) { /* no_proxy=domain1.dom,host.domain2.dom * (a comma-separated list of hosts which should @@ -4482,7 +4722,7 @@ static bool check_noproxy(const char* name, const char* no_proxy) */ size_t tok_start; size_t tok_end; - const char* separator = ", "; + const char *separator = ", "; size_t no_proxy_len; size_t namelen; char *endptr; @@ -4636,7 +4876,8 @@ static char *detect_proxy(struct connectdata *conn) * that may exist registered to the same proxy host. */ static CURLcode parse_proxy(struct Curl_easy *data, - struct connectdata *conn, char *proxy) + struct connectdata *conn, char *proxy, + curl_proxytype proxytype) { char *prox_portno; char *endofprot; @@ -4645,6 +4886,10 @@ static CURLcode parse_proxy(struct Curl_easy *data, char *proxyptr; char *portptr; char *atsign; + long port = -1; + char *proxyuser = NULL; + char *proxypasswd = NULL; + bool sockstype; /* We do the proxy host string parsing here. We want the host name and the * port name. Accept a protocol:// prefix @@ -4654,14 +4899,16 @@ static CURLcode parse_proxy(struct Curl_easy *data, endofprot = strstr(proxy, "://"); if(endofprot) { proxyptr = endofprot+3; - if(checkprefix("socks5h", proxy)) - conn->proxytype = CURLPROXY_SOCKS5_HOSTNAME; + if(checkprefix("https", proxy)) + proxytype = CURLPROXY_HTTPS; + else if(checkprefix("socks5h", proxy)) + proxytype = CURLPROXY_SOCKS5_HOSTNAME; else if(checkprefix("socks5", proxy)) - conn->proxytype = CURLPROXY_SOCKS5; + proxytype = CURLPROXY_SOCKS5; else if(checkprefix("socks4a", proxy)) - conn->proxytype = CURLPROXY_SOCKS4A; + proxytype = CURLPROXY_SOCKS4A; else if(checkprefix("socks4", proxy) || checkprefix("socks", proxy)) - conn->proxytype = CURLPROXY_SOCKS4; + proxytype = CURLPROXY_SOCKS4; else if(checkprefix("http:", proxy)) ; /* leave it as HTTP or HTTP/1.0 */ else { @@ -4673,54 +4920,28 @@ static CURLcode parse_proxy(struct Curl_easy *data, else proxyptr = proxy; /* No xxx:// head: It's a HTTP proxy */ +#ifndef HTTPS_PROXY_SUPPORT + if(proxytype == CURLPROXY_HTTPS) { + failf(data, "Unsupported proxy \'%s\'" + ", libcurl is built without the HTTPS-proxy support.", proxy); + return CURLE_NOT_BUILT_IN; + } +#endif + + sockstype = proxytype == CURLPROXY_SOCKS5_HOSTNAME || + proxytype == CURLPROXY_SOCKS5 || + proxytype == CURLPROXY_SOCKS4A || + proxytype == CURLPROXY_SOCKS4; + /* Is there a username and password given in this proxy url? */ atsign = strchr(proxyptr, '@'); if(atsign) { - char *proxyuser = NULL; - char *proxypasswd = NULL; CURLcode result = parse_login_details(proxyptr, atsign - proxyptr, - &proxyuser, &proxypasswd, NULL); - if(!result) { - /* found user and password, rip them out. note that we are - unescaping them, as there is otherwise no way to have a - username or password with reserved characters like ':' in - them. */ - Curl_safefree(conn->proxyuser); - if(proxyuser && strlen(proxyuser) < MAX_CURL_USER_LENGTH) - result = Curl_urldecode(data, proxyuser, 0, &conn->proxyuser, NULL, - FALSE); - else { - conn->proxyuser = strdup(""); - if(!conn->proxyuser) - result = CURLE_OUT_OF_MEMORY; - } - - if(!result) { - Curl_safefree(conn->proxypasswd); - if(proxypasswd && strlen(proxypasswd) < MAX_CURL_PASSWORD_LENGTH) - result = Curl_urldecode(data, proxypasswd, 0, - &conn->proxypasswd, NULL, FALSE); - else { - conn->proxypasswd = strdup(""); - if(!conn->proxypasswd) - result = CURLE_OUT_OF_MEMORY; - } - } - - if(!result) { - conn->bits.proxy_user_passwd = TRUE; /* enable it */ - atsign++; /* the right side of the @-letter */ - - proxyptr = atsign; /* now use this instead */ - } - } - - free(proxyuser); - free(proxypasswd); - + &proxyuser, &proxypasswd, NULL); if(result) return result; + proxyptr = atsign + 1; } /* start scanning for port number at this point */ @@ -4757,7 +4978,7 @@ static CURLcode parse_proxy(struct Curl_easy *data, prox_portno = strchr(portptr, ':'); if(prox_portno) { char *endp = NULL; - long port = 0; + *prox_portno = 0x0; /* cut off number from host name */ prox_portno ++; /* now set the local port number */ @@ -4791,15 +5012,59 @@ static CURLcode parse_proxy(struct Curl_easy *data, if(data->set.proxyport) /* None given in the proxy string, then get the default one if it is given */ - conn->port = data->set.proxyport; + port = data->set.proxyport; + else { + if(proxytype == CURLPROXY_HTTPS) + port = CURL_DEFAULT_HTTPS_PROXY_PORT; + else + port = CURL_DEFAULT_PROXY_PORT; + } } - /* now, clone the cleaned proxy host name */ - conn->proxy.rawalloc = strdup(proxyptr); - conn->proxy.name = conn->proxy.rawalloc; + if(*proxyptr) { + struct proxy_info *proxyinfo = + sockstype ? &conn->socks_proxy : &conn->http_proxy; + proxyinfo->proxytype = proxytype; - if(!conn->proxy.rawalloc) - return CURLE_OUT_OF_MEMORY; + if(proxyuser) { + /* found user and password, rip them out. note that we are unescaping + them, as there is otherwise no way to have a username or password + with reserved characters like ':' in them. */ + Curl_safefree(proxyinfo->user); + proxyinfo->user = curl_easy_unescape(data, proxyuser, 0, NULL); + + if(!proxyinfo->user) + return CURLE_OUT_OF_MEMORY; + + Curl_safefree(proxyinfo->passwd); + if(proxypasswd && strlen(proxypasswd) < MAX_CURL_PASSWORD_LENGTH) + proxyinfo->passwd = curl_easy_unescape(data, proxypasswd, 0, NULL); + else + proxyinfo->passwd = strdup(""); + + if(!proxyinfo->passwd) + return CURLE_OUT_OF_MEMORY; + + conn->bits.proxy_user_passwd = TRUE; /* enable it */ + } + + if(port >= 0) { + proxyinfo->port = port; + if(conn->port < 0 || sockstype || !conn->socks_proxy.host.rawalloc) + conn->port = port; + } + + /* now, clone the cleaned proxy host name */ + Curl_safefree(proxyinfo->host.rawalloc); + proxyinfo->host.rawalloc = strdup(proxyptr); + proxyinfo->host.name = proxyinfo->host.rawalloc; + + if(!proxyinfo->host.rawalloc) + return CURLE_OUT_OF_MEMORY; + } + + Curl_safefree(proxyuser); + Curl_safefree(proxypasswd); return CURLE_OK; } @@ -4825,10 +5090,11 @@ static CURLcode parse_proxy_auth(struct Curl_easy *data, proxypasswd[MAX_CURL_PASSWORD_LENGTH-1] = '\0'; /*To be on safe side*/ } - result = Curl_urldecode(data, proxyuser, 0, &conn->proxyuser, NULL, FALSE); + result = Curl_urldecode(data, proxyuser, 0, &conn->http_proxy.user, NULL, + FALSE); if(!result) - result = Curl_urldecode(data, proxypasswd, 0, &conn->proxypasswd, NULL, - FALSE); + result = Curl_urldecode(data, proxypasswd, 0, &conn->http_proxy.passwd, + NULL, FALSE); return result; } #endif /* CURL_DISABLE_PROXY */ @@ -5180,11 +5446,16 @@ static CURLcode parse_remote_port(struct Curl_easy *data, *portptr = '\0'; /* cut off the name there */ conn->remote_port = curlx_ultous(port); } - else + else { + if(rest[0]) { + failf(data, "Illegal port number"); + return CURLE_URL_MALFORMAT; + } /* Browser behavior adaptation. If there's a colon with no digits after, just cut off the name there which makes us ignore the colon and just use the default port. Firefox and Chrome both do that. */ *portptr = '\0'; + } } /* only if remote_port was not already parsed off the URL we use the @@ -5404,6 +5675,9 @@ static CURLcode parse_connect_to_string(struct Curl_easy *data, int host_match = FALSE; int port_match = FALSE; + *host_result = NULL; + *port_result = -1; + if(*ptr == ':') { /* an empty hostname always matches */ host_match = TRUE; @@ -5466,9 +5740,9 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data, { CURLcode result = CURLE_OK; char *host = NULL; - int port = 0; + int port = -1; - while(conn_to_host && !host) { + while(conn_to_host && !host && port == -1) { result = parse_connect_to_string(data, conn, conn_to_host->data, &host, &port); if(result) @@ -5487,7 +5761,7 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data, else { /* no "connect to host" */ conn->bits.conn_to_host = FALSE; - free(host); + Curl_safefree(host); } if(port >= 0) { @@ -5498,6 +5772,7 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data, else { /* no "connect to port" */ conn->bits.conn_to_port = FALSE; + port = -1; } conn_to_host = conn_to_host->next; @@ -5514,7 +5789,7 @@ static CURLcode resolve_server(struct Curl_easy *data, bool *async) { CURLcode result=CURLE_OK; - long timeout_ms = Curl_timeleft(data, NULL, TRUE); + time_t timeout_ms = Curl_timeleft(data, NULL, TRUE); /************************************************************* * Resolve the name of the server or proxy @@ -5531,32 +5806,36 @@ static CURLcode resolve_server(struct Curl_easy *data, struct Curl_dns_entry *hostaddr; #ifdef USE_UNIX_SOCKETS - if(data->set.str[STRING_UNIX_SOCKET_PATH]) { + if(conn->unix_domain_socket) { /* Unix domain sockets are local. The host gets ignored, just use the * specified domain socket address. Do not cache "DNS entries". There is * no DNS involved and we already have the filesystem path available */ - const char *path = data->set.str[STRING_UNIX_SOCKET_PATH]; + const char *path = conn->unix_domain_socket; hostaddr = calloc(1, sizeof(struct Curl_dns_entry)); if(!hostaddr) result = CURLE_OUT_OF_MEMORY; - else if((hostaddr->addr = Curl_unix2addr(path)) != NULL) - hostaddr->inuse++; else { - /* Long paths are not supported for now */ - if(strlen(path) >= sizeof(((struct sockaddr_un *)0)->sun_path)) { - failf(data, "Unix socket path too long: '%s'", path); - result = CURLE_COULDNT_RESOLVE_HOST; + int longpath=0; + hostaddr->addr = Curl_unix2addr(path, &longpath); + if(hostaddr->addr) + hostaddr->inuse++; + else { + /* Long paths are not supported for now */ + if(longpath) { + failf(data, "Unix socket path too long: '%s'", path); + result = CURLE_COULDNT_RESOLVE_HOST; + } + else + result = CURLE_OUT_OF_MEMORY; + free(hostaddr); + hostaddr = NULL; } - else - result = CURLE_OUT_OF_MEMORY; - free(hostaddr); - hostaddr = NULL; } } else #endif - if(!conn->proxy.name || !*conn->proxy.name) { + if(!conn->bits.proxy) { struct hostname *connhost; if(conn->bits.conn_to_host) connhost = &conn->conn_to_host; @@ -5588,8 +5867,11 @@ static CURLcode resolve_server(struct Curl_easy *data, else { /* This is a proxy that hasn't been resolved yet. */ + struct hostname * const host = conn->bits.socksproxy ? + &conn->socks_proxy.host : &conn->http_proxy.host; + /* resolve proxy */ - rc = Curl_resolv_timeout(conn, conn->proxy.name, (int)conn->port, + rc = Curl_resolv_timeout(conn, host->name, (int)conn->port, &hostaddr, timeout_ms); if(rc == CURLRESOLV_PENDING) @@ -5599,7 +5881,7 @@ static CURLcode resolve_server(struct Curl_easy *data, result = CURLE_OPERATION_TIMEDOUT; else if(!hostaddr) { - failf(data, "Couldn't resolve proxy '%s'", conn->proxy.dispname); + failf(data, "Couldn't resolve proxy '%s'", host->dispname); result = CURLE_COULDNT_RESOLVE_PROXY; /* don't return yet, we need to clean up the timeout first */ } @@ -5619,12 +5901,18 @@ static CURLcode resolve_server(struct Curl_easy *data, static void reuse_conn(struct connectdata *old_conn, struct connectdata *conn) { + free_fixed_hostname(&old_conn->http_proxy.host); + free_fixed_hostname(&old_conn->socks_proxy.host); free_fixed_hostname(&old_conn->proxy); + + free(old_conn->http_proxy.host.rawalloc); + free(old_conn->socks_proxy.host.rawalloc); free(old_conn->proxy.rawalloc); /* free the SSL config struct from this connection struct as this was allocated in vain and is targeted for destruction */ - Curl_free_ssl_config(&old_conn->ssl_config); + Curl_free_primary_ssl_config(&old_conn->ssl_config); + Curl_free_primary_ssl_config(&old_conn->proxy_ssl_config); conn->data = old_conn->data; @@ -5644,12 +5932,18 @@ static void reuse_conn(struct connectdata *old_conn, conn->bits.proxy_user_passwd = old_conn->bits.proxy_user_passwd; if(conn->bits.proxy_user_passwd) { /* use the new proxy user name and proxy password though */ - Curl_safefree(conn->proxyuser); - Curl_safefree(conn->proxypasswd); - conn->proxyuser = old_conn->proxyuser; - conn->proxypasswd = old_conn->proxypasswd; - old_conn->proxyuser = NULL; - old_conn->proxypasswd = NULL; + Curl_safefree(conn->http_proxy.user); + Curl_safefree(conn->socks_proxy.user); + Curl_safefree(conn->http_proxy.passwd); + Curl_safefree(conn->socks_proxy.passwd); + conn->http_proxy.user = old_conn->http_proxy.user; + conn->socks_proxy.user = old_conn->socks_proxy.user; + conn->http_proxy.passwd = old_conn->http_proxy.passwd; + conn->socks_proxy.passwd = old_conn->socks_proxy.passwd; + old_conn->http_proxy.user = NULL; + old_conn->socks_proxy.user = NULL; + old_conn->http_proxy.passwd = NULL; + old_conn->socks_proxy.passwd = NULL; } /* host can change, when doing keepalive with a proxy or if the case is @@ -5675,8 +5969,10 @@ static void reuse_conn(struct connectdata *old_conn, Curl_safefree(old_conn->user); Curl_safefree(old_conn->passwd); - Curl_safefree(old_conn->proxyuser); - Curl_safefree(old_conn->proxypasswd); + Curl_safefree(old_conn->http_proxy.user); + Curl_safefree(old_conn->socks_proxy.user); + Curl_safefree(old_conn->http_proxy.passwd); + Curl_safefree(old_conn->socks_proxy.passwd); Curl_safefree(old_conn->localdev); Curl_llist_destroy(old_conn->send_pipe, NULL); @@ -5686,6 +5982,10 @@ static void reuse_conn(struct connectdata *old_conn, old_conn->recv_pipe = NULL; Curl_safefree(old_conn->master_buffer); + +#ifdef USE_UNIX_SOCKETS + Curl_safefree(old_conn->unix_domain_socket); +#endif } /** @@ -5717,6 +6017,7 @@ static CURLcode create_conn(struct Curl_easy *data, char *options = NULL; bool reuse; char *proxy = NULL; + char *socksproxy = NULL; bool prot_missing = FALSE; bool connections_available = TRUE; bool force_reuse = FALSE; @@ -5883,18 +6184,35 @@ static CURLcode create_conn(struct Curl_easy *data, } } + if(data->set.str[STRING_PRE_PROXY]) { + socksproxy = strdup(data->set.str[STRING_PRE_PROXY]); + /* if global socks proxy is set, this is it */ + if(NULL == socksproxy) { + failf(data, "memory shortage"); + result = CURLE_OUT_OF_MEMORY; + goto out; + } + } + if(data->set.str[STRING_NOPROXY] && check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY])) { - free(proxy); /* proxy is in exception list */ - proxy = NULL; + Curl_safefree(proxy); + Curl_safefree(socksproxy); } - else if(!proxy) + else if(!proxy && !socksproxy) proxy = detect_proxy(conn); #ifdef USE_UNIX_SOCKETS - if(proxy && data->set.str[STRING_UNIX_SOCKET_PATH]) { - free(proxy); /* Unix domain sockets cannot be proxied, so disable it */ - proxy = NULL; + if(data->set.str[STRING_UNIX_SOCKET_PATH]) { + if(proxy) { + free(proxy); /* Unix domain sockets cannot be proxied, so disable it */ + proxy = NULL; + } + conn->unix_domain_socket = strdup(data->set.str[STRING_UNIX_SOCKET_PATH]); + if(conn->unix_domain_socket == NULL) { + result = CURLE_OUT_OF_MEMORY; + goto out; + } } #endif @@ -5903,23 +6221,36 @@ static CURLcode create_conn(struct Curl_easy *data, protocol doesn't work with network */ proxy = NULL; } + if(socksproxy && (!*socksproxy || + (conn->handler->flags & PROTOPT_NONETWORK))) { + free(socksproxy); /* Don't bother with an empty socks proxy string or if + the protocol doesn't work with network */ + socksproxy = NULL; + } /*********************************************************************** * If this is supposed to use a proxy, we need to figure out the proxy host * name, proxy type and port number, so that we can re-use an existing * connection that may exist registered to the same proxy host. ***********************************************************************/ - if(proxy) { - result = parse_proxy(data, conn, proxy); - - free(proxy); /* parse_proxy copies the proxy string */ - proxy = NULL; + if(proxy || socksproxy) { + if(proxy) { + result = parse_proxy(data, conn, proxy, conn->http_proxy.proxytype); + Curl_safefree(proxy); /* parse_proxy copies the proxy string */ + if(result) + goto out; + } - if(result) - goto out; + if(socksproxy) { + result = parse_proxy(data, conn, socksproxy, + conn->socks_proxy.proxytype); + /* parse_proxy copies the socks proxy string */ + Curl_safefree(socksproxy); + if(result) + goto out; + } - if((conn->proxytype == CURLPROXY_HTTP) || - (conn->proxytype == CURLPROXY_HTTP_1_0)) { + if(conn->http_proxy.host.rawalloc) { #ifdef CURL_DISABLE_HTTP /* asking for a HTTP proxy is a bit funny when HTTP is disabled... */ result = CURLE_UNSUPPORTED_PROTOCOL; @@ -5938,12 +6269,34 @@ static CURLcode create_conn(struct Curl_easy *data, conn->bits.httpproxy = FALSE; /* not a HTTP proxy */ conn->bits.tunnel_proxy = FALSE; /* no tunneling if not HTTP */ } - conn->bits.proxy = TRUE; + + if(conn->socks_proxy.host.rawalloc) { + if(!conn->http_proxy.host.rawalloc) { + /* once a socks proxy */ + if(!conn->socks_proxy.user) { + conn->socks_proxy.user = conn->http_proxy.user; + conn->http_proxy.user = NULL; + Curl_safefree(conn->socks_proxy.passwd); + conn->socks_proxy.passwd = conn->http_proxy.passwd; + conn->http_proxy.passwd = NULL; + } + } + conn->bits.socksproxy = TRUE; + } + else + conn->bits.socksproxy = FALSE; /* not a socks proxy */ } else { + conn->bits.socksproxy = FALSE; + conn->bits.httpproxy = FALSE; + } + conn->bits.proxy = conn->bits.httpproxy || conn->bits.socksproxy; + + if(!conn->bits.proxy) { /* we aren't using the proxy after all... */ conn->bits.proxy = FALSE; conn->bits.httpproxy = FALSE; + conn->bits.socksproxy = FALSE; conn->bits.proxy_user_passwd = FALSE; conn->bits.tunnel_proxy = FALSE; } @@ -6079,20 +6432,51 @@ static CURLcode create_conn(struct Curl_easy *data, that will be freed as part of the Curl_easy struct, but all cloned copies will be separately allocated. */ - data->set.ssl.CApath = data->set.str[STRING_SSL_CAPATH]; - data->set.ssl.CAfile = data->set.str[STRING_SSL_CAFILE]; - data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE]; - data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT]; - data->set.ssl.random_file = data->set.str[STRING_SSL_RANDOM_FILE]; - data->set.ssl.egdsocket = data->set.str[STRING_SSL_EGDSOCKET]; - data->set.ssl.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST]; - data->set.ssl.clientcert = data->set.str[STRING_CERT]; + data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_ORIG]; + data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY]; + data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_ORIG]; + data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY]; + data->set.ssl.primary.random_file = data->set.str[STRING_SSL_RANDOM_FILE]; + data->set.proxy_ssl.primary.random_file = + data->set.str[STRING_SSL_RANDOM_FILE]; + data->set.ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET]; + data->set.proxy_ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET]; + data->set.ssl.primary.cipher_list = + data->set.str[STRING_SSL_CIPHER_LIST_ORIG]; + data->set.proxy_ssl.primary.cipher_list = + data->set.str[STRING_SSL_CIPHER_LIST_PROXY]; + + data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_ORIG]; + data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY]; + data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_ORIG]; + data->set.proxy_ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY]; + data->set.ssl.cert = data->set.str[STRING_CERT_ORIG]; + data->set.proxy_ssl.cert = data->set.str[STRING_CERT_PROXY]; + data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE_ORIG]; + data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY]; + data->set.ssl.key = data->set.str[STRING_KEY_ORIG]; + data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY]; + data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE_ORIG]; + data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY]; + data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_ORIG]; + data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY]; + data->set.ssl.primary.clientcert = data->set.str[STRING_CERT_ORIG]; + data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY]; #ifdef USE_TLS_SRP - data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME]; - data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD]; + data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_ORIG]; + data->set.proxy_ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_PROXY]; + data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_ORIG]; + data->set.proxy_ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_PROXY]; #endif - if(!Curl_clone_ssl_config(&data->set.ssl, &conn->ssl_config)) { + if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary, + &conn->ssl_config)) { + result = CURLE_OUT_OF_MEMORY; + goto out; + } + + if(!Curl_clone_primary_ssl_config(&data->set.proxy_ssl.primary, + &conn->proxy_ssl_config)) { result = CURLE_OUT_OF_MEMORY; goto out; } @@ -6149,7 +6533,9 @@ static CURLcode create_conn(struct Curl_easy *data, infof(data, "Re-using existing connection! (#%ld) with %s %s\n", conn->connection_id, conn->bits.proxy?"proxy":"host", - conn->proxy.name?conn->proxy.dispname:conn->host.dispname); + conn->socks_proxy.host.name ? conn->socks_proxy.host.dispname : + conn->http_proxy.host.name ? conn->http_proxy.host.dispname : + conn->host.dispname); } else { /* We have decided that we want a new connection. However, we may not @@ -6280,6 +6666,7 @@ static CURLcode create_conn(struct Curl_easy *data, free(options); free(passwd); free(user); + free(socksproxy); free(proxy); return result; } diff --git a/lib/url.h b/lib/url.h index 90d9db3..f13c8e6 100644 --- a/lib/url.h +++ b/lib/url.h @@ -67,6 +67,8 @@ void Curl_getoff_all_pipelines(struct Curl_easy *data, void Curl_close_connections(struct Curl_easy *data); #define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */ +#define CURL_DEFAULT_HTTPS_PROXY_PORT 443 /* default https proxy port unless + specified */ CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex); @@ -76,5 +78,16 @@ CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex); void Curl_verboseconnect(struct connectdata *conn); #endif +#define CONNECT_PROXY_SSL()\ + (conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\ + !conn->bits.proxy_ssl_connected[sockindex]) + +#define CONNECT_FIRSTSOCKET_PROXY_SSL()\ + (conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\ + !conn->bits.proxy_ssl_connected[FIRSTSOCKET]) + +#define CONNECT_SECONDARYSOCKET_PROXY_SSL()\ + (conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\ + !conn->bits.proxy_ssl_connected[SECONDARYSOCKET]) #endif /* HEADER_CURL_URL_H */ diff --git a/lib/urldata.h b/lib/urldata.h index 7c7bf1b..0271d26 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -316,6 +316,8 @@ struct ssl_connect_data { #elif defined(USE_GSKIT) gsk_handle handle; int iocport; + int localfd; + int remotefd; #elif defined(USE_AXTLS) SSL_CTX* ssl_ctx; SSL* ssl; @@ -341,28 +343,38 @@ struct ssl_connect_data { #endif }; -struct ssl_config_data { +struct ssl_primary_config { long version; /* what version the client wants to use */ - long certverifyresult; /* result from the certificate verification */ - bool verifypeer; /* set TRUE if this is desired */ bool verifyhost; /* set TRUE if CN/SAN must match hostname */ bool verifystatus; /* set TRUE if certificate status must be checked */ char *CApath; /* certificate dir (doesn't work on windows) */ char *CAfile; /* certificate to verify peer against */ - const char *CRLfile; /* CRL to check certificate revocation */ - const char *issuercert;/* optional issuer certificate filename */ char *clientcert; char *random_file; /* path to file containing "random" data */ char *egdsocket; /* path to file containing the EGD daemon socket */ char *cipher_list; /* list of ciphers to use */ - size_t max_ssl_sessions; /* SSL session id cache size */ +}; + +struct ssl_config_data { + struct ssl_primary_config primary; + bool enable_beast; /* especially allow this flaw for interoperability's + sake*/ + bool no_revoke; /* disable SSL certificate revocation checks */ + long certverifyresult; /* result from the certificate verification */ + char *CRLfile; /* CRL to check certificate revocation */ + char *issuercert;/* optional issuer certificate filename */ curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */ void *fsslctxp; /* parameter for call back */ - bool sessionid; /* cache session IDs or not */ bool certinfo; /* gather lots of certificate info */ bool falsestart; + char *cert; /* client certificate file name */ + char *cert_type; /* format for certificate (default: PEM)*/ + char *key; /* private key file name */ + char *key_type; /* format for private key (default: PEM) */ + char *key_passwd; /* plain text private key password */ + #ifdef USE_TLS_SRP char *username; /* TLS username (for, e.g., SRP) */ char *password; /* TLS password (for, e.g., SRP) */ @@ -370,6 +382,11 @@ struct ssl_config_data { #endif }; +struct ssl_general_config { + bool sessionid; /* cache session IDs or not */ + size_t max_ssl_sessions; /* SSL session id cache size */ +}; + /* information stored about one single SSL session */ struct curl_ssl_session { char *name; /* host name for which this ID was used */ @@ -380,7 +397,7 @@ struct curl_ssl_session { long age; /* just a number, the higher the more recent */ int remote_port; /* remote port */ int conn_to_port; /* remote port for the connection (may be -1) */ - struct ssl_config_data ssl_config; /* setup for this session */ + struct ssl_primary_config ssl_config; /* setup for this session */ }; /* Struct used for Digest challenge-response authentication */ @@ -451,7 +468,7 @@ struct ntlmdata { #else unsigned int flags; unsigned char nonce[8]; - void* target_info; /* TargetInfo received in the ntlm type-2 message */ + void *target_info; /* TargetInfo received in the ntlm type-2 message */ unsigned int target_info_len; #endif }; @@ -497,6 +514,7 @@ struct ConnectBits { that overrides the port in the URL (remote port) */ bool proxy; /* if set, this transfer is done through a proxy - any type */ bool httpproxy; /* if set, this transfer is done through a http proxy */ + bool socksproxy; /* if set, this transfer is done through a socks proxy */ bool user_passwd; /* do we use user+password for this connection? */ bool proxy_user_passwd; /* user+password for the proxy? */ bool ipv6_ip; /* we communicate with a remote site specified with pure IPv6 @@ -531,6 +549,7 @@ struct ConnectBits { bool ftp_use_eprt; /* As set with CURLOPT_FTP_USE_EPRT, but if we find out EPRT doesn't work we disable it for the forthcoming requests */ + bool ftp_use_data_ssl; /* Enabled SSL for the data connection */ bool netrc; /* name+password provided by netrc */ bool userpwd_in_url; /* name+password found in url */ bool stream_was_rewound; /* Indicates that the stream was rewound after a @@ -547,6 +566,9 @@ struct ConnectBits { bool tcp_fastopen; /* use TCP Fast Open */ bool tls_enable_npn; /* TLS NPN extension? */ bool tls_enable_alpn; /* TLS ALPN extension? */ + bool proxy_ssl_connected[2]; /* TRUE when SSL initialization for HTTPS proxy + is complete */ + bool socksproxy_connecting; /* connecting through a socks proxy */ }; struct hostname { @@ -732,7 +754,7 @@ struct SingleRequest { */ struct Curl_handler { - const char * scheme; /* URL scheme name. */ + const char *scheme; /* URL scheme name. */ /* Complement to setup_connection_internals(). */ CURLcode (*setup_connection)(struct connectdata *); @@ -849,6 +871,14 @@ struct postponed_data { }; #endif /* USE_RECV_BEFORE_SEND_WORKAROUND */ +struct proxy_info { + struct hostname host; + long port; + curl_proxytype proxytype; /* what kind of proxy that is in use */ + char *user; /* proxy user name string, allocated */ + char *passwd; /* proxy password string, allocated */ +}; + /* * The connectdata struct contains all fields and variables that should be * unique for an entire connection. @@ -898,14 +928,20 @@ struct connectdata { int socktype; /* SOCK_STREAM or SOCK_DGRAM */ struct hostname host; + char *secondaryhostname; /* secondary socket host name (ftp) */ struct hostname conn_to_host; /* the host to connect to. valid only if bits.conn_to_host is set */ struct hostname proxy; + struct proxy_info socks_proxy; + struct proxy_info http_proxy; + long port; /* which port to use locally */ int remote_port; /* the remote port, not the proxy port! */ int conn_to_port; /* the remote port to connect to. valid only if bits.conn_to_port is set */ + unsigned short secondary_port; /* secondary socket remote port to connect to + (ftp) */ /* 'primary_ip' and 'primary_port' get filled with peer's numerical ip address and port number whenever an outgoing connection is @@ -930,10 +966,6 @@ struct connectdata { char *oauth_bearer; /* bearer token for OAuth 2.0, allocated */ - char *proxyuser; /* proxy user name string, allocated */ - char *proxypasswd; /* proxy password string, allocated */ - curl_proxytype proxytype; /* what kind of proxy that is in use */ - int httpversion; /* the HTTP version*10 reported by the server */ int rtspversion; /* the RTSP version*10 reported by the server */ @@ -951,7 +983,9 @@ struct connectdata { struct postponed_data postponed[2]; /* two buffers for two sockets */ #endif /* USE_RECV_BEFORE_SEND_WORKAROUND */ struct ssl_connect_data ssl[2]; /* this is for ssl-stuff */ - struct ssl_config_data ssl_config; + struct ssl_connect_data proxy_ssl[2]; /* this is for proxy ssl-stuff */ + struct ssl_primary_config ssl_config; + struct ssl_primary_config proxy_ssl_config; bool tls_upgraded; struct ConnectBits bits; /* various state-flags for this connection */ @@ -962,8 +996,8 @@ struct connectdata { struct timeval connecttime; /* The two fields below get set in Curl_connecthost */ int num_addr; /* number of addresses to try to connect to */ - long timeoutms_per_addr; /* how long time in milliseconds to spend on - trying to connect to each IP address */ + time_t timeoutms_per_addr; /* how long time in milliseconds to spend on + trying to connect to each IP address */ const struct Curl_handler *handler; /* Connection's protocol handler */ const struct Curl_handler *given; /* The protocol first given */ @@ -1020,7 +1054,7 @@ struct connectdata { send on this pipeline */ struct curl_llist *recv_pipe; /* List of handles waiting to read their responses on this pipeline */ - char* master_buffer; /* The master buffer allocated on-demand; + char *master_buffer; /* The master buffer allocated on-demand; used for pipelining. */ size_t read_pos; /* Current read position in the master buffer */ size_t buf_len; /* Length of the buffer?? */ @@ -1041,8 +1075,8 @@ struct connectdata { /* used for communication with Samba's winbind daemon helper ntlm_auth */ curl_socket_t ntlm_auth_hlpr_socket; pid_t ntlm_auth_hlpr_pid; - char* challenge_header; - char* response_header; + char *challenge_header; + char *response_header; #endif #endif @@ -1078,9 +1112,6 @@ struct connectdata { int socks5_gssapi_enctype; #endif - bool verifypeer; - bool verifyhost; - /* When this connection is created, store the conditions for the local end bind. This is stored before the actual bind and before any connection is made and will serve the purpose of being used for comparison reasons so @@ -1099,13 +1130,17 @@ struct connectdata { struct connectbundle *bundle; /* The bundle we are member of */ int negnpn; /* APLN or NPN TLS negotiated protocol, CURL_HTTP_VERSION* */ + +#ifdef USE_UNIX_SOCKETS + char *unix_domain_socket; +#endif }; /* The end of connectdata. */ /* * Struct to keep statistical and informational data. - * All variables in this struct must be reset in Curl_initinfo(). + * All variables in this struct must be initialized/reset in Curl_initinfo(). */ struct PureInfo { int httpcode; /* Recent HTTP, FTP, RTSP or SMTP response code */ @@ -1139,6 +1174,9 @@ struct PureInfo { char conn_local_ip[MAX_IPADR_LEN]; long conn_local_port; + const char *conn_scheme; + unsigned int conn_protocol; + struct curl_certinfo certs; /* info about the certs, only populated in OpenSSL builds. Asked for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */ @@ -1146,8 +1184,8 @@ struct PureInfo { struct Progress { - long lastshow; /* time() of the last displayed progress meter or NULL to - force redraw at next call */ + time_t lastshow; /* time() of the last displayed progress meter or NULL to + force redraw at next call */ curl_off_t size_dl; /* total expected size */ curl_off_t size_ul; /* total expected size */ curl_off_t downloaded; /* transferred so far */ @@ -1242,6 +1280,11 @@ struct auth { be RFC compliant */ }; +struct Curl_http2_dep { + struct Curl_http2_dep *next; + struct Curl_easy *data; +}; + struct UrlState { /* Points to the connection cache */ @@ -1402,8 +1445,10 @@ struct DynamicStatic { struct Curl_multi; /* declared and used only in multi.c */ enum dupstring { - STRING_CERT, /* client certificate file name */ - STRING_CERT_TYPE, /* format for certificate (default: PEM)*/ + STRING_CERT_ORIG, /* client certificate file name */ + STRING_CERT_PROXY, /* client certificate file name */ + STRING_CERT_TYPE_ORIG, /* format for certificate (default: PEM)*/ + STRING_CERT_TYPE_PROXY, /* format for certificate (default: PEM)*/ STRING_COOKIE, /* HTTP cookie string to send */ STRING_COOKIEJAR, /* dump all cookies to this file */ STRING_CUSTOMREQUEST, /* HTTP/FTP/RTSP request/method to use */ @@ -1413,25 +1458,35 @@ enum dupstring { STRING_FTP_ACCOUNT, /* ftp account data */ STRING_FTP_ALTERNATIVE_TO_USER, /* command to send if USER/PASS fails */ STRING_FTPPORT, /* port to send with the FTP PORT command */ - STRING_KEY, /* private key file name */ - STRING_KEY_PASSWD, /* plain text private key password */ - STRING_KEY_TYPE, /* format for private key (default: PEM) */ + STRING_KEY_ORIG, /* private key file name */ + STRING_KEY_PROXY, /* private key file name */ + STRING_KEY_PASSWD_ORIG, /* plain text private key password */ + STRING_KEY_PASSWD_PROXY, /* plain text private key password */ + STRING_KEY_TYPE_ORIG, /* format for private key (default: PEM) */ + STRING_KEY_TYPE_PROXY, /* format for private key (default: PEM) */ STRING_KRB_LEVEL, /* krb security level */ STRING_NETRC_FILE, /* if not NULL, use this instead of trying to find $HOME/.netrc */ STRING_PROXY, /* proxy to use */ + STRING_PRE_PROXY, /* pre socks proxy to use */ STRING_SET_RANGE, /* range, if used */ STRING_SET_REFERER, /* custom string for the HTTP referer field */ STRING_SET_URL, /* what original URL to work on */ - STRING_SSL_CAPATH, /* CA directory name (doesn't work on windows) */ - STRING_SSL_CAFILE, /* certificate file to verify peer against */ - STRING_SSL_PINNEDPUBLICKEY, /* public key file to verify peer against */ - STRING_SSL_CIPHER_LIST, /* list of ciphers to use */ + STRING_SSL_CAPATH_ORIG, /* CA directory name (doesn't work on windows) */ + STRING_SSL_CAPATH_PROXY, /* CA directory name (doesn't work on windows) */ + STRING_SSL_CAFILE_ORIG, /* certificate file to verify peer against */ + STRING_SSL_CAFILE_PROXY, /* certificate file to verify peer against */ + STRING_SSL_PINNEDPUBLICKEY_ORIG, /* public key file to verify peer against */ + STRING_SSL_PINNEDPUBLICKEY_PROXY, /* public key file to verify proxy */ + STRING_SSL_CIPHER_LIST_ORIG, /* list of ciphers to use */ + STRING_SSL_CIPHER_LIST_PROXY, /* list of ciphers to use */ STRING_SSL_EGDSOCKET, /* path to file containing the EGD daemon socket */ STRING_SSL_RANDOM_FILE, /* path to file containing "random" data */ STRING_USERAGENT, /* User-Agent string */ - STRING_SSL_CRLFILE, /* crl file to check certificate */ - STRING_SSL_ISSUERCERT, /* issuer cert file to check certificate */ + STRING_SSL_CRLFILE_ORIG, /* crl file to check certificate */ + STRING_SSL_CRLFILE_PROXY, /* crl file to check certificate */ + STRING_SSL_ISSUERCERT_ORIG, /* issuer cert file to check certificate */ + STRING_SSL_ISSUERCERT_PROXY, /* issuer cert file to check certificate */ STRING_USERNAME, /* , if used */ STRING_PASSWORD, /* , if used */ STRING_OPTIONS, /* , if used */ @@ -1459,8 +1514,10 @@ enum dupstring { STRING_MAIL_AUTH, #ifdef USE_TLS_SRP - STRING_TLSAUTH_USERNAME, /* TLS auth */ - STRING_TLSAUTH_PASSWORD, /* TLS auth */ + STRING_TLSAUTH_USERNAME_ORIG, /* TLS auth */ + STRING_TLSAUTH_USERNAME_PROXY, /* TLS auth */ + STRING_TLSAUTH_PASSWORD_ORIG, /* TLS auth */ + STRING_TLSAUTH_PASSWORD_PROXY, /* TLS auth */ #endif STRING_BEARER, /* , if used */ #ifdef USE_UNIX_SOCKETS @@ -1524,10 +1581,10 @@ struct UserDefined { curl_opensocket_callback fopensocket; /* function for checking/translating the address and opening the socket */ - void* opensocket_client; + void *opensocket_client; curl_closesocket_callback fclosesocket; /* function for closing the socket */ - void* closesocket_client; + void *closesocket_client; void *seek_client; /* pointer to pass to the seek callback */ /* the 3 curl_conv_callback functions below are used on non-ASCII hosts */ @@ -1578,7 +1635,10 @@ struct UserDefined { long httpversion; /* when non-zero, a specific HTTP version requested to be used in the library's request(s) */ struct ssl_config_data ssl; /* user defined SSL stuff */ + struct ssl_config_data proxy_ssl; /* user defined SSL stuff for proxy */ + struct ssl_general_config general_ssl; /* general user defined SSL stuff */ curl_proxytype proxytype; /* what kind of proxy that is in use */ + curl_proxytype socks_proxytype; /* what kind of socks proxy that is in use */ long dns_cache_timeout; /* DNS cache timeout */ long buffer_size; /* size of receive buffer to use */ void *private_data; /* application-private data */ @@ -1642,9 +1702,6 @@ struct UserDefined { bool ftp_skip_ip; /* skip the IP address the FTP server passes on to us */ bool connect_only; /* make connection, let application use the socket */ - bool ssl_enable_beast; /* especially allow this flaw for interoperability's - sake*/ - bool ssl_no_revoke; /* disable SSL certificate revocation checks */ long ssh_auth_types; /* allowed SSH auth types */ bool http_te_skip; /* pass the raw body data to the user, even when transfer-encoded (chunked, compressed) */ @@ -1695,6 +1752,8 @@ struct UserDefined { struct Curl_easy *stream_depends_on; bool stream_depends_e; /* set or don't set the Exclusive bit */ int stream_weight; + + struct Curl_http2_dep *stream_dependents; }; struct Names { diff --git a/lib/vauth/cleartext.c b/lib/vauth/cleartext.c index 6df419a..a761ae7 100644 --- a/lib/vauth/cleartext.c +++ b/lib/vauth/cleartext.c @@ -66,16 +66,27 @@ CURLcode Curl_auth_create_plain_message(struct Curl_easy *data, char *plainauth; size_t ulen; size_t plen; + size_t plainlen; + *outlen = 0; + *outptr = NULL; ulen = strlen(userp); plen = strlen(passwdp); - plainauth = malloc(2 * ulen + plen + 2); - if(!plainauth) { - *outlen = 0; - *outptr = NULL; + /* Compute binary message length, checking for overflows. */ + plainlen = 2 * ulen; + if(plainlen < ulen) + return CURLE_OUT_OF_MEMORY; + plainlen += plen; + if(plainlen < plen) + return CURLE_OUT_OF_MEMORY; + plainlen += 2; + if(plainlen < 2) + return CURLE_OUT_OF_MEMORY; + + plainauth = malloc(plainlen); + if(!plainauth) return CURLE_OUT_OF_MEMORY; - } /* Calculate the reply */ memcpy(plainauth, userp, ulen); @@ -85,8 +96,7 @@ CURLcode Curl_auth_create_plain_message(struct Curl_easy *data, memcpy(plainauth + 2 * ulen + 2, passwdp, plen); /* Base64 encode the reply */ - result = Curl_base64_encode(data, plainauth, 2 * ulen + plen + 2, outptr, - outlen); + result = Curl_base64_encode(data, plainauth, plainlen, outptr, outlen); free(plainauth); return result; diff --git a/lib/vauth/digest.c b/lib/vauth/digest.c index 0a11a30..7d9200a 100644 --- a/lib/vauth/digest.c +++ b/lib/vauth/digest.c @@ -40,6 +40,7 @@ #include "strcase.h" #include "non-ascii.h" /* included for Curl_convert_... prototypes */ #include "curl_printf.h" +#include "rand.h" /* The last #include files should be: */ #include "curl_memory.h" @@ -59,7 +60,7 @@ what ultimately goes over the network. */ #define CURL_OUTPUT_DIGEST_CONV(a, b) \ - result = Curl_convert_to_network(a, (char *)b, strlen((const char*)b)); \ + result = Curl_convert_to_network(a, (char *)b, strlen((const char *)b)); \ if(result) { \ free(b); \ return result; \ @@ -387,10 +388,9 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, return CURLE_BAD_CONTENT_ENCODING; /* Generate 16 bytes of random data */ - entropy[0] = Curl_rand(data); - entropy[1] = Curl_rand(data); - entropy[2] = Curl_rand(data); - entropy[3] = Curl_rand(data); + result = Curl_rand(data, &entropy[0], 4); + if(result) + return result; /* Convert the random data into a 32 byte hex string */ snprintf(cnonce, sizeof(cnonce), "%08x%08x%08x%08x", @@ -684,9 +684,12 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, digest->nc = 1; if(!digest->cnonce) { + unsigned int rnd[4]; + result = Curl_rand(data, &rnd[0], 4); + if(result) + return result; snprintf(cnoncebuf, sizeof(cnoncebuf), "%08x%08x%08x%08x", - Curl_rand(data), Curl_rand(data), - Curl_rand(data), Curl_rand(data)); + rnd[0], rnd[1], rnd[2], rnd[3]); result = Curl_base64_encode(data, cnoncebuf, strlen(cnoncebuf), &cnonce, &cnonce_sz); diff --git a/lib/vauth/digest_sspi.c b/lib/vauth/digest_sspi.c index 29526fc..b9ceb12 100644 --- a/lib/vauth/digest_sspi.c +++ b/lib/vauth/digest_sspi.c @@ -414,7 +414,7 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, return CURLE_OUT_OF_MEMORY; /* Populate our identity domain */ - if(Curl_override_sspi_http_realm((const char*) digest->input_token, + if(Curl_override_sspi_http_realm((const char *) digest->input_token, &identity)) return CURLE_OUT_OF_MEMORY; diff --git a/lib/vauth/ntlm.c b/lib/vauth/ntlm.c index b484a01..b4d345d 100644 --- a/lib/vauth/ntlm.c +++ b/lib/vauth/ntlm.c @@ -41,7 +41,7 @@ #include "curl_gethostname.h" #include "curl_multibyte.h" #include "warnless.h" - +#include "rand.h" #include "vtls/vtls.h" #ifdef USE_NSS @@ -558,8 +558,9 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, unsigned int entropy[2]; unsigned char ntlmv2hash[0x18]; - entropy[0] = Curl_rand(data); - entropy[1] = Curl_rand(data); + result = Curl_rand(data, &entropy[0], 2); + if(result) + return result; result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer); if(result) @@ -598,8 +599,9 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, unsigned int entropy[2]; /* Need to create 8 bytes random data */ - entropy[0] = Curl_rand(data); - entropy[1] = Curl_rand(data); + result = Curl_rand(data, &entropy[0], 2); + if(result) + return result; /* 8 bytes random data as challenge in lmresp */ memcpy(lmresp, entropy, 8); diff --git a/lib/vauth/spnego_sspi.c b/lib/vauth/spnego_sspi.c index 672b43f..5fa95e2 100644 --- a/lib/vauth/spnego_sspi.c +++ b/lib/vauth/spnego_sspi.c @@ -264,7 +264,7 @@ CURLcode Curl_auth_create_spnego_message(struct Curl_easy *data, /* Base64 encode the already generated response */ result = Curl_base64_encode(data, - (const char*) nego->output_token, + (const char *) nego->output_token, nego->output_token_length, outptr, outlen); diff --git a/lib/version.c b/lib/version.c index a434a62..3d17768 100644 --- a/lib/version.c +++ b/lib/version.c @@ -324,6 +324,9 @@ static curl_version_info_data version_info = { #if defined(USE_LIBPSL) | CURL_VERSION_PSL #endif +#if defined(HTTPS_PROXY_SUPPORT) + | CURL_VERSION_HTTPS_PROXY +#endif , NULL, /* ssl_version */ 0, /* ssl_version_num, this is kept at zero */ diff --git a/lib/vtls/axtls.c b/lib/vtls/axtls.c index 85b8bc4..ff4634e 100644 --- a/lib/vtls/axtls.c +++ b/lib/vtls/axtls.c @@ -65,7 +65,7 @@ int Curl_axtls_cleanup(void) static CURLcode map_error_to_curl(int axtls_err) { - switch (axtls_err) { + switch(axtls_err) { case SSL_ERROR_NOT_SUPPORTED: case SSL_ERROR_INVALID_VERSION: case -70: /* protocol version alert from server */ @@ -121,7 +121,7 @@ static Curl_send axtls_send; static void free_ssl_structs(struct ssl_connect_data *connssl) { if(connssl->ssl) { - ssl_free (connssl->ssl); + ssl_free(connssl->ssl); connssl->ssl = NULL; } if(connssl->ssl_ctx) { @@ -158,7 +158,7 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex) /* axTLS only supports TLSv1 */ /* check to see if we've been told to use an explicit SSL/TLS version */ - switch(data->set.ssl.version) { + switch(SSL_CONN_CONFIG(version)) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: break; @@ -183,17 +183,17 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex) conn->ssl[sockindex].ssl = NULL; /* Load the trusted CA cert bundle file */ - if(data->set.ssl.CAfile) { - if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, data->set.ssl.CAfile, NULL) - != SSL_OK) { + if(SSL_CONN_CONFIG(CAfile)) { + if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, + SSL_CONN_CONFIG(CAfile), NULL) != SSL_OK) { infof(data, "error reading ca cert file %s \n", - data->set.ssl.CAfile); - if(data->set.ssl.verifypeer) { + SSL_CONN_CONFIG(CAfile)); + if(SSL_CONN_CONFIG(verifypeer)) { return CURLE_SSL_CACERT_BADFILE; } } else - infof(data, "found certificates in %s\n", data->set.ssl.CAfile); + infof(data, "found certificates in %s\n", SSL_CONN_CONFIG(CAfile)); } /* gtls.c tasks we're skipping for now: @@ -205,15 +205,15 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex) */ /* Load client certificate */ - if(data->set.str[STRING_CERT]) { + if(SSL_SET_OPTION(cert)) { i=0; /* Instead of trying to analyze cert type here, let axTLS try them all. */ while(cert_types[i] != 0) { ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i], - data->set.str[STRING_CERT], NULL); + SSL_SET_OPTION(cert), NULL); if(ssl_fcn_return == SSL_OK) { infof(data, "successfully read cert file %s \n", - data->set.str[STRING_CERT]); + SSL_SET_OPTION(cert)); break; } i++; @@ -221,7 +221,7 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex) /* Tried all cert types, none worked. */ if(cert_types[i] == 0) { failf(data, "%s is not x509 or pkcs12 format", - data->set.str[STRING_CERT]); + SSL_SET_OPTION(cert)); return CURLE_SSL_CERTPROBLEM; } } @@ -229,15 +229,15 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex) /* Load client key. If a pkcs12 file successfully loaded a cert, then there's nothing to do because the key has already been loaded. */ - if(data->set.str[STRING_KEY] && cert_types[i] != SSL_OBJ_PKCS12) { + if(SSL_SET_OPTION(key) && cert_types[i] != SSL_OBJ_PKCS12) { i=0; /* Instead of trying to analyze key type here, let axTLS try them all. */ while(key_types[i] != 0) { ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i], - data->set.str[STRING_KEY], NULL); + SSL_SET_OPTION(key), NULL); if(ssl_fcn_return == SSL_OK) { infof(data, "successfully read key file %s \n", - data->set.str[STRING_KEY]); + SSL_SET_OPTION(key)); break; } i++; @@ -245,7 +245,7 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex) /* Tried all key types, none worked. */ if(key_types[i] == 0) { failf(data, "Failure: %s is not a supported key file", - data->set.str[STRING_KEY]); + SSL_SET_OPTION(key)); return CURLE_SSL_CONNECT_ERROR; } } @@ -256,15 +256,16 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex) * 2) setting up callbacks. these seem gnutls specific */ - if(conn->ssl_config.sessionid) { + if(data->set.general_ssl.sessionid) { const uint8_t *ssl_sessionid; size_t ssl_idsize; /* In axTLS, handshaking happens inside ssl_client_new. */ Curl_ssl_sessionid_lock(conn); - if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize)) { + if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize, + sockindex)) { /* we got a session id, use it! */ - infof (data, "SSL re-using session ID\n"); + infof(data, "SSL re-using session ID\n"); ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], ssl_sessionid, (uint8_t)ssl_idsize); } @@ -291,13 +292,17 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex) const char *dns_altname; int8_t found_subject_alt_names = 0; int8_t found_subject_alt_name_matching_conn = 0; + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + const char * const dispname = SSL_IS_PROXY() ? + conn->http_proxy.host.dispname : conn->host.dispname; /* Here, gtls.c gets the peer certificates and fails out depending on * settings in "data." axTLS api doesn't have get cert chain fcn, so omit? */ /* Verify server's certificate */ - if(data->set.ssl.verifypeer) { + if(SSL_CONN_CONFIG(verifypeer)) { if(ssl_verify_cert(ssl) != SSL_OK) { Curl_axtls_close(conn, sockindex); failf(data, "server cert verify failed"); @@ -328,8 +333,8 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex) found_subject_alt_names = 1; infof(data, "\tComparing subject alt name DNS with hostname: %s <-> %s\n", - dns_altname, conn->host.name); - if(Curl_cert_hostcheck(dns_altname, conn->host.name)) { + dns_altname, hostname); + if(Curl_cert_hostcheck(dns_altname, hostname)) { found_subject_alt_name_matching_conn = 1; break; } @@ -337,23 +342,21 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex) /* RFC2818 checks */ if(found_subject_alt_names && !found_subject_alt_name_matching_conn) { - if(data->set.ssl.verifyhost) { + if(SSL_CONN_CONFIG(verifyhost)) { /* Break connection ! */ Curl_axtls_close(conn, sockindex); - failf(data, "\tsubjectAltName(s) do not match %s\n", - conn->host.dispname); + failf(data, "\tsubjectAltName(s) do not match %s\n", dispname); return CURLE_PEER_FAILED_VERIFICATION; } else - infof(data, "\tsubjectAltName(s) do not match %s\n", - conn->host.dispname); + infof(data, "\tsubjectAltName(s) do not match %s\n", dispname); } else if(found_subject_alt_names == 0) { /* Per RFC2818, when no Subject Alt Names were available, examine the peer CN as a legacy fallback */ peer_CN = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME); if(peer_CN == NULL) { - if(data->set.ssl.verifyhost) { + if(SSL_CONN_CONFIG(verifyhost)) { Curl_axtls_close(conn, sockindex); failf(data, "unable to obtain common name from peer certificate"); return CURLE_PEER_FAILED_VERIFICATION; @@ -362,17 +365,17 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex) infof(data, "unable to obtain common name from peer certificate"); } else { - if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) { - if(data->set.ssl.verifyhost) { + if(!Curl_cert_hostcheck((const char *)peer_CN, hostname)) { + if(SSL_CONN_CONFIG(verifyhost)) { /* Break connection ! */ Curl_axtls_close(conn, sockindex); failf(data, "\tcommon name \"%s\" does not match \"%s\"\n", - peer_CN, conn->host.dispname); + peer_CN, dispname); return CURLE_PEER_FAILED_VERIFICATION; } else infof(data, "\tcommon name \"%s\" does not match \"%s\"\n", - peer_CN, conn->host.dispname); + peer_CN, dispname); } } } @@ -383,13 +386,13 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex) conn->send[sockindex] = axtls_send; /* Put our freshly minted SSL session in cache */ - if(conn->ssl_config.sessionid) { + if(data->set.general_ssl.sessionid) { const uint8_t *ssl_sessionid = ssl_get_session_id_size(ssl); size_t ssl_idsize = ssl_get_session_id(ssl); Curl_ssl_sessionid_lock(conn); - if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize) - != CURLE_OK) - infof (data, "failed to add session to cache\n"); + if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize, + sockindex) != CURLE_OK) + infof(data, "failed to add session to cache\n"); Curl_ssl_sessionid_unlock(conn); } @@ -437,7 +440,7 @@ CURLcode Curl_axtls_connect_nonblocking( return CURLE_OK; } } - infof (conn->data, "handshake completed successfully\n"); + infof(conn->data, "handshake completed successfully\n"); conn->ssl[sockindex].connecting_state = ssl_connect_3; } @@ -503,7 +506,7 @@ Curl_axtls_connect(struct connectdata *conn, /* TODO: avoid polling */ Curl_wait_ms(10); } - infof (conn->data, "handshake completed successfully\n"); + infof(conn->data, "handshake completed successfully\n"); conn_step = connect_finish(conn, sockindex); if(conn_step != CURLE_OK) { diff --git a/lib/vtls/cyassl.c b/lib/vtls/cyassl.c index 5d6dbfb..fc4dde4 100644 --- a/lib/vtls/cyassl.c +++ b/lib/vtls/cyassl.c @@ -149,7 +149,7 @@ cyassl_connect_step1(struct connectdata *conn, return CURLE_OK; /* check to see if we've been told to use an explicit SSL/TLS version */ - switch(data->set.ssl.version) { + switch(SSL_CONN_CONFIG(version)) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: #if LIBCYASSL_VERSION_HEX >= 0x03003000 /* >= 3.3.0 */ @@ -174,12 +174,15 @@ cyassl_connect_step1(struct connectdata *conn, req_method = TLSv1_2_client_method(); use_sni(TRUE); break; + case CURL_SSLVERSION_TLSv1_3: + failf(data, "CyaSSL: TLS 1.3 is not yet supported"); + return CURLE_SSL_CONNECT_ERROR; case CURL_SSLVERSION_SSLv3: #ifdef WOLFSSL_ALLOW_SSLV3 req_method = SSLv3_client_method(); use_sni(FALSE); #else - failf(data, "No support for SSLv3"); + failf(data, "CyaSSL does not support SSLv3"); return CURLE_NOT_BUILT_IN; #endif break; @@ -205,7 +208,7 @@ cyassl_connect_step1(struct connectdata *conn, return CURLE_OUT_OF_MEMORY; } - switch(data->set.ssl.version) { + switch(SSL_CONN_CONFIG(version)) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: #if LIBCYASSL_VERSION_HEX > 0x03004006 /* > 3.4.6 */ @@ -228,18 +231,18 @@ cyassl_connect_step1(struct connectdata *conn, #ifndef NO_FILESYSTEM /* load trusted cacert */ - if(data->set.str[STRING_SSL_CAFILE]) { + if(SSL_CONN_CONFIG(CAfile)) { if(1 != SSL_CTX_load_verify_locations(conssl->ctx, - data->set.str[STRING_SSL_CAFILE], - data->set.str[STRING_SSL_CAPATH])) { - if(data->set.ssl.verifypeer) { + SSL_CONN_CONFIG(CAfile), + SSL_CONN_CONFIG(CApath))) { + if(SSL_CONN_CONFIG(verifypeer)) { /* Fail if we insist on successfully verifying the server. */ failf(data, "error setting certificate verify locations:\n" " CAfile: %s\n CApath: %s", - data->set.str[STRING_SSL_CAFILE]? - data->set.str[STRING_SSL_CAFILE]: "none", - data->set.str[STRING_SSL_CAPATH]? - data->set.str[STRING_SSL_CAPATH] : "none"); + SSL_CONN_CONFIG(CAfile)? + SSL_CONN_CONFIG(CAfile): "none", + SSL_CONN_CONFIG(CApath)? + SSL_CONN_CONFIG(CApath) : "none"); return CURLE_SSL_CACERT_BADFILE; } else { @@ -256,25 +259,25 @@ cyassl_connect_step1(struct connectdata *conn, infof(data, " CAfile: %s\n" " CApath: %s\n", - data->set.str[STRING_SSL_CAFILE] ? data->set.str[STRING_SSL_CAFILE]: + SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile): "none", - data->set.str[STRING_SSL_CAPATH] ? data->set.str[STRING_SSL_CAPATH]: + SSL_CONN_CONFIG(CApath) ? SSL_CONN_CONFIG(CApath): "none"); } /* Load the client certificate, and private key */ - if(data->set.str[STRING_CERT] && data->set.str[STRING_KEY]) { - int file_type = do_file_type(data->set.str[STRING_CERT_TYPE]); + if(SSL_SET_OPTION(cert) && SSL_SET_OPTION(key)) { + int file_type = do_file_type(SSL_SET_OPTION(cert_type)); - if(SSL_CTX_use_certificate_file(conssl->ctx, data->set.str[STRING_CERT], + if(SSL_CTX_use_certificate_file(conssl->ctx, SSL_SET_OPTION(cert), file_type) != 1) { failf(data, "unable to use client certificate (no key or wrong pass" " phrase?)"); return CURLE_SSL_CONNECT_ERROR; } - file_type = do_file_type(data->set.str[STRING_KEY_TYPE]); - if(SSL_CTX_use_PrivateKey_file(conssl->ctx, data->set.str[STRING_KEY], + file_type = do_file_type(SSL_SET_OPTION(key_type)); + if(SSL_CTX_use_PrivateKey_file(conssl->ctx, SSL_SET_OPTION(key), file_type) != 1) { failf(data, "unable to set private key"); return CURLE_SSL_CONNECT_ERROR; @@ -287,7 +290,8 @@ cyassl_connect_step1(struct connectdata *conn, * anyway. In the latter case the result of the verification is checked with * SSL_get_verify_result() below. */ SSL_CTX_set_verify(conssl->ctx, - data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE, + SSL_CONN_CONFIG(verifypeer)?SSL_VERIFY_PEER: + SSL_VERIFY_NONE, NULL); #ifdef HAVE_SNI @@ -296,13 +300,15 @@ cyassl_connect_step1(struct connectdata *conn, #ifdef ENABLE_IPV6 struct in6_addr addr6; #endif - size_t hostname_len = strlen(conn->host.name); + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + size_t hostname_len = strlen(hostname); if((hostname_len < USHRT_MAX) && - (0 == Curl_inet_pton(AF_INET, conn->host.name, &addr4)) && + (0 == Curl_inet_pton(AF_INET, hostname, &addr4)) && #ifdef ENABLE_IPV6 - (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr6)) && + (0 == Curl_inet_pton(AF_INET6, hostname, &addr6)) && #endif - (CyaSSL_CTX_UseSNI(conssl->ctx, CYASSL_SNI_HOST_NAME, conn->host.name, + (CyaSSL_CTX_UseSNI(conssl->ctx, CYASSL_SNI_HOST_NAME, hostname, (unsigned short)hostname_len) != 1)) { infof(data, "WARNING: failed to configure server name indication (SNI) " "TLS extension\n"); @@ -331,7 +337,7 @@ cyassl_connect_step1(struct connectdata *conn, } } #ifdef NO_FILESYSTEM - else if(data->set.ssl.verifypeer) { + else if(SSL_CONN_CONFIG(verifypeer)) { failf(data, "SSL: Certificates couldn't be loaded because CyaSSL was built" " with \"no filesystem\". Either disable peer verification" " (insecure) or if you are building an application with libcurl you" @@ -377,11 +383,11 @@ cyassl_connect_step1(struct connectdata *conn, #endif /* HAVE_ALPN */ /* Check if there's a cached ID we can/should use here! */ - if(conn->ssl_config.sessionid) { + if(data->set.general_ssl.sessionid) { void *ssl_sessionid = NULL; Curl_ssl_sessionid_lock(conn); - if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) { + if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) { /* we got a session id, use it! */ if(!SSL_set_session(conssl->handle, ssl_sessionid)) { Curl_ssl_sessionid_unlock(conn); @@ -391,7 +397,7 @@ cyassl_connect_step1(struct connectdata *conn, return CURLE_SSL_CONNECT_ERROR; } /* Informational message */ - infof (data, "SSL re-using session ID\n"); + infof(data, "SSL re-using session ID\n"); } Curl_ssl_sessionid_unlock(conn); } @@ -414,13 +420,20 @@ cyassl_connect_step2(struct connectdata *conn, int ret = -1; struct Curl_easy *data = conn->data; struct ssl_connect_data* conssl = &conn->ssl[sockindex]; + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + const char * const dispname = SSL_IS_PROXY() ? + conn->http_proxy.host.dispname : conn->host.dispname; + const char * const pinnedpubkey = SSL_IS_PROXY() ? + data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; conn->recv[sockindex] = cyassl_recv; conn->send[sockindex] = cyassl_send; /* Enable RFC2818 checks */ - if(data->set.ssl.verifyhost) { - ret = CyaSSL_check_domain_name(conssl->handle, conn->host.name); + if(SSL_CONN_CONFIG(verifyhost)) { + ret = CyaSSL_check_domain_name(conssl->handle, hostname); if(ret == SSL_FAILURE) return CURLE_OUT_OF_MEMORY; } @@ -444,31 +457,31 @@ cyassl_connect_step2(struct connectdata *conn, else if(DOMAIN_NAME_MISMATCH == detail) { #if 1 failf(data, "\tsubject alt name(s) or common name do not match \"%s\"\n", - conn->host.dispname); + dispname); return CURLE_PEER_FAILED_VERIFICATION; #else /* When the CyaSSL_check_domain_name() is used and you desire to continue - * on a DOMAIN_NAME_MISMATCH, i.e. 'data->set.ssl.verifyhost == 0', + * on a DOMAIN_NAME_MISMATCH, i.e. 'conn->ssl_config.verifyhost == 0', * CyaSSL version 2.4.0 will fail with an INCOMPLETE_DATA error. The only * way to do this is currently to switch the CyaSSL_check_domain_name() - * in and out based on the 'data->set.ssl.verifyhost' value. */ - if(data->set.ssl.verifyhost) { + * in and out based on the 'conn->ssl_config.verifyhost' value. */ + if(SSL_CONN_CONFIG(verifyhost)) { failf(data, "\tsubject alt name(s) or common name do not match \"%s\"\n", - conn->host.dispname); + dispname); return CURLE_PEER_FAILED_VERIFICATION; } else { infof(data, "\tsubject alt name(s) and/or common name do not match \"%s\"\n", - conn->host.dispname); + dispname); return CURLE_OK; } #endif } #if LIBCYASSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */ else if(ASN_NO_SIGNER_E == detail) { - if(data->set.ssl.verifypeer) { + if(SSL_CONN_CONFIG(verifypeer)) { failf(data, "\tCA signer not available for verification\n"); return CURLE_SSL_CACERT_BADFILE; } @@ -487,7 +500,7 @@ cyassl_connect_step2(struct connectdata *conn, } } - if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) { + if(pinnedpubkey) { #ifdef KEEP_PEER_CERT X509 *x509; const char *x509_der; @@ -509,7 +522,8 @@ cyassl_connect_step2(struct connectdata *conn, } memset(&x509_parsed, 0, sizeof x509_parsed); - Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len); + if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len)) + return CURLE_SSL_PINNEDPUBKEYNOTMATCH; pubkey = &x509_parsed.subjectPublicKeyInfo; if(!pubkey->header || pubkey->end <= pubkey->header) { @@ -518,7 +532,7 @@ cyassl_connect_step2(struct connectdata *conn, } result = Curl_pin_peer_pubkey(data, - data->set.str[STRING_SSL_PINNEDPUBLICKEY], + pinnedpubkey, (const unsigned char *)pubkey->header, (size_t)(pubkey->end - pubkey->header)); if(result) { @@ -583,7 +597,7 @@ cyassl_connect_step3(struct connectdata *conn, DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); - if(conn->ssl_config.sessionid) { + if(data->set.general_ssl.sessionid) { bool incache; SSL_SESSION *our_ssl_sessionid; void *old_ssl_sessionid = NULL; @@ -591,7 +605,8 @@ cyassl_connect_step3(struct connectdata *conn, our_ssl_sessionid = SSL_get_session(connssl->handle); Curl_ssl_sessionid_lock(conn); - incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL)); + incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, + sockindex)); if(incache) { if(old_ssl_sessionid != our_ssl_sessionid) { infof(data, "old SSL session ID is stale, removing\n"); @@ -602,7 +617,7 @@ cyassl_connect_step3(struct connectdata *conn, if(!incache) { result = Curl_ssl_addsessionid(conn, our_ssl_sessionid, - 0 /* unknown size */); + 0 /* unknown size */, sockindex); if(result) { Curl_ssl_sessionid_unlock(conn); failf(data, "failed to store ssl session"); @@ -654,11 +669,11 @@ void Curl_cyassl_close(struct connectdata *conn, int sockindex) if(conssl->handle) { (void)SSL_shutdown(conssl->handle); - SSL_free (conssl->handle); + SSL_free(conssl->handle); conssl->handle = NULL; } if(conssl->ctx) { - SSL_CTX_free (conssl->ctx); + SSL_CTX_free(conssl->ctx); conssl->ctx = NULL; } } @@ -740,7 +755,7 @@ int Curl_cyassl_shutdown(struct connectdata *conn, int sockindex) struct ssl_connect_data *connssl = &conn->ssl[sockindex]; if(connssl->handle) { - SSL_free (connssl->handle); + SSL_free(connssl->handle); connssl->handle = NULL; } return retval; diff --git a/lib/vtls/darwinssl.c b/lib/vtls/darwinssl.c index 66e74f1..a43e391 100644 --- a/lib/vtls/darwinssl.c +++ b/lib/vtls/darwinssl.c @@ -197,7 +197,7 @@ static OSStatus SocketWrite(SSLConnectionRef connection, do { length = write(sock, - (char*)dataPtr + bytesSent, + (char *)dataPtr + bytesSent, dataLen - bytesSent); } while((length > 0) && ( (bytesSent += length) < dataLen) ); @@ -219,8 +219,9 @@ static OSStatus SocketWrite(SSLConnectionRef connection, return ortn; } -CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher) { - switch (cipher) { +CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher) +{ + switch(cipher) { /* SSL version 3.0 */ case SSL_RSA_WITH_NULL_MD5: return "SSL_RSA_WITH_NULL_MD5"; @@ -364,7 +365,8 @@ CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher) { return "SSL_NULL_WITH_NULL_NULL"; } -CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) { +CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) +{ switch(cipher) { /* TLS 1.0 with AES (RFC 3268) */ case TLS_RSA_WITH_AES_128_CBC_SHA: @@ -883,14 +885,18 @@ static OSStatus CopyIdentityWithLabel(char *label, SecIdentityRef *out_cert_and_key) { OSStatus status = errSecItemNotFound; + CFArrayRef keys_list; + CFIndex keys_list_count; + CFIndex i; + CFStringRef common_name; #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS /* SecItemCopyMatching() was introduced in iOS and Snow Leopard. kSecClassIdentity was introduced in Lion. If both exist, let's use them to find the certificate. */ if(SecItemCopyMatching != NULL && kSecClassIdentity != NULL) { - CFTypeRef keys[4]; - CFTypeRef values[4]; + CFTypeRef keys[5]; + CFTypeRef values[5]; CFDictionaryRef query_dict; CFStringRef label_cf = CFStringCreateWithCString(NULL, label, kCFStringEncodingUTF8); @@ -900,21 +906,53 @@ static OSStatus CopyIdentityWithLabel(char *label, keys[0] = kSecClass; values[1] = kCFBooleanTrue; /* we want a reference */ keys[1] = kSecReturnRef; - values[2] = kSecMatchLimitOne; /* one is enough, thanks */ + values[2] = kSecMatchLimitAll; /* kSecMatchLimitOne would be better if the + * label matching below worked correctly */ keys[2] = kSecMatchLimit; /* identity searches need a SecPolicyRef in order to work */ - values[3] = SecPolicyCreateSSL(false, label_cf); + values[3] = SecPolicyCreateSSL(false, NULL); keys[3] = kSecMatchPolicy; + /* match the name of the certificate (doesn't work in macOS 10.12.1) */ + values[4] = label_cf; + keys[4] = kSecAttrLabel; query_dict = CFDictionaryCreate(NULL, (const void **)keys, - (const void **)values, 4L, - &kCFCopyStringDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); + (const void **)values, 5L, + &kCFCopyStringDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); CFRelease(values[3]); - CFRelease(label_cf); /* Do we have a match? */ - status = SecItemCopyMatching(query_dict, (CFTypeRef *)out_cert_and_key); + status = SecItemCopyMatching(query_dict, (CFTypeRef *) &keys_list); + + /* Because kSecAttrLabel matching doesn't work with kSecClassIdentity, + * we need to find the correct identity ourselves */ + if(status == noErr) { + keys_list_count = CFArrayGetCount(keys_list); + *out_cert_and_key = NULL; + for(i=0; idata; curl_socket_t sockfd = conn->sock[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); + const bool verifypeer = SSL_CONN_CONFIG(verifypeer); + char * const ssl_cert = SSL_SET_OPTION(cert); + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; #ifdef ENABLE_IPV6 struct in6_addr addr; #else @@ -1052,40 +1096,46 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, /* check to see if we've been told to use an explicit SSL/TLS version */ #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS if(SSLSetProtocolVersionMax != NULL) { - switch(data->set.ssl.version) { - default: - case CURL_SSLVERSION_DEFAULT: - case CURL_SSLVERSION_TLSv1: - (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1); - (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12); - break; - case CURL_SSLVERSION_TLSv1_0: - (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1); - (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol1); - break; - case CURL_SSLVERSION_TLSv1_1: - (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol11); - (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol11); - break; - case CURL_SSLVERSION_TLSv1_2: - (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol12); - (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12); - break; - case CURL_SSLVERSION_SSLv3: - err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3); - if(err != noErr) { - failf(data, "Your version of the OS does not support SSLv3"); - return CURLE_SSL_CONNECT_ERROR; - } - (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol3); - break; - case CURL_SSLVERSION_SSLv2: - err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol2); - if(err != noErr) { - failf(data, "Your version of the OS does not support SSLv2"); - return CURLE_SSL_CONNECT_ERROR; - } - (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol2); + switch(conn->ssl_config.version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1); + (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12); + break; + case CURL_SSLVERSION_TLSv1_0: + (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1); + (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol1); + break; + case CURL_SSLVERSION_TLSv1_1: + (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol11); + (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol11); + break; + case CURL_SSLVERSION_TLSv1_2: + (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol12); + (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12); + break; + case CURL_SSLVERSION_TLSv1_3: + failf(data, "DarwinSSL: TLS 1.3 is not yet supported"); + return CURLE_SSL_CONNECT_ERROR; + case CURL_SSLVERSION_SSLv3: + err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv3"); + return CURLE_SSL_CONNECT_ERROR; + } + (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol3); + break; + case CURL_SSLVERSION_SSLv2: + err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol2); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + } + (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol2); + break; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; } } else { @@ -1093,121 +1143,131 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false); - switch (data->set.ssl.version) { - default: - case CURL_SSLVERSION_DEFAULT: - case CURL_SSLVERSION_TLSv1: - (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, - kTLSProtocol1, - true); - (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, - kTLSProtocol11, - true); - (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, - kTLSProtocol12, - true); - break; - case CURL_SSLVERSION_TLSv1_0: - (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, - kTLSProtocol1, - true); - break; - case CURL_SSLVERSION_TLSv1_1: - (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, - kTLSProtocol11, - true); - break; - case CURL_SSLVERSION_TLSv1_2: - (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, - kTLSProtocol12, - true); - break; - case CURL_SSLVERSION_SSLv3: - err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx, - kSSLProtocol3, - true); - if(err != noErr) { - failf(data, "Your version of the OS does not support SSLv3"); - return CURLE_SSL_CONNECT_ERROR; - } - break; - case CURL_SSLVERSION_SSLv2: - err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx, - kSSLProtocol2, - true); - if(err != noErr) { - failf(data, "Your version of the OS does not support SSLv2"); - return CURLE_SSL_CONNECT_ERROR; - } - break; - } -#endif /* CURL_SUPPORT_MAC_10_8 */ - } -#else - (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false); - switch(data->set.ssl.version) { - default: + switch(conn->ssl_config.version) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kTLSProtocol1, + true); + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kTLSProtocol11, + true); + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kTLSProtocol12, + true); + break; case CURL_SSLVERSION_TLSv1_0: (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kTLSProtocol1, true); break; case CURL_SSLVERSION_TLSv1_1: - failf(data, "Your version of the OS does not support TLSv1.1"); - return CURLE_SSL_CONNECT_ERROR; + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kTLSProtocol11, + true); + break; case CURL_SSLVERSION_TLSv1_2: - failf(data, "Your version of the OS does not support TLSv1.2"); + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kTLSProtocol12, + true); + break; + case CURL_SSLVERSION_TLSv1_3: + failf(data, "DarwinSSL: TLS 1.3 is not yet supported"); return CURLE_SSL_CONNECT_ERROR; - case CURL_SSLVERSION_SSLv2: + case CURL_SSLVERSION_SSLv3: err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx, - kSSLProtocol2, + kSSLProtocol3, true); if(err != noErr) { - failf(data, "Your version of the OS does not support SSLv2"); + failf(data, "Your version of the OS does not support SSLv3"); return CURLE_SSL_CONNECT_ERROR; } break; - case CURL_SSLVERSION_SSLv3: + case CURL_SSLVERSION_SSLv2: err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx, - kSSLProtocol3, + kSSLProtocol2, true); if(err != noErr) { - failf(data, "Your version of the OS does not support SSLv3"); + failf(data, "Your version of the OS does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; } break; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; + } +#endif /* CURL_SUPPORT_MAC_10_8 */ + } +#else + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false); + switch(conn->ssl_config.version) { + case CURL_SSLVERSION_DEFAULT: + case CURL_SSLVERSION_TLSv1: + case CURL_SSLVERSION_TLSv1_0: + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kTLSProtocol1, + true); + break; + case CURL_SSLVERSION_TLSv1_1: + failf(data, "Your version of the OS does not support TLSv1.1"); + return CURLE_SSL_CONNECT_ERROR; + case CURL_SSLVERSION_TLSv1_2: + failf(data, "Your version of the OS does not support TLSv1.2"); + return CURLE_SSL_CONNECT_ERROR; + case CURL_SSLVERSION_TLSv1_3: + failf(data, "Your version of the OS does not support TLSv1.3"); + return CURLE_SSL_CONNECT_ERROR; + case CURL_SSLVERSION_SSLv2: + err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kSSLProtocol2, + true); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv2"); + return CURLE_SSL_CONNECT_ERROR; + } + break; + case CURL_SSLVERSION_SSLv3: + err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kSSLProtocol3, + true); + if(err != noErr) { + failf(data, "Your version of the OS does not support SSLv3"); + return CURLE_SSL_CONNECT_ERROR; + } + break; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; } #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ - if(data->set.str[STRING_KEY]) { + if(SSL_SET_OPTION(key)) { infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure " - "Transport. The private key must be in the Keychain.\n"); + "Transport. The private key must be in the Keychain.\n"); } - if(data->set.str[STRING_CERT]) { + if(ssl_cert) { SecIdentityRef cert_and_key = NULL; - bool is_cert_file = is_file(data->set.str[STRING_CERT]); + bool is_cert_file = is_file(ssl_cert); /* User wants to authenticate with a client cert. Look for it: If we detect that this is a file on disk, then let's load it. Otherwise, assume that the user wants to use an identity loaded from the Keychain. */ if(is_cert_file) { - if(!data->set.str[STRING_CERT_TYPE]) + if(!SSL_SET_OPTION(cert_type)) infof(data, "WARNING: SSL: Certificate type not set, assuming " "PKCS#12 format.\n"); - else if(strncmp(data->set.str[STRING_CERT_TYPE], "P12", - strlen(data->set.str[STRING_CERT_TYPE])) != 0) + else if(strncmp(SSL_SET_OPTION(cert_type), "P12", + strlen(SSL_SET_OPTION(cert_type))) != 0) infof(data, "WARNING: SSL: The Security framework only supports " "loading identities that are in PKCS#12 format.\n"); - err = CopyIdentityFromPKCS12File(data->set.str[STRING_CERT], - data->set.str[STRING_KEY_PASSWD], &cert_and_key); + err = CopyIdentityFromPKCS12File(ssl_cert, + SSL_SET_OPTION(key_passwd), &cert_and_key); } else - err = CopyIdentityWithLabel(data->set.str[STRING_CERT], &cert_and_key); + err = CopyIdentityWithLabel(ssl_cert, &cert_and_key); if(err == noErr) { SecCertificateRef cert = NULL; @@ -1246,27 +1306,27 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, } else { switch(err) { - case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */ - failf(data, "SSL: Incorrect password for the certificate \"%s\" " - "and its private key.", data->set.str[STRING_CERT]); - break; - case -26275: /* errSecDecode */ case -25257: /* errSecUnknownFormat */ - failf(data, "SSL: Couldn't make sense of the data in the " - "certificate \"%s\" and its private key.", - data->set.str[STRING_CERT]); - break; - case -25260: /* errSecPassphraseRequired */ - failf(data, "SSL The certificate \"%s\" requires a password.", - data->set.str[STRING_CERT]); - break; - case errSecItemNotFound: - failf(data, "SSL: Can't find the certificate \"%s\" and its private " - "key in the Keychain.", data->set.str[STRING_CERT]); - break; - default: - failf(data, "SSL: Can't load the certificate \"%s\" and its private " - "key: OSStatus %d", data->set.str[STRING_CERT], err); - break; + case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */ + failf(data, "SSL: Incorrect password for the certificate \"%s\" " + "and its private key.", ssl_cert); + break; + case -26275: /* errSecDecode */ case -25257: /* errSecUnknownFormat */ + failf(data, "SSL: Couldn't make sense of the data in the " + "certificate \"%s\" and its private key.", + ssl_cert); + break; + case -25260: /* errSecPassphraseRequired */ + failf(data, "SSL The certificate \"%s\" requires a password.", + ssl_cert); + break; + case errSecItemNotFound: + failf(data, "SSL: Can't find the certificate \"%s\" and its private " + "key in the Keychain.", ssl_cert); + break; + default: + failf(data, "SSL: Can't load the certificate \"%s\" and its private " + "key: OSStatus %d", ssl_cert, err); + break; } return CURLE_SSL_CERTPROBLEM; } @@ -1297,8 +1357,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, #else if(SSLSetSessionOption != NULL) { #endif /* CURL_BUILD_MAC */ - bool break_on_auth = !data->set.ssl.verifypeer || - data->set.str[STRING_SSL_CAFILE]; + bool break_on_auth = !conn->ssl_config.verifypeer || ssl_cafile; err = SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionBreakOnServerAuth, break_on_auth); @@ -1310,7 +1369,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, else { #if CURL_SUPPORT_MAC_10_8 err = SSLSetEnableCertVerify(connssl->ssl_ctx, - data->set.ssl.verifypeer?true:false); + conn->ssl_config.verifypeer?true:false); if(err != noErr) { failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err); return CURLE_SSL_CONNECT_ERROR; @@ -1319,22 +1378,21 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, } #else err = SSLSetEnableCertVerify(connssl->ssl_ctx, - data->set.ssl.verifypeer?true:false); + conn->ssl_config.verifypeer?true:false); if(err != noErr) { failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err); return CURLE_SSL_CONNECT_ERROR; } #endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */ - if(data->set.str[STRING_SSL_CAFILE]) { - bool is_cert_file = is_file(data->set.str[STRING_SSL_CAFILE]); + if(ssl_cafile) { + bool is_cert_file = is_file(ssl_cafile); if(!is_cert_file) { - failf(data, "SSL: can't load CA certificate file %s", - data->set.str[STRING_SSL_CAFILE]); + failf(data, "SSL: can't load CA certificate file %s", ssl_cafile); return CURLE_SSL_CACERT_BADFILE; } - if(!data->set.ssl.verifypeer) { + if(!verifypeer) { failf(data, "SSL: CA certificate set, but certificate verification " "is disabled"); return CURLE_SSL_CONNECT_ERROR; @@ -1344,22 +1402,22 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, /* Configure hostname check. SNI is used if available. * Both hostname check and SNI require SSLSetPeerDomainName(). * Also: the verifyhost setting influences SNI usage */ - if(data->set.ssl.verifyhost) { - err = SSLSetPeerDomainName(connssl->ssl_ctx, conn->host.name, - strlen(conn->host.name)); + if(conn->ssl_config.verifyhost) { + err = SSLSetPeerDomainName(connssl->ssl_ctx, hostname, + strlen(hostname)); if(err != noErr) { infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d\n", err); } - if((Curl_inet_pton(AF_INET, conn->host.name, &addr)) + if((Curl_inet_pton(AF_INET, hostname, &addr)) #ifdef ENABLE_IPV6 - || (Curl_inet_pton(AF_INET6, conn->host.name, &addr)) + || (Curl_inet_pton(AF_INET6, hostname, &addr)) #endif ) { - infof(data, "WARNING: using IP address, SNI is being disabled by " - "the OS.\n"); + infof(data, "WARNING: using IP address, SNI is being disabled by " + "the OS.\n"); } } @@ -1382,7 +1440,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, running in an affected version of OS X. */ if(darwinver_maj == 12 && darwinver_min <= 3 && all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) { - continue; + continue; } #endif /* CURL_BUILD_MAC */ switch(all_ciphers[i]) { @@ -1474,21 +1532,22 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, /* We want to enable 1/n-1 when using a CBC cipher unless the user specifically doesn't want us doing that: */ if(SSLSetSessionOption != NULL) { + /* TODO s/data->set.ssl.enable_beast/SSL_SET_OPTION(enable_beast)/g */ SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionSendOneByteRecord, - !data->set.ssl_enable_beast); + !data->set.ssl.enable_beast); SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionFalseStart, data->set.ssl.falsestart); /* false start support */ } #endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */ /* Check if there's a cached ID we can/should use here! */ - if(conn->ssl_config.sessionid) { + if(data->set.general_ssl.sessionid) { char *ssl_sessionid; size_t ssl_sessionid_len; Curl_ssl_sessionid_lock(conn); if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid, - &ssl_sessionid_len)) { + &ssl_sessionid_len, sockindex)) { /* we got a session id, use it! */ err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len); Curl_ssl_sessionid_unlock(conn); @@ -1504,9 +1563,8 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, else { CURLcode result; ssl_sessionid = - aprintf("%s:%d:%d:%s:%hu", data->set.str[STRING_SSL_CAFILE], - data->set.ssl.verifypeer, data->set.ssl.verifyhost, - conn->host.name, conn->remote_port); + aprintf("%s:%d:%d:%s:%hu", ssl_cafile, + verifypeer, SSL_CONN_CONFIG(verifyhost), hostname, port); ssl_sessionid_len = strlen(ssl_sessionid); err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len); @@ -1516,7 +1574,8 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, return CURLE_SSL_CONNECT_ERROR; } - result = Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_sessionid_len); + result = Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_sessionid_len, + sockindex); Curl_ssl_sessionid_unlock(conn); if(result) { failf(data, "failed to store ssl session"); @@ -1820,7 +1879,7 @@ static int verify_cert(const char *cafile, struct Curl_easy *data, return sslerr_to_curlerr(data, ret); } - switch (trust_eval) { + switch(trust_eval) { case kSecTrustResultUnspecified: case kSecTrustResultProceed: return CURLE_OK; @@ -1842,6 +1901,8 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex) OSStatus err; SSLCipherSuite cipher; SSLProtocol protocol = 0; + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; DEBUGASSERT(ssl_connect_2 == connssl->connecting_state || ssl_connect_2_reading == connssl->connecting_state @@ -1851,7 +1912,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex) err = SSLHandshake(connssl->ssl_ctx); if(err != noErr) { - switch (err) { + switch(err) { case errSSLWouldBlock: /* they're not done with us yet */ connssl->connecting_state = connssl->ssl_direction ? ssl_connect_2_writing : ssl_connect_2_reading; @@ -1860,8 +1921,8 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex) /* The below is errSSLServerAuthCompleted; it's not defined in Leopard's headers */ case -9841: - if(data->set.str[STRING_SSL_CAFILE]) { - int res = verify_cert(data->set.str[STRING_SSL_CAFILE], data, + if(SSL_CONN_CONFIG(CAfile)) { + int res = verify_cert(SSL_CONN_CONFIG(CAfile), data, connssl->ssl_ctx); if(res != CURLE_OK) return res; @@ -1930,7 +1991,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex) return CURLE_SSL_CONNECT_ERROR; default: failf(data, "Unknown SSL protocol error in connection to %s:%d", - conn->host.name, err); + hostname, err); return CURLE_SSL_CONNECT_ERROR; } } @@ -1941,7 +2002,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex) /* Informational message */ (void)SSLGetNegotiatedCipher(connssl->ssl_ctx, &cipher); (void)SSLGetNegotiatedProtocolVersion(connssl->ssl_ctx, &protocol); - switch (protocol) { + switch(protocol) { case kSSLProtocol2: infof(data, "SSL 2.0 connection using %s\n", SSLCipherNameForNumber(cipher)); @@ -2390,7 +2451,8 @@ void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */ (void)CC_MD5(tmp, (CC_LONG)tmplen, md5sum); } -bool Curl_darwinssl_false_start(void) { +bool Curl_darwinssl_false_start(void) +{ #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 if(SSLSetSessionOption != NULL) return TRUE; @@ -2427,7 +2489,7 @@ static ssize_t darwinssl_send(struct connectdata *conn, if(connssl->ssl_write_buffered_length) { /* Write the buffered data: */ err = SSLWrite(connssl->ssl_ctx, NULL, 0UL, &processed); - switch (err) { + switch(err) { case noErr: /* processed is always going to be 0 because we didn't write to the buffer, so return how much was written to the socket */ @@ -2447,7 +2509,7 @@ static ssize_t darwinssl_send(struct connectdata *conn, /* We've got new data to write: */ err = SSLWrite(connssl->ssl_ctx, mem, len, &processed); if(err != noErr) { - switch (err) { + switch(err) { case errSSLWouldBlock: /* Data was buffered but not sent, we have to tell the caller to try sending again, and remember how much was buffered */ @@ -2476,7 +2538,7 @@ static ssize_t darwinssl_recv(struct connectdata *conn, OSStatus err = SSLRead(connssl->ssl_ctx, buf, buffersize, &processed); if(err != noErr) { - switch (err) { + switch(err) { case errSSLWouldBlock: /* return how much we read (if anything) */ if(processed) return (ssize_t)processed; diff --git a/lib/vtls/gskit.c b/lib/vtls/gskit.c index 3b0cfd5..a0d462b 100644 --- a/lib/vtls/gskit.c +++ b/lib/vtls/gskit.c @@ -81,6 +81,10 @@ #include "memdebug.h" +/* Directions. */ +#define SOS_READ 0x01 +#define SOS_WRITE 0x02 + /* SSL version flags. */ #define CURL_GSKPROTO_SSLV2 0 #define CURL_GSKPROTO_SSLV2_MASK (1 << CURL_GSKPROTO_SSLV2) @@ -151,7 +155,7 @@ static const gskit_cipher ciphertable[] = { static bool is_separator(char c) { /* Return whether character is a cipher list separator. */ - switch (c) { + switch(c) { case ' ': case '\t': case ':': @@ -167,7 +171,7 @@ static CURLcode gskit_status(struct Curl_easy *data, int rc, const char *procname, CURLcode defcode) { /* Process GSKit status and map it to a CURLcode. */ - switch (rc) { + switch(rc) { case GSK_OK: case GSK_OS400_ASYNCHRONOUS_SOC_INIT: return CURLE_OK; @@ -190,7 +194,7 @@ static CURLcode gskit_status(struct Curl_easy *data, int rc, case GSK_OS400_ERROR_NOT_REGISTERED: break; case GSK_ERROR_IO: - switch (errno) { + switch(errno) { case ENOMEM: return CURLE_OUT_OF_MEMORY; default: @@ -211,7 +215,7 @@ static CURLcode set_enum(struct Curl_easy *data, gsk_handle h, { int rc = gsk_attribute_set_enum(h, id, value); - switch (rc) { + switch(rc) { case GSK_OK: return CURLE_OK; case GSK_ERROR_IO: @@ -233,7 +237,7 @@ static CURLcode set_buffer(struct Curl_easy *data, gsk_handle h, { int rc = gsk_attribute_set_buffer(h, id, buffer, 0); - switch (rc) { + switch(rc) { case GSK_OK: return CURLE_OK; case GSK_ERROR_IO: @@ -255,7 +259,7 @@ static CURLcode set_numeric(struct Curl_easy *data, { int rc = gsk_attribute_set_numeric_value(h, id, value); - switch (rc) { + switch(rc) { case GSK_OK: return CURLE_OK; case GSK_ERROR_IO: @@ -275,7 +279,7 @@ static CURLcode set_callback(struct Curl_easy *data, { int rc = gsk_attribute_set_callback(h, id, info); - switch (rc) { + switch(rc) { case GSK_OK: return CURLE_OK; case GSK_ERROR_IO: @@ -289,10 +293,11 @@ static CURLcode set_callback(struct Curl_easy *data, } -static CURLcode set_ciphers(struct Curl_easy *data, +static CURLcode set_ciphers(struct connectdata *conn, gsk_handle h, unsigned int *protoflags) { - const char *cipherlist = data->set.str[STRING_SSL_CIPHER_LIST]; + struct Curl_easy *data = conn->data; + const char *cipherlist = SSL_CONN_CONFIG(cipher_list); const char *clp; const gskit_cipher *ctp; int i; @@ -340,7 +345,7 @@ static CURLcode set_ciphers(struct Curl_easy *data, break; /* Search the cipher in our table. */ for(ctp = ciphertable; ctp->name; ctp++) - if(strnequal(ctp->name, clp, l) && !ctp->name[l]) + if(strncasecompare(ctp->name, clp, l) && !ctp->name[l]) break; if(!ctp->name) { failf(data, "Unknown cipher %.*s", l, clp); @@ -448,7 +453,7 @@ static CURLcode init_environment(struct Curl_easy *data, /* Creates the GSKit environment. */ rc = gsk_environment_open(&h); - switch (rc) { + switch(rc) { case GSK_OK: break; case GSK_INSUFFICIENT_STORAGE: @@ -500,17 +505,195 @@ static void close_async_handshake(struct ssl_connect_data *connssl) connssl->iocport = -1; } +/* SSL over SSL + * Problems: + * 1) GSKit can only perform SSL on an AF_INET or AF_INET6 stream socket. To + * pipe an SSL stream into another, it is therefore needed to have a pair + * of such communicating sockets and handle the pipelining explicitly. + * 2) OS/400 socketpair() is only implemented for domain AF_UNIX, thus cannot + * be used to produce the pipeline. + * The solution is to simulate socketpair() for AF_INET with low-level API + * listen(), bind() and connect(). + */ + +static int +inetsocketpair(int sv[2]) +{ + int lfd; /* Listening socket. */ + int sfd; /* Server socket. */ + int cfd; /* Client socket. */ + int len; + struct sockaddr_in addr1; + struct sockaddr_in addr2; + + /* Create listening socket on a local dynamic port. */ + lfd = socket(AF_INET, SOCK_STREAM, 0); + if(lfd < 0) + return -1; + memset((char *) &addr1, 0, sizeof addr1); + addr1.sin_family = AF_INET; + addr1.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addr1.sin_port = 0; + if(bind(lfd, (struct sockaddr *) &addr1, sizeof addr1) || + listen(lfd, 2) < 0) { + close(lfd); + return -1; + } + + /* Get the allocated port. */ + len = sizeof addr1; + if(getsockname(lfd, (struct sockaddr *) &addr1, &len) < 0) { + close(lfd); + return -1; + } + + /* Create the client socket. */ + cfd = socket(AF_INET, SOCK_STREAM, 0); + if(cfd < 0) { + close(lfd); + return -1; + } + + /* Request unblocking connection to the listening socket. */ + curlx_nonblock(cfd, TRUE); + if(connect(cfd, (struct sockaddr *) &addr1, sizeof addr1) < 0 && + errno != EINPROGRESS) { + close(lfd); + close(cfd); + return -1; + } + + /* Get the client dynamic port for intrusion check below. */ + len = sizeof addr2; + if(getsockname(cfd, (struct sockaddr *) &addr2, &len) < 0) { + close(lfd); + close(cfd); + return -1; + } + + /* Accept the incoming connection and get the server socket. */ + curlx_nonblock(lfd, TRUE); + for(;;) { + len = sizeof addr1; + sfd = accept(lfd, (struct sockaddr *) &addr1, &len); + if(sfd < 0) { + close(lfd); + close(cfd); + return -1; + } -static void close_one(struct ssl_connect_data *conn, - struct Curl_easy *data) + /* Check for possible intrusion from an external process. */ + if(addr1.sin_addr.s_addr == addr2.sin_addr.s_addr && + addr1.sin_port == addr2.sin_port) + break; + + /* Intrusion: reject incoming connection. */ + close(sfd); + } + + /* Done, return sockets and succeed. */ + close(lfd); + curlx_nonblock(cfd, FALSE); + sv[0] = cfd; + sv[1] = sfd; + return 0; +} + +static int pipe_ssloverssl(struct connectdata *conn, int sockindex, + int directions) { - if(conn->handle) { - gskit_status(data, gsk_secure_soc_close(&conn->handle), + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_connect_data *connproxyssl = &conn->proxy_ssl[sockindex]; + fd_set fds_read; + fd_set fds_write; + int n; + int m; + int i; + int ret = 0; + struct timeval tv = {0, 0}; + char buf[CURL_MAX_WRITE_SIZE]; + + if(!connssl->use || !connproxyssl->use) + return 0; /* No SSL over SSL: OK. */ + + FD_ZERO(&fds_read); + FD_ZERO(&fds_write); + n = -1; + if(directions & SOS_READ) { + FD_SET(connssl->remotefd, &fds_write); + n = connssl->remotefd; + } + if(directions & SOS_WRITE) { + FD_SET(connssl->remotefd, &fds_read); + n = connssl->remotefd; + FD_SET(conn->sock[sockindex], &fds_write); + if(n < conn->sock[sockindex]) + n = conn->sock[sockindex]; + } + i = select(n + 1, &fds_read, &fds_write, NULL, &tv); + if(i < 0) + return -1; /* Select error. */ + + if(FD_ISSET(connssl->remotefd, &fds_write)) { + /* Try getting data from HTTPS proxy and pipe it upstream. */ + n = 0; + i = gsk_secure_soc_read(connproxyssl->handle, buf, sizeof buf, &n); + switch(i) { + case GSK_OK: + if(n) { + i = write(connssl->remotefd, buf, n); + if(i < 0) + return -1; + ret = 1; + } + break; + case GSK_OS400_ERROR_TIMED_OUT: + case GSK_WOULD_BLOCK: + break; + default: + return -1; + } + } + + if(FD_ISSET(connssl->remotefd, &fds_read) && + FD_ISSET(conn->sock[sockindex], &fds_write)) { + /* Pipe data to HTTPS proxy. */ + n = read(connssl->remotefd, buf, sizeof buf); + if(n < 0) + return -1; + if(n) { + i = gsk_secure_soc_write(connproxyssl->handle, buf, n, &m); + if(i != GSK_OK || n != m) + return -1; + ret = 1; + } + } + + return ret; /* OK */ +} + + +static void close_one(struct ssl_connect_data *connssl, + struct connectdata *conn, int sockindex) +{ + if(connssl->handle) { + gskit_status(conn->data, gsk_secure_soc_close(&connssl->handle), "gsk_secure_soc_close()", 0); - conn->handle = (gsk_handle) NULL; + /* Last chance to drain output. */ + while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0) + ; + connssl->handle = (gsk_handle) NULL; + if(connssl->localfd >= 0) { + close(connssl->localfd); + connssl->localfd = -1; + } + if(connssl->remotefd >= 0) { + close(connssl->remotefd); + connssl->remotefd = -1; + } } - if(conn->iocport >= 0) - close_async_handshake(conn); + if(connssl->iocport >= 0) + close_async_handshake(connssl); } @@ -518,13 +701,18 @@ static ssize_t gskit_send(struct connectdata *conn, int sockindex, const void *mem, size_t len, CURLcode *curlcode) { struct Curl_easy *data = conn->data; - CURLcode cc; + CURLcode cc = CURLE_SEND_ERROR; int written; - cc = gskit_status(data, - gsk_secure_soc_write(conn->ssl[sockindex].handle, - (char *) mem, (int) len, &written), - "gsk_secure_soc_write()", CURLE_SEND_ERROR); + if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) >= 0) { + cc = gskit_status(data, + gsk_secure_soc_write(conn->ssl[sockindex].handle, + (char *) mem, (int) len, &written), + "gsk_secure_soc_write()", CURLE_SEND_ERROR); + if(cc == CURLE_OK) + if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) < 0) + cc = CURLE_SEND_ERROR; + } if(cc != CURLE_OK) { *curlcode = cc; written = -1; @@ -539,15 +727,23 @@ static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf, struct Curl_easy *data = conn->data; int buffsize; int nread; - CURLcode cc; + CURLcode cc = CURLE_RECV_ERROR; - buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize; - cc = gskit_status(data, gsk_secure_soc_read(conn->ssl[num].handle, - buf, buffsize, &nread), - "gsk_secure_soc_read()", CURLE_RECV_ERROR); - if(cc != CURLE_OK) { + if(pipe_ssloverssl(conn, num, SOS_READ) >= 0) { + buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize; + cc = gskit_status(data, gsk_secure_soc_read(conn->ssl[num].handle, + buf, buffsize, &nread), + "gsk_secure_soc_read()", CURLE_RECV_ERROR); + } + switch(cc) { + case CURLE_OK: + break; + case CURLE_OPERATION_TIMEDOUT: + cc = CURLE_AGAIN; + default: *curlcode = cc; nread = -1; + break; } return (ssize_t) nread; } @@ -560,18 +756,26 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) gsk_handle envir; CURLcode result; int rc; - char *keyringfile; - char *keyringpwd; - char *keyringlabel; - char *sni; + const char * const keyringfile = SSL_CONN_CONFIG(CAfile); + const char * const keyringpwd = SSL_SET_OPTION(key_passwd); + const char * const keyringlabel = SSL_SET_OPTION(cert); + const long int ssl_version = SSL_CONN_CONFIG(version); + const bool verifypeer = SSL_CONN_CONFIG(verifypeer); + const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name: + conn->host.name; + const char *sni; unsigned int protoflags; long timeout; Qso_OverlappedIO_t commarea; + int sockpair[2]; + static const int sobufsize = CURL_MAX_WRITE_SIZE; /* Create SSL environment, start (preferably asynchronous) handshake. */ connssl->handle = (gsk_handle) NULL; connssl->iocport = -1; + connssl->localfd = -1; + connssl->remotefd = -1; /* GSKit supports two ways of specifying an SSL context: either by * application identifier (that should have been defined at the system @@ -586,9 +790,6 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) * application identifier mode is tried first, as recommended in IBM doc. */ - keyringfile = data->set.str[STRING_SSL_CAFILE]; - keyringpwd = data->set.str[STRING_KEY_PASSWD]; - keyringlabel = data->set.str[STRING_CERT]; envir = (gsk_handle) NULL; if(keyringlabel && *keyringlabel && !keyringpwd && @@ -613,19 +814,36 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) if(result) return result; + /* Establish a pipelining socket pair for SSL over SSL. */ + if(conn->proxy_ssl[sockindex].use) { + if(inetsocketpair(sockpair)) + return CURLE_SSL_CONNECT_ERROR; + connssl->localfd = sockpair[0]; + connssl->remotefd = sockpair[1]; + setsockopt(connssl->localfd, SOL_SOCKET, SO_RCVBUF, + (void *) sobufsize, sizeof sobufsize); + setsockopt(connssl->remotefd, SOL_SOCKET, SO_RCVBUF, + (void *) sobufsize, sizeof sobufsize); + setsockopt(connssl->localfd, SOL_SOCKET, SO_SNDBUF, + (void *) sobufsize, sizeof sobufsize); + setsockopt(connssl->remotefd, SOL_SOCKET, SO_SNDBUF, + (void *) sobufsize, sizeof sobufsize); + curlx_nonblock(connssl->localfd, TRUE); + curlx_nonblock(connssl->remotefd, TRUE); + } + /* Determine which SSL/TLS version should be enabled. */ - protoflags = CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK | - CURL_GSKPROTO_TLSV12_MASK; - sni = conn->host.name; - switch (data->set.ssl.version) { + sni = hostname; + switch(ssl_version) { case CURL_SSLVERSION_SSLv2: protoflags = CURL_GSKPROTO_SSLV2_MASK; - sni = (char *) NULL; + sni = NULL; break; case CURL_SSLVERSION_SSLv3: protoflags = CURL_GSKPROTO_SSLV3_MASK; - sni = (char *) NULL; + sni = NULL; break; + case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: protoflags = CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK; @@ -639,6 +857,12 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) case CURL_SSLVERSION_TLSv1_2: protoflags = CURL_GSKPROTO_TLSV12_MASK; break; + case CURL_SSLVERSION_TLSv1_3: + failf(data, "GSKit: TLS 1.3 is not yet supported"); + return CURLE_SSL_CONNECT_ERROR; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; } /* Process SNI. Ignore if not supported (on OS400 < V7R1). */ @@ -661,9 +885,12 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) (timeout + 999) / 1000); } if(!result) - result = set_numeric(data, connssl->handle, GSK_FD, conn->sock[sockindex]); + result = set_numeric(data, connssl->handle, GSK_OS400_READ_TIMEOUT, 1); if(!result) - result = set_ciphers(data, connssl->handle, &protoflags); + result = set_numeric(data, connssl->handle, GSK_FD, connssl->localfd >= 0? + connssl->localfd: conn->sock[sockindex]); + if(!result) + result = set_ciphers(conn, connssl->handle, &protoflags); if(!protoflags) { failf(data, "No SSL protocol/cipher combination enabled"); result = CURLE_SSL_CIPHER; @@ -706,7 +933,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) } if(!result) result = set_enum(data, connssl->handle, GSK_SERVER_AUTH_TYPE, - data->set.ssl.verifypeer? GSK_SERVER_AUTH_FULL: + verifypeer? GSK_SERVER_AUTH_FULL: GSK_SERVER_AUTH_PASSTHRU, FALSE); if(!result) { @@ -730,6 +957,10 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) else if(errno != ENOBUFS) result = gskit_status(data, GSK_ERROR_IO, "QsoCreateIOCompletionPort()", 0); + else if(conn->proxy_ssl[sockindex].use) { + /* Cannot pipeline while handshaking synchronously. */ + result = CURLE_SSL_CONNECT_ERROR; + } else { /* No more completion port available. Use synchronous IO. */ result = gskit_status(data, gsk_secure_soc_init(connssl->handle), @@ -742,7 +973,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex) } /* Error: rollback. */ - close_one(connssl, data); + close_one(connssl, conn, sockindex); return result; } @@ -765,7 +996,7 @@ static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex, timeout_ms = 0; stmv.tv_sec = timeout_ms / 1000; stmv.tv_usec = (timeout_ms - stmv.tv_sec * 1000) * 1000; - switch (QsoWaitForIOCompletion(connssl->iocport, &cstat, &stmv)) { + switch(QsoWaitForIOCompletion(connssl->iocport, &cstat, &stmv)) { case 1: /* Operation complete. */ break; case -1: /* An error occurred: handshake still in progress. */ @@ -822,7 +1053,7 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex) infof(data, "Server certificate:\n"); p = cdev; for(i = 0; i++ < cdec; p++) - switch (p->cert_data_id) { + switch(p->cert_data_id) { case CERT_BODY_DER: cert = p->cert_data_p; certend = cert + cdev->cert_data_l; @@ -865,14 +1096,14 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex) } /* Check pinned public key. */ - ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY]; + ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; if(!result && ptr) { curl_X509certificate x509; curl_asn1Element *p; - if(!cert) + if(Curl_parseX509(&x509, cert, certend)) return CURLE_SSL_PINNEDPUBKEYNOTMATCH; - Curl_parseX509(&x509, cert, certend); p = &x509.subjectPublicKeyInfo; result = Curl_pin_peer_pubkey(data, ptr, p->header, p->end - p->header); if(result) { @@ -913,6 +1144,11 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex, result = gskit_connect_step1(conn, sockindex); } + /* Handle handshake pipelining. */ + if(!result) + if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0) + result = CURLE_SSL_CONNECT_ERROR; + /* Step 2: check if handshake is over. */ if(!result && connssl->connecting_state == ssl_connect_2) { /* check allowed time left */ @@ -927,12 +1163,17 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex, result = gskit_connect_step2(conn, sockindex, nonblocking); } + /* Handle handshake pipelining. */ + if(!result) + if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0) + result = CURLE_SSL_CONNECT_ERROR; + /* Step 3: gather certificate info, verify host. */ if(!result && connssl->connecting_state == ssl_connect_3) result = gskit_connect_step3(conn, sockindex); if(result) - close_one(connssl, data); + close_one(connssl, conn, sockindex); else if(connssl->connecting_state == ssl_connect_done) { connssl->state = ssl_connection_complete; connssl->connecting_state = ssl_connect_1; @@ -976,11 +1217,8 @@ CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex) void Curl_gskit_close(struct connectdata *conn, int sockindex) { - struct Curl_easy *data = conn->data; - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - - if(connssl->use) - close_one(connssl, data); + close_one(&conn->ssl[sockindex], conn, sockindex); + close_one(&conn->proxy_ssl[sockindex], conn, sockindex); } @@ -999,7 +1237,7 @@ int Curl_gskit_shutdown(struct connectdata *conn, int sockindex) if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE) return 0; - close_one(connssl, data); + close_one(connssl, conn, sockindex); rc = 0; what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT); diff --git a/lib/vtls/gskit.h b/lib/vtls/gskit.h index 41483cb..2297592 100644 --- a/lib/vtls/gskit.h +++ b/lib/vtls/gskit.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -41,6 +41,9 @@ int Curl_gskit_shutdown(struct connectdata *conn, int sockindex); size_t Curl_gskit_version(char *buffer, size_t size); int Curl_gskit_check_cxn(struct connectdata *cxn); +/* Support HTTPS-proxy */ +/* TODO: add '#define HTTPS_PROXY_SUPPORT 1' and fix test #1014 (if need) */ + /* Set the API backend definition to GSKit */ #define CURL_SSL_BACKEND CURLSSLBACKEND_GSKIT @@ -64,7 +67,7 @@ int Curl_gskit_check_cxn(struct connectdata *cxn); #define curlssl_version Curl_gskit_version #define curlssl_check_cxn(x) Curl_gskit_check_cxn(x) #define curlssl_data_pending(x,y) 0 -#define curlssl_random(x,y,z) -1 +#define curlssl_random(x,y,z) (x=x, y=y, z=z, CURLE_NOT_BUILT_IN) #endif /* USE_GSKIT */ diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c index 5c87c7f..0e308cb 100644 --- a/lib/vtls/gtls.c +++ b/lib/vtls/gtls.c @@ -68,7 +68,7 @@ #define GNUTLS_POINTER_TO_INT_CAST(p) ((int) (long) (p)) #endif #ifndef GNUTLS_INT_TO_POINTER_CAST -#define GNUTLS_INT_TO_POINTER_CAST(i) ((void*) (long) (i)) +#define GNUTLS_INT_TO_POINTER_CAST(i) ((void *) (long) (i)) #endif /* Enable GnuTLS debugging by defining GTLSDEBUG */ @@ -171,6 +171,16 @@ static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len) return ret; } +static ssize_t Curl_gtls_push_ssl(void *s, const void *buf, size_t len) +{ + return gnutls_record_send((gnutls_session_t) s, buf, len); +} + +static ssize_t Curl_gtls_pull_ssl(void *s, void *buf, size_t len) +{ + return gnutls_record_recv((gnutls_session_t) s, buf, len); +} + /* Curl_gtls_init() * * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that @@ -225,14 +235,15 @@ static void showtime(struct Curl_easy *data, infof(data, "%s\n", data->state.buffer); } -static gnutls_datum_t load_file (const char *file) +static gnutls_datum_t load_file(const char *file) { FILE *f; gnutls_datum_t loaded_file = { NULL, 0 }; long filelen; void *ptr; - if(!(f = fopen(file, "rb"))) + f = fopen(file, "rb"); + if(!f) return loaded_file; if(fseek(f, 0, SEEK_END) != 0 || (filelen = ftell(f)) < 0 @@ -251,7 +262,8 @@ out: return loaded_file; } -static void unload_file(gnutls_datum_t data) { +static void unload_file(gnutls_datum_t data) +{ free(data.data); } @@ -371,6 +383,9 @@ gtls_connect_step1(struct connectdata *conn, gnutls_session_t session; int rc; bool sni = TRUE; /* default is SNI enabled */ + void *transport_ptr = NULL; + gnutls_push_func gnutls_transport_push = NULL; + gnutls_pull_func gnutls_transport_pull = NULL; #ifdef ENABLE_IPV6 struct in6_addr addr; #else @@ -397,10 +412,13 @@ gtls_connect_step1(struct connectdata *conn, requested in the priority string, so treat it specially */ #define GNUTLS_SRP "+SRP" - const char* prioritylist; + const char *prioritylist; const char *err = NULL; #endif + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + if(conn->ssl[sockindex].state == ssl_connection_complete) /* to make us tolerant against being called more than once for the same connection */ @@ -409,12 +427,11 @@ gtls_connect_step1(struct connectdata *conn, if(!gtls_inited) Curl_gtls_init(); - /* GnuTLS only supports SSLv3 and TLSv1 */ - if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { + if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) { failf(data, "GnuTLS does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; } - else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) + else if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3) sni = FALSE; /* SSLv3 has no SNI */ /* allocate a cred struct */ @@ -425,8 +442,8 @@ gtls_connect_step1(struct connectdata *conn, } #ifdef USE_TLS_SRP - if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { - infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username); + if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) { + infof(data, "Using TLS-SRP username: %s\n", SSL_SET_OPTION(username)); rc = gnutls_srp_allocate_client_credentials( &conn->ssl[sockindex].srp_client_cred); @@ -438,8 +455,8 @@ gtls_connect_step1(struct connectdata *conn, rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex]. srp_client_cred, - data->set.ssl.username, - data->set.ssl.password); + SSL_SET_OPTION(username), + SSL_SET_OPTION(password)); if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_srp_set_client_cred() failed: %s", gnutls_strerror(rc)); @@ -448,64 +465,64 @@ gtls_connect_step1(struct connectdata *conn, } #endif - if(data->set.ssl.CAfile) { + if(SSL_CONN_CONFIG(CAfile)) { /* set the trusted CA cert bundle file */ gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred, GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT); rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred, - data->set.ssl.CAfile, + SSL_CONN_CONFIG(CAfile), GNUTLS_X509_FMT_PEM); if(rc < 0) { infof(data, "error reading ca cert file %s (%s)\n", - data->set.ssl.CAfile, gnutls_strerror(rc)); - if(data->set.ssl.verifypeer) + SSL_CONN_CONFIG(CAfile), gnutls_strerror(rc)); + if(SSL_CONN_CONFIG(verifypeer)) return CURLE_SSL_CACERT_BADFILE; } else - infof(data, "found %d certificates in %s\n", - rc, data->set.ssl.CAfile); + infof(data, "found %d certificates in %s\n", rc, + SSL_CONN_CONFIG(CAfile)); } #ifdef HAS_CAPATH - if(data->set.ssl.CApath) { + if(SSL_CONN_CONFIG(CApath)) { /* set the trusted CA cert directory */ rc = gnutls_certificate_set_x509_trust_dir(conn->ssl[sockindex].cred, - data->set.ssl.CApath, - GNUTLS_X509_FMT_PEM); + SSL_CONN_CONFIG(CApath), + GNUTLS_X509_FMT_PEM); if(rc < 0) { infof(data, "error reading ca cert file %s (%s)\n", - data->set.ssl.CAfile, gnutls_strerror(rc)); - if(data->set.ssl.verifypeer) + SSL_CONN_CONFIG(CApath), gnutls_strerror(rc)); + if(SSL_CONN_CONFIG(verifypeer)) return CURLE_SSL_CACERT_BADFILE; } else infof(data, "found %d certificates in %s\n", - rc, data->set.ssl.CApath); + rc, SSL_CONN_CONFIG(CApath)); } #endif #ifdef CURL_CA_FALLBACK /* use system ca certificate store as fallback */ - if(data->set.ssl.verifypeer && - !(data->set.ssl.CAfile || data->set.ssl.CApath)) { + if(SSL_CONN_CONFIG(verifypeer) && + !(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(CApath))) { gnutls_certificate_set_x509_system_trust(conn->ssl[sockindex].cred); } #endif - if(data->set.ssl.CRLfile) { + if(SSL_SET_OPTION(CRLfile)) { /* set the CRL list file */ rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred, - data->set.ssl.CRLfile, + SSL_SET_OPTION(CRLfile), GNUTLS_X509_FMT_PEM); if(rc < 0) { failf(data, "error reading crl file %s (%s)", - data->set.ssl.CRLfile, gnutls_strerror(rc)); + SSL_SET_OPTION(CRLfile), gnutls_strerror(rc)); return CURLE_SSL_CRL_BADFILE; } else infof(data, "found %d CRL in %s\n", - rc, data->set.ssl.CRLfile); + rc, SSL_SET_OPTION(CRLfile)); } /* Initialize TLS session as a client */ @@ -518,13 +535,13 @@ gtls_connect_step1(struct connectdata *conn, /* convenient assign */ session = conn->ssl[sockindex].session; - if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) && + if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) && #ifdef ENABLE_IPV6 - (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) && + (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) && #endif sni && - (gnutls_server_name_set(session, GNUTLS_NAME_DNS, conn->host.name, - strlen(conn->host.name)) < 0)) + (gnutls_server_name_set(session, GNUTLS_NAME_DNS, hostname, + strlen(hostname)) < 0)) infof(data, "WARNING: failed to configure server name indication (SNI) " "TLS extension\n"); @@ -545,13 +562,13 @@ gtls_connect_step1(struct connectdata *conn, if(rc != GNUTLS_E_SUCCESS) return CURLE_SSL_CONNECT_ERROR; - if(data->set.ssl.cipher_list != NULL) { + if(SSL_CONN_CONFIG(cipher_list) != NULL) { failf(data, "can't pass a custom cipher list to older GnuTLS" " versions"); return CURLE_SSL_CONNECT_ERROR; } - switch (data->set.ssl.version) { + switch(SSL_CONN_CONFIG(version) { case CURL_SSLVERSION_SSLv3: protocol_priority[0] = GNUTLS_SSL3; break; @@ -569,12 +586,16 @@ gtls_connect_step1(struct connectdata *conn, break; case CURL_SSLVERSION_TLSv1_2: protocol_priority[0] = GNUTLS_TLS1_2; - break; - case CURL_SSLVERSION_SSLv2: - default: + break; + case CURL_SSLVERSION_TLSv1_3: + failf(data, "GnuTLS: TLS 1.3 is not yet supported"); + return CURLE_SSL_CONNECT_ERROR; + case CURL_SSLVERSION_SSLv2: failf(data, "GnuTLS does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; - break; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; } rc = gnutls_protocol_set_priority(session, protocol_priority); if(rc != GNUTLS_E_SUCCESS) { @@ -586,7 +607,7 @@ gtls_connect_step1(struct connectdata *conn, /* Ensure +SRP comes at the *end* of all relevant strings so that it can be * removed if a run-time error indicates that SRP is not supported by this * GnuTLS version */ - switch (data->set.ssl.version) { + switch(SSL_CONN_CONFIG(version)) { case CURL_SSLVERSION_SSLv3: prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0"; sni = false; @@ -607,11 +628,15 @@ gtls_connect_step1(struct connectdata *conn, prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:" "+VERS-TLS1.2:" GNUTLS_SRP; break; + case CURL_SSLVERSION_TLSv1_3: + failf(data, "GnuTLS: TLS 1.3 is not yet supported"); + return CURLE_SSL_CONNECT_ERROR; case CURL_SSLVERSION_SSLv2: - default: failf(data, "GnuTLS does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; - break; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; } rc = gnutls_priority_set_direct(session, prioritylist, &err); if((rc == GNUTLS_E_INVALID_REQUEST) && err) { @@ -661,8 +686,8 @@ gtls_connect_step1(struct connectdata *conn, } #endif - if(data->set.str[STRING_CERT]) { - if(data->set.str[STRING_KEY_PASSWD]) { + if(SSL_SET_OPTION(cert)) { + if(SSL_SET_OPTION(key_passwd)) { #if HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2 const unsigned int supported_key_encryption_algorithms = GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR | @@ -671,11 +696,11 @@ gtls_connect_step1(struct connectdata *conn, GNUTLS_PKCS_USE_PBES2_AES_256; rc = gnutls_certificate_set_x509_key_file2( conn->ssl[sockindex].cred, - data->set.str[STRING_CERT], - data->set.str[STRING_KEY] ? - data->set.str[STRING_KEY] : data->set.str[STRING_CERT], - do_file_type(data->set.str[STRING_CERT_TYPE]), - data->set.str[STRING_KEY_PASSWD], + SSL_SET_OPTION(cert), + SSL_SET_OPTION(key) ? + SSL_SET_OPTION(key) : SSL_SET_OPTION(cert), + do_file_type(SSL_SET_OPTION(cert_type)), + SSL_SET_OPTION(key_passwd), supported_key_encryption_algorithms); if(rc != GNUTLS_E_SUCCESS) { failf(data, @@ -689,15 +714,14 @@ gtls_connect_step1(struct connectdata *conn, #endif } else { - rc = gnutls_certificate_set_x509_key_file( + if(gnutls_certificate_set_x509_key_file( conn->ssl[sockindex].cred, - data->set.str[STRING_CERT], - data->set.str[STRING_KEY] ? - data->set.str[STRING_KEY] : data->set.str[STRING_CERT], - do_file_type(data->set.str[STRING_CERT_TYPE]) ); - if(rc != GNUTLS_E_SUCCESS) { - failf(data, "error reading X.509 key or certificate file: %s", - gnutls_strerror(rc)); + SSL_SET_OPTION(cert), + SSL_SET_OPTION(key) ? + SSL_SET_OPTION(key) : SSL_SET_OPTION(cert), + do_file_type(SSL_SET_OPTION(cert_type)) ) != + GNUTLS_E_SUCCESS) { + failf(data, "error reading X.509 key or certificate file"); return CURLE_SSL_CONNECT_ERROR; } } @@ -705,7 +729,7 @@ gtls_connect_step1(struct connectdata *conn, #ifdef USE_TLS_SRP /* put the credentials to the current session */ - if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { + if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) { rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP, conn->ssl[sockindex].srp_client_cred); if(rc != GNUTLS_E_SUCCESS) { @@ -724,19 +748,30 @@ gtls_connect_step1(struct connectdata *conn, } } - /* set the connection handle (file descriptor for the socket) */ - gnutls_transport_set_ptr(session, - GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex])); + if(conn->proxy_ssl[sockindex].use) { + transport_ptr = conn->proxy_ssl[sockindex].session; + gnutls_transport_push = Curl_gtls_push_ssl; + gnutls_transport_pull = Curl_gtls_pull_ssl; + } + else { + /* file descriptor for the socket */ + transport_ptr = GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex]); + gnutls_transport_push = Curl_gtls_push; + gnutls_transport_pull = Curl_gtls_pull; + } + + /* set the connection handle */ + gnutls_transport_set_ptr(session, transport_ptr); /* register callback functions to send and receive data. */ - gnutls_transport_set_push_function(session, Curl_gtls_push); - gnutls_transport_set_pull_function(session, Curl_gtls_pull); + gnutls_transport_set_push_function(session, gnutls_transport_push); + gnutls_transport_set_pull_function(session, gnutls_transport_pull); /* lowat must be set to zero when using custom push and pull functions. */ gnutls_transport_set_lowat(session, 0); #ifdef HAS_OCSP - if(data->set.ssl.verifystatus) { + if(SSL_CONN_CONFIG(verifystatus)) { rc = gnutls_ocsp_status_request_enable_client(session, NULL, 0, NULL); if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc); @@ -747,17 +782,17 @@ gtls_connect_step1(struct connectdata *conn, /* This might be a reconnect, so we check for a session ID in the cache to speed up things */ - if(conn->ssl_config.sessionid) { + if(data->set.general_ssl.sessionid) { void *ssl_sessionid; size_t ssl_idsize; Curl_ssl_sessionid_lock(conn); - if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize)) { + if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize, sockindex)) { /* we got a session id, use it! */ gnutls_session_set_data(session, ssl_sessionid, ssl_idsize); /* Informational message */ - infof (data, "SSL re-using session ID\n"); + infof(data, "SSL re-using session ID\n"); } Curl_ssl_sessionid_unlock(conn); } @@ -847,8 +882,9 @@ gtls_connect_step3(struct connectdata *conn, gnutls_datum_t proto; #endif CURLcode result = CURLE_OK; - gnutls_protocol_t version = gnutls_protocol_get_version(session); + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */ ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session), @@ -866,13 +902,13 @@ gtls_connect_step3(struct connectdata *conn, chainp = gnutls_certificate_get_peers(session, &cert_list_size); if(!chainp) { - if(data->set.ssl.verifypeer || - data->set.ssl.verifyhost || - data->set.ssl.issuercert) { + if(SSL_CONN_CONFIG(verifypeer) || + SSL_CONN_CONFIG(verifyhost) || + SSL_SET_OPTION(issuercert)) { #ifdef USE_TLS_SRP - if(data->set.ssl.authtype == CURL_TLSAUTH_SRP - && data->set.ssl.username != NULL - && !data->set.ssl.verifypeer + if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP + && SSL_SET_OPTION(username) != NULL + && !SSL_CONN_CONFIG(verifypeer) && gnutls_cipher_get(session)) { /* no peer cert, but auth is ok if we have SRP user and cipher and no peer verify */ @@ -905,7 +941,7 @@ gtls_connect_step3(struct connectdata *conn, } } - if(data->set.ssl.verifypeer) { + if(SSL_CONN_CONFIG(verifypeer)) { /* This function will try to verify the peer's certificate and return its status (trusted, invalid etc.). The value of status should be one or more of the gnutls_certificate_status_t enumerated elements bitwise @@ -921,10 +957,11 @@ gtls_connect_step3(struct connectdata *conn, /* verify_status is a bitmask of gnutls_certificate_status bits */ if(verify_status & GNUTLS_CERT_INVALID) { - if(data->set.ssl.verifypeer) { + if(SSL_CONN_CONFIG(verifypeer)) { failf(data, "server certificate verification failed. CAfile: %s " - "CRLfile: %s", data->set.ssl.CAfile?data->set.ssl.CAfile:"none", - data->set.ssl.CRLfile?data->set.ssl.CRLfile:"none"); + "CRLfile: %s", SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile): + "none", + SSL_SET_OPTION(CRLfile)?SSL_SET_OPTION(CRLfile):"none"); return CURLE_SSL_CACERT; } else @@ -937,7 +974,7 @@ gtls_connect_step3(struct connectdata *conn, infof(data, "\t server certificate verification SKIPPED\n"); #ifdef HAS_OCSP - if(data->set.ssl.verifystatus) { + if(SSL_CONN_CONFIG(verifystatus)) { if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) { gnutls_datum_t status_request; gnutls_ocsp_resp_t ocsp_resp; @@ -1049,21 +1086,21 @@ gtls_connect_step3(struct connectdata *conn, gnutls_x509_crt_t format */ gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER); - if(data->set.ssl.issuercert) { + if(SSL_SET_OPTION(issuercert)) { gnutls_x509_crt_init(&x509_issuer); - issuerp = load_file(data->set.ssl.issuercert); + issuerp = load_file(SSL_SET_OPTION(issuercert)); gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM); rc = gnutls_x509_crt_check_issuer(x509_cert, x509_issuer); gnutls_x509_crt_deinit(x509_issuer); unload_file(issuerp); if(rc <= 0) { failf(data, "server certificate issuer check failed (IssuerCert: %s)", - data->set.ssl.issuercert?data->set.ssl.issuercert:"none"); + SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none"); gnutls_x509_crt_deinit(x509_cert); return CURLE_SSL_ISSUER_ERROR; } infof(data, "\t server certificate issuer check OK (Issuer Cert: %s)\n", - data->set.ssl.issuercert?data->set.ssl.issuercert:"none"); + SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none"); } size=sizeof(certbuf); @@ -1082,7 +1119,7 @@ gtls_connect_step3(struct connectdata *conn, in RFC2818 (HTTPS), which takes into account wildcards, and the subject alternative name PKIX extension. Returns non zero on success, and zero on failure. */ - rc = gnutls_x509_crt_check_hostname(x509_cert, conn->host.name); + rc = gnutls_x509_crt_check_hostname(x509_cert, hostname); #if GNUTLS_VERSION_NUMBER < 0x030306 /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP addresses. */ @@ -1098,10 +1135,10 @@ gtls_connect_step3(struct connectdata *conn, int i; int ret = 0; - if(Curl_inet_pton(AF_INET, conn->host.name, addrbuf) > 0) + if(Curl_inet_pton(AF_INET, hostname, addrbuf) > 0) addrlen = 4; #ifdef ENABLE_IPV6 - else if(Curl_inet_pton(AF_INET6, conn->host.name, addrbuf) > 0) + else if(Curl_inet_pton(AF_INET6, hostname, addrbuf) > 0) addrlen = 16; #endif @@ -1126,15 +1163,18 @@ gtls_connect_step3(struct connectdata *conn, } #endif if(!rc) { - if(data->set.ssl.verifyhost) { + const char * const dispname = SSL_IS_PROXY() ? + conn->http_proxy.host.dispname : conn->host.dispname; + + if(SSL_CONN_CONFIG(verifyhost)) { failf(data, "SSL: certificate subject name (%s) does not match " - "target host name '%s'", certbuf, conn->host.dispname); + "target host name '%s'", certbuf, dispname); gnutls_x509_crt_deinit(x509_cert); return CURLE_PEER_FAILED_VERIFICATION; } else infof(data, "\t common name: %s (does not match '%s')\n", - certbuf, conn->host.dispname); + certbuf, dispname); } else infof(data, "\t common name: %s (matched)\n", certbuf); @@ -1143,7 +1183,7 @@ gtls_connect_step3(struct connectdata *conn, certclock = gnutls_x509_crt_get_expiration_time(x509_cert); if(certclock == (time_t)-1) { - if(data->set.ssl.verifypeer) { + if(SSL_CONN_CONFIG(verifypeer)) { failf(data, "server cert expiration date verify failed"); gnutls_x509_crt_deinit(x509_cert); return CURLE_SSL_CONNECT_ERROR; @@ -1153,7 +1193,7 @@ gtls_connect_step3(struct connectdata *conn, } else { if(certclock < time(NULL)) { - if(data->set.ssl.verifypeer) { + if(SSL_CONN_CONFIG(verifypeer)) { failf(data, "server certificate expiration date has passed."); gnutls_x509_crt_deinit(x509_cert); return CURLE_PEER_FAILED_VERIFICATION; @@ -1168,7 +1208,7 @@ gtls_connect_step3(struct connectdata *conn, certclock = gnutls_x509_crt_get_activation_time(x509_cert); if(certclock == (time_t)-1) { - if(data->set.ssl.verifypeer) { + if(SSL_CONN_CONFIG(verifypeer)) { failf(data, "server cert activation date verify failed"); gnutls_x509_crt_deinit(x509_cert); return CURLE_SSL_CONNECT_ERROR; @@ -1178,7 +1218,7 @@ gtls_connect_step3(struct connectdata *conn, } else { if(certclock > time(NULL)) { - if(data->set.ssl.verifypeer) { + if(SSL_CONN_CONFIG(verifypeer)) { failf(data, "server certificate not activated yet."); gnutls_x509_crt_deinit(x509_cert); return CURLE_PEER_FAILED_VERIFICATION; @@ -1190,7 +1230,8 @@ gtls_connect_step3(struct connectdata *conn, infof(data, "\t server certificate activation date OK\n"); } - ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY]; + ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; if(ptr) { result = pkp_pin_peer_pubkey(data, x509_cert, ptr); if(result != CURLE_OK) { @@ -1270,7 +1311,7 @@ gtls_connect_step3(struct connectdata *conn, conn->recv[sockindex] = gtls_recv; conn->send[sockindex] = gtls_send; - if(conn->ssl_config.sessionid) { + if(data->set.general_ssl.sessionid) { /* we always unconditionally get the session id here, as even if we already got it from the cache and asked to use it in the connection, it might've been rejected and then a new one is in use now and we need to @@ -1289,7 +1330,8 @@ gtls_connect_step3(struct connectdata *conn, gnutls_session_get_data(session, connect_sessionid, &connect_idsize); Curl_ssl_sessionid_lock(conn); - incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)); + incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, + sockindex)); if(incache) { /* there was one before in the cache, so instead of risking that the previous one was rejected, we just kill that and store the new */ @@ -1297,7 +1339,8 @@ gtls_connect_step3(struct connectdata *conn, } /* store this session id */ - result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize); + result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize, + sockindex); Curl_ssl_sessionid_unlock(conn); if(result) { free(connect_sessionid); @@ -1332,7 +1375,7 @@ gtls_connect_common(struct connectdata *conn, /* Initiate the connection, if not already done */ if(ssl_connect_1==connssl->connecting_state) { - rc = gtls_connect_step1 (conn, sockindex); + rc = gtls_connect_step1(conn, sockindex); if(rc) return rc; } @@ -1379,6 +1422,20 @@ Curl_gtls_connect(struct connectdata *conn, return CURLE_OK; } +bool Curl_gtls_data_pending(const struct connectdata *conn, int connindex) +{ + bool res = FALSE; + if(conn->ssl[connindex].session && + 0 != gnutls_record_check_pending(conn->ssl[connindex].session)) + res = TRUE; + + if(conn->proxy_ssl[connindex].session && + 0 != gnutls_record_check_pending(conn->proxy_ssl[connindex].session)) + res = TRUE; + + return res; +} + static ssize_t gtls_send(struct connectdata *conn, int sockindex, const void *mem, @@ -1398,29 +1455,29 @@ static ssize_t gtls_send(struct connectdata *conn, return rc; } -static void close_one(struct connectdata *conn, - int idx) +static void close_one(struct ssl_connect_data *ssl) { - if(conn->ssl[idx].session) { - gnutls_bye(conn->ssl[idx].session, GNUTLS_SHUT_RDWR); - gnutls_deinit(conn->ssl[idx].session); - conn->ssl[idx].session = NULL; + if(ssl->session) { + gnutls_bye(ssl->session, GNUTLS_SHUT_RDWR); + gnutls_deinit(ssl->session); + ssl->session = NULL; } - if(conn->ssl[idx].cred) { - gnutls_certificate_free_credentials(conn->ssl[idx].cred); - conn->ssl[idx].cred = NULL; + if(ssl->cred) { + gnutls_certificate_free_credentials(ssl->cred); + ssl->cred = NULL; } #ifdef USE_TLS_SRP - if(conn->ssl[idx].srp_client_cred) { - gnutls_srp_free_client_credentials(conn->ssl[idx].srp_client_cred); - conn->ssl[idx].srp_client_cred = NULL; + if(ssl->srp_client_cred) { + gnutls_srp_free_client_credentials(ssl->srp_client_cred); + ssl->srp_client_cred = NULL; } #endif } void Curl_gtls_close(struct connectdata *conn, int sockindex) { - close_one(conn, sockindex); + close_one(&conn->ssl[sockindex]); + close_one(&conn->proxy_ssl[sockindex]); } /* @@ -1486,8 +1543,8 @@ int Curl_gtls_shutdown(struct connectdata *conn, int sockindex) gnutls_certificate_free_credentials(conn->ssl[sockindex].cred); #ifdef USE_TLS_SRP - if(data->set.ssl.authtype == CURL_TLSAUTH_SRP - && data->set.ssl.username != NULL) + if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP + && SSL_SET_OPTION(username) != NULL) gnutls_srp_free_client_credentials(conn->ssl[sockindex].srp_client_cred); #endif @@ -1597,7 +1654,7 @@ void Curl_gtls_md5sum(unsigned char *tmp, /* input */ gcry_md_hd_t MD5pw; gcry_md_open(&MD5pw, GCRY_MD_MD5, 0); gcry_md_write(MD5pw, tmp, tmplen); - memcpy(md5sum, gcry_md_read (MD5pw, 0), md5len); + memcpy(md5sum, gcry_md_read(MD5pw, 0), md5len); gcry_md_close(MD5pw); #endif } @@ -1616,7 +1673,7 @@ void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */ gcry_md_hd_t SHA256pw; gcry_md_open(&SHA256pw, GCRY_MD_SHA256, 0); gcry_md_write(SHA256pw, tmp, tmplen); - memcpy(sha256sum, gcry_md_read (SHA256pw, 0), sha256len); + memcpy(sha256sum, gcry_md_read(SHA256pw, 0), sha256len); gcry_md_close(SHA256pw); #endif } diff --git a/lib/vtls/gtls.h b/lib/vtls/gtls.h index e0a95a7..6531201 100644 --- a/lib/vtls/gtls.h +++ b/lib/vtls/gtls.h @@ -34,6 +34,8 @@ CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex); CURLcode Curl_gtls_connect_nonblocking(struct connectdata *conn, int sockindex, bool *done); +bool Curl_gtls_data_pending(const struct connectdata *conn, + int connindex); /* close a SSL connection */ void Curl_gtls_close(struct connectdata *conn, int sockindex); @@ -55,6 +57,9 @@ void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */ bool Curl_gtls_cert_status_request(void); +/* Support HTTPS-proxy */ +#define HTTPS_PROXY_SUPPORT 1 + /* Set the API backend definition to GnuTLS */ #define CURL_SSL_BACKEND CURLSSLBACKEND_GNUTLS @@ -81,7 +86,7 @@ bool Curl_gtls_cert_status_request(void); #define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL) #define curlssl_version Curl_gtls_version #define curlssl_check_cxn(x) ((void)x, -1) -#define curlssl_data_pending(x,y) ((void)x, (void)y, 0) +#define curlssl_data_pending(x,y) Curl_gtls_data_pending(x,y) #define curlssl_random(x,y,z) Curl_gtls_random(x,y,z) #define curlssl_md5sum(a,b,c,d) Curl_gtls_md5sum(a,b,c,d) #define curlssl_sha256sum(a,b,c,d) Curl_gtls_sha256sum(a,b,c,d) diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c index 24249dd..8bcaddd 100644 --- a/lib/vtls/mbedtls.c +++ b/lib/vtls/mbedtls.c @@ -31,11 +31,15 @@ #ifdef USE_MBEDTLS +#include +#if MBEDTLS_VERSION_NUMBER >= 0x02040000 #include +#else +#include +#endif #include #include #include -#include #include #include @@ -159,13 +163,20 @@ mbed_connect_step1(struct connectdata *conn, { struct Curl_easy *data = conn->data; struct ssl_connect_data* connssl = &conn->ssl[sockindex]; - + const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); + const bool verifypeer = SSL_CONN_CONFIG(verifypeer); + const char * const ssl_capath = SSL_CONN_CONFIG(CApath); + char * const ssl_cert = SSL_SET_OPTION(cert); + const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile); + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; int ret = -1; char errorbuf[128]; errorbuf[0]=0; /* mbedTLS only supports SSLv3 and TLSv1 */ - if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { + if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) { failf(data, "mbedTLS does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; } @@ -201,34 +212,32 @@ mbed_connect_step1(struct connectdata *conn, /* Load the trusted CA */ mbedtls_x509_crt_init(&connssl->cacert); - if(data->set.str[STRING_SSL_CAFILE]) { - ret = mbedtls_x509_crt_parse_file(&connssl->cacert, - data->set.str[STRING_SSL_CAFILE]); + if(ssl_cafile) { + ret = mbedtls_x509_crt_parse_file(&connssl->cacert, ssl_cafile); if(ret<0) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading ca cert file %s - mbedTLS: (-0x%04X) %s", - data->set.str[STRING_SSL_CAFILE], -ret, errorbuf); + ssl_cafile, -ret, errorbuf); - if(data->set.ssl.verifypeer) + if(verifypeer) return CURLE_SSL_CACERT_BADFILE; } } - if(data->set.str[STRING_SSL_CAPATH]) { - ret = mbedtls_x509_crt_parse_path(&connssl->cacert, - data->set.str[STRING_SSL_CAPATH]); + if(ssl_capath) { + ret = mbedtls_x509_crt_parse_path(&connssl->cacert, ssl_capath); if(ret<0) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading ca cert path %s - mbedTLS: (-0x%04X) %s", - data->set.str[STRING_SSL_CAPATH], -ret, errorbuf); + ssl_capath, -ret, errorbuf); - if(data->set.ssl.verifypeer) + if(verifypeer) return CURLE_SSL_CACERT_BADFILE; } } @@ -236,16 +245,15 @@ mbed_connect_step1(struct connectdata *conn, /* Load the client certificate */ mbedtls_x509_crt_init(&connssl->clicert); - if(data->set.str[STRING_CERT]) { - ret = mbedtls_x509_crt_parse_file(&connssl->clicert, - data->set.str[STRING_CERT]); + if(ssl_cert) { + ret = mbedtls_x509_crt_parse_file(&connssl->clicert, ssl_cert); if(ret) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading client cert file %s - mbedTLS: (-0x%04X) %s", - data->set.str[STRING_CERT], -ret, errorbuf); + ssl_cert, -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } @@ -254,9 +262,9 @@ mbed_connect_step1(struct connectdata *conn, /* Load the client private key */ mbedtls_pk_init(&connssl->pk); - if(data->set.str[STRING_KEY]) { - ret = mbedtls_pk_parse_keyfile(&connssl->pk, data->set.str[STRING_KEY], - data->set.str[STRING_KEY_PASSWD]); + if(SSL_SET_OPTION(key)) { + ret = mbedtls_pk_parse_keyfile(&connssl->pk, SSL_SET_OPTION(key), + SSL_SET_OPTION(key_passwd)); if(ret == 0 && !mbedtls_pk_can_do(&connssl->pk, MBEDTLS_PK_RSA)) ret = MBEDTLS_ERR_PK_TYPE_MISMATCH; @@ -265,7 +273,7 @@ mbed_connect_step1(struct connectdata *conn, mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s", - data->set.str[STRING_KEY], -ret, errorbuf); + SSL_SET_OPTION(key), -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } @@ -274,23 +282,21 @@ mbed_connect_step1(struct connectdata *conn, /* Load the CRL */ mbedtls_x509_crl_init(&connssl->crl); - if(data->set.str[STRING_SSL_CRLFILE]) { - ret = mbedtls_x509_crl_parse_file(&connssl->crl, - data->set.str[STRING_SSL_CRLFILE]); + if(ssl_crlfile) { + ret = mbedtls_x509_crl_parse_file(&connssl->crl, ssl_crlfile); if(ret) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading CRL file %s - mbedTLS: (-0x%04X) %s", - data->set.str[STRING_SSL_CRLFILE], -ret, errorbuf); + ssl_crlfile, -ret, errorbuf); return CURLE_SSL_CRL_BADFILE; } } - infof(data, "mbedTLS: Connecting to %s:%d\n", - conn->host.name, conn->remote_port); + infof(data, "mbedTLS: Connecting to %s:%d\n", hostname, port); mbedtls_ssl_config_init(&connssl->config); @@ -312,7 +318,7 @@ mbed_connect_step1(struct connectdata *conn, mbedtls_ssl_conf_cert_profile(&connssl->config, &mbedtls_x509_crt_profile_fr); - switch(data->set.ssl.version) { + switch(SSL_CONN_CONFIG(version)) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, @@ -347,8 +353,11 @@ mbed_connect_step1(struct connectdata *conn, MBEDTLS_SSL_MINOR_VERSION_3); infof(data, "mbedTLS: Set SSL version to TLS 1.2\n"); break; + case CURL_SSLVERSION_TLSv1_3: + failf(data, "mbedTLS: TLS 1.3 is not yet supported"); + return CURLE_SSL_CONNECT_ERROR; default: - failf(data, "mbedTLS: Unsupported SSL protocol version"); + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); return CURLE_SSL_CONNECT_ERROR; } @@ -365,11 +374,11 @@ mbed_connect_step1(struct connectdata *conn, mbedtls_ssl_list_ciphersuites()); /* Check if there's a cached ID we can/should use here! */ - if(conn->ssl_config.sessionid) { + if(data->set.general_ssl.sessionid) { void *old_session = NULL; Curl_ssl_sessionid_lock(conn); - if(!Curl_ssl_getsessionid(conn, &old_session, NULL)) { + if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) { ret = mbedtls_ssl_set_session(&connssl->ssl, old_session); if(ret) { Curl_ssl_sessionid_unlock(conn); @@ -385,11 +394,11 @@ mbed_connect_step1(struct connectdata *conn, &connssl->cacert, &connssl->crl); - if(data->set.str[STRING_KEY]) { + if(SSL_SET_OPTION(key)) { mbedtls_ssl_conf_own_cert(&connssl->config, &connssl->clicert, &connssl->pk); } - if(mbedtls_ssl_set_hostname(&connssl->ssl, conn->host.name)) { + if(mbedtls_ssl_set_hostname(&connssl->ssl, hostname)) { /* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks *and* the name to set in the SNI extension. So even if curl connects to a host specified as an IP address, this function must be used. */ @@ -443,9 +452,12 @@ mbed_connect_step2(struct connectdata *conn, struct Curl_easy *data = conn->data; struct ssl_connect_data* connssl = &conn->ssl[sockindex]; const mbedtls_x509_crt *peercert; + const char * const pinnedpubkey = SSL_IS_PROXY() ? + data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; #ifdef HAS_ALPN - const char* next_protocol; + const char *next_protocol; #endif char errorbuf[128]; @@ -479,7 +491,7 @@ mbed_connect_step2(struct connectdata *conn, ret = mbedtls_ssl_get_verify_result(&conn->ssl[sockindex].ssl); - if(ret && data->set.ssl.verifypeer) { + if(ret && SSL_CONN_CONFIG(verifypeer)) { if(ret & MBEDTLS_X509_BADCERT_EXPIRED) failf(data, "Cert verify failed: BADCERT_EXPIRED"); @@ -514,7 +526,7 @@ mbed_connect_step2(struct connectdata *conn, free(buffer); } - if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) { + if(pinnedpubkey) { int size; CURLcode result; mbedtls_x509_crt *p; @@ -553,7 +565,7 @@ mbed_connect_step2(struct connectdata *conn, /* mbedtls_pk_write_pubkey_der writes data at the end of the buffer. */ result = Curl_pin_peer_pubkey(data, - data->set.str[STRING_SSL_PINNEDPUBLICKEY], + pinnedpubkey, &pubkey[PUB_DER_MAX_BYTES - size], size); if(result) { mbedtls_x509_crt_free(p); @@ -606,7 +618,7 @@ mbed_connect_step3(struct connectdata *conn, DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); - if(conn->ssl_config.sessionid) { + if(data->set.general_ssl.sessionid) { int ret; mbedtls_ssl_session *our_ssl_sessionid; void *old_ssl_sessionid = NULL; @@ -625,10 +637,10 @@ mbed_connect_step3(struct connectdata *conn, /* If there's already a matching session in the cache, delete it */ Curl_ssl_sessionid_lock(conn); - if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL)) + if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex)) Curl_ssl_delsessionid(conn, old_ssl_sessionid); - retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0); + retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex); Curl_ssl_sessionid_unlock(conn); if(retcode) { free(our_ssl_sessionid); diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c index dff1575..ba8d582 100644 --- a/lib/vtls/nss.c +++ b/lib/vtls/nss.c @@ -200,14 +200,14 @@ static const cipher_s cipherlist[] = { #endif }; -static const char* pem_library = "libnsspem.so"; -static SECMODModule* mod = NULL; +static const char *pem_library = "libnsspem.so"; +static SECMODModule *mod = NULL; /* NSPR I/O layer we use to detect blocking direction during SSL handshake */ static PRDescIdentity nspr_io_identity = PR_INVALID_IO_LAYER; static PRIOMethods nspr_io_methods; -static const char* nss_error_to_name(PRErrorCode code) +static const char *nss_error_to_name(PRErrorCode code) { const char *name = PR_ErrorToName(code); if(name) @@ -254,7 +254,8 @@ static SECStatus set_ciphers(struct Curl_easy *data, PRFileDesc * model, while((*cipher) && (ISSPACE(*cipher))) ++cipher; - if((cipher_list = strchr(cipher, ','))) { + cipher_list = strchr(cipher, ','); + if(cipher_list) { *cipher_list++ = '\0'; } @@ -337,9 +338,8 @@ static int is_file(const char *filename) * should be later deallocated using free(). If the OOM failure occurs, we * return NULL, too. */ -static char* dup_nickname(struct Curl_easy *data, enum dupstring cert_kind) +static char *dup_nickname(struct Curl_easy *data, const char *str) { - const char *str = data->set.str[cert_kind]; const char *n; if(!is_file(str)) @@ -514,7 +514,7 @@ static CURLcode nss_cache_crl(SECItem *crl_der) return CURLE_OK; } -static CURLcode nss_load_crl(const char* crlfilename) +static CURLcode nss_load_crl(const char *crlfilename) { PRFileDesc *infile; PRFileInfo info; @@ -540,7 +540,7 @@ static CURLcode nss_load_crl(const char* crlfilename) goto fail; /* place a trailing zero right after the visible data */ - body = (char*)filedata.data; + body = (char *)filedata.data; body[--filedata.len] = '\0'; body = strstr(body, "-----BEGIN"); @@ -585,6 +585,7 @@ static CURLcode nss_load_key(struct connectdata *conn, int sockindex, SECStatus status; CURLcode result; struct ssl_connect_data *ssl = conn->ssl; + struct Curl_easy *data = conn->data; (void)sockindex; /* unused */ @@ -602,8 +603,7 @@ static CURLcode nss_load_key(struct connectdata *conn, int sockindex, SECMOD_WaitForAnyTokenEvent(mod, 0, 0); PK11_IsPresent(slot); - status = PK11_Authenticate(slot, PR_TRUE, - conn->data->set.str[STRING_KEY_PASSWD]); + status = PK11_Authenticate(slot, PR_TRUE, SSL_SET_OPTION(key_passwd)); PK11_FreeSlot(slot); return (SECSuccess == status) ? CURLE_OK : CURLE_SSL_CERTPROBLEM; @@ -664,7 +664,7 @@ static CURLcode cert_stuff(struct connectdata *conn, int sockindex, return CURLE_OK; } -static char * nss_get_password(PK11SlotInfo * slot, PRBool retry, void *arg) +static char *nss_get_password(PK11SlotInfo *slot, PRBool retry, void *arg) { (void)slot; /* unused */ @@ -682,7 +682,7 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig, struct connectdata *conn = (struct connectdata *)arg; #ifdef SSL_ENABLE_OCSP_STAPLING - if(conn->data->set.ssl.verifystatus) { + if(SSL_CONN_CONFIG(verifystatus)) { SECStatus cacheResult; const SECItemArray *csa = SSL_PeerStapledOCSPResponses(fd); @@ -708,7 +708,7 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig, } #endif - if(!conn->data->set.ssl.verifypeer) { + if(!SSL_CONN_CONFIG(verifypeer)) { infof(conn->data, "skipping SSL peer certificate verification\n"); return SECSuccess; } @@ -734,6 +734,11 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg) if(SSL_GetNextProto(sock, &state, buf, &buflen, buflenmax) == SECSuccess) { switch(state) { +#if NSSVERNUM >= 0x031a00 /* 3.26.0 */ + /* used by NSS internally to implement 0-RTT */ + case SSL_NEXT_PROTO_EARLY_VALUE: + /* fall through! */ +#endif case SSL_NEXT_PROTO_NO_SUPPORT: case SSL_NEXT_PROTO_NO_OVERLAP: infof(conn->data, "ALPN/NPN, server did not agree to a protocol\n"); @@ -928,9 +933,12 @@ static SECStatus BadCertHandler(void *arg, PRFileDesc *sock) CERTCertificate *cert; /* remember the cert verification result */ - data->set.ssl.certverifyresult = err; + if(SSL_IS_PROXY()) + data->set.proxy_ssl.certverifyresult = err; + else + data->set.ssl.certverifyresult = err; - if(err == SSL_ERROR_BAD_CERT_DOMAIN && !data->set.ssl.verifyhost) + if(err == SSL_ERROR_BAD_CERT_DOMAIN && !SSL_CONN_CONFIG(verifyhost)) /* we are asked not to verify the host name */ return SECSuccess; @@ -1367,36 +1375,55 @@ Curl_nss_check_cxn(struct connectdata *conn) return -1; /* connection status unknown */ } +static void nss_close(struct ssl_connect_data *connssl) +{ + /* before the cleanup, check whether we are using a client certificate */ + const bool client_cert = (connssl->client_nickname != NULL) + || (connssl->obj_clicert != NULL); + + free(connssl->client_nickname); + connssl->client_nickname = NULL; + + /* destroy all NSS objects in order to avoid failure of NSS shutdown */ + Curl_llist_destroy(connssl->obj_list, NULL); + connssl->obj_list = NULL; + connssl->obj_clicert = NULL; + + if(connssl->handle) { + if(client_cert) + /* A server might require different authentication based on the + * particular path being requested by the client. To support this + * scenario, we must ensure that a connection will never reuse the + * authentication data from a previous connection. */ + SSL_InvalidateSession(connssl->handle); + + PR_Close(connssl->handle); + connssl->handle = NULL; + } +} + /* * This function is called when an SSL connection is closed. */ void Curl_nss_close(struct connectdata *conn, int sockindex) { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct ssl_connect_data *connssl_proxy = &conn->proxy_ssl[sockindex]; - if(connssl->handle) { + if(connssl->handle || connssl_proxy->handle) { /* NSS closes the socket we previously handed to it, so we must mark it as closed to avoid double close */ fake_sclose(conn->sock[sockindex]); conn->sock[sockindex] = CURL_SOCKET_BAD; + } - if((connssl->client_nickname != NULL) || (connssl->obj_clicert != NULL)) - /* A server might require different authentication based on the - * particular path being requested by the client. To support this - * scenario, we must ensure that a connection will never reuse the - * authentication data from a previous connection. */ - SSL_InvalidateSession(connssl->handle); - - free(connssl->client_nickname); - connssl->client_nickname = NULL; - /* destroy all NSS objects in order to avoid failure of NSS shutdown */ - Curl_llist_destroy(connssl->obj_list, NULL); - connssl->obj_list = NULL; - connssl->obj_clicert = NULL; + if(connssl->handle) + /* nss_close(connssl) will transitively close also connssl_proxy->handle + if both are used. Clear it to avoid a double close leading to crash. */ + connssl_proxy->handle = NULL; - PR_Close(connssl->handle); - connssl->handle = NULL; - } + nss_close(connssl); + nss_close(connssl_proxy); } /* return true if NSS can provide error code (and possibly msg) for the @@ -1437,8 +1464,8 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn, int sockindex) { struct Curl_easy *data = conn->data; - const char *cafile = data->set.ssl.CAfile; - const char *capath = data->set.ssl.CApath; + const char *cafile = SSL_CONN_CONFIG(CAfile); + const char *capath = SSL_CONN_CONFIG(CApath); if(cafile) { CURLcode result = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE); @@ -1486,13 +1513,22 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn, } static CURLcode nss_init_sslver(SSLVersionRange *sslver, - struct Curl_easy *data) + struct Curl_easy *data, + struct connectdata *conn) { - switch(data->set.ssl.version) { - default: + switch(SSL_CONN_CONFIG(version)) { case CURL_SSLVERSION_DEFAULT: + /* map CURL_SSLVERSION_DEFAULT to NSS default */ + if(SSL_VersionRangeGetDefault(ssl_variant_stream, sslver) != SECSuccess) + return CURLE_SSL_CONNECT_ERROR; + /* ... but make sure we use at least TLSv1.0 according to libcurl API */ + if(sslver->min < SSL_LIBRARY_VERSION_TLS_1_0) + sslver->min = SSL_LIBRARY_VERSION_TLS_1_0; + return CURLE_OK; + case CURL_SSLVERSION_TLSv1: sslver->min = SSL_LIBRARY_VERSION_TLS_1_0; + /* TODO: set sslver->max to SSL_LIBRARY_VERSION_TLS_1_3 once stable */ #ifdef SSL_LIBRARY_VERSION_TLS_1_2 sslver->max = SSL_LIBRARY_VERSION_TLS_1_2; #elif defined SSL_LIBRARY_VERSION_TLS_1_1 @@ -1532,6 +1568,18 @@ static CURLcode nss_init_sslver(SSLVersionRange *sslver, return CURLE_OK; #endif break; + + case CURL_SSLVERSION_TLSv1_3: +#ifdef SSL_LIBRARY_VERSION_TLS_1_3 + sslver->min = SSL_LIBRARY_VERSION_TLS_1_3; + sslver->max = SSL_LIBRARY_VERSION_TLS_1_3; + return CURLE_OK; +#endif + break; + + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; } failf(data, "TLS minor version cannot be set"); @@ -1589,6 +1637,7 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) curl_socket_t sockfd = conn->sock[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; CURLcode result; + bool second_layer = FALSE; SSLVersionRange sslver = { SSL_LIBRARY_VERSION_TLS_1_0, /* min */ @@ -1647,18 +1696,18 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) goto error; /* do not use SSL cache if disabled or we are not going to verify peer */ - ssl_no_cache = (conn->ssl_config.sessionid && data->set.ssl.verifypeer) ? - PR_FALSE : PR_TRUE; + ssl_no_cache = (data->set.general_ssl.sessionid + && SSL_CONN_CONFIG(verifypeer)) ? PR_FALSE : PR_TRUE; if(SSL_OptionSet(model, SSL_NO_CACHE, ssl_no_cache) != SECSuccess) goto error; /* enable/disable the requested SSL version(s) */ - if(nss_init_sslver(&sslver, data) != CURLE_OK) + if(nss_init_sslver(&sslver, data, conn) != CURLE_OK) goto error; if(SSL_VersionRangeSet(model, &sslver) != SECSuccess) goto error; - ssl_cbc_random_iv = !data->set.ssl_enable_beast; + ssl_cbc_random_iv = !SSL_SET_OPTION(enable_beast); #ifdef SSL_CBC_RANDOM_IV /* unless the user explicitly asks to allow the protocol vulnerability, we use the work-around */ @@ -1670,14 +1719,14 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) infof(data, "warning: support for SSL_CBC_RANDOM_IV not compiled in\n"); #endif - if(data->set.ssl.cipher_list) { - if(set_ciphers(data, model, data->set.ssl.cipher_list) != SECSuccess) { + if(SSL_CONN_CONFIG(cipher_list)) { + if(set_ciphers(data, model, SSL_CONN_CONFIG(cipher_list)) != SECSuccess) { result = CURLE_SSL_CIPHER; goto error; } } - if(!data->set.ssl.verifypeer && data->set.ssl.verifyhost) + if(!SSL_CONN_CONFIG(verifypeer) && SSL_CONN_CONFIG(verifyhost)) infof(data, "warning: ignoring value of ssl.verifyhost\n"); /* bypass the default SSL_AuthCertificate() hook in case we do not want to @@ -1685,14 +1734,19 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) if(SSL_AuthCertificateHook(model, nss_auth_cert_hook, conn) != SECSuccess) goto error; - data->set.ssl.certverifyresult=0; /* not checked yet */ + /* not checked yet */ + if(SSL_IS_PROXY()) + data->set.proxy_ssl.certverifyresult = 0; + else + data->set.ssl.certverifyresult = 0; + if(SSL_BadCertHook(model, BadCertHandler, conn) != SECSuccess) goto error; if(SSL_HandshakeCallback(model, HandshakeCallback, conn) != SECSuccess) goto error; - if(data->set.ssl.verifypeer) { + if(SSL_CONN_CONFIG(verifypeer)) { const CURLcode rv = nss_load_ca_certificates(conn, sockindex); if(rv) { result = rv; @@ -1700,24 +1754,24 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) } } - if(data->set.ssl.CRLfile) { - const CURLcode rv = nss_load_crl(data->set.ssl.CRLfile); + if(SSL_SET_OPTION(CRLfile)) { + const CURLcode rv = nss_load_crl(SSL_SET_OPTION(CRLfile)); if(rv) { result = rv; goto error; } - infof(data, " CRLfile: %s\n", data->set.ssl.CRLfile); + infof(data, " CRLfile: %s\n", SSL_SET_OPTION(CRLfile)); } - if(data->set.str[STRING_CERT]) { - char *nickname = dup_nickname(data, STRING_CERT); + if(SSL_SET_OPTION(cert)) { + char *nickname = dup_nickname(data, SSL_SET_OPTION(cert)); if(nickname) { /* we are not going to use libnsspem.so to read the client cert */ connssl->obj_clicert = NULL; } else { - CURLcode rv = cert_stuff(conn, sockindex, data->set.str[STRING_CERT], - data->set.str[STRING_KEY]); + CURLcode rv = cert_stuff(conn, sockindex, SSL_SET_OPTION(cert), + SSL_SET_OPTION(key)); if(rv) { /* failf() is already done in cert_stuff() */ result = rv; @@ -1737,15 +1791,24 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) goto error; } - /* wrap OS file descriptor by NSPR's file descriptor abstraction */ - nspr_io = PR_ImportTCPSocket(sockfd); - if(!nspr_io) - goto error; + if(conn->proxy_ssl[sockindex].use) { + DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state); + DEBUGASSERT(conn->proxy_ssl[sockindex].handle != NULL); + nspr_io = conn->proxy_ssl[sockindex].handle; + second_layer = TRUE; + } + else { + /* wrap OS file descriptor by NSPR's file descriptor abstraction */ + nspr_io = PR_ImportTCPSocket(sockfd); + if(!nspr_io) + goto error; + } /* create our own NSPR I/O layer */ nspr_io_stub = PR_CreateIOLayerStub(nspr_io_identity, &nspr_io_methods); if(!nspr_io_stub) { - PR_Close(nspr_io); + if(!second_layer) + PR_Close(nspr_io); goto error; } @@ -1754,7 +1817,8 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) /* push our new layer to the NSPR I/O stack */ if(PR_PushIOLayer(nspr_io, PR_TOP_IO_LAYER, nspr_io_stub) != PR_SUCCESS) { - PR_Close(nspr_io); + if(!second_layer) + PR_Close(nspr_io); PR_Close(nspr_io_stub); goto error; } @@ -1762,7 +1826,8 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) /* import our model socket onto the current I/O stack */ connssl->handle = SSL_ImportFD(model, nspr_io); if(!connssl->handle) { - PR_Close(nspr_io); + if(!second_layer) + PR_Close(nspr_io); goto error; } @@ -1770,12 +1835,12 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) model = NULL; /* This is the password associated with the cert that we're using */ - if(data->set.str[STRING_KEY_PASSWD]) { - SSL_SetPKCS11PinArg(connssl->handle, data->set.str[STRING_KEY_PASSWD]); + if(SSL_SET_OPTION(key_passwd)) { + SSL_SetPKCS11PinArg(connssl->handle, SSL_SET_OPTION(key_passwd)); } #ifdef SSL_ENABLE_OCSP_STAPLING - if(data->set.ssl.verifystatus) { + if(SSL_CONN_CONFIG(verifystatus)) { if(SSL_OptionSet(connssl->handle, SSL_ENABLE_OCSP_STAPLING, PR_TRUE) != SECSuccess) goto error; @@ -1835,11 +1900,14 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) goto error; /* propagate hostname to the TLS layer */ - if(SSL_SetURL(connssl->handle, conn->host.name) != SECSuccess) + if(SSL_SetURL(connssl->handle, SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name) != SECSuccess) goto error; /* prevent NSS from re-using the session for a different hostname */ - if(SSL_SetSockPeerID(connssl->handle, conn->host.name) != SECSuccess) + if(SSL_SetSockPeerID(connssl->handle, SSL_IS_PROXY() ? + conn->http_proxy.host.name : conn->host.name) + != SECSuccess) goto error; return CURLE_OK; @@ -1857,6 +1925,12 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) struct Curl_easy *data = conn->data; CURLcode result = CURLE_SSL_CONNECT_ERROR; PRUint32 timeout; + long * const certverifyresult = SSL_IS_PROXY() ? + &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult; + const char * const pinnedpubkey = SSL_IS_PROXY() ? + data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; + /* check timeout situation */ const long time_left = Curl_timeleft(data, NULL, TRUE); @@ -1872,9 +1946,9 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) if(PR_GetError() == PR_WOULD_BLOCK_ERROR) /* blocking direction is updated by nss_update_connecting_state() */ return CURLE_AGAIN; - else if(conn->data->set.ssl.certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN) + else if(*certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN) result = CURLE_PEER_FAILED_VERIFICATION; - else if(conn->data->set.ssl.certverifyresult!=0) + else if(*certverifyresult != 0) result = CURLE_SSL_CACERT; goto error; } @@ -1883,11 +1957,11 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) if(result) goto error; - if(data->set.str[STRING_SSL_ISSUERCERT]) { + if(SSL_SET_OPTION(issuercert)) { SECStatus ret = SECFailure; - char *nickname = dup_nickname(data, STRING_SSL_ISSUERCERT); + char *nickname = dup_nickname(data, SSL_SET_OPTION(issuercert)); if(nickname) { - /* we support only nicknames in case of STRING_SSL_ISSUERCERT for now */ + /* we support only nicknames in case of issuercert for now */ ret = check_issuer_cert(connssl->handle, nickname); free(nickname); } @@ -1902,7 +1976,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) } } - result = cmp_peer_pubkey(connssl, data->set.str[STRING_SSL_PINNEDPUBLICKEY]); + result = cmp_peer_pubkey(connssl, pinnedpubkey); if(result) /* status already printed */ goto error; @@ -2112,7 +2186,8 @@ bool Curl_nss_cert_status_request(void) #endif } -bool Curl_nss_false_start(void) { +bool Curl_nss_false_start(void) +{ #if NSSVERNUM >= 0x030f04 /* 3.15.4 */ return TRUE; #else diff --git a/lib/vtls/nssg.h b/lib/vtls/nssg.h index ac67e6a..fd94003 100644 --- a/lib/vtls/nssg.h +++ b/lib/vtls/nssg.h @@ -65,6 +65,9 @@ bool Curl_nss_cert_status_request(void); bool Curl_nss_false_start(void); +/* Support HTTPS-proxy */ +#define HTTPS_PROXY_SUPPORT 1 + /* Set the API backend definition to NSS */ #define CURL_SSL_BACKEND CURLSSLBACKEND_NSS diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c index c040928..d92e713 100644 --- a/lib/vtls/openssl.c +++ b/lib/vtls/openssl.c @@ -176,39 +176,34 @@ static int passwd_callback(char *buf, int num, int encrypting, } /* - * rand_enough() is a function that returns TRUE if we have seeded the random - * engine properly. We use some preprocessor magic to provide a seed_enough() - * macro to use, just to prevent a compiler warning on this function if we - * pass in an argument that is never used. + * rand_enough() returns TRUE if we have seeded the random engine properly. */ - -#ifdef HAVE_RAND_STATUS -#define seed_enough(x) rand_enough() static bool rand_enough(void) { return (0 != RAND_status()) ? TRUE : FALSE; } -#else -#define seed_enough(x) rand_enough(x) -static bool rand_enough(int nread) -{ - /* this is a very silly decision to make */ - return (nread > 500) ? TRUE : FALSE; -} -#endif -static int ossl_seed(struct Curl_easy *data) +static CURLcode Curl_ossl_seed(struct Curl_easy *data) { + /* we have the "SSL is seeded" boolean static to prevent multiple + time-consuming seedings in vain */ + static bool ssl_seeded = FALSE; char *buf = data->state.buffer; /* point to the big buffer */ int nread=0; - /* Q: should we add support for a random file name as a libcurl option? - A: Yes, it is here */ + if(ssl_seeded) + return CURLE_OK; + + if(rand_enough()) { + /* OpenSSL 1.1.0+ will return here */ + ssl_seeded = TRUE; + return CURLE_OK; + } #ifndef RANDOM_FILE /* if RANDOM_FILE isn't defined, we only perform this if an option tells us to! */ - if(data->set.ssl.random_file) + if(data->set.str[STRING_SSL_RANDOM_FILE]) #define RANDOM_FILE "" /* doesn't matter won't be used */ #endif { @@ -217,7 +212,7 @@ static int ossl_seed(struct Curl_easy *data) data->set.str[STRING_SSL_RANDOM_FILE]: RANDOM_FILE), RAND_LOAD_LENGTH); - if(seed_enough(nread)) + if(rand_enough()) return nread; } @@ -237,7 +232,7 @@ static int ossl_seed(struct Curl_easy *data) data->set.str[STRING_SSL_EGDSOCKET]:EGD_SOCKET); if(-1 != ret) { nread += ret; - if(seed_enough(nread)) + if(rand_enough()) return nread; } } @@ -248,9 +243,10 @@ static int ossl_seed(struct Curl_easy *data) do { unsigned char randb[64]; int len = sizeof(randb); - RAND_bytes(randb, len); + if(!RAND_bytes(randb, len)) + break; RAND_add(randb, len, (len >> 1)); - } while(!RAND_status()); + } while(!rand_enough()); /* generates a default path for the random seed file */ buf[0]=0; /* blank it first */ @@ -258,25 +254,12 @@ static int ossl_seed(struct Curl_easy *data) if(buf[0]) { /* we got a file name to try */ nread += RAND_load_file(buf, RAND_LOAD_LENGTH); - if(seed_enough(nread)) + if(rand_enough()) return nread; } infof(data, "libcurl is now using a weak random seed!\n"); - return nread; -} - -static void Curl_ossl_seed(struct Curl_easy *data) -{ - /* we have the "SSL is seeded" boolean static to prevent multiple - time-consuming seedings in vain */ - static bool ssl_seeded = FALSE; - - if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] || - data->set.str[STRING_SSL_EGDSOCKET]) { - ossl_seed(data); - ssl_seeded = TRUE; - } + return CURLE_SSL_CONNECT_ERROR; /* confusing error code */ } #ifndef SSL_FILETYPE_ENGINE @@ -312,7 +295,7 @@ static int ssl_ui_reader(UI *ui, UI_STRING *uis) switch(UI_get_string_type(uis)) { case UIT_PROMPT: case UIT_VERIFY: - password = (const char*)UI_get0_user_data(ui); + password = (const char *)UI_get0_user_data(ui); if(password && (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD)) { UI_set_result(ui, uis, password); return 1; @@ -348,7 +331,8 @@ int cert_stuff(struct connectdata *conn, char *cert_file, const char *cert_type, char *key_file, - const char *key_type) + const char *key_type, + char *key_passwd) { struct Curl_easy *data = conn->data; @@ -359,10 +343,9 @@ int cert_stuff(struct connectdata *conn, X509 *x509; int cert_done = 0; - if(data->set.str[STRING_KEY_PASSWD]) { + if(key_passwd) { /* set the password in the callback userdata */ - SSL_CTX_set_default_passwd_cb_userdata(ctx, - data->set.str[STRING_KEY_PASSWD]); + SSL_CTX_set_default_passwd_cb_userdata(ctx, key_passwd); /* Set passwd callback: */ SSL_CTX_set_default_passwd_cb(ctx, passwd_callback); } @@ -473,7 +456,7 @@ int cert_stuff(struct connectdata *conn, PKCS12_PBE_add(); - if(!PKCS12_parse(p12, data->set.str[STRING_KEY_PASSWD], &pri, &x509, + if(!PKCS12_parse(p12, key_passwd, &pri, &x509, &ca)) { failf(data, "could not parse PKCS12 file, check password, " OSSL_PACKAGE @@ -571,7 +554,7 @@ int cert_stuff(struct connectdata *conn, EVP_PKEY *priv_key = NULL; if(data->state.engine) { UI_METHOD *ui_method = - UI_create_method((char *)"cURL user interface"); + UI_create_method((char *)"curl user interface"); if(!ui_method) { failf(data, "unable do create " OSSL_PACKAGE " user-interface method"); @@ -585,7 +568,7 @@ int cert_stuff(struct connectdata *conn, priv_key = (EVP_PKEY *) ENGINE_load_private_key(data->state.engine, key_file, ui_method, - data->set.str[STRING_KEY_PASSWD]); + key_passwd); UI_destroy_method(ui_method); if(!priv_key) { failf(data, "failed to load private key from crypto engine"); @@ -916,27 +899,31 @@ struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data) } -/* - * This function is called when an SSL connection is closed. - */ -void Curl_ossl_close(struct connectdata *conn, int sockindex) +static void ossl_close(struct ssl_connect_data *connssl) { - struct ssl_connect_data *connssl = &conn->ssl[sockindex]; - if(connssl->handle) { (void)SSL_shutdown(connssl->handle); SSL_set_connect_state(connssl->handle); - SSL_free (connssl->handle); + SSL_free(connssl->handle); connssl->handle = NULL; } if(connssl->ctx) { - SSL_CTX_free (connssl->ctx); + SSL_CTX_free(connssl->ctx); connssl->ctx = NULL; } } /* + * This function is called when an SSL connection is closed. + */ +void Curl_ossl_close(struct connectdata *conn, int sockindex) +{ + ossl_close(&conn->ssl[sockindex]); + ossl_close(&conn->proxy_ssl[sockindex]); +} + +/* * This function is called to shut down the SSL layer but keep the * socket open (CCC - Clear Command Channel) */ @@ -1031,7 +1018,7 @@ int Curl_ossl_shutdown(struct connectdata *conn, int sockindex) #endif } - SSL_free (connssl->handle); + SSL_free(connssl->handle); connssl->handle = NULL; } return retval; @@ -1107,16 +1094,20 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) CURLcode result = CURLE_OK; bool dNSName = FALSE; /* if a dNSName field exists in the cert */ bool iPAddress = FALSE; /* if a iPAddress field exists in the cert */ + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + const char * const dispname = SSL_IS_PROXY() ? + conn->http_proxy.host.dispname : conn->host.dispname; #ifdef ENABLE_IPV6 if(conn->bits.ipv6_ip && - Curl_inet_pton(AF_INET6, conn->host.name, &addr)) { + Curl_inet_pton(AF_INET6, hostname, &addr)) { target = GEN_IPADD; addrlen = sizeof(struct in6_addr); } else #endif - if(Curl_inet_pton(AF_INET, conn->host.name, &addr)) { + if(Curl_inet_pton(AF_INET, hostname, &addr)) { target = GEN_IPADD; addrlen = sizeof(struct in_addr); } @@ -1165,11 +1156,11 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) if((altlen == strlen(altptr)) && /* if this isn't true, there was an embedded zero in the name string and we cannot match it. */ - Curl_cert_hostcheck(altptr, conn->host.name)) { + Curl_cert_hostcheck(altptr, hostname)) { dnsmatched = TRUE; infof(data, " subjectAltName: host \"%s\" matched cert's \"%s\"\n", - conn->host.dispname, altptr); + dispname, altptr); } break; @@ -1180,7 +1171,7 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) ipmatched = TRUE; infof(data, " subjectAltName: host \"%s\" matched cert's IP address!\n", - conn->host.dispname); + dispname); } break; } @@ -1196,9 +1187,9 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) /* an alternative name matched */ ; else if(dNSName || iPAddress) { - infof(data, " subjectAltName does not match %s\n", conn->host.dispname); + infof(data, " subjectAltName does not match %s\n", dispname); failf(data, "SSL: no alternative certificate subject name matches " - "target host name '%s'", conn->host.dispname); + "target host name '%s'", dispname); result = CURLE_PEER_FAILED_VERIFICATION; } else { @@ -1272,9 +1263,9 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert) "SSL: unable to obtain common name from peer certificate"); result = CURLE_PEER_FAILED_VERIFICATION; } - else if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) { + else if(!Curl_cert_hostcheck((const char *)peer_CN, hostname)) { failf(data, "SSL: certificate subject name '%s' does not match " - "target host name '%s'", peer_CN, conn->host.dispname); + "target host name '%s'", peer_CN, dispname); result = CURLE_PEER_FAILED_VERIFICATION; } else { @@ -1425,7 +1416,7 @@ static const char *ssl_msg_type(int ssl_ver, int msg) { #ifdef SSL2_VERSION_MAJOR if(ssl_ver == SSL2_VERSION_MAJOR) { - switch (msg) { + switch(msg) { case SSL2_MT_ERROR: return "Error"; case SSL2_MT_CLIENT_HELLO: @@ -1449,7 +1440,7 @@ static const char *ssl_msg_type(int ssl_ver, int msg) else #endif if(ssl_ver == SSL3_VERSION_MAJOR) { - switch (msg) { + switch(msg) { case SSL3_MT_HELLO_REQUEST: return "Hello request"; case SSL3_MT_CLIENT_HELLO: @@ -1549,6 +1540,11 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type, verstr = "TLSv1.2"; break; #endif +#ifdef TLS1_3_VERSION + case TLS1_3_VERSION: + verstr = "TLSv1.3"; + break; +#endif case 0: break; default: @@ -1571,7 +1567,7 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type, else tls_rt_name = ""; - msg_type = *(char*)buf; + msg_type = *(char *)buf; msg_name = ssl_msg_type(ssl_ver, msg_type); txt_len = snprintf(ssl_buf, sizeof(ssl_buf), "%s (%s), %s, %s (%d):\n", @@ -1677,6 +1673,10 @@ get_ssl_version_txt(SSL *ssl) return ""; switch(SSL_version(ssl)) { +#ifdef TLS1_3_VERSION + case TLS1_3_VERSION: + return "TLSv1.3"; +#endif #if OPENSSL_VERSION_NUMBER >= 0x1000100FL case TLS1_2_VERSION: return "TLSv1.2"; @@ -1711,23 +1711,39 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) struct in_addr addr; #endif #endif + long * const certverifyresult = SSL_IS_PROXY() ? + &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult; + const long int ssl_version = SSL_CONN_CONFIG(version); +#ifdef USE_TLS_SRP + const enum CURL_TLSAUTH ssl_authtype = SSL_SET_OPTION(authtype); +#endif + char * const ssl_cert = SSL_SET_OPTION(cert); + const char * const ssl_cert_type = SSL_SET_OPTION(cert_type); + const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); + const char * const ssl_capath = SSL_CONN_CONFIG(CApath); + const bool verifypeer = SSL_CONN_CONFIG(verifypeer); + const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile); + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; DEBUGASSERT(ssl_connect_1 == connssl->connecting_state); /* Make funny stuff to get random input */ - Curl_ossl_seed(data); + result = Curl_ossl_seed(data); + if(result) + return result; - data->set.ssl.certverifyresult = !X509_V_OK; + *certverifyresult = !X509_V_OK; /* check to see if we've been told to use an explicit SSL/TLS version */ - switch(data->set.ssl.version) { - default: + switch(ssl_version) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: case CURL_SSLVERSION_TLSv1_0: case CURL_SSLVERSION_TLSv1_1: case CURL_SSLVERSION_TLSv1_2: + case CURL_SSLVERSION_TLSv1_3: /* it will be handled later with the context options */ #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \ !defined(LIBRESSL_VERSION_NUMBER) @@ -1743,7 +1759,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) return CURLE_NOT_BUILT_IN; #else #ifdef USE_TLS_SRP - if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) + if(ssl_authtype == CURL_TLSAUTH_SRP) return CURLE_SSL_CONNECT_ERROR; #endif req_method = SSLv2_client_method(); @@ -1756,13 +1772,16 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) return CURLE_NOT_BUILT_IN; #else #ifdef USE_TLS_SRP - if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) + if(ssl_authtype == CURL_TLSAUTH_SRP) return CURLE_SSL_CONNECT_ERROR; #endif req_method = SSLv3_client_method(); use_sni(FALSE); break; #endif + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; } if(connssl->ctx) @@ -1841,14 +1860,14 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) #ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS /* unless the user explicitly ask to allow the protocol vulnerability we use the work-around */ - if(!conn->data->set.ssl_enable_beast) + if(!SSL_SET_OPTION(enable_beast)) ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; #endif - switch(data->set.ssl.version) { + switch(ssl_version) { case CURL_SSLVERSION_SSLv3: #ifdef USE_TLS_SRP - if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { + if(ssl_authtype == CURL_TLSAUTH_SRP) { infof(data, "Set version TLSv1.x for SRP authorisation\n"); } #endif @@ -1857,6 +1876,9 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) #if OPENSSL_VERSION_NUMBER >= 0x1000100FL ctx_options |= SSL_OP_NO_TLSv1_1; ctx_options |= SSL_OP_NO_TLSv1_2; +#ifdef TLS1_3_VERSION + ctx_options |= SSL_OP_NO_TLSv1_3; +#endif #endif break; @@ -1872,38 +1894,75 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) #if OPENSSL_VERSION_NUMBER >= 0x1000100FL ctx_options |= SSL_OP_NO_TLSv1_1; ctx_options |= SSL_OP_NO_TLSv1_2; +#ifdef TLS1_3_VERSION + ctx_options |= SSL_OP_NO_TLSv1_3; +#endif #endif break; -#if OPENSSL_VERSION_NUMBER >= 0x1000100FL case CURL_SSLVERSION_TLSv1_1: +#if OPENSSL_VERSION_NUMBER >= 0x1000100FL ctx_options |= SSL_OP_NO_SSLv2; ctx_options |= SSL_OP_NO_SSLv3; ctx_options |= SSL_OP_NO_TLSv1; ctx_options |= SSL_OP_NO_TLSv1_2; +#ifdef TLS1_3_VERSION + ctx_options |= SSL_OP_NO_TLSv1_3; +#endif break; +#else + failf(data, OSSL_PACKAGE " was built without TLS 1.1 support"); + return CURLE_NOT_BUILT_IN; +#endif case CURL_SSLVERSION_TLSv1_2: +#if OPENSSL_VERSION_NUMBER >= 0x1000100FL ctx_options |= SSL_OP_NO_SSLv2; ctx_options |= SSL_OP_NO_SSLv3; ctx_options |= SSL_OP_NO_TLSv1; ctx_options |= SSL_OP_NO_TLSv1_1; +#ifdef TLS1_3_VERSION + ctx_options |= SSL_OP_NO_TLSv1_3; +#endif break; +#else + failf(data, OSSL_PACKAGE " was built without TLS 1.2 support"); + return CURLE_NOT_BUILT_IN; +#endif + + case CURL_SSLVERSION_TLSv1_3: +#ifdef TLS1_3_VERSION + SSL_CTX_set_max_proto_version(connssl->ctx, TLS1_3_VERSION); + ctx_options |= SSL_OP_NO_SSLv2; + ctx_options |= SSL_OP_NO_SSLv3; + ctx_options |= SSL_OP_NO_TLSv1; + ctx_options |= SSL_OP_NO_TLSv1_1; + ctx_options |= SSL_OP_NO_TLSv1_2; + break; +#else + failf(data, OSSL_PACKAGE " was built without TLS 1.3 support"); + return CURLE_NOT_BUILT_IN; #endif -#ifndef OPENSSL_NO_SSL2 case CURL_SSLVERSION_SSLv2: +#ifndef OPENSSL_NO_SSL2 ctx_options |= SSL_OP_NO_SSLv3; ctx_options |= SSL_OP_NO_TLSv1; #if OPENSSL_VERSION_NUMBER >= 0x1000100FL ctx_options |= SSL_OP_NO_TLSv1_1; ctx_options |= SSL_OP_NO_TLSv1_2; +#ifdef TLS1_3_VERSION + ctx_options |= SSL_OP_NO_TLSv1_3; +#endif #endif break; +#else + failf(data, OSSL_PACKAGE " was built without SSLv2 support"); + return CURLE_NOT_BUILT_IN; #endif default: - failf(data, "Unsupported SSL protocol version"); + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); return CURLE_SSL_CONNECT_ERROR; } @@ -1942,19 +2001,16 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) } #endif - if(data->set.str[STRING_CERT] || data->set.str[STRING_CERT_TYPE]) { - if(!cert_stuff(conn, - connssl->ctx, - data->set.str[STRING_CERT], - data->set.str[STRING_CERT_TYPE], - data->set.str[STRING_KEY], - data->set.str[STRING_KEY_TYPE])) { + if(ssl_cert || ssl_cert_type) { + if(!cert_stuff(conn, connssl->ctx, ssl_cert, ssl_cert_type, + SSL_SET_OPTION(key), SSL_SET_OPTION(key_type), + SSL_SET_OPTION(key_passwd))) { /* failf() is already done in cert_stuff() */ return CURLE_SSL_CERTPROBLEM; } } - ciphers = data->set.str[STRING_SSL_CIPHER_LIST]; + ciphers = SSL_CONN_CONFIG(cipher_list); if(!ciphers) ciphers = (char *)DEFAULT_CIPHER_SELECTION; if(!SSL_CTX_set_cipher_list(connssl->ctx, ciphers)) { @@ -1964,18 +2020,20 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) infof(data, "Cipher selection: %s\n", ciphers); #ifdef USE_TLS_SRP - if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { - infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username); + if(ssl_authtype == CURL_TLSAUTH_SRP) { + char * const ssl_username = SSL_SET_OPTION(username); + + infof(data, "Using TLS-SRP username: %s\n", ssl_username); - if(!SSL_CTX_set_srp_username(connssl->ctx, data->set.ssl.username)) { + if(!SSL_CTX_set_srp_username(connssl->ctx, ssl_username)) { failf(data, "Unable to set SRP user name"); return CURLE_BAD_FUNCTION_ARGUMENT; } - if(!SSL_CTX_set_srp_password(connssl->ctx, data->set.ssl.password)) { + if(!SSL_CTX_set_srp_password(connssl->ctx, SSL_SET_OPTION(password))) { failf(data, "failed setting SRP password"); return CURLE_BAD_FUNCTION_ARGUMENT; } - if(!data->set.str[STRING_SSL_CIPHER_LIST]) { + if(!SSL_CONN_CONFIG(cipher_list)) { infof(data, "Setting cipher list SRP\n"); if(!SSL_CTX_set_cipher_list(connssl->ctx, "SRP")) { @@ -1985,20 +2043,17 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) } } #endif - if(data->set.str[STRING_SSL_CAFILE] || data->set.str[STRING_SSL_CAPATH]) { + + if(ssl_cafile || ssl_capath) { /* tell SSL where to find CA certificates that are used to verify the servers certificate. */ - if(!SSL_CTX_load_verify_locations(connssl->ctx, - data->set.str[STRING_SSL_CAFILE], - data->set.str[STRING_SSL_CAPATH])) { - if(data->set.ssl.verifypeer) { + if(!SSL_CTX_load_verify_locations(connssl->ctx, ssl_cafile, ssl_capath)) { + if(verifypeer) { /* Fail if we insist on successfully verifying the server. */ failf(data, "error setting certificate verify locations:\n" " CAfile: %s\n CApath: %s", - data->set.str[STRING_SSL_CAFILE]? - data->set.str[STRING_SSL_CAFILE]: "none", - data->set.str[STRING_SSL_CAPATH]? - data->set.str[STRING_SSL_CAPATH] : "none"); + ssl_cafile ? ssl_cafile : "none", + ssl_capath ? ssl_capath : "none"); return CURLE_SSL_CACERT_BADFILE; } else { @@ -2015,29 +2070,25 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) infof(data, " CAfile: %s\n" " CApath: %s\n", - data->set.str[STRING_SSL_CAFILE] ? data->set.str[STRING_SSL_CAFILE]: - "none", - data->set.str[STRING_SSL_CAPATH] ? data->set.str[STRING_SSL_CAPATH]: - "none"); + ssl_cafile ? ssl_cafile : "none", + ssl_capath ? ssl_capath : "none"); } #ifdef CURL_CA_FALLBACK - else if(data->set.ssl.verifypeer) { + else if(verifypeer) { /* verfying the peer without any CA certificates won't work so use openssl's built in default as fallback */ SSL_CTX_set_default_verify_paths(connssl->ctx); } #endif - if(data->set.str[STRING_SSL_CRLFILE]) { + if(ssl_crlfile) { /* tell SSL where to find CRL file that is used to check certificate * revocation */ lookup=X509_STORE_add_lookup(SSL_CTX_get_cert_store(connssl->ctx), X509_LOOKUP_file()); if(!lookup || - (!X509_load_crl_file(lookup, data->set.str[STRING_SSL_CRLFILE], - X509_FILETYPE_PEM)) ) { - failf(data, "error loading CRL file: %s", - data->set.str[STRING_SSL_CRLFILE]); + (!X509_load_crl_file(lookup, ssl_crlfile, X509_FILETYPE_PEM)) ) { + failf(data, "error loading CRL file: %s", ssl_crlfile); return CURLE_SSL_CRL_BADFILE; } else { @@ -2046,9 +2097,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) X509_STORE_set_flags(SSL_CTX_get_cert_store(connssl->ctx), X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL); } - infof(data, - " CRLfile: %s\n", data->set.str[STRING_SSL_CRLFILE] ? - data->set.str[STRING_SSL_CRLFILE]: "none"); + infof(data, " CRLfile: %s\n", ssl_crlfile); } /* Try building a chain using issuers in the trusted store first to avoid @@ -2059,7 +2108,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) https://rt.openssl.org/Ticket/Display.html?id=3621&user=guest&pass=guest */ #if defined(X509_V_FLAG_TRUSTED_FIRST) && !defined(X509_V_FLAG_NO_ALT_CHAINS) - if(data->set.ssl.verifypeer) { + if(verifypeer) { X509_STORE_set_flags(SSL_CTX_get_cert_store(connssl->ctx), X509_V_FLAG_TRUSTED_FIRST); } @@ -2070,8 +2119,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) * anyway. In the latter case the result of the verification is checked with * SSL_get_verify_result() below. */ SSL_CTX_set_verify(connssl->ctx, - data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE, - NULL); + verifypeer ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL); /* give application a chance to interfere with SSL set up. */ if(data->set.ssl.fsslctx) { @@ -2094,31 +2142,30 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ !defined(OPENSSL_NO_OCSP) - if(data->set.ssl.verifystatus) + if(SSL_CONN_CONFIG(verifystatus)) SSL_set_tlsext_status_type(connssl->handle, TLSEXT_STATUSTYPE_ocsp); #endif SSL_set_connect_state(connssl->handle); connssl->server_cert = 0x0; - #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME - if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) && + if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) && #ifdef ENABLE_IPV6 - (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) && + (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) && #endif sni && - !SSL_set_tlsext_host_name(connssl->handle, conn->host.name)) + !SSL_set_tlsext_host_name(connssl->handle, hostname)) infof(data, "WARNING: failed to configure server name indication (SNI) " "TLS extension\n"); #endif /* Check if there's a cached ID we can/should use here! */ - if(conn->ssl_config.sessionid) { + if(data->set.general_ssl.sessionid) { void *ssl_sessionid = NULL; Curl_ssl_sessionid_lock(conn); - if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) { + if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) { /* we got a session id, use it! */ if(!SSL_set_session(connssl->handle, ssl_sessionid)) { Curl_ssl_sessionid_unlock(conn); @@ -2127,13 +2174,21 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex) return CURLE_SSL_CONNECT_ERROR; } /* Informational message */ - infof (data, "SSL re-using session ID\n"); + infof(data, "SSL re-using session ID\n"); } Curl_ssl_sessionid_unlock(conn); } - /* pass the raw socket into the SSL layers */ - if(!SSL_set_fd(connssl->handle, (int)sockfd)) { + if(conn->proxy_ssl[sockindex].use) { + BIO *const bio = BIO_new(BIO_f_ssl()); + DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state); + DEBUGASSERT(conn->proxy_ssl[sockindex].handle != NULL); + DEBUGASSERT(bio != NULL); + BIO_set_ssl(bio, conn->proxy_ssl[sockindex].handle, FALSE); + SSL_set_bio(connssl->handle, bio, bio); + } + else if(!SSL_set_fd(connssl->handle, (int)sockfd)) { + /* pass the raw socket into the SSL layers */ failf(data, "SSL: SSL_set_fd failed: %s", ERR_error_string(ERR_get_error(), NULL)); return CURLE_SSL_CONNECT_ERROR; @@ -2149,9 +2204,11 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) struct Curl_easy *data = conn->data; int err; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + long * const certverifyresult = SSL_IS_PROXY() ? + &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult; DEBUGASSERT(ssl_connect_2 == connssl->connecting_state - || ssl_connect_2_reading == connssl->connecting_state - || ssl_connect_2_writing == connssl->connecting_state); + || ssl_connect_2_reading == connssl->connecting_state + || ssl_connect_2_writing == connssl->connecting_state); ERR_clear_error(); @@ -2198,7 +2255,7 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) lerr = SSL_get_verify_result(connssl->handle); if(lerr != X509_V_OK) { - data->set.ssl.certverifyresult = lerr; + *certverifyresult = lerr; snprintf(error_buffer, sizeof(error_buffer), "SSL certificate problem: %s", X509_verify_cert_error_string(lerr)); @@ -2220,8 +2277,11 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) * the SO_ERROR is also lost. */ if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) { + const char * const hostname = SSL_IS_PROXY() ? + conn->http_proxy.host.name : conn->host.name; + const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; failf(data, "Unknown SSL protocol error in connection to %s:%ld ", - conn->host.name, conn->remote_port); + hostname, port); return result; } @@ -2245,7 +2305,7 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex) * negotiated */ if(conn->bits.tls_enable_alpn) { - const unsigned char* neg_protocol; + const unsigned char *neg_protocol; unsigned int len; SSL_get0_alpn_selected(connssl->handle, &neg_protocol, &len); if(len != 0) { @@ -2276,7 +2336,8 @@ static int asn1_object_dump(ASN1_OBJECT *a, char *buf, size_t len) { int i, ilen; - if((ilen = (int)len) < 0) + ilen = (int)len; + if(ilen < 0) return 1; /* buffer too big */ i = i2t_ASN1_OBJECT(buf, ilen, a); @@ -2698,6 +2759,8 @@ static CURLcode servercert(struct connectdata *conn, FILE *fp; char *buffer = data->state.buffer; const char *ptr; + long * const certverifyresult = SSL_IS_PROXY() ? + &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult; BIO *mem = BIO_new(BIO_s_mem()); if(data->set.ssl.certinfo) @@ -2713,7 +2776,7 @@ static CURLcode servercert(struct connectdata *conn, return CURLE_PEER_FAILED_VERIFICATION; } - infof(data, "Server certificate:\n"); + infof(data, "%s certificate:\n", SSL_IS_PROXY() ? "Proxy" : "Server"); rc = x509_name_oneline(X509_get_subject_name(connssl->server_cert), buffer, BUFSIZE); @@ -2731,7 +2794,7 @@ static CURLcode servercert(struct connectdata *conn, BIO_free(mem); - if(data->set.ssl.verifyhost) { + if(SSL_CONN_CONFIG(verifyhost)) { result = verifyhost(conn, connssl->server_cert); if(result) { X509_free(connssl->server_cert); @@ -2754,12 +2817,12 @@ static CURLcode servercert(struct connectdata *conn, deallocating the certificate. */ /* e.g. match issuer name with provided issuer certificate */ - if(data->set.str[STRING_SSL_ISSUERCERT]) { - fp = fopen(data->set.str[STRING_SSL_ISSUERCERT], FOPEN_READTEXT); + if(SSL_SET_OPTION(issuercert)) { + fp = fopen(SSL_SET_OPTION(issuercert), FOPEN_READTEXT); if(!fp) { if(strict) failf(data, "SSL: Unable to open issuer cert (%s)", - data->set.str[STRING_SSL_ISSUERCERT]); + SSL_SET_OPTION(issuercert)); X509_free(connssl->server_cert); connssl->server_cert = NULL; return CURLE_SSL_ISSUER_ERROR; @@ -2769,7 +2832,7 @@ static CURLcode servercert(struct connectdata *conn, if(!issuer) { if(strict) failf(data, "SSL: Unable to read issuer cert (%s)", - data->set.str[STRING_SSL_ISSUERCERT]); + SSL_SET_OPTION(issuercert)); X509_free(connssl->server_cert); X509_free(issuer); fclose(fp); @@ -2781,7 +2844,7 @@ static CURLcode servercert(struct connectdata *conn, if(X509_check_issued(issuer, connssl->server_cert) != X509_V_OK) { if(strict) failf(data, "SSL: Certificate issuer check failed (%s)", - data->set.str[STRING_SSL_ISSUERCERT]); + SSL_SET_OPTION(issuercert)); X509_free(connssl->server_cert); X509_free(issuer); connssl->server_cert = NULL; @@ -2789,15 +2852,14 @@ static CURLcode servercert(struct connectdata *conn, } infof(data, " SSL certificate issuer check ok (%s)\n", - data->set.str[STRING_SSL_ISSUERCERT]); + SSL_SET_OPTION(issuercert)); X509_free(issuer); } - lerr = data->set.ssl.certverifyresult = - SSL_get_verify_result(connssl->handle); + lerr = *certverifyresult = SSL_get_verify_result(connssl->handle); - if(data->set.ssl.certverifyresult != X509_V_OK) { - if(data->set.ssl.verifypeer) { + if(*certverifyresult != X509_V_OK) { + if(SSL_CONN_CONFIG(verifypeer)) { /* We probably never reach this, because SSL_connect() will fail and we return earlier if verifypeer is set? */ if(strict) @@ -2816,7 +2878,7 @@ static CURLcode servercert(struct connectdata *conn, #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ !defined(OPENSSL_NO_OCSP) - if(data->set.ssl.verifystatus) { + if(SSL_CONN_CONFIG(verifystatus)) { result = verifystatus(conn, connssl); if(result) { X509_free(connssl->server_cert); @@ -2830,7 +2892,8 @@ static CURLcode servercert(struct connectdata *conn, /* when not strict, we don't bother about the verify cert problems */ result = CURLE_OK; - ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY]; + ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; if(!result && ptr) { result = pkp_pin_peer_pubkey(data, connssl->server_cert, ptr); if(result) @@ -2852,7 +2915,7 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex) DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); - if(conn->ssl_config.sessionid) { + if(data->set.general_ssl.sessionid) { bool incache; SSL_SESSION *our_ssl_sessionid; void *old_ssl_sessionid = NULL; @@ -2864,7 +2927,8 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex) regardless of its state. */ Curl_ssl_sessionid_lock(conn); - incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL)); + incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, + sockindex)); if(incache) { if(old_ssl_sessionid != our_ssl_sessionid) { infof(data, "old SSL session ID is stale, removing\n"); @@ -2875,7 +2939,7 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex) if(!incache) { result = Curl_ssl_addsessionid(conn, our_ssl_sessionid, - 0 /* unknown size */); + 0 /* unknown size */, sockindex); if(result) { Curl_ssl_sessionid_unlock(conn); failf(data, "failed to store ssl session"); @@ -2899,8 +2963,8 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex) * operations. */ - result = servercert(conn, connssl, - (data->set.ssl.verifypeer || data->set.ssl.verifyhost)); + result = servercert(conn, connssl, (SSL_CONN_CONFIG(verifypeer) || + SSL_CONN_CONFIG(verifyhost))); if(!result) connssl->connecting_state = ssl_connect_done; @@ -2920,7 +2984,7 @@ static CURLcode ossl_connect_common(struct connectdata *conn, struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; curl_socket_t sockfd = conn->sock[sockindex]; - long timeout_ms; + time_t timeout_ms; int what; /* check if the connection has already been established */ @@ -3048,7 +3112,10 @@ bool Curl_ossl_data_pending(const struct connectdata *conn, int connindex) { if(conn->ssl[connindex].handle) /* SSL is in use */ - return (0 != SSL_pending(conn->ssl[connindex].handle)) ? TRUE : FALSE; + return (0 != SSL_pending(conn->ssl[connindex].handle) || + (conn->proxy_ssl[connindex].handle && + 0 != SSL_pending(conn->proxy_ssl[connindex].handle))) ? + TRUE : FALSE; else return FALSE; } @@ -3093,8 +3160,18 @@ static ssize_t ossl_send(struct connectdata *conn, /* A failure in the SSL library occurred, usually a protocol error. The OpenSSL error queue contains more information on the error. */ sslerror = ERR_get_error(); - failf(conn->data, "SSL_write() error: %s", - ossl_strerror(sslerror, error_buffer, sizeof(error_buffer))); + if(ERR_GET_LIB(sslerror) == ERR_LIB_SSL && + ERR_GET_REASON(sslerror) == SSL_R_BIO_NOT_SET && + conn->ssl[sockindex].state == ssl_connection_complete && + conn->proxy_ssl[sockindex].state == ssl_connection_complete) { + char ver[120]; + Curl_ossl_version(ver, 120); + failf(conn->data, "Error: %s does not support double SSL tunneling.", + ver); + } + else + failf(conn->data, "SSL_write() error: %s", + ossl_strerror(sslerror, error_buffer, sizeof(error_buffer))); *curlcode = CURLE_SEND_ERROR; return -1; } @@ -3178,7 +3255,7 @@ size_t Curl_ossl_version(char *buffer, size_t size) sub[0] = 'z'; } else { - sub[0]=(char)(((ssleay_value>>4)&0xff) + 'a' -1); + sub[0] = (char) (minor_ver + 'a' - 1); } } else @@ -3199,7 +3276,12 @@ int Curl_ossl_random(struct Curl_easy *data, unsigned char *entropy, size_t length) { if(data) { - Curl_ossl_seed(data); /* Initiate the seed if not already done */ + if(Curl_ossl_seed(data)) /* Initiate the seed if not already done */ + return 1; /* couldn't seed for some reason */ + } + else { + if(!rand_enough()) + return 1; } RAND_bytes(entropy, curlx_uztosi(length)); return 0; /* 0 as in no problem */ diff --git a/lib/vtls/openssl.h b/lib/vtls/openssl.h index ee18e71..cff1e90 100644 --- a/lib/vtls/openssl.h +++ b/lib/vtls/openssl.h @@ -79,6 +79,9 @@ void Curl_ossl_sha256sum(const unsigned char *tmp, /* input */ bool Curl_ossl_cert_status_request(void); +/* Support HTTPS-proxy */ +#define HTTPS_PROXY_SUPPORT 1 + /* Set the API backend definition to OpenSSL */ #define CURL_SSL_BACKEND CURLSSLBACKEND_OPENSSL diff --git a/lib/vtls/polarssl.c b/lib/vtls/polarssl.c index 18b564e..4bba3e3 100644 --- a/lib/vtls/polarssl.c +++ b/lib/vtls/polarssl.c @@ -147,12 +147,16 @@ polarssl_connect_step1(struct connectdata *conn, { struct Curl_easy *data = conn->data; struct ssl_connect_data* connssl = &conn->ssl[sockindex]; + const char *capath = SSL_CONN_CONFIG(CApath); + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; + const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; int ret = -1; char errorbuf[128]; errorbuf[0]=0; /* PolarSSL only supports SSLv3 and TLSv1 */ - if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { + if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) { failf(data, "PolarSSL does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; } @@ -180,30 +184,29 @@ polarssl_connect_step1(struct connectdata *conn, /* Load the trusted CA */ memset(&connssl->cacert, 0, sizeof(x509_crt)); - if(data->set.str[STRING_SSL_CAFILE]) { + if(SSL_CONN_CONFIG(CAfile)) { ret = x509_crt_parse_file(&connssl->cacert, - data->set.str[STRING_SSL_CAFILE]); + SSL_CONN_CONFIG(CAfile)); if(ret<0) { error_strerror(ret, errorbuf, sizeof(errorbuf)); failf(data, "Error reading ca cert file %s - PolarSSL: (-0x%04X) %s", - data->set.str[STRING_SSL_CAFILE], -ret, errorbuf); + SSL_CONN_CONFIG(CAfile), -ret, errorbuf); - if(data->set.ssl.verifypeer) + if(SSL_CONN_CONFIG(verifypeer)) return CURLE_SSL_CACERT_BADFILE; } } - if(data->set.str[STRING_SSL_CAPATH]) { - ret = x509_crt_parse_path(&connssl->cacert, - data->set.str[STRING_SSL_CAPATH]); + if(capath) { + ret = x509_crt_parse_path(&connssl->cacert, capath); if(ret<0) { error_strerror(ret, errorbuf, sizeof(errorbuf)); failf(data, "Error reading ca cert path %s - PolarSSL: (-0x%04X) %s", - data->set.str[STRING_SSL_CAPATH], -ret, errorbuf); + capath, -ret, errorbuf); - if(data->set.ssl.verifypeer) + if(SSL_CONN_CONFIG(verifypeer)) return CURLE_SSL_CACERT_BADFILE; } } @@ -211,25 +214,25 @@ polarssl_connect_step1(struct connectdata *conn, /* Load the client certificate */ memset(&connssl->clicert, 0, sizeof(x509_crt)); - if(data->set.str[STRING_CERT]) { + if(SSL_SET_OPTION(cert)) { ret = x509_crt_parse_file(&connssl->clicert, - data->set.str[STRING_CERT]); + SSL_SET_OPTION(cert)); if(ret) { error_strerror(ret, errorbuf, sizeof(errorbuf)); failf(data, "Error reading client cert file %s - PolarSSL: (-0x%04X) %s", - data->set.str[STRING_CERT], -ret, errorbuf); + SSL_SET_OPTION(cert), -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } } /* Load the client private key */ - if(data->set.str[STRING_KEY]) { + if(SSL_SET_OPTION(key)) { pk_context pk; pk_init(&pk); - ret = pk_parse_keyfile(&pk, data->set.str[STRING_KEY], - data->set.str[STRING_KEY_PASSWD]); + ret = pk_parse_keyfile(&pk, SSL_SET_OPTION(key), + SSL_SET_OPTION(key_passwd)); if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA)) ret = POLARSSL_ERR_PK_TYPE_MISMATCH; if(ret == 0) @@ -241,7 +244,7 @@ polarssl_connect_step1(struct connectdata *conn, if(ret) { error_strerror(ret, errorbuf, sizeof(errorbuf)); failf(data, "Error reading private key %s - PolarSSL: (-0x%04X) %s", - data->set.str[STRING_KEY], -ret, errorbuf); + SSL_SET_OPTION(key), -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } @@ -250,29 +253,27 @@ polarssl_connect_step1(struct connectdata *conn, /* Load the CRL */ memset(&connssl->crl, 0, sizeof(x509_crl)); - if(data->set.str[STRING_SSL_CRLFILE]) { + if(SSL_SET_OPTION(CRLfile)) { ret = x509_crl_parse_file(&connssl->crl, - data->set.str[STRING_SSL_CRLFILE]); + SSL_SET_OPTION(CRLfile)); if(ret) { error_strerror(ret, errorbuf, sizeof(errorbuf)); failf(data, "Error reading CRL file %s - PolarSSL: (-0x%04X) %s", - data->set.str[STRING_SSL_CRLFILE], -ret, errorbuf); + SSL_SET_OPTION(CRLfile), -ret, errorbuf); return CURLE_SSL_CRL_BADFILE; } } - infof(data, "PolarSSL: Connecting to %s:%d\n", - conn->host.name, conn->remote_port); + infof(data, "PolarSSL: Connecting to %s:%d\n", hostname, port); if(ssl_init(&connssl->ssl)) { failf(data, "PolarSSL: ssl_init failed"); return CURLE_SSL_CONNECT_ERROR; } - switch(data->set.ssl.version) { - default: + switch(SSL_CONN_CONFIG(version)) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, @@ -306,6 +307,12 @@ polarssl_connect_step1(struct connectdata *conn, SSL_MINOR_VERSION_3); infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.2\n"); break; + case CURL_SSLVERSION_TLSv1_3: + failf(data, "PolarSSL: TLS 1.3 is not yet supported"); + return CURLE_SSL_CONNECT_ERROR; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; } ssl_set_endpoint(&connssl->ssl, SSL_IS_CLIENT); @@ -320,11 +327,11 @@ polarssl_connect_step1(struct connectdata *conn, ssl_set_ciphersuites(&connssl->ssl, ssl_list_ciphersuites()); /* Check if there's a cached ID we can/should use here! */ - if(conn->ssl_config.sessionid) { + if(data->set.general_ssl.sessionid) { void *old_session = NULL; Curl_ssl_sessionid_lock(conn); - if(!Curl_ssl_getsessionid(conn, &old_session, NULL)) { + if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) { ret = ssl_set_session(&connssl->ssl, old_session); if(ret) { Curl_ssl_sessionid_unlock(conn); @@ -339,12 +346,12 @@ polarssl_connect_step1(struct connectdata *conn, ssl_set_ca_chain(&connssl->ssl, &connssl->cacert, &connssl->crl, - conn->host.name); + hostname); ssl_set_own_cert_rsa(&connssl->ssl, &connssl->clicert, &connssl->rsa); - if(ssl_set_hostname(&connssl->ssl, conn->host.name)) { + if(ssl_set_hostname(&connssl->ssl, hostname)) { /* ssl_set_hostname() sets the name to use in CN/SAN checks *and* the name to set in the SNI extension. So even if curl connects to a host specified as an IP address, this function must be used. */ @@ -354,7 +361,7 @@ polarssl_connect_step1(struct connectdata *conn, #ifdef HAS_ALPN if(conn->bits.tls_enable_alpn) { - static const char* protocols[3]; + static const char *protocols[3]; int cur = 0; #ifdef USE_NGHTTP2 @@ -390,6 +397,10 @@ polarssl_connect_step2(struct connectdata *conn, struct Curl_easy *data = conn->data; struct ssl_connect_data* connssl = &conn->ssl[sockindex]; char buffer[1024]; + const char * const pinnedpubkey = SSL_IS_PROXY() ? + data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : + data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; + char errorbuf[128]; errorbuf[0] = 0; @@ -423,7 +434,7 @@ polarssl_connect_step2(struct connectdata *conn, ret = ssl_get_verify_result(&conn->ssl[sockindex].ssl); - if(ret && data->set.ssl.verifypeer) { + if(ret && SSL_CONN_CONFIG(verifypeer)) { if(ret & BADCERT_EXPIRED) failf(data, "Cert verify failed: BADCERT_EXPIRED"); @@ -451,7 +462,7 @@ polarssl_connect_step2(struct connectdata *conn, } /* adapted from mbedtls.c */ - if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) { + if(pinnedpubkey) { int size; CURLcode result; x509_crt *p; @@ -493,7 +504,7 @@ polarssl_connect_step2(struct connectdata *conn, /* pk_write_pubkey_der writes data at the end of the buffer. */ result = Curl_pin_peer_pubkey(data, - data->set.str[STRING_SSL_PINNEDPUBLICKEY], + pinnedpubkey, &pubkey[PUB_DER_MAX_BYTES - size], size); if(result) { x509_crt_free(p); @@ -544,7 +555,7 @@ polarssl_connect_step3(struct connectdata *conn, DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); - if(conn->ssl_config.sessionid) { + if(data->set.general_ssl.sessionid) { int ret; ssl_session *our_ssl_sessionid; void *old_ssl_sessionid = NULL; @@ -563,10 +574,10 @@ polarssl_connect_step3(struct connectdata *conn, /* If there's already a matching session in the cache, delete it */ Curl_ssl_sessionid_lock(conn); - if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL)) + if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex)) Curl_ssl_delsessionid(conn, old_ssl_sessionid); - retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0); + retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex); Curl_ssl_sessionid_unlock(conn); if(retcode) { free(our_ssl_sessionid); diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c index f731eeb..ac8b705 100644 --- a/lib/vtls/schannel.c +++ b/lib/vtls/schannel.c @@ -59,6 +59,7 @@ #include "x509asn1.h" #include "curl_printf.h" #include "system_win32.h" +#include "hostcheck.h" /* The last #include file should be: */ #include "curl_memory.h" @@ -123,9 +124,11 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) #endif TCHAR *host_name; CURLcode result; + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; infof(data, "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n", - conn->host.name, conn->remote_port); + hostname, conn->remote_port); #ifdef HAS_ALPN /* ALPN is only supported on Windows 8.1 / Server 2012 R2 and above. @@ -142,9 +145,9 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) connssl->cred = NULL; /* check for an existing re-usable credential handle */ - if(conn->ssl_config.sessionid) { + if(data->set.general_ssl.sessionid) { Curl_ssl_sessionid_lock(conn); - if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL)) { + if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, sockindex)) { connssl->cred = old_cred; infof(data, "schannel: re-using existing credential handle\n"); @@ -161,7 +164,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) memset(&schannel_cred, 0, sizeof(schannel_cred)); schannel_cred.dwVersion = SCHANNEL_CRED_VERSION; - if(data->set.ssl.verifypeer) { + if(conn->ssl_config.verifypeer) { #ifdef _WIN32_WCE /* certificate validation on CE doesn't seem to work right; we'll do it following a more manual process. */ @@ -170,13 +173,14 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) SCH_CRED_IGNORE_REVOCATION_OFFLINE; #else schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION; - if(data->set.ssl_no_revoke) + /* TODO s/data->set.ssl.no_revoke/SSL_SET_OPTION(no_revoke)/g */ + if(data->set.ssl.no_revoke) schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK | SCH_CRED_IGNORE_REVOCATION_OFFLINE; else schannel_cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN; #endif - if(data->set.ssl_no_revoke) + if(data->set.ssl.no_revoke) infof(data, "schannel: disabled server certificate revocation " "checks\n"); else @@ -189,15 +193,14 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) infof(data, "schannel: disabled server certificate revocation checks\n"); } - if(!data->set.ssl.verifyhost) { + if(!conn->ssl_config.verifyhost) { schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; infof(data, "schannel: verifyhost setting prevents Schannel from " "comparing the supplied target name with the subject " "names in server certificates. Also disables SNI.\n"); } - switch(data->set.ssl.version) { - default: + switch(conn->ssl_config.version) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT | @@ -213,12 +216,18 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) case CURL_SSLVERSION_TLSv1_2: schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_2_CLIENT; break; + case CURL_SSLVERSION_TLSv1_3: + failf(data, "Schannel: TLS 1.3 is not yet supported"); + return CURLE_SSL_CONNECT_ERROR; case CURL_SSLVERSION_SSLv3: schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT; break; case CURL_SSLVERSION_SSLv2: schannel_cred.grbitEnabledProtocols = SP_PROT_SSL2_CLIENT; break; + default: + failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); + return CURLE_SSL_CONNECT_ERROR; } /* allocate memory for the re-usable credential handle */ @@ -253,9 +262,9 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) } /* Warn if SNI is disabled due to use of an IP address */ - if(Curl_inet_pton(AF_INET, conn->host.name, &addr) + if(Curl_inet_pton(AF_INET, hostname, &addr) #ifdef ENABLE_IPV6 - || Curl_inet_pton(AF_INET6, conn->host.name, &addr6) + || Curl_inet_pton(AF_INET6, hostname, &addr6) #endif ) { infof(data, "schannel: using IP address, SNI is not supported by OS.\n"); @@ -265,17 +274,17 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) if(connssl->use_alpn) { int cur = 0; int list_start_index = 0; - unsigned int* extension_len = NULL; + unsigned int *extension_len = NULL; unsigned short* list_len = NULL; /* The first four bytes will be an unsigned int indicating number of bytes of data in the rest of the the buffer. */ - extension_len = (unsigned int*)(&alpn_buffer[cur]); + extension_len = (unsigned int *)(&alpn_buffer[cur]); cur += sizeof(unsigned int); /* The next four bytes are an indicator that this buffer will contain ALPN data, as opposed to NPN, for example. */ - *(unsigned int*)&alpn_buffer[cur] = + *(unsigned int *)&alpn_buffer[cur] = SecApplicationProtocolNegotiationExt_ALPN; cur += sizeof(unsigned int); @@ -333,7 +342,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) } memset(connssl->ctxt, 0, sizeof(struct curl_schannel_ctxt)); - host_name = Curl_convert_UTF8_to_tchar(conn->host.name); + host_name = Curl_convert_UTF8_to_tchar(hostname); if(!host_name) return CURLE_OUT_OF_MEMORY; @@ -406,11 +415,13 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) TCHAR *host_name; CURLcode result; bool doread; + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE; infof(data, "schannel: SSL/TLS connection with %s port %hu (step 2/3)\n", - conn->host.name, conn->remote_port); + hostname, conn->remote_port); if(!connssl->cred || !connssl->ctxt) return CURLE_SSL_CONNECT_ERROR; @@ -506,7 +517,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) memcpy(inbuf[0].pvBuffer, connssl->encdata_buffer, connssl->encdata_offset); - host_name = Curl_convert_UTF8_to_tchar(conn->host.name); + host_name = Curl_convert_UTF8_to_tchar(hostname); if(!host_name) return CURLE_OUT_OF_MEMORY; @@ -623,7 +634,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) #ifdef _WIN32_WCE /* Windows CE doesn't do any server certificate validation. We have to do it manually. */ - if(data->set.ssl.verifypeer) + if(conn->ssl_config.verifypeer) return verify_certificate(conn, sockindex); #endif @@ -638,6 +649,8 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) struct ssl_connect_data *connssl = &conn->ssl[sockindex]; SECURITY_STATUS sspi_status = SEC_E_OK; CERT_CONTEXT *ccert_context = NULL; + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; #ifdef HAS_ALPN SecPkgContext_ApplicationProtocol alpn_result; #endif @@ -645,7 +658,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); infof(data, "schannel: SSL/TLS connection with %s port %hu (step 3/3)\n", - conn->host.name, conn->remote_port); + hostname, conn->remote_port); if(!connssl->cred) return CURLE_SSL_CONNECT_ERROR; @@ -701,12 +714,13 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) #endif /* save the current session data for possible re-use */ - if(conn->ssl_config.sessionid) { + if(data->set.general_ssl.sessionid) { bool incache; struct curl_schannel_cred *old_cred = NULL; Curl_ssl_sessionid_lock(conn); - incache = !(Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL)); + incache = !(Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, + sockindex)); if(incache) { if(old_cred != connssl->cred) { infof(data, "schannel: old credential handle is stale, removing\n"); @@ -717,7 +731,8 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) } if(!incache) { result = Curl_ssl_addsessionid(conn, (void *)connssl->cred, - sizeof(struct curl_schannel_cred)); + sizeof(struct curl_schannel_cred), + sockindex); if(result) { Curl_ssl_sessionid_unlock(conn); failf(data, "schannel: failed to store credential handle"); @@ -769,7 +784,7 @@ schannel_connect_common(struct connectdata *conn, int sockindex, struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; curl_socket_t sockfd = conn->sock[sockindex]; - long timeout_ms; + time_t timeout_ms; int what; /* check if the connection has already been established */ @@ -957,7 +972,7 @@ schannel_send(struct connectdata *conn, int sockindex, /* send entire message or fail */ while(len > (size_t)written) { ssize_t this_write; - long timeleft; + time_t timeleft; int what; this_write = 0; @@ -1376,9 +1391,11 @@ int Curl_schannel_shutdown(struct connectdata *conn, int sockindex) */ struct Curl_easy *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : + conn->host.name; infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu\n", - conn->host.name, conn->remote_port); + hostname, conn->remote_port); if(connssl->cred && connssl->ctxt) { SecBufferDesc BuffDesc; @@ -1400,7 +1417,7 @@ int Curl_schannel_shutdown(struct connectdata *conn, int sockindex) failf(data, "schannel: ApplyControlToken failure: %s", Curl_sspi_strerror(conn, sspi_status)); - host_name = Curl_convert_UTF8_to_tchar(conn->host.name); + host_name = Curl_convert_UTF8_to_tchar(hostname); if(!host_name) return CURLE_OUT_OF_MEMORY; @@ -1525,6 +1542,9 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex) CURLcode result = CURLE_OK; CERT_CONTEXT *pCertContextServer = NULL; const CERT_CHAIN_CONTEXT *pChainContext = NULL; + const char * const conn_hostname = SSL_IS_PROXY() ? + conn->http_proxy.host.name : + conn->host.name; status = s_pSecFn->QueryContextAttributes(&connssl->ctxt->ctxt_handle, SECPKG_ATTR_REMOTE_CERT_CONTEXT, @@ -1546,7 +1566,7 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex) NULL, pCertContextServer->hCertStore, &ChainPara, - (data->set.ssl_no_revoke ? 0 : + (data->set.ssl.no_revoke ? 0 : CERT_CHAIN_REVOCATION_CHECK_CHAIN), NULL, &pChainContext)) { @@ -1582,15 +1602,10 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex) } if(result == CURLE_OK) { - if(data->set.ssl.verifyhost) { - TCHAR cert_hostname_buff[128]; - xcharp_u hostname; - xcharp_u cert_hostname; + if(conn->ssl_config.verifyhost) { + TCHAR cert_hostname_buff[256]; DWORD len; - cert_hostname.const_tchar_ptr = cert_hostname_buff; - hostname.tchar_ptr = Curl_convert_UTF8_to_tchar(conn->host.name); - /* TODO: Fix this for certificates with multiple alternative names. Right now we're only asking for the first preferred alternative name. Instead we'd need to do all via CERT_NAME_SEARCH_ALL_NAMES_FLAG @@ -1601,31 +1616,50 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex) */ len = CertGetNameString(pCertContextServer, CERT_NAME_DNS_TYPE, - 0, + CERT_NAME_DISABLE_IE4_UTF8_FLAG, NULL, - cert_hostname.tchar_ptr, - 128); - if(len > 0 && *cert_hostname.tchar_ptr == '*') { - /* this is a wildcard cert. try matching the last len - 1 chars */ - int hostname_len = strlen(conn->host.name); - cert_hostname.tchar_ptr++; - if(_tcsicmp(cert_hostname.const_tchar_ptr, - hostname.const_tchar_ptr + hostname_len - len + 2) != 0) - result = CURLE_PEER_FAILED_VERIFICATION; + cert_hostname_buff, + 256); + if(len > 0) { + const char *cert_hostname; + + /* Comparing the cert name and the connection hostname encoded as UTF-8 + * is acceptable since both values are assumed to use ASCII + * (or some equivalent) encoding + */ + cert_hostname = Curl_convert_tchar_to_UTF8(cert_hostname_buff); + if(!cert_hostname) { + result = CURLE_OUT_OF_MEMORY; + } + else{ + int match_result; + + match_result = Curl_cert_hostcheck(cert_hostname, conn->host.name); + if(match_result == CURL_HOST_MATCH) { + infof(data, + "schannel: connection hostname (%s) validated " + "against certificate name (%s)\n", + conn->host.name, + cert_hostname); + result = CURLE_OK; + } + else{ + failf(data, + "schannel: connection hostname (%s) " + "does not match certificate name (%s)", + conn->host.name, + cert_hostname); + result = CURLE_PEER_FAILED_VERIFICATION; + } + Curl_unicodefree(cert_hostname); + } } - else if(len == 0 || _tcsicmp(hostname.const_tchar_ptr, - cert_hostname.const_tchar_ptr) != 0) { + else { + failf(data, + "schannel: CertGetNameString did not provide any " + "certificate name information"); result = CURLE_PEER_FAILED_VERIFICATION; } - if(result == CURLE_PEER_FAILED_VERIFICATION) { - char *_cert_hostname; - _cert_hostname = Curl_convert_tchar_to_UTF8(cert_hostname.tchar_ptr); - failf(data, "schannel: CertGetNameString() certificate hostname " - "(%s) did not match connection (%s)", - _cert_hostname, conn->host.name); - Curl_unicodefree(_cert_hostname); - } - Curl_unicodefree(hostname.tchar_ptr); } } diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c index 56a8823..b808e1c 100644 --- a/lib/vtls/vtls.c +++ b/lib/vtls/vtls.c @@ -65,6 +65,7 @@ #include "url.h" #include "progress.h" #include "share.h" +#include "multiif.h" #include "timeval.h" #include "curl_md5.h" #include "warnless.h" @@ -80,94 +81,49 @@ (data->share->specifier & \ (1<var) { \ + dest->var = strdup(source->var); \ + if(!dest->var) \ + return FALSE; \ + } \ + else \ + dest->var = NULL; bool -Curl_ssl_config_matches(struct ssl_config_data* data, - struct ssl_config_data* needle) +Curl_ssl_config_matches(struct ssl_primary_config* data, + struct ssl_primary_config* needle) { if((data->version == needle->version) && (data->verifypeer == needle->verifypeer) && (data->verifyhost == needle->verifyhost) && - safe_strequal(data->CApath, needle->CApath) && - safe_strequal(data->CAfile, needle->CAfile) && - safe_strequal(data->clientcert, needle->clientcert) && - safe_strequal(data->cipher_list, needle->cipher_list)) + Curl_safe_strcasecompare(data->CApath, needle->CApath) && + Curl_safe_strcasecompare(data->CAfile, needle->CAfile) && + Curl_safe_strcasecompare(data->clientcert, needle->clientcert) && + Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list)) return TRUE; return FALSE; } bool -Curl_clone_ssl_config(struct ssl_config_data *source, - struct ssl_config_data *dest) +Curl_clone_primary_ssl_config(struct ssl_primary_config *source, + struct ssl_primary_config *dest) { - dest->sessionid = source->sessionid; dest->verifyhost = source->verifyhost; dest->verifypeer = source->verifypeer; dest->version = source->version; - if(source->CAfile) { - dest->CAfile = strdup(source->CAfile); - if(!dest->CAfile) - return FALSE; - } - else - dest->CAfile = NULL; - - if(source->CApath) { - dest->CApath = strdup(source->CApath); - if(!dest->CApath) - return FALSE; - } - else - dest->CApath = NULL; - - if(source->cipher_list) { - dest->cipher_list = strdup(source->cipher_list); - if(!dest->cipher_list) - return FALSE; - } - else - dest->cipher_list = NULL; - - if(source->egdsocket) { - dest->egdsocket = strdup(source->egdsocket); - if(!dest->egdsocket) - return FALSE; - } - else - dest->egdsocket = NULL; - - if(source->random_file) { - dest->random_file = strdup(source->random_file); - if(!dest->random_file) - return FALSE; - } - else - dest->random_file = NULL; - - if(source->clientcert) { - dest->clientcert = strdup(source->clientcert); - if(!dest->clientcert) - return FALSE; - dest->sessionid = FALSE; - } - else - dest->clientcert = NULL; - + CLONE_STRING(CAfile); + CLONE_STRING(CApath); + CLONE_STRING(cipher_list); + CLONE_STRING(egdsocket); + CLONE_STRING(random_file); + CLONE_STRING(clientcert); return TRUE; } -void Curl_free_ssl_config(struct ssl_config_data* sslc) +void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc) { Curl_safefree(sslc->CAfile); Curl_safefree(sslc->CApath); @@ -177,77 +133,6 @@ void Curl_free_ssl_config(struct ssl_config_data* sslc) Curl_safefree(sslc->clientcert); } - -/* - * Curl_rand() returns a random unsigned integer, 32bit. - * - * This non-SSL function is put here only because this file is the only one - * with knowledge of what the underlying SSL libraries provide in terms of - * randomizers. - * - * NOTE: 'data' may be passed in as NULL when coming from external API without - * easy handle! - * - */ - -unsigned int Curl_rand(struct Curl_easy *data) -{ - unsigned int r = 0; - static unsigned int randseed; - static bool seeded = FALSE; - -#ifdef CURLDEBUG - char *force_entropy = getenv("CURL_ENTROPY"); - if(force_entropy) { - if(!seeded) { - size_t elen = strlen(force_entropy); - size_t clen = sizeof(randseed); - size_t min = elen < clen ? elen : clen; - memcpy((char *)&randseed, force_entropy, min); - seeded = TRUE; - } - else - randseed++; - return randseed; - } -#endif - - /* data may be NULL! */ - if(!Curl_ssl_random(data, (unsigned char *)&r, sizeof(r))) - return r; - - /* If Curl_ssl_random() returns non-zero it couldn't offer randomness and we - instead perform a "best effort" */ - -#ifdef RANDOM_FILE - if(!seeded) { - /* if there's a random file to read a seed from, use it */ - int fd = open(RANDOM_FILE, O_RDONLY); - if(fd > -1) { - /* read random data into the randseed variable */ - ssize_t nread = read(fd, &randseed, sizeof(randseed)); - if(nread == sizeof(randseed)) - seeded = TRUE; - close(fd); - } - } -#endif - - if(!seeded) { - struct timeval now = curlx_tvnow(); - infof(data, "WARNING: Using weak random seed\n"); - randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec; - randseed = randseed * 1103515245 + 12345; - randseed = randseed * 1103515245 + 12345; - randseed = randseed * 1103515245 + 12345; - seeded = TRUE; - } - - /* Return an unsigned 32-bit pseudo-random number. */ - r = randseed = randseed * 1103515245 + 12345; - return (r << 16) | ((r >> 16) & 0xFFFF); -} - int Curl_ssl_backend(void) { return (int)CURL_SSL_BACKEND; @@ -288,19 +173,41 @@ void Curl_ssl_cleanup(void) static bool ssl_prefs_check(struct Curl_easy *data) { /* check for CURLOPT_SSLVERSION invalid parameter value */ - if((data->set.ssl.version < 0) - || (data->set.ssl.version >= CURL_SSLVERSION_LAST)) { + if((data->set.ssl.primary.version < 0) + || (data->set.ssl.primary.version >= CURL_SSLVERSION_LAST)) { failf(data, "Unrecognized parameter value passed via CURLOPT_SSLVERSION"); return FALSE; } return TRUE; } +static CURLcode +ssl_connect_init_proxy(struct connectdata *conn, int sockindex) +{ + DEBUGASSERT(conn->bits.proxy_ssl_connected[sockindex]); + if(ssl_connection_complete == conn->ssl[sockindex].state && + !conn->proxy_ssl[sockindex].use) { +#if defined(HTTPS_PROXY_SUPPORT) + conn->proxy_ssl[sockindex] = conn->ssl[sockindex]; + memset(&conn->ssl[sockindex], 0, sizeof(conn->ssl[sockindex])); +#else + return CURLE_NOT_BUILT_IN; +#endif + } + return CURLE_OK; +} + CURLcode Curl_ssl_connect(struct connectdata *conn, int sockindex) { CURLcode result; + if(conn->bits.proxy_ssl_connected[sockindex]) { + result = ssl_connect_init_proxy(conn, sockindex); + if(result) + return result; + } + if(!ssl_prefs_check(conn->data)) return CURLE_SSL_CONNECT_ERROR; @@ -321,6 +228,11 @@ Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex, bool *done) { CURLcode result; + if(conn->bits.proxy_ssl_connected[sockindex]) { + result = ssl_connect_init_proxy(conn, sockindex); + if(result) + return result; + } if(!ssl_prefs_check(conn->data)) return CURLE_SSL_CONNECT_ERROR; @@ -363,7 +275,8 @@ void Curl_ssl_sessionid_unlock(struct connectdata *conn) */ bool Curl_ssl_getsessionid(struct connectdata *conn, void **ssl_sessionid, - size_t *idsize) /* set 0 if unknown */ + size_t *idsize, /* set 0 if unknown */ + int sockindex) { struct curl_ssl_session *check; struct Curl_easy *data = conn->data; @@ -371,11 +284,18 @@ bool Curl_ssl_getsessionid(struct connectdata *conn, long *general_age; bool no_match = TRUE; + const bool isProxy = CONNECT_PROXY_SSL(); + struct ssl_primary_config * const ssl_config = isProxy ? + &conn->proxy_ssl_config : + &conn->ssl_config; + const char * const name = isProxy ? conn->http_proxy.host.name : + conn->host.name; + int port = isProxy ? (int)conn->port : conn->remote_port; *ssl_sessionid = NULL; - DEBUGASSERT(conn->ssl_config.sessionid); + DEBUGASSERT(data->set.general_ssl.sessionid); - if(!conn->ssl_config.sessionid) + if(!data->set.general_ssl.sessionid) /* session ID re-use is disabled */ return TRUE; @@ -385,21 +305,21 @@ bool Curl_ssl_getsessionid(struct connectdata *conn, else general_age = &data->state.sessionage; - for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) { + for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) { check = &data->state.session[i]; if(!check->sessionid) /* not session ID means blank entry */ continue; - if(strcasecompare(conn->host.name, check->name) && + if(strcasecompare(name, check->name) && ((!conn->bits.conn_to_host && !check->conn_to_host) || (conn->bits.conn_to_host && check->conn_to_host && strcasecompare(conn->conn_to_host.name, check->conn_to_host))) && ((!conn->bits.conn_to_port && check->conn_to_port == -1) || (conn->bits.conn_to_port && check->conn_to_port != -1 && conn->conn_to_port == check->conn_to_port)) && - (conn->remote_port == check->remote_port) && + (port == check->remote_port) && strcasecompare(conn->handler->scheme, check->scheme) && - Curl_ssl_config_matches(&conn->ssl_config, &check->ssl_config)) { + Curl_ssl_config_matches(ssl_config, &check->ssl_config)) { /* yes, we have a session ID! */ (*general_age)++; /* increase general age */ check->age = *general_age; /* set this as used in this age */ @@ -428,7 +348,7 @@ void Curl_ssl_kill_session(struct curl_ssl_session *session) session->sessionid = NULL; session->age = 0; /* fresh */ - Curl_free_ssl_config(&session->ssl_config); + Curl_free_primary_ssl_config(&session->ssl_config); Curl_safefree(session->name); Curl_safefree(session->conn_to_host); @@ -443,7 +363,7 @@ void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid) size_t i; struct Curl_easy *data=conn->data; - for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) { + for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) { struct curl_ssl_session *check = &data->state.session[i]; if(check->sessionid == ssl_sessionid) { @@ -461,7 +381,8 @@ void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid) */ CURLcode Curl_ssl_addsessionid(struct connectdata *conn, void *ssl_sessionid, - size_t idsize) + size_t idsize, + int sockindex) { size_t i; struct Curl_easy *data=conn->data; /* the mother of all structs */ @@ -471,10 +392,14 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn, char *clone_conn_to_host; int conn_to_port; long *general_age; + const bool isProxy = CONNECT_PROXY_SSL(); + struct ssl_primary_config * const ssl_config = isProxy ? + &conn->proxy_ssl_config : + &conn->ssl_config; - DEBUGASSERT(conn->ssl_config.sessionid); + DEBUGASSERT(data->set.general_ssl.sessionid); - clone_host = strdup(conn->host.name); + clone_host = strdup(isProxy ? conn->http_proxy.host.name : conn->host.name); if(!clone_host) return CURLE_OUT_OF_MEMORY; /* bail out */ @@ -505,14 +430,14 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn, } /* find an empty slot for us, or find the oldest */ - for(i = 1; (i < data->set.ssl.max_ssl_sessions) && + for(i = 1; (i < data->set.general_ssl.max_ssl_sessions) && data->state.session[i].sessionid; i++) { if(data->state.session[i].age < oldest_age) { oldest_age = data->state.session[i].age; store = &data->state.session[i]; } } - if(i == data->set.ssl.max_ssl_sessions) + if(i == data->set.general_ssl.max_ssl_sessions) /* cache is full, we must "kill" the oldest entry! */ Curl_ssl_kill_session(store); else @@ -528,10 +453,11 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn, store->name = clone_host; /* clone host name */ store->conn_to_host = clone_conn_to_host; /* clone connect to host name */ store->conn_to_port = conn_to_port; /* connect to port number */ - store->remote_port = conn->remote_port; /* port number */ + /* port number */ + store->remote_port = isProxy ? (int)conn->port : conn->remote_port; store->scheme = conn->handler->scheme; - if(!Curl_clone_ssl_config(&conn->ssl_config, &store->ssl_config)) { + if(!Curl_clone_primary_ssl_config(ssl_config, &store->ssl_config)) { store->sessionid = NULL; /* let caller free sessionid */ free(clone_host); free(clone_conn_to_host); @@ -547,7 +473,7 @@ void Curl_ssl_close_all(struct Curl_easy *data) size_t i; /* kill the session ID cache if not shared */ if(data->state.session && !SSLSESSION_SHARED(data)) { - for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) + for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) /* the single-killer function handles empty table slots */ Curl_ssl_kill_session(&data->state.session[i]); @@ -558,6 +484,43 @@ void Curl_ssl_close_all(struct Curl_easy *data) curlssl_close_all(data); } +#if defined(USE_SSLEAY) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \ + defined(USE_DARWINSSL) || defined(USE_NSS) +/* This function is for OpenSSL, GnuTLS, darwinssl, and schannel only. */ +int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks) +{ + struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; + + if(!numsocks) + return GETSOCK_BLANK; + + if(connssl->connecting_state == ssl_connect_2_writing) { + /* write mode */ + socks[0] = conn->sock[FIRSTSOCKET]; + return GETSOCK_WRITESOCK(0); + } + else if(connssl->connecting_state == ssl_connect_2_reading) { + /* read mode */ + socks[0] = conn->sock[FIRSTSOCKET]; + return GETSOCK_READSOCK(0); + } + + return GETSOCK_BLANK; +} +#else +int Curl_ssl_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks) +{ + (void)conn; + (void)socks; + (void)numsocks; + return GETSOCK_BLANK; +} +/* USE_SSLEAY || USE_GNUTLS || USE_SCHANNEL || USE_DARWINSSL || USE_NSS */ +#endif + void Curl_ssl_close(struct connectdata *conn, int sockindex) { DEBUGASSERT((sockindex <= 1) && (sockindex >= -1)); @@ -615,7 +578,7 @@ CURLcode Curl_ssl_initsessions(struct Curl_easy *data, size_t amount) return CURLE_OUT_OF_MEMORY; /* store the info in the SSL section */ - data->set.ssl.max_ssl_sessions = amount; + data->set.general_ssl.max_ssl_sessions = amount; data->state.session = session; data->state.sessionage = 1; /* this is brand new */ return CURLE_OK; @@ -691,9 +654,9 @@ CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data, const char *value, size_t valuelen) { - struct curl_certinfo * ci = &data->info.certs; - char * output; - struct curl_slist * nl; + struct curl_certinfo *ci = &data->info.certs; + char *output; + struct curl_slist *nl; CURLcode result = CURLE_OK; size_t labellen = strlen(label); size_t outlen = labellen + 1 + valuelen + 1; /* label:value\0 */ @@ -736,11 +699,16 @@ CURLcode Curl_ssl_push_certinfo(struct Curl_easy *data, return Curl_ssl_push_certinfo_len(data, certnum, label, value, valuelen); } -int Curl_ssl_random(struct Curl_easy *data, - unsigned char *entropy, - size_t length) +CURLcode Curl_ssl_random(struct Curl_easy *data, + unsigned char *entropy, + size_t length) { - return curlssl_random(data, entropy, length); + int rc = curlssl_random(data, entropy, length); + if(rc) { + failf(data, "PRNG seeding failed"); + return CURLE_FAILED_INIT; /* possibly weird return code */ + } + return CURLE_OK; } /* diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h index a41ecc3..2aabeda 100644 --- a/lib/vtls/vtls.h +++ b/lib/vtls/vtls.h @@ -50,13 +50,24 @@ #define ALPN_HTTP_1_1_LENGTH 8 #define ALPN_HTTP_1_1 "http/1.1" -bool Curl_ssl_config_matches(struct ssl_config_data* data, - struct ssl_config_data* needle); -bool Curl_clone_ssl_config(struct ssl_config_data* source, - struct ssl_config_data* dest); -void Curl_free_ssl_config(struct ssl_config_data* sslc); - -unsigned int Curl_rand(struct Curl_easy *); +/* set of helper macros for the backends to access the correct fields. For the + proxy or for the remote host - to properly support HTTPS proxy */ + +#define SSL_IS_PROXY() (CURLPROXY_HTTPS == conn->http_proxy.proxytype && \ + ssl_connection_complete != conn->proxy_ssl[conn->sock[SECONDARYSOCKET] == \ + CURL_SOCKET_BAD ? FIRSTSOCKET : SECONDARYSOCKET].state) +#define SSL_SET_OPTION(var) (SSL_IS_PROXY() ? data->set.proxy_ssl.var : \ + data->set.ssl.var) +#define SSL_CONN_CONFIG(var) (SSL_IS_PROXY() ? \ + conn->proxy_ssl_config.var : conn->ssl_config.var) + +bool Curl_ssl_config_matches(struct ssl_primary_config* data, + struct ssl_primary_config* needle); +bool Curl_clone_primary_ssl_config(struct ssl_primary_config *source, + struct ssl_primary_config *dest); +void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc); +int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); int Curl_ssl_backend(void); @@ -87,12 +98,12 @@ int Curl_ssl_check_cxn(struct connectdata *conn); /* Certificate information list handling. */ void Curl_ssl_free_certinfo(struct Curl_easy *data); -CURLcode Curl_ssl_init_certinfo(struct Curl_easy * data, int num); -CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy * data, int certnum, - const char * label, const char * value, +CURLcode Curl_ssl_init_certinfo(struct Curl_easy *data, int num); +CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data, int certnum, + const char *label, const char *value, size_t valuelen); -CURLcode Curl_ssl_push_certinfo(struct Curl_easy * data, int certnum, - const char * label, const char * value); +CURLcode Curl_ssl_push_certinfo(struct Curl_easy *data, int certnum, + const char *label, const char *value); /* Functions to be used by SSL library adaptation functions */ @@ -116,7 +127,8 @@ void Curl_ssl_sessionid_unlock(struct connectdata *conn); */ bool Curl_ssl_getsessionid(struct connectdata *conn, void **ssl_sessionid, - size_t *idsize); /* set 0 if unknown */ + size_t *idsize, /* set 0 if unknown */ + int sockindex); /* add a new session ID * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock). * Caller must ensure that it has properly shared ownership of this sessionid @@ -124,7 +136,8 @@ bool Curl_ssl_getsessionid(struct connectdata *conn, */ CURLcode Curl_ssl_addsessionid(struct connectdata *conn, void *ssl_sessionid, - size_t idsize); + size_t idsize, + int sockindex); /* Kill a single session ID entry in the cache * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock). * This will call engine-specific curlssl_session_free function, which must @@ -140,10 +153,9 @@ void Curl_ssl_kill_session(struct curl_ssl_session *session); */ void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid); -/* get N random bytes into the buffer, return 0 if a find random is filled - in */ -int Curl_ssl_random(struct Curl_easy *data, unsigned char *buffer, - size_t length); +/* get N random bytes into the buffer */ +CURLcode Curl_ssl_random(struct Curl_easy *data, unsigned char *buffer, + size_t length); CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */ size_t tmplen, unsigned char *md5sum, /* output */ diff --git a/lib/x509asn1.c b/lib/x509asn1.c index 74a511b..c4bc7c1 100644 --- a/lib/x509asn1.c +++ b/lib/x509asn1.c @@ -40,6 +40,9 @@ #include "curl_memory.h" #include "memdebug.h" +/* For overflow checks. */ +#define CURL_SIZE_T_MAX ((size_t)-1) + /* ASN.1 OIDs. */ static const char cnOID[] = "2.5.4.3"; /* Common name. */ @@ -105,8 +108,8 @@ static const curl_OID OIDtable[] = { */ -const char * Curl_getASN1Element(curl_asn1Element * elem, - const char * beg, const char * end) +const char *Curl_getASN1Element(curl_asn1Element *elem, + const char *beg, const char *end) { unsigned char b; unsigned long len; @@ -116,8 +119,8 @@ const char * Curl_getASN1Element(curl_asn1Element * elem, ending at `end'. Returns a pointer in source string after the parsed element, or NULL if an error occurs. */ - - if(beg >= end || !*beg) + if(!beg || !end || beg >= end || !*beg || + (size_t)(end - beg) > CURL_ASN1_MAX) return (const char *) NULL; /* Process header byte. */ @@ -152,7 +155,7 @@ const char * Curl_getASN1Element(curl_asn1Element * elem, elem->end = beg; return beg + 1; } - else if(beg + b > end) + else if((unsigned)b > (size_t)(end - beg)) return (const char *) NULL; /* Does not fit in source. */ else { /* Get long length. */ @@ -163,16 +166,16 @@ const char * Curl_getASN1Element(curl_asn1Element * elem, len = (len << 8) | (unsigned char) *beg++; } while(--b); } - if((unsigned long) (end - beg) < len) + if(len > (size_t)(end - beg)) return (const char *) NULL; /* Element data does not fit in source. */ elem->beg = beg; elem->end = beg + len; return elem->end; } -static const curl_OID * searchOID(const char * oid) +static const curl_OID * searchOID(const char *oid) { - const curl_OID * op; + const curl_OID *op; /* Search the null terminated OID or OID identifier in local table. Return the table entry pointer or NULL if not found. */ @@ -184,7 +187,7 @@ static const curl_OID * searchOID(const char * oid) return (const curl_OID *) NULL; } -static const char * bool2str(const char * beg, const char * end) +static const char *bool2str(const char *beg, const char *end) { /* Convert an ASN.1 Boolean value into its string representation. Return the dynamically allocated string, or NULL if source is not an @@ -195,22 +198,24 @@ static const char * bool2str(const char * beg, const char * end) return strdup(*beg? "TRUE": "FALSE"); } -static const char * octet2str(const char * beg, const char * end) +static const char *octet2str(const char *beg, const char *end) { size_t n = end - beg; - char * buf; + char *buf = NULL; /* Convert an ASN.1 octet string to a printable string. Return the dynamically allocated string, or NULL if an error occurs. */ - buf = malloc(3 * n + 1); - if(buf) - for(n = 0; beg < end; n += 3) - snprintf(buf + n, 4, "%02x:", *(const unsigned char *) beg++); + if(n <= (CURL_SIZE_T_MAX - 1) / 3) { + buf = malloc(3 * n + 1); + if(buf) + for(n = 0; beg < end; n += 3) + snprintf(buf + n, 4, "%02x:", *(const unsigned char *) beg++); + } return buf; } -static const char * bit2str(const char * beg, const char * end) +static const char *bit2str(const char *beg, const char *end) { /* Convert an ASN.1 bit string to a printable string. Return the dynamically allocated string, or NULL if an error occurs. */ @@ -220,7 +225,7 @@ static const char * bit2str(const char * beg, const char * end) return octet2str(beg, end); } -static const char * int2str(const char * beg, const char * end) +static const char *int2str(const char *beg, const char *end) { long val = 0; size_t n = end - beg; @@ -246,14 +251,14 @@ static const char * int2str(const char * beg, const char * end) } static ssize_t -utf8asn1str(char * * to, int type, const char * from, const char * end) +utf8asn1str(char **to, int type, const char *from, const char *end) { size_t inlength = end - from; int size = 1; size_t outlength; int charsize; unsigned int wc; - char * buf; + char *buf; /* Perform a lazy conversion from an ASN.1 typed string to UTF8. Allocate the destination buffer dynamically. The allocation size will normally be too @@ -262,7 +267,7 @@ utf8asn1str(char * * to, int type, const char * from, const char * end) string length. */ *to = (char *) NULL; - switch (type) { + switch(type) { case CURL_ASN1_BMP_STRING: size = 2; break; @@ -282,6 +287,8 @@ utf8asn1str(char * * to, int type, const char * from, const char * end) if(inlength % size) return -1; /* Length inconsistent with character size. */ + if(inlength / size > (CURL_SIZE_T_MAX - 1) / 4) + return -1; /* Too big. */ buf = malloc(4 * (inlength / size) + 1); if(!buf) return -1; /* Not enough memory. */ @@ -295,7 +302,7 @@ utf8asn1str(char * * to, int type, const char * from, const char * end) else { for(outlength = 0; from < end;) { wc = 0; - switch (size) { + switch(size) { case 4: wc = (wc << 8) | *(const unsigned char *) from++; wc = (wc << 8) | *(const unsigned char *) from++; @@ -335,9 +342,9 @@ utf8asn1str(char * * to, int type, const char * from, const char * end) return outlength; } -static const char * string2str(int type, const char * beg, const char * end) +static const char *string2str(int type, const char *beg, const char *end) { - char * buf; + char *buf; /* Convert an ASN.1 String into its UTF-8 string representation. Return the dynamically allocated string, or NULL if an error occurs. */ @@ -347,7 +354,7 @@ static const char * string2str(int type, const char * beg, const char * end) return buf; } -static int encodeUint(char * buf, int n, unsigned int x) +static int encodeUint(char *buf, int n, unsigned int x) { int i = 0; unsigned int y = x / 10; @@ -367,7 +374,7 @@ static int encodeUint(char * buf, int n, unsigned int x) return i; } -static int encodeOID(char * buf, int n, const char * beg, const char * end) +static int encodeOID(char *buf, int n, const char *beg, const char *end) { int i = 0; unsigned int x; @@ -406,9 +413,9 @@ static int encodeOID(char * buf, int n, const char * beg, const char * end) return i; } -static const char * OID2str(const char * beg, const char * end, bool symbolic) +static const char *OID2str(const char *beg, const char *end, bool symbolic) { - char * buf = (char *) NULL; + char *buf = (char *) NULL; const curl_OID * op; int n; @@ -436,14 +443,14 @@ static const char * OID2str(const char * beg, const char * end, bool symbolic) return buf; } -static const char * GTime2str(const char * beg, const char * end) +static const char *GTime2str(const char *beg, const char *end) { - const char * tzp; - const char * fracp; + const char *tzp; + const char *fracp; char sec1, sec2; size_t fracl; size_t tzl; - const char * sep = ""; + const char *sep = ""; /* Convert an ASN.1 Generalized time to a printable string. Return the dynamically allocated string, or NULL if an error occurs. */ @@ -453,7 +460,7 @@ static const char * GTime2str(const char * beg, const char * end) /* Get seconds digits. */ sec1 = '0'; - switch (fracp - beg - 12) { + switch(fracp - beg - 12) { case 0: sec2 = '0'; break; @@ -499,11 +506,11 @@ static const char * GTime2str(const char * beg, const char * end) sep, tzl, tzp); } -static const char * UTime2str(const char * beg, const char * end) +static const char *UTime2str(const char *beg, const char *end) { - const char * tzp; + const char *tzp; size_t tzl; - const char * sec; + const char *sec; /* Convert an ASN.1 UTC time to a printable string. Return the dynamically allocated string, or NULL if an error occurs. */ @@ -512,7 +519,7 @@ static const char * UTime2str(const char * beg, const char * end) ; /* Get the seconds. */ sec = beg + 10; - switch (tzp - sec) { + switch(tzp - sec) { case 0: sec = "00"; case 2: @@ -538,7 +545,7 @@ static const char * UTime2str(const char * beg, const char * end) tzl, tzp); } -const char * Curl_ASN1tostr(curl_asn1Element * elem, int type) +const char *Curl_ASN1tostr(curl_asn1Element *elem, int type) { /* Convert an ASN.1 element to a printable string. Return the dynamically allocated string, or NULL if an error occurs. */ @@ -549,7 +556,7 @@ const char * Curl_ASN1tostr(curl_asn1Element * elem, int type) if(!type) type = elem->tag; /* Type not forced: use element tag as type. */ - switch (type) { + switch(type) { case CURL_ASN1_BOOLEAN: return bool2str(elem->beg, elem->end); case CURL_ASN1_INTEGER: @@ -581,17 +588,17 @@ const char * Curl_ASN1tostr(curl_asn1Element * elem, int type) return (const char *) NULL; /* Unsupported. */ } -static ssize_t encodeDN(char * buf, size_t n, curl_asn1Element * dn) +static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn) { curl_asn1Element rdn; curl_asn1Element atv; curl_asn1Element oid; curl_asn1Element value; size_t l = 0; - const char * p1; - const char * p2; - const char * p3; - const char * str; + const char *p1; + const char *p2; + const char *p3; + const char *str; /* ASCII encode distinguished name at `dn' into the `n'-byte buffer at `buf'. Return the total string length, even if larger than `n'. */ @@ -647,9 +654,9 @@ static ssize_t encodeDN(char * buf, size_t n, curl_asn1Element * dn) return l; } -const char * Curl_DNtostr(curl_asn1Element * dn) +const char *Curl_DNtostr(curl_asn1Element *dn) { - char * buf = (char *) NULL; + char *buf = (char *) NULL; ssize_t n = encodeDN(buf, 0, dn); /* Convert an ASN.1 distinguished name into a printable string. @@ -669,12 +676,12 @@ const char * Curl_DNtostr(curl_asn1Element * dn) * X509 parser. */ -void Curl_parseX509(curl_X509certificate * cert, - const char * beg, const char * end) +int Curl_parseX509(curl_X509certificate *cert, + const char *beg, const char *end) { curl_asn1Element elem; curl_asn1Element tbsCertificate; - const char * ccp; + const char *ccp; static const char defaultVersion = 0; /* v1. */ /* ASN.1 parse an X509 certificate into structure subfields. @@ -686,7 +693,8 @@ void Curl_parseX509(curl_X509certificate * cert, cert->certificate.end = end; /* Get the sequence content. */ - Curl_getASN1Element(&elem, beg, end); + if(!Curl_getASN1Element(&elem, beg, end)) + return -1; /* Invalid bounds/size. */ beg = elem.beg; end = elem.end; @@ -749,9 +757,10 @@ void Curl_parseX509(curl_X509certificate * cert, } if(elem.tag == 3) Curl_getASN1Element(&cert->extensions, elem.beg, elem.end); + return 0; } -static size_t copySubstring(char * to, const char * from) +static size_t copySubstring(char *to, const char *from) { size_t i; @@ -768,8 +777,8 @@ static size_t copySubstring(char * to, const char * from) return i; } -static const char * dumpAlgo(curl_asn1Element * param, - const char * beg, const char * end) +static const char *dumpAlgo(curl_asn1Element *param, + const char *beg, const char *end) { curl_asn1Element oid; @@ -784,10 +793,10 @@ static const char * dumpAlgo(curl_asn1Element * param, return OID2str(oid.beg, oid.end, TRUE); } -static void do_pubkey_field(struct Curl_easy * data, int certnum, - const char * label, curl_asn1Element * elem) +static void do_pubkey_field(struct Curl_easy *data, int certnum, + const char *label, curl_asn1Element *elem) { - const char * output; + const char *output; /* Generate a certificate information record for the public key. */ @@ -801,14 +810,14 @@ static void do_pubkey_field(struct Curl_easy * data, int certnum, } } -static void do_pubkey(struct Curl_easy * data, int certnum, - const char * algo, curl_asn1Element * param, - curl_asn1Element * pubkey) +static void do_pubkey(struct Curl_easy *data, int certnum, + const char *algo, curl_asn1Element *param, + curl_asn1Element *pubkey) { curl_asn1Element elem; curl_asn1Element pk; - const char * p; - const char * q; + const char *p; + const char *q; unsigned long len; unsigned int i; @@ -865,18 +874,18 @@ static void do_pubkey(struct Curl_easy * data, int certnum, #endif } -CURLcode Curl_extract_certinfo(struct connectdata * conn, +CURLcode Curl_extract_certinfo(struct connectdata *conn, int certnum, - const char * beg, - const char * end) + const char *beg, + const char *end) { curl_X509certificate cert; - struct Curl_easy * data = conn->data; + struct Curl_easy *data = conn->data; curl_asn1Element param; - const char * ccp; - char * cp1; + const char *ccp; + char *cp1; size_t cl1; - char * cp2; + char *cp2; CURLcode result; unsigned long version; size_t i; @@ -889,7 +898,8 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn, /* Prepare the certificate information for curl_easy_getinfo(). */ /* Extract the certificate ASN.1 elements. */ - Curl_parseX509(&cert, beg, end); + if(Curl_parseX509(&cert, beg, end)) + return CURLE_OUT_OF_MEMORY; /* Subject. */ ccp = Curl_DNtostr(&cert.subject); @@ -1029,12 +1039,12 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn, #if defined(USE_GSKIT) -static const char * checkOID(const char * beg, const char * end, - const char * oid) +static const char *checkOID(const char *beg, const char *end, + const char *oid) { curl_asn1Element e; - const char * ccp; - const char * p; + const char *ccp; + const char *p; bool matched; /* Check if first ASN.1 element at `beg' is the given OID. @@ -1053,21 +1063,26 @@ static const char * checkOID(const char * beg, const char * end, return matched? ccp: (const char *) NULL; } -CURLcode Curl_verifyhost(struct connectdata * conn, - const char * beg, const char * end) +CURLcode Curl_verifyhost(struct connectdata *conn, + const char *beg, const char *end) { - struct Curl_easy * data = conn->data; + struct Curl_easy *data = conn->data; curl_X509certificate cert; curl_asn1Element dn; curl_asn1Element elem; curl_asn1Element ext; curl_asn1Element name; - const char * p; - const char * q; - char * dnsname; + const char *p; + const char *q; + char *dnsname; int matched = -1; size_t addrlen = (size_t) -1; ssize_t len; + const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name: + conn->host.name; + const char * const dispname = SSL_IS_PROXY()? + conn->http_proxy.host.dispname: + conn->host.dispname; #ifdef ENABLE_IPV6 struct in6_addr addr; #else @@ -1077,20 +1092,19 @@ CURLcode Curl_verifyhost(struct connectdata * conn, /* Verify that connection server matches info in X509 certificate at `beg'..`end'. */ - if(!data->set.ssl.verifyhost) + if(!SSL_CONN_CONFIG(verifyhost)) return CURLE_OK; - if(!beg) + if(Curl_parseX509(&cert, beg, end)) return CURLE_PEER_FAILED_VERIFICATION; - Curl_parseX509(&cert, beg, end); /* Get the server IP address. */ #ifdef ENABLE_IPV6 - if(conn->bits.ipv6_ip && Curl_inet_pton(AF_INET6, conn->host.name, &addr)) + if(conn->bits.ipv6_ip && Curl_inet_pton(AF_INET6, hostname, &addr)) addrlen = sizeof(struct in6_addr); else #endif - if(Curl_inet_pton(AF_INET, conn->host.name, &addr)) + if(Curl_inet_pton(AF_INET, hostname, &addr)) addrlen = sizeof(struct in_addr); /* Process extensions. */ @@ -1108,12 +1122,12 @@ CURLcode Curl_verifyhost(struct connectdata * conn, /* Check all GeneralNames. */ for(q = elem.beg; matched != 1 && q < elem.end;) { q = Curl_getASN1Element(&name, q, elem.end); - switch (name.tag) { + switch(name.tag) { case 2: /* DNS name. */ len = utf8asn1str(&dnsname, CURL_ASN1_IA5_STRING, name.beg, name.end); if(len > 0 && (size_t)len == strlen(dnsname)) - matched = Curl_cert_hostcheck(dnsname, conn->host.name); + matched = Curl_cert_hostcheck(dnsname, hostname); else matched = 0; free(dnsname); @@ -1128,15 +1142,15 @@ CURLcode Curl_verifyhost(struct connectdata * conn, } } - switch (matched) { + switch(matched) { case 1: /* an alternative name matched the server hostname */ - infof(data, "\t subjectAltName: %s matched\n", conn->host.dispname); + infof(data, "\t subjectAltName: %s matched\n", dispname); return CURLE_OK; case 0: /* an alternative name field existed, but didn't match and then we MUST fail */ - infof(data, "\t subjectAltName does not match %s\n", conn->host.dispname); + infof(data, "\t subjectAltName does not match %s\n", dispname); return CURLE_PEER_FAILED_VERIFICATION; } @@ -1168,14 +1182,14 @@ CURLcode Curl_verifyhost(struct connectdata * conn, } if(strlen(dnsname) != (size_t) len) /* Nul byte in string ? */ failf(data, "SSL: illegal cert name field"); - else if(Curl_cert_hostcheck((const char *) dnsname, conn->host.name)) { + else if(Curl_cert_hostcheck((const char *) dnsname, hostname)) { infof(data, "\t common name: %s (matched)\n", dnsname); free(dnsname); return CURLE_OK; } else failf(data, "SSL: certificate subject name '%s' does not match " - "target host name '%s'", dnsname, conn->host.dispname); + "target host name '%s'", dnsname, dispname); free(dnsname); } diff --git a/lib/x509asn1.h b/lib/x509asn1.h index 0f2b930..ce40297 100644 --- a/lib/x509asn1.h +++ b/lib/x509asn1.h @@ -8,7 +8,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -34,6 +34,9 @@ * Constants. */ +/* Largest supported ASN.1 structure. */ +#define CURL_ASN1_MAX ((size_t) 0x40000) /* 256K */ + /* ASN.1 classes. */ #define CURL_ASN1_UNIVERSAL 0 #define CURL_ASN1_APPLICATION 1 @@ -117,16 +120,15 @@ typedef struct { * Prototypes. */ -const char * Curl_getASN1Element(curl_asn1Element * elem, - const char * beg, const char * end); -const char * Curl_ASN1tostr(curl_asn1Element * elem, int type); -const char * Curl_DNtostr(curl_asn1Element * dn); -void Curl_parseX509(curl_X509certificate * cert, - const char * beg, const char * end); -CURLcode Curl_extract_certinfo(struct connectdata * conn, int certnum, - const char * beg, const char * end); -CURLcode Curl_verifyhost(struct connectdata * conn, - const char * beg, const char * end); - +const char *Curl_getASN1Element(curl_asn1Element *elem, + const char *beg, const char *end); +const char *Curl_ASN1tostr(curl_asn1Element *elem, int type); +const char *Curl_DNtostr(curl_asn1Element *dn); +int Curl_parseX509(curl_X509certificate *cert, + const char *beg, const char *end); +CURLcode Curl_extract_certinfo(struct connectdata *conn, int certnum, + const char *beg, const char *end); +CURLcode Curl_verifyhost(struct connectdata *conn, + const char *beg, const char *end); #endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_CYASSL or USE_SCHANNEL */ #endif /* HEADER_CURL_X509ASN1_H */ https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f4a3290ae7ae096f8b92f7adfba7088e6918bc0b commit f4a3290ae7ae096f8b92f7adfba7088e6918bc0b Author: Brad King AuthorDate: Tue Feb 7 11:33:09 2017 -0500 Commit: Brad King CommitDate: Tue Feb 7 11:36:59 2017 -0500 curl: Update script to get curl 7.52.1 diff --git a/Utilities/Scripts/update-curl.bash b/Utilities/Scripts/update-curl.bash index 22d1d8a..9cff7ca 100755 --- a/Utilities/Scripts/update-curl.bash +++ b/Utilities/Scripts/update-curl.bash @@ -8,7 +8,7 @@ readonly name="curl" readonly ownership="Curl Upstream " readonly subtree="Utilities/cmcurl" readonly repo="https://github.com/curl/curl.git" -readonly tag="curl-7_51_0" +readonly tag="curl-7_52_1" readonly shortlog=false readonly paths=" CMake/* ----------------------------------------------------------------------- Summary of changes: Help/release/dev/update-curl.rst | 6 + Tests/CMakeTests/FileDownloadBadHashTest.cmake.in | 2 +- Tests/CMakeTests/FileDownloadTest.cmake.in | 2 +- Tests/CMakeTests/FileUploadTest.cmake.in | 2 +- Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake | 2 +- Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake | 2 +- Tests/RunCMake/file/UPLOAD-unused-argument.cmake | 2 +- Utilities/Scripts/update-curl.bash | 2 +- Utilities/cmcurl/CMake/OtherTests.cmake | 25 +- Utilities/cmcurl/CMakeLists.txt | 8 +- Utilities/cmcurl/include/curl/curl.h | 84 +- Utilities/cmcurl/include/curl/curlver.h | 8 +- Utilities/cmcurl/include/curl/easy.h | 4 +- Utilities/cmcurl/include/curl/stdcheaders.h | 6 +- Utilities/cmcurl/include/curl/typecheck-gcc.h | 55 +- Utilities/cmcurl/lib/Makefile.inc | 4 +- Utilities/cmcurl/lib/asyn-ares.c | 4 +- Utilities/cmcurl/lib/asyn-thread.c | 24 +- Utilities/cmcurl/lib/conncache.c | 6 +- Utilities/cmcurl/lib/connect.c | 98 ++- Utilities/cmcurl/lib/connect.h | 13 +- Utilities/cmcurl/lib/content_encoding.c | 23 +- Utilities/cmcurl/lib/cookie.c | 10 +- Utilities/cmcurl/lib/curl_addrinfo.c | 34 +- Utilities/cmcurl/lib/curl_addrinfo.h | 2 +- Utilities/cmcurl/lib/curl_endian.c | 18 +- Utilities/cmcurl/lib/curl_endian.h | 18 +- Utilities/cmcurl/lib/curl_gethostname.c | 8 +- Utilities/cmcurl/lib/curl_gssapi.c | 2 +- Utilities/cmcurl/lib/curl_hmac.h | 26 +- Utilities/cmcurl/lib/curl_ntlm_core.c | 2 +- Utilities/cmcurl/lib/curl_ntlm_wb.c | 13 +- Utilities/cmcurl/lib/curl_sasl.c | 20 +- Utilities/cmcurl/lib/curl_sec.h | 16 +- Utilities/cmcurl/lib/curl_setup.h | 4 +- Utilities/cmcurl/lib/curl_threads.c | 5 +- Utilities/cmcurl/lib/curl_threads.h | 5 +- Utilities/cmcurl/lib/easy.c | 2 + Utilities/cmcurl/lib/escape.c | 9 +- Utilities/cmcurl/lib/file.c | 2 +- Utilities/cmcurl/lib/formdata.c | 46 +- Utilities/cmcurl/lib/formdata.h | 2 +- Utilities/cmcurl/lib/ftp.c | 196 ++--- Utilities/cmcurl/lib/ftp.h | 2 +- Utilities/cmcurl/lib/ftplistparser.c | 8 +- Utilities/cmcurl/lib/getinfo.c | 29 +- Utilities/cmcurl/lib/hash.c | 6 +- Utilities/cmcurl/lib/hash.h | 15 +- Utilities/cmcurl/lib/hmac.c | 10 +- Utilities/cmcurl/lib/hostcheck.c | 9 +- Utilities/cmcurl/lib/hostip.c | 4 +- Utilities/cmcurl/lib/hostip.h | 8 +- Utilities/cmcurl/lib/hostip4.c | 2 +- Utilities/cmcurl/lib/http.c | 85 +- Utilities/cmcurl/lib/http2.c | 212 ++++- Utilities/cmcurl/lib/http2.h | 8 + Utilities/cmcurl/lib/http_chunks.c | 14 +- Utilities/cmcurl/lib/http_digest.c | 20 +- Utilities/cmcurl/lib/http_negotiate.c | 16 +- Utilities/cmcurl/lib/http_ntlm.c | 4 +- Utilities/cmcurl/lib/http_proxy.c | 529 +++++------ Utilities/cmcurl/lib/http_proxy.h | 4 +- Utilities/cmcurl/lib/if2ip.c | 2 +- Utilities/cmcurl/lib/imap.c | 6 +- Utilities/cmcurl/lib/inet_ntop.c | 6 +- Utilities/cmcurl/lib/inet_pton.c | 8 +- Utilities/cmcurl/lib/krb5.c | 2 +- Utilities/cmcurl/lib/ldap.c | 46 +- Utilities/cmcurl/lib/md4.c | 3 +- Utilities/cmcurl/lib/md5.c | 7 +- Utilities/cmcurl/lib/memdebug.c | 2 +- Utilities/cmcurl/lib/mprintf.c | 25 +- Utilities/cmcurl/lib/multi.c | 38 +- Utilities/cmcurl/lib/multihandle.h | 4 +- Utilities/cmcurl/lib/multiif.h | 4 +- Utilities/cmcurl/lib/non-ascii.c | 4 +- Utilities/cmcurl/lib/nwlib.c | 10 +- Utilities/cmcurl/lib/nwos.c | 8 +- Utilities/cmcurl/lib/pingpong.c | 14 +- Utilities/cmcurl/lib/pingpong.h | 2 +- Utilities/cmcurl/lib/pop3.c | 8 +- Utilities/cmcurl/lib/progress.c | 40 +- Utilities/cmcurl/lib/rand.c | 130 +++ Utilities/cmcurl/lib/{easyif.h => rand.h} | 26 +- Utilities/cmcurl/lib/rtsp.c | 24 +- Utilities/cmcurl/lib/security.c | 13 +- Utilities/cmcurl/lib/select.c | 2 +- Utilities/cmcurl/lib/select.h | 2 +- Utilities/cmcurl/lib/sendf.c | 21 +- Utilities/cmcurl/lib/sendf.h | 2 + Utilities/cmcurl/lib/setup-os400.h | 52 +- Utilities/cmcurl/lib/setup-vms.h | 139 +-- Utilities/cmcurl/lib/share.h | 8 +- Utilities/cmcurl/lib/smb.c | 14 +- Utilities/cmcurl/lib/smtp.c | 6 +- Utilities/cmcurl/lib/socks.c | 43 +- Utilities/cmcurl/lib/socks.h | 5 +- Utilities/cmcurl/lib/socks_gssapi.c | 24 +- Utilities/cmcurl/lib/socks_sspi.c | 11 +- Utilities/cmcurl/lib/speedcheck.c | 6 +- Utilities/cmcurl/lib/ssh.c | 58 +- Utilities/cmcurl/lib/strcase.c | 12 +- Utilities/cmcurl/lib/strcase.h | 1 + Utilities/cmcurl/lib/strdup.c | 23 + Utilities/cmcurl/lib/strdup.h | 1 + Utilities/cmcurl/lib/strerror.c | 32 +- Utilities/cmcurl/lib/strtoofft.c | 4 +- Utilities/cmcurl/lib/telnet.c | 23 +- Utilities/cmcurl/lib/tftp.c | 8 +- Utilities/cmcurl/lib/timeval.c | 6 +- Utilities/cmcurl/lib/timeval.h | 6 +- Utilities/cmcurl/lib/transfer.c | 14 +- Utilities/cmcurl/lib/url.c | 925 ++++++++++++++------ Utilities/cmcurl/lib/url.h | 13 + Utilities/cmcurl/lib/urldata.h | 147 +++- Utilities/cmcurl/lib/vauth/cleartext.c | 24 +- Utilities/cmcurl/lib/vauth/digest.c | 17 +- Utilities/cmcurl/lib/vauth/digest_sspi.c | 2 +- Utilities/cmcurl/lib/vauth/ntlm.c | 12 +- Utilities/cmcurl/lib/vauth/spnego_sspi.c | 2 +- Utilities/cmcurl/lib/version.c | 3 + Utilities/cmcurl/lib/vtls/axtls.c | 81 +- Utilities/cmcurl/lib/vtls/cyassl.c | 105 ++- Utilities/cmcurl/lib/vtls/darwinssl.c | 412 +++++---- Utilities/cmcurl/lib/vtls/gskit.c | 354 ++++++-- Utilities/cmcurl/lib/vtls/gskit.h | 7 +- Utilities/cmcurl/lib/vtls/gtls.c | 289 +++--- Utilities/cmcurl/lib/vtls/gtls.h | 7 +- Utilities/cmcurl/lib/vtls/mbedtls.c | 92 +- Utilities/cmcurl/lib/vtls/nss.c | 219 +++-- Utilities/cmcurl/lib/vtls/nssg.h | 3 + Utilities/cmcurl/lib/vtls/openssl.c | 398 +++++---- Utilities/cmcurl/lib/vtls/openssl.h | 3 + Utilities/cmcurl/lib/vtls/polarssl.c | 81 +- Utilities/cmcurl/lib/vtls/schannel.c | 144 +-- Utilities/cmcurl/lib/vtls/vtls.c | 300 +++---- Utilities/cmcurl/lib/vtls/vtls.h | 48 +- Utilities/cmcurl/lib/x509asn1.c | 194 ++-- Utilities/cmcurl/lib/x509asn1.h | 26 +- 139 files changed, 4145 insertions(+), 2525 deletions(-) create mode 100644 Help/release/dev/update-curl.rst create mode 100644 Utilities/cmcurl/lib/rand.c copy Utilities/cmcurl/lib/{easyif.h => rand.h} (59%) hooks/post-receive -- CMake From kwrobot at kitware.com Thu Feb 9 00:01:07 2017 From: kwrobot at kitware.com (Kitware Robot) Date: Thu, 9 Feb 2017 00:01:07 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-22-g90a55bb Message-ID: <20170209050107.B8615FA316@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 90a55bb1d2b18d14eec3c972e1b045205acfd708 (commit) from 787c5f37dde5982dea71b34339b9f546907bb368 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=90a55bb1d2b18d14eec3c972e1b045205acfd708 commit 90a55bb1d2b18d14eec3c972e1b045205acfd708 Author: Kitware Robot AuthorDate: Thu Feb 9 00:01:05 2017 -0500 Commit: Kitware Robot CommitDate: Thu Feb 9 00:01:05 2017 -0500 CMake Nightly Date Stamp diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 7d63f1a..61ac90e 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 8) -set(CMake_VERSION_PATCH 20170208) +set(CMake_VERSION_PATCH 20170209) #set(CMake_VERSION_RC 1) ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 9 16:03:59 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 9 Feb 2017 16:03:59 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-49-gb9bc47f Message-ID: <20170209210400.074CAFA5D7@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via b9bc47f7cb9806eb328f830ca162d1b08222b247 (commit) via 9f1f05fa14b26f45b664fba54c084cde36b22edb (commit) from 3373f1efa71ea5cc3cb98238b25c5dd08420748c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b9bc47f7cb9806eb328f830ca162d1b08222b247 commit b9bc47f7cb9806eb328f830ca162d1b08222b247 Merge: 3373f1e 9f1f05f Author: Brad King AuthorDate: Thu Feb 9 16:03:59 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 9 16:03:59 2017 -0500 Merge topic 'update-curl' into next 9f1f05fa fixup! Tests: Fix `file://` URLs given to curl https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9f1f05fa14b26f45b664fba54c084cde36b22edb commit 9f1f05fa14b26f45b664fba54c084cde36b22edb Author: Brad King AuthorDate: Thu Feb 9 16:00:26 2017 -0500 Commit: Brad King CommitDate: Thu Feb 9 16:03:25 2017 -0500 fixup! Tests: Fix `file://` URLs given to curl diff --git a/Tests/CMakeTests/FileDownloadBadHashTest.cmake.in b/Tests/CMakeTests/FileDownloadBadHashTest.cmake.in index 82280dd..64b45ed 100644 --- a/Tests/CMakeTests/FileDownloadBadHashTest.cmake.in +++ b/Tests/CMakeTests/FileDownloadBadHashTest.cmake.in @@ -1,4 +1,7 @@ -set(url "file:///@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png") +if(NOT "@CMAKE_CURRENT_SOURCE_DIR@" MATCHES "^/") + set(slash /) +endif() +set(url "file://${slash}@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png") set(dir "@CMAKE_CURRENT_BINARY_DIR@/downloads") file(DOWNLOAD diff --git a/Tests/CMakeTests/FileDownloadTest.cmake.in b/Tests/CMakeTests/FileDownloadTest.cmake.in index 48b4afe..f6d9ad9 100644 --- a/Tests/CMakeTests/FileDownloadTest.cmake.in +++ b/Tests/CMakeTests/FileDownloadTest.cmake.in @@ -1,4 +1,7 @@ -set(url "file:///@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png") +if(NOT "@CMAKE_CURRENT_SOURCE_DIR@" MATCHES "^/") + set(slash /) +endif() +set(url "file://${slash}@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png") set(dir "@CMAKE_CURRENT_BINARY_DIR@/downloads") message(STATUS "FileDownload:1") diff --git a/Tests/CMakeTests/FileUploadTest.cmake.in b/Tests/CMakeTests/FileUploadTest.cmake.in index 452090f..9e22909 100644 --- a/Tests/CMakeTests/FileUploadTest.cmake.in +++ b/Tests/CMakeTests/FileUploadTest.cmake.in @@ -10,7 +10,10 @@ endif() file(MAKE_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@/uploads") set(filename "@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png") -set(urlbase "file:///@CMAKE_CURRENT_BINARY_DIR@/uploads") +if(NOT "@CMAKE_CURRENT_BINARY_DIR@" MATCHES "^/") + set(slash /) +endif() +set(urlbase "file://${slash}@CMAKE_CURRENT_BINARY_DIR@/uploads") message(STATUS "FileUpload:1") file(UPLOAD diff --git a/Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake b/Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake index 02e67dc..a91b217 100644 --- a/Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake +++ b/Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake @@ -1,5 +1,8 @@ +if(NOT "${CMAKE_CURRENT_SOURCE_DIR}" MATCHES "^/") + set(slash /) +endif() file(DOWNLOAD - "file:///${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-hash-mismatch.txt" + "file://${slash}${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-hash-mismatch.txt" ${CMAKE_CURRENT_BINARY_DIR}/hash-mismatch.txt EXPECTED_HASH SHA1=0123456789abcdef0123456789abcdef01234567 STATUS status diff --git a/Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake b/Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake index 862d833..2fa5482 100644 --- a/Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake +++ b/Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake @@ -1,5 +1,8 @@ +if(NOT "${CMAKE_CURRENT_SOURCE_DIR}" MATCHES "^/") + set(slash /) +endif() file(DOWNLOAD - "file:///${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-unused-argument.txt" + "file://${slash}${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-unused-argument.txt" "${CMAKE_CURRENT_BINARY_DIR}/unused-argument.txt" JUNK ) diff --git a/Tests/RunCMake/file/UPLOAD-unused-argument.cmake b/Tests/RunCMake/file/UPLOAD-unused-argument.cmake index 408da0e..92c878c 100644 --- a/Tests/RunCMake/file/UPLOAD-unused-argument.cmake +++ b/Tests/RunCMake/file/UPLOAD-unused-argument.cmake @@ -1,5 +1,8 @@ +if(NOT "${CMAKE_CURRENT_BINARY_DIR}" MATCHES "^/") + set(slash /) +endif() file(UPLOAD "${CMAKE_CURRENT_SOURCE_DIR}/UPLOAD-unused-argument.txt" - "file:///${CMAKE_CURRENT_BINARY_DIR}/unused-argument.txt" + "file://${slash}${CMAKE_CURRENT_BINARY_DIR}/unused-argument.txt" JUNK ) ----------------------------------------------------------------------- Summary of changes: Tests/CMakeTests/FileDownloadBadHashTest.cmake.in | 5 ++++- Tests/CMakeTests/FileDownloadTest.cmake.in | 5 ++++- Tests/CMakeTests/FileUploadTest.cmake.in | 5 ++++- Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake | 5 ++++- Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake | 5 ++++- Tests/RunCMake/file/UPLOAD-unused-argument.cmake | 5 ++++- 6 files changed, 24 insertions(+), 6 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 9 16:05:42 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 9 Feb 2017 16:05:42 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-51-ge703924 Message-ID: <20170209210542.B2F76FA66E@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via e70392430de41387679706c6c1b01cc74b261aa5 (commit) via e2ee0971474ce92766f77d77025319ef575aa303 (commit) from b9bc47f7cb9806eb328f830ca162d1b08222b247 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e70392430de41387679706c6c1b01cc74b261aa5 commit e70392430de41387679706c6c1b01cc74b261aa5 Merge: b9bc47f e2ee097 Author: Brad King AuthorDate: Thu Feb 9 16:05:42 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 9 16:05:42 2017 -0500 Merge topic 'gcc-cpp98' into next e2ee0971 g++ knows about C++98 selection flags since at least 3.4 https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e2ee0971474ce92766f77d77025319ef575aa303 commit e2ee0971474ce92766f77d77025319ef575aa303 Author: Rolf Eike Beer AuthorDate: Wed Feb 8 18:18:17 2017 +0100 Commit: Rolf Eike Beer CommitDate: Wed Feb 8 21:04:31 2017 +0100 g++ knows about C++98 selection flags since at least 3.4 https://gcc.gnu.org/onlinedocs/gcc-3.4.0/gcc/C-Dialect-Options.html#C-Dialect-Options diff --git a/Modules/Compiler/GNU-CXX.cmake b/Modules/Compiler/GNU-CXX.cmake index c007c98..2499d2f 100644 --- a/Modules/Compiler/GNU-CXX.cmake +++ b/Modules/Compiler/GNU-CXX.cmake @@ -11,8 +11,7 @@ else() endif() endif() -if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.4) - # Supported since 4.3 +if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.4) set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "-std=c++98") set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "-std=gnu++98") endif() ----------------------------------------------------------------------- Summary of changes: Modules/Compiler/GNU-CXX.cmake | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) hooks/post-receive -- CMake From kwrobot at kitware.com Fri Feb 10 00:01:11 2017 From: kwrobot at kitware.com (Kitware Robot) Date: Fri, 10 Feb 2017 00:01:11 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-23-gada0bc2 Message-ID: <20170210050112.62322F9FDE@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via ada0bc21f42e25882ddf5a8aab10eaf3ea7e0b89 (commit) from 90a55bb1d2b18d14eec3c972e1b045205acfd708 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ada0bc21f42e25882ddf5a8aab10eaf3ea7e0b89 commit ada0bc21f42e25882ddf5a8aab10eaf3ea7e0b89 Author: Kitware Robot AuthorDate: Fri Feb 10 00:01:08 2017 -0500 Commit: Kitware Robot CommitDate: Fri Feb 10 00:01:08 2017 -0500 CMake Nightly Date Stamp diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 61ac90e..070abf8 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 8) -set(CMake_VERSION_PATCH 20170209) +set(CMake_VERSION_PATCH 20170210) #set(CMake_VERSION_RC 1) ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 10 11:20:53 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 10 Feb 2017 11:20:53 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-55-gf7993cb Message-ID: <20170210162053.92EAEF95DD@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via f7993cbeaa9d770646a97d7abeaa9b46087dfe59 (commit) via 30abf145fd48f50c26ee7553fd2512e59be97f25 (commit) via 97917900d146acd55a7e453f477c52cd2e816eb3 (commit) via 971384c28759ad042624bda3893be6fdb1795591 (commit) from e70392430de41387679706c6c1b01cc74b261aa5 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f7993cbeaa9d770646a97d7abeaa9b46087dfe59 commit f7993cbeaa9d770646a97d7abeaa9b46087dfe59 Merge: e703924 30abf14 Author: Brad King AuthorDate: Fri Feb 10 11:20:52 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 10 11:20:52 2017 -0500 Merge topic 'sphinx-1.4' into next 30abf145 Help: Fix cmake code block warnings produced by Sphinx 1.4 97917900 Utilities/Sphinx: Port qthelp css workaround to Sphinx 1.4 971384c2 Utilities/Sphinx: Port cmake extension to Sphinx 1.4 https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=30abf145fd48f50c26ee7553fd2512e59be97f25 commit 30abf145fd48f50c26ee7553fd2512e59be97f25 Author: Brad King AuthorDate: Fri Feb 10 09:55:46 2017 -0500 Commit: Brad King CommitDate: Fri Feb 10 10:43:30 2017 -0500 Help: Fix cmake code block warnings produced by Sphinx 1.4 Some of our "cmake" code blocks do not use fully valid CMake syntax because they have placeholders for human reference. Sphinx has never been able to properly lex and highlight these, but now warns. Fix each block's syntax or change to a non-cmake block as appropriate. diff --git a/Help/command/if.rst b/Help/command/if.rst index 0941029..2a087d0 100644 --- a/Help/command/if.rst +++ b/Help/command/if.rst @@ -9,17 +9,17 @@ Conditionally execute a group of commands. # then section. COMMAND1(ARGS ...) COMMAND2(ARGS ...) - ... + #... elseif(expression2) # elseif section. COMMAND1(ARGS ...) COMMAND2(ARGS ...) - ... + #... else(expression) # else section. COMMAND1(ARGS ...) COMMAND2(ARGS ...) - ... + #... endif(expression) Evaluates the given expression. If the result is true, the commands diff --git a/Help/manual/cmake-developer.7.rst b/Help/manual/cmake-developer.7.rst index 46b922b..f77d8c0 100644 --- a/Help/manual/cmake-developer.7.rst +++ b/Help/manual/cmake-developer.7.rst @@ -540,7 +540,7 @@ a :ref:`Line Comment` block of the form: or a :ref:`Bracket Comment` of the form: -.. code-block:: cmake +:: #[[.rst: @@ -558,7 +558,7 @@ All such comments must start with ``#`` in the first column. For example, a ``Modules/Findxxx.cmake`` module may contain: -.. code-block:: cmake +:: # Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. diff --git a/Help/manual/cmake-language.7.rst b/Help/manual/cmake-language.7.rst index 41542c9..ba0b30f 100644 --- a/Help/manual/cmake-language.7.rst +++ b/Help/manual/cmake-language.7.rst @@ -255,7 +255,7 @@ invocation as exactly one argument. For example: -.. code-block:: cmake +:: message("This is a quoted argument containing multiple lines. This is always one argument even though it contains a ; character. @@ -421,7 +421,7 @@ A ``#`` immediately followed by a `Bracket Argument`_ forms a For example: -.. code-block:: cmake +:: #[[This is a bracket comment. It runs until the close bracket.]] diff --git a/Modules/CMakePackageConfigHelpers.cmake b/Modules/CMakePackageConfigHelpers.cmake index 3210222..90c2a57 100644 --- a/Modules/CMakePackageConfigHelpers.cmake +++ b/Modules/CMakePackageConfigHelpers.cmake @@ -40,7 +40,7 @@ # set(FOO_INCLUDE_DIR "@CMAKE_INSTALL_FULL_INCLUDEDIR@" ) # set(FOO_DATA_DIR "@CMAKE_INSTALL_PREFIX@/@RELATIVE_DATA_INSTALL_DIR@" ) # set(FOO_ICONS_DIR "@CMAKE_INSTALL_PREFIX@/share/icons" ) -# ...logic to determine installedPrefix from the own location... +# #...logic to determine installedPrefix from the own location... # set(FOO_CONFIG_DIR "${installedPrefix}/@CONFIG_INSTALL_DIR@" ) # # All 4 options shown above are not sufficient, since the first 3 hardcode the @@ -174,7 +174,7 @@ # set(INCLUDE_INSTALL_DIR include/ ... CACHE ) # set(LIB_INSTALL_DIR lib/ ... CACHE ) # set(SYSCONFIG_INSTALL_DIR etc/foo/ ... CACHE ) -# ... +# #... # include(CMakePackageConfigHelpers) # configure_package_config_file(FooConfig.cmake.in # ${CMAKE_CURRENT_BINARY_DIR}/FooConfig.cmake @@ -190,7 +190,7 @@ # # ``FooConfig.cmake.in``: # -# .. code-block:: cmake +# :: # # set(FOO_VERSION x.y.z) # ... https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=97917900d146acd55a7e453f477c52cd2e816eb3 commit 97917900d146acd55a7e453f477c52cd2e816eb3 Author: Brad King AuthorDate: Fri Feb 10 10:41:50 2017 -0500 Commit: Brad King CommitDate: Fri Feb 10 10:43:29 2017 -0500 Utilities/Sphinx: Port qthelp css workaround to Sphinx 1.4 The `default.css` static content is no longer placed in the qthelp `_static` directory. If it does not exist, skip over it and insert the content of `basic.css` directly into `cmake.css`. diff --git a/Utilities/Sphinx/apply_qthelp_css_workaround.cmake b/Utilities/Sphinx/apply_qthelp_css_workaround.cmake index 8b74d12..288f370 100644 --- a/Utilities/Sphinx/apply_qthelp_css_workaround.cmake +++ b/Utilities/Sphinx/apply_qthelp_css_workaround.cmake @@ -1,11 +1,15 @@ file(READ "${CSS_DIR}/basic.css" BasicCssContent) -file(READ "${CSS_DIR}/default.css" DefaultCssContent) -string(REPLACE - "@import url(\"basic.css\")" "${BasicCssContent}" - DefaultCssContent "${DefaultCssContent}" -) +if(EXISTS "${CSS_DIR}/default.css") + file(READ "${CSS_DIR}/default.css" DefaultCssContent) + string(REPLACE + "@import url(\"basic.css\")" "${BasicCssContent}" + DefaultCssContent "${DefaultCssContent}" + ) +else() + set(DefaultCssContent "${BasicCssContent}") +endif() file(READ "${CSS_DIR}/cmake.css" CMakeCssContent) string(REPLACE https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=971384c28759ad042624bda3893be6fdb1795591 commit 971384c28759ad042624bda3893be6fdb1795591 Author: Gregor Jasny AuthorDate: Thu Feb 9 18:48:31 2017 +0100 Commit: Brad King CommitDate: Fri Feb 10 10:24:25 2017 -0500 Utilities/Sphinx: Port cmake extension to Sphinx 1.4 Sphinx 1.4 introduced a breaking change to `indexnode` by changing the length of a tuple. Teach our extension to produce a tuple of the proper length for the version of Sphinx in use. This gets rid of the "4 column based index found" warning. diff --git a/Utilities/Sphinx/cmake.py b/Utilities/Sphinx/cmake.py index edc7667..6f273f9 100644 --- a/Utilities/Sphinx/cmake.py +++ b/Utilities/Sphinx/cmake.py @@ -46,7 +46,7 @@ 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 +from sphinx import addnodes, version_info class CMakeModule(Directive): required_arguments = 1 @@ -123,7 +123,11 @@ class _cmake_index_entry: self.desc = desc def __call__(self, title, targetid, main = 'main'): - return ('pair', u'%s ; %s' % (self.desc, title), targetid, main) + # See https://github.com/sphinx-doc/sphinx/issues/2673 + if version_info < (1, 4): + return ('pair', u'%s ; %s' % (self.desc, title), targetid, main) + else: + return ('pair', u'%s ; %s' % (self.desc, title), targetid, main, None) _cmake_index_objs = { 'command': _cmake_index_entry('command'), ----------------------------------------------------------------------- Summary of changes: Help/command/if.rst | 6 +++--- Help/manual/cmake-developer.7.rst | 4 ++-- Help/manual/cmake-language.7.rst | 4 ++-- Modules/CMakePackageConfigHelpers.cmake | 6 +++--- Utilities/Sphinx/apply_qthelp_css_workaround.cmake | 14 +++++++++----- Utilities/Sphinx/cmake.py | 8 ++++++-- 6 files changed, 25 insertions(+), 17 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 10 11:32:23 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 10 Feb 2017 11:32:23 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-27-g46c6489 Message-ID: <20170210163223.4CA9AFA2C1@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 46c6489850ca9029bb75d17ed652563fc58a0082 (commit) via 30abf145fd48f50c26ee7553fd2512e59be97f25 (commit) via 97917900d146acd55a7e453f477c52cd2e816eb3 (commit) via 971384c28759ad042624bda3893be6fdb1795591 (commit) from ada0bc21f42e25882ddf5a8aab10eaf3ea7e0b89 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=46c6489850ca9029bb75d17ed652563fc58a0082 commit 46c6489850ca9029bb75d17ed652563fc58a0082 Merge: ada0bc2 30abf14 Author: Brad King AuthorDate: Fri Feb 10 11:32:21 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 10 11:32:21 2017 -0500 Merge topic 'sphinx-1.4' 30abf145 Help: Fix cmake code block warnings produced by Sphinx 1.4 97917900 Utilities/Sphinx: Port qthelp css workaround to Sphinx 1.4 971384c2 Utilities/Sphinx: Port cmake extension to Sphinx 1.4 ----------------------------------------------------------------------- Summary of changes: Help/command/if.rst | 6 +++--- Help/manual/cmake-developer.7.rst | 4 ++-- Help/manual/cmake-language.7.rst | 4 ++-- Modules/CMakePackageConfigHelpers.cmake | 6 +++--- Utilities/Sphinx/apply_qthelp_css_workaround.cmake | 14 +++++++++----- Utilities/Sphinx/cmake.py | 8 ++++++-- 6 files changed, 25 insertions(+), 17 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 10 11:32:46 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 10 Feb 2017 11:32:46 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-59-g8068f44 Message-ID: <20170210163246.9D992FA2B1@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 8068f441f6ae65bec7d0cf3ba50cbbf97f2087b4 (commit) via 46c6489850ca9029bb75d17ed652563fc58a0082 (commit) via ada0bc21f42e25882ddf5a8aab10eaf3ea7e0b89 (commit) via 90a55bb1d2b18d14eec3c972e1b045205acfd708 (commit) from f7993cbeaa9d770646a97d7abeaa9b46087dfe59 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8068f441f6ae65bec7d0cf3ba50cbbf97f2087b4 commit 8068f441f6ae65bec7d0cf3ba50cbbf97f2087b4 Merge: f7993cb 46c6489 Author: Brad King AuthorDate: Fri Feb 10 11:32:32 2017 -0500 Commit: Brad King CommitDate: Fri Feb 10 11:32:32 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 10 12:36:51 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 10 Feb 2017 12:36:51 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-62-gc8333e0 Message-ID: <20170210173651.1E62DFA791@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via c8333e08fed572086f0e0fa9694f4ff75a3c9127 (commit) via b628a1dcb0548c56477e25b0c992d9929562502d (commit) via d73d9d01b996a17788362c0a12dfe28d9948b29d (commit) from 8068f441f6ae65bec7d0cf3ba50cbbf97f2087b4 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c8333e08fed572086f0e0fa9694f4ff75a3c9127 commit c8333e08fed572086f0e0fa9694f4ff75a3c9127 Merge: 8068f44 b628a1d Author: Brad King AuthorDate: Fri Feb 10 12:36:50 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 10 12:36:50 2017 -0500 Merge topic 'update-kwsys' into next b628a1dc Merge branch 'upstream-KWSys' into update-kwsys d73d9d01 KWSys 2017-02-10 (06efe24e) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b628a1dcb0548c56477e25b0c992d9929562502d commit b628a1dcb0548c56477e25b0c992d9929562502d Merge: 46c6489 d73d9d0 Author: Brad King AuthorDate: Fri Feb 10 12:30:37 2017 -0500 Commit: Brad King CommitDate: Fri Feb 10 12:30:37 2017 -0500 Merge branch 'upstream-KWSys' into update-kwsys * upstream-KWSys: KWSys 2017-02-10 (06efe24e) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d73d9d01b996a17788362c0a12dfe28d9948b29d commit d73d9d01b996a17788362c0a12dfe28d9948b29d Author: KWSys Upstream AuthorDate: Fri Feb 10 12:30:10 2017 -0500 Commit: Brad King CommitDate: Fri Feb 10 12:30:36 2017 -0500 KWSys 2017-02-10 (06efe24e) Code extracted from: https://gitlab.kitware.com/utils/kwsys.git at commit 06efe24e4166911b7658f17164ade108ddfd35d0 (master). Upstream Shortlog ----------------- Nicol?s B?rtolo (1): 9c4230b7 SystemInformation: Fix counts of logical and physical cores diff --git a/SystemInformation.cxx b/SystemInformation.cxx index e01dcd7..fc1a752 100644 --- a/SystemInformation.cxx +++ b/SystemInformation.cxx @@ -35,8 +35,13 @@ #include "SystemInformation.hxx.in" #endif +#include +#include +#include #include #include +#include +#include #include #include #include @@ -394,7 +399,6 @@ public: bool SupportsMP; bool HasMMXPlus; bool HasSSEMMX; - bool SupportsHyperthreading; unsigned int LogicalProcessorsPerPhysical; int APIC_ID; CPUPowerManagement PowerManagement; @@ -463,10 +467,9 @@ protected: unsigned int NumberOfLogicalCPU; unsigned int NumberOfPhysicalCPU; - int CPUCount(); // For windows - unsigned char LogicalCPUPerPhysicalCPU(); + void CPUCountWindows(); // For windows unsigned char GetAPICId(); // For windows - bool IsHyperThreadingSupported(); + bool IsSMTSupported(); static LongLong GetCyclesDifference(DELAY_FUNC, unsigned int); // For windows // For Linux and Cygwin, /proc/cpuinfo formats are slightly different @@ -1542,7 +1545,7 @@ void SystemInformationImplementation::RunCPUCheck() RetrieveProcessorSerialNumber(); } - this->CPUCount(); + this->CPUCountWindows(); #elif defined(__APPLE__) this->ParseSysCtl(); @@ -2090,16 +2093,10 @@ bool SystemInformationImplementation::RetrieveCPUFeatures() // Retrieve Intel specific extended features. if (this->ChipManufacturer == Intel) { - this->Features.ExtendedFeatures.SupportsHyperthreading = - ((cpuinfo[3] & 0x10000000) != - 0); // Intel specific: Hyperthreading --> Bit 28 - this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = - (this->Features.ExtendedFeatures.SupportsHyperthreading) - ? ((cpuinfo[1] & 0x00FF0000) >> 16) - : 1; - - if ((this->Features.ExtendedFeatures.SupportsHyperthreading) && - (this->Features.HasAPIC)) { + bool SupportsSMT = + ((cpuinfo[3] & 0x10000000) != 0); // Intel specific: SMT --> Bit 28 + + if ((SupportsSMT) && (this->Features.HasAPIC)) { // Retrieve APIC information if there is one present. this->Features.ExtendedFeatures.APIC_ID = ((cpuinfo[1] & 0xFF000000) >> 24); @@ -3401,7 +3398,7 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() fclose(fd); buffer.resize(fileSize - 2); // Number of logical CPUs (combination of multiple processors, multi-core - // and hyperthreading) + // and SMT) size_t pos = buffer.find("processor\t"); while (pos != buffer.npos) { this->NumberOfLogicalCPU++; @@ -3409,30 +3406,24 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() } #ifdef __linux - // Find the largest physical id. - int maxId = -1; + // Count sockets. + std::set PhysicalIDs; std::string idc = this->ExtractValueFromCpuInfoFile(buffer, "physical id"); while (this->CurrentPositionInFile != buffer.npos) { int id = atoi(idc.c_str()); - if (id > maxId) { - maxId = id; - } + PhysicalIDs.insert(id); idc = this->ExtractValueFromCpuInfoFile(buffer, "physical id", this->CurrentPositionInFile + 1); } + uint64_t NumberOfSockets = PhysicalIDs.size(); + NumberOfSockets = std::max(NumberOfSockets, (uint64_t)1); // Physical ids returned by Linux don't distinguish cores. // We want to record the total number of cores in this->NumberOfPhysicalCPU // (checking only the first proc) - std::string cores = this->ExtractValueFromCpuInfoFile(buffer, "cpu cores"); - int numberOfCoresPerCPU = atoi(cores.c_str()); - if (maxId > 0) { - this->NumberOfPhysicalCPU = - static_cast(numberOfCoresPerCPU * (maxId + 1)); - } else { - // Linux Sparc: get cpu count - this->NumberOfPhysicalCPU = - atoi(this->ExtractValueFromCpuInfoFile(buffer, "ncpus active").c_str()); - } + std::string Cores = this->ExtractValueFromCpuInfoFile(buffer, "cpu cores"); + int NumberOfCoresPerSocket = atoi(Cores.c_str()); + NumberOfCoresPerSocket = std::max(NumberOfCoresPerSocket, 1); + this->NumberOfPhysicalCPU = NumberOfCoresPerSocket * NumberOfSockets; #else // __CYGWIN__ // does not have "physical id" entries, neither "cpu cores" @@ -3447,7 +3438,7 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() if (this->NumberOfPhysicalCPU <= 0) { this->NumberOfPhysicalCPU = 1; } - // LogicalProcessorsPerPhysical>1 => hyperthreading. + // LogicalProcessorsPerPhysical>1 => SMT. this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = this->NumberOfLogicalCPU / this->NumberOfPhysicalCPU; @@ -4322,68 +4313,10 @@ void SystemInformationImplementation::DelayOverhead(unsigned int uiMS) (void)uiMS; } -/** Return the number of logical CPU per physical CPUs Works only for windows - */ -unsigned char SystemInformationImplementation::LogicalCPUPerPhysicalCPU(void) -{ -#ifdef __APPLE__ - size_t len = 4; - int cores_per_package = 0; - int err = sysctlbyname("machdep.cpu.cores_per_package", &cores_per_package, - &len, NULL, 0); - if (err != 0) { - return 1; // That name was not found, default to 1 - } - return static_cast(cores_per_package); -#else - int Regs[4] = { 0, 0, 0, 0 }; -#if USE_CPUID - if (!this->IsHyperThreadingSupported()) { - return static_cast(1); // HT not supported - } - call_cpuid(1, Regs); -#endif - return static_cast((Regs[1] & NUM_LOGICAL_BITS) >> 16); -#endif -} - /** Works only for windows */ -bool SystemInformationImplementation::IsHyperThreadingSupported() +bool SystemInformationImplementation::IsSMTSupported() { - if (this->Features.ExtendedFeatures.SupportsHyperthreading) { - return true; - } - -#if USE_CPUID - int Regs[4] = { 0, 0, 0, 0 }, VendorId[4] = { 0, 0, 0, 0 }; - // Get vendor id string - if (!call_cpuid(0, VendorId)) { - return false; - } - // eax contains family processor type - // edx has info about the availability of hyper-Threading - if (!call_cpuid(1, Regs)) { - return false; - } - - if (((Regs[0] & FAMILY_ID) == PENTIUM4_ID) || (Regs[0] & EXT_FAMILY_ID)) { - if (VendorId[1] == 0x756e6547) // 'uneG' - { - if (VendorId[3] == 0x49656e69) // 'Ieni' - { - if (VendorId[2] == 0x6c65746e) // 'letn' - { - // Genuine Intel with hyper-Threading technology - this->Features.ExtendedFeatures.SupportsHyperthreading = - ((Regs[3] & HT_BIT) != 0); - return this->Features.ExtendedFeatures.SupportsHyperthreading; - } - } - } - } -#endif - - return 0; // Not genuine Intel processor + return this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical > 1; } /** Return the APIC Id. Works only for windows. */ @@ -4392,7 +4325,7 @@ unsigned char SystemInformationImplementation::GetAPICId() int Regs[4] = { 0, 0, 0, 0 }; #if USE_CPUID - if (!this->IsHyperThreadingSupported()) { + if (!this->IsSMTSupported()) { return static_cast(-1); // HT not supported } // Logical processor = 1 call_cpuid(1, Regs); @@ -4402,102 +4335,46 @@ unsigned char SystemInformationImplementation::GetAPICId() } /** Count the number of CPUs. Works only on windows. */ -int SystemInformationImplementation::CPUCount() +void SystemInformationImplementation::CPUCountWindows() { #if defined(_WIN32) - unsigned char StatusFlag = 0; - SYSTEM_INFO info; - + std::vector ProcInfo; this->NumberOfPhysicalCPU = 0; this->NumberOfLogicalCPU = 0; - info.dwNumberOfProcessors = 0; - GetSystemInfo(&info); - - // Number of physical processors in a non-Intel system - // or in a 32-bit Intel system with Hyper-Threading technology disabled - this->NumberOfPhysicalCPU = (unsigned char)info.dwNumberOfProcessors; - - if (this->IsHyperThreadingSupported()) { - unsigned char HT_Enabled = 0; - this->NumberOfLogicalCPU = this->LogicalCPUPerPhysicalCPU(); - if (this->NumberOfLogicalCPU >= - 1) // >1 Doesn't mean HT is enabled in the BIOS - { - HANDLE hCurrentProcessHandle; -#ifndef _WIN64 -#define DWORD_PTR DWORD -#endif - DWORD_PTR dwProcessAffinity; - DWORD_PTR dwSystemAffinity; - DWORD dwAffinityMask; - - // Calculate the appropriate shifts and mask based on the - // number of logical processors. - unsigned int i = 1; - unsigned char PHY_ID_MASK = 0xFF; - // unsigned char PHY_ID_SHIFT = 0; - - while (i < this->NumberOfLogicalCPU) { - i *= 2; - PHY_ID_MASK <<= 1; - // PHY_ID_SHIFT++; - } - hCurrentProcessHandle = GetCurrentProcess(); - GetProcessAffinityMask(hCurrentProcessHandle, &dwProcessAffinity, - &dwSystemAffinity); - - // Check if available process affinity mask is equal to the - // available system affinity mask - if (dwProcessAffinity != dwSystemAffinity) { - StatusFlag = HT_CANNOT_DETECT; - this->NumberOfPhysicalCPU = (unsigned char)-1; - return StatusFlag; - } - - dwAffinityMask = 1; - while (dwAffinityMask != 0 && dwAffinityMask <= dwProcessAffinity) { - // Check if this CPU is available - if (dwAffinityMask & dwProcessAffinity) { - if (SetProcessAffinityMask(hCurrentProcessHandle, dwAffinityMask)) { - unsigned char APIC_ID, LOG_ID; - Sleep(0); // Give OS time to switch CPU - - APIC_ID = GetAPICId(); - LOG_ID = APIC_ID & ~PHY_ID_MASK; - - if (LOG_ID != 0) { - HT_Enabled = 1; - } - } - } - dwAffinityMask = dwAffinityMask << 1; - } - // Reset the processor affinity - SetProcessAffinityMask(hCurrentProcessHandle, dwProcessAffinity); + { + DWORD Length = 0; + DWORD rc = GetLogicalProcessorInformation(NULL, &Length); + assert(FALSE == rc); + (void)rc; // Silence unused variable warning in Borland C++ 5.81 + assert(GetLastError() == ERROR_INSUFFICIENT_BUFFER); + ProcInfo.resize(Length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)); + rc = GetLogicalProcessorInformation(&ProcInfo[0], &Length); + assert(rc != FALSE); + (void)rc; // Silence unused variable warning in Borland C++ 5.81 + } + + typedef std::vector::iterator + pinfoIt_t; + for (pinfoIt_t it = ProcInfo.begin(); it != ProcInfo.end(); ++it) { + SYSTEM_LOGICAL_PROCESSOR_INFORMATION PInfo = *it; + if (PInfo.Relationship != RelationProcessorCore) { + continue; + } - if (this->NumberOfLogicalCPU == - 1) // Normal P4 : HT is disabled in hardware - { - StatusFlag = HT_DISABLED; - } else { - if (HT_Enabled) { - // Total physical processors in a Hyper-Threading enabled system. - this->NumberOfPhysicalCPU /= (this->NumberOfLogicalCPU); - StatusFlag = HT_ENABLED; - } else { - StatusFlag = HT_SUPPORTED_NOT_ENABLED; - } - } + std::bitset::digits> ProcMask( + (unsigned long long)PInfo.ProcessorMask); + unsigned int count = (unsigned int)ProcMask.count(); + if (count == 0) { // I think this should never happen, but just to be safe. + continue; } - } else { - // Processors do not have Hyper-Threading technology - StatusFlag = HT_NOT_CAPABLE; - this->NumberOfLogicalCPU = 1; + this->NumberOfPhysicalCPU++; + this->NumberOfLogicalCPU += (unsigned int)count; + this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = count; } - return StatusFlag; + this->NumberOfPhysicalCPU = std::max(1u, this->NumberOfPhysicalCPU); + this->NumberOfLogicalCPU = std::max(1u, this->NumberOfLogicalCPU); #else - return 0; #endif } @@ -4559,8 +4436,14 @@ bool SystemInformationImplementation::ParseSysCtl() sysctlbyname("hw.physicalcpu", &this->NumberOfPhysicalCPU, &len, NULL, 0); len = sizeof(this->NumberOfLogicalCPU); sysctlbyname("hw.logicalcpu", &this->NumberOfLogicalCPU, &len, NULL, 0); + + int cores_per_package = 0; + len = sizeof(cores_per_package); + err = sysctlbyname("machdep.cpu.cores_per_package", &cores_per_package, &len, + NULL, 0); + // That name was not found, default to 1 this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = - this->LogicalCPUPerPhysicalCPU(); + err != 0 ? 1 : static_cast(cores_per_package); len = sizeof(value); sysctlbyname("hw.cpufrequency", &value, &len, NULL, 0); diff --git a/SystemInformation.hxx.in b/SystemInformation.hxx.in index 0fc1067..cc09393 100644 --- a/SystemInformation.hxx.in +++ b/SystemInformation.hxx.in @@ -67,7 +67,7 @@ public: bool Is64Bits(); - unsigned int GetNumberOfLogicalCPU(); // per physical cpu + unsigned int GetNumberOfLogicalCPU(); unsigned int GetNumberOfPhysicalCPU(); bool DoesCPUSupportCPUID(); ----------------------------------------------------------------------- Summary of changes: Source/kwsys/SystemInformation.cxx | 245 +++++++++------------------------ Source/kwsys/SystemInformation.hxx.in | 2 +- 2 files changed, 65 insertions(+), 182 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 10 13:10:32 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 10 Feb 2017 13:10:32 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-65-gf78dfcf Message-ID: <20170210181032.5381F14DA@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via f78dfcfd57e10ab8f2d020bfbc462e535918bec0 (commit) via d4da4755cdab41679ae7c2fa6ef2984a2d6837ec (commit) via 14c771530a12feb4f92fb0ab466b40ff68997b05 (commit) from c8333e08fed572086f0e0fa9694f4ff75a3c9127 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f78dfcfd57e10ab8f2d020bfbc462e535918bec0 commit f78dfcfd57e10ab8f2d020bfbc462e535918bec0 Merge: c8333e0 d4da475 Author: Brad King AuthorDate: Fri Feb 10 13:10:31 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 10 13:10:31 2017 -0500 Merge topic 'update-curl' into next d4da4755 Help: Add notes for topic 'update-curl' 14c77153 Tests: Fix `file://` URLs given to curl https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d4da4755cdab41679ae7c2fa6ef2984a2d6837ec commit d4da4755cdab41679ae7c2fa6ef2984a2d6837ec Author: Brad King AuthorDate: Tue Feb 7 14:36:49 2017 -0500 Commit: Brad King CommitDate: Fri Feb 10 13:10:07 2017 -0500 Help: Add notes for topic 'update-curl' diff --git a/Help/release/dev/update-curl.rst b/Help/release/dev/update-curl.rst new file mode 100644 index 0000000..852ad5a --- /dev/null +++ b/Help/release/dev/update-curl.rst @@ -0,0 +1,6 @@ +update-curl +----------- + +* The version of curl bundled with CMake no longer accepts URLs of the form + ``file://c:/...`` on Windows due to a change in upstream curl 7.52. Use + the form ``file:///c:/...`` instead to work on all versions. https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=14c771530a12feb4f92fb0ab466b40ff68997b05 commit 14c771530a12feb4f92fb0ab466b40ff68997b05 Author: Brad King AuthorDate: Tue Feb 7 14:25:49 2017 -0500 Commit: Brad King CommitDate: Fri Feb 10 13:10:07 2017 -0500 Tests: Fix `file://` URLs given to curl Since upstream curl commit curl-7_52_0~131 (URL-parser: for file://[host]/ URLs, the [host] must be localhost, 2016-11-11) we can no longer use URLs of the form `file://c:/...` on Windows. These worked only accidentally before. Use `file:///c:/...` instead. diff --git a/Tests/CMakeTests/FileDownloadBadHashTest.cmake.in b/Tests/CMakeTests/FileDownloadBadHashTest.cmake.in index 4a47c06..64b45ed 100644 --- a/Tests/CMakeTests/FileDownloadBadHashTest.cmake.in +++ b/Tests/CMakeTests/FileDownloadBadHashTest.cmake.in @@ -1,4 +1,7 @@ -set(url "file://@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png") +if(NOT "@CMAKE_CURRENT_SOURCE_DIR@" MATCHES "^/") + set(slash /) +endif() +set(url "file://${slash}@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png") set(dir "@CMAKE_CURRENT_BINARY_DIR@/downloads") file(DOWNLOAD diff --git a/Tests/CMakeTests/FileDownloadTest.cmake.in b/Tests/CMakeTests/FileDownloadTest.cmake.in index 83ade2b..f6d9ad9 100644 --- a/Tests/CMakeTests/FileDownloadTest.cmake.in +++ b/Tests/CMakeTests/FileDownloadTest.cmake.in @@ -1,4 +1,7 @@ -set(url "file://@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png") +if(NOT "@CMAKE_CURRENT_SOURCE_DIR@" MATCHES "^/") + set(slash /) +endif() +set(url "file://${slash}@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png") set(dir "@CMAKE_CURRENT_BINARY_DIR@/downloads") message(STATUS "FileDownload:1") diff --git a/Tests/CMakeTests/FileUploadTest.cmake.in b/Tests/CMakeTests/FileUploadTest.cmake.in index 8577aef..9e22909 100644 --- a/Tests/CMakeTests/FileUploadTest.cmake.in +++ b/Tests/CMakeTests/FileUploadTest.cmake.in @@ -10,7 +10,10 @@ endif() file(MAKE_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@/uploads") set(filename "@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png") -set(urlbase "file://@CMAKE_CURRENT_BINARY_DIR@/uploads") +if(NOT "@CMAKE_CURRENT_BINARY_DIR@" MATCHES "^/") + set(slash /) +endif() +set(urlbase "file://${slash}@CMAKE_CURRENT_BINARY_DIR@/uploads") message(STATUS "FileUpload:1") file(UPLOAD diff --git a/Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake b/Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake index ca72692..a91b217 100644 --- a/Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake +++ b/Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake @@ -1,5 +1,8 @@ +if(NOT "${CMAKE_CURRENT_SOURCE_DIR}" MATCHES "^/") + set(slash /) +endif() file(DOWNLOAD - "file://${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-hash-mismatch.txt" + "file://${slash}${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-hash-mismatch.txt" ${CMAKE_CURRENT_BINARY_DIR}/hash-mismatch.txt EXPECTED_HASH SHA1=0123456789abcdef0123456789abcdef01234567 STATUS status diff --git a/Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake b/Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake index 2e3fbe1..2fa5482 100644 --- a/Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake +++ b/Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake @@ -1,5 +1,8 @@ +if(NOT "${CMAKE_CURRENT_SOURCE_DIR}" MATCHES "^/") + set(slash /) +endif() file(DOWNLOAD - "file://${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-unused-argument.txt" + "file://${slash}${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-unused-argument.txt" "${CMAKE_CURRENT_BINARY_DIR}/unused-argument.txt" JUNK ) diff --git a/Tests/RunCMake/file/UPLOAD-unused-argument.cmake b/Tests/RunCMake/file/UPLOAD-unused-argument.cmake index 94ac9ac..92c878c 100644 --- a/Tests/RunCMake/file/UPLOAD-unused-argument.cmake +++ b/Tests/RunCMake/file/UPLOAD-unused-argument.cmake @@ -1,5 +1,8 @@ +if(NOT "${CMAKE_CURRENT_BINARY_DIR}" MATCHES "^/") + set(slash /) +endif() file(UPLOAD "${CMAKE_CURRENT_SOURCE_DIR}/UPLOAD-unused-argument.txt" - "file://${CMAKE_CURRENT_BINARY_DIR}/unused-argument.txt" + "file://${slash}${CMAKE_CURRENT_BINARY_DIR}/unused-argument.txt" JUNK ) ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 10 13:36:11 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 10 Feb 2017 13:36:11 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-29-gf236c9c Message-ID: <20170210183611.0EC7FFA035@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via f236c9cff9dcb4d4534e5532a9792e648d48d921 (commit) via e2ee0971474ce92766f77d77025319ef575aa303 (commit) from 46c6489850ca9029bb75d17ed652563fc58a0082 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f236c9cff9dcb4d4534e5532a9792e648d48d921 commit f236c9cff9dcb4d4534e5532a9792e648d48d921 Merge: 46c6489 e2ee097 Author: Brad King AuthorDate: Fri Feb 10 13:36:09 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 10 13:36:09 2017 -0500 Merge topic 'gcc-cpp98' e2ee0971 g++ knows about C++98 selection flags since at least 3.4 ----------------------------------------------------------------------- Summary of changes: Modules/Compiler/GNU-CXX.cmake | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 10 13:36:14 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 10 Feb 2017 13:36:14 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-36-gbb72fff Message-ID: <20170210183614.2622CFA070@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via bb72fff2f09ef307b74de35ab00dfc08e6da83ee (commit) via d4da4755cdab41679ae7c2fa6ef2984a2d6837ec (commit) via 14c771530a12feb4f92fb0ab466b40ff68997b05 (commit) via 73ae67006c952b8804f2566e868bc3acf7539857 (commit) via 1df9d5f91944e0b5ba00815d55bb7dc545053b4c (commit) via 4cc2908fdaaf1ab8afe5c2ae5dbb3401859a9aab (commit) via f4a3290ae7ae096f8b92f7adfba7088e6918bc0b (commit) from f236c9cff9dcb4d4534e5532a9792e648d48d921 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=bb72fff2f09ef307b74de35ab00dfc08e6da83ee commit bb72fff2f09ef307b74de35ab00dfc08e6da83ee Merge: f236c9c d4da475 Author: Brad King AuthorDate: Fri Feb 10 13:36:11 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 10 13:36:11 2017 -0500 Merge topic 'update-curl' d4da4755 Help: Add notes for topic 'update-curl' 14c77153 Tests: Fix `file://` URLs given to curl 73ae6700 curl: Fix passing _WINSOCKAPI_ macro to compiler 1df9d5f9 Merge branch 'upstream-curl' into update-curl 4cc2908f curl 2016-12-22 (44b9b4d4) f4a3290a curl: Update script to get curl 7.52.1 ----------------------------------------------------------------------- Summary of changes: Help/release/dev/update-curl.rst | 6 + Tests/CMakeTests/FileDownloadBadHashTest.cmake.in | 5 +- Tests/CMakeTests/FileDownloadTest.cmake.in | 5 +- Tests/CMakeTests/FileUploadTest.cmake.in | 5 +- Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake | 5 +- Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake | 5 +- Tests/RunCMake/file/UPLOAD-unused-argument.cmake | 5 +- Utilities/Scripts/update-curl.bash | 2 +- Utilities/cmcurl/CMake/OtherTests.cmake | 25 +- Utilities/cmcurl/CMakeLists.txt | 8 +- Utilities/cmcurl/include/curl/curl.h | 84 +- Utilities/cmcurl/include/curl/curlver.h | 8 +- Utilities/cmcurl/include/curl/easy.h | 4 +- Utilities/cmcurl/include/curl/stdcheaders.h | 6 +- Utilities/cmcurl/include/curl/typecheck-gcc.h | 55 +- Utilities/cmcurl/lib/Makefile.inc | 4 +- Utilities/cmcurl/lib/asyn-ares.c | 4 +- Utilities/cmcurl/lib/asyn-thread.c | 24 +- Utilities/cmcurl/lib/conncache.c | 6 +- Utilities/cmcurl/lib/connect.c | 98 ++- Utilities/cmcurl/lib/connect.h | 13 +- Utilities/cmcurl/lib/content_encoding.c | 23 +- Utilities/cmcurl/lib/cookie.c | 10 +- Utilities/cmcurl/lib/curl_addrinfo.c | 34 +- Utilities/cmcurl/lib/curl_addrinfo.h | 2 +- Utilities/cmcurl/lib/curl_endian.c | 18 +- Utilities/cmcurl/lib/curl_endian.h | 18 +- Utilities/cmcurl/lib/curl_gethostname.c | 8 +- Utilities/cmcurl/lib/curl_gssapi.c | 2 +- Utilities/cmcurl/lib/curl_hmac.h | 26 +- Utilities/cmcurl/lib/curl_ntlm_core.c | 2 +- Utilities/cmcurl/lib/curl_ntlm_wb.c | 13 +- Utilities/cmcurl/lib/curl_sasl.c | 20 +- Utilities/cmcurl/lib/curl_sec.h | 16 +- Utilities/cmcurl/lib/curl_setup.h | 4 +- Utilities/cmcurl/lib/curl_threads.c | 5 +- Utilities/cmcurl/lib/curl_threads.h | 5 +- Utilities/cmcurl/lib/easy.c | 2 + Utilities/cmcurl/lib/escape.c | 9 +- Utilities/cmcurl/lib/file.c | 2 +- Utilities/cmcurl/lib/formdata.c | 46 +- Utilities/cmcurl/lib/formdata.h | 2 +- Utilities/cmcurl/lib/ftp.c | 196 ++--- Utilities/cmcurl/lib/ftp.h | 2 +- Utilities/cmcurl/lib/ftplistparser.c | 8 +- Utilities/cmcurl/lib/getinfo.c | 29 +- Utilities/cmcurl/lib/hash.c | 6 +- Utilities/cmcurl/lib/hash.h | 15 +- Utilities/cmcurl/lib/hmac.c | 10 +- Utilities/cmcurl/lib/hostcheck.c | 9 +- Utilities/cmcurl/lib/hostip.c | 4 +- Utilities/cmcurl/lib/hostip.h | 8 +- Utilities/cmcurl/lib/hostip4.c | 2 +- Utilities/cmcurl/lib/http.c | 85 +- Utilities/cmcurl/lib/http2.c | 212 ++++- Utilities/cmcurl/lib/http2.h | 8 + Utilities/cmcurl/lib/http_chunks.c | 14 +- Utilities/cmcurl/lib/http_digest.c | 20 +- Utilities/cmcurl/lib/http_negotiate.c | 16 +- Utilities/cmcurl/lib/http_ntlm.c | 4 +- Utilities/cmcurl/lib/http_proxy.c | 529 +++++------ Utilities/cmcurl/lib/http_proxy.h | 4 +- Utilities/cmcurl/lib/if2ip.c | 2 +- Utilities/cmcurl/lib/imap.c | 6 +- Utilities/cmcurl/lib/inet_ntop.c | 6 +- Utilities/cmcurl/lib/inet_pton.c | 8 +- Utilities/cmcurl/lib/krb5.c | 2 +- Utilities/cmcurl/lib/ldap.c | 46 +- Utilities/cmcurl/lib/md4.c | 3 +- Utilities/cmcurl/lib/md5.c | 7 +- Utilities/cmcurl/lib/memdebug.c | 2 +- Utilities/cmcurl/lib/mprintf.c | 25 +- Utilities/cmcurl/lib/multi.c | 38 +- Utilities/cmcurl/lib/multihandle.h | 4 +- Utilities/cmcurl/lib/multiif.h | 4 +- Utilities/cmcurl/lib/non-ascii.c | 4 +- Utilities/cmcurl/lib/nwlib.c | 10 +- Utilities/cmcurl/lib/nwos.c | 8 +- Utilities/cmcurl/lib/pingpong.c | 14 +- Utilities/cmcurl/lib/pingpong.h | 2 +- Utilities/cmcurl/lib/pop3.c | 8 +- Utilities/cmcurl/lib/progress.c | 40 +- Utilities/cmcurl/lib/rand.c | 130 +++ Utilities/cmcurl/lib/{easyif.h => rand.h} | 26 +- Utilities/cmcurl/lib/rtsp.c | 24 +- Utilities/cmcurl/lib/security.c | 13 +- Utilities/cmcurl/lib/select.c | 2 +- Utilities/cmcurl/lib/select.h | 2 +- Utilities/cmcurl/lib/sendf.c | 21 +- Utilities/cmcurl/lib/sendf.h | 2 + Utilities/cmcurl/lib/setup-os400.h | 52 +- Utilities/cmcurl/lib/setup-vms.h | 139 +-- Utilities/cmcurl/lib/share.h | 8 +- Utilities/cmcurl/lib/smb.c | 14 +- Utilities/cmcurl/lib/smtp.c | 6 +- Utilities/cmcurl/lib/socks.c | 43 +- Utilities/cmcurl/lib/socks.h | 5 +- Utilities/cmcurl/lib/socks_gssapi.c | 24 +- Utilities/cmcurl/lib/socks_sspi.c | 11 +- Utilities/cmcurl/lib/speedcheck.c | 6 +- Utilities/cmcurl/lib/ssh.c | 58 +- Utilities/cmcurl/lib/strcase.c | 12 +- Utilities/cmcurl/lib/strcase.h | 1 + Utilities/cmcurl/lib/strdup.c | 23 + Utilities/cmcurl/lib/strdup.h | 1 + Utilities/cmcurl/lib/strerror.c | 32 +- Utilities/cmcurl/lib/strtoofft.c | 4 +- Utilities/cmcurl/lib/telnet.c | 23 +- Utilities/cmcurl/lib/tftp.c | 8 +- Utilities/cmcurl/lib/timeval.c | 6 +- Utilities/cmcurl/lib/timeval.h | 6 +- Utilities/cmcurl/lib/transfer.c | 14 +- Utilities/cmcurl/lib/url.c | 925 ++++++++++++++------ Utilities/cmcurl/lib/url.h | 13 + Utilities/cmcurl/lib/urldata.h | 147 +++- Utilities/cmcurl/lib/vauth/cleartext.c | 24 +- Utilities/cmcurl/lib/vauth/digest.c | 17 +- Utilities/cmcurl/lib/vauth/digest_sspi.c | 2 +- Utilities/cmcurl/lib/vauth/ntlm.c | 12 +- Utilities/cmcurl/lib/vauth/spnego_sspi.c | 2 +- Utilities/cmcurl/lib/version.c | 3 + Utilities/cmcurl/lib/vtls/axtls.c | 81 +- Utilities/cmcurl/lib/vtls/cyassl.c | 105 ++- Utilities/cmcurl/lib/vtls/darwinssl.c | 412 +++++---- Utilities/cmcurl/lib/vtls/gskit.c | 354 ++++++-- Utilities/cmcurl/lib/vtls/gskit.h | 7 +- Utilities/cmcurl/lib/vtls/gtls.c | 289 +++--- Utilities/cmcurl/lib/vtls/gtls.h | 7 +- Utilities/cmcurl/lib/vtls/mbedtls.c | 92 +- Utilities/cmcurl/lib/vtls/nss.c | 219 +++-- Utilities/cmcurl/lib/vtls/nssg.h | 3 + Utilities/cmcurl/lib/vtls/openssl.c | 398 +++++---- Utilities/cmcurl/lib/vtls/openssl.h | 3 + Utilities/cmcurl/lib/vtls/polarssl.c | 81 +- Utilities/cmcurl/lib/vtls/schannel.c | 144 +-- Utilities/cmcurl/lib/vtls/vtls.c | 300 +++---- Utilities/cmcurl/lib/vtls/vtls.h | 48 +- Utilities/cmcurl/lib/x509asn1.c | 194 ++-- Utilities/cmcurl/lib/x509asn1.h | 26 +- 139 files changed, 4163 insertions(+), 2525 deletions(-) create mode 100644 Help/release/dev/update-curl.rst create mode 100644 Utilities/cmcurl/lib/rand.c copy Utilities/cmcurl/lib/{easyif.h => rand.h} (59%) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 10 13:36:17 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 10 Feb 2017 13:36:17 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-38-g0a30938 Message-ID: <20170210183617.CFFE1FA0BC@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 0a30938848518a0e5095a5dd7e4739922a78b743 (commit) via 9837ed96992a0a5e151c4cb5d4cbe6c7890d7db4 (commit) from bb72fff2f09ef307b74de35ab00dfc08e6da83ee (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0a30938848518a0e5095a5dd7e4739922a78b743 commit 0a30938848518a0e5095a5dd7e4739922a78b743 Merge: bb72fff 9837ed9 Author: Brad King AuthorDate: Fri Feb 10 13:36:14 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 10 13:36:14 2017 -0500 Merge topic 'ExtractGTestMacro' 9837ed96 GoogleTest: Add module to contain gtest_add_tests independently ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-modules.7.rst | 1 + Help/module/GoogleTest.rst | 1 + Help/release/dev/ExtractGTestMacro.rst | 5 +++ Modules/FindGTest.cmake | 60 ++------------------------ Modules/GoogleTest.cmake | 73 ++++++++++++++++++++++++++++++++ 5 files changed, 83 insertions(+), 57 deletions(-) create mode 100644 Help/module/GoogleTest.rst create mode 100644 Help/release/dev/ExtractGTestMacro.rst create mode 100644 Modules/GoogleTest.cmake hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 10 13:36:21 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 10 Feb 2017 13:36:21 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-40-gee3295e Message-ID: <20170210183621.1210EFA089@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via ee3295e91740033ebe9d9a0c800c0a3070108624 (commit) via 5ba2c9e5e08cb391c366065210a95a46ac74f310 (commit) from 0a30938848518a0e5095a5dd7e4739922a78b743 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ee3295e91740033ebe9d9a0c800c0a3070108624 commit ee3295e91740033ebe9d9a0c800c0a3070108624 Merge: 0a30938 5ba2c9e Author: Brad King AuthorDate: Fri Feb 10 13:36:18 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 10 13:36:18 2017 -0500 Merge topic 'vs-nasm' 5ba2c9e5 VS: Add support for ASM_NASM language diff --cc Modules/CMakeDetermineASMCompiler.cmake index 3f18a8c,66bf14b..7d5e2b2 --- a/Modules/CMakeDetermineASMCompiler.cmake +++ b/Modules/CMakeDetermineASMCompiler.cmake @@@ -92,9 -92,17 +92,17 @@@ if(NOT CMAKE_ASM${ASM_DIALECT}_COMPILER set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_FLAGS_ARMCC ) set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_ARMCC "(ARM Compiler)|(ARM Assembler)") + list(APPEND CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDORS NASM) + set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_FLAGS_NASM "-v") + set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_NASM "(NASM version)") + + list(APPEND CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDORS YASM) + set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_FLAGS_YASM "--version") + set(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_VENDOR_REGEX_YASM "(yasm)") + include(CMakeDetermineCompilerId) - CMAKE_DETERMINE_COMPILER_ID_VENDOR(ASM${ASM_DIALECT}) - + set(userflags) + CMAKE_DETERMINE_COMPILER_ID_VENDOR(ASM${ASM_DIALECT} "${userflags}") endif() if(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID) ----------------------------------------------------------------------- Summary of changes: Help/release/dev/vs-nasm.rst | 5 ++ Modules/CMakeDetermineASMCompiler.cmake | 8 ++ Modules/CMakeDetermineASM_NASMCompiler.cmake | 17 +++- Source/cmGlobalVisualStudio10Generator.cxx | 14 ++++ Source/cmGlobalVisualStudio10Generator.h | 2 + Source/cmGlobalVisualStudio7Generator.cxx | 1 + Source/cmGlobalVisualStudio7Generator.h | 2 + Source/cmVS10NASMFlagTable.h | 50 ++++++++++++ Source/cmVisualStudio10TargetGenerator.cxx | 105 ++++++++++++++++++++++++ Source/cmVisualStudio10TargetGenerator.h | 9 ++- Source/cmVisualStudio10ToolsetOptions.cxx | 1 + Source/cmVisualStudioGeneratorOptions.h | 1 + Templates/MSBuild/nasm.props.in | 17 ++++ Templates/MSBuild/nasm.targets | 41 ++++++++++ Templates/MSBuild/nasm.xml | 110 ++++++++++++++++++++++++++ Tests/CMakeLists.txt | 7 +- Tests/{VSMASM => VSNASM}/CMakeLists.txt | 6 +- Tests/VSNASM/foo.asm | 7 ++ Tests/VSNASM/include/foo-proc.asm | 7 ++ Tests/{VSMASM => VSNASM}/main.c | 0 20 files changed, 403 insertions(+), 7 deletions(-) create mode 100644 Help/release/dev/vs-nasm.rst create mode 100644 Source/cmVS10NASMFlagTable.h create mode 100644 Templates/MSBuild/nasm.props.in create mode 100644 Templates/MSBuild/nasm.targets create mode 100644 Templates/MSBuild/nasm.xml copy Tests/{VSMASM => VSNASM}/CMakeLists.txt (63%) create mode 100644 Tests/VSNASM/foo.asm create mode 100644 Tests/VSNASM/include/foo-proc.asm copy Tests/{VSMASM => VSNASM}/main.c (100%) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 10 13:36:41 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 10 Feb 2017 13:36:41 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-70-g36fd53b Message-ID: <20170210183641.74DEBFA070@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 36fd53b534c9678996b7bac971ac608cbbd2e910 (commit) via ee3295e91740033ebe9d9a0c800c0a3070108624 (commit) via 0a30938848518a0e5095a5dd7e4739922a78b743 (commit) via bb72fff2f09ef307b74de35ab00dfc08e6da83ee (commit) via f236c9cff9dcb4d4534e5532a9792e648d48d921 (commit) from f78dfcfd57e10ab8f2d020bfbc462e535918bec0 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=36fd53b534c9678996b7bac971ac608cbbd2e910 commit 36fd53b534c9678996b7bac971ac608cbbd2e910 Merge: f78dfcf ee3295e Author: Brad King AuthorDate: Fri Feb 10 13:36:28 2017 -0500 Commit: Brad King CommitDate: Fri Feb 10 13:36:28 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 10 14:02:33 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 10 Feb 2017 14:02:33 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-81-g97eb120 Message-ID: <20170210190233.D2E67FA37A@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 97eb120fd3b755ceb24da8ab159ecd68a8f62330 (commit) via 166b3393875e4f6752907b9b06c2518dce0432e9 (commit) via cbe4d5957b526f9a9bb6954d0c6944ad7642bb90 (commit) via 8731701cb636317df2691359361562f32adfe759 (commit) via 0ae5386aa953d1670074c2f1bfc9a04ddb382684 (commit) via ce19607fed3990b8e828330e77f09061c99aa113 (commit) via 008ed80dcf1d03640879b4168f4fba956aa03196 (commit) via c0d7bb8368c3d157d1a2758b620fc726355e554d (commit) via 21a125cdbff24efa746249a3b8ccc6296c5f0aff (commit) via eebb2be8b0db17bb5f760e7fa04c020406e6f6eb (commit) via 84f3c87b030037646c1110b1e4237f597ad3dd88 (commit) from 36fd53b534c9678996b7bac971ac608cbbd2e910 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=97eb120fd3b755ceb24da8ab159ecd68a8f62330 commit 97eb120fd3b755ceb24da8ab159ecd68a8f62330 Merge: 36fd53b 166b339 Author: Brad King AuthorDate: Fri Feb 10 14:02:31 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 10 14:02:31 2017 -0500 Merge topic 'cuda_tests_improve_error_reporting' into next 166b3393 Tests/Cuda: Select a CUDA device supporting compute 3.0 cbe4d595 Tests/Cuda: Return a non-zero code if errors occurred 8731701c Tests/Cuda: Use memory allocated on the GPU in the kernels 0ae5386a Tests/Cuda: Add missing separable compilation property ce19607f Tests/Cuda: Fix missing CUDA static library at runtime on macOS 008ed80d Tests/Cuda: Output error messages to std::cerr instead of std::cout c0d7bb83 Tests/Cuda: Print asynchronous error messages, if any 21a125cd Tests/Cuda: Print error message if mixed_kernel failed eebb2be8 Tests/Cuda: Add identifiers to error messages 84f3c87b Tests/Cuda: Print error message if an error occurred https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=166b3393875e4f6752907b9b06c2518dce0432e9 commit 166b3393875e4f6752907b9b06c2518dce0432e9 Author: Pierre Moreau AuthorDate: Wed Feb 8 22:50:58 2017 +0100 Commit: Brad King CommitDate: Fri Feb 10 13:47:05 2017 -0500 Tests/Cuda: Select a CUDA device supporting compute 3.0 diff --git a/Tests/Cuda/Complex/dynamic.cu b/Tests/Cuda/Complex/dynamic.cu index 0206bb4..2b04ac9 100644 --- a/Tests/Cuda/Complex/dynamic.cu +++ b/Tests/Cuda/Complex/dynamic.cu @@ -22,6 +22,46 @@ void DetermineIfValidCudaDevice() { } +EXPORT int choose_cuda_device() +{ + int nDevices = 0; + cudaError_t err = cudaGetDeviceCount(&nDevices); + if (err != cudaSuccess) + { + std::cerr << "Failed to retrieve the number of CUDA enabled devices" + << std::endl; + return 1; + } + for (int i = 0; i < nDevices; ++i) + { + cudaDeviceProp prop; + cudaError_t err = cudaGetDeviceProperties(&prop, i); + if (err != cudaSuccess) + { + std::cerr << "Could not retrieve properties from CUDA device " << i + << std::endl; + return 1; + } + if (prop.major >= 4) + { + err = cudaSetDevice(i); + if (err != cudaSuccess) + { + std::cout << "Could not select CUDA device " << i << std::endl; + } + else + { + return 0; + } + } + } + + std::cout << "Could not find a CUDA enabled card supporting compute >=3.0" + << std::endl; + + return 1; +} + EXPORT void cuda_dynamic_lib_func() { DetermineIfValidCudaDevice <<<1,1>>> (); diff --git a/Tests/Cuda/Complex/main.cpp b/Tests/Cuda/Complex/main.cpp index 92d1fb0..2498235 100644 --- a/Tests/Cuda/Complex/main.cpp +++ b/Tests/Cuda/Complex/main.cpp @@ -9,11 +9,17 @@ #define IMPORT #endif +IMPORT int choose_cuda_device(); IMPORT int call_cuda_seperable_code(int x); IMPORT int mixed_launch_kernel(int x); int main(int argc, char** argv) { + int ret = choose_cuda_device(); + if (ret) { + return 0; + } + int r1 = call_cuda_seperable_code(42); int r2 = mixed_launch_kernel(42); return (r1 == 42 || r2 == 42) ? 1 : 0; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=cbe4d5957b526f9a9bb6954d0c6944ad7642bb90 commit cbe4d5957b526f9a9bb6954d0c6944ad7642bb90 Author: Pierre Moreau AuthorDate: Thu Feb 2 23:12:15 2017 +0100 Commit: Brad King CommitDate: Fri Feb 10 13:46:42 2017 -0500 Tests/Cuda: Return a non-zero code if errors occurred diff --git a/Tests/Cuda/Complex/main.cpp b/Tests/Cuda/Complex/main.cpp index 5a3f820..92d1fb0 100644 --- a/Tests/Cuda/Complex/main.cpp +++ b/Tests/Cuda/Complex/main.cpp @@ -14,7 +14,7 @@ IMPORT int mixed_launch_kernel(int x); int main(int argc, char** argv) { - call_cuda_seperable_code(42); - mixed_launch_kernel(42); - return 0; + int r1 = call_cuda_seperable_code(42); + int r2 = mixed_launch_kernel(42); + return (r1 == 42 || r2 == 42) ? 1 : 0; } diff --git a/Tests/Cuda/ObjectLibrary/main.cpp b/Tests/Cuda/ObjectLibrary/main.cpp index 1a70a99..4d2f890 100644 --- a/Tests/Cuda/ObjectLibrary/main.cpp +++ b/Tests/Cuda/ObjectLibrary/main.cpp @@ -4,14 +4,16 @@ int static_func(int); int file1_sq_func(int); -void test_functions() +int test_functions() { - file1_sq_func(static_func(42)); + return file1_sq_func(static_func(42)); } int main(int argc, char** argv) { - test_functions(); + if (test_functions() == 1) { + return 1; + } std::cout << "this executable doesn't use cuda code, just call methods defined" << std::endl; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8731701cb636317df2691359361562f32adfe759 commit 8731701cb636317df2691359361562f32adfe759 Author: Pierre Moreau AuthorDate: Thu Feb 2 22:54:24 2017 +0100 Commit: Brad King CommitDate: Fri Feb 10 13:46:08 2017 -0500 Tests/Cuda: Use memory allocated on the GPU in the kernels diff --git a/Tests/Cuda/Complex/file3.cu b/Tests/Cuda/Complex/file3.cu index 912105a..bd8198d 100644 --- a/Tests/Cuda/Complex/file3.cu +++ b/Tests/Cuda/Complex/file3.cu @@ -9,17 +9,25 @@ result_type_dynamic __device__ file2_func(int x); static __global__ -void file3_kernel(result_type& r, int x) +void file3_kernel(result_type* r, int x) { - r = file1_func(x); + *r = file1_func(x); result_type_dynamic rd = file2_func(x); } int file3_launch_kernel(int x) { - result_type r; + result_type* r; + cudaError_t err = cudaMallocManaged(&r, sizeof(result_type)); + if(err != cudaSuccess) + { + std::cerr << "file3_launch_kernel: cudaMallocManaged failed: " + << cudaGetErrorString(err) << std::endl; + return x; + } + file3_kernel <<<1,1>>> (r,x); - cudaError_t err = cudaGetLastError(); + err = cudaGetLastError(); if(err != cudaSuccess) { std::cerr << "file3_kernel [SYNC] failed: " @@ -33,5 +41,14 @@ int file3_launch_kernel(int x) << cudaGetErrorString(cudaGetLastError()) << std::endl; return x; } - return r.sum; + int result = r->sum; + err = cudaFree(r); + if(err != cudaSuccess) + { + std::cerr << "file3_launch_kernel: cudaFree failed: " + << cudaGetErrorString(err) << std::endl; + return x; + } + + return result; } diff --git a/Tests/Cuda/Complex/mixed.cu b/Tests/Cuda/Complex/mixed.cu index a7bcd4e..d96cc7c 100644 --- a/Tests/Cuda/Complex/mixed.cu +++ b/Tests/Cuda/Complex/mixed.cu @@ -19,9 +19,9 @@ IMPORT void __host__ cuda_dynamic_lib_func(); static __global__ -void mixed_kernel(result_type& r, int x) +void mixed_kernel(result_type* r, int x) { - r = file1_func(x); + *r = file1_func(x); result_type_dynamic rd = file2_func(x); } @@ -29,9 +29,17 @@ EXPORT int mixed_launch_kernel(int x) { cuda_dynamic_lib_func(); - result_type r; + result_type* r; + cudaError_t err = cudaMallocManaged(&r, sizeof(result_type)); + if(err != cudaSuccess) + { + std::cerr << "mixed_launch_kernel: cudaMallocManaged failed: " + << cudaGetErrorString(err) << std::endl; + return x; + } + mixed_kernel <<<1,1>>> (r,x); - cudaError_t err = cudaGetLastError(); + err = cudaGetLastError(); if(err != cudaSuccess) { std::cerr << "mixed_kernel [SYNC] failed: " @@ -45,5 +53,15 @@ EXPORT int mixed_launch_kernel(int x) << cudaGetErrorString(cudaGetLastError()) << std::endl; return x; } - return r.sum; + + int result = r->sum; + err = cudaFree(r); + if(err != cudaSuccess) + { + std::cerr << "mixed_launch_kernel: cudaFree failed: " + << cudaGetErrorString(err) << std::endl; + return x; + } + + return result; } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0ae5386aa953d1670074c2f1bfc9a04ddb382684 commit 0ae5386aa953d1670074c2f1bfc9a04ddb382684 Author: Pierre Moreau AuthorDate: Thu Feb 2 22:41:14 2017 +0100 Commit: Brad King CommitDate: Fri Feb 10 13:46:08 2017 -0500 Tests/Cuda: Add missing separable compilation property This resulted in `mixed_kernel()` returning an "invalid device function" at runtime for `file1_func()`. Suggested-by: Robert Maynard diff --git a/Tests/Cuda/Complex/CMakeLists.txt b/Tests/Cuda/Complex/CMakeLists.txt index 14454cf..2dd6f73 100644 --- a/Tests/Cuda/Complex/CMakeLists.txt +++ b/Tests/Cuda/Complex/CMakeLists.txt @@ -32,6 +32,8 @@ add_library(CudaComplexSharedLib SHARED dynamic.cu) target_link_libraries(CudaComplexSharedLib PUBLIC CudaComplexCppBase) add_library(CudaComplexMixedLib SHARED mixed.cpp mixed.cu) +set_target_properties(CudaComplexMixedLib + PROPERTIES CUDA_SEPARABLE_COMPILATION ON) target_link_libraries(CudaComplexMixedLib PUBLIC CudaComplexSharedLib PRIVATE CudaComplexSeperableLib) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ce19607fed3990b8e828330e77f09061c99aa113 commit ce19607fed3990b8e828330e77f09061c99aa113 Author: Pierre Moreau AuthorDate: Thu Feb 2 22:38:32 2017 +0100 Commit: Brad King CommitDate: Fri Feb 10 13:46:07 2017 -0500 Tests/Cuda: Fix missing CUDA static library at runtime on macOS Suggested-by: Robert Maynard diff --git a/Tests/Cuda/Complex/CMakeLists.txt b/Tests/Cuda/Complex/CMakeLists.txt index 9a3703a..14454cf 100644 --- a/Tests/Cuda/Complex/CMakeLists.txt +++ b/Tests/Cuda/Complex/CMakeLists.txt @@ -38,3 +38,9 @@ target_link_libraries(CudaComplexMixedLib add_executable(CudaComplex main.cpp) target_link_libraries(CudaComplex PUBLIC CudaComplexMixedLib) + +if(APPLE) + # We need to add the default path to the driver (libcuda.dylib) as an rpath, so that + # the static cuda runtime can find it at runtime. + target_link_libraries(CudaComplex PRIVATE -Wl,-rpath,/usr/local/cuda/lib) +endif() https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=008ed80dcf1d03640879b4168f4fba956aa03196 commit 008ed80dcf1d03640879b4168f4fba956aa03196 Author: Pierre Moreau AuthorDate: Thu Feb 2 22:52:53 2017 +0100 Commit: Brad King CommitDate: Fri Feb 10 13:46:07 2017 -0500 Tests/Cuda: Output error messages to std::cerr instead of std::cout diff --git a/Tests/Cuda/ObjectLibrary/static.cu b/Tests/Cuda/ObjectLibrary/static.cu index 2374c23..a801153 100644 --- a/Tests/Cuda/ObjectLibrary/static.cu +++ b/Tests/Cuda/ObjectLibrary/static.cu @@ -10,8 +10,8 @@ int __host__ file1_sq_func(int x) err = cudaGetDeviceCount(&nDevices); if(err != cudaSuccess) { - std::cout << "nDevices: " << nDevices << std::endl; - std::cout << "err: " << err << std::endl; + std::cerr << "nDevices: " << nDevices << std::endl; + std::cerr << "err: " << err << std::endl; return 1; } std::cout << "this library uses cuda code" << std::endl; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c0d7bb8368c3d157d1a2758b620fc726355e554d commit c0d7bb8368c3d157d1a2758b620fc726355e554d Author: Pierre Moreau AuthorDate: Thu Feb 2 13:58:09 2017 +0100 Commit: Brad King CommitDate: Fri Feb 10 13:46:07 2017 -0500 Tests/Cuda: Print asynchronous error messages, if any As kernel launches are asynchronous, a `cudaGetLastError()` right after the kernel launch might be executed while the kernel is still running. Synchronizing the device will ensure that all the work is completed before progressing further on, and allows to catch errors that were previously missed. The `cudaGetLastError()` after the `cudaDeviceSynchronize()` is there to reset the error variable to `cudaSuccess`. diff --git a/Tests/Cuda/Complex/dynamic.cu b/Tests/Cuda/Complex/dynamic.cu index fc22c8b..0206bb4 100644 --- a/Tests/Cuda/Complex/dynamic.cu +++ b/Tests/Cuda/Complex/dynamic.cu @@ -31,4 +31,10 @@ EXPORT void cuda_dynamic_lib_func() std::cerr << "DetermineIfValidCudaDevice [SYNC] failed: " << cudaGetErrorString(err) << std::endl; } + err = cudaDeviceSynchronize(); + if(err != cudaSuccess) + { + std::cerr << "DetermineIfValidCudaDevice [ASYNC] failed: " + << cudaGetErrorString(cudaGetLastError()) << std::endl; + } } diff --git a/Tests/Cuda/Complex/file3.cu b/Tests/Cuda/Complex/file3.cu index 1daf47e..912105a 100644 --- a/Tests/Cuda/Complex/file3.cu +++ b/Tests/Cuda/Complex/file3.cu @@ -26,5 +26,12 @@ int file3_launch_kernel(int x) << cudaGetErrorString(err) << std::endl; return x; } + err = cudaDeviceSynchronize(); + if(err != cudaSuccess) + { + std::cerr << "file3_kernel [ASYNC] failed: " + << cudaGetErrorString(cudaGetLastError()) << std::endl; + return x; + } return r.sum; } diff --git a/Tests/Cuda/Complex/mixed.cu b/Tests/Cuda/Complex/mixed.cu index 429f1f3..a7bcd4e 100644 --- a/Tests/Cuda/Complex/mixed.cu +++ b/Tests/Cuda/Complex/mixed.cu @@ -38,5 +38,12 @@ EXPORT int mixed_launch_kernel(int x) << cudaGetErrorString(err) << std::endl; return x; } + err = cudaDeviceSynchronize(); + if(err != cudaSuccess) + { + std::cerr << "mixed_kernel [ASYNC] failed: " + << cudaGetErrorString(cudaGetLastError()) << std::endl; + return x; + } return r.sum; } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=21a125cdbff24efa746249a3b8ccc6296c5f0aff commit 21a125cdbff24efa746249a3b8ccc6296c5f0aff Author: Pierre Moreau AuthorDate: Thu Feb 2 13:44:49 2017 +0100 Commit: Brad King CommitDate: Fri Feb 10 13:46:06 2017 -0500 Tests/Cuda: Print error message if mixed_kernel failed diff --git a/Tests/Cuda/Complex/mixed.cu b/Tests/Cuda/Complex/mixed.cu index 7051de0..429f1f3 100644 --- a/Tests/Cuda/Complex/mixed.cu +++ b/Tests/Cuda/Complex/mixed.cu @@ -31,5 +31,12 @@ EXPORT int mixed_launch_kernel(int x) result_type r; mixed_kernel <<<1,1>>> (r,x); + cudaError_t err = cudaGetLastError(); + if(err != cudaSuccess) + { + std::cerr << "mixed_kernel [SYNC] failed: " + << cudaGetErrorString(err) << std::endl; + return x; + } return r.sum; } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=eebb2be8b0db17bb5f760e7fa04c020406e6f6eb commit eebb2be8b0db17bb5f760e7fa04c020406e6f6eb Author: Pierre Moreau AuthorDate: Thu Feb 2 23:22:16 2017 +0100 Commit: Brad King CommitDate: Fri Feb 10 13:46:06 2017 -0500 Tests/Cuda: Add identifiers to error messages diff --git a/Tests/Cuda/Complex/dynamic.cu b/Tests/Cuda/Complex/dynamic.cu index b0a27d4..fc22c8b 100644 --- a/Tests/Cuda/Complex/dynamic.cu +++ b/Tests/Cuda/Complex/dynamic.cu @@ -28,6 +28,7 @@ EXPORT void cuda_dynamic_lib_func() cudaError_t err = cudaGetLastError(); if(err != cudaSuccess) { - std::cerr << cudaGetErrorString(err) << std::endl; + std::cerr << "DetermineIfValidCudaDevice [SYNC] failed: " + << cudaGetErrorString(err) << std::endl; } } diff --git a/Tests/Cuda/Complex/file3.cu b/Tests/Cuda/Complex/file3.cu index 0c8a09b..1daf47e 100644 --- a/Tests/Cuda/Complex/file3.cu +++ b/Tests/Cuda/Complex/file3.cu @@ -22,7 +22,8 @@ int file3_launch_kernel(int x) cudaError_t err = cudaGetLastError(); if(err != cudaSuccess) { - std::cerr << cudaGetErrorString(err) << std::endl; + std::cerr << "file3_kernel [SYNC] failed: " + << cudaGetErrorString(err) << std::endl; return x; } return r.sum; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=84f3c87b030037646c1110b1e4237f597ad3dd88 commit 84f3c87b030037646c1110b1e4237f597ad3dd88 Author: Pierre Moreau AuthorDate: Thu Feb 2 13:40:42 2017 +0100 Commit: Brad King CommitDate: Fri Feb 10 13:46:06 2017 -0500 Tests/Cuda: Print error message if an error occurred Fixes c59811a2 "CUDA: Tests now state why they are failing when no CUDA card is found." diff --git a/Tests/Cuda/Complex/dynamic.cu b/Tests/Cuda/Complex/dynamic.cu index a23dc25..b0a27d4 100644 --- a/Tests/Cuda/Complex/dynamic.cu +++ b/Tests/Cuda/Complex/dynamic.cu @@ -26,7 +26,7 @@ EXPORT void cuda_dynamic_lib_func() { DetermineIfValidCudaDevice <<<1,1>>> (); cudaError_t err = cudaGetLastError(); - if(err == cudaSuccess) + if(err != cudaSuccess) { std::cerr << cudaGetErrorString(err) << std::endl; } diff --git a/Tests/Cuda/Complex/file3.cu b/Tests/Cuda/Complex/file3.cu index 47e64c5..0c8a09b 100644 --- a/Tests/Cuda/Complex/file3.cu +++ b/Tests/Cuda/Complex/file3.cu @@ -20,7 +20,7 @@ int file3_launch_kernel(int x) result_type r; file3_kernel <<<1,1>>> (r,x); cudaError_t err = cudaGetLastError(); - if(err == cudaSuccess) + if(err != cudaSuccess) { std::cerr << cudaGetErrorString(err) << std::endl; return x; ----------------------------------------------------------------------- Summary of changes: Tests/Cuda/Complex/CMakeLists.txt | 8 ++++++ Tests/Cuda/Complex/dynamic.cu | 51 ++++++++++++++++++++++++++++++++++-- Tests/Cuda/Complex/file3.cu | 39 ++++++++++++++++++++++----- Tests/Cuda/Complex/main.cpp | 12 ++++++--- Tests/Cuda/Complex/mixed.cu | 40 +++++++++++++++++++++++++--- Tests/Cuda/ObjectLibrary/main.cpp | 8 +++--- Tests/Cuda/ObjectLibrary/static.cu | 4 +-- 7 files changed, 141 insertions(+), 21 deletions(-) hooks/post-receive -- CMake From daniel at pfeifer-mail.de Fri Feb 10 17:05:33 2017 From: daniel at pfeifer-mail.de (Daniel Pfeifer) Date: Fri, 10 Feb 2017 17:05:33 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-83-gfe4c8e4 Message-ID: <20170210220533.61DA5FA5B6@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via fe4c8e497ce4eb67bd14187f8729710a72cfe37a (commit) via c3800e54583208ac4a6435884bb8832e72af3183 (commit) from 97eb120fd3b755ceb24da8ab159ecd68a8f62330 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=fe4c8e497ce4eb67bd14187f8729710a72cfe37a commit fe4c8e497ce4eb67bd14187f8729710a72cfe37a Merge: 97eb120 c3800e5 Author: Daniel Pfeifer AuthorDate: Fri Feb 10 17:05:32 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 10 17:05:32 2017 -0500 Merge topic 'erase-if' into next c3800e54 cmAlgorithms: add cmEraseIf function https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c3800e54583208ac4a6435884bb8832e72af3183 commit c3800e54583208ac4a6435884bb8832e72af3183 Author: Daniel Pfeifer AuthorDate: Fri Feb 10 23:04:32 2017 +0100 Commit: Daniel Pfeifer CommitDate: Fri Feb 10 23:04:32 2017 +0100 cmAlgorithms: add cmEraseIf function diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h index 7c683ad..f5469e5 100644 --- a/Source/cmAlgorithms.h +++ b/Source/cmAlgorithms.h @@ -101,6 +101,12 @@ FwdIt cmRotate(FwdIt first, FwdIt middle, FwdIt last) return first; } +template +void cmEraseIf(Container& cont, Predicate pred) +{ + cont.erase(std::remove_if(cont.begin(), cont.end(), pred), cont.end()); +} + namespace ContainerAlgorithms { template diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx index 81c305c..d2ac36b 100644 --- a/Source/cmGlobalVisualStudio14Generator.cxx +++ b/Source/cmGlobalVisualStudio14Generator.cxx @@ -238,8 +238,7 @@ std::string cmGlobalVisualStudio14Generator::GetWindows10SDKVersion() // Skip SDKs that do not contain because that indicates that // only the UCRT MSIs were installed for them. - sdks.erase(std::remove_if(sdks.begin(), sdks.end(), NoWindowsH()), - sdks.end()); + cmEraseIf(sdks, NoWindowsH()); if (!sdks.empty()) { // Only use the filename, which will be the SDK version. diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 41a4caf..4388e75 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -1864,10 +1864,7 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo( std::string binaryDir = this->GetState()->GetBinaryDirectory(); if (this->Makefile->IsOn("CMAKE_DEPENDS_IN_PROJECT_ONLY")) { const char* sourceDir = this->GetState()->GetSourceDirectory(); - std::vector::iterator itr = - std::remove_if(includes.begin(), includes.end(), - ::NotInProjectDir(sourceDir, binaryDir)); - includes.erase(itr, includes.end()); + cmEraseIf(includes, ::NotInProjectDir(sourceDir, binaryDir)); } for (std::vector::iterator i = includes.begin(); i != includes.end(); ++i) { diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index bfe46ae..618f694 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -653,21 +653,12 @@ void cmMakefile::FinalPass() // we don't want cmake to re-run if a configured file is created and deleted // during processing as that would make it a transient file that can't // influence the build process - - // remove_if will move all items that don't have a valid file name to the - // back of the vector - std::vector::iterator new_output_files_end = std::remove_if( - this->OutputFiles.begin(), this->OutputFiles.end(), file_not_persistent()); - // we just have to erase all items at the back - this->OutputFiles.erase(new_output_files_end, this->OutputFiles.end()); + cmEraseIf(this->OutputFiles, file_not_persistent()); // if a configured file is used as input for another configured file, // and then deleted it will show up in the input list files so we // need to scan those too - std::vector::iterator new_list_files_end = std::remove_if( - this->ListFiles.begin(), this->ListFiles.end(), file_not_persistent()); - - this->ListFiles.erase(new_list_files_end, this->ListFiles.end()); + cmEraseIf(this->ListFiles, file_not_persistent()); } // Generate the output file diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index b172478..9bf0ccd 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -260,12 +260,9 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule(bool useResponseFile) rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(), *i, vars); } - { - // If there is no ranlib the command will be ":". Skip it. - std::vector::iterator newEnd = std::remove_if( - linkCmds.begin(), linkCmds.end(), cmNinjaRemoveNoOpCommands()); - linkCmds.erase(newEnd, linkCmds.end()); - } + + // If there is no ranlib the command will be ":". Skip it. + cmEraseIf(linkCmds, cmNinjaRemoveNoOpCommands()); std::string linkCmd = this->GetLocalGenerator()->BuildCommandLine(linkCmds); @@ -388,12 +385,9 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile) rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(), *i, vars); } - { - // If there is no ranlib the command will be ":". Skip it. - std::vector::iterator newEnd = std::remove_if( - linkCmds.begin(), linkCmds.end(), cmNinjaRemoveNoOpCommands()); - linkCmds.erase(newEnd, linkCmds.end()); - } + + // If there is no ranlib the command will be ":". Skip it. + cmEraseIf(linkCmds, cmNinjaRemoveNoOpCommands()); linkCmds.insert(linkCmds.begin(), "$PRE_LINK"); linkCmds.push_back("$POST_BUILD"); ----------------------------------------------------------------------- Summary of changes: Source/cmAlgorithms.h | 6 ++++++ Source/cmGlobalVisualStudio14Generator.cxx | 3 +-- Source/cmLocalUnixMakefileGenerator3.cxx | 5 +---- Source/cmMakefile.cxx | 13 ++----------- Source/cmNinjaNormalTargetGenerator.cxx | 18 ++++++------------ 5 files changed, 16 insertions(+), 29 deletions(-) hooks/post-receive -- CMake From daniel at pfeifer-mail.de Fri Feb 10 18:21:20 2017 From: daniel at pfeifer-mail.de (Daniel Pfeifer) Date: Fri, 10 Feb 2017 18:21:20 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-90-g4c53c29 Message-ID: <20170210232121.11029F9A16@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 4c53c29d86e7dc4c580fb5b7c8f06551934ae03c (commit) via 4ff5dce9f8be34d556f1fb98272a8654b1f6c5bb (commit) via 934ac7916e4e4df6ef55441d58fd1c310e4ad9f1 (commit) via 717491dd7d4a886d484025fd9002df44458117b5 (commit) via b75e7691425d4cb658f3b0981fdbfbc25dedfb43 (commit) via 17926f29cecc7574c9173ff06f5e3d0e4e250b02 (commit) via c1bfff2e72bd673e7b7bebddf58c7ea508bf4196 (commit) from fe4c8e497ce4eb67bd14187f8729710a72cfe37a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4c53c29d86e7dc4c580fb5b7c8f06551934ae03c commit 4c53c29d86e7dc4c580fb5b7c8f06551934ae03c Merge: fe4c8e4 4ff5dce Author: Daniel Pfeifer AuthorDate: Fri Feb 10 18:21:19 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 10 18:21:19 2017 -0500 Merge topic 'command-cleanup' into next 4ff5dce9 cmCommands: add commands directly to cmState 934ac791 split Default commands into Scripting and Project 717491dd cmDeprecatedCommand: extract policy checking from cmCommand b75e7691 cmCommand: Don't prefix error message with command name 17926f29 cmCommand: make noncopyable c1bfff2e cmCommand: remove member Helper https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4ff5dce9f8be34d556f1fb98272a8654b1f6c5bb commit 4ff5dce9f8be34d556f1fb98272a8654b1f6c5bb Author: Daniel Pfeifer AuthorDate: Fri Jan 20 22:40:16 2017 +0100 Commit: Daniel Pfeifer CommitDate: Sat Feb 11 00:20:22 2017 +0100 cmCommands: add commands directly to cmState diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index bc24234..9ff395a 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -1,6 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCommands.h" +#include "cmState.h" #include "cmAddCustomCommandCommand.h" #include "cmAddCustomTargetCommand.h" @@ -105,170 +106,162 @@ #include "cmWriteFileCommand.h" #endif -std::vector GetScriptingCommands() +void GetScriptingCommands(cmState* state) { - std::vector commands; + state->AddCommand(new cmBreakCommand); + state->AddCommand(new cmCMakeMinimumRequired); + state->AddCommand(new cmCMakePolicyCommand); + state->AddCommand(new cmConfigureFileCommand); + state->AddCommand(new cmContinueCommand); + state->AddCommand(new cmExecProgramCommand); + state->AddCommand(new cmExecuteProcessCommand); + state->AddCommand(new cmFileCommand); + state->AddCommand(new cmFindFileCommand); + state->AddCommand(new cmFindLibraryCommand); + state->AddCommand(new cmFindPackageCommand); + state->AddCommand(new cmFindPathCommand); + state->AddCommand(new cmFindProgramCommand); + state->AddCommand(new cmForEachCommand); + state->AddCommand(new cmFunctionCommand); + state->AddCommand(new cmGetCMakePropertyCommand); + state->AddCommand(new cmGetDirectoryPropertyCommand); + state->AddCommand(new cmGetFilenameComponentCommand); + state->AddCommand(new cmGetPropertyCommand); + state->AddCommand(new cmIfCommand); + state->AddCommand(new cmIncludeCommand); + state->AddCommand(new cmListCommand); + state->AddCommand(new cmMacroCommand); + state->AddCommand(new cmMakeDirectoryCommand); + state->AddCommand(new cmMarkAsAdvancedCommand); + state->AddCommand(new cmMathCommand); + state->AddCommand(new cmMessageCommand); + state->AddCommand(new cmOptionCommand); + state->AddCommand(new cmParseArgumentsCommand); + state->AddCommand(new cmReturnCommand); + state->AddCommand(new cmSeparateArgumentsCommand); + state->AddCommand(new cmSetCommand); + state->AddCommand(new cmSetDirectoryPropertiesCommand); + state->AddCommand(new cmSetPropertyCommand); + state->AddCommand(new cmSiteNameCommand); + state->AddCommand(new cmStringCommand); + state->AddCommand(new cmUnsetCommand); + state->AddCommand(new cmWhileCommand); - commands.push_back(new cmBreakCommand); - commands.push_back(new cmCMakeMinimumRequired); - commands.push_back(new cmCMakePolicyCommand); - commands.push_back(new cmConfigureFileCommand); - commands.push_back(new cmContinueCommand); - commands.push_back(new cmExecProgramCommand); - commands.push_back(new cmExecuteProcessCommand); - commands.push_back(new cmFileCommand); - commands.push_back(new cmFindFileCommand); - commands.push_back(new cmFindLibraryCommand); - commands.push_back(new cmFindPackageCommand); - commands.push_back(new cmFindPathCommand); - commands.push_back(new cmFindProgramCommand); - commands.push_back(new cmForEachCommand); - commands.push_back(new cmFunctionCommand); - commands.push_back(new cmGetCMakePropertyCommand); - commands.push_back(new cmGetDirectoryPropertyCommand); - commands.push_back(new cmGetFilenameComponentCommand); - commands.push_back(new cmGetPropertyCommand); - commands.push_back(new cmIfCommand); - commands.push_back(new cmIncludeCommand); - commands.push_back(new cmListCommand); - commands.push_back(new cmMacroCommand); - commands.push_back(new cmMakeDirectoryCommand); - commands.push_back(new cmMarkAsAdvancedCommand); - commands.push_back(new cmMathCommand); - commands.push_back(new cmMessageCommand); - commands.push_back(new cmOptionCommand); - commands.push_back(new cmParseArgumentsCommand); - commands.push_back(new cmReturnCommand); - commands.push_back(new cmSeparateArgumentsCommand); - commands.push_back(new cmSetCommand); - commands.push_back(new cmSetDirectoryPropertiesCommand); - commands.push_back(new cmSetPropertyCommand); - commands.push_back(new cmSiteNameCommand); - commands.push_back(new cmStringCommand); - commands.push_back(new cmUnsetCommand); - commands.push_back(new cmWhileCommand); - - commands.push_back(new cmUnexpectedCommand( + state->AddCommand(new cmUnexpectedCommand( "else", "An ELSE command was found outside of a proper " "IF ENDIF structure. Or its arguments did not match " "the opening IF command.")); - commands.push_back(new cmUnexpectedCommand( + state->AddCommand(new cmUnexpectedCommand( "elseif", "An ELSEIF command was found outside of a proper " "IF ENDIF structure.")); - commands.push_back(new cmUnexpectedCommand( + state->AddCommand(new cmUnexpectedCommand( "endforeach", "An ENDFOREACH command was found outside of a proper " "FOREACH ENDFOREACH structure. Or its arguments did " "not match the opening FOREACH command.")); - commands.push_back(new cmUnexpectedCommand( + state->AddCommand(new cmUnexpectedCommand( "endfunction", "An ENDFUNCTION command was found outside of a proper " "FUNCTION ENDFUNCTION structure. Or its arguments did not " "match the opening FUNCTION command.")); - commands.push_back(new cmUnexpectedCommand( + state->AddCommand(new cmUnexpectedCommand( "endif", "An ENDIF command was found outside of a proper " "IF ENDIF structure. Or its arguments did not match " "the opening IF command.")); - commands.push_back(new cmUnexpectedCommand( + state->AddCommand(new cmUnexpectedCommand( "endmacro", "An ENDMACRO command was found outside of a proper " "MACRO ENDMACRO structure. Or its arguments did not " "match the opening MACRO command.")); - commands.push_back(new cmUnexpectedCommand( + state->AddCommand(new cmUnexpectedCommand( "endwhile", "An ENDWHILE command was found outside of a proper " "WHILE ENDWHILE structure. Or its arguments did not " "match the opening WHILE command.")); #if defined(CMAKE_BUILD_WITH_CMAKE) - commands.push_back(new cmCMakeHostSystemInformationCommand); - commands.push_back(new cmRemoveCommand); - commands.push_back(new cmVariableWatchCommand); - commands.push_back(new cmWriteFileCommand); + state->AddCommand(new cmCMakeHostSystemInformationCommand); + state->AddCommand(new cmRemoveCommand); + state->AddCommand(new cmVariableWatchCommand); + state->AddCommand(new cmWriteFileCommand); - commands.push_back(new cmDeprecatedCommand( + state->AddCommand(new cmDeprecatedCommand( new cmBuildNameCommand, cmPolicies::CMP0036, "The build_name command should not be called; see CMP0036.")); - commands.push_back(new cmDeprecatedCommand( + state->AddCommand(new cmDeprecatedCommand( new cmUseMangledMesaCommand, cmPolicies::CMP0030, "The use_mangled_mesa command should not be called; see CMP0030.")); #endif - - return commands; } -std::vector GetProjectCommands() +void GetProjectCommands(cmState* state) { - std::vector commands; - - commands.push_back(new cmAddCustomCommandCommand); - commands.push_back(new cmAddCustomTargetCommand); - commands.push_back(new cmAddDefinitionsCommand); - commands.push_back(new cmAddDependenciesCommand); - commands.push_back(new cmAddExecutableCommand); - commands.push_back(new cmAddLibraryCommand); - commands.push_back(new cmAddSubDirectoryCommand); - commands.push_back(new cmAddTestCommand); - commands.push_back(new cmBuildCommand); - commands.push_back(new cmCreateTestSourceList); - commands.push_back(new cmDefinePropertyCommand); - commands.push_back(new cmEnableLanguageCommand); - commands.push_back(new cmEnableTestingCommand); - commands.push_back(new cmGetSourceFilePropertyCommand); - commands.push_back(new cmGetTargetPropertyCommand); - commands.push_back(new cmGetTestPropertyCommand); - commands.push_back(new cmIncludeDirectoryCommand); - commands.push_back(new cmIncludeRegularExpressionCommand); - commands.push_back(new cmInstallCommand); - commands.push_back(new cmInstallFilesCommand); - commands.push_back(new cmInstallTargetsCommand); - commands.push_back(new cmLinkDirectoriesCommand); - commands.push_back(new cmProjectCommand); - commands.push_back(new cmSetSourceFilesPropertiesCommand); - commands.push_back(new cmSetTargetPropertiesCommand); - commands.push_back(new cmSetTestsPropertiesCommand); - commands.push_back(new cmSubdirCommand); - commands.push_back(new cmTargetLinkLibrariesCommand); - commands.push_back(new cmTryCompileCommand); - commands.push_back(new cmTryRunCommand); + state->AddCommand(new cmAddCustomCommandCommand); + state->AddCommand(new cmAddCustomTargetCommand); + state->AddCommand(new cmAddDefinitionsCommand); + state->AddCommand(new cmAddDependenciesCommand); + state->AddCommand(new cmAddExecutableCommand); + state->AddCommand(new cmAddLibraryCommand); + state->AddCommand(new cmAddSubDirectoryCommand); + state->AddCommand(new cmAddTestCommand); + state->AddCommand(new cmBuildCommand); + state->AddCommand(new cmCreateTestSourceList); + state->AddCommand(new cmDefinePropertyCommand); + state->AddCommand(new cmEnableLanguageCommand); + state->AddCommand(new cmEnableTestingCommand); + state->AddCommand(new cmGetSourceFilePropertyCommand); + state->AddCommand(new cmGetTargetPropertyCommand); + state->AddCommand(new cmGetTestPropertyCommand); + state->AddCommand(new cmIncludeDirectoryCommand); + state->AddCommand(new cmIncludeRegularExpressionCommand); + state->AddCommand(new cmInstallCommand); + state->AddCommand(new cmInstallFilesCommand); + state->AddCommand(new cmInstallTargetsCommand); + state->AddCommand(new cmLinkDirectoriesCommand); + state->AddCommand(new cmProjectCommand); + state->AddCommand(new cmSetSourceFilesPropertiesCommand); + state->AddCommand(new cmSetTargetPropertiesCommand); + state->AddCommand(new cmSetTestsPropertiesCommand); + state->AddCommand(new cmSubdirCommand); + state->AddCommand(new cmTargetLinkLibrariesCommand); + state->AddCommand(new cmTryCompileCommand); + state->AddCommand(new cmTryRunCommand); #if defined(CMAKE_BUILD_WITH_CMAKE) - commands.push_back(new cmAddCompileOptionsCommand); - commands.push_back(new cmAuxSourceDirectoryCommand); - commands.push_back(new cmExportCommand); - commands.push_back(new cmFLTKWrapUICommand); - commands.push_back(new cmIncludeExternalMSProjectCommand); - commands.push_back(new cmInstallProgramsCommand); - commands.push_back(new cmLinkLibrariesCommand); - commands.push_back(new cmLoadCacheCommand); - commands.push_back(new cmQTWrapCPPCommand); - commands.push_back(new cmQTWrapUICommand); - commands.push_back(new cmRemoveDefinitionsCommand); - commands.push_back(new cmSourceGroupCommand); - commands.push_back(new cmTargetCompileDefinitionsCommand); - commands.push_back(new cmTargetCompileFeaturesCommand); - commands.push_back(new cmTargetCompileOptionsCommand); - commands.push_back(new cmTargetIncludeDirectoriesCommand); - commands.push_back(new cmTargetSourcesCommand); + state->AddCommand(new cmAddCompileOptionsCommand); + state->AddCommand(new cmAuxSourceDirectoryCommand); + state->AddCommand(new cmExportCommand); + state->AddCommand(new cmFLTKWrapUICommand); + state->AddCommand(new cmIncludeExternalMSProjectCommand); + state->AddCommand(new cmInstallProgramsCommand); + state->AddCommand(new cmLinkLibrariesCommand); + state->AddCommand(new cmLoadCacheCommand); + state->AddCommand(new cmQTWrapCPPCommand); + state->AddCommand(new cmQTWrapUICommand); + state->AddCommand(new cmRemoveDefinitionsCommand); + state->AddCommand(new cmSourceGroupCommand); + state->AddCommand(new cmTargetCompileDefinitionsCommand); + state->AddCommand(new cmTargetCompileFeaturesCommand); + state->AddCommand(new cmTargetCompileOptionsCommand); + state->AddCommand(new cmTargetIncludeDirectoriesCommand); + state->AddCommand(new cmTargetSourcesCommand); - commands.push_back(new cmDeprecatedCommand( + state->AddCommand(new cmDeprecatedCommand( new cmExportLibraryDependenciesCommand, cmPolicies::CMP0033, "The export_library_dependencies command should not be called; " "see CMP0033.")); - commands.push_back(new cmDeprecatedCommand( + state->AddCommand(new cmDeprecatedCommand( new cmLoadCommandCommand, cmPolicies::CMP0031, "The load_command command should not be called; see CMP0031.")); - commands.push_back(new cmDeprecatedCommand( + state->AddCommand(new cmDeprecatedCommand( new cmOutputRequiredFilesCommand, cmPolicies::CMP0032, "The output_required_files command should not be called; " "see CMP0032.")); - commands.push_back(new cmDeprecatedCommand( + state->AddCommand(new cmDeprecatedCommand( new cmSubdirDependsCommand, cmPolicies::CMP0029, "The subdir_depends command should not be called; see CMP0029.")); - commands.push_back(new cmDeprecatedCommand( + state->AddCommand(new cmDeprecatedCommand( new cmUtilitySourceCommand, cmPolicies::CMP0034, "The utility_source command should not be called; see CMP0034.")); - commands.push_back(new cmDeprecatedCommand( + state->AddCommand(new cmDeprecatedCommand( new cmVariableRequiresCommand, cmPolicies::CMP0035, "The variable_requires command should not be called; see CMP0035.")); #endif - - return commands; } diff --git a/Source/cmCommands.h b/Source/cmCommands.h index 4d09e42..7895ece 100644 --- a/Source/cmCommands.h +++ b/Source/cmCommands.h @@ -3,17 +3,14 @@ #ifndef cmCommands_h #define cmCommands_h -#include // IWYU pragma: keep +class cmState; -#include - -class cmCommand; /** - * Global function to return all compiled in commands. + * Global function to register all compiled in commands. * To add a new command edit cmCommands.cxx and add your command. * It is up to the caller to delete the commands created by this call. */ -std::vector GetScriptingCommands(); -std::vector GetProjectCommands(); +void GetScriptingCommands(cmState* state); +void GetProjectCommands(cmState* state); #endif diff --git a/Source/cmake.cxx b/Source/cmake.cxx index c6292ce..b2384cd 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -120,8 +120,6 @@ #include #include -class cmCommand; - namespace { #if defined(CMAKE_BUILD_WITH_CMAKE) @@ -1657,20 +1655,12 @@ const char* cmake::GetCacheDefinition(const std::string& name) const void cmake::AddScriptingCommands() { - std::vector const commands = GetScriptingCommands(); - for (std::vector::const_iterator i = commands.begin(); - i != commands.end(); ++i) { - this->State->AddCommand(*i); - } + GetScriptingCommands(this->State); } void cmake::AddProjectCommands() { - std::vector const commands = GetProjectCommands(); - for (std::vector::const_iterator i = commands.begin(); - i != commands.end(); ++i) { - this->State->AddCommand(*i); - } + GetProjectCommands(this->State); } void cmake::AddDefaultGenerators() https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=934ac7916e4e4df6ef55441d58fd1c310e4ad9f1 commit 934ac7916e4e4df6ef55441d58fd1c310e4ad9f1 Author: Daniel Pfeifer AuthorDate: Fri Jan 20 22:12:32 2017 +0100 Commit: Daniel Pfeifer CommitDate: Sat Feb 11 00:01:22 2017 +0100 split Default commands into Scripting and Project diff --git a/Help/manual/cmake-commands.7.rst b/Help/manual/cmake-commands.7.rst index d0c2986..8f019d2 100644 --- a/Help/manual/cmake-commands.7.rst +++ b/Help/manual/cmake-commands.7.rst @@ -7,91 +7,103 @@ cmake-commands(7) .. contents:: -Normal Commands -=============== +Scripting Commands +================== -These commands may be used freely in CMake projects. +These commands are always available. .. toctree:: :maxdepth: 1 - /command/add_compile_options - /command/add_custom_command - /command/add_custom_target - /command/add_definitions - /command/add_dependencies - /command/add_executable - /command/add_library - /command/add_subdirectory - /command/add_test - /command/aux_source_directory /command/break - /command/build_command /command/cmake_host_system_information /command/cmake_minimum_required /command/cmake_parse_arguments /command/cmake_policy /command/configure_file /command/continue - /command/create_test_sourcelist - /command/define_property /command/elseif /command/else - /command/enable_language - /command/enable_testing /command/endforeach /command/endfunction /command/endif /command/endmacro /command/endwhile /command/execute_process - /command/export /command/file /command/find_file /command/find_library /command/find_package /command/find_path /command/find_program - /command/fltk_wrap_ui /command/foreach /command/function /command/get_cmake_property /command/get_directory_property /command/get_filename_component /command/get_property + /command/if + /command/include + /command/list + /command/macro + /command/mark_as_advanced + /command/math + /command/message + /command/option + /command/return + /command/separate_arguments + /command/set_directory_properties + /command/set_property + /command/set + /command/site_name + /command/string + /command/unset + /command/variable_watch + /command/while + +Project Commands +================ + +These commands are available only in CMake projects. + +.. toctree:: + :maxdepth: 1 + + /command/add_compile_options + /command/add_custom_command + /command/add_custom_target + /command/add_definitions + /command/add_dependencies + /command/add_executable + /command/add_library + /command/add_subdirectory + /command/add_test + /command/aux_source_directory + /command/build_command + /command/create_test_sourcelist + /command/define_property + /command/enable_language + /command/enable_testing + /command/export + /command/fltk_wrap_ui /command/get_source_file_property /command/get_target_property /command/get_test_property - /command/if /command/include_directories /command/include_external_msproject /command/include_regular_expression - /command/include /command/install /command/link_directories /command/link_libraries - /command/list /command/load_cache - /command/macro - /command/mark_as_advanced - /command/math - /command/message - /command/option /command/project /command/qt_wrap_cpp /command/qt_wrap_ui /command/remove_definitions - /command/return - /command/separate_arguments - /command/set_directory_properties - /command/set_property - /command/set /command/set_source_files_properties /command/set_target_properties /command/set_tests_properties - /command/site_name /command/source_group - /command/string /command/target_compile_definitions /command/target_compile_features /command/target_compile_options @@ -100,9 +112,28 @@ These commands may be used freely in CMake projects. /command/target_sources /command/try_compile /command/try_run - /command/unset - /command/variable_watch - /command/while + +CTest Commands +============== + +These commands are available only in CTest scripts. + +.. toctree:: + :maxdepth: 1 + + /command/ctest_build + /command/ctest_configure + /command/ctest_coverage + /command/ctest_empty_binary_directory + /command/ctest_memcheck + /command/ctest_read_custom_files + /command/ctest_run_script + /command/ctest_sleep + /command/ctest_start + /command/ctest_submit + /command/ctest_test + /command/ctest_update + /command/ctest_upload Deprecated Commands =================== @@ -129,27 +160,3 @@ versions of CMake. Do not use them in new code. /command/utility_source /command/variable_requires /command/write_file - -.. _`CTest Commands`: - -CTest Commands -============== - -These commands are available only in ctest scripts. - -.. toctree:: - :maxdepth: 1 - - /command/ctest_build - /command/ctest_configure - /command/ctest_coverage - /command/ctest_empty_binary_directory - /command/ctest_memcheck - /command/ctest_read_custom_files - /command/ctest_run_script - /command/ctest_sleep - /command/ctest_start - /command/ctest_submit - /command/ctest_test - /command/ctest_update - /command/ctest_upload diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index f9e02cd..bc24234 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -105,28 +105,15 @@ #include "cmWriteFileCommand.h" #endif -std::vector GetPredefinedCommands() +std::vector GetScriptingCommands() { std::vector commands; - commands.push_back(new cmAddCustomCommandCommand); - commands.push_back(new cmAddCustomTargetCommand); - commands.push_back(new cmAddDefinitionsCommand); - commands.push_back(new cmAddDependenciesCommand); - commands.push_back(new cmAddExecutableCommand); - commands.push_back(new cmAddLibraryCommand); - commands.push_back(new cmAddSubDirectoryCommand); - commands.push_back(new cmAddTestCommand); commands.push_back(new cmBreakCommand); - commands.push_back(new cmBuildCommand); commands.push_back(new cmCMakeMinimumRequired); commands.push_back(new cmCMakePolicyCommand); commands.push_back(new cmConfigureFileCommand); commands.push_back(new cmContinueCommand); - commands.push_back(new cmCreateTestSourceList); - commands.push_back(new cmDefinePropertyCommand); - commands.push_back(new cmEnableLanguageCommand); - commands.push_back(new cmEnableTestingCommand); commands.push_back(new cmExecProgramCommand); commands.push_back(new cmExecuteProcessCommand); commands.push_back(new cmFileCommand); @@ -141,17 +128,8 @@ std::vector GetPredefinedCommands() commands.push_back(new cmGetDirectoryPropertyCommand); commands.push_back(new cmGetFilenameComponentCommand); commands.push_back(new cmGetPropertyCommand); - commands.push_back(new cmGetSourceFilePropertyCommand); - commands.push_back(new cmGetTargetPropertyCommand); - commands.push_back(new cmGetTestPropertyCommand); commands.push_back(new cmIfCommand); commands.push_back(new cmIncludeCommand); - commands.push_back(new cmIncludeDirectoryCommand); - commands.push_back(new cmIncludeRegularExpressionCommand); - commands.push_back(new cmInstallCommand); - commands.push_back(new cmInstallFilesCommand); - commands.push_back(new cmInstallTargetsCommand); - commands.push_back(new cmLinkDirectoriesCommand); commands.push_back(new cmListCommand); commands.push_back(new cmMacroCommand); commands.push_back(new cmMakeDirectoryCommand); @@ -160,21 +138,13 @@ std::vector GetPredefinedCommands() commands.push_back(new cmMessageCommand); commands.push_back(new cmOptionCommand); commands.push_back(new cmParseArgumentsCommand); - commands.push_back(new cmProjectCommand); commands.push_back(new cmReturnCommand); commands.push_back(new cmSeparateArgumentsCommand); commands.push_back(new cmSetCommand); commands.push_back(new cmSetDirectoryPropertiesCommand); commands.push_back(new cmSetPropertyCommand); - commands.push_back(new cmSetSourceFilesPropertiesCommand); - commands.push_back(new cmSetTargetPropertiesCommand); - commands.push_back(new cmSetTestsPropertiesCommand); commands.push_back(new cmSiteNameCommand); commands.push_back(new cmStringCommand); - commands.push_back(new cmSubdirCommand); - commands.push_back(new cmTargetLinkLibrariesCommand); - commands.push_back(new cmTryCompileCommand); - commands.push_back(new cmTryRunCommand); commands.push_back(new cmUnsetCommand); commands.push_back(new cmWhileCommand); @@ -207,9 +177,61 @@ std::vector GetPredefinedCommands() "match the opening WHILE command.")); #if defined(CMAKE_BUILD_WITH_CMAKE) + commands.push_back(new cmCMakeHostSystemInformationCommand); + commands.push_back(new cmRemoveCommand); + commands.push_back(new cmVariableWatchCommand); + commands.push_back(new cmWriteFileCommand); + + commands.push_back(new cmDeprecatedCommand( + new cmBuildNameCommand, cmPolicies::CMP0036, + "The build_name command should not be called; see CMP0036.")); + commands.push_back(new cmDeprecatedCommand( + new cmUseMangledMesaCommand, cmPolicies::CMP0030, + "The use_mangled_mesa command should not be called; see CMP0030.")); + +#endif + + return commands; +} + +std::vector GetProjectCommands() +{ + std::vector commands; + + commands.push_back(new cmAddCustomCommandCommand); + commands.push_back(new cmAddCustomTargetCommand); + commands.push_back(new cmAddDefinitionsCommand); + commands.push_back(new cmAddDependenciesCommand); + commands.push_back(new cmAddExecutableCommand); + commands.push_back(new cmAddLibraryCommand); + commands.push_back(new cmAddSubDirectoryCommand); + commands.push_back(new cmAddTestCommand); + commands.push_back(new cmBuildCommand); + commands.push_back(new cmCreateTestSourceList); + commands.push_back(new cmDefinePropertyCommand); + commands.push_back(new cmEnableLanguageCommand); + commands.push_back(new cmEnableTestingCommand); + commands.push_back(new cmGetSourceFilePropertyCommand); + commands.push_back(new cmGetTargetPropertyCommand); + commands.push_back(new cmGetTestPropertyCommand); + commands.push_back(new cmIncludeDirectoryCommand); + commands.push_back(new cmIncludeRegularExpressionCommand); + commands.push_back(new cmInstallCommand); + commands.push_back(new cmInstallFilesCommand); + commands.push_back(new cmInstallTargetsCommand); + commands.push_back(new cmLinkDirectoriesCommand); + commands.push_back(new cmProjectCommand); + commands.push_back(new cmSetSourceFilesPropertiesCommand); + commands.push_back(new cmSetTargetPropertiesCommand); + commands.push_back(new cmSetTestsPropertiesCommand); + commands.push_back(new cmSubdirCommand); + commands.push_back(new cmTargetLinkLibrariesCommand); + commands.push_back(new cmTryCompileCommand); + commands.push_back(new cmTryRunCommand); + +#if defined(CMAKE_BUILD_WITH_CMAKE) commands.push_back(new cmAddCompileOptionsCommand); commands.push_back(new cmAuxSourceDirectoryCommand); - commands.push_back(new cmCMakeHostSystemInformationCommand); commands.push_back(new cmExportCommand); commands.push_back(new cmFLTKWrapUICommand); commands.push_back(new cmIncludeExternalMSProjectCommand); @@ -218,7 +240,6 @@ std::vector GetPredefinedCommands() commands.push_back(new cmLoadCacheCommand); commands.push_back(new cmQTWrapCPPCommand); commands.push_back(new cmQTWrapUICommand); - commands.push_back(new cmRemoveCommand); commands.push_back(new cmRemoveDefinitionsCommand); commands.push_back(new cmSourceGroupCommand); commands.push_back(new cmTargetCompileDefinitionsCommand); @@ -226,13 +247,8 @@ std::vector GetPredefinedCommands() commands.push_back(new cmTargetCompileOptionsCommand); commands.push_back(new cmTargetIncludeDirectoriesCommand); commands.push_back(new cmTargetSourcesCommand); - commands.push_back(new cmVariableWatchCommand); - commands.push_back(new cmWriteFileCommand); commands.push_back(new cmDeprecatedCommand( - new cmBuildNameCommand, cmPolicies::CMP0036, - "The build_name command should not be called; see CMP0036.")); - commands.push_back(new cmDeprecatedCommand( new cmExportLibraryDependenciesCommand, cmPolicies::CMP0033, "The export_library_dependencies command should not be called; " "see CMP0033.")); @@ -247,9 +263,6 @@ std::vector GetPredefinedCommands() new cmSubdirDependsCommand, cmPolicies::CMP0029, "The subdir_depends command should not be called; see CMP0029.")); commands.push_back(new cmDeprecatedCommand( - new cmUseMangledMesaCommand, cmPolicies::CMP0030, - "The use_mangled_mesa command should not be called; see CMP0030.")); - commands.push_back(new cmDeprecatedCommand( new cmUtilitySourceCommand, cmPolicies::CMP0034, "The utility_source command should not be called; see CMP0034.")); commands.push_back(new cmDeprecatedCommand( diff --git a/Source/cmCommands.h b/Source/cmCommands.h index 649dea6..4d09e42 100644 --- a/Source/cmCommands.h +++ b/Source/cmCommands.h @@ -13,6 +13,7 @@ class cmCommand; * To add a new command edit cmCommands.cxx and add your command. * It is up to the caller to delete the commands created by this call. */ -std::vector GetPredefinedCommands(); +std::vector GetScriptingCommands(); +std::vector GetProjectCommands(); #endif diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 6141f50..c6292ce 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -179,7 +179,8 @@ cmake::cmake() this->AddDefaultGenerators(); this->AddDefaultExtraGenerators(); - this->AddDefaultCommands(); + this->AddScriptingCommands(); + this->AddProjectCommands(); // Make sure we can capture the build tool output. cmSystemTools::EnableVSConsoleOutput(); @@ -1654,9 +1655,18 @@ const char* cmake::GetCacheDefinition(const std::string& name) const return this->State->GetInitializedCacheValue(name); } -void cmake::AddDefaultCommands() +void cmake::AddScriptingCommands() { - std::vector const commands = GetPredefinedCommands(); + std::vector const commands = GetScriptingCommands(); + for (std::vector::const_iterator i = commands.begin(); + i != commands.end(); ++i) { + this->State->AddCommand(*i); + } +} + +void cmake::AddProjectCommands() +{ + std::vector const commands = GetProjectCommands(); for (std::vector::const_iterator i = commands.begin(); i != commands.end(); ++i) { this->State->AddCommand(*i); diff --git a/Source/cmake.h b/Source/cmake.h index 5347745..abb13ac 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -425,7 +425,8 @@ protected: typedef std::vector RegisteredExtraGeneratorsVector; RegisteredExtraGeneratorsVector ExtraGenerators; - void AddDefaultCommands(); + void AddScriptingCommands(); + void AddProjectCommands(); void AddDefaultGenerators(); void AddDefaultExtraGenerators(); https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=717491dd7d4a886d484025fd9002df44458117b5 commit 717491dd7d4a886d484025fd9002df44458117b5 Author: Daniel Pfeifer AuthorDate: Mon Dec 26 00:34:44 2016 +0100 Commit: Daniel Pfeifer CommitDate: Sat Feb 11 00:01:22 2017 +0100 cmDeprecatedCommand: extract policy checking from cmCommand Implement cmDeprecatedCommand as a wrapper class for cmCommand. diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 2835ee6..3b05f4c 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -440,6 +440,8 @@ set(SRCS cmCreateTestSourceList.h cmDefinePropertyCommand.cxx cmDefinePropertyCommand.h + cmDeprecatedCommand.cxx + cmDeprecatedCommand.h cmEnableLanguageCommand.cxx cmEnableLanguageCommand.h cmEnableTestingCommand.cxx diff --git a/Source/cmBuildNameCommand.cxx b/Source/cmBuildNameCommand.cxx index 1e1cd21..12b69a8 100644 --- a/Source/cmBuildNameCommand.cxx +++ b/Source/cmBuildNameCommand.cxx @@ -16,11 +16,6 @@ class cmExecutionStatus; bool cmBuildNameCommand::InitialPass(std::vector const& args, cmExecutionStatus&) { - if (this->Disallowed( - cmPolicies::CMP0036, - "The build_name command should not be called; see CMP0036.")) { - return true; - } if (args.empty()) { this->SetError("called with incorrect number of arguments"); return false; diff --git a/Source/cmCommand.cxx b/Source/cmCommand.cxx index 15bed27..d349c91 100644 --- a/Source/cmCommand.cxx +++ b/Source/cmCommand.cxx @@ -3,7 +3,6 @@ #include "cmCommand.h" #include "cmMakefile.h" -#include "cmake.h" class cmExecutionStatus; struct cmListFileArgument; @@ -32,20 +31,3 @@ void cmCommand::SetError(const std::string& e) { this->Error = e; } - -bool cmCommand::Disallowed(cmPolicies::PolicyID pol, const char* e) -{ - switch (this->Makefile->GetPolicyStatus(pol)) { - case cmPolicies::WARN: - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, - cmPolicies::GetPolicyWarning(pol)); - case cmPolicies::OLD: - return false; - case cmPolicies::REQUIRED_IF_USED: - case cmPolicies::REQUIRED_ALWAYS: - case cmPolicies::NEW: - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e); - break; - } - return true; -} diff --git a/Source/cmCommand.h b/Source/cmCommand.h index 32f4472..9107d85 100644 --- a/Source/cmCommand.h +++ b/Source/cmCommand.h @@ -7,8 +7,6 @@ #include #include -#include "cmPolicies.h" - class cmExecutionStatus; class cmMakefile; struct cmListFileArgument; @@ -104,9 +102,6 @@ public: */ void SetError(const std::string& e); - /** Check if the command is disallowed by a policy. */ - bool Disallowed(cmPolicies::PolicyID pol, const char* e); - private: cmCommand(cmCommand const&); // = delete; cmCommand& operator=(cmCommand const&); // = delete; diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index 4c5b093..f9e02cd 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -77,6 +77,7 @@ #include "cmAuxSourceDirectoryCommand.h" #include "cmBuildNameCommand.h" #include "cmCMakeHostSystemInformationCommand.h" +#include "cmDeprecatedCommand.h" #include "cmExportCommand.h" #include "cmExportLibraryDependenciesCommand.h" #include "cmFLTKWrapUICommand.h" @@ -208,33 +209,52 @@ std::vector GetPredefinedCommands() #if defined(CMAKE_BUILD_WITH_CMAKE) commands.push_back(new cmAddCompileOptionsCommand); commands.push_back(new cmAuxSourceDirectoryCommand); - commands.push_back(new cmBuildNameCommand); commands.push_back(new cmCMakeHostSystemInformationCommand); commands.push_back(new cmExportCommand); - commands.push_back(new cmExportLibraryDependenciesCommand); commands.push_back(new cmFLTKWrapUICommand); commands.push_back(new cmIncludeExternalMSProjectCommand); commands.push_back(new cmInstallProgramsCommand); commands.push_back(new cmLinkLibrariesCommand); commands.push_back(new cmLoadCacheCommand); - commands.push_back(new cmLoadCommandCommand); - commands.push_back(new cmOutputRequiredFilesCommand); commands.push_back(new cmQTWrapCPPCommand); commands.push_back(new cmQTWrapUICommand); commands.push_back(new cmRemoveCommand); commands.push_back(new cmRemoveDefinitionsCommand); commands.push_back(new cmSourceGroupCommand); - commands.push_back(new cmSubdirDependsCommand); commands.push_back(new cmTargetCompileDefinitionsCommand); commands.push_back(new cmTargetCompileFeaturesCommand); commands.push_back(new cmTargetCompileOptionsCommand); commands.push_back(new cmTargetIncludeDirectoriesCommand); commands.push_back(new cmTargetSourcesCommand); - commands.push_back(new cmUseMangledMesaCommand); - commands.push_back(new cmUtilitySourceCommand); - commands.push_back(new cmVariableRequiresCommand); commands.push_back(new cmVariableWatchCommand); commands.push_back(new cmWriteFileCommand); + + commands.push_back(new cmDeprecatedCommand( + new cmBuildNameCommand, cmPolicies::CMP0036, + "The build_name command should not be called; see CMP0036.")); + commands.push_back(new cmDeprecatedCommand( + new cmExportLibraryDependenciesCommand, cmPolicies::CMP0033, + "The export_library_dependencies command should not be called; " + "see CMP0033.")); + commands.push_back(new cmDeprecatedCommand( + new cmLoadCommandCommand, cmPolicies::CMP0031, + "The load_command command should not be called; see CMP0031.")); + commands.push_back(new cmDeprecatedCommand( + new cmOutputRequiredFilesCommand, cmPolicies::CMP0032, + "The output_required_files command should not be called; " + "see CMP0032.")); + commands.push_back(new cmDeprecatedCommand( + new cmSubdirDependsCommand, cmPolicies::CMP0029, + "The subdir_depends command should not be called; see CMP0029.")); + commands.push_back(new cmDeprecatedCommand( + new cmUseMangledMesaCommand, cmPolicies::CMP0030, + "The use_mangled_mesa command should not be called; see CMP0030.")); + commands.push_back(new cmDeprecatedCommand( + new cmUtilitySourceCommand, cmPolicies::CMP0034, + "The utility_source command should not be called; see CMP0034.")); + commands.push_back(new cmDeprecatedCommand( + new cmVariableRequiresCommand, cmPolicies::CMP0035, + "The variable_requires command should not be called; see CMP0035.")); #endif return commands; diff --git a/Source/cmDeprecatedCommand.cxx b/Source/cmDeprecatedCommand.cxx new file mode 100644 index 0000000..cd0c7ab --- /dev/null +++ b/Source/cmDeprecatedCommand.cxx @@ -0,0 +1,31 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmDeprecatedCommand.h" + +#include "cmMakefile.h" +#include "cmake.h" + +class cmExecutionStatus; + +bool cmDeprecatedCommand::InitialPass(std::vector const& args, + cmExecutionStatus& status) +{ + switch (this->Makefile->GetPolicyStatus(this->Policy)) { + case cmPolicies::WARN: + this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, + cmPolicies::GetPolicyWarning(this->Policy)); + break; + case cmPolicies::OLD: + break; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + this->Makefile->IssueMessage(cmake::FATAL_ERROR, this->Message); + return true; + } + + this->Command->SetMakefile(this->GetMakefile()); + bool const ret = this->Command->InitialPass(args, status); + this->SetError(this->Command->GetError()); + return ret; +} diff --git a/Source/cmDeprecatedCommand.h b/Source/cmDeprecatedCommand.h new file mode 100644 index 0000000..7424fbc --- /dev/null +++ b/Source/cmDeprecatedCommand.h @@ -0,0 +1,50 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmDeprecatedCommand_h +#define cmDeprecatedCommand_h + +#include +#include +#include + +#include "cmCommand.h" +#include "cmPolicies.h" + +class cmExecutionStatus; + +class cmDeprecatedCommand : public cmCommand +{ +public: + cmDeprecatedCommand(cmCommand* command, cmPolicies::PolicyID policy, + const char* message) + : Command(command) + , Policy(policy) + , Message(message) + { + } + + ~cmDeprecatedCommand() { delete this->Command; } + + cmCommand* Clone() CM_OVERRIDE + { + return new cmDeprecatedCommand(this->Command->Clone(), this->Policy, + this->Message); + } + + bool InitialPass(std::vector const& args, + cmExecutionStatus& status) CM_OVERRIDE; + + bool IsScriptable() const CM_OVERRIDE + { + return this->Command->IsScriptable(); + } + + std::string GetName() const CM_OVERRIDE { return this->Command->GetName(); } + +private: + cmCommand* Command; + cmPolicies::PolicyID Policy; + const char* Message; +}; + +#endif diff --git a/Source/cmExportLibraryDependenciesCommand.cxx b/Source/cmExportLibraryDependenciesCommand.cxx index ac4f040..e3fb412 100644 --- a/Source/cmExportLibraryDependenciesCommand.cxx +++ b/Source/cmExportLibraryDependenciesCommand.cxx @@ -23,12 +23,6 @@ class cmExecutionStatus; bool cmExportLibraryDependenciesCommand::InitialPass( std::vector const& args, cmExecutionStatus&) { - if (this->Disallowed( - cmPolicies::CMP0033, - "The export_library_dependencies command should not be called; " - "see CMP0033.")) { - return true; - } if (args.empty()) { this->SetError("called with incorrect number of arguments"); return false; diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx index b6743f1..39e5684 100644 --- a/Source/cmLoadCommandCommand.cxx +++ b/Source/cmLoadCommandCommand.cxx @@ -174,11 +174,6 @@ cmLoadedCommand::~cmLoadedCommand() bool cmLoadCommandCommand::InitialPass(std::vector const& args, cmExecutionStatus&) { - if (this->Disallowed( - cmPolicies::CMP0031, - "The load_command command should not be called; see CMP0031.")) { - return true; - } if (args.empty()) { return true; } diff --git a/Source/cmOutputRequiredFilesCommand.cxx b/Source/cmOutputRequiredFilesCommand.cxx index 7a17f2c..f120971 100644 --- a/Source/cmOutputRequiredFilesCommand.cxx +++ b/Source/cmOutputRequiredFilesCommand.cxx @@ -495,11 +495,6 @@ protected: bool cmOutputRequiredFilesCommand::InitialPass( std::vector const& args, cmExecutionStatus&) { - if (this->Disallowed(cmPolicies::CMP0032, "The output_required_files " - "command should not be called; " - "see CMP0032.")) { - return true; - } if (args.size() != 2) { this->SetError("called with incorrect number of arguments"); return false; diff --git a/Source/cmSubdirDependsCommand.cxx b/Source/cmSubdirDependsCommand.cxx index 9259836..36e84d5 100644 --- a/Source/cmSubdirDependsCommand.cxx +++ b/Source/cmSubdirDependsCommand.cxx @@ -9,8 +9,5 @@ class cmExecutionStatus; bool cmSubdirDependsCommand::InitialPass(std::vector const&, cmExecutionStatus&) { - this->Disallowed( - cmPolicies::CMP0029, - "The subdir_depends command should not be called; see CMP0029."); return true; } diff --git a/Source/cmUseMangledMesaCommand.cxx b/Source/cmUseMangledMesaCommand.cxx index 3e72d75..3d57f0e 100644 --- a/Source/cmUseMangledMesaCommand.cxx +++ b/Source/cmUseMangledMesaCommand.cxx @@ -13,11 +13,6 @@ class cmExecutionStatus; bool cmUseMangledMesaCommand::InitialPass(std::vector const& args, cmExecutionStatus&) { - if (this->Disallowed( - cmPolicies::CMP0030, - "The use_mangled_mesa command should not be called; see CMP0030.")) { - return true; - } // expected two arguments: // arguement one: the full path to gl_mangle.h // arguement two : directory for output of edited headers diff --git a/Source/cmUtilitySourceCommand.cxx b/Source/cmUtilitySourceCommand.cxx index 3b78abe..9b24a74 100644 --- a/Source/cmUtilitySourceCommand.cxx +++ b/Source/cmUtilitySourceCommand.cxx @@ -16,11 +16,6 @@ class cmExecutionStatus; bool cmUtilitySourceCommand::InitialPass(std::vector const& args, cmExecutionStatus&) { - if (this->Disallowed( - cmPolicies::CMP0034, - "The utility_source command should not be called; see CMP0034.")) { - return true; - } if (args.size() < 3) { this->SetError("called with incorrect number of arguments"); return false; diff --git a/Source/cmVariableRequiresCommand.cxx b/Source/cmVariableRequiresCommand.cxx index 1eb1f20..bff6ec5 100644 --- a/Source/cmVariableRequiresCommand.cxx +++ b/Source/cmVariableRequiresCommand.cxx @@ -13,11 +13,6 @@ class cmExecutionStatus; bool cmVariableRequiresCommand::InitialPass( std::vector const& args, cmExecutionStatus&) { - if (this->Disallowed( - cmPolicies::CMP0035, - "The variable_requires command should not be called; see CMP0035.")) { - return true; - } if (args.size() < 3) { this->SetError("called with incorrect number of arguments"); return false; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b75e7691425d4cb658f3b0981fdbfbc25dedfb43 commit b75e7691425d4cb658f3b0981fdbfbc25dedfb43 Author: Daniel Pfeifer AuthorDate: Sat Jan 7 13:48:44 2017 +0100 Commit: Daniel Pfeifer CommitDate: Sat Feb 11 00:01:22 2017 +0100 cmCommand: Don't prefix error message with command name Instead, prefix the error message at the two places where the errors are handled: cmMakefile and cmCTestHandlerCommand. diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx index a989b12..2a67d47 100644 --- a/Source/CTest/cmCTestHandlerCommand.cxx +++ b/Source/CTest/cmCTestHandlerCommand.cxx @@ -123,8 +123,8 @@ bool cmCTestHandlerCommand::InitialPass(std::vector const& args, if (capureCMakeError) { this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR], "-1"); - const char* err = this->GetError(); - if (err && !cmSystemTools::FindLastString(err, "unknown error.")) { + std::string const err = this->GetName() + " " + this->GetError(); + if (!cmSystemTools::FindLastString(err.c_str(), "unknown error.")) { cmCTestLog(this->CTest, ERROR_MESSAGE, err << " error from command\n"); } // return success because failure is recorded in CAPTURE_CMAKE_ERROR diff --git a/Source/cmCommand.cxx b/Source/cmCommand.cxx index 181b412..15bed27 100644 --- a/Source/cmCommand.cxx +++ b/Source/cmCommand.cxx @@ -23,17 +23,14 @@ bool cmCommand::InvokeInitialPass(const std::vector& args, const char* cmCommand::GetError() { if (this->Error.empty()) { - this->Error = this->GetName(); - this->Error += " unknown error."; + return "unknown error."; } return this->Error.c_str(); } void cmCommand::SetError(const std::string& e) { - this->Error = this->GetName(); - this->Error += " "; - this->Error += e; + this->Error = e; } bool cmCommand::Disallowed(cmPolicies::PolicyID pol, const char* e) diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index bfe46ae..4520c8e 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -281,7 +281,8 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff, if (!invokeSucceeded || hadNestedError) { if (!hadNestedError) { // The command invocation requested that we report an error. - this->IssueMessage(cmake::FATAL_ERROR, pcmd->GetError()); + std::string const error = name + " " + pcmd->GetError(); + this->IssueMessage(cmake::FATAL_ERROR, error.c_str()); } result = false; if (this->GetCMakeInstance()->GetWorkingMode() != cmake::NORMAL_MODE) { https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=17926f29cecc7574c9173ff06f5e3d0e4e250b02 commit 17926f29cecc7574c9173ff06f5e3d0e4e250b02 Author: Daniel Pfeifer AuthorDate: Sun Dec 25 23:50:18 2016 +0100 Commit: Daniel Pfeifer CommitDate: Sat Feb 11 00:01:22 2017 +0100 cmCommand: make noncopyable diff --git a/Source/cmCommand.h b/Source/cmCommand.h index ff30638..32f4472 100644 --- a/Source/cmCommand.h +++ b/Source/cmCommand.h @@ -107,6 +107,10 @@ public: /** Check if the command is disallowed by a policy. */ bool Disallowed(cmPolicies::PolicyID pol, const char* e); +private: + cmCommand(cmCommand const&); // = delete; + cmCommand& operator=(cmCommand const&); // = delete; + protected: cmMakefile* Makefile; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c1bfff2e72bd673e7b7bebddf58c7ea508bf4196 commit c1bfff2e72bd673e7b7bebddf58c7ea508bf4196 Author: Daniel Pfeifer AuthorDate: Sun Dec 25 23:27:48 2016 +0100 Commit: Daniel Pfeifer CommitDate: Sat Feb 11 00:01:22 2017 +0100 cmCommand: remove member Helper The Helper member is used in a single derived class only. Remove it from the base class to the only place where it is used. diff --git a/Source/cmCommand.h b/Source/cmCommand.h index d9fd5a2..ff30638 100644 --- a/Source/cmCommand.h +++ b/Source/cmCommand.h @@ -7,7 +7,6 @@ #include #include -#include "cmCommandArgumentsHelper.h" #include "cmPolicies.h" class cmExecutionStatus; @@ -110,7 +109,6 @@ public: protected: cmMakefile* Makefile; - cmCommandArgumentsHelper Helper; private: std::string Error; diff --git a/Source/cmExportCommand.h b/Source/cmExportCommand.h index 99dac7d..a0224d0 100644 --- a/Source/cmExportCommand.h +++ b/Source/cmExportCommand.h @@ -41,6 +41,7 @@ public: std::string GetName() const CM_OVERRIDE { return "export"; } private: + cmCommandArgumentsHelper Helper; cmCommandArgumentGroup ArgumentGroup; cmCAStringVector Targets; cmCAEnabler Append; ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-commands.7.rst | 131 ++++++------- Source/CMakeLists.txt | 2 + Source/CTest/cmCTestHandlerCommand.cxx | 4 +- Source/cmBuildNameCommand.cxx | 5 - Source/cmCommand.cxx | 25 +-- Source/cmCommand.h | 9 +- Source/cmCommands.cxx | 242 ++++++++++++++----------- Source/cmCommands.h | 10 +- Source/cmDeprecatedCommand.cxx | 31 ++++ Source/cmDeprecatedCommand.h | 50 +++++ Source/cmExportCommand.h | 1 + Source/cmExportLibraryDependenciesCommand.cxx | 6 - Source/cmLoadCommandCommand.cxx | 5 - Source/cmMakefile.cxx | 3 +- Source/cmOutputRequiredFilesCommand.cxx | 5 - Source/cmSubdirDependsCommand.cxx | 3 - Source/cmUseMangledMesaCommand.cxx | 5 - Source/cmUtilitySourceCommand.cxx | 5 - Source/cmVariableRequiresCommand.cxx | 5 - Source/cmake.cxx | 18 +- Source/cmake.h | 3 +- 21 files changed, 311 insertions(+), 257 deletions(-) create mode 100644 Source/cmDeprecatedCommand.cxx create mode 100644 Source/cmDeprecatedCommand.h hooks/post-receive -- CMake From kwrobot at kitware.com Sat Feb 11 00:01:11 2017 From: kwrobot at kitware.com (Kitware Robot) Date: Sat, 11 Feb 2017 00:01:11 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-41-g6c8d659 Message-ID: <20170211050112.0A3A7FA2F0@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 6c8d65963104451b15aa331a6914173af42a224c (commit) from ee3295e91740033ebe9d9a0c800c0a3070108624 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6c8d65963104451b15aa331a6914173af42a224c commit 6c8d65963104451b15aa331a6914173af42a224c Author: Kitware Robot AuthorDate: Sat Feb 11 00:01:08 2017 -0500 Commit: Kitware Robot CommitDate: Sat Feb 11 00:01:08 2017 -0500 CMake Nightly Date Stamp diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 070abf8..78cee13 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 8) -set(CMake_VERSION_PATCH 20170210) +set(CMake_VERSION_PATCH 20170211) #set(CMake_VERSION_RC 1) ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From daniel at pfeifer-mail.de Sat Feb 11 16:10:17 2017 From: daniel at pfeifer-mail.de (Daniel Pfeifer) Date: Sat, 11 Feb 2017 16:10:17 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-92-g9862605 Message-ID: <20170211211017.69DBE1DC4@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 9862605636abde65ca8e651d42b3d706beeaaecc (commit) via a45a5847e096e7f077acb0a4fde44bda9225fbc4 (commit) from 4c53c29d86e7dc4c580fb5b7c8f06551934ae03c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9862605636abde65ca8e651d42b3d706beeaaecc commit 9862605636abde65ca8e651d42b3d706beeaaecc Merge: 4c53c29 a45a584 Author: Daniel Pfeifer AuthorDate: Sat Feb 11 16:10:16 2017 -0500 Commit: CMake Topic Stage CommitDate: Sat Feb 11 16:10:16 2017 -0500 Merge topic 'command-cleanup' into next a45a5847 fixup! split Default commands into Scripting and Project https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a45a5847e096e7f077acb0a4fde44bda9225fbc4 commit a45a5847e096e7f077acb0a4fde44bda9225fbc4 Author: Daniel Pfeifer AuthorDate: Sat Feb 11 22:09:37 2017 +0100 Commit: Daniel Pfeifer CommitDate: Sat Feb 11 22:09:37 2017 +0100 fixup! split Default commands into Scripting and Project diff --git a/Help/manual/cmake-commands.7.rst b/Help/manual/cmake-commands.7.rst index 8f019d2..611c989 100644 --- a/Help/manual/cmake-commands.7.rst +++ b/Help/manual/cmake-commands.7.rst @@ -113,6 +113,8 @@ These commands are available only in CMake projects. /command/try_compile /command/try_run +.. _`CTest Commands`: + CTest Commands ============== ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-commands.7.rst | 2 ++ 1 file changed, 2 insertions(+) hooks/post-receive -- CMake From kwrobot at kitware.com Sun Feb 12 00:01:10 2017 From: kwrobot at kitware.com (Kitware Robot) Date: Sun, 12 Feb 2017 00:01:10 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-42-g26662fc Message-ID: <20170212050110.6E214FA360@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 26662fc3d38f93b5aaebdcb59d8937f9661020f9 (commit) from 6c8d65963104451b15aa331a6914173af42a224c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=26662fc3d38f93b5aaebdcb59d8937f9661020f9 commit 26662fc3d38f93b5aaebdcb59d8937f9661020f9 Author: Kitware Robot AuthorDate: Sun Feb 12 00:01:04 2017 -0500 Commit: Kitware Robot CommitDate: Sun Feb 12 00:01:04 2017 -0500 CMake Nightly Date Stamp diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 78cee13..6912c4c 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 8) -set(CMake_VERSION_PATCH 20170211) +set(CMake_VERSION_PATCH 20170212) #set(CMake_VERSION_RC 1) ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From kwrobot at kitware.com Mon Feb 13 00:01:08 2017 From: kwrobot at kitware.com (Kitware Robot) Date: Mon, 13 Feb 2017 00:01:08 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-43-g0cab748 Message-ID: <20170213050108.293DDF9FF4@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 0cab748cf84a844df36623f03c5ed7b8065ceb5a (commit) from 26662fc3d38f93b5aaebdcb59d8937f9661020f9 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0cab748cf84a844df36623f03c5ed7b8065ceb5a commit 0cab748cf84a844df36623f03c5ed7b8065ceb5a Author: Kitware Robot AuthorDate: Mon Feb 13 00:01:04 2017 -0500 Commit: Kitware Robot CommitDate: Mon Feb 13 00:01:04 2017 -0500 CMake Nightly Date Stamp diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 6912c4c..bb79b6d 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 8) -set(CMake_VERSION_PATCH 20170212) +set(CMake_VERSION_PATCH 20170213) #set(CMake_VERSION_RC 1) ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 13 11:12:36 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 13 Feb 2017 11:12:36 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-94-ge8d7474 Message-ID: <20170213161236.CB68EF4E53@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via e8d7474006657657f4fc66b48d98b6e1c80fce03 (commit) via e1b5a54d1da318510445fe1fcc969018e1a6b6dd (commit) from 9862605636abde65ca8e651d42b3d706beeaaecc (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e8d7474006657657f4fc66b48d98b6e1c80fce03 commit e8d7474006657657f4fc66b48d98b6e1c80fce03 Merge: 9862605 e1b5a54 Author: Brad King AuthorDate: Mon Feb 13 11:12:35 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 13 11:12:35 2017 -0500 Merge topic 'update-kwsys' into next e1b5a54d Revert topic 'update-kwsys' https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e1b5a54d1da318510445fe1fcc969018e1a6b6dd commit e1b5a54d1da318510445fe1fcc969018e1a6b6dd Author: Brad King AuthorDate: Mon Feb 13 11:11:54 2017 -0500 Commit: Brad King CommitDate: Mon Feb 13 11:11:54 2017 -0500 Revert topic 'update-kwsys' It introduces warnings that need to be fixed upstream first. diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx index fc1a752..e01dcd7 100644 --- a/Source/kwsys/SystemInformation.cxx +++ b/Source/kwsys/SystemInformation.cxx @@ -35,13 +35,8 @@ #include "SystemInformation.hxx.in" #endif -#include -#include -#include #include #include -#include -#include #include #include #include @@ -399,6 +394,7 @@ public: bool SupportsMP; bool HasMMXPlus; bool HasSSEMMX; + bool SupportsHyperthreading; unsigned int LogicalProcessorsPerPhysical; int APIC_ID; CPUPowerManagement PowerManagement; @@ -467,9 +463,10 @@ protected: unsigned int NumberOfLogicalCPU; unsigned int NumberOfPhysicalCPU; - void CPUCountWindows(); // For windows + int CPUCount(); // For windows + unsigned char LogicalCPUPerPhysicalCPU(); unsigned char GetAPICId(); // For windows - bool IsSMTSupported(); + bool IsHyperThreadingSupported(); static LongLong GetCyclesDifference(DELAY_FUNC, unsigned int); // For windows // For Linux and Cygwin, /proc/cpuinfo formats are slightly different @@ -1545,7 +1542,7 @@ void SystemInformationImplementation::RunCPUCheck() RetrieveProcessorSerialNumber(); } - this->CPUCountWindows(); + this->CPUCount(); #elif defined(__APPLE__) this->ParseSysCtl(); @@ -2093,10 +2090,16 @@ bool SystemInformationImplementation::RetrieveCPUFeatures() // Retrieve Intel specific extended features. if (this->ChipManufacturer == Intel) { - bool SupportsSMT = - ((cpuinfo[3] & 0x10000000) != 0); // Intel specific: SMT --> Bit 28 - - if ((SupportsSMT) && (this->Features.HasAPIC)) { + this->Features.ExtendedFeatures.SupportsHyperthreading = + ((cpuinfo[3] & 0x10000000) != + 0); // Intel specific: Hyperthreading --> Bit 28 + this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = + (this->Features.ExtendedFeatures.SupportsHyperthreading) + ? ((cpuinfo[1] & 0x00FF0000) >> 16) + : 1; + + if ((this->Features.ExtendedFeatures.SupportsHyperthreading) && + (this->Features.HasAPIC)) { // Retrieve APIC information if there is one present. this->Features.ExtendedFeatures.APIC_ID = ((cpuinfo[1] & 0xFF000000) >> 24); @@ -3398,7 +3401,7 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() fclose(fd); buffer.resize(fileSize - 2); // Number of logical CPUs (combination of multiple processors, multi-core - // and SMT) + // and hyperthreading) size_t pos = buffer.find("processor\t"); while (pos != buffer.npos) { this->NumberOfLogicalCPU++; @@ -3406,24 +3409,30 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() } #ifdef __linux - // Count sockets. - std::set PhysicalIDs; + // Find the largest physical id. + int maxId = -1; std::string idc = this->ExtractValueFromCpuInfoFile(buffer, "physical id"); while (this->CurrentPositionInFile != buffer.npos) { int id = atoi(idc.c_str()); - PhysicalIDs.insert(id); + if (id > maxId) { + maxId = id; + } idc = this->ExtractValueFromCpuInfoFile(buffer, "physical id", this->CurrentPositionInFile + 1); } - uint64_t NumberOfSockets = PhysicalIDs.size(); - NumberOfSockets = std::max(NumberOfSockets, (uint64_t)1); // Physical ids returned by Linux don't distinguish cores. // We want to record the total number of cores in this->NumberOfPhysicalCPU // (checking only the first proc) - std::string Cores = this->ExtractValueFromCpuInfoFile(buffer, "cpu cores"); - int NumberOfCoresPerSocket = atoi(Cores.c_str()); - NumberOfCoresPerSocket = std::max(NumberOfCoresPerSocket, 1); - this->NumberOfPhysicalCPU = NumberOfCoresPerSocket * NumberOfSockets; + std::string cores = this->ExtractValueFromCpuInfoFile(buffer, "cpu cores"); + int numberOfCoresPerCPU = atoi(cores.c_str()); + if (maxId > 0) { + this->NumberOfPhysicalCPU = + static_cast(numberOfCoresPerCPU * (maxId + 1)); + } else { + // Linux Sparc: get cpu count + this->NumberOfPhysicalCPU = + atoi(this->ExtractValueFromCpuInfoFile(buffer, "ncpus active").c_str()); + } #else // __CYGWIN__ // does not have "physical id" entries, neither "cpu cores" @@ -3438,7 +3447,7 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() if (this->NumberOfPhysicalCPU <= 0) { this->NumberOfPhysicalCPU = 1; } - // LogicalProcessorsPerPhysical>1 => SMT. + // LogicalProcessorsPerPhysical>1 => hyperthreading. this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = this->NumberOfLogicalCPU / this->NumberOfPhysicalCPU; @@ -4313,10 +4322,68 @@ void SystemInformationImplementation::DelayOverhead(unsigned int uiMS) (void)uiMS; } +/** Return the number of logical CPU per physical CPUs Works only for windows + */ +unsigned char SystemInformationImplementation::LogicalCPUPerPhysicalCPU(void) +{ +#ifdef __APPLE__ + size_t len = 4; + int cores_per_package = 0; + int err = sysctlbyname("machdep.cpu.cores_per_package", &cores_per_package, + &len, NULL, 0); + if (err != 0) { + return 1; // That name was not found, default to 1 + } + return static_cast(cores_per_package); +#else + int Regs[4] = { 0, 0, 0, 0 }; +#if USE_CPUID + if (!this->IsHyperThreadingSupported()) { + return static_cast(1); // HT not supported + } + call_cpuid(1, Regs); +#endif + return static_cast((Regs[1] & NUM_LOGICAL_BITS) >> 16); +#endif +} + /** Works only for windows */ -bool SystemInformationImplementation::IsSMTSupported() +bool SystemInformationImplementation::IsHyperThreadingSupported() { - return this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical > 1; + if (this->Features.ExtendedFeatures.SupportsHyperthreading) { + return true; + } + +#if USE_CPUID + int Regs[4] = { 0, 0, 0, 0 }, VendorId[4] = { 0, 0, 0, 0 }; + // Get vendor id string + if (!call_cpuid(0, VendorId)) { + return false; + } + // eax contains family processor type + // edx has info about the availability of hyper-Threading + if (!call_cpuid(1, Regs)) { + return false; + } + + if (((Regs[0] & FAMILY_ID) == PENTIUM4_ID) || (Regs[0] & EXT_FAMILY_ID)) { + if (VendorId[1] == 0x756e6547) // 'uneG' + { + if (VendorId[3] == 0x49656e69) // 'Ieni' + { + if (VendorId[2] == 0x6c65746e) // 'letn' + { + // Genuine Intel with hyper-Threading technology + this->Features.ExtendedFeatures.SupportsHyperthreading = + ((Regs[3] & HT_BIT) != 0); + return this->Features.ExtendedFeatures.SupportsHyperthreading; + } + } + } + } +#endif + + return 0; // Not genuine Intel processor } /** Return the APIC Id. Works only for windows. */ @@ -4325,7 +4392,7 @@ unsigned char SystemInformationImplementation::GetAPICId() int Regs[4] = { 0, 0, 0, 0 }; #if USE_CPUID - if (!this->IsSMTSupported()) { + if (!this->IsHyperThreadingSupported()) { return static_cast(-1); // HT not supported } // Logical processor = 1 call_cpuid(1, Regs); @@ -4335,46 +4402,102 @@ unsigned char SystemInformationImplementation::GetAPICId() } /** Count the number of CPUs. Works only on windows. */ -void SystemInformationImplementation::CPUCountWindows() +int SystemInformationImplementation::CPUCount() { #if defined(_WIN32) - std::vector ProcInfo; + unsigned char StatusFlag = 0; + SYSTEM_INFO info; + this->NumberOfPhysicalCPU = 0; this->NumberOfLogicalCPU = 0; + info.dwNumberOfProcessors = 0; + GetSystemInfo(&info); + + // Number of physical processors in a non-Intel system + // or in a 32-bit Intel system with Hyper-Threading technology disabled + this->NumberOfPhysicalCPU = (unsigned char)info.dwNumberOfProcessors; + + if (this->IsHyperThreadingSupported()) { + unsigned char HT_Enabled = 0; + this->NumberOfLogicalCPU = this->LogicalCPUPerPhysicalCPU(); + if (this->NumberOfLogicalCPU >= + 1) // >1 Doesn't mean HT is enabled in the BIOS + { + HANDLE hCurrentProcessHandle; +#ifndef _WIN64 +#define DWORD_PTR DWORD +#endif + DWORD_PTR dwProcessAffinity; + DWORD_PTR dwSystemAffinity; + DWORD dwAffinityMask; + + // Calculate the appropriate shifts and mask based on the + // number of logical processors. + unsigned int i = 1; + unsigned char PHY_ID_MASK = 0xFF; + // unsigned char PHY_ID_SHIFT = 0; + + while (i < this->NumberOfLogicalCPU) { + i *= 2; + PHY_ID_MASK <<= 1; + // PHY_ID_SHIFT++; + } - { - DWORD Length = 0; - DWORD rc = GetLogicalProcessorInformation(NULL, &Length); - assert(FALSE == rc); - (void)rc; // Silence unused variable warning in Borland C++ 5.81 - assert(GetLastError() == ERROR_INSUFFICIENT_BUFFER); - ProcInfo.resize(Length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)); - rc = GetLogicalProcessorInformation(&ProcInfo[0], &Length); - assert(rc != FALSE); - (void)rc; // Silence unused variable warning in Borland C++ 5.81 - } - - typedef std::vector::iterator - pinfoIt_t; - for (pinfoIt_t it = ProcInfo.begin(); it != ProcInfo.end(); ++it) { - SYSTEM_LOGICAL_PROCESSOR_INFORMATION PInfo = *it; - if (PInfo.Relationship != RelationProcessorCore) { - continue; - } + hCurrentProcessHandle = GetCurrentProcess(); + GetProcessAffinityMask(hCurrentProcessHandle, &dwProcessAffinity, + &dwSystemAffinity); - std::bitset::digits> ProcMask( - (unsigned long long)PInfo.ProcessorMask); - unsigned int count = (unsigned int)ProcMask.count(); - if (count == 0) { // I think this should never happen, but just to be safe. - continue; + // Check if available process affinity mask is equal to the + // available system affinity mask + if (dwProcessAffinity != dwSystemAffinity) { + StatusFlag = HT_CANNOT_DETECT; + this->NumberOfPhysicalCPU = (unsigned char)-1; + return StatusFlag; + } + + dwAffinityMask = 1; + while (dwAffinityMask != 0 && dwAffinityMask <= dwProcessAffinity) { + // Check if this CPU is available + if (dwAffinityMask & dwProcessAffinity) { + if (SetProcessAffinityMask(hCurrentProcessHandle, dwAffinityMask)) { + unsigned char APIC_ID, LOG_ID; + Sleep(0); // Give OS time to switch CPU + + APIC_ID = GetAPICId(); + LOG_ID = APIC_ID & ~PHY_ID_MASK; + + if (LOG_ID != 0) { + HT_Enabled = 1; + } + } + } + dwAffinityMask = dwAffinityMask << 1; + } + // Reset the processor affinity + SetProcessAffinityMask(hCurrentProcessHandle, dwProcessAffinity); + + if (this->NumberOfLogicalCPU == + 1) // Normal P4 : HT is disabled in hardware + { + StatusFlag = HT_DISABLED; + } else { + if (HT_Enabled) { + // Total physical processors in a Hyper-Threading enabled system. + this->NumberOfPhysicalCPU /= (this->NumberOfLogicalCPU); + StatusFlag = HT_ENABLED; + } else { + StatusFlag = HT_SUPPORTED_NOT_ENABLED; + } + } } - this->NumberOfPhysicalCPU++; - this->NumberOfLogicalCPU += (unsigned int)count; - this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = count; + } else { + // Processors do not have Hyper-Threading technology + StatusFlag = HT_NOT_CAPABLE; + this->NumberOfLogicalCPU = 1; } - this->NumberOfPhysicalCPU = std::max(1u, this->NumberOfPhysicalCPU); - this->NumberOfLogicalCPU = std::max(1u, this->NumberOfLogicalCPU); + return StatusFlag; #else + return 0; #endif } @@ -4436,14 +4559,8 @@ bool SystemInformationImplementation::ParseSysCtl() sysctlbyname("hw.physicalcpu", &this->NumberOfPhysicalCPU, &len, NULL, 0); len = sizeof(this->NumberOfLogicalCPU); sysctlbyname("hw.logicalcpu", &this->NumberOfLogicalCPU, &len, NULL, 0); - - int cores_per_package = 0; - len = sizeof(cores_per_package); - err = sysctlbyname("machdep.cpu.cores_per_package", &cores_per_package, &len, - NULL, 0); - // That name was not found, default to 1 this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = - err != 0 ? 1 : static_cast(cores_per_package); + this->LogicalCPUPerPhysicalCPU(); len = sizeof(value); sysctlbyname("hw.cpufrequency", &value, &len, NULL, 0); diff --git a/Source/kwsys/SystemInformation.hxx.in b/Source/kwsys/SystemInformation.hxx.in index cc09393..0fc1067 100644 --- a/Source/kwsys/SystemInformation.hxx.in +++ b/Source/kwsys/SystemInformation.hxx.in @@ -67,7 +67,7 @@ public: bool Is64Bits(); - unsigned int GetNumberOfLogicalCPU(); + unsigned int GetNumberOfLogicalCPU(); // per physical cpu unsigned int GetNumberOfPhysicalCPU(); bool DoesCPUSupportCPUID(); ----------------------------------------------------------------------- Summary of changes: Source/kwsys/SystemInformation.cxx | 245 ++++++++++++++++++++++++--------- Source/kwsys/SystemInformation.hxx.in | 2 +- 2 files changed, 182 insertions(+), 65 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 13 11:41:48 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 13 Feb 2017 11:41:48 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-45-g0c43793 Message-ID: <20170213164148.AD1D6E6C4D@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 0c4379353fb82e0d5223e82faeaf14f4dcc7a80b (commit) via c3800e54583208ac4a6435884bb8832e72af3183 (commit) from 0cab748cf84a844df36623f03c5ed7b8065ceb5a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0c4379353fb82e0d5223e82faeaf14f4dcc7a80b commit 0c4379353fb82e0d5223e82faeaf14f4dcc7a80b Merge: 0cab748 c3800e5 Author: Brad King AuthorDate: Mon Feb 13 11:41:46 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 13 11:41:46 2017 -0500 Merge topic 'erase-if' c3800e54 cmAlgorithms: add cmEraseIf function ----------------------------------------------------------------------- Summary of changes: Source/cmAlgorithms.h | 6 ++++++ Source/cmGlobalVisualStudio14Generator.cxx | 3 +-- Source/cmLocalUnixMakefileGenerator3.cxx | 5 +---- Source/cmMakefile.cxx | 13 ++----------- Source/cmNinjaNormalTargetGenerator.cxx | 18 ++++++------------ 5 files changed, 16 insertions(+), 29 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 13 11:41:51 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 13 Feb 2017 11:41:51 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-56-g7da1cde Message-ID: <20170213164151.BD105E71D9@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 7da1cde3aedd3f09dffaadbe5815a04aa71d411a (commit) via 166b3393875e4f6752907b9b06c2518dce0432e9 (commit) via cbe4d5957b526f9a9bb6954d0c6944ad7642bb90 (commit) via 8731701cb636317df2691359361562f32adfe759 (commit) via 0ae5386aa953d1670074c2f1bfc9a04ddb382684 (commit) via ce19607fed3990b8e828330e77f09061c99aa113 (commit) via 008ed80dcf1d03640879b4168f4fba956aa03196 (commit) via c0d7bb8368c3d157d1a2758b620fc726355e554d (commit) via 21a125cdbff24efa746249a3b8ccc6296c5f0aff (commit) via eebb2be8b0db17bb5f760e7fa04c020406e6f6eb (commit) via 84f3c87b030037646c1110b1e4237f597ad3dd88 (commit) from 0c4379353fb82e0d5223e82faeaf14f4dcc7a80b (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7da1cde3aedd3f09dffaadbe5815a04aa71d411a commit 7da1cde3aedd3f09dffaadbe5815a04aa71d411a Merge: 0c43793 166b339 Author: Brad King AuthorDate: Mon Feb 13 11:41:49 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 13 11:41:49 2017 -0500 Merge topic 'cuda_tests_improve_error_reporting' 166b3393 Tests/Cuda: Select a CUDA device supporting compute 3.0 cbe4d595 Tests/Cuda: Return a non-zero code if errors occurred 8731701c Tests/Cuda: Use memory allocated on the GPU in the kernels 0ae5386a Tests/Cuda: Add missing separable compilation property ce19607f Tests/Cuda: Fix missing CUDA static library at runtime on macOS 008ed80d Tests/Cuda: Output error messages to std::cerr instead of std::cout c0d7bb83 Tests/Cuda: Print asynchronous error messages, if any 21a125cd Tests/Cuda: Print error message if mixed_kernel failed eebb2be8 Tests/Cuda: Add identifiers to error messages 84f3c87b Tests/Cuda: Print error message if an error occurred ----------------------------------------------------------------------- Summary of changes: Tests/Cuda/Complex/CMakeLists.txt | 8 ++++++ Tests/Cuda/Complex/dynamic.cu | 51 ++++++++++++++++++++++++++++++++++-- Tests/Cuda/Complex/file3.cu | 39 ++++++++++++++++++++++----- Tests/Cuda/Complex/main.cpp | 12 ++++++--- Tests/Cuda/Complex/mixed.cu | 40 +++++++++++++++++++++++++--- Tests/Cuda/ObjectLibrary/main.cpp | 8 +++--- Tests/Cuda/ObjectLibrary/static.cu | 4 +-- 7 files changed, 141 insertions(+), 21 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 13 11:42:16 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 13 Feb 2017 11:42:16 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-100-gc7a665b Message-ID: <20170213164216.110C6F1FEC@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via c7a665b6002f98abb4d48f270ef7127bc2306b5a (commit) via 7da1cde3aedd3f09dffaadbe5815a04aa71d411a (commit) via 0c4379353fb82e0d5223e82faeaf14f4dcc7a80b (commit) via 0cab748cf84a844df36623f03c5ed7b8065ceb5a (commit) via 26662fc3d38f93b5aaebdcb59d8937f9661020f9 (commit) via 6c8d65963104451b15aa331a6914173af42a224c (commit) from e8d7474006657657f4fc66b48d98b6e1c80fce03 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c7a665b6002f98abb4d48f270ef7127bc2306b5a commit c7a665b6002f98abb4d48f270ef7127bc2306b5a Merge: e8d7474 7da1cde Author: Brad King AuthorDate: Mon Feb 13 11:42:03 2017 -0500 Commit: Brad King CommitDate: Mon Feb 13 11:42:03 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 13 11:45:03 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 13 Feb 2017 11:45:03 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-102-gfb4044b Message-ID: <20170213164503.2FE7EF95F8@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via fb4044b6f07df33a146df4e19da65e415899cda7 (commit) via 44f3acb202c316bc6a863a1823aaafae486c899a (commit) from c7a665b6002f98abb4d48f270ef7127bc2306b5a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=fb4044b6f07df33a146df4e19da65e415899cda7 commit fb4044b6f07df33a146df4e19da65e415899cda7 Merge: c7a665b 44f3acb Author: Brad King AuthorDate: Mon Feb 13 11:45:01 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 13 11:45:01 2017 -0500 Merge topic 'cmake_provide_include_dir_for_toolkit' into next 44f3acb2 CUDA: Detect the toolkit include directories https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=44f3acb202c316bc6a863a1823aaafae486c899a commit 44f3acb202c316bc6a863a1823aaafae486c899a Author: Robert Maynard AuthorDate: Wed Feb 8 16:51:18 2017 -0500 Commit: Brad King CommitDate: Fri Feb 10 16:08:06 2017 -0500 CUDA: Detect the toolkit include directories The `nvcc -v` output provides what include directories need to be added to use the CUDA toolkit from other languages ( C/C++ ). diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 95f780a..38444d1 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -353,6 +353,7 @@ Variables for Languages /variable/CMAKE_CUDA_EXTENSIONS /variable/CMAKE_CUDA_STANDARD /variable/CMAKE_CUDA_STANDARD_REQUIRED + /variable/CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES /variable/CMAKE_CXX_COMPILE_FEATURES /variable/CMAKE_CXX_EXTENSIONS /variable/CMAKE_CXX_STANDARD diff --git a/Help/variable/CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES.rst b/Help/variable/CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES.rst new file mode 100644 index 0000000..768f571 --- /dev/null +++ b/Help/variable/CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES.rst @@ -0,0 +1,7 @@ +CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES +-------------------------------------- + +When the ``CUDA`` language has been enabled, this provides a +:ref:`;-list ` of include directories provided +by the CUDA Toolkit. The value may be useful for C++ source files +to include CUDA headers. diff --git a/Modules/CMakeCUDACompiler.cmake.in b/Modules/CMakeCUDACompiler.cmake.in index 158d12b..f524e5f 100644 --- a/Modules/CMakeCUDACompiler.cmake.in +++ b/Modules/CMakeCUDACompiler.cmake.in @@ -16,6 +16,8 @@ set(CMAKE_CUDA_SOURCE_FILE_EXTENSIONS cu) set(CMAKE_CUDA_LINKER_PREFERENCE 15) set(CMAKE_CUDA_LINKER_PREFERENCE_PROPAGATES 1) +set(CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES "@CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES@") + set(CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES "@CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES@") set(CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES "@CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES@") set(CMAKE_CUDA_HOST_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "@CMAKE_CUDA_HOST_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES@") diff --git a/Modules/CMakeDetermineCUDACompiler.cmake b/Modules/CMakeDetermineCUDACompiler.cmake index bef6d0e..7b6d17b 100644 --- a/Modules/CMakeDetermineCUDACompiler.cmake +++ b/Modules/CMakeDetermineCUDACompiler.cmake @@ -84,20 +84,20 @@ endif() #the compiler with cuda-fake-ld and pass too CMAKE_PARSE_IMPLICIT_LINK_INFO if(CMAKE_CUDA_COMPILER_ID STREQUAL NVIDIA) set(_nvcc_log "") - string(REPLACE "\r" "" _nvcc_output "${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}") - if(_nvcc_output MATCHES "#\\\$ +LIBRARIES= *([^\n]*)\n") + string(REPLACE "\r" "" _nvcc_output_orig "${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}") + if(_nvcc_output_orig MATCHES "#\\\$ +LIBRARIES= *([^\n]*)\n") set(_nvcc_libraries "${CMAKE_MATCH_1}") string(APPEND _nvcc_log " found 'LIBRARIES=' string: [${_nvcc_libraries}]\n") else() set(_nvcc_libraries "") - string(REPLACE "\n" "\n " _nvcc_output_log "\n${_nvcc_output}") + string(REPLACE "\n" "\n " _nvcc_output_log "\n${_nvcc_output_orig}") string(APPEND _nvcc_log " no 'LIBRARIES=' string found in nvcc output:${_nvcc_output_log}\n") endif() set(_nvcc_link_line "") if(_nvcc_libraries) # Remove variable assignments. - string(REGEX REPLACE "#\\\$ *[^= ]+=[^\n]*\n" "" _nvcc_output "${_nvcc_output}") + string(REGEX REPLACE "#\\\$ *[^= ]+=[^\n]*\n" "" _nvcc_output "${_nvcc_output_orig}") # Split lines. string(REGEX REPLACE "\n+(#\\\$ )?" ";" _nvcc_output "${_nvcc_output}") foreach(line IN LISTS _nvcc_output) @@ -150,6 +150,32 @@ if(CMAKE_CUDA_COMPILER_ID STREQUAL NVIDIA) message(FATAL_ERROR "Failed to extract nvcc implicit link line.") endif() + set(CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES ) + if(_nvcc_output_orig MATCHES "#\\\$ +INCLUDES= *([^\n]*)\n") + set(_nvcc_includes "${CMAKE_MATCH_1}") + string(APPEND _nvcc_log " found 'INCLUDES=' string: [${_nvcc_includes}]\n") + else() + set(_nvcc_includes "") + string(REPLACE "\n" "\n " _nvcc_output_log "\n${_nvcc_output_orig}") + string(APPEND _nvcc_log " no 'INCLUDES=' string found in nvcc output:${_nvcc_output_log}\n") + endif() + if(_nvcc_includes) + # across all operating system each include directory is prefixed with -I + separate_arguments(_nvcc_output UNIX_COMMAND "${_nvcc_includes}") + foreach(line IN LISTS _nvcc_output) + string(REGEX REPLACE "^-I" "" line "${line}") + get_filename_component(line "${line}" ABSOLUTE) + list(APPEND CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES "${line}") + endforeach() + + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Parsed CUDA nvcc include information from above output:\n${_nvcc_log}\n${log}\n\n") + else() + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Failed to detect CUDA nvcc include information:\n${_nvcc_log}\n\n") + endif() + + endif() # configure all variables set in this file diff --git a/Tests/Cuda/CMakeLists.txt b/Tests/Cuda/CMakeLists.txt index 40c9675..42b00e1 100644 --- a/Tests/Cuda/CMakeLists.txt +++ b/Tests/Cuda/CMakeLists.txt @@ -2,4 +2,5 @@ ADD_TEST_MACRO(Cuda.Complex CudaComplex) ADD_TEST_MACRO(Cuda.ConsumeCompileFeatures CudaConsumeCompileFeatures) ADD_TEST_MACRO(Cuda.ObjectLibrary CudaObjectLibrary) +ADD_TEST_MACRO(Cuda.ToolkitInclude CudaToolkitInclude) ADD_TEST_MACRO(Cuda.ProperLinkFlags ProperLinkFlags) diff --git a/Tests/Cuda/ToolkitInclude/CMakeLists.txt b/Tests/Cuda/ToolkitInclude/CMakeLists.txt new file mode 100644 index 0000000..f246b54 --- /dev/null +++ b/Tests/Cuda/ToolkitInclude/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 3.8) +project (ToolkitInclude CXX CUDA) + +#Goal for this example: +# Validate that between the CXX implicit include directories and the +# CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES directories we can find +# the cuda runtime headers + +add_executable(CudaToolkitInclude main.cpp) +target_include_directories(CudaToolkitInclude PRIVATE + ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES}) diff --git a/Tests/Cuda/ToolkitInclude/main.cpp b/Tests/Cuda/ToolkitInclude/main.cpp new file mode 100644 index 0000000..c8d5c6b --- /dev/null +++ b/Tests/Cuda/ToolkitInclude/main.cpp @@ -0,0 +1,8 @@ +// Only thing we care about is that these headers are found +#include +#include + +int main() +{ + return 0; +} diff --git a/Tests/CudaOnly/EnableStandard/CMakeLists.txt b/Tests/CudaOnly/EnableStandard/CMakeLists.txt index 53b9132..35a1deb 100644 --- a/Tests/CudaOnly/EnableStandard/CMakeLists.txt +++ b/Tests/CudaOnly/EnableStandard/CMakeLists.txt @@ -13,3 +13,14 @@ target_link_libraries(CudaOnlyEnableStandard PRIVATE CUDAStatic11 CUDADynamic11) set_target_properties(CUDAStatic11 CUDADynamic11 PROPERTIES CUDA_STANDARD 11) set_target_properties(CUDAStatic11 CUDADynamic11 PROPERTIES CUDA_STANDARD_REQUIRED TRUE) + +#Verify CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES +foreach(dir ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES}) + if(NOT IS_DIRECTORY "${dir}") + message(FATAL_ERROR + "CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES entry\n" + " ${dir}\n" + "is not an existing directory." + ) + endif() +endforeach() ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-variables.7.rst | 1 + .../CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES.rst | 7 ++++ Modules/CMakeCUDACompiler.cmake.in | 2 ++ Modules/CMakeDetermineCUDACompiler.cmake | 34 +++++++++++++++++--- Tests/Cuda/CMakeLists.txt | 1 + Tests/Cuda/ToolkitInclude/CMakeLists.txt | 11 +++++++ Tests/Cuda/ToolkitInclude/main.cpp | 8 +++++ Tests/CudaOnly/EnableStandard/CMakeLists.txt | 11 +++++++ 8 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 Help/variable/CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES.rst create mode 100644 Tests/Cuda/ToolkitInclude/CMakeLists.txt create mode 100644 Tests/Cuda/ToolkitInclude/main.cpp hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 13 11:46:26 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 13 Feb 2017 11:46:26 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-58-g38bfe65 Message-ID: <20170213164627.81A45F9A16@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 38bfe65eba21c697d05e8bed79635fc125cdac17 (commit) via 6cbad490c2fdbd9bdc67b406b9f2dcdc21e08ddb (commit) from 7da1cde3aedd3f09dffaadbe5815a04aa71d411a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 13 11:46:27 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 13 Feb 2017 11:46:27 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-105-g6ddde7c Message-ID: <20170213164627.D8DA4F99A3@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 6ddde7ce0264de27af6a5160695506abb52906e2 (commit) via 38bfe65eba21c697d05e8bed79635fc125cdac17 (commit) via 6cbad490c2fdbd9bdc67b406b9f2dcdc21e08ddb (commit) from fb4044b6f07df33a146df4e19da65e415899cda7 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6ddde7ce0264de27af6a5160695506abb52906e2 commit 6ddde7ce0264de27af6a5160695506abb52906e2 Merge: fb4044b 38bfe65 Author: Brad King AuthorDate: Mon Feb 13 11:46:16 2017 -0500 Commit: Brad King CommitDate: Mon Feb 13 11:46:16 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 13 11:46:27 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 13 Feb 2017 11:46:27 -0500 (EST) Subject: [Cmake-commits] CMake branch, release, updated. v3.8.0-rc1-4-g6cbad49 Message-ID: <20170213164628.2156CF9A36@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, release has been updated via 6cbad490c2fdbd9bdc67b406b9f2dcdc21e08ddb (commit) via 30abf145fd48f50c26ee7553fd2512e59be97f25 (commit) via 97917900d146acd55a7e453f477c52cd2e816eb3 (commit) via 971384c28759ad042624bda3893be6fdb1795591 (commit) from 84df4a49500e51ac6e2a19a77e385e66234386f7 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- Summary of changes: Help/command/if.rst | 6 +++--- Help/manual/cmake-developer.7.rst | 4 ++-- Help/manual/cmake-language.7.rst | 4 ++-- Modules/CMakePackageConfigHelpers.cmake | 6 +++--- Utilities/Sphinx/apply_qthelp_css_workaround.cmake | 14 +++++++++----- Utilities/Sphinx/cmake.py | 8 ++++++-- 6 files changed, 25 insertions(+), 17 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 13 13:20:23 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 13 Feb 2017 13:20:23 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-107-gf8c5b31 Message-ID: <20170213182023.B7C4FFA1FB@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via f8c5b31f33becfba9f25ca29cc4caee6b343f93c (commit) via d5d8170f3628c867bd14f385de3d5b8b82f01109 (commit) from 6ddde7ce0264de27af6a5160695506abb52906e2 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f8c5b31f33becfba9f25ca29cc4caee6b343f93c commit f8c5b31f33becfba9f25ca29cc4caee6b343f93c Merge: 6ddde7c d5d8170 Author: Brad King AuthorDate: Mon Feb 13 13:20:22 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 13 13:20:22 2017 -0500 Merge topic 'command-cleanup' into next d5d8170f Revert topic 'command-cleanup' https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d5d8170f3628c867bd14f385de3d5b8b82f01109 commit d5d8170f3628c867bd14f385de3d5b8b82f01109 Author: Brad King AuthorDate: Mon Feb 13 13:19:59 2017 -0500 Commit: Brad King CommitDate: Mon Feb 13 13:19:59 2017 -0500 Revert topic 'command-cleanup' It will be revised and restored. diff --git a/Help/manual/cmake-commands.7.rst b/Help/manual/cmake-commands.7.rst index 611c989..d0c2986 100644 --- a/Help/manual/cmake-commands.7.rst +++ b/Help/manual/cmake-commands.7.rst @@ -7,103 +7,91 @@ cmake-commands(7) .. contents:: -Scripting Commands -================== +Normal Commands +=============== -These commands are always available. +These commands may be used freely in CMake projects. .. toctree:: :maxdepth: 1 + /command/add_compile_options + /command/add_custom_command + /command/add_custom_target + /command/add_definitions + /command/add_dependencies + /command/add_executable + /command/add_library + /command/add_subdirectory + /command/add_test + /command/aux_source_directory /command/break + /command/build_command /command/cmake_host_system_information /command/cmake_minimum_required /command/cmake_parse_arguments /command/cmake_policy /command/configure_file /command/continue + /command/create_test_sourcelist + /command/define_property /command/elseif /command/else + /command/enable_language + /command/enable_testing /command/endforeach /command/endfunction /command/endif /command/endmacro /command/endwhile /command/execute_process + /command/export /command/file /command/find_file /command/find_library /command/find_package /command/find_path /command/find_program + /command/fltk_wrap_ui /command/foreach /command/function /command/get_cmake_property /command/get_directory_property /command/get_filename_component /command/get_property - /command/if - /command/include - /command/list - /command/macro - /command/mark_as_advanced - /command/math - /command/message - /command/option - /command/return - /command/separate_arguments - /command/set_directory_properties - /command/set_property - /command/set - /command/site_name - /command/string - /command/unset - /command/variable_watch - /command/while - -Project Commands -================ - -These commands are available only in CMake projects. - -.. toctree:: - :maxdepth: 1 - - /command/add_compile_options - /command/add_custom_command - /command/add_custom_target - /command/add_definitions - /command/add_dependencies - /command/add_executable - /command/add_library - /command/add_subdirectory - /command/add_test - /command/aux_source_directory - /command/build_command - /command/create_test_sourcelist - /command/define_property - /command/enable_language - /command/enable_testing - /command/export - /command/fltk_wrap_ui /command/get_source_file_property /command/get_target_property /command/get_test_property + /command/if /command/include_directories /command/include_external_msproject /command/include_regular_expression + /command/include /command/install /command/link_directories /command/link_libraries + /command/list /command/load_cache + /command/macro + /command/mark_as_advanced + /command/math + /command/message + /command/option /command/project /command/qt_wrap_cpp /command/qt_wrap_ui /command/remove_definitions + /command/return + /command/separate_arguments + /command/set_directory_properties + /command/set_property + /command/set /command/set_source_files_properties /command/set_target_properties /command/set_tests_properties + /command/site_name /command/source_group + /command/string /command/target_compile_definitions /command/target_compile_features /command/target_compile_options @@ -112,30 +100,9 @@ These commands are available only in CMake projects. /command/target_sources /command/try_compile /command/try_run - -.. _`CTest Commands`: - -CTest Commands -============== - -These commands are available only in CTest scripts. - -.. toctree:: - :maxdepth: 1 - - /command/ctest_build - /command/ctest_configure - /command/ctest_coverage - /command/ctest_empty_binary_directory - /command/ctest_memcheck - /command/ctest_read_custom_files - /command/ctest_run_script - /command/ctest_sleep - /command/ctest_start - /command/ctest_submit - /command/ctest_test - /command/ctest_update - /command/ctest_upload + /command/unset + /command/variable_watch + /command/while Deprecated Commands =================== @@ -162,3 +129,27 @@ versions of CMake. Do not use them in new code. /command/utility_source /command/variable_requires /command/write_file + +.. _`CTest Commands`: + +CTest Commands +============== + +These commands are available only in ctest scripts. + +.. toctree:: + :maxdepth: 1 + + /command/ctest_build + /command/ctest_configure + /command/ctest_coverage + /command/ctest_empty_binary_directory + /command/ctest_memcheck + /command/ctest_read_custom_files + /command/ctest_run_script + /command/ctest_sleep + /command/ctest_start + /command/ctest_submit + /command/ctest_test + /command/ctest_update + /command/ctest_upload diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 3b05f4c..2835ee6 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -440,8 +440,6 @@ set(SRCS cmCreateTestSourceList.h cmDefinePropertyCommand.cxx cmDefinePropertyCommand.h - cmDeprecatedCommand.cxx - cmDeprecatedCommand.h cmEnableLanguageCommand.cxx cmEnableLanguageCommand.h cmEnableTestingCommand.cxx diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx index 2a67d47..a989b12 100644 --- a/Source/CTest/cmCTestHandlerCommand.cxx +++ b/Source/CTest/cmCTestHandlerCommand.cxx @@ -123,8 +123,8 @@ bool cmCTestHandlerCommand::InitialPass(std::vector const& args, if (capureCMakeError) { this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR], "-1"); - std::string const err = this->GetName() + " " + this->GetError(); - if (!cmSystemTools::FindLastString(err.c_str(), "unknown error.")) { + const char* err = this->GetError(); + if (err && !cmSystemTools::FindLastString(err, "unknown error.")) { cmCTestLog(this->CTest, ERROR_MESSAGE, err << " error from command\n"); } // return success because failure is recorded in CAPTURE_CMAKE_ERROR diff --git a/Source/cmBuildNameCommand.cxx b/Source/cmBuildNameCommand.cxx index 12b69a8..1e1cd21 100644 --- a/Source/cmBuildNameCommand.cxx +++ b/Source/cmBuildNameCommand.cxx @@ -16,6 +16,11 @@ class cmExecutionStatus; bool cmBuildNameCommand::InitialPass(std::vector const& args, cmExecutionStatus&) { + if (this->Disallowed( + cmPolicies::CMP0036, + "The build_name command should not be called; see CMP0036.")) { + return true; + } if (args.empty()) { this->SetError("called with incorrect number of arguments"); return false; diff --git a/Source/cmCommand.cxx b/Source/cmCommand.cxx index d349c91..181b412 100644 --- a/Source/cmCommand.cxx +++ b/Source/cmCommand.cxx @@ -3,6 +3,7 @@ #include "cmCommand.h" #include "cmMakefile.h" +#include "cmake.h" class cmExecutionStatus; struct cmListFileArgument; @@ -22,12 +23,32 @@ bool cmCommand::InvokeInitialPass(const std::vector& args, const char* cmCommand::GetError() { if (this->Error.empty()) { - return "unknown error."; + this->Error = this->GetName(); + this->Error += " unknown error."; } return this->Error.c_str(); } void cmCommand::SetError(const std::string& e) { - this->Error = e; + this->Error = this->GetName(); + this->Error += " "; + this->Error += e; +} + +bool cmCommand::Disallowed(cmPolicies::PolicyID pol, const char* e) +{ + switch (this->Makefile->GetPolicyStatus(pol)) { + case cmPolicies::WARN: + this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, + cmPolicies::GetPolicyWarning(pol)); + case cmPolicies::OLD: + return false; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e); + break; + } + return true; } diff --git a/Source/cmCommand.h b/Source/cmCommand.h index 9107d85..d9fd5a2 100644 --- a/Source/cmCommand.h +++ b/Source/cmCommand.h @@ -7,6 +7,9 @@ #include #include +#include "cmCommandArgumentsHelper.h" +#include "cmPolicies.h" + class cmExecutionStatus; class cmMakefile; struct cmListFileArgument; @@ -102,12 +105,12 @@ public: */ void SetError(const std::string& e); -private: - cmCommand(cmCommand const&); // = delete; - cmCommand& operator=(cmCommand const&); // = delete; + /** Check if the command is disallowed by a policy. */ + bool Disallowed(cmPolicies::PolicyID pol, const char* e); protected: cmMakefile* Makefile; + cmCommandArgumentsHelper Helper; private: std::string Error; diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index 9ff395a..4c5b093 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -1,7 +1,6 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCommands.h" -#include "cmState.h" #include "cmAddCustomCommandCommand.h" #include "cmAddCustomTargetCommand.h" @@ -78,7 +77,6 @@ #include "cmAuxSourceDirectoryCommand.h" #include "cmBuildNameCommand.h" #include "cmCMakeHostSystemInformationCommand.h" -#include "cmDeprecatedCommand.h" #include "cmExportCommand.h" #include "cmExportLibraryDependenciesCommand.h" #include "cmFLTKWrapUICommand.h" @@ -106,162 +104,138 @@ #include "cmWriteFileCommand.h" #endif -void GetScriptingCommands(cmState* state) +std::vector GetPredefinedCommands() { - state->AddCommand(new cmBreakCommand); - state->AddCommand(new cmCMakeMinimumRequired); - state->AddCommand(new cmCMakePolicyCommand); - state->AddCommand(new cmConfigureFileCommand); - state->AddCommand(new cmContinueCommand); - state->AddCommand(new cmExecProgramCommand); - state->AddCommand(new cmExecuteProcessCommand); - state->AddCommand(new cmFileCommand); - state->AddCommand(new cmFindFileCommand); - state->AddCommand(new cmFindLibraryCommand); - state->AddCommand(new cmFindPackageCommand); - state->AddCommand(new cmFindPathCommand); - state->AddCommand(new cmFindProgramCommand); - state->AddCommand(new cmForEachCommand); - state->AddCommand(new cmFunctionCommand); - state->AddCommand(new cmGetCMakePropertyCommand); - state->AddCommand(new cmGetDirectoryPropertyCommand); - state->AddCommand(new cmGetFilenameComponentCommand); - state->AddCommand(new cmGetPropertyCommand); - state->AddCommand(new cmIfCommand); - state->AddCommand(new cmIncludeCommand); - state->AddCommand(new cmListCommand); - state->AddCommand(new cmMacroCommand); - state->AddCommand(new cmMakeDirectoryCommand); - state->AddCommand(new cmMarkAsAdvancedCommand); - state->AddCommand(new cmMathCommand); - state->AddCommand(new cmMessageCommand); - state->AddCommand(new cmOptionCommand); - state->AddCommand(new cmParseArgumentsCommand); - state->AddCommand(new cmReturnCommand); - state->AddCommand(new cmSeparateArgumentsCommand); - state->AddCommand(new cmSetCommand); - state->AddCommand(new cmSetDirectoryPropertiesCommand); - state->AddCommand(new cmSetPropertyCommand); - state->AddCommand(new cmSiteNameCommand); - state->AddCommand(new cmStringCommand); - state->AddCommand(new cmUnsetCommand); - state->AddCommand(new cmWhileCommand); + std::vector commands; - state->AddCommand(new cmUnexpectedCommand( + commands.push_back(new cmAddCustomCommandCommand); + commands.push_back(new cmAddCustomTargetCommand); + commands.push_back(new cmAddDefinitionsCommand); + commands.push_back(new cmAddDependenciesCommand); + commands.push_back(new cmAddExecutableCommand); + commands.push_back(new cmAddLibraryCommand); + commands.push_back(new cmAddSubDirectoryCommand); + commands.push_back(new cmAddTestCommand); + commands.push_back(new cmBreakCommand); + commands.push_back(new cmBuildCommand); + commands.push_back(new cmCMakeMinimumRequired); + commands.push_back(new cmCMakePolicyCommand); + commands.push_back(new cmConfigureFileCommand); + commands.push_back(new cmContinueCommand); + commands.push_back(new cmCreateTestSourceList); + commands.push_back(new cmDefinePropertyCommand); + commands.push_back(new cmEnableLanguageCommand); + commands.push_back(new cmEnableTestingCommand); + commands.push_back(new cmExecProgramCommand); + commands.push_back(new cmExecuteProcessCommand); + commands.push_back(new cmFileCommand); + commands.push_back(new cmFindFileCommand); + commands.push_back(new cmFindLibraryCommand); + commands.push_back(new cmFindPackageCommand); + commands.push_back(new cmFindPathCommand); + commands.push_back(new cmFindProgramCommand); + commands.push_back(new cmForEachCommand); + commands.push_back(new cmFunctionCommand); + commands.push_back(new cmGetCMakePropertyCommand); + commands.push_back(new cmGetDirectoryPropertyCommand); + commands.push_back(new cmGetFilenameComponentCommand); + commands.push_back(new cmGetPropertyCommand); + commands.push_back(new cmGetSourceFilePropertyCommand); + commands.push_back(new cmGetTargetPropertyCommand); + commands.push_back(new cmGetTestPropertyCommand); + commands.push_back(new cmIfCommand); + commands.push_back(new cmIncludeCommand); + commands.push_back(new cmIncludeDirectoryCommand); + commands.push_back(new cmIncludeRegularExpressionCommand); + commands.push_back(new cmInstallCommand); + commands.push_back(new cmInstallFilesCommand); + commands.push_back(new cmInstallTargetsCommand); + commands.push_back(new cmLinkDirectoriesCommand); + commands.push_back(new cmListCommand); + commands.push_back(new cmMacroCommand); + commands.push_back(new cmMakeDirectoryCommand); + commands.push_back(new cmMarkAsAdvancedCommand); + commands.push_back(new cmMathCommand); + commands.push_back(new cmMessageCommand); + commands.push_back(new cmOptionCommand); + commands.push_back(new cmParseArgumentsCommand); + commands.push_back(new cmProjectCommand); + commands.push_back(new cmReturnCommand); + commands.push_back(new cmSeparateArgumentsCommand); + commands.push_back(new cmSetCommand); + commands.push_back(new cmSetDirectoryPropertiesCommand); + commands.push_back(new cmSetPropertyCommand); + commands.push_back(new cmSetSourceFilesPropertiesCommand); + commands.push_back(new cmSetTargetPropertiesCommand); + commands.push_back(new cmSetTestsPropertiesCommand); + commands.push_back(new cmSiteNameCommand); + commands.push_back(new cmStringCommand); + commands.push_back(new cmSubdirCommand); + commands.push_back(new cmTargetLinkLibrariesCommand); + commands.push_back(new cmTryCompileCommand); + commands.push_back(new cmTryRunCommand); + commands.push_back(new cmUnsetCommand); + commands.push_back(new cmWhileCommand); + + commands.push_back(new cmUnexpectedCommand( "else", "An ELSE command was found outside of a proper " "IF ENDIF structure. Or its arguments did not match " "the opening IF command.")); - state->AddCommand(new cmUnexpectedCommand( + commands.push_back(new cmUnexpectedCommand( "elseif", "An ELSEIF command was found outside of a proper " "IF ENDIF structure.")); - state->AddCommand(new cmUnexpectedCommand( + commands.push_back(new cmUnexpectedCommand( "endforeach", "An ENDFOREACH command was found outside of a proper " "FOREACH ENDFOREACH structure. Or its arguments did " "not match the opening FOREACH command.")); - state->AddCommand(new cmUnexpectedCommand( + commands.push_back(new cmUnexpectedCommand( "endfunction", "An ENDFUNCTION command was found outside of a proper " "FUNCTION ENDFUNCTION structure. Or its arguments did not " "match the opening FUNCTION command.")); - state->AddCommand(new cmUnexpectedCommand( + commands.push_back(new cmUnexpectedCommand( "endif", "An ENDIF command was found outside of a proper " "IF ENDIF structure. Or its arguments did not match " "the opening IF command.")); - state->AddCommand(new cmUnexpectedCommand( + commands.push_back(new cmUnexpectedCommand( "endmacro", "An ENDMACRO command was found outside of a proper " "MACRO ENDMACRO structure. Or its arguments did not " "match the opening MACRO command.")); - state->AddCommand(new cmUnexpectedCommand( + commands.push_back(new cmUnexpectedCommand( "endwhile", "An ENDWHILE command was found outside of a proper " "WHILE ENDWHILE structure. Or its arguments did not " "match the opening WHILE command.")); #if defined(CMAKE_BUILD_WITH_CMAKE) - state->AddCommand(new cmCMakeHostSystemInformationCommand); - state->AddCommand(new cmRemoveCommand); - state->AddCommand(new cmVariableWatchCommand); - state->AddCommand(new cmWriteFileCommand); - - state->AddCommand(new cmDeprecatedCommand( - new cmBuildNameCommand, cmPolicies::CMP0036, - "The build_name command should not be called; see CMP0036.")); - state->AddCommand(new cmDeprecatedCommand( - new cmUseMangledMesaCommand, cmPolicies::CMP0030, - "The use_mangled_mesa command should not be called; see CMP0030.")); - + commands.push_back(new cmAddCompileOptionsCommand); + commands.push_back(new cmAuxSourceDirectoryCommand); + commands.push_back(new cmBuildNameCommand); + commands.push_back(new cmCMakeHostSystemInformationCommand); + commands.push_back(new cmExportCommand); + commands.push_back(new cmExportLibraryDependenciesCommand); + commands.push_back(new cmFLTKWrapUICommand); + commands.push_back(new cmIncludeExternalMSProjectCommand); + commands.push_back(new cmInstallProgramsCommand); + commands.push_back(new cmLinkLibrariesCommand); + commands.push_back(new cmLoadCacheCommand); + commands.push_back(new cmLoadCommandCommand); + commands.push_back(new cmOutputRequiredFilesCommand); + commands.push_back(new cmQTWrapCPPCommand); + commands.push_back(new cmQTWrapUICommand); + commands.push_back(new cmRemoveCommand); + commands.push_back(new cmRemoveDefinitionsCommand); + commands.push_back(new cmSourceGroupCommand); + commands.push_back(new cmSubdirDependsCommand); + commands.push_back(new cmTargetCompileDefinitionsCommand); + commands.push_back(new cmTargetCompileFeaturesCommand); + commands.push_back(new cmTargetCompileOptionsCommand); + commands.push_back(new cmTargetIncludeDirectoriesCommand); + commands.push_back(new cmTargetSourcesCommand); + commands.push_back(new cmUseMangledMesaCommand); + commands.push_back(new cmUtilitySourceCommand); + commands.push_back(new cmVariableRequiresCommand); + commands.push_back(new cmVariableWatchCommand); + commands.push_back(new cmWriteFileCommand); #endif -} -void GetProjectCommands(cmState* state) -{ - state->AddCommand(new cmAddCustomCommandCommand); - state->AddCommand(new cmAddCustomTargetCommand); - state->AddCommand(new cmAddDefinitionsCommand); - state->AddCommand(new cmAddDependenciesCommand); - state->AddCommand(new cmAddExecutableCommand); - state->AddCommand(new cmAddLibraryCommand); - state->AddCommand(new cmAddSubDirectoryCommand); - state->AddCommand(new cmAddTestCommand); - state->AddCommand(new cmBuildCommand); - state->AddCommand(new cmCreateTestSourceList); - state->AddCommand(new cmDefinePropertyCommand); - state->AddCommand(new cmEnableLanguageCommand); - state->AddCommand(new cmEnableTestingCommand); - state->AddCommand(new cmGetSourceFilePropertyCommand); - state->AddCommand(new cmGetTargetPropertyCommand); - state->AddCommand(new cmGetTestPropertyCommand); - state->AddCommand(new cmIncludeDirectoryCommand); - state->AddCommand(new cmIncludeRegularExpressionCommand); - state->AddCommand(new cmInstallCommand); - state->AddCommand(new cmInstallFilesCommand); - state->AddCommand(new cmInstallTargetsCommand); - state->AddCommand(new cmLinkDirectoriesCommand); - state->AddCommand(new cmProjectCommand); - state->AddCommand(new cmSetSourceFilesPropertiesCommand); - state->AddCommand(new cmSetTargetPropertiesCommand); - state->AddCommand(new cmSetTestsPropertiesCommand); - state->AddCommand(new cmSubdirCommand); - state->AddCommand(new cmTargetLinkLibrariesCommand); - state->AddCommand(new cmTryCompileCommand); - state->AddCommand(new cmTryRunCommand); - -#if defined(CMAKE_BUILD_WITH_CMAKE) - state->AddCommand(new cmAddCompileOptionsCommand); - state->AddCommand(new cmAuxSourceDirectoryCommand); - state->AddCommand(new cmExportCommand); - state->AddCommand(new cmFLTKWrapUICommand); - state->AddCommand(new cmIncludeExternalMSProjectCommand); - state->AddCommand(new cmInstallProgramsCommand); - state->AddCommand(new cmLinkLibrariesCommand); - state->AddCommand(new cmLoadCacheCommand); - state->AddCommand(new cmQTWrapCPPCommand); - state->AddCommand(new cmQTWrapUICommand); - state->AddCommand(new cmRemoveDefinitionsCommand); - state->AddCommand(new cmSourceGroupCommand); - state->AddCommand(new cmTargetCompileDefinitionsCommand); - state->AddCommand(new cmTargetCompileFeaturesCommand); - state->AddCommand(new cmTargetCompileOptionsCommand); - state->AddCommand(new cmTargetIncludeDirectoriesCommand); - state->AddCommand(new cmTargetSourcesCommand); - - state->AddCommand(new cmDeprecatedCommand( - new cmExportLibraryDependenciesCommand, cmPolicies::CMP0033, - "The export_library_dependencies command should not be called; " - "see CMP0033.")); - state->AddCommand(new cmDeprecatedCommand( - new cmLoadCommandCommand, cmPolicies::CMP0031, - "The load_command command should not be called; see CMP0031.")); - state->AddCommand(new cmDeprecatedCommand( - new cmOutputRequiredFilesCommand, cmPolicies::CMP0032, - "The output_required_files command should not be called; " - "see CMP0032.")); - state->AddCommand(new cmDeprecatedCommand( - new cmSubdirDependsCommand, cmPolicies::CMP0029, - "The subdir_depends command should not be called; see CMP0029.")); - state->AddCommand(new cmDeprecatedCommand( - new cmUtilitySourceCommand, cmPolicies::CMP0034, - "The utility_source command should not be called; see CMP0034.")); - state->AddCommand(new cmDeprecatedCommand( - new cmVariableRequiresCommand, cmPolicies::CMP0035, - "The variable_requires command should not be called; see CMP0035.")); -#endif + return commands; } diff --git a/Source/cmCommands.h b/Source/cmCommands.h index 7895ece..649dea6 100644 --- a/Source/cmCommands.h +++ b/Source/cmCommands.h @@ -3,14 +3,16 @@ #ifndef cmCommands_h #define cmCommands_h -class cmState; +#include // IWYU pragma: keep +#include + +class cmCommand; /** - * Global function to register all compiled in commands. + * Global function to return all compiled in commands. * To add a new command edit cmCommands.cxx and add your command. * It is up to the caller to delete the commands created by this call. */ -void GetScriptingCommands(cmState* state); -void GetProjectCommands(cmState* state); +std::vector GetPredefinedCommands(); #endif diff --git a/Source/cmDeprecatedCommand.cxx b/Source/cmDeprecatedCommand.cxx deleted file mode 100644 index cd0c7ab..0000000 --- a/Source/cmDeprecatedCommand.cxx +++ /dev/null @@ -1,31 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#include "cmDeprecatedCommand.h" - -#include "cmMakefile.h" -#include "cmake.h" - -class cmExecutionStatus; - -bool cmDeprecatedCommand::InitialPass(std::vector const& args, - cmExecutionStatus& status) -{ - switch (this->Makefile->GetPolicyStatus(this->Policy)) { - case cmPolicies::WARN: - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, - cmPolicies::GetPolicyWarning(this->Policy)); - break; - case cmPolicies::OLD: - break; - case cmPolicies::REQUIRED_IF_USED: - case cmPolicies::REQUIRED_ALWAYS: - case cmPolicies::NEW: - this->Makefile->IssueMessage(cmake::FATAL_ERROR, this->Message); - return true; - } - - this->Command->SetMakefile(this->GetMakefile()); - bool const ret = this->Command->InitialPass(args, status); - this->SetError(this->Command->GetError()); - return ret; -} diff --git a/Source/cmDeprecatedCommand.h b/Source/cmDeprecatedCommand.h deleted file mode 100644 index 7424fbc..0000000 --- a/Source/cmDeprecatedCommand.h +++ /dev/null @@ -1,50 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmDeprecatedCommand_h -#define cmDeprecatedCommand_h - -#include -#include -#include - -#include "cmCommand.h" -#include "cmPolicies.h" - -class cmExecutionStatus; - -class cmDeprecatedCommand : public cmCommand -{ -public: - cmDeprecatedCommand(cmCommand* command, cmPolicies::PolicyID policy, - const char* message) - : Command(command) - , Policy(policy) - , Message(message) - { - } - - ~cmDeprecatedCommand() { delete this->Command; } - - cmCommand* Clone() CM_OVERRIDE - { - return new cmDeprecatedCommand(this->Command->Clone(), this->Policy, - this->Message); - } - - bool InitialPass(std::vector const& args, - cmExecutionStatus& status) CM_OVERRIDE; - - bool IsScriptable() const CM_OVERRIDE - { - return this->Command->IsScriptable(); - } - - std::string GetName() const CM_OVERRIDE { return this->Command->GetName(); } - -private: - cmCommand* Command; - cmPolicies::PolicyID Policy; - const char* Message; -}; - -#endif diff --git a/Source/cmExportCommand.h b/Source/cmExportCommand.h index a0224d0..99dac7d 100644 --- a/Source/cmExportCommand.h +++ b/Source/cmExportCommand.h @@ -41,7 +41,6 @@ public: std::string GetName() const CM_OVERRIDE { return "export"; } private: - cmCommandArgumentsHelper Helper; cmCommandArgumentGroup ArgumentGroup; cmCAStringVector Targets; cmCAEnabler Append; diff --git a/Source/cmExportLibraryDependenciesCommand.cxx b/Source/cmExportLibraryDependenciesCommand.cxx index e3fb412..ac4f040 100644 --- a/Source/cmExportLibraryDependenciesCommand.cxx +++ b/Source/cmExportLibraryDependenciesCommand.cxx @@ -23,6 +23,12 @@ class cmExecutionStatus; bool cmExportLibraryDependenciesCommand::InitialPass( std::vector const& args, cmExecutionStatus&) { + if (this->Disallowed( + cmPolicies::CMP0033, + "The export_library_dependencies command should not be called; " + "see CMP0033.")) { + return true; + } if (args.empty()) { this->SetError("called with incorrect number of arguments"); return false; diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx index 39e5684..b6743f1 100644 --- a/Source/cmLoadCommandCommand.cxx +++ b/Source/cmLoadCommandCommand.cxx @@ -174,6 +174,11 @@ cmLoadedCommand::~cmLoadedCommand() bool cmLoadCommandCommand::InitialPass(std::vector const& args, cmExecutionStatus&) { + if (this->Disallowed( + cmPolicies::CMP0031, + "The load_command command should not be called; see CMP0031.")) { + return true; + } if (args.empty()) { return true; } diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 4520c8e..bfe46ae 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -281,8 +281,7 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff, if (!invokeSucceeded || hadNestedError) { if (!hadNestedError) { // The command invocation requested that we report an error. - std::string const error = name + " " + pcmd->GetError(); - this->IssueMessage(cmake::FATAL_ERROR, error.c_str()); + this->IssueMessage(cmake::FATAL_ERROR, pcmd->GetError()); } result = false; if (this->GetCMakeInstance()->GetWorkingMode() != cmake::NORMAL_MODE) { diff --git a/Source/cmOutputRequiredFilesCommand.cxx b/Source/cmOutputRequiredFilesCommand.cxx index f120971..7a17f2c 100644 --- a/Source/cmOutputRequiredFilesCommand.cxx +++ b/Source/cmOutputRequiredFilesCommand.cxx @@ -495,6 +495,11 @@ protected: bool cmOutputRequiredFilesCommand::InitialPass( std::vector const& args, cmExecutionStatus&) { + if (this->Disallowed(cmPolicies::CMP0032, "The output_required_files " + "command should not be called; " + "see CMP0032.")) { + return true; + } if (args.size() != 2) { this->SetError("called with incorrect number of arguments"); return false; diff --git a/Source/cmSubdirDependsCommand.cxx b/Source/cmSubdirDependsCommand.cxx index 36e84d5..9259836 100644 --- a/Source/cmSubdirDependsCommand.cxx +++ b/Source/cmSubdirDependsCommand.cxx @@ -9,5 +9,8 @@ class cmExecutionStatus; bool cmSubdirDependsCommand::InitialPass(std::vector const&, cmExecutionStatus&) { + this->Disallowed( + cmPolicies::CMP0029, + "The subdir_depends command should not be called; see CMP0029."); return true; } diff --git a/Source/cmUseMangledMesaCommand.cxx b/Source/cmUseMangledMesaCommand.cxx index 3d57f0e..3e72d75 100644 --- a/Source/cmUseMangledMesaCommand.cxx +++ b/Source/cmUseMangledMesaCommand.cxx @@ -13,6 +13,11 @@ class cmExecutionStatus; bool cmUseMangledMesaCommand::InitialPass(std::vector const& args, cmExecutionStatus&) { + if (this->Disallowed( + cmPolicies::CMP0030, + "The use_mangled_mesa command should not be called; see CMP0030.")) { + return true; + } // expected two arguments: // arguement one: the full path to gl_mangle.h // arguement two : directory for output of edited headers diff --git a/Source/cmUtilitySourceCommand.cxx b/Source/cmUtilitySourceCommand.cxx index 9b24a74..3b78abe 100644 --- a/Source/cmUtilitySourceCommand.cxx +++ b/Source/cmUtilitySourceCommand.cxx @@ -16,6 +16,11 @@ class cmExecutionStatus; bool cmUtilitySourceCommand::InitialPass(std::vector const& args, cmExecutionStatus&) { + if (this->Disallowed( + cmPolicies::CMP0034, + "The utility_source command should not be called; see CMP0034.")) { + return true; + } if (args.size() < 3) { this->SetError("called with incorrect number of arguments"); return false; diff --git a/Source/cmVariableRequiresCommand.cxx b/Source/cmVariableRequiresCommand.cxx index bff6ec5..1eb1f20 100644 --- a/Source/cmVariableRequiresCommand.cxx +++ b/Source/cmVariableRequiresCommand.cxx @@ -13,6 +13,11 @@ class cmExecutionStatus; bool cmVariableRequiresCommand::InitialPass( std::vector const& args, cmExecutionStatus&) { + if (this->Disallowed( + cmPolicies::CMP0035, + "The variable_requires command should not be called; see CMP0035.")) { + return true; + } if (args.size() < 3) { this->SetError("called with incorrect number of arguments"); return false; diff --git a/Source/cmake.cxx b/Source/cmake.cxx index b2384cd..6141f50 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -120,6 +120,8 @@ #include #include +class cmCommand; + namespace { #if defined(CMAKE_BUILD_WITH_CMAKE) @@ -177,8 +179,7 @@ cmake::cmake() this->AddDefaultGenerators(); this->AddDefaultExtraGenerators(); - this->AddScriptingCommands(); - this->AddProjectCommands(); + this->AddDefaultCommands(); // Make sure we can capture the build tool output. cmSystemTools::EnableVSConsoleOutput(); @@ -1653,14 +1654,13 @@ const char* cmake::GetCacheDefinition(const std::string& name) const return this->State->GetInitializedCacheValue(name); } -void cmake::AddScriptingCommands() +void cmake::AddDefaultCommands() { - GetScriptingCommands(this->State); -} - -void cmake::AddProjectCommands() -{ - GetProjectCommands(this->State); + std::vector const commands = GetPredefinedCommands(); + for (std::vector::const_iterator i = commands.begin(); + i != commands.end(); ++i) { + this->State->AddCommand(*i); + } } void cmake::AddDefaultGenerators() diff --git a/Source/cmake.h b/Source/cmake.h index abb13ac..5347745 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -425,8 +425,7 @@ protected: typedef std::vector RegisteredExtraGeneratorsVector; RegisteredExtraGeneratorsVector ExtraGenerators; - void AddScriptingCommands(); - void AddProjectCommands(); + void AddDefaultCommands(); void AddDefaultGenerators(); void AddDefaultExtraGenerators(); ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-commands.7.rst | 133 +++++++------- Source/CMakeLists.txt | 2 - Source/CTest/cmCTestHandlerCommand.cxx | 4 +- Source/cmBuildNameCommand.cxx | 5 + Source/cmCommand.cxx | 25 ++- Source/cmCommand.h | 9 +- Source/cmCommands.cxx | 242 +++++++++++-------------- Source/cmCommands.h | 10 +- Source/cmDeprecatedCommand.cxx | 31 ---- Source/cmDeprecatedCommand.h | 50 ----- Source/cmExportCommand.h | 1 - Source/cmExportLibraryDependenciesCommand.cxx | 6 + Source/cmLoadCommandCommand.cxx | 5 + Source/cmMakefile.cxx | 3 +- Source/cmOutputRequiredFilesCommand.cxx | 5 + Source/cmSubdirDependsCommand.cxx | 3 + Source/cmUseMangledMesaCommand.cxx | 5 + Source/cmUtilitySourceCommand.cxx | 5 + Source/cmVariableRequiresCommand.cxx | 5 + Source/cmake.cxx | 18 +- Source/cmake.h | 3 +- 21 files changed, 257 insertions(+), 313 deletions(-) delete mode 100644 Source/cmDeprecatedCommand.cxx delete mode 100644 Source/cmDeprecatedCommand.h hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 13 14:02:34 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 13 Feb 2017 14:02:34 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-110-gd8aec3f Message-ID: <20170213190234.405DDFA521@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via d8aec3f2d5478ffb7235b638d33d08e944093916 (commit) via 07c3380a6e2a09b7e5976ddbacf385b8b4cde2cd (commit) via 4168bc184e3e15ee76485e49d3bc5852b90f27de (commit) from f8c5b31f33becfba9f25ca29cc4caee6b343f93c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d8aec3f2d5478ffb7235b638d33d08e944093916 commit d8aec3f2d5478ffb7235b638d33d08e944093916 Merge: f8c5b31 07c3380 Author: Brad King AuthorDate: Mon Feb 13 14:02:33 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 13 14:02:33 2017 -0500 Merge topic 'execute_process-default-encoding' into next 07c3380a execute_process: Restore no-decoding default behavior 4168bc18 Help: Improve execute_process ENCODING option documentation https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=07c3380a6e2a09b7e5976ddbacf385b8b4cde2cd commit 07c3380a6e2a09b7e5976ddbacf385b8b4cde2cd Author: Brad King AuthorDate: Mon Feb 13 13:49:14 2017 -0500 Commit: Brad King CommitDate: Mon Feb 13 13:53:17 2017 -0500 execute_process: Restore no-decoding default behavior Since commit v3.8.0-rc1~232^2 (execute_process: Add ENCODING option for Windows child process output, 2016-11-23) we decode child process output using the console's active codepage by default. This differs from previous versions of CMake and is therefore incompatible. Changing this default will require a policy, so for now revert the default behavior back to performing no decoding. Reported-by: Nils Gladitz diff --git a/Help/command/execute_process.rst b/Help/command/execute_process.rst index 5a77735..d617243 100644 --- a/Help/command/execute_process.rst +++ b/Help/command/execute_process.rst @@ -75,10 +75,10 @@ Options: ``NONE`` Perform no decoding. This assumes that the process output is encoded in the same way as CMake's internal encoding (UTF-8). + This is the default. ``AUTO`` Use the current active console's codepage or if that isn't available then use ANSI. - This is the default. ``ANSI`` Use the ANSI codepage. ``OEM`` diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx index eb26a50..92cdf64 100644 --- a/Source/cmExecuteProcessCommand.cxx +++ b/Source/cmExecuteProcessCommand.cxx @@ -47,7 +47,7 @@ bool cmExecuteProcessCommand::InitialPass(std::vector const& args, std::string error_variable; std::string result_variable; std::string working_directory; - cmProcessOutput::Encoding encoding = cmProcessOutput::Auto; + cmProcessOutput::Encoding encoding = cmProcessOutput::None; for (size_t i = 0; i < args.size(); ++i) { if (args[i] == "COMMAND") { doing_command = true; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4168bc184e3e15ee76485e49d3bc5852b90f27de commit 4168bc184e3e15ee76485e49d3bc5852b90f27de Author: Brad King AuthorDate: Mon Feb 13 13:43:01 2017 -0500 Commit: Brad King CommitDate: Mon Feb 13 13:53:17 2017 -0500 Help: Improve execute_process ENCODING option documentation Spell out the options in a definition list and document each one. diff --git a/Help/command/execute_process.rst b/Help/command/execute_process.rst index 71233d9..5a77735 100644 --- a/Help/command/execute_process.rst +++ b/Help/command/execute_process.rst @@ -70,10 +70,21 @@ Options: ``ENCODING `` On Windows, the encoding that is used to decode output from the process. Ignored on other platforms. - Valid encoding names are: ``AUTO`` (the default), ``NONE``, ``UTF8``, - ``ANSI`` and ``OEM``. - ``AUTO`` encoding means current active console's codepage will be used - or if that isn't available then ``ANSI`` codepage will be used. + Valid encoding names are: + + ``NONE`` + Perform no decoding. This assumes that the process output is encoded + in the same way as CMake's internal encoding (UTF-8). + ``AUTO`` + Use the current active console's codepage or if that isn't + available then use ANSI. + This is the default. + ``ANSI`` + Use the ANSI codepage. + ``OEM`` + Use the original equipment manufacturer (OEM) code page. + ``UTF8`` + Use the UTF-8 codepage. If more than one ``OUTPUT_*`` or ``ERROR_*`` option is given for the same pipe the precedence is not specified. ----------------------------------------------------------------------- Summary of changes: Help/command/execute_process.rst | 19 +++++++++++++++---- Source/cmExecuteProcessCommand.cxx | 2 +- 2 files changed, 16 insertions(+), 5 deletions(-) hooks/post-receive -- CMake From daniel at pfeifer-mail.de Mon Feb 13 17:29:13 2017 From: daniel at pfeifer-mail.de (Daniel Pfeifer) Date: Mon, 13 Feb 2017 17:29:13 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-117-gd358f8b Message-ID: <20170213222913.A749AFA1DA@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via d358f8bba5418d0a8e95bd5efe0a913b8acb2a13 (commit) via e0f3931226d6f947572bce7a4b98c55812bba105 (commit) via 72dcbbe5c017a4c071187259f9594ccf02f7b466 (commit) via 7fb14775a3cce73dc0cb0d759b96059a95f7104b (commit) via 615e2a17e499b2bd53cce8da1a0cfae36d67b24a (commit) via 45b49099d9dd034fd1e7344b3bae88b0e3d3427a (commit) via 5396bc92d0162fa9a9462e15ccaae8764da8ff98 (commit) from d8aec3f2d5478ffb7235b638d33d08e944093916 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d358f8bba5418d0a8e95bd5efe0a913b8acb2a13 commit d358f8bba5418d0a8e95bd5efe0a913b8acb2a13 Merge: d8aec3f e0f3931 Author: Daniel Pfeifer AuthorDate: Mon Feb 13 17:29:12 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 13 17:29:12 2017 -0500 Merge topic 'command-cleanup' into next e0f39312 cmCommands: add commands directly to cmState 72dcbbe5 split Default commands into Scripting and Project 7fb14775 cmDisallowedCommand: extract policy checking from cmCommand 615e2a17 cmCommand: Don't prefix error message with command name 45b49099 cmCommand: make noncopyable 5396bc92 cmCommand: remove member Helper https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e0f3931226d6f947572bce7a4b98c55812bba105 commit e0f3931226d6f947572bce7a4b98c55812bba105 Author: Daniel Pfeifer AuthorDate: Fri Jan 20 22:40:16 2017 +0100 Commit: Daniel Pfeifer CommitDate: Mon Feb 13 22:39:20 2017 +0100 cmCommands: add commands directly to cmState diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index 64cd12e..b58dc62 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -1,6 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCommands.h" +#include "cmState.h" #include "cmAddCustomCommandCommand.h" #include "cmAddCustomTargetCommand.h" @@ -105,170 +106,162 @@ #include "cmWriteFileCommand.h" #endif -std::vector GetScriptingCommands() +void GetScriptingCommands(cmState* state) { - std::vector commands; + state->AddCommand(new cmBreakCommand); + state->AddCommand(new cmCMakeMinimumRequired); + state->AddCommand(new cmCMakePolicyCommand); + state->AddCommand(new cmConfigureFileCommand); + state->AddCommand(new cmContinueCommand); + state->AddCommand(new cmExecProgramCommand); + state->AddCommand(new cmExecuteProcessCommand); + state->AddCommand(new cmFileCommand); + state->AddCommand(new cmFindFileCommand); + state->AddCommand(new cmFindLibraryCommand); + state->AddCommand(new cmFindPackageCommand); + state->AddCommand(new cmFindPathCommand); + state->AddCommand(new cmFindProgramCommand); + state->AddCommand(new cmForEachCommand); + state->AddCommand(new cmFunctionCommand); + state->AddCommand(new cmGetCMakePropertyCommand); + state->AddCommand(new cmGetDirectoryPropertyCommand); + state->AddCommand(new cmGetFilenameComponentCommand); + state->AddCommand(new cmGetPropertyCommand); + state->AddCommand(new cmIfCommand); + state->AddCommand(new cmIncludeCommand); + state->AddCommand(new cmListCommand); + state->AddCommand(new cmMacroCommand); + state->AddCommand(new cmMakeDirectoryCommand); + state->AddCommand(new cmMarkAsAdvancedCommand); + state->AddCommand(new cmMathCommand); + state->AddCommand(new cmMessageCommand); + state->AddCommand(new cmOptionCommand); + state->AddCommand(new cmParseArgumentsCommand); + state->AddCommand(new cmReturnCommand); + state->AddCommand(new cmSeparateArgumentsCommand); + state->AddCommand(new cmSetCommand); + state->AddCommand(new cmSetDirectoryPropertiesCommand); + state->AddCommand(new cmSetPropertyCommand); + state->AddCommand(new cmSiteNameCommand); + state->AddCommand(new cmStringCommand); + state->AddCommand(new cmUnsetCommand); + state->AddCommand(new cmWhileCommand); - commands.push_back(new cmBreakCommand); - commands.push_back(new cmCMakeMinimumRequired); - commands.push_back(new cmCMakePolicyCommand); - commands.push_back(new cmConfigureFileCommand); - commands.push_back(new cmContinueCommand); - commands.push_back(new cmExecProgramCommand); - commands.push_back(new cmExecuteProcessCommand); - commands.push_back(new cmFileCommand); - commands.push_back(new cmFindFileCommand); - commands.push_back(new cmFindLibraryCommand); - commands.push_back(new cmFindPackageCommand); - commands.push_back(new cmFindPathCommand); - commands.push_back(new cmFindProgramCommand); - commands.push_back(new cmForEachCommand); - commands.push_back(new cmFunctionCommand); - commands.push_back(new cmGetCMakePropertyCommand); - commands.push_back(new cmGetDirectoryPropertyCommand); - commands.push_back(new cmGetFilenameComponentCommand); - commands.push_back(new cmGetPropertyCommand); - commands.push_back(new cmIfCommand); - commands.push_back(new cmIncludeCommand); - commands.push_back(new cmListCommand); - commands.push_back(new cmMacroCommand); - commands.push_back(new cmMakeDirectoryCommand); - commands.push_back(new cmMarkAsAdvancedCommand); - commands.push_back(new cmMathCommand); - commands.push_back(new cmMessageCommand); - commands.push_back(new cmOptionCommand); - commands.push_back(new cmParseArgumentsCommand); - commands.push_back(new cmReturnCommand); - commands.push_back(new cmSeparateArgumentsCommand); - commands.push_back(new cmSetCommand); - commands.push_back(new cmSetDirectoryPropertiesCommand); - commands.push_back(new cmSetPropertyCommand); - commands.push_back(new cmSiteNameCommand); - commands.push_back(new cmStringCommand); - commands.push_back(new cmUnsetCommand); - commands.push_back(new cmWhileCommand); - - commands.push_back(new cmUnexpectedCommand( + state->AddCommand(new cmUnexpectedCommand( "else", "An ELSE command was found outside of a proper " "IF ENDIF structure. Or its arguments did not match " "the opening IF command.")); - commands.push_back(new cmUnexpectedCommand( + state->AddCommand(new cmUnexpectedCommand( "elseif", "An ELSEIF command was found outside of a proper " "IF ENDIF structure.")); - commands.push_back(new cmUnexpectedCommand( + state->AddCommand(new cmUnexpectedCommand( "endforeach", "An ENDFOREACH command was found outside of a proper " "FOREACH ENDFOREACH structure. Or its arguments did " "not match the opening FOREACH command.")); - commands.push_back(new cmUnexpectedCommand( + state->AddCommand(new cmUnexpectedCommand( "endfunction", "An ENDFUNCTION command was found outside of a proper " "FUNCTION ENDFUNCTION structure. Or its arguments did not " "match the opening FUNCTION command.")); - commands.push_back(new cmUnexpectedCommand( + state->AddCommand(new cmUnexpectedCommand( "endif", "An ENDIF command was found outside of a proper " "IF ENDIF structure. Or its arguments did not match " "the opening IF command.")); - commands.push_back(new cmUnexpectedCommand( + state->AddCommand(new cmUnexpectedCommand( "endmacro", "An ENDMACRO command was found outside of a proper " "MACRO ENDMACRO structure. Or its arguments did not " "match the opening MACRO command.")); - commands.push_back(new cmUnexpectedCommand( + state->AddCommand(new cmUnexpectedCommand( "endwhile", "An ENDWHILE command was found outside of a proper " "WHILE ENDWHILE structure. Or its arguments did not " "match the opening WHILE command.")); #if defined(CMAKE_BUILD_WITH_CMAKE) - commands.push_back(new cmCMakeHostSystemInformationCommand); - commands.push_back(new cmRemoveCommand); - commands.push_back(new cmVariableWatchCommand); - commands.push_back(new cmWriteFileCommand); + state->AddCommand(new cmCMakeHostSystemInformationCommand); + state->AddCommand(new cmRemoveCommand); + state->AddCommand(new cmVariableWatchCommand); + state->AddCommand(new cmWriteFileCommand); - commands.push_back(new cmDisallowedCommand( + state->AddCommand(new cmDisallowedCommand( new cmBuildNameCommand, cmPolicies::CMP0036, "The build_name command should not be called; see CMP0036.")); - commands.push_back(new cmDisallowedCommand( + state->AddCommand(new cmDisallowedCommand( new cmUseMangledMesaCommand, cmPolicies::CMP0030, "The use_mangled_mesa command should not be called; see CMP0030.")); #endif - - return commands; } -std::vector GetProjectCommands() +void GetProjectCommands(cmState* state) { - std::vector commands; - - commands.push_back(new cmAddCustomCommandCommand); - commands.push_back(new cmAddCustomTargetCommand); - commands.push_back(new cmAddDefinitionsCommand); - commands.push_back(new cmAddDependenciesCommand); - commands.push_back(new cmAddExecutableCommand); - commands.push_back(new cmAddLibraryCommand); - commands.push_back(new cmAddSubDirectoryCommand); - commands.push_back(new cmAddTestCommand); - commands.push_back(new cmBuildCommand); - commands.push_back(new cmCreateTestSourceList); - commands.push_back(new cmDefinePropertyCommand); - commands.push_back(new cmEnableLanguageCommand); - commands.push_back(new cmEnableTestingCommand); - commands.push_back(new cmGetSourceFilePropertyCommand); - commands.push_back(new cmGetTargetPropertyCommand); - commands.push_back(new cmGetTestPropertyCommand); - commands.push_back(new cmIncludeDirectoryCommand); - commands.push_back(new cmIncludeRegularExpressionCommand); - commands.push_back(new cmInstallCommand); - commands.push_back(new cmInstallFilesCommand); - commands.push_back(new cmInstallTargetsCommand); - commands.push_back(new cmLinkDirectoriesCommand); - commands.push_back(new cmProjectCommand); - commands.push_back(new cmSetSourceFilesPropertiesCommand); - commands.push_back(new cmSetTargetPropertiesCommand); - commands.push_back(new cmSetTestsPropertiesCommand); - commands.push_back(new cmSubdirCommand); - commands.push_back(new cmTargetLinkLibrariesCommand); - commands.push_back(new cmTryCompileCommand); - commands.push_back(new cmTryRunCommand); + state->AddCommand(new cmAddCustomCommandCommand); + state->AddCommand(new cmAddCustomTargetCommand); + state->AddCommand(new cmAddDefinitionsCommand); + state->AddCommand(new cmAddDependenciesCommand); + state->AddCommand(new cmAddExecutableCommand); + state->AddCommand(new cmAddLibraryCommand); + state->AddCommand(new cmAddSubDirectoryCommand); + state->AddCommand(new cmAddTestCommand); + state->AddCommand(new cmBuildCommand); + state->AddCommand(new cmCreateTestSourceList); + state->AddCommand(new cmDefinePropertyCommand); + state->AddCommand(new cmEnableLanguageCommand); + state->AddCommand(new cmEnableTestingCommand); + state->AddCommand(new cmGetSourceFilePropertyCommand); + state->AddCommand(new cmGetTargetPropertyCommand); + state->AddCommand(new cmGetTestPropertyCommand); + state->AddCommand(new cmIncludeDirectoryCommand); + state->AddCommand(new cmIncludeRegularExpressionCommand); + state->AddCommand(new cmInstallCommand); + state->AddCommand(new cmInstallFilesCommand); + state->AddCommand(new cmInstallTargetsCommand); + state->AddCommand(new cmLinkDirectoriesCommand); + state->AddCommand(new cmProjectCommand); + state->AddCommand(new cmSetSourceFilesPropertiesCommand); + state->AddCommand(new cmSetTargetPropertiesCommand); + state->AddCommand(new cmSetTestsPropertiesCommand); + state->AddCommand(new cmSubdirCommand); + state->AddCommand(new cmTargetLinkLibrariesCommand); + state->AddCommand(new cmTryCompileCommand); + state->AddCommand(new cmTryRunCommand); #if defined(CMAKE_BUILD_WITH_CMAKE) - commands.push_back(new cmAddCompileOptionsCommand); - commands.push_back(new cmAuxSourceDirectoryCommand); - commands.push_back(new cmExportCommand); - commands.push_back(new cmFLTKWrapUICommand); - commands.push_back(new cmIncludeExternalMSProjectCommand); - commands.push_back(new cmInstallProgramsCommand); - commands.push_back(new cmLinkLibrariesCommand); - commands.push_back(new cmLoadCacheCommand); - commands.push_back(new cmQTWrapCPPCommand); - commands.push_back(new cmQTWrapUICommand); - commands.push_back(new cmRemoveDefinitionsCommand); - commands.push_back(new cmSourceGroupCommand); - commands.push_back(new cmTargetCompileDefinitionsCommand); - commands.push_back(new cmTargetCompileFeaturesCommand); - commands.push_back(new cmTargetCompileOptionsCommand); - commands.push_back(new cmTargetIncludeDirectoriesCommand); - commands.push_back(new cmTargetSourcesCommand); + state->AddCommand(new cmAddCompileOptionsCommand); + state->AddCommand(new cmAuxSourceDirectoryCommand); + state->AddCommand(new cmExportCommand); + state->AddCommand(new cmFLTKWrapUICommand); + state->AddCommand(new cmIncludeExternalMSProjectCommand); + state->AddCommand(new cmInstallProgramsCommand); + state->AddCommand(new cmLinkLibrariesCommand); + state->AddCommand(new cmLoadCacheCommand); + state->AddCommand(new cmQTWrapCPPCommand); + state->AddCommand(new cmQTWrapUICommand); + state->AddCommand(new cmRemoveDefinitionsCommand); + state->AddCommand(new cmSourceGroupCommand); + state->AddCommand(new cmTargetCompileDefinitionsCommand); + state->AddCommand(new cmTargetCompileFeaturesCommand); + state->AddCommand(new cmTargetCompileOptionsCommand); + state->AddCommand(new cmTargetIncludeDirectoriesCommand); + state->AddCommand(new cmTargetSourcesCommand); - commands.push_back(new cmDisallowedCommand( + state->AddCommand(new cmDisallowedCommand( new cmExportLibraryDependenciesCommand, cmPolicies::CMP0033, "The export_library_dependencies command should not be called; " "see CMP0033.")); - commands.push_back(new cmDisallowedCommand( + state->AddCommand(new cmDisallowedCommand( new cmLoadCommandCommand, cmPolicies::CMP0031, "The load_command command should not be called; see CMP0031.")); - commands.push_back(new cmDisallowedCommand( + state->AddCommand(new cmDisallowedCommand( new cmOutputRequiredFilesCommand, cmPolicies::CMP0032, "The output_required_files command should not be called; " "see CMP0032.")); - commands.push_back(new cmDisallowedCommand( + state->AddCommand(new cmDisallowedCommand( new cmSubdirDependsCommand, cmPolicies::CMP0029, "The subdir_depends command should not be called; see CMP0029.")); - commands.push_back(new cmDisallowedCommand( + state->AddCommand(new cmDisallowedCommand( new cmUtilitySourceCommand, cmPolicies::CMP0034, "The utility_source command should not be called; see CMP0034.")); - commands.push_back(new cmDisallowedCommand( + state->AddCommand(new cmDisallowedCommand( new cmVariableRequiresCommand, cmPolicies::CMP0035, "The variable_requires command should not be called; see CMP0035.")); #endif - - return commands; } diff --git a/Source/cmCommands.h b/Source/cmCommands.h index 4d09e42..7895ece 100644 --- a/Source/cmCommands.h +++ b/Source/cmCommands.h @@ -3,17 +3,14 @@ #ifndef cmCommands_h #define cmCommands_h -#include // IWYU pragma: keep +class cmState; -#include - -class cmCommand; /** - * Global function to return all compiled in commands. + * Global function to register all compiled in commands. * To add a new command edit cmCommands.cxx and add your command. * It is up to the caller to delete the commands created by this call. */ -std::vector GetScriptingCommands(); -std::vector GetProjectCommands(); +void GetScriptingCommands(cmState* state); +void GetProjectCommands(cmState* state); #endif diff --git a/Source/cmake.cxx b/Source/cmake.cxx index c6292ce..b2384cd 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -120,8 +120,6 @@ #include #include -class cmCommand; - namespace { #if defined(CMAKE_BUILD_WITH_CMAKE) @@ -1657,20 +1655,12 @@ const char* cmake::GetCacheDefinition(const std::string& name) const void cmake::AddScriptingCommands() { - std::vector const commands = GetScriptingCommands(); - for (std::vector::const_iterator i = commands.begin(); - i != commands.end(); ++i) { - this->State->AddCommand(*i); - } + GetScriptingCommands(this->State); } void cmake::AddProjectCommands() { - std::vector const commands = GetProjectCommands(); - for (std::vector::const_iterator i = commands.begin(); - i != commands.end(); ++i) { - this->State->AddCommand(*i); - } + GetProjectCommands(this->State); } void cmake::AddDefaultGenerators() https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=72dcbbe5c017a4c071187259f9594ccf02f7b466 commit 72dcbbe5c017a4c071187259f9594ccf02f7b466 Author: Daniel Pfeifer AuthorDate: Fri Jan 20 22:12:32 2017 +0100 Commit: Daniel Pfeifer CommitDate: Mon Feb 13 22:32:55 2017 +0100 split Default commands into Scripting and Project diff --git a/Help/manual/cmake-commands.7.rst b/Help/manual/cmake-commands.7.rst index d0c2986..611c989 100644 --- a/Help/manual/cmake-commands.7.rst +++ b/Help/manual/cmake-commands.7.rst @@ -7,91 +7,103 @@ cmake-commands(7) .. contents:: -Normal Commands -=============== +Scripting Commands +================== -These commands may be used freely in CMake projects. +These commands are always available. .. toctree:: :maxdepth: 1 - /command/add_compile_options - /command/add_custom_command - /command/add_custom_target - /command/add_definitions - /command/add_dependencies - /command/add_executable - /command/add_library - /command/add_subdirectory - /command/add_test - /command/aux_source_directory /command/break - /command/build_command /command/cmake_host_system_information /command/cmake_minimum_required /command/cmake_parse_arguments /command/cmake_policy /command/configure_file /command/continue - /command/create_test_sourcelist - /command/define_property /command/elseif /command/else - /command/enable_language - /command/enable_testing /command/endforeach /command/endfunction /command/endif /command/endmacro /command/endwhile /command/execute_process - /command/export /command/file /command/find_file /command/find_library /command/find_package /command/find_path /command/find_program - /command/fltk_wrap_ui /command/foreach /command/function /command/get_cmake_property /command/get_directory_property /command/get_filename_component /command/get_property + /command/if + /command/include + /command/list + /command/macro + /command/mark_as_advanced + /command/math + /command/message + /command/option + /command/return + /command/separate_arguments + /command/set_directory_properties + /command/set_property + /command/set + /command/site_name + /command/string + /command/unset + /command/variable_watch + /command/while + +Project Commands +================ + +These commands are available only in CMake projects. + +.. toctree:: + :maxdepth: 1 + + /command/add_compile_options + /command/add_custom_command + /command/add_custom_target + /command/add_definitions + /command/add_dependencies + /command/add_executable + /command/add_library + /command/add_subdirectory + /command/add_test + /command/aux_source_directory + /command/build_command + /command/create_test_sourcelist + /command/define_property + /command/enable_language + /command/enable_testing + /command/export + /command/fltk_wrap_ui /command/get_source_file_property /command/get_target_property /command/get_test_property - /command/if /command/include_directories /command/include_external_msproject /command/include_regular_expression - /command/include /command/install /command/link_directories /command/link_libraries - /command/list /command/load_cache - /command/macro - /command/mark_as_advanced - /command/math - /command/message - /command/option /command/project /command/qt_wrap_cpp /command/qt_wrap_ui /command/remove_definitions - /command/return - /command/separate_arguments - /command/set_directory_properties - /command/set_property - /command/set /command/set_source_files_properties /command/set_target_properties /command/set_tests_properties - /command/site_name /command/source_group - /command/string /command/target_compile_definitions /command/target_compile_features /command/target_compile_options @@ -100,9 +112,30 @@ These commands may be used freely in CMake projects. /command/target_sources /command/try_compile /command/try_run - /command/unset - /command/variable_watch - /command/while + +.. _`CTest Commands`: + +CTest Commands +============== + +These commands are available only in CTest scripts. + +.. toctree:: + :maxdepth: 1 + + /command/ctest_build + /command/ctest_configure + /command/ctest_coverage + /command/ctest_empty_binary_directory + /command/ctest_memcheck + /command/ctest_read_custom_files + /command/ctest_run_script + /command/ctest_sleep + /command/ctest_start + /command/ctest_submit + /command/ctest_test + /command/ctest_update + /command/ctest_upload Deprecated Commands =================== @@ -129,27 +162,3 @@ versions of CMake. Do not use them in new code. /command/utility_source /command/variable_requires /command/write_file - -.. _`CTest Commands`: - -CTest Commands -============== - -These commands are available only in ctest scripts. - -.. toctree:: - :maxdepth: 1 - - /command/ctest_build - /command/ctest_configure - /command/ctest_coverage - /command/ctest_empty_binary_directory - /command/ctest_memcheck - /command/ctest_read_custom_files - /command/ctest_run_script - /command/ctest_sleep - /command/ctest_start - /command/ctest_submit - /command/ctest_test - /command/ctest_update - /command/ctest_upload diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index a6754eb..64cd12e 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -105,28 +105,15 @@ #include "cmWriteFileCommand.h" #endif -std::vector GetPredefinedCommands() +std::vector GetScriptingCommands() { std::vector commands; - commands.push_back(new cmAddCustomCommandCommand); - commands.push_back(new cmAddCustomTargetCommand); - commands.push_back(new cmAddDefinitionsCommand); - commands.push_back(new cmAddDependenciesCommand); - commands.push_back(new cmAddExecutableCommand); - commands.push_back(new cmAddLibraryCommand); - commands.push_back(new cmAddSubDirectoryCommand); - commands.push_back(new cmAddTestCommand); commands.push_back(new cmBreakCommand); - commands.push_back(new cmBuildCommand); commands.push_back(new cmCMakeMinimumRequired); commands.push_back(new cmCMakePolicyCommand); commands.push_back(new cmConfigureFileCommand); commands.push_back(new cmContinueCommand); - commands.push_back(new cmCreateTestSourceList); - commands.push_back(new cmDefinePropertyCommand); - commands.push_back(new cmEnableLanguageCommand); - commands.push_back(new cmEnableTestingCommand); commands.push_back(new cmExecProgramCommand); commands.push_back(new cmExecuteProcessCommand); commands.push_back(new cmFileCommand); @@ -141,17 +128,8 @@ std::vector GetPredefinedCommands() commands.push_back(new cmGetDirectoryPropertyCommand); commands.push_back(new cmGetFilenameComponentCommand); commands.push_back(new cmGetPropertyCommand); - commands.push_back(new cmGetSourceFilePropertyCommand); - commands.push_back(new cmGetTargetPropertyCommand); - commands.push_back(new cmGetTestPropertyCommand); commands.push_back(new cmIfCommand); commands.push_back(new cmIncludeCommand); - commands.push_back(new cmIncludeDirectoryCommand); - commands.push_back(new cmIncludeRegularExpressionCommand); - commands.push_back(new cmInstallCommand); - commands.push_back(new cmInstallFilesCommand); - commands.push_back(new cmInstallTargetsCommand); - commands.push_back(new cmLinkDirectoriesCommand); commands.push_back(new cmListCommand); commands.push_back(new cmMacroCommand); commands.push_back(new cmMakeDirectoryCommand); @@ -160,21 +138,13 @@ std::vector GetPredefinedCommands() commands.push_back(new cmMessageCommand); commands.push_back(new cmOptionCommand); commands.push_back(new cmParseArgumentsCommand); - commands.push_back(new cmProjectCommand); commands.push_back(new cmReturnCommand); commands.push_back(new cmSeparateArgumentsCommand); commands.push_back(new cmSetCommand); commands.push_back(new cmSetDirectoryPropertiesCommand); commands.push_back(new cmSetPropertyCommand); - commands.push_back(new cmSetSourceFilesPropertiesCommand); - commands.push_back(new cmSetTargetPropertiesCommand); - commands.push_back(new cmSetTestsPropertiesCommand); commands.push_back(new cmSiteNameCommand); commands.push_back(new cmStringCommand); - commands.push_back(new cmSubdirCommand); - commands.push_back(new cmTargetLinkLibrariesCommand); - commands.push_back(new cmTryCompileCommand); - commands.push_back(new cmTryRunCommand); commands.push_back(new cmUnsetCommand); commands.push_back(new cmWhileCommand); @@ -207,9 +177,61 @@ std::vector GetPredefinedCommands() "match the opening WHILE command.")); #if defined(CMAKE_BUILD_WITH_CMAKE) + commands.push_back(new cmCMakeHostSystemInformationCommand); + commands.push_back(new cmRemoveCommand); + commands.push_back(new cmVariableWatchCommand); + commands.push_back(new cmWriteFileCommand); + + commands.push_back(new cmDisallowedCommand( + new cmBuildNameCommand, cmPolicies::CMP0036, + "The build_name command should not be called; see CMP0036.")); + commands.push_back(new cmDisallowedCommand( + new cmUseMangledMesaCommand, cmPolicies::CMP0030, + "The use_mangled_mesa command should not be called; see CMP0030.")); + +#endif + + return commands; +} + +std::vector GetProjectCommands() +{ + std::vector commands; + + commands.push_back(new cmAddCustomCommandCommand); + commands.push_back(new cmAddCustomTargetCommand); + commands.push_back(new cmAddDefinitionsCommand); + commands.push_back(new cmAddDependenciesCommand); + commands.push_back(new cmAddExecutableCommand); + commands.push_back(new cmAddLibraryCommand); + commands.push_back(new cmAddSubDirectoryCommand); + commands.push_back(new cmAddTestCommand); + commands.push_back(new cmBuildCommand); + commands.push_back(new cmCreateTestSourceList); + commands.push_back(new cmDefinePropertyCommand); + commands.push_back(new cmEnableLanguageCommand); + commands.push_back(new cmEnableTestingCommand); + commands.push_back(new cmGetSourceFilePropertyCommand); + commands.push_back(new cmGetTargetPropertyCommand); + commands.push_back(new cmGetTestPropertyCommand); + commands.push_back(new cmIncludeDirectoryCommand); + commands.push_back(new cmIncludeRegularExpressionCommand); + commands.push_back(new cmInstallCommand); + commands.push_back(new cmInstallFilesCommand); + commands.push_back(new cmInstallTargetsCommand); + commands.push_back(new cmLinkDirectoriesCommand); + commands.push_back(new cmProjectCommand); + commands.push_back(new cmSetSourceFilesPropertiesCommand); + commands.push_back(new cmSetTargetPropertiesCommand); + commands.push_back(new cmSetTestsPropertiesCommand); + commands.push_back(new cmSubdirCommand); + commands.push_back(new cmTargetLinkLibrariesCommand); + commands.push_back(new cmTryCompileCommand); + commands.push_back(new cmTryRunCommand); + +#if defined(CMAKE_BUILD_WITH_CMAKE) commands.push_back(new cmAddCompileOptionsCommand); commands.push_back(new cmAuxSourceDirectoryCommand); - commands.push_back(new cmCMakeHostSystemInformationCommand); commands.push_back(new cmExportCommand); commands.push_back(new cmFLTKWrapUICommand); commands.push_back(new cmIncludeExternalMSProjectCommand); @@ -218,7 +240,6 @@ std::vector GetPredefinedCommands() commands.push_back(new cmLoadCacheCommand); commands.push_back(new cmQTWrapCPPCommand); commands.push_back(new cmQTWrapUICommand); - commands.push_back(new cmRemoveCommand); commands.push_back(new cmRemoveDefinitionsCommand); commands.push_back(new cmSourceGroupCommand); commands.push_back(new cmTargetCompileDefinitionsCommand); @@ -226,13 +247,8 @@ std::vector GetPredefinedCommands() commands.push_back(new cmTargetCompileOptionsCommand); commands.push_back(new cmTargetIncludeDirectoriesCommand); commands.push_back(new cmTargetSourcesCommand); - commands.push_back(new cmVariableWatchCommand); - commands.push_back(new cmWriteFileCommand); commands.push_back(new cmDisallowedCommand( - new cmBuildNameCommand, cmPolicies::CMP0036, - "The build_name command should not be called; see CMP0036.")); - commands.push_back(new cmDisallowedCommand( new cmExportLibraryDependenciesCommand, cmPolicies::CMP0033, "The export_library_dependencies command should not be called; " "see CMP0033.")); @@ -247,9 +263,6 @@ std::vector GetPredefinedCommands() new cmSubdirDependsCommand, cmPolicies::CMP0029, "The subdir_depends command should not be called; see CMP0029.")); commands.push_back(new cmDisallowedCommand( - new cmUseMangledMesaCommand, cmPolicies::CMP0030, - "The use_mangled_mesa command should not be called; see CMP0030.")); - commands.push_back(new cmDisallowedCommand( new cmUtilitySourceCommand, cmPolicies::CMP0034, "The utility_source command should not be called; see CMP0034.")); commands.push_back(new cmDisallowedCommand( diff --git a/Source/cmCommands.h b/Source/cmCommands.h index 649dea6..4d09e42 100644 --- a/Source/cmCommands.h +++ b/Source/cmCommands.h @@ -13,6 +13,7 @@ class cmCommand; * To add a new command edit cmCommands.cxx and add your command. * It is up to the caller to delete the commands created by this call. */ -std::vector GetPredefinedCommands(); +std::vector GetScriptingCommands(); +std::vector GetProjectCommands(); #endif diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 6141f50..c6292ce 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -179,7 +179,8 @@ cmake::cmake() this->AddDefaultGenerators(); this->AddDefaultExtraGenerators(); - this->AddDefaultCommands(); + this->AddScriptingCommands(); + this->AddProjectCommands(); // Make sure we can capture the build tool output. cmSystemTools::EnableVSConsoleOutput(); @@ -1654,9 +1655,18 @@ const char* cmake::GetCacheDefinition(const std::string& name) const return this->State->GetInitializedCacheValue(name); } -void cmake::AddDefaultCommands() +void cmake::AddScriptingCommands() { - std::vector const commands = GetPredefinedCommands(); + std::vector const commands = GetScriptingCommands(); + for (std::vector::const_iterator i = commands.begin(); + i != commands.end(); ++i) { + this->State->AddCommand(*i); + } +} + +void cmake::AddProjectCommands() +{ + std::vector const commands = GetProjectCommands(); for (std::vector::const_iterator i = commands.begin(); i != commands.end(); ++i) { this->State->AddCommand(*i); diff --git a/Source/cmake.h b/Source/cmake.h index 5347745..abb13ac 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -425,7 +425,8 @@ protected: typedef std::vector RegisteredExtraGeneratorsVector; RegisteredExtraGeneratorsVector ExtraGenerators; - void AddDefaultCommands(); + void AddScriptingCommands(); + void AddProjectCommands(); void AddDefaultGenerators(); void AddDefaultExtraGenerators(); https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7fb14775a3cce73dc0cb0d759b96059a95f7104b commit 7fb14775a3cce73dc0cb0d759b96059a95f7104b Author: Daniel Pfeifer AuthorDate: Mon Dec 26 00:34:44 2016 +0100 Commit: Daniel Pfeifer CommitDate: Mon Feb 13 21:37:08 2017 +0100 cmDisallowedCommand: extract policy checking from cmCommand Implement cmDisallowedCommand as a wrapper class for cmCommand. diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 2835ee6..3b49f72 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -440,6 +440,8 @@ set(SRCS cmCreateTestSourceList.h cmDefinePropertyCommand.cxx cmDefinePropertyCommand.h + cmDisallowedCommand.cxx + cmDisallowedCommand.h cmEnableLanguageCommand.cxx cmEnableLanguageCommand.h cmEnableTestingCommand.cxx diff --git a/Source/cmBuildNameCommand.cxx b/Source/cmBuildNameCommand.cxx index 1e1cd21..12b69a8 100644 --- a/Source/cmBuildNameCommand.cxx +++ b/Source/cmBuildNameCommand.cxx @@ -16,11 +16,6 @@ class cmExecutionStatus; bool cmBuildNameCommand::InitialPass(std::vector const& args, cmExecutionStatus&) { - if (this->Disallowed( - cmPolicies::CMP0036, - "The build_name command should not be called; see CMP0036.")) { - return true; - } if (args.empty()) { this->SetError("called with incorrect number of arguments"); return false; diff --git a/Source/cmCommand.cxx b/Source/cmCommand.cxx index 15bed27..d349c91 100644 --- a/Source/cmCommand.cxx +++ b/Source/cmCommand.cxx @@ -3,7 +3,6 @@ #include "cmCommand.h" #include "cmMakefile.h" -#include "cmake.h" class cmExecutionStatus; struct cmListFileArgument; @@ -32,20 +31,3 @@ void cmCommand::SetError(const std::string& e) { this->Error = e; } - -bool cmCommand::Disallowed(cmPolicies::PolicyID pol, const char* e) -{ - switch (this->Makefile->GetPolicyStatus(pol)) { - case cmPolicies::WARN: - this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, - cmPolicies::GetPolicyWarning(pol)); - case cmPolicies::OLD: - return false; - case cmPolicies::REQUIRED_IF_USED: - case cmPolicies::REQUIRED_ALWAYS: - case cmPolicies::NEW: - this->Makefile->IssueMessage(cmake::FATAL_ERROR, e); - break; - } - return true; -} diff --git a/Source/cmCommand.h b/Source/cmCommand.h index 32f4472..9107d85 100644 --- a/Source/cmCommand.h +++ b/Source/cmCommand.h @@ -7,8 +7,6 @@ #include #include -#include "cmPolicies.h" - class cmExecutionStatus; class cmMakefile; struct cmListFileArgument; @@ -104,9 +102,6 @@ public: */ void SetError(const std::string& e); - /** Check if the command is disallowed by a policy. */ - bool Disallowed(cmPolicies::PolicyID pol, const char* e); - private: cmCommand(cmCommand const&); // = delete; cmCommand& operator=(cmCommand const&); // = delete; diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index 4c5b093..a6754eb 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -77,6 +77,7 @@ #include "cmAuxSourceDirectoryCommand.h" #include "cmBuildNameCommand.h" #include "cmCMakeHostSystemInformationCommand.h" +#include "cmDisallowedCommand.h" #include "cmExportCommand.h" #include "cmExportLibraryDependenciesCommand.h" #include "cmFLTKWrapUICommand.h" @@ -208,33 +209,52 @@ std::vector GetPredefinedCommands() #if defined(CMAKE_BUILD_WITH_CMAKE) commands.push_back(new cmAddCompileOptionsCommand); commands.push_back(new cmAuxSourceDirectoryCommand); - commands.push_back(new cmBuildNameCommand); commands.push_back(new cmCMakeHostSystemInformationCommand); commands.push_back(new cmExportCommand); - commands.push_back(new cmExportLibraryDependenciesCommand); commands.push_back(new cmFLTKWrapUICommand); commands.push_back(new cmIncludeExternalMSProjectCommand); commands.push_back(new cmInstallProgramsCommand); commands.push_back(new cmLinkLibrariesCommand); commands.push_back(new cmLoadCacheCommand); - commands.push_back(new cmLoadCommandCommand); - commands.push_back(new cmOutputRequiredFilesCommand); commands.push_back(new cmQTWrapCPPCommand); commands.push_back(new cmQTWrapUICommand); commands.push_back(new cmRemoveCommand); commands.push_back(new cmRemoveDefinitionsCommand); commands.push_back(new cmSourceGroupCommand); - commands.push_back(new cmSubdirDependsCommand); commands.push_back(new cmTargetCompileDefinitionsCommand); commands.push_back(new cmTargetCompileFeaturesCommand); commands.push_back(new cmTargetCompileOptionsCommand); commands.push_back(new cmTargetIncludeDirectoriesCommand); commands.push_back(new cmTargetSourcesCommand); - commands.push_back(new cmUseMangledMesaCommand); - commands.push_back(new cmUtilitySourceCommand); - commands.push_back(new cmVariableRequiresCommand); commands.push_back(new cmVariableWatchCommand); commands.push_back(new cmWriteFileCommand); + + commands.push_back(new cmDisallowedCommand( + new cmBuildNameCommand, cmPolicies::CMP0036, + "The build_name command should not be called; see CMP0036.")); + commands.push_back(new cmDisallowedCommand( + new cmExportLibraryDependenciesCommand, cmPolicies::CMP0033, + "The export_library_dependencies command should not be called; " + "see CMP0033.")); + commands.push_back(new cmDisallowedCommand( + new cmLoadCommandCommand, cmPolicies::CMP0031, + "The load_command command should not be called; see CMP0031.")); + commands.push_back(new cmDisallowedCommand( + new cmOutputRequiredFilesCommand, cmPolicies::CMP0032, + "The output_required_files command should not be called; " + "see CMP0032.")); + commands.push_back(new cmDisallowedCommand( + new cmSubdirDependsCommand, cmPolicies::CMP0029, + "The subdir_depends command should not be called; see CMP0029.")); + commands.push_back(new cmDisallowedCommand( + new cmUseMangledMesaCommand, cmPolicies::CMP0030, + "The use_mangled_mesa command should not be called; see CMP0030.")); + commands.push_back(new cmDisallowedCommand( + new cmUtilitySourceCommand, cmPolicies::CMP0034, + "The utility_source command should not be called; see CMP0034.")); + commands.push_back(new cmDisallowedCommand( + new cmVariableRequiresCommand, cmPolicies::CMP0035, + "The variable_requires command should not be called; see CMP0035.")); #endif return commands; diff --git a/Source/cmDisallowedCommand.cxx b/Source/cmDisallowedCommand.cxx new file mode 100644 index 0000000..ce1965d --- /dev/null +++ b/Source/cmDisallowedCommand.cxx @@ -0,0 +1,31 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmDisallowedCommand.h" + +#include "cmMakefile.h" +#include "cmake.h" + +class cmExecutionStatus; + +bool cmDisallowedCommand::InitialPass(std::vector const& args, + cmExecutionStatus& status) +{ + switch (this->Makefile->GetPolicyStatus(this->Policy)) { + case cmPolicies::WARN: + this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, + cmPolicies::GetPolicyWarning(this->Policy)); + break; + case cmPolicies::OLD: + break; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + this->Makefile->IssueMessage(cmake::FATAL_ERROR, this->Message); + return true; + } + + this->Command->SetMakefile(this->GetMakefile()); + bool const ret = this->Command->InitialPass(args, status); + this->SetError(this->Command->GetError()); + return ret; +} diff --git a/Source/cmDisallowedCommand.h b/Source/cmDisallowedCommand.h new file mode 100644 index 0000000..9cf5e6f --- /dev/null +++ b/Source/cmDisallowedCommand.h @@ -0,0 +1,50 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmDisallowedCommand_h +#define cmDisallowedCommand_h + +#include +#include +#include + +#include "cmCommand.h" +#include "cmPolicies.h" + +class cmExecutionStatus; + +class cmDisallowedCommand : public cmCommand +{ +public: + cmDisallowedCommand(cmCommand* command, cmPolicies::PolicyID policy, + const char* message) + : Command(command) + , Policy(policy) + , Message(message) + { + } + + ~cmDisallowedCommand() CM_OVERRIDE { delete this->Command; } + + cmCommand* Clone() CM_OVERRIDE + { + return new cmDisallowedCommand(this->Command->Clone(), this->Policy, + this->Message); + } + + bool InitialPass(std::vector const& args, + cmExecutionStatus& status) CM_OVERRIDE; + + bool IsScriptable() const CM_OVERRIDE + { + return this->Command->IsScriptable(); + } + + std::string GetName() const CM_OVERRIDE { return this->Command->GetName(); } + +private: + cmCommand* Command; + cmPolicies::PolicyID Policy; + const char* Message; +}; + +#endif diff --git a/Source/cmExportLibraryDependenciesCommand.cxx b/Source/cmExportLibraryDependenciesCommand.cxx index ac4f040..e3fb412 100644 --- a/Source/cmExportLibraryDependenciesCommand.cxx +++ b/Source/cmExportLibraryDependenciesCommand.cxx @@ -23,12 +23,6 @@ class cmExecutionStatus; bool cmExportLibraryDependenciesCommand::InitialPass( std::vector const& args, cmExecutionStatus&) { - if (this->Disallowed( - cmPolicies::CMP0033, - "The export_library_dependencies command should not be called; " - "see CMP0033.")) { - return true; - } if (args.empty()) { this->SetError("called with incorrect number of arguments"); return false; diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx index b6743f1..39e5684 100644 --- a/Source/cmLoadCommandCommand.cxx +++ b/Source/cmLoadCommandCommand.cxx @@ -174,11 +174,6 @@ cmLoadedCommand::~cmLoadedCommand() bool cmLoadCommandCommand::InitialPass(std::vector const& args, cmExecutionStatus&) { - if (this->Disallowed( - cmPolicies::CMP0031, - "The load_command command should not be called; see CMP0031.")) { - return true; - } if (args.empty()) { return true; } diff --git a/Source/cmOutputRequiredFilesCommand.cxx b/Source/cmOutputRequiredFilesCommand.cxx index 7a17f2c..f120971 100644 --- a/Source/cmOutputRequiredFilesCommand.cxx +++ b/Source/cmOutputRequiredFilesCommand.cxx @@ -495,11 +495,6 @@ protected: bool cmOutputRequiredFilesCommand::InitialPass( std::vector const& args, cmExecutionStatus&) { - if (this->Disallowed(cmPolicies::CMP0032, "The output_required_files " - "command should not be called; " - "see CMP0032.")) { - return true; - } if (args.size() != 2) { this->SetError("called with incorrect number of arguments"); return false; diff --git a/Source/cmSubdirDependsCommand.cxx b/Source/cmSubdirDependsCommand.cxx index 9259836..36e84d5 100644 --- a/Source/cmSubdirDependsCommand.cxx +++ b/Source/cmSubdirDependsCommand.cxx @@ -9,8 +9,5 @@ class cmExecutionStatus; bool cmSubdirDependsCommand::InitialPass(std::vector const&, cmExecutionStatus&) { - this->Disallowed( - cmPolicies::CMP0029, - "The subdir_depends command should not be called; see CMP0029."); return true; } diff --git a/Source/cmUseMangledMesaCommand.cxx b/Source/cmUseMangledMesaCommand.cxx index 3e72d75..3d57f0e 100644 --- a/Source/cmUseMangledMesaCommand.cxx +++ b/Source/cmUseMangledMesaCommand.cxx @@ -13,11 +13,6 @@ class cmExecutionStatus; bool cmUseMangledMesaCommand::InitialPass(std::vector const& args, cmExecutionStatus&) { - if (this->Disallowed( - cmPolicies::CMP0030, - "The use_mangled_mesa command should not be called; see CMP0030.")) { - return true; - } // expected two arguments: // arguement one: the full path to gl_mangle.h // arguement two : directory for output of edited headers diff --git a/Source/cmUtilitySourceCommand.cxx b/Source/cmUtilitySourceCommand.cxx index 3b78abe..9b24a74 100644 --- a/Source/cmUtilitySourceCommand.cxx +++ b/Source/cmUtilitySourceCommand.cxx @@ -16,11 +16,6 @@ class cmExecutionStatus; bool cmUtilitySourceCommand::InitialPass(std::vector const& args, cmExecutionStatus&) { - if (this->Disallowed( - cmPolicies::CMP0034, - "The utility_source command should not be called; see CMP0034.")) { - return true; - } if (args.size() < 3) { this->SetError("called with incorrect number of arguments"); return false; diff --git a/Source/cmVariableRequiresCommand.cxx b/Source/cmVariableRequiresCommand.cxx index 1eb1f20..bff6ec5 100644 --- a/Source/cmVariableRequiresCommand.cxx +++ b/Source/cmVariableRequiresCommand.cxx @@ -13,11 +13,6 @@ class cmExecutionStatus; bool cmVariableRequiresCommand::InitialPass( std::vector const& args, cmExecutionStatus&) { - if (this->Disallowed( - cmPolicies::CMP0035, - "The variable_requires command should not be called; see CMP0035.")) { - return true; - } if (args.size() < 3) { this->SetError("called with incorrect number of arguments"); return false; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=615e2a17e499b2bd53cce8da1a0cfae36d67b24a commit 615e2a17e499b2bd53cce8da1a0cfae36d67b24a Author: Daniel Pfeifer AuthorDate: Sat Jan 7 13:48:44 2017 +0100 Commit: Daniel Pfeifer CommitDate: Mon Feb 13 20:49:20 2017 +0100 cmCommand: Don't prefix error message with command name Instead, prefix the error message at the two places where the errors are handled: cmMakefile and cmCTestHandlerCommand. diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx index a989b12..2a67d47 100644 --- a/Source/CTest/cmCTestHandlerCommand.cxx +++ b/Source/CTest/cmCTestHandlerCommand.cxx @@ -123,8 +123,8 @@ bool cmCTestHandlerCommand::InitialPass(std::vector const& args, if (capureCMakeError) { this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR], "-1"); - const char* err = this->GetError(); - if (err && !cmSystemTools::FindLastString(err, "unknown error.")) { + std::string const err = this->GetName() + " " + this->GetError(); + if (!cmSystemTools::FindLastString(err.c_str(), "unknown error.")) { cmCTestLog(this->CTest, ERROR_MESSAGE, err << " error from command\n"); } // return success because failure is recorded in CAPTURE_CMAKE_ERROR diff --git a/Source/cmCommand.cxx b/Source/cmCommand.cxx index 181b412..15bed27 100644 --- a/Source/cmCommand.cxx +++ b/Source/cmCommand.cxx @@ -23,17 +23,14 @@ bool cmCommand::InvokeInitialPass(const std::vector& args, const char* cmCommand::GetError() { if (this->Error.empty()) { - this->Error = this->GetName(); - this->Error += " unknown error."; + return "unknown error."; } return this->Error.c_str(); } void cmCommand::SetError(const std::string& e) { - this->Error = this->GetName(); - this->Error += " "; - this->Error += e; + this->Error = e; } bool cmCommand::Disallowed(cmPolicies::PolicyID pol, const char* e) diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 618f694..bdaca97 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -281,7 +281,8 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff, if (!invokeSucceeded || hadNestedError) { if (!hadNestedError) { // The command invocation requested that we report an error. - this->IssueMessage(cmake::FATAL_ERROR, pcmd->GetError()); + std::string const error = name + " " + pcmd->GetError(); + this->IssueMessage(cmake::FATAL_ERROR, error); } result = false; if (this->GetCMakeInstance()->GetWorkingMode() != cmake::NORMAL_MODE) { https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=45b49099d9dd034fd1e7344b3bae88b0e3d3427a commit 45b49099d9dd034fd1e7344b3bae88b0e3d3427a Author: Daniel Pfeifer AuthorDate: Sun Dec 25 23:50:18 2016 +0100 Commit: Daniel Pfeifer CommitDate: Mon Feb 13 20:48:29 2017 +0100 cmCommand: make noncopyable diff --git a/Source/cmCommand.h b/Source/cmCommand.h index ff30638..32f4472 100644 --- a/Source/cmCommand.h +++ b/Source/cmCommand.h @@ -107,6 +107,10 @@ public: /** Check if the command is disallowed by a policy. */ bool Disallowed(cmPolicies::PolicyID pol, const char* e); +private: + cmCommand(cmCommand const&); // = delete; + cmCommand& operator=(cmCommand const&); // = delete; + protected: cmMakefile* Makefile; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=5396bc92d0162fa9a9462e15ccaae8764da8ff98 commit 5396bc92d0162fa9a9462e15ccaae8764da8ff98 Author: Daniel Pfeifer AuthorDate: Sun Dec 25 23:27:48 2016 +0100 Commit: Daniel Pfeifer CommitDate: Mon Feb 13 20:48:29 2017 +0100 cmCommand: remove member Helper The Helper member is used in a single derived class only. Remove it from the base class to the only place where it is used. diff --git a/Source/cmCommand.h b/Source/cmCommand.h index d9fd5a2..ff30638 100644 --- a/Source/cmCommand.h +++ b/Source/cmCommand.h @@ -7,7 +7,6 @@ #include #include -#include "cmCommandArgumentsHelper.h" #include "cmPolicies.h" class cmExecutionStatus; @@ -110,7 +109,6 @@ public: protected: cmMakefile* Makefile; - cmCommandArgumentsHelper Helper; private: std::string Error; diff --git a/Source/cmExportCommand.h b/Source/cmExportCommand.h index 99dac7d..a0224d0 100644 --- a/Source/cmExportCommand.h +++ b/Source/cmExportCommand.h @@ -41,6 +41,7 @@ public: std::string GetName() const CM_OVERRIDE { return "export"; } private: + cmCommandArgumentsHelper Helper; cmCommandArgumentGroup ArgumentGroup; cmCAStringVector Targets; cmCAEnabler Append; ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-commands.7.rst | 133 +++++++------- Source/CMakeLists.txt | 2 + Source/CTest/cmCTestHandlerCommand.cxx | 4 +- Source/cmBuildNameCommand.cxx | 5 - Source/cmCommand.cxx | 25 +-- Source/cmCommand.h | 9 +- Source/cmCommands.cxx | 242 ++++++++++++++----------- Source/cmCommands.h | 10 +- Source/cmDisallowedCommand.cxx | 31 ++++ Source/cmDisallowedCommand.h | 50 +++++ Source/cmExportCommand.h | 1 + Source/cmExportLibraryDependenciesCommand.cxx | 6 - Source/cmLoadCommandCommand.cxx | 5 - Source/cmMakefile.cxx | 3 +- Source/cmOutputRequiredFilesCommand.cxx | 5 - Source/cmSubdirDependsCommand.cxx | 3 - Source/cmUseMangledMesaCommand.cxx | 5 - Source/cmUtilitySourceCommand.cxx | 5 - Source/cmVariableRequiresCommand.cxx | 5 - Source/cmake.cxx | 18 +- Source/cmake.h | 3 +- 21 files changed, 313 insertions(+), 257 deletions(-) create mode 100644 Source/cmDisallowedCommand.cxx create mode 100644 Source/cmDisallowedCommand.h hooks/post-receive -- CMake From kwrobot at kitware.com Tue Feb 14 00:01:09 2017 From: kwrobot at kitware.com (Kitware Robot) Date: Tue, 14 Feb 2017 00:01:09 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-59-g11e9605 Message-ID: <20170214050109.8BD76FA257@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 11e9605179e340833d95115fb0178d2ee84b3e24 (commit) from 38bfe65eba21c697d05e8bed79635fc125cdac17 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=11e9605179e340833d95115fb0178d2ee84b3e24 commit 11e9605179e340833d95115fb0178d2ee84b3e24 Author: Kitware Robot AuthorDate: Tue Feb 14 00:01:05 2017 -0500 Commit: Kitware Robot CommitDate: Tue Feb 14 00:01:05 2017 -0500 CMake Nightly Date Stamp diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index bb79b6d..8b1882f 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 8) -set(CMake_VERSION_PATCH 20170213) +set(CMake_VERSION_PATCH 20170214) #set(CMake_VERSION_RC 1) ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 14 08:30:29 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 14 Feb 2017 08:30:29 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-62-g31e96cc Message-ID: <20170214133029.A1A30FA6C4@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 31e96ccca23a034700e780470bf48cff0d7fd15e (commit) via 07c3380a6e2a09b7e5976ddbacf385b8b4cde2cd (commit) via 4168bc184e3e15ee76485e49d3bc5852b90f27de (commit) from 11e9605179e340833d95115fb0178d2ee84b3e24 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=31e96ccca23a034700e780470bf48cff0d7fd15e commit 31e96ccca23a034700e780470bf48cff0d7fd15e Merge: 11e9605 07c3380 Author: Brad King AuthorDate: Tue Feb 14 08:30:27 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 14 08:30:27 2017 -0500 Merge topic 'execute_process-default-encoding' 07c3380a execute_process: Restore no-decoding default behavior 4168bc18 Help: Improve execute_process ENCODING option documentation ----------------------------------------------------------------------- Summary of changes: Help/command/execute_process.rst | 19 +++++++++++++++---- Source/cmExecuteProcessCommand.cxx | 2 +- 2 files changed, 16 insertions(+), 5 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 14 08:30:32 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 14 Feb 2017 08:30:32 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-64-gb7d8d80 Message-ID: <20170214133032.888F7FA27E@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via b7d8d80a62d2e2c31863efedd41945c2e9db9bcf (commit) via 44f3acb202c316bc6a863a1823aaafae486c899a (commit) from 31e96ccca23a034700e780470bf48cff0d7fd15e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b7d8d80a62d2e2c31863efedd41945c2e9db9bcf commit b7d8d80a62d2e2c31863efedd41945c2e9db9bcf Merge: 31e96cc 44f3acb Author: Brad King AuthorDate: Tue Feb 14 08:30:30 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 14 08:30:30 2017 -0500 Merge topic 'cmake_provide_include_dir_for_toolkit' 44f3acb2 CUDA: Detect the toolkit include directories ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-variables.7.rst | 1 + .../CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES.rst | 7 ++++ Modules/CMakeCUDACompiler.cmake.in | 2 ++ Modules/CMakeDetermineCUDACompiler.cmake | 34 +++++++++++++++++--- Tests/Cuda/CMakeLists.txt | 1 + Tests/Cuda/ToolkitInclude/CMakeLists.txt | 11 +++++++ Tests/Cuda/ToolkitInclude/main.cpp | 8 +++++ Tests/CudaOnly/EnableStandard/CMakeLists.txt | 11 +++++++ 8 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 Help/variable/CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES.rst create mode 100644 Tests/Cuda/ToolkitInclude/CMakeLists.txt create mode 100644 Tests/Cuda/ToolkitInclude/main.cpp hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 14 08:30:35 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 14 Feb 2017 08:30:35 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-71-gdc58d9f Message-ID: <20170214133035.27C8CFA6D1@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via dc58d9f06d921e3e5d03b9adf9a4d9ec5359d9ba (commit) via e0f3931226d6f947572bce7a4b98c55812bba105 (commit) via 72dcbbe5c017a4c071187259f9594ccf02f7b466 (commit) via 7fb14775a3cce73dc0cb0d759b96059a95f7104b (commit) via 615e2a17e499b2bd53cce8da1a0cfae36d67b24a (commit) via 45b49099d9dd034fd1e7344b3bae88b0e3d3427a (commit) via 5396bc92d0162fa9a9462e15ccaae8764da8ff98 (commit) from b7d8d80a62d2e2c31863efedd41945c2e9db9bcf (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=dc58d9f06d921e3e5d03b9adf9a4d9ec5359d9ba commit dc58d9f06d921e3e5d03b9adf9a4d9ec5359d9ba Merge: b7d8d80 e0f3931 Author: Brad King AuthorDate: Tue Feb 14 08:30:33 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 14 08:30:33 2017 -0500 Merge topic 'command-cleanup' e0f39312 cmCommands: add commands directly to cmState 72dcbbe5 split Default commands into Scripting and Project 7fb14775 cmDisallowedCommand: extract policy checking from cmCommand 615e2a17 cmCommand: Don't prefix error message with command name 45b49099 cmCommand: make noncopyable 5396bc92 cmCommand: remove member Helper ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-commands.7.rst | 133 +++++++------- Source/CMakeLists.txt | 2 + Source/CTest/cmCTestHandlerCommand.cxx | 4 +- Source/cmBuildNameCommand.cxx | 5 - Source/cmCommand.cxx | 25 +-- Source/cmCommand.h | 9 +- Source/cmCommands.cxx | 242 ++++++++++++++----------- Source/cmCommands.h | 10 +- Source/cmDisallowedCommand.cxx | 31 ++++ Source/cmDisallowedCommand.h | 50 +++++ Source/cmExportCommand.h | 1 + Source/cmExportLibraryDependenciesCommand.cxx | 6 - Source/cmLoadCommandCommand.cxx | 5 - Source/cmMakefile.cxx | 3 +- Source/cmOutputRequiredFilesCommand.cxx | 5 - Source/cmSubdirDependsCommand.cxx | 3 - Source/cmUseMangledMesaCommand.cxx | 5 - Source/cmUtilitySourceCommand.cxx | 5 - Source/cmVariableRequiresCommand.cxx | 5 - Source/cmake.cxx | 18 +- Source/cmake.h | 3 +- 21 files changed, 313 insertions(+), 257 deletions(-) create mode 100644 Source/cmDisallowedCommand.cxx create mode 100644 Source/cmDisallowedCommand.h hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 14 08:31:30 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 14 Feb 2017 08:31:30 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-122-ge6f8142 Message-ID: <20170214133130.C0215FA6E3@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via e6f8142ae6ad655897827031acb791d15f6c2896 (commit) via dc58d9f06d921e3e5d03b9adf9a4d9ec5359d9ba (commit) via b7d8d80a62d2e2c31863efedd41945c2e9db9bcf (commit) via 31e96ccca23a034700e780470bf48cff0d7fd15e (commit) via 11e9605179e340833d95115fb0178d2ee84b3e24 (commit) from d358f8bba5418d0a8e95bd5efe0a913b8acb2a13 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e6f8142ae6ad655897827031acb791d15f6c2896 commit e6f8142ae6ad655897827031acb791d15f6c2896 Merge: d358f8b dc58d9f Author: Brad King AuthorDate: Tue Feb 14 08:30:48 2017 -0500 Commit: Brad King CommitDate: Tue Feb 14 08:30:48 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 14 08:33:19 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 14 Feb 2017 08:33:19 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-74-g03be8cc Message-ID: <20170214133319.76BF9FA6FB@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 03be8ccbf607b378c7ffcfd2ffe6797612837efa (commit) via f0e5954fcee6b546eaa858b1e3323f529d906d04 (commit) via bcd28f04b161be26b3b95ee3bbe2c4d8df5c6bac (commit) from dc58d9f06d921e3e5d03b9adf9a4d9ec5359d9ba (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 14 08:33:19 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 14 Feb 2017 08:33:19 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-126-gef4c923 Message-ID: <20170214133319.90069FA6E8@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via ef4c9231c4c33905d77f9a86b3d6f201d93fefb2 (commit) via 03be8ccbf607b378c7ffcfd2ffe6797612837efa (commit) via f0e5954fcee6b546eaa858b1e3323f529d906d04 (commit) via bcd28f04b161be26b3b95ee3bbe2c4d8df5c6bac (commit) from e6f8142ae6ad655897827031acb791d15f6c2896 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ef4c9231c4c33905d77f9a86b3d6f201d93fefb2 commit ef4c9231c4c33905d77f9a86b3d6f201d93fefb2 Merge: e6f8142 03be8cc Author: Brad King AuthorDate: Tue Feb 14 08:33:08 2017 -0500 Commit: Brad King CommitDate: Tue Feb 14 08:33:08 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 14 08:33:19 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 14 Feb 2017 08:33:19 -0500 (EST) Subject: [Cmake-commits] CMake branch, release, updated. v3.8.0-rc1-9-gf0e5954 Message-ID: <20170214133319.DD5E6FA6E8@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, release has been updated via f0e5954fcee6b546eaa858b1e3323f529d906d04 (commit) via 07c3380a6e2a09b7e5976ddbacf385b8b4cde2cd (commit) via 4168bc184e3e15ee76485e49d3bc5852b90f27de (commit) via bcd28f04b161be26b3b95ee3bbe2c4d8df5c6bac (commit) via 44f3acb202c316bc6a863a1823aaafae486c899a (commit) from 6cbad490c2fdbd9bdc67b406b9f2dcdc21e08ddb (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- Summary of changes: Help/command/execute_process.rst | 19 ++++++++--- Help/manual/cmake-variables.7.rst | 1 + .../CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES.rst | 7 ++++ Modules/CMakeCUDACompiler.cmake.in | 2 ++ Modules/CMakeDetermineCUDACompiler.cmake | 34 +++++++++++++++++--- Source/cmExecuteProcessCommand.cxx | 2 +- Tests/Cuda/CMakeLists.txt | 1 + Tests/Cuda/ToolkitInclude/CMakeLists.txt | 11 +++++++ Tests/Cuda/ToolkitInclude/main.cpp | 8 +++++ Tests/CudaOnly/EnableStandard/CMakeLists.txt | 11 +++++++ 10 files changed, 87 insertions(+), 9 deletions(-) create mode 100644 Help/variable/CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES.rst create mode 100644 Tests/Cuda/ToolkitInclude/CMakeLists.txt create mode 100644 Tests/Cuda/ToolkitInclude/main.cpp hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 14 09:22:30 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 14 Feb 2017 09:22:30 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-129-g726660c Message-ID: <20170214142230.6FDD4FA354@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 726660c22aa5116222cc0b5d713899b8fac92a24 (commit) via ff843dbd547d06b9dcb25c3970e857fe395f2dcf (commit) via ced3396d048c8389327f661a99986fef51ee8a3f (commit) from ef4c9231c4c33905d77f9a86b3d6f201d93fefb2 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=726660c22aa5116222cc0b5d713899b8fac92a24 commit 726660c22aa5116222cc0b5d713899b8fac92a24 Merge: ef4c923 ff843db Author: Brad King AuthorDate: Tue Feb 14 09:22:29 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 14 09:22:29 2017 -0500 Merge topic 'update-kwsys' into next ff843dbd Merge branch 'upstream-KWSys' into update-kwsys ced3396d KWSys 2017-02-14 (5c6f7836) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ff843dbd547d06b9dcb25c3970e857fe395f2dcf commit ff843dbd547d06b9dcb25c3970e857fe395f2dcf Merge: 03be8cc ced3396 Author: Brad King AuthorDate: Tue Feb 14 09:22:07 2017 -0500 Commit: Brad King CommitDate: Tue Feb 14 09:22:07 2017 -0500 Merge branch 'upstream-KWSys' into update-kwsys * upstream-KWSys: KWSys 2017-02-14 (5c6f7836) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ced3396d048c8389327f661a99986fef51ee8a3f commit ced3396d048c8389327f661a99986fef51ee8a3f Author: KWSys Upstream AuthorDate: Tue Feb 14 09:21:42 2017 -0500 Commit: Brad King CommitDate: Tue Feb 14 09:22:06 2017 -0500 KWSys 2017-02-14 (5c6f7836) Code extracted from: https://gitlab.kitware.com/utils/kwsys.git at commit 5c6f78360d93742bace501bef0c45664d317972a (master). Upstream Shortlog ----------------- Brad King (1): a673a722 SystemInformation: Fix -Wconversion warning Nicol?s B?rtolo (1): 9c4230b7 SystemInformation: Fix counts of logical and physical cores diff --git a/SystemInformation.cxx b/SystemInformation.cxx index e01dcd7..86f7552 100644 --- a/SystemInformation.cxx +++ b/SystemInformation.cxx @@ -35,8 +35,13 @@ #include "SystemInformation.hxx.in" #endif +#include +#include +#include #include #include +#include +#include #include #include #include @@ -394,7 +399,6 @@ public: bool SupportsMP; bool HasMMXPlus; bool HasSSEMMX; - bool SupportsHyperthreading; unsigned int LogicalProcessorsPerPhysical; int APIC_ID; CPUPowerManagement PowerManagement; @@ -463,10 +467,9 @@ protected: unsigned int NumberOfLogicalCPU; unsigned int NumberOfPhysicalCPU; - int CPUCount(); // For windows - unsigned char LogicalCPUPerPhysicalCPU(); + void CPUCountWindows(); // For windows unsigned char GetAPICId(); // For windows - bool IsHyperThreadingSupported(); + bool IsSMTSupported(); static LongLong GetCyclesDifference(DELAY_FUNC, unsigned int); // For windows // For Linux and Cygwin, /proc/cpuinfo formats are slightly different @@ -1542,7 +1545,7 @@ void SystemInformationImplementation::RunCPUCheck() RetrieveProcessorSerialNumber(); } - this->CPUCount(); + this->CPUCountWindows(); #elif defined(__APPLE__) this->ParseSysCtl(); @@ -2090,16 +2093,10 @@ bool SystemInformationImplementation::RetrieveCPUFeatures() // Retrieve Intel specific extended features. if (this->ChipManufacturer == Intel) { - this->Features.ExtendedFeatures.SupportsHyperthreading = - ((cpuinfo[3] & 0x10000000) != - 0); // Intel specific: Hyperthreading --> Bit 28 - this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = - (this->Features.ExtendedFeatures.SupportsHyperthreading) - ? ((cpuinfo[1] & 0x00FF0000) >> 16) - : 1; - - if ((this->Features.ExtendedFeatures.SupportsHyperthreading) && - (this->Features.HasAPIC)) { + bool SupportsSMT = + ((cpuinfo[3] & 0x10000000) != 0); // Intel specific: SMT --> Bit 28 + + if ((SupportsSMT) && (this->Features.HasAPIC)) { // Retrieve APIC information if there is one present. this->Features.ExtendedFeatures.APIC_ID = ((cpuinfo[1] & 0xFF000000) >> 24); @@ -3401,7 +3398,7 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() fclose(fd); buffer.resize(fileSize - 2); // Number of logical CPUs (combination of multiple processors, multi-core - // and hyperthreading) + // and SMT) size_t pos = buffer.find("processor\t"); while (pos != buffer.npos) { this->NumberOfLogicalCPU++; @@ -3409,30 +3406,25 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() } #ifdef __linux - // Find the largest physical id. - int maxId = -1; + // Count sockets. + std::set PhysicalIDs; std::string idc = this->ExtractValueFromCpuInfoFile(buffer, "physical id"); while (this->CurrentPositionInFile != buffer.npos) { int id = atoi(idc.c_str()); - if (id > maxId) { - maxId = id; - } + PhysicalIDs.insert(id); idc = this->ExtractValueFromCpuInfoFile(buffer, "physical id", this->CurrentPositionInFile + 1); } + uint64_t NumberOfSockets = PhysicalIDs.size(); + NumberOfSockets = std::max(NumberOfSockets, (uint64_t)1); // Physical ids returned by Linux don't distinguish cores. // We want to record the total number of cores in this->NumberOfPhysicalCPU // (checking only the first proc) - std::string cores = this->ExtractValueFromCpuInfoFile(buffer, "cpu cores"); - int numberOfCoresPerCPU = atoi(cores.c_str()); - if (maxId > 0) { - this->NumberOfPhysicalCPU = - static_cast(numberOfCoresPerCPU * (maxId + 1)); - } else { - // Linux Sparc: get cpu count - this->NumberOfPhysicalCPU = - atoi(this->ExtractValueFromCpuInfoFile(buffer, "ncpus active").c_str()); - } + std::string Cores = this->ExtractValueFromCpuInfoFile(buffer, "cpu cores"); + unsigned int NumberOfCoresPerSocket = (unsigned int)atoi(Cores.c_str()); + NumberOfCoresPerSocket = std::max(NumberOfCoresPerSocket, 1u); + this->NumberOfPhysicalCPU = + NumberOfCoresPerSocket * (unsigned int)NumberOfSockets; #else // __CYGWIN__ // does not have "physical id" entries, neither "cpu cores" @@ -3447,7 +3439,7 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile() if (this->NumberOfPhysicalCPU <= 0) { this->NumberOfPhysicalCPU = 1; } - // LogicalProcessorsPerPhysical>1 => hyperthreading. + // LogicalProcessorsPerPhysical>1 => SMT. this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = this->NumberOfLogicalCPU / this->NumberOfPhysicalCPU; @@ -4322,68 +4314,10 @@ void SystemInformationImplementation::DelayOverhead(unsigned int uiMS) (void)uiMS; } -/** Return the number of logical CPU per physical CPUs Works only for windows - */ -unsigned char SystemInformationImplementation::LogicalCPUPerPhysicalCPU(void) -{ -#ifdef __APPLE__ - size_t len = 4; - int cores_per_package = 0; - int err = sysctlbyname("machdep.cpu.cores_per_package", &cores_per_package, - &len, NULL, 0); - if (err != 0) { - return 1; // That name was not found, default to 1 - } - return static_cast(cores_per_package); -#else - int Regs[4] = { 0, 0, 0, 0 }; -#if USE_CPUID - if (!this->IsHyperThreadingSupported()) { - return static_cast(1); // HT not supported - } - call_cpuid(1, Regs); -#endif - return static_cast((Regs[1] & NUM_LOGICAL_BITS) >> 16); -#endif -} - /** Works only for windows */ -bool SystemInformationImplementation::IsHyperThreadingSupported() +bool SystemInformationImplementation::IsSMTSupported() { - if (this->Features.ExtendedFeatures.SupportsHyperthreading) { - return true; - } - -#if USE_CPUID - int Regs[4] = { 0, 0, 0, 0 }, VendorId[4] = { 0, 0, 0, 0 }; - // Get vendor id string - if (!call_cpuid(0, VendorId)) { - return false; - } - // eax contains family processor type - // edx has info about the availability of hyper-Threading - if (!call_cpuid(1, Regs)) { - return false; - } - - if (((Regs[0] & FAMILY_ID) == PENTIUM4_ID) || (Regs[0] & EXT_FAMILY_ID)) { - if (VendorId[1] == 0x756e6547) // 'uneG' - { - if (VendorId[3] == 0x49656e69) // 'Ieni' - { - if (VendorId[2] == 0x6c65746e) // 'letn' - { - // Genuine Intel with hyper-Threading technology - this->Features.ExtendedFeatures.SupportsHyperthreading = - ((Regs[3] & HT_BIT) != 0); - return this->Features.ExtendedFeatures.SupportsHyperthreading; - } - } - } - } -#endif - - return 0; // Not genuine Intel processor + return this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical > 1; } /** Return the APIC Id. Works only for windows. */ @@ -4392,7 +4326,7 @@ unsigned char SystemInformationImplementation::GetAPICId() int Regs[4] = { 0, 0, 0, 0 }; #if USE_CPUID - if (!this->IsHyperThreadingSupported()) { + if (!this->IsSMTSupported()) { return static_cast(-1); // HT not supported } // Logical processor = 1 call_cpuid(1, Regs); @@ -4402,102 +4336,46 @@ unsigned char SystemInformationImplementation::GetAPICId() } /** Count the number of CPUs. Works only on windows. */ -int SystemInformationImplementation::CPUCount() +void SystemInformationImplementation::CPUCountWindows() { #if defined(_WIN32) - unsigned char StatusFlag = 0; - SYSTEM_INFO info; - + std::vector ProcInfo; this->NumberOfPhysicalCPU = 0; this->NumberOfLogicalCPU = 0; - info.dwNumberOfProcessors = 0; - GetSystemInfo(&info); - - // Number of physical processors in a non-Intel system - // or in a 32-bit Intel system with Hyper-Threading technology disabled - this->NumberOfPhysicalCPU = (unsigned char)info.dwNumberOfProcessors; - - if (this->IsHyperThreadingSupported()) { - unsigned char HT_Enabled = 0; - this->NumberOfLogicalCPU = this->LogicalCPUPerPhysicalCPU(); - if (this->NumberOfLogicalCPU >= - 1) // >1 Doesn't mean HT is enabled in the BIOS - { - HANDLE hCurrentProcessHandle; -#ifndef _WIN64 -#define DWORD_PTR DWORD -#endif - DWORD_PTR dwProcessAffinity; - DWORD_PTR dwSystemAffinity; - DWORD dwAffinityMask; - - // Calculate the appropriate shifts and mask based on the - // number of logical processors. - unsigned int i = 1; - unsigned char PHY_ID_MASK = 0xFF; - // unsigned char PHY_ID_SHIFT = 0; - - while (i < this->NumberOfLogicalCPU) { - i *= 2; - PHY_ID_MASK <<= 1; - // PHY_ID_SHIFT++; - } - hCurrentProcessHandle = GetCurrentProcess(); - GetProcessAffinityMask(hCurrentProcessHandle, &dwProcessAffinity, - &dwSystemAffinity); - - // Check if available process affinity mask is equal to the - // available system affinity mask - if (dwProcessAffinity != dwSystemAffinity) { - StatusFlag = HT_CANNOT_DETECT; - this->NumberOfPhysicalCPU = (unsigned char)-1; - return StatusFlag; - } - - dwAffinityMask = 1; - while (dwAffinityMask != 0 && dwAffinityMask <= dwProcessAffinity) { - // Check if this CPU is available - if (dwAffinityMask & dwProcessAffinity) { - if (SetProcessAffinityMask(hCurrentProcessHandle, dwAffinityMask)) { - unsigned char APIC_ID, LOG_ID; - Sleep(0); // Give OS time to switch CPU - - APIC_ID = GetAPICId(); - LOG_ID = APIC_ID & ~PHY_ID_MASK; - - if (LOG_ID != 0) { - HT_Enabled = 1; - } - } - } - dwAffinityMask = dwAffinityMask << 1; - } - // Reset the processor affinity - SetProcessAffinityMask(hCurrentProcessHandle, dwProcessAffinity); + { + DWORD Length = 0; + DWORD rc = GetLogicalProcessorInformation(NULL, &Length); + assert(FALSE == rc); + (void)rc; // Silence unused variable warning in Borland C++ 5.81 + assert(GetLastError() == ERROR_INSUFFICIENT_BUFFER); + ProcInfo.resize(Length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)); + rc = GetLogicalProcessorInformation(&ProcInfo[0], &Length); + assert(rc != FALSE); + (void)rc; // Silence unused variable warning in Borland C++ 5.81 + } + + typedef std::vector::iterator + pinfoIt_t; + for (pinfoIt_t it = ProcInfo.begin(); it != ProcInfo.end(); ++it) { + SYSTEM_LOGICAL_PROCESSOR_INFORMATION PInfo = *it; + if (PInfo.Relationship != RelationProcessorCore) { + continue; + } - if (this->NumberOfLogicalCPU == - 1) // Normal P4 : HT is disabled in hardware - { - StatusFlag = HT_DISABLED; - } else { - if (HT_Enabled) { - // Total physical processors in a Hyper-Threading enabled system. - this->NumberOfPhysicalCPU /= (this->NumberOfLogicalCPU); - StatusFlag = HT_ENABLED; - } else { - StatusFlag = HT_SUPPORTED_NOT_ENABLED; - } - } + std::bitset::digits> ProcMask( + (unsigned long long)PInfo.ProcessorMask); + unsigned int count = (unsigned int)ProcMask.count(); + if (count == 0) { // I think this should never happen, but just to be safe. + continue; } - } else { - // Processors do not have Hyper-Threading technology - StatusFlag = HT_NOT_CAPABLE; - this->NumberOfLogicalCPU = 1; + this->NumberOfPhysicalCPU++; + this->NumberOfLogicalCPU += (unsigned int)count; + this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = count; } - return StatusFlag; + this->NumberOfPhysicalCPU = std::max(1u, this->NumberOfPhysicalCPU); + this->NumberOfLogicalCPU = std::max(1u, this->NumberOfLogicalCPU); #else - return 0; #endif } @@ -4559,8 +4437,14 @@ bool SystemInformationImplementation::ParseSysCtl() sysctlbyname("hw.physicalcpu", &this->NumberOfPhysicalCPU, &len, NULL, 0); len = sizeof(this->NumberOfLogicalCPU); sysctlbyname("hw.logicalcpu", &this->NumberOfLogicalCPU, &len, NULL, 0); + + int cores_per_package = 0; + len = sizeof(cores_per_package); + err = sysctlbyname("machdep.cpu.cores_per_package", &cores_per_package, &len, + NULL, 0); + // That name was not found, default to 1 this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = - this->LogicalCPUPerPhysicalCPU(); + err != 0 ? 1 : static_cast(cores_per_package); len = sizeof(value); sysctlbyname("hw.cpufrequency", &value, &len, NULL, 0); diff --git a/SystemInformation.hxx.in b/SystemInformation.hxx.in index 0fc1067..cc09393 100644 --- a/SystemInformation.hxx.in +++ b/SystemInformation.hxx.in @@ -67,7 +67,7 @@ public: bool Is64Bits(); - unsigned int GetNumberOfLogicalCPU(); // per physical cpu + unsigned int GetNumberOfLogicalCPU(); unsigned int GetNumberOfPhysicalCPU(); bool DoesCPUSupportCPUID(); ----------------------------------------------------------------------- Summary of changes: Source/kwsys/SystemInformation.cxx | 246 +++++++++------------------------ Source/kwsys/SystemInformation.hxx.in | 2 +- 2 files changed, 66 insertions(+), 182 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 14 10:31:27 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 14 Feb 2017 10:31:27 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-136-gc415052 Message-ID: <20170214153127.9AC94FA3A6@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via c415052b368c6b1dd822332b443f896841804d0e (commit) via 1009e1d708212d939feda5e761ce758d20fb3752 (commit) via 33a65941fa5d7c12d79f9a4e002fed418ba6adc7 (commit) via fa5188d0edf081396ca0134d07cd8706549ddede (commit) via c4a6135039a417087b478c031849337316022263 (commit) via 0b2f8ae3ba4ee6077051c97b503e1a165d4938f2 (commit) via 592e3d2f96850365ee6d17989c1bca55049cfd23 (commit) from 726660c22aa5116222cc0b5d713899b8fac92a24 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c415052b368c6b1dd822332b443f896841804d0e commit c415052b368c6b1dd822332b443f896841804d0e Merge: 726660c 1009e1d Author: Brad King AuthorDate: Tue Feb 14 10:31:26 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 14 10:31:26 2017 -0500 Merge topic 'clang-format-cuda' into next 1009e1d7 Merge branch 'backport-clang-format-cuda' into clang-format-cuda 33a65941 Tests: Run clang-format on CUDA code fa5188d0 Merge branch 'backport-clang-format-cuda' into clang-format-cuda c4a61350 Tests: Run clang-format on CUDA code 0b2f8ae3 Modules: Run clang-format on CUDA code 592e3d2f clang-format.bash: Format CUDA source files too https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1009e1d708212d939feda5e761ce758d20fb3752 commit 1009e1d708212d939feda5e761ce758d20fb3752 Merge: 33a6594 c4a6135 Author: Brad King AuthorDate: Tue Feb 14 10:22:22 2017 -0500 Commit: Brad King CommitDate: Tue Feb 14 10:22:22 2017 -0500 Merge branch 'backport-clang-format-cuda' into clang-format-cuda https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=33a65941fa5d7c12d79f9a4e002fed418ba6adc7 commit 33a65941fa5d7c12d79f9a4e002fed418ba6adc7 Author: Brad King AuthorDate: Tue Feb 14 10:16:32 2017 -0500 Commit: Brad King CommitDate: Tue Feb 14 10:21:48 2017 -0500 Tests: Run clang-format on CUDA code diff --git a/Tests/Cuda/Complex/dynamic.cu b/Tests/Cuda/Complex/dynamic.cu index 2b04ac9..f677868 100644 --- a/Tests/Cuda/Complex/dynamic.cu +++ b/Tests/Cuda/Complex/dynamic.cu @@ -1,7 +1,7 @@ -#include #include #include +#include #ifdef _WIN32 #define EXPORT __declspec(dllexport) @@ -16,9 +16,7 @@ EXPORT int __host__ cuda_dynamic_host_func(int x) return dynamic_base_func(x); } -static -__global__ -void DetermineIfValidCudaDevice() +static __global__ void DetermineIfValidCudaDevice() { } @@ -26,35 +24,28 @@ EXPORT int choose_cuda_device() { int nDevices = 0; cudaError_t err = cudaGetDeviceCount(&nDevices); - if (err != cudaSuccess) - { + if (err != cudaSuccess) { std::cerr << "Failed to retrieve the number of CUDA enabled devices" << std::endl; return 1; - } - for (int i = 0; i < nDevices; ++i) - { + } + for (int i = 0; i < nDevices; ++i) { cudaDeviceProp prop; cudaError_t err = cudaGetDeviceProperties(&prop, i); - if (err != cudaSuccess) - { + if (err != cudaSuccess) { std::cerr << "Could not retrieve properties from CUDA device " << i << std::endl; return 1; - } - if (prop.major >= 4) - { - err = cudaSetDevice(i); - if (err != cudaSuccess) - { - std::cout << "Could not select CUDA device " << i << std::endl; - } - else - { - return 0; - } + } + if (prop.major >= 4) { + err = cudaSetDevice(i); + if (err != cudaSuccess) { + std::cout << "Could not select CUDA device " << i << std::endl; + } else { + return 0; } } + } std::cout << "Could not find a CUDA enabled card supporting compute >=3.0" << std::endl; @@ -64,17 +55,15 @@ EXPORT int choose_cuda_device() EXPORT void cuda_dynamic_lib_func() { - DetermineIfValidCudaDevice <<<1,1>>> (); + DetermineIfValidCudaDevice<<<1, 1>>>(); cudaError_t err = cudaGetLastError(); - if(err != cudaSuccess) - { + if (err != cudaSuccess) { std::cerr << "DetermineIfValidCudaDevice [SYNC] failed: " << cudaGetErrorString(err) << std::endl; - } + } err = cudaDeviceSynchronize(); - if(err != cudaSuccess) - { + if (err != cudaSuccess) { std::cerr << "DetermineIfValidCudaDevice [ASYNC] failed: " << cudaGetErrorString(cudaGetLastError()) << std::endl; - } + } } diff --git a/Tests/Cuda/Complex/file1.cu b/Tests/Cuda/Complex/file1.cu index a2e8bf3..1ce63bf 100644 --- a/Tests/Cuda/Complex/file1.cu +++ b/Tests/Cuda/Complex/file1.cu @@ -5,6 +5,6 @@ result_type __device__ file1_func(int x) { result_type r; r.input = x; - r.sum = x*x; + r.sum = x * x; return r; } diff --git a/Tests/Cuda/Complex/file2.cu b/Tests/Cuda/Complex/file2.cu index 6b8b06b..74f3558 100644 --- a/Tests/Cuda/Complex/file2.cu +++ b/Tests/Cuda/Complex/file2.cu @@ -5,16 +5,12 @@ result_type __device__ file1_func(int x); result_type_dynamic __device__ file2_func(int x) { - if(x!=42) - { + if (x != 42) { const result_type r = file1_func(x); - const result_type_dynamic rd { r.input, r.sum, true }; + const result_type_dynamic rd{ r.input, r.sum, true }; return rd; - } - else - { - const result_type_dynamic rd { x, x*x*x, false }; + } else { + const result_type_dynamic rd{ x, x * x * x, false }; return rd; - } - + } } diff --git a/Tests/Cuda/Complex/file3.cu b/Tests/Cuda/Complex/file3.cu index bd8198d..d055b42 100644 --- a/Tests/Cuda/Complex/file3.cu +++ b/Tests/Cuda/Complex/file3.cu @@ -7,9 +7,7 @@ result_type __device__ file1_func(int x); result_type_dynamic __device__ file2_func(int x); -static -__global__ -void file3_kernel(result_type* r, int x) +static __global__ void file3_kernel(result_type* r, int x) { *r = file1_func(x); result_type_dynamic rd = file2_func(x); @@ -19,36 +17,32 @@ int file3_launch_kernel(int x) { result_type* r; cudaError_t err = cudaMallocManaged(&r, sizeof(result_type)); - if(err != cudaSuccess) - { + if (err != cudaSuccess) { std::cerr << "file3_launch_kernel: cudaMallocManaged failed: " << cudaGetErrorString(err) << std::endl; return x; - } + } - file3_kernel <<<1,1>>> (r,x); + file3_kernel<<<1, 1>>>(r, x); err = cudaGetLastError(); - if(err != cudaSuccess) - { - std::cerr << "file3_kernel [SYNC] failed: " - << cudaGetErrorString(err) << std::endl; + if (err != cudaSuccess) { + std::cerr << "file3_kernel [SYNC] failed: " << cudaGetErrorString(err) + << std::endl; return x; - } + } err = cudaDeviceSynchronize(); - if(err != cudaSuccess) - { + if (err != cudaSuccess) { std::cerr << "file3_kernel [ASYNC] failed: " << cudaGetErrorString(cudaGetLastError()) << std::endl; return x; - } + } int result = r->sum; err = cudaFree(r); - if(err != cudaSuccess) - { + if (err != cudaSuccess) { std::cerr << "file3_launch_kernel: cudaFree failed: " << cudaGetErrorString(err) << std::endl; return x; - } + } return result; } diff --git a/Tests/Cuda/Complex/mixed.cu b/Tests/Cuda/Complex/mixed.cu index d96cc7c..a81ccb7 100644 --- a/Tests/Cuda/Complex/mixed.cu +++ b/Tests/Cuda/Complex/mixed.cu @@ -17,9 +17,7 @@ result_type_dynamic __device__ file2_func(int x); IMPORT void __host__ cuda_dynamic_lib_func(); -static -__global__ -void mixed_kernel(result_type* r, int x) +static __global__ void mixed_kernel(result_type* r, int x) { *r = file1_func(x); result_type_dynamic rd = file2_func(x); @@ -31,37 +29,33 @@ EXPORT int mixed_launch_kernel(int x) result_type* r; cudaError_t err = cudaMallocManaged(&r, sizeof(result_type)); - if(err != cudaSuccess) - { + if (err != cudaSuccess) { std::cerr << "mixed_launch_kernel: cudaMallocManaged failed: " << cudaGetErrorString(err) << std::endl; return x; - } + } - mixed_kernel <<<1,1>>> (r,x); + mixed_kernel<<<1, 1>>>(r, x); err = cudaGetLastError(); - if(err != cudaSuccess) - { - std::cerr << "mixed_kernel [SYNC] failed: " - << cudaGetErrorString(err) << std::endl; + if (err != cudaSuccess) { + std::cerr << "mixed_kernel [SYNC] failed: " << cudaGetErrorString(err) + << std::endl; return x; - } + } err = cudaDeviceSynchronize(); - if(err != cudaSuccess) - { + if (err != cudaSuccess) { std::cerr << "mixed_kernel [ASYNC] failed: " << cudaGetErrorString(cudaGetLastError()) << std::endl; return x; - } + } int result = r->sum; err = cudaFree(r); - if(err != cudaSuccess) - { + if (err != cudaSuccess) { std::cerr << "mixed_launch_kernel: cudaFree failed: " << cudaGetErrorString(err) << std::endl; return x; - } + } return result; } diff --git a/Tests/Cuda/ConsumeCompileFeatures/main.cu b/Tests/Cuda/ConsumeCompileFeatures/main.cu index 712871c..bc32450 100644 --- a/Tests/Cuda/ConsumeCompileFeatures/main.cu +++ b/Tests/Cuda/ConsumeCompileFeatures/main.cu @@ -5,14 +5,16 @@ int static_cxx11_func(int); void test_functions() { - auto x = static_cxx11_func( int(42) ); + auto x = static_cxx11_func(int(42)); std::cout << x << std::endl; } -int main(int argc, char **argv) +int main(int argc, char** argv) { test_functions(); - std::cout << "this executable doesn't use cuda code, just call methods defined" << std::endl; + std::cout + << "this executable doesn't use cuda code, just call methods defined" + << std::endl; std::cout << "in libraries that have cuda code" << std::endl; return 0; } diff --git a/Tests/Cuda/ObjectLibrary/static.cu b/Tests/Cuda/ObjectLibrary/static.cu index a801153..aa35729 100644 --- a/Tests/Cuda/ObjectLibrary/static.cu +++ b/Tests/Cuda/ObjectLibrary/static.cu @@ -8,14 +8,14 @@ int __host__ file1_sq_func(int x) cudaError_t err; int nDevices = 0; err = cudaGetDeviceCount(&nDevices); - if(err != cudaSuccess) - { + if (err != cudaSuccess) { std::cerr << "nDevices: " << nDevices << std::endl; std::cerr << "err: " << err << std::endl; return 1; } std::cout << "this library uses cuda code" << std::endl; - std::cout << "you have " << nDevices << " devices that support cuda" << std::endl; + std::cout << "you have " << nDevices << " devices that support cuda" + << std::endl; return x * x; } diff --git a/Tests/Cuda/ProperLinkFlags/file1.cu b/Tests/Cuda/ProperLinkFlags/file1.cu index d93dc9f..9a105f0 100644 --- a/Tests/Cuda/ProperLinkFlags/file1.cu +++ b/Tests/Cuda/ProperLinkFlags/file1.cu @@ -6,6 +6,6 @@ result_type __device__ file1_func(int x) __ldg(&x); result_type r; r.input = x; - r.sum = x*x; + r.sum = x * x; return r; } diff --git a/Tests/CudaOnly/EnableStandard/main.cu b/Tests/CudaOnly/EnableStandard/main.cu index f7144e6..f219583 100644 --- a/Tests/CudaOnly/EnableStandard/main.cu +++ b/Tests/CudaOnly/EnableStandard/main.cu @@ -12,11 +12,11 @@ IMPORT int shared_cuda11_func(int); void test_functions() { - static_cuda11_func( int(42) ); - shared_cuda11_func( int(42) ); + static_cuda11_func(int(42)); + shared_cuda11_func(int(42)); } -int main(int argc, char **argv) +int main(int argc, char** argv) { test_functions(); return 0; diff --git a/Tests/CudaOnly/SeparateCompilation/file1.cu b/Tests/CudaOnly/SeparateCompilation/file1.cu index a2e8bf3..1ce63bf 100644 --- a/Tests/CudaOnly/SeparateCompilation/file1.cu +++ b/Tests/CudaOnly/SeparateCompilation/file1.cu @@ -5,6 +5,6 @@ result_type __device__ file1_func(int x) { result_type r; r.input = x; - r.sum = x*x; + r.sum = x * x; return r; } diff --git a/Tests/CudaOnly/SeparateCompilation/file2.cu b/Tests/CudaOnly/SeparateCompilation/file2.cu index 6b8b06b..74f3558 100644 --- a/Tests/CudaOnly/SeparateCompilation/file2.cu +++ b/Tests/CudaOnly/SeparateCompilation/file2.cu @@ -5,16 +5,12 @@ result_type __device__ file1_func(int x); result_type_dynamic __device__ file2_func(int x) { - if(x!=42) - { + if (x != 42) { const result_type r = file1_func(x); - const result_type_dynamic rd { r.input, r.sum, true }; + const result_type_dynamic rd{ r.input, r.sum, true }; return rd; - } - else - { - const result_type_dynamic rd { x, x*x*x, false }; + } else { + const result_type_dynamic rd{ x, x * x * x, false }; return rd; - } - + } } diff --git a/Tests/CudaOnly/SeparateCompilation/file3.cu b/Tests/CudaOnly/SeparateCompilation/file3.cu index 670a18b..155b513 100644 --- a/Tests/CudaOnly/SeparateCompilation/file3.cu +++ b/Tests/CudaOnly/SeparateCompilation/file3.cu @@ -6,13 +6,10 @@ result_type __device__ file1_func(int x); result_type_dynamic __device__ file2_func(int x); - -static -__global__ -void file3_kernel(result_type& r, int x) +static __global__ void file3_kernel(result_type& r, int x) { - //call static_func which is a method that is defined in the - //static library that is always out of date + // call static_func which is a method that is defined in the + // static library that is always out of date r = file1_func(x); result_type_dynamic rd = file2_func(x); } @@ -20,6 +17,6 @@ void file3_kernel(result_type& r, int x) result_type file3_launch_kernel(int x) { result_type r; - file3_kernel <<<1,1>>> (r,x); + file3_kernel<<<1, 1>>>(r, x); return r; } diff --git a/Tests/CudaOnly/SeparateCompilation/file4.cu b/Tests/CudaOnly/SeparateCompilation/file4.cu index 86ef623..2e3e01e 100644 --- a/Tests/CudaOnly/SeparateCompilation/file4.cu +++ b/Tests/CudaOnly/SeparateCompilation/file4.cu @@ -7,12 +7,10 @@ result_type __device__ file1_func(int x); result_type_dynamic __device__ file2_func(int x); -static -__global__ -void file4_kernel(result_type& r, int x) +static __global__ void file4_kernel(result_type& r, int x) { - //call static_func which is a method that is defined in the - //static library that is always out of date + // call static_func which is a method that is defined in the + // static library that is always out of date r = file1_func(x); result_type_dynamic rd = file2_func(x); } @@ -20,6 +18,6 @@ void file4_kernel(result_type& r, int x) int file4_launch_kernel(int x) { result_type r; - file4_kernel <<<1,1>>> (r,x); + file4_kernel<<<1, 1>>>(r, x); return r.sum; } diff --git a/Tests/CudaOnly/SeparateCompilation/file5.cu b/Tests/CudaOnly/SeparateCompilation/file5.cu index 6fdb32a..fee8e9e 100644 --- a/Tests/CudaOnly/SeparateCompilation/file5.cu +++ b/Tests/CudaOnly/SeparateCompilation/file5.cu @@ -7,12 +7,10 @@ result_type __device__ file1_func(int x); result_type_dynamic __device__ file2_func(int x); -static -__global__ -void file5_kernel(result_type& r, int x) +static __global__ void file5_kernel(result_type& r, int x) { - //call static_func which is a method that is defined in the - //static library that is always out of date + // call static_func which is a method that is defined in the + // static library that is always out of date r = file1_func(x); result_type_dynamic rd = file2_func(x); } @@ -20,6 +18,6 @@ void file5_kernel(result_type& r, int x) int file5_launch_kernel(int x) { result_type r; - file5_kernel <<<1,1>>> (r,x); + file5_kernel<<<1, 1>>>(r, x); return r.sum; } diff --git a/Tests/CudaOnly/SeparateCompilation/main.cu b/Tests/CudaOnly/SeparateCompilation/main.cu index 5c8e150..03e0921 100644 --- a/Tests/CudaOnly/SeparateCompilation/main.cu +++ b/Tests/CudaOnly/SeparateCompilation/main.cu @@ -7,7 +7,7 @@ int file4_launch_kernel(int x); int file5_launch_kernel(int x); -int main(int argc, char **argv) +int main(int argc, char** argv) { file4_launch_kernel(42); file5_launch_kernel(42); diff --git a/Tests/CudaOnly/WithDefs/main.notcu b/Tests/CudaOnly/WithDefs/main.notcu index 67bf10c..80ed3a5 100644 --- a/Tests/CudaOnly/WithDefs/main.notcu +++ b/Tests/CudaOnly/WithDefs/main.notcu @@ -6,14 +6,12 @@ #error "PACKED_DEFINE not defined!" #endif -static -__global__ -void DetermineIfValidCudaDevice() +static __global__ void DetermineIfValidCudaDevice() { } #ifdef _MSC_VER -#pragma pack(push,1) +#pragma pack(push, 1) #undef PACKED_DEFINE #define PACKED_DEFINE #endif @@ -32,28 +30,24 @@ struct PACKED_DEFINE result_type result_type can_launch_kernel() { result_type r; - DetermineIfValidCudaDevice <<<1,1>>> (); + DetermineIfValidCudaDevice<<<1, 1>>>(); r.valid = (cudaSuccess == cudaGetLastError()); - if(r.valid) - { + if (r.valid) { r.value = 1; - } - else - { + } else { r.value = -1; - } + } return r; } -int main(int argc, char **argv) +int main(int argc, char** argv) { cudaError_t err; int nDevices = 0; err = cudaGetDeviceCount(&nDevices); - if(err != cudaSuccess) - { - std::cerr << cudaGetErrorString(err) << std::endl; - return 1; - } + if (err != cudaSuccess) { + std::cerr << cudaGetErrorString(err) << std::endl; + return 1; + } return 0; } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=fa5188d0edf081396ca0134d07cd8706549ddede commit fa5188d0edf081396ca0134d07cd8706549ddede Merge: 03be8cc 0b2f8ae Author: Brad King AuthorDate: Tue Feb 14 10:21:22 2017 -0500 Commit: Brad King CommitDate: Tue Feb 14 10:21:22 2017 -0500 Merge branch 'backport-clang-format-cuda' into clang-format-cuda https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c4a6135039a417087b478c031849337316022263 commit c4a6135039a417087b478c031849337316022263 Author: Brad King AuthorDate: Tue Feb 14 10:16:32 2017 -0500 Commit: Brad King CommitDate: Tue Feb 14 10:20:50 2017 -0500 Tests: Run clang-format on CUDA code diff --git a/Tests/Cuda/Complex/dynamic.cu b/Tests/Cuda/Complex/dynamic.cu index a23dc25..82255c5 100644 --- a/Tests/Cuda/Complex/dynamic.cu +++ b/Tests/Cuda/Complex/dynamic.cu @@ -1,7 +1,7 @@ -#include #include #include +#include #ifdef _WIN32 #define EXPORT __declspec(dllexport) @@ -16,18 +16,15 @@ EXPORT int __host__ cuda_dynamic_host_func(int x) return dynamic_base_func(x); } -static -__global__ -void DetermineIfValidCudaDevice() +static __global__ void DetermineIfValidCudaDevice() { } EXPORT void cuda_dynamic_lib_func() { - DetermineIfValidCudaDevice <<<1,1>>> (); + DetermineIfValidCudaDevice<<<1, 1>>>(); cudaError_t err = cudaGetLastError(); - if(err == cudaSuccess) - { + if (err == cudaSuccess) { std::cerr << cudaGetErrorString(err) << std::endl; - } + } } diff --git a/Tests/Cuda/Complex/file1.cu b/Tests/Cuda/Complex/file1.cu index a2e8bf3..1ce63bf 100644 --- a/Tests/Cuda/Complex/file1.cu +++ b/Tests/Cuda/Complex/file1.cu @@ -5,6 +5,6 @@ result_type __device__ file1_func(int x) { result_type r; r.input = x; - r.sum = x*x; + r.sum = x * x; return r; } diff --git a/Tests/Cuda/Complex/file2.cu b/Tests/Cuda/Complex/file2.cu index 6b8b06b..74f3558 100644 --- a/Tests/Cuda/Complex/file2.cu +++ b/Tests/Cuda/Complex/file2.cu @@ -5,16 +5,12 @@ result_type __device__ file1_func(int x); result_type_dynamic __device__ file2_func(int x) { - if(x!=42) - { + if (x != 42) { const result_type r = file1_func(x); - const result_type_dynamic rd { r.input, r.sum, true }; + const result_type_dynamic rd{ r.input, r.sum, true }; return rd; - } - else - { - const result_type_dynamic rd { x, x*x*x, false }; + } else { + const result_type_dynamic rd{ x, x * x * x, false }; return rd; - } - + } } diff --git a/Tests/Cuda/Complex/file3.cu b/Tests/Cuda/Complex/file3.cu index 47e64c5..7c37d66 100644 --- a/Tests/Cuda/Complex/file3.cu +++ b/Tests/Cuda/Complex/file3.cu @@ -7,9 +7,7 @@ result_type __device__ file1_func(int x); result_type_dynamic __device__ file2_func(int x); -static -__global__ -void file3_kernel(result_type& r, int x) +static __global__ void file3_kernel(result_type& r, int x) { r = file1_func(x); result_type_dynamic rd = file2_func(x); @@ -18,12 +16,11 @@ void file3_kernel(result_type& r, int x) int file3_launch_kernel(int x) { result_type r; - file3_kernel <<<1,1>>> (r,x); + file3_kernel<<<1, 1>>>(r, x); cudaError_t err = cudaGetLastError(); - if(err == cudaSuccess) - { + if (err == cudaSuccess) { std::cerr << cudaGetErrorString(err) << std::endl; return x; - } + } return r.sum; } diff --git a/Tests/Cuda/Complex/mixed.cu b/Tests/Cuda/Complex/mixed.cu index 7051de0..4bba07c 100644 --- a/Tests/Cuda/Complex/mixed.cu +++ b/Tests/Cuda/Complex/mixed.cu @@ -17,9 +17,7 @@ result_type_dynamic __device__ file2_func(int x); IMPORT void __host__ cuda_dynamic_lib_func(); -static -__global__ -void mixed_kernel(result_type& r, int x) +static __global__ void mixed_kernel(result_type& r, int x) { r = file1_func(x); result_type_dynamic rd = file2_func(x); @@ -30,6 +28,6 @@ EXPORT int mixed_launch_kernel(int x) cuda_dynamic_lib_func(); result_type r; - mixed_kernel <<<1,1>>> (r,x); + mixed_kernel<<<1, 1>>>(r, x); return r.sum; } diff --git a/Tests/Cuda/ConsumeCompileFeatures/main.cu b/Tests/Cuda/ConsumeCompileFeatures/main.cu index 712871c..bc32450 100644 --- a/Tests/Cuda/ConsumeCompileFeatures/main.cu +++ b/Tests/Cuda/ConsumeCompileFeatures/main.cu @@ -5,14 +5,16 @@ int static_cxx11_func(int); void test_functions() { - auto x = static_cxx11_func( int(42) ); + auto x = static_cxx11_func(int(42)); std::cout << x << std::endl; } -int main(int argc, char **argv) +int main(int argc, char** argv) { test_functions(); - std::cout << "this executable doesn't use cuda code, just call methods defined" << std::endl; + std::cout + << "this executable doesn't use cuda code, just call methods defined" + << std::endl; std::cout << "in libraries that have cuda code" << std::endl; return 0; } diff --git a/Tests/Cuda/ObjectLibrary/static.cu b/Tests/Cuda/ObjectLibrary/static.cu index 2374c23..cdf682b 100644 --- a/Tests/Cuda/ObjectLibrary/static.cu +++ b/Tests/Cuda/ObjectLibrary/static.cu @@ -8,14 +8,14 @@ int __host__ file1_sq_func(int x) cudaError_t err; int nDevices = 0; err = cudaGetDeviceCount(&nDevices); - if(err != cudaSuccess) - { + if (err != cudaSuccess) { std::cout << "nDevices: " << nDevices << std::endl; std::cout << "err: " << err << std::endl; return 1; } std::cout << "this library uses cuda code" << std::endl; - std::cout << "you have " << nDevices << " devices that support cuda" << std::endl; + std::cout << "you have " << nDevices << " devices that support cuda" + << std::endl; return x * x; } diff --git a/Tests/Cuda/ProperLinkFlags/file1.cu b/Tests/Cuda/ProperLinkFlags/file1.cu index d93dc9f..9a105f0 100644 --- a/Tests/Cuda/ProperLinkFlags/file1.cu +++ b/Tests/Cuda/ProperLinkFlags/file1.cu @@ -6,6 +6,6 @@ result_type __device__ file1_func(int x) __ldg(&x); result_type r; r.input = x; - r.sum = x*x; + r.sum = x * x; return r; } diff --git a/Tests/CudaOnly/EnableStandard/main.cu b/Tests/CudaOnly/EnableStandard/main.cu index f7144e6..f219583 100644 --- a/Tests/CudaOnly/EnableStandard/main.cu +++ b/Tests/CudaOnly/EnableStandard/main.cu @@ -12,11 +12,11 @@ IMPORT int shared_cuda11_func(int); void test_functions() { - static_cuda11_func( int(42) ); - shared_cuda11_func( int(42) ); + static_cuda11_func(int(42)); + shared_cuda11_func(int(42)); } -int main(int argc, char **argv) +int main(int argc, char** argv) { test_functions(); return 0; diff --git a/Tests/CudaOnly/SeparateCompilation/file1.cu b/Tests/CudaOnly/SeparateCompilation/file1.cu index a2e8bf3..1ce63bf 100644 --- a/Tests/CudaOnly/SeparateCompilation/file1.cu +++ b/Tests/CudaOnly/SeparateCompilation/file1.cu @@ -5,6 +5,6 @@ result_type __device__ file1_func(int x) { result_type r; r.input = x; - r.sum = x*x; + r.sum = x * x; return r; } diff --git a/Tests/CudaOnly/SeparateCompilation/file2.cu b/Tests/CudaOnly/SeparateCompilation/file2.cu index 6b8b06b..74f3558 100644 --- a/Tests/CudaOnly/SeparateCompilation/file2.cu +++ b/Tests/CudaOnly/SeparateCompilation/file2.cu @@ -5,16 +5,12 @@ result_type __device__ file1_func(int x); result_type_dynamic __device__ file2_func(int x) { - if(x!=42) - { + if (x != 42) { const result_type r = file1_func(x); - const result_type_dynamic rd { r.input, r.sum, true }; + const result_type_dynamic rd{ r.input, r.sum, true }; return rd; - } - else - { - const result_type_dynamic rd { x, x*x*x, false }; + } else { + const result_type_dynamic rd{ x, x * x * x, false }; return rd; - } - + } } diff --git a/Tests/CudaOnly/SeparateCompilation/file3.cu b/Tests/CudaOnly/SeparateCompilation/file3.cu index 670a18b..155b513 100644 --- a/Tests/CudaOnly/SeparateCompilation/file3.cu +++ b/Tests/CudaOnly/SeparateCompilation/file3.cu @@ -6,13 +6,10 @@ result_type __device__ file1_func(int x); result_type_dynamic __device__ file2_func(int x); - -static -__global__ -void file3_kernel(result_type& r, int x) +static __global__ void file3_kernel(result_type& r, int x) { - //call static_func which is a method that is defined in the - //static library that is always out of date + // call static_func which is a method that is defined in the + // static library that is always out of date r = file1_func(x); result_type_dynamic rd = file2_func(x); } @@ -20,6 +17,6 @@ void file3_kernel(result_type& r, int x) result_type file3_launch_kernel(int x) { result_type r; - file3_kernel <<<1,1>>> (r,x); + file3_kernel<<<1, 1>>>(r, x); return r; } diff --git a/Tests/CudaOnly/SeparateCompilation/file4.cu b/Tests/CudaOnly/SeparateCompilation/file4.cu index 86ef623..2e3e01e 100644 --- a/Tests/CudaOnly/SeparateCompilation/file4.cu +++ b/Tests/CudaOnly/SeparateCompilation/file4.cu @@ -7,12 +7,10 @@ result_type __device__ file1_func(int x); result_type_dynamic __device__ file2_func(int x); -static -__global__ -void file4_kernel(result_type& r, int x) +static __global__ void file4_kernel(result_type& r, int x) { - //call static_func which is a method that is defined in the - //static library that is always out of date + // call static_func which is a method that is defined in the + // static library that is always out of date r = file1_func(x); result_type_dynamic rd = file2_func(x); } @@ -20,6 +18,6 @@ void file4_kernel(result_type& r, int x) int file4_launch_kernel(int x) { result_type r; - file4_kernel <<<1,1>>> (r,x); + file4_kernel<<<1, 1>>>(r, x); return r.sum; } diff --git a/Tests/CudaOnly/SeparateCompilation/file5.cu b/Tests/CudaOnly/SeparateCompilation/file5.cu index 6fdb32a..fee8e9e 100644 --- a/Tests/CudaOnly/SeparateCompilation/file5.cu +++ b/Tests/CudaOnly/SeparateCompilation/file5.cu @@ -7,12 +7,10 @@ result_type __device__ file1_func(int x); result_type_dynamic __device__ file2_func(int x); -static -__global__ -void file5_kernel(result_type& r, int x) +static __global__ void file5_kernel(result_type& r, int x) { - //call static_func which is a method that is defined in the - //static library that is always out of date + // call static_func which is a method that is defined in the + // static library that is always out of date r = file1_func(x); result_type_dynamic rd = file2_func(x); } @@ -20,6 +18,6 @@ void file5_kernel(result_type& r, int x) int file5_launch_kernel(int x) { result_type r; - file5_kernel <<<1,1>>> (r,x); + file5_kernel<<<1, 1>>>(r, x); return r.sum; } diff --git a/Tests/CudaOnly/SeparateCompilation/main.cu b/Tests/CudaOnly/SeparateCompilation/main.cu index 5c8e150..03e0921 100644 --- a/Tests/CudaOnly/SeparateCompilation/main.cu +++ b/Tests/CudaOnly/SeparateCompilation/main.cu @@ -7,7 +7,7 @@ int file4_launch_kernel(int x); int file5_launch_kernel(int x); -int main(int argc, char **argv) +int main(int argc, char** argv) { file4_launch_kernel(42); file5_launch_kernel(42); diff --git a/Tests/CudaOnly/WithDefs/main.notcu b/Tests/CudaOnly/WithDefs/main.notcu index 67bf10c..80ed3a5 100644 --- a/Tests/CudaOnly/WithDefs/main.notcu +++ b/Tests/CudaOnly/WithDefs/main.notcu @@ -6,14 +6,12 @@ #error "PACKED_DEFINE not defined!" #endif -static -__global__ -void DetermineIfValidCudaDevice() +static __global__ void DetermineIfValidCudaDevice() { } #ifdef _MSC_VER -#pragma pack(push,1) +#pragma pack(push, 1) #undef PACKED_DEFINE #define PACKED_DEFINE #endif @@ -32,28 +30,24 @@ struct PACKED_DEFINE result_type result_type can_launch_kernel() { result_type r; - DetermineIfValidCudaDevice <<<1,1>>> (); + DetermineIfValidCudaDevice<<<1, 1>>>(); r.valid = (cudaSuccess == cudaGetLastError()); - if(r.valid) - { + if (r.valid) { r.value = 1; - } - else - { + } else { r.value = -1; - } + } return r; } -int main(int argc, char **argv) +int main(int argc, char** argv) { cudaError_t err; int nDevices = 0; err = cudaGetDeviceCount(&nDevices); - if(err != cudaSuccess) - { - std::cerr << cudaGetErrorString(err) << std::endl; - return 1; - } + if (err != cudaSuccess) { + std::cerr << cudaGetErrorString(err) << std::endl; + return 1; + } return 0; } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0b2f8ae3ba4ee6077051c97b503e1a165d4938f2 commit 0b2f8ae3ba4ee6077051c97b503e1a165d4938f2 Author: Brad King AuthorDate: Tue Feb 14 10:00:05 2017 -0500 Commit: Brad King CommitDate: Tue Feb 14 10:20:42 2017 -0500 Modules: Run clang-format on CUDA code diff --git a/Modules/CMakeCUDACompilerABI.cu b/Modules/CMakeCUDACompilerABI.cu index 5aa1b8a..99bacef 100644 --- a/Modules/CMakeCUDACompilerABI.cu +++ b/Modules/CMakeCUDACompilerABI.cu @@ -1,5 +1,5 @@ #ifndef __CUDACC__ -# error "A C or C++ compiler has been selected for CUDA" +#error "A C or C++ compiler has been selected for CUDA" #endif #include "CMakeCompilerABI.h" https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=592e3d2f96850365ee6d17989c1bca55049cfd23 commit 592e3d2f96850365ee6d17989c1bca55049cfd23 Author: Brad King AuthorDate: Tue Feb 14 09:58:42 2017 -0500 Commit: Brad King CommitDate: Tue Feb 14 10:20:23 2017 -0500 clang-format.bash: Format CUDA source files too Add `.clang-format` configuration files for Cuda test directories that use `Standard: Cpp11`. Otherwise clang-format splits the triple angle brackets used for CUDA kernels. diff --git a/Tests/Cuda/.clang-format b/Tests/Cuda/.clang-format new file mode 100644 index 0000000..a77589a --- /dev/null +++ b/Tests/Cuda/.clang-format @@ -0,0 +1,9 @@ +--- +# This configuration requires clang-format 3.8 or higher. +BasedOnStyle: Mozilla +AlignOperands: false +AlwaysBreakAfterReturnType: None +AlwaysBreakAfterDefinitionReturnType: None +ColumnLimit: 79 +Standard: Cpp11 +... diff --git a/Tests/CudaOnly/.clang-format b/Tests/CudaOnly/.clang-format new file mode 100644 index 0000000..a77589a --- /dev/null +++ b/Tests/CudaOnly/.clang-format @@ -0,0 +1,9 @@ +--- +# This configuration requires clang-format 3.8 or higher. +BasedOnStyle: Mozilla +AlignOperands: false +AlwaysBreakAfterReturnType: None +AlwaysBreakAfterDefinitionReturnType: None +ColumnLimit: 79 +Standard: Cpp11 +... diff --git a/Utilities/Scripts/clang-format.bash b/Utilities/Scripts/clang-format.bash index 8e07c99..2b36ac5 100755 --- a/Utilities/Scripts/clang-format.bash +++ b/Utilities/Scripts/clang-format.bash @@ -107,7 +107,7 @@ case "$mode" in esac # Filter sources to which our style should apply. -$git_ls -z -- '*.c' '*.cc' '*.cpp' '*.cxx' '*.h' '*.hh' '*.hpp' '*.hxx' | +$git_ls -z -- '*.c' '*.cc' '*.cpp' '*.cxx' '*.h' '*.hh' '*.hpp' '*.hxx' '*.cu' '*.notcu' | # Exclude lexer/parser generator input and output. egrep -z -v '^Source/cmCommandArgumentLexer\.' | ----------------------------------------------------------------------- Summary of changes: Modules/CMakeCUDACompilerABI.cu | 2 +- .clang-format => Tests/Cuda/.clang-format | 2 +- Tests/Cuda/Complex/dynamic.cu | 49 ++++++++++--------------- Tests/Cuda/Complex/file1.cu | 2 +- Tests/Cuda/Complex/file2.cu | 14 +++---- Tests/Cuda/Complex/file3.cu | 30 ++++++--------- Tests/Cuda/Complex/mixed.cu | 30 ++++++--------- Tests/Cuda/ConsumeCompileFeatures/main.cu | 8 ++-- Tests/Cuda/ObjectLibrary/static.cu | 6 +-- Tests/Cuda/ProperLinkFlags/file1.cu | 2 +- .clang-format => Tests/CudaOnly/.clang-format | 2 +- Tests/CudaOnly/EnableStandard/main.cu | 6 +-- Tests/CudaOnly/SeparateCompilation/file1.cu | 2 +- Tests/CudaOnly/SeparateCompilation/file2.cu | 14 +++---- Tests/CudaOnly/SeparateCompilation/file3.cu | 11 ++---- Tests/CudaOnly/SeparateCompilation/file4.cu | 10 ++--- Tests/CudaOnly/SeparateCompilation/file5.cu | 10 ++--- Tests/CudaOnly/SeparateCompilation/main.cu | 2 +- Tests/CudaOnly/WithDefs/main.notcu | 28 ++++++-------- Utilities/Scripts/clang-format.bash | 2 +- 20 files changed, 95 insertions(+), 137 deletions(-) copy .clang-format => Tests/Cuda/.clang-format (92%) copy .clang-format => Tests/CudaOnly/.clang-format (92%) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 14 10:38:07 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 14 Feb 2017 10:38:07 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-81-g5af61d4 Message-ID: <20170214153807.C4A88FA5BC@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 5af61d446d53517a90806ce45060f48b511d263d (commit) via 1009e1d708212d939feda5e761ce758d20fb3752 (commit) via 33a65941fa5d7c12d79f9a4e002fed418ba6adc7 (commit) via fa5188d0edf081396ca0134d07cd8706549ddede (commit) via c4a6135039a417087b478c031849337316022263 (commit) via 0b2f8ae3ba4ee6077051c97b503e1a165d4938f2 (commit) via 592e3d2f96850365ee6d17989c1bca55049cfd23 (commit) from 03be8ccbf607b378c7ffcfd2ffe6797612837efa (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=5af61d446d53517a90806ce45060f48b511d263d commit 5af61d446d53517a90806ce45060f48b511d263d Merge: 03be8cc 1009e1d Author: Brad King AuthorDate: Tue Feb 14 10:37:57 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 14 10:37:57 2017 -0500 Merge topic 'clang-format-cuda' 1009e1d7 Merge branch 'backport-clang-format-cuda' into clang-format-cuda 33a65941 Tests: Run clang-format on CUDA code fa5188d0 Merge branch 'backport-clang-format-cuda' into clang-format-cuda c4a61350 Tests: Run clang-format on CUDA code 0b2f8ae3 Modules: Run clang-format on CUDA code 592e3d2f clang-format.bash: Format CUDA source files too ----------------------------------------------------------------------- Summary of changes: Modules/CMakeCUDACompilerABI.cu | 2 +- .clang-format => Tests/Cuda/.clang-format | 2 +- Tests/Cuda/Complex/dynamic.cu | 49 ++++++++++--------------- Tests/Cuda/Complex/file1.cu | 2 +- Tests/Cuda/Complex/file2.cu | 14 +++---- Tests/Cuda/Complex/file3.cu | 30 ++++++--------- Tests/Cuda/Complex/mixed.cu | 30 ++++++--------- Tests/Cuda/ConsumeCompileFeatures/main.cu | 8 ++-- Tests/Cuda/ObjectLibrary/static.cu | 6 +-- Tests/Cuda/ProperLinkFlags/file1.cu | 2 +- .clang-format => Tests/CudaOnly/.clang-format | 2 +- Tests/CudaOnly/EnableStandard/main.cu | 6 +-- Tests/CudaOnly/SeparateCompilation/file1.cu | 2 +- Tests/CudaOnly/SeparateCompilation/file2.cu | 14 +++---- Tests/CudaOnly/SeparateCompilation/file3.cu | 11 ++---- Tests/CudaOnly/SeparateCompilation/file4.cu | 10 ++--- Tests/CudaOnly/SeparateCompilation/file5.cu | 10 ++--- Tests/CudaOnly/SeparateCompilation/main.cu | 2 +- Tests/CudaOnly/WithDefs/main.notcu | 28 ++++++-------- Utilities/Scripts/clang-format.bash | 2 +- 20 files changed, 95 insertions(+), 137 deletions(-) copy .clang-format => Tests/Cuda/.clang-format (92%) copy .clang-format => Tests/CudaOnly/.clang-format (92%) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 14 10:38:22 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 14 Feb 2017 10:38:22 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-138-geed7ebb Message-ID: <20170214153822.C7154FA1B3@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via eed7ebb5ca6bb7430e2601b94eb1d2fde40f6884 (commit) via 5af61d446d53517a90806ce45060f48b511d263d (commit) from c415052b368c6b1dd822332b443f896841804d0e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=eed7ebb5ca6bb7430e2601b94eb1d2fde40f6884 commit eed7ebb5ca6bb7430e2601b94eb1d2fde40f6884 Merge: c415052 5af61d4 Author: Brad King AuthorDate: Tue Feb 14 10:38:16 2017 -0500 Commit: Brad King CommitDate: Tue Feb 14 10:38:16 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 14 10:39:06 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 14 Feb 2017 10:39:06 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-83-g34ce301 Message-ID: <20170214153906.F0F80480@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 34ce3017b530595753b5987bd0702aceded683be (commit) via f45e3b950991f5c4f66cd132bda61a369a3016d7 (commit) from 5af61d446d53517a90806ce45060f48b511d263d (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 14 10:39:07 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 14 Feb 2017 10:39:07 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-141-g47f4a0c Message-ID: <20170214153907.1451C9AC@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 47f4a0c1ed5243f2d8482a952a0a687ab9307bd0 (commit) via 34ce3017b530595753b5987bd0702aceded683be (commit) via f45e3b950991f5c4f66cd132bda61a369a3016d7 (commit) from eed7ebb5ca6bb7430e2601b94eb1d2fde40f6884 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=47f4a0c1ed5243f2d8482a952a0a687ab9307bd0 commit 47f4a0c1ed5243f2d8482a952a0a687ab9307bd0 Merge: eed7ebb 34ce301 Author: Brad King AuthorDate: Tue Feb 14 10:38:57 2017 -0500 Commit: Brad King CommitDate: Tue Feb 14 10:38:57 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 14 10:39:07 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 14 Feb 2017 10:39:07 -0500 (EST) Subject: [Cmake-commits] CMake branch, release, updated. v3.8.0-rc1-13-gf45e3b9 Message-ID: <20170214153907.48AEB480@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, release has been updated via f45e3b950991f5c4f66cd132bda61a369a3016d7 (commit) via c4a6135039a417087b478c031849337316022263 (commit) via 0b2f8ae3ba4ee6077051c97b503e1a165d4938f2 (commit) via 592e3d2f96850365ee6d17989c1bca55049cfd23 (commit) from f0e5954fcee6b546eaa858b1e3323f529d906d04 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- Summary of changes: Modules/CMakeCUDACompilerABI.cu | 2 +- .clang-format => Tests/Cuda/.clang-format | 2 +- Tests/Cuda/Complex/dynamic.cu | 13 +++++------- Tests/Cuda/Complex/file1.cu | 2 +- Tests/Cuda/Complex/file2.cu | 14 +++++-------- Tests/Cuda/Complex/file3.cu | 11 ++++------ Tests/Cuda/Complex/mixed.cu | 6 ++---- Tests/Cuda/ConsumeCompileFeatures/main.cu | 8 ++++--- Tests/Cuda/ObjectLibrary/static.cu | 6 +++--- Tests/Cuda/ProperLinkFlags/file1.cu | 2 +- .clang-format => Tests/CudaOnly/.clang-format | 2 +- Tests/CudaOnly/EnableStandard/main.cu | 6 +++--- Tests/CudaOnly/SeparateCompilation/file1.cu | 2 +- Tests/CudaOnly/SeparateCompilation/file2.cu | 14 +++++-------- Tests/CudaOnly/SeparateCompilation/file3.cu | 11 ++++------ Tests/CudaOnly/SeparateCompilation/file4.cu | 10 ++++----- Tests/CudaOnly/SeparateCompilation/file5.cu | 10 ++++----- Tests/CudaOnly/SeparateCompilation/main.cu | 2 +- Tests/CudaOnly/WithDefs/main.notcu | 28 ++++++++++--------------- Utilities/Scripts/clang-format.bash | 2 +- 20 files changed, 63 insertions(+), 90 deletions(-) copy .clang-format => Tests/Cuda/.clang-format (92%) copy .clang-format => Tests/CudaOnly/.clang-format (92%) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 14 11:06:44 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 14 Feb 2017 11:06:44 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-144-g20d3916 Message-ID: <20170214160644.3A292FA654@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 20d39160baf3301acdfac3f844b2c23cb1a2dd9b (commit) via 1c60231ca546597ef8b80e7340c8991b06387cbf (commit) via 8d75d8dc72a0ac4502991891782a2c84df1f61c3 (commit) from 47f4a0c1ed5243f2d8482a952a0a687ab9307bd0 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=20d39160baf3301acdfac3f844b2c23cb1a2dd9b commit 20d39160baf3301acdfac3f844b2c23cb1a2dd9b Merge: 47f4a0c 1c60231 Author: Brad King AuthorDate: Tue Feb 14 11:06:43 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 14 11:06:43 2017 -0500 Merge topic 'cuda-with-c' into next 1c60231c CUDA: Link to standard system libraries when linking as CUDA 8d75d8dc Tests: Add case for CUDA with C but not C++ https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1c60231ca546597ef8b80e7340c8991b06387cbf commit 1c60231ca546597ef8b80e7340c8991b06387cbf Author: Brad King AuthorDate: Tue Feb 14 10:34:10 2017 -0500 Commit: Brad King CommitDate: Tue Feb 14 10:34:15 2017 -0500 CUDA: Link to standard system libraries when linking as CUDA On Windows with MSVC-like host compilers we must honor the standard libraries chosen by the `Platform/Windows-MSVC` module. Otherwise C code linked into the CUDA binary that expects to have these libraries available may not link. diff --git a/Modules/CMakeCUDAInformation.cmake b/Modules/CMakeCUDAInformation.cmake index 13b1789..1c48159 100644 --- a/Modules/CMakeCUDAInformation.cmake +++ b/Modules/CMakeCUDAInformation.cmake @@ -93,6 +93,12 @@ if(NOT CMAKE_NOT_USING_CONFIG_FLAGS) endif() +if(CMAKE_CUDA_STANDARD_LIBRARIES_INIT) + set(CMAKE_CUDA_STANDARD_LIBRARIES "${CMAKE_CUDA_STANDARD_LIBRARIES_INIT}" + CACHE STRING "Libraries linked by default with all CUDA applications.") + mark_as_advanced(CMAKE_CUDA_STANDARD_LIBRARIES) +endif() + include(CMakeCommonLanguageInclude) # now define the following rules: diff --git a/Modules/Platform/Windows-NVIDIA-CUDA.cmake b/Modules/Platform/Windows-NVIDIA-CUDA.cmake index 809ee06..eda41e0 100644 --- a/Modules/Platform/Windows-NVIDIA-CUDA.cmake +++ b/Modules/Platform/Windows-NVIDIA-CUDA.cmake @@ -40,3 +40,5 @@ string(APPEND CMAKE_CUDA_FLAGS_DEBUG_INIT " -Xcompiler=-MDd,-Zi,-RTC1") string(APPEND CMAKE_CUDA_FLAGS_RELEASE_INIT " -Xcompiler=-MD") string(APPEND CMAKE_CUDA_FLAGS_RELWITHDEBINFO_INIT " -Xcompiler=-MD") string(APPEND CMAKE_CUDA_FLAGS_MINSIZEREL_INIT " -Xcompiler=-MD") + +set(CMAKE_CUDA_STANDARD_LIBRARIES_INIT "${CMAKE_C_STANDARD_LIBRARIES_INIT}") diff --git a/Tests/Cuda/WithC/main.c b/Tests/Cuda/WithC/main.c index f9101a7..cb5fddc 100644 --- a/Tests/Cuda/WithC/main.c +++ b/Tests/Cuda/WithC/main.c @@ -1,6 +1,14 @@ extern int use_cuda(void); +#ifdef _WIN32 +#include +#endif + int main() { +#ifdef _WIN32 + /* Use an API that requires CMake's "standard" C libraries. */ + GetOpenFileName(NULL); +#endif return use_cuda(); } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8d75d8dc72a0ac4502991891782a2c84df1f61c3 commit 8d75d8dc72a0ac4502991891782a2c84df1f61c3 Author: Brad King AuthorDate: Tue Feb 14 10:32:44 2017 -0500 Commit: Brad King CommitDate: Tue Feb 14 10:34:06 2017 -0500 Tests: Add case for CUDA with C but not C++ An executable using CUDA and C should link as CUDA. diff --git a/Tests/Cuda/CMakeLists.txt b/Tests/Cuda/CMakeLists.txt index 42b00e1..de48501 100644 --- a/Tests/Cuda/CMakeLists.txt +++ b/Tests/Cuda/CMakeLists.txt @@ -4,3 +4,4 @@ ADD_TEST_MACRO(Cuda.ConsumeCompileFeatures CudaConsumeCompileFeatures) ADD_TEST_MACRO(Cuda.ObjectLibrary CudaObjectLibrary) ADD_TEST_MACRO(Cuda.ToolkitInclude CudaToolkitInclude) ADD_TEST_MACRO(Cuda.ProperLinkFlags ProperLinkFlags) +ADD_TEST_MACRO(Cuda.WithC CudaWithC) diff --git a/Tests/Cuda/WithC/CMakeLists.txt b/Tests/Cuda/WithC/CMakeLists.txt new file mode 100644 index 0000000..7596804 --- /dev/null +++ b/Tests/Cuda/WithC/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 3.7) +project(CudaComplex CUDA C) + +set(CMAKE_CUDA_FLAGS "-gencode arch=compute_30,code=compute_30") + +add_executable(CudaWithC main.c cuda.cu) + +if(APPLE) + # We need to add the default path to the driver (libcuda.dylib) as an rpath, so that + # the static cuda runtime can find it at runtime. + target_link_libraries(CudaWithC PRIVATE -Wl,-rpath,/usr/local/cuda/lib) +endif() diff --git a/Tests/Cuda/WithC/cuda.cu b/Tests/Cuda/WithC/cuda.cu new file mode 100644 index 0000000..06bd7b9 --- /dev/null +++ b/Tests/Cuda/WithC/cuda.cu @@ -0,0 +1,16 @@ +#include + +#include + +extern "C" int use_cuda(void) +{ + int nDevices = 0; + cudaError_t err = cudaGetDeviceCount(&nDevices); + if (err != cudaSuccess) { + std::cerr << "Failed to retrieve the number of CUDA enabled devices" + << std::endl; + return 1; + } + std::cout << "Found " << nDevices << " CUDA enabled devices" << std::endl; + return 0; +} diff --git a/Tests/Cuda/WithC/main.c b/Tests/Cuda/WithC/main.c new file mode 100644 index 0000000..f9101a7 --- /dev/null +++ b/Tests/Cuda/WithC/main.c @@ -0,0 +1,6 @@ +extern int use_cuda(void); + +int main() +{ + return use_cuda(); +} ----------------------------------------------------------------------- Summary of changes: Modules/CMakeCUDAInformation.cmake | 6 ++++++ Modules/Platform/Windows-NVIDIA-CUDA.cmake | 2 ++ Tests/Cuda/CMakeLists.txt | 1 + Tests/Cuda/WithC/CMakeLists.txt | 12 ++++++++++++ Tests/Cuda/WithC/cuda.cu | 16 ++++++++++++++++ Tests/Cuda/WithC/main.c | 14 ++++++++++++++ 6 files changed, 51 insertions(+) create mode 100644 Tests/Cuda/WithC/CMakeLists.txt create mode 100644 Tests/Cuda/WithC/cuda.cu create mode 100644 Tests/Cuda/WithC/main.c hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 14 13:28:58 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 14 Feb 2017 13:28:58 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-147-gd4bf5af Message-ID: <20170214182858.AB43DFA4EF@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via d4bf5af08435c5bdc0a1575f9b1763844dabc148 (commit) via 8ba6dc362dd1c5b073c68f8a873a91ddd2743e34 (commit) via 1d04d2ce3609da4c4f8d59ccfabd8848a6e765d4 (commit) from 20d39160baf3301acdfac3f844b2c23cb1a2dd9b (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d4bf5af08435c5bdc0a1575f9b1763844dabc148 commit d4bf5af08435c5bdc0a1575f9b1763844dabc148 Merge: 20d3916 8ba6dc3 Author: Brad King AuthorDate: Tue Feb 14 13:28:57 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 14 13:28:57 2017 -0500 Merge topic 'vs-refactor-libs' into next 8ba6dc36 VS: Place CMAKE__STANDARD_LIBRARIES after other libraries 1d04d2ce VS: Refactor parsing of CMAKE__STANDARD_LIBRARIES https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8ba6dc362dd1c5b073c68f8a873a91ddd2743e34 commit 8ba6dc362dd1c5b073c68f8a873a91ddd2743e34 Author: Brad King AuthorDate: Tue Feb 14 11:18:51 2017 -0500 Commit: Brad King CommitDate: Tue Feb 14 11:21:08 2017 -0500 VS: Place CMAKE__STANDARD_LIBRARIES after other libraries Make the VS generator consistent with the Ninja and Makefile generators that place the libraries listed in this variable after other libraries on the link command line. These system libraries never depend on the project libraries. diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index a60222e..f084e19 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -2781,13 +2781,6 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( flags += " "; flags += flagsConfig; } - std::string standardLibsVar = "CMAKE_"; - standardLibsVar += linkLanguage; - standardLibsVar += "_STANDARD_LIBRARIES"; - std::string const libs = - this->Makefile->GetSafeDefinition(standardLibsVar.c_str()); - std::vector libVec; - cmSystemTools::ParseWindowsCommandLine(libs.c_str(), libVec); cmComputeLinkInformation* pcli = this->GeneratorTarget->GetLinkInformation(config.c_str()); @@ -2797,10 +2790,17 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( this->Name.c_str()); return false; } - // add the libraries for the target to libs string cmComputeLinkInformation& cli = *pcli; + + std::vector libVec; std::vector vsTargetVec; this->AddLibraries(cli, libVec, vsTargetVec); + std::string standardLibsVar = "CMAKE_"; + standardLibsVar += linkLanguage; + standardLibsVar += "_STANDARD_LIBRARIES"; + std::string const libs = + this->Makefile->GetSafeDefinition(standardLibsVar.c_str()); + cmSystemTools::ParseWindowsCommandLine(libs.c_str(), libVec); linkOptions.AddFlag("AdditionalDependencies", libVec); // Populate TargetsFileAndConfigsVec https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1d04d2ce3609da4c4f8d59ccfabd8848a6e765d4 commit 1d04d2ce3609da4c4f8d59ccfabd8848a6e765d4 Author: Brad King AuthorDate: Tue Feb 14 11:15:08 2017 -0500 Commit: Brad King CommitDate: Tue Feb 14 11:15:08 2017 -0500 VS: Refactor parsing of CMAKE__STANDARD_LIBRARIES Parse the value as a command line string just as the MS CRT would. This makes the VS generator behavior consistent with how the string is used by the Ninja and Makefile generators. diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index a7edc95..a60222e 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -2784,22 +2784,10 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( std::string standardLibsVar = "CMAKE_"; standardLibsVar += linkLanguage; standardLibsVar += "_STANDARD_LIBRARIES"; - std::string libs = + std::string const libs = this->Makefile->GetSafeDefinition(standardLibsVar.c_str()); - // Remove trailing spaces from libs - std::string::size_type pos = libs.size() - 1; - if (!libs.empty()) { - while (libs[pos] == ' ') { - pos--; - } - } - if (pos != libs.size() - 1) { - libs = libs.substr(0, pos + 1); - } - // Replace spaces in libs with ; - std::replace(libs.begin(), libs.end(), ' ', ';'); std::vector libVec; - cmSystemTools::ExpandListArgument(libs, libVec); + cmSystemTools::ParseWindowsCommandLine(libs.c_str(), libVec); cmComputeLinkInformation* pcli = this->GeneratorTarget->GetLinkInformation(config.c_str()); ----------------------------------------------------------------------- Summary of changes: Source/cmVisualStudio10TargetGenerator.cxx | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 14 13:29:08 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 14 Feb 2017 13:29:08 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-149-g3cffa4c Message-ID: <20170214182908.04780FA4C4@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 3cffa4c58ecdeaf44d05124a6cc2799205ca9670 (commit) via 5e6a882345a53c0dfc96ad8cfe4cd825b8bfa571 (commit) from d4bf5af08435c5bdc0a1575f9b1763844dabc148 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3cffa4c58ecdeaf44d05124a6cc2799205ca9670 commit 3cffa4c58ecdeaf44d05124a6cc2799205ca9670 Merge: d4bf5af 5e6a882 Author: Brad King AuthorDate: Tue Feb 14 13:29:07 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 14 13:29:07 2017 -0500 Merge topic 'vs-refactor-toolset-parsing' into next 5e6a8823 VS: Refactor generator toolset parsing https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=5e6a882345a53c0dfc96ad8cfe4cd825b8bfa571 commit 5e6a882345a53c0dfc96ad8cfe4cd825b8bfa571 Author: Brad King AuthorDate: Wed Feb 8 15:25:23 2017 -0500 Commit: Brad King CommitDate: Tue Feb 14 11:46:07 2017 -0500 VS: Refactor generator toolset parsing We parse `CMAKE_GENERATOR_TOOLSET` values of the forms: * `toolset` * `toolset,host=x64` * `host=x64` Generalize the parsing to support the forms: * `toolset` * `toolset[,key=value]*` * `key=value[,key=value]*` Disallow duplicate keys. Require all but the first field to be of `key=value` form. diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index b64ae26..b1285ac 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -182,24 +182,80 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( bool cmGlobalVisualStudio10Generator::ParseGeneratorToolset( std::string const& ts, cmMakefile* mf) { - if (ts.find_first_of(",=") != ts.npos) { - std::ostringstream e; - /* clang-format off */ - e << - "Generator\n" - " " << this->GetName() << "\n" - "does not recognize the toolset\n" - " " << ts << "\n" - "that was specified."; - /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); - return false; + std::vector const fields = cmSystemTools::tokenize(ts, ","); + std::vector::const_iterator fi = fields.begin(); + if (fi == fields.end()) { + return true; + } + + // The first field may be the VS platform toolset. + if (fi->find('=') == fi->npos) { + this->GeneratorToolset = *fi; + ++fi; + } + + std::set handled; + + // The rest of the fields must be key=value pairs. + for (; fi != fields.end(); ++fi) { + std::string::size_type pos = fi->find('='); + if (pos == fi->npos) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "given toolset specification\n" + " " << ts << "\n" + "that contains a field after the first ',' with no '='." + ; + /* clang-format on */ + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + std::string const key = fi->substr(0, pos); + std::string const value = fi->substr(pos + 1); + if (!handled.insert(key).second) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "given toolset specification\n" + " " << ts << "\n" + "that contains duplicate field key '" << key << "'." + ; + /* clang-format on */ + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + if (!this->ProcessGeneratorToolsetField(key, value)) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "given toolset specification\n" + " " << ts << "\n" + "that contains invalid field '" << *fi << "'." + ; + /* clang-format on */ + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } } - this->GeneratorToolset = ts; return true; } +bool cmGlobalVisualStudio10Generator::ProcessGeneratorToolsetField( + std::string const& key, std::string const& value) +{ + static_cast(key); + static_cast(value); + return false; +} + bool cmGlobalVisualStudio10Generator::InitializeSystem(cmMakefile* mf) { if (this->SystemName == "Windows") { diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 3fc62ec..c5e4bcd 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -23,7 +23,6 @@ public: virtual bool SetSystemName(std::string const& s, cmMakefile* mf); virtual bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf); virtual bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf); - virtual bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf); virtual void GenerateBuildCommand( std::vector& makeCommand, const std::string& makeProgram, @@ -106,6 +105,9 @@ protected: virtual bool InitializeWindowsPhone(cmMakefile* mf); virtual bool InitializeWindowsStore(cmMakefile* mf); + virtual bool ProcessGeneratorToolsetField(std::string const& key, + std::string const& value); + virtual std::string SelectWindowsCEToolset() const; virtual bool SelectWindowsPhoneToolset(std::string& toolset) const; virtual bool SelectWindowsStoreToolset(std::string& toolset) const; @@ -156,6 +158,8 @@ private: virtual std::string FindDevEnvCommand(); virtual std::string GetVSMakeProgram() { return this->GetMSBuildCommand(); } + bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf); + // We do not use the reload macros for VS >= 10. virtual std::string GetUserMacrosDirectory() { return ""; } }; diff --git a/Source/cmGlobalVisualStudio12Generator.cxx b/Source/cmGlobalVisualStudio12Generator.cxx index 2656dcc..de62ff0 100644 --- a/Source/cmGlobalVisualStudio12Generator.cxx +++ b/Source/cmGlobalVisualStudio12Generator.cxx @@ -109,19 +109,15 @@ bool cmGlobalVisualStudio12Generator::MatchesGeneratorName( return false; } -bool cmGlobalVisualStudio12Generator::ParseGeneratorToolset( - std::string const& ts, cmMakefile* mf) +bool cmGlobalVisualStudio12Generator::ProcessGeneratorToolsetField( + std::string const& key, std::string const& value) { - std::string::size_type ts_end = ts.size(); - if (cmHasLiteralSuffix(ts, ",host=x64")) { + if (key == "host" && value == "x64") { this->GeneratorToolsetHostArchitecture = "x64"; - ts_end -= 9; - } else if (ts == "host=x64") { - this->GeneratorToolsetHostArchitecture = "x64"; - ts_end = 0; + return true; } - return this->cmGlobalVisualStudio11Generator::ParseGeneratorToolset( - ts.substr(0, ts_end), mf); + return this->cmGlobalVisualStudio11Generator::ProcessGeneratorToolsetField( + key, value); } bool cmGlobalVisualStudio12Generator::InitializeWindowsPhone(cmMakefile* mf) diff --git a/Source/cmGlobalVisualStudio12Generator.h b/Source/cmGlobalVisualStudio12Generator.h index 79efe52..3453628 100644 --- a/Source/cmGlobalVisualStudio12Generator.h +++ b/Source/cmGlobalVisualStudio12Generator.h @@ -31,8 +31,8 @@ public: // version number virtual const char* GetToolsVersion() { return "12.0"; } protected: - bool ParseGeneratorToolset(std::string const& ts, - cmMakefile* mf) CM_OVERRIDE; + bool ProcessGeneratorToolsetField(std::string const& key, + std::string const& value) CM_OVERRIDE; virtual bool InitializeWindowsPhone(cmMakefile* mf); virtual bool InitializeWindowsStore(cmMakefile* mf); diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetFormat-result.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetFormat-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetFormat-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetFormat-stderr.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetFormat-stderr.txt new file mode 100644 index 0000000..ab3a98f --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetFormat-stderr.txt @@ -0,0 +1,10 @@ +CMake Error at CMakeLists.txt:[0-9]+ \(project\): + Generator + + .* + + given toolset specification + + Test Toolset,not_a_key + + that contains a field after the first ',' with no '='\.$ diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetFormat.cmake b/Tests/RunCMake/GeneratorToolset/BadToolsetFormat.cmake new file mode 100644 index 0000000..2fc38e5 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetFormat.cmake @@ -0,0 +1 @@ +message(FATAL_ERROR "This should not be reached!") diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArch-stderr.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArch-stderr.txt index 5737e95..bd0063a 100644 --- a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArch-stderr.txt +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArch-stderr.txt @@ -3,8 +3,8 @@ CMake Error at CMakeLists.txt:[0-9]+ \(project\): .* - does not recognize the toolset + given toolset specification Test Toolset,host=x6[45] - that was specified\.$ + that contains invalid field 'host=x6[45]'\.$ diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice-result.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice-stderr.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice-stderr.txt new file mode 100644 index 0000000..164d3aa --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice-stderr.txt @@ -0,0 +1,10 @@ +CMake Error at CMakeLists.txt:[0-9]+ \(project\): + Generator + + .* + + given toolset specification + + Test Toolset,host=x64,host=x64 + + that contains duplicate field key 'host'\.$ diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice.cmake b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice.cmake new file mode 100644 index 0000000..2fc38e5 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice.cmake @@ -0,0 +1 @@ +message(FATAL_ERROR "This should not be reached!") diff --git a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake index e8ce47d..902569d 100644 --- a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake @@ -17,10 +17,14 @@ if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[01245]|Xcode" AND NOT XCODE_ run_cmake(TestToolsetHostArchNone) set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x65") run_cmake(BadToolsetHostArch) + set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64,host=x64") + run_cmake(BadToolsetHostArchTwice) else() set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64") run_cmake(BadToolsetHostArch) endif() + set(RunCMake_GENERATOR_TOOLSET "Test Toolset,not_a_key") + run_cmake(BadToolsetFormat) else() set(RunCMake_GENERATOR_TOOLSET "Bad Toolset") run_cmake(BadToolset) ----------------------------------------------------------------------- Summary of changes: Source/cmGlobalVisualStudio10Generator.cxx | 82 ++++++++++++++++---- Source/cmGlobalVisualStudio10Generator.h | 6 +- Source/cmGlobalVisualStudio12Generator.cxx | 16 ++-- Source/cmGlobalVisualStudio12Generator.h | 4 +- .../BadToolsetFormat-result.txt} | 0 .../GeneratorToolset/BadToolsetFormat-stderr.txt | 10 +++ .../BadToolsetFormat.cmake} | 0 .../GeneratorToolset/BadToolsetHostArch-stderr.txt | 4 +- .../BadToolsetHostArchTwice-result.txt} | 0 .../BadToolsetHostArchTwice-stderr.txt | 10 +++ .../BadToolsetHostArchTwice.cmake} | 0 Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake | 4 + 12 files changed, 108 insertions(+), 28 deletions(-) copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => GeneratorToolset/BadToolsetFormat-result.txt} (100%) create mode 100644 Tests/RunCMake/GeneratorToolset/BadToolsetFormat-stderr.txt copy Tests/RunCMake/{GeneratorPlatform/BadPlatform.cmake => GeneratorToolset/BadToolsetFormat.cmake} (100%) copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => GeneratorToolset/BadToolsetHostArchTwice-result.txt} (100%) create mode 100644 Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice-stderr.txt copy Tests/RunCMake/{GeneratorPlatform/BadPlatform.cmake => GeneratorToolset/BadToolsetHostArchTwice.cmake} (100%) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 14 13:38:30 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 14 Feb 2017 13:38:30 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-151-g00340d9 Message-ID: <20170214183830.5D0A8FA62F@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 00340d929ffb8986aa9349137149ae0edd28b60e (commit) via f7e5c6820a6eed8e6f29f7a5634a30b4f42a43aa (commit) from 3cffa4c58ecdeaf44d05124a6cc2799205ca9670 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=00340d929ffb8986aa9349137149ae0edd28b60e commit 00340d929ffb8986aa9349137149ae0edd28b60e Merge: 3cffa4c f7e5c68 Author: Brad King AuthorDate: Tue Feb 14 13:38:29 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 14 13:38:29 2017 -0500 Merge topic 'vs-dedup-tag' into next f7e5c682 VS: De-duplicate PreprocessorDefinitions tag name https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f7e5c6820a6eed8e6f29f7a5634a30b4f42a43aa commit f7e5c6820a6eed8e6f29f7a5634a30b4f42a43aa Author: Brad King AuthorDate: Fri Feb 10 14:23:08 2017 -0500 Commit: Brad King CommitDate: Tue Feb 14 13:37:54 2017 -0500 VS: De-duplicate PreprocessorDefinitions tag name Store the name in a variable for re-use. diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx index c0913e6..6bacfa1 100644 --- a/Source/cmVisualStudioGeneratorOptions.cxx +++ b/Source/cmVisualStudioGeneratorOptions.cxx @@ -252,19 +252,19 @@ void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions( if (this->Defines.empty()) { return; } + const char* tag = "PreprocessorDefinitions"; if (this->Version >= cmGlobalVisualStudioGenerator::VS10) { // if there are configuration specific flags, then // use the configuration specific tag for PreprocessorDefinitions if (!this->Configuration.empty()) { fout << prefix; this->TargetGenerator->WritePlatformConfigTag( - "PreprocessorDefinitions", this->Configuration.c_str(), 0, 0, 0, - &fout); + tag, this->Configuration.c_str(), 0, 0, 0, &fout); } else { - fout << prefix << ""; + fout << prefix << "<" << tag << ">"; } } else { - fout << prefix << "PreprocessorDefinitions=\""; + fout << prefix << tag << "=\""; } const char* sep = ""; for (std::vector::const_iterator di = this->Defines.begin(); @@ -291,7 +291,7 @@ void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions( sep = ";"; } if (this->Version >= cmGlobalVisualStudioGenerator::VS10) { - fout << ";%(PreprocessorDefinitions)" << suffix; + fout << ";%(" << tag << ")" << suffix; } else { fout << "\"" << suffix; } ----------------------------------------------------------------------- Summary of changes: Source/cmVisualStudioGeneratorOptions.cxx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 14 13:40:31 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 14 Feb 2017 13:40:31 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-153-g4a46ce0 Message-ID: <20170214184031.2C3EEBFFC6@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 4a46ce0e5cad085dd7e0013ce1b3d976a2c437c2 (commit) via 7c29a0c860c4bf92a941f6752e0b5c4ebf4c88f3 (commit) from 00340d929ffb8986aa9349137149ae0edd28b60e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4a46ce0e5cad085dd7e0013ce1b3d976a2c437c2 commit 4a46ce0e5cad085dd7e0013ce1b3d976a2c437c2 Merge: 00340d9 7c29a0c Author: Brad King AuthorDate: Tue Feb 14 13:40:30 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 14 13:40:30 2017 -0500 Merge topic 'cuda-drop-comment' into next 7c29a0c8 CMakeDetermineCUDACompiler: Drop out-of-date comment https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7c29a0c860c4bf92a941f6752e0b5c4ebf4c88f3 commit 7c29a0c860c4bf92a941f6752e0b5c4ebf4c88f3 Author: Brad King AuthorDate: Mon Jan 16 15:50:11 2017 -0500 Commit: Brad King CommitDate: Tue Feb 14 13:40:20 2017 -0500 CMakeDetermineCUDACompiler: Drop out-of-date comment diff --git a/Modules/CMakeDetermineCUDACompiler.cmake b/Modules/CMakeDetermineCUDACompiler.cmake index 7b6d17b..375e230 100644 --- a/Modules/CMakeDetermineCUDACompiler.cmake +++ b/Modules/CMakeDetermineCUDACompiler.cmake @@ -75,13 +75,6 @@ if(MSVC_CUDA_ARCHITECTURE_ID) "set(MSVC_CUDA_ARCHITECTURE_ID ${MSVC_CUDA_ARCHITECTURE_ID})") endif() -#if this compiler vendor is matches NVIDIA we can determine -#what the host compiler is. This only needs to be done if the CMAKE_CUDA_HOST_COMPILER -#has NOT been explicitly set -# -#Find the line from compiler ID that contains a.out ( or last line ) -#We also need to find the implicit link lines. Which can be done by replacing -#the compiler with cuda-fake-ld and pass too CMAKE_PARSE_IMPLICIT_LINK_INFO if(CMAKE_CUDA_COMPILER_ID STREQUAL NVIDIA) set(_nvcc_log "") string(REPLACE "\r" "" _nvcc_output_orig "${CMAKE_CUDA_COMPILER_PRODUCED_OUTPUT}") ----------------------------------------------------------------------- Summary of changes: Modules/CMakeDetermineCUDACompiler.cmake | 7 ------- 1 file changed, 7 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 14 14:52:31 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 14 Feb 2017 14:52:31 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-155-g60c0bb2 Message-ID: <20170214195232.6DC05F5DD8@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 60c0bb2d4a7390ce63237da1b6a3d5dfcc79bab6 (commit) via 59ed323d4648a61d911679190273c35f950e20ce (commit) from 4a46ce0e5cad085dd7e0013ce1b3d976a2c437c2 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=60c0bb2d4a7390ce63237da1b6a3d5dfcc79bab6 commit 60c0bb2d4a7390ce63237da1b6a3d5dfcc79bab6 Merge: 4a46ce0 59ed323 Author: Brad King AuthorDate: Tue Feb 14 14:52:31 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 14 14:52:31 2017 -0500 Merge topic 'cuda-no-Os' into next 59ed323d CUDA: Do not use non-existent -Os flag for nvcc https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=59ed323d4648a61d911679190273c35f950e20ce commit 59ed323d4648a61d911679190273c35f950e20ce Author: Brad King AuthorDate: Tue Feb 14 14:49:53 2017 -0500 Commit: Brad King CommitDate: Tue Feb 14 14:49:53 2017 -0500 CUDA: Do not use non-existent -Os flag for nvcc Fix the CUDA MinSizeRel configuration flags to avoid using the `-Os` flag that nvcc does not support. diff --git a/Modules/Compiler/NVIDIA-CUDA.cmake b/Modules/Compiler/NVIDIA-CUDA.cmake index ae35132..7903313 100644 --- a/Modules/Compiler/NVIDIA-CUDA.cmake +++ b/Modules/Compiler/NVIDIA-CUDA.cmake @@ -13,7 +13,7 @@ set(CMAKE_INCLUDE_SYSTEM_FLAG_CUDA -isystem=) string(APPEND CMAKE_CUDA_FLAGS_INIT " ") string(APPEND CMAKE_CUDA_FLAGS_DEBUG_INIT " -g") -string(APPEND CMAKE_CUDA_FLAGS_MINSIZEREL_INIT " -Os -DNDEBUG") +string(APPEND CMAKE_CUDA_FLAGS_MINSIZEREL_INIT " -O1 -DNDEBUG") string(APPEND CMAKE_CUDA_FLAGS_RELEASE_INIT " -O3 -DNDEBUG") string(APPEND CMAKE_CUDA_FLAGS_RELWITHDEBINFO_INIT " -O2 -g -DNDEBUG") ----------------------------------------------------------------------- Summary of changes: Modules/Compiler/NVIDIA-CUDA.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From kwrobot at kitware.com Wed Feb 15 00:01:09 2017 From: kwrobot at kitware.com (Kitware Robot) Date: Wed, 15 Feb 2017 00:01:09 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-84-g8b155a6 Message-ID: <20170215050110.3767DFA820@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 8b155a6c092d2b5e5355d6488fd7fa7e71f58207 (commit) from 34ce3017b530595753b5987bd0702aceded683be (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8b155a6c092d2b5e5355d6488fd7fa7e71f58207 commit 8b155a6c092d2b5e5355d6488fd7fa7e71f58207 Author: Kitware Robot AuthorDate: Wed Feb 15 00:01:04 2017 -0500 Commit: Kitware Robot CommitDate: Wed Feb 15 00:01:04 2017 -0500 CMake Nightly Date Stamp diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 8b1882f..2efc5bf 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 8) -set(CMake_VERSION_PATCH 20170214) +set(CMake_VERSION_PATCH 20170215) #set(CMake_VERSION_RC 1) ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 15 08:16:47 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 15 Feb 2017 08:16:47 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-157-gc497701 Message-ID: <20170215131647.57820FA394@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via c4977015291e195193f0e529d86ebc039e009907 (commit) via db86099f386b59ed8fe0b66d1956454de14aede8 (commit) from 60c0bb2d4a7390ce63237da1b6a3d5dfcc79bab6 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c4977015291e195193f0e529d86ebc039e009907 commit c4977015291e195193f0e529d86ebc039e009907 Merge: 60c0bb2 db86099 Author: Brad King AuthorDate: Wed Feb 15 08:16:43 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 15 08:16:43 2017 -0500 Merge topic 'vs-refactor-toolset-parsing' into next db86099f fixup! VS: Refactor generator toolset parsing https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=db86099f386b59ed8fe0b66d1956454de14aede8 commit db86099f386b59ed8fe0b66d1956454de14aede8 Author: Brad King AuthorDate: Wed Feb 15 08:10:11 2017 -0500 Commit: Brad King CommitDate: Wed Feb 15 08:10:11 2017 -0500 fixup! VS: Refactor generator toolset parsing diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-result.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-stderr.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-stderr.txt new file mode 100644 index 0000000..5737e95 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-stderr.txt @@ -0,0 +1,10 @@ +CMake Error at CMakeLists.txt:[0-9]+ \(project\): + Generator + + .* + + does not recognize the toolset + + Test Toolset,host=x6[45] + + that was specified\.$ diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode.cmake b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode.cmake new file mode 100644 index 0000000..2fc38e5 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode.cmake @@ -0,0 +1 @@ +message(FATAL_ERROR "This should not be reached!") diff --git a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake index 902569d..44c67a2 100644 --- a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake @@ -3,7 +3,7 @@ include(RunCMake) set(RunCMake_GENERATOR_TOOLSET "") run_cmake(NoToolset) -if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[01245]|Xcode" AND NOT XCODE_BELOW_3) +if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[01245]") set(RunCMake_GENERATOR_TOOLSET "Test Toolset") run_cmake(TestToolset) if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[245]") @@ -25,6 +25,11 @@ if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[01245]|Xcode" AND NOT XCODE_ endif() set(RunCMake_GENERATOR_TOOLSET "Test Toolset,not_a_key") run_cmake(BadToolsetFormat) +elseif("${RunCMake_GENERATOR}" STREQUAL "Xcode" AND NOT XCODE_BELOW_3) + set(RunCMake_GENERATOR_TOOLSET "Test Toolset") + run_cmake(TestToolset) + set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64") + run_cmake(BadToolsetHostArchXcode) else() set(RunCMake_GENERATOR_TOOLSET "Bad Toolset") run_cmake(BadToolset) ----------------------------------------------------------------------- Summary of changes: .../BadToolsetHostArchXcode-result.txt} | 0 ...etHostArch-stderr.txt => BadToolsetHostArchXcode-stderr.txt} | 4 ++-- .../BadToolsetHostArchXcode.cmake} | 0 Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake | 7 ++++++- 4 files changed, 8 insertions(+), 3 deletions(-) copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => GeneratorToolset/BadToolsetHostArchXcode-result.txt} (100%) copy Tests/RunCMake/GeneratorToolset/{BadToolsetHostArch-stderr.txt => BadToolsetHostArchXcode-stderr.txt} (56%) copy Tests/RunCMake/{GeneratorPlatform/BadPlatform.cmake => GeneratorToolset/BadToolsetHostArchXcode.cmake} (100%) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 15 08:17:34 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 15 Feb 2017 08:17:34 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-160-g258250c Message-ID: <20170215131734.C1102FA3D0@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 258250c4452bf6d73a0065d5914ce55360603d84 (commit) via f773933f2630a17ce6b3b2aa6f8d7d8b65eb336c (commit) via d9e2b9a909b5f5b51ef3a106ed1d60a8d4cb795a (commit) from c4977015291e195193f0e529d86ebc039e009907 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=258250c4452bf6d73a0065d5914ce55360603d84 commit 258250c4452bf6d73a0065d5914ce55360603d84 Merge: c497701 f773933 Author: Brad King AuthorDate: Wed Feb 15 08:17:34 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 15 08:17:34 2017 -0500 Merge topic 'vs-refactor-toolset-parsing' into next f773933f VS: Refactor generator toolset parsing d9e2b9a9 Tests: Split out RunCMake.GeneratorToolset Xcode checks https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f773933f2630a17ce6b3b2aa6f8d7d8b65eb336c commit f773933f2630a17ce6b3b2aa6f8d7d8b65eb336c Author: Brad King AuthorDate: Wed Feb 8 15:25:23 2017 -0500 Commit: Brad King CommitDate: Wed Feb 15 08:15:37 2017 -0500 VS: Refactor generator toolset parsing We parse `CMAKE_GENERATOR_TOOLSET` values of the forms: * `toolset` * `toolset,host=x64` * `host=x64` Generalize the parsing to support the forms: * `toolset` * `toolset[,key=value]*` * `key=value[,key=value]*` Disallow duplicate keys. Require all but the first field to be of `key=value` form. diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index b64ae26..b1285ac 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -182,24 +182,80 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( bool cmGlobalVisualStudio10Generator::ParseGeneratorToolset( std::string const& ts, cmMakefile* mf) { - if (ts.find_first_of(",=") != ts.npos) { - std::ostringstream e; - /* clang-format off */ - e << - "Generator\n" - " " << this->GetName() << "\n" - "does not recognize the toolset\n" - " " << ts << "\n" - "that was specified."; - /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); - return false; + std::vector const fields = cmSystemTools::tokenize(ts, ","); + std::vector::const_iterator fi = fields.begin(); + if (fi == fields.end()) { + return true; + } + + // The first field may be the VS platform toolset. + if (fi->find('=') == fi->npos) { + this->GeneratorToolset = *fi; + ++fi; + } + + std::set handled; + + // The rest of the fields must be key=value pairs. + for (; fi != fields.end(); ++fi) { + std::string::size_type pos = fi->find('='); + if (pos == fi->npos) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "given toolset specification\n" + " " << ts << "\n" + "that contains a field after the first ',' with no '='." + ; + /* clang-format on */ + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + std::string const key = fi->substr(0, pos); + std::string const value = fi->substr(pos + 1); + if (!handled.insert(key).second) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "given toolset specification\n" + " " << ts << "\n" + "that contains duplicate field key '" << key << "'." + ; + /* clang-format on */ + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + if (!this->ProcessGeneratorToolsetField(key, value)) { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "given toolset specification\n" + " " << ts << "\n" + "that contains invalid field '" << *fi << "'." + ; + /* clang-format on */ + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } } - this->GeneratorToolset = ts; return true; } +bool cmGlobalVisualStudio10Generator::ProcessGeneratorToolsetField( + std::string const& key, std::string const& value) +{ + static_cast(key); + static_cast(value); + return false; +} + bool cmGlobalVisualStudio10Generator::InitializeSystem(cmMakefile* mf) { if (this->SystemName == "Windows") { diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 3fc62ec..c5e4bcd 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -23,7 +23,6 @@ public: virtual bool SetSystemName(std::string const& s, cmMakefile* mf); virtual bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf); virtual bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf); - virtual bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf); virtual void GenerateBuildCommand( std::vector& makeCommand, const std::string& makeProgram, @@ -106,6 +105,9 @@ protected: virtual bool InitializeWindowsPhone(cmMakefile* mf); virtual bool InitializeWindowsStore(cmMakefile* mf); + virtual bool ProcessGeneratorToolsetField(std::string const& key, + std::string const& value); + virtual std::string SelectWindowsCEToolset() const; virtual bool SelectWindowsPhoneToolset(std::string& toolset) const; virtual bool SelectWindowsStoreToolset(std::string& toolset) const; @@ -156,6 +158,8 @@ private: virtual std::string FindDevEnvCommand(); virtual std::string GetVSMakeProgram() { return this->GetMSBuildCommand(); } + bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf); + // We do not use the reload macros for VS >= 10. virtual std::string GetUserMacrosDirectory() { return ""; } }; diff --git a/Source/cmGlobalVisualStudio12Generator.cxx b/Source/cmGlobalVisualStudio12Generator.cxx index 2656dcc..de62ff0 100644 --- a/Source/cmGlobalVisualStudio12Generator.cxx +++ b/Source/cmGlobalVisualStudio12Generator.cxx @@ -109,19 +109,15 @@ bool cmGlobalVisualStudio12Generator::MatchesGeneratorName( return false; } -bool cmGlobalVisualStudio12Generator::ParseGeneratorToolset( - std::string const& ts, cmMakefile* mf) +bool cmGlobalVisualStudio12Generator::ProcessGeneratorToolsetField( + std::string const& key, std::string const& value) { - std::string::size_type ts_end = ts.size(); - if (cmHasLiteralSuffix(ts, ",host=x64")) { + if (key == "host" && value == "x64") { this->GeneratorToolsetHostArchitecture = "x64"; - ts_end -= 9; - } else if (ts == "host=x64") { - this->GeneratorToolsetHostArchitecture = "x64"; - ts_end = 0; + return true; } - return this->cmGlobalVisualStudio11Generator::ParseGeneratorToolset( - ts.substr(0, ts_end), mf); + return this->cmGlobalVisualStudio11Generator::ProcessGeneratorToolsetField( + key, value); } bool cmGlobalVisualStudio12Generator::InitializeWindowsPhone(cmMakefile* mf) diff --git a/Source/cmGlobalVisualStudio12Generator.h b/Source/cmGlobalVisualStudio12Generator.h index 79efe52..3453628 100644 --- a/Source/cmGlobalVisualStudio12Generator.h +++ b/Source/cmGlobalVisualStudio12Generator.h @@ -31,8 +31,8 @@ public: // version number virtual const char* GetToolsVersion() { return "12.0"; } protected: - bool ParseGeneratorToolset(std::string const& ts, - cmMakefile* mf) CM_OVERRIDE; + bool ProcessGeneratorToolsetField(std::string const& key, + std::string const& value) CM_OVERRIDE; virtual bool InitializeWindowsPhone(cmMakefile* mf); virtual bool InitializeWindowsStore(cmMakefile* mf); diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetFormat-result.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetFormat-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetFormat-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetFormat-stderr.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetFormat-stderr.txt new file mode 100644 index 0000000..ab3a98f --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetFormat-stderr.txt @@ -0,0 +1,10 @@ +CMake Error at CMakeLists.txt:[0-9]+ \(project\): + Generator + + .* + + given toolset specification + + Test Toolset,not_a_key + + that contains a field after the first ',' with no '='\.$ diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetFormat.cmake b/Tests/RunCMake/GeneratorToolset/BadToolsetFormat.cmake new file mode 100644 index 0000000..2fc38e5 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetFormat.cmake @@ -0,0 +1 @@ +message(FATAL_ERROR "This should not be reached!") diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArch-stderr.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArch-stderr.txt index 5737e95..bd0063a 100644 --- a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArch-stderr.txt +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArch-stderr.txt @@ -3,8 +3,8 @@ CMake Error at CMakeLists.txt:[0-9]+ \(project\): .* - does not recognize the toolset + given toolset specification Test Toolset,host=x6[45] - that was specified\.$ + that contains invalid field 'host=x6[45]'\.$ diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice-result.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice-stderr.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice-stderr.txt new file mode 100644 index 0000000..164d3aa --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice-stderr.txt @@ -0,0 +1,10 @@ +CMake Error at CMakeLists.txt:[0-9]+ \(project\): + Generator + + .* + + given toolset specification + + Test Toolset,host=x64,host=x64 + + that contains duplicate field key 'host'\.$ diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice.cmake b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice.cmake new file mode 100644 index 0000000..2fc38e5 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice.cmake @@ -0,0 +1 @@ +message(FATAL_ERROR "This should not be reached!") diff --git a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake index 3c3d974..44c67a2 100644 --- a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake @@ -17,10 +17,14 @@ if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[01245]") run_cmake(TestToolsetHostArchNone) set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x65") run_cmake(BadToolsetHostArch) + set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64,host=x64") + run_cmake(BadToolsetHostArchTwice) else() set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64") run_cmake(BadToolsetHostArch) endif() + set(RunCMake_GENERATOR_TOOLSET "Test Toolset,not_a_key") + run_cmake(BadToolsetFormat) elseif("${RunCMake_GENERATOR}" STREQUAL "Xcode" AND NOT XCODE_BELOW_3) set(RunCMake_GENERATOR_TOOLSET "Test Toolset") run_cmake(TestToolset) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d9e2b9a909b5f5b51ef3a106ed1d60a8d4cb795a commit d9e2b9a909b5f5b51ef3a106ed1d60a8d4cb795a Author: Brad King AuthorDate: Wed Feb 15 08:14:25 2017 -0500 Commit: Brad King CommitDate: Wed Feb 15 08:15:00 2017 -0500 Tests: Split out RunCMake.GeneratorToolset Xcode checks This will allow the behavior of VS and Xcode generators to differ. diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-result.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-stderr.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-stderr.txt new file mode 100644 index 0000000..5737e95 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-stderr.txt @@ -0,0 +1,10 @@ +CMake Error at CMakeLists.txt:[0-9]+ \(project\): + Generator + + .* + + does not recognize the toolset + + Test Toolset,host=x6[45] + + that was specified\.$ diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode.cmake b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode.cmake new file mode 100644 index 0000000..2fc38e5 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode.cmake @@ -0,0 +1 @@ +message(FATAL_ERROR "This should not be reached!") diff --git a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake index e8ce47d..3c3d974 100644 --- a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake @@ -3,7 +3,7 @@ include(RunCMake) set(RunCMake_GENERATOR_TOOLSET "") run_cmake(NoToolset) -if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[01245]|Xcode" AND NOT XCODE_BELOW_3) +if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[01245]") set(RunCMake_GENERATOR_TOOLSET "Test Toolset") run_cmake(TestToolset) if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[245]") @@ -21,6 +21,11 @@ if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 1[01245]|Xcode" AND NOT XCODE_ set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64") run_cmake(BadToolsetHostArch) endif() +elseif("${RunCMake_GENERATOR}" STREQUAL "Xcode" AND NOT XCODE_BELOW_3) + set(RunCMake_GENERATOR_TOOLSET "Test Toolset") + run_cmake(TestToolset) + set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64") + run_cmake(BadToolsetHostArchXcode) else() set(RunCMake_GENERATOR_TOOLSET "Bad Toolset") run_cmake(BadToolset) ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 15 08:24:02 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 15 Feb 2017 08:24:02 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-87-g75040fc Message-ID: <20170215132402.4FBA6FA56D@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 75040fc103b763092e54274d088659da792e72e8 (commit) via ff843dbd547d06b9dcb25c3970e857fe395f2dcf (commit) via ced3396d048c8389327f661a99986fef51ee8a3f (commit) from 8b155a6c092d2b5e5355d6488fd7fa7e71f58207 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=75040fc103b763092e54274d088659da792e72e8 commit 75040fc103b763092e54274d088659da792e72e8 Merge: 8b155a6 ff843db Author: Brad King AuthorDate: Wed Feb 15 08:24:00 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 15 08:24:00 2017 -0500 Merge topic 'update-kwsys' ff843dbd Merge branch 'upstream-KWSys' into update-kwsys ced3396d KWSys 2017-02-14 (5c6f7836) ----------------------------------------------------------------------- Summary of changes: Source/kwsys/SystemInformation.cxx | 246 +++++++++------------------------ Source/kwsys/SystemInformation.hxx.in | 2 +- 2 files changed, 66 insertions(+), 182 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 15 08:24:04 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 15 Feb 2017 08:24:04 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-89-g8ba5c21 Message-ID: <20170215132404.A7745FA590@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 8ba5c21db774cb23d223612ba67963723010e9f3 (commit) via 59ed323d4648a61d911679190273c35f950e20ce (commit) from 75040fc103b763092e54274d088659da792e72e8 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8ba5c21db774cb23d223612ba67963723010e9f3 commit 8ba5c21db774cb23d223612ba67963723010e9f3 Merge: 75040fc 59ed323 Author: Brad King AuthorDate: Wed Feb 15 08:24:02 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 15 08:24:02 2017 -0500 Merge topic 'cuda-no-Os' 59ed323d CUDA: Do not use non-existent -Os flag for nvcc ----------------------------------------------------------------------- Summary of changes: Modules/Compiler/NVIDIA-CUDA.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 15 08:24:07 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 15 Feb 2017 08:24:07 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-92-ge853dfe Message-ID: <20170215132407.4CC29FA56D@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via e853dfed6aef2dccc6bf05b6d19a5911e76f51c6 (commit) via 1c60231ca546597ef8b80e7340c8991b06387cbf (commit) via 8d75d8dc72a0ac4502991891782a2c84df1f61c3 (commit) from 8ba5c21db774cb23d223612ba67963723010e9f3 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e853dfed6aef2dccc6bf05b6d19a5911e76f51c6 commit e853dfed6aef2dccc6bf05b6d19a5911e76f51c6 Merge: 8ba5c21 1c60231 Author: Brad King AuthorDate: Wed Feb 15 08:24:05 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 15 08:24:05 2017 -0500 Merge topic 'cuda-with-c' 1c60231c CUDA: Link to standard system libraries when linking as CUDA 8d75d8dc Tests: Add case for CUDA with C but not C++ ----------------------------------------------------------------------- Summary of changes: Modules/CMakeCUDAInformation.cmake | 6 ++++++ Modules/Platform/Windows-NVIDIA-CUDA.cmake | 2 ++ Tests/Cuda/CMakeLists.txt | 1 + Tests/Cuda/WithC/CMakeLists.txt | 12 ++++++++++++ Tests/Cuda/WithC/cuda.cu | 16 ++++++++++++++++ Tests/Cuda/WithC/main.c | 14 ++++++++++++++ 6 files changed, 51 insertions(+) create mode 100644 Tests/Cuda/WithC/CMakeLists.txt create mode 100644 Tests/Cuda/WithC/cuda.cu create mode 100644 Tests/Cuda/WithC/main.c hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 15 08:24:10 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 15 Feb 2017 08:24:10 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-94-g99ca1e2 Message-ID: <20170215132410.607F9FA5AB@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 99ca1e27e2453977d9b6e1b2a886c5b767fa9606 (commit) via 7c29a0c860c4bf92a941f6752e0b5c4ebf4c88f3 (commit) from e853dfed6aef2dccc6bf05b6d19a5911e76f51c6 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=99ca1e27e2453977d9b6e1b2a886c5b767fa9606 commit 99ca1e27e2453977d9b6e1b2a886c5b767fa9606 Merge: e853dfe 7c29a0c Author: Brad King AuthorDate: Wed Feb 15 08:24:07 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 15 08:24:07 2017 -0500 Merge topic 'cuda-drop-comment' 7c29a0c8 CMakeDetermineCUDACompiler: Drop out-of-date comment ----------------------------------------------------------------------- Summary of changes: Modules/CMakeDetermineCUDACompiler.cmake | 7 ------- 1 file changed, 7 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 15 08:24:12 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 15 Feb 2017 08:24:12 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-96-g6a5e5a9 Message-ID: <20170215132412.B9715FA5A5@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 6a5e5a926817f7318a2a80822aa2ce28674344f4 (commit) via f7e5c6820a6eed8e6f29f7a5634a30b4f42a43aa (commit) from 99ca1e27e2453977d9b6e1b2a886c5b767fa9606 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6a5e5a926817f7318a2a80822aa2ce28674344f4 commit 6a5e5a926817f7318a2a80822aa2ce28674344f4 Merge: 99ca1e2 f7e5c68 Author: Brad King AuthorDate: Wed Feb 15 08:24:10 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 15 08:24:10 2017 -0500 Merge topic 'vs-dedup-tag' f7e5c682 VS: De-duplicate PreprocessorDefinitions tag name ----------------------------------------------------------------------- Summary of changes: Source/cmVisualStudioGeneratorOptions.cxx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 15 08:24:15 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 15 Feb 2017 08:24:15 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-99-g8ff8766 Message-ID: <20170215132415.0D77DFA5B5@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 8ff87662325b2f2c216111100da03fb78bca142c (commit) via 8ba6dc362dd1c5b073c68f8a873a91ddd2743e34 (commit) via 1d04d2ce3609da4c4f8d59ccfabd8848a6e765d4 (commit) from 6a5e5a926817f7318a2a80822aa2ce28674344f4 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8ff87662325b2f2c216111100da03fb78bca142c commit 8ff87662325b2f2c216111100da03fb78bca142c Merge: 6a5e5a9 8ba6dc3 Author: Brad King AuthorDate: Wed Feb 15 08:24:13 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 15 08:24:13 2017 -0500 Merge topic 'vs-refactor-libs' 8ba6dc36 VS: Place CMAKE__STANDARD_LIBRARIES after other libraries 1d04d2ce VS: Refactor parsing of CMAKE__STANDARD_LIBRARIES ----------------------------------------------------------------------- Summary of changes: Source/cmVisualStudio10TargetGenerator.cxx | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 15 08:24:29 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 15 Feb 2017 08:24:29 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-168-g85cb919 Message-ID: <20170215132429.DD4F3FA56E@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 85cb9195338bfb9a3db0f3a4c60fe031599172eb (commit) via 8ff87662325b2f2c216111100da03fb78bca142c (commit) via 6a5e5a926817f7318a2a80822aa2ce28674344f4 (commit) via 99ca1e27e2453977d9b6e1b2a886c5b767fa9606 (commit) via e853dfed6aef2dccc6bf05b6d19a5911e76f51c6 (commit) via 8ba5c21db774cb23d223612ba67963723010e9f3 (commit) via 75040fc103b763092e54274d088659da792e72e8 (commit) via 8b155a6c092d2b5e5355d6488fd7fa7e71f58207 (commit) from 258250c4452bf6d73a0065d5914ce55360603d84 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=85cb9195338bfb9a3db0f3a4c60fe031599172eb commit 85cb9195338bfb9a3db0f3a4c60fe031599172eb Merge: 258250c 8ff8766 Author: Brad King AuthorDate: Wed Feb 15 08:24:21 2017 -0500 Commit: Brad King CommitDate: Wed Feb 15 08:24:21 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 15 08:26:03 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 15 Feb 2017 08:26:03 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-102-g72cfb3c Message-ID: <20170215132603.83349FA5B8@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 72cfb3c3d2e8f6167cf08289691f7b0c61d0d331 (commit) via 272c348d5a1c3f713586e05e0d73fd18441f7bb2 (commit) via 81ebf4be3eeabe7f1fc42929b3cc46e515fd4800 (commit) from 8ff87662325b2f2c216111100da03fb78bca142c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 15 08:26:03 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 15 Feb 2017 08:26:03 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-172-g4e93e90 Message-ID: <20170215132603.9BB7AFA5D5@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 4e93e9036ad904278b1634e082dbc627aea868e8 (commit) via 72cfb3c3d2e8f6167cf08289691f7b0c61d0d331 (commit) via 272c348d5a1c3f713586e05e0d73fd18441f7bb2 (commit) via 81ebf4be3eeabe7f1fc42929b3cc46e515fd4800 (commit) from 85cb9195338bfb9a3db0f3a4c60fe031599172eb (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4e93e9036ad904278b1634e082dbc627aea868e8 commit 4e93e9036ad904278b1634e082dbc627aea868e8 Merge: 85cb919 72cfb3c Author: Brad King AuthorDate: Wed Feb 15 08:25:52 2017 -0500 Commit: Brad King CommitDate: Wed Feb 15 08:25:52 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 15 08:26:03 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 15 Feb 2017 08:26:03 -0500 (EST) Subject: [Cmake-commits] CMake branch, release, updated. v3.8.0-rc1-18-g272c348 Message-ID: <20170215132603.DE12DFA5B5@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, release has been updated via 272c348d5a1c3f713586e05e0d73fd18441f7bb2 (commit) via 59ed323d4648a61d911679190273c35f950e20ce (commit) via 81ebf4be3eeabe7f1fc42929b3cc46e515fd4800 (commit) via 1c60231ca546597ef8b80e7340c8991b06387cbf (commit) via 8d75d8dc72a0ac4502991891782a2c84df1f61c3 (commit) from f45e3b950991f5c4f66cd132bda61a369a3016d7 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- Summary of changes: Modules/CMakeCUDAInformation.cmake | 6 ++++++ Modules/Compiler/NVIDIA-CUDA.cmake | 2 +- Modules/Platform/Windows-NVIDIA-CUDA.cmake | 2 ++ Tests/Cuda/CMakeLists.txt | 1 + Tests/Cuda/WithC/CMakeLists.txt | 12 ++++++++++++ Tests/Cuda/WithC/cuda.cu | 16 ++++++++++++++++ Tests/Cuda/WithC/main.c | 14 ++++++++++++++ 7 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 Tests/Cuda/WithC/CMakeLists.txt create mode 100644 Tests/Cuda/WithC/cuda.cu create mode 100644 Tests/Cuda/WithC/main.c hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 15 08:42:00 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 15 Feb 2017 08:42:00 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-175-g13314a3 Message-ID: <20170215134200.3F477C02E3@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 13314a3e27942a44e747a9ba52e0c819a1b602d2 (commit) via 67fbc2b24e549ce159378277d651e72302b9fc70 (commit) via 6581d3c2df248a6afdcbf19c48bf6d69c29d5bd0 (commit) from 4e93e9036ad904278b1634e082dbc627aea868e8 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=13314a3e27942a44e747a9ba52e0c819a1b602d2 commit 13314a3e27942a44e747a9ba52e0c819a1b602d2 Merge: 4e93e90 67fbc2b Author: Brad King AuthorDate: Wed Feb 15 08:41:59 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 15 08:41:59 2017 -0500 Merge topic 'cuda-msvc-flags' into next 67fbc2b2 CUDA: Fix default compiler flags on Windows 6581d3c2 CUDA: Fix test cases to not override CUDA flags https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=67fbc2b24e549ce159378277d651e72302b9fc70 commit 67fbc2b24e549ce159378277d651e72302b9fc70 Author: Brad King AuthorDate: Tue Feb 14 15:11:25 2017 -0500 Commit: Brad King CommitDate: Wed Feb 15 08:29:54 2017 -0500 CUDA: Fix default compiler flags on Windows Fix the default values of `CMAKE_CUDA_FLAGS[_]` on Windows to make the host compiler flags match those produced for C++ by the `Platform/Windows-MSVC` module. This makes the flags consistent with those used for C++. diff --git a/Modules/Compiler/NVIDIA-CUDA.cmake b/Modules/Compiler/NVIDIA-CUDA.cmake index 7903313..316cab8 100644 --- a/Modules/Compiler/NVIDIA-CUDA.cmake +++ b/Modules/Compiler/NVIDIA-CUDA.cmake @@ -7,16 +7,15 @@ if(NOT "x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC") # CMAKE_SHARED_LIBRARY_CUDA_FLAGS is sent to the host linker so we # don't need to forward it through nvcc. set(CMAKE_SHARED_LIBRARY_CUDA_FLAGS -fPIC) + string(APPEND CMAKE_CUDA_FLAGS_INIT " ") + string(APPEND CMAKE_CUDA_FLAGS_DEBUG_INIT " -g") + string(APPEND CMAKE_CUDA_FLAGS_RELEASE_INIT " -O3 -DNDEBUG") + string(APPEND CMAKE_CUDA_FLAGS_MINSIZEREL_INIT " -O1 -DNDEBUG") + string(APPEND CMAKE_CUDA_FLAGS_RELWITHDEBINFO_INIT " -O2 -g -DNDEBUG") endif() set(CMAKE_SHARED_LIBRARY_CREATE_CUDA_FLAGS -shared) set(CMAKE_INCLUDE_SYSTEM_FLAG_CUDA -isystem=) -string(APPEND CMAKE_CUDA_FLAGS_INIT " ") -string(APPEND CMAKE_CUDA_FLAGS_DEBUG_INIT " -g") -string(APPEND CMAKE_CUDA_FLAGS_MINSIZEREL_INIT " -O1 -DNDEBUG") -string(APPEND CMAKE_CUDA_FLAGS_RELEASE_INIT " -O3 -DNDEBUG") -string(APPEND CMAKE_CUDA_FLAGS_RELWITHDEBINFO_INIT " -O2 -g -DNDEBUG") - if("x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC") set(CMAKE_CUDA_STANDARD_DEFAULT "") else() diff --git a/Modules/Platform/Windows-NVIDIA-CUDA.cmake b/Modules/Platform/Windows-NVIDIA-CUDA.cmake index eda41e0..23473ed 100644 --- a/Modules/Platform/Windows-NVIDIA-CUDA.cmake +++ b/Modules/Platform/Windows-NVIDIA-CUDA.cmake @@ -35,10 +35,12 @@ set(CMAKE_CUDA_DEVICE_LINK_LIBRARY set(CMAKE_CUDA_DEVICE_LINK_EXECUTABLE " -shared -dlink -o -Xcompiler=-Fd,-FS") -string(APPEND CMAKE_CUDA_FLAGS_INIT " -Xcompiler=-GR,-EHsc") -string(APPEND CMAKE_CUDA_FLAGS_DEBUG_INIT " -Xcompiler=-MDd,-Zi,-RTC1") -string(APPEND CMAKE_CUDA_FLAGS_RELEASE_INIT " -Xcompiler=-MD") -string(APPEND CMAKE_CUDA_FLAGS_RELWITHDEBINFO_INIT " -Xcompiler=-MD") -string(APPEND CMAKE_CUDA_FLAGS_MINSIZEREL_INIT " -Xcompiler=-MD") +string(REPLACE "/D" "-D" _PLATFORM_DEFINES_CUDA "${_PLATFORM_DEFINES}${_PLATFORM_DEFINES_CXX}") + +string(APPEND CMAKE_CUDA_FLAGS_INIT " ${PLATFORM_DEFINES_CUDA} -D_WINDOWS -Xcompiler=\"/W3${_FLAGS_CXX}\"") +string(APPEND CMAKE_CUDA_FLAGS_DEBUG_INIT " -Xcompiler=\"-MDd -Zi ${_RTC1}\"") +string(APPEND CMAKE_CUDA_FLAGS_RELEASE_INIT " -Xcompiler=\"-MD -O2 -Ob2\" -DNDEBUG") +string(APPEND CMAKE_CUDA_FLAGS_RELWITHDEBINFO_INIT " -Xcompiler=\"-MD -Zi -O2 -Ob1\" -DNDEBUG") +string(APPEND CMAKE_CUDA_FLAGS_MINSIZEREL_INIT " -Xcompiler=\"-MD -O1 -Ob1\" -DNDEBUG") set(CMAKE_CUDA_STANDARD_LIBRARIES_INIT "${CMAKE_C_STANDARD_LIBRARIES_INIT}") https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6581d3c2df248a6afdcbf19c48bf6d69c29d5bd0 commit 6581d3c2df248a6afdcbf19c48bf6d69c29d5bd0 Author: Brad King AuthorDate: Tue Feb 14 15:09:55 2017 -0500 Commit: Brad King CommitDate: Wed Feb 15 08:29:54 2017 -0500 CUDA: Fix test cases to not override CUDA flags Append to `CMAKE_CUDA_FLAGS` instead of overwriting it. diff --git a/Tests/Cuda/Complex/CMakeLists.txt b/Tests/Cuda/Complex/CMakeLists.txt index 9a3703a..bff7d07 100644 --- a/Tests/Cuda/Complex/CMakeLists.txt +++ b/Tests/Cuda/Complex/CMakeLists.txt @@ -15,7 +15,7 @@ project (CudaComplex CXX CUDA) #and also bulding cpp targets that need cuda implicit libraries #verify that we can pass explicit cuda arch flags -set(CMAKE_CUDA_FLAGS "-gencode arch=compute_30,code=compute_30") +string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=compute_30") set(CMAKE_CUDA_STANDARD 11) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CUDA_STANDARD_REQUIRED TRUE) diff --git a/Tests/Cuda/ProperLinkFlags/CMakeLists.txt b/Tests/Cuda/ProperLinkFlags/CMakeLists.txt index a9eb8bd..b6e0e39 100644 --- a/Tests/Cuda/ProperLinkFlags/CMakeLists.txt +++ b/Tests/Cuda/ProperLinkFlags/CMakeLists.txt @@ -9,7 +9,7 @@ project (ProperLinkFlags CUDA CXX) #Specify a set of valid CUDA flags and an invalid set of CXX flags ( for CUDA ) #to make sure we don't use the CXX flags when linking CUDA executables -set(CMAKE_CUDA_FLAGS "-arch=sm_35 --use_fast_math") +string(APPEND CMAKE_CUDA_FLAGS " -arch=sm_35 --use_fast_math") set(CMAKE_CXX_FLAGS "-Wall") set(CMAKE_CXX_STANDARD 11) diff --git a/Tests/Cuda/WithC/CMakeLists.txt b/Tests/Cuda/WithC/CMakeLists.txt index 7596804..1f25ab4 100644 --- a/Tests/Cuda/WithC/CMakeLists.txt +++ b/Tests/Cuda/WithC/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.7) project(CudaComplex CUDA C) -set(CMAKE_CUDA_FLAGS "-gencode arch=compute_30,code=compute_30") +string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=compute_30") add_executable(CudaWithC main.c cuda.cu) diff --git a/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt b/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt index 7055eef..d134b96 100644 --- a/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt +++ b/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt @@ -9,7 +9,7 @@ project (CudaOnlySeparateCompilation CUDA) #and executables. #We complicate the matter by also testing that multiple static libraries #all containing cuda separable compilation code links properly -set(CMAKE_CUDA_FLAGS "-gencode arch=compute_30,code=compute_30") +string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=compute_30") set(CMAKE_CXX_STANDARD 11) set(CMAKE_CUDA_STANDARD 11) add_library(CUDASerarateLibA STATIC file1.cu file2.cu file3.cu) diff --git a/Tests/CudaOnly/WithDefs/CMakeLists.txt b/Tests/CudaOnly/WithDefs/CMakeLists.txt index 6c4011c..2646d29 100644 --- a/Tests/CudaOnly/WithDefs/CMakeLists.txt +++ b/Tests/CudaOnly/WithDefs/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.7) project (CudaOnlyWithDefs CUDA) #verify that we can pass explicit cuda arch flags -set(CMAKE_CUDA_FLAGS "-gencode arch=compute_30,code=compute_30") +string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=compute_30") set(debug_compile_flags --generate-code arch=compute_20,code=sm_20) if(CMAKE_CUDA_SIMULATE_ID STREQUAL "MSVC") list(APPEND debug_compile_flags -Xcompiler=-WX) ----------------------------------------------------------------------- Summary of changes: Modules/Compiler/NVIDIA-CUDA.cmake | 11 +++++------ Modules/Platform/Windows-NVIDIA-CUDA.cmake | 12 +++++++----- Tests/Cuda/Complex/CMakeLists.txt | 2 +- Tests/Cuda/ProperLinkFlags/CMakeLists.txt | 2 +- Tests/Cuda/WithC/CMakeLists.txt | 2 +- Tests/CudaOnly/SeparateCompilation/CMakeLists.txt | 2 +- Tests/CudaOnly/WithDefs/CMakeLists.txt | 2 +- 7 files changed, 17 insertions(+), 16 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 15 09:26:23 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 15 Feb 2017 09:26:23 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-177-ga146979 Message-ID: <20170215142623.BA436FA4DF@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via a146979be3b0890d376f6c722f3b0744189367c9 (commit) via 20ae76b1da82d87792fb54335dbf95e871261f52 (commit) from 13314a3e27942a44e747a9ba52e0c819a1b602d2 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a146979be3b0890d376f6c722f3b0744189367c9 commit a146979be3b0890d376f6c722f3b0744189367c9 Merge: 13314a3 20ae76b Author: Brad King AuthorDate: Wed Feb 15 09:26:23 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 15 09:26:23 2017 -0500 Merge topic 'command-cleanup-fix' into next 20ae76b1 cmDisallowedCommand: Forward final pass too https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=20ae76b1da82d87792fb54335dbf95e871261f52 commit 20ae76b1da82d87792fb54335dbf95e871261f52 Author: Brad King AuthorDate: Wed Feb 15 09:18:26 2017 -0500 Commit: Brad King CommitDate: Wed Feb 15 09:22:22 2017 -0500 cmDisallowedCommand: Forward final pass too Refactoring in commit 7fb14775 (cmDisallowedCommand: extract policy checking from cmCommand, 2016-12-26) introduced a wrapper for disallowed commands that forwards to their original commands. This broke the `export_library_dependencies` command that uses a final pass. Forward the final pass too to fix it. diff --git a/Source/cmDisallowedCommand.h b/Source/cmDisallowedCommand.h index 9cf5e6f..00b0183 100644 --- a/Source/cmDisallowedCommand.h +++ b/Source/cmDisallowedCommand.h @@ -34,6 +34,13 @@ public: bool InitialPass(std::vector const& args, cmExecutionStatus& status) CM_OVERRIDE; + void FinalPass() CM_OVERRIDE { this->Command->FinalPass(); } + + bool HasFinalPass() const CM_OVERRIDE + { + return this->Command->HasFinalPass(); + } + bool IsScriptable() const CM_OVERRIDE { return this->Command->IsScriptable(); ----------------------------------------------------------------------- Summary of changes: Source/cmDisallowedCommand.h | 7 +++++++ 1 file changed, 7 insertions(+) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 15 11:12:00 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 15 Feb 2017 11:12:00 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-179-gd4c222c Message-ID: <20170215161200.D03D5F20A3@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via d4c222c5af0612ae0ec200bc540a733d0941fa19 (commit) via 84c3eddac6e9de29995141f2cd12bb5cba16cbb5 (commit) from a146979be3b0890d376f6c722f3b0744189367c9 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d4c222c5af0612ae0ec200bc540a733d0941fa19 commit d4c222c5af0612ae0ec200bc540a733d0941fa19 Merge: a146979 84c3edd Author: Brad King AuthorDate: Wed Feb 15 11:12:00 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 15 11:12:00 2017 -0500 Merge topic 'cuda-msvc-flags' into next 84c3edda fixup! CUDA: Fix default compiler flags on Windows https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=84c3eddac6e9de29995141f2cd12bb5cba16cbb5 commit 84c3eddac6e9de29995141f2cd12bb5cba16cbb5 Author: Brad King AuthorDate: Wed Feb 15 11:10:22 2017 -0500 Commit: Brad King CommitDate: Wed Feb 15 11:10:22 2017 -0500 fixup! CUDA: Fix default compiler flags on Windows diff --git a/Modules/Platform/Windows-NVIDIA-CUDA.cmake b/Modules/Platform/Windows-NVIDIA-CUDA.cmake index 23473ed..845fa4b 100644 --- a/Modules/Platform/Windows-NVIDIA-CUDA.cmake +++ b/Modules/Platform/Windows-NVIDIA-CUDA.cmake @@ -38,7 +38,7 @@ set(CMAKE_CUDA_DEVICE_LINK_EXECUTABLE string(REPLACE "/D" "-D" _PLATFORM_DEFINES_CUDA "${_PLATFORM_DEFINES}${_PLATFORM_DEFINES_CXX}") string(APPEND CMAKE_CUDA_FLAGS_INIT " ${PLATFORM_DEFINES_CUDA} -D_WINDOWS -Xcompiler=\"/W3${_FLAGS_CXX}\"") -string(APPEND CMAKE_CUDA_FLAGS_DEBUG_INIT " -Xcompiler=\"-MDd -Zi ${_RTC1}\"") +string(APPEND CMAKE_CUDA_FLAGS_DEBUG_INIT " -Xcompiler=\"-MDd -Zi -Ob0 -Od ${_RTC1}\"") string(APPEND CMAKE_CUDA_FLAGS_RELEASE_INIT " -Xcompiler=\"-MD -O2 -Ob2\" -DNDEBUG") string(APPEND CMAKE_CUDA_FLAGS_RELWITHDEBINFO_INIT " -Xcompiler=\"-MD -Zi -O2 -Ob1\" -DNDEBUG") string(APPEND CMAKE_CUDA_FLAGS_MINSIZEREL_INIT " -Xcompiler=\"-MD -O1 -Ob1\" -DNDEBUG") ----------------------------------------------------------------------- Summary of changes: Modules/Platform/Windows-NVIDIA-CUDA.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 15 11:12:26 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 15 Feb 2017 11:12:26 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-182-gb0ea076 Message-ID: <20170215161226.D72D0F1E31@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via b0ea076370600cd3e6a5d04a90667c0d2a8e4727 (commit) via 55fb46d273e8ab51d5df366286052c71b9008437 (commit) via d7c80f60362cbc40216fab67318d94988030315c (commit) from d4c222c5af0612ae0ec200bc540a733d0941fa19 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b0ea076370600cd3e6a5d04a90667c0d2a8e4727 commit b0ea076370600cd3e6a5d04a90667c0d2a8e4727 Merge: d4c222c 55fb46d Author: Brad King AuthorDate: Wed Feb 15 11:12:26 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 15 11:12:26 2017 -0500 Merge topic 'cuda-msvc-flags' into next 55fb46d2 CUDA: Fix default compiler flags on Windows d7c80f60 CUDA: Fix test cases to not override CUDA flags https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=55fb46d273e8ab51d5df366286052c71b9008437 commit 55fb46d273e8ab51d5df366286052c71b9008437 Author: Brad King AuthorDate: Tue Feb 14 15:11:25 2017 -0500 Commit: Brad King CommitDate: Wed Feb 15 11:12:12 2017 -0500 CUDA: Fix default compiler flags on Windows Fix the default values of `CMAKE_CUDA_FLAGS[_]` on Windows to make the host compiler flags match those produced for C++ by the `Platform/Windows-MSVC` module. This makes the flags consistent with those used for C++. diff --git a/Modules/Compiler/NVIDIA-CUDA.cmake b/Modules/Compiler/NVIDIA-CUDA.cmake index 7903313..316cab8 100644 --- a/Modules/Compiler/NVIDIA-CUDA.cmake +++ b/Modules/Compiler/NVIDIA-CUDA.cmake @@ -7,16 +7,15 @@ if(NOT "x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC") # CMAKE_SHARED_LIBRARY_CUDA_FLAGS is sent to the host linker so we # don't need to forward it through nvcc. set(CMAKE_SHARED_LIBRARY_CUDA_FLAGS -fPIC) + string(APPEND CMAKE_CUDA_FLAGS_INIT " ") + string(APPEND CMAKE_CUDA_FLAGS_DEBUG_INIT " -g") + string(APPEND CMAKE_CUDA_FLAGS_RELEASE_INIT " -O3 -DNDEBUG") + string(APPEND CMAKE_CUDA_FLAGS_MINSIZEREL_INIT " -O1 -DNDEBUG") + string(APPEND CMAKE_CUDA_FLAGS_RELWITHDEBINFO_INIT " -O2 -g -DNDEBUG") endif() set(CMAKE_SHARED_LIBRARY_CREATE_CUDA_FLAGS -shared) set(CMAKE_INCLUDE_SYSTEM_FLAG_CUDA -isystem=) -string(APPEND CMAKE_CUDA_FLAGS_INIT " ") -string(APPEND CMAKE_CUDA_FLAGS_DEBUG_INIT " -g") -string(APPEND CMAKE_CUDA_FLAGS_MINSIZEREL_INIT " -O1 -DNDEBUG") -string(APPEND CMAKE_CUDA_FLAGS_RELEASE_INIT " -O3 -DNDEBUG") -string(APPEND CMAKE_CUDA_FLAGS_RELWITHDEBINFO_INIT " -O2 -g -DNDEBUG") - if("x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC") set(CMAKE_CUDA_STANDARD_DEFAULT "") else() diff --git a/Modules/Platform/Windows-NVIDIA-CUDA.cmake b/Modules/Platform/Windows-NVIDIA-CUDA.cmake index eda41e0..845fa4b 100644 --- a/Modules/Platform/Windows-NVIDIA-CUDA.cmake +++ b/Modules/Platform/Windows-NVIDIA-CUDA.cmake @@ -35,10 +35,12 @@ set(CMAKE_CUDA_DEVICE_LINK_LIBRARY set(CMAKE_CUDA_DEVICE_LINK_EXECUTABLE " -shared -dlink -o -Xcompiler=-Fd,-FS") -string(APPEND CMAKE_CUDA_FLAGS_INIT " -Xcompiler=-GR,-EHsc") -string(APPEND CMAKE_CUDA_FLAGS_DEBUG_INIT " -Xcompiler=-MDd,-Zi,-RTC1") -string(APPEND CMAKE_CUDA_FLAGS_RELEASE_INIT " -Xcompiler=-MD") -string(APPEND CMAKE_CUDA_FLAGS_RELWITHDEBINFO_INIT " -Xcompiler=-MD") -string(APPEND CMAKE_CUDA_FLAGS_MINSIZEREL_INIT " -Xcompiler=-MD") +string(REPLACE "/D" "-D" _PLATFORM_DEFINES_CUDA "${_PLATFORM_DEFINES}${_PLATFORM_DEFINES_CXX}") + +string(APPEND CMAKE_CUDA_FLAGS_INIT " ${PLATFORM_DEFINES_CUDA} -D_WINDOWS -Xcompiler=\"/W3${_FLAGS_CXX}\"") +string(APPEND CMAKE_CUDA_FLAGS_DEBUG_INIT " -Xcompiler=\"-MDd -Zi -Ob0 -Od ${_RTC1}\"") +string(APPEND CMAKE_CUDA_FLAGS_RELEASE_INIT " -Xcompiler=\"-MD -O2 -Ob2\" -DNDEBUG") +string(APPEND CMAKE_CUDA_FLAGS_RELWITHDEBINFO_INIT " -Xcompiler=\"-MD -Zi -O2 -Ob1\" -DNDEBUG") +string(APPEND CMAKE_CUDA_FLAGS_MINSIZEREL_INIT " -Xcompiler=\"-MD -O1 -Ob1\" -DNDEBUG") set(CMAKE_CUDA_STANDARD_LIBRARIES_INIT "${CMAKE_C_STANDARD_LIBRARIES_INIT}") https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d7c80f60362cbc40216fab67318d94988030315c commit d7c80f60362cbc40216fab67318d94988030315c Author: Brad King AuthorDate: Tue Feb 14 15:09:55 2017 -0500 Commit: Brad King CommitDate: Wed Feb 15 11:12:09 2017 -0500 CUDA: Fix test cases to not override CUDA flags Append to `CMAKE_CUDA_FLAGS` instead of overwriting it. diff --git a/Tests/Cuda/Complex/CMakeLists.txt b/Tests/Cuda/Complex/CMakeLists.txt index 9a3703a..bff7d07 100644 --- a/Tests/Cuda/Complex/CMakeLists.txt +++ b/Tests/Cuda/Complex/CMakeLists.txt @@ -15,7 +15,7 @@ project (CudaComplex CXX CUDA) #and also bulding cpp targets that need cuda implicit libraries #verify that we can pass explicit cuda arch flags -set(CMAKE_CUDA_FLAGS "-gencode arch=compute_30,code=compute_30") +string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=compute_30") set(CMAKE_CUDA_STANDARD 11) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CUDA_STANDARD_REQUIRED TRUE) diff --git a/Tests/Cuda/ProperLinkFlags/CMakeLists.txt b/Tests/Cuda/ProperLinkFlags/CMakeLists.txt index a9eb8bd..b6e0e39 100644 --- a/Tests/Cuda/ProperLinkFlags/CMakeLists.txt +++ b/Tests/Cuda/ProperLinkFlags/CMakeLists.txt @@ -9,7 +9,7 @@ project (ProperLinkFlags CUDA CXX) #Specify a set of valid CUDA flags and an invalid set of CXX flags ( for CUDA ) #to make sure we don't use the CXX flags when linking CUDA executables -set(CMAKE_CUDA_FLAGS "-arch=sm_35 --use_fast_math") +string(APPEND CMAKE_CUDA_FLAGS " -arch=sm_35 --use_fast_math") set(CMAKE_CXX_FLAGS "-Wall") set(CMAKE_CXX_STANDARD 11) diff --git a/Tests/Cuda/WithC/CMakeLists.txt b/Tests/Cuda/WithC/CMakeLists.txt index 7596804..1f25ab4 100644 --- a/Tests/Cuda/WithC/CMakeLists.txt +++ b/Tests/Cuda/WithC/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.7) project(CudaComplex CUDA C) -set(CMAKE_CUDA_FLAGS "-gencode arch=compute_30,code=compute_30") +string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=compute_30") add_executable(CudaWithC main.c cuda.cu) diff --git a/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt b/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt index 7055eef..d134b96 100644 --- a/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt +++ b/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt @@ -9,7 +9,7 @@ project (CudaOnlySeparateCompilation CUDA) #and executables. #We complicate the matter by also testing that multiple static libraries #all containing cuda separable compilation code links properly -set(CMAKE_CUDA_FLAGS "-gencode arch=compute_30,code=compute_30") +string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=compute_30") set(CMAKE_CXX_STANDARD 11) set(CMAKE_CUDA_STANDARD 11) add_library(CUDASerarateLibA STATIC file1.cu file2.cu file3.cu) diff --git a/Tests/CudaOnly/WithDefs/CMakeLists.txt b/Tests/CudaOnly/WithDefs/CMakeLists.txt index 6c4011c..2646d29 100644 --- a/Tests/CudaOnly/WithDefs/CMakeLists.txt +++ b/Tests/CudaOnly/WithDefs/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.7) project (CudaOnlyWithDefs CUDA) #verify that we can pass explicit cuda arch flags -set(CMAKE_CUDA_FLAGS "-gencode arch=compute_30,code=compute_30") +string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=compute_30") set(debug_compile_flags --generate-code arch=compute_20,code=sm_20) if(CMAKE_CUDA_SIMULATE_ID STREQUAL "MSVC") list(APPEND debug_compile_flags -Xcompiler=-WX) ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 15 15:00:57 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 15 Feb 2017 15:00:57 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-184-gdd0648f Message-ID: <20170215200057.8E86FFA334@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via dd0648f5baa4a6ddf640191fb9c82fc300c3732b (commit) via 51849bbab8b1b6b8299dc08e98ca1524cc1e168a (commit) from b0ea076370600cd3e6a5d04a90667c0d2a8e4727 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=dd0648f5baa4a6ddf640191fb9c82fc300c3732b commit dd0648f5baa4a6ddf640191fb9c82fc300c3732b Merge: b0ea076 51849bb Author: Brad King AuthorDate: Wed Feb 15 15:00:55 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 15 15:00:55 2017 -0500 Merge topic 'fix-ctest_update-svn' into next 51849bba ctest_update: Fix svn log and external loading https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=51849bbab8b1b6b8299dc08e98ca1524cc1e168a commit 51849bbab8b1b6b8299dc08e98ca1524cc1e168a Author: Brad King AuthorDate: Wed Feb 15 13:43:34 2017 -0500 Commit: Brad King CommitDate: Wed Feb 15 14:44:37 2017 -0500 ctest_update: Fix svn log and external loading Since commit v3.7.0-rc1~132^2 (CTestSVN: Fix segfault when CTEST_UPDATE_VERSION_ONLY is enabled, 2016-09-12) we do not properly extract svn log or externals. After updating we erase the information that was loaded before updating and can no longer log the changes between revisions to extract authors. Fix this by only loading the repository information once, whether needed by `NoteOldRevision`, `NoteNewRevision`, or both. Fixes: #12630, #16646 diff --git a/Source/CTest/cmCTestSVN.cxx b/Source/CTest/cmCTestSVN.cxx index fc405ca..410e0d4 100644 --- a/Source/CTest/cmCTestSVN.cxx +++ b/Source/CTest/cmCTestSVN.cxx @@ -523,8 +523,11 @@ private: void cmCTestSVN::LoadRepositories() { + if (!this->Repositories.empty()) { + return; + } + // Info for root repository - this->Repositories.clear(); this->Repositories.push_back(SVNInfo("")); this->RootInfo = &(this->Repositories.back()); ----------------------------------------------------------------------- Summary of changes: Source/CTest/cmCTestSVN.cxx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 15 15:03:43 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 15 Feb 2017 15:03:43 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-188-g2556769 Message-ID: <20170215200343.4B949FA50D@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 2556769b73a707529a73df5a474620281e3fb7d8 (commit) via 109b8a6fd32be9886de71f98170e0c512ac9883f (commit) via bd5ea6993c8376cd3612100019e15ee256a758d8 (commit) via 3936a2886efc1fd46560352f3a48d6a656f95367 (commit) from dd0648f5baa4a6ddf640191fb9c82fc300c3732b (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=2556769b73a707529a73df5a474620281e3fb7d8 commit 2556769b73a707529a73df5a474620281e3fb7d8 Merge: dd0648f 109b8a6 Author: Brad King AuthorDate: Wed Feb 15 15:03:42 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 15 15:03:42 2017 -0500 Merge topic 'vs-refactor-unknown-flags' into next 109b8a6f VS: Refactor AdditionalOptions generation bd5ea699 cmVisualStudioGeneratorOptions: Add PrependInerhitedString method 3936a288 cmIDEOptions: Add SpaceAppendable flag table type https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=109b8a6fd32be9886de71f98170e0c512ac9883f commit 109b8a6fd32be9886de71f98170e0c512ac9883f Author: Brad King AuthorDate: Wed Feb 15 10:40:00 2017 -0500 Commit: Brad King CommitDate: Wed Feb 15 10:41:36 2017 -0500 VS: Refactor AdditionalOptions generation Store unknown flags directly in a flag map entry for `AdditionalOptions` instead of having a separate member for them. This avoids duplicating the output generation logic for the entry. diff --git a/Source/cmIDEOptions.h b/Source/cmIDEOptions.h index aaa9d3d..465cf2c 100644 --- a/Source/cmIDEOptions.h +++ b/Source/cmIDEOptions.h @@ -74,9 +74,6 @@ protected: // Preprocessor definitions. std::vector Defines; - // Unrecognized flags that get no special handling. - std::string FlagString; - bool DoingDefine; bool AllowDefine; bool AllowSlash; diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 38dda04..6e976e1 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -787,7 +787,6 @@ void cmLocalVisualStudio7Generator::WriteConfiguration( << this->ConvertToXMLOutputPath(modDir.c_str()) << "\\$(ConfigurationName)\"\n"; } - targetOptions.OutputAdditionalOptions(fout, "\t\t\t\t", "\n"); fout << "\t\t\t\tAdditionalIncludeDirectories=\""; std::vector includes; this->GetIncludeDirectories(includes, target, "C", configName); @@ -1090,7 +1089,6 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( if (!gg->NeedLinkLibraryDependencies(target)) { fout << "\t\t\t\tLinkLibraryDependencies=\"false\"\n"; } - linkOptions.OutputAdditionalOptions(fout, "\t\t\t\t", "\n"); // Use the NOINHERIT macro to avoid getting VS project default // libraries which may be set by the user to something bad. fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) " @@ -1176,7 +1174,6 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( if (!gg->NeedLinkLibraryDependencies(target)) { fout << "\t\t\t\tLinkLibraryDependencies=\"false\"\n"; } - linkOptions.OutputAdditionalOptions(fout, "\t\t\t\t", "\n"); // Use the NOINHERIT macro to avoid getting VS project default // libraries which may be set by the user to something bad. fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) " @@ -1675,7 +1672,6 @@ bool cmLocalVisualStudio7Generator::WriteGroup( fileOptions.Parse(fc.CompileFlags.c_str()); fileOptions.AddDefines(fc.CompileDefs.c_str()); fileOptions.AddDefines(fc.CompileDefsConfig.c_str()); - fileOptions.OutputAdditionalOptions(fout, "\t\t\t\t\t", "\n"); fileOptions.OutputFlagMap(fout, "\t\t\t\t\t"); fileOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t\t", "\n", ppLang); diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index f084e19..e3853ed 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -1939,7 +1939,7 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( } clOptions.AddDefines(configDefines.c_str()); clOptions.SetConfiguration((*config).c_str()); - clOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", ""); + clOptions.PrependInheritedString("AdditionalOptions"); clOptions.OutputFlagMap(*this->BuildFileStream, " "); clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ", "\n", lang); @@ -2293,7 +2293,7 @@ void cmVisualStudio10TargetGenerator::WriteClOptions( return; } this->WriteString("\n", 2); - clOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", ""); + clOptions.PrependInheritedString("AdditionalOptions"); clOptions.AppendFlag("AdditionalIncludeDirectories", includes); clOptions.AppendFlag("AdditionalIncludeDirectories", "%(AdditionalIncludeDirectories)"); @@ -2395,8 +2395,8 @@ void cmVisualStudio10TargetGenerator::WriteRCOptions( rcOptions.AppendFlag("AdditionalIncludeDirectories", includes); rcOptions.AppendFlag("AdditionalIncludeDirectories", "%(AdditionalIncludeDirectories)"); + rcOptions.PrependInheritedString("AdditionalOptions"); rcOptions.OutputFlagMap(*this->BuildFileStream, " "); - rcOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", ""); this->WriteString("\n", 2); } @@ -2453,8 +2453,8 @@ void cmVisualStudio10TargetGenerator::WriteMasmOptions( Options& masmOptions = *(this->MasmOptions[configName]); masmOptions.AppendFlag("IncludePaths", includes); masmOptions.AppendFlag("IncludePaths", "%(IncludePaths)"); + masmOptions.PrependInheritedString("AdditionalOptions"); masmOptions.OutputFlagMap(*this->BuildFileStream, " "); - masmOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", ""); this->WriteString("\n", 2); } @@ -2512,7 +2512,7 @@ void cmVisualStudio10TargetGenerator::WriteNasmOptions( nasmOptions.AppendFlag("IncludePaths", includes); nasmOptions.AppendFlag("IncludePaths", "%(IncludePaths)"); nasmOptions.OutputFlagMap(*this->BuildFileStream, " "); - nasmOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", ""); + nasmOptions.PrependInheritedString("AdditionalOptions"); nasmOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ", "\n", "ASM_NASM"); @@ -2542,7 +2542,7 @@ void cmVisualStudio10TargetGenerator::WriteLibOptions( this->LocalGenerator, cmVisualStudioGeneratorOptions::Linker, gg->GetLibFlagTable(), 0, this); libOptions.Parse(libflags.c_str()); - libOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", ""); + libOptions.PrependInheritedString("AdditionalOptions"); libOptions.OutputFlagMap(*this->BuildFileStream, " "); this->WriteString("\n", 2); } @@ -3019,7 +3019,7 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions( Options& linkOptions = *(this->LinkOptions[config]); this->WriteString("\n", 2); - linkOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", ""); + linkOptions.PrependInheritedString("AdditionalOptions"); linkOptions.OutputFlagMap(*this->BuildFileStream, " "); this->WriteString("\n", 2); diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx index f8de3f8..dfe5ce6 100644 --- a/Source/cmVisualStudioGeneratorOptions.cxx +++ b/Source/cmVisualStudioGeneratorOptions.cxx @@ -245,10 +245,10 @@ void cmVisualStudioGeneratorOptions::StoreUnknownFlag(const char* flag) } // This option is not known. Store it in the output flags. - this->FlagString += " "; - this->FlagString += cmOutputConverter::EscapeWindowsShellArgument( + std::string const opts = cmOutputConverter::EscapeWindowsShellArgument( flag, cmOutputConverter::Shell_Flag_AllowMakeVariables | cmOutputConverter::Shell_Flag_VSIDE); + this->AppendFlagString("AdditionalOptions", opts); } void cmVisualStudioGeneratorOptions::SetConfiguration(const char* config) @@ -343,26 +343,3 @@ void cmVisualStudioGeneratorOptions::OutputFlagMap(std::ostream& fout, } } } - -void cmVisualStudioGeneratorOptions::OutputAdditionalOptions( - std::ostream& fout, const char* prefix, const char* suffix) -{ - if (!this->FlagString.empty()) { - if (this->Version >= cmGlobalVisualStudioGenerator::VS10) { - fout << prefix; - if (!this->Configuration.empty()) { - this->TargetGenerator->WritePlatformConfigTag( - "AdditionalOptions", this->Configuration.c_str(), 0, 0, 0, &fout); - } else { - fout << ""; - } - fout << "%(AdditionalOptions) " - << cmVisualStudio10GeneratorOptionsEscapeForXML(this->FlagString) - << "\n"; - } else { - fout << prefix << "AdditionalOptions=\""; - fout << cmVisualStudioGeneratorOptionsEscapeForXML(this->FlagString); - fout << "\"" << suffix; - } - } -} diff --git a/Source/cmVisualStudioGeneratorOptions.h b/Source/cmVisualStudioGeneratorOptions.h index ee9d0a5..8c49470 100644 --- a/Source/cmVisualStudioGeneratorOptions.h +++ b/Source/cmVisualStudioGeneratorOptions.h @@ -67,8 +67,6 @@ public: const char* suffix, const std::string& lang); void OutputFlagMap(std::ostream& fout, const char* indent); - void OutputAdditionalOptions(std::ostream& fout, const char* prefix, - const char* suffix); void SetConfiguration(const char* config); private: https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=bd5ea6993c8376cd3612100019e15ee256a758d8 commit bd5ea6993c8376cd3612100019e15ee256a758d8 Author: Brad King AuthorDate: Wed Feb 15 10:36:56 2017 -0500 Commit: Brad King CommitDate: Wed Feb 15 10:37:35 2017 -0500 cmVisualStudioGeneratorOptions: Add PrependInerhitedString method diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx index 6bacfa1..f8de3f8 100644 --- a/Source/cmVisualStudioGeneratorOptions.cxx +++ b/Source/cmVisualStudioGeneratorOptions.cxx @@ -211,6 +211,17 @@ void cmVisualStudioGeneratorOptions::ParseFinish() } } +void cmVisualStudioGeneratorOptions::PrependInheritedString( + std::string const& key) +{ + std::map::iterator i = this->FlagMap.find(key); + if (i == this->FlagMap.end() || i->second.size() != 1) { + return; + } + std::string& value = i->second[0]; + value = "%(" + key + ") " + value; +} + void cmVisualStudioGeneratorOptions::StoreUnknownFlag(const char* flag) { // Look for Intel Fortran flags that do not map well in the flag table. diff --git a/Source/cmVisualStudioGeneratorOptions.h b/Source/cmVisualStudioGeneratorOptions.h index 3a53ff5..ee9d0a5 100644 --- a/Source/cmVisualStudioGeneratorOptions.h +++ b/Source/cmVisualStudioGeneratorOptions.h @@ -47,6 +47,8 @@ public: void Parse(const char* flags); void ParseFinish(); + void PrependInheritedString(std::string const& key); + // Fix the ExceptionHandling option to default to off. void FixExceptionHandlingDefault(); https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3936a2886efc1fd46560352f3a48d6a656f95367 commit 3936a2886efc1fd46560352f3a48d6a656f95367 Author: Brad King AuthorDate: Wed Feb 15 09:35:36 2017 -0500 Commit: Brad King CommitDate: Wed Feb 15 10:36:09 2017 -0500 cmIDEOptions: Add SpaceAppendable flag table type diff --git a/Source/cmIDEFlagTable.h b/Source/cmIDEFlagTable.h index 64ade76..152e293 100644 --- a/Source/cmIDEFlagTable.h +++ b/Source/cmIDEFlagTable.h @@ -24,6 +24,9 @@ struct cmIDEFlagTable // IgnoreDefaultLibraryNames) UserFollowing = (1 << 5), // expect value in following argument CaseInsensitive = (1 << 6), // flag may be any case + SpaceAppendable = (1 << 7), // a flag that if specified multiple times + // should have its value appended to the + // old value with spaces UserValueIgnored = UserValue | UserIgnored, UserValueRequired = UserValue | UserRequired diff --git a/Source/cmIDEOptions.cxx b/Source/cmIDEOptions.cxx index c6c0e05..1c0a99e 100644 --- a/Source/cmIDEOptions.cxx +++ b/Source/cmIDEOptions.cxx @@ -125,6 +125,8 @@ void cmIDEOptions::FlagMapUpdate(cmIDEFlagTable const* entry, this->FlagMap[entry->IDEName] = entry->value; } else if (entry->special & cmIDEFlagTable::SemicolonAppendable) { this->FlagMap[entry->IDEName].push_back(new_value); + } else if (entry->special & cmIDEFlagTable::SpaceAppendable) { + this->FlagMap[entry->IDEName].append_with_space(new_value); } else { // Use the user-specified value. this->FlagMap[entry->IDEName] = new_value; @@ -172,6 +174,12 @@ void cmIDEOptions::AppendFlag(std::string const& flag, std::copy(value.begin(), value.end(), std::back_inserter(fv)); } +void cmIDEOptions::AppendFlagString(std::string const& flag, + std::string const& value) +{ + this->FlagMap[flag].append_with_space(value); +} + void cmIDEOptions::RemoveFlag(const char* flag) { this->FlagMap.erase(flag); diff --git a/Source/cmIDEOptions.h b/Source/cmIDEOptions.h index a0696e1..aaa9d3d 100644 --- a/Source/cmIDEOptions.h +++ b/Source/cmIDEOptions.h @@ -29,6 +29,7 @@ public: void AppendFlag(std::string const& flag, std::string const& value); void AppendFlag(std::string const& flag, std::vector const& value); + void AppendFlagString(std::string const& flag, std::string const& value); void RemoveFlag(const char* flag); bool HasFlag(std::string const& flag) const; const char* GetFlag(const char* flag); @@ -57,6 +58,16 @@ protected: this->derived::operator=(r); return *this; } + FlagValue& append_with_space(std::string const& r) + { + this->resize(1); + std::string& l = this->operator[](0); + if (!l.empty()) { + l += " "; + } + l += r; + return *this; + } }; std::map FlagMap; ----------------------------------------------------------------------- Summary of changes: Source/cmIDEFlagTable.h | 3 +++ Source/cmIDEOptions.cxx | 8 ++++++ Source/cmIDEOptions.h | 14 +++++++--- Source/cmLocalVisualStudio7Generator.cxx | 4 --- Source/cmVisualStudio10TargetGenerator.cxx | 14 +++++----- Source/cmVisualStudioGeneratorOptions.cxx | 38 ++++++++++------------------ Source/cmVisualStudioGeneratorOptions.h | 4 +-- 7 files changed, 44 insertions(+), 41 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 15 15:12:22 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 15 Feb 2017 15:12:22 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-190-g37537d9 Message-ID: <20170215201223.9A393E2CDE@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 37537d95cbcb3e7265599523bd31fe13cef25654 (commit) via ac0962cead1db76b44cbb9d9a413956ca31a7982 (commit) from 2556769b73a707529a73df5a474620281e3fb7d8 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=37537d95cbcb3e7265599523bd31fe13cef25654 commit 37537d95cbcb3e7265599523bd31fe13cef25654 Merge: 2556769 ac0962c Author: Brad King AuthorDate: Wed Feb 15 15:12:22 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 15 15:12:22 2017 -0500 Merge topic 'TestBigEndian-cxx-only' into next ac0962ce TestBigEndian: Fix to work with CXX without C https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ac0962cead1db76b44cbb9d9a413956ca31a7982 commit ac0962cead1db76b44cbb9d9a413956ca31a7982 Author: Uwe Koloska AuthorDate: Wed Feb 15 18:21:35 2017 +0100 Commit: Brad King CommitDate: Wed Feb 15 15:08:37 2017 -0500 TestBigEndian: Fix to work with CXX without C diff --git a/Modules/TestBigEndian.cmake b/Modules/TestBigEndian.cmake index 085be22..cc627d0 100644 --- a/Modules/TestBigEndian.cmake +++ b/Modules/TestBigEndian.cmake @@ -19,21 +19,29 @@ macro(TEST_BIG_ENDIAN VARIABLE) message(STATUS "Check if the system is big endian") message(STATUS "Searching 16 bit integer") + if(CMAKE_C_COMPILER_LOADED) + set(_test_language "C") + elseif(CMAKE_CXX_COMPILER_LOADED) + set(_test_language "CXX") + else() + message(FATAL_ERROR "TEST_BIG_ENDIAN needs either C or CXX language enabled") + endif() + include(CheckTypeSize) - CHECK_TYPE_SIZE("unsigned short" CMAKE_SIZEOF_UNSIGNED_SHORT) + CHECK_TYPE_SIZE("unsigned short" CMAKE_SIZEOF_UNSIGNED_SHORT LANGUAGE ${_test_language}) if(CMAKE_SIZEOF_UNSIGNED_SHORT EQUAL 2) message(STATUS "Using unsigned short") set(CMAKE_16BIT_TYPE "unsigned short") else() - CHECK_TYPE_SIZE("unsigned int" CMAKE_SIZEOF_UNSIGNED_INT) + CHECK_TYPE_SIZE("unsigned int" CMAKE_SIZEOF_UNSIGNED_INT LANGUAGE ${_test_language}) if(CMAKE_SIZEOF_UNSIGNED_INT) message(STATUS "Using unsigned int") set(CMAKE_16BIT_TYPE "unsigned int") else() - CHECK_TYPE_SIZE("unsigned long" CMAKE_SIZEOF_UNSIGNED_LONG) + CHECK_TYPE_SIZE("unsigned long" CMAKE_SIZEOF_UNSIGNED_LONG LANGUAGE ${_test_language}) if(CMAKE_SIZEOF_UNSIGNED_LONG) message(STATUS "Using unsigned long") set(CMAKE_16BIT_TYPE "unsigned long") @@ -45,17 +53,21 @@ macro(TEST_BIG_ENDIAN VARIABLE) endif() + if(_test_language STREQUAL "CXX") + set(_test_file "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/TestEndianess.cpp") + else() + set(_test_file "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/TestEndianess.c") + endif() configure_file("${CMAKE_ROOT}/Modules/TestEndianess.c.in" - "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/TestEndianess.c" + ${_test_file} @ONLY) - file(READ "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/TestEndianess.c" - TEST_ENDIANESS_FILE_CONTENT) + file(READ ${_test_file} TEST_ENDIANESS_FILE_CONTENT) try_compile(HAVE_${VARIABLE} "${CMAKE_BINARY_DIR}" - "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/TestEndianess.c" + ${_test_file} OUTPUT_VARIABLE OUTPUT COPY_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestEndianess.bin" ) ----------------------------------------------------------------------- Summary of changes: Modules/TestBigEndian.cmake | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 15 15:19:26 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 15 Feb 2017 15:19:26 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-192-ge080ad3 Message-ID: <20170215201926.525CDF9F4E@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via e080ad36397d6b7d813b3b1c26a78414858c668a (commit) via 28ee3784055ab6b21563d56024b1324c16949cbc (commit) from 37537d95cbcb3e7265599523bd31fe13cef25654 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e080ad36397d6b7d813b3b1c26a78414858c668a commit e080ad36397d6b7d813b3b1c26a78414858c668a Merge: 37537d9 28ee378 Author: Brad King AuthorDate: Wed Feb 15 15:19:25 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 15 15:19:25 2017 -0500 Merge topic 'autogen_fix_3.8' into next 28ee3784 Autogen: Fix headers not skipped https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=28ee3784055ab6b21563d56024b1324c16949cbc commit 28ee3784055ab6b21563d56024b1324c16949cbc Author: Sebastian Holtermann AuthorDate: Wed Feb 15 21:00:39 2017 +0100 Commit: Sebastian Holtermann CommitDate: Wed Feb 15 21:00:39 2017 +0100 Autogen: Fix headers not skipped diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index c84fe4f..1d6972b 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -655,10 +655,10 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) it != this->Headers.end(); ++it) { const std::string& headerName = *it; if (!this->MocSkipTest(headerName)) { - headerFilesMoc.insert(this->Headers.begin(), this->Headers.end()); + headerFilesMoc.insert(headerName); } if (!this->UicSkipTest(headerName)) { - headerFilesUic.insert(this->Headers.begin(), this->Headers.end()); + headerFilesUic.insert(headerName); } } this->ParseHeaders(headerFilesMoc, headerFilesUic, includedMocs, ----------------------------------------------------------------------- Summary of changes: Source/cmQtAutoGenerators.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- CMake From kwrobot at kitware.com Thu Feb 16 00:01:12 2017 From: kwrobot at kitware.com (Kitware Robot) Date: Thu, 16 Feb 2017 00:01:12 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-103-gb922994 Message-ID: <20170216050112.DF726FA554@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via b9229944cf1b9f27e1fc97921e736ca17fc4eb0c (commit) from 72cfb3c3d2e8f6167cf08289691f7b0c61d0d331 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b9229944cf1b9f27e1fc97921e736ca17fc4eb0c commit b9229944cf1b9f27e1fc97921e736ca17fc4eb0c Author: Kitware Robot AuthorDate: Thu Feb 16 00:01:10 2017 -0500 Commit: Kitware Robot CommitDate: Thu Feb 16 00:01:10 2017 -0500 CMake Nightly Date Stamp diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 2efc5bf..a92cb20 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 8) -set(CMake_VERSION_PATCH 20170215) +set(CMake_VERSION_PATCH 20170216) #set(CMake_VERSION_RC 1) ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 16 13:15:37 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 16 Feb 2017 13:15:37 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-106-gd1530cc Message-ID: <20170216181537.D5973F9D02@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via d1530cc9a5bf16c83d7ad9246d6a7e35a0235b3e (commit) via 55fb46d273e8ab51d5df366286052c71b9008437 (commit) via d7c80f60362cbc40216fab67318d94988030315c (commit) from b9229944cf1b9f27e1fc97921e736ca17fc4eb0c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d1530cc9a5bf16c83d7ad9246d6a7e35a0235b3e commit d1530cc9a5bf16c83d7ad9246d6a7e35a0235b3e Merge: b922994 55fb46d Author: Brad King AuthorDate: Thu Feb 16 13:15:35 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 16 13:15:35 2017 -0500 Merge topic 'cuda-msvc-flags' 55fb46d2 CUDA: Fix default compiler flags on Windows d7c80f60 CUDA: Fix test cases to not override CUDA flags ----------------------------------------------------------------------- Summary of changes: Modules/Compiler/NVIDIA-CUDA.cmake | 11 +++++------ Modules/Platform/Windows-NVIDIA-CUDA.cmake | 12 +++++++----- Tests/Cuda/Complex/CMakeLists.txt | 2 +- Tests/Cuda/ProperLinkFlags/CMakeLists.txt | 2 +- Tests/Cuda/WithC/CMakeLists.txt | 2 +- Tests/CudaOnly/SeparateCompilation/CMakeLists.txt | 2 +- Tests/CudaOnly/WithDefs/CMakeLists.txt | 2 +- 7 files changed, 17 insertions(+), 16 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 16 13:15:40 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 16 Feb 2017 13:15:40 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-108-g5d5be3b Message-ID: <20170216181541.0C0AAF9E26@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 5d5be3bd96f4521b38774855fb70e4238e346db2 (commit) via 28ee3784055ab6b21563d56024b1324c16949cbc (commit) from d1530cc9a5bf16c83d7ad9246d6a7e35a0235b3e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=5d5be3bd96f4521b38774855fb70e4238e346db2 commit 5d5be3bd96f4521b38774855fb70e4238e346db2 Merge: d1530cc 28ee378 Author: Brad King AuthorDate: Thu Feb 16 13:15:38 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 16 13:15:38 2017 -0500 Merge topic 'autogen_fix_3.8' 28ee3784 Autogen: Fix headers not skipped ----------------------------------------------------------------------- Summary of changes: Source/cmQtAutoGenerators.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 16 13:15:44 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 16 Feb 2017 13:15:44 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-110-gaa18d5b Message-ID: <20170216181544.05506F9E26@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via aa18d5befec57e69628106cc5d95829a687bfd5c (commit) via 51849bbab8b1b6b8299dc08e98ca1524cc1e168a (commit) from 5d5be3bd96f4521b38774855fb70e4238e346db2 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=aa18d5befec57e69628106cc5d95829a687bfd5c commit aa18d5befec57e69628106cc5d95829a687bfd5c Merge: 5d5be3b 51849bb Author: Brad King AuthorDate: Thu Feb 16 13:15:42 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 16 13:15:42 2017 -0500 Merge topic 'fix-ctest_update-svn' 51849bba ctest_update: Fix svn log and external loading ----------------------------------------------------------------------- Summary of changes: Source/CTest/cmCTestSVN.cxx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 16 13:15:46 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 16 Feb 2017 13:15:46 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-112-g60b5616 Message-ID: <20170216181546.98C50F9EE6@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 60b5616af7966076ffce43610559d8a0bf7a9550 (commit) via 20ae76b1da82d87792fb54335dbf95e871261f52 (commit) from aa18d5befec57e69628106cc5d95829a687bfd5c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=60b5616af7966076ffce43610559d8a0bf7a9550 commit 60b5616af7966076ffce43610559d8a0bf7a9550 Merge: aa18d5b 20ae76b Author: Brad King AuthorDate: Thu Feb 16 13:15:44 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 16 13:15:44 2017 -0500 Merge topic 'command-cleanup-fix' 20ae76b1 cmDisallowedCommand: Forward final pass too ----------------------------------------------------------------------- Summary of changes: Source/cmDisallowedCommand.h | 7 +++++++ 1 file changed, 7 insertions(+) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 16 13:15:48 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 16 Feb 2017 13:15:48 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-114-gfb3fd78 Message-ID: <20170216181548.E0BA3F9E7C@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via fb3fd78d580d0ad0aa138fd8edd7f81f44a3f275 (commit) via ac0962cead1db76b44cbb9d9a413956ca31a7982 (commit) from 60b5616af7966076ffce43610559d8a0bf7a9550 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=fb3fd78d580d0ad0aa138fd8edd7f81f44a3f275 commit fb3fd78d580d0ad0aa138fd8edd7f81f44a3f275 Merge: 60b5616 ac0962c Author: Brad King AuthorDate: Thu Feb 16 13:15:47 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 16 13:15:47 2017 -0500 Merge topic 'TestBigEndian-cxx-only' ac0962ce TestBigEndian: Fix to work with CXX without C ----------------------------------------------------------------------- Summary of changes: Modules/TestBigEndian.cmake | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 16 13:15:51 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 16 Feb 2017 13:15:51 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-117-g160083b Message-ID: <20170216181551.88F00F9E26@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 160083b04ddde9904e90cbf8146193e28eb58124 (commit) via f773933f2630a17ce6b3b2aa6f8d7d8b65eb336c (commit) via d9e2b9a909b5f5b51ef3a106ed1d60a8d4cb795a (commit) from fb3fd78d580d0ad0aa138fd8edd7f81f44a3f275 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=160083b04ddde9904e90cbf8146193e28eb58124 commit 160083b04ddde9904e90cbf8146193e28eb58124 Merge: fb3fd78 f773933 Author: Brad King AuthorDate: Thu Feb 16 13:15:49 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 16 13:15:49 2017 -0500 Merge topic 'vs-refactor-toolset-parsing' f773933f VS: Refactor generator toolset parsing d9e2b9a9 Tests: Split out RunCMake.GeneratorToolset Xcode checks ----------------------------------------------------------------------- Summary of changes: Source/cmGlobalVisualStudio10Generator.cxx | 82 ++++++++++++++++---- Source/cmGlobalVisualStudio10Generator.h | 6 +- Source/cmGlobalVisualStudio12Generator.cxx | 16 ++-- Source/cmGlobalVisualStudio12Generator.h | 4 +- .../BadToolsetFormat-result.txt} | 0 .../GeneratorToolset/BadToolsetFormat-stderr.txt | 10 +++ .../BadToolsetFormat.cmake} | 0 .../GeneratorToolset/BadToolsetHostArch-stderr.txt | 4 +- .../BadToolsetHostArchTwice-result.txt} | 0 .../BadToolsetHostArchTwice-stderr.txt | 10 +++ .../BadToolsetHostArchTwice.cmake} | 0 .../BadToolsetHostArchXcode-result.txt} | 0 ...derr.txt => BadToolsetHostArchXcode-stderr.txt} | 0 .../BadToolsetHostArchXcode.cmake} | 0 Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake | 11 ++- 15 files changed, 114 insertions(+), 29 deletions(-) copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => GeneratorToolset/BadToolsetFormat-result.txt} (100%) create mode 100644 Tests/RunCMake/GeneratorToolset/BadToolsetFormat-stderr.txt copy Tests/RunCMake/{GeneratorPlatform/BadPlatform.cmake => GeneratorToolset/BadToolsetFormat.cmake} (100%) copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => GeneratorToolset/BadToolsetHostArchTwice-result.txt} (100%) create mode 100644 Tests/RunCMake/GeneratorToolset/BadToolsetHostArchTwice-stderr.txt copy Tests/RunCMake/{GeneratorPlatform/BadPlatform.cmake => GeneratorToolset/BadToolsetHostArchTwice.cmake} (100%) copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => GeneratorToolset/BadToolsetHostArchXcode-result.txt} (100%) copy Tests/RunCMake/GeneratorToolset/{BadToolsetHostArch-stderr.txt => BadToolsetHostArchXcode-stderr.txt} (100%) copy Tests/RunCMake/{GeneratorPlatform/BadPlatform.cmake => GeneratorToolset/BadToolsetHostArchXcode.cmake} (100%) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 16 13:15:53 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 16 Feb 2017 13:15:53 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-121-gbb4730d Message-ID: <20170216181553.D3B80F9E7C@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via bb4730dc5add8c5ac54b41efa5375189636429f3 (commit) via 109b8a6fd32be9886de71f98170e0c512ac9883f (commit) via bd5ea6993c8376cd3612100019e15ee256a758d8 (commit) via 3936a2886efc1fd46560352f3a48d6a656f95367 (commit) from 160083b04ddde9904e90cbf8146193e28eb58124 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=bb4730dc5add8c5ac54b41efa5375189636429f3 commit bb4730dc5add8c5ac54b41efa5375189636429f3 Merge: 160083b 109b8a6 Author: Brad King AuthorDate: Thu Feb 16 13:15:52 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 16 13:15:52 2017 -0500 Merge topic 'vs-refactor-unknown-flags' 109b8a6f VS: Refactor AdditionalOptions generation bd5ea699 cmVisualStudioGeneratorOptions: Add PrependInerhitedString method 3936a288 cmIDEOptions: Add SpaceAppendable flag table type ----------------------------------------------------------------------- Summary of changes: Source/cmIDEFlagTable.h | 3 +++ Source/cmIDEOptions.cxx | 8 ++++++ Source/cmIDEOptions.h | 14 +++++++--- Source/cmLocalVisualStudio7Generator.cxx | 4 --- Source/cmVisualStudio10TargetGenerator.cxx | 14 +++++----- Source/cmVisualStudioGeneratorOptions.cxx | 38 ++++++++++------------------ Source/cmVisualStudioGeneratorOptions.h | 4 +-- 7 files changed, 44 insertions(+), 41 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 16 13:16:18 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 16 Feb 2017 13:16:18 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-201-g0239a87 Message-ID: <20170216181618.CFA29F9D7A@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 0239a87173935c2d10e518c5070e4d90c9b6c79a (commit) via bb4730dc5add8c5ac54b41efa5375189636429f3 (commit) via 160083b04ddde9904e90cbf8146193e28eb58124 (commit) via fb3fd78d580d0ad0aa138fd8edd7f81f44a3f275 (commit) via 60b5616af7966076ffce43610559d8a0bf7a9550 (commit) via aa18d5befec57e69628106cc5d95829a687bfd5c (commit) via 5d5be3bd96f4521b38774855fb70e4238e346db2 (commit) via d1530cc9a5bf16c83d7ad9246d6a7e35a0235b3e (commit) via b9229944cf1b9f27e1fc97921e736ca17fc4eb0c (commit) from e080ad36397d6b7d813b3b1c26a78414858c668a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0239a87173935c2d10e518c5070e4d90c9b6c79a commit 0239a87173935c2d10e518c5070e4d90c9b6c79a Merge: e080ad3 bb4730d Author: Brad King AuthorDate: Thu Feb 16 13:16:01 2017 -0500 Commit: Brad King CommitDate: Thu Feb 16 13:16:01 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 16 13:20:28 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 16 Feb 2017 13:20:28 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-204-g5dc1ca6 Message-ID: <20170216182028.74E38FA19A@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 5dc1ca679d48a4ef7ef0cd5c987e077bb75915c2 (commit) via f10b2f72f6979ccb16410d97bac98c440eb7f992 (commit) via ef399f9bc6b8e2ff917a5f2809346fb81fd954ae (commit) from 0239a87173935c2d10e518c5070e4d90c9b6c79a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=5dc1ca679d48a4ef7ef0cd5c987e077bb75915c2 commit 5dc1ca679d48a4ef7ef0cd5c987e077bb75915c2 Merge: 0239a87 f10b2f7 Author: Brad King AuthorDate: Thu Feb 16 13:20:27 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 16 13:20:27 2017 -0500 Merge topic 'capture-ctest_update-svn-failures' into next f10b2f72 ctest_update: Capture failure of svn to load revisions and local mods ef399f9b ctest_update: Refactor internal APIs to support more failure cases https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f10b2f72f6979ccb16410d97bac98c440eb7f992 commit f10b2f72f6979ccb16410d97bac98c440eb7f992 Author: Brad King AuthorDate: Wed Feb 15 14:12:03 2017 -0500 Commit: Brad King CommitDate: Thu Feb 16 13:19:26 2017 -0500 ctest_update: Capture failure of svn to load revisions and local mods Issue: #16646 diff --git a/Source/CTest/cmCTestSVN.cxx b/Source/CTest/cmCTestSVN.cxx index e85d01c..ce395cd 100644 --- a/Source/CTest/cmCTestSVN.cxx +++ b/Source/CTest/cmCTestSVN.cxx @@ -99,7 +99,9 @@ std::string cmCTestSVN::LoadInfo(SVNInfo& svninfo) bool cmCTestSVN::NoteOldRevision() { - this->LoadRepositories(); + if (!this->LoadRepositories()) { + return false; + } std::list::iterator itbeg = this->Repositories.begin(); std::list::iterator itend = this->Repositories.end(); @@ -121,7 +123,9 @@ bool cmCTestSVN::NoteOldRevision() bool cmCTestSVN::NoteNewRevision() { - this->LoadRepositories(); + if (!this->LoadRepositories()) { + return false; + } std::list::iterator itbeg = this->Repositories.begin(); std::list::iterator itend = this->Repositories.end(); @@ -374,17 +378,18 @@ private: bool cmCTestSVN::LoadRevisions() { + bool result = true; // Get revisions for all the external repositories std::list::iterator itbeg = this->Repositories.begin(); std::list::iterator itend = this->Repositories.end(); for (; itbeg != itend; itbeg++) { SVNInfo& svninfo = *itbeg; - LoadRevisions(svninfo); + result = this->LoadRevisions(svninfo) && result; } - return true; + return result; } -void cmCTestSVN::LoadRevisions(SVNInfo& svninfo) +bool cmCTestSVN::LoadRevisions(SVNInfo& svninfo) { // We are interested in every revision included in the update. std::string revs; @@ -403,7 +408,7 @@ void cmCTestSVN::LoadRevisions(SVNInfo& svninfo) svn_log.push_back(svninfo.LocalPath.c_str()); LogParser out(this, "log-out> ", svninfo); OutputLogger err(this->Log, "log-err> "); - this->RunSVNCommand(svn_log, &out, &err); + return this->RunSVNCommand(svn_log, &out, &err); } void cmCTestSVN::DoRevisionSVN(Revision const& revision, @@ -525,10 +530,10 @@ private: } }; -void cmCTestSVN::LoadRepositories() +bool cmCTestSVN::LoadRepositories() { if (!this->Repositories.empty()) { - return; + return true; } // Info for root repository @@ -540,7 +545,7 @@ void cmCTestSVN::LoadRepositories() svn_status.push_back("status"); ExternalParser out(this, "external-out> "); OutputLogger err(this->Log, "external-err> "); - this->RunSVNCommand(svn_status, &out, &err); + return this->RunSVNCommand(svn_status, &out, &err); } std::string cmCTestSVN::SVNInfo::BuildLocalPath(std::string const& path) const diff --git a/Source/CTest/cmCTestSVN.h b/Source/CTest/cmCTestSVN.h index 1832fd9..e5fe5b7 100644 --- a/Source/CTest/cmCTestSVN.h +++ b/Source/CTest/cmCTestSVN.h @@ -77,10 +77,10 @@ private: SVNInfo* RootInfo; std::string LoadInfo(SVNInfo& svninfo); - void LoadRepositories(); + bool LoadRepositories(); bool LoadModifications() CM_OVERRIDE; bool LoadRevisions() CM_OVERRIDE; - void LoadRevisions(SVNInfo& svninfo); + bool LoadRevisions(SVNInfo& svninfo); void GuessBase(SVNInfo& svninfo, std::vector const& changes); https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ef399f9bc6b8e2ff917a5f2809346fb81fd954ae commit ef399f9bc6b8e2ff917a5f2809346fb81fd954ae Author: Brad King AuthorDate: Wed Feb 15 13:58:40 2017 -0500 Commit: Brad King CommitDate: Thu Feb 16 13:19:26 2017 -0500 ctest_update: Refactor internal APIs to support more failure cases Thread failure of VC tool commands through more APIs so that we can detect when they fail. Defer updating of the individual VC tool usage the future and just return true from them for now. diff --git a/Source/CTest/cmCTestBZR.cxx b/Source/CTest/cmCTestBZR.cxx index b42953b..6769ee5 100644 --- a/Source/CTest/cmCTestBZR.cxx +++ b/Source/CTest/cmCTestBZR.cxx @@ -151,22 +151,24 @@ std::string cmCTestBZR::LoadInfo() return rev; } -void cmCTestBZR::NoteOldRevision() +bool cmCTestBZR::NoteOldRevision() { this->OldRevision = this->LoadInfo(); this->Log << "Revision before update: " << this->OldRevision << "\n"; cmCTestLog(this->CTest, HANDLER_OUTPUT, " Old revision of repository is: " << this->OldRevision << "\n"); this->PriorRev.Rev = this->OldRevision; + return true; } -void cmCTestBZR::NoteNewRevision() +bool cmCTestBZR::NoteNewRevision() { this->NewRevision = this->LoadInfo(); this->Log << "Revision after update: " << this->NewRevision << "\n"; cmCTestLog(this->CTest, HANDLER_OUTPUT, " New revision of repository is: " << this->NewRevision << "\n"); this->Log << "URL = " << this->URL << "\n"; + return true; } class cmCTestBZR::LogParser : public cmCTestVC::OutputLogger, @@ -386,7 +388,7 @@ bool cmCTestBZR::UpdateImpl() return this->RunUpdateCommand(&bzr_update[0], &out, &err); } -void cmCTestBZR::LoadRevisions() +bool cmCTestBZR::LoadRevisions() { cmCTestLog(this->CTest, HANDLER_OUTPUT, " Gathering version information (one . per revision):\n" @@ -400,7 +402,7 @@ void cmCTestBZR::LoadRevisions() // DoRevision takes care of discarding the information about OldRevision revs = this->OldRevision + ".." + this->NewRevision; } else { - return; + return true; } // Run "bzr log" to get all global revisions of interest. @@ -415,6 +417,7 @@ void cmCTestBZR::LoadRevisions() this->RunChild(bzr_log, &out, &err); } cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl); + return true; } class cmCTestBZR::StatusParser : public cmCTestVC::LineParser @@ -460,7 +463,7 @@ private: } }; -void cmCTestBZR::LoadModifications() +bool cmCTestBZR::LoadModifications() { // Run "bzr status" which reports local modifications. const char* bzr = this->CommandLineTool.c_str(); @@ -468,4 +471,5 @@ void cmCTestBZR::LoadModifications() StatusParser out(this, "status-out> "); OutputLogger err(this->Log, "status-err> "); this->RunChild(bzr_status, &out, &err); + return true; } diff --git a/Source/CTest/cmCTestBZR.h b/Source/CTest/cmCTestBZR.h index e7af90b..0b62582 100644 --- a/Source/CTest/cmCTestBZR.h +++ b/Source/CTest/cmCTestBZR.h @@ -26,16 +26,16 @@ public: private: // Implement cmCTestVC internal API. - void NoteOldRevision() CM_OVERRIDE; - void NoteNewRevision() CM_OVERRIDE; + bool NoteOldRevision() CM_OVERRIDE; + bool NoteNewRevision() CM_OVERRIDE; bool UpdateImpl() CM_OVERRIDE; // URL of repository directory checked out in the working tree. std::string URL; std::string LoadInfo(); - void LoadModifications() CM_OVERRIDE; - void LoadRevisions() CM_OVERRIDE; + bool LoadModifications() CM_OVERRIDE; + bool LoadRevisions() CM_OVERRIDE; // Parsing helper classes. class InfoParser; diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx index d30f6b3..9c53aa1 100644 --- a/Source/CTest/cmCTestGIT.cxx +++ b/Source/CTest/cmCTestGIT.cxx @@ -67,19 +67,21 @@ std::string cmCTestGIT::GetWorkingRevision() return rev; } -void cmCTestGIT::NoteOldRevision() +bool cmCTestGIT::NoteOldRevision() { this->OldRevision = this->GetWorkingRevision(); cmCTestLog(this->CTest, HANDLER_OUTPUT, " Old revision of repository is: " << this->OldRevision << "\n"); this->PriorRev.Rev = this->OldRevision; + return true; } -void cmCTestGIT::NoteNewRevision() +bool cmCTestGIT::NoteNewRevision() { this->NewRevision = this->GetWorkingRevision(); cmCTestLog(this->CTest, HANDLER_OUTPUT, " New revision of repository is: " << this->NewRevision << "\n"); + return true; } std::string cmCTestGIT::FindGitDir() @@ -607,7 +609,7 @@ private: char const cmCTestGIT::CommitParser::SectionSep[SectionCount] = { '\n', '\n', '\0' }; -void cmCTestGIT::LoadRevisions() +bool cmCTestGIT::LoadRevisions() { // Use 'git rev-list ... | git diff-tree ...' to get revisions. std::string range = this->OldRevision + ".." + this->NewRevision; @@ -634,9 +636,10 @@ void cmCTestGIT::LoadRevisions() out.Process("", 1); cmsysProcess_Delete(cp); + return true; } -void cmCTestGIT::LoadModifications() +bool cmCTestGIT::LoadModifications() { const char* git = this->CommandLineTool.c_str(); @@ -660,4 +663,5 @@ void cmCTestGIT::LoadModifications() ci != out.Changes.end(); ++ci) { this->DoModification(PathModified, ci->Path); } + return true; } diff --git a/Source/CTest/cmCTestGIT.h b/Source/CTest/cmCTestGIT.h index a655502..d5a1ee3 100644 --- a/Source/CTest/cmCTestGIT.h +++ b/Source/CTest/cmCTestGIT.h @@ -28,8 +28,8 @@ private: unsigned int CurrentGitVersion; unsigned int GetGitVersion(); std::string GetWorkingRevision(); - void NoteOldRevision() CM_OVERRIDE; - void NoteNewRevision() CM_OVERRIDE; + bool NoteOldRevision() CM_OVERRIDE; + bool NoteNewRevision() CM_OVERRIDE; bool UpdateImpl() CM_OVERRIDE; std::string FindGitDir(); @@ -39,8 +39,8 @@ private: bool UpdateByCustom(std::string const& custom); bool UpdateInternal(); - void LoadRevisions() CM_OVERRIDE; - void LoadModifications() CM_OVERRIDE; + bool LoadRevisions() CM_OVERRIDE; + bool LoadModifications() CM_OVERRIDE; // "public" needed by older Sun compilers public: diff --git a/Source/CTest/cmCTestGlobalVC.cxx b/Source/CTest/cmCTestGlobalVC.cxx index 08af179..25294b5 100644 --- a/Source/CTest/cmCTestGlobalVC.cxx +++ b/Source/CTest/cmCTestGlobalVC.cxx @@ -102,14 +102,15 @@ void cmCTestGlobalVC::WriteXMLGlobal(cmXMLWriter& xml) bool cmCTestGlobalVC::WriteXMLUpdates(cmXMLWriter& xml) { + bool result = true; cmCTestLog(this->CTest, HANDLER_OUTPUT, " Gathering version information (one . per revision):\n" " " << std::flush); - this->LoadRevisions(); + result = this->LoadRevisions() && result; cmCTestLog(this->CTest, HANDLER_OUTPUT, std::endl); - this->LoadModifications(); + result = this->LoadModifications() && result; this->WriteXMLGlobal(xml); @@ -119,5 +120,5 @@ bool cmCTestGlobalVC::WriteXMLUpdates(cmXMLWriter& xml) this->WriteXMLDirectory(xml, di->first, di->second); } - return true; + return result; } diff --git a/Source/CTest/cmCTestGlobalVC.h b/Source/CTest/cmCTestGlobalVC.h index 9a3757d..9fa5f21 100644 --- a/Source/CTest/cmCTestGlobalVC.h +++ b/Source/CTest/cmCTestGlobalVC.h @@ -64,8 +64,8 @@ protected: virtual void DoRevision(Revision const& revision, std::vector const& changes); virtual void DoModification(PathStatus status, std::string const& path); - virtual void LoadModifications() = 0; - virtual void LoadRevisions() = 0; + virtual bool LoadModifications() = 0; + virtual bool LoadRevisions() = 0; virtual void WriteXMLGlobal(cmXMLWriter& xml); void WriteXMLDirectory(cmXMLWriter& xml, std::string const& path, diff --git a/Source/CTest/cmCTestHG.cxx b/Source/CTest/cmCTestHG.cxx index 8443c93..68ebd37 100644 --- a/Source/CTest/cmCTestHG.cxx +++ b/Source/CTest/cmCTestHG.cxx @@ -104,19 +104,21 @@ std::string cmCTestHG::GetWorkingRevision() return rev; } -void cmCTestHG::NoteOldRevision() +bool cmCTestHG::NoteOldRevision() { this->OldRevision = this->GetWorkingRevision(); cmCTestLog(this->CTest, HANDLER_OUTPUT, " Old revision of repository is: " << this->OldRevision << "\n"); this->PriorRev.Rev = this->OldRevision; + return true; } -void cmCTestHG::NoteNewRevision() +bool cmCTestHG::NoteNewRevision() { this->NewRevision = this->GetWorkingRevision(); cmCTestLog(this->CTest, HANDLER_OUTPUT, " New revision of repository is: " << this->NewRevision << "\n"); + return true; } bool cmCTestHG::UpdateImpl() @@ -262,7 +264,7 @@ private: } }; -void cmCTestHG::LoadRevisions() +bool cmCTestHG::LoadRevisions() { // Use 'hg log' to get revisions in a xml format. // @@ -293,9 +295,10 @@ void cmCTestHG::LoadRevisions() OutputLogger err(this->Log, "log-err> "); this->RunChild(hg_log, &out, &err); out.Process("\n"); + return true; } -void cmCTestHG::LoadModifications() +bool cmCTestHG::LoadModifications() { // Use 'hg status' to get modified files. const char* hg = this->CommandLineTool.c_str(); @@ -303,4 +306,5 @@ void cmCTestHG::LoadModifications() StatusParser out(this, "status-out> "); OutputLogger err(this->Log, "status-err> "); this->RunChild(hg_status, &out, &err); + return true; } diff --git a/Source/CTest/cmCTestHG.h b/Source/CTest/cmCTestHG.h index a81c347..63baba2 100644 --- a/Source/CTest/cmCTestHG.h +++ b/Source/CTest/cmCTestHG.h @@ -26,12 +26,12 @@ public: private: std::string GetWorkingRevision(); - void NoteOldRevision() CM_OVERRIDE; - void NoteNewRevision() CM_OVERRIDE; + bool NoteOldRevision() CM_OVERRIDE; + bool NoteNewRevision() CM_OVERRIDE; bool UpdateImpl() CM_OVERRIDE; - void LoadRevisions() CM_OVERRIDE; - void LoadModifications() CM_OVERRIDE; + bool LoadRevisions() CM_OVERRIDE; + bool LoadModifications() CM_OVERRIDE; // Parsing helper classes. class IdentifyParser; diff --git a/Source/CTest/cmCTestP4.cxx b/Source/CTest/cmCTestP4.cxx index 41b45a8..4f78876 100644 --- a/Source/CTest/cmCTestP4.cxx +++ b/Source/CTest/cmCTestP4.cxx @@ -369,24 +369,26 @@ std::string cmCTestP4::GetWorkingRevision() return rev; } -void cmCTestP4::NoteOldRevision() +bool cmCTestP4::NoteOldRevision() { this->OldRevision = this->GetWorkingRevision(); cmCTestLog(this->CTest, HANDLER_OUTPUT, " Old revision of repository is: " << this->OldRevision << "\n"); this->PriorRev.Rev = this->OldRevision; + return true; } -void cmCTestP4::NoteNewRevision() +bool cmCTestP4::NoteNewRevision() { this->NewRevision = this->GetWorkingRevision(); cmCTestLog(this->CTest, HANDLER_OUTPUT, " New revision of repository is: " << this->NewRevision << "\n"); + return true; } -void cmCTestP4::LoadRevisions() +bool cmCTestP4::LoadRevisions() { std::vector p4_changes; SetP4Options(p4_changes); @@ -399,7 +401,7 @@ void cmCTestP4::LoadRevisions() if (this->OldRevision == "" || this->NewRevision == "") { cmCTestLog(this->CTest, HANDLER_OUTPUT, " At least one of the revisions " << "is unknown. No repository changes will be reported.\n"); - return; + return false; } range.append("@") @@ -418,7 +420,7 @@ void cmCTestP4::LoadRevisions() this->RunChild(&p4_changes[0], &out, &err); if (ChangeLists.empty()) { - return; + return true; } // p4 describe -s ... at 1111111,2222222 @@ -435,9 +437,10 @@ void cmCTestP4::LoadRevisions() OutputLogger errDescribe(this->Log, "p4_describe-err> "); this->RunChild(&p4_describe[0], &outDescribe, &errDescribe); } + return true; } -void cmCTestP4::LoadModifications() +bool cmCTestP4::LoadModifications() { std::vector p4_diff; SetP4Options(p4_diff); @@ -453,6 +456,7 @@ void cmCTestP4::LoadModifications() DiffParser out(this, "p4_diff-out> "); OutputLogger err(this->Log, "p4_diff-err> "); this->RunChild(&p4_diff[0], &out, &err); + return true; } bool cmCTestP4::UpdateCustom(const std::string& custom) diff --git a/Source/CTest/cmCTestP4.h b/Source/CTest/cmCTestP4.h index eadc4fb..2c04dc6 100644 --- a/Source/CTest/cmCTestP4.h +++ b/Source/CTest/cmCTestP4.h @@ -51,13 +51,13 @@ private: void SetP4Options(std::vector& options); std::string GetWorkingRevision(); - void NoteOldRevision() CM_OVERRIDE; - void NoteNewRevision() CM_OVERRIDE; + bool NoteOldRevision() CM_OVERRIDE; + bool NoteNewRevision() CM_OVERRIDE; bool UpdateImpl() CM_OVERRIDE; bool UpdateCustom(const std::string& custom); - void LoadRevisions() CM_OVERRIDE; - void LoadModifications() CM_OVERRIDE; + bool LoadRevisions() CM_OVERRIDE; + bool LoadModifications() CM_OVERRIDE; class ChangesParser; class DescribeParser; diff --git a/Source/CTest/cmCTestSVN.cxx b/Source/CTest/cmCTestSVN.cxx index 410e0d4..e85d01c 100644 --- a/Source/CTest/cmCTestSVN.cxx +++ b/Source/CTest/cmCTestSVN.cxx @@ -97,7 +97,7 @@ std::string cmCTestSVN::LoadInfo(SVNInfo& svninfo) return rev; } -void cmCTestSVN::NoteOldRevision() +bool cmCTestSVN::NoteOldRevision() { this->LoadRepositories(); @@ -116,9 +116,10 @@ void cmCTestSVN::NoteOldRevision() // Set the global old revision to the one of the root this->OldRevision = this->RootInfo->OldRevision; this->PriorRev.Rev = this->OldRevision; + return true; } -void cmCTestSVN::NoteNewRevision() +bool cmCTestSVN::NoteNewRevision() { this->LoadRepositories(); @@ -153,6 +154,7 @@ void cmCTestSVN::NoteNewRevision() // Set the global new revision to the one of the root this->NewRevision = this->RootInfo->NewRevision; + return true; } void cmCTestSVN::GuessBase(SVNInfo& svninfo, @@ -370,7 +372,7 @@ private: } }; -void cmCTestSVN::LoadRevisions() +bool cmCTestSVN::LoadRevisions() { // Get revisions for all the external repositories std::list::iterator itbeg = this->Repositories.begin(); @@ -379,6 +381,7 @@ void cmCTestSVN::LoadRevisions() SVNInfo& svninfo = *itbeg; LoadRevisions(svninfo); } + return true; } void cmCTestSVN::LoadRevisions(SVNInfo& svninfo) @@ -468,7 +471,7 @@ private: } }; -void cmCTestSVN::LoadModifications() +bool cmCTestSVN::LoadModifications() { // Run "svn status" which reports local modifications. std::vector svn_status; @@ -476,6 +479,7 @@ void cmCTestSVN::LoadModifications() StatusParser out(this, "status-out> "); OutputLogger err(this->Log, "status-err> "); this->RunSVNCommand(svn_status, &out, &err); + return true; } void cmCTestSVN::WriteXMLGlobal(cmXMLWriter& xml) diff --git a/Source/CTest/cmCTestSVN.h b/Source/CTest/cmCTestSVN.h index c0348c2..1832fd9 100644 --- a/Source/CTest/cmCTestSVN.h +++ b/Source/CTest/cmCTestSVN.h @@ -30,8 +30,8 @@ public: private: // Implement cmCTestVC internal API. void CleanupImpl() CM_OVERRIDE; - void NoteOldRevision() CM_OVERRIDE; - void NoteNewRevision() CM_OVERRIDE; + bool NoteOldRevision() CM_OVERRIDE; + bool NoteNewRevision() CM_OVERRIDE; bool UpdateImpl() CM_OVERRIDE; bool RunSVNCommand(std::vector const& parameters, @@ -78,8 +78,8 @@ private: std::string LoadInfo(SVNInfo& svninfo); void LoadRepositories(); - void LoadModifications() CM_OVERRIDE; - void LoadRevisions() CM_OVERRIDE; + bool LoadModifications() CM_OVERRIDE; + bool LoadRevisions() CM_OVERRIDE; void LoadRevisions(SVNInfo& svninfo); void GuessBase(SVNInfo& svninfo, std::vector const& changes); diff --git a/Source/CTest/cmCTestUpdateHandler.cxx b/Source/CTest/cmCTestUpdateHandler.cxx index 0998d59..2b5683a 100644 --- a/Source/CTest/cmCTestUpdateHandler.cxx +++ b/Source/CTest/cmCTestUpdateHandler.cxx @@ -198,7 +198,7 @@ int cmCTestUpdateHandler::ProcessHandler() xml.Element("UpdateType", cmCTestUpdateHandlerUpdateToString(this->UpdateType)); - vc->WriteXML(xml); + bool loadedMods = vc->WriteXML(xml); int localModifications = 0; int numUpdated = vc->GetPathCount(cmCTestVC::PathUpdated); @@ -246,7 +246,7 @@ int cmCTestUpdateHandler::ProcessHandler() xml.EndElement(); // UpdateReturnStatus xml.EndElement(); // Update xml.EndDocument(); - return updated ? numUpdated : -1; + return updated && loadedMods ? numUpdated : -1; } int cmCTestUpdateHandler::DetectVCS(const char* dir) diff --git a/Source/CTest/cmCTestVC.cxx b/Source/CTest/cmCTestVC.cxx index 444c43d..26c9bb5 100644 --- a/Source/CTest/cmCTestVC.cxx +++ b/Source/CTest/cmCTestVC.cxx @@ -147,23 +147,25 @@ bool cmCTestVC::Update() // just note the current version and finish if (!cmSystemTools::IsOn( this->CTest->GetCTestConfiguration("UpdateVersionOnly").c_str())) { - this->NoteOldRevision(); + result = this->NoteOldRevision() && result; this->Log << "--- Begin Update ---\n"; - result = this->UpdateImpl(); + result = this->UpdateImpl() && result; this->Log << "--- End Update ---\n"; } - this->NoteNewRevision(); + result = this->NoteNewRevision() && result; return result; } -void cmCTestVC::NoteOldRevision() +bool cmCTestVC::NoteOldRevision() { // We do nothing by default. + return true; } -void cmCTestVC::NoteNewRevision() +bool cmCTestVC::NoteNewRevision() { // We do nothing by default. + return true; } bool cmCTestVC::UpdateImpl() diff --git a/Source/CTest/cmCTestVC.h b/Source/CTest/cmCTestVC.h index 2681ba0..a1c1673 100644 --- a/Source/CTest/cmCTestVC.h +++ b/Source/CTest/cmCTestVC.h @@ -67,9 +67,9 @@ public: protected: // Internal API to be implemented by subclasses. virtual void CleanupImpl(); - virtual void NoteOldRevision(); + virtual bool NoteOldRevision(); virtual bool UpdateImpl(); - virtual void NoteNewRevision(); + virtual bool NoteNewRevision(); virtual bool WriteXMLUpdates(cmXMLWriter& xml); #if defined(__SUNPRO_CC) && __SUNPRO_CC <= 0x510 ----------------------------------------------------------------------- Summary of changes: Source/CTest/cmCTestBZR.cxx | 14 +++++++++----- Source/CTest/cmCTestBZR.h | 8 ++++---- Source/CTest/cmCTestGIT.cxx | 12 ++++++++---- Source/CTest/cmCTestGIT.h | 8 ++++---- Source/CTest/cmCTestGlobalVC.cxx | 7 ++++--- Source/CTest/cmCTestGlobalVC.h | 4 ++-- Source/CTest/cmCTestHG.cxx | 12 ++++++++---- Source/CTest/cmCTestHG.h | 8 ++++---- Source/CTest/cmCTestP4.cxx | 16 ++++++++++------ Source/CTest/cmCTestP4.h | 8 ++++---- Source/CTest/cmCTestSVN.cxx | 33 +++++++++++++++++++++------------ Source/CTest/cmCTestSVN.h | 12 ++++++------ Source/CTest/cmCTestUpdateHandler.cxx | 4 ++-- Source/CTest/cmCTestVC.cxx | 12 +++++++----- Source/CTest/cmCTestVC.h | 4 ++-- 15 files changed, 95 insertions(+), 67 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 16 13:21:51 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 16 Feb 2017 13:21:51 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-209-ged67fe7 Message-ID: <20170216182151.60847FA1B3@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via ed67fe7451a5ebdf179bbfc5c2517f0e19e651d6 (commit) via 1ba91291e3237e5535a46c6ff1bce6a33d298a76 (commit) via f7b9bf41c5386dfc38b7a722f75b0e23a02d542b (commit) via 4bff2d14fd3010ba4aa1bfc3eda2fb2cdcc5da0f (commit) via 624fb9d7175ee011f8a86c8d7614be4806a53184 (commit) from 5dc1ca679d48a4ef7ef0cd5c987e077bb75915c2 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ed67fe7451a5ebdf179bbfc5c2517f0e19e651d6 commit ed67fe7451a5ebdf179bbfc5c2517f0e19e651d6 Merge: 5dc1ca6 1ba9129 Author: Brad King AuthorDate: Thu Feb 16 13:21:49 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 16 13:21:49 2017 -0500 Merge topic 'install_name_policy' into next 1ba91291 Add policy CMP0068 separate install_name and RPATH settings on macOS f7b9bf41 Apple: Add BUILD_WITH_INSTALL_NAME_DIR target property 4bff2d14 Apple: Refactor support for using INSTALL_NAME_DIR. 624fb9d7 Help: Format BUILD_WITH_INSTALL_RPATH documentation https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1ba91291e3237e5535a46c6ff1bce6a33d298a76 commit 1ba91291e3237e5535a46c6ff1bce6a33d298a76 Author: Clinton Stimpson AuthorDate: Thu Feb 9 08:12:10 2017 -0700 Commit: Clinton Stimpson CommitDate: Tue Feb 14 14:28:07 2017 -0700 Add policy CMP0068 separate install_name and RPATH settings on macOS BUILD_WITH_INSTALL_RPATH, SKIP_BUILD_RPATH, CMAKE_SKIP_RPATH and CMAKE_SKIP_INSTALL_RPATH no longer any effect on the install name of a target on macOS. Fixes: #16589 diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index 3266958..0c9ee2d 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -51,6 +51,14 @@ The :variable:`CMAKE_MINIMUM_REQUIRED_VERSION` variable may also be used to determine whether to report an error on use of deprecated macros or functions. +Policies Introduced by CMake 3.9 +================================ + +.. toctree:: + :maxdepth: 1 + + CMP0068: RPATH settings on macOS do not affect install_name. + Policies Introduced by CMake 3.8 ================================ diff --git a/Help/policy/CMP0068.rst b/Help/policy/CMP0068.rst new file mode 100644 index 0000000..978a6e3 --- /dev/null +++ b/Help/policy/CMP0068.rst @@ -0,0 +1,35 @@ +CMP0068 +------- + +``RPATH`` settings on macOS do not affect ``install_name``. + +CMake 3.9 and newer remove any effect the following settings may have on the +``install_name`` of a target on macOS: + +* :prop_tgt:`BUILD_WITH_INSTALL_RPATH` target property +* :prop_tgt:`SKIP_BUILD_RPATH` target property +* :variable:`CMAKE_SKIP_RPATH` variable +* :variable:`CMAKE_SKIP_INSTALL_RPATH` variable + +Previously, setting :prop_tgt:`BUILD_WITH_INSTALL_RPATH` had the effect of +setting both the ``install_name`` of a target to :prop_tgt:`INSTALL_NAME_DIR` +and the ``RPATH`` to :prop_tgt:`INSTALL_RPATH`. In CMake 3.9, it only affects +setting of ``RPATH``. However, if one wants :prop_tgt:`INSTALL_NAME_DIR` to +apply to the target in the build tree, one may set +:prop_tgt:`BUILD_WITH_INSTALL_NAME_DIR`. + +If :prop_tgt:`SKIP_BUILD_RPATH`, :variable:`CMAKE_SKIP_RPATH` or +:variable:`CMAKE_SKIP_INSTALL_RPATH` were used to strip the directory portion +of the ``install_name`` of a target, one may set ``INSTALL_NAME_DIR=""`` +instead. + +The ``OLD`` behavior of this policy is to use the ``RPATH`` settings for +``install_name`` on macOS. The ``NEW`` behavior of this policy is to ignore +the ``RPATH`` settings for ``install_name`` on macOS. + +This policy was introduced in CMake version 3.9. 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/prop_tgt/BUILD_WITH_INSTALL_NAME_DIR.rst b/Help/prop_tgt/BUILD_WITH_INSTALL_NAME_DIR.rst index 7e02518..bbb9a24 100644 --- a/Help/prop_tgt/BUILD_WITH_INSTALL_NAME_DIR.rst +++ b/Help/prop_tgt/BUILD_WITH_INSTALL_NAME_DIR.rst @@ -9,5 +9,5 @@ This property is initialized by the value of the variable :variable:`CMAKE_BUILD_WITH_INSTALL_NAME_DIR` if it is set when a target is created. -If this property is not set, the value of :prop_tgt:`BUILD_WITH_INSTALL_RPATH` -is used in its place. +If this property is not set and policy :policy:`CMP0068` is not ``NEW``, the +value of :prop_tgt:`BUILD_WITH_INSTALL_RPATH` is used in its place. diff --git a/Help/prop_tgt/BUILD_WITH_INSTALL_RPATH.rst b/Help/prop_tgt/BUILD_WITH_INSTALL_RPATH.rst index 97c3736..0244351 100644 --- a/Help/prop_tgt/BUILD_WITH_INSTALL_RPATH.rst +++ b/Help/prop_tgt/BUILD_WITH_INSTALL_RPATH.rst @@ -10,6 +10,6 @@ This property is initialized by the value of the :variable:`CMAKE_BUILD_WITH_INSTALL_RPATH` variable if it is set when a target is created. -This property also controls use of :prop_tgt:`INSTALL_NAME_DIR` in the build -tree on macOS, but defers to the :prop_tgt:`BUILD_WITH_INSTALL_NAME_DIR` target -property if the latter is set. +If policy :policy:`CMP0068` is not ``NEW``, this property also controls use of +:prop_tgt:`INSTALL_NAME_DIR` in the build tree on macOS. Either way, the +:prop_tgt:`BUILD_WITH_INSTALL_NAME_DIR` target property takes precedence. diff --git a/Help/release/dev/install_name_policy.rst b/Help/release/dev/install_name_policy.rst index 71bdf35..7fe9a86 100644 --- a/Help/release/dev/install_name_policy.rst +++ b/Help/release/dev/install_name_policy.rst @@ -6,3 +6,6 @@ install_name_policy control whether to use the :prop_tgt:`INSTALL_NAME_DIR` target property value for binaries in the build tree. This is for macOS ``install_name`` as :prop_tgt:`BUILD_WITH_INSTALL_RPATH` is for ``RPATH``. + +* On macOS, ``RPATH`` settings such as :prop_tgt:`BUILD_WITH_INSTALL_RPATH` + no longer affect the ``install_name`` field. See policy :policy:`CMP0068`. diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index d32bcd8..8512b99 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -1402,14 +1402,30 @@ bool cmGeneratorTarget::MacOSXUseInstallNameDir() const return cmSystemTools::IsOn(build_with_install_name); } + cmPolicies::PolicyStatus cmp0068 = this->GetPolicyStatusCMP0068(); + if (cmp0068 == cmPolicies::NEW) { + return false; + } + bool use_install_name = this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH"); + if (use_install_name && cmp0068 == cmPolicies::WARN) { + this->LocalGenerator->GetGlobalGenerator()->AddCMP0068WarnTarget( + this->GetName()); + } + return use_install_name; } bool cmGeneratorTarget::CanGenerateInstallNameDir( InstallNameType name_type) const { + cmPolicies::PolicyStatus cmp0068 = this->GetPolicyStatusCMP0068(); + + if (cmp0068 == cmPolicies::NEW) { + return true; + } + bool skip = this->Makefile->IsOn("CMAKE_SKIP_RPATH"); if (name_type == INSTALL_NAME_FOR_INSTALL) { skip |= this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH"); @@ -1417,6 +1433,11 @@ bool cmGeneratorTarget::CanGenerateInstallNameDir( skip |= this->GetPropertyAsBool("SKIP_BUILD_RPATH"); } + if (skip && cmp0068 == cmPolicies::WARN) { + this->LocalGenerator->GetGlobalGenerator()->AddCMP0068WarnTarget( + this->GetName()); + } + return !skip; } diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index f118250..b6b7d9e 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1194,6 +1194,11 @@ void cmGlobalGenerator::AddCMP0042WarnTarget(const std::string& target) this->CMP0042WarnTargets.insert(target); } +void cmGlobalGenerator::AddCMP0068WarnTarget(const std::string& target) +{ + this->CMP0068WarnTargets.insert(target); +} + bool cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const { // If the property is not enabled then okay. @@ -1235,6 +1240,8 @@ bool cmGlobalGenerator::Compute() // clear targets to issue warning CMP0042 for this->CMP0042WarnTargets.clear(); + // clear targets to issue warning CMP0068 for + this->CMP0068WarnTargets.clear(); // Check whether this generator is allowed to run. if (!this->CheckALLOW_DUPLICATE_CUSTOM_TARGETS()) { @@ -1366,6 +1373,24 @@ void cmGlobalGenerator::Generate() this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, w.str()); } + if (!this->CMP0068WarnTargets.empty()) { + std::ostringstream w; + /* clang-format off */ + w << + cmPolicies::GetPolicyWarning(cmPolicies::CMP0068) << "\n" + "For compatibility with older versions of CMake, the install_name " + "fields for the following targets are still affected by RPATH " + "settings:\n" + ; + /* clang-format on */ + for (std::set::iterator iter = + this->CMP0068WarnTargets.begin(); + iter != this->CMP0068WarnTargets.end(); ++iter) { + w << " " << *iter << "\n"; + } + this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, w.str()); + } + this->CMakeInstance->UpdateProgress("Generating done", -1); } diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 18e3730..b3cb41f 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -357,6 +357,7 @@ public: cmExportBuildFileGenerator* GetExportedTargetsFile( const std::string& filename) const; void AddCMP0042WarnTarget(const std::string& target); + void AddCMP0068WarnTarget(const std::string& target); virtual void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const; @@ -562,6 +563,8 @@ private: // track targets to issue CMP0042 warning for. std::set CMP0042WarnTargets; + // track targets to issue CMP0068 warning for. + std::set CMP0068WarnTargets; mutable std::map > FilenameTargetDepends; diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 62e67c7..ecf06b3 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -200,7 +200,10 @@ class cmMakefile; 7, 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0067, \ "Honor language standard in try_compile() source-file signature.", \ - 3, 8, 0, cmPolicies::WARN) + 3, 8, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0068, \ + "RPATH settings on macOS do not affect install_name.", 3, 9, 0, \ + cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ @@ -221,7 +224,8 @@ class cmMakefile; F(CMP0052) \ F(CMP0060) \ F(CMP0063) \ - F(CMP0065) + F(CMP0065) \ + F(CMP0068) /** \class cmPolicies * \brief Handles changes in CMake behavior and policies diff --git a/Tests/RunCMake/CMP0068/CMP0068-NEW-result.txt b/Tests/RunCMake/CMP0068/CMP0068-NEW-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CMP0068/CMP0068-NEW-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CMP0068/CMP0068-NEW.cmake b/Tests/RunCMake/CMP0068/CMP0068-NEW.cmake new file mode 100644 index 0000000..eb8cfa1 --- /dev/null +++ b/Tests/RunCMake/CMP0068/CMP0068-NEW.cmake @@ -0,0 +1,6 @@ + +cmake_policy(SET CMP0068 NEW) +cmake_policy(SET CMP0042 NEW) + +add_library(foo SHARED empty.cpp) +set_target_properties(foo PROPERTIES INSTALL_NAME_DIR "@rpath" INSTALL_RPATH "@loader_path/" BUILD_WITH_INSTALL_RPATH 1) diff --git a/Tests/RunCMake/CMP0068/CMP0068-OLD-result.txt b/Tests/RunCMake/CMP0068/CMP0068-OLD-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CMP0068/CMP0068-OLD-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CMP0068/CMP0068-OLD.cmake b/Tests/RunCMake/CMP0068/CMP0068-OLD.cmake new file mode 100644 index 0000000..cf1040f --- /dev/null +++ b/Tests/RunCMake/CMP0068/CMP0068-OLD.cmake @@ -0,0 +1,6 @@ + +cmake_policy(SET CMP0068 OLD) +cmake_policy(SET CMP0042 NEW) + +add_library(foo SHARED empty.cpp) +set_target_properties(foo PROPERTIES INSTALL_NAME_DIR "@rpath" INSTALL_RPATH "@loader_path/" BUILD_WITH_INSTALL_RPATH 1) diff --git a/Tests/RunCMake/CMP0068/CMP0068-WARN-result.txt b/Tests/RunCMake/CMP0068/CMP0068-WARN-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CMP0068/CMP0068-WARN-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CMP0068/CMP0068-WARN-stderr.txt b/Tests/RunCMake/CMP0068/CMP0068-WARN-stderr.txt new file mode 100644 index 0000000..3cb5854 --- /dev/null +++ b/Tests/RunCMake/CMP0068/CMP0068-WARN-stderr.txt @@ -0,0 +1,12 @@ +CMake Warning \(dev\): + Policy CMP0068 is not set: RPATH settings on macOS do not affect + install_name. Run "cmake --help-policy CMP0068" for policy details. Use + the cmake_policy command to set the policy and suppress this warning. + + For compatibility with older versions of CMake, the install_name fields for + the following targets are still affected by RPATH settings: + + foo3 + foo4 + +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CMP0068/CMP0068-WARN.cmake b/Tests/RunCMake/CMP0068/CMP0068-WARN.cmake new file mode 100644 index 0000000..b7ec480 --- /dev/null +++ b/Tests/RunCMake/CMP0068/CMP0068-WARN.cmake @@ -0,0 +1,12 @@ +cmake_policy(SET CMP0042 NEW) + +add_library(foo SHARED empty.cpp) +add_library(foo-static STATIC empty.cpp) +add_library(foo2 SHARED empty.cpp) +set_target_properties(foo2 PROPERTIES MACOSX_RPATH 1) +add_library(foo3 SHARED empty.cpp) +set_target_properties(foo3 PROPERTIES BUILD_WITH_INSTALL_RPATH 1 INSTALL_NAME_DIR "@loader_path") +add_library(foo4 SHARED empty.cpp) +set_target_properties(foo4 PROPERTIES BUILD_WITH_INSTALL_RPATH 1 INSTALL_NAME_DIR "@rpath") +add_library(foo5 SHARED empty.cpp) +set_target_properties(foo5 PROPERTIES BUILD_WITH_INSTALL_RPATH 1 BUILD_WITH_INSTALL_NAME_DIR 1 INSTALL_NAME_DIR "@rpath") diff --git a/Tests/RunCMake/CMP0068/CMakeLists.txt b/Tests/RunCMake/CMP0068/CMakeLists.txt new file mode 100644 index 0000000..375cbdb --- /dev/null +++ b/Tests/RunCMake/CMP0068/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.8) +project(${RunCMake_TEST} CXX) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/CMP0068/RunCMakeTest.cmake b/Tests/RunCMake/CMP0068/RunCMakeTest.cmake new file mode 100644 index 0000000..88a6225 --- /dev/null +++ b/Tests/RunCMake/CMP0068/RunCMakeTest.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +run_cmake(CMP0068-OLD) +run_cmake(CMP0068-NEW) +run_cmake(CMP0068-WARN) diff --git a/Tests/RunCMake/CMP0068/empty.cpp b/Tests/RunCMake/CMP0068/empty.cpp new file mode 100644 index 0000000..11ec041 --- /dev/null +++ b/Tests/RunCMake/CMP0068/empty.cpp @@ -0,0 +1,7 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif + int empty() +{ + return 0; +} diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 63016f1..bd92013 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -104,6 +104,9 @@ add_RunCMake_test(CMP0057) add_RunCMake_test(CMP0059) add_RunCMake_test(CMP0060) add_RunCMake_test(CMP0064) +if(CMAKE_SYSTEM_NAME MATCHES Darwin AND CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG) + add_RunCMake_test(CMP0068) +endif() # The test for Policy 65 requires the use of the # CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS variable, which both the VS and Xcode diff --git a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt index 57047fb..78657ef 100644 --- a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt +++ b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt @@ -20,6 +20,7 @@ \* CMP0060 \* CMP0063 \* CMP0065 + \* CMP0068 Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/install/EXPORT-OldIFace.cmake b/Tests/RunCMake/install/EXPORT-OldIFace.cmake index 033f684..ee3fb23 100644 --- a/Tests/RunCMake/install/EXPORT-OldIFace.cmake +++ b/Tests/RunCMake/install/EXPORT-OldIFace.cmake @@ -1,5 +1,6 @@ enable_language(C) set(CMAKE_BUILD_WITH_INSTALL_RPATH 1) +set(CMAKE_BUILD_WITH_INSTALL_NAME_DIR 1) add_subdirectory(EXPORT-OldIFace) add_library(foo SHARED empty.c) target_link_libraries(foo bar) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f7b9bf41c5386dfc38b7a722f75b0e23a02d542b commit f7b9bf41c5386dfc38b7a722f75b0e23a02d542b Author: Clinton Stimpson AuthorDate: Thu Feb 9 08:05:10 2017 -0700 Commit: Clinton Stimpson CommitDate: Tue Feb 14 14:28:07 2017 -0700 Apple: Add BUILD_WITH_INSTALL_NAME_DIR target property This new property controls whether to apply INSTALL_NAME_DIR to the build tree. It also overrides BUILD_WITH_INSTALL_RPATH. diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 38aba81..5fad10c 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -123,6 +123,7 @@ Properties on Targets /prop_tgt/AUTORCC_OPTIONS /prop_tgt/BINARY_DIR /prop_tgt/BUILD_RPATH + /prop_tgt/BUILD_WITH_INSTALL_NAME_DIR /prop_tgt/BUILD_WITH_INSTALL_RPATH /prop_tgt/BUNDLE_EXTENSION /prop_tgt/BUNDLE diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 95f780a..2aea851 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -263,6 +263,7 @@ Variables that Control the Build /variable/CMAKE_AUTOUIC /variable/CMAKE_AUTOUIC_OPTIONS /variable/CMAKE_BUILD_RPATH + /variable/CMAKE_BUILD_WITH_INSTALL_NAME_DIR /variable/CMAKE_BUILD_WITH_INSTALL_RPATH /variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY /variable/CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG diff --git a/Help/prop_tgt/BUILD_WITH_INSTALL_NAME_DIR.rst b/Help/prop_tgt/BUILD_WITH_INSTALL_NAME_DIR.rst new file mode 100644 index 0000000..7e02518 --- /dev/null +++ b/Help/prop_tgt/BUILD_WITH_INSTALL_NAME_DIR.rst @@ -0,0 +1,13 @@ +BUILD_WITH_INSTALL_NAME_DIR +--------------------------- + +``BUILD_WITH_INSTALL_NAME_DIR`` is a boolean specifying whether the macOS +``install_name`` of a target in the build tree uses the directory given by +:prop_tgt:`INSTALL_NAME_DIR`. This setting only applies to targets on macOS. + +This property is initialized by the value of the variable +:variable:`CMAKE_BUILD_WITH_INSTALL_NAME_DIR` if it is set when a target is +created. + +If this property is not set, the value of :prop_tgt:`BUILD_WITH_INSTALL_RPATH` +is used in its place. diff --git a/Help/prop_tgt/BUILD_WITH_INSTALL_RPATH.rst b/Help/prop_tgt/BUILD_WITH_INSTALL_RPATH.rst index 35297e9..97c3736 100644 --- a/Help/prop_tgt/BUILD_WITH_INSTALL_RPATH.rst +++ b/Help/prop_tgt/BUILD_WITH_INSTALL_RPATH.rst @@ -9,3 +9,7 @@ installation. This property is initialized by the value of the :variable:`CMAKE_BUILD_WITH_INSTALL_RPATH` variable if it is set when a target is created. + +This property also controls use of :prop_tgt:`INSTALL_NAME_DIR` in the build +tree on macOS, but defers to the :prop_tgt:`BUILD_WITH_INSTALL_NAME_DIR` target +property if the latter is set. diff --git a/Help/release/dev/install_name_policy.rst b/Help/release/dev/install_name_policy.rst new file mode 100644 index 0000000..71bdf35 --- /dev/null +++ b/Help/release/dev/install_name_policy.rst @@ -0,0 +1,8 @@ +install_name_policy +------------------- + +* A :prop_tgt:`BUILD_WITH_INSTALL_NAME_DIR` target property and corresponding + :variable:`CMAKE_BUILD_WITH_INSTALL_NAME_DIR` variable were added to + control whether to use the :prop_tgt:`INSTALL_NAME_DIR` target property + value for binaries in the build tree. This is for macOS ``install_name`` + as :prop_tgt:`BUILD_WITH_INSTALL_RPATH` is for ``RPATH``. diff --git a/Help/variable/CMAKE_BUILD_WITH_INSTALL_NAME_DIR.rst b/Help/variable/CMAKE_BUILD_WITH_INSTALL_NAME_DIR.rst new file mode 100644 index 0000000..30d5d3b --- /dev/null +++ b/Help/variable/CMAKE_BUILD_WITH_INSTALL_NAME_DIR.rst @@ -0,0 +1,7 @@ +CMAKE_BUILD_WITH_INSTALL_NAME_DIR +--------------------------------- + +Whether to use :prop_tgt:`INSTALL_NAME_DIR` on targets in the build tree. + +This variable is used to initialize the :prop_tgt:`BUILD_WITH_INSTALL_NAME_DIR` +property on all targets. diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 5dd0261..d32bcd8 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -1396,6 +1396,12 @@ bool cmGeneratorTarget::MacOSXRpathInstallNameDirDefault() const bool cmGeneratorTarget::MacOSXUseInstallNameDir() const { + const char* build_with_install_name = + this->GetProperty("BUILD_WITH_INSTALL_NAME_DIR"); + if (build_with_install_name) { + return cmSystemTools::IsOn(build_with_install_name); + } + bool use_install_name = this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH"); return use_install_name; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index fe3472d..ad3d604 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -253,6 +253,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, this->SetPropertyDefault("WIN32_EXECUTABLE", CM_NULLPTR); this->SetPropertyDefault("MACOSX_BUNDLE", CM_NULLPTR); this->SetPropertyDefault("MACOSX_RPATH", CM_NULLPTR); + this->SetPropertyDefault("BUILD_WITH_INSTALL_NAME_DIR", CM_NULLPTR); this->SetPropertyDefault("C_CLANG_TIDY", CM_NULLPTR); this->SetPropertyDefault("C_COMPILER_LAUNCHER", CM_NULLPTR); this->SetPropertyDefault("C_CPPLINT", CM_NULLPTR); https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4bff2d14fd3010ba4aa1bfc3eda2fb2cdcc5da0f commit 4bff2d14fd3010ba4aa1bfc3eda2fb2cdcc5da0f Author: Clinton Stimpson AuthorDate: Thu Feb 9 07:46:40 2017 -0700 Commit: Clinton Stimpson CommitDate: Tue Feb 14 14:28:01 2017 -0700 Apple: Refactor support for using INSTALL_NAME_DIR. diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 6ce8140..5dd0261 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -1321,8 +1321,7 @@ bool cmGeneratorTarget::HasMacOSXRpathInstallNameDir( return false; } const char* install_name = this->GetProperty("INSTALL_NAME_DIR"); - bool use_install_name = - this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH"); + bool use_install_name = this->MacOSXUseInstallNameDir(); if (install_name && use_install_name && std::string(install_name) == "@rpath") { install_name_is_rpath = true; @@ -1395,6 +1394,26 @@ bool cmGeneratorTarget::MacOSXRpathInstallNameDirDefault() const return cmp0042 == cmPolicies::NEW; } +bool cmGeneratorTarget::MacOSXUseInstallNameDir() const +{ + bool use_install_name = this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH"); + + return use_install_name; +} + +bool cmGeneratorTarget::CanGenerateInstallNameDir( + InstallNameType name_type) const +{ + bool skip = this->Makefile->IsOn("CMAKE_SKIP_RPATH"); + if (name_type == INSTALL_NAME_FOR_INSTALL) { + skip |= this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH"); + } else { + skip |= this->GetPropertyAsBool("SKIP_BUILD_RPATH"); + } + + return !skip; +} + std::string cmGeneratorTarget::GetSOName(const std::string& config) const { if (this->IsImported()) { @@ -1503,24 +1522,25 @@ std::string cmGeneratorTarget::GetFullName(const std::string& config, std::string cmGeneratorTarget::GetInstallNameDirForBuildTree( const std::string& config) const { - // If building directly for installation then the build tree install_name - // is the same as the install tree. - if (this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH")) { - return this->GetInstallNameDirForInstallTree(); - } + if (this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) { - // Use the build tree directory for the target. - if (this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME") && - !this->Makefile->IsOn("CMAKE_SKIP_RPATH") && - !this->GetPropertyAsBool("SKIP_BUILD_RPATH")) { - std::string dir; - if (this->MacOSXRpathInstallNameDirDefault()) { - dir = "@rpath"; - } else { - dir = this->GetDirectory(config); + // If building directly for installation then the build tree install_name + // is the same as the install tree. + if (this->MacOSXUseInstallNameDir()) { + return this->GetInstallNameDirForInstallTree(); + } + + // Use the build tree directory for the target. + if (this->CanGenerateInstallNameDir(INSTALL_NAME_FOR_BUILD)) { + std::string dir; + if (this->MacOSXRpathInstallNameDirDefault()) { + dir = "@rpath"; + } else { + dir = this->GetDirectory(config); + } + dir += "/"; + return dir; } - dir += "/"; - return dir; } return ""; } @@ -1531,8 +1551,7 @@ std::string cmGeneratorTarget::GetInstallNameDirForInstallTree() const std::string dir; const char* install_name_dir = this->GetProperty("INSTALL_NAME_DIR"); - if (!this->Makefile->IsOn("CMAKE_SKIP_RPATH") && - !this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH")) { + if (this->CanGenerateInstallNameDir(INSTALL_NAME_FOR_INSTALL)) { if (install_name_dir && *install_name_dir) { dir = install_name_dir; dir += "/"; diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index f568699..689fbda 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -525,6 +525,16 @@ public: /** Whether this library defaults to \@rpath. */ bool MacOSXRpathInstallNameDirDefault() const; + enum InstallNameType + { + INSTALL_NAME_FOR_BUILD, + INSTALL_NAME_FOR_INSTALL + }; + /** Whether to use INSTALL_NAME_DIR. */ + bool MacOSXUseInstallNameDir() const; + /** Whether to generate an install_name. */ + bool CanGenerateInstallNameDir(InstallNameType t) const; + /** Test for special case of a third-party shared library that has no soname at all. */ bool IsImportedSharedLibWithoutSOName(const std::string& config) const; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=624fb9d7175ee011f8a86c8d7614be4806a53184 commit 624fb9d7175ee011f8a86c8d7614be4806a53184 Author: Brad King AuthorDate: Tue Feb 14 08:51:37 2017 -0500 Commit: Brad King CommitDate: Tue Feb 14 08:52:02 2017 -0500 Help: Format BUILD_WITH_INSTALL_RPATH documentation diff --git a/Help/prop_tgt/BUILD_WITH_INSTALL_RPATH.rst b/Help/prop_tgt/BUILD_WITH_INSTALL_RPATH.rst index abcf28f..35297e9 100644 --- a/Help/prop_tgt/BUILD_WITH_INSTALL_RPATH.rst +++ b/Help/prop_tgt/BUILD_WITH_INSTALL_RPATH.rst @@ -1,11 +1,11 @@ BUILD_WITH_INSTALL_RPATH ------------------------ -Should build tree targets have install tree rpaths. +``BUILD_WITH_INSTALL_RPATH`` is a boolean specifying whether to link the target +in the build tree with the :prop_tgt:`INSTALL_RPATH`. This takes precedence +over :prop_tgt:`SKIP_BUILD_RPATH` and avoids the need for relinking before +installation. -BUILD_WITH_INSTALL_RPATH is a boolean specifying whether to link the -target in the build tree with the INSTALL_RPATH. This takes -precedence over SKIP_BUILD_RPATH and avoids the need for relinking -before installation. This property is initialized by the value of the -variable CMAKE_BUILD_WITH_INSTALL_RPATH if it is set when a target is -created. +This property is initialized by the value of the +:variable:`CMAKE_BUILD_WITH_INSTALL_RPATH` variable if it is set when a target +is created. ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-policies.7.rst | 8 ++ Help/manual/cmake-properties.7.rst | 1 + Help/manual/cmake-variables.7.rst | 1 + Help/policy/CMP0068.rst | 35 ++++++++ Help/prop_tgt/BUILD_WITH_INSTALL_NAME_DIR.rst | 13 +++ Help/prop_tgt/BUILD_WITH_INSTALL_RPATH.rst | 18 ++-- Help/release/dev/install_name_policy.rst | 11 +++ .../variable/CMAKE_BUILD_WITH_INSTALL_NAME_DIR.rst | 7 ++ Source/cmGeneratorTarget.cxx | 86 +++++++++++++++----- Source/cmGeneratorTarget.h | 10 +++ Source/cmGlobalGenerator.cxx | 25 ++++++ Source/cmGlobalGenerator.h | 3 + Source/cmPolicies.h | 8 +- Source/cmTarget.cxx | 1 + .../CMP0068-NEW-result.txt} | 0 Tests/RunCMake/CMP0068/CMP0068-NEW.cmake | 6 ++ .../CMP0068-OLD-result.txt} | 0 Tests/RunCMake/CMP0068/CMP0068-OLD.cmake | 6 ++ .../CMP0068-WARN-result.txt} | 0 Tests/RunCMake/CMP0068/CMP0068-WARN-stderr.txt | 12 +++ .../CMP0068-WARN.cmake} | 3 + Tests/RunCMake/{CMP0051 => CMP0068}/CMakeLists.txt | 2 +- Tests/RunCMake/CMP0068/RunCMakeTest.cmake | 5 ++ .../Export => RunCMake/CMP0068}/empty.cpp | 0 Tests/RunCMake/CMakeLists.txt | 3 + .../RunCMake/TargetPolicies/PolicyList-stderr.txt | 1 + Tests/RunCMake/install/EXPORT-OldIFace.cmake | 1 + 27 files changed, 236 insertions(+), 30 deletions(-) create mode 100644 Help/policy/CMP0068.rst create mode 100644 Help/prop_tgt/BUILD_WITH_INSTALL_NAME_DIR.rst create mode 100644 Help/release/dev/install_name_policy.rst create mode 100644 Help/variable/CMAKE_BUILD_WITH_INSTALL_NAME_DIR.rst copy Tests/RunCMake/{CMP0022/CMP0022-WARN-empty-old-result.txt => CMP0068/CMP0068-NEW-result.txt} (100%) create mode 100644 Tests/RunCMake/CMP0068/CMP0068-NEW.cmake copy Tests/RunCMake/{CMP0022/CMP0022-WARN-empty-old-result.txt => CMP0068/CMP0068-OLD-result.txt} (100%) create mode 100644 Tests/RunCMake/CMP0068/CMP0068-OLD.cmake copy Tests/RunCMake/{CMP0022/CMP0022-WARN-empty-old-result.txt => CMP0068/CMP0068-WARN-result.txt} (100%) create mode 100644 Tests/RunCMake/CMP0068/CMP0068-WARN-stderr.txt copy Tests/RunCMake/{CMP0042/CMP0042-WARN.cmake => CMP0068/CMP0068-WARN.cmake} (69%) copy Tests/RunCMake/{CMP0051 => CMP0068}/CMakeLists.txt (63%) create mode 100644 Tests/RunCMake/CMP0068/RunCMakeTest.cmake copy Tests/{ExportImport/Export => RunCMake/CMP0068}/empty.cpp (100%) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 16 13:27:12 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 16 Feb 2017 13:27:12 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-211-g0823533 Message-ID: <20170216182712.245C8FA448@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 0823533dd339ef714c0d0efbc8321bafec48c501 (commit) via 9b78dca3a909ce3161d235718f935bf2fb9b7f64 (commit) from ed67fe7451a5ebdf179bbfc5c2517f0e19e651d6 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0823533dd339ef714c0d0efbc8321bafec48c501 commit 0823533dd339ef714c0d0efbc8321bafec48c501 Merge: ed67fe7 9b78dca Author: Brad King AuthorDate: Thu Feb 16 13:27:11 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 16 13:27:11 2017 -0500 Merge topic 'FindOpenSSL-crypto-name' into next 9b78dca3 FindOpenSSL: Add another name for libcrypto with MSVC https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9b78dca3a909ce3161d235718f935bf2fb9b7f64 commit 9b78dca3a909ce3161d235718f935bf2fb9b7f64 Author: Kevin Whitaker AuthorDate: Thu Feb 16 09:38:30 2017 -0500 Commit: Brad King CommitDate: Thu Feb 16 13:26:42 2017 -0500 FindOpenSSL: Add another name for libcrypto with MSVC Add the `crypto` name without any prefix or suffix as a fallback, just as we already have for `ssl`. diff --git a/Modules/FindOpenSSL.cmake b/Modules/FindOpenSSL.cmake index 6259ce1..117811c 100644 --- a/Modules/FindOpenSSL.cmake +++ b/Modules/FindOpenSSL.cmake @@ -160,6 +160,7 @@ if(WIN32 AND NOT CYGWIN) libcrypto libeay32${_OPENSSL_MSVC_RT_MODE} libeay32 + crypto NAMES_PER_DIR ${_OPENSSL_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES ----------------------------------------------------------------------- Summary of changes: Modules/FindOpenSSL.cmake | 1 + 1 file changed, 1 insertion(+) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 16 13:36:17 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 16 Feb 2017 13:36:17 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-127-gc508fd8 Message-ID: <20170216183617.F1980FA6B9@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via c508fd8481d87aef7843942ba186d3dea4246c7f (commit) via 1f9c879759a92a4bdbb264aafacac05d2da89132 (commit) via 2c354f4ee44e9690ca6ed6c7266283bda1070ca4 (commit) via 93737d8012d262711bee9b3fbf2b4927e4a0255a (commit) via efac65d67b32c407044db6536da4f43ed9546be7 (commit) via ac7489e03c02d4e485804197ae8a0a771da6e55e (commit) from bb4730dc5add8c5ac54b41efa5375189636429f3 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 16 13:36:18 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 16 Feb 2017 13:36:18 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-218-g638f376 Message-ID: <20170216183618.18C20FA6C4@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 638f37623af0431c640d6020a3253dbb4d5c4841 (commit) via c508fd8481d87aef7843942ba186d3dea4246c7f (commit) via 1f9c879759a92a4bdbb264aafacac05d2da89132 (commit) via 2c354f4ee44e9690ca6ed6c7266283bda1070ca4 (commit) via 93737d8012d262711bee9b3fbf2b4927e4a0255a (commit) via efac65d67b32c407044db6536da4f43ed9546be7 (commit) via ac7489e03c02d4e485804197ae8a0a771da6e55e (commit) from 0823533dd339ef714c0d0efbc8321bafec48c501 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=638f37623af0431c640d6020a3253dbb4d5c4841 commit 638f37623af0431c640d6020a3253dbb4d5c4841 Merge: 0823533 c508fd8 Author: Brad King AuthorDate: Thu Feb 16 13:35:57 2017 -0500 Commit: Brad King CommitDate: Thu Feb 16 13:35:57 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 16 13:36:18 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 16 Feb 2017 13:36:18 -0500 (EST) Subject: [Cmake-commits] CMake branch, release, updated. v3.8.0-rc1-25-g2c354f4 Message-ID: <20170216183618.31AFEFA6C7@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, release has been updated via 2c354f4ee44e9690ca6ed6c7266283bda1070ca4 (commit) via 28ee3784055ab6b21563d56024b1324c16949cbc (commit) via 93737d8012d262711bee9b3fbf2b4927e4a0255a (commit) via 51849bbab8b1b6b8299dc08e98ca1524cc1e168a (commit) via ac7489e03c02d4e485804197ae8a0a771da6e55e (commit) via 55fb46d273e8ab51d5df366286052c71b9008437 (commit) via d7c80f60362cbc40216fab67318d94988030315c (commit) from 272c348d5a1c3f713586e05e0d73fd18441f7bb2 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- Summary of changes: Modules/Compiler/NVIDIA-CUDA.cmake | 11 +++++------ Modules/Platform/Windows-NVIDIA-CUDA.cmake | 12 +++++++----- Source/CTest/cmCTestSVN.cxx | 5 ++++- Source/cmQtAutoGenerators.cxx | 4 ++-- Tests/Cuda/Complex/CMakeLists.txt | 2 +- Tests/Cuda/ProperLinkFlags/CMakeLists.txt | 2 +- Tests/Cuda/WithC/CMakeLists.txt | 2 +- Tests/CudaOnly/SeparateCompilation/CMakeLists.txt | 2 +- Tests/CudaOnly/WithDefs/CMakeLists.txt | 2 +- 9 files changed, 23 insertions(+), 19 deletions(-) hooks/post-receive -- CMake From daniel at pfeifer-mail.de Thu Feb 16 17:31:44 2017 From: daniel at pfeifer-mail.de (Daniel Pfeifer) Date: Thu, 16 Feb 2017 17:31:44 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-222-ge889750 Message-ID: <20170216223145.58959FA4FC@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via e889750e7bce9750ef1f8cc505e77ead0b5aad1d (commit) via 761ea20518081de976a40e590577056f23188fbd (commit) via 1728b9c076a34ef017f10499e5b637d025b2afd8 (commit) via fe75e140d617dd2d8401a85c718d03a6466a8bd9 (commit) from 638f37623af0431c640d6020a3253dbb4d5c4841 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e889750e7bce9750ef1f8cc505e77ead0b5aad1d commit e889750e7bce9750ef1f8cc505e77ead0b5aad1d Merge: 638f376 761ea20 Author: Daniel Pfeifer AuthorDate: Thu Feb 16 17:31:37 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 16 17:31:37 2017 -0500 Merge topic 'bison3' into next 761ea205 cmCommandArgumentParser: reformat grammar 1728b9c0 cmDependsJavaParser: Port to bison 3 fe75e140 cmCommandArgumentParser: Port to bison 3 https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=761ea20518081de976a40e590577056f23188fbd commit 761ea20518081de976a40e590577056f23188fbd Author: Daniel Pfeifer AuthorDate: Fri Feb 10 22:18:04 2017 +0100 Commit: Daniel Pfeifer CommitDate: Thu Feb 16 21:34:27 2017 +0100 cmCommandArgumentParser: reformat grammar diff --git a/Source/cmCommandArgumentParser.cxx b/Source/cmCommandArgumentParser.cxx index 8bd3082..75191c8 100644 --- a/Source/cmCommandArgumentParser.cxx +++ b/Source/cmCommandArgumentParser.cxx @@ -496,9 +496,9 @@ static const yytype_uint8 yytranslate[] = /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { - 0, 94, 94, 101, 106, 112, 116, 122, 127, 133, - 138, 143, 148, 153, 158, 164, 170, 176, 182, 188, - 193, 199, 203, 209, 214 + 0, 94, 94, 100, 103, 108, 111, 116, 119, 124, + 127, 130, 133, 136, 139, 144, 147, 150, 153, 158, + 161, 166, 169, 174, 177 }; #endif @@ -1295,195 +1295,192 @@ yyreduce: switch (yyn) { case 2: -#line 95 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 94 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = 0; - yyGetParser->SetResult((yyvsp[0].str)); -} + (yyval.str) = 0; + yyGetParser->SetResult((yyvsp[0].str)); + } #line 1304 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 3: -#line 102 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 100 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[0].str); -} + (yyval.str) = (yyvsp[0].str); + } #line 1312 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 4: -#line 107 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 103 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); -} + (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); + } #line 1320 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 5: -#line 112 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 108 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = 0; -} + (yyval.str) = 0; + } #line 1328 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 6: -#line 117 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 111 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); -} + (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); + } #line 1336 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 7: -#line 123 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 116 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[0].str); -} + (yyval.str) = (yyvsp[0].str); + } #line 1344 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 8: -#line 128 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 119 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[0].str); -} + (yyval.str) = (yyvsp[0].str); + } #line 1352 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 9: -#line 134 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 124 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[0].str); -} + (yyval.str) = (yyvsp[0].str); + } #line 1360 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 10: -#line 139 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 127 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[0].str); -} + (yyval.str) = (yyvsp[0].str); + } #line 1368 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 11: -#line 144 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 130 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[0].str); -} + (yyval.str) = (yyvsp[0].str); + } #line 1376 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 12: -#line 149 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 133 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[0].str); -} + (yyval.str) = (yyvsp[0].str); + } #line 1384 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 13: -#line 154 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 136 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[0].str); -} + (yyval.str) = (yyvsp[0].str); + } #line 1392 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 14: -#line 159 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 139 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[0].str); -} + (yyval.str) = (yyvsp[0].str); + } #line 1400 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 15: -#line 165 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 144 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str),(yyvsp[-1].str)); - //std::cerr << __LINE__ << " here: [" << $1 << "] [" << $2 << "] [" << $3 << "]" << std::endl; -} -#line 1409 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ + (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str)); + } +#line 1408 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 16: -#line 171 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 147 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str),(yyvsp[-1].str)); - //std::cerr << __LINE__ << " here: [" << $1 << "] [" << $2 << "] [" << $3 << "]" << std::endl; -} -#line 1418 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ + (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str)); + } +#line 1416 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 17: -#line 177 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 150 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = yyGetParser->ExpandVariable((yyvsp[-1].str)); - //std::cerr << __LINE__ << " here: [" << $1 << "] [" << $2 << "] [" << $3 << "]" << std::endl; -} -#line 1427 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ + (yyval.str) = yyGetParser->ExpandVariable((yyvsp[-1].str)); + } +#line 1424 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 18: -#line 183 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 153 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = yyGetParser->ExpandVariableForAt((yyvsp[0].str)); -} -#line 1435 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ + (yyval.str) = yyGetParser->ExpandVariableForAt((yyvsp[0].str)); + } +#line 1432 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 19: -#line 189 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 158 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[0].str); -} -#line 1443 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ + (yyval.str) = (yyvsp[0].str); + } +#line 1440 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 20: -#line 194 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 161 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[-1].str); -} -#line 1451 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ + (yyval.str) = (yyvsp[-1].str); + } +#line 1448 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 21: -#line 199 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 166 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = 0; -} -#line 1459 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ + (yyval.str) = 0; + } +#line 1456 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 22: -#line 204 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 169 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); -} -#line 1467 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ + (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); + } +#line 1464 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 23: -#line 210 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 174 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[0].str); -} -#line 1475 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ + (yyval.str) = (yyvsp[0].str); + } +#line 1472 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 24: -#line 215 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 177 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[0].str); -} -#line 1483 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ + (yyval.str) = (yyvsp[0].str); + } +#line 1480 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; -#line 1487 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1484 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -1713,7 +1710,7 @@ yyreturn: #endif return yyresult; } -#line 220 "cmCommandArgumentParser.y" /* yacc.c:1906 */ +#line 182 "cmCommandArgumentParser.y" /* yacc.c:1906 */ /* End of grammar */ diff --git a/Source/cmCommandArgumentParser.y b/Source/cmCommandArgumentParser.y index 9a9ba10..cfd76d1 100644 --- a/Source/cmCommandArgumentParser.y +++ b/Source/cmCommandArgumentParser.y @@ -91,131 +91,93 @@ static void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message); Start: -GoalWithOptionalBackSlash -{ - $$ = 0; - yyGetParser->SetResult($1); -} + GoalWithOptionalBackSlash { + $$ = 0; + yyGetParser->SetResult($1); + } GoalWithOptionalBackSlash: -Goal -{ - $$ = $1; -} -| -Goal cal_BSLASH -{ - $$ = yyGetParser->CombineUnions($1, $2); -} + Goal { + $$ = $1; + } +| Goal cal_BSLASH { + $$ = yyGetParser->CombineUnions($1, $2); + } Goal: -{ - $$ = 0; -} -| -String Goal -{ - $$ = yyGetParser->CombineUnions($1, $2); -} + { + $$ = 0; + } +| String Goal { + $$ = yyGetParser->CombineUnions($1, $2); + } String: -OuterText -{ - $$ = $1; -} -| -Variable -{ - $$ = $1; -} + OuterText { + $$ = $1; + } +| Variable { + $$ = $1; + } OuterText: -cal_NAME -{ - $$ = $1; -} -| -cal_AT -{ - $$ = $1; -} -| -cal_DOLLAR -{ - $$ = $1; -} -| -cal_LCURLY -{ - $$ = $1; -} -| -cal_RCURLY -{ - $$ = $1; -} -| -cal_SYMBOL -{ - $$ = $1; -} + cal_NAME { + $$ = $1; + } +| cal_AT { + $$ = $1; + } +| cal_DOLLAR { + $$ = $1; + } +| cal_LCURLY { + $$ = $1; + } +| cal_RCURLY { + $$ = $1; + } +| cal_SYMBOL { + $$ = $1; + } Variable: -cal_ENVCURLY EnvVarName cal_RCURLY -{ - $$ = yyGetParser->ExpandSpecialVariable($1,$2); - //std::cerr << __LINE__ << " here: [" << $1 << "] [" << $2 << "] [" << $3 << "]" << std::endl; -} -| -cal_NCURLY MultipleIds cal_RCURLY -{ - $$ = yyGetParser->ExpandSpecialVariable($1,$2); - //std::cerr << __LINE__ << " here: [" << $1 << "] [" << $2 << "] [" << $3 << "]" << std::endl; -} -| -cal_DCURLY MultipleIds cal_RCURLY -{ - $$ = yyGetParser->ExpandVariable($2); - //std::cerr << __LINE__ << " here: [" << $1 << "] [" << $2 << "] [" << $3 << "]" << std::endl; -} -| -cal_ATNAME -{ - $$ = yyGetParser->ExpandVariableForAt($1); -} + cal_ENVCURLY EnvVarName cal_RCURLY { + $$ = yyGetParser->ExpandSpecialVariable($1, $2); + } +| cal_NCURLY MultipleIds cal_RCURLY { + $$ = yyGetParser->ExpandSpecialVariable($1, $2); + } +| cal_DCURLY MultipleIds cal_RCURLY { + $$ = yyGetParser->ExpandVariable($2); + } +| cal_ATNAME { + $$ = yyGetParser->ExpandVariableForAt($1); + } EnvVarName: -MultipleIds -{ - $$ = $1; -} -| -cal_SYMBOL EnvVarName -{ - $$ = $1; -} + MultipleIds { + $$ = $1; + } +| cal_SYMBOL EnvVarName { + $$ = $1; + } MultipleIds: -{ - $$ = 0; -} -| -ID MultipleIds -{ - $$ = yyGetParser->CombineUnions($1, $2); -} + { + $$ = 0; + } +| ID MultipleIds { + $$ = yyGetParser->CombineUnions($1, $2); + } ID: -cal_NAME -{ - $$ = $1; -} -| -Variable -{ - $$ = $1; -} - + cal_NAME { + $$ = $1; + } +| Variable { + $$ = $1; + } +; %% /* End of grammar */ https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1728b9c076a34ef017f10499e5b637d025b2afd8 commit 1728b9c076a34ef017f10499e5b637d025b2afd8 Author: Daniel Pfeifer AuthorDate: Thu Feb 16 21:26:36 2017 +0100 Commit: Daniel Pfeifer CommitDate: Thu Feb 16 21:26:36 2017 +0100 cmDependsJavaParser: Port to bison 3 Use %-directives to specify the scanner/lexer arguments and update the yyerror signature. Reduce the list of post-bison modifications needed. diff --git a/Source/cmDependsJavaParser.cxx b/Source/cmDependsJavaParser.cxx index b99d631..a1beb58 100644 --- a/Source/cmDependsJavaParser.cxx +++ b/Source/cmDependsJavaParser.cxx @@ -1,12 +1,13 @@ -/* A Bison parser, made by GNU Bison 1.875d. */ +/* A Bison parser, made by GNU Bison 3.0.4. */ -/* Skeleton parser for Yacc-like parsing with Bison, Copyright (C) 1984, - 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. +/* Bison implementation for Yacc-like parsers in C - This program is free software; you can redistribute it and/or modify + Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -14,17 +15,23 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. -/* As a special exception, when this file is copied by Bison into a - Bison output file, you may use that output file without restriction. - This special exception was added by the Free Software Foundation - in version 1.24 of Bison. */ + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ -/* Written by Richard Stallman by simplifying the original so called - ``semantic'' parser. */ +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local @@ -33,145 +40,217 @@ define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ -/* turn off some warning as this is generated code */ -#if defined(_MSC_VER) -# pragma warning ( disable : 4702 ) /* unreachable code */ -#endif - /* Identify Bison output. */ #define YYBISON 1 +/* Bison version. */ +#define YYBISON_VERSION "3.0.4" + /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" /* Pure parsers. */ #define YYPURE 1 -/* Using locations. */ -#define YYLSP_NEEDED 0 +/* Push parsers. */ +#define YYPUSH 0 -/* If NAME_PREFIX is specified substitute the variables and functions - names. */ -#define yyparse cmDependsJava_yyparse -#define yylex cmDependsJava_yylex -#define yyerror cmDependsJava_yyerror -#define yylval cmDependsJava_yylval -#define yychar cmDependsJava_yychar -#define yydebug cmDependsJava_yydebug -#define yynerrs cmDependsJava_yynerrs +/* Pull parsers. */ +#define YYPULL 1 -/* Tokens. */ +/* Substitute the variable and function names. */ +#define yyparse cmDependsJava_yyparse +#define yylex cmDependsJava_yylex +#define yyerror cmDependsJava_yyerror +#define yydebug cmDependsJava_yydebug +#define yynerrs cmDependsJava_yynerrs + + +/* Copy the first part of user declarations. */ +#line 1 "cmDependsJavaParser.y" /* yacc.c:339 */ + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +/* + +This file must be translated to C and modified to build everywhere. + +Run bison like this: + + bison --yacc --name-prefix=cmDependsJava_yy --defines=cmDependsJavaParserTokens.h -ocmDependsJavaParser.cxx cmDependsJavaParser.y + +Modify cmDependsJavaParser.cxx: + - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"] + +*/ + +#define yyGetParser (cmDependsJava_yyget_extra(yyscanner)) + +/*-------------------------------------------------------------------------*/ +#include "cmDependsJavaParserHelper.h" /* Interface to parser object. */ +#include "cmDependsJavaLexer.h" /* Interface to lexer object. */ +#include "cmDependsJavaParserTokens.h" /* Need YYSTYPE for YY_DECL. */ + +/* Forward declare the lexer entry point. */ +YY_DECL; + +/* Helper function to forward error callback from parser. */ +static void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message); + +#define YYMAXDEPTH 1000000 + + +#define jpCheckEmpty(cnt) yyGetParser->CheckEmpty(__LINE__, cnt, yyvsp); +#define jpElementStart(cnt) yyGetParser->PrepareElement(&yyval) +#define jpStoreClass(str) yyGetParser->AddClassFound(str); yyGetParser->DeallocateParserType(&(str)) +/* Disable some warnings in the generated code. */ +#ifdef _MSC_VER +# pragma warning (disable: 4102) /* Unused goto label. */ +# pragma warning (disable: 4065) /* Switch statement contains default but no case. */ +#endif + +#line 114 "cmDependsJavaParser.cxx" /* yacc.c:339 */ + +# ifndef YY_NULLPTR +# if defined __cplusplus && 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif +# endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 1 +#endif + +/* In a future release of Bison, this section will be replaced + by #include "cmDependsJavaParserTokens.h". */ +#ifndef YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED +# define YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int cmDependsJava_yydebug; +#endif + +/* Token type. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - enum yytokentype { - jp_ABSTRACT = 258, - jp_ASSERT = 259, - jp_BOOLEAN_TYPE = 260, - jp_BREAK = 261, - jp_BYTE_TYPE = 262, - jp_CASE = 263, - jp_CATCH = 264, - jp_CHAR_TYPE = 265, - jp_CLASS = 266, - jp_CONTINUE = 267, - jp_DEFAULT = 268, - jp_DO = 269, - jp_DOUBLE_TYPE = 270, - jp_ELSE = 271, - jp_EXTENDS = 272, - jp_FINAL = 273, - jp_FINALLY = 274, - jp_FLOAT_TYPE = 275, - jp_FOR = 276, - jp_IF = 277, - jp_IMPLEMENTS = 278, - jp_IMPORT = 279, - jp_INSTANCEOF = 280, - jp_INT_TYPE = 281, - jp_INTERFACE = 282, - jp_LONG_TYPE = 283, - jp_NATIVE = 284, - jp_NEW = 285, - jp_PACKAGE = 286, - jp_PRIVATE = 287, - jp_PROTECTED = 288, - jp_PUBLIC = 289, - jp_RETURN = 290, - jp_SHORT_TYPE = 291, - jp_STATIC = 292, - jp_STRICTFP = 293, - jp_SUPER = 294, - jp_SWITCH = 295, - jp_SYNCHRONIZED = 296, - jp_THIS = 297, - jp_THROW = 298, - jp_THROWS = 299, - jp_TRANSIENT = 300, - jp_TRY = 301, - jp_VOID = 302, - jp_VOLATILE = 303, - jp_WHILE = 304, - jp_BOOLEANLITERAL = 305, - jp_CHARACTERLITERAL = 306, - jp_DECIMALINTEGERLITERAL = 307, - jp_FLOATINGPOINTLITERAL = 308, - jp_HEXINTEGERLITERAL = 309, - jp_NULLLITERAL = 310, - jp_STRINGLITERAL = 311, - jp_NAME = 312, - jp_AND = 313, - jp_ANDAND = 314, - jp_ANDEQUALS = 315, - jp_BRACKETEND = 316, - jp_BRACKETSTART = 317, - jp_CARROT = 318, - jp_CARROTEQUALS = 319, - jp_COLON = 320, - jp_COMMA = 321, - jp_CURLYEND = 322, - jp_CURLYSTART = 323, - jp_DIVIDE = 324, - jp_DIVIDEEQUALS = 325, - jp_DOLLAR = 326, - jp_DOT = 327, - jp_EQUALS = 328, - jp_EQUALSEQUALS = 329, - jp_EXCLAMATION = 330, - jp_EXCLAMATIONEQUALS = 331, - jp_GREATER = 332, - jp_GTEQUALS = 333, - jp_GTGT = 334, - jp_GTGTEQUALS = 335, - jp_GTGTGT = 336, - jp_GTGTGTEQUALS = 337, - jp_LESLESEQUALS = 338, - jp_LESSTHAN = 339, - jp_LTEQUALS = 340, - jp_LTLT = 341, - jp_MINUS = 342, - jp_MINUSEQUALS = 343, - jp_MINUSMINUS = 344, - jp_PAREEND = 345, - jp_PARESTART = 346, - jp_PERCENT = 347, - jp_PERCENTEQUALS = 348, - jp_PIPE = 349, - jp_PIPEEQUALS = 350, - jp_PIPEPIPE = 351, - jp_PLUS = 352, - jp_PLUSEQUALS = 353, - jp_PLUSPLUS = 354, - jp_QUESTION = 355, - jp_SEMICOL = 356, - jp_TILDE = 357, - jp_TIMES = 358, - jp_TIMESEQUALS = 359, - jp_ERROR = 360 - }; + enum yytokentype + { + jp_ABSTRACT = 258, + jp_ASSERT = 259, + jp_BOOLEAN_TYPE = 260, + jp_BREAK = 261, + jp_BYTE_TYPE = 262, + jp_CASE = 263, + jp_CATCH = 264, + jp_CHAR_TYPE = 265, + jp_CLASS = 266, + jp_CONTINUE = 267, + jp_DEFAULT = 268, + jp_DO = 269, + jp_DOUBLE_TYPE = 270, + jp_ELSE = 271, + jp_EXTENDS = 272, + jp_FINAL = 273, + jp_FINALLY = 274, + jp_FLOAT_TYPE = 275, + jp_FOR = 276, + jp_IF = 277, + jp_IMPLEMENTS = 278, + jp_IMPORT = 279, + jp_INSTANCEOF = 280, + jp_INT_TYPE = 281, + jp_INTERFACE = 282, + jp_LONG_TYPE = 283, + jp_NATIVE = 284, + jp_NEW = 285, + jp_PACKAGE = 286, + jp_PRIVATE = 287, + jp_PROTECTED = 288, + jp_PUBLIC = 289, + jp_RETURN = 290, + jp_SHORT_TYPE = 291, + jp_STATIC = 292, + jp_STRICTFP = 293, + jp_SUPER = 294, + jp_SWITCH = 295, + jp_SYNCHRONIZED = 296, + jp_THIS = 297, + jp_THROW = 298, + jp_THROWS = 299, + jp_TRANSIENT = 300, + jp_TRY = 301, + jp_VOID = 302, + jp_VOLATILE = 303, + jp_WHILE = 304, + jp_BOOLEANLITERAL = 305, + jp_CHARACTERLITERAL = 306, + jp_DECIMALINTEGERLITERAL = 307, + jp_FLOATINGPOINTLITERAL = 308, + jp_HEXINTEGERLITERAL = 309, + jp_NULLLITERAL = 310, + jp_STRINGLITERAL = 311, + jp_NAME = 312, + jp_AND = 313, + jp_ANDAND = 314, + jp_ANDEQUALS = 315, + jp_BRACKETEND = 316, + jp_BRACKETSTART = 317, + jp_CARROT = 318, + jp_CARROTEQUALS = 319, + jp_COLON = 320, + jp_COMMA = 321, + jp_CURLYEND = 322, + jp_CURLYSTART = 323, + jp_DIVIDE = 324, + jp_DIVIDEEQUALS = 325, + jp_DOLLAR = 326, + jp_DOT = 327, + jp_EQUALS = 328, + jp_EQUALSEQUALS = 329, + jp_EXCLAMATION = 330, + jp_EXCLAMATIONEQUALS = 331, + jp_GREATER = 332, + jp_GTEQUALS = 333, + jp_GTGT = 334, + jp_GTGTEQUALS = 335, + jp_GTGTGT = 336, + jp_GTGTGTEQUALS = 337, + jp_LESLESEQUALS = 338, + jp_LESSTHAN = 339, + jp_LTEQUALS = 340, + jp_LTLT = 341, + jp_MINUS = 342, + jp_MINUSEQUALS = 343, + jp_MINUSMINUS = 344, + jp_PAREEND = 345, + jp_PARESTART = 346, + jp_PERCENT = 347, + jp_PERCENTEQUALS = 348, + jp_PIPE = 349, + jp_PIPEEQUALS = 350, + jp_PIPEPIPE = 351, + jp_PLUS = 352, + jp_PLUSEQUALS = 353, + jp_PLUSPLUS = 354, + jp_QUESTION = 355, + jp_SEMICOL = 356, + jp_TILDE = 357, + jp_TIMES = 358, + jp_TIMESEQUALS = 359, + jp_ERROR = 360 + }; #endif +/* Tokens. */ #define jp_ABSTRACT 258 #define jp_ASSERT 259 #define jp_BOOLEAN_TYPE 260 @@ -276,141 +355,205 @@ #define jp_TIMESEQUALS 359 #define jp_ERROR 360 +/* Value type. */ -/* Copy the first part of user declarations. */ -#line 1 "cmDependsJavaParser.y" +int cmDependsJava_yyparse (yyscan_t yyscanner); -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -/* +#endif /* !YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED */ -This file must be translated to C and modified to build everywhere. +/* Copy the second part of user declarations. */ -Run bison like this: +#line 369 "cmDependsJavaParser.cxx" /* yacc.c:358 */ - bison --yacc --name-prefix=cmDependsJava_yy - --defines=cmDependsJavaParserTokens.h -ocmDependsJavaParser.cxx - cmDependsJavaParser.y +#ifdef short +# undef short +#endif -Modify cmDependsJavaParser.c: - - remove TABs +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif -*/ +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#else +typedef signed char yytype_int8; +#endif -/* Configure the parser to use a lexer object. */ -#define YYPARSE_PARAM yyscanner -#define YYLEX_PARAM yyscanner -#define YYERROR_VERBOSE 1 -#define cmDependsJava_yyerror(x) \ - cmDependsJavaError(yyscanner, x) -#define yyGetParser (cmDependsJava_yyget_extra(yyscanner)) +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif -/*-------------------------------------------------------------------------*/ -#include "cmDependsJavaParserHelper.h" /* Interface to parser object. */ -#include "cmDependsJavaLexer.h" /* Interface to lexer object. */ -#include "cmDependsJavaParserTokens.h" /* Need YYSTYPE for YY_DECL. */ +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif -/* Forward declare the lexer entry point. */ -YY_DECL; +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif -/* Internal utility functions. */ -static void cmDependsJavaError(yyscan_t yyscanner, const char* message); +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) -#define YYDEBUG 1 -#define YYMAXDEPTH 1000000 +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(Msgid) dgettext ("bison-runtime", Msgid) +# endif +# endif +# ifndef YY_ +# define YY_(Msgid) Msgid +# endif +#endif +#ifndef YY_ATTRIBUTE +# if (defined __GNUC__ \ + && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \ + || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C +# define YY_ATTRIBUTE(Spec) __attribute__(Spec) +# else +# define YY_ATTRIBUTE(Spec) /* empty */ +# endif +#endif -#define jpCheckEmpty(cnt) yyGetParser->CheckEmpty(__LINE__, cnt, yyvsp); -#define jpElementStart(cnt) yyGetParser->PrepareElement(&yyval) -#define jpStoreClass(str) \ -yyGetParser->AddClassFound(str); yyGetParser->DeallocateParserType(&(str)) -/* Disable some warnings in the generated code. */ -#ifdef _MSC_VER -# pragma warning (disable: 4102) /* Unused goto label. */ -# pragma warning (disable: 4065) /* Switch statement contains default but - no case. */ +#ifndef YY_ATTRIBUTE_PURE +# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__)) #endif +#ifndef YY_ATTRIBUTE_UNUSED +# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) +#endif -/* Enabling traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 +#if !defined _Noreturn \ + && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) +# if defined _MSC_VER && 1200 <= _MSC_VER +# define _Noreturn __declspec (noreturn) +# else +# define _Noreturn YY_ATTRIBUTE ((__noreturn__)) +# endif #endif -/* Enabling verbose error messages. */ -#ifdef YYERROR_VERBOSE -# undef YYERROR_VERBOSE -# define YYERROR_VERBOSE 1 +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(E) ((void) (E)) #else -# define YYERROR_VERBOSE 0 +# define YYUSE(E) /* empty */ #endif -#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) -typedef int YYSTYPE; -# define yystype YYSTYPE /* obsolescent; will be withdrawn */ -# define YYSTYPE_IS_DECLARED 1 -# define YYSTYPE_IS_TRIVIAL 1 +#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ +/* Suppress an incorrect diagnostic about yylval being uninitialized. */ +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ + _Pragma ("GCC diagnostic pop") +#else +# define YY_INITIAL_VALUE(Value) Value +#endif +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ #endif - -/* Copy the second part of user declarations. */ - - -/* Line 214 of yacc.c. */ -#line 372 "cmDependsJavaParser.cxx" - -#if ! defined (yyoverflow) || YYERROR_VERBOSE - -# ifndef YYFREE -# define YYFREE free -# endif -# ifndef YYMALLOC -# define YYMALLOC malloc -# endif +#if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ # ifdef YYSTACK_USE_ALLOCA # if YYSTACK_USE_ALLOCA -# define YYSTACK_ALLOC alloca -# endif -# else -# if defined (alloca) || defined (_ALLOCA_H) -# define YYSTACK_ALLOC alloca -# else # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS +# include /* INFRINGES ON USER NAME SPACE */ + /* Use EXIT_SUCCESS as a witness for stdlib.h. */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif # endif # endif # endif # ifdef YYSTACK_ALLOC - /* Pacify GCC's `empty if-body' warning. */ + /* Pacify GCC's 'empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) -# else -# if defined (__STDC__) || defined (__cplusplus) -# include /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ # endif +# else # define YYSTACK_ALLOC YYMALLOC # define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined EXIT_SUCCESS +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined EXIT_SUCCESS +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif # endif -#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ -#if (! defined (yyoverflow) \ - && (! defined (__cplusplus) \ - || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL))) +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { - short int yyss; - YYSTYPE yyvs; - }; + yytype_int16 yyss_alloc; + YYSTYPE yyvs_alloc; +}; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) @@ -418,74 +561,74 @@ union yyalloc /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ - ((N) * (sizeof (short int) + sizeof (YYSTYPE)) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) -/* Copy COUNT objects from FROM to TO. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined (__GNUC__) && 1 < __GNUC__ -# define YYCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) -# else -# define YYCOPY(To, From, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ - } \ - while (0) -# endif -# endif +# define YYCOPY_NEEDED 1 /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ -# define YYSTACK_RELOCATE(Stack) \ - do \ - { \ - YYSIZE_T yynewbytes; \ - YYCOPY (&yyptr->Stack, Stack, yysize); \ - Stack = &yyptr->Stack; \ - yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ - yyptr += yynewbytes / sizeof (*yyptr); \ - } \ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ while (0) #endif -#if defined (__STDC__) || defined (__cplusplus) - typedef signed char yysigned_char; -#else - typedef short int yysigned_char; -#endif +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from SRC to DST. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) +# else +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ + while (0) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ -/* YYFINAL -- State number of the termination state. */ +/* YYFINAL -- State number of the termination state. */ #define YYFINAL 23 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 2215 -/* YYNTOKENS -- Number of terminals. */ +/* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 106 -/* YYNNTS -- Number of nonterminals. */ +/* YYNNTS -- Number of nonterminals. */ #define YYNNTS 158 -/* YYNRULES -- Number of rules. */ +/* YYNRULES -- Number of rules. */ #define YYNRULES 351 -/* YYNRULES -- Number of states. */ +/* YYNSTATES -- Number of states. */ #define YYNSTATES 575 -/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned + by yylex, with out-of-bounds checking. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 360 -#define YYTRANSLATE(YYX) \ +#define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) -/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ -static const unsigned char yytranslate[] = +/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, without out-of-bounds checking. */ +static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -527,201 +670,51 @@ static const unsigned char yytranslate[] = }; #if YYDEBUG -/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in - YYRHS. */ -static const unsigned short int yyprhs[] = -{ - 0, 0, 3, 5, 7, 9, 11, 13, 15, 17, - 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, - 39, 41, 43, 45, 47, 49, 51, 54, 57, 59, - 61, 63, 65, 68, 72, 76, 80, 84, 86, 88, - 92, 93, 95, 96, 99, 100, 103, 107, 109, 111, - 115, 121, 123, 125, 127, 129, 132, 134, 136, 138, - 140, 142, 144, 146, 148, 150, 152, 154, 158, 161, - 165, 169, 174, 175, 177, 180, 183, 185, 189, 193, - 194, 197, 199, 201, 203, 205, 207, 209, 214, 216, - 220, 222, 226, 228, 232, 234, 236, 239, 242, 246, - 251, 256, 257, 259, 264, 268, 269, 271, 273, 277, - 281, 284, 286, 290, 292, 295, 300, 306, 311, 316, - 317, 320, 326, 332, 336, 340, 341, 343, 346, 350, - 354, 355, 358, 360, 362, 364, 367, 369, 372, 374, - 377, 379, 382, 386, 387, 389, 392, 394, 398, 402, - 403, 405, 407, 410, 412, 414, 416, 419, 423, 426, - 428, 430, 432, 434, 436, 438, 440, 442, 444, 446, - 448, 450, 452, 454, 456, 458, 460, 462, 464, 466, - 468, 470, 472, 474, 478, 482, 485, 487, 489, 491, - 493, 495, 497, 499, 505, 513, 521, 527, 532, 533, - 535, 536, 539, 542, 544, 547, 551, 554, 560, 566, - 574, 584, 585, 587, 588, 590, 600, 601, 603, 605, - 607, 609, 611, 615, 619, 625, 629, 630, 632, 636, - 640, 644, 650, 654, 659, 660, 662, 664, 667, 673, - 676, 678, 680, 682, 684, 688, 690, 692, 694, 696, - 703, 704, 706, 707, 709, 711, 715, 720, 725, 730, - 735, 736, 738, 740, 743, 747, 750, 754, 758, 762, - 766, 770, 775, 782, 789, 796, 801, 806, 808, 810, - 814, 816, 818, 821, 824, 826, 828, 831, 834, 836, - 839, 842, 844, 847, 850, 852, 858, 863, 869, 871, - 875, 879, 883, 885, 889, 893, 895, 899, 903, 907, - 909, 913, 917, 921, 925, 929, 931, 935, 939, 941, - 945, 947, 951, 953, 957, 959, 963, 965, 969, 971, - 977, 979, 981, 985, 987, 989, 991, 993, 995, 997, - 999, 1001, 1003, 1005, 1007, 1009, 1011, 1013, 1015, 1017, - 1019, 1021 -}; - -/* YYRHS -- A `-1'-separated list of the rules' RHS. */ -static const short int yyrhs[] = + /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ +static const yytype_uint16 yyrline[] = { - 107, 0, -1, 122, -1, 109, -1, 53, -1, 50, - -1, 51, -1, 56, -1, 55, -1, 52, -1, 54, - -1, 111, -1, 112, -1, 7, -1, 36, -1, 26, - -1, 28, -1, 10, -1, 20, -1, 15, -1, 5, - -1, 113, -1, 116, -1, 117, -1, 113, -1, 113, - -1, 111, 234, -1, 117, 234, -1, 118, -1, 120, - -1, 119, -1, 57, -1, 71, 57, -1, 117, 72, - 119, -1, 117, 72, 11, -1, 117, 72, 42, -1, - 121, 72, 11, -1, 111, -1, 47, -1, 123, 124, - 125, -1, -1, 126, -1, -1, 124, 127, -1, -1, - 125, 130, -1, 31, 117, 101, -1, 128, -1, 129, - -1, 24, 117, 101, -1, 24, 117, 72, 103, 101, - -1, 134, -1, 165, -1, 101, -1, 132, -1, 131, - 132, -1, 34, -1, 33, -1, 32, -1, 37, -1, - 3, -1, 18, -1, 29, -1, 41, -1, 45, -1, - 48, -1, 38, -1, 135, 11, 119, -1, 133, 139, - -1, 133, 137, 139, -1, 133, 136, 139, -1, 133, - 136, 137, 139, -1, -1, 131, -1, 17, 114, -1, - 23, 138, -1, 115, -1, 138, 66, 115, -1, 68, - 140, 67, -1, -1, 140, 141, -1, 142, -1, 158, - -1, 159, -1, 130, -1, 143, -1, 148, -1, 135, - 110, 144, 101, -1, 145, -1, 144, 66, 145, -1, - 146, -1, 146, 73, 147, -1, 119, -1, 146, 62, - 61, -1, 261, -1, 174, -1, 149, 101, -1, 149, - 157, -1, 149, 157, 101, -1, 135, 110, 151, 150, - -1, 135, 47, 151, 150, -1, -1, 155, -1, 119, - 91, 152, 90, -1, 151, 62, 61, -1, -1, 153, - -1, 154, -1, 153, 66, 154, -1, 135, 110, 146, - -1, 44, 156, -1, 114, -1, 156, 66, 114, -1, - 177, -1, 37, 177, -1, 135, 160, 150, 161, -1, - 135, 160, 150, 161, 101, -1, 118, 91, 152, 90, - -1, 68, 162, 178, 67, -1, -1, 162, 163, -1, - 42, 91, 228, 90, 101, -1, 39, 91, 228, 90, - 101, -1, 135, 27, 119, -1, 164, 166, 168, -1, - -1, 167, -1, 17, 115, -1, 167, 66, 115, -1, - 68, 169, 67, -1, -1, 169, 170, -1, 171, -1, - 172, -1, 134, -1, 134, 101, -1, 165, -1, 165, - 101, -1, 143, -1, 149, 173, -1, 101, -1, 173, - 101, -1, 68, 175, 67, -1, -1, 176, -1, 176, - 66, -1, 147, -1, 176, 66, 147, -1, 68, 178, - 67, -1, -1, 179, -1, 180, -1, 179, 180, -1, - 181, -1, 183, -1, 134, -1, 182, 101, -1, 131, - 110, 144, -1, 110, 144, -1, 185, -1, 187, -1, - 191, -1, 192, -1, 201, -1, 204, -1, 185, -1, - 188, -1, 193, -1, 202, -1, 207, -1, 177, -1, - 186, -1, 189, -1, 194, -1, 203, -1, 213, -1, - 215, -1, 216, -1, 218, -1, 217, -1, 219, -1, - 212, -1, 101, -1, 119, 65, 183, -1, 119, 65, - 184, -1, 190, 101, -1, 258, -1, 242, -1, 243, - -1, 239, -1, 240, -1, 236, -1, 226, -1, 22, - 91, 261, 90, 183, -1, 22, 91, 261, 90, 184, - 16, 183, -1, 22, 91, 261, 90, 184, 16, 184, - -1, 40, 91, 261, 90, 195, -1, 68, 197, 196, - 67, -1, -1, 199, -1, -1, 197, 198, -1, 199, - 179, -1, 200, -1, 199, 200, -1, 8, 262, 65, - -1, 13, 65, -1, 49, 91, 261, 90, 183, -1, - 49, 91, 261, 90, 184, -1, 14, 183, 49, 91, - 261, 90, 101, -1, 21, 91, 206, 101, 208, 101, - 205, 90, 183, -1, -1, 210, -1, -1, 209, -1, - 21, 91, 206, 101, 208, 101, 205, 90, 184, -1, - -1, 261, -1, 211, -1, 182, -1, 211, -1, 190, - -1, 211, 66, 190, -1, 4, 261, 101, -1, 4, - 261, 65, 261, 101, -1, 6, 214, 101, -1, -1, - 119, -1, 12, 214, 101, -1, 35, 208, 101, -1, - 43, 261, 101, -1, 41, 91, 261, 90, 177, -1, - 46, 177, 221, -1, 46, 177, 220, 223, -1, -1, - 221, -1, 222, -1, 221, 222, -1, 9, 91, 154, - 90, 177, -1, 19, 177, -1, 225, -1, 230, -1, - 108, -1, 42, -1, 91, 261, 90, -1, 226, -1, - 235, -1, 236, -1, 237, -1, 263, 114, 91, 228, - 90, 227, -1, -1, 139, -1, -1, 229, -1, 261, - -1, 229, 66, 261, -1, 263, 111, 232, 231, -1, - 263, 113, 232, 231, -1, 263, 111, 234, 174, -1, - 263, 113, 234, 174, -1, -1, 234, -1, 233, -1, - 232, 233, -1, 62, 261, 61, -1, 62, 61, -1, - 234, 62, 61, -1, 224, 72, 119, -1, 39, 72, - 119, -1, 42, 72, 119, -1, 224, 72, 42, -1, - 117, 91, 228, 90, -1, 224, 72, 119, 91, 228, - 90, -1, 39, 72, 119, 91, 228, 90, -1, 42, - 72, 119, 91, 228, 90, -1, 117, 62, 261, 61, - -1, 225, 62, 261, 61, -1, 224, -1, 117, -1, - 116, 72, 11, -1, 239, -1, 240, -1, 238, 99, - -1, 238, 89, -1, 242, -1, 243, -1, 97, 241, - -1, 87, 241, -1, 244, -1, 99, 241, -1, 89, - 241, -1, 238, -1, 102, 241, -1, 75, 241, -1, - 245, -1, 91, 111, 231, 90, 241, -1, 91, 261, - 90, 244, -1, 91, 117, 234, 90, 244, -1, 241, - -1, 246, 103, 241, -1, 246, 69, 241, -1, 246, - 92, 241, -1, 246, -1, 247, 97, 246, -1, 247, - 87, 246, -1, 247, -1, 248, 86, 247, -1, 248, - 79, 247, -1, 248, 81, 247, -1, 248, -1, 249, - 84, 248, -1, 249, 77, 248, -1, 249, 85, 248, - -1, 249, 78, 248, -1, 249, 25, 112, -1, 249, - -1, 250, 74, 249, -1, 250, 76, 249, -1, 250, - -1, 251, 58, 250, -1, 251, -1, 252, 63, 251, - -1, 252, -1, 253, 94, 252, -1, 253, -1, 254, - 59, 253, -1, 254, -1, 255, 96, 254, -1, 255, - -1, 255, 100, 261, 65, 256, -1, 256, -1, 258, - -1, 259, 260, 257, -1, 117, -1, 235, -1, 237, - -1, 73, -1, 104, -1, 70, -1, 93, -1, 98, - -1, 88, -1, 83, -1, 80, -1, 82, -1, 60, - -1, 64, -1, 95, -1, 257, -1, 261, -1, 30, - -1, 117, 72, 30, -1 -}; - -/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ -static const unsigned short int yyrline[] = -{ - 0, 191, 191, 200, 208, 216, 224, 232, 240, 249, - 257, 266, 274, 283, 288, 293, 298, 303, 308, 313, - 318, 324, 332, 341, 351, 360, 369, 377, 387, 393, - 400, 407, 413, 420, 429, 439, 449, 458, 466, 475, - 484, 490, 499, 505, 514, 520, 529, 541, 549, 558, - 570, 583, 591, 599, 608, 616, 625, 625, 625, 626, - 627, 627, 627, 627, 627, 627, 628, 631, 641, 650, - 659, 668, 678, 684, 693, 702, 711, 719, 728, 737, - 743, 752, 760, 768, 776, 785, 793, 802, 808, 816, - 825, 833, 842, 851, 860, 868, 877, 885, 893, 902, - 911, 921, 928, 938, 948, 955, 962, 965, 971, 981, - 991, 1001, 1007, 1017, 1027, 1037, 1046, 1056, 1067, 1077, - 1084, 1094, 1103, 1113, 1122, 1132, 1138, 1148, 1157, 1167, - 1177, 1184, 1193, 1202, 1211, 1220, 1228, 1237, 1246, 1256, - 1266, 1275, 1285, 1295, 1302, 1311, 1321, 1330, 1340, 1349, - 1356, 1366, 1375, 1385, 1394, 1403, 1413, 1423, 1432, 1442, - 1451, 1460, 1469, 1478, 1487, 1497, 1506, 1515, 1524, 1533, - 1543, 1552, 1561, 1570, 1579, 1588, 1597, 1606, 1615, 1624, - 1633, 1642, 1652, 1662, 1673, 1683, 1693, 1702, 1711, 1720, - 1729, 1738, 1747, 1757, 1767, 1777, 1787, 1794, 1801, 1808, - 1818, 1825, 1835, 1845, 1854, 1864, 1873, 1883, 1890, 1897, - 1904, 1912, 1919, 1929, 1936, 1946, 1956, 1963, 1973, 1982, - 1992, 2002, 2011, 2021, 2030, 2040, 2051, 2058, 2065, 2076, - 2086, 2096, 2106, 2115, 2125, 2132, 2142, 2151, 2161, 2168, - 2178, 2187, 2197, 2206, 2212, 2221, 2230, 2239, 2248, 2258, - 2268, 2275, 2285, 2292, 2302, 2311, 2321, 2330, 2339, 2348, - 2358, 2365, 2375, 2384, 2394, 2404, 2410, 2417, 2427, 2437, - 2447, 2458, 2468, 2479, 2489, 2500, 2510, 2520, 2529, 2538, - 2547, 2556, 2566, 2576, 2586, 2595, 2604, 2613, 2622, 2632, - 2642, 2652, 2661, 2670, 2679, 2689, 2698, 2707, 2714, 2723, - 2732, 2741, 2751, 2760, 2769, 2779, 2788, 2797, 2806, 2816, - 2825, 2834, 2843, 2852, 2861, 2871, 2880, 2889, 2899, 2908, - 2918, 2927, 2937, 2946, 2956, 2965, 2975, 2984, 2994, 3003, - 3013, 3022, 3032, 3042, 3052, 3061, 3071, 3080, 3089, 3098, - 3107, 3116, 3125, 3134, 3143, 3152, 3161, 3170, 3180, 3190, - 3200, 3209 + 0, 173, 173, 182, 190, 198, 206, 214, 222, 231, + 239, 248, 256, 265, 270, 275, 280, 285, 290, 295, + 300, 306, 314, 323, 333, 342, 351, 359, 369, 375, + 382, 389, 395, 402, 411, 421, 431, 440, 448, 457, + 466, 472, 481, 487, 496, 502, 511, 523, 531, 540, + 552, 565, 573, 581, 590, 598, 607, 607, 607, 608, + 609, 609, 609, 609, 609, 609, 610, 613, 623, 632, + 641, 650, 660, 666, 675, 684, 693, 701, 710, 719, + 725, 734, 742, 750, 758, 767, 775, 784, 790, 798, + 807, 815, 824, 833, 842, 850, 859, 867, 875, 884, + 893, 903, 910, 920, 930, 937, 944, 947, 953, 963, + 973, 983, 989, 999, 1009, 1019, 1028, 1038, 1049, 1059, + 1066, 1076, 1085, 1095, 1104, 1114, 1120, 1130, 1139, 1149, + 1159, 1166, 1175, 1184, 1193, 1202, 1210, 1219, 1228, 1238, + 1248, 1257, 1267, 1277, 1284, 1293, 1303, 1312, 1322, 1331, + 1338, 1348, 1357, 1367, 1376, 1385, 1395, 1405, 1414, 1424, + 1433, 1442, 1451, 1460, 1469, 1479, 1488, 1497, 1506, 1515, + 1525, 1534, 1543, 1552, 1561, 1570, 1579, 1588, 1597, 1606, + 1615, 1624, 1634, 1644, 1655, 1665, 1675, 1684, 1693, 1702, + 1711, 1720, 1729, 1739, 1749, 1759, 1769, 1776, 1783, 1790, + 1800, 1807, 1817, 1827, 1836, 1846, 1855, 1865, 1872, 1879, + 1886, 1894, 1901, 1911, 1918, 1928, 1938, 1945, 1955, 1964, + 1974, 1984, 1993, 2003, 2012, 2022, 2033, 2040, 2047, 2058, + 2068, 2078, 2088, 2097, 2107, 2114, 2124, 2133, 2143, 2150, + 2160, 2169, 2179, 2188, 2194, 2203, 2212, 2221, 2230, 2240, + 2250, 2257, 2267, 2274, 2284, 2293, 2303, 2312, 2321, 2330, + 2340, 2347, 2357, 2366, 2376, 2386, 2392, 2399, 2409, 2419, + 2429, 2440, 2450, 2461, 2471, 2482, 2492, 2502, 2511, 2520, + 2529, 2538, 2548, 2558, 2568, 2577, 2586, 2595, 2604, 2614, + 2624, 2634, 2643, 2652, 2661, 2671, 2680, 2689, 2696, 2705, + 2714, 2723, 2733, 2742, 2751, 2761, 2770, 2779, 2788, 2798, + 2807, 2816, 2825, 2834, 2843, 2853, 2862, 2871, 2881, 2890, + 2900, 2909, 2919, 2928, 2938, 2947, 2957, 2966, 2976, 2985, + 2995, 3004, 3014, 3024, 3034, 3043, 3053, 3062, 3071, 3080, + 3089, 3098, 3107, 3116, 3125, 3134, 3143, 3152, 3162, 3172, + 3182, 3191 }; #endif -#if YYDEBUG || YYERROR_VERBOSE -/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. - First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +#if YYDEBUG || YYERROR_VERBOSE || 1 +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { "$end", "error", "$undefined", "jp_ABSTRACT", "jp_ASSERT", @@ -798,14 +791,14 @@ static const char *const yytname[] = "ConditionalAndExpression", "ConditionalOrExpression", "ConditionalExpression", "AssignmentExpression", "Assignment", "LeftHandSide", "AssignmentOperator", "Expression", "ConstantExpression", - "New", 0 + "New", YY_NULLPTR }; #endif # ifdef YYPRINT -/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to - token YYLEX-NUM. */ -static const unsigned short int yytoknum[] = +/* YYTOKNUM[NUM] -- (External) token number corresponding to the + (internal) symbol number NUM (which must be that of a token). */ +static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, @@ -821,178 +814,19 @@ static const unsigned short int yytoknum[] = }; # endif -/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const unsigned short int yyr1[] = -{ - 0, 106, 107, 108, 108, 108, 108, 108, 108, 109, - 109, 110, 110, 111, 111, 111, 111, 111, 111, 111, - 111, 112, 112, 113, 114, 115, 116, 116, 117, 117, - 118, 119, 119, 120, 120, 120, 120, 121, 121, 122, - 123, 123, 124, 124, 125, 125, 126, 127, 127, 128, - 129, 130, 130, 130, 131, 131, 132, 132, 132, 132, - 132, 132, 132, 132, 132, 132, 132, 133, 134, 134, - 134, 134, 135, 135, 136, 137, 138, 138, 139, 140, - 140, 141, 141, 141, 141, 142, 142, 143, 144, 144, - 145, 145, 146, 146, 147, 147, 148, 148, 148, 149, - 149, 150, 150, 151, 151, 152, 152, 153, 153, 154, - 155, 156, 156, 157, 158, 159, 159, 160, 161, 162, - 162, 163, 163, 164, 165, 166, 166, 167, 167, 168, - 169, 169, 170, 170, 170, 170, 170, 170, 171, 172, - 173, 173, 174, 175, 175, 175, 176, 176, 177, 178, - 178, 179, 179, 180, 180, 180, 181, 182, 182, 183, - 183, 183, 183, 183, 183, 184, 184, 184, 184, 184, - 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, - 185, 185, 186, 187, 188, 189, 190, 190, 190, 190, - 190, 190, 190, 191, 192, 193, 194, 195, 196, 196, - 197, 197, 198, 199, 199, 200, 200, 201, 202, 203, - 204, 205, 205, 206, 206, 207, 208, 208, 209, 209, - 210, 211, 211, 212, 212, 213, 214, 214, 215, 216, - 217, 218, 219, 219, 220, 220, 221, 221, 222, 223, - 224, 224, 225, 225, 225, 225, 225, 225, 225, 226, - 227, 227, 228, 228, 229, 229, 230, 230, 230, 230, - 231, 231, 232, 232, 233, 234, 234, 235, 235, 235, - 235, 236, 236, 236, 236, 237, 237, 238, 238, 238, - 238, 238, 239, 240, 241, 241, 241, 241, 241, 242, - 243, 244, 244, 244, 244, 245, 245, 245, 246, 246, - 246, 246, 247, 247, 247, 248, 248, 248, 248, 249, - 249, 249, 249, 249, 249, 250, 250, 250, 251, 251, - 252, 252, 253, 253, 254, 254, 255, 255, 256, 256, - 257, 257, 258, 259, 259, 259, 260, 260, 260, 260, - 260, 260, 260, 260, 260, 260, 260, 260, 261, 262, - 263, 263 -}; +#define YYPACT_NINF -503 -/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ -static const unsigned char yyr2[] = -{ - 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, - 1, 1, 2, 3, 3, 3, 3, 1, 1, 3, - 0, 1, 0, 2, 0, 2, 3, 1, 1, 3, - 5, 1, 1, 1, 1, 2, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 3, 2, 3, - 3, 4, 0, 1, 2, 2, 1, 3, 3, 0, - 2, 1, 1, 1, 1, 1, 1, 4, 1, 3, - 1, 3, 1, 3, 1, 1, 2, 2, 3, 4, - 4, 0, 1, 4, 3, 0, 1, 1, 3, 3, - 2, 1, 3, 1, 2, 4, 5, 4, 4, 0, - 2, 5, 5, 3, 3, 0, 1, 2, 3, 3, - 0, 2, 1, 1, 1, 2, 1, 2, 1, 2, - 1, 2, 3, 0, 1, 2, 1, 3, 3, 0, - 1, 1, 2, 1, 1, 1, 2, 3, 2, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 3, 3, 2, 1, 1, 1, 1, - 1, 1, 1, 5, 7, 7, 5, 4, 0, 1, - 0, 2, 2, 1, 2, 3, 2, 5, 5, 7, - 9, 0, 1, 0, 1, 9, 0, 1, 1, 1, - 1, 1, 3, 3, 5, 3, 0, 1, 3, 3, - 3, 5, 3, 4, 0, 1, 1, 2, 5, 2, - 1, 1, 1, 1, 3, 1, 1, 1, 1, 6, - 0, 1, 0, 1, 1, 3, 4, 4, 4, 4, - 0, 1, 1, 2, 3, 2, 3, 3, 3, 3, - 3, 4, 6, 6, 6, 4, 4, 1, 1, 3, - 1, 1, 2, 2, 1, 1, 2, 2, 1, 2, - 2, 1, 2, 2, 1, 5, 4, 5, 1, 3, - 3, 3, 1, 3, 3, 1, 3, 3, 3, 1, - 3, 3, 3, 3, 3, 1, 3, 3, 1, 3, - 1, 3, 1, 3, 1, 3, 1, 3, 1, 5, - 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 3 -}; +#define yypact_value_is_default(Yystate) \ + (!!((Yystate) == (-503))) -/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state - STATE-NUM when YYTABLE doesn't specify something else to do. Zero - means the default is an error. */ -static const unsigned short int yydefact[] = -{ - 40, 0, 0, 2, 42, 41, 20, 13, 17, 19, - 18, 15, 16, 14, 38, 31, 0, 37, 0, 28, - 30, 29, 0, 1, 44, 32, 0, 46, 0, 0, - 72, 43, 47, 48, 34, 35, 33, 36, 0, 60, - 61, 62, 58, 57, 56, 59, 66, 63, 64, 65, - 53, 45, 73, 54, 0, 51, 0, 125, 52, 0, - 49, 55, 0, 0, 79, 0, 0, 68, 0, 0, - 0, 0, 126, 0, 24, 74, 23, 25, 76, 75, - 72, 0, 70, 69, 67, 123, 127, 130, 124, 0, - 50, 0, 59, 78, 84, 0, 80, 81, 85, 86, - 0, 82, 83, 71, 72, 128, 77, 72, 114, 38, - 0, 11, 12, 21, 22, 23, 28, 101, 96, 97, - 113, 129, 134, 0, 138, 0, 136, 131, 132, 133, - 0, 226, 226, 0, 0, 0, 350, 216, 0, 0, - 63, 243, 0, 0, 0, 5, 6, 9, 4, 10, - 8, 7, 0, 0, 0, 182, 242, 3, 0, 22, - 333, 30, 73, 155, 0, 170, 0, 72, 151, 153, - 0, 154, 159, 171, 160, 172, 0, 161, 162, 173, - 163, 174, 164, 181, 175, 176, 177, 179, 178, 180, - 277, 240, 245, 241, 246, 247, 248, 0, 189, 190, - 187, 188, 186, 0, 0, 0, 101, 92, 0, 88, - 90, 101, 0, 26, 27, 72, 0, 0, 102, 98, - 135, 140, 139, 137, 0, 0, 0, 0, 0, 37, - 0, 278, 245, 247, 291, 280, 281, 298, 284, 285, - 288, 294, 302, 305, 309, 315, 318, 320, 322, 324, - 326, 328, 330, 348, 331, 0, 227, 0, 0, 0, - 0, 213, 0, 0, 217, 0, 0, 0, 0, 0, - 234, 0, 278, 246, 248, 290, 0, 289, 92, 158, - 0, 0, 0, 252, 0, 0, 148, 152, 156, 185, - 0, 0, 283, 282, 345, 346, 338, 336, 343, 344, - 342, 341, 339, 347, 340, 337, 0, 37, 24, 0, - 72, 0, 100, 0, 87, 0, 0, 99, 265, 0, - 0, 0, 106, 107, 111, 110, 119, 115, 141, 293, - 287, 37, 278, 0, 286, 292, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 223, 225, - 228, 0, 0, 219, 221, 0, 214, 218, 0, 229, - 268, 0, 0, 269, 230, 0, 0, 232, 236, 0, - 244, 279, 0, 351, 0, 253, 254, 183, 157, 270, - 267, 0, 332, 0, 260, 262, 0, 260, 0, 252, - 0, 104, 89, 93, 143, 91, 95, 94, 266, 0, - 117, 72, 0, 72, 116, 0, 26, 27, 244, 300, - 301, 299, 304, 303, 307, 308, 306, 314, 311, 313, - 310, 312, 316, 317, 319, 321, 323, 325, 327, 0, - 0, 0, 216, 0, 0, 252, 0, 0, 252, 72, - 0, 233, 237, 0, 275, 271, 0, 252, 276, 0, - 256, 263, 261, 258, 257, 259, 0, 103, 146, 0, - 144, 109, 108, 112, 0, 243, 120, 0, 0, 0, - 296, 0, 224, 0, 0, 222, 0, 0, 0, 30, - 193, 0, 159, 166, 167, 168, 169, 0, 200, 196, - 231, 0, 0, 239, 207, 255, 0, 264, 250, 142, - 145, 252, 252, 118, 295, 297, 329, 0, 211, 213, - 0, 0, 0, 0, 273, 198, 274, 0, 272, 251, - 249, 147, 0, 0, 209, 0, 212, 220, 0, 0, - 0, 184, 194, 0, 0, 0, 201, 72, 203, 238, - 0, 0, 0, 216, 0, 0, 349, 0, 206, 197, - 202, 204, 122, 121, 210, 0, 0, 208, 205, 211, - 0, 0, 195, 0, 215 -}; +#define YYTABLE_NINF -336 -/* YYDEFGOTO[NTERM-NUM]. */ -static const short int yydefgoto[] = -{ - -1, 2, 156, 157, 158, 229, 112, 113, 75, 78, - 230, 231, 19, 20, 21, 22, 3, 4, 24, 30, - 5, 31, 32, 33, 51, 52, 53, 54, 163, 164, - 65, 66, 79, 67, 80, 96, 97, 98, 208, 209, - 210, 405, 99, 100, 217, 206, 321, 322, 323, 218, - 325, 119, 101, 102, 117, 327, 413, 476, 57, 58, - 71, 72, 88, 104, 127, 128, 129, 222, 406, 469, - 470, 165, 166, 167, 168, 169, 170, 171, 491, 172, - 173, 174, 493, 175, 176, 177, 178, 494, 179, 499, - 545, 525, 546, 547, 548, 180, 495, 181, 182, 535, - 365, 496, 263, 366, 536, 367, 183, 184, 257, 185, - 186, 187, 188, 189, 376, 377, 378, 451, 190, 191, - 232, 530, 384, 385, 193, 415, 394, 395, 214, 194, - 233, 196, 234, 235, 236, 237, 238, 239, 240, 241, - 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 203, 306, 386, 557, 204 -}; +#define yytable_value_is_error(Yytable_value) \ + 0 -/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing - STATE-NUM. */ -#define YYPACT_NINF -503 -static const short int yypact[] = + /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +static const yytype_int16 yypact[] = { 159, 1039, 236, -503, -503, -503, -503, -503, -503, -503, -503, -503, -503, -503, -503, -503, 186, -503, 56, -503, @@ -1054,8 +888,73 @@ static const short int yypact[] = 1699, 432, -503, 1699, -503 }; -/* YYPGOTO[NTERM-NUM]. */ -static const short int yypgoto[] = + /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE does not specify something else to do. Zero + means the default is an error. */ +static const yytype_uint16 yydefact[] = +{ + 40, 0, 0, 2, 42, 41, 20, 13, 17, 19, + 18, 15, 16, 14, 38, 31, 0, 37, 0, 28, + 30, 29, 0, 1, 44, 32, 0, 46, 0, 0, + 72, 43, 47, 48, 34, 35, 33, 36, 0, 60, + 61, 62, 58, 57, 56, 59, 66, 63, 64, 65, + 53, 45, 73, 54, 0, 51, 0, 125, 52, 0, + 49, 55, 0, 0, 79, 0, 0, 68, 0, 0, + 0, 0, 126, 0, 24, 74, 23, 25, 76, 75, + 72, 0, 70, 69, 67, 123, 127, 130, 124, 0, + 50, 0, 59, 78, 84, 0, 80, 81, 85, 86, + 0, 82, 83, 71, 72, 128, 77, 72, 114, 38, + 0, 11, 12, 21, 22, 23, 28, 101, 96, 97, + 113, 129, 134, 0, 138, 0, 136, 131, 132, 133, + 0, 226, 226, 0, 0, 0, 350, 216, 0, 0, + 63, 243, 0, 0, 0, 5, 6, 9, 4, 10, + 8, 7, 0, 0, 0, 182, 242, 3, 0, 22, + 333, 30, 73, 155, 0, 170, 0, 72, 151, 153, + 0, 154, 159, 171, 160, 172, 0, 161, 162, 173, + 163, 174, 164, 181, 175, 176, 177, 179, 178, 180, + 277, 240, 245, 241, 246, 247, 248, 0, 189, 190, + 187, 188, 186, 0, 0, 0, 101, 92, 0, 88, + 90, 101, 0, 26, 27, 72, 0, 0, 102, 98, + 135, 140, 139, 137, 0, 0, 0, 0, 0, 37, + 0, 278, 245, 247, 291, 280, 281, 298, 284, 285, + 288, 294, 302, 305, 309, 315, 318, 320, 322, 324, + 326, 328, 330, 348, 331, 0, 227, 0, 0, 0, + 0, 213, 0, 0, 217, 0, 0, 0, 0, 0, + 234, 0, 278, 246, 248, 290, 0, 289, 92, 158, + 0, 0, 0, 252, 0, 0, 148, 152, 156, 185, + 0, 0, 283, 282, 345, 346, 338, 336, 343, 344, + 342, 341, 339, 347, 340, 337, 0, 37, 24, 0, + 72, 0, 100, 0, 87, 0, 0, 99, 265, 0, + 0, 0, 106, 107, 111, 110, 119, 115, 141, 293, + 287, 37, 278, 0, 286, 292, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 223, 225, + 228, 0, 0, 219, 221, 0, 214, 218, 0, 229, + 268, 0, 0, 269, 230, 0, 0, 232, 236, 0, + 244, 279, 0, 351, 0, 253, 254, 183, 157, 270, + 267, 0, 332, 0, 260, 262, 0, 260, 0, 252, + 0, 104, 89, 93, 143, 91, 95, 94, 266, 0, + 117, 72, 0, 72, 116, 0, 26, 27, 244, 300, + 301, 299, 304, 303, 307, 308, 306, 314, 311, 313, + 310, 312, 316, 317, 319, 321, 323, 325, 327, 0, + 0, 0, 216, 0, 0, 252, 0, 0, 252, 72, + 0, 233, 237, 0, 275, 271, 0, 252, 276, 0, + 256, 263, 261, 258, 257, 259, 0, 103, 146, 0, + 144, 109, 108, 112, 0, 243, 120, 0, 0, 0, + 296, 0, 224, 0, 0, 222, 0, 0, 0, 30, + 193, 0, 159, 166, 167, 168, 169, 0, 200, 196, + 231, 0, 0, 239, 207, 255, 0, 264, 250, 142, + 145, 252, 252, 118, 295, 297, 329, 0, 211, 213, + 0, 0, 0, 0, 273, 198, 274, 0, 272, 251, + 249, 147, 0, 0, 209, 0, 212, 220, 0, 0, + 0, 184, 194, 0, 0, 0, 201, 72, 203, 238, + 0, 0, 0, 216, 0, 0, 349, 0, 206, 197, + 202, 204, 122, 121, 210, 0, 0, 208, 205, 211, + 0, 0, 195, 0, 215 +}; + + /* YYPGOTO[NTERM-NUM]. */ +static const yytype_int16 yypgoto[] = { -503, -503, -503, -503, -85, 2, 181, -41, -198, -45, -87, -1, 431, 14, -503, -503, -503, -503, -503, -503, @@ -1075,12 +974,31 @@ static const short int yypgoto[] = 95, 274, 350, -503, -503, 660, -503, -503 }; -/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule which - number is the opposite. If zero, do what YYDEFACT says. - If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -336 -static const short int yytable[] = + /* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int16 yydefgoto[] = +{ + -1, 2, 156, 157, 158, 229, 112, 113, 75, 78, + 230, 231, 19, 20, 21, 22, 3, 4, 24, 30, + 5, 31, 32, 33, 51, 52, 53, 54, 163, 164, + 65, 66, 79, 67, 80, 96, 97, 98, 208, 209, + 210, 405, 99, 100, 217, 206, 321, 322, 323, 218, + 325, 119, 101, 102, 117, 327, 413, 476, 57, 58, + 71, 72, 88, 104, 127, 128, 129, 222, 406, 469, + 470, 165, 166, 167, 168, 169, 170, 171, 491, 172, + 173, 174, 493, 175, 176, 177, 178, 494, 179, 499, + 545, 525, 546, 547, 548, 180, 495, 181, 182, 535, + 365, 496, 263, 366, 536, 367, 183, 184, 257, 185, + 186, 187, 188, 189, 376, 377, 378, 451, 190, 191, + 232, 530, 384, 385, 193, 415, 394, 395, 214, 194, + 233, 196, 234, 235, 236, 237, 238, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 203, 306, 386, 557, 204 +}; + + /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule whose + number is the opposite. If YYTABLE_NINF, syntax error. */ +static const yytype_int16 yytable[] = { 18, 82, 83, 17, 287, 61, 309, 56, 114, 364, 110, 363, 279, 468, 34, 108, 537, 103, 324, 107, @@ -1306,7 +1224,7 @@ static const short int yytable[] = 0, 0, 0, 0, 0, 305 }; -static const short int yycheck[] = +static const yytype_int16 yycheck[] = { 1, 65, 66, 1, 167, 52, 204, 30, 95, 261, 95, 261, 158, 404, 11, 92, 518, 81, 216, 68, @@ -1532,9 +1450,9 @@ static const short int yycheck[] = -1, -1, -1, -1, -1, 104 }; -/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing - symbol of state STATE-NUM. */ -static const unsigned short int yystos[] = + /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint16 yystos[] = { 0, 31, 107, 122, 123, 126, 5, 7, 10, 15, 20, 26, 28, 36, 47, 57, 71, 111, 117, 118, @@ -1596,78 +1514,123 @@ static const unsigned short int yystos[] = 16, 205, 184, 90, 184 }; -#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) -# define YYSIZE_T __SIZE_TYPE__ -#endif -#if ! defined (YYSIZE_T) && defined (size_t) -# define YYSIZE_T size_t -#endif -#if ! defined (YYSIZE_T) -# if defined (__STDC__) || defined (__cplusplus) -# include /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t -# endif -#endif -#if ! defined (YYSIZE_T) -# define YYSIZE_T unsigned int -#endif - -#define yyerrok (yyerrstatus = 0) -#define yyclearin (yychar = YYEMPTY) -#define YYEMPTY (-2) -#define YYEOF 0 + /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint16 yyr1[] = +{ + 0, 106, 107, 108, 108, 108, 108, 108, 108, 109, + 109, 110, 110, 111, 111, 111, 111, 111, 111, 111, + 111, 112, 112, 113, 114, 115, 116, 116, 117, 117, + 118, 119, 119, 120, 120, 120, 120, 121, 121, 122, + 123, 123, 124, 124, 125, 125, 126, 127, 127, 128, + 129, 130, 130, 130, 131, 131, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 132, 133, 134, 134, + 134, 134, 135, 135, 136, 137, 138, 138, 139, 140, + 140, 141, 141, 141, 141, 142, 142, 143, 144, 144, + 145, 145, 146, 146, 147, 147, 148, 148, 148, 149, + 149, 150, 150, 151, 151, 152, 152, 153, 153, 154, + 155, 156, 156, 157, 158, 159, 159, 160, 161, 162, + 162, 163, 163, 164, 165, 166, 166, 167, 167, 168, + 169, 169, 170, 170, 170, 170, 170, 170, 171, 172, + 173, 173, 174, 175, 175, 175, 176, 176, 177, 178, + 178, 179, 179, 180, 180, 180, 181, 182, 182, 183, + 183, 183, 183, 183, 183, 184, 184, 184, 184, 184, + 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 186, 187, 188, 189, 190, 190, 190, 190, + 190, 190, 190, 191, 192, 193, 194, 195, 196, 196, + 197, 197, 198, 199, 199, 200, 200, 201, 202, 203, + 204, 205, 205, 206, 206, 207, 208, 208, 209, 209, + 210, 211, 211, 212, 212, 213, 214, 214, 215, 216, + 217, 218, 219, 219, 220, 220, 221, 221, 222, 223, + 224, 224, 225, 225, 225, 225, 225, 225, 225, 226, + 227, 227, 228, 228, 229, 229, 230, 230, 230, 230, + 231, 231, 232, 232, 233, 234, 234, 235, 235, 235, + 235, 236, 236, 236, 236, 237, 237, 238, 238, 238, + 238, 238, 239, 240, 241, 241, 241, 241, 241, 242, + 243, 244, 244, 244, 244, 245, 245, 245, 246, 246, + 246, 246, 247, 247, 247, 248, 248, 248, 248, 249, + 249, 249, 249, 249, 249, 250, 250, 250, 251, 251, + 252, 252, 253, 253, 254, 254, 255, 255, 256, 256, + 257, 257, 258, 259, 259, 259, 260, 260, 260, 260, + 260, 260, 260, 260, 260, 260, 260, 260, 261, 262, + 263, 263 +}; + + /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, + 1, 1, 2, 3, 3, 3, 3, 1, 1, 3, + 0, 1, 0, 2, 0, 2, 3, 1, 1, 3, + 5, 1, 1, 1, 1, 2, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 3, 2, 3, + 3, 4, 0, 1, 2, 2, 1, 3, 3, 0, + 2, 1, 1, 1, 1, 1, 1, 4, 1, 3, + 1, 3, 1, 3, 1, 1, 2, 2, 3, 4, + 4, 0, 1, 4, 3, 0, 1, 1, 3, 3, + 2, 1, 3, 1, 2, 4, 5, 4, 4, 0, + 2, 5, 5, 3, 3, 0, 1, 2, 3, 3, + 0, 2, 1, 1, 1, 2, 1, 2, 1, 2, + 1, 2, 3, 0, 1, 2, 1, 3, 3, 0, + 1, 1, 2, 1, 1, 1, 2, 3, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 3, 3, 2, 1, 1, 1, 1, + 1, 1, 1, 5, 7, 7, 5, 4, 0, 1, + 0, 2, 2, 1, 2, 3, 2, 5, 5, 7, + 9, 0, 1, 0, 1, 9, 0, 1, 1, 1, + 1, 1, 3, 3, 5, 3, 0, 1, 3, 3, + 3, 5, 3, 4, 0, 1, 1, 2, 5, 2, + 1, 1, 1, 1, 3, 1, 1, 1, 1, 6, + 0, 1, 0, 1, 1, 3, 4, 4, 4, 4, + 0, 1, 1, 2, 3, 2, 3, 3, 3, 3, + 3, 4, 6, 6, 6, 4, 4, 1, 1, 3, + 1, 1, 2, 2, 1, 1, 2, 2, 1, 2, + 2, 1, 2, 2, 1, 5, 4, 5, 1, 3, + 3, 3, 1, 3, 3, 1, 3, 3, 3, 1, + 3, 3, 3, 3, 3, 1, 3, 3, 1, 3, + 1, 3, 1, 3, 1, 3, 1, 3, 1, 5, + 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 3 +}; -#define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab -#define YYERROR goto yyerrorlab +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 -/* Like YYERROR except do call yyerror. This remains here temporarily - to ease the transition to the new meaning of YYERROR, for GCC. - Once GCC version 2 has supplanted version 1, this can go. */ +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab -#define YYFAIL goto yyerrlab #define YYRECOVERING() (!!yyerrstatus) -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY && yylen == 1) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - yytoken = YYTRANSLATE (yychar); \ - YYPOPSTACK; \ - goto yybackup; \ - } \ - else \ - { \ - yyerror ("syntax error: cannot back up");\ - YYERROR; \ - } \ +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (yyscanner, YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ while (0) -#define YYTERROR 1 -#define YYERRCODE 256 +/* Error token number */ +#define YYTERROR 1 +#define YYERRCODE 256 -/* YYLLOC_DEFAULT -- Compute the default location (before the actions - are run). */ -#ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - ((Current).first_line = (Rhs)[1].first_line, \ - (Current).first_column = (Rhs)[1].first_column, \ - (Current).last_line = (Rhs)[N].last_line, \ - (Current).last_column = (Rhs)[N].last_column) -#endif - -/* YYLEX -- calling `yylex' with the right arguments. */ - -#ifdef YYLEX_PARAM -# define YYLEX yylex (&yylval, YYLEX_PARAM) -#else -# define YYLEX yylex (&yylval) -#endif /* Enable debugging if requested. */ #if YYDEBUG @@ -1677,54 +1640,85 @@ while (0) # define YYFPRINTF fprintf # endif -# define YYDPRINTF(Args) \ -do { \ - if (yydebug) \ - YYFPRINTF Args; \ +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ } while (0) -# define YYDSYMPRINT(Args) \ -do { \ - if (yydebug) \ - yysymprint Args; \ -} while (0) +/* This macro is provided for backward compatibility. */ +#ifndef YY_LOCATION_PRINT +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +#endif + -# define YYDSYMPRINTF(Title, Token, Value, Location) \ -do { \ - if (yydebug) \ - { \ - YYFPRINTF (stderr, "%s ", Title); \ - yysymprint (stderr, \ - Token, Value); \ - YYFPRINTF (stderr, "\n"); \ - } \ +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value, yyscanner); \ + YYFPRINTF (stderr, "\n"); \ + } \ } while (0) + +/*----------------------------------------. +| Print this symbol's value on YYOUTPUT. | +`----------------------------------------*/ + +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) +{ + FILE *yyo = yyoutput; + YYUSE (yyo); + YYUSE (yyscanner); + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# endif + YYUSE (yytype); +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) +{ + YYFPRINTF (yyoutput, "%s %s (", + yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); + + yy_symbol_value_print (yyoutput, yytype, yyvaluep, yyscanner); + YYFPRINTF (yyoutput, ")"); +} + /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | | TOP (included). | `------------------------------------------------------------------*/ -#if defined (__STDC__) || defined (__cplusplus) static void -yy_stack_print (short int *bottom, short int *top) -#else -static void -yy_stack_print (bottom, top) - short int *bottom; - short int *top; -#endif +yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) { YYFPRINTF (stderr, "Stack now"); - for (/* Nothing. */; bottom <= top; ++bottom) - YYFPRINTF (stderr, " %d", *bottom); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } YYFPRINTF (stderr, "\n"); } -# define YY_STACK_PRINT(Bottom, Top) \ -do { \ - if (yydebug) \ - yy_stack_print ((Bottom), (Top)); \ +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ } while (0) @@ -1732,29 +1726,30 @@ do { \ | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ -#if defined (__STDC__) || defined (__cplusplus) -static void -yy_reduce_print (int yyrule) -#else static void -yy_reduce_print (yyrule) - int yyrule; -#endif +yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner) { + unsigned long int yylno = yyrline[yyrule]; + int yynrhs = yyr2[yyrule]; int yyi; - unsigned int yylno = yyrline[yyrule]; - YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ", + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", yyrule - 1, yylno); - /* Print the symbols being reduced, and their result. */ - for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++) - YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]); - YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, + yystos[yyssp[yyi + 1 - yynrhs]], + &(yyvsp[(yyi + 1) - (yynrhs)]) + , yyscanner); + YYFPRINTF (stderr, "\n"); + } } -# define YY_REDUCE_PRINT(Rule) \ -do { \ - if (yydebug) \ - yy_reduce_print (Rule); \ +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyssp, yyvsp, Rule, yyscanner); \ } while (0) /* Nonzero means print parse trace. It is left uninitialized so that @@ -1762,15 +1757,14 @@ do { \ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) -# define YYDSYMPRINT(Args) -# define YYDSYMPRINTF(Title, Token, Value, Location) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ /* YYINITDEPTH -- initial size of the parser's stacks. */ -#ifndef YYINITDEPTH +#ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif @@ -1778,58 +1772,40 @@ int yydebug; if the built-in stack extension method is used). Do not make this value too large; the results are undefined if - SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ -#if defined (YYMAXDEPTH) && YYMAXDEPTH == 0 -# undef YYMAXDEPTH -#endif - #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif - #if YYERROR_VERBOSE # ifndef yystrlen -# if defined (__GLIBC__) && defined (_STRING_H) +# if defined __GLIBC__ && defined _STRING_H # define yystrlen strlen # else /* Return the length of YYSTR. */ static YYSIZE_T -# if defined (__STDC__) || defined (__cplusplus) yystrlen (const char *yystr) -# else -yystrlen (yystr) - const char *yystr; -# endif { - const char *yys = yystr; - - while (*yys++ != '\0') + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) continue; - - return yys - yystr - 1; + return yylen; } # endif # endif # ifndef yystpcpy -# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE # define yystpcpy stpcpy # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ static char * -# if defined (__STDC__) || defined (__cplusplus) yystpcpy (char *yydest, const char *yysrc) -# else -yystpcpy (yydest, yysrc) - char *yydest; - const char *yysrc; -# endif { char *yyd = yydest; const char *yys = yysrc; @@ -1842,91 +1818,207 @@ yystpcpy (yydest, yysrc) # endif # endif -#endif /* !YYERROR_VERBOSE */ +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; - + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } -#if YYDEBUG -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ + if (! yyres) + return yystrlen (yystr); -#if defined (__STDC__) || defined (__cplusplus) -static void -yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep) -#else -static void -yysymprint (yyoutput, yytype, yyvaluep) - FILE *yyoutput; - int yytype; - YYSTYPE *yyvaluep; -#endif + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message + about the unexpected token YYTOKEN for the state stack whose top is + YYSSP. + + Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is + not large enough to hold the message. In that case, also set + *YYMSG_ALLOC to the required number of bytes. Return 2 if the + required number of bytes is too large to store. */ +static int +yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, + yytype_int16 *yyssp, int yytoken) { - /* Pacify ``unused variable'' warnings. */ - (void) yyvaluep; + YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]); + YYSIZE_T yysize = yysize0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + /* Internationalized format string. */ + const char *yyformat = YY_NULLPTR; + /* Arguments of yyformat. */ + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + /* Number of reported tokens (one for the "unexpected", one per + "expected"). */ + int yycount = 0; + + /* There are many possibilities here to consider: + - If this state is a consistent state with a default action, then + the only way this function was invoked is if the default action + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yychar) is if + this state is a consistent state with a default action. Thus, + detecting the absence of a lookahead is sufficient to determine + that there is no unexpected or expected token to report. In that + case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is a + consistent state with a default action. There might have been a + previous inconsistent state, consistent state with a non-default + action, or user semantic action that manipulated yychar. + - Of course, the expected token list depends on states to have + correct lookahead information, and it depends on the parser not + to perform extra reductions after fetching a lookahead from the + scanner and before detecting a syntax error. Thus, state merging + (from LALR or IELR) and default reductions corrupt the expected + token list. However, the list is correct for canonical LR with + one exception: it will still contain any token that will not be + accepted due to an error action in a later state. + */ + if (yytoken != YYEMPTY) + { + int yyn = yypact[*yyssp]; + yyarg[yycount++] = yytname[yytoken]; + if (!yypact_value_is_default (yyn)) + { + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. In other words, skip the first -YYN actions for + this state because they are default actions. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yyx; + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR + && !yytable_value_is_error (yytable[yyx + yyn])) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + break; + } + yyarg[yycount++] = yytname[yyx]; + { + YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + } + } + } - if (yytype < YYNTOKENS) - { - YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); -# ifdef YYPRINT - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); -# endif + switch (yycount) + { +# define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + YYCASE_(0, YY_("syntax error")); + YYCASE_(1, YY_("syntax error, unexpected %s")); + YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); + YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); + YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); + YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +# undef YYCASE_ } - else - YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); - switch (yytype) + { + YYSIZE_T yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + + if (*yymsg_alloc < yysize) { - default: - break; + *yymsg_alloc = 2 * yysize; + if (! (yysize <= *yymsg_alloc + && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) + *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; + return 1; } - YYFPRINTF (yyoutput, ")"); + + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + { + char *yyp = *yymsg; + int yyi = 0; + while ((*yyp = *yyformat) != '\0') + if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyformat += 2; + } + else + { + yyp++; + yyformat++; + } + } + return 0; } +#endif /* YYERROR_VERBOSE */ -#endif /* ! YYDEBUG */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ -#if defined (__STDC__) || defined (__cplusplus) -static void -yydestruct (int yytype, YYSTYPE *yyvaluep) -#else static void -yydestruct (yytype, yyvaluep) - int yytype; - YYSTYPE *yyvaluep; -#endif +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, yyscan_t yyscanner) { - /* Pacify ``unused variable'' warnings. */ - (void) yyvaluep; - - switch (yytype) - { + YYUSE (yyvaluep); + YYUSE (yyscanner); + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); - default: - break; - } + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YYUSE (yytype); + YY_IGNORE_MAYBE_UNINITIALIZED_END } - - -/* Prevent warnings from -Wmissing-prototypes. */ - -#ifdef YYPARSE_PARAM -# if defined (__STDC__) || defined (__cplusplus) -int yyparse (void *YYPARSE_PARAM); -# else -int yyparse (); -# endif -#else /* ! YYPARSE_PARAM */ -#if defined (__STDC__) || defined (__cplusplus) -int yyparse (void); -#else -int yyparse (); -#endif -#endif /* ! YYPARSE_PARAM */ - - @@ -1935,90 +2027,76 @@ int yyparse (); | yyparse. | `----------*/ -#ifdef YYPARSE_PARAM -# if defined (__STDC__) || defined (__cplusplus) -int yyparse (void *YYPARSE_PARAM) -# else -int yyparse (YYPARSE_PARAM) - void *YYPARSE_PARAM; -# endif -#else /* ! YYPARSE_PARAM */ -#if defined (__STDC__) || defined (__cplusplus) -int -yyparse (void) -#else int -yyparse () - -#endif -#endif +yyparse (yyscan_t yyscanner) { - /* The lookahead symbol. */ +/* The lookahead symbol. */ int yychar; -/* The semantic value of the lookahead symbol. */ -YYSTYPE yylval; - -/* Number of syntax errors so far. */ -int yynerrs; - - int yystate; - int yyn; - int yyresult; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; - /* Lookahead token as an internal (translated) token number. */ - int yytoken = 0; - /* Three stacks and their tools: - `yyss': related to states, - `yyvs': related to semantic values, - `yyls': related to locations. +/* The semantic value of the lookahead symbol. */ +/* Default value used for initialization, for pacifying older GCCs + or non-GCC compilers. */ +YY_INITIAL_VALUE (static YYSTYPE yyval_default;) +YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); - Refer to the stacks thru separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ + /* Number of syntax errors so far. */ + int yynerrs; - /* The state stack. */ - short int yyssa[YYINITDEPTH]; - short int *yyss = yyssa; - short int *yyssp; + int yystate; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; - /* The semantic value stack. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs = yyvsa; - YYSTYPE *yyvsp; + /* The stacks and their tools: + 'yyss': related to states. + 'yyvs': related to semantic values. + Refer to the stacks through separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss; + yytype_int16 *yyssp; -#define YYPOPSTACK (yyvsp--, yyssp--) + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs; + YYSTYPE *yyvsp; - YYSIZE_T yystacksize = YYINITDEPTH; + YYSIZE_T yystacksize; + int yyn; + int yyresult; + /* Lookahead token as an internal (translated) token number. */ + int yytoken = 0; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; - /* When reducing, the number of symbols on the RHS of the reduced - rule. */ - int yylen; + yyssp = yyss = yyssa; + yyvsp = yyvs = yyvsa; + yystacksize = YYINITDEPTH; YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; - yychar = YYEMPTY; /* Cause a token to be read. */ - - /* Initialize stack pointers. - Waste one element of value and location stack - so that they stay on the same level as the state stack. - The wasted elements are never initialized. */ - - yyssp = yyss; - yyvsp = yyvs; - - + yychar = YYEMPTY; /* Cause a token to be read. */ goto yysetstate; /*------------------------------------------------------------. @@ -2026,8 +2104,7 @@ int yynerrs; `------------------------------------------------------------*/ yynewstate: /* In all cases, when you get here, the value and location stacks - have just been pushed. so pushing a state here evens the stacks. - */ + have just been pushed. So pushing a state here evens the stacks. */ yyssp++; yysetstate: @@ -2040,49 +2117,46 @@ int yynerrs; #ifdef yyoverflow { - /* Give user a chance to reallocate the stack. Use copies of - these so that the &'s don't force the real ones into - memory. */ - YYSTYPE *yyvs1 = yyvs; - short int *yyss1 = yyss; - - - /* Each stack pointer address is followed by the size of the - data in use in that stack, in bytes. This used to be a - conditional around just the two extra args, but that might - be undefined if yyoverflow is a macro. */ - yyoverflow ("parser stack overflow", - &yyss1, yysize * sizeof (*yyssp), - &yyvs1, yysize * sizeof (*yyvsp), - - &yystacksize); - - yyss = yyss1; - yyvs = yyvs1; + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE - goto yyoverflowlab; + goto yyexhaustedlab; # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) - goto yyoverflowlab; + goto yyexhaustedlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) - yystacksize = YYMAXDEPTH; + yystacksize = YYMAXDEPTH; { - short int *yyss1 = yyss; - union yyalloc *yyptr = - (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); - if (! yyptr) - goto yyoverflowlab; - YYSTACK_RELOCATE (yyss); - YYSTACK_RELOCATE (yyvs); - + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); # undef YYSTACK_RELOCATE - if (yyss1 != yyssa) - YYSTACK_FREE (yyss1); + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); } # endif #endif /* no yyoverflow */ @@ -2090,16 +2164,18 @@ int yynerrs; yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; - YYDPRINTF ((stderr, "Stack size increased to %lu\n", - (unsigned long int) yystacksize)); + (unsigned long int) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) - YYABORT; + YYABORT; } YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + if (yystate == YYFINAL) + YYACCEPT; + goto yybackup; /*-----------. @@ -2107,14 +2183,12 @@ int yynerrs; `-----------*/ yybackup: -/* Do appropriate processing given the current state. */ -/* Read a lookahead token if we need one and don't already have one. */ -/* yyresume: */ + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ /* First try to decide what to do without reference to lookahead token. */ - yyn = yypact[yystate]; - if (yyn == YYPACT_NINF) + if (yypact_value_is_default (yyn)) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ @@ -2123,7 +2197,7 @@ yybackup: if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); - yychar = YYLEX; + yychar = yylex (&yylval, yyscanner); } if (yychar <= YYEOF) @@ -2134,7 +2208,7 @@ yybackup: else { yytoken = YYTRANSLATE (yychar); - YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to @@ -2145,31 +2219,28 @@ yybackup: yyn = yytable[yyn]; if (yyn <= 0) { - if (yyn == 0 || yyn == YYTABLE_NINF) - goto yyerrlab; + if (yytable_value_is_error (yyn)) + goto yyerrlab; yyn = -yyn; goto yyreduce; } - if (yyn == YYFINAL) - YYACCEPT; - - /* Shift the lookahead token. */ - YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken])); - - /* Discard the token being shifted unless it is eof. */ - if (yychar != YYEOF) - yychar = YYEMPTY; - - *++yyvsp = yylval; - - /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token. */ + yychar = YYEMPTY; + yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + goto yynewstate; @@ -2191,7 +2262,7 @@ yyreduce: yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: - `$$ = $1'. + '$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison @@ -2205,3581 +2276,3927 @@ yyreduce: switch (yyn) { case 2: -#line 192 "cmDependsJavaParser.y" +#line 174 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2287 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 3: -#line 201 "cmDependsJavaParser.y" +#line 183 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2298 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 4: -#line 209 "cmDependsJavaParser.y" +#line 191 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2309 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 5: -#line 217 "cmDependsJavaParser.y" +#line 199 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2320 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 6: -#line 225 "cmDependsJavaParser.y" +#line 207 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2331 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 7: -#line 233 "cmDependsJavaParser.y" +#line 215 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2342 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 8: -#line 241 "cmDependsJavaParser.y" +#line 223 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2353 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 9: -#line 250 "cmDependsJavaParser.y" +#line 232 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2364 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 10: -#line 258 "cmDependsJavaParser.y" +#line 240 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2375 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 11: -#line 267 "cmDependsJavaParser.y" +#line 249 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2386 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 12: -#line 275 "cmDependsJavaParser.y" +#line 257 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2397 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 13: -#line 284 "cmDependsJavaParser.y" +#line 266 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } +#line 2405 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 14: -#line 289 "cmDependsJavaParser.y" +#line 271 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } +#line 2413 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 15: -#line 294 "cmDependsJavaParser.y" +#line 276 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } +#line 2421 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 16: -#line 299 "cmDependsJavaParser.y" +#line 281 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } +#line 2429 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 17: -#line 304 "cmDependsJavaParser.y" +#line 286 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } +#line 2437 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 18: -#line 309 "cmDependsJavaParser.y" +#line 291 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } +#line 2445 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 19: -#line 314 "cmDependsJavaParser.y" +#line 296 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } +#line 2453 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 20: -#line 319 "cmDependsJavaParser.y" +#line 301 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } +#line 2461 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 21: -#line 325 "cmDependsJavaParser.y" +#line 307 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2472 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 22: -#line 333 "cmDependsJavaParser.y" +#line 315 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2483 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 23: -#line 342 "cmDependsJavaParser.y" +#line 324 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); - jpStoreClass(yyvsp[0].str); + jpStoreClass((yyvsp[0].str)); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2495 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 24: -#line 352 "cmDependsJavaParser.y" +#line 334 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2506 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 25: -#line 361 "cmDependsJavaParser.y" +#line 343 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2517 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 26: -#line 370 "cmDependsJavaParser.y" +#line 352 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2528 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 27: -#line 378 "cmDependsJavaParser.y" +#line 360 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); - jpStoreClass(yyvsp[-1].str); + jpStoreClass((yyvsp[-1].str)); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2540 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 28: -#line 388 "cmDependsJavaParser.y" +#line 370 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); - yyval.str = yyvsp[0].str; + (yyval.str) = (yyvsp[0].str); } +#line 2549 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 29: -#line 394 "cmDependsJavaParser.y" +#line 376 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); - yyval.str = yyvsp[0].str; + (yyval.str) = (yyvsp[0].str); } +#line 2558 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 30: -#line 401 "cmDependsJavaParser.y" +#line 383 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); - yyval.str = yyvsp[0].str; + (yyval.str) = (yyvsp[0].str); } +#line 2567 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 31: -#line 408 "cmDependsJavaParser.y" +#line 390 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); - yyval.str = yyvsp[0].str; + (yyval.str) = (yyvsp[0].str); } +#line 2576 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 32: -#line 414 "cmDependsJavaParser.y" +#line 396 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); - yyval.str = yyvsp[0].str; + (yyval.str) = (yyvsp[0].str); } +#line 2585 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 33: -#line 421 "cmDependsJavaParser.y" +#line 403 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); - yyGetParser->AddClassFound(yyvsp[-2].str); - yyGetParser->UpdateCombine(yyvsp[-2].str, yyvsp[0].str); - yyGetParser->DeallocateParserType(&(yyvsp[-2].str)); - yyval.str = const_cast(yyGetParser->GetCurrentCombine()); + yyGetParser->AddClassFound((yyvsp[-2].str)); + yyGetParser->UpdateCombine((yyvsp[-2].str), (yyvsp[0].str)); + yyGetParser->DeallocateParserType(&((yyvsp[-2].str))); + (yyval.str) = const_cast(yyGetParser->GetCurrentCombine()); } +#line 2597 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 34: -#line 430 "cmDependsJavaParser.y" +#line 412 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); - jpStoreClass(yyvsp[-2].str); + jpStoreClass((yyvsp[-2].str)); jpCheckEmpty(3); yyGetParser->SetCurrentCombine(""); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2610 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 35: -#line 440 "cmDependsJavaParser.y" +#line 422 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); - jpStoreClass(yyvsp[-2].str); + jpStoreClass((yyvsp[-2].str)); yyGetParser->SetCurrentCombine(""); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2623 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 36: -#line 450 "cmDependsJavaParser.y" +#line 432 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2634 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 37: -#line 459 "cmDependsJavaParser.y" +#line 441 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2645 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 38: -#line 467 "cmDependsJavaParser.y" +#line 449 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2656 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 39: -#line 476 "cmDependsJavaParser.y" +#line 458 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2667 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 40: -#line 484 "cmDependsJavaParser.y" +#line 466 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2677 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 41: -#line 491 "cmDependsJavaParser.y" +#line 473 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2688 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 42: -#line 499 "cmDependsJavaParser.y" +#line 481 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2698 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 43: -#line 506 "cmDependsJavaParser.y" +#line 488 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2709 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 44: -#line 514 "cmDependsJavaParser.y" +#line 496 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2719 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 45: -#line 521 "cmDependsJavaParser.y" +#line 503 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2730 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 46: -#line 530 "cmDependsJavaParser.y" +#line 512 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); - yyGetParser->SetCurrentPackage(yyvsp[-1].str); - yyGetParser->DeallocateParserType(&(yyvsp[-1].str)); + yyGetParser->SetCurrentPackage((yyvsp[-1].str)); + yyGetParser->DeallocateParserType(&((yyvsp[-1].str))); yyGetParser->SetCurrentCombine(""); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2744 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 47: -#line 542 "cmDependsJavaParser.y" +#line 524 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2755 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 48: -#line 550 "cmDependsJavaParser.y" +#line 532 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2766 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 49: -#line 559 "cmDependsJavaParser.y" +#line 541 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); - yyGetParser->AddPackagesImport(yyvsp[-1].str); - yyGetParser->DeallocateParserType(&(yyvsp[-1].str)); + yyGetParser->AddPackagesImport((yyvsp[-1].str)); + yyGetParser->DeallocateParserType(&((yyvsp[-1].str))); yyGetParser->SetCurrentCombine(""); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2780 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 50: -#line 571 "cmDependsJavaParser.y" +#line 553 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); - std::string str = yyvsp[-3].str; + std::string str = (yyvsp[-3].str); str += ".*"; yyGetParser->AddPackagesImport(str.c_str()); - yyGetParser->DeallocateParserType(&(yyvsp[-3].str)); + yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); yyGetParser->SetCurrentCombine(""); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2795 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 51: -#line 584 "cmDependsJavaParser.y" +#line 566 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2806 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 52: -#line 592 "cmDependsJavaParser.y" +#line 574 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2817 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 53: -#line 600 "cmDependsJavaParser.y" +#line 582 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2828 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 54: -#line 609 "cmDependsJavaParser.y" +#line 591 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2839 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 55: -#line 617 "cmDependsJavaParser.y" +#line 599 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2850 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 67: -#line 632 "cmDependsJavaParser.y" +#line 614 "cmDependsJavaParser.y" /* yacc.c:1646 */ { - yyGetParser->StartClass(yyvsp[0].str); + yyGetParser->StartClass((yyvsp[0].str)); jpElementStart(3); - yyGetParser->DeallocateParserType(&(yyvsp[0].str)); + yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(3); } +#line 2861 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 68: -#line 642 "cmDependsJavaParser.y" +#line 624 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } +#line 2873 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 69: -#line 651 "cmDependsJavaParser.y" +#line 633 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } +#line 2885 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 70: -#line 660 "cmDependsJavaParser.y" +#line 642 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } +#line 2897 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 71: -#line 669 "cmDependsJavaParser.y" +#line 651 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } +#line 2909 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 72: -#line 678 "cmDependsJavaParser.y" +#line 660 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2919 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 73: -#line 685 "cmDependsJavaParser.y" +#line 667 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2930 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 74: -#line 694 "cmDependsJavaParser.y" +#line 676 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2941 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 75: -#line 703 "cmDependsJavaParser.y" +#line 685 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2952 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 76: -#line 712 "cmDependsJavaParser.y" +#line 694 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2963 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 77: -#line 720 "cmDependsJavaParser.y" +#line 702 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2974 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 78: -#line 729 "cmDependsJavaParser.y" +#line 711 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2985 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 79: -#line 737 "cmDependsJavaParser.y" +#line 719 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 2995 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 80: -#line 744 "cmDependsJavaParser.y" +#line 726 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3006 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 81: -#line 753 "cmDependsJavaParser.y" +#line 735 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3017 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 82: -#line 761 "cmDependsJavaParser.y" +#line 743 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3028 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 83: -#line 769 "cmDependsJavaParser.y" +#line 751 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3039 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 84: -#line 777 "cmDependsJavaParser.y" +#line 759 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3050 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 85: -#line 786 "cmDependsJavaParser.y" +#line 768 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3061 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 86: -#line 794 "cmDependsJavaParser.y" +#line 776 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3072 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 87: -#line 803 "cmDependsJavaParser.y" +#line 785 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); } +#line 3080 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 88: -#line 809 "cmDependsJavaParser.y" +#line 791 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3091 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 89: -#line 817 "cmDependsJavaParser.y" +#line 799 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3102 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 90: -#line 826 "cmDependsJavaParser.y" +#line 808 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3113 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 91: -#line 834 "cmDependsJavaParser.y" +#line 816 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3124 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 92: -#line 843 "cmDependsJavaParser.y" +#line 825 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); - yyGetParser->DeallocateParserType(&(yyvsp[0].str)); + yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3136 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 93: -#line 852 "cmDependsJavaParser.y" +#line 834 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3147 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 94: -#line 861 "cmDependsJavaParser.y" +#line 843 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3158 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 95: -#line 869 "cmDependsJavaParser.y" +#line 851 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3169 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 96: -#line 878 "cmDependsJavaParser.y" +#line 860 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3180 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 97: -#line 886 "cmDependsJavaParser.y" +#line 868 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3191 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 98: -#line 894 "cmDependsJavaParser.y" +#line 876 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3202 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 99: -#line 903 "cmDependsJavaParser.y" +#line 885 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3214 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 100: -#line 912 "cmDependsJavaParser.y" +#line 894 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3226 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 101: -#line 921 "cmDependsJavaParser.y" +#line 903 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3237 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 102: -#line 929 "cmDependsJavaParser.y" +#line 911 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3249 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 103: -#line 939 "cmDependsJavaParser.y" +#line 921 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); - yyGetParser->DeallocateParserType(&(yyvsp[-3].str)); + yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3262 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 104: -#line 949 "cmDependsJavaParser.y" +#line 931 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); } +#line 3271 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 105: -#line 955 "cmDependsJavaParser.y" +#line 937 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3282 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 107: -#line 966 "cmDependsJavaParser.y" +#line 948 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); } +#line 3291 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 108: -#line 972 "cmDependsJavaParser.y" +#line 954 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3303 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 109: -#line 982 "cmDependsJavaParser.y" +#line 964 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3315 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 110: -#line 992 "cmDependsJavaParser.y" +#line 974 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3327 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 111: -#line 1002 "cmDependsJavaParser.y" +#line 984 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); } +#line 3336 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 112: -#line 1008 "cmDependsJavaParser.y" +#line 990 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3348 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 113: -#line 1018 "cmDependsJavaParser.y" +#line 1000 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3360 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 114: -#line 1028 "cmDependsJavaParser.y" +#line 1010 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3372 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 115: -#line 1038 "cmDependsJavaParser.y" +#line 1020 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3384 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 116: -#line 1047 "cmDependsJavaParser.y" +#line 1029 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3396 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 117: -#line 1057 "cmDependsJavaParser.y" +#line 1039 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); - yyGetParser->DeallocateParserType(&(yyvsp[-3].str)); + yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3409 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 118: -#line 1068 "cmDependsJavaParser.y" +#line 1050 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3421 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 119: -#line 1077 "cmDependsJavaParser.y" +#line 1059 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3432 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 120: -#line 1085 "cmDependsJavaParser.y" +#line 1067 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3444 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 121: -#line 1095 "cmDependsJavaParser.y" +#line 1077 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3456 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 122: -#line 1104 "cmDependsJavaParser.y" +#line 1086 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3468 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 123: -#line 1114 "cmDependsJavaParser.y" +#line 1096 "cmDependsJavaParser.y" /* yacc.c:1646 */ { - yyGetParser->StartClass(yyvsp[0].str); + yyGetParser->StartClass((yyvsp[0].str)); jpElementStart(3); - yyGetParser->DeallocateParserType(&(yyvsp[0].str)); + yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(3); } +#line 3479 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 124: -#line 1123 "cmDependsJavaParser.y" +#line 1105 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } +#line 3491 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 125: -#line 1132 "cmDependsJavaParser.y" +#line 1114 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3501 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 126: -#line 1139 "cmDependsJavaParser.y" +#line 1121 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3513 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 127: -#line 1149 "cmDependsJavaParser.y" +#line 1131 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3525 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 128: -#line 1158 "cmDependsJavaParser.y" +#line 1140 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3537 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 129: -#line 1168 "cmDependsJavaParser.y" +#line 1150 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3549 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 130: -#line 1177 "cmDependsJavaParser.y" +#line 1159 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3560 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 131: -#line 1185 "cmDependsJavaParser.y" +#line 1167 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3571 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 132: -#line 1194 "cmDependsJavaParser.y" +#line 1176 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3583 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 133: -#line 1203 "cmDependsJavaParser.y" +#line 1185 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3595 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 134: -#line 1212 "cmDependsJavaParser.y" +#line 1194 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3607 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 135: -#line 1221 "cmDependsJavaParser.y" +#line 1203 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3618 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 136: -#line 1229 "cmDependsJavaParser.y" +#line 1211 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3630 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 137: -#line 1238 "cmDependsJavaParser.y" +#line 1220 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3641 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 138: -#line 1247 "cmDependsJavaParser.y" +#line 1229 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3653 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 139: -#line 1257 "cmDependsJavaParser.y" +#line 1239 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3665 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 140: -#line 1267 "cmDependsJavaParser.y" +#line 1249 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3677 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 141: -#line 1276 "cmDependsJavaParser.y" +#line 1258 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3689 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 142: -#line 1286 "cmDependsJavaParser.y" +#line 1268 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3701 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 143: -#line 1295 "cmDependsJavaParser.y" +#line 1277 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3712 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 144: -#line 1303 "cmDependsJavaParser.y" +#line 1285 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3724 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 145: -#line 1312 "cmDependsJavaParser.y" +#line 1294 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3736 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 146: -#line 1322 "cmDependsJavaParser.y" +#line 1304 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3748 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 147: -#line 1331 "cmDependsJavaParser.y" +#line 1313 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3760 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 148: -#line 1341 "cmDependsJavaParser.y" +#line 1323 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3771 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 149: -#line 1349 "cmDependsJavaParser.y" +#line 1331 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3782 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 150: -#line 1357 "cmDependsJavaParser.y" +#line 1339 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3794 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 151: -#line 1367 "cmDependsJavaParser.y" +#line 1349 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3806 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 152: -#line 1376 "cmDependsJavaParser.y" +#line 1358 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3818 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 153: -#line 1386 "cmDependsJavaParser.y" +#line 1368 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3830 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 154: -#line 1395 "cmDependsJavaParser.y" +#line 1377 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3842 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 155: -#line 1404 "cmDependsJavaParser.y" +#line 1386 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3854 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 156: -#line 1414 "cmDependsJavaParser.y" +#line 1396 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3866 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 157: -#line 1424 "cmDependsJavaParser.y" +#line 1406 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3878 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 158: -#line 1433 "cmDependsJavaParser.y" +#line 1415 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3890 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 159: -#line 1443 "cmDependsJavaParser.y" +#line 1425 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3902 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 160: -#line 1452 "cmDependsJavaParser.y" +#line 1434 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3914 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 161: -#line 1461 "cmDependsJavaParser.y" +#line 1443 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3926 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 162: -#line 1470 "cmDependsJavaParser.y" +#line 1452 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3938 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 163: -#line 1479 "cmDependsJavaParser.y" +#line 1461 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3950 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 164: -#line 1488 "cmDependsJavaParser.y" +#line 1470 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3962 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 165: -#line 1498 "cmDependsJavaParser.y" +#line 1480 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3974 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 166: -#line 1507 "cmDependsJavaParser.y" +#line 1489 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3986 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 167: -#line 1516 "cmDependsJavaParser.y" +#line 1498 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 3998 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 168: -#line 1525 "cmDependsJavaParser.y" +#line 1507 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4010 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 169: -#line 1534 "cmDependsJavaParser.y" +#line 1516 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4022 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 170: -#line 1544 "cmDependsJavaParser.y" +#line 1526 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4034 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 171: -#line 1553 "cmDependsJavaParser.y" +#line 1535 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4046 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 172: -#line 1562 "cmDependsJavaParser.y" +#line 1544 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4058 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 173: -#line 1571 "cmDependsJavaParser.y" +#line 1553 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4070 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 174: -#line 1580 "cmDependsJavaParser.y" +#line 1562 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4082 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 175: -#line 1589 "cmDependsJavaParser.y" +#line 1571 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4094 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 176: -#line 1598 "cmDependsJavaParser.y" +#line 1580 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4106 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 177: -#line 1607 "cmDependsJavaParser.y" +#line 1589 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4118 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 178: -#line 1616 "cmDependsJavaParser.y" +#line 1598 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4130 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 179: -#line 1625 "cmDependsJavaParser.y" +#line 1607 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4142 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 180: -#line 1634 "cmDependsJavaParser.y" +#line 1616 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4154 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 181: -#line 1643 "cmDependsJavaParser.y" +#line 1625 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4166 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 182: -#line 1653 "cmDependsJavaParser.y" +#line 1635 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4178 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 183: -#line 1663 "cmDependsJavaParser.y" +#line 1645 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); - yyGetParser->DeallocateParserType(&(yyvsp[-2].str)); + yyGetParser->DeallocateParserType(&((yyvsp[-2].str))); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4191 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 184: -#line 1674 "cmDependsJavaParser.y" +#line 1656 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4203 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 185: -#line 1684 "cmDependsJavaParser.y" +#line 1666 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4215 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 186: -#line 1694 "cmDependsJavaParser.y" +#line 1676 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4227 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 187: -#line 1703 "cmDependsJavaParser.y" +#line 1685 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4239 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 188: -#line 1712 "cmDependsJavaParser.y" +#line 1694 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4251 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 189: -#line 1721 "cmDependsJavaParser.y" +#line 1703 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4263 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 190: -#line 1730 "cmDependsJavaParser.y" +#line 1712 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4275 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 191: -#line 1739 "cmDependsJavaParser.y" +#line 1721 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4287 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 192: -#line 1748 "cmDependsJavaParser.y" +#line 1730 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4299 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 193: -#line 1758 "cmDependsJavaParser.y" +#line 1740 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4311 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 194: -#line 1768 "cmDependsJavaParser.y" +#line 1750 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(7); jpCheckEmpty(7); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4323 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 195: -#line 1778 "cmDependsJavaParser.y" +#line 1760 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(7); jpCheckEmpty(7); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4335 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 196: -#line 1788 "cmDependsJavaParser.y" +#line 1770 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); } +#line 4344 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 197: -#line 1795 "cmDependsJavaParser.y" +#line 1777 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); } +#line 4353 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 198: -#line 1801 "cmDependsJavaParser.y" +#line 1783 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4364 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 199: -#line 1809 "cmDependsJavaParser.y" +#line 1791 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4376 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 200: -#line 1818 "cmDependsJavaParser.y" +#line 1800 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4387 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 201: -#line 1826 "cmDependsJavaParser.y" +#line 1808 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4399 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 202: -#line 1836 "cmDependsJavaParser.y" +#line 1818 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4411 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 203: -#line 1846 "cmDependsJavaParser.y" +#line 1828 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4423 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 204: -#line 1855 "cmDependsJavaParser.y" +#line 1837 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4435 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 205: -#line 1865 "cmDependsJavaParser.y" +#line 1847 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4447 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 206: -#line 1874 "cmDependsJavaParser.y" +#line 1856 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4459 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 207: -#line 1884 "cmDependsJavaParser.y" +#line 1866 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); } +#line 4468 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 208: -#line 1891 "cmDependsJavaParser.y" +#line 1873 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); } +#line 4477 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 209: -#line 1898 "cmDependsJavaParser.y" +#line 1880 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(7); } +#line 4486 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 210: -#line 1906 "cmDependsJavaParser.y" +#line 1888 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(9); } +#line 4495 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 211: -#line 1912 "cmDependsJavaParser.y" +#line 1894 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4506 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 212: -#line 1920 "cmDependsJavaParser.y" +#line 1902 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4518 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 213: -#line 1929 "cmDependsJavaParser.y" +#line 1911 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4529 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 214: -#line 1937 "cmDependsJavaParser.y" +#line 1919 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4541 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 215: -#line 1948 "cmDependsJavaParser.y" +#line 1930 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(9); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4552 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 216: -#line 1956 "cmDependsJavaParser.y" +#line 1938 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4563 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 217: -#line 1964 "cmDependsJavaParser.y" +#line 1946 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4575 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 218: -#line 1974 "cmDependsJavaParser.y" +#line 1956 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4587 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 219: -#line 1983 "cmDependsJavaParser.y" +#line 1965 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4599 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 220: -#line 1993 "cmDependsJavaParser.y" +#line 1975 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4611 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 221: -#line 2003 "cmDependsJavaParser.y" +#line 1985 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4623 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 222: -#line 2012 "cmDependsJavaParser.y" +#line 1994 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4635 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 223: -#line 2022 "cmDependsJavaParser.y" +#line 2004 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4647 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 224: -#line 2031 "cmDependsJavaParser.y" +#line 2013 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4659 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 225: -#line 2041 "cmDependsJavaParser.y" +#line 2023 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); - yyGetParser->DeallocateParserType(&(yyvsp[-1].str)); + yyGetParser->DeallocateParserType(&((yyvsp[-1].str))); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4672 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 226: -#line 2051 "cmDependsJavaParser.y" +#line 2033 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4683 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 227: -#line 2059 "cmDependsJavaParser.y" +#line 2041 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); } +#line 4692 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 228: -#line 2066 "cmDependsJavaParser.y" +#line 2048 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); - yyGetParser->DeallocateParserType(&(yyvsp[-1].str)); + yyGetParser->DeallocateParserType(&((yyvsp[-1].str))); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4705 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 229: -#line 2077 "cmDependsJavaParser.y" +#line 2059 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4717 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 230: -#line 2087 "cmDependsJavaParser.y" +#line 2069 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4729 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 231: -#line 2097 "cmDependsJavaParser.y" +#line 2079 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4741 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 232: -#line 2107 "cmDependsJavaParser.y" +#line 2089 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4753 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 233: -#line 2116 "cmDependsJavaParser.y" +#line 2098 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4765 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 234: -#line 2125 "cmDependsJavaParser.y" +#line 2107 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4776 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 235: -#line 2133 "cmDependsJavaParser.y" +#line 2115 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4788 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 236: -#line 2143 "cmDependsJavaParser.y" +#line 2125 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4800 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 237: -#line 2152 "cmDependsJavaParser.y" +#line 2134 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4812 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 238: -#line 2162 "cmDependsJavaParser.y" +#line 2144 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); } +#line 4821 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 239: -#line 2169 "cmDependsJavaParser.y" +#line 2151 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4833 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 240: -#line 2179 "cmDependsJavaParser.y" +#line 2161 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4845 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 241: -#line 2188 "cmDependsJavaParser.y" +#line 2170 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4857 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 242: -#line 2198 "cmDependsJavaParser.y" +#line 2180 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4869 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 243: -#line 2207 "cmDependsJavaParser.y" +#line 2189 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); } +#line 4878 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 244: -#line 2213 "cmDependsJavaParser.y" +#line 2195 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4890 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 245: -#line 2222 "cmDependsJavaParser.y" +#line 2204 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4902 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 246: -#line 2231 "cmDependsJavaParser.y" +#line 2213 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4914 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 247: -#line 2240 "cmDependsJavaParser.y" +#line 2222 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4926 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 248: -#line 2249 "cmDependsJavaParser.y" +#line 2231 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4938 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 249: -#line 2259 "cmDependsJavaParser.y" +#line 2241 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(6); jpCheckEmpty(6); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4950 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 250: -#line 2268 "cmDependsJavaParser.y" +#line 2250 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4961 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 251: -#line 2276 "cmDependsJavaParser.y" +#line 2258 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4973 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 252: -#line 2285 "cmDependsJavaParser.y" +#line 2267 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4984 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 253: -#line 2293 "cmDependsJavaParser.y" +#line 2275 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 4996 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 254: -#line 2303 "cmDependsJavaParser.y" +#line 2285 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5008 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 255: -#line 2312 "cmDependsJavaParser.y" +#line 2294 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5020 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 256: -#line 2322 "cmDependsJavaParser.y" +#line 2304 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5032 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 257: -#line 2331 "cmDependsJavaParser.y" +#line 2313 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5044 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 258: -#line 2340 "cmDependsJavaParser.y" +#line 2322 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5056 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 259: -#line 2349 "cmDependsJavaParser.y" +#line 2331 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5068 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 260: -#line 2358 "cmDependsJavaParser.y" +#line 2340 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5079 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 261: -#line 2366 "cmDependsJavaParser.y" +#line 2348 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5091 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 262: -#line 2376 "cmDependsJavaParser.y" +#line 2358 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5103 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 263: -#line 2385 "cmDependsJavaParser.y" +#line 2367 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5115 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 264: -#line 2395 "cmDependsJavaParser.y" +#line 2377 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5127 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 265: -#line 2405 "cmDependsJavaParser.y" +#line 2387 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); } +#line 5136 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 266: -#line 2411 "cmDependsJavaParser.y" +#line 2393 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); } +#line 5145 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 267: -#line 2418 "cmDependsJavaParser.y" +#line 2400 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); - yyGetParser->DeallocateParserType(&(yyvsp[0].str)); + yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5158 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 268: -#line 2428 "cmDependsJavaParser.y" +#line 2410 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); - yyGetParser->DeallocateParserType(&(yyvsp[0].str)); + yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5171 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 269: -#line 2438 "cmDependsJavaParser.y" +#line 2420 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); - yyGetParser->DeallocateParserType(&(yyvsp[0].str)); + yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5184 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 270: -#line 2448 "cmDependsJavaParser.y" +#line 2430 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); - yyGetParser->DeallocateParserType(&(yyvsp[0].str)); + yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5197 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 271: -#line 2459 "cmDependsJavaParser.y" +#line 2441 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); - yyGetParser->DeallocateParserType(&(yyvsp[-3].str)); + yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5210 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 272: -#line 2469 "cmDependsJavaParser.y" +#line 2451 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(6); - yyGetParser->DeallocateParserType(&(yyvsp[-5].str)); - yyGetParser->DeallocateParserType(&(yyvsp[-3].str)); + yyGetParser->DeallocateParserType(&((yyvsp[-5].str))); + yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); jpCheckEmpty(6); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5224 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 273: -#line 2480 "cmDependsJavaParser.y" +#line 2462 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(6); - yyGetParser->DeallocateParserType(&(yyvsp[-3].str)); + yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); jpCheckEmpty(6); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5237 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 274: -#line 2490 "cmDependsJavaParser.y" +#line 2472 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(6); - yyGetParser->DeallocateParserType(&(yyvsp[-3].str)); + yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); jpCheckEmpty(6); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5250 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 275: -#line 2501 "cmDependsJavaParser.y" +#line 2483 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); - yyGetParser->DeallocateParserType(&(yyvsp[-3].str)); + yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5263 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 276: -#line 2511 "cmDependsJavaParser.y" +#line 2493 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5275 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 277: -#line 2521 "cmDependsJavaParser.y" +#line 2503 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5287 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 278: -#line 2530 "cmDependsJavaParser.y" +#line 2512 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); - yyGetParser->DeallocateParserType(&(yyvsp[0].str)); - yyval.str = 0; + yyGetParser->DeallocateParserType(&((yyvsp[0].str))); + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5299 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 279: -#line 2539 "cmDependsJavaParser.y" +#line 2521 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5311 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 280: -#line 2548 "cmDependsJavaParser.y" +#line 2530 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5323 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 281: -#line 2557 "cmDependsJavaParser.y" +#line 2539 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5335 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 282: -#line 2567 "cmDependsJavaParser.y" +#line 2549 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5347 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 283: -#line 2577 "cmDependsJavaParser.y" +#line 2559 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5359 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 284: -#line 2587 "cmDependsJavaParser.y" +#line 2569 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5371 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 285: -#line 2596 "cmDependsJavaParser.y" +#line 2578 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5383 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 286: -#line 2605 "cmDependsJavaParser.y" +#line 2587 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5395 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 287: -#line 2614 "cmDependsJavaParser.y" +#line 2596 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5407 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 288: -#line 2623 "cmDependsJavaParser.y" +#line 2605 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5419 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 289: -#line 2633 "cmDependsJavaParser.y" +#line 2615 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5431 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 290: -#line 2643 "cmDependsJavaParser.y" +#line 2625 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5443 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 291: -#line 2653 "cmDependsJavaParser.y" +#line 2635 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5455 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 292: -#line 2662 "cmDependsJavaParser.y" +#line 2644 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5467 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 293: -#line 2671 "cmDependsJavaParser.y" +#line 2653 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5479 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 294: -#line 2680 "cmDependsJavaParser.y" +#line 2662 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5491 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 295: -#line 2690 "cmDependsJavaParser.y" +#line 2672 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5503 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 296: -#line 2699 "cmDependsJavaParser.y" +#line 2681 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5515 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 297: -#line 2708 "cmDependsJavaParser.y" +#line 2690 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); } +#line 5524 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 298: -#line 2715 "cmDependsJavaParser.y" +#line 2697 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5536 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 299: -#line 2724 "cmDependsJavaParser.y" +#line 2706 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5548 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 300: -#line 2733 "cmDependsJavaParser.y" +#line 2715 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5560 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 301: -#line 2742 "cmDependsJavaParser.y" +#line 2724 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5572 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 302: -#line 2752 "cmDependsJavaParser.y" +#line 2734 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5584 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 303: -#line 2761 "cmDependsJavaParser.y" +#line 2743 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5596 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 304: -#line 2770 "cmDependsJavaParser.y" +#line 2752 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5608 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 305: -#line 2780 "cmDependsJavaParser.y" +#line 2762 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5620 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 306: -#line 2789 "cmDependsJavaParser.y" +#line 2771 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5632 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 307: -#line 2798 "cmDependsJavaParser.y" +#line 2780 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5644 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 308: -#line 2807 "cmDependsJavaParser.y" +#line 2789 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5656 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 309: -#line 2817 "cmDependsJavaParser.y" +#line 2799 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5668 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 310: -#line 2826 "cmDependsJavaParser.y" +#line 2808 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5680 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 311: -#line 2835 "cmDependsJavaParser.y" +#line 2817 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5692 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 312: -#line 2844 "cmDependsJavaParser.y" +#line 2826 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5704 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 313: -#line 2853 "cmDependsJavaParser.y" +#line 2835 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5716 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 314: -#line 2862 "cmDependsJavaParser.y" +#line 2844 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5728 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 315: -#line 2872 "cmDependsJavaParser.y" +#line 2854 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5740 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 316: -#line 2881 "cmDependsJavaParser.y" +#line 2863 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5752 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 317: -#line 2890 "cmDependsJavaParser.y" +#line 2872 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5764 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 318: -#line 2900 "cmDependsJavaParser.y" +#line 2882 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5776 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 319: -#line 2909 "cmDependsJavaParser.y" +#line 2891 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5788 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 320: -#line 2919 "cmDependsJavaParser.y" +#line 2901 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5800 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 321: -#line 2928 "cmDependsJavaParser.y" +#line 2910 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5812 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 322: -#line 2938 "cmDependsJavaParser.y" +#line 2920 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5824 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 323: -#line 2947 "cmDependsJavaParser.y" +#line 2929 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5836 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 324: -#line 2957 "cmDependsJavaParser.y" +#line 2939 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5848 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 325: -#line 2966 "cmDependsJavaParser.y" +#line 2948 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5860 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 326: -#line 2976 "cmDependsJavaParser.y" +#line 2958 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5872 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 327: -#line 2985 "cmDependsJavaParser.y" +#line 2967 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5884 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 328: -#line 2995 "cmDependsJavaParser.y" +#line 2977 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5896 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 329: -#line 3004 "cmDependsJavaParser.y" +#line 2986 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5908 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 330: -#line 3014 "cmDependsJavaParser.y" +#line 2996 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5920 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 331: -#line 3023 "cmDependsJavaParser.y" +#line 3005 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5932 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 332: -#line 3033 "cmDependsJavaParser.y" +#line 3015 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5944 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 333: -#line 3043 "cmDependsJavaParser.y" +#line 3025 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); - yyGetParser->DeallocateParserType(&(yyvsp[0].str)); + yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5957 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 334: -#line 3053 "cmDependsJavaParser.y" +#line 3035 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5969 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 335: -#line 3062 "cmDependsJavaParser.y" +#line 3044 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5981 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 336: -#line 3072 "cmDependsJavaParser.y" +#line 3054 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 5993 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 337: -#line 3081 "cmDependsJavaParser.y" +#line 3063 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 6005 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 338: -#line 3090 "cmDependsJavaParser.y" +#line 3072 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 6017 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 339: -#line 3099 "cmDependsJavaParser.y" +#line 3081 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 6029 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 340: -#line 3108 "cmDependsJavaParser.y" +#line 3090 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 6041 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 341: -#line 3117 "cmDependsJavaParser.y" +#line 3099 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 6053 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 342: -#line 3126 "cmDependsJavaParser.y" +#line 3108 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 6065 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 343: -#line 3135 "cmDependsJavaParser.y" +#line 3117 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 6077 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 344: -#line 3144 "cmDependsJavaParser.y" +#line 3126 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 6089 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 345: -#line 3153 "cmDependsJavaParser.y" +#line 3135 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 6101 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 346: -#line 3162 "cmDependsJavaParser.y" +#line 3144 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 6113 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 347: -#line 3171 "cmDependsJavaParser.y" +#line 3153 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 6125 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 348: -#line 3181 "cmDependsJavaParser.y" +#line 3163 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 6137 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 349: -#line 3191 "cmDependsJavaParser.y" +#line 3173 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 6149 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 350: -#line 3201 "cmDependsJavaParser.y" +#line 3183 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 6161 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 351: -#line 3210 "cmDependsJavaParser.y" +#line 3192 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); - jpStoreClass(yyvsp[-2].str); + jpStoreClass((yyvsp[-2].str)); jpCheckEmpty(3); - yyval.str = 0; + (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } +#line 6174 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; +#line 6178 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ + default: break; } - -/* Line 1010 of yacc.c. */ -#line 5780 "cmDependsJavaParser.cxx" - - yyvsp -= yylen; - yyssp -= yylen; - - + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; - - /* Now `shift' the result of the reduction. Determine what state + /* Now 'shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ @@ -5794,74 +6211,52 @@ yyreduce: goto yynewstate; -/*------------------------------------. -| yyerrlab -- here on detecting error | -`------------------------------------*/ +/*--------------------------------------. +| yyerrlab -- here on detecting error. | +`--------------------------------------*/ yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); + /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; -#if YYERROR_VERBOSE - yyn = yypact[yystate]; - - if (YYPACT_NINF < yyn && yyn < YYLAST) - { - YYSIZE_T yysize = 0; - int yytype = YYTRANSLATE (yychar); - const char* yyprefix; - char *yymsg; - int yyx; - - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yycount = 0; - - yyprefix = ", expecting "; - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) - { - yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]); - yycount += 1; - if (yycount == 5) - { - yysize = 0; - break; - } - } - yysize += (sizeof ("syntax error, unexpected ") - + yystrlen (yytname[yytype])); - yymsg = (char *) YYSTACK_ALLOC (yysize); - if (yymsg != 0) +#if ! YYERROR_VERBOSE + yyerror (yyscanner, YY_("syntax error")); +#else +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ + yyssp, yytoken) { - char *yyp = yystpcpy (yymsg, "syntax error, unexpected "); - yyp = yystpcpy (yyp, yytname[yytype]); - - if (yycount < 5) - { - yyprefix = ", expecting "; - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + char const *yymsgp = YY_("syntax error"); + int yysyntax_error_status; + yysyntax_error_status = YYSYNTAX_ERROR; + if (yysyntax_error_status == 0) + yymsgp = yymsg; + else if (yysyntax_error_status == 1) { - yyp = yystpcpy (yyp, yyprefix); - yyp = yystpcpy (yyp, yytname[yyx]); - yyprefix = " or "; + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); + if (!yymsg) + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + yysyntax_error_status = 2; + } + else + { + yysyntax_error_status = YYSYNTAX_ERROR; + yymsgp = yymsg; + } } - } - yyerror (yymsg); - YYSTACK_FREE (yymsg); + yyerror (yyscanner, yymsgp); + if (yysyntax_error_status == 2) + goto yyexhaustedlab; } - else - yyerror ("syntax error; also virtual memory exhausted"); - } - else -#endif /* YYERROR_VERBOSE */ - yyerror ("syntax error"); +# undef YYSYNTAX_ERROR +#endif } @@ -5869,31 +6264,23 @@ yyerrlab: if (yyerrstatus == 3) { /* If just tried and failed to reuse lookahead token after an - error, discard it. */ + error, discard it. */ if (yychar <= YYEOF) { - /* If at end of input, pop the error token, - then the rest of the stack, then return failure. */ - if (yychar == YYEOF) - for (;;) - { - YYPOPSTACK; - if (yyssp == yyss) - YYABORT; - YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); - yydestruct (yystos[*yyssp], yyvsp); - } + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; } else - { - YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc); - yydestruct (yytoken, &yylval); - yychar = YYEMPTY; - - } + { + yydestruct ("Error: discarding", + yytoken, &yylval, yyscanner); + yychar = YYEMPTY; + } } +#if 0 /* Else will try to reuse lookahead token after shifting the error token. */ goto yyerrlab1; @@ -5904,15 +6291,17 @@ yyerrlab: `---------------------------------------------------*/ yyerrorlab: -#if defined(__GNUC__) || defined(__HP_aCC) - /* Pacify GCC when the user code never invokes YYERROR and the label - yyerrorlab therefore never appears in user code. */ - if (0) + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) goto yyerrorlab; -#endif - yyvsp -= yylen; - yyssp -= yylen; + /* Do not reclaim the symbols of the rule whose action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); yystate = *yyssp; goto yyerrlab1; @@ -5921,41 +6310,43 @@ yyerrorlab: | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: - yyerrstatus = 3; /* Each real token shifted decrements this. */ +#endif + yyerrstatus = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact[yystate]; - if (yyn != YYPACT_NINF) - { - yyn += YYTERROR; - if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) - { - yyn = yytable[yyn]; - if (0 < yyn) - break; - } - } + if (!yypact_value_is_default (yyn)) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) - YYABORT; + YYABORT; - YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); - yydestruct (yystos[yystate], yyvsp); - YYPOPSTACK; + + yydestruct ("Error: popping", + yystos[yystate], yyvsp, yyscanner); + YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } - if (yyn == YYFINAL) - YYACCEPT; - - YYDPRINTF ((stderr, "Shifting error token, ")); - + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + yystate = yyn; goto yynewstate; @@ -5974,33 +6365,51 @@ yyabortlab: yyresult = 1; goto yyreturn; -#ifndef yyoverflow -/*----------------------------------------------. -| yyoverflowlab -- parser overflow comes here. | -`----------------------------------------------*/ -yyoverflowlab: - yyerror ("parser stack overflow"); +#if !defined yyoverflow || YYERROR_VERBOSE +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (yyscanner, YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif yyreturn: + if (yychar != YYEMPTY) + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval, yyscanner); + } + /* Do not reclaim the symbols of the rule whose action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp, yyscanner); + YYPOPSTACK (1); + } #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif return yyresult; } - - -#line 3219 "cmDependsJavaParser.y" +#line 3201 "cmDependsJavaParser.y" /* yacc.c:1906 */ /* End of grammar */ /*--------------------------------------------------------------------------*/ -void cmDependsJavaError(yyscan_t yyscanner, const char* message) +void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message) { yyGetParser->Error(message); } - - diff --git a/Source/cmDependsJavaParser.y b/Source/cmDependsJavaParser.y index 91ee7c8..ea7ca0f 100644 --- a/Source/cmDependsJavaParser.y +++ b/Source/cmDependsJavaParser.y @@ -10,18 +10,10 @@ Run bison like this: bison --yacc --name-prefix=cmDependsJava_yy --defines=cmDependsJavaParserTokens.h -ocmDependsJavaParser.cxx cmDependsJavaParser.y Modify cmDependsJavaParser.cxx: - - remove TABs - - remove use of the 'register' storage class specifier - - add __HP_aCC to the #if test for yyerrorlab warning suppression + - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"] */ -/* Configure the parser to use a lexer object. */ -#define YYPARSE_PARAM yyscanner -#define YYLEX_PARAM yyscanner -#define YYERROR_VERBOSE 1 -#define cmDependsJava_yyerror(x) \ - cmDependsJavaError(yyscanner, x) #define yyGetParser (cmDependsJava_yyget_extra(yyscanner)) /*-------------------------------------------------------------------------*/ @@ -32,10 +24,9 @@ Modify cmDependsJavaParser.cxx: /* Forward declare the lexer entry point. */ YY_DECL; -/* Internal utility functions. */ -static void cmDependsJavaError(yyscan_t yyscanner, const char* message); +/* Helper function to forward error callback from parser. */ +static void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message); -#define YYDEBUG 1 #define YYMAXDEPTH 1000000 @@ -50,7 +41,13 @@ static void cmDependsJavaError(yyscan_t yyscanner, const char* message); %} /* Generate a reentrant parser object. */ -%pure_parser +%define api.pure + +/* Configure the parser to use a lexer object. */ +%lex-param {yyscan_t yyscanner} +%parse-param {yyscan_t yyscanner} + +%define parse.error verbose /* %union { @@ -3205,7 +3202,7 @@ Name jp_DOT jp_NEW /* End of grammar */ /*--------------------------------------------------------------------------*/ -void cmDependsJavaError(yyscan_t yyscanner, const char* message) +void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message) { yyGetParser->Error(message); } diff --git a/Source/cmDependsJavaParserTokens.h b/Source/cmDependsJavaParserTokens.h index c7a414f..7f18f1d 100644 --- a/Source/cmDependsJavaParserTokens.h +++ b/Source/cmDependsJavaParserTokens.h @@ -1,12 +1,13 @@ -/* A Bison parser, made by GNU Bison 1.875d. */ +/* A Bison parser, made by GNU Bison 3.0.4. */ -/* Skeleton parser for Yacc-like parsing with Bison, Copyright (C) 1984, - 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. +/* Bison interface for Yacc-like parsers in C - This program is free software; you can redistribute it and/or modify + Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -14,126 +15,142 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + along with this program. If not, see . */ -/* As a special exception, when this file is copied by Bison into a - Bison output file, you may use that output file without restriction. - This special exception was added by the Free Software Foundation - in version 1.24 of Bison. */ +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. -/* Tokens. */ + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +#ifndef YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED +# define YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int cmDependsJava_yydebug; +#endif + +/* Token type. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - enum yytokentype { - jp_ABSTRACT = 258, - jp_ASSERT = 259, - jp_BOOLEAN_TYPE = 260, - jp_BREAK = 261, - jp_BYTE_TYPE = 262, - jp_CASE = 263, - jp_CATCH = 264, - jp_CHAR_TYPE = 265, - jp_CLASS = 266, - jp_CONTINUE = 267, - jp_DEFAULT = 268, - jp_DO = 269, - jp_DOUBLE_TYPE = 270, - jp_ELSE = 271, - jp_EXTENDS = 272, - jp_FINAL = 273, - jp_FINALLY = 274, - jp_FLOAT_TYPE = 275, - jp_FOR = 276, - jp_IF = 277, - jp_IMPLEMENTS = 278, - jp_IMPORT = 279, - jp_INSTANCEOF = 280, - jp_INT_TYPE = 281, - jp_INTERFACE = 282, - jp_LONG_TYPE = 283, - jp_NATIVE = 284, - jp_NEW = 285, - jp_PACKAGE = 286, - jp_PRIVATE = 287, - jp_PROTECTED = 288, - jp_PUBLIC = 289, - jp_RETURN = 290, - jp_SHORT_TYPE = 291, - jp_STATIC = 292, - jp_STRICTFP = 293, - jp_SUPER = 294, - jp_SWITCH = 295, - jp_SYNCHRONIZED = 296, - jp_THIS = 297, - jp_THROW = 298, - jp_THROWS = 299, - jp_TRANSIENT = 300, - jp_TRY = 301, - jp_VOID = 302, - jp_VOLATILE = 303, - jp_WHILE = 304, - jp_BOOLEANLITERAL = 305, - jp_CHARACTERLITERAL = 306, - jp_DECIMALINTEGERLITERAL = 307, - jp_FLOATINGPOINTLITERAL = 308, - jp_HEXINTEGERLITERAL = 309, - jp_NULLLITERAL = 310, - jp_STRINGLITERAL = 311, - jp_NAME = 312, - jp_AND = 313, - jp_ANDAND = 314, - jp_ANDEQUALS = 315, - jp_BRACKETEND = 316, - jp_BRACKETSTART = 317, - jp_CARROT = 318, - jp_CARROTEQUALS = 319, - jp_COLON = 320, - jp_COMMA = 321, - jp_CURLYEND = 322, - jp_CURLYSTART = 323, - jp_DIVIDE = 324, - jp_DIVIDEEQUALS = 325, - jp_DOLLAR = 326, - jp_DOT = 327, - jp_EQUALS = 328, - jp_EQUALSEQUALS = 329, - jp_EXCLAMATION = 330, - jp_EXCLAMATIONEQUALS = 331, - jp_GREATER = 332, - jp_GTEQUALS = 333, - jp_GTGT = 334, - jp_GTGTEQUALS = 335, - jp_GTGTGT = 336, - jp_GTGTGTEQUALS = 337, - jp_LESLESEQUALS = 338, - jp_LESSTHAN = 339, - jp_LTEQUALS = 340, - jp_LTLT = 341, - jp_MINUS = 342, - jp_MINUSEQUALS = 343, - jp_MINUSMINUS = 344, - jp_PAREEND = 345, - jp_PARESTART = 346, - jp_PERCENT = 347, - jp_PERCENTEQUALS = 348, - jp_PIPE = 349, - jp_PIPEEQUALS = 350, - jp_PIPEPIPE = 351, - jp_PLUS = 352, - jp_PLUSEQUALS = 353, - jp_PLUSPLUS = 354, - jp_QUESTION = 355, - jp_SEMICOL = 356, - jp_TILDE = 357, - jp_TIMES = 358, - jp_TIMESEQUALS = 359, - jp_ERROR = 360 - }; + enum yytokentype + { + jp_ABSTRACT = 258, + jp_ASSERT = 259, + jp_BOOLEAN_TYPE = 260, + jp_BREAK = 261, + jp_BYTE_TYPE = 262, + jp_CASE = 263, + jp_CATCH = 264, + jp_CHAR_TYPE = 265, + jp_CLASS = 266, + jp_CONTINUE = 267, + jp_DEFAULT = 268, + jp_DO = 269, + jp_DOUBLE_TYPE = 270, + jp_ELSE = 271, + jp_EXTENDS = 272, + jp_FINAL = 273, + jp_FINALLY = 274, + jp_FLOAT_TYPE = 275, + jp_FOR = 276, + jp_IF = 277, + jp_IMPLEMENTS = 278, + jp_IMPORT = 279, + jp_INSTANCEOF = 280, + jp_INT_TYPE = 281, + jp_INTERFACE = 282, + jp_LONG_TYPE = 283, + jp_NATIVE = 284, + jp_NEW = 285, + jp_PACKAGE = 286, + jp_PRIVATE = 287, + jp_PROTECTED = 288, + jp_PUBLIC = 289, + jp_RETURN = 290, + jp_SHORT_TYPE = 291, + jp_STATIC = 292, + jp_STRICTFP = 293, + jp_SUPER = 294, + jp_SWITCH = 295, + jp_SYNCHRONIZED = 296, + jp_THIS = 297, + jp_THROW = 298, + jp_THROWS = 299, + jp_TRANSIENT = 300, + jp_TRY = 301, + jp_VOID = 302, + jp_VOLATILE = 303, + jp_WHILE = 304, + jp_BOOLEANLITERAL = 305, + jp_CHARACTERLITERAL = 306, + jp_DECIMALINTEGERLITERAL = 307, + jp_FLOATINGPOINTLITERAL = 308, + jp_HEXINTEGERLITERAL = 309, + jp_NULLLITERAL = 310, + jp_STRINGLITERAL = 311, + jp_NAME = 312, + jp_AND = 313, + jp_ANDAND = 314, + jp_ANDEQUALS = 315, + jp_BRACKETEND = 316, + jp_BRACKETSTART = 317, + jp_CARROT = 318, + jp_CARROTEQUALS = 319, + jp_COLON = 320, + jp_COMMA = 321, + jp_CURLYEND = 322, + jp_CURLYSTART = 323, + jp_DIVIDE = 324, + jp_DIVIDEEQUALS = 325, + jp_DOLLAR = 326, + jp_DOT = 327, + jp_EQUALS = 328, + jp_EQUALSEQUALS = 329, + jp_EXCLAMATION = 330, + jp_EXCLAMATIONEQUALS = 331, + jp_GREATER = 332, + jp_GTEQUALS = 333, + jp_GTGT = 334, + jp_GTGTEQUALS = 335, + jp_GTGTGT = 336, + jp_GTGTGTEQUALS = 337, + jp_LESLESEQUALS = 338, + jp_LESSTHAN = 339, + jp_LTEQUALS = 340, + jp_LTLT = 341, + jp_MINUS = 342, + jp_MINUSEQUALS = 343, + jp_MINUSMINUS = 344, + jp_PAREEND = 345, + jp_PARESTART = 346, + jp_PERCENT = 347, + jp_PERCENTEQUALS = 348, + jp_PIPE = 349, + jp_PIPEEQUALS = 350, + jp_PIPEPIPE = 351, + jp_PLUS = 352, + jp_PLUSEQUALS = 353, + jp_PLUSPLUS = 354, + jp_QUESTION = 355, + jp_SEMICOL = 356, + jp_TILDE = 357, + jp_TIMES = 358, + jp_TIMESEQUALS = 359, + jp_ERROR = 360 + }; #endif +/* Tokens. */ #define jp_ABSTRACT 258 #define jp_ASSERT 259 #define jp_BOOLEAN_TYPE 260 @@ -238,17 +255,10 @@ #define jp_TIMESEQUALS 359 #define jp_ERROR 360 +/* Value type. */ -#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) -typedef int YYSTYPE; -# define yystype YYSTYPE /* obsolescent; will be withdrawn */ -# define YYSTYPE_IS_DECLARED 1 -# define YYSTYPE_IS_TRIVIAL 1 -#endif - - - - +int cmDependsJava_yyparse (yyscan_t yyscanner); +#endif /* !YY_CMDEPENDSJAVA_YY_CMDEPENDSJAVAPARSERTOKENS_H_INCLUDED */ https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=fe75e140d617dd2d8401a85c718d03a6466a8bd9 commit fe75e140d617dd2d8401a85c718d03a6466a8bd9 Author: Daniel Pfeifer AuthorDate: Thu Feb 16 21:18:15 2017 +0100 Commit: Daniel Pfeifer CommitDate: Thu Feb 16 21:18:15 2017 +0100 cmCommandArgumentParser: Port to bison 3 Use %-directives to specify the scanner/lexer arguments and update the yyerror signature. Reduce the list of post-bison modifications needed. diff --git a/Source/cmCommandArgumentParser.cxx b/Source/cmCommandArgumentParser.cxx index e384f21..8bd3082 100644 --- a/Source/cmCommandArgumentParser.cxx +++ b/Source/cmCommandArgumentParser.cxx @@ -1,16 +1,13 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -/* A Bison parser, made by GNU Bison 2.3. */ +/* A Bison parser, made by GNU Bison 3.0.4. */ -/* Skeleton implementation for Bison's Yacc-like parsers in C +/* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 - Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. - This program is free software; you can redistribute it and/or modify + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -18,9 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. */ + along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -49,7 +44,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.3" +#define YYBISON_VERSION "3.0.4" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -57,58 +52,23 @@ /* Pure parsers. */ #define YYPURE 1 -/* Using locations. */ -#define YYLSP_NEEDED 0 - -/* Substitute the variable and function names. */ -#define yyparse cmCommandArgument_yyparse -#define yylex cmCommandArgument_yylex -#define yyerror cmCommandArgument_yyerror -#define yylval cmCommandArgument_yylval -#define yychar cmCommandArgument_yychar -#define yydebug cmCommandArgument_yydebug -#define yynerrs cmCommandArgument_yynerrs +/* Push parsers. */ +#define YYPUSH 0 - -/* Tokens. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - enum yytokentype { - cal_ENVCURLY = 258, - cal_NCURLY = 259, - cal_DCURLY = 260, - cal_DOLLAR = 261, - cal_LCURLY = 262, - cal_RCURLY = 263, - cal_NAME = 264, - cal_BSLASH = 265, - cal_SYMBOL = 266, - cal_AT = 267, - cal_ERROR = 268, - cal_ATNAME = 269 - }; -#endif -/* Tokens. */ -#define cal_ENVCURLY 258 -#define cal_NCURLY 259 -#define cal_DCURLY 260 -#define cal_DOLLAR 261 -#define cal_LCURLY 262 -#define cal_RCURLY 263 -#define cal_NAME 264 -#define cal_BSLASH 265 -#define cal_SYMBOL 266 -#define cal_AT 267 -#define cal_ERROR 268 -#define cal_ATNAME 269 +/* Pull parsers. */ +#define YYPULL 1 +/* Substitute the variable and function names. */ +#define yyparse cmCommandArgument_yyparse +#define yylex cmCommandArgument_yylex +#define yyerror cmCommandArgument_yyerror +#define yydebug cmCommandArgument_yydebug +#define yynerrs cmCommandArgument_yynerrs /* Copy the first part of user declarations. */ -#line 1 "cmCommandArgumentParser.y" +#line 1 "cmCommandArgumentParser.y" /* yacc.c:339 */ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ @@ -121,19 +81,12 @@ Run bison like this: bison --yacc --name-prefix=cmCommandArgument_yy --defines=cmCommandArgumentParserTokens.h -ocmCommandArgumentParser.cxx cmCommandArgumentParser.y Modify cmCommandArgumentParser.cxx: - - remove TABs - - put header block at top of file + - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"] */ #include "cmStandardIncludes.h" -/* Configure the parser to use a lexer object. */ -#define YYPARSE_PARAM yyscanner -#define YYLEX_PARAM yyscanner -#define YYERROR_VERBOSE 1 -#define cmCommandArgument_yyerror(x) \ - cmCommandArgumentError(yyscanner, x) #define yyGetParser (cmCommandArgument_yyget_extra(yyscanner)) /* Make sure malloc and free are available on QNX. */ @@ -156,10 +109,9 @@ Modify cmCommandArgumentParser.cxx: /* Forward declare the lexer entry point. */ YY_DECL; -/* Internal utility functions. */ -static void cmCommandArgumentError(yyscan_t yyscanner, const char* message); +/* Helper function to forward error callback from parser. */ +static void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message); -#define YYDEBUG 1 /* Configure the parser to support large input. */ #define YYMAXDEPTH 100000 #define YYINITDEPTH 10000 @@ -173,39 +125,80 @@ static void cmCommandArgumentError(yyscan_t yyscanner, const char* message); # pragma warning (disable: 4702) /* unreachable code */ #endif +#line 129 "cmCommandArgumentParser.cxx" /* yacc.c:339 */ -/* Enabling traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif +# ifndef YY_NULLPTR +# if defined __cplusplus && 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif +# endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE # undef YYERROR_VERBOSE # define YYERROR_VERBOSE 1 #else -# define YYERROR_VERBOSE 0 +# define YYERROR_VERBOSE 1 #endif -/* Enabling the token table. */ -#ifndef YYTOKEN_TABLE -# define YYTOKEN_TABLE 0 +/* In a future release of Bison, this section will be replaced + by #include "cmCommandArgumentParserTokens.h". */ +#ifndef YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED +# define YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int cmCommandArgument_yydebug; #endif -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -typedef int YYSTYPE; -# define yystype YYSTYPE /* obsolescent; will be withdrawn */ -# define YYSTYPE_IS_DECLARED 1 -# define YYSTYPE_IS_TRIVIAL 1 +/* Token type. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + enum yytokentype + { + cal_ENVCURLY = 258, + cal_NCURLY = 259, + cal_DCURLY = 260, + cal_DOLLAR = 261, + cal_LCURLY = 262, + cal_RCURLY = 263, + cal_NAME = 264, + cal_BSLASH = 265, + cal_SYMBOL = 266, + cal_AT = 267, + cal_ERROR = 268, + cal_ATNAME = 269 + }; #endif +/* Tokens. */ +#define cal_ENVCURLY 258 +#define cal_NCURLY 259 +#define cal_DCURLY 260 +#define cal_DOLLAR 261 +#define cal_LCURLY 262 +#define cal_RCURLY 263 +#define cal_NAME 264 +#define cal_BSLASH 265 +#define cal_SYMBOL 266 +#define cal_AT 267 +#define cal_ERROR 268 +#define cal_ATNAME 269 +/* Value type. */ -/* Copy the second part of user declarations. */ +int cmCommandArgument_yyparse (yyscan_t yyscanner); -/* Line 216 of yacc.c. */ -#line 227 "cmCommandArgumentParser.cxx" +#endif /* !YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED */ + +/* Copy the second part of user declarations. */ + +#line 202 "cmCommandArgumentParser.cxx" /* yacc.c:358 */ #ifdef short # undef short @@ -219,11 +212,8 @@ typedef unsigned char yytype_uint8; #ifdef YYTYPE_INT8 typedef YYTYPE_INT8 yytype_int8; -#elif (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -typedef signed char yytype_int8; #else -typedef short int yytype_int8; +typedef signed char yytype_int8; #endif #ifdef YYTYPE_UINT16 @@ -243,8 +233,7 @@ typedef short int yytype_int16; # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t -# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) +# elif ! defined YYSIZE_T # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else @@ -258,39 +247,68 @@ typedef short int yytype_int16; # if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ -# define YY_(msgid) dgettext ("bison-runtime", msgid) +# define YY_(Msgid) dgettext ("bison-runtime", Msgid) # endif # endif # ifndef YY_ -# define YY_(msgid) msgid +# define YY_(Msgid) Msgid +# endif +#endif + +#ifndef YY_ATTRIBUTE +# if (defined __GNUC__ \ + && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \ + || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C +# define YY_ATTRIBUTE(Spec) __attribute__(Spec) +# else +# define YY_ATTRIBUTE(Spec) /* empty */ +# endif +#endif + +#ifndef YY_ATTRIBUTE_PURE +# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__)) +#endif + +#ifndef YY_ATTRIBUTE_UNUSED +# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) +#endif + +#if !defined _Noreturn \ + && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) +# if defined _MSC_VER && 1200 <= _MSC_VER +# define _Noreturn __declspec (noreturn) +# else +# define _Noreturn YY_ATTRIBUTE ((__noreturn__)) # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ -# define YYUSE(e) ((void) (e)) +# define YYUSE(E) ((void) (E)) #else -# define YYUSE(e) /* empty */ +# define YYUSE(E) /* empty */ #endif -/* Identity function, used to suppress warnings about constant conditions. */ -#ifndef lint -# define YYID(n) (n) +#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ +/* Suppress an incorrect diagnostic about yylval being uninitialized. */ +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ + _Pragma ("GCC diagnostic pop") #else -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static int -YYID (int i) -#else -static int -YYID (i) - int i; +# define YY_INITIAL_VALUE(Value) Value #endif -{ - return i; -} +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ #endif + #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ @@ -308,11 +326,11 @@ YYID (i) # define alloca _alloca # else # define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS # include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 + /* Use EXIT_SUCCESS as a witness for stdlib.h. */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 # endif # endif # endif @@ -320,8 +338,8 @@ YYID (i) # endif # ifdef YYSTACK_ALLOC - /* Pacify GCC's `empty if-body' warning. */ -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) + /* Pacify GCC's 'empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) # ifndef YYSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely @@ -335,25 +353,23 @@ YYID (i) # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif -# if (defined __cplusplus && ! defined _STDLIB_H \ +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ -# ifndef _STDLIB_H -# define _STDLIB_H 1 +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc -# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) +# if ! defined malloc && ! defined EXIT_SUCCESS void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free -# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) +# if ! defined free && ! defined EXIT_SUCCESS void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif @@ -368,9 +384,9 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */ /* A type that is properly aligned for any stack member. */ union yyalloc { - yytype_int16 yyss; - YYSTYPE yyvs; - }; + yytype_int16 yyss_alloc; + YYSTYPE yyvs_alloc; +}; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) @@ -381,42 +397,46 @@ union yyalloc ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) -/* Copy COUNT objects from FROM to TO. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) -# else -# define YYCOPY(To, From, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ - } \ - while (YYID (0)) -# endif -# endif +# define YYCOPY_NEEDED 1 /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ -# define YYSTACK_RELOCATE(Stack) \ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ do \ { \ YYSIZE_T yynewbytes; \ - YYCOPY (&yyptr->Stack, Stack, yysize); \ - Stack = &yyptr->Stack; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ - while (YYID (0)) + while (0) #endif +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from SRC to DST. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) +# else +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ + while (0) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + /* YYFINAL -- State number of the termination state. */ #define YYFINAL 25 /* YYLAST -- Last index in YYTABLE. */ @@ -428,17 +448,19 @@ union yyalloc #define YYNNTS 10 /* YYNRULES -- Number of rules. */ #define YYNRULES 24 -/* YYNRULES -- Number of states. */ +/* YYNSTATES -- Number of states. */ #define YYNSTATES 33 -/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned + by yylex, with out-of-bounds checking. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 269 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) -/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, without out-of-bounds checking. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -471,36 +493,16 @@ static const yytype_uint8 yytranslate[] = }; #if YYDEBUG -/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in - YYRHS. */ -static const yytype_uint8 yyprhs[] = -{ - 0, 0, 3, 5, 7, 10, 11, 14, 16, 18, - 20, 22, 24, 26, 28, 30, 34, 38, 42, 44, - 46, 49, 50, 53, 55 -}; - -/* YYRHS -- A `-1'-separated list of the rules' RHS. */ -static const yytype_int8 yyrhs[] = -{ - 16, 0, -1, 17, -1, 18, -1, 18, 10, -1, - -1, 19, 18, -1, 20, -1, 21, -1, 9, -1, - 12, -1, 6, -1, 7, -1, 8, -1, 11, -1, - 3, 22, 8, -1, 4, 23, 8, -1, 5, 23, - 8, -1, 14, -1, 23, -1, 11, 22, -1, -1, - 24, 23, -1, 9, -1, 21, -1 -}; - -/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ + /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { - 0, 116, 116, 123, 128, 134, 138, 144, 149, 155, - 160, 165, 170, 175, 180, 186, 192, 198, 204, 210, - 215, 221, 225, 231, 236 + 0, 94, 94, 101, 106, 112, 116, 122, 127, 133, + 138, 143, 148, 153, 158, 164, 170, 176, 182, 188, + 193, 199, 203, 209, 214 }; #endif -#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +#if YYDEBUG || YYERROR_VERBOSE || 1 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = @@ -509,13 +511,13 @@ static const char *const yytname[] = "cal_DCURLY", "\"$\"", "\"{\"", "\"}\"", "cal_NAME", "\"\\\\\"", "cal_SYMBOL", "\"@\"", "cal_ERROR", "cal_ATNAME", "$accept", "Start", "GoalWithOptionalBackSlash", "Goal", "String", "OuterText", "Variable", - "EnvVarName", "MultipleIds", "ID", 0 + "EnvVarName", "MultipleIds", "ID", YY_NULLPTR }; #endif # ifdef YYPRINT -/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to - token YYLEX-NUM. */ +/* YYTOKNUM[NUM] -- (External) token number corresponding to the + (internal) symbol number NUM (which must be that of a token). */ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, @@ -523,25 +525,29 @@ static const yytype_uint16 yytoknum[] = }; # endif -/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const yytype_uint8 yyr1[] = -{ - 0, 15, 16, 17, 17, 18, 18, 19, 19, 20, - 20, 20, 20, 20, 20, 21, 21, 21, 21, 22, - 22, 23, 23, 24, 24 -}; +#define YYPACT_NINF -3 -/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ -static const yytype_uint8 yyr2[] = +#define yypact_value_is_default(Yystate) \ + (!!((Yystate) == (-3))) + +#define YYTABLE_NINF -1 + +#define yytable_value_is_error(Yytable_value) \ + 0 + + /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +static const yytype_int8 yypact[] = { - 0, 2, 1, 1, 2, 0, 2, 1, 1, 1, - 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, - 2, 0, 2, 1, 1 + 0, 14, 26, 26, -3, -3, -3, -3, -3, -3, + -3, 10, -3, 3, 0, -3, -3, -3, 14, -3, + 7, -3, 26, 13, 16, -3, -3, -3, -3, -3, + -3, -3, -3 }; -/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state - STATE-NUM when YYTABLE doesn't specify something else to do. Zero - means the default is an error. */ + /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE does not specify something else to do. Zero + means the default is an error. */ static const yytype_uint8 yydefact[] = { 5, 21, 21, 21, 11, 12, 13, 9, 14, 10, @@ -550,34 +556,21 @@ static const yytype_uint8 yydefact[] = 22, 16, 17 }; -/* YYDEFGOTO[NTERM-NUM]. */ -static const yytype_int8 yydefgoto[] = -{ - -1, 11, 12, 13, 14, 15, 19, 20, 21, 22 -}; - -/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing - STATE-NUM. */ -#define YYPACT_NINF -3 -static const yytype_int8 yypact[] = + /* YYPGOTO[NTERM-NUM]. */ +static const yytype_int8 yypgoto[] = { - 0, 14, 26, 26, -3, -3, -3, -3, -3, -3, - -3, 10, -3, 3, 0, -3, -3, -3, 14, -3, - 7, -3, 26, 13, 16, -3, -3, -3, -3, -3, - -3, -3, -3 + -3, -3, -3, 8, -3, -3, 2, 9, -2, -3 }; -/* YYPGOTO[NTERM-NUM]. */ -static const yytype_int8 yypgoto[] = + /* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int8 yydefgoto[] = { - -3, -3, -3, 8, -3, -3, 2, 9, -2, -3 + -1, 11, 12, 13, 14, 15, 19, 20, 21, 22 }; -/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule which - number is the opposite. If zero, do what YYDEFACT says. - If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -1 + /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule whose + number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_uint8 yytable[] = { 23, 24, 16, 1, 2, 3, 4, 5, 6, 7, @@ -596,8 +589,8 @@ static const yytype_int8 yycheck[] = 14 }; -/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing - symbol of state STATE-NUM. */ + /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { 0, 3, 4, 5, 6, 7, 8, 9, 11, 12, @@ -606,6 +599,23 @@ static const yytype_uint8 yystos[] = 23, 8, 8 }; + /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 15, 16, 17, 17, 18, 18, 19, 19, 20, + 20, 20, 20, 20, 20, 21, 21, 21, 21, 22, + 22, 23, 23, 24, 24 +}; + + /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 1, 1, 2, 0, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 3, 3, 3, 1, 1, + 2, 0, 2, 1, 1 +}; + + #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY (-2) @@ -616,85 +626,30 @@ static const yytype_uint8 yystos[] = #define YYERROR goto yyerrorlab -/* Like YYERROR except do call yyerror. This remains here temporarily - to ease the transition to the new meaning of YYERROR, for GCC. - Once GCC version 2 has supplanted version 1, this can go. */ - -#define YYFAIL goto yyerrlab - #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ - if (yychar == YYEMPTY && yylen == 1) \ + if (yychar == YYEMPTY) \ { \ yychar = (Token); \ yylval = (Value); \ - yytoken = YYTRANSLATE (yychar); \ - YYPOPSTACK (1); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ goto yybackup; \ } \ else \ { \ - yyerror (YY_("syntax error: cannot back up")); \ + yyerror (yyscanner, YY_("syntax error: cannot back up")); \ YYERROR; \ } \ -while (YYID (0)) - +while (0) +/* Error token number */ #define YYTERROR 1 #define YYERRCODE 256 -/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. - If N is 0, then set CURRENT to the empty location which ends - the previous symbol: RHS[0] (always defined). */ - -#define YYRHSLOC(Rhs, K) ((Rhs)[K]) -#ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - do \ - if (YYID (N)) \ - { \ - (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ - (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ - (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ - (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ - } \ - else \ - { \ - (Current).first_line = (Current).last_line = \ - YYRHSLOC (Rhs, 0).last_line; \ - (Current).first_column = (Current).last_column = \ - YYRHSLOC (Rhs, 0).last_column; \ - } \ - while (YYID (0)) -#endif - - -/* YY_LOCATION_PRINT -- Print the location on the stream. - This macro was not mandated originally: define only if we know - we won't break user code: when these are the locations we know. */ - -#ifndef YY_LOCATION_PRINT -# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL -# define YY_LOCATION_PRINT(File, Loc) \ - fprintf (File, "%d.%d-%d.%d", \ - (Loc).first_line, (Loc).first_column, \ - (Loc).last_line, (Loc).last_column) -# else -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -# endif -#endif - - -/* YYLEX -- calling `yylex' with the right arguments. */ - -#ifdef YYLEX_PARAM -# define YYLEX yylex (&yylval, YYLEX_PARAM) -#else -# define YYLEX yylex (&yylval) -#endif /* Enable debugging if requested. */ #if YYDEBUG @@ -708,7 +663,13 @@ while (YYID (0)) do { \ if (yydebug) \ YYFPRINTF Args; \ -} while (YYID (0)) +} while (0) + +/* This macro is provided for backward compatibility. */ +#ifndef YY_LOCATION_PRINT +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +#endif + # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ @@ -716,42 +677,29 @@ do { \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ - Type, Value); \ + Type, Value, yyscanner); \ YYFPRINTF (stderr, "\n"); \ } \ -} while (YYID (0)) +} while (0) -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ +/*----------------------------------------. +| Print this symbol's value on YYOUTPUT. | +`----------------------------------------*/ -/*ARGSUSED*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) -#else static void -yy_symbol_value_print (yyoutput, yytype, yyvaluep) - FILE *yyoutput; - int yytype; - YYSTYPE const * const yyvaluep; -#endif +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) { + FILE *yyo = yyoutput; + YYUSE (yyo); + YYUSE (yyscanner); if (!yyvaluep) return; # ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); -# else - YYUSE (yyoutput); # endif - switch (yytype) - { - default: - break; - } + YYUSE (yytype); } @@ -759,24 +707,13 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep) | Print this symbol on YYOUTPUT. | `--------------------------------*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) -#else -static void -yy_symbol_print (yyoutput, yytype, yyvaluep) - FILE *yyoutput; - int yytype; - YYSTYPE const * const yyvaluep; -#endif +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, yyscan_t yyscanner) { - if (yytype < YYNTOKENS) - YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); - else - YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + YYFPRINTF (yyoutput, "%s %s (", + yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); - yy_symbol_value_print (yyoutput, yytype, yyvaluep); + yy_symbol_value_print (yyoutput, yytype, yyvaluep, yyscanner); YYFPRINTF (yyoutput, ")"); } @@ -785,20 +722,15 @@ yy_symbol_print (yyoutput, yytype, yyvaluep) | TOP (included). | `------------------------------------------------------------------*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) static void -yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) -#else -static void -yy_stack_print (bottom, top) - yytype_int16 *bottom; - yytype_int16 *top; -#endif +yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) { YYFPRINTF (stderr, "Stack now"); - for (; bottom <= top; ++bottom) - YYFPRINTF (stderr, " %d", *bottom); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } YYFPRINTF (stderr, "\n"); } @@ -806,45 +738,38 @@ yy_stack_print (bottom, top) do { \ if (yydebug) \ yy_stack_print ((Bottom), (Top)); \ -} while (YYID (0)) +} while (0) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) static void -yy_reduce_print (YYSTYPE *yyvsp, int yyrule) -#else -static void -yy_reduce_print (yyvsp, yyrule) - YYSTYPE *yyvsp; - int yyrule; -#endif +yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, yyscan_t yyscanner) { + unsigned long int yylno = yyrline[yyrule]; int yynrhs = yyr2[yyrule]; int yyi; - unsigned long int yylno = yyrline[yyrule]; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", yyrule - 1, yylno); /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { - fprintf (stderr, " $%d = ", yyi + 1); - yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, + yystos[yyssp[yyi + 1 - yynrhs]], &(yyvsp[(yyi + 1) - (yynrhs)]) - ); - fprintf (stderr, "\n"); + , yyscanner); + YYFPRINTF (stderr, "\n"); } } # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ - yy_reduce_print (yyvsp, Rule); \ -} while (YYID (0)) + yy_reduce_print (yyssp, yyvsp, Rule, yyscanner); \ +} while (0) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ @@ -873,7 +798,6 @@ int yydebug; # define YYMAXDEPTH 10000 #endif - #if YYERROR_VERBOSE @@ -882,15 +806,8 @@ int yydebug; # define yystrlen strlen # else /* Return the length of YYSTR. */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) static YYSIZE_T yystrlen (const char *yystr) -#else -static YYSIZE_T -yystrlen (yystr) - const char *yystr; -#endif { YYSIZE_T yylen; for (yylen = 0; yystr[yylen]; yylen++) @@ -906,16 +823,8 @@ yystrlen (yystr) # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) static char * yystpcpy (char *yydest, const char *yysrc) -#else -static char * -yystpcpy (yydest, yysrc) - char *yydest; - const char *yysrc; -#endif { char *yyd = yydest; const char *yys = yysrc; @@ -976,165 +885,159 @@ yytnamerr (char *yyres, const char *yystr) } # endif -/* Copy into YYRESULT an error message about the unexpected token - YYCHAR while in state YYSTATE. Return the number of bytes copied, - including the terminating null byte. If YYRESULT is null, do not - copy anything; just return the number of bytes that would be - copied. As a special case, return 0 if an ordinary "syntax error" - message will do. Return YYSIZE_MAXIMUM if overflow occurs during - size calculation. */ -static YYSIZE_T -yysyntax_error (char *yyresult, int yystate, int yychar) -{ - int yyn = yypact[yystate]; +/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message + about the unexpected token YYTOKEN for the state stack whose top is + YYSSP. - if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) - return 0; - else + Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is + not large enough to hold the message. In that case, also set + *YYMSG_ALLOC to the required number of bytes. Return 2 if the + required number of bytes is too large to store. */ +static int +yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, + yytype_int16 *yyssp, int yytoken) +{ + YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]); + YYSIZE_T yysize = yysize0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + /* Internationalized format string. */ + const char *yyformat = YY_NULLPTR; + /* Arguments of yyformat. */ + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + /* Number of reported tokens (one for the "unexpected", one per + "expected"). */ + int yycount = 0; + + /* There are many possibilities here to consider: + - If this state is a consistent state with a default action, then + the only way this function was invoked is if the default action + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yychar) is if + this state is a consistent state with a default action. Thus, + detecting the absence of a lookahead is sufficient to determine + that there is no unexpected or expected token to report. In that + case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is a + consistent state with a default action. There might have been a + previous inconsistent state, consistent state with a non-default + action, or user semantic action that manipulated yychar. + - Of course, the expected token list depends on states to have + correct lookahead information, and it depends on the parser not + to perform extra reductions after fetching a lookahead from the + scanner and before detecting a syntax error. Thus, state merging + (from LALR or IELR) and default reductions corrupt the expected + token list. However, the list is correct for canonical LR with + one exception: it will still contain any token that will not be + accepted due to an error action in a later state. + */ + if (yytoken != YYEMPTY) { - int yytype = YYTRANSLATE (yychar); - YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); - YYSIZE_T yysize = yysize0; - YYSIZE_T yysize1; - int yysize_overflow = 0; - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - int yyx; - -# if 0 - /* This is so xgettext sees the translatable formats that are - constructed on the fly. */ - YY_("syntax error, unexpected %s"); - YY_("syntax error, unexpected %s, expecting %s"); - YY_("syntax error, unexpected %s, expecting %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); -# endif - char *yyfmt; - char const *yyf; - static char const yyunexpected[] = "syntax error, unexpected %s"; - static char const yyexpecting[] = ", expecting %s"; - static char const yyor[] = " or %s"; - char yyformat[sizeof yyunexpected - + sizeof yyexpecting - 1 - + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) - * (sizeof yyor - 1))]; - char const *yyprefix = yyexpecting; - - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yycount = 1; - - yyarg[0] = yytname[yytype]; - yyfmt = yystpcpy (yyformat, yyunexpected); - - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) - { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + int yyn = yypact[*yyssp]; + yyarg[yycount++] = yytname[yytoken]; + if (!yypact_value_is_default (yyn)) + { + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. In other words, skip the first -YYN actions for + this state because they are default actions. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yyx; + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR + && !yytable_value_is_error (yytable[yyx + yyn])) { - yycount = 1; - yysize = yysize0; - yyformat[sizeof yyunexpected - 1] = '\0'; - break; + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + break; + } + yyarg[yycount++] = yytname[yyx]; + { + YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } } - yyarg[yycount++] = yytname[yyx]; - yysize1 = yysize + yytnamerr (0, yytname[yyx]); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - yyfmt = yystpcpy (yyfmt, yyprefix); - yyprefix = yyor; - } + } + } + + switch (yycount) + { +# define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + YYCASE_(0, YY_("syntax error")); + YYCASE_(1, YY_("syntax error, unexpected %s")); + YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); + YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); + YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); + YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +# undef YYCASE_ + } - yyf = YY_(yyformat); - yysize1 = yysize + yystrlen (yyf); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; + { + YYSIZE_T yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } - if (yysize_overflow) - return YYSIZE_MAXIMUM; + if (*yymsg_alloc < yysize) + { + *yymsg_alloc = 2 * yysize; + if (! (yysize <= *yymsg_alloc + && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) + *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; + return 1; + } - if (yyresult) + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + { + char *yyp = *yymsg; + int yyi = 0; + while ((*yyp = *yyformat) != '\0') + if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) { - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - char *yyp = yyresult; - int yyi = 0; - while ((*yyp = *yyf) != '\0') - { - if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyf += 2; - } - else - { - yyp++; - yyf++; - } - } + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyformat += 2; } - return yysize; - } + else + { + yyp++; + yyformat++; + } + } + return 0; } #endif /* YYERROR_VERBOSE */ - /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ -/*ARGSUSED*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) -#else static void -yydestruct (yymsg, yytype, yyvaluep) - const char *yymsg; - int yytype; - YYSTYPE *yyvaluep; -#endif +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, yyscan_t yyscanner) { YYUSE (yyvaluep); - + YYUSE (yyscanner); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); - switch (yytype) - { - - default: - break; - } + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YYUSE (yytype); + YY_IGNORE_MAYBE_UNINITIALIZED_END } - - -/* Prevent warnings from -Wmissing-prototypes. */ - -#ifdef YYPARSE_PARAM -#if defined __STDC__ || defined __cplusplus -int yyparse (void *YYPARSE_PARAM); -#else -int yyparse (); -#endif -#else /* ! YYPARSE_PARAM */ -#if defined __STDC__ || defined __cplusplus -int yyparse (void); -#else -int yyparse (); -#endif -#endif /* ! YYPARSE_PARAM */ - - @@ -1143,99 +1046,76 @@ int yyparse (); | yyparse. | `----------*/ -#ifdef YYPARSE_PARAM -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -int -yyparse (void *YYPARSE_PARAM) -#else -int -yyparse (YYPARSE_PARAM) - void *YYPARSE_PARAM; -#endif -#else /* ! YYPARSE_PARAM */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -int -yyparse (void) -#else int -yyparse () - -#endif -#endif +yyparse (yyscan_t yyscanner) { - /* The look-ahead symbol. */ +/* The lookahead symbol. */ int yychar; -/* The semantic value of the look-ahead symbol. */ -YYSTYPE yylval; - -/* Number of syntax errors so far. */ -int yynerrs; - - int yystate; - int yyn; - int yyresult; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; - /* Look-ahead token as an internal (translated) token number. */ - int yytoken = 0; -#if YYERROR_VERBOSE - /* Buffer for error messages, and its allocated size. */ - char yymsgbuf[128]; - char *yymsg = yymsgbuf; - YYSIZE_T yymsg_alloc = sizeof yymsgbuf; -#endif - /* Three stacks and their tools: - `yyss': related to states, - `yyvs': related to semantic values, - `yyls': related to locations. +/* The semantic value of the lookahead symbol. */ +/* Default value used for initialization, for pacifying older GCCs + or non-GCC compilers. */ +YY_INITIAL_VALUE (static YYSTYPE yyval_default;) +YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); - Refer to the stacks thru separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ + /* Number of syntax errors so far. */ + int yynerrs; - /* The state stack. */ - yytype_int16 yyssa[YYINITDEPTH]; - yytype_int16 *yyss = yyssa; - yytype_int16 *yyssp; + int yystate; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; - /* The semantic value stack. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs = yyvsa; - YYSTYPE *yyvsp; + /* The stacks and their tools: + 'yyss': related to states. + 'yyvs': related to semantic values. + Refer to the stacks through separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss; + yytype_int16 *yyssp; -#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs; + YYSTYPE *yyvsp; - YYSIZE_T yystacksize = YYINITDEPTH; + YYSIZE_T yystacksize; + int yyn; + int yyresult; + /* Lookahead token as an internal (translated) token number. */ + int yytoken = 0; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int yylen = 0; + yyssp = yyss = yyssa; + yyvsp = yyvs = yyvsa; + yystacksize = YYINITDEPTH; + YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; - yychar = YYEMPTY; /* Cause a token to be read. */ - - /* Initialize stack pointers. - Waste one element of value and location stack - so that they stay on the same level as the state stack. - The wasted elements are never initialized. */ - - yyssp = yyss; - yyvsp = yyvs; - + yychar = YYEMPTY; /* Cause a token to be read. */ goto yysetstate; /*------------------------------------------------------------. @@ -1262,7 +1142,6 @@ int yynerrs; YYSTYPE *yyvs1 = yyvs; yytype_int16 *yyss1 = yyss; - /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might @@ -1270,7 +1149,6 @@ int yynerrs; yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), - &yystacksize); yyss = yyss1; @@ -1293,9 +1171,8 @@ int yynerrs; (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyexhaustedlab; - YYSTACK_RELOCATE (yyss); - YYSTACK_RELOCATE (yyvs); - + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); @@ -1306,7 +1183,6 @@ int yynerrs; yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; - YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); @@ -1316,6 +1192,9 @@ int yynerrs; YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + if (yystate == YYFINAL) + YYACCEPT; + goto yybackup; /*-----------. @@ -1324,20 +1203,20 @@ int yynerrs; yybackup: /* Do appropriate processing given the current state. Read a - look-ahead token if we need one and don't already have one. */ + lookahead token if we need one and don't already have one. */ - /* First try to decide what to do without reference to look-ahead token. */ + /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; - if (yyn == YYPACT_NINF) + if (yypact_value_is_default (yyn)) goto yydefault; - /* Not known => get a look-ahead token if don't already have one. */ + /* Not known => get a lookahead token if don't already have one. */ - /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); - yychar = YYLEX; + yychar = yylex (&yylval, yyscanner); } if (yychar <= YYEOF) @@ -1359,29 +1238,27 @@ yybackup: yyn = yytable[yyn]; if (yyn <= 0) { - if (yyn == 0 || yyn == YYTABLE_NINF) + if (yytable_value_is_error (yyn)) goto yyerrlab; yyn = -yyn; goto yyreduce; } - if (yyn == YYFINAL) - YYACCEPT; - /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; - /* Shift the look-ahead token. */ + /* Shift the lookahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - /* Discard the shifted token unless it is eof. */ - if (yychar != YYEOF) - yychar = YYEMPTY; + /* Discard the shifted token. */ + yychar = YYEMPTY; yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END goto yynewstate; @@ -1404,7 +1281,7 @@ yyreduce: yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: - `$$ = $1'. + '$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison @@ -1418,175 +1295,208 @@ yyreduce: switch (yyn) { case 2: -#line 117 "cmCommandArgumentParser.y" +#line 95 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = 0; - yyGetParser->SetResult((yyvsp[(1) - (1)].str)); + yyGetParser->SetResult((yyvsp[0].str)); } +#line 1304 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 3: -#line 124 "cmCommandArgumentParser.y" +#line 102 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[(1) - (1)].str); + (yyval.str) = (yyvsp[0].str); } +#line 1312 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 4: -#line 129 "cmCommandArgumentParser.y" +#line 107 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = yyGetParser->CombineUnions((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].str)); + (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); } +#line 1320 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 5: -#line 134 "cmCommandArgumentParser.y" +#line 112 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = 0; } +#line 1328 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 6: -#line 139 "cmCommandArgumentParser.y" +#line 117 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = yyGetParser->CombineUnions((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].str)); + (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); } +#line 1336 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 7: -#line 145 "cmCommandArgumentParser.y" +#line 123 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[(1) - (1)].str); + (yyval.str) = (yyvsp[0].str); } +#line 1344 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 8: -#line 150 "cmCommandArgumentParser.y" +#line 128 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[(1) - (1)].str); + (yyval.str) = (yyvsp[0].str); } +#line 1352 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 9: -#line 156 "cmCommandArgumentParser.y" +#line 134 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[(1) - (1)].str); + (yyval.str) = (yyvsp[0].str); } +#line 1360 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 10: -#line 161 "cmCommandArgumentParser.y" +#line 139 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[(1) - (1)].str); + (yyval.str) = (yyvsp[0].str); } +#line 1368 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 11: -#line 166 "cmCommandArgumentParser.y" +#line 144 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[(1) - (1)].str); + (yyval.str) = (yyvsp[0].str); } +#line 1376 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 12: -#line 171 "cmCommandArgumentParser.y" +#line 149 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[(1) - (1)].str); + (yyval.str) = (yyvsp[0].str); } +#line 1384 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 13: -#line 176 "cmCommandArgumentParser.y" +#line 154 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[(1) - (1)].str); + (yyval.str) = (yyvsp[0].str); } +#line 1392 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 14: -#line 181 "cmCommandArgumentParser.y" +#line 159 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[(1) - (1)].str); + (yyval.str) = (yyvsp[0].str); } +#line 1400 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 15: -#line 187 "cmCommandArgumentParser.y" +#line 165 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[(1) - (3)].str),(yyvsp[(2) - (3)].str)); + (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str),(yyvsp[-1].str)); //std::cerr << __LINE__ << " here: [" << $1 << "] [" << $2 << "] [" << $3 << "]" << std::endl; } +#line 1409 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 16: -#line 193 "cmCommandArgumentParser.y" +#line 171 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[(1) - (3)].str),(yyvsp[(2) - (3)].str)); + (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str),(yyvsp[-1].str)); //std::cerr << __LINE__ << " here: [" << $1 << "] [" << $2 << "] [" << $3 << "]" << std::endl; } +#line 1418 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 17: -#line 199 "cmCommandArgumentParser.y" +#line 177 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = yyGetParser->ExpandVariable((yyvsp[(2) - (3)].str)); + (yyval.str) = yyGetParser->ExpandVariable((yyvsp[-1].str)); //std::cerr << __LINE__ << " here: [" << $1 << "] [" << $2 << "] [" << $3 << "]" << std::endl; } +#line 1427 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 18: -#line 205 "cmCommandArgumentParser.y" +#line 183 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = yyGetParser->ExpandVariableForAt((yyvsp[(1) - (1)].str)); + (yyval.str) = yyGetParser->ExpandVariableForAt((yyvsp[0].str)); } +#line 1435 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 19: -#line 211 "cmCommandArgumentParser.y" +#line 189 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[(1) - (1)].str); + (yyval.str) = (yyvsp[0].str); } +#line 1443 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 20: -#line 216 "cmCommandArgumentParser.y" +#line 194 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[(1) - (2)].str); + (yyval.str) = (yyvsp[-1].str); } +#line 1451 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 21: -#line 221 "cmCommandArgumentParser.y" +#line 199 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = 0; } +#line 1459 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 22: -#line 226 "cmCommandArgumentParser.y" +#line 204 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = yyGetParser->CombineUnions((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].str)); + (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); } +#line 1467 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 23: -#line 232 "cmCommandArgumentParser.y" +#line 210 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[(1) - (1)].str); + (yyval.str) = (yyvsp[0].str); } +#line 1475 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 24: -#line 237 "cmCommandArgumentParser.y" +#line 215 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { - (yyval.str) = (yyvsp[(1) - (1)].str); + (yyval.str) = (yyvsp[0].str); } +#line 1483 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; -/* Line 1267 of yacc.c. */ -#line 1606 "cmCommandArgumentParser.cxx" +#line 1487 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ default: break; } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); @@ -1595,8 +1505,7 @@ yyreduce: *++yyvsp = yyval; - - /* Now `shift' the result of the reduction. Determine what state + /* Now 'shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ @@ -1611,48 +1520,51 @@ yyreduce: goto yynewstate; -/*------------------------------------. -| yyerrlab -- here on detecting error | -`------------------------------------*/ +/*--------------------------------------. +| yyerrlab -- here on detecting error. | +`--------------------------------------*/ yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); + /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; #if ! YYERROR_VERBOSE - yyerror (YY_("syntax error")); + yyerror (yyscanner, YY_("syntax error")); #else +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ + yyssp, yytoken) { - YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); - if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + char const *yymsgp = YY_("syntax error"); + int yysyntax_error_status; + yysyntax_error_status = YYSYNTAX_ERROR; + if (yysyntax_error_status == 0) + yymsgp = yymsg; + else if (yysyntax_error_status == 1) { - YYSIZE_T yyalloc = 2 * yysize; - if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) - yyalloc = YYSTACK_ALLOC_MAXIMUM; if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yyalloc); - if (yymsg) - yymsg_alloc = yyalloc; - else + yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); + if (!yymsg) { yymsg = yymsgbuf; yymsg_alloc = sizeof yymsgbuf; + yysyntax_error_status = 2; + } + else + { + yysyntax_error_status = YYSYNTAX_ERROR; + yymsgp = yymsg; } } - - if (0 < yysize && yysize <= yymsg_alloc) - { - (void) yysyntax_error (yymsg, yystate, yychar); - yyerror (yymsg); - } - else - { - yyerror (YY_("syntax error")); - if (yysize != 0) - goto yyexhaustedlab; - } + yyerror (yyscanner, yymsgp); + if (yysyntax_error_status == 2) + goto yyexhaustedlab; } +# undef YYSYNTAX_ERROR #endif } @@ -1660,7 +1572,7 @@ yyerrlab: if (yyerrstatus == 3) { - /* If just tried and failed to reuse look-ahead token after an + /* If just tried and failed to reuse lookahead token after an error, discard it. */ if (yychar <= YYEOF) @@ -1672,12 +1584,13 @@ yyerrlab: else { yydestruct ("Error: discarding", - yytoken, &yylval); + yytoken, &yylval, yyscanner); yychar = YYEMPTY; } } - /* Else will try to reuse look-ahead token after shifting the error +#if 0 + /* Else will try to reuse lookahead token after shifting the error token. */ goto yyerrlab1; @@ -1693,7 +1606,7 @@ yyerrorlab: if (/*CONSTCOND*/ 0) goto yyerrorlab; - /* Do not reclaim the symbols of the rule which action triggered + /* Do not reclaim the symbols of the rule whose action triggered this YYERROR. */ YYPOPSTACK (yylen); yylen = 0; @@ -1706,12 +1619,13 @@ yyerrorlab: | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: +#endif yyerrstatus = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact[yystate]; - if (yyn != YYPACT_NINF) + if (!yypact_value_is_default (yyn)) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) @@ -1728,16 +1642,15 @@ yyerrlab1: yydestruct ("Error: popping", - yystos[yystate], yyvsp); + yystos[yystate], yyvsp, yyscanner); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } - if (yyn == YYFINAL) - YYACCEPT; - + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END /* Shift the error token. */ @@ -1761,28 +1674,33 @@ yyabortlab: yyresult = 1; goto yyreturn; -#ifndef yyoverflow +#if !defined yyoverflow || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: - yyerror (YY_("memory exhausted")); + yyerror (yyscanner, YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif yyreturn: - if (yychar != YYEOF && yychar != YYEMPTY) - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval); - /* Do not reclaim the symbols of the rule which action triggered + if (yychar != YYEMPTY) + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval, yyscanner); + } + /* Do not reclaim the symbols of the rule whose action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); YY_STACK_PRINT (yyss, yyssp); while (yyssp != yyss) { yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp); + yystos[*yyssp], yyvsp, yyscanner); YYPOPSTACK (1); } #ifndef yyoverflow @@ -1793,19 +1711,14 @@ yyreturn: if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); #endif - /* Make sure YYID is used. */ - return YYID (yyresult); + return yyresult; } - - -#line 242 "cmCommandArgumentParser.y" +#line 220 "cmCommandArgumentParser.y" /* yacc.c:1906 */ /* End of grammar */ /*--------------------------------------------------------------------------*/ -void cmCommandArgumentError(yyscan_t yyscanner, const char* message) +void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message) { yyGetParser->Error(message); } - - diff --git a/Source/cmCommandArgumentParser.y b/Source/cmCommandArgumentParser.y index b2f4b1b..9a9ba10 100644 --- a/Source/cmCommandArgumentParser.y +++ b/Source/cmCommandArgumentParser.y @@ -10,20 +10,12 @@ Run bison like this: bison --yacc --name-prefix=cmCommandArgument_yy --defines=cmCommandArgumentParserTokens.h -ocmCommandArgumentParser.cxx cmCommandArgumentParser.y Modify cmCommandArgumentParser.cxx: - - remove TABs - - remove use of the 'register' storage class specifier - - put header block at top of file + - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"] */ #include "cmStandardIncludes.h" -/* Configure the parser to use a lexer object. */ -#define YYPARSE_PARAM yyscanner -#define YYLEX_PARAM yyscanner -#define YYERROR_VERBOSE 1 -#define cmCommandArgument_yyerror(x) \ - cmCommandArgumentError(yyscanner, x) #define yyGetParser (cmCommandArgument_yyget_extra(yyscanner)) /* Make sure malloc and free are available on QNX. */ @@ -46,10 +38,9 @@ Modify cmCommandArgumentParser.cxx: /* Forward declare the lexer entry point. */ YY_DECL; -/* Internal utility functions. */ -static void cmCommandArgumentError(yyscan_t yyscanner, const char* message); +/* Helper function to forward error callback from parser. */ +static void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message); -#define YYDEBUG 1 /* Configure the parser to support large input. */ #define YYMAXDEPTH 100000 #define YYINITDEPTH 10000 @@ -65,7 +56,13 @@ static void cmCommandArgumentError(yyscan_t yyscanner, const char* message); %} /* Generate a reentrant parser object. */ -%pure_parser +%define api.pure + +/* Configure the parser to use a lexer object. */ +%lex-param {yyscan_t yyscanner} +%parse-param {yyscan_t yyscanner} + +%define parse.error verbose /* %union { @@ -224,7 +221,7 @@ Variable /* End of grammar */ /*--------------------------------------------------------------------------*/ -void cmCommandArgumentError(yyscan_t yyscanner, const char* message) +void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message) { yyGetParser->Error(message); } diff --git a/Source/cmCommandArgumentParserTokens.h b/Source/cmCommandArgumentParserTokens.h index d162b82..3172182 100644 --- a/Source/cmCommandArgumentParserTokens.h +++ b/Source/cmCommandArgumentParserTokens.h @@ -1,16 +1,13 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -/* A Bison parser, made by GNU Bison 2.3. */ +/* A Bison parser, made by GNU Bison 3.0.4. */ -/* Skeleton interface for Bison's Yacc-like parsers in C +/* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 - Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. - This program is free software; you can redistribute it and/or modify + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -18,9 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. */ + along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -35,25 +30,34 @@ This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ -/* Tokens. */ +#ifndef YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED +# define YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int cmCommandArgument_yydebug; +#endif + +/* Token type. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - enum yytokentype { - cal_ENVCURLY = 258, - cal_NCURLY = 259, - cal_DCURLY = 260, - cal_DOLLAR = 261, - cal_LCURLY = 262, - cal_RCURLY = 263, - cal_NAME = 264, - cal_BSLASH = 265, - cal_SYMBOL = 266, - cal_AT = 267, - cal_ERROR = 268, - cal_ATNAME = 269 - }; + enum yytokentype + { + cal_ENVCURLY = 258, + cal_NCURLY = 259, + cal_DCURLY = 260, + cal_DOLLAR = 261, + cal_LCURLY = 262, + cal_RCURLY = 263, + cal_NAME = 264, + cal_BSLASH = 265, + cal_SYMBOL = 266, + cal_AT = 267, + cal_ERROR = 268, + cal_ATNAME = 269 + }; #endif /* Tokens. */ #define cal_ENVCURLY 258 @@ -69,15 +73,10 @@ #define cal_ERROR 268 #define cal_ATNAME 269 +/* Value type. */ -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -typedef int YYSTYPE; -# define yystype YYSTYPE /* obsolescent; will be withdrawn */ -# define YYSTYPE_IS_DECLARED 1 -# define YYSTYPE_IS_TRIVIAL 1 -#endif - - +int cmCommandArgument_yyparse (yyscan_t yyscanner); +#endif /* !YY_CMCOMMANDARGUMENT_YY_CMCOMMANDARGUMENTPARSERTOKENS_H_INCLUDED */ ----------------------------------------------------------------------- Summary of changes: Source/cmCommandArgumentParser.cxx | 1328 +++++------ Source/cmCommandArgumentParser.y | 205 +- Source/cmCommandArgumentParserTokens.h | 73 +- Source/cmDependsJavaParser.cxx | 3959 ++++++++++++++++++-------------- Source/cmDependsJavaParser.y | 25 +- Source/cmDependsJavaParserTokens.h | 272 +-- 6 files changed, 3073 insertions(+), 2789 deletions(-) hooks/post-receive -- CMake From kwrobot at kitware.com Fri Feb 17 00:01:06 2017 From: kwrobot at kitware.com (Kitware Robot) Date: Fri, 17 Feb 2017 00:01:06 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-128-gb6c9a85 Message-ID: <20170217050107.BE6DDF9D7A@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via b6c9a851cba4f28bf0614b145803dc46096b6cde (commit) from c508fd8481d87aef7843942ba186d3dea4246c7f (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b6c9a851cba4f28bf0614b145803dc46096b6cde commit b6c9a851cba4f28bf0614b145803dc46096b6cde Author: Kitware Robot AuthorDate: Fri Feb 17 00:01:02 2017 -0500 Commit: Kitware Robot CommitDate: Fri Feb 17 00:01:02 2017 -0500 CMake Nightly Date Stamp diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index a92cb20..24d45c5 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 8) -set(CMake_VERSION_PATCH 20170216) +set(CMake_VERSION_PATCH 20170217) #set(CMake_VERSION_RC 1) ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 17 08:45:39 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 17 Feb 2017 08:45:39 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-131-g261b578 Message-ID: <20170217134539.D27DCF3720@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 261b5785adbadd994c5f8869766f5c1017cbf721 (commit) via f10b2f72f6979ccb16410d97bac98c440eb7f992 (commit) via ef399f9bc6b8e2ff917a5f2809346fb81fd954ae (commit) from b6c9a851cba4f28bf0614b145803dc46096b6cde (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=261b5785adbadd994c5f8869766f5c1017cbf721 commit 261b5785adbadd994c5f8869766f5c1017cbf721 Merge: b6c9a85 f10b2f7 Author: Brad King AuthorDate: Fri Feb 17 08:45:36 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 17 08:45:36 2017 -0500 Merge topic 'capture-ctest_update-svn-failures' f10b2f72 ctest_update: Capture failure of svn to load revisions and local mods ef399f9b ctest_update: Refactor internal APIs to support more failure cases ----------------------------------------------------------------------- Summary of changes: Source/CTest/cmCTestBZR.cxx | 14 +++++++++----- Source/CTest/cmCTestBZR.h | 8 ++++---- Source/CTest/cmCTestGIT.cxx | 12 ++++++++---- Source/CTest/cmCTestGIT.h | 8 ++++---- Source/CTest/cmCTestGlobalVC.cxx | 7 ++++--- Source/CTest/cmCTestGlobalVC.h | 4 ++-- Source/CTest/cmCTestHG.cxx | 12 ++++++++---- Source/CTest/cmCTestHG.h | 8 ++++---- Source/CTest/cmCTestP4.cxx | 16 ++++++++++------ Source/CTest/cmCTestP4.h | 8 ++++---- Source/CTest/cmCTestSVN.cxx | 33 +++++++++++++++++++++------------ Source/CTest/cmCTestSVN.h | 12 ++++++------ Source/CTest/cmCTestUpdateHandler.cxx | 4 ++-- Source/CTest/cmCTestVC.cxx | 12 +++++++----- Source/CTest/cmCTestVC.h | 4 ++-- 15 files changed, 95 insertions(+), 67 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 17 08:46:06 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 17 Feb 2017 08:46:06 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-133-g5febec7 Message-ID: <20170217134606.C2061F3707@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 5febec7a4b3069f3661887ecc0e6b24d7d169fcf (commit) via 9b78dca3a909ce3161d235718f935bf2fb9b7f64 (commit) from 261b5785adbadd994c5f8869766f5c1017cbf721 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=5febec7a4b3069f3661887ecc0e6b24d7d169fcf commit 5febec7a4b3069f3661887ecc0e6b24d7d169fcf Merge: 261b578 9b78dca Author: Brad King AuthorDate: Fri Feb 17 08:46:03 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 17 08:46:03 2017 -0500 Merge topic 'FindOpenSSL-crypto-name' 9b78dca3 FindOpenSSL: Add another name for libcrypto with MSVC ----------------------------------------------------------------------- Summary of changes: Modules/FindOpenSSL.cmake | 1 + 1 file changed, 1 insertion(+) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 17 08:46:13 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 17 Feb 2017 08:46:13 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-137-g988c635 Message-ID: <20170217134613.5EDC4F3B63@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 988c63527ded3cfcb0469532a00c12abe7bc8d0c (commit) via 761ea20518081de976a40e590577056f23188fbd (commit) via 1728b9c076a34ef017f10499e5b637d025b2afd8 (commit) via fe75e140d617dd2d8401a85c718d03a6466a8bd9 (commit) from 5febec7a4b3069f3661887ecc0e6b24d7d169fcf (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=988c63527ded3cfcb0469532a00c12abe7bc8d0c commit 988c63527ded3cfcb0469532a00c12abe7bc8d0c Merge: 5febec7 761ea20 Author: Brad King AuthorDate: Fri Feb 17 08:46:11 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 17 08:46:11 2017 -0500 Merge topic 'bison3' 761ea205 cmCommandArgumentParser: reformat grammar 1728b9c0 cmDependsJavaParser: Port to bison 3 fe75e140 cmCommandArgumentParser: Port to bison 3 ----------------------------------------------------------------------- Summary of changes: Source/cmCommandArgumentParser.cxx | 1328 +++++------ Source/cmCommandArgumentParser.y | 205 +- Source/cmCommandArgumentParserTokens.h | 73 +- Source/cmDependsJavaParser.cxx | 3959 ++++++++++++++++++-------------- Source/cmDependsJavaParser.y | 25 +- Source/cmDependsJavaParserTokens.h | 272 +-- 6 files changed, 3073 insertions(+), 2789 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 17 08:46:17 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 17 Feb 2017 08:46:17 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-142-gf3e8a89 Message-ID: <20170217134617.AF1AEF38A4@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via f3e8a89a9b9a859b0e55abe474f85858a3cb2f40 (commit) via 1ba91291e3237e5535a46c6ff1bce6a33d298a76 (commit) via f7b9bf41c5386dfc38b7a722f75b0e23a02d542b (commit) via 4bff2d14fd3010ba4aa1bfc3eda2fb2cdcc5da0f (commit) via 624fb9d7175ee011f8a86c8d7614be4806a53184 (commit) from 988c63527ded3cfcb0469532a00c12abe7bc8d0c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f3e8a89a9b9a859b0e55abe474f85858a3cb2f40 commit f3e8a89a9b9a859b0e55abe474f85858a3cb2f40 Merge: 988c635 1ba9129 Author: Brad King AuthorDate: Fri Feb 17 08:46:14 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 17 08:46:14 2017 -0500 Merge topic 'install_name_policy' 1ba91291 Add policy CMP0068 separate install_name and RPATH settings on macOS f7b9bf41 Apple: Add BUILD_WITH_INSTALL_NAME_DIR target property 4bff2d14 Apple: Refactor support for using INSTALL_NAME_DIR. 624fb9d7 Help: Format BUILD_WITH_INSTALL_RPATH documentation ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-policies.7.rst | 8 ++ Help/manual/cmake-properties.7.rst | 1 + Help/manual/cmake-variables.7.rst | 1 + Help/policy/CMP0068.rst | 35 ++++++++ Help/prop_tgt/BUILD_WITH_INSTALL_NAME_DIR.rst | 13 +++ Help/prop_tgt/BUILD_WITH_INSTALL_RPATH.rst | 18 ++-- Help/release/dev/install_name_policy.rst | 11 +++ .../variable/CMAKE_BUILD_WITH_INSTALL_NAME_DIR.rst | 7 ++ Source/cmGeneratorTarget.cxx | 86 +++++++++++++++----- Source/cmGeneratorTarget.h | 10 +++ Source/cmGlobalGenerator.cxx | 25 ++++++ Source/cmGlobalGenerator.h | 3 + Source/cmPolicies.h | 8 +- Source/cmTarget.cxx | 1 + .../CMP0068-NEW-result.txt} | 0 Tests/RunCMake/CMP0068/CMP0068-NEW.cmake | 6 ++ .../CMP0068-OLD-result.txt} | 0 Tests/RunCMake/CMP0068/CMP0068-OLD.cmake | 6 ++ .../CMP0068-WARN-result.txt} | 0 Tests/RunCMake/CMP0068/CMP0068-WARN-stderr.txt | 12 +++ .../CMP0068-WARN.cmake} | 3 + Tests/RunCMake/{CMP0051 => CMP0068}/CMakeLists.txt | 2 +- Tests/RunCMake/CMP0068/RunCMakeTest.cmake | 5 ++ .../Export => RunCMake/CMP0068}/empty.cpp | 0 Tests/RunCMake/CMakeLists.txt | 3 + .../RunCMake/TargetPolicies/PolicyList-stderr.txt | 1 + Tests/RunCMake/install/EXPORT-OldIFace.cmake | 1 + 27 files changed, 236 insertions(+), 30 deletions(-) create mode 100644 Help/policy/CMP0068.rst create mode 100644 Help/prop_tgt/BUILD_WITH_INSTALL_NAME_DIR.rst create mode 100644 Help/release/dev/install_name_policy.rst create mode 100644 Help/variable/CMAKE_BUILD_WITH_INSTALL_NAME_DIR.rst copy Tests/RunCMake/{CMP0022/CMP0022-WARN-empty-old-result.txt => CMP0068/CMP0068-NEW-result.txt} (100%) create mode 100644 Tests/RunCMake/CMP0068/CMP0068-NEW.cmake copy Tests/RunCMake/{CMP0022/CMP0022-WARN-empty-old-result.txt => CMP0068/CMP0068-OLD-result.txt} (100%) create mode 100644 Tests/RunCMake/CMP0068/CMP0068-OLD.cmake copy Tests/RunCMake/{CMP0022/CMP0022-WARN-empty-old-result.txt => CMP0068/CMP0068-WARN-result.txt} (100%) create mode 100644 Tests/RunCMake/CMP0068/CMP0068-WARN-stderr.txt copy Tests/RunCMake/{CMP0042/CMP0042-WARN.cmake => CMP0068/CMP0068-WARN.cmake} (69%) copy Tests/RunCMake/{CMP0051 => CMP0068}/CMakeLists.txt (63%) create mode 100644 Tests/RunCMake/CMP0068/RunCMakeTest.cmake copy Tests/{ExportImport/Export => RunCMake/CMP0068}/empty.cpp (100%) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 17 08:47:28 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 17 Feb 2017 08:47:28 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-228-gf80f94e Message-ID: <20170217134728.2EFA1F484D@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via f80f94e6538a62d6de430c12630e15ecfd902830 (commit) via f3e8a89a9b9a859b0e55abe474f85858a3cb2f40 (commit) via 988c63527ded3cfcb0469532a00c12abe7bc8d0c (commit) via 5febec7a4b3069f3661887ecc0e6b24d7d169fcf (commit) via 261b5785adbadd994c5f8869766f5c1017cbf721 (commit) via b6c9a851cba4f28bf0614b145803dc46096b6cde (commit) from e889750e7bce9750ef1f8cc505e77ead0b5aad1d (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f80f94e6538a62d6de430c12630e15ecfd902830 commit f80f94e6538a62d6de430c12630e15ecfd902830 Merge: e889750 f3e8a89 Author: Brad King AuthorDate: Fri Feb 17 08:47:17 2017 -0500 Commit: Brad King CommitDate: Fri Feb 17 08:47:17 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 17 09:17:55 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 17 Feb 2017 09:17:55 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-230-g75b0769 Message-ID: <20170217141756.28C7DFA2D2@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 75b076980b1522345e07bc3db45a13874896bae2 (commit) via 28bb68e3472a9f8c6d8eec894e85de74b976ff02 (commit) from f80f94e6538a62d6de430c12630e15ecfd902830 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=75b076980b1522345e07bc3db45a13874896bae2 commit 75b076980b1522345e07bc3db45a13874896bae2 Merge: f80f94e 28bb68e Author: Brad King AuthorDate: Fri Feb 17 09:17:53 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 17 09:17:53 2017 -0500 Merge topic 'FindHDF5-include-dir-advanced' into next 28bb68e3 FindHDF5: Restore HDF5__INCLUDE_DIR advanced cache entry mark https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=28bb68e3472a9f8c6d8eec894e85de74b976ff02 commit 28bb68e3472a9f8c6d8eec894e85de74b976ff02 Author: Brad King AuthorDate: Fri Feb 17 09:07:18 2017 -0500 Commit: Brad King CommitDate: Fri Feb 17 09:10:03 2017 -0500 FindHDF5: Restore HDF5__INCLUDE_DIR advanced cache entry mark Refactoring in commit v3.6.0-rc1~72^2 (HDF5: Rework component searching to correctly find HL for all bindings, 2016-05-12) renamed the language loop variable used to construct the name of `HDF5__INCLUDE_DIR` but forgot to update it in the `mark_as_advanced` call. Fix it now. Issue: #16651 diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake index e1199a7..fb97d68 100644 --- a/Modules/FindHDF5.cmake +++ b/Modules/FindHDF5.cmake @@ -680,7 +680,7 @@ if( NOT HDF5_FOUND ) PATH_SUFFIXES include Include ${_HDF5_SEARCH_OPTS} ) - mark_as_advanced(HDF5_${LANGUAGE}_INCLUDE_DIR) + mark_as_advanced(HDF5_${__lang}_INCLUDE_DIR) list(APPEND HDF5_INCLUDE_DIRS ${HDF5_${__lang}_INCLUDE_DIR}) # find the HDF5 libraries ----------------------------------------------------------------------- Summary of changes: Modules/FindHDF5.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 17 09:18:46 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 17 Feb 2017 09:18:46 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-144-gc58b092 Message-ID: <20170217141846.8933CFA334@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via c58b0926a7941096e77a7d75760f68523cb01107 (commit) via 28bb68e3472a9f8c6d8eec894e85de74b976ff02 (commit) from f3e8a89a9b9a859b0e55abe474f85858a3cb2f40 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c58b0926a7941096e77a7d75760f68523cb01107 commit c58b0926a7941096e77a7d75760f68523cb01107 Merge: f3e8a89 28bb68e Author: Brad King AuthorDate: Fri Feb 17 09:18:44 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 17 09:18:44 2017 -0500 Merge topic 'FindHDF5-include-dir-advanced' 28bb68e3 FindHDF5: Restore HDF5__INCLUDE_DIR advanced cache entry mark ----------------------------------------------------------------------- Summary of changes: Modules/FindHDF5.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 17 09:19:30 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 17 Feb 2017 09:19:30 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-232-g2ba45d5 Message-ID: <20170217141932.E2AE4FA336@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 2ba45d5adf671b82ed11aa994b920e988d0500a9 (commit) via c58b0926a7941096e77a7d75760f68523cb01107 (commit) from 75b076980b1522345e07bc3db45a13874896bae2 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=2ba45d5adf671b82ed11aa994b920e988d0500a9 commit 2ba45d5adf671b82ed11aa994b920e988d0500a9 Merge: 75b0769 c58b092 Author: Brad King AuthorDate: Fri Feb 17 09:19:22 2017 -0500 Commit: Brad King CommitDate: Fri Feb 17 09:19:22 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 17 09:32:55 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 17 Feb 2017 09:32:55 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-234-g829748c Message-ID: <20170217143255.99746FA632@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 829748c7d25f49059e79031fc747ccf75fe11242 (commit) via 96d6139386e22f672f14071eae3911fd7200f079 (commit) from 2ba45d5adf671b82ed11aa994b920e988d0500a9 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=829748c7d25f49059e79031fc747ccf75fe11242 commit 829748c7d25f49059e79031fc747ccf75fe11242 Merge: 2ba45d5 96d6139 Author: Brad King AuthorDate: Fri Feb 17 09:32:53 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 17 09:32:53 2017 -0500 Merge topic 'FindHDF5-fix-header-langs' into next 96d61393 FindHDF5: Fix search for language-specific header file https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=96d6139386e22f672f14071eae3911fd7200f079 commit 96d6139386e22f672f14071eae3911fd7200f079 Author: Brad King AuthorDate: Fri Feb 17 09:21:02 2017 -0500 Commit: Brad King CommitDate: Fri Feb 17 09:25:46 2017 -0500 FindHDF5: Fix search for language-specific header file Refactoring in commit v3.6.0-rc1~85^2 (HDF5: Refactor the use of compiler wrappers, 2016-04-04) converted code of the form if(${LANGUAGE} MATCHES ...) to if(LANGUAGE MATCHES ...) However, `LANGUAGE` is a foreach() loop variable and not a normal variable so auto-dereference does not occur. Restore the explicit `${}` syntax and use the new name of the loop variable that has changed since then too. Fixes: #16651 diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake index fb97d68..65a825d 100644 --- a/Modules/FindHDF5.cmake +++ b/Modules/FindHDF5.cmake @@ -666,9 +666,9 @@ if( NOT HDF5_FOUND ) foreach(__lang IN LISTS HDF5_LANGUAGE_BINDINGS) # find the HDF5 include directories - if(LANGUAGE STREQUAL "Fortran") + if("${__lang}" STREQUAL "Fortran") set(HDF5_INCLUDE_FILENAME hdf5.mod) - elseif(LANGUAGE STREQUAL "CXX") + elseif("${__lang}" STREQUAL "CXX") set(HDF5_INCLUDE_FILENAME H5Cpp.h) else() set(HDF5_INCLUDE_FILENAME hdf5.h) ----------------------------------------------------------------------- Summary of changes: Modules/FindHDF5.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 17 09:32:59 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 17 Feb 2017 09:32:59 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-146-gdbdd25b Message-ID: <20170217143300.3F7741C29@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via dbdd25bc95af100633008a31f1bbdf7146e211f7 (commit) via 96d6139386e22f672f14071eae3911fd7200f079 (commit) from c58b0926a7941096e77a7d75760f68523cb01107 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=dbdd25bc95af100633008a31f1bbdf7146e211f7 commit dbdd25bc95af100633008a31f1bbdf7146e211f7 Merge: c58b092 96d6139 Author: Brad King AuthorDate: Fri Feb 17 09:32:57 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 17 09:32:57 2017 -0500 Merge topic 'FindHDF5-fix-header-langs' 96d61393 FindHDF5: Fix search for language-specific header file ----------------------------------------------------------------------- Summary of changes: Modules/FindHDF5.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 17 09:33:25 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 17 Feb 2017 09:33:25 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-236-g477b3d2 Message-ID: <20170217143325.B4D50FA64F@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 477b3d2aee0dbd793710556ef798e8189cf7bcd5 (commit) via dbdd25bc95af100633008a31f1bbdf7146e211f7 (commit) from 829748c7d25f49059e79031fc747ccf75fe11242 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=477b3d2aee0dbd793710556ef798e8189cf7bcd5 commit 477b3d2aee0dbd793710556ef798e8189cf7bcd5 Merge: 829748c dbdd25b Author: Brad King AuthorDate: Fri Feb 17 09:33:09 2017 -0500 Commit: Brad King CommitDate: Fri Feb 17 09:33:09 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 17 11:42:16 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 17 Feb 2017 11:42:16 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-238-g8cf6ac2 Message-ID: <20170217164216.9DB70F38A4@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 8cf6ac2226d23ac78cea34ddfae28e1626d289e1 (commit) via d32f9debc80e1fc90efb07392f829d998cbbc2c5 (commit) from 477b3d2aee0dbd793710556ef798e8189cf7bcd5 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8cf6ac2226d23ac78cea34ddfae28e1626d289e1 commit 8cf6ac2226d23ac78cea34ddfae28e1626d289e1 Merge: 477b3d2 d32f9de Author: Brad King AuthorDate: Fri Feb 17 11:42:15 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 17 11:42:15 2017 -0500 Merge topic 'productbuild_component_plist' into next d32f9deb CPack: Add option to specify --component-plist for productbuild https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d32f9debc80e1fc90efb07392f829d998cbbc2c5 commit d32f9debc80e1fc90efb07392f829d998cbbc2c5 Author: Tim Hutt AuthorDate: Tue Feb 14 13:18:42 2017 +0000 Commit: Brad King CommitDate: Fri Feb 17 11:40:45 2017 -0500 CPack: Add option to specify --component-plist for productbuild When using the productbuild generator this lets you specify the value of the `--component-plist` parameter when it runs pkgbuild for a component. Fixes: #16638 diff --git a/Help/release/dev/productbuild_component_plist.rst b/Help/release/dev/productbuild_component_plist.rst new file mode 100644 index 0000000..78d305c --- /dev/null +++ b/Help/release/dev/productbuild_component_plist.rst @@ -0,0 +1,7 @@ +productbuild_component_plist +---------------------------- + +* The :module:`CPackComponent` module :command:`cpack_add_component` command + gained a new ``PLIST `` option to specify the ``pkgbuild`` + ``--component-plist`` argument when using the + :module:`productbuild ` generator. diff --git a/Modules/CPackComponent.cmake b/Modules/CPackComponent.cmake index 188dde3..395a268 100644 --- a/Modules/CPackComponent.cmake +++ b/Modules/CPackComponent.cmake @@ -105,7 +105,8 @@ # [DEPENDS comp1 comp2 ... ] # [INSTALL_TYPES type1 type2 ... ] # [DOWNLOADED] -# [ARCHIVE_FILE filename]) +# [ARCHIVE_FILE filename] +# [PLIST filename]) # # # @@ -163,6 +164,9 @@ # a file with some name based on CPACK_PACKAGE_FILE_NAME and the name of # the component. See cpack_configure_downloads for more information. # +# PLIST gives a filename that is passed to pkgbuild with the +# ``--component-plist`` argument when using the productbuild generator. +# # .. command:: cpack_add_component_group # # Describes a group of related CPack installation components. @@ -389,7 +393,7 @@ endmacro() macro(cpack_add_component compname) string(TOUPPER ${compname} _CPACK_ADDCOMP_UNAME) cpack_parse_arguments(CPACK_COMPONENT_${_CPACK_ADDCOMP_UNAME} - "DISPLAY_NAME;DESCRIPTION;GROUP;DEPENDS;INSTALL_TYPES;ARCHIVE_FILE" + "DISPLAY_NAME;DESCRIPTION;GROUP;DEPENDS;INSTALL_TYPES;ARCHIVE_FILE;PLIST" "HIDDEN;REQUIRED;DISABLED;DOWNLOADED" ${ARGN} ) @@ -445,6 +449,9 @@ macro(cpack_add_component compname) cpack_append_option_set_command( CPACK_COMPONENT_${_CPACK_ADDCOMP_UNAME}_DOWNLOADED _CPACK_ADDCOMP_STR) + cpack_append_string_variable_set_command( + CPACK_COMPONENT_${_CPACK_ADDCOMP_UNAME}_PLIST + _CPACK_ADDCOMP_STR) # Backward compatibility issue. # Write to config iff the macros is used after CPack.cmake has been # included, other it's not necessary because the variables diff --git a/Source/CPack/cmCPackComponentGroup.h b/Source/CPack/cmCPackComponentGroup.h index f955daf..510adc2 100644 --- a/Source/CPack/cmCPackComponentGroup.h +++ b/Source/CPack/cmCPackComponentGroup.h @@ -78,6 +78,10 @@ public: /// contains the files that are part of this component. std::string ArchiveFile; + /// The file to pass to --component-plist when using the + /// productbuild generator. + std::string Plist; + /// The components that this component depends on. std::vector Dependencies; diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 21eda79..e1a4a2a 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -1396,6 +1396,11 @@ cmCPackComponent* cmCPackGenerator::GetComponent( component->ArchiveFile = archiveFile; } + const char* plist = this->GetOption(macroPrefix + "_PLIST"); + if (plist && *plist) { + component->Plist = plist; + } + const char* groupName = this->GetOption(macroPrefix + "_GROUP"); if (groupName && *groupName) { component->Group = GetComponentGroup(projectName, groupName); diff --git a/Source/CPack/cmCPackProductBuildGenerator.cxx b/Source/CPack/cmCPackProductBuildGenerator.cxx index a5a18dc..076cc25 100644 --- a/Source/CPack/cmCPackProductBuildGenerator.cxx +++ b/Source/CPack/cmCPackProductBuildGenerator.cxx @@ -223,6 +223,10 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage( : " --keychain \"" + keychainPath + "\"") << " \"" << packageFile << "\""; + if (component && !component->Plist.empty()) { + pkgCmd << " --component-plist \"" << component->Plist << "\""; + } + // Run ProductBuild return RunProductBuild(pkgCmd.str()); } ----------------------------------------------------------------------- Summary of changes: Help/release/dev/productbuild_component_plist.rst | 7 +++++++ Modules/CPackComponent.cmake | 11 +++++++++-- Source/CPack/cmCPackComponentGroup.h | 4 ++++ Source/CPack/cmCPackGenerator.cxx | 5 +++++ Source/CPack/cmCPackProductBuildGenerator.cxx | 4 ++++ 5 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 Help/release/dev/productbuild_component_plist.rst hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 17 11:47:42 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 17 Feb 2017 11:47:42 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-240-g0f8ea1f Message-ID: <20170217164742.4117AF9D98@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 0f8ea1fdfa8e8ad51633d17dd0ffc158f619a8fb (commit) via 734581f49fc0eac4c49e941c0cc450a04c866896 (commit) from 8cf6ac2226d23ac78cea34ddfae28e1626d289e1 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0f8ea1fdfa8e8ad51633d17dd0ffc158f619a8fb commit 0f8ea1fdfa8e8ad51633d17dd0ffc158f619a8fb Merge: 8cf6ac2 734581f Author: Brad King AuthorDate: Fri Feb 17 11:47:41 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 17 11:47:41 2017 -0500 Merge topic 'productbuild_resources' into next 734581f4 CPack: Add support for CPACK_PRODUCTBULID_RESOURCES_DIR https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=734581f49fc0eac4c49e941c0cc450a04c866896 commit 734581f49fc0eac4c49e941c0cc450a04c866896 Author: Tim Hutt AuthorDate: Tue Feb 14 10:09:23 2017 +0000 Commit: Brad King CommitDate: Fri Feb 17 11:47:00 2017 -0500 CPack: Add support for CPACK_PRODUCTBULID_RESOURCES_DIR This allows you to copy custom files (e.g. a background image) into the macOS installer. Fixes: #16604 diff --git a/Help/release/dev/productbuild_resources.rst b/Help/release/dev/productbuild_resources.rst new file mode 100644 index 0000000..f381e63 --- /dev/null +++ b/Help/release/dev/productbuild_resources.rst @@ -0,0 +1,7 @@ +productbuild_resources +---------------------- + +* The :module:`CPackProductBuild` module gained a new + :variable:`CPACK_PRODUCTBUILD_RESOURCES_DIR` variable to + specify resources to be copied into the ``Resources`` + directory. diff --git a/Modules/CPackProductBuild.cmake b/Modules/CPackProductBuild.cmake index d545d3e..4779b95 100644 --- a/Modules/CPackProductBuild.cmake +++ b/Modules/CPackProductBuild.cmake @@ -46,3 +46,11 @@ # # Specify a specific keychain to search for the signing identity. # +# +# .. variable:: CPACK_PRODUCTBUILD_RESOURCES_DIR +# +# If specified the productbuild generator copies files from this directory +# (including subdirectories) to the ``Resources`` directory. This is done +# before the :variable:`CPACK_RESOURCE_FILE_WELCOME`, +# :variable:`CPACK_RESOURCE_FILE_README`, and +# :variable:`CPACK_RESOURCE_FILE_LICENSE` files are copied. diff --git a/Source/CPack/cmCPackProductBuildGenerator.cxx b/Source/CPack/cmCPackProductBuildGenerator.cxx index a5a18dc..0e93234 100644 --- a/Source/CPack/cmCPackProductBuildGenerator.cxx +++ b/Source/CPack/cmCPackProductBuildGenerator.cxx @@ -59,12 +59,25 @@ int cmCPackProductBuildGenerator::PackageFiles() } } - // Copy or create all of the resource files we need. std::string resDir = packageDirFileName + "/Contents"; + + if (this->IsSet("CPACK_PRODUCTBUILD_RESOURCES_DIR")) { + std::string userResDir = + this->GetOption("CPACK_PRODUCTBUILD_RESOURCES_DIR"); + + if (!cmSystemTools::CopyADirectory(userResDir, resDir)) { + cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem copying the resource files" + << std::endl); + return 0; + } + } + + // Copy or create all of the resource files we need. if (!this->CopyCreateResourceFile("License", resDir) || !this->CopyCreateResourceFile("ReadMe", resDir) || !this->CopyCreateResourceFile("Welcome", resDir)) { - cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem copying the resource files" + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Problem copying the License, ReadMe and Welcome files" << std::endl); return 0; } ----------------------------------------------------------------------- Summary of changes: Help/release/dev/productbuild_resources.rst | 7 +++++++ Modules/CPackProductBuild.cmake | 8 ++++++++ Source/CPack/cmCPackProductBuildGenerator.cxx | 17 +++++++++++++++-- 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 Help/release/dev/productbuild_resources.rst hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 17 14:33:46 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 17 Feb 2017 14:33:46 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-242-g38c92f8 Message-ID: <20170217193346.9DA3BFA6BA@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 38c92f8d1c4e372aaeb598f54822dc71281a580a (commit) via e2d78f7535951adc505014d3afde59b52caf35f1 (commit) from 0f8ea1fdfa8e8ad51633d17dd0ffc158f619a8fb (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=38c92f8d1c4e372aaeb598f54822dc71281a580a commit 38c92f8d1c4e372aaeb598f54822dc71281a580a Merge: 0f8ea1f e2d78f7 Author: Brad King AuthorDate: Fri Feb 17 14:33:45 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 17 14:33:45 2017 -0500 Merge topic 'fix-CMP0017-path-case' into next e2d78f75 Windows: Fix inconsistent behavior on changes to case of path to cmake https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e2d78f7535951adc505014d3afde59b52caf35f1 commit e2d78f7535951adc505014d3afde59b52caf35f1 Author: Brad King AuthorDate: Fri Feb 17 10:15:21 2017 -0500 Commit: Brad King CommitDate: Fri Feb 17 11:10:45 2017 -0500 Windows: Fix inconsistent behavior on changes to case of path to cmake In commit v3.4.0-rc1~333^2 (Merge branch 'upstream-kwsys' into update-kwsys, 2015-07-15) we brought in upstream KWSys commit 86a24794 (SystemTools: Fix GetActualCaseForPath drive letter case handling, 2015-07-09). This caused our path processing to convert drive letters to upper-case and exposed an existing bug in our implementation of CMP0017. Policy CMP0017 is responsible for ensuring that modules included from a builtin module only load other builtin modules and cannot be overridden by a file in `CMAKE_MODULE_PATH`. If there is a case difference in the drive letter (or other path components) then the path to the including module may not match our builtin module directory in a simple string comparison. This means builtin modules may not be recognized as such, and they may not reliably include their builtin dependencies. For example, if a project provides a `Platform/Windows` module in `CMAKE_MODULE_PATH` it can break inclusion of our builtin `Platform/Windows` module, leading to strange behavior. Fix this by comparing the path to the including module to our builtin module directory using a function that is aware of case-insensitivity of paths on Windows. Fixes: #16648, #16622 diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index bfe46ae..1e995fb 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -3362,7 +3362,7 @@ std::string cmMakefile::GetModulesFile(const char* filename) const if (!moduleInCMakeModulePath.empty() && !moduleInCMakeRoot.empty()) { const char* currentFile = this->GetDefinition("CMAKE_CURRENT_LIST_FILE"); std::string mods = cmSystemTools::GetCMakeRoot() + "/Modules/"; - if (currentFile && strncmp(currentFile, mods.c_str(), mods.size()) == 0) { + if (currentFile && cmSystemTools::IsSubDirectory(currentFile, mods)) { switch (this->GetPolicyStatus(cmPolicies::CMP0017)) { case cmPolicies::WARN: { std::ostringstream e; ----------------------------------------------------------------------- Summary of changes: Source/cmMakefile.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 17 14:33:52 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 17 Feb 2017 14:33:52 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-244-g0b303f9 Message-ID: <20170217193352.5AD0DFA6BE@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 0b303f9d018b06a0d46937d6ddc3001484e1c1b8 (commit) via 3287ba02540ae94d6b0105f84e930aa19cf61b19 (commit) from 38c92f8d1c4e372aaeb598f54822dc71281a580a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0b303f9d018b06a0d46937d6ddc3001484e1c1b8 commit 0b303f9d018b06a0d46937d6ddc3001484e1c1b8 Merge: 38c92f8 3287ba0 Author: Brad King AuthorDate: Fri Feb 17 14:33:51 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 17 14:33:51 2017 -0500 Merge topic 'fix-CMAKE_ROOT-case' into next 3287ba02 Make CMAKE_ROOT independent of case of path used to invoke cmake https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3287ba02540ae94d6b0105f84e930aa19cf61b19 commit 3287ba02540ae94d6b0105f84e930aa19cf61b19 Author: Brad King AuthorDate: Fri Feb 17 10:59:47 2017 -0500 Commit: Brad King CommitDate: Fri Feb 17 11:09:12 2017 -0500 Make CMAKE_ROOT independent of case of path used to invoke cmake We compute the location of `CMAKE_ROOT` and other resources relative to the location of our own executable. On some platforms this path is computed in a way that depends on the case of the path used to invoke the executable. Convert the result to the actual case preserved by the filesystem on disk in order to make it consistent regardless of how the executable is launched. This approach generalizes the fix made by commit v3.8.0-rc1~71^2 (cmSystemTools: use the actual case for root detection, 2017-01-18). Issue: #16648 diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 9efc13b..b3a7248 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -1978,6 +1978,7 @@ void cmSystemTools::FindCMakeResources(const char* argv0) // ??? } #endif + exe_dir = cmSystemTools::GetActualCaseForPath(exe_dir); cmSystemToolsCMakeCommand = exe_dir; cmSystemToolsCMakeCommand += "/cmake"; cmSystemToolsCMakeCommand += cmSystemTools::GetExecutableExtension(); @@ -2015,8 +2016,7 @@ void cmSystemTools::FindCMakeResources(const char* argv0) // Install tree has // - "/cmake" // - "" - const std::string actual_case = cmSystemTools::GetActualCaseForPath(exe_dir); - if (cmHasSuffix(actual_case, CMAKE_BIN_DIR)) { + if (cmHasSuffix(exe_dir, CMAKE_BIN_DIR)) { std::string const prefix = exe_dir.substr(0, exe_dir.size() - strlen(CMAKE_BIN_DIR)); cmSystemToolsCMakeRoot = prefix + CMAKE_DATA_DIR; ----------------------------------------------------------------------- Summary of changes: Source/cmSystemTools.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- CMake From daniel at pfeifer-mail.de Fri Feb 17 16:25:36 2017 From: daniel at pfeifer-mail.de (Daniel Pfeifer) Date: Fri, 17 Feb 2017 16:25:36 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-251-gb7af957 Message-ID: <20170217212536.5A69BFA22A@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via b7af957834c120064057a0180487a56fc12ec7e1 (commit) via ba807f282e5573adc20519394f32431fe4c54904 (commit) via 3340213f8c2fbe3dcc4031e1d5f06484d468bc5e (commit) via b74314c6fdfcc1520dff6ac93d7150c8bf3f75f4 (commit) via 74404df4405528d4d156d8761f71566d80ba4119 (commit) via e7168c087f6b7a917099cd196959d39f44fb0412 (commit) via ee72803e9f2988d2cf493a6d096c2a0d483fc547 (commit) from 0b303f9d018b06a0d46937d6ddc3001484e1c1b8 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b7af957834c120064057a0180487a56fc12ec7e1 commit b7af957834c120064057a0180487a56fc12ec7e1 Merge: 0b303f9 ba807f2 Author: Daniel Pfeifer AuthorDate: Fri Feb 17 16:25:35 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 17 16:25:35 2017 -0500 Merge topic 'iwyu' into next ba807f28 remove file cmStandardIncludes.h 3340213f cmFortranParser: include what you use b74314c6 cmDependsJavaParser: include what you use 74404df4 cmCommandArgumentParser: include what you use e7168c08 cmExprParser: include what you use ee72803e fix some include-what-you-use diagnostics https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ba807f282e5573adc20519394f32431fe4c54904 commit ba807f282e5573adc20519394f32431fe4c54904 Author: Daniel Pfeifer AuthorDate: Fri Feb 17 22:25:09 2017 +0100 Commit: Daniel Pfeifer CommitDate: Fri Feb 17 22:25:09 2017 +0100 remove file cmStandardIncludes.h diff --git a/Source/cmFortranParser.h b/Source/cmFortranParser.h index 06985d2..e8273fb 100644 --- a/Source/cmFortranParser.h +++ b/Source/cmFortranParser.h @@ -6,7 +6,9 @@ #if !defined(cmFortranLexer_cxx) && !defined(cmFortranParser_cxx) #include -#include "cmStandardIncludes.h" +#include +#include +#include #endif #include /* size_t */ diff --git a/Source/cmStandardIncludes.h b/Source/cmStandardIncludes.h deleted file mode 100644 index a2047af..0000000 --- a/Source/cmStandardIncludes.h +++ /dev/null @@ -1,53 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -/** - * Include header files as a function of the build process, compiler, - * and operating system. - */ -#ifndef cmStandardIncludes_h -#define cmStandardIncludes_h - -#include - -// Provide fixed-size integer types. -#include - -#include -#include -#include -#include - -// we must have stl with the standard include style -#include -#include -#include -#include -#include -#include -#include - -// include the "c" string header -#include -#include -#include - -#if defined(_MSC_VER) -typedef unsigned short mode_t; -#else -#include -#endif - -// use this class to shrink the size of symbols in .o files -// std::string is really basic_string<....lots of stuff....> -// when combined with a map or set, the symbols can be > 2000 chars! -#include -// typedef cmsys::String std::string; - -/* Poison this operator to avoid common mistakes. */ -extern void operator<<(std::ostream&, const std::ostringstream&); - -#include "cmCustomCommandLines.h" -#include "cmDocumentationEntry.h" -#include "cmTargetLinkLibraryType.h" - -#endif https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3340213f8c2fbe3dcc4031e1d5f06484d468bc5e commit 3340213f8c2fbe3dcc4031e1d5f06484d468bc5e Author: Daniel Pfeifer AuthorDate: Fri Feb 17 22:12:21 2017 +0100 Commit: Daniel Pfeifer CommitDate: Fri Feb 17 22:12:21 2017 +0100 cmFortranParser: include what you use diff --git a/Source/cmFortranParser.cxx b/Source/cmFortranParser.cxx index 896e589..45d9639 100644 --- a/Source/cmFortranParser.cxx +++ b/Source/cmFortranParser.cxx @@ -97,13 +97,17 @@ Modify cmFortranParser.cxx: - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"] */ +#include + +#include +#include +#include + /*-------------------------------------------------------------------------*/ #define cmFortranParser_cxx #include "cmFortranParser.h" /* Interface to parser object. */ #include "cmFortranParserTokens.h" /* Need YYSTYPE for YY_DECL. */ -#include - /* Forward declare the lexer entry point. */ YY_DECL; @@ -124,7 +128,7 @@ static void cmFortran_yyerror(yyscan_t yyscanner, const char* message) # pragma warning (disable: 4244) /* Conversion to smaller type, data loss. */ #endif -#line 137 "cmFortranParser.cxx" /* yacc.c:339 */ +#line 132 "cmFortranParser.cxx" /* yacc.c:339 */ # ifndef YY_NULLPTR # if defined __cplusplus && 201103L <= __cplusplus @@ -244,11 +248,11 @@ extern int cmFortran_yydebug; union YYSTYPE { -#line 75 "cmFortranParser.y" /* yacc.c:355 */ +#line 70 "cmFortranParser.y" /* yacc.c:355 */ char* string; -#line 261 "cmFortranParser.cxx" /* yacc.c:355 */ +#line 256 "cmFortranParser.cxx" /* yacc.c:355 */ }; typedef union YYSTYPE YYSTYPE; @@ -264,7 +268,7 @@ int cmFortran_yyparse (yyscan_t yyscanner); /* Copy the second part of user declarations. */ -#line 277 "cmFortranParser.cxx" /* yacc.c:358 */ +#line 272 "cmFortranParser.cxx" /* yacc.c:358 */ #ifdef short # undef short @@ -565,13 +569,13 @@ static const yytype_uint8 yytranslate[] = /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { - 0, 103, 103, 103, 106, 110, 115, 124, 130, 137, - 142, 146, 151, 159, 164, 169, 174, 179, 184, 189, - 194, 199, 203, 207, 211, 215, 216, 221, 221, 221, - 222, 222, 223, 223, 224, 224, 225, 225, 226, 226, - 227, 227, 228, 228, 229, 229, 230, 230, 233, 234, - 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, - 245, 246, 247, 248 + 0, 98, 98, 98, 101, 105, 110, 119, 125, 132, + 137, 141, 146, 154, 159, 164, 169, 174, 179, 184, + 189, 194, 198, 202, 206, 210, 211, 216, 216, 216, + 217, 217, 218, 218, 219, 219, 220, 220, 221, 221, + 222, 222, 223, 223, 224, 224, 225, 225, 228, 229, + 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243 }; #endif @@ -1523,26 +1527,26 @@ yyreduce: switch (yyn) { case 4: -#line 106 "cmFortranParser.y" /* yacc.c:1646 */ +#line 101 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, true); } -#line 1541 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1536 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 5: -#line 110 "cmFortranParser.y" /* yacc.c:1646 */ +#line 105 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUse(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1551 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1546 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 6: -#line 115 "cmFortranParser.y" /* yacc.c:1646 */ +#line 110 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); if (cmsysString_strcasecmp((yyvsp[-2].string), "function") != 0 && @@ -1552,22 +1556,22 @@ yyreduce: } free((yyvsp[-2].string)); } -#line 1565 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1560 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 7: -#line 124 "cmFortranParser.y" /* yacc.c:1646 */ +#line 119 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUse(parser, (yyvsp[-4].string)); free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1576 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1571 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 8: -#line 130 "cmFortranParser.y" /* yacc.c:1646 */ +#line 125 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUse(parser, (yyvsp[-6].string)); @@ -1575,40 +1579,40 @@ yyreduce: free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1588 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1583 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 9: -#line 137 "cmFortranParser.y" /* yacc.c:1646 */ +#line 132 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, true); free((yyvsp[-2].string)); } -#line 1598 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1593 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 10: -#line 142 "cmFortranParser.y" /* yacc.c:1646 */ +#line 137 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, false); } -#line 1607 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1602 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 11: -#line 146 "cmFortranParser.y" /* yacc.c:1646 */ +#line 141 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUse(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1617 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1612 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 12: -#line 151 "cmFortranParser.y" /* yacc.c:1646 */ +#line 146 "cmFortranParser.y" /* yacc.c:1646 */ { if (cmsysString_strcasecmp((yyvsp[-4].string), "non_intrinsic") == 0) { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); @@ -1617,139 +1621,139 @@ yyreduce: free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1630 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1625 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 13: -#line 159 "cmFortranParser.y" /* yacc.c:1646 */ +#line 154 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1640 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1635 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 14: -#line 164 "cmFortranParser.y" /* yacc.c:1646 */ +#line 159 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleLineDirective(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1650 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1645 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 15: -#line 169 "cmFortranParser.y" /* yacc.c:1646 */ +#line 164 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1660 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1655 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 16: -#line 174 "cmFortranParser.y" /* yacc.c:1646 */ +#line 169 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1670 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1665 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 17: -#line 179 "cmFortranParser.y" /* yacc.c:1646 */ +#line 174 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleDefine(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1680 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1675 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 18: -#line 184 "cmFortranParser.y" /* yacc.c:1646 */ +#line 179 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUndef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1690 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1685 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 19: -#line 189 "cmFortranParser.y" /* yacc.c:1646 */ +#line 184 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIfdef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1700 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1695 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 20: -#line 194 "cmFortranParser.y" /* yacc.c:1646 */ +#line 189 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIfndef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1710 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1705 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 21: -#line 199 "cmFortranParser.y" /* yacc.c:1646 */ +#line 194 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIf(parser); } -#line 1719 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1714 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 22: -#line 203 "cmFortranParser.y" /* yacc.c:1646 */ +#line 198 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleElif(parser); } -#line 1728 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1723 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 23: -#line 207 "cmFortranParser.y" /* yacc.c:1646 */ +#line 202 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleElse(parser); } -#line 1737 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1732 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 24: -#line 211 "cmFortranParser.y" /* yacc.c:1646 */ +#line 206 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleEndif(parser); } -#line 1746 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1741 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 48: -#line 233 "cmFortranParser.y" /* yacc.c:1646 */ +#line 228 "cmFortranParser.y" /* yacc.c:1646 */ { free ((yyvsp[0].string)); } -#line 1752 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1747 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 55: -#line 240 "cmFortranParser.y" /* yacc.c:1646 */ +#line 235 "cmFortranParser.y" /* yacc.c:1646 */ { free ((yyvsp[0].string)); } -#line 1758 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1753 "cmFortranParser.cxx" /* yacc.c:1646 */ break; -#line 1762 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1757 "cmFortranParser.cxx" /* yacc.c:1646 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -1979,6 +1983,6 @@ yyreturn: #endif return yyresult; } -#line 251 "cmFortranParser.y" /* yacc.c:1906 */ +#line 246 "cmFortranParser.y" /* yacc.c:1906 */ /* End of grammar */ diff --git a/Source/cmFortranParser.y b/Source/cmFortranParser.y index 7eb5ef5..be4959c 100644 --- a/Source/cmFortranParser.y +++ b/Source/cmFortranParser.y @@ -26,13 +26,17 @@ Modify cmFortranParser.cxx: - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"] */ +#include + +#include +#include +#include + /*-------------------------------------------------------------------------*/ #define cmFortranParser_cxx #include "cmFortranParser.h" /* Interface to parser object. */ #include "cmFortranParserTokens.h" /* Need YYSTYPE for YY_DECL. */ -#include - /* Forward declare the lexer entry point. */ YY_DECL; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b74314c6fdfcc1520dff6ac93d7150c8bf3f75f4 commit b74314c6fdfcc1520dff6ac93d7150c8bf3f75f4 Author: Daniel Pfeifer AuthorDate: Fri Feb 17 22:12:21 2017 +0100 Commit: Daniel Pfeifer CommitDate: Fri Feb 17 22:12:21 2017 +0100 cmDependsJavaParser: include what you use diff --git a/Source/cmDependsJavaParser.cxx b/Source/cmDependsJavaParser.cxx index a1beb58..b09bd0c 100644 --- a/Source/cmDependsJavaParser.cxx +++ b/Source/cmDependsJavaParser.cxx @@ -85,6 +85,12 @@ Modify cmDependsJavaParser.cxx: */ +#include // IWYU pragma: keep + +#include +#include +#include + #define yyGetParser (cmDependsJava_yyget_extra(yyscanner)) /*-------------------------------------------------------------------------*/ @@ -110,7 +116,7 @@ static void cmDependsJava_yyerror(yyscan_t yyscanner, const char* message); # pragma warning (disable: 4065) /* Switch statement contains default but no case. */ #endif -#line 114 "cmDependsJavaParser.cxx" /* yacc.c:339 */ +#line 120 "cmDependsJavaParser.cxx" /* yacc.c:339 */ # ifndef YY_NULLPTR # if defined __cplusplus && 201103L <= __cplusplus @@ -365,7 +371,7 @@ int cmDependsJava_yyparse (yyscan_t yyscanner); /* Copy the second part of user declarations. */ -#line 369 "cmDependsJavaParser.cxx" /* yacc.c:358 */ +#line 375 "cmDependsJavaParser.cxx" /* yacc.c:358 */ #ifdef short # undef short @@ -673,42 +679,42 @@ static const yytype_uint8 yytranslate[] = /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 173, 173, 182, 190, 198, 206, 214, 222, 231, - 239, 248, 256, 265, 270, 275, 280, 285, 290, 295, - 300, 306, 314, 323, 333, 342, 351, 359, 369, 375, - 382, 389, 395, 402, 411, 421, 431, 440, 448, 457, - 466, 472, 481, 487, 496, 502, 511, 523, 531, 540, - 552, 565, 573, 581, 590, 598, 607, 607, 607, 608, - 609, 609, 609, 609, 609, 609, 610, 613, 623, 632, - 641, 650, 660, 666, 675, 684, 693, 701, 710, 719, - 725, 734, 742, 750, 758, 767, 775, 784, 790, 798, - 807, 815, 824, 833, 842, 850, 859, 867, 875, 884, - 893, 903, 910, 920, 930, 937, 944, 947, 953, 963, - 973, 983, 989, 999, 1009, 1019, 1028, 1038, 1049, 1059, - 1066, 1076, 1085, 1095, 1104, 1114, 1120, 1130, 1139, 1149, - 1159, 1166, 1175, 1184, 1193, 1202, 1210, 1219, 1228, 1238, - 1248, 1257, 1267, 1277, 1284, 1293, 1303, 1312, 1322, 1331, - 1338, 1348, 1357, 1367, 1376, 1385, 1395, 1405, 1414, 1424, - 1433, 1442, 1451, 1460, 1469, 1479, 1488, 1497, 1506, 1515, - 1525, 1534, 1543, 1552, 1561, 1570, 1579, 1588, 1597, 1606, - 1615, 1624, 1634, 1644, 1655, 1665, 1675, 1684, 1693, 1702, - 1711, 1720, 1729, 1739, 1749, 1759, 1769, 1776, 1783, 1790, - 1800, 1807, 1817, 1827, 1836, 1846, 1855, 1865, 1872, 1879, - 1886, 1894, 1901, 1911, 1918, 1928, 1938, 1945, 1955, 1964, - 1974, 1984, 1993, 2003, 2012, 2022, 2033, 2040, 2047, 2058, - 2068, 2078, 2088, 2097, 2107, 2114, 2124, 2133, 2143, 2150, - 2160, 2169, 2179, 2188, 2194, 2203, 2212, 2221, 2230, 2240, - 2250, 2257, 2267, 2274, 2284, 2293, 2303, 2312, 2321, 2330, - 2340, 2347, 2357, 2366, 2376, 2386, 2392, 2399, 2409, 2419, - 2429, 2440, 2450, 2461, 2471, 2482, 2492, 2502, 2511, 2520, - 2529, 2538, 2548, 2558, 2568, 2577, 2586, 2595, 2604, 2614, - 2624, 2634, 2643, 2652, 2661, 2671, 2680, 2689, 2696, 2705, - 2714, 2723, 2733, 2742, 2751, 2761, 2770, 2779, 2788, 2798, - 2807, 2816, 2825, 2834, 2843, 2853, 2862, 2871, 2881, 2890, - 2900, 2909, 2919, 2928, 2938, 2947, 2957, 2966, 2976, 2985, - 2995, 3004, 3014, 3024, 3034, 3043, 3053, 3062, 3071, 3080, - 3089, 3098, 3107, 3116, 3125, 3134, 3143, 3152, 3162, 3172, - 3182, 3191 + 0, 179, 179, 188, 196, 204, 212, 220, 228, 237, + 245, 254, 262, 271, 276, 281, 286, 291, 296, 301, + 306, 312, 320, 329, 339, 348, 357, 365, 375, 381, + 388, 395, 401, 408, 417, 427, 437, 446, 454, 463, + 472, 478, 487, 493, 502, 508, 517, 529, 537, 546, + 558, 571, 579, 587, 596, 604, 613, 613, 613, 614, + 615, 615, 615, 615, 615, 615, 616, 619, 629, 638, + 647, 656, 666, 672, 681, 690, 699, 707, 716, 725, + 731, 740, 748, 756, 764, 773, 781, 790, 796, 804, + 813, 821, 830, 839, 848, 856, 865, 873, 881, 890, + 899, 909, 916, 926, 936, 943, 950, 953, 959, 969, + 979, 989, 995, 1005, 1015, 1025, 1034, 1044, 1055, 1065, + 1072, 1082, 1091, 1101, 1110, 1120, 1126, 1136, 1145, 1155, + 1165, 1172, 1181, 1190, 1199, 1208, 1216, 1225, 1234, 1244, + 1254, 1263, 1273, 1283, 1290, 1299, 1309, 1318, 1328, 1337, + 1344, 1354, 1363, 1373, 1382, 1391, 1401, 1411, 1420, 1430, + 1439, 1448, 1457, 1466, 1475, 1485, 1494, 1503, 1512, 1521, + 1531, 1540, 1549, 1558, 1567, 1576, 1585, 1594, 1603, 1612, + 1621, 1630, 1640, 1650, 1661, 1671, 1681, 1690, 1699, 1708, + 1717, 1726, 1735, 1745, 1755, 1765, 1775, 1782, 1789, 1796, + 1806, 1813, 1823, 1833, 1842, 1852, 1861, 1871, 1878, 1885, + 1892, 1900, 1907, 1917, 1924, 1934, 1944, 1951, 1961, 1970, + 1980, 1990, 1999, 2009, 2018, 2028, 2039, 2046, 2053, 2064, + 2074, 2084, 2094, 2103, 2113, 2120, 2130, 2139, 2149, 2156, + 2166, 2175, 2185, 2194, 2200, 2209, 2218, 2227, 2236, 2246, + 2256, 2263, 2273, 2280, 2290, 2299, 2309, 2318, 2327, 2336, + 2346, 2353, 2363, 2372, 2382, 2392, 2398, 2405, 2415, 2425, + 2435, 2446, 2456, 2467, 2477, 2488, 2498, 2508, 2517, 2526, + 2535, 2544, 2554, 2564, 2574, 2583, 2592, 2601, 2610, 2620, + 2630, 2640, 2649, 2658, 2667, 2677, 2686, 2695, 2702, 2711, + 2720, 2729, 2739, 2748, 2757, 2767, 2776, 2785, 2794, 2804, + 2813, 2822, 2831, 2840, 2849, 2859, 2868, 2877, 2887, 2896, + 2906, 2915, 2925, 2934, 2944, 2953, 2963, 2972, 2982, 2991, + 3001, 3010, 3020, 3030, 3040, 3049, 3059, 3068, 3077, 3086, + 3095, 3104, 3113, 3122, 3131, 3140, 3149, 3158, 3168, 3178, + 3188, 3197 }; #endif @@ -2276,214 +2282,214 @@ yyreduce: switch (yyn) { case 2: -#line 174 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 180 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2287 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2293 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 3: -#line 183 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 189 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2298 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2304 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 4: -#line 191 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 197 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2309 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2315 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 5: -#line 199 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 205 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2320 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2326 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 6: -#line 207 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 213 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2331 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2337 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 7: -#line 215 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 221 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2342 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2348 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 8: -#line 223 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 229 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2353 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2359 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 9: -#line 232 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 238 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2364 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2370 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 10: -#line 240 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 246 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2375 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2381 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 11: -#line 249 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 255 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2386 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2392 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 12: -#line 257 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 263 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2397 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2403 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 13: -#line 266 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 272 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } -#line 2405 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2411 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 14: -#line 271 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 277 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } -#line 2413 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2419 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 15: -#line 276 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 282 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } -#line 2421 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2427 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 16: -#line 281 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 287 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } -#line 2429 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2435 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 17: -#line 286 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 292 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } -#line 2437 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2443 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 18: -#line 291 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 297 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } -#line 2445 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2451 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 19: -#line 296 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 302 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } -#line 2453 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2459 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 20: -#line 301 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 307 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); } -#line 2461 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2467 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 21: -#line 307 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 313 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2472 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2478 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 22: -#line 315 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 321 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2483 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2489 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 23: -#line 324 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 330 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpStoreClass((yyvsp[0].str)); @@ -2491,44 +2497,44 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2495 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2501 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 24: -#line 334 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 340 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2506 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2512 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 25: -#line 343 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 349 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2517 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2523 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 26: -#line 352 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 358 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2528 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2534 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 27: -#line 360 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 366 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpStoreClass((yyvsp[-1].str)); @@ -2536,56 +2542,56 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2540 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2546 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 28: -#line 370 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 376 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2549 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2555 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 29: -#line 376 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 382 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2558 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2564 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 30: -#line 383 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 389 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2567 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2573 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 31: -#line 390 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 396 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); (yyval.str) = (yyvsp[0].str); } -#line 2576 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2582 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 32: -#line 396 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 402 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); (yyval.str) = (yyvsp[0].str); } -#line 2585 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2591 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 33: -#line 403 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 409 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); yyGetParser->AddClassFound((yyvsp[-2].str)); @@ -2593,11 +2599,11 @@ yyreduce: yyGetParser->DeallocateParserType(&((yyvsp[-2].str))); (yyval.str) = const_cast(yyGetParser->GetCurrentCombine()); } -#line 2597 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2603 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 34: -#line 412 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 418 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpStoreClass((yyvsp[-2].str)); @@ -2606,11 +2612,11 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2610 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2616 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 35: -#line 422 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 428 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpStoreClass((yyvsp[-2].str)); @@ -2619,118 +2625,118 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2623 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2629 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 36: -#line 432 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 438 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2634 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2640 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 37: -#line 441 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 447 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2645 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2651 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 38: -#line 449 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 455 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2656 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2662 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 39: -#line 458 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 464 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2667 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2673 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 40: -#line 466 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 472 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2677 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2683 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 41: -#line 473 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 479 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2688 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2694 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 42: -#line 481 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 487 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2698 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2704 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 43: -#line 488 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 494 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2709 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2715 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 44: -#line 496 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 502 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2719 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2725 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 45: -#line 503 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 509 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2730 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2736 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 46: -#line 512 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 518 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); yyGetParser->SetCurrentPackage((yyvsp[-1].str)); @@ -2740,33 +2746,33 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2744 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2750 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 47: -#line 524 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 530 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2755 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2761 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 48: -#line 532 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 538 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2766 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2772 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 49: -#line 541 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 547 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); yyGetParser->AddPackagesImport((yyvsp[-1].str)); @@ -2776,11 +2782,11 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2780 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2786 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 50: -#line 553 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 559 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); std::string str = (yyvsp[-3].str); @@ -2791,77 +2797,77 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2795 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2801 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 51: -#line 566 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 572 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2806 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2812 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 52: -#line 574 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 580 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2817 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2823 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 53: -#line 582 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 588 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2828 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2834 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 54: -#line 591 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 597 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2839 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2845 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 55: -#line 599 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 605 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2850 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2856 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 67: -#line 614 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 620 "cmDependsJavaParser.y" /* yacc.c:1646 */ { yyGetParser->StartClass((yyvsp[0].str)); jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(3); } -#line 2861 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2867 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 68: -#line 624 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 630 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -2869,11 +2875,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 2873 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2879 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 69: -#line 633 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 639 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(2); @@ -2881,11 +2887,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 2885 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2891 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 70: -#line 642 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 648 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -2893,11 +2899,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 2897 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2903 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 71: -#line 651 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 657 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); @@ -2905,226 +2911,226 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 2909 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2915 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 72: -#line 660 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 666 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2919 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2925 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 73: -#line 667 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 673 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2930 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2936 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 74: -#line 676 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 682 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2941 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2947 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 75: -#line 685 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 691 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2952 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2958 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 76: -#line 694 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 700 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2963 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2969 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 77: -#line 702 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 708 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2974 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2980 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 78: -#line 711 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 717 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2985 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 2991 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 79: -#line 719 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 725 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 2995 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3001 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 80: -#line 726 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 732 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3006 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3012 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 81: -#line 735 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 741 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3017 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3023 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 82: -#line 743 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 749 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3028 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3034 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 83: -#line 751 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 757 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3039 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3045 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 84: -#line 759 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 765 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3050 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3056 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 85: -#line 768 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 774 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3061 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3067 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 86: -#line 776 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 782 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3072 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3078 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 87: -#line 785 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 791 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); } -#line 3080 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3086 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 88: -#line 791 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 797 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3091 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3097 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 89: -#line 799 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 805 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3102 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3108 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 90: -#line 808 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 814 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3113 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3119 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 91: -#line 816 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 822 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3124 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3130 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 92: -#line 825 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 831 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -3132,77 +3138,77 @@ yyreduce: (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3136 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3142 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 93: -#line 834 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 840 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3147 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3153 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 94: -#line 843 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 849 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3158 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3164 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 95: -#line 851 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 857 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3169 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3175 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 96: -#line 860 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 866 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3180 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3186 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 97: -#line 868 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 874 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3191 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3197 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 98: -#line 876 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 882 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3202 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3208 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 99: -#line 885 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 891 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); @@ -3210,11 +3216,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3214 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3220 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 100: -#line 894 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 900 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); @@ -3222,22 +3228,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3226 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3232 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 101: -#line 903 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 909 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3237 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3243 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 102: -#line 911 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 917 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3245,11 +3251,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3249 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3255 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 103: -#line 921 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 927 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -3258,40 +3264,40 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3262 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3268 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 104: -#line 931 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 937 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); } -#line 3271 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3277 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 105: -#line 937 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 943 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3282 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3288 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 107: -#line 948 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 954 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); } -#line 3291 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3297 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 108: -#line 954 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 960 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -3299,11 +3305,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3303 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3309 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 109: -#line 964 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 970 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -3311,11 +3317,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3315 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3321 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 110: -#line 974 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 980 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -3323,20 +3329,20 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3327 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3333 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 111: -#line 984 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 990 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); } -#line 3336 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3342 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 112: -#line 990 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 996 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -3344,11 +3350,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3348 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3354 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 113: -#line 1000 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1006 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3356,11 +3362,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3360 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3366 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 114: -#line 1010 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1016 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -3368,11 +3374,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3372 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3378 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 115: -#line 1020 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1026 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); @@ -3380,11 +3386,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3384 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3390 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 116: -#line 1029 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1035 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); @@ -3392,11 +3398,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3396 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3402 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 117: -#line 1039 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1045 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -3405,11 +3411,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3409 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3415 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 118: -#line 1050 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1056 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); @@ -3417,22 +3423,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3421 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3427 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 119: -#line 1059 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1065 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3432 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3438 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 120: -#line 1067 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1073 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -3440,11 +3446,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3444 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3450 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 121: -#line 1077 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1083 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); @@ -3452,11 +3458,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3456 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3462 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 122: -#line 1086 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1092 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); @@ -3464,22 +3470,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3468 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3474 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 123: -#line 1096 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1102 "cmDependsJavaParser.y" /* yacc.c:1646 */ { yyGetParser->StartClass((yyvsp[0].str)); jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); jpCheckEmpty(3); } -#line 3479 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3485 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 124: -#line 1105 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1111 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -3487,21 +3493,21 @@ yyreduce: yyGetParser->SetCurrentCombine(""); yyGetParser->EndClass(); } -#line 3491 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3497 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 125: -#line 1114 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1120 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3501 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3507 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 126: -#line 1121 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1127 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3509,11 +3515,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3513 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3519 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 127: -#line 1131 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1137 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -3521,11 +3527,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3525 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3531 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 128: -#line 1140 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1146 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -3533,11 +3539,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3537 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3543 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 129: -#line 1150 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1156 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -3545,33 +3551,33 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3549 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3555 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 130: -#line 1159 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1165 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3560 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3566 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 131: -#line 1167 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1173 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3571 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3577 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 132: -#line 1176 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1182 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3579,11 +3585,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3583 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3589 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 133: -#line 1185 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1191 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3591,11 +3597,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3595 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3601 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 134: -#line 1194 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1200 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3603,22 +3609,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3607 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3613 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 135: -#line 1203 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1209 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3618 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3624 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 136: -#line 1211 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1217 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3626,22 +3632,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3630 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3636 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 137: -#line 1220 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1226 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3641 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3647 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 138: -#line 1229 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1235 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3649,11 +3655,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3653 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3659 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 139: -#line 1239 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1245 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -3661,11 +3667,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3665 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3671 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 140: -#line 1249 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1255 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3673,11 +3679,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3677 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3683 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 141: -#line 1258 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1264 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -3685,11 +3691,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3689 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3695 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 142: -#line 1268 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1274 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -3697,22 +3703,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3701 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3707 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 143: -#line 1277 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1283 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3712 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3718 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 144: -#line 1285 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1291 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3720,11 +3726,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3724 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3730 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 145: -#line 1294 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1300 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -3732,11 +3738,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3736 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3742 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 146: -#line 1304 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1310 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3744,11 +3750,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3748 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3754 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 147: -#line 1313 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1319 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -3756,33 +3762,33 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3760 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3766 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 148: -#line 1323 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1329 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3771 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3777 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 149: -#line 1331 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1337 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 3782 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3788 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 150: -#line 1339 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1345 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3790,11 +3796,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3794 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3800 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 151: -#line 1349 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1355 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3802,11 +3808,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3806 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3812 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 152: -#line 1358 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1364 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(2); @@ -3814,11 +3820,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3818 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3824 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 153: -#line 1368 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1374 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3826,11 +3832,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3830 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3836 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 154: -#line 1377 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1383 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3838,11 +3844,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3842 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3848 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 155: -#line 1386 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1392 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3850,11 +3856,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3854 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3860 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 156: -#line 1396 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1402 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(2); @@ -3862,11 +3868,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3866 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3872 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 157: -#line 1406 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1412 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(3); @@ -3874,11 +3880,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3878 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3884 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 158: -#line 1415 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1421 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(2); @@ -3886,11 +3892,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3890 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3896 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 159: -#line 1425 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1431 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3898,11 +3904,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3902 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3908 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 160: -#line 1434 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1440 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3910,11 +3916,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3914 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3920 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 161: -#line 1443 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1449 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3922,11 +3928,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3926 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3932 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 162: -#line 1452 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1458 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3934,11 +3940,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3938 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3944 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 163: -#line 1461 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1467 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3946,11 +3952,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3950 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3956 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 164: -#line 1470 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1476 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3958,11 +3964,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3962 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3968 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 165: -#line 1480 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1486 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3970,11 +3976,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3974 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3980 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 166: -#line 1489 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1495 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3982,11 +3988,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3986 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 3992 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 167: -#line 1498 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1504 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -3994,11 +4000,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 3998 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4004 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 168: -#line 1507 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1513 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4006,11 +4012,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4010 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4016 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 169: -#line 1516 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1522 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4018,11 +4024,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4022 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4028 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 170: -#line 1526 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1532 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4030,11 +4036,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4034 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4040 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 171: -#line 1535 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1541 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4042,11 +4048,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4046 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4052 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 172: -#line 1544 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1550 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4054,11 +4060,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4058 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4064 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 173: -#line 1553 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1559 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4066,11 +4072,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4070 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4076 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 174: -#line 1562 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1568 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4078,11 +4084,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4082 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4088 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 175: -#line 1571 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1577 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4090,11 +4096,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4094 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4100 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 176: -#line 1580 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1586 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4102,11 +4108,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4106 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4112 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 177: -#line 1589 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1595 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4114,11 +4120,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4118 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4124 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 178: -#line 1598 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1604 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4126,11 +4132,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4130 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4136 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 179: -#line 1607 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1613 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4138,11 +4144,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4142 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4148 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 180: -#line 1616 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1622 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4150,11 +4156,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4154 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4160 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 181: -#line 1625 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1631 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4162,11 +4168,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4166 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4172 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 182: -#line 1635 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1641 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4174,11 +4180,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4178 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4184 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 183: -#line 1645 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1651 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[-2].str))); @@ -4187,11 +4193,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4191 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4197 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 184: -#line 1656 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1662 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -4199,11 +4205,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4203 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4209 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 185: -#line 1666 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1672 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -4211,11 +4217,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4215 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4221 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 186: -#line 1676 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1682 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4223,11 +4229,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4227 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4233 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 187: -#line 1685 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1691 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4235,11 +4241,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4239 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4245 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 188: -#line 1694 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1700 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4247,11 +4253,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4251 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4257 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 189: -#line 1703 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1709 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4259,11 +4265,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4263 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4269 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 190: -#line 1712 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1718 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4271,11 +4277,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4275 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4281 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 191: -#line 1721 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1727 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4283,11 +4289,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4287 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4293 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 192: -#line 1730 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1736 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4295,11 +4301,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4299 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4305 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 193: -#line 1740 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1746 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); @@ -4307,11 +4313,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4311 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4317 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 194: -#line 1750 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1756 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(7); jpCheckEmpty(7); @@ -4319,11 +4325,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4323 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4329 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 195: -#line 1760 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1766 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(7); jpCheckEmpty(7); @@ -4331,40 +4337,40 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4335 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4341 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 196: -#line 1770 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1776 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); } -#line 4344 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4350 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 197: -#line 1777 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1783 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); } -#line 4353 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4359 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 198: -#line 1783 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1789 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4364 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4370 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 199: -#line 1791 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1797 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4372,22 +4378,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4376 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4382 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 200: -#line 1800 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1806 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4387 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4393 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 201: -#line 1808 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1814 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -4395,11 +4401,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4399 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4405 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 202: -#line 1818 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1824 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -4407,11 +4413,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4411 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4417 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 203: -#line 1828 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1834 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4419,11 +4425,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4423 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4429 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 204: -#line 1837 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1843 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -4431,11 +4437,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4435 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4441 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 205: -#line 1847 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1853 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -4443,11 +4449,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4447 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4453 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 206: -#line 1856 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1862 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -4455,58 +4461,58 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4459 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4465 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 207: -#line 1866 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1872 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); } -#line 4468 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4474 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 208: -#line 1873 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1879 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); } -#line 4477 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4483 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 209: -#line 1880 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1886 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(7); } -#line 4486 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4492 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 210: -#line 1888 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1894 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(9); } -#line 4495 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4501 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 211: -#line 1894 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1900 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4506 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4512 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 212: -#line 1902 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1908 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4514,22 +4520,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4518 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4524 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 213: -#line 1911 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1917 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4529 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4535 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 214: -#line 1919 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1925 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4537,33 +4543,33 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4541 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4547 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 215: -#line 1930 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1936 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(9); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4552 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4558 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 216: -#line 1938 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1944 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4563 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4569 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 217: -#line 1946 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1952 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4571,11 +4577,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4575 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4581 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 218: -#line 1956 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1962 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4583,11 +4589,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4587 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4593 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 219: -#line 1965 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1971 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4595,11 +4601,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4599 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4605 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 220: -#line 1975 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1981 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4607,11 +4613,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4611 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4617 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 221: -#line 1985 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 1991 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4619,11 +4625,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4623 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4629 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 222: -#line 1994 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2000 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -4631,11 +4637,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4635 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4641 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 223: -#line 2004 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2010 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -4643,11 +4649,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4647 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4653 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 224: -#line 2013 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2019 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); @@ -4655,11 +4661,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4659 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4665 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 225: -#line 2023 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2029 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[-1].str))); @@ -4668,31 +4674,31 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4672 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4678 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 226: -#line 2033 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2039 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4683 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4689 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 227: -#line 2041 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2047 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); } -#line 4692 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4698 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 228: -#line 2048 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2054 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[-1].str))); @@ -4701,11 +4707,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4705 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4711 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 229: -#line 2059 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2065 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -4713,11 +4719,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4717 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4723 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 230: -#line 2069 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2075 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -4725,11 +4731,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4729 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4735 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 231: -#line 2079 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2085 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); @@ -4737,11 +4743,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4741 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4747 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 232: -#line 2089 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2095 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -4749,11 +4755,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4753 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4759 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 233: -#line 2098 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2104 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); @@ -4761,22 +4767,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4765 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4771 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 234: -#line 2107 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2113 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4776 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4782 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 235: -#line 2115 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2121 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4784,11 +4790,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4788 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4794 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 236: -#line 2125 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2131 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4796,11 +4802,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4800 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4806 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 237: -#line 2134 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2140 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -4808,20 +4814,20 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4812 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4818 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 238: -#line 2144 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2150 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); } -#line 4821 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4827 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 239: -#line 2151 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2157 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -4829,11 +4835,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4833 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4839 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 240: -#line 2161 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2167 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4841,11 +4847,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4845 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4851 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 241: -#line 2170 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2176 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4853,11 +4859,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4857 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4863 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 242: -#line 2180 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2186 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4865,20 +4871,20 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4869 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4875 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 243: -#line 2189 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2195 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); } -#line 4878 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4884 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 244: -#line 2195 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2201 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -4886,11 +4892,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4890 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4896 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 245: -#line 2204 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2210 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4898,11 +4904,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4902 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4908 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 246: -#line 2213 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2219 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4910,11 +4916,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4914 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4920 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 247: -#line 2222 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2228 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4922,11 +4928,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4926 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4932 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 248: -#line 2231 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2237 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4934,11 +4940,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4938 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4944 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 249: -#line 2241 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2247 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(6); jpCheckEmpty(6); @@ -4946,22 +4952,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4950 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4956 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 250: -#line 2250 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2256 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4961 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4967 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 251: -#line 2258 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2264 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4969,22 +4975,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4973 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4979 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 252: -#line 2267 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2273 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 4984 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 4990 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 253: -#line 2275 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2281 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -4992,11 +4998,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 4996 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5002 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 254: -#line 2285 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2291 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5004,11 +5010,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5008 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5014 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 255: -#line 2294 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2300 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5016,11 +5022,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5020 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5026 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 256: -#line 2304 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2310 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); @@ -5028,11 +5034,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5032 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5038 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 257: -#line 2313 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2319 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); @@ -5040,11 +5046,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5044 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5050 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 258: -#line 2322 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2328 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); @@ -5052,11 +5058,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5056 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5062 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 259: -#line 2331 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2337 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); @@ -5064,22 +5070,22 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5068 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5074 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 260: -#line 2340 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2346 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(0); (yyval.str) = 0; yyGetParser->SetCurrentCombine(""); } -#line 5079 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5085 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 261: -#line 2348 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2354 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5087,11 +5093,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5091 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5097 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 262: -#line 2358 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2364 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5099,11 +5105,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5103 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5109 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 263: -#line 2367 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2373 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -5111,11 +5117,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5115 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5121 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 264: -#line 2377 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2383 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5123,29 +5129,29 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5127 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5133 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 265: -#line 2387 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2393 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); } -#line 5136 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5142 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 266: -#line 2393 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2399 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); } -#line 5145 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5151 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 267: -#line 2400 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2406 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5154,11 +5160,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5158 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5164 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 268: -#line 2410 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2416 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5167,11 +5173,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5171 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5177 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 269: -#line 2420 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2426 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5180,11 +5186,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5184 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5190 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 270: -#line 2430 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2436 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5193,11 +5199,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5197 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5203 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 271: -#line 2441 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2447 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -5206,11 +5212,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5210 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5216 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 272: -#line 2451 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2457 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(6); yyGetParser->DeallocateParserType(&((yyvsp[-5].str))); @@ -5220,11 +5226,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5224 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5230 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 273: -#line 2462 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2468 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(6); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -5233,11 +5239,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5237 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5243 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 274: -#line 2472 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2478 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(6); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -5246,11 +5252,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5250 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5256 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 275: -#line 2483 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2489 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); yyGetParser->DeallocateParserType(&((yyvsp[-3].str))); @@ -5259,11 +5265,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5263 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5269 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 276: -#line 2493 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2499 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); @@ -5271,11 +5277,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5275 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5281 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 277: -#line 2503 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2509 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5283,11 +5289,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5287 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5293 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 278: -#line 2512 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2518 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5295,11 +5301,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5299 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5305 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 279: -#line 2521 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2527 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5307,11 +5313,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5311 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5317 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 280: -#line 2530 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2536 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5319,11 +5325,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5323 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5329 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 281: -#line 2539 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2545 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5331,11 +5337,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5335 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5341 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 282: -#line 2549 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2555 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -5343,11 +5349,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5347 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5353 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 283: -#line 2559 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2565 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -5355,11 +5361,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5359 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5365 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 284: -#line 2569 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2575 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5367,11 +5373,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5371 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5377 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 285: -#line 2578 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2584 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5379,11 +5385,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5383 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5389 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 286: -#line 2587 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2593 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -5391,11 +5397,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5395 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5401 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 287: -#line 2596 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2602 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -5403,11 +5409,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5407 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5413 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 288: -#line 2605 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2611 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5415,11 +5421,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5419 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5425 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 289: -#line 2615 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2621 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -5427,11 +5433,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5431 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5437 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 290: -#line 2625 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2631 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -5439,11 +5445,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5443 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5449 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 291: -#line 2635 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2641 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5451,11 +5457,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5455 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5461 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 292: -#line 2644 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2650 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -5463,11 +5469,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5467 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5473 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 293: -#line 2653 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2659 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(2); jpCheckEmpty(2); @@ -5475,11 +5481,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5479 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5485 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 294: -#line 2662 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2668 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5487,11 +5493,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5491 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5497 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 295: -#line 2672 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2678 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); @@ -5499,11 +5505,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5503 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5509 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 296: -#line 2681 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2687 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(4); jpCheckEmpty(4); @@ -5511,20 +5517,20 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5515 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5521 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 297: -#line 2690 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2696 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); } -#line 5524 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5530 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 298: -#line 2697 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2703 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5532,11 +5538,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5536 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5542 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 299: -#line 2706 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2712 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5544,11 +5550,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5548 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5554 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 300: -#line 2715 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2721 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5556,11 +5562,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5560 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5566 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 301: -#line 2724 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2730 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5568,11 +5574,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5572 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5578 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 302: -#line 2734 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2740 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5580,11 +5586,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5584 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5590 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 303: -#line 2743 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2749 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5592,11 +5598,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5596 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5602 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 304: -#line 2752 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2758 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5604,11 +5610,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5608 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5614 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 305: -#line 2762 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2768 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5616,11 +5622,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5620 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5626 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 306: -#line 2771 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2777 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5628,11 +5634,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5632 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5638 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 307: -#line 2780 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2786 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5640,11 +5646,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5644 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5650 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 308: -#line 2789 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2795 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5652,11 +5658,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5656 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5662 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 309: -#line 2799 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2805 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5664,11 +5670,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5668 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5674 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 310: -#line 2808 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2814 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5676,11 +5682,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5680 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5686 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 311: -#line 2817 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2823 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5688,11 +5694,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5692 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5698 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 312: -#line 2826 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2832 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5700,11 +5706,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5704 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5710 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 313: -#line 2835 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2841 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5712,11 +5718,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5716 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5722 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 314: -#line 2844 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2850 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5724,11 +5730,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5728 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5734 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 315: -#line 2854 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2860 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5736,11 +5742,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5740 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5746 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 316: -#line 2863 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2869 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5748,11 +5754,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5752 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5758 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 317: -#line 2872 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2878 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5760,11 +5766,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5764 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5770 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 318: -#line 2882 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2888 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5772,11 +5778,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5776 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5782 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 319: -#line 2891 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2897 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5784,11 +5790,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5788 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5794 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 320: -#line 2901 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2907 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5796,11 +5802,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5800 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5806 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 321: -#line 2910 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2916 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5808,11 +5814,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5812 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5818 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 322: -#line 2920 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2926 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5820,11 +5826,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5824 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5830 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 323: -#line 2929 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2935 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5832,11 +5838,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5836 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5842 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 324: -#line 2939 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2945 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5844,11 +5850,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5848 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5854 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 325: -#line 2948 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2954 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5856,11 +5862,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5860 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5866 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 326: -#line 2958 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2964 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5868,11 +5874,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5872 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5878 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 327: -#line 2967 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2973 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5880,11 +5886,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5884 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5890 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 328: -#line 2977 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2983 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5892,11 +5898,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5896 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5902 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 329: -#line 2986 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 2992 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(5); jpCheckEmpty(5); @@ -5904,11 +5910,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5908 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5914 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 330: -#line 2996 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3002 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5916,11 +5922,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5920 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5926 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 331: -#line 3005 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3011 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5928,11 +5934,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5932 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5938 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 332: -#line 3015 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3021 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpCheckEmpty(3); @@ -5940,11 +5946,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5944 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5950 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 333: -#line 3025 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3031 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); yyGetParser->DeallocateParserType(&((yyvsp[0].str))); @@ -5953,11 +5959,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5957 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5963 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 334: -#line 3035 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3041 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5965,11 +5971,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5969 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5975 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 335: -#line 3044 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3050 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5977,11 +5983,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5981 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5987 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 336: -#line 3054 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3060 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -5989,11 +5995,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 5993 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 5999 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 337: -#line 3063 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3069 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6001,11 +6007,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6005 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6011 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 338: -#line 3072 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3078 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6013,11 +6019,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6017 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6023 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 339: -#line 3081 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3087 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6025,11 +6031,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6029 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6035 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 340: -#line 3090 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3096 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6037,11 +6043,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6041 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6047 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 341: -#line 3099 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3105 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6049,11 +6055,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6053 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6059 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 342: -#line 3108 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3114 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6061,11 +6067,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6065 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6071 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 343: -#line 3117 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3123 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6073,11 +6079,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6077 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6083 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 344: -#line 3126 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3132 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6085,11 +6091,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6089 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6095 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 345: -#line 3135 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3141 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6097,11 +6103,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6101 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6107 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 346: -#line 3144 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3150 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6109,11 +6115,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6113 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6119 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 347: -#line 3153 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3159 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6121,11 +6127,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6125 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6131 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 348: -#line 3163 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3169 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6133,11 +6139,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6137 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6143 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 349: -#line 3173 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3179 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6145,11 +6151,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6149 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6155 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 350: -#line 3183 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3189 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(1); jpCheckEmpty(1); @@ -6157,11 +6163,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6161 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6167 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; case 351: -#line 3192 "cmDependsJavaParser.y" /* yacc.c:1646 */ +#line 3198 "cmDependsJavaParser.y" /* yacc.c:1646 */ { jpElementStart(3); jpStoreClass((yyvsp[-2].str)); @@ -6170,11 +6176,11 @@ yyreduce: yyGetParser->SetCurrentCombine(""); } -#line 6174 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6180 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ break; -#line 6178 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ +#line 6184 "cmDependsJavaParser.cxx" /* yacc.c:1646 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -6404,7 +6410,7 @@ yyreturn: #endif return yyresult; } -#line 3201 "cmDependsJavaParser.y" /* yacc.c:1906 */ +#line 3207 "cmDependsJavaParser.y" /* yacc.c:1906 */ /* End of grammar */ diff --git a/Source/cmDependsJavaParser.y b/Source/cmDependsJavaParser.y index ea7ca0f..150ac92 100644 --- a/Source/cmDependsJavaParser.y +++ b/Source/cmDependsJavaParser.y @@ -14,6 +14,12 @@ Modify cmDependsJavaParser.cxx: */ +#include // IWYU pragma: keep + +#include +#include +#include + #define yyGetParser (cmDependsJava_yyget_extra(yyscanner)) /*-------------------------------------------------------------------------*/ https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=74404df4405528d4d156d8761f71566d80ba4119 commit 74404df4405528d4d156d8761f71566d80ba4119 Author: Daniel Pfeifer AuthorDate: Fri Feb 17 22:12:21 2017 +0100 Commit: Daniel Pfeifer CommitDate: Fri Feb 17 22:12:21 2017 +0100 cmCommandArgumentParser: include what you use diff --git a/Source/cmCommandArgumentParser.cxx b/Source/cmCommandArgumentParser.cxx index 75191c8..4a7acfc 100644 --- a/Source/cmCommandArgumentParser.cxx +++ b/Source/cmCommandArgumentParser.cxx @@ -85,7 +85,9 @@ Modify cmCommandArgumentParser.cxx: */ -#include "cmStandardIncludes.h" +#include // IWYU pragma: keep + +#include #define yyGetParser (cmCommandArgument_yyget_extra(yyscanner)) @@ -125,7 +127,7 @@ static void cmCommandArgument_yyerror(yyscan_t yyscanner, const char* message); # pragma warning (disable: 4702) /* unreachable code */ #endif -#line 129 "cmCommandArgumentParser.cxx" /* yacc.c:339 */ +#line 131 "cmCommandArgumentParser.cxx" /* yacc.c:339 */ # ifndef YY_NULLPTR # if defined __cplusplus && 201103L <= __cplusplus @@ -198,7 +200,7 @@ int cmCommandArgument_yyparse (yyscan_t yyscanner); /* Copy the second part of user declarations. */ -#line 202 "cmCommandArgumentParser.cxx" /* yacc.c:358 */ +#line 204 "cmCommandArgumentParser.cxx" /* yacc.c:358 */ #ifdef short # undef short @@ -496,9 +498,9 @@ static const yytype_uint8 yytranslate[] = /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { - 0, 94, 94, 100, 103, 108, 111, 116, 119, 124, - 127, 130, 133, 136, 139, 144, 147, 150, 153, 158, - 161, 166, 169, 174, 177 + 0, 96, 96, 102, 105, 110, 113, 118, 121, 126, + 129, 132, 135, 138, 141, 146, 149, 152, 155, 160, + 163, 168, 171, 176, 179 }; #endif @@ -1295,192 +1297,192 @@ yyreduce: switch (yyn) { case 2: -#line 94 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 96 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = 0; yyGetParser->SetResult((yyvsp[0].str)); } -#line 1304 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1306 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 3: -#line 100 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 102 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = (yyvsp[0].str); } -#line 1312 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1314 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 4: -#line 103 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 105 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); } -#line 1320 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1322 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 5: -#line 108 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 110 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = 0; } -#line 1328 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1330 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 6: -#line 111 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 113 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); } -#line 1336 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1338 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 7: -#line 116 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 118 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = (yyvsp[0].str); } -#line 1344 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1346 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 8: -#line 119 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 121 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = (yyvsp[0].str); } -#line 1352 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1354 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 9: -#line 124 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 126 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = (yyvsp[0].str); } -#line 1360 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1362 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 10: -#line 127 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 129 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = (yyvsp[0].str); } -#line 1368 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1370 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 11: -#line 130 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 132 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = (yyvsp[0].str); } -#line 1376 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1378 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 12: -#line 133 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 135 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = (yyvsp[0].str); } -#line 1384 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1386 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 13: -#line 136 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 138 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = (yyvsp[0].str); } -#line 1392 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1394 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 14: -#line 139 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 141 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = (yyvsp[0].str); } -#line 1400 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1402 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 15: -#line 144 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 146 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str)); } -#line 1408 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1410 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 16: -#line 147 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 149 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = yyGetParser->ExpandSpecialVariable((yyvsp[-2].str), (yyvsp[-1].str)); } -#line 1416 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1418 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 17: -#line 150 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 152 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = yyGetParser->ExpandVariable((yyvsp[-1].str)); } -#line 1424 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1426 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 18: -#line 153 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 155 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = yyGetParser->ExpandVariableForAt((yyvsp[0].str)); } -#line 1432 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1434 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 19: -#line 158 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 160 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = (yyvsp[0].str); } -#line 1440 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1442 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 20: -#line 161 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 163 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = (yyvsp[-1].str); } -#line 1448 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1450 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 21: -#line 166 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 168 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = 0; } -#line 1456 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1458 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 22: -#line 169 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 171 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = yyGetParser->CombineUnions((yyvsp[-1].str), (yyvsp[0].str)); } -#line 1464 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1466 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 23: -#line 174 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 176 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = (yyvsp[0].str); } -#line 1472 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1474 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; case 24: -#line 177 "cmCommandArgumentParser.y" /* yacc.c:1646 */ +#line 179 "cmCommandArgumentParser.y" /* yacc.c:1646 */ { (yyval.str) = (yyvsp[0].str); } -#line 1480 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1482 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ break; -#line 1484 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ +#line 1486 "cmCommandArgumentParser.cxx" /* yacc.c:1646 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -1710,7 +1712,7 @@ yyreturn: #endif return yyresult; } -#line 182 "cmCommandArgumentParser.y" /* yacc.c:1906 */ +#line 184 "cmCommandArgumentParser.y" /* yacc.c:1906 */ /* End of grammar */ diff --git a/Source/cmCommandArgumentParser.y b/Source/cmCommandArgumentParser.y index cfd76d1..d71b605 100644 --- a/Source/cmCommandArgumentParser.y +++ b/Source/cmCommandArgumentParser.y @@ -14,7 +14,9 @@ Modify cmCommandArgumentParser.cxx: */ -#include "cmStandardIncludes.h" +#include // IWYU pragma: keep + +#include #define yyGetParser (cmCommandArgument_yyget_extra(yyscanner)) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e7168c087f6b7a917099cd196959d39f44fb0412 commit e7168c087f6b7a917099cd196959d39f44fb0412 Author: Daniel Pfeifer AuthorDate: Fri Feb 17 22:12:21 2017 +0100 Commit: Daniel Pfeifer CommitDate: Fri Feb 17 22:12:21 2017 +0100 cmExprParser: include what you use diff --git a/Source/cmExprParser.cxx b/Source/cmExprParser.cxx index d11d0b6..a9088a6 100644 --- a/Source/cmExprParser.cxx +++ b/Source/cmExprParser.cxx @@ -85,14 +85,17 @@ Modify cmExprParser.cxx: */ +#include // IWYU pragma: keep + +#include +#include + /*-------------------------------------------------------------------------*/ #define YYDEBUG 1 #include "cmExprParserHelper.h" /* Interface to parser object. */ #include "cmExprLexer.h" /* Interface to lexer object. */ #include "cmExprParserTokens.h" /* Need YYSTYPE for YY_DECL. */ -#include - /* Forward declare the lexer entry point. */ YY_DECL; @@ -105,7 +108,7 @@ static void cmExpr_yyerror(yyscan_t yyscanner, const char* message); # pragma warning (disable: 4065) /* Switch statement contains default but no case. */ #endif -#line 109 "cmExprParser.cxx" /* yacc.c:339 */ +#line 112 "cmExprParser.cxx" /* yacc.c:339 */ # ifndef YY_NULLPTR # if defined __cplusplus && 201103L <= __cplusplus @@ -182,7 +185,7 @@ int cmExpr_yyparse (yyscan_t yyscanner); /* Copy the second part of user declarations. */ -#line 186 "cmExprParser.cxx" /* yacc.c:358 */ +#line 189 "cmExprParser.cxx" /* yacc.c:358 */ #ifdef short # undef short @@ -481,9 +484,9 @@ static const yytype_uint8 yytranslate[] = /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { - 0, 70, 70, 75, 78, 83, 86, 91, 94, 99, - 102, 105, 110, 113, 116, 121, 124, 127, 130, 135, - 138, 141, 146, 149 + 0, 73, 73, 78, 81, 86, 89, 94, 97, 102, + 105, 108, 113, 116, 119, 124, 127, 130, 133, 138, + 141, 144, 149, 152 }; #endif @@ -1278,183 +1281,183 @@ yyreduce: switch (yyn) { case 2: -#line 70 "cmExprParser.y" /* yacc.c:1646 */ +#line 73 "cmExprParser.y" /* yacc.c:1646 */ { cmExpr_yyget_extra(yyscanner)->SetResult((yyvsp[0].Number)); } -#line 1286 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1289 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 3: -#line 75 "cmExprParser.y" /* yacc.c:1646 */ +#line 78 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1294 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1297 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 4: -#line 78 "cmExprParser.y" /* yacc.c:1646 */ +#line 81 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-2].Number) | (yyvsp[0].Number); } -#line 1302 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1305 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 5: -#line 83 "cmExprParser.y" /* yacc.c:1646 */ +#line 86 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1310 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1313 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 6: -#line 86 "cmExprParser.y" /* yacc.c:1646 */ +#line 89 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-2].Number) ^ (yyvsp[0].Number); } -#line 1318 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1321 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 7: -#line 91 "cmExprParser.y" /* yacc.c:1646 */ +#line 94 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1326 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1329 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 8: -#line 94 "cmExprParser.y" /* yacc.c:1646 */ +#line 97 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-2].Number) & (yyvsp[0].Number); } -#line 1334 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1337 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 9: -#line 99 "cmExprParser.y" /* yacc.c:1646 */ +#line 102 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1342 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1345 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 10: -#line 102 "cmExprParser.y" /* yacc.c:1646 */ +#line 105 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-2].Number) << (yyvsp[0].Number); } -#line 1350 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1353 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 11: -#line 105 "cmExprParser.y" /* yacc.c:1646 */ +#line 108 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-2].Number) >> (yyvsp[0].Number); } -#line 1358 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1361 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 12: -#line 110 "cmExprParser.y" /* yacc.c:1646 */ +#line 113 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1366 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1369 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 13: -#line 113 "cmExprParser.y" /* yacc.c:1646 */ +#line 116 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-2].Number) + (yyvsp[0].Number); } -#line 1374 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1377 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 14: -#line 116 "cmExprParser.y" /* yacc.c:1646 */ +#line 119 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-2].Number) - (yyvsp[0].Number); } -#line 1382 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1385 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 15: -#line 121 "cmExprParser.y" /* yacc.c:1646 */ +#line 124 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1390 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1393 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 16: -#line 124 "cmExprParser.y" /* yacc.c:1646 */ +#line 127 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-2].Number) * (yyvsp[0].Number); } -#line 1398 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1401 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 17: -#line 127 "cmExprParser.y" /* yacc.c:1646 */ +#line 130 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-2].Number) / (yyvsp[0].Number); } -#line 1406 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1409 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 18: -#line 130 "cmExprParser.y" /* yacc.c:1646 */ +#line 133 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-2].Number) % (yyvsp[0].Number); } -#line 1414 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1417 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 19: -#line 135 "cmExprParser.y" /* yacc.c:1646 */ +#line 138 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1422 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1425 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 20: -#line 138 "cmExprParser.y" /* yacc.c:1646 */ +#line 141 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = + (yyvsp[0].Number); } -#line 1430 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1433 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 21: -#line 141 "cmExprParser.y" /* yacc.c:1646 */ +#line 144 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = - (yyvsp[0].Number); } -#line 1438 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1441 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 22: -#line 146 "cmExprParser.y" /* yacc.c:1646 */ +#line 149 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[0].Number); } -#line 1446 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1449 "cmExprParser.cxx" /* yacc.c:1646 */ break; case 23: -#line 149 "cmExprParser.y" /* yacc.c:1646 */ +#line 152 "cmExprParser.y" /* yacc.c:1646 */ { (yyval.Number) = (yyvsp[-1].Number); } -#line 1454 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1457 "cmExprParser.cxx" /* yacc.c:1646 */ break; -#line 1458 "cmExprParser.cxx" /* yacc.c:1646 */ +#line 1461 "cmExprParser.cxx" /* yacc.c:1646 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -1684,7 +1687,7 @@ yyreturn: #endif return yyresult; } -#line 154 "cmExprParser.y" /* yacc.c:1906 */ +#line 157 "cmExprParser.y" /* yacc.c:1906 */ /* End of grammar */ diff --git a/Source/cmExprParser.y b/Source/cmExprParser.y index c7c4a7b..0429663 100644 --- a/Source/cmExprParser.y +++ b/Source/cmExprParser.y @@ -14,14 +14,17 @@ Modify cmExprParser.cxx: */ +#include // IWYU pragma: keep + +#include +#include + /*-------------------------------------------------------------------------*/ #define YYDEBUG 1 #include "cmExprParserHelper.h" /* Interface to parser object. */ #include "cmExprLexer.h" /* Interface to lexer object. */ #include "cmExprParserTokens.h" /* Need YYSTYPE for YY_DECL. */ -#include - /* Forward declare the lexer entry point. */ YY_DECL; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ee72803e9f2988d2cf493a6d096c2a0d483fc547 commit ee72803e9f2988d2cf493a6d096c2a0d483fc547 Author: Daniel Pfeifer AuthorDate: Fri Feb 17 22:12:21 2017 +0100 Commit: Daniel Pfeifer CommitDate: Fri Feb 17 22:12:21 2017 +0100 fix some include-what-you-use diagnostics diff --git a/Source/CPack/cmCPackGenerator.h b/Source/CPack/cmCPackGenerator.h index 5354fca..57b8fff 100644 --- a/Source/CPack/cmCPackGenerator.h +++ b/Source/CPack/cmCPackGenerator.h @@ -13,7 +13,6 @@ #include "cmCPackComponentGroup.h" #include "cmSystemTools.h" -class cmCPackGenerator; class cmCPackLog; class cmInstalledFile; class cmMakefile; diff --git a/Source/cmBuildNameCommand.cxx b/Source/cmBuildNameCommand.cxx index 12b69a8..93e5ca2 100644 --- a/Source/cmBuildNameCommand.cxx +++ b/Source/cmBuildNameCommand.cxx @@ -6,7 +6,6 @@ #include #include "cmMakefile.h" -#include "cmPolicies.h" #include "cmStateTypes.h" #include "cmSystemTools.h" diff --git a/Source/cmCTest.h b/Source/cmCTest.h index 4d33458..ebdc8b0 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -14,7 +14,6 @@ #include #include -class cmCTest; class cmCTestGenericHandler; class cmCTestStartCommand; class cmGeneratedFileStream; diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index b58dc62..1576722 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -1,6 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCommands.h" +#include "cmPolicies.h" #include "cmState.h" #include "cmAddCustomCommandCommand.h" diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index ff9ffc0..fd9d04b 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -8,6 +8,7 @@ #include #include #include +#include #include "cmAlgorithms.h" #include "cmExportTryCompileFileGenerator.h" diff --git a/Source/cmExportLibraryDependenciesCommand.cxx b/Source/cmExportLibraryDependenciesCommand.cxx index e3fb412..deecad8 100644 --- a/Source/cmExportLibraryDependenciesCommand.cxx +++ b/Source/cmExportLibraryDependenciesCommand.cxx @@ -9,7 +9,6 @@ #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" -#include "cmPolicies.h" #include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmTarget.h" diff --git a/Source/cmLinkLineDeviceComputer.cxx b/Source/cmLinkLineDeviceComputer.cxx index 6a700ff..6789555 100644 --- a/Source/cmLinkLineDeviceComputer.cxx +++ b/Source/cmLinkLineDeviceComputer.cxx @@ -2,10 +2,18 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmLinkLineDeviceComputer.h" + +#include +#include +#include + #include "cmComputeLinkInformation.h" #include "cmGeneratorTarget.h" #include "cmGlobalNinjaGenerator.h" -#include "cmOutputConverter.h" +#include "cmStateDirectory.h" +#include "cmStateTypes.h" + +class cmOutputConverter; cmLinkLineDeviceComputer::cmLinkLineDeviceComputer( cmOutputConverter* outputConverter, cmStateDirectory stateDir) diff --git a/Source/cmLinkLineDeviceComputer.h b/Source/cmLinkLineDeviceComputer.h index f4bb3eb..f275a0d 100644 --- a/Source/cmLinkLineDeviceComputer.h +++ b/Source/cmLinkLineDeviceComputer.h @@ -4,8 +4,17 @@ #ifndef cmLinkLineDeviceComputer_h #define cmLinkLineDeviceComputer_h +#include + +#include + #include "cmLinkLineComputer.h" + +class cmComputeLinkInformation; +class cmGeneratorTarget; class cmGlobalNinjaGenerator; +class cmOutputConverter; +class cmStateDirectory; class cmLinkLineDeviceComputer : public cmLinkLineComputer { diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx index 39e5684..5cf1853 100644 --- a/Source/cmLoadCommandCommand.cxx +++ b/Source/cmLoadCommandCommand.cxx @@ -2,22 +2,21 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmLoadCommandCommand.h" +#include +#include +#include +#include +#include + #include "cmCPluginAPI.cxx" #include "cmCPluginAPI.h" #include "cmDynamicLoader.h" #include "cmMakefile.h" -#include "cmPolicies.h" #include "cmState.h" #include "cmSystemTools.h" class cmExecutionStatus; -#include -#include -#include -#include -#include - #ifdef __QNX__ #include /* for malloc/free on QNX */ #endif diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 44c390c..07d712c 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -13,7 +13,6 @@ #include "cmInstallScriptGenerator.h" #include "cmInstallTargetGenerator.h" #include "cmLinkLineComputer.h" -#include "cmLinkLineDeviceComputer.h" #include "cmMakefile.h" #include "cmRulePlaceholderExpander.h" #include "cmSourceFile.h" diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index b76ddeb..8ed5051 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmMakefileExecutableTargetGenerator.h" +#include #include #include #include diff --git a/Source/cmMakefileExecutableTargetGenerator.h b/Source/cmMakefileExecutableTargetGenerator.h index 642182b..598ac3d 100644 --- a/Source/cmMakefileExecutableTargetGenerator.h +++ b/Source/cmMakefileExecutableTargetGenerator.h @@ -5,6 +5,8 @@ #include +#include + #include "cmMakefileTargetGenerator.h" class cmGeneratorTarget; diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index ff8b604..bc456cf 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -2,8 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmMakefileLibraryTargetGenerator.h" -#include // IWYU pragma: keep - +#include #include #include diff --git a/Source/cmOutputRequiredFilesCommand.cxx b/Source/cmOutputRequiredFilesCommand.cxx index f120971..3db0fec 100644 --- a/Source/cmOutputRequiredFilesCommand.cxx +++ b/Source/cmOutputRequiredFilesCommand.cxx @@ -10,7 +10,6 @@ #include "cmAlgorithms.h" #include "cmGeneratorExpression.h" #include "cmMakefile.h" -#include "cmPolicies.h" #include "cmSourceFile.h" #include "cmSystemTools.h" #include "cmTarget.h" diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 1d6972b..32dd547 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -14,6 +14,7 @@ #include #include "cmAlgorithms.h" +#include "cmFilePathChecksum.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmOutputConverter.h" diff --git a/Source/cmSourceGroupCommand.cxx b/Source/cmSourceGroupCommand.cxx index 5555199..631f2a6 100644 --- a/Source/cmSourceGroupCommand.cxx +++ b/Source/cmSourceGroupCommand.cxx @@ -2,7 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmSourceGroupCommand.h" +#include #include +#include #include "cmMakefile.h" #include "cmSourceGroup.h" diff --git a/Source/cmSubdirDependsCommand.cxx b/Source/cmSubdirDependsCommand.cxx index 36e84d5..0bb2c0a 100644 --- a/Source/cmSubdirDependsCommand.cxx +++ b/Source/cmSubdirDependsCommand.cxx @@ -2,8 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmSubdirDependsCommand.h" -#include "cmPolicies.h" - class cmExecutionStatus; bool cmSubdirDependsCommand::InitialPass(std::vector const&, diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 9efc13b..87fe440 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -45,6 +45,7 @@ #include #include #include +#include #if defined(_WIN32) #include diff --git a/Source/cmUseMangledMesaCommand.cxx b/Source/cmUseMangledMesaCommand.cxx index 3d57f0e..8ef0958 100644 --- a/Source/cmUseMangledMesaCommand.cxx +++ b/Source/cmUseMangledMesaCommand.cxx @@ -5,7 +5,6 @@ #include #include -#include "cmPolicies.h" #include "cmSystemTools.h" class cmExecutionStatus; diff --git a/Source/cmUtilitySourceCommand.cxx b/Source/cmUtilitySourceCommand.cxx index 9b24a74..37d8bfb 100644 --- a/Source/cmUtilitySourceCommand.cxx +++ b/Source/cmUtilitySourceCommand.cxx @@ -5,7 +5,6 @@ #include #include "cmMakefile.h" -#include "cmPolicies.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmSystemTools.h" diff --git a/Source/cmVariableRequiresCommand.cxx b/Source/cmVariableRequiresCommand.cxx index bff6ec5..10b0a88 100644 --- a/Source/cmVariableRequiresCommand.cxx +++ b/Source/cmVariableRequiresCommand.cxx @@ -3,7 +3,6 @@ #include "cmVariableRequiresCommand.h" #include "cmMakefile.h" -#include "cmPolicies.h" #include "cmState.h" #include "cmSystemTools.h" ----------------------------------------------------------------------- Summary of changes: Source/CPack/cmCPackGenerator.h | 1 - Source/cmBuildNameCommand.cxx | 1 - Source/cmCTest.h | 1 - Source/cmCommandArgumentParser.cxx | 110 +- Source/cmCommandArgumentParser.y | 4 +- Source/cmCommands.cxx | 1 + Source/cmCoreTryCompile.cxx | 1 + Source/cmDependsJavaParser.cxx | 1438 ++++++++++++------------ Source/cmDependsJavaParser.y | 6 + Source/cmExportLibraryDependenciesCommand.cxx | 1 - Source/cmExprParser.cxx | 109 +- Source/cmExprParser.y | 7 +- Source/cmFortranParser.cxx | 126 ++- Source/cmFortranParser.h | 4 +- Source/cmFortranParser.y | 8 +- Source/cmLinkLineDeviceComputer.cxx | 10 +- Source/cmLinkLineDeviceComputer.h | 9 + Source/cmLoadCommandCommand.cxx | 13 +- Source/cmLocalGenerator.cxx | 1 - Source/cmMakefileExecutableTargetGenerator.cxx | 1 + Source/cmMakefileExecutableTargetGenerator.h | 2 + Source/cmMakefileLibraryTargetGenerator.cxx | 3 +- Source/cmOutputRequiredFilesCommand.cxx | 1 - Source/cmQtAutoGenerators.cxx | 1 + Source/cmSourceGroupCommand.cxx | 2 + Source/cmStandardIncludes.h | 53 - Source/cmSubdirDependsCommand.cxx | 2 - Source/cmSystemTools.cxx | 1 + Source/cmUseMangledMesaCommand.cxx | 1 - Source/cmUtilitySourceCommand.cxx | 1 - Source/cmVariableRequiresCommand.cxx | 1 - 31 files changed, 956 insertions(+), 964 deletions(-) delete mode 100644 Source/cmStandardIncludes.h hooks/post-receive -- CMake From daniel at pfeifer-mail.de Fri Feb 17 16:51:07 2017 From: daniel at pfeifer-mail.de (Daniel Pfeifer) Date: Fri, 17 Feb 2017 16:51:07 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-254-ge939f8b Message-ID: <20170217215107.0E9C2F9FD4@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via e939f8b18003e9b3fd2e2f398d3a2a0f8e5a46ad (commit) via 89541d043d1d53b1a6c1082a9e9574b16165562d (commit) via a3ff237a5c221be52bbd2cf7b526fd19b5202a35 (commit) from b7af957834c120064057a0180487a56fc12ec7e1 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e939f8b18003e9b3fd2e2f398d3a2a0f8e5a46ad commit e939f8b18003e9b3fd2e2f398d3a2a0f8e5a46ad Merge: b7af957 89541d0 Author: Daniel Pfeifer AuthorDate: Fri Feb 17 16:51:06 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 17 16:51:06 2017 -0500 Merge topic 'iwyu' into next 89541d04 fixup! cmFortranParser: include what you use a3ff237a ParserHelper: Move macros to bottom of files https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=89541d043d1d53b1a6c1082a9e9574b16165562d commit 89541d043d1d53b1a6c1082a9e9574b16165562d Author: Daniel Pfeifer AuthorDate: Fri Feb 17 22:49:24 2017 +0100 Commit: Daniel Pfeifer CommitDate: Fri Feb 17 22:49:24 2017 +0100 fixup! cmFortranParser: include what you use diff --git a/Source/cmFortranParser.cxx b/Source/cmFortranParser.cxx index 45d9639..c67227f 100644 --- a/Source/cmFortranParser.cxx +++ b/Source/cmFortranParser.cxx @@ -97,7 +97,7 @@ Modify cmFortranParser.cxx: - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"] */ -#include +#include // IWYU pragma: keep #include #include diff --git a/Source/cmFortranParser.y b/Source/cmFortranParser.y index be4959c..3d68134 100644 --- a/Source/cmFortranParser.y +++ b/Source/cmFortranParser.y @@ -26,7 +26,7 @@ Modify cmFortranParser.cxx: - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"] */ -#include +#include // IWYU pragma: keep #include #include diff --git a/Source/cmFortranParserTokens.h b/Source/cmFortranParserTokens.h index 18b9e0a..8d6a5fe 100644 --- a/Source/cmFortranParserTokens.h +++ b/Source/cmFortranParserTokens.h @@ -130,7 +130,7 @@ extern int cmFortran_yydebug; union YYSTYPE { -#line 75 "cmFortranParser.y" /* yacc.c:1909 */ +#line 70 "cmFortranParser.y" /* yacc.c:1909 */ char* string; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a3ff237a5c221be52bbd2cf7b526fd19b5202a35 commit a3ff237a5c221be52bbd2cf7b526fd19b5202a35 Author: Daniel Pfeifer AuthorDate: Fri Feb 17 22:43:43 2017 +0100 Commit: Daniel Pfeifer CommitDate: Fri Feb 17 22:43:43 2017 +0100 ParserHelper: Move macros to bottom of files Since the class name is used in the macros, the iwyu tool gets confused wheter it needs a forward declaration or not. While editing the files, make sure structs have no typedef. Also, remove confusing comments about Java. diff --git a/Source/cmCommandArgumentParserHelper.h b/Source/cmCommandArgumentParserHelper.h index 95bf0ad..5bfb236 100644 --- a/Source/cmCommandArgumentParserHelper.h +++ b/Source/cmCommandArgumentParserHelper.h @@ -8,27 +8,15 @@ #include #include -#define YYSTYPE cmCommandArgumentParserHelper::ParserType -#define YYSTYPE_IS_DECLARED -#define YY_EXTRA_TYPE cmCommandArgumentParserHelper* -#define YY_DECL \ - int cmCommandArgument_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner) - -/** \class cmCommandArgumentParserHelper - * \brief Helper class for parsing java source files - * - * Finds dependencies for java file and list of outputs - */ - class cmMakefile; class cmCommandArgumentParserHelper { public: - typedef struct + struct ParserType { char* str; - } ParserType; + }; cmCommandArgumentParserHelper(); ~cmCommandArgumentParserHelper(); @@ -100,4 +88,10 @@ private: bool RemoveEmpty; }; +#define YYSTYPE cmCommandArgumentParserHelper::ParserType +#define YYSTYPE_IS_DECLARED +#define YY_EXTRA_TYPE cmCommandArgumentParserHelper* +#define YY_DECL \ + int cmCommandArgument_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner) + #endif diff --git a/Source/cmDependsJavaParserHelper.h b/Source/cmDependsJavaParserHelper.h index 71b939c..5f28f70 100644 --- a/Source/cmDependsJavaParserHelper.h +++ b/Source/cmDependsJavaParserHelper.h @@ -8,26 +8,18 @@ #include #include -class cmDependsJavaParserHelper; - -#define YYSTYPE cmDependsJavaParserHelper::ParserType -#define YYSTYPE_IS_DECLARED -#define YY_EXTRA_TYPE cmDependsJavaParserHelper* -#define YY_DECL int cmDependsJava_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner) - /** \class cmDependsJavaParserHelper * \brief Helper class for parsing java source files * * Finds dependencies for java file and list of outputs */ - class cmDependsJavaParserHelper { public: - typedef struct + struct ParserType { char* str; - } ParserType; + }; cmDependsJavaParserHelper(); ~cmDependsJavaParserHelper(); @@ -96,4 +88,9 @@ private: void CleanupParser(); }; +#define YYSTYPE cmDependsJavaParserHelper::ParserType +#define YYSTYPE_IS_DECLARED +#define YY_EXTRA_TYPE cmDependsJavaParserHelper* +#define YY_DECL int cmDependsJava_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner) + #endif diff --git a/Source/cmExprParserHelper.h b/Source/cmExprParserHelper.h index 8f00f1d..df365fc 100644 --- a/Source/cmExprParserHelper.h +++ b/Source/cmExprParserHelper.h @@ -8,23 +8,13 @@ #include #include -#define YYSTYPE cmExprParserHelper::ParserType -#define YYSTYPE_IS_DECLARED -#define YY_EXTRA_TYPE cmExprParserHelper* -#define YY_DECL int cmExpr_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner) - -/** \class cmExprParserHelper - * \brief Helper class for parsing java source files - * - * Finds dependencies for java file and list of outputs - */ class cmExprParserHelper { public: - typedef struct + struct ParserType { int Number; - } ParserType; + }; cmExprParserHelper(); ~cmExprParserHelper(); @@ -57,4 +47,9 @@ private: std::string ErrorString; }; +#define YYSTYPE cmExprParserHelper::ParserType +#define YYSTYPE_IS_DECLARED +#define YY_EXTRA_TYPE cmExprParserHelper* +#define YY_DECL int cmExpr_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner) + #endif ----------------------------------------------------------------------- Summary of changes: Source/cmCommandArgumentParserHelper.h | 22 ++++++++-------------- Source/cmDependsJavaParserHelper.h | 17 +++++++---------- Source/cmExprParserHelper.h | 19 +++++++------------ Source/cmFortranParser.cxx | 2 +- Source/cmFortranParser.y | 2 +- Source/cmFortranParserTokens.h | 2 +- 6 files changed, 25 insertions(+), 39 deletions(-) hooks/post-receive -- CMake From kwrobot at kitware.com Sat Feb 18 00:01:06 2017 From: kwrobot at kitware.com (Kitware Robot) Date: Sat, 18 Feb 2017 00:01:06 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-147-g74e83c5 Message-ID: <20170218050106.2F6E1FA27C@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 74e83c5ff5238af2c4dbb0001160a6b90a008ed6 (commit) from dbdd25bc95af100633008a31f1bbdf7146e211f7 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=74e83c5ff5238af2c4dbb0001160a6b90a008ed6 commit 74e83c5ff5238af2c4dbb0001160a6b90a008ed6 Author: Kitware Robot AuthorDate: Sat Feb 18 00:01:03 2017 -0500 Commit: Kitware Robot CommitDate: Sat Feb 18 00:01:03 2017 -0500 CMake Nightly Date Stamp diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 24d45c5..8420ee9 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 8) -set(CMake_VERSION_PATCH 20170217) +set(CMake_VERSION_PATCH 20170218) #set(CMake_VERSION_RC 1) ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From kwrobot at kitware.com Sun Feb 19 00:01:05 2017 From: kwrobot at kitware.com (Kitware Robot) Date: Sun, 19 Feb 2017 00:01:05 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-148-g96b6afd Message-ID: <20170219050105.DCD29FA2DB@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 96b6afdc4289a3f04983ee5f5af82c83b422c583 (commit) from 74e83c5ff5238af2c4dbb0001160a6b90a008ed6 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=96b6afdc4289a3f04983ee5f5af82c83b422c583 commit 96b6afdc4289a3f04983ee5f5af82c83b422c583 Author: Kitware Robot AuthorDate: Sun Feb 19 00:01:03 2017 -0500 Commit: Kitware Robot CommitDate: Sun Feb 19 00:01:03 2017 -0500 CMake Nightly Date Stamp diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 8420ee9..d8abb2a 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 8) -set(CMake_VERSION_PATCH 20170218) +set(CMake_VERSION_PATCH 20170219) #set(CMake_VERSION_RC 1) ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From kwrobot at kitware.com Mon Feb 20 00:01:05 2017 From: kwrobot at kitware.com (Kitware Robot) Date: Mon, 20 Feb 2017 00:01:05 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-149-gd36016a Message-ID: <20170220050105.64BE1FA759@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via d36016a8ff67fe72e9a388467f3fce456225c3ec (commit) from 96b6afdc4289a3f04983ee5f5af82c83b422c583 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d36016a8ff67fe72e9a388467f3fce456225c3ec commit d36016a8ff67fe72e9a388467f3fce456225c3ec Author: Kitware Robot AuthorDate: Mon Feb 20 00:01:02 2017 -0500 Commit: Kitware Robot CommitDate: Mon Feb 20 00:01:02 2017 -0500 CMake Nightly Date Stamp diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index d8abb2a..5dda9d0 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 8) -set(CMake_VERSION_PATCH 20170219) +set(CMake_VERSION_PATCH 20170220) #set(CMake_VERSION_RC 1) ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 20 10:03:43 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 20 Feb 2017 10:03:43 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-256-g503369e Message-ID: <20170220150343.8195DFA6C4@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 503369e7ca9efff903df4c551b60cb6ba424d2c1 (commit) via 8aa14994e338ac140a41a99c29c891f7a1548ab7 (commit) from e939f8b18003e9b3fd2e2f398d3a2a0f8e5a46ad (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=503369e7ca9efff903df4c551b60cb6ba424d2c1 commit 503369e7ca9efff903df4c551b60cb6ba424d2c1 Merge: e939f8b 8aa1499 Author: Brad King AuthorDate: Mon Feb 20 10:03:42 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 20 10:03:42 2017 -0500 Merge topic 'vs2017-fallback-sdk' into next 8aa14994 VS2017: If Win 8.1 SDK is not available, use Win 10 SDK https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8aa14994e338ac140a41a99c29c891f7a1548ab7 commit 8aa14994e338ac140a41a99c29c891f7a1548ab7 Author: Brad King AuthorDate: Mon Feb 20 09:46:58 2017 -0500 Commit: Brad King CommitDate: Mon Feb 20 10:00:28 2017 -0500 VS2017: If Win 8.1 SDK is not available, use Win 10 SDK We try to choose the Windows SDK version based on the version of Windows targeted by the build. However, if using VS 2017 without the Windows 8.1 SDK installed then we must fall back to the Windows 10 SDK even when targeting an older version of Windows. Inspired-by: gnaggnoyil diff --git a/Source/cmGlobalVisualStudio15Generator.cxx b/Source/cmGlobalVisualStudio15Generator.cxx index d11ee7c..4ded7a1 100644 --- a/Source/cmGlobalVisualStudio15Generator.cxx +++ b/Source/cmGlobalVisualStudio15Generator.cxx @@ -109,6 +109,18 @@ void cmGlobalVisualStudio15Generator::WriteSLNHeader(std::ostream& fout) } } +bool cmGlobalVisualStudio15Generator::InitializeWindows(cmMakefile *mf) +{ + // If the Win 8.1 SDK is installed then we can select a SDK matching + // the target Windows version. + if (vsSetupAPIHelper.IsWin81SDKInstalled()) { + return cmGlobalVisualStudio14Generator::InitializeWindows(mf); + } + // Otherwise we must choose a Win 10 SDK even if we are not targeting + // Windows 10. + return this->SelectWindows10SDK(mf, false); +} + bool cmGlobalVisualStudio15Generator::SelectWindowsStoreToolset( std::string& toolset) const { diff --git a/Source/cmGlobalVisualStudio15Generator.h b/Source/cmGlobalVisualStudio15Generator.h index 781b41e..ecf224d 100644 --- a/Source/cmGlobalVisualStudio15Generator.h +++ b/Source/cmGlobalVisualStudio15Generator.h @@ -28,6 +28,7 @@ public: virtual const char* GetToolsVersion() { return "15.0"; } protected: + bool InitializeWindows(cmMakefile *mf) CM_OVERRIDE; virtual bool SelectWindowsStoreToolset(std::string& toolset) const; virtual const char* GetIDEVersion() { return "15.0"; } ----------------------------------------------------------------------- Summary of changes: Source/cmGlobalVisualStudio15Generator.cxx | 12 ++++++++++++ Source/cmGlobalVisualStudio15Generator.h | 1 + 2 files changed, 13 insertions(+) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 20 10:34:27 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 20 Feb 2017 10:34:27 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-258-g76839b6 Message-ID: <20170220153427.F167EFA71E@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 76839b6a522342fd85190cce6bf052140ea2d5af (commit) via 4984d86008d6d40a96d6bc2b7a27f53627427bac (commit) from 503369e7ca9efff903df4c551b60cb6ba424d2c1 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=76839b6a522342fd85190cce6bf052140ea2d5af commit 76839b6a522342fd85190cce6bf052140ea2d5af Merge: 503369e 4984d86 Author: Brad King AuthorDate: Mon Feb 20 10:34:27 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 20 10:34:27 2017 -0500 Merge topic 'vs2017-fallback-sdk' into next 4984d860 fixup! VS2017: If Win 8.1 SDK is not available, use Win 10 SDK https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4984d86008d6d40a96d6bc2b7a27f53627427bac commit 4984d86008d6d40a96d6bc2b7a27f53627427bac Author: Brad King AuthorDate: Mon Feb 20 10:34:14 2017 -0500 Commit: Brad King CommitDate: Mon Feb 20 10:34:14 2017 -0500 fixup! VS2017: If Win 8.1 SDK is not available, use Win 10 SDK diff --git a/Source/cmGlobalVisualStudio15Generator.cxx b/Source/cmGlobalVisualStudio15Generator.cxx index 4ded7a1..ac67051 100644 --- a/Source/cmGlobalVisualStudio15Generator.cxx +++ b/Source/cmGlobalVisualStudio15Generator.cxx @@ -109,7 +109,7 @@ void cmGlobalVisualStudio15Generator::WriteSLNHeader(std::ostream& fout) } } -bool cmGlobalVisualStudio15Generator::InitializeWindows(cmMakefile *mf) +bool cmGlobalVisualStudio15Generator::InitializeWindows(cmMakefile* mf) { // If the Win 8.1 SDK is installed then we can select a SDK matching // the target Windows version. diff --git a/Source/cmGlobalVisualStudio15Generator.h b/Source/cmGlobalVisualStudio15Generator.h index ecf224d..7240e1a 100644 --- a/Source/cmGlobalVisualStudio15Generator.h +++ b/Source/cmGlobalVisualStudio15Generator.h @@ -28,7 +28,7 @@ public: virtual const char* GetToolsVersion() { return "15.0"; } protected: - bool InitializeWindows(cmMakefile *mf) CM_OVERRIDE; + bool InitializeWindows(cmMakefile* mf) CM_OVERRIDE; virtual bool SelectWindowsStoreToolset(std::string& toolset) const; virtual const char* GetIDEVersion() { return "15.0"; } ----------------------------------------------------------------------- Summary of changes: Source/cmGlobalVisualStudio15Generator.cxx | 2 +- Source/cmGlobalVisualStudio15Generator.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 20 10:34:46 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 20 Feb 2017 10:34:46 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-260-gaacd0cb Message-ID: <20170220153446.E9FACFA71D@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via aacd0cb0c9deb4f9f9ea78a0fd9320cb32fb5ede (commit) via f582eb753eb746086ef29f6249040f1d7d7e35f9 (commit) from 76839b6a522342fd85190cce6bf052140ea2d5af (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=aacd0cb0c9deb4f9f9ea78a0fd9320cb32fb5ede commit aacd0cb0c9deb4f9f9ea78a0fd9320cb32fb5ede Merge: 76839b6 f582eb7 Author: Brad King AuthorDate: Mon Feb 20 10:34:46 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 20 10:34:46 2017 -0500 Merge topic 'vs2017-fallback-sdk' into next f582eb75 VS2017: If Win 8.1 SDK is not available, use Win 10 SDK https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f582eb753eb746086ef29f6249040f1d7d7e35f9 commit f582eb753eb746086ef29f6249040f1d7d7e35f9 Author: Brad King AuthorDate: Mon Feb 20 09:46:58 2017 -0500 Commit: Brad King CommitDate: Mon Feb 20 10:34:31 2017 -0500 VS2017: If Win 8.1 SDK is not available, use Win 10 SDK We try to choose the Windows SDK version based on the version of Windows targeted by the build. However, if using VS 2017 without the Windows 8.1 SDK installed then we must fall back to the Windows 10 SDK even when targeting an older version of Windows. Inspired-by: gnaggnoyil diff --git a/Source/cmGlobalVisualStudio15Generator.cxx b/Source/cmGlobalVisualStudio15Generator.cxx index d11ee7c..ac67051 100644 --- a/Source/cmGlobalVisualStudio15Generator.cxx +++ b/Source/cmGlobalVisualStudio15Generator.cxx @@ -109,6 +109,18 @@ void cmGlobalVisualStudio15Generator::WriteSLNHeader(std::ostream& fout) } } +bool cmGlobalVisualStudio15Generator::InitializeWindows(cmMakefile* mf) +{ + // If the Win 8.1 SDK is installed then we can select a SDK matching + // the target Windows version. + if (vsSetupAPIHelper.IsWin81SDKInstalled()) { + return cmGlobalVisualStudio14Generator::InitializeWindows(mf); + } + // Otherwise we must choose a Win 10 SDK even if we are not targeting + // Windows 10. + return this->SelectWindows10SDK(mf, false); +} + bool cmGlobalVisualStudio15Generator::SelectWindowsStoreToolset( std::string& toolset) const { diff --git a/Source/cmGlobalVisualStudio15Generator.h b/Source/cmGlobalVisualStudio15Generator.h index 781b41e..7240e1a 100644 --- a/Source/cmGlobalVisualStudio15Generator.h +++ b/Source/cmGlobalVisualStudio15Generator.h @@ -28,6 +28,7 @@ public: virtual const char* GetToolsVersion() { return "15.0"; } protected: + bool InitializeWindows(cmMakefile* mf) CM_OVERRIDE; virtual bool SelectWindowsStoreToolset(std::string& toolset) const; virtual const char* GetIDEVersion() { return "15.0"; } ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 20 10:39:50 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 20 Feb 2017 10:39:50 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-264-g339b2b3 Message-ID: <20170220153950.677BEAFF17@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 339b2b31d66d599bb433c09d5eb34143dbff0d2c (commit) via d58d28a94142bfd290ea8053a60927138ac98d4d (commit) via 07953c18f3cf64ae599d38bcf3cdc2408fb5533b (commit) via f918b053b257690db4405a302da39fa5de14f1d9 (commit) from aacd0cb0c9deb4f9f9ea78a0fd9320cb32fb5ede (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=339b2b31d66d599bb433c09d5eb34143dbff0d2c commit 339b2b31d66d599bb433c09d5eb34143dbff0d2c Merge: aacd0cb d58d28a Author: Brad King AuthorDate: Mon Feb 20 10:39:47 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 20 10:39:47 2017 -0500 Merge topic 'iwyu' into next d58d28a9 ParserHelper: Move macros to bottom of files 07953c18 remove file cmStandardIncludes.h f918b053 cmFortranParser: include what you use https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d58d28a94142bfd290ea8053a60927138ac98d4d commit d58d28a94142bfd290ea8053a60927138ac98d4d Author: Daniel Pfeifer AuthorDate: Fri Feb 17 22:43:43 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 10:35:55 2017 -0500 ParserHelper: Move macros to bottom of files Since the class name is used in the macros, the iwyu tool gets confused wheter it needs a forward declaration or not. While editing the files, make sure structs have no typedef. Also, remove confusing comments about Java. diff --git a/Source/cmCommandArgumentParserHelper.h b/Source/cmCommandArgumentParserHelper.h index 95bf0ad..5bfb236 100644 --- a/Source/cmCommandArgumentParserHelper.h +++ b/Source/cmCommandArgumentParserHelper.h @@ -8,27 +8,15 @@ #include #include -#define YYSTYPE cmCommandArgumentParserHelper::ParserType -#define YYSTYPE_IS_DECLARED -#define YY_EXTRA_TYPE cmCommandArgumentParserHelper* -#define YY_DECL \ - int cmCommandArgument_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner) - -/** \class cmCommandArgumentParserHelper - * \brief Helper class for parsing java source files - * - * Finds dependencies for java file and list of outputs - */ - class cmMakefile; class cmCommandArgumentParserHelper { public: - typedef struct + struct ParserType { char* str; - } ParserType; + }; cmCommandArgumentParserHelper(); ~cmCommandArgumentParserHelper(); @@ -100,4 +88,10 @@ private: bool RemoveEmpty; }; +#define YYSTYPE cmCommandArgumentParserHelper::ParserType +#define YYSTYPE_IS_DECLARED +#define YY_EXTRA_TYPE cmCommandArgumentParserHelper* +#define YY_DECL \ + int cmCommandArgument_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner) + #endif diff --git a/Source/cmDependsJavaParserHelper.h b/Source/cmDependsJavaParserHelper.h index 71b939c..5f28f70 100644 --- a/Source/cmDependsJavaParserHelper.h +++ b/Source/cmDependsJavaParserHelper.h @@ -8,26 +8,18 @@ #include #include -class cmDependsJavaParserHelper; - -#define YYSTYPE cmDependsJavaParserHelper::ParserType -#define YYSTYPE_IS_DECLARED -#define YY_EXTRA_TYPE cmDependsJavaParserHelper* -#define YY_DECL int cmDependsJava_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner) - /** \class cmDependsJavaParserHelper * \brief Helper class for parsing java source files * * Finds dependencies for java file and list of outputs */ - class cmDependsJavaParserHelper { public: - typedef struct + struct ParserType { char* str; - } ParserType; + }; cmDependsJavaParserHelper(); ~cmDependsJavaParserHelper(); @@ -96,4 +88,9 @@ private: void CleanupParser(); }; +#define YYSTYPE cmDependsJavaParserHelper::ParserType +#define YYSTYPE_IS_DECLARED +#define YY_EXTRA_TYPE cmDependsJavaParserHelper* +#define YY_DECL int cmDependsJava_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner) + #endif diff --git a/Source/cmExprParserHelper.h b/Source/cmExprParserHelper.h index 8f00f1d..df365fc 100644 --- a/Source/cmExprParserHelper.h +++ b/Source/cmExprParserHelper.h @@ -8,23 +8,13 @@ #include #include -#define YYSTYPE cmExprParserHelper::ParserType -#define YYSTYPE_IS_DECLARED -#define YY_EXTRA_TYPE cmExprParserHelper* -#define YY_DECL int cmExpr_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner) - -/** \class cmExprParserHelper - * \brief Helper class for parsing java source files - * - * Finds dependencies for java file and list of outputs - */ class cmExprParserHelper { public: - typedef struct + struct ParserType { int Number; - } ParserType; + }; cmExprParserHelper(); ~cmExprParserHelper(); @@ -57,4 +47,9 @@ private: std::string ErrorString; }; +#define YYSTYPE cmExprParserHelper::ParserType +#define YYSTYPE_IS_DECLARED +#define YY_EXTRA_TYPE cmExprParserHelper* +#define YY_DECL int cmExpr_yylex(YYSTYPE* yylvalp, yyscan_t yyscanner) + #endif https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=07953c18f3cf64ae599d38bcf3cdc2408fb5533b commit 07953c18f3cf64ae599d38bcf3cdc2408fb5533b Author: Daniel Pfeifer AuthorDate: Fri Feb 17 22:25:09 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 10:35:55 2017 -0500 remove file cmStandardIncludes.h diff --git a/Source/cmFortranParser.h b/Source/cmFortranParser.h index 06985d2..e8273fb 100644 --- a/Source/cmFortranParser.h +++ b/Source/cmFortranParser.h @@ -6,7 +6,9 @@ #if !defined(cmFortranLexer_cxx) && !defined(cmFortranParser_cxx) #include -#include "cmStandardIncludes.h" +#include +#include +#include #endif #include /* size_t */ diff --git a/Source/cmStandardIncludes.h b/Source/cmStandardIncludes.h deleted file mode 100644 index a2047af..0000000 --- a/Source/cmStandardIncludes.h +++ /dev/null @@ -1,53 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -/** - * Include header files as a function of the build process, compiler, - * and operating system. - */ -#ifndef cmStandardIncludes_h -#define cmStandardIncludes_h - -#include - -// Provide fixed-size integer types. -#include - -#include -#include -#include -#include - -// we must have stl with the standard include style -#include -#include -#include -#include -#include -#include -#include - -// include the "c" string header -#include -#include -#include - -#if defined(_MSC_VER) -typedef unsigned short mode_t; -#else -#include -#endif - -// use this class to shrink the size of symbols in .o files -// std::string is really basic_string<....lots of stuff....> -// when combined with a map or set, the symbols can be > 2000 chars! -#include -// typedef cmsys::String std::string; - -/* Poison this operator to avoid common mistakes. */ -extern void operator<<(std::ostream&, const std::ostringstream&); - -#include "cmCustomCommandLines.h" -#include "cmDocumentationEntry.h" -#include "cmTargetLinkLibraryType.h" - -#endif https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f918b053b257690db4405a302da39fa5de14f1d9 commit f918b053b257690db4405a302da39fa5de14f1d9 Author: Daniel Pfeifer AuthorDate: Fri Feb 17 22:12:21 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 10:35:55 2017 -0500 cmFortranParser: include what you use diff --git a/Source/cmFortranParser.cxx b/Source/cmFortranParser.cxx index 896e589..c67227f 100644 --- a/Source/cmFortranParser.cxx +++ b/Source/cmFortranParser.cxx @@ -97,13 +97,17 @@ Modify cmFortranParser.cxx: - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"] */ +#include // IWYU pragma: keep + +#include +#include +#include + /*-------------------------------------------------------------------------*/ #define cmFortranParser_cxx #include "cmFortranParser.h" /* Interface to parser object. */ #include "cmFortranParserTokens.h" /* Need YYSTYPE for YY_DECL. */ -#include - /* Forward declare the lexer entry point. */ YY_DECL; @@ -124,7 +128,7 @@ static void cmFortran_yyerror(yyscan_t yyscanner, const char* message) # pragma warning (disable: 4244) /* Conversion to smaller type, data loss. */ #endif -#line 137 "cmFortranParser.cxx" /* yacc.c:339 */ +#line 132 "cmFortranParser.cxx" /* yacc.c:339 */ # ifndef YY_NULLPTR # if defined __cplusplus && 201103L <= __cplusplus @@ -244,11 +248,11 @@ extern int cmFortran_yydebug; union YYSTYPE { -#line 75 "cmFortranParser.y" /* yacc.c:355 */ +#line 70 "cmFortranParser.y" /* yacc.c:355 */ char* string; -#line 261 "cmFortranParser.cxx" /* yacc.c:355 */ +#line 256 "cmFortranParser.cxx" /* yacc.c:355 */ }; typedef union YYSTYPE YYSTYPE; @@ -264,7 +268,7 @@ int cmFortran_yyparse (yyscan_t yyscanner); /* Copy the second part of user declarations. */ -#line 277 "cmFortranParser.cxx" /* yacc.c:358 */ +#line 272 "cmFortranParser.cxx" /* yacc.c:358 */ #ifdef short # undef short @@ -565,13 +569,13 @@ static const yytype_uint8 yytranslate[] = /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { - 0, 103, 103, 103, 106, 110, 115, 124, 130, 137, - 142, 146, 151, 159, 164, 169, 174, 179, 184, 189, - 194, 199, 203, 207, 211, 215, 216, 221, 221, 221, - 222, 222, 223, 223, 224, 224, 225, 225, 226, 226, - 227, 227, 228, 228, 229, 229, 230, 230, 233, 234, - 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, - 245, 246, 247, 248 + 0, 98, 98, 98, 101, 105, 110, 119, 125, 132, + 137, 141, 146, 154, 159, 164, 169, 174, 179, 184, + 189, 194, 198, 202, 206, 210, 211, 216, 216, 216, + 217, 217, 218, 218, 219, 219, 220, 220, 221, 221, + 222, 222, 223, 223, 224, 224, 225, 225, 228, 229, + 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243 }; #endif @@ -1523,26 +1527,26 @@ yyreduce: switch (yyn) { case 4: -#line 106 "cmFortranParser.y" /* yacc.c:1646 */ +#line 101 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, true); } -#line 1541 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1536 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 5: -#line 110 "cmFortranParser.y" /* yacc.c:1646 */ +#line 105 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUse(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1551 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1546 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 6: -#line 115 "cmFortranParser.y" /* yacc.c:1646 */ +#line 110 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); if (cmsysString_strcasecmp((yyvsp[-2].string), "function") != 0 && @@ -1552,22 +1556,22 @@ yyreduce: } free((yyvsp[-2].string)); } -#line 1565 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1560 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 7: -#line 124 "cmFortranParser.y" /* yacc.c:1646 */ +#line 119 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUse(parser, (yyvsp[-4].string)); free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1576 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1571 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 8: -#line 130 "cmFortranParser.y" /* yacc.c:1646 */ +#line 125 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUse(parser, (yyvsp[-6].string)); @@ -1575,40 +1579,40 @@ yyreduce: free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1588 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1583 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 9: -#line 137 "cmFortranParser.y" /* yacc.c:1646 */ +#line 132 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, true); free((yyvsp[-2].string)); } -#line 1598 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1593 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 10: -#line 142 "cmFortranParser.y" /* yacc.c:1646 */ +#line 137 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, false); } -#line 1607 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1602 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 11: -#line 146 "cmFortranParser.y" /* yacc.c:1646 */ +#line 141 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUse(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1617 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1612 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 12: -#line 151 "cmFortranParser.y" /* yacc.c:1646 */ +#line 146 "cmFortranParser.y" /* yacc.c:1646 */ { if (cmsysString_strcasecmp((yyvsp[-4].string), "non_intrinsic") == 0) { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); @@ -1617,139 +1621,139 @@ yyreduce: free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1630 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1625 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 13: -#line 159 "cmFortranParser.y" /* yacc.c:1646 */ +#line 154 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1640 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1635 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 14: -#line 164 "cmFortranParser.y" /* yacc.c:1646 */ +#line 159 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleLineDirective(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1650 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1645 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 15: -#line 169 "cmFortranParser.y" /* yacc.c:1646 */ +#line 164 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1660 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1655 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 16: -#line 174 "cmFortranParser.y" /* yacc.c:1646 */ +#line 169 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1670 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1665 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 17: -#line 179 "cmFortranParser.y" /* yacc.c:1646 */ +#line 174 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleDefine(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1680 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1675 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 18: -#line 184 "cmFortranParser.y" /* yacc.c:1646 */ +#line 179 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUndef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1690 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1685 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 19: -#line 189 "cmFortranParser.y" /* yacc.c:1646 */ +#line 184 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIfdef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1700 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1695 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 20: -#line 194 "cmFortranParser.y" /* yacc.c:1646 */ +#line 189 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIfndef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1710 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1705 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 21: -#line 199 "cmFortranParser.y" /* yacc.c:1646 */ +#line 194 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIf(parser); } -#line 1719 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1714 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 22: -#line 203 "cmFortranParser.y" /* yacc.c:1646 */ +#line 198 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleElif(parser); } -#line 1728 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1723 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 23: -#line 207 "cmFortranParser.y" /* yacc.c:1646 */ +#line 202 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleElse(parser); } -#line 1737 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1732 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 24: -#line 211 "cmFortranParser.y" /* yacc.c:1646 */ +#line 206 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleEndif(parser); } -#line 1746 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1741 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 48: -#line 233 "cmFortranParser.y" /* yacc.c:1646 */ +#line 228 "cmFortranParser.y" /* yacc.c:1646 */ { free ((yyvsp[0].string)); } -#line 1752 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1747 "cmFortranParser.cxx" /* yacc.c:1646 */ break; case 55: -#line 240 "cmFortranParser.y" /* yacc.c:1646 */ +#line 235 "cmFortranParser.y" /* yacc.c:1646 */ { free ((yyvsp[0].string)); } -#line 1758 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1753 "cmFortranParser.cxx" /* yacc.c:1646 */ break; -#line 1762 "cmFortranParser.cxx" /* yacc.c:1646 */ +#line 1757 "cmFortranParser.cxx" /* yacc.c:1646 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -1979,6 +1983,6 @@ yyreturn: #endif return yyresult; } -#line 251 "cmFortranParser.y" /* yacc.c:1906 */ +#line 246 "cmFortranParser.y" /* yacc.c:1906 */ /* End of grammar */ diff --git a/Source/cmFortranParser.y b/Source/cmFortranParser.y index 7eb5ef5..3d68134 100644 --- a/Source/cmFortranParser.y +++ b/Source/cmFortranParser.y @@ -26,13 +26,17 @@ Modify cmFortranParser.cxx: - "#if 0" out yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"] */ +#include // IWYU pragma: keep + +#include +#include +#include + /*-------------------------------------------------------------------------*/ #define cmFortranParser_cxx #include "cmFortranParser.h" /* Interface to parser object. */ #include "cmFortranParserTokens.h" /* Need YYSTYPE for YY_DECL. */ -#include - /* Forward declare the lexer entry point. */ YY_DECL; diff --git a/Source/cmFortranParserTokens.h b/Source/cmFortranParserTokens.h index 18b9e0a..8d6a5fe 100644 --- a/Source/cmFortranParserTokens.h +++ b/Source/cmFortranParserTokens.h @@ -130,7 +130,7 @@ extern int cmFortran_yydebug; union YYSTYPE { -#line 75 "cmFortranParser.y" /* yacc.c:1909 */ +#line 70 "cmFortranParser.y" /* yacc.c:1909 */ char* string; ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 20 10:42:59 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 20 Feb 2017 10:42:59 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-151-g53a1ec6 Message-ID: <20170220154259.D15EDE4CDD@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 53a1ec631ddd59f4f4eaaf1633a784045e455342 (commit) via e2d78f7535951adc505014d3afde59b52caf35f1 (commit) from d36016a8ff67fe72e9a388467f3fce456225c3ec (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=53a1ec631ddd59f4f4eaaf1633a784045e455342 commit 53a1ec631ddd59f4f4eaaf1633a784045e455342 Merge: d36016a e2d78f7 Author: Brad King AuthorDate: Mon Feb 20 10:42:57 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 20 10:42:57 2017 -0500 Merge topic 'fix-CMP0017-path-case' e2d78f75 Windows: Fix inconsistent behavior on changes to case of path to cmake ----------------------------------------------------------------------- Summary of changes: Source/cmMakefile.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 20 10:43:02 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 20 Feb 2017 10:43:02 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-153-g168420f Message-ID: <20170220154302.33EB3E644E@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 168420f35cbcbd1ef0b2d24f3b254064e21c018e (commit) via 3287ba02540ae94d6b0105f84e930aa19cf61b19 (commit) from 53a1ec631ddd59f4f4eaaf1633a784045e455342 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=168420f35cbcbd1ef0b2d24f3b254064e21c018e commit 168420f35cbcbd1ef0b2d24f3b254064e21c018e Merge: 53a1ec6 3287ba0 Author: Brad King AuthorDate: Mon Feb 20 10:43:00 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 20 10:43:00 2017 -0500 Merge topic 'fix-CMAKE_ROOT-case' 3287ba02 Make CMAKE_ROOT independent of case of path used to invoke cmake ----------------------------------------------------------------------- Summary of changes: Source/cmSystemTools.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 20 10:43:04 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 20 Feb 2017 10:43:04 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-155-g5d17b68 Message-ID: <20170220154304.A4AD1F291A@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 5d17b68c675e0d05cd45835f366c62119ec7d7c8 (commit) via 734581f49fc0eac4c49e941c0cc450a04c866896 (commit) from 168420f35cbcbd1ef0b2d24f3b254064e21c018e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=5d17b68c675e0d05cd45835f366c62119ec7d7c8 commit 5d17b68c675e0d05cd45835f366c62119ec7d7c8 Merge: 168420f 734581f Author: Brad King AuthorDate: Mon Feb 20 10:43:02 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 20 10:43:02 2017 -0500 Merge topic 'productbuild_resources' 734581f4 CPack: Add support for CPACK_PRODUCTBULID_RESOURCES_DIR ----------------------------------------------------------------------- Summary of changes: Help/release/dev/productbuild_resources.rst | 7 +++++++ Modules/CPackProductBuild.cmake | 8 ++++++++ Source/CPack/cmCPackProductBuildGenerator.cxx | 17 +++++++++++++++-- 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 Help/release/dev/productbuild_resources.rst hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 20 10:43:07 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 20 Feb 2017 10:43:07 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-157-g66094d1 Message-ID: <20170220154307.3C6E5F3841@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 66094d12241417d9a1080c2f059bd053cda6dc82 (commit) via d32f9debc80e1fc90efb07392f829d998cbbc2c5 (commit) from 5d17b68c675e0d05cd45835f366c62119ec7d7c8 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=66094d12241417d9a1080c2f059bd053cda6dc82 commit 66094d12241417d9a1080c2f059bd053cda6dc82 Merge: 5d17b68 d32f9de Author: Brad King AuthorDate: Mon Feb 20 10:43:05 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 20 10:43:05 2017 -0500 Merge topic 'productbuild_component_plist' d32f9deb CPack: Add option to specify --component-plist for productbuild ----------------------------------------------------------------------- Summary of changes: Help/release/dev/productbuild_component_plist.rst | 7 +++++++ Modules/CPackComponent.cmake | 11 +++++++++-- Source/CPack/cmCPackComponentGroup.h | 4 ++++ Source/CPack/cmCPackGenerator.cxx | 5 +++++ Source/CPack/cmCPackProductBuildGenerator.cxx | 4 ++++ 5 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 Help/release/dev/productbuild_component_plist.rst hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 20 10:43:09 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 20 Feb 2017 10:43:09 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-165-g3c0de6d Message-ID: <20170220154309.A198EF38A4@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 3c0de6db2d9e0580f23cc95c4a1e00a8f66108c9 (commit) via d58d28a94142bfd290ea8053a60927138ac98d4d (commit) via 07953c18f3cf64ae599d38bcf3cdc2408fb5533b (commit) via f918b053b257690db4405a302da39fa5de14f1d9 (commit) via b74314c6fdfcc1520dff6ac93d7150c8bf3f75f4 (commit) via 74404df4405528d4d156d8761f71566d80ba4119 (commit) via e7168c087f6b7a917099cd196959d39f44fb0412 (commit) via ee72803e9f2988d2cf493a6d096c2a0d483fc547 (commit) from 66094d12241417d9a1080c2f059bd053cda6dc82 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3c0de6db2d9e0580f23cc95c4a1e00a8f66108c9 commit 3c0de6db2d9e0580f23cc95c4a1e00a8f66108c9 Merge: 66094d1 d58d28a Author: Brad King AuthorDate: Mon Feb 20 10:43:07 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 20 10:43:07 2017 -0500 Merge topic 'iwyu' d58d28a9 ParserHelper: Move macros to bottom of files 07953c18 remove file cmStandardIncludes.h f918b053 cmFortranParser: include what you use b74314c6 cmDependsJavaParser: include what you use 74404df4 cmCommandArgumentParser: include what you use e7168c08 cmExprParser: include what you use ee72803e fix some include-what-you-use diagnostics ----------------------------------------------------------------------- Summary of changes: Source/CPack/cmCPackGenerator.h | 1 - Source/cmBuildNameCommand.cxx | 1 - Source/cmCTest.h | 1 - Source/cmCommandArgumentParser.cxx | 110 +- Source/cmCommandArgumentParser.y | 4 +- Source/cmCommandArgumentParserHelper.h | 22 +- Source/cmCommands.cxx | 1 + Source/cmCoreTryCompile.cxx | 1 + Source/cmDependsJavaParser.cxx | 1438 ++++++++++++------------ Source/cmDependsJavaParser.y | 6 + Source/cmDependsJavaParserHelper.h | 17 +- Source/cmExportLibraryDependenciesCommand.cxx | 1 - Source/cmExprParser.cxx | 109 +- Source/cmExprParser.y | 7 +- Source/cmExprParserHelper.h | 19 +- Source/cmFortranParser.cxx | 126 ++- Source/cmFortranParser.h | 4 +- Source/cmFortranParser.y | 8 +- Source/cmFortranParserTokens.h | 2 +- Source/cmLinkLineDeviceComputer.cxx | 10 +- Source/cmLinkLineDeviceComputer.h | 9 + Source/cmLoadCommandCommand.cxx | 13 +- Source/cmLocalGenerator.cxx | 1 - Source/cmMakefileExecutableTargetGenerator.cxx | 1 + Source/cmMakefileExecutableTargetGenerator.h | 2 + Source/cmMakefileLibraryTargetGenerator.cxx | 3 +- Source/cmOutputRequiredFilesCommand.cxx | 1 - Source/cmQtAutoGenerators.cxx | 1 + Source/cmSourceGroupCommand.cxx | 2 + Source/cmStandardIncludes.h | 53 - Source/cmSubdirDependsCommand.cxx | 2 - Source/cmSystemTools.cxx | 1 + Source/cmUseMangledMesaCommand.cxx | 1 - Source/cmUtilitySourceCommand.cxx | 1 - Source/cmVariableRequiresCommand.cxx | 1 - 35 files changed, 979 insertions(+), 1001 deletions(-) delete mode 100644 Source/cmStandardIncludes.h hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 20 10:43:23 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 20 Feb 2017 10:43:23 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-273-g51286f9 Message-ID: <20170220154323.E85AAD788E@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 51286f98bb800640d3d39e53366e09012bffb824 (commit) via 3c0de6db2d9e0580f23cc95c4a1e00a8f66108c9 (commit) via 66094d12241417d9a1080c2f059bd053cda6dc82 (commit) via 5d17b68c675e0d05cd45835f366c62119ec7d7c8 (commit) via 168420f35cbcbd1ef0b2d24f3b254064e21c018e (commit) via 53a1ec631ddd59f4f4eaaf1633a784045e455342 (commit) via d36016a8ff67fe72e9a388467f3fce456225c3ec (commit) via 96b6afdc4289a3f04983ee5f5af82c83b422c583 (commit) via 74e83c5ff5238af2c4dbb0001160a6b90a008ed6 (commit) from 339b2b31d66d599bb433c09d5eb34143dbff0d2c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=51286f98bb800640d3d39e53366e09012bffb824 commit 51286f98bb800640d3d39e53366e09012bffb824 Merge: 339b2b3 3c0de6d Author: Brad King AuthorDate: Mon Feb 20 10:43:15 2017 -0500 Commit: Brad King CommitDate: Mon Feb 20 10:43:15 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 20 10:50:49 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 20 Feb 2017 10:50:49 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-276-g76fbab5 Message-ID: <20170220155049.543D4FA04A@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 76fbab5740aae8fbc9cd7566af34cc0b86909aea (commit) via 717e1f3056b45e79dcb433b1098e8b6fd813d07b (commit) via 0bbd993f618e4ded1d949e64ba778dfab3106262 (commit) from 51286f98bb800640d3d39e53366e09012bffb824 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=76fbab5740aae8fbc9cd7566af34cc0b86909aea commit 76fbab5740aae8fbc9cd7566af34cc0b86909aea Merge: 51286f9 717e1f3 Author: Brad King AuthorDate: Mon Feb 20 10:50:48 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 20 10:50:48 2017 -0500 Merge topic 'cmake-host-system-name' into next 717e1f30 Use looked up uname path for command execution 0bbd993f Make CMAKE_HOST_SYSTEM_NAME available in scripting context https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=717e1f3056b45e79dcb433b1098e8b6fd813d07b commit 717e1f3056b45e79dcb433b1098e8b6fd813d07b Author: Gregor Jasny AuthorDate: Sun Feb 19 17:28:49 2017 +0100 Commit: Gregor Jasny CommitDate: Sun Feb 19 19:27:34 2017 +0100 Use looked up uname path for command execution diff --git a/Modules/CMakeDetermineSystem.cmake b/Modules/CMakeDetermineSystem.cmake index fb1a9ed..f34ec5d 100644 --- a/Modules/CMakeDetermineSystem.cmake +++ b/Modules/CMakeDetermineSystem.cmake @@ -35,9 +35,9 @@ if(CMAKE_HOST_UNIX) find_program(CMAKE_UNAME uname /bin /usr/bin /usr/local/bin ) if(CMAKE_UNAME) - exec_program(uname ARGS -r OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_VERSION) + exec_program(${CMAKE_UNAME} ARGS -r OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_VERSION) if(CMAKE_HOST_SYSTEM_NAME MATCHES "Linux|CYGWIN.*|Darwin|^GNU$") - exec_program(uname ARGS -m OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR + exec_program(${CMAKE_UNAME} ARGS -m OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR RETURN_VALUE val) if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin" AND CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "Power Macintosh") @@ -48,10 +48,10 @@ if(CMAKE_HOST_UNIX) exec_program(arch ARGS -s OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR RETURN_VALUE val) else() - exec_program(uname ARGS -p OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR + exec_program(${CMAKE_UNAME} ARGS -p OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR RETURN_VALUE val) if("${val}" GREATER 0) - exec_program(uname ARGS -m OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR + exec_program(${CMAKE_UNAME} ARGS -m OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR RETURN_VALUE val) endif() endif() https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0bbd993f618e4ded1d949e64ba778dfab3106262 commit 0bbd993f618e4ded1d949e64ba778dfab3106262 Author: Gregor Jasny AuthorDate: Mon Dec 26 16:08:51 2016 +0100 Commit: Gregor Jasny CommitDate: Sun Feb 19 19:27:34 2017 +0100 Make CMAKE_HOST_SYSTEM_NAME available in scripting context diff --git a/Modules/CMakeDetermineSystem.cmake b/Modules/CMakeDetermineSystem.cmake index 8675553..fb1a9ed 100644 --- a/Modules/CMakeDetermineSystem.cmake +++ b/Modules/CMakeDetermineSystem.cmake @@ -35,7 +35,6 @@ if(CMAKE_HOST_UNIX) find_program(CMAKE_UNAME uname /bin /usr/bin /usr/local/bin ) if(CMAKE_UNAME) - exec_program(uname ARGS -s OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_NAME) exec_program(uname ARGS -r OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_VERSION) if(CMAKE_HOST_SYSTEM_NAME MATCHES "Linux|CYGWIN.*|Darwin|^GNU$") exec_program(uname ARGS -m OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_PROCESSOR @@ -67,7 +66,6 @@ if(CMAKE_HOST_UNIX) endif() else() if(CMAKE_HOST_WIN32) - set (CMAKE_HOST_SYSTEM_NAME "Windows") if (DEFINED ENV{PROCESSOR_ARCHITEW6432}) set (CMAKE_HOST_SYSTEM_PROCESSOR "$ENV{PROCESSOR_ARCHITEW6432}") else() diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx index c6288a5..80e494b 100644 --- a/Source/cmStateSnapshot.cxx +++ b/Source/cmStateSnapshot.cxx @@ -18,6 +18,10 @@ #include "cmVersion.h" #include "cmake.h" +#if !defined(_WIN32) +#include +#endif + #if defined(__CYGWIN__) #include "cmSystemTools.h" #endif @@ -298,9 +302,15 @@ void cmStateSnapshot::SetDefaultDefinitions() #if defined(_WIN32) this->SetDefinition("WIN32", "1"); this->SetDefinition("CMAKE_HOST_WIN32", "1"); + this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", "Windows"); #else this->SetDefinition("UNIX", "1"); this->SetDefinition("CMAKE_HOST_UNIX", "1"); + + struct utsname uts_name; + if (uname(&uts_name) == 0) { + this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", uts_name.sysname); + } #endif #if defined(__CYGWIN__) std::string legacy; diff --git a/Tests/CMakeTests/ToolchainTest.cmake.in b/Tests/CMakeTests/ToolchainTest.cmake.in index 96e7196..ea44f42 100644 --- a/Tests/CMakeTests/ToolchainTest.cmake.in +++ b/Tests/CMakeTests/ToolchainTest.cmake.in @@ -48,7 +48,6 @@ set(CMAKE_SYSTEM_NAME) set(CMAKE_SYSTEM_VERSION) set(CMAKE_SYSTEM_PROCESSOR) set(CMAKE_HOST_SYSTEM) -set(CMAKE_HOST_SYSTEM_NAME) set(CMAKE_HOST_SYSTEM_VERSION) set(CMAKE_HOST_SYSTEM_PROCESSOR) ----------------------------------------------------------------------- Summary of changes: Modules/CMakeDetermineSystem.cmake | 10 ++++------ Source/cmStateSnapshot.cxx | 10 ++++++++++ Tests/CMakeTests/ToolchainTest.cmake.in | 1 - 3 files changed, 14 insertions(+), 7 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 20 14:04:07 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 20 Feb 2017 14:04:07 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-278-g84c1cea Message-ID: <20170220190407.2C33EFA708@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 84c1cea905340971bc168f07cbd9114cfa86ceb4 (commit) via 2ab118a8591d8b27ae89de8f3c65b5797fd01dc2 (commit) from 76fbab5740aae8fbc9cd7566af34cc0b86909aea (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=84c1cea905340971bc168f07cbd9114cfa86ceb4 commit 84c1cea905340971bc168f07cbd9114cfa86ceb4 Merge: 76fbab5 2ab118a Author: Brad King AuthorDate: Mon Feb 20 14:04:06 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 20 14:04:06 2017 -0500 Merge topic 'FindGTK2-old-sigc++' into next 2ab118a8 FindGTK2: handle old libsigc++ versions https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=2ab118a8591d8b27ae89de8f3c65b5797fd01dc2 commit 2ab118a8591d8b27ae89de8f3c65b5797fd01dc2 Author: Ben Boeckel AuthorDate: Mon Feb 20 10:21:06 2017 -0500 Commit: Ben Boeckel CommitDate: Mon Feb 20 11:58:57 2017 -0500 FindGTK2: handle old libsigc++ versions Old versions of `libsigc++` do not have the version macros inside of its `sigc++config.h` header. Assume nothing about such headers and report version "zero". Fixes: #16654 diff --git a/Modules/FindGTK2.cmake b/Modules/FindGTK2.cmake index 6747be5..20d7924 100644 --- a/Modules/FindGTK2.cmake +++ b/Modules/FindGTK2.cmake @@ -223,7 +223,10 @@ function(_GTK2_SIGCXX_GET_VERSION _OUT_major _OUT_minor _OUT_micro _sigcxxversio set(${_OUT_minor} ${${_OUT_minor}} PARENT_SCOPE) set(${_OUT_micro} ${${_OUT_micro}} PARENT_SCOPE) else() - message(FATAL_ERROR "Include file ${_gtkversion_hdr} does not exist") + # The header does not have the version macros; assume it is ``0.0.0``. + set(${_OUT_major} 0) + set(${_OUT_minor} 0) + set(${_OUT_micro} 0) endif() endfunction() ----------------------------------------------------------------------- Summary of changes: Modules/FindGTK2.cmake | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 20 14:37:40 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 20 Feb 2017 14:37:40 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-335-g23f45e6 Message-ID: <20170220193740.A8C57FA672@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 23f45e62c9a7597f257b3da5f3cb82d15f6c167e (commit) via 786bd14c93e7d67209e9bacb0cb8bf0e56528681 (commit) via 279f14fb0b9546a14d9cb4ec358863ea60750d75 (commit) via 846484b2e2a1e4271553a27343fe8679bb21e229 (commit) via b7deafc692edd9183adc6b993e8df122b7d9e503 (commit) via 2f263657fd2b544ed75bfc9725dd30d6bc1cfd7d (commit) via ca38804669676e531c6f7cf6d2e442092194c6d0 (commit) via 50cde9c55aedb16eeb8c7fd2b550e980afca9f5b (commit) via 0e88ab697ca02665a44a60f005c8623100c26b95 (commit) via 364e60cdf76c05c4f87ab3aad19a81ee6145a4c4 (commit) via 06a0700afd94c14d6d9219f776904f1787b41945 (commit) via bcc6001f3cbf8ef47da872288f3c81e9600b9bc1 (commit) via 45de32fa6c20de954e0571dfb9a44b375c87a6c6 (commit) via 4612c1f6a7b201c12e7ff55633e744d4a4320147 (commit) via 45e9d66545cdabc6ea5103e6c5c2546e2e0a982b (commit) via 408b3783d63fc5f1ea0ee4a7a2bb2281bb13d64d (commit) via 6988d0e8d6f81326c938224387533e30890e63d6 (commit) via b636dae9b209b8f8e26bc7a7e579a0e1197dc414 (commit) via 4633cbb96fcaee77f0da674c5caa766447406e99 (commit) via a2a7d36b9b978ada6e41294fddba1ccd7332d6f5 (commit) via 50138b2dd140df493aaff2fccd0388322b6eebb8 (commit) via acb159fb817913c936a700cede9bff6383d2b0b8 (commit) via 9fc0cedfcf71a31d7334fd73ffb26410db32b174 (commit) via 8efe5364780a37b620d29c8ec3777a4406f46934 (commit) via 13cc1f905284d00424cb165bb6f06353df3ccb82 (commit) via 9d1508caf4faf0835cedd4e7d838fc685b11d92b (commit) via 9a7c167351958027c7139cb712deda58a5858ffc (commit) via 35f30aef42ec888a26aeb68b4b86cb25c6f20232 (commit) via 074534a56d4d6146c2389fd256299197e5bad027 (commit) via a51f1a91d9733c596113f799154ef45d647e7764 (commit) via b2063fd70fa6955acb2b9f02507097d03e2011a7 (commit) via 10beb4a0345f673feaeec798d452a48797c6820a (commit) via f37f1a647d5aba4de5903a3a3dc7700be55c99ec (commit) via 5bb997c24a7ba8b6f252cc7914858f5c12a543b6 (commit) via a9e3c903b6f74d181c76d1a2014a3af2babe6e41 (commit) via 2f3ecd4ea9518b2a110b995fe9ac171f026ccad5 (commit) via 739592c9256fb6f89ee15081c3944d42515ef8db (commit) via ad1f21313f553ecc7064accf582986112dc678d1 (commit) via 2296a2e9ee04fc83a294d51421038dca40b3150f (commit) via d3a9887149d638dd23df2b46ff67a90cd91d33fe (commit) via 6ae09b7c1473836236275e553fe9ff77f48306c1 (commit) via 9a7c9efeea0c2c2dfa20eb46dc75359c7f787629 (commit) via 86c2b552ad7bb3af97bb3c59576ddc7cac841d26 (commit) via 2fed7bcc1f4a19f4942cddfdd42278f1c20feccc (commit) via c29950cc1f532d78158b146c50b0c49b8d41c47a (commit) via 74a2fcff50356dcdcd4004664a2b2b81a8142660 (commit) via 21886ff66a8a84c20a3c7f24601b5a353d8c7d06 (commit) via 22faeef2626e10b281c82d10ba2653ecd940f398 (commit) via 32d0ee3576c9203104a17c6a75bfc1bf13192045 (commit) via 119876e6d5e71fb8a3f72ba35593ee43fd124203 (commit) via c88a3f72289a1fdfb9b47cdea025d50efee94501 (commit) via 25f0c2e14b0285d81ad0c6be401398e12e7ea89e (commit) via 763f717ce2251a7237e85a0ad9a4c86c94942642 (commit) via 3ee2b1623ecbef3164c412bb6a1d826ba788002b (commit) via ec24dcdb36db7b460113b2ce3f7a954800d41e90 (commit) via 6b31416d6c9bdc8b89a918f217a6678cc6083fed (commit) via 1bd74130f2a804d073081f7e3e4f307c3fecb07c (commit) from 84c1cea905340971bc168f07cbd9114cfa86ceb4 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=23f45e62c9a7597f257b3da5f3cb82d15f6c167e commit 23f45e62c9a7597f257b3da5f3cb82d15f6c167e Merge: 84c1cea 786bd14 Author: Brad King AuthorDate: Mon Feb 20 14:37:37 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 20 14:37:37 2017 -0500 Merge topic 'autogen_json' into next 786bd14c Autogen: Documentation update 279f14fb Autogen: Add release notes for Q_PLUGIN_METADATA support 846484b2 Autogen: Tests: Set different compression levels in rcc test b7deafc6 Autogen: Overhaul and simplify AutogenInfo.cmake file generation 2f263657 Autogen: Optimize GetCompileDefinitionsAndDirectories function ca388046 Autogen: Sort AutogenInfo.cmake.in 50cde9c5 Autogen: Tests: Add Q_PLUGIN_METADATA test 0e88ab69 Autogen: Tests: Add moc include tests 364e60cd Autogen: Tests: Clean comments 06a0700a Autogen: Log simplifications bcc6001f Autogen: Only touch an unchanged moc_compilation.cpp 45de32fa Autogen: Rebuild moc when Q_PLUGIN_METADATA json file changes 4612c1f6 Autogen: Use GetRealPath in central places only 45e9d665 Autogen: Search moc includes in include directories 408b3783 Autogen: Sort includes before composing include options 6988d0e8 Autogen: Add FindInIncludeDirectories method ... https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=786bd14c93e7d67209e9bacb0cb8bf0e56528681 commit 786bd14c93e7d67209e9bacb0cb8bf0e56528681 Author: Sebastian Holtermann AuthorDate: Sun Feb 19 20:11:18 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 14:36:54 2017 -0500 Autogen: Documentation update Closes #15254 diff --git a/Help/manual/cmake-qt.7.rst b/Help/manual/cmake-qt.7.rst index 56d4ca7..e9da396 100644 --- a/Help/manual/cmake-qt.7.rst +++ b/Help/manual/cmake-qt.7.rst @@ -63,20 +63,24 @@ If a ``Q_OBJECT`` or ``Q_GADGET`` macro is found in a header file, ``moc`` will be run on the file. The result will be put into a file named according to ``moc_.cpp``. If the macro is found in a C++ implementation file, the moc output will be put into a file named according to -``.moc``, following the Qt conventions. The ``moc file`` may be -included by the user in the C++ implementation file with a preprocessor -``#include``. If it is not so included, it will be added to a separate file -which is compiled into the target. +``.moc``, following the Qt conventions. The ``.moc`` must +be included by the user in the C++ implementation file with a preprocessor +``#include``. -The ``moc`` command line will consume the :prop_tgt:`COMPILE_DEFINITIONS` and -:prop_tgt:`INCLUDE_DIRECTORIES` target properties from the target it is being -invoked for, and for the appropriate build configuration. - -The generated ``moc_*.cpp`` and ``*.moc`` files are placed in the +Included ``moc_*.cpp`` and ``*.moc`` files will be generated in the ``/_autogen/include`` directory which is automatically added to the target's :prop_tgt:`INCLUDE_DIRECTORIES`. (This differs from CMake 3.7 and below; see their documentation for details.) +Not included ``moc_.cpp`` files will be generated in custom +folders to avoid name collisions and included in a separate +``/_autogen/moc_compilation.cpp`` +file which is compiled into the target. + +The ``moc`` command line will consume the :prop_tgt:`COMPILE_DEFINITIONS` and +:prop_tgt:`INCLUDE_DIRECTORIES` target properties from the target it is being +invoked for, and for the appropriate build configuration. + The :prop_tgt:`AUTOMOC` target property may be pre-set for all following targets by setting the :variable:`CMAKE_AUTOMOC` variable. The :prop_tgt:`AUTOMOC_MOC_OPTIONS` target property may be populated to set diff --git a/Help/prop_tgt/AUTOMOC.rst b/Help/prop_tgt/AUTOMOC.rst index b42643f..4ac9b6e 100644 --- a/Help/prop_tgt/AUTOMOC.rst +++ b/Help/prop_tgt/AUTOMOC.rst @@ -8,31 +8,41 @@ preprocessor automatically, i.e. without having to use the :module:`QT4_WRAP_CPP() ` or QT5_WRAP_CPP() macro. Currently Qt4 and Qt5 are supported. -When this property is set ``ON``, CMake will scan the +When this property is set ``ON``, CMake will scan the header and source files at build time and invoke moc accordingly. -* If an ``#include`` statement like ``#include "moc_foo.cpp"`` is found, - the ``Q_OBJECT`` class declaration is expected in the header, and - ``moc`` is run on the header file. A ``moc_foo.cpp`` file will be - generated from the source's header into the - ``/_autogen/include`` - directory which is automatically added to the target's +* If an ``#include`` statement like ``#include "moc_.cpp"`` is found, + the ``Q_OBJECT`` or ``Q_GADGET`` macros are expected in an otherwise empty + line of the ``.h(xx)`` header file. ``moc`` is run on the header file to + generate ``moc_.cpp`` in the + ``/_autogen/include`` directory + which is automatically added to the target's :prop_tgt:`INCLUDE_DIRECTORIES`. This allows the compiler to find the - included ``moc_foo.cpp`` file regardless of the location the original source. - However, if multiple source files in different directories do this then their - generated moc files would collide. In this case a diagnostic will be issued. - -* If an ``#include`` statement like ``#include "foo.moc"`` is found, - then a ``Q_OBJECT`` is expected in the current source file and ``moc`` - is run on the file itself. Additionally, header files with the same - base name (like ``foo.h``) or ``_p`` appended to the base name (like - ``foo_p.h``) are parsed for ``Q_OBJECT`` macros, and if found, ``moc`` - is also executed on those files. ``AUTOMOC`` checks multiple header - alternative extensions, such as ``hpp``, ``hxx`` etc when searching - for headers. The resulting moc files, which are not included as shown - above in any of the source files are included in a generated - ``moc_compilation.cpp`` file, which is compiled as part of the - target. + included ``moc_.cpp`` file regardless of the location the + original source. + +* If an ``#include`` statement like ``#include ".moc"`` is found, + then ``Q_OBJECT`` or ``Q_GADGET`` macros are expected in the current source + file and ``moc`` is run on the source file itself. + +* Header files that are not included by an ``#include "moc_.cpp"`` + statement are nonetheless scanned for ``Q_OBJECT`` or ``Q_GADGET`` macros. + The resulting ``moc_.cpp`` files are generated in custom + directories and automatically included in the generated + ``/_autogen/moc_compilation.cpp`` file, + which is compiled as part of the target. The custom directories help to + avoid name collisions for moc files with the same ````. + +* Additionally, header files with the same base name as a source file, + (like ``.h``) or ``_p`` appended to the base name (like + ``_p.h``), are parsed for ``Q_OBJECT`` or ``Q_GADGET`` macros, + and if found, ``moc`` is also executed on those files. + +* ``AUTOMOC`` always checks multiple header alternative extensions, + such as ``hpp``, ``hxx``, etc. when searching for headers. + +* ``AUTOMOC`` looks for the ``Q_PLUGIN_METADATA`` macro and reruns the + ``moc`` when the file addressed by the ``FILE`` argument of the macro changes. This property is initialized by the value of the :variable:`CMAKE_AUTOMOC` variable if it is set when a target is created. https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=279f14fb0b9546a14d9cb4ec358863ea60750d75 commit 279f14fb0b9546a14d9cb4ec358863ea60750d75 Author: Sebastian Holtermann AuthorDate: Sun Feb 19 18:35:40 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 14:36:54 2017 -0500 Autogen: Add release notes for Q_PLUGIN_METADATA support diff --git a/Help/release/dev/Autogen_json.rst b/Help/release/dev/Autogen_json.rst new file mode 100644 index 0000000..73bbdf1 --- /dev/null +++ b/Help/release/dev/Autogen_json.rst @@ -0,0 +1,10 @@ +AutoGen json +------------ + +* When using :prop_tgt:`AUTOMOC`, CMake scans for the presence of the + ``Q_PLUGIN_METADATA`` macro and reruns moc when the file from the + macro's ``FILE`` argument changes. + +* When :prop_tgt:`AUTOMOC` detects an include statement of the form + ``#include "moc_.cpp"`` the respective header file is searched + for in the :prop_tgt:`INCLUDE_DIRECTORIES` of the target as well. https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=846484b2e2a1e4271553a27343fe8679bb21e229 commit 846484b2e2a1e4271553a27343fe8679bb21e229 Author: Sebastian Holtermann AuthorDate: Sun Feb 19 17:24:30 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 20:34:35 2017 +0100 Autogen: Tests: Set different compression levels in rcc test diff --git a/Tests/QtAutogen/sameName/CMakeLists.txt b/Tests/QtAutogen/sameName/CMakeLists.txt index 9e47a3e..4d2dcd9 100644 --- a/Tests/QtAutogen/sameName/CMakeLists.txt +++ b/Tests/QtAutogen/sameName/CMakeLists.txt @@ -18,3 +18,14 @@ add_executable(sameName ) target_link_libraries(sameName ${QT_LIBRARIES}) set_target_properties(sameName PROPERTIES AUTOMOC TRUE AUTORCC TRUE) + +# Set different compression levels +if (QT_TEST_VERSION STREQUAL 4) + set(rccCompress "-compress") +else() + set(rccCompress "--compress") +endif() +set_target_properties(sameName PROPERTIES AUTORCC_OPTIONS "${rccCompress};0" ) +set_source_files_properties(aaa/data.qrc PROPERTIES AUTORCC_OPTIONS "${rccCompress};1" ) +set_source_files_properties(bbb/data.qrc PROPERTIES AUTORCC_OPTIONS "${rccCompress};2" ) +set_source_files_properties(ccc/data.qrc PROPERTIES AUTORCC_OPTIONS "${rccCompress};3" ) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b7deafc692edd9183adc6b993e8df122b7d9e503 commit b7deafc692edd9183adc6b993e8df122b7d9e503 Author: Sebastian Holtermann AuthorDate: Sun Feb 19 16:46:47 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 20:34:35 2017 +0100 Autogen: Overhaul and simplify AutogenInfo.cmake file generation diff --git a/Modules/AutogenInfo.cmake.in b/Modules/AutogenInfo.cmake.in index 3135909..b647ecf 100644 --- a/Modules/AutogenInfo.cmake.in +++ b/Modules/AutogenInfo.cmake.in @@ -1,5 +1,5 @@ # Target names -set(AM_TARGET_NAME @_moc_target_name@) +set(AM_TARGET_NAME @_autogen_target_name@) set(AM_ORIGIN_TARGET_NAME @_origin_target_name@) # Directories and files set(AM_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@/") @@ -10,16 +10,16 @@ set(AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE "@CMAKE_INCLUDE_DIRECTORIES_PROJ set(AM_SOURCES @_sources@) set(AM_HEADERS @_headers@) # Qt environment -set(AM_QT_VERSION_MAJOR "@_target_qt_version@") -set(AM_QT_MOC_EXECUTABLE "@_qt_moc_executable@") -set(AM_QT_UIC_EXECUTABLE "@_qt_uic_executable@") -set(AM_QT_RCC_EXECUTABLE "@_qt_rcc_executable@") +set(AM_QT_VERSION_MAJOR @_qt_version_major@) +set(AM_QT_MOC_EXECUTABLE @_qt_moc_executable@) +set(AM_QT_UIC_EXECUTABLE @_qt_uic_executable@) +set(AM_QT_RCC_EXECUTABLE @_qt_rcc_executable@) # MOC settings set(AM_MOC_SKIP @_moc_skip@) set(AM_MOC_COMPILE_DEFINITIONS @_moc_compile_defs@) set(AM_MOC_INCLUDES @_moc_incs@) set(AM_MOC_OPTIONS @_moc_options@) -set(AM_MOC_RELAXED_MODE "@_moc_relaxed_mode@") +set(AM_MOC_RELAXED_MODE @_moc_relaxed_mode@) # UIC settings set(AM_UIC_SKIP @_uic_skip@) set(AM_UIC_TARGET_OPTIONS @_uic_target_options@) diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index c201023..cad0911 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -55,6 +55,13 @@ static std::string utilStripCR(std::string const& line) return line; } +static std::string GetSafeProperty(cmGeneratorTarget const* target, + const char* key) +{ + const char* tmp = target->GetProperty(key); + return std::string((tmp != CM_NULLPTR) ? tmp : ""); +} + static std::string GetAutogenTargetName(cmGeneratorTarget const* target) { std::string autogenTargetName = target->GetName(); @@ -118,19 +125,33 @@ static void GetCompileDefinitionsAndDirectories( } } +static void AddDefinitionEscaped(cmMakefile* makefile, const char* key, + const std::string& value) +{ + makefile->AddDefinition(key, + cmOutputConverter::EscapeForCMake(value).c_str()); +} + +static void AddDefinitionEscaped(cmMakefile* makefile, const char* key, + const std::vector values) +{ + makefile->AddDefinition( + key, cmOutputConverter::EscapeForCMake(cmJoin(values, ";")).c_str()); +} + static void SetupSourceFiles(cmGeneratorTarget const* target, std::vector& mocUicSources, std::vector& mocUicHeaders, - std::vector& skipMocList, - std::vector& skipUicList) + std::vector& mocSkipList, + std::vector& uicSkipList) { cmMakefile* makefile = target->Target->GetMakefile(); std::vector srcFiles; target->GetConfigCommonSourceFiles(srcFiles); - const bool targetMoc = target->GetPropertyAsBool("AUTOMOC"); - const bool targetUic = target->GetPropertyAsBool("AUTOUIC"); + const bool mocTarget = target->GetPropertyAsBool("AUTOMOC"); + const bool uicTarget = target->GetPropertyAsBool("AUTOUIC"); cmFilePathChecksum fpathCheckSum(makefile); for (std::vector::const_iterator fileIt = srcFiles.begin(); @@ -151,22 +172,22 @@ static void SetupSourceFiles(cmGeneratorTarget const* target, // Skip flags const bool skipAll = cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOGEN")); - const bool skipMoc = + const bool mocSkip = skipAll || cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOMOC")); - const bool skipUic = + const bool uicSkip = skipAll || cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOUIC")); // 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 // processing - if (skipMoc) { - skipMocList.push_back(absFile); + if (mocSkip) { + mocSkipList.push_back(absFile); } - if (skipUic) { - skipUicList.push_back(absFile); + if (uicSkip) { + uicSkipList.push_back(absFile); } - if ((targetMoc && !skipMoc) || (targetUic && !skipUic)) { + if ((mocTarget && !mocSkip) || (uicTarget && !uicSkip)) { // Add file name to sources or headers list switch (fileType) { case cmSystemTools::CXX_FILE_FORMAT: @@ -184,80 +205,85 @@ static void SetupSourceFiles(cmGeneratorTarget const* target, static void MocSetupAutoTarget( cmGeneratorTarget const* target, const std::string& autogenTargetName, - std::vector const& skipMoc, + const std::string& qtMajorVersion, + std::vector const& mocSkipList, std::map& configIncludes, std::map& configDefines) { cmLocalGenerator* lg = target->GetLocalGenerator(); cmMakefile* makefile = target->Target->GetMakefile(); - const char* tmp = target->GetProperty("AUTOMOC_MOC_OPTIONS"); - std::string _moc_options = (tmp != CM_NULLPTR ? tmp : ""); - makefile->AddDefinition( - "_moc_options", cmOutputConverter::EscapeForCMake(_moc_options).c_str()); - makefile->AddDefinition( - "_moc_skip", - cmOutputConverter::EscapeForCMake(cmJoin(skipMoc, ";")).c_str()); - bool relaxedMode = makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE"); - makefile->AddDefinition("_moc_relaxed_mode", relaxedMode ? "TRUE" : "FALSE"); - - std::string _moc_incs; - std::string _moc_compile_defs; - std::vector configs; - const std::string& config = makefile->GetConfigurations(configs); - GetCompileDefinitionsAndDirectories(target, config, _moc_incs, - _moc_compile_defs); + AddDefinitionEscaped(makefile, "_moc_options", + GetSafeProperty(target, "AUTOMOC_MOC_OPTIONS")); + AddDefinitionEscaped(makefile, "_moc_skip", mocSkipList); + AddDefinitionEscaped(makefile, "_moc_relaxed_mode", + makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE") ? "TRUE" + : "FALSE"); - makefile->AddDefinition( - "_moc_incs", cmOutputConverter::EscapeForCMake(_moc_incs).c_str()); - makefile->AddDefinition( - "_moc_compile_defs", - cmOutputConverter::EscapeForCMake(_moc_compile_defs).c_str()); - - for (std::vector::const_iterator li = configs.begin(); - li != configs.end(); ++li) { - std::string config_moc_incs; - std::string config_moc_compile_defs; - GetCompileDefinitionsAndDirectories(target, *li, config_moc_incs, - config_moc_compile_defs); - if (config_moc_incs != _moc_incs) { - configIncludes[*li] = cmOutputConverter::EscapeForCMake(config_moc_incs); - if (_moc_incs.empty()) { - _moc_incs = config_moc_incs; + // Moc includes and compile definitions + { + std::string _moc_incs; + std::string _moc_compile_defs; + std::vector configs; + { + const std::string& config = makefile->GetConfigurations(configs); + GetCompileDefinitionsAndDirectories(target, config, _moc_incs, + _moc_compile_defs); + AddDefinitionEscaped(makefile, "_moc_incs", _moc_incs); + AddDefinitionEscaped(makefile, "_moc_compile_defs", _moc_compile_defs); + } + for (std::vector::const_iterator li = configs.begin(); + li != configs.end(); ++li) { + std::string config_moc_incs; + std::string config_moc_compile_defs; + GetCompileDefinitionsAndDirectories(target, *li, config_moc_incs, + config_moc_compile_defs); + if (config_moc_incs != _moc_incs) { + configIncludes[*li] = + cmOutputConverter::EscapeForCMake(config_moc_incs); + if (_moc_incs.empty()) { + _moc_incs = config_moc_incs; + } } - } - if (config_moc_compile_defs != _moc_compile_defs) { - configDefines[*li] = - cmOutputConverter::EscapeForCMake(config_moc_compile_defs); - if (_moc_compile_defs.empty()) { - _moc_compile_defs = config_moc_compile_defs; + if (config_moc_compile_defs != _moc_compile_defs) { + configDefines[*li] = + cmOutputConverter::EscapeForCMake(config_moc_compile_defs); + if (_moc_compile_defs.empty()) { + _moc_compile_defs = config_moc_compile_defs; + } } } } - const char* qtVersion = makefile->GetDefinition("_target_qt_version"); - if (strcmp(qtVersion, "5") == 0) { - cmGeneratorTarget* qt5Moc = lg->FindGeneratorTargetToUse("Qt5::moc"); - if (!qt5Moc) { - cmSystemTools::Error("Qt5::moc target not found ", - autogenTargetName.c_str()); - return; + // Moc executable + { + std::string err; + const char* mocExec = CM_NULLPTR; + if (qtMajorVersion == "5") { + cmGeneratorTarget* qt5Moc = lg->FindGeneratorTargetToUse("Qt5::moc"); + if (qt5Moc != CM_NULLPTR) { + mocExec = qt5Moc->ImportedGetLocation(""); + } else { + err = "Qt5::moc target not found " + autogenTargetName; + } + } else if (qtMajorVersion == "4") { + cmGeneratorTarget* qt4Moc = lg->FindGeneratorTargetToUse("Qt4::moc"); + if (qt4Moc != CM_NULLPTR) { + mocExec = qt4Moc->ImportedGetLocation(""); + } else { + err = "Qt4::moc target not found " + autogenTargetName; + } + } else { + err = "The CMAKE_AUTOMOC feature supports only Qt 4 and Qt 5 "; + err += autogenTargetName; } - makefile->AddDefinition("_qt_moc_executable", - qt5Moc->ImportedGetLocation("")); - } else if (strcmp(qtVersion, "4") == 0) { - cmGeneratorTarget* qt4Moc = lg->FindGeneratorTargetToUse("Qt4::moc"); - if (!qt4Moc) { - cmSystemTools::Error("Qt4::moc target not found ", - autogenTargetName.c_str()); - return; + // Add definition or error + if (err.empty()) { + AddDefinitionEscaped(makefile, "_qt_moc_executable", + mocExec ? mocExec : ""); + } else { + cmSystemTools::Error(err.c_str()); } - makefile->AddDefinition("_qt_moc_executable", - qt4Moc->ImportedGetLocation("")); - } else { - cmSystemTools::Error("The CMAKE_AUTOMOC feature supports only Qt 4 and " - "Qt 5 ", - autogenTargetName.c_str()); } } @@ -270,126 +296,126 @@ static void UicGetOpts(cmGeneratorTarget const* target, } static void UicSetupAutoTarget( - cmGeneratorTarget const* target, std::vector const& skipUic, + cmGeneratorTarget const* target, const std::string& qtMajorVersion, + std::vector const& uicSkipList, std::map& configUicOptions) { cmLocalGenerator* lg = target->GetLocalGenerator(); cmMakefile* makefile = target->Target->GetMakefile(); - std::set skipped; - skipped.insert(skipUic.begin(), skipUic.end()); + AddDefinitionEscaped(makefile, "_uic_skip", uicSkipList); - makefile->AddDefinition( - "_uic_skip", - cmOutputConverter::EscapeForCMake(cmJoin(skipUic, ";")).c_str()); - - std::vector uiFilesWithOptions = - makefile->GetQtUiFilesWithOptions(); - - const char* qtVersion = makefile->GetDefinition("_target_qt_version"); - - std::string _uic_opts; - std::vector configs; - const std::string& config = makefile->GetConfigurations(configs); - UicGetOpts(target, config, _uic_opts); - - if (!_uic_opts.empty()) { - _uic_opts = cmOutputConverter::EscapeForCMake(_uic_opts); - makefile->AddDefinition("_uic_target_options", _uic_opts.c_str()); - } - for (std::vector::const_iterator li = configs.begin(); - li != configs.end(); ++li) { - std::string config_uic_opts; - UicGetOpts(target, *li, config_uic_opts); - if (config_uic_opts != _uic_opts) { - configUicOptions[*li] = - cmOutputConverter::EscapeForCMake(config_uic_opts); - if (_uic_opts.empty()) { - _uic_opts = config_uic_opts; + // Uic target options + { + std::string _uic_opts; + std::vector configs; + UicGetOpts(target, makefile->GetConfigurations(configs), _uic_opts); + + AddDefinitionEscaped(makefile, "_uic_target_options", _uic_opts); + + for (std::vector::const_iterator li = configs.begin(); + li != configs.end(); ++li) { + std::string config_uic_opts; + UicGetOpts(target, *li, config_uic_opts); + if (config_uic_opts != _uic_opts) { + configUicOptions[*li] = + cmOutputConverter::EscapeForCMake(config_uic_opts); + if (_uic_opts.empty()) { + _uic_opts = config_uic_opts; + } } } } - - std::string uiFileFiles; - std::string uiFileOptions; - const char* sep = ""; - - for (std::vector::const_iterator fileIt = - uiFilesWithOptions.begin(); - fileIt != uiFilesWithOptions.end(); ++fileIt) { - cmSourceFile* sf = *fileIt; - std::string absFile = cmsys::SystemTools::GetRealPath(sf->GetFullPath()); - - if (!skipped.insert(absFile).second) { - continue; + // Uic files options + { + std::vector uiFileFiles; + std::vector uiFileOptions; + { + std::set skipped; + skipped.insert(uicSkipList.begin(), uicSkipList.end()); + + const std::vector uiFilesWithOptions = + makefile->GetQtUiFilesWithOptions(); + for (std::vector::const_iterator fileIt = + uiFilesWithOptions.begin(); + fileIt != uiFilesWithOptions.end(); ++fileIt) { + cmSourceFile* sf = *fileIt; + const std::string absFile = + cmsys::SystemTools::GetRealPath(sf->GetFullPath()); + if (skipped.insert(absFile).second) { + // The file wasn't skipped + uiFileFiles.push_back(absFile); + { + std::string opts = sf->GetProperty("AUTOUIC_OPTIONS"); + cmSystemTools::ReplaceString(opts, ";", "@list_sep@"); + uiFileOptions.push_back(opts); + } + } + } } - uiFileFiles += sep; - uiFileFiles += absFile; - uiFileOptions += sep; - std::string opts = sf->GetProperty("AUTOUIC_OPTIONS"); - cmSystemTools::ReplaceString(opts, ";", "@list_sep@"); - uiFileOptions += opts; - sep = ";"; + AddDefinitionEscaped(makefile, "_qt_uic_options_files", uiFileFiles); + AddDefinitionEscaped(makefile, "_qt_uic_options_options", uiFileOptions); } - makefile->AddDefinition( - "_qt_uic_options_files", - cmOutputConverter::EscapeForCMake(uiFileFiles).c_str()); - makefile->AddDefinition( - "_qt_uic_options_options", - cmOutputConverter::EscapeForCMake(uiFileOptions).c_str()); - - std::string targetName = target->GetName(); - if (strcmp(qtVersion, "5") == 0) { - cmGeneratorTarget* qt5Uic = lg->FindGeneratorTargetToUse("Qt5::uic"); - if (!qt5Uic) { - // Project does not use Qt5Widgets, but has AUTOUIC ON anyway + // Uic executable + { + std::string err; + const char* uicExec = CM_NULLPTR; + if (qtMajorVersion == "5") { + cmGeneratorTarget* qt5Uic = lg->FindGeneratorTargetToUse("Qt5::uic"); + if (qt5Uic != CM_NULLPTR) { + uicExec = qt5Uic->ImportedGetLocation(""); + } else { + // Project does not use Qt5Widgets, but has AUTOUIC ON anyway + } + } else if (qtMajorVersion == "4") { + cmGeneratorTarget* qt4Uic = lg->FindGeneratorTargetToUse("Qt4::uic"); + if (qt4Uic != CM_NULLPTR) { + uicExec = qt4Uic->ImportedGetLocation(""); + } else { + err = "Qt4::uic target not found " + target->GetName(); + } } else { - makefile->AddDefinition("_qt_uic_executable", - qt5Uic->ImportedGetLocation("")); + err = "The CMAKE_AUTOUIC feature supports only Qt 4 and Qt 5 "; + err += target->GetName(); } - } else if (strcmp(qtVersion, "4") == 0) { - cmGeneratorTarget* qt4Uic = lg->FindGeneratorTargetToUse("Qt4::uic"); - if (!qt4Uic) { - cmSystemTools::Error("Qt4::uic target not found ", targetName.c_str()); - return; + // Add definition or error + if (err.empty()) { + AddDefinitionEscaped(makefile, "_qt_uic_executable", + uicExec ? uicExec : ""); + } else { + cmSystemTools::Error(err.c_str()); } - makefile->AddDefinition("_qt_uic_executable", - qt4Uic->ImportedGetLocation("")); - } else { - cmSystemTools::Error("The CMAKE_AUTOUIC feature supports only Qt 4 and " - "Qt 5 ", - targetName.c_str()); } } static std::string RccGetExecutable(cmGeneratorTarget const* target, const std::string& qtMajorVersion) { + std::string rccExec; cmLocalGenerator* lg = target->GetLocalGenerator(); - - std::string const& targetName = target->GetName(); if (qtMajorVersion == "5") { cmGeneratorTarget* qt5Rcc = lg->FindGeneratorTargetToUse("Qt5::rcc"); - if (!qt5Rcc) { - cmSystemTools::Error("Qt5::rcc target not found ", targetName.c_str()); - return std::string(); + if (qt5Rcc != CM_NULLPTR) { + rccExec = qt5Rcc->ImportedGetLocation(""); + } else { + cmSystemTools::Error("Qt5::rcc target not found ", + target->GetName().c_str()); } - return qt5Rcc->ImportedGetLocation(""); - } - if (qtMajorVersion == "4") { + } else if (qtMajorVersion == "4") { cmGeneratorTarget* qt4Rcc = lg->FindGeneratorTargetToUse("Qt4::rcc"); - if (!qt4Rcc) { - cmSystemTools::Error("Qt4::rcc target not found ", targetName.c_str()); - return std::string(); + if (qt4Rcc != CM_NULLPTR) { + rccExec = qt4Rcc->ImportedGetLocation(""); + } else { + cmSystemTools::Error("Qt4::rcc target not found ", + target->GetName().c_str()); } - return qt4Rcc->ImportedGetLocation(""); + } else { + cmSystemTools::Error( + "The CMAKE_AUTORCC feature supports only Qt 4 and Qt 5 ", + target->GetName().c_str()); } - - cmSystemTools::Error("The CMAKE_AUTORCC feature supports only Qt 4 and " - "Qt 5 ", - targetName.c_str()); - return std::string(); + return rccExec; } static void RccMergeOptions(std::vector& opts, @@ -399,26 +425,31 @@ static void RccMergeOptions(std::vector& opts, static const char* valueOptions[] = { "name", "root", "compress", "threshold" }; std::vector extraOpts; - for (std::vector::const_iterator it = fileOpts.begin(); - it != fileOpts.end(); ++it) { + for (std::vector::const_iterator fit = fileOpts.begin(); + fit != fileOpts.end(); ++fit) { std::vector::iterator existingIt = - std::find(opts.begin(), opts.end(), *it); + std::find(opts.begin(), opts.end(), *fit); if (existingIt != opts.end()) { - const char* o = it->c_str(); - if (*o == '-') { - ++o; - } - if (isQt5 && *o == '-') { - ++o; + const char* optName = fit->c_str(); + if (*optName == '-') { + ++optName; + if (isQt5 && *optName == '-') { + ++optName; + } } - if (std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions), - cmStrCmp(*it)) != cmArrayEnd(valueOptions)) { - assert(existingIt + 1 != opts.end()); - *(existingIt + 1) = *(it + 1); - ++it; + // Test if this is a value option and change the existing value + if ((optName != fit->c_str()) && + std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions), + cmStrCmp(optName)) != cmArrayEnd(valueOptions)) { + const std::vector::iterator existValueIt(existingIt + 1); + const std::vector::const_iterator fileValueIt(fit + 1); + if ((existValueIt != opts.end()) && (fileValueIt != fileOpts.end())) { + *existValueIt = *fileValueIt; + ++fit; + } } } else { - extraOpts.push_back(*it); + extraOpts.push_back(*fit); } } opts.insert(opts.end(), extraOpts.begin(), extraOpts.end()); @@ -528,23 +559,20 @@ static bool RccListInputsQt4(cmSourceFile* sf, } cmsys::RegularExpression fileMatchRegex("(]*>)"); size_t offset = 0; while (fileMatchRegex.find(qrcContents.c_str() + offset)) { std::string qrcEntry = fileMatchRegex.match(1); - offset += qrcEntry.size(); - - cmsys::RegularExpression fileReplaceRegex("(^]*>)"); - fileReplaceRegex.find(qrcEntry); - std::string tag = fileReplaceRegex.match(1); - - qrcEntry = qrcEntry.substr(tag.size()); - + { + fileReplaceRegex.find(qrcEntry); + std::string tag = fileReplaceRegex.match(1); + qrcEntry = qrcEntry.substr(tag.size()); + } if (!cmSystemTools::FileIsFullPath(qrcEntry.c_str())) { qrcEntry = sf->GetLocation().GetDirectory() + "/" + qrcEntry; } - depends.push_back(qrcEntry); } return true; @@ -565,89 +593,69 @@ static bool RccListInputs(const std::string& qtMajorVersion, cmSourceFile* sf, static void RccSetupAutoTarget(cmGeneratorTarget const* target, const std::string& qtMajorVersion) { - std::string _rcc_files; - const char* sepRccFiles = ""; cmMakefile* makefile = target->Target->GetMakefile(); - - std::vector srcFiles; - target->GetConfigCommonSourceFiles(srcFiles); - - std::string qrcInputs; - const char* qrcInputsSep = ""; - - std::string rccFileFiles; - std::string rccFileOptions; - const char* optionSep = ""; - const bool qtMajorVersion5 = (qtMajorVersion == "5"); - - std::vector rccOptions; + std::vector _rcc_files; + std::vector _rcc_inputs; + std::vector rccFileFiles; + std::vector rccFileOptions; + std::vector rccOptionsTarget; if (const char* opts = target->GetProperty("AUTORCC_OPTIONS")) { - cmSystemTools::ExpandListArgument(opts, rccOptions); + cmSystemTools::ExpandListArgument(opts, rccOptionsTarget); } + std::vector srcFiles; + target->GetConfigCommonSourceFiles(srcFiles); for (std::vector::const_iterator fileIt = srcFiles.begin(); fileIt != srcFiles.end(); ++fileIt) { cmSourceFile* sf = *fileIt; - std::string ext = sf->GetExtension(); - if (ext == "qrc") { - std::string absFile = cmsys::SystemTools::GetRealPath(sf->GetFullPath()); + if (sf->GetExtension() == "qrc") { const bool skip = cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOGEN")) || cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC")); - if (!skip) { - _rcc_files += sepRccFiles; - _rcc_files += absFile; - sepRccFiles = ";"; - - if (const char* prop = sf->GetProperty("AUTORCC_OPTIONS")) { - std::vector optsVec; - cmSystemTools::ExpandListArgument(prop, optsVec); - RccMergeOptions(rccOptions, optsVec, qtMajorVersion5); - } - - if (!rccOptions.empty()) { - rccFileFiles += optionSep; - rccFileFiles += absFile; - rccFileOptions += optionSep; - } - const char* listSep = ""; - for (std::vector::const_iterator it = rccOptions.begin(); - it != rccOptions.end(); ++it) { - rccFileOptions += listSep; - rccFileOptions += *it; - listSep = "@list_sep@"; + const std::string absFile = + cmsys::SystemTools::GetRealPath(sf->GetFullPath()); + // qrc file + _rcc_files.push_back(absFile); + // qrc file entries + { + std::string entriesList; + if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) { + std::vector depends; + if (RccListInputs(qtMajorVersion, sf, target, depends)) { + entriesList = cmJoin(depends, "@list_sep@"); + } else { + return; + } + } + _rcc_inputs.push_back(entriesList); } - optionSep = ";"; - - std::string entriesList; - if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) { - std::vector depends; - if (RccListInputs(qtMajorVersion, sf, target, depends)) { - entriesList = cmJoin(depends, "@list_sep@"); - } else { - return; + // rcc options for this qrc file + { + // Merged target and file options + std::vector rccOptions(rccOptionsTarget); + if (const char* prop = sf->GetProperty("AUTORCC_OPTIONS")) { + std::vector optsVec; + cmSystemTools::ExpandListArgument(prop, optsVec); + RccMergeOptions(rccOptions, optsVec, qtMajorVersion5); + } + // Only store non empty options lists + if (!rccOptions.empty()) { + rccFileFiles.push_back(absFile); + rccFileOptions.push_back(cmJoin(rccOptions, "@list_sep@")); } } - qrcInputs += qrcInputsSep; - qrcInputs += entriesList; - qrcInputsSep = ";"; } } } - makefile->AddDefinition( - "_rcc_inputs", cmOutputConverter::EscapeForCMake(qrcInputs).c_str()); - makefile->AddDefinition( - "_rcc_files", cmOutputConverter::EscapeForCMake(_rcc_files).c_str()); - makefile->AddDefinition( - "_rcc_options_files", - cmOutputConverter::EscapeForCMake(rccFileFiles).c_str()); - makefile->AddDefinition( - "_rcc_options_options", - cmOutputConverter::EscapeForCMake(rccFileOptions).c_str()); - makefile->AddDefinition("_qt_rcc_executable", - RccGetExecutable(target, qtMajorVersion).c_str()); + + AddDefinitionEscaped(makefile, "_rcc_files", _rcc_files); + AddDefinitionEscaped(makefile, "_rcc_inputs", _rcc_inputs); + AddDefinitionEscaped(makefile, "_rcc_options_files", rccFileFiles); + AddDefinitionEscaped(makefile, "_rcc_options_options", rccFileOptions); + AddDefinitionEscaped(makefile, "_qt_rcc_executable", + RccGetExecutable(target, qtMajorVersion)); } void cmQtAutoGeneratorInitializer::InitializeAutogenSources( @@ -874,47 +882,42 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( cmMakefile::ScopePushPop varScope(makefile); static_cast(varScope); - // create a custom target for running generators at buildtime: - const std::string autogenTargetName = GetAutogenTargetName(target); - const std::string qtMajorVersion = GetQtMajorVersion(target); - - makefile->AddDefinition( - "_moc_target_name", - cmOutputConverter::EscapeForCMake(autogenTargetName).c_str()); - makefile->AddDefinition( - "_origin_target_name", - cmOutputConverter::EscapeForCMake(target->GetName()).c_str()); - makefile->AddDefinition("_target_qt_version", qtMajorVersion.c_str()); - - std::vector mocUicSources; - std::vector mocUicHeaders; - std::vector skipMoc; - std::vector skipUic; std::map configMocIncludes; std::map configMocDefines; std::map configUicOptions; + { + // create a custom target for running generators at buildtime: + const std::string autogenTargetName = GetAutogenTargetName(target); + const std::string qtMajorVersion = GetQtMajorVersion(target); - if (target->GetPropertyAsBool("AUTOMOC") || - target->GetPropertyAsBool("AUTOUIC") || - target->GetPropertyAsBool("AUTORCC")) { - SetupSourceFiles(target, mocUicSources, mocUicHeaders, skipMoc, skipUic); - } - makefile->AddDefinition( - "_sources", - cmOutputConverter::EscapeForCMake(cmJoin(mocUicSources, ";")).c_str()); - makefile->AddDefinition( - "_headers", - cmOutputConverter::EscapeForCMake(cmJoin(mocUicHeaders, ";")).c_str()); + AddDefinitionEscaped(makefile, "_autogen_target_name", autogenTargetName); + AddDefinitionEscaped(makefile, "_origin_target_name", target->GetName()); + AddDefinitionEscaped(makefile, "_qt_version_major", qtMajorVersion); - if (target->GetPropertyAsBool("AUTOMOC")) { - MocSetupAutoTarget(target, autogenTargetName, skipMoc, configMocIncludes, - configMocDefines); - } - if (target->GetPropertyAsBool("AUTOUIC")) { - UicSetupAutoTarget(target, skipUic, configUicOptions); - } - if (target->GetPropertyAsBool("AUTORCC")) { - RccSetupAutoTarget(target, qtMajorVersion); + std::vector _sources; + std::vector _headers; + std::vector mocSkipList; + std::vector uicSkipList; + + if (target->GetPropertyAsBool("AUTOMOC") || + target->GetPropertyAsBool("AUTOUIC") || + target->GetPropertyAsBool("AUTORCC")) { + SetupSourceFiles(target, _sources, _headers, mocSkipList, uicSkipList); + } + AddDefinitionEscaped(makefile, "_sources", _sources); + AddDefinitionEscaped(makefile, "_headers", _headers); + + if (target->GetPropertyAsBool("AUTOMOC")) { + MocSetupAutoTarget(target, autogenTargetName, qtMajorVersion, + mocSkipList, configMocIncludes, configMocDefines); + } + if (target->GetPropertyAsBool("AUTOUIC")) { + UicSetupAutoTarget(target, qtMajorVersion, uicSkipList, + configUicOptions); + } + if (target->GetPropertyAsBool("AUTORCC")) { + RccSetupAutoTarget(target, qtMajorVersion); + } } // Generate config file @@ -926,7 +929,7 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( makefile->ConfigureFile(inputFile.c_str(), outputFile.c_str(), false, true, false); - // Append custom definitions to config file + // Append custom config definitions to info file if (!configMocDefines.empty() || !configMocIncludes.empty() || !configUicOptions.empty()) { @@ -948,33 +951,34 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( error += outputFile; error += " for writing."; cmSystemTools::Error(error.c_str()); - return; - } - if (!configMocDefines.empty()) { - for (std::map::iterator - it = configMocDefines.begin(), - end = configMocDefines.end(); - it != end; ++it) { - infoFile << "set(AM_MOC_COMPILE_DEFINITIONS_" << it->first << " " - << it->second << ")\n"; + } else { + infoFile << "# Configuration specific options\n"; + if (!configMocDefines.empty()) { + for (std::map::iterator + it = configMocDefines.begin(), + end = configMocDefines.end(); + it != end; ++it) { + infoFile << "set(AM_MOC_COMPILE_DEFINITIONS_" << it->first << " " + << it->second << ")\n"; + } } - } - if (!configMocIncludes.empty()) { - for (std::map::iterator - it = configMocIncludes.begin(), - end = configMocIncludes.end(); - it != end; ++it) { - infoFile << "set(AM_MOC_INCLUDES_" << it->first << " " << it->second - << ")\n"; + if (!configMocIncludes.empty()) { + for (std::map::iterator + it = configMocIncludes.begin(), + end = configMocIncludes.end(); + it != end; ++it) { + infoFile << "set(AM_MOC_INCLUDES_" << it->first << " " << it->second + << ")\n"; + } } - } - if (!configUicOptions.empty()) { - for (std::map::iterator - it = configUicOptions.begin(), - end = configUicOptions.end(); - it != end; ++it) { - infoFile << "set(AM_UIC_TARGET_OPTIONS_" << it->first << " " - << it->second << ")\n"; + if (!configUicOptions.empty()) { + for (std::map::iterator + it = configUicOptions.begin(), + end = configUicOptions.end(); + it != end; ++it) { + infoFile << "set(AM_UIC_TARGET_OPTIONS_" << it->first << " " + << it->second << ")\n"; + } } } } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=2f263657fd2b544ed75bfc9725dd30d6bc1cfd7d commit 2f263657fd2b544ed75bfc9725dd30d6bc1cfd7d Author: Sebastian Holtermann AuthorDate: Sun Feb 19 13:17:42 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 20:34:18 2017 +0100 Autogen: Optimize GetCompileDefinitionsAndDirectories function diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index d17faf6..c201023 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -98,6 +98,26 @@ static std::string GetQtMajorVersion(cmGeneratorTarget const* target) return qtMajorVersion; } +static void GetCompileDefinitionsAndDirectories( + cmGeneratorTarget const* target, const std::string& config, + std::string& incs, std::string& defs) +{ + cmLocalGenerator* localGen = target->GetLocalGenerator(); + { + std::vector includeDirs; + // Get the include dirs for this target, without stripping the implicit + // include dirs off, see + // https://gitlab.kitware.com/cmake/cmake/issues/13667 + localGen->GetIncludeDirectories(includeDirs, target, "CXX", config, false); + incs = cmJoin(includeDirs, ";"); + } + { + std::set defines; + localGen->AddCompileDefinitions(defines, target, config, "CXX"); + defs += cmJoin(defines, ";"); + } +} + static void SetupSourceFiles(cmGeneratorTarget const* target, std::vector& mocUicSources, std::vector& mocUicHeaders, @@ -162,24 +182,6 @@ static void SetupSourceFiles(cmGeneratorTarget const* target, } } -static void GetCompileDefinitionsAndDirectories( - cmGeneratorTarget const* target, const std::string& config, - std::string& incs, std::string& defs) -{ - std::vector includeDirs; - cmLocalGenerator* localGen = target->GetLocalGenerator(); - // Get the include dirs for this target, without stripping the implicit - // include dirs off, see https://gitlab.kitware.com/cmake/cmake/issues/13667 - localGen->GetIncludeDirectories(includeDirs, target, "CXX", config, false); - - incs = cmJoin(includeDirs, ";"); - - std::set defines; - localGen->AddCompileDefinitions(defines, target, config, "CXX"); - - defs += cmJoin(defines, ";"); -} - static void MocSetupAutoTarget( cmGeneratorTarget const* target, const std::string& autogenTargetName, std::vector const& skipMoc, https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ca38804669676e531c6f7cf6d2e442092194c6d0 commit ca38804669676e531c6f7cf6d2e442092194c6d0 Author: Sebastian Holtermann AuthorDate: Sun Feb 19 12:57:47 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 20:30:17 2017 +0100 Autogen: Sort AutogenInfo.cmake.in Also rename AM_SKIP_MOC to AM_MOC_SKIP and AM_SKIP_UIC to AM_UIC_SKIP diff --git a/Modules/AutogenInfo.cmake.in b/Modules/AutogenInfo.cmake.in index 3fafaff..3135909 100644 --- a/Modules/AutogenInfo.cmake.in +++ b/Modules/AutogenInfo.cmake.in @@ -1,25 +1,31 @@ -set(AM_SOURCES @_moc_uic_sources@) -set(AM_HEADERS @_moc_uic_headers@) -set(AM_SKIP_MOC @_skip_moc@) -set(AM_SKIP_UIC @_skip_uic@) -set(AM_MOC_COMPILE_DEFINITIONS @_moc_compile_defs@) -set(AM_MOC_INCLUDES @_moc_incs@) -set(AM_MOC_OPTIONS @_moc_options@) -set(AM_MOC_RELAXED_MODE "@_moc_relaxed_mode@") -set(AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE "@CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE@") +# Target names +set(AM_TARGET_NAME @_moc_target_name@) +set(AM_ORIGIN_TARGET_NAME @_origin_target_name@) +# Directories and files set(AM_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@/") set(AM_CMAKE_SOURCE_DIR "@CMAKE_SOURCE_DIR@/") -set(AM_QT_MOC_EXECUTABLE "@_qt_moc_executable@") -set(AM_QT_UIC_EXECUTABLE "@_qt_uic_executable@") -set(AM_QT_RCC_EXECUTABLE "@_qt_rcc_executable@") set(AM_CMAKE_CURRENT_SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@/") set(AM_CMAKE_CURRENT_BINARY_DIR "@CMAKE_CURRENT_BINARY_DIR@/") +set(AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE "@CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE@") +set(AM_SOURCES @_sources@) +set(AM_HEADERS @_headers@) +# Qt environment set(AM_QT_VERSION_MAJOR "@_target_qt_version@") -set(AM_TARGET_NAME @_moc_target_name@) -set(AM_ORIGIN_TARGET_NAME @_origin_target_name@) +set(AM_QT_MOC_EXECUTABLE "@_qt_moc_executable@") +set(AM_QT_UIC_EXECUTABLE "@_qt_uic_executable@") +set(AM_QT_RCC_EXECUTABLE "@_qt_rcc_executable@") +# MOC settings +set(AM_MOC_SKIP @_moc_skip@) +set(AM_MOC_COMPILE_DEFINITIONS @_moc_compile_defs@) +set(AM_MOC_INCLUDES @_moc_incs@) +set(AM_MOC_OPTIONS @_moc_options@) +set(AM_MOC_RELAXED_MODE "@_moc_relaxed_mode@") +# UIC settings +set(AM_UIC_SKIP @_uic_skip@) set(AM_UIC_TARGET_OPTIONS @_uic_target_options@) set(AM_UIC_OPTIONS_FILES @_qt_uic_options_files@) set(AM_UIC_OPTIONS_OPTIONS @_qt_uic_options_options@) +# RCC settings set(AM_RCC_SOURCES @_rcc_files@ ) set(AM_RCC_INPUTS @_rcc_inputs@) set(AM_RCC_OPTIONS_FILES @_rcc_options_files@) diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index 825eba0..d17faf6 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -194,7 +194,7 @@ static void MocSetupAutoTarget( makefile->AddDefinition( "_moc_options", cmOutputConverter::EscapeForCMake(_moc_options).c_str()); makefile->AddDefinition( - "_skip_moc", + "_moc_skip", cmOutputConverter::EscapeForCMake(cmJoin(skipMoc, ";")).c_str()); bool relaxedMode = makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE"); makefile->AddDefinition("_moc_relaxed_mode", relaxedMode ? "TRUE" : "FALSE"); @@ -278,7 +278,7 @@ static void UicSetupAutoTarget( skipped.insert(skipUic.begin(), skipUic.end()); makefile->AddDefinition( - "_skip_uic", + "_uic_skip", cmOutputConverter::EscapeForCMake(cmJoin(skipUic, ";")).c_str()); std::vector uiFilesWithOptions = @@ -898,10 +898,10 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( SetupSourceFiles(target, mocUicSources, mocUicHeaders, skipMoc, skipUic); } makefile->AddDefinition( - "_moc_uic_sources", + "_sources", cmOutputConverter::EscapeForCMake(cmJoin(mocUicSources, ";")).c_str()); makefile->AddDefinition( - "_moc_uic_headers", + "_headers", cmOutputConverter::EscapeForCMake(cmJoin(mocUicHeaders, ";")).c_str()); if (target->GetPropertyAsBool("AUTOMOC")) { diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 199e5cc..1d120d7 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -306,7 +306,7 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( this->Headers); // - Moc - cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_SKIP_MOC"), + cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_MOC_SKIP"), this->MocSkipList); cmSystemTools::ExpandListArgument( GetConfigDefinition(makefile, "AM_MOC_COMPILE_DEFINITIONS", config), @@ -318,7 +318,7 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( makefile->GetSafeDefinition("AM_MOC_OPTIONS"), this->MocOptions); // - Uic - cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_SKIP_UIC"), + cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_UIC_SKIP"), this->UicSkipList); cmSystemTools::ExpandListArgument( GetConfigDefinition(makefile, "AM_UIC_TARGET_OPTIONS", config), https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=50cde9c55aedb16eeb8c7fd2b550e980afca9f5b commit 50cde9c55aedb16eeb8c7fd2b550e980afca9f5b Author: Sebastian Holtermann AuthorDate: Fri Feb 17 13:50:33 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 20:30:17 2017 +0100 Autogen: Tests: Add Q_PLUGIN_METADATA test diff --git a/Tests/QtAutogen/CMakeLists.txt b/Tests/QtAutogen/CMakeLists.txt index 40c23fa..260331b 100644 --- a/Tests/QtAutogen/CMakeLists.txt +++ b/Tests/QtAutogen/CMakeLists.txt @@ -86,7 +86,8 @@ try_compile(RCC_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/autorcc_depends" "${CMAKE_CURRENT_SOURCE_DIR}/autorcc_depends" autorcc_depends - CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" "-DQT_TEST_VERSION=${QT_TEST_VERSION}" + CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" + "-DQT_TEST_VERSION=${QT_TEST_VERSION}" "-DCMAKE_PREFIX_PATH=${Qt_PREFIX_DIR}" OUTPUT_VARIABLE output ) @@ -121,7 +122,8 @@ try_compile(MOC_RERUN "${CMAKE_CURRENT_BINARY_DIR}/automoc_rerun" "${CMAKE_CURRENT_SOURCE_DIR}/automoc_rerun" automoc_rerun - CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" "-DQT_TEST_VERSION=${QT_TEST_VERSION}" + CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" + "-DQT_TEST_VERSION=${QT_TEST_VERSION}" "-DCMAKE_PREFIX_PATH=${Qt_PREFIX_DIR}" OUTPUT_VARIABLE output ) @@ -215,5 +217,60 @@ add_subdirectory(mocIncludeStrict) add_subdirectory(mocIncludeRelaxed) # -- 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(mocPluginBinDir "${CMAKE_CURRENT_BINARY_DIR}/mocPlugin") + find_library(style_a_file "PluginStyleA" "${mocPluginBinDir}") + find_library(style_b_file "PluginStyleB" "${mocPluginBinDir}") + find_library(style_c_file "PluginStyleC" "${mocPluginBinDir}") + find_library(style_d_file "PluginStyleD" "${mocPluginBinDir}") + + file(TIMESTAMP "${style_a_file}" style_a_before "${timeformat}") + file(TIMESTAMP "${style_b_file}" style_b_before "${timeformat}") + file(TIMESTAMP "${style_c_file}" style_c_before "${timeformat}") + file(TIMESTAMP "${style_d_file}" style_d_before "${timeformat}") + + # Ensure that the timestamp will change and touch the json files + execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) + execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${mocPluginBinDir}/jsonFiles/StyleC.json") + execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${mocPluginBinDir}/jsonFiles/sub/StyleD.json") + + execute_process(COMMAND "${CMAKE_COMMAND}" --build . + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mocPlugin" + ) + + file(TIMESTAMP "${style_a_file}" style_a_after "${timeformat}") + file(TIMESTAMP "${style_b_file}" style_b_after "${timeformat}") + file(TIMESTAMP "${style_c_file}" style_c_after "${timeformat}") + file(TIMESTAMP "${style_d_file}" style_d_after "${timeformat}") + + if (style_a_after GREATER style_a_before) + message(SEND_ERROR "file (${style_a_file}) should not have changed!") + endif() + if (style_b_after GREATER style_b_before) + message(SEND_ERROR "file (${style_b_file}) should not have changed!") + endif() + if (NOT style_c_after GREATER style_c_before) + message(SEND_ERROR "file (${style_c_file}) should have changed!") + endif() + if (NOT style_d_after GREATER style_d_before) + message(SEND_ERROR "file (${style_d_file}) should have changed!") + endif() +endif() + +# -- Test # Complex test case add_subdirectory(complex) diff --git a/Tests/QtAutogen/mocPlugin/CMakeLists.txt b/Tests/QtAutogen/mocPlugin/CMakeLists.txt new file mode 100644 index 0000000..eed7d39 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 3.8) + +if (NOT QT_TEST_VERSION STREQUAL 5) + message(SEND_ERROR "Invalid Qt version specified.") +endif() +find_package(Qt5Widgets REQUIRED) + +if(Qt5_POSITION_INDEPENDENT_CODE AND CMAKE_CXX_COMPILE_OPTIONS_PIC) + add_definitions(${CMAKE_CXX_COMPILE_OPTIONS_PIC}) +endif() + +configure_file(jsonIn/StyleC.json jsonFiles/StyleC.json @ONLY) +configure_file(jsonIn/StyleD.json jsonFiles/sub/StyleD.json @ONLY) + +# Enable automoc +set(CMAKE_AUTOMOC TRUE) + +include_directories("${CMAKE_CURRENT_BINARY_DIR}/jsonFiles") +link_libraries(Qt5::Widgets) + +add_library(PluginStyleA MODULE StyleA.cpp) +add_library(PluginStyleB MODULE StyleB.cpp) +add_library(PluginStyleC MODULE StyleC.cpp) +add_library(PluginStyleD MODULE StyleD.cpp) +add_library(PluginStyleE MODULE StyleE.cpp) diff --git a/Tests/QtAutogen/mocPlugin/StyleA.cpp b/Tests/QtAutogen/mocPlugin/StyleA.cpp new file mode 100644 index 0000000..b5e8753 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleA.cpp @@ -0,0 +1,6 @@ +#include "StyleA.hpp" + +QStyle* StyleA::create(const QString& key) +{ + return 0; +} diff --git a/Tests/QtAutogen/mocPlugin/StyleA.hpp b/Tests/QtAutogen/mocPlugin/StyleA.hpp new file mode 100644 index 0000000..b105b02 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleA.hpp @@ -0,0 +1,15 @@ +#ifndef STYLEA_HPP +#define STYLEA_HPP + +#include + +class StyleA : public QStylePlugin +{ + Q_OBJECT + // Json file in local directory + Q_PLUGIN_METADATA(IID "org.styles.A" FILE "StyleA.json") +public: + QStyle* create(const QString& key); +}; + +#endif diff --git a/Tests/QtAutogen/mocPlugin/StyleA.json b/Tests/QtAutogen/mocPlugin/StyleA.json new file mode 100644 index 0000000..cc33953 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleA.json @@ -0,0 +1 @@ +{ "Keys": [ "Rocket", "Starbuster" ] } diff --git a/Tests/QtAutogen/mocPlugin/StyleB.cpp b/Tests/QtAutogen/mocPlugin/StyleB.cpp new file mode 100644 index 0000000..17d4400 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleB.cpp @@ -0,0 +1,6 @@ +#include "StyleB.hpp" + +QStyle* StyleB::create(const QString& key) +{ + return 0; +} diff --git a/Tests/QtAutogen/mocPlugin/StyleB.hpp b/Tests/QtAutogen/mocPlugin/StyleB.hpp new file mode 100644 index 0000000..ba89127 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleB.hpp @@ -0,0 +1,15 @@ +#ifndef STYLEB_HPP +#define STYLEB_HPP + +#include + +class StyleB : public QStylePlugin +{ + Q_OBJECT + // Json file in local subdirectory + Q_PLUGIN_METADATA(IID "org.styles.B" FILE "jsonIn/StyleB.json") +public: + QStyle* create(const QString& key); +}; + +#endif diff --git a/Tests/QtAutogen/mocPlugin/StyleC.cpp b/Tests/QtAutogen/mocPlugin/StyleC.cpp new file mode 100644 index 0000000..37e7564 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleC.cpp @@ -0,0 +1,6 @@ +#include "StyleC.hpp" + +QStyle* StyleC::create(const QString& key) +{ + return 0; +} diff --git a/Tests/QtAutogen/mocPlugin/StyleC.hpp b/Tests/QtAutogen/mocPlugin/StyleC.hpp new file mode 100644 index 0000000..9f71d75 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleC.hpp @@ -0,0 +1,15 @@ +#ifndef STYLEC_HPP +#define STYLEC_HPP + +#include + +class StyleC : public QStylePlugin +{ + Q_OBJECT + // Json file in global root directory + Q_PLUGIN_METADATA(IID "org.styles.C" FILE "StyleC.json") +public: + QStyle* create(const QString& key); +}; + +#endif diff --git a/Tests/QtAutogen/mocPlugin/StyleD.cpp b/Tests/QtAutogen/mocPlugin/StyleD.cpp new file mode 100644 index 0000000..48398bb --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleD.cpp @@ -0,0 +1,17 @@ +#include "StyleD.hpp" + +class StyleD : public QStylePlugin +{ + Q_OBJECT + // Json file in global sub director + Q_PLUGIN_METADATA(IID "org.styles.D" FILE "sub/StyleD.json") +public: + QStyle* create(const QString& key); +}; + +QStyle* StyleD::create(const QString& key) +{ + return 0; +} + +#include "StyleD.moc" diff --git a/Tests/QtAutogen/mocPlugin/StyleD.hpp b/Tests/QtAutogen/mocPlugin/StyleD.hpp new file mode 100644 index 0000000..2afe055 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleD.hpp @@ -0,0 +1,8 @@ +#ifndef STYLED_HPP +#define STYLED_HPP + +#include + +class StyleD; + +#endif diff --git a/Tests/QtAutogen/mocPlugin/StyleE.cpp b/Tests/QtAutogen/mocPlugin/StyleE.cpp new file mode 100644 index 0000000..8fc9a7f --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleE.cpp @@ -0,0 +1,6 @@ +#include "StyleE.hpp" + +QStyle* StyleE::create(const QString& key) +{ + return 0; +} diff --git a/Tests/QtAutogen/mocPlugin/StyleE.hpp b/Tests/QtAutogen/mocPlugin/StyleE.hpp new file mode 100644 index 0000000..80e0b79 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleE.hpp @@ -0,0 +1,15 @@ +#ifndef STYLEE_HPP +#define STYLEE_HPP + +#include + +class StyleE : public QStylePlugin +{ + Q_OBJECT + // No Json file + Q_PLUGIN_METADATA(IID "org.styles.E") +public: + QStyle* create(const QString& key); +}; + +#endif diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleB.json b/Tests/QtAutogen/mocPlugin/jsonIn/StyleB.json new file mode 100644 index 0000000..129cac4 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/jsonIn/StyleB.json @@ -0,0 +1 @@ +{ "Keys": [ "Rocket", "StarbusterB" ] } diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json b/Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json new file mode 100644 index 0000000..bf17580 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json @@ -0,0 +1 @@ +{ "Keys": [ "Rocket", "StarbusterC" ] } diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json b/Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json new file mode 100644 index 0000000..f7fcc19 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json @@ -0,0 +1 @@ +{ "Keys": [ "Rocket", "StarbusterD" ] } diff --git a/Tests/QtAutogen/mocPlugin/main.cpp b/Tests/QtAutogen/mocPlugin/main.cpp new file mode 100644 index 0000000..3ba2ddc --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/main.cpp @@ -0,0 +1,6 @@ +#include "StyleA.hpp" + +int main(int argv, char** args) +{ + return 0; +} https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0e88ab697ca02665a44a60f005c8623100c26b95 commit 0e88ab697ca02665a44a60f005c8623100c26b95 Author: Sebastian Holtermann AuthorDate: Thu Feb 16 15:59:56 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 20:30:17 2017 +0100 Autogen: Tests: Add moc include tests diff --git a/Tests/QtAutogen/CMakeLists.txt b/Tests/QtAutogen/CMakeLists.txt index c1cdee2..40c23fa 100644 --- a/Tests/QtAutogen/CMakeLists.txt +++ b/Tests/QtAutogen/CMakeLists.txt @@ -207,5 +207,13 @@ target_link_libraries(skipRccB ${QT_LIBRARIES}) add_subdirectory(sameName) # -- Test +# Tests various include moc patterns +add_subdirectory(mocIncludeStrict) + +# -- Test +# Tests various include moc patterns +add_subdirectory(mocIncludeRelaxed) + +# -- Test # Complex test case add_subdirectory(complex) diff --git a/Tests/QtAutogen/mocInclude/ObjA.cpp b/Tests/QtAutogen/mocInclude/ObjA.cpp new file mode 100644 index 0000000..2ee47ec --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjA.cpp @@ -0,0 +1,24 @@ +#include "ObjA.hpp" + +class SubObjA : public QObject +{ + Q_OBJECT + +public: + SubObjA() = default; + ~SubObjA() = default; + + Q_SLOT + void aSlot(); +}; + +void SubObjA::aSlot() +{ +} + +void ObjA::go() +{ + SubObjA subObj; +} + +#include "ObjA.moc" diff --git a/Tests/QtAutogen/mocInclude/ObjA.hpp b/Tests/QtAutogen/mocInclude/ObjA.hpp new file mode 100644 index 0000000..281e90d --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjA.hpp @@ -0,0 +1,13 @@ +#ifndef OBJA_HPP +#define OBJA_HPP + +#include + +class ObjA : public QObject +{ + Q_OBJECT + Q_SLOT + void go(); +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/ObjB.cpp b/Tests/QtAutogen/mocInclude/ObjB.cpp new file mode 100644 index 0000000..abec06a --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjB.cpp @@ -0,0 +1,25 @@ +#include "ObjB.hpp" + +class SubObjB : public QObject +{ + Q_OBJECT + +public: + SubObjB() = default; + ~SubObjB() = default; + + Q_SLOT + void aSlot(); +}; + +void SubObjB::aSlot() +{ +} + +void ObjB::go() +{ + SubObjB subObj; +} + +#include "ObjB.moc" +#include "moc_ObjB.cpp" diff --git a/Tests/QtAutogen/mocInclude/ObjB.hpp b/Tests/QtAutogen/mocInclude/ObjB.hpp new file mode 100644 index 0000000..94f3d49 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjB.hpp @@ -0,0 +1,13 @@ +#ifndef OBJB_HPP +#define OBJB_HPP + +#include + +class ObjB : public QObject +{ + Q_OBJECT + Q_SLOT + void go(); +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/ObjC.cpp b/Tests/QtAutogen/mocInclude/ObjC.cpp new file mode 100644 index 0000000..bdcdb13 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjC.cpp @@ -0,0 +1,26 @@ +#include "ObjC.hpp" + +class SubObjC : public QObject +{ + Q_OBJECT + +public: + SubObjC() = default; + ~SubObjC() = default; + + 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 new file mode 100644 index 0000000..a8e98eb --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjC.hpp @@ -0,0 +1,13 @@ +#ifndef OBJC_HPP +#define OBJC_HPP + +#include + +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 new file mode 100644 index 0000000..9145ba3 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjD.cpp @@ -0,0 +1,26 @@ +#include "ObjD.hpp" + +class SubObjD : public QObject +{ + Q_OBJECT + +public: + SubObjD() = default; + ~SubObjD() = default; + + 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 new file mode 100644 index 0000000..b6ee098 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjD.hpp @@ -0,0 +1,13 @@ +#ifndef OBJD_HPP +#define OBJD_HPP + +#include + +class ObjD : public QObject +{ + Q_OBJECT + Q_SLOT + void go(); +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/subA/SubObjA.cpp b/Tests/QtAutogen/mocInclude/subA/SubObjA.cpp new file mode 100644 index 0000000..d780942 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subA/SubObjA.cpp @@ -0,0 +1,27 @@ +#include "SubObjA.hpp" + +namespace subA { + +class SubObjA : public QObject +{ + Q_OBJECT + +public: + SubObjA() = default; + ~SubObjA() = default; + + 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 new file mode 100644 index 0000000..31a18b6 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subA/SubObjA.hpp @@ -0,0 +1,16 @@ +#ifndef SUBOBJA_HPP +#define SUBOBJA_HPP + +#include + +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 new file mode 100644 index 0000000..e602e06 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subB/SubObjB.cpp @@ -0,0 +1,27 @@ +#include "SubObjB.hpp" + +namespace subB { + +class SubObjB : public QObject +{ + Q_OBJECT + +public: + SubObjB() = default; + ~SubObjB() = default; + + 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 new file mode 100644 index 0000000..3f29fa2 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subB/SubObjB.hpp @@ -0,0 +1,16 @@ +#ifndef SUBOBJB_HPP +#define SUBOBJB_HPP + +#include + +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 new file mode 100644 index 0000000..fb2d1ec --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subC/SubObjC.cpp @@ -0,0 +1,27 @@ +#include "SubObjC.hpp" + +namespace subC { + +class SubObjC : public QObject +{ + Q_OBJECT + +public: + SubObjC() = default; + ~SubObjC() = default; + + 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 new file mode 100644 index 0000000..dc251fd --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subC/SubObjC.hpp @@ -0,0 +1,16 @@ +#ifndef SUBOBJC_HPP +#define SUBOBJC_HPP + +#include + +namespace subC { + +class ObjC : public QObject +{ + Q_OBJECT + Q_SLOT + void go(); +}; +} + +#endif diff --git a/Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt b/Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt new file mode 100644 index 0000000..6a0829d --- /dev/null +++ b/Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt @@ -0,0 +1,18 @@ +# Test moc include patterns + +set(CMAKE_AUTOMOC_RELAXED_MODE TRUE) + +include_directories("../mocInclude") + +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 +) +target_link_libraries(mocIncludeRelaxed ${QT_LIBRARIES}) +set_target_properties(mocIncludeRelaxed PROPERTIES AUTOMOC ON) diff --git a/Tests/QtAutogen/mocIncludeRelaxed/main.cpp b/Tests/QtAutogen/mocIncludeRelaxed/main.cpp new file mode 100644 index 0000000..142d59e --- /dev/null +++ b/Tests/QtAutogen/mocIncludeRelaxed/main.cpp @@ -0,0 +1,14 @@ +#include "ObjA.hpp" +#include "ObjB.hpp" +#include "ObjC.hpp" + +int main(int argv, char** args) +{ + ObjA objA; + ObjB objB; + ObjC objC; + return 0; +} + +// Header in global subdirectory +#include "subB/moc_SubObjB.cpp" diff --git a/Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt b/Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt new file mode 100644 index 0000000..22e93a8 --- /dev/null +++ b/Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt @@ -0,0 +1,18 @@ +# Test moc include patterns + +set(CMAKE_AUTOMOC_RELAXED_MODE FALSE) + +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) diff --git a/Tests/QtAutogen/mocIncludeStrict/main.cpp b/Tests/QtAutogen/mocIncludeStrict/main.cpp new file mode 100644 index 0000000..142d59e --- /dev/null +++ b/Tests/QtAutogen/mocIncludeStrict/main.cpp @@ -0,0 +1,14 @@ +#include "ObjA.hpp" +#include "ObjB.hpp" +#include "ObjC.hpp" + +int main(int argv, char** args) +{ + ObjA objA; + ObjB objB; + ObjC objC; + return 0; +} + +// Header in global subdirectory +#include "subB/moc_SubObjB.cpp" https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=364e60cdf76c05c4f87ab3aad19a81ee6145a4c4 commit 364e60cdf76c05c4f87ab3aad19a81ee6145a4c4 Author: Sebastian Holtermann AuthorDate: Thu Feb 16 15:05:11 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 20:30:17 2017 +0100 Autogen: Tests: Clean comments diff --git a/Tests/QtAutogen/CMakeLists.txt b/Tests/QtAutogen/CMakeLists.txt index 4b90ad8..c1cdee2 100644 --- a/Tests/QtAutogen/CMakeLists.txt +++ b/Tests/QtAutogen/CMakeLists.txt @@ -46,26 +46,26 @@ endif() get_property(QT_COMPILE_FEATURES TARGET ${QT_QTCORE_TARGET} PROPERTY INTERFACE_COMPILE_FEATURES) -# -- Test: AUTORCC +# -- Test # RCC only add_executable(rccOnly rccOnly.cpp rccOnlyRes.qrc) set_property(TARGET rccOnly PROPERTY AUTORCC ON) target_link_libraries(rccOnly ${QT_QTCORE_TARGET}) -# -- Test: AUTORCC +# -- Test # RCC empty add_executable(rccEmpty rccEmpty.cpp rccEmptyRes.qrc) set_property(TARGET rccEmpty PROPERTY AUTORCC ON) target_link_libraries(rccEmpty ${QT_QTCORE_TARGET}) -# -- Test: AUTOUIC +# -- Test # UIC only qtx_wrap_cpp(uicOnlyMoc uicOnlySource/uiconly.h) add_executable(uicOnly uicOnlySource/uiconly.cpp ${uicOnlyMoc}) set_property(TARGET uicOnly PROPERTY AUTOUIC ON) target_link_libraries(uicOnly ${QT_LIBRARIES}) -# -- Test: AUTOMOC, AUTORCC +# -- Test # Add not_generated_file.qrc to the source list to get the file-level # dependency, but don't generate a c++ file from it. Disable the AUTORCC # feature for this target. This tests that qrc files in the sources don't @@ -80,7 +80,7 @@ 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: AUTORCC +# -- Test # When a file listed in a .qrc file changes the target must be rebuilt try_compile(RCC_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/autorcc_depends" @@ -115,7 +115,7 @@ if (NOT file1_step1 GREATER file1_before) message(SEND_ERROR "file1 (${qrc_file1}) should have changed in the first step!") endif() -# -- Test: AUTOMOC +# -- Test # Ensure a repeated build succeeds when a header containing a QObject changes try_compile(MOC_RERUN "${CMAKE_CURRENT_BINARY_DIR}/automoc_rerun" @@ -139,7 +139,7 @@ if (automoc_rerun_result) message(SEND_ERROR "Second build of automoc_rerun failed.") endif() -# -- Test: AUTOMOC, SKIP_AUTOMOC +# -- Test # Test for SKIP_AUTOMOC and SKIP_AUTOGEN on an AUTOMOC enabled target qtx_wrap_cpp(skipMocWrapMoc skipSource/qItemA.hpp @@ -161,7 +161,7 @@ set_property(TARGET skipMocB PROPERTY AUTOMOC ON) set_property(TARGET skipMocB PROPERTY AUTOUIC ON) target_link_libraries(skipMocB ${QT_LIBRARIES}) -# -- Test: AUTOUIC, SKIP_AUTOUIC +# -- Test # Test for SKIP_AUTOUIC and SKIP_AUTOGEN on an AUTOUIC enabled target set(skipUicSources skipUic.cpp @@ -181,7 +181,7 @@ set_property(TARGET skipUicB PROPERTY AUTOUIC ON) set_property(TARGET skipUicB PROPERTY AUTOMOC ON) target_link_libraries(skipUicB ${QT_LIBRARIES}) -# -- Test: AUTORCC, SKIP_AUTORCC +# -- Test # Test for SKIP_AUTORCC and SKIP_AUTOGEN on an AUTORCC enabled target set(skipRccSources skipRcc.cpp @@ -202,10 +202,10 @@ set_property(TARGET skipRccB PROPERTY AUTOUIC ON) set_property(TARGET skipRccB PROPERTY AUTOMOC ON) target_link_libraries(skipRccB ${QT_LIBRARIES}) -# -- Test: AUTOMOC AUTORCC +# -- Test # Source files with the same basename in different subdirectories add_subdirectory(sameName) -# -- Test: AUTOMOC AUTORCC AUTOUIC +# -- Test # Complex test case add_subdirectory(complex) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=06a0700afd94c14d6d9219f776904f1787b41945 commit 06a0700afd94c14d6d9219f776904f1787b41945 Author: Sebastian Holtermann AuthorDate: Fri Feb 17 18:44:10 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 20:30:17 2017 +0100 Autogen: Log simplifications The logging methods now automatically add an end-of-line to the message if it is missing. diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 7c7ad83..199e5cc 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -464,9 +464,7 @@ bool cmQtAutoGenerators::SettingsFileWrite(const std::string& targetDirectory) if (this->GenerateAllAny()) { const std::string filename = SettingsFile(targetDirectory); if (this->Verbose) { - std::ostringstream err; - err << "AutoGen: Writing settings file " << filename << "\n"; - this->LogInfo(err.str()); + this->LogInfo("AutoGen: Writing settings file " + filename); } cmsys::ofstream outfile; outfile.open(filename.c_str(), std::ios::trunc); @@ -482,8 +480,8 @@ bool cmQtAutoGenerators::SettingsFileWrite(const std::string& targetDirectory) cmSystemTools::RemoveFile(filename); { std::ostringstream err; - err << "AutoGen: Error: Writing old settings file failed: " << filename - << std::endl; + err << "AutoGen: Error: Writing old settings file failed: " + << filename; this->LogError(err.str()); } } @@ -685,12 +683,12 @@ void cmQtAutoGenerators::MocFindDepends( mocDepends[absFilename].insert(incFile); if (this->Verbose) { this->LogInfo("AutoMoc: Found dependency:\n \"" + absFilename + - "\"\n \"" + incFile + "\"\n"); + "\"\n \"" + incFile + "\""); } } else { this->LogWarning("AutoMoc: Warning: \"" + absFilename + "\"\n" + "Could not find dependency file \"" + match + - "\"\n"); + "\""); } } contentChars += filter.regExp.end(); @@ -740,10 +738,10 @@ bool cmQtAutoGenerators::ParseSourceFile( bool success = true; const std::string contentText = ReadAll(absFilename); if (contentText.empty()) { - std::ostringstream err; - err << "AutoGen: Warning: " << absFilename << "\n" + std::ostringstream ost; + ost << "AutoGen: Warning: " << absFilename << "\n" << "The file is empty\n"; - this->LogWarning(err.str()); + this->LogWarning(ost.str()); } else { // Parse source contents for MOC if (success && !this->MocSkip(absFilename)) { @@ -763,9 +761,7 @@ void cmQtAutoGenerators::UicParseContent( std::map >& uisIncluded) { if (this->Verbose) { - std::ostringstream err; - err << "AutoUic: Checking " << absFilename << "\n"; - this->LogInfo(err.str()); + this->LogInfo("AutoUic: Checking " + absFilename); } const char* contentChars = contentText.c_str(); @@ -791,9 +787,7 @@ bool cmQtAutoGenerators::MocParseSourceContent( std::map >& mocDepends, bool relaxed) { if (this->Verbose) { - std::ostringstream err; - err << "AutoMoc: Checking " << absFilename << "\n"; - this->LogInfo(err.str()); + this->LogInfo("AutoMoc: Checking " + absFilename); } const std::string scannedFileAbsPath = @@ -845,12 +839,12 @@ bool cmQtAutoGenerators::MocParseSourceContent( ownMocUnderscoreHeader = headerToMoc; } } else { - std::ostringstream err; - err << "AutoMoc: Error: " << absFilename << "\n" + std::ostringstream ost; + ost << "AutoMoc: Error: " << absFilename << "\n" << "The file includes the moc file \"" << incString << "\", but could not find header \"" << incRealBasename << '{' << JoinExts(this->HeaderExtensions) << "}\"\n"; - this->LogError(err.str()); + this->LogError(ost.str()); return false; } } else { @@ -870,34 +864,34 @@ bool cmQtAutoGenerators::MocParseSourceContent( // This is for KDE4 compatibility: fileToMoc = headerToMoc; if (!requiresMoc && (incBasename == scannedFileBasename)) { - std::ostringstream err; - err << "AutoMoc: Warning: " << absFilename << "\n" + std::ostringstream ost; + ost << "AutoMoc: Warning: " << absFilename << "\n" << "The file includes the moc file \"" << incString << "\"" << ", but does not contain a Q_OBJECT or Q_GADGET macro.\n" << "Running moc on \"" << headerToMoc << "\"!\n" << "Include \"moc_" << incBasename << ".cpp\" for a compatibility with " "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; - this->LogWarning(err.str()); + this->LogWarning(ost.str()); } else { - std::ostringstream err; - err << "AutoMoc: Warning: " << absFilename << "\n" + std::ostringstream ost; + ost << "AutoMoc: Warning: " << absFilename << "\n" << "The file includes the moc file \"" << incString << "\" instead of \"moc_" << incBasename << ".cpp\".\n" << "Running moc on \"" << headerToMoc << "\"!\n" << "Include \"moc_" << incBasename << ".cpp\" for compatibility with " "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; - this->LogWarning(err.str()); + this->LogWarning(ost.str()); } } else { - std::ostringstream err; - err << "AutoMoc: Error: " << absFilename << "\n" + std::ostringstream ost; + ost << "AutoMoc: Error: " << absFilename << "\n" << "The file includes the moc file \"" << incString << "\", which seems to be the moc file from a different " "source file. CMake also could not find a matching " "header.\n"; - this->LogError(err.str()); + this->LogError(ost.str()); return false; } } @@ -909,23 +903,23 @@ bool cmQtAutoGenerators::MocParseSourceContent( ownDotMocIncluded = true; // Accept but issue a warning if moc isn't required if (!requiresMoc) { - std::ostringstream err; - err << "AutoMoc: Error: " << absFilename << "\n" + std::ostringstream ost; + ost << "AutoMoc: Error: " << absFilename << "\n" << "The file includes the moc file \"" << incString << "\"" << ", but does not contain a Q_OBJECT or Q_GADGET " "macro.\n"; - this->LogWarning(err.str()); + this->LogWarning(ost.str()); } } else { // Don't allow FOO.moc include other than self in strict mode - std::ostringstream err; - err << "AutoMoc: Error: " << absFilename << "\n" + std::ostringstream ost; + ost << "AutoMoc: Error: " << absFilename << "\n" << "The file includes the moc file \"" << incString << "\", which seems to be the moc file from a different " "source file. This is not supported. Include \"" << scannedFileBasename << ".moc\" to run moc on this source file.\n"; - this->LogError(err.str()); + this->LogError(ost.str()); return false; } } @@ -946,8 +940,8 @@ bool cmQtAutoGenerators::MocParseSourceContent( // But warn, since this is not how it is supposed to be used. if (relaxed && !ownMocUnderscoreInclude.empty()) { // This is for KDE4 compatibility: - std::ostringstream err; - err << "AutoMoc: Warning: " << absFilename << "\n" + std::ostringstream ost; + ost << "AutoMoc: Warning: " << absFilename << "\n" << "The file contains a " << macroName << " macro, but does not include " << "\"" << scannedFileBasename << ".moc\", but instead includes " @@ -956,7 +950,7 @@ bool cmQtAutoGenerators::MocParseSourceContent( << "Better include \"" << scannedFileBasename << ".moc\" for compatibility with " "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; - this->LogWarning(err.str()); + this->LogWarning(ost.str()); // Use scanned source file instead of scanned header file as moc source mocsIncluded[absFilename] = ownMocUnderscoreInclude; @@ -965,12 +959,12 @@ bool cmQtAutoGenerators::MocParseSourceContent( mocsIncluded.erase(ownMocUnderscoreHeader); } else { // Otherwise always error out since it will not compile: - std::ostringstream err; - err << "AutoMoc: Error: " << absFilename << "\n" + std::ostringstream ost; + ost << "AutoMoc: Error: " << absFilename << "\n" << "The file contains a " << macroName << " macro, but does not include " << "\"" << scannedFileBasename << ".moc\"!\n"; - this->LogError(err.str()); + this->LogError(ost.str()); return false; } } @@ -985,9 +979,7 @@ void cmQtAutoGenerators::MocParseHeaderContent( { // Log if (this->Verbose) { - std::ostringstream err; - err << "AutoMoc: Checking " << absFilename << "\n"; - this->LogInfo(err.str()); + this->LogInfo("AutoMoc: Checking " + absFilename); } if (this->MocRequired(contentText)) { // Register moc job @@ -1079,15 +1071,14 @@ bool cmQtAutoGenerators::MocGenerateAll( std::map mergedMocs(mocsIncluded); mergedMocs.insert(mocsNotIncluded.begin(), mocsNotIncluded.end()); if (this->NameCollisionTest(mergedMocs, collisions)) { - std::ostringstream err; - err << "AutoMoc: Error: " + std::ostringstream ost; + ost << "AutoMoc: Error: " "The same moc file will be generated " - "from different sources." - << std::endl - << "To avoid this error either" << std::endl - << "- rename the source files or" << std::endl - << "- do not include the (moc_NAME.cpp|NAME.moc) file" << std::endl; - this->LogErrorNameCollision(err.str(), collisions); + "from different sources.\n" + "To avoid this error either\n" + "- rename the source files or\n" + "- do not include the (moc_NAME.cpp|NAME.moc) file"; + this->LogErrorNameCollision(ost.str(), collisions); return false; } } @@ -1123,21 +1114,20 @@ bool cmQtAutoGenerators::MocGenerateAll( // Compose moc_compilation.cpp content std::string automocSource; { - std::ostringstream outStream; - outStream << "/* This file is autogenerated, do not edit*/\n"; + std::ostringstream ost; + ost << "/* This file is autogenerated, do not edit*/\n"; if (mocsNotIncluded.empty()) { // Dummy content - outStream << "enum some_compilers { need_more_than_nothing };\n"; + ost << "enum some_compilers { need_more_than_nothing };\n"; } else { // Valid content for (std::map::const_iterator it = mocsNotIncluded.begin(); it != mocsNotIncluded.end(); ++it) { - outStream << "#include \"" << it->second << "\"\n"; + ost << "#include \"" << it->second << "\"\n"; } } - outStream.flush(); - automocSource = outStream.str(); + automocSource = ost.str(); } // Check if the content of moc_compilation.cpp changed @@ -1158,25 +1148,20 @@ bool cmQtAutoGenerators::MocGenerateAll( outfile.open(this->MocCppFilenameAbs.c_str(), std::ios::trunc); if (!outfile) { success = false; - std::ostringstream err; - err << "AutoMoc: error opening " << this->MocCppFilenameAbs << "\n"; - this->LogError(err.str()); + this->LogError("AutoMoc: error opening " + this->MocCppFilenameAbs); } else { outfile << automocSource; // Check for write errors if (!outfile.good()) { success = false; - std::ostringstream err; - err << "AutoMoc: error writing " << this->MocCppFilenameAbs << "\n"; - this->LogError(err.str()); + this->LogError("AutoMoc: error writing " + this->MocCppFilenameAbs); } } } } else if (mocCompFileGenerated) { // Only touch moc_compilation.cpp if (this->Verbose) { - this->LogInfo("Touching MOC compilation " + this->MocCppFilenameRel + - "\n"); + this->LogInfo("Touching MOC compilation " + this->MocCppFilenameRel); } cmSystemTools::Touch(this->MocCppFilenameAbs, false); } @@ -1256,12 +1241,12 @@ bool cmQtAutoGenerators::MocGenerateFile( if (!res || (retVal != 0)) { // Command failed { - std::ostringstream err; - err << "AutoMoc: Error: moc process failed for\n"; - err << "\"" << mocFileRel << "\"\n"; - err << "AutoMoc: Command:\n" << cmJoin(cmd, " ") << "\n"; - err << "AutoMoc: Command output:\n" << output << "\n"; - this->LogError(err.str()); + std::ostringstream ost; + ost << "AutoMoc: Error: moc process failed for\n"; + ost << "\"" << mocFileRel << "\"\n"; + ost << "AutoMoc: Command:\n" << cmJoin(cmd, " ") << "\n"; + ost << "AutoMoc: Command output:\n" << output << "\n"; + this->LogError(ost.str()); } cmSystemTools::RemoveFile(mocFileAbs); this->RunMocFailed = true; @@ -1310,12 +1295,11 @@ bool cmQtAutoGenerators::UicGenerateAll( { std::multimap collisions; if (this->NameCollisionTest(testMap, collisions)) { - std::ostringstream err; - err << "AutoUic: Error: The same ui_NAME.h file will be generated " - "from different sources." - << std::endl - << "To avoid this error rename the source files." << std::endl; - this->LogErrorNameCollision(err.str(), collisions); + std::ostringstream ost; + ost << "AutoUic: Error: The same ui_NAME.h file will be generated " + "from different sources.\n" + "To avoid this error rename the source files.\n"; + this->LogErrorNameCollision(ost.str(), collisions); return false; } } @@ -1396,13 +1380,13 @@ bool cmQtAutoGenerators::UicGenerateFile(const std::string& realName, if (!res || (retVal != 0)) { // Command failed { - std::ostringstream err; - err << "AutoUic: Error: uic process failed for\n"; - err << "\"" << uicFileRel << "\" needed by\n"; - err << "\"" << realName << "\"\n"; - err << "AutoUic: Command:\n" << cmJoin(cmd, " ") << "\n"; - err << "AutoUic: Command output:\n" << output << "\n"; - this->LogError(err.str()); + std::ostringstream ost; + ost << "AutoUic: Error: uic process failed for\n"; + ost << "\"" << uicFileRel << "\" needed by\n"; + ost << "\"" << realName << "\"\n"; + ost << "AutoUic: Command:\n" << cmJoin(cmd, " ") << "\n"; + ost << "AutoUic: Command output:\n" << output << "\n"; + this->LogError(ost.str()); } cmSystemTools::RemoveFile(uicFileAbs); this->RunUicFailed = true; @@ -1439,12 +1423,11 @@ bool cmQtAutoGenerators::RccGenerateAll() { std::multimap collisions; if (this->NameCollisionTest(qrcGenMap, collisions)) { - std::ostringstream err; - err << "AutoRcc: Error: The same qrc_NAME.cpp file" - " will be generated from different sources." - << std::endl - << "To avoid this error rename the source .qrc files." << std::endl; - this->LogErrorNameCollision(err.str(), collisions); + std::ostringstream ost; + ost << "AutoRcc: Error: The same qrc_NAME.cpp file" + " will be generated from different sources.\n" + "To avoid this error rename the source .qrc files.\n"; + this->LogErrorNameCollision(ost.str(), collisions); return false; } } @@ -1536,12 +1519,12 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile, if (!res || (retVal != 0)) { // Command failed { - std::ostringstream err; - err << "AutoRcc: Error: rcc process failed for\n"; - err << "\"" << rccOutputFile << "\"\n"; - err << "AutoRcc: Command:\n" << cmJoin(cmd, " ") << "\n"; - err << "AutoRcc: Command output:\n" << output << "\n"; - this->LogError(err.str()); + std::ostringstream ost; + ost << "AutoRcc: Error: rcc process failed for\n"; + ost << "\"" << rccOutputFile << "\"\n"; + ost << "AutoRcc: Command:\n" << cmJoin(cmd, " ") << "\n"; + ost << "AutoRcc: Command output:\n" << output << "\n"; + this->LogError(ost.str()); } cmSystemTools::RemoveFile(rccBuildFile); this->RunRccFailed = true; @@ -1559,18 +1542,23 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile, void cmQtAutoGenerators::LogErrorNameCollision( const std::string& message, - const std::multimap& collisions) + const std::multimap& collisions) const { typedef std::multimap::const_iterator Iter; - std::ostringstream err; + std::ostringstream ost; // Add message - err << message; + if (!message.empty()) { + ost << message; + if (message[message.size() - 1] != '\n') { + ost << '\n'; + } + } // Append collision list for (Iter it = collisions.begin(); it != collisions.end(); ++it) { - err << it->first << " : " << it->second << std::endl; + ost << it->first << " : " << it->second << '\n'; } - this->LogError(err.str()); + this->LogError(ost.str()); } void cmQtAutoGenerators::LogBold(const std::string& message) const @@ -1582,38 +1570,45 @@ void cmQtAutoGenerators::LogBold(const std::string& message) const void cmQtAutoGenerators::LogInfo(const std::string& message) const { - cmSystemTools::Stdout(message.c_str(), message.size()); + std::string msg(message); + if (!msg.empty()) { + if (msg[msg.size() - 1] != '\n') { + msg.push_back('\n'); + } + cmSystemTools::Stdout(msg.c_str(), msg.size()); + } } void cmQtAutoGenerators::LogWarning(const std::string& message) const { std::string msg(message); - msg += "\n"; - cmSystemTools::Stdout(msg.c_str(), msg.size()); + if (!msg.empty()) { + if (msg[msg.size() - 1] != '\n') { + msg.push_back('\n'); + } + // Append empty line + msg.push_back('\n'); + cmSystemTools::Stdout(msg.c_str(), msg.size()); + } } void cmQtAutoGenerators::LogError(const std::string& message) const { std::string msg(message); - msg += "\n"; - cmSystemTools::Stderr(msg.c_str(), msg.size()); + if (!msg.empty()) { + if (msg[msg.size() - 1] != '\n') { + msg.push_back('\n'); + } + // Append empty line + msg.push_back('\n'); + cmSystemTools::Stderr(msg.c_str(), msg.size()); + } } void cmQtAutoGenerators::LogCommand( const std::vector& command) const { - std::ostringstream sbuf; - for (std::vector::const_iterator cmdIt = command.begin(); - cmdIt != command.end(); ++cmdIt) { - if (cmdIt != command.begin()) { - sbuf << " "; - } - sbuf << *cmdIt; - } - if (!sbuf.str().empty()) { - sbuf << std::endl; - this->LogInfo(sbuf.str()); - } + this->LogInfo(cmJoin(command, " ")); } /** @@ -1736,7 +1731,7 @@ std::string cmQtAutoGenerators::FindIncludedFile( return cmsys::SystemTools::GetRealPath(testPath); } } - // Search globaly + // Search globally return FindInIncludeDirectories(includeString); } @@ -1764,16 +1759,14 @@ std::string cmQtAutoGenerators::FindInIncludeDirectories( * @brief Generates the parent directory of the given file on demand * @return True on success */ -bool cmQtAutoGenerators::MakeParentDirectory(const std::string& filename) +bool cmQtAutoGenerators::MakeParentDirectory(const std::string& filename) const { bool success = true; const std::string dirName = cmSystemTools::GetFilenamePath(filename); if (!dirName.empty()) { success = cmsys::SystemTools::MakeDirectory(dirName); if (!success) { - std::ostringstream err; - err << "AutoGen: Directory creation failed: " << dirName << std::endl; - this->LogError(err.str()); + this->LogError("AutoGen: Directory creation failed: " + dirName); } } return success; diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 1011632..2021e4a 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -124,7 +124,7 @@ private: // - Logging void LogErrorNameCollision( const std::string& message, - const std::multimap& collisions); + const std::multimap& collisions) const; void LogBold(const std::string& message) const; void LogInfo(const std::string& message) const; void LogWarning(const std::string& message) const; @@ -138,7 +138,7 @@ private: std::string ChecksumedPath(const std::string& sourceFile, const char* basePrefix, const char* baseSuffix) const; - bool MakeParentDirectory(const std::string& filename); + bool MakeParentDirectory(const std::string& filename) const; bool FindHeader(std::string& header, const std::string& testBasePath) const; bool FindHeaderGlobal(std::string& header, https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=bcc6001f3cbf8ef47da872288f3c81e9600b9bc1 commit bcc6001f3cbf8ef47da872288f3c81e9600b9bc1 Author: Sebastian Holtermann AuthorDate: Fri Feb 17 14:47:20 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 20:30:17 2017 +0100 Autogen: Only touch an unchanged moc_compilation.cpp diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index e0e6d61..7c7ad83 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -1069,6 +1069,9 @@ bool cmQtAutoGenerators::MocGenerateAll( return true; } + bool mocCompFileGenerated = false; + bool mocCompChanged = false; + // look for name collisions { std::multimap collisions; @@ -1088,8 +1091,7 @@ bool cmQtAutoGenerators::MocGenerateAll( return false; } } - - // generate moc files that are included by source files. + // Generate moc files that are included by source files. { const std::string subDir = "include/"; for (std::map::const_iterator it = @@ -1102,16 +1104,14 @@ bool cmQtAutoGenerators::MocGenerateAll( } } } - - // generate moc files that are _not_ included by source files. - bool automocCppChanged = false; + // Generate moc files that are _not_ included by source files. { const std::string subDir; for (std::map::const_iterator it = mocsNotIncluded.begin(); it != mocsNotIncluded.end(); ++it) { if (this->MocGenerateFile(it->first, it->second, subDir, mocDepends)) { - automocCppChanged = true; + mocCompFileGenerated = true; } else { if (this->RunMocFailed) { return false; @@ -1140,46 +1140,47 @@ bool cmQtAutoGenerators::MocGenerateAll( automocSource = outStream.str(); } - // Check if we even need to update moc_compilation.cpp - if (!automocCppChanged) { - // compare contents of the moc_compilation.cpp file + // Check if the content of moc_compilation.cpp changed + { const std::string oldContents = ReadAll(this->MocCppFilenameAbs); - if (oldContents == automocSource) { - // nothing changed: don't touch the moc_compilation.cpp file - if (this->Verbose) { - std::ostringstream err; - err << "AutoMoc: " << this->MocCppFilenameRel << " still up to date" - << std::endl; - this->LogInfo(err.str()); - } - return true; - } + mocCompChanged = (oldContents != automocSource); } - // Actually write moc_compilation.cpp - this->LogBold("Generating MOC compilation " + this->MocCppFilenameRel); + bool success = true; + if (mocCompChanged) { + // Actually write moc_compilation.cpp + this->LogBold("Generating MOC compilation " + this->MocCppFilenameRel); - // Make sure the parent directory exists - bool success = this->MakeParentDirectory(this->MocCppFilenameAbs); - if (success) { - cmsys::ofstream outfile; - outfile.open(this->MocCppFilenameAbs.c_str(), std::ios::trunc); - if (!outfile) { - success = false; - std::ostringstream err; - err << "AutoMoc: error opening " << this->MocCppFilenameAbs << "\n"; - this->LogError(err.str()); - } else { - outfile << automocSource; - // Check for write errors - if (!outfile.good()) { + // Make sure the parent directory exists + success = this->MakeParentDirectory(this->MocCppFilenameAbs); + if (success) { + cmsys::ofstream outfile; + outfile.open(this->MocCppFilenameAbs.c_str(), std::ios::trunc); + if (!outfile) { success = false; std::ostringstream err; - err << "AutoMoc: error writing " << this->MocCppFilenameAbs << "\n"; + err << "AutoMoc: error opening " << this->MocCppFilenameAbs << "\n"; this->LogError(err.str()); + } else { + outfile << automocSource; + // Check for write errors + if (!outfile.good()) { + success = false; + std::ostringstream err; + err << "AutoMoc: error writing " << this->MocCppFilenameAbs << "\n"; + this->LogError(err.str()); + } } } + } else if (mocCompFileGenerated) { + // Only touch moc_compilation.cpp + if (this->Verbose) { + this->LogInfo("Touching MOC compilation " + this->MocCppFilenameRel + + "\n"); + } + cmSystemTools::Touch(this->MocCppFilenameAbs, false); } + return success; } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=45de32fa6c20de954e0571dfb9a44b375c87a6c6 commit 45de32fa6c20de954e0571dfb9a44b375c87a6c6 Author: Sebastian Holtermann AuthorDate: Fri Feb 17 11:56:02 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 20:30:17 2017 +0100 Autogen: Rebuild moc when Q_PLUGIN_METADATA json file changes Closes #15419 diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index e2d5f9b..e0e6d61 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -564,6 +564,16 @@ void cmQtAutoGenerators::Init(cmMakefile* makefile) this->MocIncludes.push_back(*it); } } + + // Insert MocDependFilter for Q_PLUGIN_METADATA + if (QtMajorVersion != "4") { + MocDependFilter filter; + filter.key = "Q_PLUGIN_METADATA"; + filter.regExp.compile("[\n][ \t]*" + "Q_PLUGIN_METADATA[ \t]*\\(" + "[^\\)]*FILE[ \t]*\"([^\"]+)\""); + this->MocDependFilters.push_back(filter); + } } bool cmQtAutoGenerators::RunAutogen() @@ -579,6 +589,7 @@ bool cmQtAutoGenerators::RunAutogen() // key = moc source filepath, value = moc output filepath std::map mocsIncluded; std::map mocsNotIncluded; + std::map > mocDepends; std::map > uisIncluded; // collects all headers which may need to be mocced std::set mocHeaderFiles; @@ -589,8 +600,8 @@ bool cmQtAutoGenerators::RunAutogen() it != this->Sources.end(); ++it) { const std::string& absFilename = cmsys::SystemTools::GetRealPath(*it); // Parse source file for MOC/UIC - if (!this->ParseSourceFile(absFilename, mocsIncluded, uisIncluded, - this->MocRelaxedMode)) { + if (!this->ParseSourceFile(absFilename, mocsIncluded, mocDepends, + uisIncluded, this->MocRelaxedMode)) { return false; } // Find additional headers @@ -610,10 +621,10 @@ bool cmQtAutoGenerators::RunAutogen() } } this->ParseHeaders(mocHeaderFiles, uicHeaderFiles, mocsIncluded, - mocsNotIncluded, uisIncluded); + mocsNotIncluded, mocDepends, uisIncluded); // Generate files - if (!this->MocGenerateAll(mocsIncluded, mocsNotIncluded)) { + if (!this->MocGenerateAll(mocsIncluded, mocsNotIncluded, mocDepends)) { return false; } if (!this->UicGenerateAll(uisIncluded)) { @@ -630,17 +641,18 @@ bool cmQtAutoGenerators::RunAutogen() * @brief Tests if the C++ content requires moc processing * @return True if moc is required */ -bool cmQtAutoGenerators::MocRequired(const std::string& text, +bool cmQtAutoGenerators::MocRequired(const std::string& contentText, std::string* macroName) { for (unsigned int ii = 0; ii != cmArraySize(this->MacroFilters); ++ii) { - MacroFilter& macroFilter = this->MacroFilters[ii]; - // Run a simple check before an expensive regular expression check - if (text.find(macroFilter.first) != std::string::npos) { - if (macroFilter.second.find(text)) { + MacroFilter& filter = this->MacroFilters[ii]; + // Run a simple find string operation before the expensive + // regular expression check + if (contentText.find(filter.first) != std::string::npos) { + if (filter.second.find(contentText)) { // Return macro name on demand if (macroName != CM_NULLPTR) { - *macroName = macroFilter.first; + *macroName = filter.first; } return true; } @@ -649,6 +661,44 @@ bool cmQtAutoGenerators::MocRequired(const std::string& text, return false; } +void cmQtAutoGenerators::MocFindDepends( + const std::string& absFilename, const std::string& contentText, + std::map >& mocDepends) +{ + for (std::vector::iterator fit = + this->MocDependFilters.begin(); + fit != this->MocDependFilters.end(); ++fit) { + MocDependFilter& filter = *fit; + // Run a simple find string operation before the expensive + // regular expression check + if (contentText.find(filter.key) != std::string::npos) { + // Run regular expression check loop + const char* contentChars = contentText.c_str(); + while (filter.regExp.find(contentChars)) { + // Evaluate match + const std::string match = filter.regExp.match(1); + if (!match.empty()) { + // Find the dependency file + const std::string incFile = + this->FindIncludedFile(absFilename, match); + if (!incFile.empty()) { + mocDepends[absFilename].insert(incFile); + if (this->Verbose) { + this->LogInfo("AutoMoc: Found dependency:\n \"" + absFilename + + "\"\n \"" + incFile + "\"\n"); + } + } else { + this->LogWarning("AutoMoc: Warning: \"" + absFilename + "\"\n" + + "Could not find dependency file \"" + match + + "\"\n"); + } + } + contentChars += filter.regExp.end(); + } + } + } +} + /** * @brief Tests if the file should be ignored for moc scanning * @return True if the file should be ignored @@ -684,11 +734,12 @@ bool cmQtAutoGenerators::UicSkip(const std::string& absFilename) const bool cmQtAutoGenerators::ParseSourceFile( const std::string& absFilename, std::map& mocsIncluded, + std::map >& mocDepends, std::map >& uisIncluded, bool relaxed) { bool success = true; - const std::string contentsString = ReadAll(absFilename); - if (contentsString.empty()) { + const std::string contentText = ReadAll(absFilename); + if (contentText.empty()) { std::ostringstream err; err << "AutoGen: Warning: " << absFilename << "\n" << "The file is empty\n"; @@ -696,19 +747,19 @@ bool cmQtAutoGenerators::ParseSourceFile( } else { // Parse source contents for MOC if (success && !this->MocSkip(absFilename)) { - success = this->ParseContentForMoc(absFilename, contentsString, - mocsIncluded, relaxed); + success = this->MocParseSourceContent(absFilename, contentText, + mocsIncluded, mocDepends, relaxed); } // Parse source contents for UIC if (success && !this->UicSkip(absFilename)) { - this->ParseContentForUic(absFilename, contentsString, uisIncluded); + this->UicParseContent(absFilename, contentText, uisIncluded); } } return success; } -void cmQtAutoGenerators::ParseContentForUic( - const std::string& absFilename, const std::string& contentsString, +void cmQtAutoGenerators::UicParseContent( + const std::string& absFilename, const std::string& contentText, std::map >& uisIncluded) { if (this->Verbose) { @@ -717,7 +768,7 @@ void cmQtAutoGenerators::ParseContentForUic( this->LogInfo(err.str()); } - const char* contentChars = contentsString.c_str(); + const char* contentChars = contentText.c_str(); if (strstr(contentChars, "ui_") != CM_NULLPTR) { while (this->RegExpUicInclude.find(contentChars)) { const std::string currentUi = this->RegExpUicInclude.match(1); @@ -734,9 +785,10 @@ void cmQtAutoGenerators::ParseContentForUic( /** * @return True on success */ -bool cmQtAutoGenerators::ParseContentForMoc( - const std::string& absFilename, const std::string& contentsString, - std::map& mocsIncluded, bool relaxed) +bool cmQtAutoGenerators::MocParseSourceContent( + const std::string& absFilename, const std::string& contentText, + std::map& mocsIncluded, + std::map >& mocDepends, bool relaxed) { if (this->Verbose) { std::ostringstream err; @@ -750,16 +802,15 @@ bool cmQtAutoGenerators::ParseContentForMoc( cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename); std::string macroName; - const bool requiresMoc = this->MocRequired(contentsString, ¯oName); + const bool requiresMoc = this->MocRequired(contentText, ¯oName); bool ownDotMocIncluded = false; - bool ownMocUnderscoreIncluded = false; - std::string ownMocUnderscoreFile; - std::string ownMocHeaderFile; + std::string ownMocUnderscoreInclude; + std::string ownMocUnderscoreHeader; // first a simple string check for "moc" is *much* faster than the regexp, // and if the string search already fails, we don't have to try the // expensive regexp - const char* contentChars = contentsString.c_str(); + const char* contentChars = contentText.c_str(); if (strstr(contentChars, "moc") != CM_NULLPTR) { // Iterate over all included moc files while (this->RegExpMocInclude.find(contentChars)) { @@ -785,11 +836,13 @@ bool cmQtAutoGenerators::ParseContentForMoc( const std::string headerToMoc = this->FindMocHeader(scannedFileAbsPath, incRealBasename, incSubDir); if (!headerToMoc.empty()) { + // Register moc job mocsIncluded[headerToMoc] = incString; + this->MocFindDepends(headerToMoc, contentText, mocDepends); + // Store meta information for relaxed mode if (relaxed && (incRealBasename == scannedFileBasename)) { - ownMocUnderscoreIncluded = true; - ownMocUnderscoreFile = incString; - ownMocHeaderFile = headerToMoc; + ownMocUnderscoreInclude = incString; + ownMocUnderscoreHeader = headerToMoc; } } else { std::ostringstream err; @@ -878,6 +931,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( } if (!fileToMoc.empty()) { mocsIncluded[fileToMoc] = incString; + this->MocFindDepends(fileToMoc, contentText, mocDepends); } } // Forward content pointer @@ -890,14 +944,14 @@ bool cmQtAutoGenerators::ParseContentForMoc( // If this is the case, the moc_foo.cpp should probably be generated from // foo.cpp instead of foo.h, because otherwise it won't build. // But warn, since this is not how it is supposed to be used. - if (relaxed && ownMocUnderscoreIncluded) { + if (relaxed && !ownMocUnderscoreInclude.empty()) { // This is for KDE4 compatibility: std::ostringstream err; err << "AutoMoc: Warning: " << absFilename << "\n" << "The file contains a " << macroName << " macro, but does not include " << "\"" << scannedFileBasename << ".moc\", but instead includes " - << "\"" << ownMocUnderscoreFile << "\".\n" + << "\"" << ownMocUnderscoreInclude << "\".\n" << "Running moc on \"" << absFilename << "\"!\n" << "Better include \"" << scannedFileBasename << ".moc\" for compatibility with " @@ -905,8 +959,10 @@ bool cmQtAutoGenerators::ParseContentForMoc( this->LogWarning(err.str()); // Use scanned source file instead of scanned header file as moc source - mocsIncluded[absFilename] = ownMocUnderscoreFile; - mocsIncluded.erase(ownMocHeaderFile); + mocsIncluded[absFilename] = ownMocUnderscoreInclude; + this->MocFindDepends(absFilename, contentText, mocDepends); + // Remove + mocsIncluded.erase(ownMocUnderscoreHeader); } else { // Otherwise always error out since it will not compile: std::ostringstream err; @@ -922,6 +978,25 @@ bool cmQtAutoGenerators::ParseContentForMoc( return true; } +void cmQtAutoGenerators::MocParseHeaderContent( + const std::string& absFilename, const std::string& contentText, + std::map& mocsNotIncluded, + std::map >& mocDepends) +{ + // Log + if (this->Verbose) { + std::ostringstream err; + err << "AutoMoc: Checking " << absFilename << "\n"; + this->LogInfo(err.str()); + } + if (this->MocRequired(contentText)) { + // Register moc job + mocsNotIncluded[absFilename] = + this->ChecksumedPath(absFilename, "moc_", ".cpp"); + this->MocFindDepends(absFilename, contentText, mocDepends); + } +} + void cmQtAutoGenerators::SearchHeadersForSourceFile( const std::string& absFilename, std::set& mocHeaderFiles, std::set& uicHeaderFiles) const @@ -958,6 +1033,7 @@ void cmQtAutoGenerators::ParseHeaders( const std::set& uicHeaderFiles, const std::map& mocsIncluded, std::map& mocsNotIncluded, + std::map >& mocDepends, std::map >& uisIncluded) { // Merged header files list to read files only once @@ -968,33 +1044,26 @@ void cmQtAutoGenerators::ParseHeaders( for (std::set::const_iterator hIt = headerFiles.begin(); hIt != headerFiles.end(); ++hIt) { const std::string& headerName = *hIt; - const std::string contents = ReadAll(headerName); + const std::string contentText = ReadAll(headerName); // Parse header content for MOC if ((mocHeaderFiles.find(headerName) != mocHeaderFiles.end()) && (mocsIncluded.find(headerName) == mocsIncluded.end())) { - // Log - if (this->Verbose) { - std::ostringstream err; - err << "AutoMoc: Checking " << headerName << "\n"; - this->LogInfo(err.str()); - } - if (this->MocRequired(contents)) { - mocsNotIncluded[headerName] = - this->ChecksumedPath(headerName, "moc_", ".cpp"); - } + this->MocParseHeaderContent(headerName, contentText, mocsNotIncluded, + mocDepends); } // Parse header content for UIC if (uicHeaderFiles.find(headerName) != uicHeaderFiles.end()) { - this->ParseContentForUic(headerName, contents, uisIncluded); + this->UicParseContent(headerName, contentText, uisIncluded); } } } bool cmQtAutoGenerators::MocGenerateAll( const std::map& mocsIncluded, - const std::map& mocsNotIncluded) + const std::map& mocsNotIncluded, + const std::map >& mocDepends) { if (!this->MocEnabled()) { return true; @@ -1022,11 +1091,11 @@ bool cmQtAutoGenerators::MocGenerateAll( // generate moc files that are included by source files. { - const std::string subDirPrefix = "include/"; + const std::string subDir = "include/"; for (std::map::const_iterator it = mocsIncluded.begin(); it != mocsIncluded.end(); ++it) { - if (!this->MocGenerateFile(it->first, it->second, subDirPrefix)) { + if (!this->MocGenerateFile(it->first, it->second, subDir, mocDepends)) { if (this->RunMocFailed) { return false; } @@ -1037,11 +1106,11 @@ bool cmQtAutoGenerators::MocGenerateAll( // generate moc files that are _not_ included by source files. bool automocCppChanged = false; { - const std::string subDirPrefix; + const std::string subDir; for (std::map::const_iterator it = mocsNotIncluded.begin(); it != mocsNotIncluded.end(); ++it) { - if (this->MocGenerateFile(it->first, it->second, subDirPrefix)) { + if (this->MocGenerateFile(it->first, it->second, subDir, mocDepends)) { automocCppChanged = true; } else { if (this->RunMocFailed) { @@ -1117,9 +1186,10 @@ bool cmQtAutoGenerators::MocGenerateAll( /** * @return True if a moc file was created. False may indicate an error. */ -bool cmQtAutoGenerators::MocGenerateFile(const std::string& sourceFile, - const std::string& mocFileName, - const std::string& subDirPrefix) +bool cmQtAutoGenerators::MocGenerateFile( + const std::string& sourceFile, const std::string& mocFileName, + const std::string& subDirPrefix, + const std::map >& mocDepends) { bool mocGenerated = false; bool generateMoc = this->GenerateAllMoc; @@ -1131,6 +1201,20 @@ bool cmQtAutoGenerators::MocGenerateFile(const std::string& sourceFile, if (!generateMoc) { // Test if the source file is newer that the build file generateMoc = FileAbsentOrOlder(mocFileAbs, sourceFile); + if (!generateMoc) { + // Test if a dependency file changed + std::map >::const_iterator dit = + mocDepends.find(sourceFile); + if (dit != mocDepends.end()) { + for (std::set::const_iterator fit = dit->second.begin(); + fit != dit->second.end(); ++fit) { + if (FileAbsentOrOlder(mocFileAbs, *fit)) { + generateMoc = true; + break; + } + } + } + } } if (generateMoc) { // Log @@ -1488,33 +1572,34 @@ void cmQtAutoGenerators::LogErrorNameCollision( this->LogError(err.str()); } -void cmQtAutoGenerators::LogBold(const std::string& message) +void cmQtAutoGenerators::LogBold(const std::string& message) const { cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue | cmsysTerminal_Color_ForegroundBold, message.c_str(), true, this->ColorOutput); } -void cmQtAutoGenerators::LogInfo(const std::string& message) +void cmQtAutoGenerators::LogInfo(const std::string& message) const { cmSystemTools::Stdout(message.c_str(), message.size()); } -void cmQtAutoGenerators::LogWarning(const std::string& message) +void cmQtAutoGenerators::LogWarning(const std::string& message) const { std::string msg(message); msg += "\n"; cmSystemTools::Stdout(msg.c_str(), msg.size()); } -void cmQtAutoGenerators::LogError(const std::string& message) +void cmQtAutoGenerators::LogError(const std::string& message) const { std::string msg(message); msg += "\n"; cmSystemTools::Stderr(msg.c_str(), msg.size()); } -void cmQtAutoGenerators::LogCommand(const std::vector& command) +void cmQtAutoGenerators::LogCommand( + const std::vector& command) const { std::ostringstream sbuf; for (std::vector::const_iterator cmdIt = command.begin(); @@ -1638,23 +1723,40 @@ std::string cmQtAutoGenerators::FindMocHeader(const std::string& basePath, return header; } +std::string cmQtAutoGenerators::FindIncludedFile( + const std::string& sourceFile, const std::string& includeString) const +{ + // Search in vicinity of the source + { + std::string testPath = cmSystemTools::GetFilenamePath(sourceFile); + testPath += '/'; + testPath += includeString; + if (cmsys::SystemTools::FileExists(testPath.c_str())) { + return cmsys::SystemTools::GetRealPath(testPath); + } + } + // Search globaly + return FindInIncludeDirectories(includeString); +} + /** * @brief Tries to find a file in the include directories * @return True on success */ -bool cmQtAutoGenerators::FindInIncludeDirectories( - std::string& file_n, const std::string& searchString) const +std::string cmQtAutoGenerators::FindInIncludeDirectories( + const std::string& includeString) const { + std::string res; for (std::vector::const_iterator iit = this->MocIncludePaths.begin(); iit != this->MocIncludePaths.end(); ++iit) { - const std::string fullPath = ((*iit) + '/' + searchString); + const std::string fullPath = ((*iit) + '/' + includeString); if (cmsys::SystemTools::FileExists(fullPath.c_str())) { - file_n = fullPath; - return true; + res = cmsys::SystemTools::GetRealPath(fullPath); + break; } } - return false; + return res; } /** diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 3fe284f..1011632 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -22,6 +22,16 @@ public: bool Run(const std::string& targetDirectory, const std::string& config); private: + // - Types + + /// @brief Used to extract additional dependencies from content text + struct MocDependFilter + { + std::string key; + cmsys::RegularExpression regExp; + }; + typedef std::pair MacroFilter; + // - Configuration bool ReadAutogenInfoFile(cmMakefile* makefile, const std::string& targetDirectory, @@ -47,14 +57,19 @@ private: bool RunAutogen(); // - Content analysis - bool MocRequired(const std::string& text, + bool MocRequired(const std::string& contentText, std::string* macroName = CM_NULLPTR); + void MocFindDepends( + const std::string& absFilename, const std::string& contentText, + std::map >& mocDepends); + bool MocSkip(const std::string& absFilename) const; bool UicSkip(const std::string& absFilename) const; bool ParseSourceFile( const std::string& absFilename, std::map& mocsIncluded, + std::map >& mocDepends, std::map >& includedUis, bool relaxed); @@ -67,24 +82,32 @@ private: const std::set& uicHeaderFiles, const std::map& mocsIncluded, std::map& mocsNotIncluded, + std::map >& mocDepends, std::map >& includedUis); - void ParseContentForUic( - const std::string& fileName, const std::string& contentsString, + void UicParseContent( + const std::string& fileName, const std::string& contentText, std::map >& includedUis); - bool ParseContentForMoc(const std::string& absFilename, - const std::string& contentsString, - std::map& mocsIncluded, - bool relaxed); + bool MocParseSourceContent( + const std::string& absFilename, const std::string& contentText, + std::map& mocsIncluded, + std::map >& mocDepends, bool relaxed); + + void MocParseHeaderContent( + const std::string& absFilename, const std::string& contentText, + std::map& mocsNotIncluded, + std::map >& mocDepends); // - Moc file generation bool MocGenerateAll( const std::map& mocsIncluded, - const std::map& mocsNotIncluded); - bool MocGenerateFile(const std::string& sourceFile, - const std::string& mocFileName, - const std::string& subDirPrefix); + const std::map& mocsNotIncluded, + const std::map >& mocDepends); + bool MocGenerateFile( + const std::string& sourceFile, const std::string& mocFileName, + const std::string& subDirPrefix, + const std::map >& mocDepends); // - Uic file generation bool UicGenerateAll( @@ -102,11 +125,11 @@ private: void LogErrorNameCollision( const std::string& message, const std::multimap& collisions); - void LogBold(const std::string& message); - void LogInfo(const std::string& message); - void LogWarning(const std::string& message); - void LogError(const std::string& message); - void LogCommand(const std::vector& command); + void LogBold(const std::string& message) const; + void LogInfo(const std::string& message) const; + void LogWarning(const std::string& message) const; + void LogError(const std::string& message) const; + void LogCommand(const std::vector& command) const; // - Utility bool NameCollisionTest( @@ -123,8 +146,9 @@ private: std::string FindMocHeader(const std::string& basePath, const std::string& baseName, const std::string& subDir) const; - bool FindInIncludeDirectories(std::string& file_n, - const std::string& searchString) const; + std::string FindIncludedFile(const std::string& sourceFile, + const std::string& includeString) const; + std::string FindInIncludeDirectories(const std::string& includeString) const; // - Target names std::string OriginTargetName; @@ -155,6 +179,7 @@ private: std::vector MocIncludes; std::vector MocDefinitions; std::vector MocOptions; + std::vector MocDependFilters; // - Uic std::vector UicSkipList; std::vector UicTargetOptions; @@ -166,7 +191,6 @@ private: // - Utility cmFilePathChecksum fpathCheckSum; std::vector HeaderExtensions; - typedef std::pair MacroFilter; MacroFilter MacroFilters[2]; cmsys::RegularExpression RegExpMocInclude; cmsys::RegularExpression RegExpUicInclude; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4612c1f6a7b201c12e7ff55633e744d4a4320147 commit 4612c1f6a7b201c12e7ff55633e744d4a4320147 Author: Sebastian Holtermann AuthorDate: Thu Feb 16 23:55:59 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:45 2017 +0100 Autogen: Use GetRealPath in central places only diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index a0cac68..e2d5f9b 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -587,7 +587,7 @@ bool cmQtAutoGenerators::RunAutogen() // Parse sources for (std::vector::const_iterator it = this->Sources.begin(); it != this->Sources.end(); ++it) { - const std::string& absFilename = *it; + const std::string& absFilename = cmsys::SystemTools::GetRealPath(*it); // Parse source file for MOC/UIC if (!this->ParseSourceFile(absFilename, mocsIncluded, uisIncluded, this->MocRelaxedMode)) { @@ -601,7 +601,7 @@ bool cmQtAutoGenerators::RunAutogen() // Parse headers for (std::vector::const_iterator it = this->Headers.begin(); it != this->Headers.end(); ++it) { - const std::string& headerName = *it; + const std::string& headerName = cmsys::SystemTools::GetRealPath(*it); if (!this->MocSkip(headerName)) { mocHeaderFiles.insert(headerName); } @@ -717,7 +717,6 @@ void cmQtAutoGenerators::ParseContentForUic( this->LogInfo(err.str()); } - const std::string realName = cmsys::SystemTools::GetRealPath(absFilename); const char* contentChars = contentsString.c_str(); if (strstr(contentChars, "ui_") != CM_NULLPTR) { while (this->RegExpUicInclude.find(contentChars)) { @@ -726,7 +725,7 @@ void cmQtAutoGenerators::ParseContentForUic( cmsys::SystemTools::GetFilenameWithoutLastExtension(currentUi); // basename should be the part of the ui filename used for // finding the correct header, so we need to remove the ui_ part - uisIncluded[realName].push_back(basename.substr(3)); + uisIncluded[absFilename].push_back(basename.substr(3)); contentChars += this->RegExpUicInclude.end(); } } @@ -746,9 +745,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( } const std::string scannedFileAbsPath = - cmsys::SystemTools::GetFilenamePath( - cmsys::SystemTools::GetRealPath(absFilename)) + - '/'; + cmsys::SystemTools::GetFilenamePath(absFilename) + '/'; const std::string scannedFileBasename = cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename); @@ -931,33 +928,27 @@ void cmQtAutoGenerators::SearchHeadersForSourceFile( { std::string basepaths[2]; { - std::string bpath = cmsys::SystemTools::GetFilenamePath( - cmsys::SystemTools::GetRealPath(absFilename)); + std::string bpath = cmsys::SystemTools::GetFilenamePath(absFilename); bpath += '/'; bpath += cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename); - // search for default header files and private header files - basepaths[0] = (bpath + "."); - basepaths[1] = (bpath + "_p."); + basepaths[0] = bpath; + basepaths[1] = bpath + "_p"; } for (const std::string* bpit = cmArrayBegin(basepaths); bpit != cmArrayEnd(basepaths); ++bpit) { - for (std::vector::const_iterator heit = - this->HeaderExtensions.begin(); - heit != this->HeaderExtensions.end(); ++heit) { - const std::string hname = (*bpit) + (*heit); - if (cmsys::SystemTools::FileExists(hname.c_str())) { - // Moc headers - if (!this->MocSkip(absFilename) && !this->MocSkip(hname)) { - mocHeaderFiles.insert(hname); - } - // Uic headers - if (!this->UicSkip(absFilename) && !this->UicSkip(hname)) { - uicHeaderFiles.insert(hname); - } - break; + std::string headerName; + if (this->FindHeader(headerName, *bpit)) { + // Moc headers + if (!this->MocSkip(absFilename) && !this->MocSkip(headerName)) { + mocHeaderFiles.insert(headerName); + } + // Uic headers + if (!this->UicSkip(absFilename) && !this->UicSkip(headerName)) { + uicHeaderFiles.insert(headerName); } + break; } } } @@ -1642,7 +1633,7 @@ std::string cmQtAutoGenerators::FindMocHeader(const std::string& basePath, } while (false); // Sanitize if (!header.empty()) { - header = cmSystemTools::CollapseFullPath(header); + header = cmsys::SystemTools::GetRealPath(header); } return header; } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=45e9d66545cdabc6ea5103e6c5c2546e2e0a982b commit 45e9d66545cdabc6ea5103e6c5c2546e2e0a982b Author: Sebastian Holtermann AuthorDate: Thu Feb 16 22:03:43 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:45 2017 +0100 Autogen: Search moc includes in include directories diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index a98ae09..a0cac68 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -772,7 +772,8 @@ bool cmQtAutoGenerators::ParseContentForMoc( cmsys::SystemTools::GetFilenameWithoutLastExtension(incString); std::string incSubDir; if (incString.find_first_of('/') != std::string::npos) { - incSubDir = cmsys::SystemTools::GetFilenamePath(incString) + '/'; + incSubDir = cmsys::SystemTools::GetFilenamePath(incString); + incSubDir += '/'; } // If the moc include is of the moc_foo.cpp style we expect @@ -784,8 +785,8 @@ bool cmQtAutoGenerators::ParseContentForMoc( // Include: moc_FOO.cxx // Remove the moc_ part const std::string incRealBasename = incBasename.substr(4); - const std::string headerToMoc = this->FindMatchingHeader( - scannedFileAbsPath, incRealBasename, incSubDir); + const std::string headerToMoc = + this->FindMocHeader(scannedFileAbsPath, incRealBasename, incSubDir); if (!headerToMoc.empty()) { mocsIncluded[headerToMoc] = incString; if (relaxed && (incRealBasename == scannedFileBasename)) { @@ -813,8 +814,8 @@ bool cmQtAutoGenerators::ParseContentForMoc( ownDotMocIncluded = true; } else { // In relaxed mode try to find a header instead but issue a warning - const std::string headerToMoc = this->FindMatchingHeader( - scannedFileAbsPath, incBasename, incSubDir); + const std::string headerToMoc = + this->FindMocHeader(scannedFileAbsPath, incBasename, incSubDir); if (!headerToMoc.empty()) { // This is for KDE4 compatibility: fileToMoc = headerToMoc; @@ -1606,9 +1607,23 @@ bool cmQtAutoGenerators::FindHeader(std::string& header, return false; } -std::string cmQtAutoGenerators::FindMatchingHeader( - const std::string& basePath, const std::string& baseName, - const std::string& subDir) const +bool cmQtAutoGenerators::FindHeaderGlobal( + std::string& header, const std::string& testBasePath) const +{ + for (std::vector::const_iterator iit = + this->MocIncludePaths.begin(); + iit != this->MocIncludePaths.end(); ++iit) { + const std::string fullPath = ((*iit) + '/' + testBasePath); + if (FindHeader(header, fullPath)) { + return true; + } + } + return false; +} + +std::string cmQtAutoGenerators::FindMocHeader(const std::string& basePath, + const std::string& baseName, + const std::string& subDir) const { std::string header; do { @@ -1620,7 +1635,15 @@ std::string cmQtAutoGenerators::FindMatchingHeader( if (this->FindHeader(header, basePath + baseName)) { break; } + // Try include directories + if (this->FindHeaderGlobal(header, subDir + baseName)) { + break; + } } while (false); + // Sanitize + if (!header.empty()) { + header = cmSystemTools::CollapseFullPath(header); + } return header; } diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index b5ffff8..3fe284f 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -118,9 +118,11 @@ private: bool MakeParentDirectory(const std::string& filename); bool FindHeader(std::string& header, const std::string& testBasePath) const; - std::string FindMatchingHeader(const std::string& basePath, - const std::string& baseName, - const std::string& subDir) const; + bool FindHeaderGlobal(std::string& header, + const std::string& testBasePath) const; + std::string FindMocHeader(const std::string& basePath, + const std::string& baseName, + const std::string& subDir) const; bool FindInIncludeDirectories(std::string& file_n, const std::string& searchString) const; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=408b3783d63fc5f1ea0ee4a7a2bb2281bb13d64d commit 408b3783d63fc5f1ea0ee4a7a2bb2281bb13d64d Author: Sebastian Holtermann AuthorDate: Thu Feb 16 21:09:04 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:45 2017 +0100 Autogen: Sort includes before composing include options diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 444acdb..a98ae09 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -509,15 +509,44 @@ void cmQtAutoGenerators::Init(cmMakefile* makefile) // Acquire header extensions this->HeaderExtensions = makefile->GetCMakeInstance()->GetHeaderExtensions(); + // Sort include directories on demand + if (this->IncludeProjectDirsBefore) { + // Move strings to temporary list + std::list includes; + includes.insert(includes.end(), this->MocIncludePaths.begin(), + this->MocIncludePaths.end()); + this->MocIncludePaths.clear(); + this->MocIncludePaths.reserve(includes.size()); + // Append project directories only + { + const char* movePaths[2] = { this->ProjectBinaryDir.c_str(), + this->ProjectSourceDir.c_str() }; + for (const char* const* mpit = cmArrayBegin(movePaths); + mpit != cmArrayEnd(movePaths); ++mpit) { + std::list::iterator it = includes.begin(); + while (it != includes.end()) { + const std::string& path = *it; + if (cmsys::SystemTools::StringStartsWith(path, *mpit)) { + this->MocIncludePaths.push_back(path); + it = includes.erase(it); + } else { + ++it; + } + } + } + } + // Append remaining directories + this->MocIncludePaths.insert(this->MocIncludePaths.end(), includes.begin(), + includes.end()); + } // Compose moc includes list - std::list mocIncludes; { std::set frameworkPaths; for (std::vector::const_iterator it = this->MocIncludePaths.begin(); it != this->MocIncludePaths.end(); ++it) { const std::string& path = *it; - mocIncludes.push_back("-I" + path); + this->MocIncludes.push_back("-I" + path); // Extract framework path if (cmHasLiteralSuffix(path, ".framework/Headers")) { // Go up twice to get to the framework root @@ -531,40 +560,10 @@ void cmQtAutoGenerators::Init(cmMakefile* makefile) // Append framework includes for (std::set::const_iterator it = frameworkPaths.begin(); it != frameworkPaths.end(); ++it) { - mocIncludes.push_back("-F"); - mocIncludes.push_back(*it); + this->MocIncludes.push_back("-F"); + this->MocIncludes.push_back(*it); } } - if (this->IncludeProjectDirsBefore) { - // Extract project includes - std::vector mocSortedIncludes; - { - std::vector movePaths; - movePaths.push_back("-I" + this->ProjectBinaryDir); - movePaths.push_back("-I" + this->ProjectSourceDir); - - for (std::vector::const_iterator mpit = movePaths.begin(); - mpit != movePaths.end(); ++mpit) { - std::list::iterator it = mocIncludes.begin(); - while (it != mocIncludes.end()) { - const std::string& path = *it; - if (cmsys::SystemTools::StringStartsWith(path, mpit->c_str())) { - mocSortedIncludes.push_back(path); - it = mocIncludes.erase(it); - } else { - ++it; - } - } - } - } - // Place extracted includes at the begin - this->MocIncludes.insert(this->MocIncludes.end(), - mocSortedIncludes.begin(), - mocSortedIncludes.end()); - } - // Append remaining includes - this->MocIncludes.insert(this->MocIncludes.end(), mocIncludes.begin(), - mocIncludes.end()); } bool cmQtAutoGenerators::RunAutogen() https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6988d0e8d6f81326c938224387533e30890e63d6 commit 6988d0e8d6f81326c938224387533e30890e63d6 Author: Sebastian Holtermann AuthorDate: Thu Feb 16 19:47:40 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:45 2017 +0100 Autogen: Add FindInIncludeDirectories method diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 8db7754..444acdb 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -1626,6 +1626,25 @@ std::string cmQtAutoGenerators::FindMatchingHeader( } /** + * @brief Tries to find a file in the include directories + * @return True on success + */ +bool cmQtAutoGenerators::FindInIncludeDirectories( + std::string& file_n, const std::string& searchString) const +{ + for (std::vector::const_iterator iit = + this->MocIncludePaths.begin(); + iit != this->MocIncludePaths.end(); ++iit) { + const std::string fullPath = ((*iit) + '/' + searchString); + if (cmsys::SystemTools::FileExists(fullPath.c_str())) { + file_n = fullPath; + return true; + } + } + return false; +} + +/** * @brief Generates the parent directory of the given file on demand * @return True on success */ diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index dc83703..b5ffff8 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -121,6 +121,8 @@ private: std::string FindMatchingHeader(const std::string& basePath, const std::string& baseName, const std::string& subDir) const; + bool FindInIncludeDirectories(std::string& file_n, + const std::string& searchString) const; // - Target names std::string OriginTargetName; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b636dae9b209b8f8e26bc7a7e579a0e1197dc414 commit b636dae9b209b8f8e26bc7a7e579a0e1197dc414 Author: Sebastian Holtermann AuthorDate: Thu Feb 16 17:53:19 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:45 2017 +0100 Autogen: Synchronize header/source argument names diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 87913a1..dc83703 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -54,19 +54,19 @@ private: bool ParseSourceFile( const std::string& absFilename, - std::map& includedMocs, + std::map& mocsIncluded, std::map >& includedUis, bool relaxed); void SearchHeadersForSourceFile(const std::string& absFilename, - std::set& absHeadersMoc, - std::set& absHeadersUic) const; + std::set& mocHeaderFiles, + std::set& uicHeaderFiles) const; void ParseHeaders( - const std::set& absHeadersMoc, - const std::set& absHeadersUic, - const std::map& includedMocs, - std::map& notIncludedMocs, + const std::set& mocHeaderFiles, + const std::set& uicHeaderFiles, + const std::map& mocsIncluded, + std::map& mocsNotIncluded, std::map >& includedUis); void ParseContentForUic( @@ -75,13 +75,13 @@ private: bool ParseContentForMoc(const std::string& absFilename, const std::string& contentsString, - std::map& includedMocs, + std::map& mocsIncluded, bool relaxed); // - Moc file generation bool MocGenerateAll( - const std::map& includedMocs, - const std::map& notIncludedMocs); + const std::map& mocsIncluded, + const std::map& mocsNotIncluded); bool MocGenerateFile(const std::string& sourceFile, const std::string& mocFileName, const std::string& subDirPrefix); https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4633cbb96fcaee77f0da674c5caa766447406e99 commit 4633cbb96fcaee77f0da674c5caa766447406e99 Author: Sebastian Holtermann AuthorDate: Thu Feb 16 11:10:46 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:45 2017 +0100 Autogen: Split moc include paths on info reading diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 8daf4c1..8db7754 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -311,8 +311,9 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( cmSystemTools::ExpandListArgument( GetConfigDefinition(makefile, "AM_MOC_COMPILE_DEFINITIONS", config), this->MocDefinitions); - this->MocInfoIncludes = - GetConfigDefinition(makefile, "AM_MOC_INCLUDES", config); + cmSystemTools::ExpandListArgument( + GetConfigDefinition(makefile, "AM_MOC_INCLUDES", config), + this->MocIncludePaths); cmSystemTools::ExpandListArgument( makefile->GetSafeDefinition("AM_MOC_OPTIONS"), this->MocOptions); @@ -410,7 +411,7 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile, std::string& str = this->SettingsStringMoc; str += JoinOptionsList(this->MocDefinitions); str += " ~~~ "; - str += this->MocInfoIncludes; + str += JoinOptionsList(this->MocIncludePaths); str += " ~~~ "; str += JoinOptionsList(this->MocOptions); str += " ~~~ "; @@ -512,22 +513,19 @@ void cmQtAutoGenerators::Init(cmMakefile* makefile) std::list mocIncludes; { std::set frameworkPaths; - { - std::vector incPaths; - cmSystemTools::ExpandListArgument(this->MocInfoIncludes, incPaths); - for (std::vector::const_iterator it = incPaths.begin(); - it != incPaths.end(); ++it) { - const std::string& path = *it; - mocIncludes.push_back("-I" + path); - // Extract framework path - if (cmHasLiteralSuffix(path, ".framework/Headers")) { - // Go up twice to get to the framework root - std::vector pathComponents; - cmsys::SystemTools::SplitPath(path, pathComponents); - std::string frameworkPath = cmsys::SystemTools::JoinPath( - pathComponents.begin(), pathComponents.end() - 2); - frameworkPaths.insert(frameworkPath); - } + for (std::vector::const_iterator it = + this->MocIncludePaths.begin(); + it != this->MocIncludePaths.end(); ++it) { + const std::string& path = *it; + mocIncludes.push_back("-I" + path); + // Extract framework path + if (cmHasLiteralSuffix(path, ".framework/Headers")) { + // Go up twice to get to the framework root + std::vector pathComponents; + cmsys::SystemTools::SplitPath(path, pathComponents); + std::string frameworkPath = cmsys::SystemTools::JoinPath( + pathComponents.begin(), pathComponents.end() - 2); + frameworkPaths.insert(frameworkPath); } } // Append framework includes diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 253cc71..87913a1 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -144,10 +144,10 @@ private: std::string SettingsStringUic; std::string SettingsStringRcc; // - Moc - std::string MocInfoIncludes; std::string MocCppFilenameRel; std::string MocCppFilenameAbs; std::vector MocSkipList; + std::vector MocIncludePaths; std::vector MocIncludes; std::vector MocDefinitions; std::vector MocOptions; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a2a7d36b9b978ada6e41294fddba1ccd7332d6f5 commit a2a7d36b9b978ada6e41294fddba1ccd7332d6f5 Author: Sebastian Holtermann AuthorDate: Thu Feb 16 10:31:03 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:44 2017 +0100 Autogen: Loop based macro detection instead of code duplication diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 27b99af..8daf4c1 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -213,9 +213,12 @@ cmQtAutoGenerators::cmQtAutoGenerators() } } + this->MacroFilters[0].first = "Q_OBJECT"; + this->MacroFilters[0].second.compile("[\n][ \t]*Q_OBJECT[^a-zA-Z0-9_]"); + this->MacroFilters[1].first = "Q_GADGET"; + this->MacroFilters[1].second.compile("[\n][ \t]*Q_GADGET[^a-zA-Z0-9_]"); + // Precompile regular expressions - this->RegExpQObject.compile("[\n][ \t]*Q_OBJECT[^a-zA-Z0-9_]"); - this->RegExpQGadget.compile("[\n][ \t]*Q_GADGET[^a-zA-Z0-9_]"); this->RegExpMocInclude.compile( "[\n][ \t]*#[ \t]*include[ \t]+" "[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]"); @@ -631,19 +634,19 @@ bool cmQtAutoGenerators::RunAutogen() * @return True if moc is required */ bool cmQtAutoGenerators::MocRequired(const std::string& text, - std::string& macroName) + std::string* macroName) { - // Run a simple check before an expensive regular expression check - if (strstr(text.c_str(), "Q_OBJECT") != CM_NULLPTR) { - if (this->RegExpQObject.find(text)) { - macroName = "Q_OBJECT"; - return true; - } - } - if (strstr(text.c_str(), "Q_GADGET") != CM_NULLPTR) { - if (this->RegExpQGadget.find(text)) { - macroName = "Q_GADGET"; - return true; + for (unsigned int ii = 0; ii != cmArraySize(this->MacroFilters); ++ii) { + MacroFilter& macroFilter = this->MacroFilters[ii]; + // Run a simple check before an expensive regular expression check + if (text.find(macroFilter.first) != std::string::npos) { + if (macroFilter.second.find(text)) { + // Return macro name on demand + if (macroName != CM_NULLPTR) { + *macroName = macroFilter.first; + } + return true; + } } } return false; @@ -753,7 +756,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename); std::string macroName; - const bool requiresMoc = this->MocRequired(contentsString, macroName); + const bool requiresMoc = this->MocRequired(contentsString, ¯oName); bool ownDotMocIncluded = false; bool ownMocUnderscoreIncluded = false; std::string ownMocUnderscoreFile; @@ -987,8 +990,7 @@ void cmQtAutoGenerators::ParseHeaders( err << "AutoMoc: Checking " << headerName << "\n"; this->LogInfo(err.str()); } - std::string macroName; - if (this->MocRequired(contents, macroName)) { + if (this->MocRequired(contents)) { mocsNotIncluded[headerName] = this->ChecksumedPath(headerName, "moc_", ".cpp"); } diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 11e4e74..253cc71 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -47,7 +47,8 @@ private: bool RunAutogen(); // - Content analysis - bool MocRequired(const std::string& text, std::string& macroName); + bool MocRequired(const std::string& text, + std::string* macroName = CM_NULLPTR); bool MocSkip(const std::string& absFilename) const; bool UicSkip(const std::string& absFilename) const; @@ -161,8 +162,8 @@ private: // - Utility cmFilePathChecksum fpathCheckSum; std::vector HeaderExtensions; - cmsys::RegularExpression RegExpQObject; - cmsys::RegularExpression RegExpQGadget; + typedef std::pair MacroFilter; + MacroFilter MacroFilters[2]; cmsys::RegularExpression RegExpMocInclude; cmsys::RegularExpression RegExpUicInclude; // - Flags https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=50138b2dd140df493aaff2fccd0388322b6eebb8 commit 50138b2dd140df493aaff2fccd0388322b6eebb8 Author: Sebastian Holtermann AuthorDate: Wed Feb 15 20:47:58 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:44 2017 +0100 Autogen: Issue a warning if moc isn't required in strict mode diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index f86a24b..27b99af 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -856,6 +856,15 @@ bool cmQtAutoGenerators::ParseContentForMoc( // Include self fileToMoc = absFilename; ownDotMocIncluded = true; + // Accept but issue a warning if moc isn't required + if (!requiresMoc) { + std::ostringstream err; + err << "AutoMoc: Error: " << absFilename << "\n" + << "The file includes the moc file \"" << incString << "\"" + << ", but does not contain a Q_OBJECT or Q_GADGET " + "macro.\n"; + this->LogWarning(err.str()); + } } else { // Don't allow FOO.moc include other than self in strict mode std::ostringstream err; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=acb159fb817913c936a700cede9bff6383d2b0b8 commit acb159fb817913c936a700cede9bff6383d2b0b8 Author: Sebastian Holtermann AuthorDate: Wed Feb 15 20:36:39 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:44 2017 +0100 Autogen: Error message tweaks diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 7fb7bfb..f86a24b 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -807,7 +807,12 @@ bool cmQtAutoGenerators::ParseContentForMoc( std::string fileToMoc; if (relaxed) { // Mode: Relaxed - if (!requiresMoc || (incBasename != scannedFileBasename)) { + if (requiresMoc && (incBasename == scannedFileBasename)) { + // Include self + fileToMoc = absFilename; + ownDotMocIncluded = true; + } else { + // In relaxed mode try to find a header instead but issue a warning const std::string headerToMoc = this->FindMatchingHeader( scannedFileAbsPath, incBasename, incSubDir); if (!headerToMoc.empty()) { @@ -816,11 +821,10 @@ bool cmQtAutoGenerators::ParseContentForMoc( if (!requiresMoc && (incBasename == scannedFileBasename)) { std::ostringstream err; err << "AutoMoc: Warning: " << absFilename << "\n" - << "The file includes the moc file \"" << incString - << "\", but does not contain a " << macroName - << " macro. Running moc on " - << "\"" << headerToMoc << "\" ! Include \"moc_" - << incBasename + << "The file includes the moc file \"" << incString << "\"" + << ", but does not contain a Q_OBJECT or Q_GADGET macro.\n" + << "Running moc on \"" << headerToMoc << "\"!\n" + << "Include \"moc_" << incBasename << ".cpp\" for a compatibility with " "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; this->LogWarning(err.str()); @@ -828,10 +832,9 @@ bool cmQtAutoGenerators::ParseContentForMoc( std::ostringstream err; err << "AutoMoc: Warning: " << absFilename << "\n" << "The file includes the moc file \"" << incString - << "\" instead of \"moc_" << incBasename - << ".cpp\". Running moc on " - << "\"" << headerToMoc << "\" ! Include \"moc_" - << incBasename + << "\" instead of \"moc_" << incBasename << ".cpp\".\n" + << "Running moc on \"" << headerToMoc << "\"!\n" + << "Include \"moc_" << incBasename << ".cpp\" for compatibility with " "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; this->LogWarning(err.str()); @@ -846,10 +849,6 @@ bool cmQtAutoGenerators::ParseContentForMoc( this->LogError(err.str()); return false; } - } else { - // Include self - fileToMoc = absFilename; - ownDotMocIncluded = true; } } else { // Mode: Strict @@ -891,9 +890,9 @@ bool cmQtAutoGenerators::ParseContentForMoc( << "The file contains a " << macroName << " macro, but does not include " << "\"" << scannedFileBasename << ".moc\", but instead includes " - << "\"" << ownMocUnderscoreFile << "\". Running moc on " - << "\"" << absFilename << "\" ! Better include \"" - << scannedFileBasename + << "\"" << ownMocUnderscoreFile << "\".\n" + << "Running moc on \"" << absFilename << "\"!\n" + << "Better include \"" << scannedFileBasename << ".moc\" for compatibility with " "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; this->LogWarning(err.str()); @@ -907,7 +906,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( err << "AutoMoc: Error: " << absFilename << "\n" << "The file contains a " << macroName << " macro, but does not include " - << "\"" << scannedFileBasename << ".moc\" !\n"; + << "\"" << scannedFileBasename << ".moc\"!\n"; this->LogError(err.str()); return false; } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9fc0cedfcf71a31d7334fd73ffb26410db32b174 commit 9fc0cedfcf71a31d7334fd73ffb26410db32b174 Author: Sebastian Holtermann AuthorDate: Wed Feb 15 19:30:08 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:44 2017 +0100 Autogen: Acquire and store header extensions in Init() diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 129a04e..7fb7bfb 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -245,9 +245,9 @@ bool cmQtAutoGenerators::Run(const std::string& targetDirectory, // Read old settings this->SettingsFileRead(mf.get(), targetDirectory); // Init and run - this->Init(); + this->Init(mf.get()); if (this->QtMajorVersion == "4" || this->QtMajorVersion == "5") { - if (!this->RunAutogen(mf.get())) { + if (!this->RunAutogen()) { return false; } } @@ -487,7 +487,7 @@ bool cmQtAutoGenerators::SettingsFileWrite(const std::string& targetDirectory) return success; } -void cmQtAutoGenerators::Init() +void cmQtAutoGenerators::Init(cmMakefile* makefile) { this->AutogenBuildSubDir = this->AutogenTargetName; this->AutogenBuildSubDir += "/"; @@ -502,6 +502,9 @@ void cmQtAutoGenerators::Init() this->ProjectSourceDir, this->ProjectBinaryDir); + // Acquire header extensions + this->HeaderExtensions = makefile->GetCMakeInstance()->GetHeaderExtensions(); + // Compose moc includes list std::list mocIncludes; { @@ -563,7 +566,7 @@ void cmQtAutoGenerators::Init() mocIncludes.end()); } -bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) +bool cmQtAutoGenerators::RunAutogen() { // the program goes through all .cpp files to see which moc files are // included. It is not really interesting how the moc file is named, but @@ -582,22 +585,17 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) std::set uicHeaderFiles; // Parse sources - { - const std::vector& headerExtensions = - makefile->GetCMakeInstance()->GetHeaderExtensions(); - - for (std::vector::const_iterator it = this->Sources.begin(); - it != this->Sources.end(); ++it) { - const std::string& absFilename = *it; - // Parse source file for MOC/UIC - if (!this->ParseSourceFile(absFilename, headerExtensions, mocsIncluded, - uisIncluded, this->MocRelaxedMode)) { - return false; - } - // Find additional headers - this->SearchHeadersForSourceFile(absFilename, headerExtensions, - mocHeaderFiles, uicHeaderFiles); + for (std::vector::const_iterator it = this->Sources.begin(); + it != this->Sources.end(); ++it) { + const std::string& absFilename = *it; + // Parse source file for MOC/UIC + if (!this->ParseSourceFile(absFilename, mocsIncluded, uisIncluded, + this->MocRelaxedMode)) { + return false; } + // Find additional headers + this->SearchHeadersForSourceFile(absFilename, mocHeaderFiles, + uicHeaderFiles); } // Parse headers @@ -655,7 +653,7 @@ bool cmQtAutoGenerators::MocRequired(const std::string& text, * @brief Tests if the file should be ignored for moc scanning * @return True if the file should be ignored */ -bool cmQtAutoGenerators::MocSkip(const std::string& absFilename) +bool cmQtAutoGenerators::MocSkip(const std::string& absFilename) const { if (this->MocEnabled()) { // Test if the file name is on the skip list @@ -669,7 +667,7 @@ bool cmQtAutoGenerators::MocSkip(const std::string& absFilename) /** * @brief Tests if the file name is in the skip list */ -bool cmQtAutoGenerators::UicSkip(const std::string& absFilename) +bool cmQtAutoGenerators::UicSkip(const std::string& absFilename) const { if (this->UicEnabled()) { // Test if the file name is on the skip list @@ -685,7 +683,6 @@ bool cmQtAutoGenerators::UicSkip(const std::string& absFilename) */ bool cmQtAutoGenerators::ParseSourceFile( const std::string& absFilename, - const std::vector& headerExtensions, std::map& mocsIncluded, std::map >& uisIncluded, bool relaxed) { @@ -699,8 +696,8 @@ bool cmQtAutoGenerators::ParseSourceFile( } else { // Parse source contents for MOC if (success && !this->MocSkip(absFilename)) { - success = this->ParseContentForMoc( - absFilename, contentsString, headerExtensions, mocsIncluded, relaxed); + success = this->ParseContentForMoc(absFilename, contentsString, + mocsIncluded, relaxed); } // Parse source contents for UIC if (success && !this->UicSkip(absFilename)) { @@ -740,7 +737,6 @@ void cmQtAutoGenerators::ParseContentForUic( */ bool cmQtAutoGenerators::ParseContentForMoc( const std::string& absFilename, const std::string& contentsString, - const std::vector& headerExtensions, std::map& mocsIncluded, bool relaxed) { if (this->Verbose) { @@ -788,8 +784,8 @@ bool cmQtAutoGenerators::ParseContentForMoc( // Include: moc_FOO.cxx // Remove the moc_ part const std::string incRealBasename = incBasename.substr(4); - const std::string headerToMoc = FindMatchingHeader( - scannedFileAbsPath, incRealBasename, incSubDir, headerExtensions); + const std::string headerToMoc = this->FindMatchingHeader( + scannedFileAbsPath, incRealBasename, incSubDir); if (!headerToMoc.empty()) { mocsIncluded[headerToMoc] = incString; if (relaxed && (incRealBasename == scannedFileBasename)) { @@ -802,7 +798,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( err << "AutoMoc: Error: " << absFilename << "\n" << "The file includes the moc file \"" << incString << "\", but could not find header \"" << incRealBasename << '{' - << JoinExts(headerExtensions) << "}\"\n"; + << JoinExts(this->HeaderExtensions) << "}\"\n"; this->LogError(err.str()); return false; } @@ -812,8 +808,8 @@ bool cmQtAutoGenerators::ParseContentForMoc( if (relaxed) { // Mode: Relaxed if (!requiresMoc || (incBasename != scannedFileBasename)) { - const std::string headerToMoc = FindMatchingHeader( - scannedFileAbsPath, incBasename, incSubDir, headerExtensions); + const std::string headerToMoc = this->FindMatchingHeader( + scannedFileAbsPath, incBasename, incSubDir); if (!headerToMoc.empty()) { // This is for KDE4 compatibility: fileToMoc = headerToMoc; @@ -921,9 +917,8 @@ bool cmQtAutoGenerators::ParseContentForMoc( } void cmQtAutoGenerators::SearchHeadersForSourceFile( - const std::string& absFilename, - const std::vector& headerExtensions, - std::set& mocHeaderFiles, std::set& uicHeaderFiles) + const std::string& absFilename, std::set& mocHeaderFiles, + std::set& uicHeaderFiles) const { std::string basepaths[2]; { @@ -940,8 +935,8 @@ void cmQtAutoGenerators::SearchHeadersForSourceFile( for (const std::string* bpit = cmArrayBegin(basepaths); bpit != cmArrayEnd(basepaths); ++bpit) { for (std::vector::const_iterator heit = - headerExtensions.begin(); - heit != headerExtensions.end(); ++heit) { + this->HeaderExtensions.begin(); + heit != this->HeaderExtensions.end(); ++heit) { const std::string hname = (*bpit) + (*heit); if (cmsys::SystemTools::FileExists(hname.c_str())) { // Moc headers @@ -1587,12 +1582,12 @@ std::string cmQtAutoGenerators::ChecksumedPath(const std::string& sourceFile, * appending different header extensions * @return True on success */ -bool cmQtAutoGenerators::FindHeader( - std::string& header, const std::string& testBasePath, - const std::vector& headerExtensions) const +bool cmQtAutoGenerators::FindHeader(std::string& header, + const std::string& testBasePath) const { - for (std::vector::const_iterator ext = headerExtensions.begin(); - ext != headerExtensions.end(); ++ext) { + for (std::vector::const_iterator ext = + this->HeaderExtensions.begin(); + ext != this->HeaderExtensions.end(); ++ext) { std::string testFilePath(testBasePath); testFilePath += '.'; testFilePath += (*ext); @@ -1606,17 +1601,16 @@ bool cmQtAutoGenerators::FindHeader( std::string cmQtAutoGenerators::FindMatchingHeader( const std::string& basePath, const std::string& baseName, - const std::string& subDir, - const std::vector& headerExtensions) const + const std::string& subDir) const { std::string header; do { if (!subDir.empty()) { - if (FindHeader(header, basePath + subDir + baseName, headerExtensions)) { + if (this->FindHeader(header, basePath + subDir + baseName)) { break; } } - if (FindHeader(header, basePath + baseName, headerExtensions)) { + if (this->FindHeader(header, basePath + baseName)) { break; } } while (false); diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index fcf0d19..11e4e74 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -43,26 +43,23 @@ private: } // - Init and run - void Init(); - bool RunAutogen(cmMakefile* makefile); + void Init(cmMakefile* makefile); + bool RunAutogen(); // - Content analysis bool MocRequired(const std::string& text, std::string& macroName); - bool MocSkip(const std::string& absFilename); - bool UicSkip(const std::string& absFilename); + bool MocSkip(const std::string& absFilename) const; + bool UicSkip(const std::string& absFilename) const; bool ParseSourceFile( const std::string& absFilename, - const std::vector& headerExtensions, std::map& includedMocs, std::map >& includedUis, bool relaxed); - void SearchHeadersForSourceFile( - const std::string& absFilename, - const std::vector& headerExtensions, - std::set& absHeadersMoc, - std::set& absHeadersUic); + void SearchHeadersForSourceFile(const std::string& absFilename, + std::set& absHeadersMoc, + std::set& absHeadersUic) const; void ParseHeaders( const std::set& absHeadersMoc, @@ -77,7 +74,6 @@ private: bool ParseContentForMoc(const std::string& absFilename, const std::string& contentsString, - const std::vector& headerExtensions, std::map& includedMocs, bool relaxed); @@ -120,12 +116,10 @@ private: const char* baseSuffix) const; bool MakeParentDirectory(const std::string& filename); - bool FindHeader(std::string& header, const std::string& testBasePath, - const std::vector& headerExtensions) const; - std::string FindMatchingHeader( - const std::string& basePath, const std::string& baseName, - const std::string& subDir, - const std::vector& headerExtensions) const; + bool FindHeader(std::string& header, const std::string& testBasePath) const; + std::string FindMatchingHeader(const std::string& basePath, + const std::string& baseName, + const std::string& subDir) const; // - Target names std::string OriginTargetName; @@ -166,6 +160,7 @@ private: std::map > RccInputs; // - Utility cmFilePathChecksum fpathCheckSum; + std::vector HeaderExtensions; cmsys::RegularExpression RegExpQObject; cmsys::RegularExpression RegExpQGadget; cmsys::RegularExpression RegExpMocInclude; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8efe5364780a37b620d29c8ec3777a4406f46934 commit 8efe5364780a37b620d29c8ec3777a4406f46934 Author: Sebastian Holtermann AuthorDate: Wed Feb 15 19:19:37 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:44 2017 +0100 Autogen: Overhaul FindMatchingHeader function diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 0605418..129a04e 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -73,42 +73,6 @@ static void SettingWrite(std::ostream& ostr, const char* key, } } -static std::string FindMatchingHeader( - const std::string& absPath, const std::string& mocSubDir, - const std::string& basename, - const std::vector& headerExtensions) -{ - std::string header; - for (std::vector::const_iterator ext = headerExtensions.begin(); - ext != headerExtensions.end(); ++ext) { - std::string sourceFilePath = absPath + basename + "." + (*ext); - if (cmsys::SystemTools::FileExists(sourceFilePath.c_str())) { - header = sourceFilePath; - break; - } - // Try subdirectory instead - if (!mocSubDir.empty()) { - sourceFilePath = mocSubDir + basename + "." + (*ext); - if (cmsys::SystemTools::FileExists(sourceFilePath.c_str())) { - header = sourceFilePath; - break; - } - } - } - - return header; -} - -static std::string ExtractSubDir(const std::string& absPath, - const std::string& currentMoc) -{ - std::string subDir; - if (currentMoc.find_first_of('/') != std::string::npos) { - subDir = absPath + cmsys::SystemTools::GetFilenamePath(currentMoc) + '/'; - } - return subDir; -} - static bool FileNameIsUnique(const std::string& filePath, const std::map& fileMap) { @@ -806,38 +770,38 @@ bool cmQtAutoGenerators::ParseContentForMoc( if (strstr(contentChars, "moc") != CM_NULLPTR) { // Iterate over all included moc files while (this->RegExpMocInclude.find(contentChars)) { - const std::string currentMoc = this->RegExpMocInclude.match(1); - // Basename of the current moc include - std::string basename = - cmsys::SystemTools::GetFilenameWithoutLastExtension(currentMoc); + const std::string incString = this->RegExpMocInclude.match(1); + // Basename of the moc include + const std::string incBasename = + cmsys::SystemTools::GetFilenameWithoutLastExtension(incString); + std::string incSubDir; + if (incString.find_first_of('/') != std::string::npos) { + incSubDir = cmsys::SystemTools::GetFilenamePath(incString) + '/'; + } // If the moc include is of the moc_foo.cpp style we expect // the Q_OBJECT class declaration in a header file. // If the moc include is of the foo.moc style we need to look for // a Q_OBJECT macro in the current source file, if it contains the // macro we generate the moc file from the source file. - if (cmHasLiteralPrefix(basename, "moc_")) { + if (cmHasLiteralPrefix(incBasename, "moc_")) { // Include: moc_FOO.cxx - // basename should be the part of the moc filename used for - // finding the correct header, so we need to remove the moc_ part - basename = basename.substr(4); - const std::string mocSubDir = - ExtractSubDir(scannedFileAbsPath, currentMoc); + // Remove the moc_ part + const std::string incRealBasename = incBasename.substr(4); const std::string headerToMoc = FindMatchingHeader( - scannedFileAbsPath, mocSubDir, basename, headerExtensions); - + scannedFileAbsPath, incRealBasename, incSubDir, headerExtensions); if (!headerToMoc.empty()) { - mocsIncluded[headerToMoc] = currentMoc; - if (relaxed && (basename == scannedFileBasename)) { + mocsIncluded[headerToMoc] = incString; + if (relaxed && (incRealBasename == scannedFileBasename)) { ownMocUnderscoreIncluded = true; - ownMocUnderscoreFile = currentMoc; + ownMocUnderscoreFile = incString; ownMocHeaderFile = headerToMoc; } } else { std::ostringstream err; err << "AutoMoc: Error: " << absFilename << "\n" - << "The file includes the moc file \"" << currentMoc - << "\", but could not find header \"" << basename << '{' + << "The file includes the moc file \"" << incString + << "\", but could not find header \"" << incRealBasename << '{' << JoinExts(headerExtensions) << "}\"\n"; this->LogError(err.str()); return false; @@ -847,31 +811,31 @@ bool cmQtAutoGenerators::ParseContentForMoc( std::string fileToMoc; if (relaxed) { // Mode: Relaxed - if (!requiresMoc || basename != scannedFileBasename) { - const std::string mocSubDir = - ExtractSubDir(scannedFileAbsPath, currentMoc); + if (!requiresMoc || (incBasename != scannedFileBasename)) { const std::string headerToMoc = FindMatchingHeader( - scannedFileAbsPath, mocSubDir, basename, headerExtensions); + scannedFileAbsPath, incBasename, incSubDir, headerExtensions); if (!headerToMoc.empty()) { // This is for KDE4 compatibility: fileToMoc = headerToMoc; - if (!requiresMoc && basename == scannedFileBasename) { + if (!requiresMoc && (incBasename == scannedFileBasename)) { std::ostringstream err; err << "AutoMoc: Warning: " << absFilename << "\n" - << "The file includes the moc file \"" << currentMoc + << "The file includes the moc file \"" << incString << "\", but does not contain a " << macroName << " macro. Running moc on " - << "\"" << headerToMoc << "\" ! Include \"moc_" << basename + << "\"" << headerToMoc << "\" ! Include \"moc_" + << incBasename << ".cpp\" for a compatibility with " "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; this->LogWarning(err.str()); } else { std::ostringstream err; err << "AutoMoc: Warning: " << absFilename << "\n" - << "The file includes the moc file \"" << currentMoc - << "\" instead of \"moc_" << basename + << "The file includes the moc file \"" << incString + << "\" instead of \"moc_" << incBasename << ".cpp\". Running moc on " - << "\"" << headerToMoc << "\" ! Include \"moc_" << basename + << "\"" << headerToMoc << "\" ! Include \"moc_" + << incBasename << ".cpp\" for compatibility with " "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; this->LogWarning(err.str()); @@ -879,7 +843,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( } else { std::ostringstream err; err << "AutoMoc: Error: " << absFilename << "\n" - << "The file includes the moc file \"" << currentMoc + << "The file includes the moc file \"" << incString << "\", which seems to be the moc file from a different " "source file. CMake also could not find a matching " "header.\n"; @@ -893,7 +857,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( } } else { // Mode: Strict - if (basename == scannedFileBasename) { + if (incBasename == scannedFileBasename) { // Include self fileToMoc = absFilename; ownDotMocIncluded = true; @@ -901,7 +865,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( // Don't allow FOO.moc include other than self in strict mode std::ostringstream err; err << "AutoMoc: Error: " << absFilename << "\n" - << "The file includes the moc file \"" << currentMoc + << "The file includes the moc file \"" << incString << "\", which seems to be the moc file from a different " "source file. This is not supported. Include \"" << scannedFileBasename @@ -911,7 +875,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( } } if (!fileToMoc.empty()) { - mocsIncluded[fileToMoc] = currentMoc; + mocsIncluded[fileToMoc] = incString; } } // Forward content pointer @@ -919,11 +883,11 @@ bool cmQtAutoGenerators::ParseContentForMoc( } } - // In this case, check whether the scanned file itself contains a Q_OBJECT. - // If this is the case, the moc_foo.cpp should probably be generated from - // foo.cpp instead of foo.h, because otherwise it won't build. - // But warn, since this is not how it is supposed to be used. if (requiresMoc && !ownDotMocIncluded) { + // In this case, check whether the scanned file itself contains a Q_OBJECT. + // If this is the case, the moc_foo.cpp should probably be generated from + // foo.cpp instead of foo.h, because otherwise it won't build. + // But warn, since this is not how it is supposed to be used. if (relaxed && ownMocUnderscoreIncluded) { // This is for KDE4 compatibility: std::ostringstream err; @@ -1619,6 +1583,47 @@ std::string cmQtAutoGenerators::ChecksumedPath(const std::string& sourceFile, } /** + * @brief Tries to find the header file to the given file base path by + * appending different header extensions + * @return True on success + */ +bool cmQtAutoGenerators::FindHeader( + std::string& header, const std::string& testBasePath, + const std::vector& headerExtensions) const +{ + for (std::vector::const_iterator ext = headerExtensions.begin(); + ext != headerExtensions.end(); ++ext) { + std::string testFilePath(testBasePath); + testFilePath += '.'; + testFilePath += (*ext); + if (cmsys::SystemTools::FileExists(testFilePath.c_str())) { + header = testFilePath; + return true; + } + } + return false; +} + +std::string cmQtAutoGenerators::FindMatchingHeader( + const std::string& basePath, const std::string& baseName, + const std::string& subDir, + const std::vector& headerExtensions) const +{ + std::string header; + do { + if (!subDir.empty()) { + if (FindHeader(header, basePath + subDir + baseName, headerExtensions)) { + break; + } + } + if (FindHeader(header, basePath + baseName, headerExtensions)) { + break; + } + } while (false); + return header; +} + +/** * @brief Generates the parent directory of the given file on demand * @return True on success */ diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 6eaedaf..fcf0d19 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -120,6 +120,13 @@ private: const char* baseSuffix) const; bool MakeParentDirectory(const std::string& filename); + bool FindHeader(std::string& header, const std::string& testBasePath, + const std::vector& headerExtensions) const; + std::string FindMatchingHeader( + const std::string& basePath, const std::string& baseName, + const std::string& subDir, + const std::vector& headerExtensions) const; + // - Target names std::string OriginTargetName; std::string AutogenTargetName; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=13cc1f905284d00424cb165bb6f06353df3ccb82 commit 13cc1f905284d00424cb165bb6f06353df3ccb82 Author: Sebastian Holtermann AuthorDate: Wed Feb 15 17:36:58 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:44 2017 +0100 Autogen: Don't list all search paths in error message diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index ebe9f28..0605418 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -838,13 +838,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( err << "AutoMoc: Error: " << absFilename << "\n" << "The file includes the moc file \"" << currentMoc << "\", but could not find header \"" << basename << '{' - << JoinExts(headerExtensions) << "}\" "; - if (mocSubDir.empty()) { - err << "in " << scannedFileAbsPath << "\n"; - } else { - err << "neither in " << scannedFileAbsPath << " nor in " - << mocSubDir << "\n"; - } + << JoinExts(headerExtensions) << "}\"\n"; this->LogError(err.str()); return false; } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9d1508caf4faf0835cedd4e7d838fc685b11d92b commit 9d1508caf4faf0835cedd4e7d838fc685b11d92b Author: Sebastian Holtermann AuthorDate: Wed Feb 15 13:43:19 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:44 2017 +0100 Autogen: Indentation fix diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 1453711..ebe9f28 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -607,8 +607,7 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) // may not be included in the moc_compilation.cpp file anymore. OTOH if // there's a header containing Q_OBJECT where no corresponding moc file // is included anywhere a moc_.cpp file is created and included - // in - // the moc_compilation.cpp file. + // in the moc_compilation.cpp file. // key = moc source filepath, value = moc output filepath std::map mocsIncluded; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9a7c167351958027c7139cb712deda58a5858ffc commit 9a7c167351958027c7139cb712deda58a5858ffc Author: Sebastian Holtermann AuthorDate: Wed Feb 15 13:23:27 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:43 2017 +0100 Autogen: Rename moc related variables diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index f2a4174..1453711 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -528,11 +528,10 @@ void cmQtAutoGenerators::Init() this->AutogenBuildSubDir = this->AutogenTargetName; this->AutogenBuildSubDir += "/"; - this->OutMocCppFilenameRel = this->AutogenBuildSubDir; - this->OutMocCppFilenameRel += "moc_compilation.cpp"; + this->MocCppFilenameRel = this->AutogenBuildSubDir; + this->MocCppFilenameRel += "moc_compilation.cpp"; - this->OutMocCppFilenameAbs = - this->CurrentBinaryDir + this->OutMocCppFilenameRel; + this->MocCppFilenameAbs = this->CurrentBinaryDir + this->MocCppFilenameRel; // Init file path checksum generator fpathCheckSum.setupParentDirs(this->CurrentSourceDir, this->CurrentBinaryDir, @@ -1124,12 +1123,12 @@ bool cmQtAutoGenerators::MocGenerateAll( // Check if we even need to update moc_compilation.cpp if (!automocCppChanged) { // compare contents of the moc_compilation.cpp file - const std::string oldContents = ReadAll(this->OutMocCppFilenameAbs); + const std::string oldContents = ReadAll(this->MocCppFilenameAbs); if (oldContents == automocSource) { // nothing changed: don't touch the moc_compilation.cpp file if (this->Verbose) { std::ostringstream err; - err << "AutoMoc: " << this->OutMocCppFilenameRel << " still up to date" + err << "AutoMoc: " << this->MocCppFilenameRel << " still up to date" << std::endl; this->LogInfo(err.str()); } @@ -1138,17 +1137,17 @@ bool cmQtAutoGenerators::MocGenerateAll( } // Actually write moc_compilation.cpp - this->LogBold("Generating MOC compilation " + this->OutMocCppFilenameRel); + this->LogBold("Generating MOC compilation " + this->MocCppFilenameRel); // Make sure the parent directory exists - bool success = this->MakeParentDirectory(this->OutMocCppFilenameAbs); + bool success = this->MakeParentDirectory(this->MocCppFilenameAbs); if (success) { cmsys::ofstream outfile; - outfile.open(this->OutMocCppFilenameAbs.c_str(), std::ios::trunc); + outfile.open(this->MocCppFilenameAbs.c_str(), std::ios::trunc); if (!outfile) { success = false; std::ostringstream err; - err << "AutoMoc: error opening " << this->OutMocCppFilenameAbs << "\n"; + err << "AutoMoc: error opening " << this->MocCppFilenameAbs << "\n"; this->LogError(err.str()); } else { outfile << automocSource; @@ -1156,7 +1155,7 @@ bool cmQtAutoGenerators::MocGenerateAll( if (!outfile.good()) { success = false; std::ostringstream err; - err << "AutoMoc: error writing " << this->OutMocCppFilenameAbs << "\n"; + err << "AutoMoc: error writing " << this->MocCppFilenameAbs << "\n"; this->LogError(err.str()); } } diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 38824e8..6eaedaf 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -142,10 +142,10 @@ private: std::string SettingsStringUic; std::string SettingsStringRcc; // - Moc - std::vector MocSkipList; std::string MocInfoIncludes; - std::string OutMocCppFilenameRel; - std::string OutMocCppFilenameAbs; + std::string MocCppFilenameRel; + std::string MocCppFilenameAbs; + std::vector MocSkipList; std::vector MocIncludes; std::vector MocDefinitions; std::vector MocOptions; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=35f30aef42ec888a26aeb68b4b86cb25c6f20232 commit 35f30aef42ec888a26aeb68b4b86cb25c6f20232 Author: Sebastian Holtermann AuthorDate: Wed Feb 15 12:53:39 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:43 2017 +0100 Autogen: Overhaul moc include list generation diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index a167705..f2a4174 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -539,58 +539,65 @@ void cmQtAutoGenerators::Init() this->ProjectSourceDir, this->ProjectBinaryDir); - std::vector incPaths; - cmSystemTools::ExpandListArgument(this->MocInfoIncludes, incPaths); - - std::set frameworkPaths; - for (std::vector::const_iterator it = incPaths.begin(); - it != incPaths.end(); ++it) { - const std::string& path = *it; - this->MocIncludes.push_back("-I" + path); - if (cmHasLiteralSuffix(path, ".framework/Headers")) { - // Go up twice to get to the framework root - std::vector pathComponents; - cmsys::SystemTools::SplitPath(path, pathComponents); - std::string frameworkPath = cmsys::SystemTools::JoinPath( - pathComponents.begin(), pathComponents.end() - 2); - frameworkPaths.insert(frameworkPath); + // Compose moc includes list + std::list mocIncludes; + { + std::set frameworkPaths; + { + std::vector incPaths; + cmSystemTools::ExpandListArgument(this->MocInfoIncludes, incPaths); + for (std::vector::const_iterator it = incPaths.begin(); + it != incPaths.end(); ++it) { + const std::string& path = *it; + mocIncludes.push_back("-I" + path); + // Extract framework path + if (cmHasLiteralSuffix(path, ".framework/Headers")) { + // Go up twice to get to the framework root + std::vector pathComponents; + cmsys::SystemTools::SplitPath(path, pathComponents); + std::string frameworkPath = cmsys::SystemTools::JoinPath( + pathComponents.begin(), pathComponents.end() - 2); + frameworkPaths.insert(frameworkPath); + } + } + } + // Append framework includes + for (std::set::const_iterator it = frameworkPaths.begin(); + it != frameworkPaths.end(); ++it) { + mocIncludes.push_back("-F"); + mocIncludes.push_back(*it); } } - - for (std::set::const_iterator it = frameworkPaths.begin(); - it != frameworkPaths.end(); ++it) { - this->MocIncludes.push_back("-F"); - this->MocIncludes.push_back(*it); - } - if (this->IncludeProjectDirsBefore) { - const std::string binDir = "-I" + this->ProjectBinaryDir; - const std::string srcDir = "-I" + this->ProjectSourceDir; - - std::list sortedMocIncludes; - std::list::iterator it = this->MocIncludes.begin(); - while (it != this->MocIncludes.end()) { - if (cmsys::SystemTools::StringStartsWith(*it, binDir.c_str())) { - sortedMocIncludes.push_back(*it); - it = this->MocIncludes.erase(it); - } else { - ++it; - } - } - it = this->MocIncludes.begin(); - while (it != this->MocIncludes.end()) { - if (cmsys::SystemTools::StringStartsWith(*it, srcDir.c_str())) { - sortedMocIncludes.push_back(*it); - it = this->MocIncludes.erase(it); - } else { - ++it; + // Extract project includes + std::vector mocSortedIncludes; + { + std::vector movePaths; + movePaths.push_back("-I" + this->ProjectBinaryDir); + movePaths.push_back("-I" + this->ProjectSourceDir); + + for (std::vector::const_iterator mpit = movePaths.begin(); + mpit != movePaths.end(); ++mpit) { + std::list::iterator it = mocIncludes.begin(); + while (it != mocIncludes.end()) { + const std::string& path = *it; + if (cmsys::SystemTools::StringStartsWith(path, mpit->c_str())) { + mocSortedIncludes.push_back(path); + it = mocIncludes.erase(it); + } else { + ++it; + } + } } } - sortedMocIncludes.insert(sortedMocIncludes.end(), - this->MocIncludes.begin(), - this->MocIncludes.end()); - this->MocIncludes = sortedMocIncludes; - } + // Place extracted includes at the begin + this->MocIncludes.insert(this->MocIncludes.end(), + mocSortedIncludes.begin(), + mocSortedIncludes.end()); + } + // Append remaining includes + this->MocIncludes.insert(this->MocIncludes.end(), mocIncludes.begin(), + mocIncludes.end()); } bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index e60320b..38824e8 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -146,7 +146,7 @@ private: std::string MocInfoIncludes; std::string OutMocCppFilenameRel; std::string OutMocCppFilenameAbs; - std::list MocIncludes; + std::vector MocIncludes; std::vector MocDefinitions; std::vector MocOptions; // - Uic https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=074534a56d4d6146c2389fd256299197e5bad027 commit 074534a56d4d6146c2389fd256299197e5bad027 Author: Sebastian Holtermann AuthorDate: Wed Feb 15 11:28:27 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:43 2017 +0100 Autogen: Inline string generation diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 842461a..a167705 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -1131,11 +1131,8 @@ bool cmQtAutoGenerators::MocGenerateAll( } // Actually write moc_compilation.cpp - { - std::string msg = "Generating MOC compilation "; - msg += this->OutMocCppFilenameRel; - this->LogBold(msg); - } + this->LogBold("Generating MOC compilation " + this->OutMocCppFilenameRel); + // Make sure the parent directory exists bool success = this->MakeParentDirectory(this->OutMocCppFilenameAbs); if (success) { https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a51f1a91d9733c596113f799154ef45d647e7764 commit a51f1a91d9733c596113f799154ef45d647e7764 Author: Sebastian Holtermann AuthorDate: Wed Feb 15 11:17:12 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:43 2017 +0100 Autogen: Synchronize variable names diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index fcaf43d..842461a 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -605,12 +605,12 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) // the moc_compilation.cpp file. // key = moc source filepath, value = moc output filepath - std::map includedMocs; - std::map notIncludedMocs; - std::map > includedUis; + std::map mocsIncluded; + std::map mocsNotIncluded; + std::map > uisIncluded; // collects all headers which may need to be mocced - std::set headerFilesMoc; - std::set headerFilesUic; + std::set mocHeaderFiles; + std::set uicHeaderFiles; // Parse sources { @@ -621,13 +621,13 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) it != this->Sources.end(); ++it) { const std::string& absFilename = *it; // Parse source file for MOC/UIC - if (!this->ParseSourceFile(absFilename, headerExtensions, includedMocs, - includedUis, this->MocRelaxedMode)) { + if (!this->ParseSourceFile(absFilename, headerExtensions, mocsIncluded, + uisIncluded, this->MocRelaxedMode)) { return false; } // Find additional headers this->SearchHeadersForSourceFile(absFilename, headerExtensions, - headerFilesMoc, headerFilesUic); + mocHeaderFiles, uicHeaderFiles); } } @@ -636,20 +636,20 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) it != this->Headers.end(); ++it) { const std::string& headerName = *it; if (!this->MocSkip(headerName)) { - headerFilesMoc.insert(headerName); + mocHeaderFiles.insert(headerName); } if (!this->UicSkip(headerName)) { - headerFilesUic.insert(headerName); + uicHeaderFiles.insert(headerName); } } - this->ParseHeaders(headerFilesMoc, headerFilesUic, includedMocs, - notIncludedMocs, includedUis); + this->ParseHeaders(mocHeaderFiles, uicHeaderFiles, mocsIncluded, + mocsNotIncluded, uisIncluded); // Generate files - if (!this->MocGenerateAll(includedMocs, notIncludedMocs)) { + if (!this->MocGenerateAll(mocsIncluded, mocsNotIncluded)) { return false; } - if (!this->UicGenerateAll(includedUis)) { + if (!this->UicGenerateAll(uisIncluded)) { return false; } if (!this->RccGenerateAll()) { @@ -717,8 +717,8 @@ bool cmQtAutoGenerators::UicSkip(const std::string& absFilename) bool cmQtAutoGenerators::ParseSourceFile( const std::string& absFilename, const std::vector& headerExtensions, - std::map& includedMocs, - std::map >& includedUis, bool relaxed) + std::map& mocsIncluded, + std::map >& uisIncluded, bool relaxed) { bool success = true; const std::string contentsString = ReadAll(absFilename); @@ -731,11 +731,11 @@ bool cmQtAutoGenerators::ParseSourceFile( // Parse source contents for MOC if (success && !this->MocSkip(absFilename)) { success = this->ParseContentForMoc( - absFilename, contentsString, headerExtensions, includedMocs, relaxed); + absFilename, contentsString, headerExtensions, mocsIncluded, relaxed); } // Parse source contents for UIC if (success && !this->UicSkip(absFilename)) { - this->ParseContentForUic(absFilename, contentsString, includedUis); + this->ParseContentForUic(absFilename, contentsString, uisIncluded); } } return success; @@ -743,7 +743,7 @@ bool cmQtAutoGenerators::ParseSourceFile( void cmQtAutoGenerators::ParseContentForUic( const std::string& absFilename, const std::string& contentsString, - std::map >& includedUis) + std::map >& uisIncluded) { if (this->Verbose) { std::ostringstream err; @@ -760,7 +760,7 @@ void cmQtAutoGenerators::ParseContentForUic( cmsys::SystemTools::GetFilenameWithoutLastExtension(currentUi); // basename should be the part of the ui filename used for // finding the correct header, so we need to remove the ui_ part - includedUis[realName].push_back(basename.substr(3)); + uisIncluded[realName].push_back(basename.substr(3)); contentChars += this->RegExpUicInclude.end(); } } @@ -772,7 +772,7 @@ void cmQtAutoGenerators::ParseContentForUic( bool cmQtAutoGenerators::ParseContentForMoc( const std::string& absFilename, const std::string& contentsString, const std::vector& headerExtensions, - std::map& includedMocs, bool relaxed) + std::map& mocsIncluded, bool relaxed) { if (this->Verbose) { std::ostringstream err; @@ -822,7 +822,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( scannedFileAbsPath, mocSubDir, basename, headerExtensions); if (!headerToMoc.empty()) { - includedMocs[headerToMoc] = currentMoc; + mocsIncluded[headerToMoc] = currentMoc; if (relaxed && (basename == scannedFileBasename)) { ownMocUnderscoreIncluded = true; ownMocUnderscoreFile = currentMoc; @@ -912,7 +912,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( } } if (!fileToMoc.empty()) { - includedMocs[fileToMoc] = currentMoc; + mocsIncluded[fileToMoc] = currentMoc; } } // Forward content pointer @@ -940,8 +940,8 @@ bool cmQtAutoGenerators::ParseContentForMoc( this->LogWarning(err.str()); // Use scanned source file instead of scanned header file as moc source - includedMocs[absFilename] = ownMocUnderscoreFile; - includedMocs.erase(ownMocHeaderFile); + mocsIncluded[absFilename] = ownMocUnderscoreFile; + mocsIncluded.erase(ownMocHeaderFile); } else { // Otherwise always error out since it will not compile: std::ostringstream err; @@ -960,7 +960,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( void cmQtAutoGenerators::SearchHeadersForSourceFile( const std::string& absFilename, const std::vector& headerExtensions, - std::set& absHeadersMoc, std::set& absHeadersUic) + std::set& mocHeaderFiles, std::set& uicHeaderFiles) { std::string basepaths[2]; { @@ -983,11 +983,11 @@ void cmQtAutoGenerators::SearchHeadersForSourceFile( if (cmsys::SystemTools::FileExists(hname.c_str())) { // Moc headers if (!this->MocSkip(absFilename) && !this->MocSkip(hname)) { - absHeadersMoc.insert(hname); + mocHeaderFiles.insert(hname); } // Uic headers if (!this->UicSkip(absFilename) && !this->UicSkip(hname)) { - absHeadersUic.insert(hname); + uicHeaderFiles.insert(hname); } break; } @@ -996,16 +996,16 @@ void cmQtAutoGenerators::SearchHeadersForSourceFile( } void cmQtAutoGenerators::ParseHeaders( - const std::set& absHeadersMoc, - const std::set& absHeadersUic, - const std::map& includedMocs, - std::map& notIncludedMocs, - std::map >& includedUis) + const std::set& mocHeaderFiles, + const std::set& uicHeaderFiles, + const std::map& mocsIncluded, + std::map& mocsNotIncluded, + std::map >& uisIncluded) { // Merged header files list to read files only once std::set headerFiles; - headerFiles.insert(absHeadersMoc.begin(), absHeadersMoc.end()); - headerFiles.insert(absHeadersUic.begin(), absHeadersUic.end()); + headerFiles.insert(mocHeaderFiles.begin(), mocHeaderFiles.end()); + headerFiles.insert(uicHeaderFiles.begin(), uicHeaderFiles.end()); for (std::set::const_iterator hIt = headerFiles.begin(); hIt != headerFiles.end(); ++hIt) { @@ -1013,8 +1013,8 @@ void cmQtAutoGenerators::ParseHeaders( const std::string contents = ReadAll(headerName); // Parse header content for MOC - if ((absHeadersMoc.find(headerName) != absHeadersMoc.end()) && - (includedMocs.find(headerName) == includedMocs.end())) { + if ((mocHeaderFiles.find(headerName) != mocHeaderFiles.end()) && + (mocsIncluded.find(headerName) == mocsIncluded.end())) { // Log if (this->Verbose) { std::ostringstream err; @@ -1023,21 +1023,21 @@ void cmQtAutoGenerators::ParseHeaders( } std::string macroName; if (this->MocRequired(contents, macroName)) { - notIncludedMocs[headerName] = + mocsNotIncluded[headerName] = this->ChecksumedPath(headerName, "moc_", ".cpp"); } } // Parse header content for UIC - if (absHeadersUic.find(headerName) != absHeadersUic.end()) { - this->ParseContentForUic(headerName, contents, includedUis); + if (uicHeaderFiles.find(headerName) != uicHeaderFiles.end()) { + this->ParseContentForUic(headerName, contents, uisIncluded); } } } bool cmQtAutoGenerators::MocGenerateAll( - const std::map& includedMocs, - const std::map& notIncludedMocs) + const std::map& mocsIncluded, + const std::map& mocsNotIncluded) { if (!this->MocEnabled()) { return true; @@ -1047,8 +1047,8 @@ bool cmQtAutoGenerators::MocGenerateAll( { std::multimap collisions; // Test merged map of included and notIncluded - std::map mergedMocs(includedMocs); - mergedMocs.insert(notIncludedMocs.begin(), notIncludedMocs.end()); + std::map mergedMocs(mocsIncluded); + mergedMocs.insert(mocsNotIncluded.begin(), mocsNotIncluded.end()); if (this->NameCollisionTest(mergedMocs, collisions)) { std::ostringstream err; err << "AutoMoc: Error: " @@ -1067,8 +1067,8 @@ bool cmQtAutoGenerators::MocGenerateAll( { const std::string subDirPrefix = "include/"; for (std::map::const_iterator it = - includedMocs.begin(); - it != includedMocs.end(); ++it) { + mocsIncluded.begin(); + it != mocsIncluded.end(); ++it) { if (!this->MocGenerateFile(it->first, it->second, subDirPrefix)) { if (this->RunMocFailed) { return false; @@ -1082,8 +1082,8 @@ bool cmQtAutoGenerators::MocGenerateAll( { const std::string subDirPrefix; for (std::map::const_iterator it = - notIncludedMocs.begin(); - it != notIncludedMocs.end(); ++it) { + mocsNotIncluded.begin(); + it != mocsNotIncluded.end(); ++it) { if (this->MocGenerateFile(it->first, it->second, subDirPrefix)) { automocCppChanged = true; } else { @@ -1099,14 +1099,14 @@ bool cmQtAutoGenerators::MocGenerateAll( { std::ostringstream outStream; outStream << "/* This file is autogenerated, do not edit*/\n"; - if (notIncludedMocs.empty()) { + if (mocsNotIncluded.empty()) { // Dummy content outStream << "enum some_compilers { need_more_than_nothing };\n"; } else { // Valid content for (std::map::const_iterator it = - notIncludedMocs.begin(); - it != notIncludedMocs.end(); ++it) { + mocsNotIncluded.begin(); + it != mocsNotIncluded.end(); ++it) { outStream << "#include \"" << it->second << "\"\n"; } } @@ -1239,7 +1239,7 @@ bool cmQtAutoGenerators::MocGenerateFile(const std::string& sourceFile, } bool cmQtAutoGenerators::UicGenerateAll( - const std::map >& includedUis) + const std::map >& uisIncluded) { if (!this->UicEnabled()) { return true; @@ -1249,8 +1249,8 @@ bool cmQtAutoGenerators::UicGenerateAll( std::map > uiGenMap; std::map testMap; for (std::map >::const_iterator it = - includedUis.begin(); - it != includedUis.end(); ++it) { + uisIncluded.begin(); + it != uisIncluded.end(); ++it) { // source file path std::string sourcePath = cmsys::SystemTools::GetFilenamePath(it->first); sourcePath += '/'; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b2063fd70fa6955acb2b9f02507097d03e2011a7 commit b2063fd70fa6955acb2b9f02507097d03e2011a7 Author: Sebastian Holtermann AuthorDate: Wed Feb 15 11:01:31 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:43 2017 +0100 Autogen: Move method declarations; Remove comments diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 6896ba4..fcaf43d 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -688,7 +688,6 @@ bool cmQtAutoGenerators::MocRequired(const std::string& text, */ bool cmQtAutoGenerators::MocSkip(const std::string& absFilename) { - // Test if moc scanning is enabled if (this->MocEnabled()) { // Test if the file name is on the skip list if (!ListContains(this->MocSkipList, absFilename)) { @@ -703,7 +702,6 @@ bool cmQtAutoGenerators::MocSkip(const std::string& absFilename) */ bool cmQtAutoGenerators::UicSkip(const std::string& absFilename) { - // Test if uic scanning is enabled if (this->UicEnabled()) { // Test if the file name is on the skip list if (!ListContains(this->UicSkipList, absFilename)) { @@ -747,7 +745,6 @@ void cmQtAutoGenerators::ParseContentForUic( const std::string& absFilename, const std::string& contentsString, std::map >& includedUis) { - // Process if (this->Verbose) { std::ostringstream err; err << "AutoUic: Checking " << absFilename << "\n"; @@ -777,7 +774,6 @@ bool cmQtAutoGenerators::ParseContentForMoc( const std::vector& headerExtensions, std::map& includedMocs, bool relaxed) { - // Process if (this->Verbose) { std::ostringstream err; err << "AutoMoc: Checking " << absFilename << "\n"; @@ -1019,7 +1015,7 @@ void cmQtAutoGenerators::ParseHeaders( // Parse header content for MOC if ((absHeadersMoc.find(headerName) != absHeadersMoc.end()) && (includedMocs.find(headerName) == includedMocs.end())) { - // Process + // Log if (this->Verbose) { std::ostringstream err; err << "AutoMoc: Checking " << headerName << "\n"; diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index f14c7a7..e60320b 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -27,11 +27,21 @@ private: const std::string& targetDirectory, const std::string& config); + bool MocEnabled() const { return !this->MocExecutable.empty(); } + bool UicEnabled() const { return !this->UicExecutable.empty(); } + bool RccEnabled() const { return !this->RccExecutable.empty(); } + // - Settings file void SettingsFileRead(cmMakefile* makefile, const std::string& targetDirectory); bool SettingsFileWrite(const std::string& targetDirectory); + bool GenerateAllAny() const + { + return (this->GenerateAllMoc || this->GenerateAllRcc || + this->GenerateAllUic); + } + // - Init and run void Init(); bool RunAutogen(cmMakefile* makefile); @@ -110,16 +120,6 @@ private: const char* baseSuffix) const; bool MakeParentDirectory(const std::string& filename); - bool MocEnabled() const { return !this->MocExecutable.empty(); } - bool UicEnabled() const { return !this->UicExecutable.empty(); } - bool RccEnabled() const { return !this->RccExecutable.empty(); } - - bool GenerateAllAny() const - { - return (this->GenerateAllMoc || this->GenerateAllRcc || - this->GenerateAllUic); - } - // - Target names std::string OriginTargetName; std::string AutogenTargetName; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=10beb4a0345f673feaeec798d452a48797c6820a commit 10beb4a0345f673feaeec798d452a48797c6820a Author: Sebastian Holtermann AuthorDate: Wed Feb 15 10:56:44 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:43 2017 +0100 Autogen: Rename SkipFoo variables/methods to FooSkip diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 56c09f8..6896ba4 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -340,7 +340,7 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( // - Moc cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_SKIP_MOC"), - this->SkipMoc); + this->MocSkipList); cmSystemTools::ExpandListArgument( GetConfigDefinition(makefile, "AM_MOC_COMPILE_DEFINITIONS", config), this->MocDefinitions); @@ -351,7 +351,7 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( // - Uic cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_SKIP_UIC"), - this->SkipUic); + this->UicSkipList); cmSystemTools::ExpandListArgument( GetConfigDefinition(makefile, "AM_UIC_TARGET_OPTIONS", config), this->UicTargetOptions); @@ -635,10 +635,10 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) for (std::vector::const_iterator it = this->Headers.begin(); it != this->Headers.end(); ++it) { const std::string& headerName = *it; - if (!this->MocSkipTest(headerName)) { + if (!this->MocSkip(headerName)) { headerFilesMoc.insert(headerName); } - if (!this->UicSkipTest(headerName)) { + if (!this->UicSkip(headerName)) { headerFilesUic.insert(headerName); } } @@ -686,12 +686,12 @@ bool cmQtAutoGenerators::MocRequired(const std::string& text, * @brief Tests if the file should be ignored for moc scanning * @return True if the file should be ignored */ -bool cmQtAutoGenerators::MocSkipTest(const std::string& absFilename) +bool cmQtAutoGenerators::MocSkip(const std::string& absFilename) { // Test if moc scanning is enabled if (this->MocEnabled()) { // Test if the file name is on the skip list - if (!ListContains(this->SkipMoc, absFilename)) { + if (!ListContains(this->MocSkipList, absFilename)) { return false; } } @@ -701,12 +701,12 @@ bool cmQtAutoGenerators::MocSkipTest(const std::string& absFilename) /** * @brief Tests if the file name is in the skip list */ -bool cmQtAutoGenerators::UicSkipTest(const std::string& absFilename) +bool cmQtAutoGenerators::UicSkip(const std::string& absFilename) { // Test if uic scanning is enabled if (this->UicEnabled()) { // Test if the file name is on the skip list - if (!ListContains(this->SkipUic, absFilename)) { + if (!ListContains(this->UicSkipList, absFilename)) { return false; } } @@ -731,12 +731,12 @@ bool cmQtAutoGenerators::ParseSourceFile( this->LogWarning(err.str()); } else { // Parse source contents for MOC - if (success && !this->MocSkipTest(absFilename)) { + if (success && !this->MocSkip(absFilename)) { success = this->ParseContentForMoc( absFilename, contentsString, headerExtensions, includedMocs, relaxed); } // Parse source contents for UIC - if (success && !this->UicSkipTest(absFilename)) { + if (success && !this->UicSkip(absFilename)) { this->ParseContentForUic(absFilename, contentsString, includedUis); } } @@ -986,11 +986,11 @@ void cmQtAutoGenerators::SearchHeadersForSourceFile( const std::string hname = (*bpit) + (*heit); if (cmsys::SystemTools::FileExists(hname.c_str())) { // Moc headers - if (!this->MocSkipTest(absFilename) && !this->MocSkipTest(hname)) { + if (!this->MocSkip(absFilename) && !this->MocSkip(hname)) { absHeadersMoc.insert(hname); } // Uic headers - if (!this->UicSkipTest(absFilename) && !this->UicSkipTest(hname)) { + if (!this->UicSkip(absFilename) && !this->UicSkip(hname)) { absHeadersUic.insert(hname); } break; diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index ec9afef..f14c7a7 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -38,8 +38,8 @@ private: // - Content analysis bool MocRequired(const std::string& text, std::string& macroName); - bool MocSkipTest(const std::string& absFilename); - bool UicSkipTest(const std::string& absFilename); + bool MocSkip(const std::string& absFilename); + bool UicSkip(const std::string& absFilename); bool ParseSourceFile( const std::string& absFilename, @@ -142,7 +142,7 @@ private: std::string SettingsStringUic; std::string SettingsStringRcc; // - Moc - std::vector SkipMoc; + std::vector MocSkipList; std::string MocInfoIncludes; std::string OutMocCppFilenameRel; std::string OutMocCppFilenameAbs; @@ -150,7 +150,7 @@ private: std::vector MocDefinitions; std::vector MocOptions; // - Uic - std::vector SkipUic; + std::vector UicSkipList; std::vector UicTargetOptions; std::map UicOptions; // - Rcc https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f37f1a647d5aba4de5903a3a3dc7700be55c99ec commit f37f1a647d5aba4de5903a3a3dc7700be55c99ec Author: Sebastian Holtermann AuthorDate: Wed Feb 15 10:47:54 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:43 2017 +0100 Autogen: Split moc options info string immediately diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index ab9ca2c..56c09f8 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -154,13 +154,19 @@ static bool ListContains(const std::vector& list, return (std::find(list.begin(), list.end(), entry) != list.end()); } -static std::string JoinOptions(const std::map& opts) +static std::string JoinOptionsList(const std::vector& opts) +{ + return cmOutputConverter::EscapeForCMake(cmJoin(opts, ";")); +} + +static std::string JoinOptionsMap( + const std::map& opts) { std::string result; for (std::map::const_iterator it = opts.begin(); it != opts.end(); ++it) { if (it != opts.begin()) { - result += "%%%"; + result += "@list_sep@"; } result += it->first; result += "==="; @@ -340,7 +346,8 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( this->MocDefinitions); this->MocInfoIncludes = GetConfigDefinition(makefile, "AM_MOC_INCLUDES", config); - this->MocInfoOptions = makefile->GetSafeDefinition("AM_MOC_OPTIONS"); + cmSystemTools::ExpandListArgument( + makefile->GetSafeDefinition("AM_MOC_OPTIONS"), this->MocOptions); // - Uic cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_SKIP_UIC"), @@ -434,26 +441,25 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile, // Compose current settings strings if (this->MocEnabled()) { std::string& str = this->SettingsStringMoc; - str += - cmOutputConverter::EscapeForCMake(cmJoin(this->MocDefinitions, ";")); + str += JoinOptionsList(this->MocDefinitions); str += " ~~~ "; str += this->MocInfoIncludes; str += " ~~~ "; - str += this->MocInfoOptions; + str += JoinOptionsList(this->MocOptions); str += " ~~~ "; str += this->IncludeProjectDirsBefore ? "TRUE" : "FALSE"; str += " ~~~ "; } if (this->UicEnabled()) { std::string& str = this->SettingsStringUic; - str += cmJoin(this->UicTargetOptions, "@osep@"); + str += JoinOptionsList(this->UicTargetOptions); str += " ~~~ "; - str += JoinOptions(this->UicOptions); + str += JoinOptionsMap(this->UicOptions); str += " ~~~ "; } if (this->RccEnabled()) { std::string& str = this->SettingsStringRcc; - str += JoinOptions(this->RccOptions); + str += JoinOptionsMap(this->RccOptions); str += " ~~~ "; } @@ -533,8 +539,6 @@ void cmQtAutoGenerators::Init() this->ProjectSourceDir, this->ProjectBinaryDir); - cmSystemTools::ExpandListArgument(this->MocInfoOptions, this->MocOptions); - std::vector incPaths; cmSystemTools::ExpandListArgument(this->MocInfoIncludes, incPaths); diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index c9c31fc..ec9afef 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -144,7 +144,6 @@ private: // - Moc std::vector SkipMoc; std::string MocInfoIncludes; - std::string MocInfoOptions; std::string OutMocCppFilenameRel; std::string OutMocCppFilenameAbs; std::list MocIncludes; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=5bb997c24a7ba8b6f252cc7914858f5c12a543b6 commit 5bb997c24a7ba8b6f252cc7914858f5c12a543b6 Author: Sebastian Holtermann AuthorDate: Wed Feb 15 10:36:51 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:42 2017 +0100 Autogen: Split moc compile options info string immediately diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 002e95b..ab9ca2c 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -335,8 +335,9 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( // - Moc cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_SKIP_MOC"), this->SkipMoc); - this->MocInfoCompileDefinitions = - GetConfigDefinition(makefile, "AM_MOC_COMPILE_DEFINITIONS", config); + cmSystemTools::ExpandListArgument( + GetConfigDefinition(makefile, "AM_MOC_COMPILE_DEFINITIONS", config), + this->MocDefinitions); this->MocInfoIncludes = GetConfigDefinition(makefile, "AM_MOC_INCLUDES", config); this->MocInfoOptions = makefile->GetSafeDefinition("AM_MOC_OPTIONS"); @@ -433,7 +434,8 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile, // Compose current settings strings if (this->MocEnabled()) { std::string& str = this->SettingsStringMoc; - str += this->MocInfoCompileDefinitions; + str += + cmOutputConverter::EscapeForCMake(cmJoin(this->MocDefinitions, ";")); str += " ~~~ "; str += this->MocInfoIncludes; str += " ~~~ "; @@ -531,13 +533,6 @@ void cmQtAutoGenerators::Init() this->ProjectSourceDir, this->ProjectBinaryDir); - std::vector cdefList; - cmSystemTools::ExpandListArgument(this->MocInfoCompileDefinitions, cdefList); - for (std::vector::const_iterator it = cdefList.begin(); - it != cdefList.end(); ++it) { - this->MocDefinitions.push_back("-D" + (*it)); - } - cmSystemTools::ExpandListArgument(this->MocInfoOptions, this->MocOptions); std::vector incPaths; @@ -1194,8 +1189,12 @@ bool cmQtAutoGenerators::MocGenerateFile(const std::string& sourceFile, cmd.push_back(this->MocExecutable); cmd.insert(cmd.end(), this->MocIncludes.begin(), this->MocIncludes.end()); - cmd.insert(cmd.end(), this->MocDefinitions.begin(), - this->MocDefinitions.end()); + // Add definitions + for (std::vector::const_iterator it = + this->MocDefinitions.begin(); + it != this->MocDefinitions.end(); ++it) { + cmd.push_back("-D" + (*it)); + } cmd.insert(cmd.end(), this->MocOptions.begin(), this->MocOptions.end()); #ifdef _WIN32 cmd.push_back("-DWIN32"); diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index b9c372e..c9c31fc 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -143,13 +143,12 @@ private: std::string SettingsStringRcc; // - Moc std::vector SkipMoc; - std::string MocInfoCompileDefinitions; std::string MocInfoIncludes; std::string MocInfoOptions; std::string OutMocCppFilenameRel; std::string OutMocCppFilenameAbs; std::list MocIncludes; - std::list MocDefinitions; + std::vector MocDefinitions; std::vector MocOptions; // - Uic std::vector SkipUic; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a9e3c903b6f74d181c76d1a2014a3af2babe6e41 commit a9e3c903b6f74d181c76d1a2014a3af2babe6e41 Author: Sebastian Holtermann AuthorDate: Wed Feb 15 10:22:29 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:42 2017 +0100 Autogen: Rename variables read from info file diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 99f5ef7..002e95b 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -335,11 +335,11 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( // - Moc cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_SKIP_MOC"), this->SkipMoc); - this->MocCompileDefinitionsStr = + this->MocInfoCompileDefinitions = GetConfigDefinition(makefile, "AM_MOC_COMPILE_DEFINITIONS", config); - this->MocIncludesStr = + this->MocInfoIncludes = GetConfigDefinition(makefile, "AM_MOC_INCLUDES", config); - this->MocOptionsStr = makefile->GetSafeDefinition("AM_MOC_OPTIONS"); + this->MocInfoOptions = makefile->GetSafeDefinition("AM_MOC_OPTIONS"); // - Uic cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_SKIP_UIC"), @@ -433,11 +433,11 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile, // Compose current settings strings if (this->MocEnabled()) { std::string& str = this->SettingsStringMoc; - str += this->MocCompileDefinitionsStr; + str += this->MocInfoCompileDefinitions; str += " ~~~ "; - str += this->MocIncludesStr; + str += this->MocInfoIncludes; str += " ~~~ "; - str += this->MocOptionsStr; + str += this->MocInfoOptions; str += " ~~~ "; str += this->IncludeProjectDirsBefore ? "TRUE" : "FALSE"; str += " ~~~ "; @@ -532,16 +532,16 @@ void cmQtAutoGenerators::Init() this->ProjectBinaryDir); std::vector cdefList; - cmSystemTools::ExpandListArgument(this->MocCompileDefinitionsStr, cdefList); + cmSystemTools::ExpandListArgument(this->MocInfoCompileDefinitions, cdefList); for (std::vector::const_iterator it = cdefList.begin(); it != cdefList.end(); ++it) { this->MocDefinitions.push_back("-D" + (*it)); } - cmSystemTools::ExpandListArgument(this->MocOptionsStr, this->MocOptions); + cmSystemTools::ExpandListArgument(this->MocInfoOptions, this->MocOptions); std::vector incPaths; - cmSystemTools::ExpandListArgument(this->MocIncludesStr, incPaths); + cmSystemTools::ExpandListArgument(this->MocInfoIncludes, incPaths); std::set frameworkPaths; for (std::vector::const_iterator it = incPaths.begin(); diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 78d0314..b9c372e 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -143,9 +143,9 @@ private: std::string SettingsStringRcc; // - Moc std::vector SkipMoc; - std::string MocCompileDefinitionsStr; - std::string MocIncludesStr; - std::string MocOptionsStr; + std::string MocInfoCompileDefinitions; + std::string MocInfoIncludes; + std::string MocInfoOptions; std::string OutMocCppFilenameRel; std::string OutMocCppFilenameAbs; std::list MocIncludes; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=2f3ecd4ea9518b2a110b995fe9ac171f026ccad5 commit 2f3ecd4ea9518b2a110b995fe9ac171f026ccad5 Author: Sebastian Holtermann AuthorDate: Wed Feb 15 10:18:17 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:42 2017 +0100 Autogen: Inline settings string generation methods diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index d3fbd02..99f5ef7 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -427,51 +427,33 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( return true; } -std::string cmQtAutoGenerators::SettingsStringGenMoc() const +void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile, + const std::string& targetDirectory) { - std::string res; + // Compose current settings strings if (this->MocEnabled()) { - res += this->MocCompileDefinitionsStr; - res += " ~~~ "; - res += this->MocIncludesStr; - res += " ~~~ "; - res += this->MocOptionsStr; - res += " ~~~ "; - res += this->IncludeProjectDirsBefore ? "TRUE" : "FALSE"; - res += " ~~~ "; + std::string& str = this->SettingsStringMoc; + str += this->MocCompileDefinitionsStr; + str += " ~~~ "; + str += this->MocIncludesStr; + str += " ~~~ "; + str += this->MocOptionsStr; + str += " ~~~ "; + str += this->IncludeProjectDirsBefore ? "TRUE" : "FALSE"; + str += " ~~~ "; } - return res; -} - -std::string cmQtAutoGenerators::SettingsStringGenUic() const -{ - std::string res; if (this->UicEnabled()) { - res += cmJoin(this->UicTargetOptions, "@osep@"); - res += " ~~~ "; - res += JoinOptions(this->UicOptions); - res += " ~~~ "; + std::string& str = this->SettingsStringUic; + str += cmJoin(this->UicTargetOptions, "@osep@"); + str += " ~~~ "; + str += JoinOptions(this->UicOptions); + str += " ~~~ "; } - return res; -} - -std::string cmQtAutoGenerators::SettingsStringGenRcc() const -{ - std::string res; if (this->RccEnabled()) { - res += JoinOptions(this->RccOptions); - res += " ~~~ "; + std::string& str = this->SettingsStringRcc; + str += JoinOptions(this->RccOptions); + str += " ~~~ "; } - return res; -} - -void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile, - const std::string& targetDirectory) -{ - // Compose current settings strings - this->SettingsStringMoc = this->SettingsStringGenMoc(); - this->SettingsStringUic = this->SettingsStringGenUic(); - this->SettingsStringRcc = this->SettingsStringGenRcc(); // Read old settings const std::string filename = SettingsFile(targetDirectory); diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 7383c99..78d0314 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -28,9 +28,6 @@ private: const std::string& config); // - Settings file - std::string SettingsStringGenMoc() const; - std::string SettingsStringGenUic() const; - std::string SettingsStringGenRcc() const; void SettingsFileRead(cmMakefile* makefile, const std::string& targetDirectory); bool SettingsFileWrite(const std::string& targetDirectory); https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=739592c9256fb6f89ee15081c3944d42515ef8db commit 739592c9256fb6f89ee15081c3944d42515ef8db Author: Sebastian Holtermann AuthorDate: Wed Feb 15 10:15:05 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:42 2017 +0100 Autogen: Rename settings string variables diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 9c9142e..d3fbd02 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -469,20 +469,20 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile, const std::string& targetDirectory) { // Compose current settings strings - this->MocSettingsString = this->SettingsStringGenMoc(); - this->UicSettingsString = this->SettingsStringGenUic(); - this->RccSettingsString = this->SettingsStringGenRcc(); + this->SettingsStringMoc = this->SettingsStringGenMoc(); + this->SettingsStringUic = this->SettingsStringGenUic(); + this->SettingsStringRcc = this->SettingsStringGenRcc(); // Read old settings const std::string filename = SettingsFile(targetDirectory); if (makefile->ReadListFile(filename.c_str())) { - if (!SettingsMatch(makefile, SettingsKeyMoc, this->MocSettingsString)) { + if (!SettingsMatch(makefile, SettingsKeyMoc, this->SettingsStringMoc)) { this->GenerateAllMoc = true; } - if (!SettingsMatch(makefile, SettingsKeyUic, this->UicSettingsString)) { + if (!SettingsMatch(makefile, SettingsKeyUic, this->SettingsStringUic)) { this->GenerateAllUic = true; } - if (!SettingsMatch(makefile, SettingsKeyRcc, this->RccSettingsString)) { + if (!SettingsMatch(makefile, SettingsKeyRcc, this->SettingsStringRcc)) { this->GenerateAllRcc = true; } // In case any setting changed remove the old settings file. @@ -513,9 +513,9 @@ bool cmQtAutoGenerators::SettingsFileWrite(const std::string& targetDirectory) cmsys::ofstream outfile; outfile.open(filename.c_str(), std::ios::trunc); if (outfile) { - SettingWrite(outfile, SettingsKeyMoc, this->MocSettingsString); - SettingWrite(outfile, SettingsKeyUic, this->UicSettingsString); - SettingWrite(outfile, SettingsKeyRcc, this->RccSettingsString); + SettingWrite(outfile, SettingsKeyMoc, this->SettingsStringMoc); + SettingWrite(outfile, SettingsKeyUic, this->SettingsStringUic); + SettingWrite(outfile, SettingsKeyRcc, this->SettingsStringRcc); success = outfile.good(); outfile.close(); } else { diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 068ec1d..7383c99 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -140,6 +140,10 @@ private: // - File lists std::vector Sources; std::vector Headers; + // - Settings + std::string SettingsStringMoc; + std::string SettingsStringUic; + std::string SettingsStringRcc; // - Moc std::vector SkipMoc; std::string MocCompileDefinitionsStr; @@ -150,17 +154,14 @@ private: std::list MocIncludes; std::list MocDefinitions; std::vector MocOptions; - std::string MocSettingsString; // - Uic std::vector SkipUic; std::vector UicTargetOptions; std::map UicOptions; - std::string UicSettingsString; // - Rcc std::vector RccSources; std::map RccOptions; std::map > RccInputs; - std::string RccSettingsString; // - Utility cmFilePathChecksum fpathCheckSum; cmsys::RegularExpression RegExpQObject; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ad1f21313f553ecc7064accf582986112dc678d1 commit ad1f21313f553ecc7064accf582986112dc678d1 Author: Sebastian Holtermann AuthorDate: Wed Feb 15 00:04:49 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:42 2017 +0100 Autogen: Make methods const diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 0a90c7e..9c9142e 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -427,7 +427,7 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( return true; } -std::string cmQtAutoGenerators::SettingsStringGenMoc() +std::string cmQtAutoGenerators::SettingsStringGenMoc() const { std::string res; if (this->MocEnabled()) { @@ -443,7 +443,7 @@ std::string cmQtAutoGenerators::SettingsStringGenMoc() return res; } -std::string cmQtAutoGenerators::SettingsStringGenUic() +std::string cmQtAutoGenerators::SettingsStringGenUic() const { std::string res; if (this->UicEnabled()) { @@ -455,7 +455,7 @@ std::string cmQtAutoGenerators::SettingsStringGenUic() return res; } -std::string cmQtAutoGenerators::SettingsStringGenRcc() +std::string cmQtAutoGenerators::SettingsStringGenRcc() const { std::string res; if (this->RccEnabled()) { @@ -1601,7 +1601,7 @@ void cmQtAutoGenerators::LogCommand(const std::vector& command) */ bool cmQtAutoGenerators::NameCollisionTest( const std::map& genFiles, - std::multimap& collisions) + std::multimap& collisions) const { typedef std::map::const_iterator Iter; typedef std::map::value_type VType; @@ -1631,7 +1631,7 @@ bool cmQtAutoGenerators::NameCollisionTest( */ std::string cmQtAutoGenerators::ChecksumedPath(const std::string& sourceFile, const char* basePrefix, - const char* baseSuffix) + const char* baseSuffix) const { std::string res = fpathCheckSum.getPart(sourceFile); res += "/"; diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index dcb3a4f..068ec1d 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -28,9 +28,9 @@ private: const std::string& config); // - Settings file - std::string SettingsStringGenMoc(); - std::string SettingsStringGenUic(); - std::string SettingsStringGenRcc(); + std::string SettingsStringGenMoc() const; + std::string SettingsStringGenUic() const; + std::string SettingsStringGenRcc() const; void SettingsFileRead(cmMakefile* makefile, const std::string& targetDirectory); bool SettingsFileWrite(const std::string& targetDirectory); @@ -105,17 +105,19 @@ private: void LogCommand(const std::vector& command); // - Utility - bool NameCollisionTest(const std::map& genFiles, - std::multimap& collisions); + bool NameCollisionTest( + const std::map& genFiles, + std::multimap& collisions) const; std::string ChecksumedPath(const std::string& sourceFile, - const char* basePrefix, const char* baseSuffix); + const char* basePrefix, + const char* baseSuffix) const; bool MakeParentDirectory(const std::string& filename); bool MocEnabled() const { return !this->MocExecutable.empty(); } bool UicEnabled() const { return !this->UicExecutable.empty(); } bool RccEnabled() const { return !this->RccExecutable.empty(); } - bool GenerateAllAny() + bool GenerateAllAny() const { return (this->GenerateAllMoc || this->GenerateAllRcc || this->GenerateAllUic); https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=2296a2e9ee04fc83a294d51421038dca40b3150f commit 2296a2e9ee04fc83a294d51421038dca40b3150f Author: Sebastian Holtermann AuthorDate: Wed Feb 15 00:00:51 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:42 2017 +0100 cmFilePathChecksum: Make methods const useable diff --git a/Source/cmFilePathChecksum.cxx b/Source/cmFilePathChecksum.cxx index 3d8b695..62f52e5 100644 --- a/Source/cmFilePathChecksum.cxx +++ b/Source/cmFilePathChecksum.cxx @@ -45,7 +45,7 @@ void cmFilePathChecksum::setupParentDirs(const std::string& currentSrcDir, parentDirs[3].second = "ProjectBinary"; } -std::string cmFilePathChecksum::get(const std::string& filePath) +std::string cmFilePathChecksum::get(const std::string& filePath) const { std::string relPath; std::string relSeed; @@ -82,7 +82,7 @@ std::string cmFilePathChecksum::get(const std::string& filePath) } std::string cmFilePathChecksum::getPart(const std::string& filePath, - size_t length) + size_t length) const { return get(filePath).substr(0, length); } diff --git a/Source/cmFilePathChecksum.h b/Source/cmFilePathChecksum.h index df19053..59ca34c 100644 --- a/Source/cmFilePathChecksum.h +++ b/Source/cmFilePathChecksum.h @@ -47,13 +47,13 @@ public: /* @brief Calculates the path checksum for the parent directory of a file * */ - std::string get(const std::string& filePath); + std::string get(const std::string& filePath) const; /* @brief Same as get() but returns only the first length characters * */ std::string getPart(const std::string& filePath, - size_t length = partLengthDefault); + size_t length = partLengthDefault) const; private: /// Size of the parent directory list https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d3a9887149d638dd23df2b46ff67a90cd91d33fe commit d3a9887149d638dd23df2b46ff67a90cd91d33fe Author: Sebastian Holtermann AuthorDate: Tue Feb 14 23:59:07 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:42 2017 +0100 Autogen: Add method for checksum based path generation diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 218bbc3..0a90c7e 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -1046,10 +1046,8 @@ void cmQtAutoGenerators::ParseHeaders( } std::string macroName; if (this->MocRequired(contents, macroName)) { - notIncludedMocs[headerName] = fpathCheckSum.getPart(headerName) + - "/moc_" + - cmsys::SystemTools::GetFilenameWithoutLastExtension(headerName) + - ".cpp"; + notIncludedMocs[headerName] = + this->ChecksumedPath(headerName, "moc_", ".cpp"); } } @@ -1412,9 +1410,8 @@ bool cmQtAutoGenerators::RccGenerateAll() si != this->RccSources.end(); ++si) { const std::string ext = cmsys::SystemTools::GetFilenameLastExtension(*si); if (ext == ".qrc") { - qrcGenMap[*si] = this->AutogenBuildSubDir + fpathCheckSum.getPart(*si) + - "/qrc_" + cmsys::SystemTools::GetFilenameWithoutLastExtension(*si) + - ".cpp"; + qrcGenMap[*si] = + this->AutogenBuildSubDir + this->ChecksumedPath(*si, "qrc_", ".cpp"); } } @@ -1629,6 +1626,22 @@ bool cmQtAutoGenerators::NameCollisionTest( } /** + * @brief Generates a file path based on the checksum of the source file path + * @return The path + */ +std::string cmQtAutoGenerators::ChecksumedPath(const std::string& sourceFile, + const char* basePrefix, + const char* baseSuffix) +{ + std::string res = fpathCheckSum.getPart(sourceFile); + res += "/"; + res += basePrefix; + res += cmsys::SystemTools::GetFilenameWithoutLastExtension(sourceFile); + res += baseSuffix; + return res; +} + +/** * @brief Generates the parent directory of the given file on demand * @return True on success */ diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index bf4a251..dcb3a4f 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -107,6 +107,8 @@ private: // - Utility bool NameCollisionTest(const std::map& genFiles, std::multimap& collisions); + std::string ChecksumedPath(const std::string& sourceFile, + const char* basePrefix, const char* baseSuffix); bool MakeParentDirectory(const std::string& filename); bool MocEnabled() const { return !this->MocExecutable.empty(); } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6ae09b7c1473836236275e553fe9ff77f48306c1 commit 6ae09b7c1473836236275e553fe9ff77f48306c1 Author: Sebastian Holtermann AuthorDate: Tue Feb 14 23:42:10 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:41 2017 +0100 Autogen: Use nested loops instead of code duplication diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 10ecc1b..218bbc3 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -985,42 +985,35 @@ void cmQtAutoGenerators::SearchHeadersForSourceFile( const std::vector& headerExtensions, std::set& absHeadersMoc, std::set& absHeadersUic) { - // search for header files and private header files we may need to moc: - std::string basepath = cmsys::SystemTools::GetFilenamePath( - cmsys::SystemTools::GetRealPath(absFilename)); - basepath += '/'; - basepath += cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename); - - // Search for regular header - for (std::vector::const_iterator ext = headerExtensions.begin(); - ext != headerExtensions.end(); ++ext) { - const std::string headerName = basepath + "." + (*ext); - if (cmsys::SystemTools::FileExists(headerName.c_str())) { - // Moc headers - if (!this->MocSkipTest(absFilename) && !this->MocSkipTest(headerName)) { - absHeadersMoc.insert(headerName); - } - // Uic headers - if (!this->UicSkipTest(absFilename) && !this->UicSkipTest(headerName)) { - absHeadersUic.insert(headerName); - } - break; - } - } - // Search for private header - for (std::vector::const_iterator ext = headerExtensions.begin(); - ext != headerExtensions.end(); ++ext) { - const std::string headerName = basepath + "_p." + (*ext); - if (cmsys::SystemTools::FileExists(headerName.c_str())) { - // Moc headers - if (!this->MocSkipTest(absFilename) && !this->MocSkipTest(headerName)) { - absHeadersMoc.insert(headerName); - } - // Uic headers - if (!this->UicSkipTest(absFilename) && !this->UicSkipTest(headerName)) { - absHeadersUic.insert(headerName); + std::string basepaths[2]; + { + std::string bpath = cmsys::SystemTools::GetFilenamePath( + cmsys::SystemTools::GetRealPath(absFilename)); + bpath += '/'; + bpath += cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename); + + // search for default header files and private header files + basepaths[0] = (bpath + "."); + basepaths[1] = (bpath + "_p."); + } + + for (const std::string* bpit = cmArrayBegin(basepaths); + bpit != cmArrayEnd(basepaths); ++bpit) { + for (std::vector::const_iterator heit = + headerExtensions.begin(); + heit != headerExtensions.end(); ++heit) { + const std::string hname = (*bpit) + (*heit); + if (cmsys::SystemTools::FileExists(hname.c_str())) { + // Moc headers + if (!this->MocSkipTest(absFilename) && !this->MocSkipTest(hname)) { + absHeadersMoc.insert(hname); + } + // Uic headers + if (!this->UicSkipTest(absFilename) && !this->UicSkipTest(hname)) { + absHeadersUic.insert(hname); + } + break; } - break; } } } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9a7c9efeea0c2c2dfa20eb46dc75359c7f787629 commit 9a7c9efeea0c2c2dfa20eb46dc75359c7f787629 Author: Sebastian Holtermann AuthorDate: Tue Feb 14 22:30:16 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:41 2017 +0100 Autogen: Use cmSystemTools::Stdout/err instead of std::cout/err diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index f1cd67e..10ecc1b 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -1573,21 +1572,21 @@ void cmQtAutoGenerators::LogBold(const std::string& message) void cmQtAutoGenerators::LogInfo(const std::string& message) { - std::cout << message.c_str(); + cmSystemTools::Stdout(message.c_str(), message.size()); } void cmQtAutoGenerators::LogWarning(const std::string& message) { - std::ostringstream ostr; - ostr << message << "\n"; - std::cout << ostr.str(); + std::string msg(message); + msg += "\n"; + cmSystemTools::Stdout(msg.c_str(), msg.size()); } void cmQtAutoGenerators::LogError(const std::string& message) { - std::ostringstream ostr; - ostr << message << "\n"; - std::cerr << ostr.str(); + std::string msg(message); + msg += "\n"; + cmSystemTools::Stderr(msg.c_str(), msg.size()); } void cmQtAutoGenerators::LogCommand(const std::vector& command) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=86c2b552ad7bb3af97bb3c59576ddc7cac841d26 commit 86c2b552ad7bb3af97bb3c59576ddc7cac841d26 Author: Sebastian Holtermann AuthorDate: Tue Feb 14 22:21:00 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:41 2017 +0100 Autogen: LogWarning method fix diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 075059e..f1cd67e 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -1580,13 +1580,13 @@ void cmQtAutoGenerators::LogWarning(const std::string& message) { std::ostringstream ostr; ostr << message << "\n"; - std::cout << message.c_str(); + std::cout << ostr.str(); } void cmQtAutoGenerators::LogError(const std::string& message) { std::ostringstream ostr; - ostr << message << "\n\n"; + ostr << message << "\n"; std::cerr << ostr.str(); } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=2fed7bcc1f4a19f4942cddfdd42278f1c20feccc commit 2fed7bcc1f4a19f4942cddfdd42278f1c20feccc Author: Sebastian Holtermann AuthorDate: Tue Feb 14 21:59:36 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:41 2017 +0100 Autogen: Single point of return in RccGenerateFile diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index a21fe52..075059e 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -672,7 +672,7 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) if (!this->UicGenerateAll(includedUis)) { return false; } - if (!this->QrcGenerateAll()) { + if (!this->RccGenerateAll()) { return false; } @@ -1408,7 +1408,7 @@ bool cmQtAutoGenerators::UicGenerateFile(const std::string& realName, return uicGenerated; } -bool cmQtAutoGenerators::QrcGenerateAll() +bool cmQtAutoGenerators::RccGenerateAll() { if (!this->RccEnabled()) { return true; @@ -1445,7 +1445,7 @@ bool cmQtAutoGenerators::QrcGenerateAll() qrcGenMap.begin(); si != qrcGenMap.end(); ++si) { bool unique = FileNameIsUnique(si->first, qrcGenMap); - if (!this->QrcGenerateFile(si->first, si->second, unique)) { + if (!this->RccGenerateFile(si->first, si->second, unique)) { if (this->RunRccFailed) { return false; } @@ -1457,88 +1457,95 @@ bool cmQtAutoGenerators::QrcGenerateAll() /** * @return True if a rcc file was created. False may indicate an error. */ -bool cmQtAutoGenerators::QrcGenerateFile(const std::string& qrcInputFile, - const std::string& qrcOutputFile, +bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile, + const std::string& rccOutputFile, bool unique_n) { - std::string symbolName = - cmsys::SystemTools::GetFilenameWithoutLastExtension(qrcInputFile); - if (!unique_n) { - symbolName += "_"; - symbolName += fpathCheckSum.getPart(qrcInputFile); - } - // Replace '-' with '_'. The former is valid for - // file names but not for symbol names. - std::replace(symbolName.begin(), symbolName.end(), '-', '_'); - - const std::string qrcBuildFile = this->CurrentBinaryDir + qrcOutputFile; - - bool generateQrc = this->GenerateAllRcc; - // Test if the resources list file is newer than build file - if (!generateQrc) { - generateQrc = FileAbsentOrOlder(qrcBuildFile, qrcInputFile); - } - // Test if any resource file is newer than the build file - if (!generateQrc) { - const std::vector& files = this->RccInputs[qrcInputFile]; - for (std::vector::const_iterator it = files.begin(); - it != files.end(); ++it) { - if (FileAbsentOrOlder(qrcBuildFile, *it)) { - generateQrc = true; - break; + bool rccGenerated = false; + bool generateRcc = this->GenerateAllRcc; + + const std::string rccBuildFile = this->CurrentBinaryDir + rccOutputFile; + + if (!generateRcc) { + // Test if the resources list file is newer than build file + generateRcc = FileAbsentOrOlder(rccBuildFile, rccInputFile); + if (!generateRcc) { + // Test if any resource file is newer than the build file + const std::vector& files = this->RccInputs[rccInputFile]; + for (std::vector::const_iterator it = files.begin(); + it != files.end(); ++it) { + if (FileAbsentOrOlder(rccBuildFile, *it)) { + generateRcc = true; + break; + } } } } - if (generateQrc) { - { - std::string msg = "Generating RCC source "; - msg += qrcOutputFile; - this->LogBold(msg); - } + if (generateRcc) { + // Log + this->LogBold("Generating RCC source " + rccOutputFile); // Make sure the parent directory exists - if (!this->MakeParentDirectory(qrcOutputFile)) { - this->RunRccFailed = true; - return false; - } - - std::vector command; - command.push_back(this->RccExecutable); - { - std::map::const_iterator optionIt = - this->RccOptions.find(qrcInputFile); - if (optionIt != this->RccOptions.end()) { - cmSystemTools::ExpandListArgument(optionIt->second, command); + if (this->MakeParentDirectory(rccBuildFile)) { + // Compose symbol name + std::string symbolName = + cmsys::SystemTools::GetFilenameWithoutLastExtension(rccInputFile); + if (!unique_n) { + symbolName += "_"; + symbolName += fpathCheckSum.getPart(rccInputFile); } - } - command.push_back("-name"); - command.push_back(symbolName); - command.push_back("-o"); - command.push_back(qrcBuildFile); - command.push_back(qrcInputFile); + // Replace '-' with '_'. The former is valid for + // file names but not for symbol names. + std::replace(symbolName.begin(), symbolName.end(), '-', '_'); - if (this->Verbose) { - this->LogCommand(command); - } - std::string output; - int retVal = 0; - bool result = - cmSystemTools::RunSingleCommand(command, &output, &output, &retVal); - if (!result || retVal) { + // Compose rcc command + std::vector cmd; + cmd.push_back(this->RccExecutable); { - std::ostringstream err; - err << "AutoRcc: Error: rcc process for " << qrcOutputFile - << " failed:\n" - << output << std::endl; - this->LogError(err.str()); + std::map::const_iterator optionIt = + this->RccOptions.find(rccInputFile); + if (optionIt != this->RccOptions.end()) { + cmSystemTools::ExpandListArgument(optionIt->second, cmd); + } + } + cmd.push_back("-name"); + cmd.push_back(symbolName); + cmd.push_back("-o"); + cmd.push_back(rccBuildFile); + cmd.push_back(rccInputFile); + + // Log command + if (this->Verbose) { + this->LogCommand(cmd); } - cmSystemTools::RemoveFile(qrcBuildFile); + + // Execute command + bool res = false; + int retVal = 0; + std::string output; + res = cmSystemTools::RunSingleCommand(cmd, &output, &output, &retVal); + if (!res || (retVal != 0)) { + // Command failed + { + std::ostringstream err; + err << "AutoRcc: Error: rcc process failed for\n"; + err << "\"" << rccOutputFile << "\"\n"; + err << "AutoRcc: Command:\n" << cmJoin(cmd, " ") << "\n"; + err << "AutoRcc: Command output:\n" << output << "\n"; + this->LogError(err.str()); + } + cmSystemTools::RemoveFile(rccBuildFile); + this->RunRccFailed = true; + } else { + // Success + rccGenerated = true; + } + } else { + // Parent directory creation failed this->RunRccFailed = true; - return false; } - return true; } - return false; + return rccGenerated; } void cmQtAutoGenerators::LogErrorNameCollision( diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 68cdbb4..bf4a251 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -89,9 +89,9 @@ private: const std::string& uiInputFile, const std::string& uiOutputFile); - // - Qrc file generation - bool QrcGenerateAll(); - bool QrcGenerateFile(const std::string& qrcInputFile, + // - Rcc file generation + bool RccGenerateAll(); + bool RccGenerateFile(const std::string& qrcInputFile, const std::string& qrcOutputFile, bool unique_n); // - Logging https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c29950cc1f532d78158b146c50b0c49b8d41c47a commit c29950cc1f532d78158b146c50b0c49b8d41c47a Author: Sebastian Holtermann AuthorDate: Tue Feb 14 20:26:22 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:41 2017 +0100 Autogen: Single point of return in UicGenerateFile diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index ac0acb3..a21fe52 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -1337,13 +1337,15 @@ bool cmQtAutoGenerators::UicGenerateFile(const std::string& realName, const std::string& uiInputFile, const std::string& uiOutputFile) { + bool uicGenerated = false; + bool generateUic = this->GenerateAllUic; + const std::string uicFileRel = this->AutogenBuildSubDir + "include/" + uiOutputFile; const std::string uicFileAbs = this->CurrentBinaryDir + uicFileRel; - bool generateUic = this->GenerateAllUic; - // Test if the source file is newer that the build file if (!generateUic) { + // Test if the source file is newer that the build file generateUic = FileAbsentOrOlder(uicFileAbs, uiInputFile); } if (generateUic) { @@ -1351,50 +1353,59 @@ bool cmQtAutoGenerators::UicGenerateFile(const std::string& realName, this->LogBold("Generating UIC header " + uicFileRel); // Make sure the parent directory exists - if (!this->MakeParentDirectory(uicFileAbs)) { - this->RunUicFailed = true; - return false; - } + if (this->MakeParentDirectory(uicFileAbs)) { + // Compose uic command + std::vector cmd; + cmd.push_back(this->UicExecutable); + { + std::vector opts = this->UicTargetOptions; + std::map::const_iterator optionIt = + this->UicOptions.find(uiInputFile); + if (optionIt != this->UicOptions.end()) { + std::vector fileOpts; + cmSystemTools::ExpandListArgument(optionIt->second, fileOpts); + UicMergeOptions(opts, fileOpts, (this->QtMajorVersion == "5")); + } + cmd.insert(cmd.end(), opts.begin(), opts.end()); + } + cmd.push_back("-o"); + cmd.push_back(uicFileAbs); + cmd.push_back(uiInputFile); - std::vector command; - command.push_back(this->UicExecutable); - - std::vector opts = this->UicTargetOptions; - std::map::const_iterator optionIt = - this->UicOptions.find(uiInputFile); - if (optionIt != this->UicOptions.end()) { - std::vector fileOpts; - cmSystemTools::ExpandListArgument(optionIt->second, fileOpts); - UicMergeOptions(opts, fileOpts, this->QtMajorVersion == "5"); - } - command.insert(command.end(), opts.begin(), opts.end()); + // Log command + if (this->Verbose) { + this->LogCommand(cmd); + } - command.push_back("-o"); - command.push_back(uicFileAbs); - command.push_back(uiInputFile); + // Execute command + bool res = false; + int retVal = 0; + std::string output; + res = cmSystemTools::RunSingleCommand(cmd, &output, &output, &retVal); - if (this->Verbose) { - this->LogCommand(command); - } - std::string output; - int retVal = 0; - bool result = - cmSystemTools::RunSingleCommand(command, &output, &output, &retVal); - if (!result || retVal) { - { - std::ostringstream err; - err << "AutoUic: Error: uic process for " << uicFileRel - << " needed by\n \"" << realName << "\"\nfailed:\n" - << output << std::endl; - this->LogError(err.str()); + if (!res || (retVal != 0)) { + // Command failed + { + std::ostringstream err; + err << "AutoUic: Error: uic process failed for\n"; + err << "\"" << uicFileRel << "\" needed by\n"; + err << "\"" << realName << "\"\n"; + err << "AutoUic: Command:\n" << cmJoin(cmd, " ") << "\n"; + err << "AutoUic: Command output:\n" << output << "\n"; + this->LogError(err.str()); + } + cmSystemTools::RemoveFile(uicFileAbs); + this->RunUicFailed = true; + } else { + // Success + uicGenerated = true; } - cmSystemTools::RemoveFile(uicFileAbs); + } else { + // Parent directory creation failed this->RunUicFailed = true; - return false; } - return true; } - return false; + return uicGenerated; } bool cmQtAutoGenerators::QrcGenerateAll() https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=74a2fcff50356dcdcd4004664a2b2b81a8142660 commit 74a2fcff50356dcdcd4004664a2b2b81a8142660 Author: Sebastian Holtermann AuthorDate: Tue Feb 14 19:53:08 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:41 2017 +0100 Autogen: Single point of return in MocGenerateFile diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 8d8b47a..ac0acb3 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -1200,13 +1200,15 @@ bool cmQtAutoGenerators::MocGenerateFile(const std::string& sourceFile, const std::string& mocFileName, const std::string& subDirPrefix) { + bool mocGenerated = false; + bool generateMoc = this->GenerateAllMoc; + const std::string mocFileRel = this->AutogenBuildSubDir + subDirPrefix + mocFileName; const std::string mocFileAbs = this->CurrentBinaryDir + mocFileRel; - bool generateMoc = this->GenerateAllMoc; - // Test if the source file is newer that the build file if (!generateMoc) { + // Test if the source file is newer that the build file generateMoc = FileAbsentOrOlder(mocFileAbs, sourceFile); } if (generateMoc) { @@ -1214,48 +1216,55 @@ bool cmQtAutoGenerators::MocGenerateFile(const std::string& sourceFile, this->LogBold("Generating MOC source " + mocFileRel); // Make sure the parent directory exists - if (!this->MakeParentDirectory(mocFileAbs)) { - this->RunMocFailed = true; - return false; - } - - std::vector command; - command.push_back(this->MocExecutable); - command.insert(command.end(), this->MocIncludes.begin(), - this->MocIncludes.end()); - command.insert(command.end(), this->MocDefinitions.begin(), - this->MocDefinitions.end()); - command.insert(command.end(), this->MocOptions.begin(), - this->MocOptions.end()); + if (this->MakeParentDirectory(mocFileAbs)) { + // Compose moc command + std::vector cmd; + cmd.push_back(this->MocExecutable); + cmd.insert(cmd.end(), this->MocIncludes.begin(), + this->MocIncludes.end()); + cmd.insert(cmd.end(), this->MocDefinitions.begin(), + this->MocDefinitions.end()); + cmd.insert(cmd.end(), this->MocOptions.begin(), this->MocOptions.end()); #ifdef _WIN32 - command.push_back("-DWIN32"); + cmd.push_back("-DWIN32"); #endif - command.push_back("-o"); - command.push_back(mocFileAbs); - command.push_back(sourceFile); + cmd.push_back("-o"); + cmd.push_back(mocFileAbs); + cmd.push_back(sourceFile); - if (this->Verbose) { - this->LogCommand(command); - } + // Log moc command + if (this->Verbose) { + this->LogCommand(cmd); + } - std::string output; - int retVal = 0; - bool result = - cmSystemTools::RunSingleCommand(command, &output, &output, &retVal); - if (!result || retVal) { - { - std::ostringstream err; - err << "AutoMoc: Error: moc process for " << mocFileRel << " failed:\n" - << output << std::endl; - this->LogError(err.str()); + // Execute moc command + bool res = false; + int retVal = 0; + std::string output; + res = cmSystemTools::RunSingleCommand(cmd, &output, &output, &retVal); + + if (!res || (retVal != 0)) { + // Command failed + { + std::ostringstream err; + err << "AutoMoc: Error: moc process failed for\n"; + err << "\"" << mocFileRel << "\"\n"; + err << "AutoMoc: Command:\n" << cmJoin(cmd, " ") << "\n"; + err << "AutoMoc: Command output:\n" << output << "\n"; + this->LogError(err.str()); + } + cmSystemTools::RemoveFile(mocFileAbs); + this->RunMocFailed = true; + } else { + // Success + mocGenerated = true; } - cmSystemTools::RemoveFile(mocFileAbs); + } else { + // Parent directory creation failed this->RunMocFailed = true; - return false; } - return true; } - return false; + return mocGenerated; } bool cmQtAutoGenerators::UicGenerateAll( https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=21886ff66a8a84c20a3c7f24601b5a353d8c7d06 commit 21886ff66a8a84c20a3c7f24601b5a353d8c7d06 Author: Sebastian Holtermann AuthorDate: Tue Feb 14 19:17:48 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:41 2017 +0100 Autogen: Use FooEnabled() utility methods diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 3807c3d..8d8b47a 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -431,7 +431,7 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( std::string cmQtAutoGenerators::SettingsStringGenMoc() { std::string res; - if (!this->MocExecutable.empty()) { + if (this->MocEnabled()) { res += this->MocCompileDefinitionsStr; res += " ~~~ "; res += this->MocIncludesStr; @@ -447,7 +447,7 @@ std::string cmQtAutoGenerators::SettingsStringGenMoc() std::string cmQtAutoGenerators::SettingsStringGenUic() { std::string res; - if (!this->UicExecutable.empty()) { + if (this->UicEnabled()) { res += cmJoin(this->UicTargetOptions, "@osep@"); res += " ~~~ "; res += JoinOptions(this->UicOptions); @@ -459,7 +459,7 @@ std::string cmQtAutoGenerators::SettingsStringGenUic() std::string cmQtAutoGenerators::SettingsStringGenRcc() { std::string res; - if (!this->RccExecutable.empty()) { + if (this->RccEnabled()) { res += JoinOptions(this->RccOptions); res += " ~~~ "; } @@ -709,7 +709,7 @@ bool cmQtAutoGenerators::MocRequired(const std::string& text, bool cmQtAutoGenerators::MocSkipTest(const std::string& absFilename) { // Test if moc scanning is enabled - if (!this->MocExecutable.empty()) { + if (this->MocEnabled()) { // Test if the file name is on the skip list if (!ListContains(this->SkipMoc, absFilename)) { return false; @@ -724,7 +724,7 @@ bool cmQtAutoGenerators::MocSkipTest(const std::string& absFilename) bool cmQtAutoGenerators::UicSkipTest(const std::string& absFilename) { // Test if uic scanning is enabled - if (!this->UicExecutable.empty()) { + if (this->UicEnabled()) { // Test if the file name is on the skip list if (!ListContains(this->SkipUic, absFilename)) { return false; @@ -1072,7 +1072,7 @@ bool cmQtAutoGenerators::MocGenerateAll( const std::map& includedMocs, const std::map& notIncludedMocs) { - if (this->MocExecutable.empty()) { + if (!this->MocEnabled()) { return true; } @@ -1261,7 +1261,7 @@ bool cmQtAutoGenerators::MocGenerateFile(const std::string& sourceFile, bool cmQtAutoGenerators::UicGenerateAll( const std::map >& includedUis) { - if (this->UicExecutable.empty()) { + if (!this->UicEnabled()) { return true; } @@ -1390,7 +1390,7 @@ bool cmQtAutoGenerators::UicGenerateFile(const std::string& realName, bool cmQtAutoGenerators::QrcGenerateAll() { - if (this->RccExecutable.empty()) { + if (!this->RccEnabled()) { return true; } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=22faeef2626e10b281c82d10ba2653ecd940f398 commit 22faeef2626e10b281c82d10ba2653ecd940f398 Author: Sebastian Holtermann AuthorDate: Tue Feb 14 19:06:38 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:40 2017 +0100 Autogen: Add FooEnabled() utility methods diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 36519c5..68cdbb4 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -109,6 +109,10 @@ private: std::multimap& collisions); bool MakeParentDirectory(const std::string& filename); + bool MocEnabled() const { return !this->MocExecutable.empty(); } + bool UicEnabled() const { return !this->UicExecutable.empty(); } + bool RccEnabled() const { return !this->RccExecutable.empty(); } + bool GenerateAllAny() { return (this->GenerateAllMoc || this->GenerateAllRcc || https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=32d0ee3576c9203104a17c6a75bfc1bf13192045 commit 32d0ee3576c9203104a17c6a75bfc1bf13192045 Author: Sebastian Holtermann AuthorDate: Tue Feb 14 18:58:31 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:40 2017 +0100 Autogen: Generate empty settings string for disabled feature diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 6f07716..3807c3d 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -68,8 +68,10 @@ inline static bool SettingsMatch(cmMakefile* makefile, const char* key, static void SettingWrite(std::ostream& ostr, const char* key, const std::string& value) { - ostr << "set(" << key << " " << cmOutputConverter::EscapeForCMake(value) - << ")\n"; + if (!value.empty()) { + ostr << "set(" << key << " " << cmOutputConverter::EscapeForCMake(value) + << ")\n"; + } } static std::string FindMatchingHeader( @@ -429,32 +431,38 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( std::string cmQtAutoGenerators::SettingsStringGenMoc() { std::string res; - res += this->MocCompileDefinitionsStr; - res += " ~~~ "; - res += this->MocIncludesStr; - res += " ~~~ "; - res += this->MocOptionsStr; - res += " ~~~ "; - res += this->IncludeProjectDirsBefore ? "TRUE" : "FALSE"; - res += " ~~~ "; + if (!this->MocExecutable.empty()) { + res += this->MocCompileDefinitionsStr; + res += " ~~~ "; + res += this->MocIncludesStr; + res += " ~~~ "; + res += this->MocOptionsStr; + res += " ~~~ "; + res += this->IncludeProjectDirsBefore ? "TRUE" : "FALSE"; + res += " ~~~ "; + } return res; } std::string cmQtAutoGenerators::SettingsStringGenUic() { std::string res; - res += cmJoin(this->UicTargetOptions, "@osep@"); - res += " ~~~ "; - res += JoinOptions(this->UicOptions); - res += " ~~~ "; + if (!this->UicExecutable.empty()) { + res += cmJoin(this->UicTargetOptions, "@osep@"); + res += " ~~~ "; + res += JoinOptions(this->UicOptions); + res += " ~~~ "; + } return res; } std::string cmQtAutoGenerators::SettingsStringGenRcc() { std::string res; - res += JoinOptions(this->RccOptions); - res += " ~~~ "; + if (!this->RccExecutable.empty()) { + res += JoinOptions(this->RccOptions); + res += " ~~~ "; + } return res; } @@ -498,18 +506,17 @@ bool cmQtAutoGenerators::SettingsFileWrite(const std::string& targetDirectory) // Only write if any setting changed if (this->GenerateAllAny()) { const std::string filename = SettingsFile(targetDirectory); + if (this->Verbose) { + std::ostringstream err; + err << "AutoGen: Writing settings file " << filename << "\n"; + this->LogInfo(err.str()); + } cmsys::ofstream outfile; outfile.open(filename.c_str(), std::ios::trunc); if (outfile) { - if (!this->MocExecutable.empty()) { - SettingWrite(outfile, SettingsKeyMoc, this->MocSettingsString); - } - if (!this->UicExecutable.empty()) { - SettingWrite(outfile, SettingsKeyUic, this->UicSettingsString); - } - if (!this->RccExecutable.empty()) { - SettingWrite(outfile, SettingsKeyRcc, this->RccSettingsString); - } + SettingWrite(outfile, SettingsKeyMoc, this->MocSettingsString); + SettingWrite(outfile, SettingsKeyUic, this->UicSettingsString); + SettingWrite(outfile, SettingsKeyRcc, this->RccSettingsString); success = outfile.good(); outfile.close(); } else { https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=119876e6d5e71fb8a3f72ba35593ee43fd124203 commit 119876e6d5e71fb8a3f72ba35593ee43fd124203 Author: Sebastian Holtermann AuthorDate: Tue Feb 14 18:31:13 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:40 2017 +0100 Autogen: Simplify settings write method diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 8e5c3fd..6f07716 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -65,6 +65,13 @@ inline static bool SettingsMatch(cmMakefile* makefile, const char* key, return (value == makefile->GetSafeDefinition(key)); } +static void SettingWrite(std::ostream& ostr, const char* key, + const std::string& value) +{ + ostr << "set(" << key << " " << cmOutputConverter::EscapeForCMake(value) + << ")\n"; +} + static std::string FindMatchingHeader( const std::string& absPath, const std::string& mocSubDir, const std::string& basename, @@ -495,19 +502,13 @@ bool cmQtAutoGenerators::SettingsFileWrite(const std::string& targetDirectory) outfile.open(filename.c_str(), std::ios::trunc); if (outfile) { if (!this->MocExecutable.empty()) { - outfile << "set(" << SettingsKeyMoc << " " - << cmOutputConverter::EscapeForCMake(this->MocSettingsString) - << ")\n"; + SettingWrite(outfile, SettingsKeyMoc, this->MocSettingsString); } if (!this->UicExecutable.empty()) { - outfile << "set(" << SettingsKeyUic << " " - << cmOutputConverter::EscapeForCMake(this->UicSettingsString) - << ")\n"; + SettingWrite(outfile, SettingsKeyUic, this->UicSettingsString); } if (!this->RccExecutable.empty()) { - outfile << "set(" << SettingsKeyRcc << " " - << cmOutputConverter::EscapeForCMake(this->RccSettingsString) - << ")\n"; + SettingWrite(outfile, SettingsKeyRcc, this->RccSettingsString); } success = outfile.good(); outfile.close(); https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c88a3f72289a1fdfb9b47cdea025d50efee94501 commit c88a3f72289a1fdfb9b47cdea025d50efee94501 Author: Sebastian Holtermann AuthorDate: Tue Feb 14 18:19:12 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:40 2017 +0100 Autogen: Simplify settings read method diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index ba5a39e..8e5c3fd 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -51,7 +51,7 @@ static std::string GetConfigDefinition(cmMakefile* makefile, return makefile->GetSafeDefinition(key); } -static std::string OldSettingsFile(const std::string& targetDirectory) +static std::string SettingsFile(const std::string& targetDirectory) { std::string filename(cmSystemTools::CollapseFullPath(targetDirectory)); cmSystemTools::ConvertToUnixSlashes(filename); @@ -59,6 +59,12 @@ static std::string OldSettingsFile(const std::string& targetDirectory) return filename; } +inline static bool SettingsMatch(cmMakefile* makefile, const char* key, + const std::string& value) +{ + return (value == makefile->GetSafeDefinition(key)); +} + static std::string FindMatchingHeader( const std::string& absPath, const std::string& mocSubDir, const std::string& basename, @@ -454,25 +460,16 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile, this->RccSettingsString = this->SettingsStringGenRcc(); // Read old settings - const std::string filename = OldSettingsFile(targetDirectory); + const std::string filename = SettingsFile(targetDirectory); if (makefile->ReadListFile(filename.c_str())) { - if (!this->MocExecutable.empty()) { - const std::string sol = makefile->GetSafeDefinition(SettingsKeyMoc); - if (sol != this->MocSettingsString) { - this->GenerateAllMoc = true; - } + if (!SettingsMatch(makefile, SettingsKeyMoc, this->MocSettingsString)) { + this->GenerateAllMoc = true; } - if (!this->UicExecutable.empty()) { - const std::string sol = makefile->GetSafeDefinition(SettingsKeyUic); - if (sol != this->UicSettingsString) { - this->GenerateAllUic = true; - } + if (!SettingsMatch(makefile, SettingsKeyUic, this->UicSettingsString)) { + this->GenerateAllUic = true; } - if (!this->RccExecutable.empty()) { - const std::string sol = makefile->GetSafeDefinition(SettingsKeyRcc); - if (sol != this->RccSettingsString) { - this->GenerateAllRcc = true; - } + if (!SettingsMatch(makefile, SettingsKeyRcc, this->RccSettingsString)) { + this->GenerateAllRcc = true; } // In case any setting changed remove the old settings file. // This triggers a full rebuild on the next run if the current @@ -493,7 +490,7 @@ bool cmQtAutoGenerators::SettingsFileWrite(const std::string& targetDirectory) bool success = true; // Only write if any setting changed if (this->GenerateAllAny()) { - const std::string filename = OldSettingsFile(targetDirectory); + const std::string filename = SettingsFile(targetDirectory); cmsys::ofstream outfile; outfile.open(filename.c_str(), std::ios::trunc); if (outfile) { @@ -615,7 +612,8 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) // what file the moc is created from. Once a moc is included the same moc // may not be included in the moc_compilation.cpp file anymore. OTOH if // there's a header containing Q_OBJECT where no corresponding moc file - // is included anywhere a moc_.cpp file is created and included in + // is included anywhere a moc_.cpp file is created and included + // in // the moc_compilation.cpp file. // key = moc source filepath, value = moc output filepath https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=25f0c2e14b0285d81ad0c6be401398e12e7ea89e commit 25f0c2e14b0285d81ad0c6be401398e12e7ea89e Author: Sebastian Holtermann AuthorDate: Tue Feb 14 18:00:21 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:40 2017 +0100 Autogen: Rename settings key variables diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 95873a2..ba5a39e 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -29,9 +29,9 @@ // -- Static variables -static const char* MocOldSettingsKey = "AM_MOC_OLD_SETTINGS"; -static const char* UicOldSettingsKey = "AM_UIC_OLD_SETTINGS"; -static const char* RccOldSettingsKey = "AM_RCC_OLD_SETTINGS"; +static const char* SettingsKeyMoc = "AM_MOC_OLD_SETTINGS"; +static const char* SettingsKeyUic = "AM_UIC_OLD_SETTINGS"; +static const char* SettingsKeyRcc = "AM_RCC_OLD_SETTINGS"; // -- Static functions @@ -457,19 +457,19 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile, const std::string filename = OldSettingsFile(targetDirectory); if (makefile->ReadListFile(filename.c_str())) { if (!this->MocExecutable.empty()) { - const std::string sol = makefile->GetSafeDefinition(MocOldSettingsKey); + const std::string sol = makefile->GetSafeDefinition(SettingsKeyMoc); if (sol != this->MocSettingsString) { this->GenerateAllMoc = true; } } if (!this->UicExecutable.empty()) { - const std::string sol = makefile->GetSafeDefinition(UicOldSettingsKey); + const std::string sol = makefile->GetSafeDefinition(SettingsKeyUic); if (sol != this->UicSettingsString) { this->GenerateAllUic = true; } } if (!this->RccExecutable.empty()) { - const std::string sol = makefile->GetSafeDefinition(RccOldSettingsKey); + const std::string sol = makefile->GetSafeDefinition(SettingsKeyRcc); if (sol != this->RccSettingsString) { this->GenerateAllRcc = true; } @@ -498,17 +498,17 @@ bool cmQtAutoGenerators::SettingsFileWrite(const std::string& targetDirectory) outfile.open(filename.c_str(), std::ios::trunc); if (outfile) { if (!this->MocExecutable.empty()) { - outfile << "set(" << MocOldSettingsKey << " " + outfile << "set(" << SettingsKeyMoc << " " << cmOutputConverter::EscapeForCMake(this->MocSettingsString) << ")\n"; } if (!this->UicExecutable.empty()) { - outfile << "set(" << UicOldSettingsKey << " " + outfile << "set(" << SettingsKeyUic << " " << cmOutputConverter::EscapeForCMake(this->UicSettingsString) << ")\n"; } if (!this->RccExecutable.empty()) { - outfile << "set(" << RccOldSettingsKey << " " + outfile << "set(" << SettingsKeyRcc << " " << cmOutputConverter::EscapeForCMake(this->RccSettingsString) << ")\n"; } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=763f717ce2251a7237e85a0ad9a4c86c94942642 commit 763f717ce2251a7237e85a0ad9a4c86c94942642 Author: Sebastian Holtermann AuthorDate: Tue Feb 14 17:52:13 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:40 2017 +0100 Autogen: Rename settings string generation methods diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 2fd28c3..95873a2 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -413,7 +413,7 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( return true; } -std::string cmQtAutoGenerators::MocSettingsStringCompose() +std::string cmQtAutoGenerators::SettingsStringGenMoc() { std::string res; res += this->MocCompileDefinitionsStr; @@ -427,7 +427,7 @@ std::string cmQtAutoGenerators::MocSettingsStringCompose() return res; } -std::string cmQtAutoGenerators::UicSettingsStringCompose() +std::string cmQtAutoGenerators::SettingsStringGenUic() { std::string res; res += cmJoin(this->UicTargetOptions, "@osep@"); @@ -437,7 +437,7 @@ std::string cmQtAutoGenerators::UicSettingsStringCompose() return res; } -std::string cmQtAutoGenerators::RccSettingsStringCompose() +std::string cmQtAutoGenerators::SettingsStringGenRcc() { std::string res; res += JoinOptions(this->RccOptions); @@ -449,9 +449,9 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile, const std::string& targetDirectory) { // Compose current settings strings - this->MocSettingsString = this->MocSettingsStringCompose(); - this->UicSettingsString = this->UicSettingsStringCompose(); - this->RccSettingsString = this->RccSettingsStringCompose(); + this->MocSettingsString = this->SettingsStringGenMoc(); + this->UicSettingsString = this->SettingsStringGenUic(); + this->RccSettingsString = this->SettingsStringGenRcc(); // Read old settings const std::string filename = OldSettingsFile(targetDirectory); diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 953349b..36519c5 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -27,9 +27,10 @@ private: const std::string& targetDirectory, const std::string& config); - std::string MocSettingsStringCompose(); - std::string UicSettingsStringCompose(); - std::string RccSettingsStringCompose(); + // - Settings file + std::string SettingsStringGenMoc(); + std::string SettingsStringGenUic(); + std::string SettingsStringGenRcc(); void SettingsFileRead(cmMakefile* makefile, const std::string& targetDirectory); bool SettingsFileWrite(const std::string& targetDirectory); https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3ee2b1623ecbef3164c412bb6a1d826ba788002b commit 3ee2b1623ecbef3164c412bb6a1d826ba788002b Author: Sebastian Holtermann AuthorDate: Tue Feb 14 17:48:39 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:40 2017 +0100 Autogen: Rename settings file read/write methods diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 4a88201..2fd28c3 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -259,7 +259,7 @@ bool cmQtAutoGenerators::Run(const std::string& targetDirectory, return false; } // Read old settings - this->OldSettingsReadFile(mf.get(), targetDirectory); + this->SettingsFileRead(mf.get(), targetDirectory); // Init and run this->Init(); if (this->QtMajorVersion == "4" || this->QtMajorVersion == "5") { @@ -268,7 +268,7 @@ bool cmQtAutoGenerators::Run(const std::string& targetDirectory, } } // Write latest settings - if (!this->OldSettingsWriteFile(targetDirectory)) { + if (!this->SettingsFileWrite(targetDirectory)) { return false; } return true; @@ -445,8 +445,8 @@ std::string cmQtAutoGenerators::RccSettingsStringCompose() return res; } -void cmQtAutoGenerators::OldSettingsReadFile( - cmMakefile* makefile, const std::string& targetDirectory) +void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile, + const std::string& targetDirectory) { // Compose current settings strings this->MocSettingsString = this->MocSettingsStringCompose(); @@ -488,8 +488,7 @@ void cmQtAutoGenerators::OldSettingsReadFile( } } -bool cmQtAutoGenerators::OldSettingsWriteFile( - const std::string& targetDirectory) +bool cmQtAutoGenerators::SettingsFileWrite(const std::string& targetDirectory) { bool success = true; // Only write if any setting changed diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index d442ec3..953349b 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -30,9 +30,9 @@ private: std::string MocSettingsStringCompose(); std::string UicSettingsStringCompose(); std::string RccSettingsStringCompose(); - void OldSettingsReadFile(cmMakefile* makefile, - const std::string& targetDirectory); - bool OldSettingsWriteFile(const std::string& targetDirectory); + void SettingsFileRead(cmMakefile* makefile, + const std::string& targetDirectory); + bool SettingsFileWrite(const std::string& targetDirectory); // - Init and run void Init(); https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ec24dcdb36db7b460113b2ce3f7a954800d41e90 commit ec24dcdb36db7b460113b2ce3f7a954800d41e90 Author: Sebastian Holtermann AuthorDate: Tue Feb 14 17:46:19 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:39 2017 +0100 Autogen: Remove unnecessary test diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index df19a1c..4a88201 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -448,46 +448,43 @@ std::string cmQtAutoGenerators::RccSettingsStringCompose() void cmQtAutoGenerators::OldSettingsReadFile( cmMakefile* makefile, const std::string& targetDirectory) { - if (!this->MocExecutable.empty() || !this->UicExecutable.empty() || - !this->RccExecutable.empty()) { - // Compose current settings strings - this->MocSettingsString = this->MocSettingsStringCompose(); - this->UicSettingsString = this->UicSettingsStringCompose(); - this->RccSettingsString = this->RccSettingsStringCompose(); - - // Read old settings - const std::string filename = OldSettingsFile(targetDirectory); - if (makefile->ReadListFile(filename.c_str())) { - if (!this->MocExecutable.empty()) { - const std::string sol = makefile->GetSafeDefinition(MocOldSettingsKey); - if (sol != this->MocSettingsString) { - this->GenerateAllMoc = true; - } - } - if (!this->UicExecutable.empty()) { - const std::string sol = makefile->GetSafeDefinition(UicOldSettingsKey); - if (sol != this->UicSettingsString) { - this->GenerateAllUic = true; - } + // Compose current settings strings + this->MocSettingsString = this->MocSettingsStringCompose(); + this->UicSettingsString = this->UicSettingsStringCompose(); + this->RccSettingsString = this->RccSettingsStringCompose(); + + // Read old settings + const std::string filename = OldSettingsFile(targetDirectory); + if (makefile->ReadListFile(filename.c_str())) { + if (!this->MocExecutable.empty()) { + const std::string sol = makefile->GetSafeDefinition(MocOldSettingsKey); + if (sol != this->MocSettingsString) { + this->GenerateAllMoc = true; } - if (!this->RccExecutable.empty()) { - const std::string sol = makefile->GetSafeDefinition(RccOldSettingsKey); - if (sol != this->RccSettingsString) { - this->GenerateAllRcc = true; - } + } + if (!this->UicExecutable.empty()) { + const std::string sol = makefile->GetSafeDefinition(UicOldSettingsKey); + if (sol != this->UicSettingsString) { + this->GenerateAllUic = true; } - // In case any setting changed remove the old settings file. - // This triggers a full rebuild on the next run if the current - // build is aborted before writing the current settings in the end. - if (this->GenerateAllAny()) { - cmSystemTools::RemoveFile(filename); + } + if (!this->RccExecutable.empty()) { + const std::string sol = makefile->GetSafeDefinition(RccOldSettingsKey); + if (sol != this->RccSettingsString) { + this->GenerateAllRcc = true; } - } else { - // If the file could not be read re-generate everythiung. - this->GenerateAllMoc = true; - this->GenerateAllUic = true; - this->GenerateAllRcc = true; } + // In case any setting changed remove the old settings file. + // This triggers a full rebuild on the next run if the current + // build is aborted before writing the current settings in the end. + if (this->GenerateAllAny()) { + cmSystemTools::RemoveFile(filename); + } + } else { + // If the file could not be read re-generate everythiung. + this->GenerateAllMoc = true; + this->GenerateAllUic = true; + this->GenerateAllRcc = true; } } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6b31416d6c9bdc8b89a918f217a6678cc6083fed commit 6b31416d6c9bdc8b89a918f217a6678cc6083fed Author: Sebastian Holtermann AuthorDate: Tue Feb 14 17:42:52 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:39 2017 +0100 Autogen: Add GenerateAllAny flag test method diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 765cb74..df19a1c 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -479,8 +479,7 @@ void cmQtAutoGenerators::OldSettingsReadFile( // In case any setting changed remove the old settings file. // This triggers a full rebuild on the next run if the current // build is aborted before writing the current settings in the end. - if (this->GenerateAllMoc || this->GenerateAllUic || - this->GenerateAllRcc) { + if (this->GenerateAllAny()) { cmSystemTools::RemoveFile(filename); } } else { @@ -497,7 +496,7 @@ bool cmQtAutoGenerators::OldSettingsWriteFile( { bool success = true; // Only write if any setting changed - if (this->GenerateAllMoc || this->GenerateAllUic || this->GenerateAllRcc) { + if (this->GenerateAllAny()) { const std::string filename = OldSettingsFile(targetDirectory); cmsys::ofstream outfile; outfile.open(filename.c_str(), std::ios::trunc); diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 8dd44f6..d442ec3 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -108,6 +108,12 @@ private: std::multimap& collisions); bool MakeParentDirectory(const std::string& filename); + bool GenerateAllAny() + { + return (this->GenerateAllMoc || this->GenerateAllRcc || + this->GenerateAllUic); + } + // - Target names std::string OriginTargetName; std::string AutogenTargetName; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1bd74130f2a804d073081f7e3e4f307c3fecb07c commit 1bd74130f2a804d073081f7e3e4f307c3fecb07c Author: Sebastian Holtermann AuthorDate: Tue Feb 14 17:36:59 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 19 12:35:39 2017 +0100 Autogen: Rename GenerateFooAll variables to GenerateAllFoo diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 1d6972b..765cb74 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -214,9 +214,9 @@ cmQtAutoGenerators::cmQtAutoGenerators() , RunMocFailed(false) , RunUicFailed(false) , RunRccFailed(false) - , GenerateMocAll(false) - , GenerateUicAll(false) - , GenerateRccAll(false) + , GenerateAllMoc(false) + , GenerateAllUic(false) + , GenerateAllRcc(false) { std::string colorEnv; @@ -461,33 +461,33 @@ void cmQtAutoGenerators::OldSettingsReadFile( if (!this->MocExecutable.empty()) { const std::string sol = makefile->GetSafeDefinition(MocOldSettingsKey); if (sol != this->MocSettingsString) { - this->GenerateMocAll = true; + this->GenerateAllMoc = true; } } if (!this->UicExecutable.empty()) { const std::string sol = makefile->GetSafeDefinition(UicOldSettingsKey); if (sol != this->UicSettingsString) { - this->GenerateUicAll = true; + this->GenerateAllUic = true; } } if (!this->RccExecutable.empty()) { const std::string sol = makefile->GetSafeDefinition(RccOldSettingsKey); if (sol != this->RccSettingsString) { - this->GenerateRccAll = true; + this->GenerateAllRcc = true; } } // In case any setting changed remove the old settings file. // This triggers a full rebuild on the next run if the current // build is aborted before writing the current settings in the end. - if (this->GenerateMocAll || this->GenerateUicAll || - this->GenerateRccAll) { + if (this->GenerateAllMoc || this->GenerateAllUic || + this->GenerateAllRcc) { cmSystemTools::RemoveFile(filename); } } else { // If the file could not be read re-generate everythiung. - this->GenerateMocAll = true; - this->GenerateUicAll = true; - this->GenerateRccAll = true; + this->GenerateAllMoc = true; + this->GenerateAllUic = true; + this->GenerateAllRcc = true; } } } @@ -497,7 +497,7 @@ bool cmQtAutoGenerators::OldSettingsWriteFile( { bool success = true; // Only write if any setting changed - if (this->GenerateMocAll || this->GenerateUicAll || this->GenerateRccAll) { + if (this->GenerateAllMoc || this->GenerateAllUic || this->GenerateAllRcc) { const std::string filename = OldSettingsFile(targetDirectory); cmsys::ofstream outfile; outfile.open(filename.c_str(), std::ios::trunc); @@ -1203,7 +1203,7 @@ bool cmQtAutoGenerators::MocGenerateFile(const std::string& sourceFile, this->AutogenBuildSubDir + subDirPrefix + mocFileName; const std::string mocFileAbs = this->CurrentBinaryDir + mocFileRel; - bool generateMoc = this->GenerateMocAll; + bool generateMoc = this->GenerateAllMoc; // Test if the source file is newer that the build file if (!generateMoc) { generateMoc = FileAbsentOrOlder(mocFileAbs, sourceFile); @@ -1331,7 +1331,7 @@ bool cmQtAutoGenerators::UicGenerateFile(const std::string& realName, this->AutogenBuildSubDir + "include/" + uiOutputFile; const std::string uicFileAbs = this->CurrentBinaryDir + uicFileRel; - bool generateUic = this->GenerateUicAll; + bool generateUic = this->GenerateAllUic; // Test if the source file is newer that the build file if (!generateUic) { generateUic = FileAbsentOrOlder(uicFileAbs, uiInputFile); @@ -1452,7 +1452,7 @@ bool cmQtAutoGenerators::QrcGenerateFile(const std::string& qrcInputFile, const std::string qrcBuildFile = this->CurrentBinaryDir + qrcOutputFile; - bool generateQrc = this->GenerateRccAll; + bool generateQrc = this->GenerateAllRcc; // Test if the resources list file is newer than build file if (!generateQrc) { generateQrc = FileAbsentOrOlder(qrcBuildFile, qrcInputFile); diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 7891eb9..8dd44f6 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -159,9 +159,9 @@ private: bool RunMocFailed; bool RunUicFailed; bool RunRccFailed; - bool GenerateMocAll; - bool GenerateUicAll; - bool GenerateRccAll; + bool GenerateAllMoc; + bool GenerateAllUic; + bool GenerateAllRcc; bool MocRelaxedMode; }; ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-qt.7.rst | 22 +- Help/prop_tgt/AUTOMOC.rst | 54 +- Help/release/dev/Autogen_json.rst | 10 + Modules/AutogenInfo.cmake.in | 36 +- Source/cmFilePathChecksum.cxx | 4 +- Source/cmFilePathChecksum.h | 4 +- Source/cmQtAutoGeneratorInitializer.cxx | 670 ++++----- Source/cmQtAutoGenerators.cxx | 1575 ++++++++++++---------- Source/cmQtAutoGenerators.h | 168 ++- Tests/QtAutogen/CMakeLists.txt | 91 +- Tests/QtAutogen/mocInclude/ObjA.cpp | 24 + Tests/QtAutogen/mocInclude/ObjA.hpp | 13 + Tests/QtAutogen/mocInclude/ObjB.cpp | 25 + Tests/QtAutogen/mocInclude/ObjB.hpp | 13 + Tests/QtAutogen/mocInclude/ObjC.cpp | 26 + Tests/QtAutogen/mocInclude/ObjC.hpp | 13 + Tests/QtAutogen/mocInclude/ObjD.cpp | 26 + Tests/QtAutogen/mocInclude/ObjD.hpp | 13 + Tests/QtAutogen/mocInclude/subA/SubObjA.cpp | 27 + Tests/QtAutogen/mocInclude/subA/SubObjA.hpp | 16 + Tests/QtAutogen/mocInclude/subB/SubObjB.cpp | 27 + Tests/QtAutogen/mocInclude/subB/SubObjB.hpp | 16 + Tests/QtAutogen/mocInclude/subC/SubObjC.cpp | 27 + Tests/QtAutogen/mocInclude/subC/SubObjC.hpp | 16 + Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt | 18 + Tests/QtAutogen/mocIncludeRelaxed/main.cpp | 14 + Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt | 18 + Tests/QtAutogen/mocIncludeStrict/main.cpp | 14 + Tests/QtAutogen/mocPlugin/CMakeLists.txt | 25 + Tests/QtAutogen/mocPlugin/StyleA.cpp | 6 + Tests/QtAutogen/mocPlugin/StyleA.hpp | 15 + Tests/QtAutogen/mocPlugin/StyleA.json | 1 + Tests/QtAutogen/mocPlugin/StyleB.cpp | 6 + Tests/QtAutogen/mocPlugin/StyleB.hpp | 15 + Tests/QtAutogen/mocPlugin/StyleC.cpp | 6 + Tests/QtAutogen/mocPlugin/StyleC.hpp | 15 + Tests/QtAutogen/mocPlugin/StyleD.cpp | 17 + Tests/QtAutogen/mocPlugin/StyleD.hpp | 8 + Tests/QtAutogen/mocPlugin/StyleE.cpp | 6 + Tests/QtAutogen/mocPlugin/StyleE.hpp | 15 + Tests/QtAutogen/mocPlugin/jsonIn/StyleB.json | 1 + Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json | 1 + Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json | 1 + Tests/QtAutogen/mocPlugin/main.cpp | 6 + Tests/QtAutogen/sameName/CMakeLists.txt | 11 + 45 files changed, 1962 insertions(+), 1173 deletions(-) create mode 100644 Help/release/dev/Autogen_json.rst create mode 100644 Tests/QtAutogen/mocInclude/ObjA.cpp create mode 100644 Tests/QtAutogen/mocInclude/ObjA.hpp create mode 100644 Tests/QtAutogen/mocInclude/ObjB.cpp create mode 100644 Tests/QtAutogen/mocInclude/ObjB.hpp create mode 100644 Tests/QtAutogen/mocInclude/ObjC.cpp create mode 100644 Tests/QtAutogen/mocInclude/ObjC.hpp create mode 100644 Tests/QtAutogen/mocInclude/ObjD.cpp create mode 100644 Tests/QtAutogen/mocInclude/ObjD.hpp create mode 100644 Tests/QtAutogen/mocInclude/subA/SubObjA.cpp create mode 100644 Tests/QtAutogen/mocInclude/subA/SubObjA.hpp create mode 100644 Tests/QtAutogen/mocInclude/subB/SubObjB.cpp create mode 100644 Tests/QtAutogen/mocInclude/subB/SubObjB.hpp create mode 100644 Tests/QtAutogen/mocInclude/subC/SubObjC.cpp create mode 100644 Tests/QtAutogen/mocInclude/subC/SubObjC.hpp create mode 100644 Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt create mode 100644 Tests/QtAutogen/mocIncludeRelaxed/main.cpp create mode 100644 Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt create mode 100644 Tests/QtAutogen/mocIncludeStrict/main.cpp create mode 100644 Tests/QtAutogen/mocPlugin/CMakeLists.txt create mode 100644 Tests/QtAutogen/mocPlugin/StyleA.cpp create mode 100644 Tests/QtAutogen/mocPlugin/StyleA.hpp create mode 100644 Tests/QtAutogen/mocPlugin/StyleA.json create mode 100644 Tests/QtAutogen/mocPlugin/StyleB.cpp create mode 100644 Tests/QtAutogen/mocPlugin/StyleB.hpp create mode 100644 Tests/QtAutogen/mocPlugin/StyleC.cpp create mode 100644 Tests/QtAutogen/mocPlugin/StyleC.hpp create mode 100644 Tests/QtAutogen/mocPlugin/StyleD.cpp create mode 100644 Tests/QtAutogen/mocPlugin/StyleD.hpp create mode 100644 Tests/QtAutogen/mocPlugin/StyleE.cpp create mode 100644 Tests/QtAutogen/mocPlugin/StyleE.hpp create mode 100644 Tests/QtAutogen/mocPlugin/jsonIn/StyleB.json create mode 100644 Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json create mode 100644 Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json create mode 100644 Tests/QtAutogen/mocPlugin/main.cpp hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 20 15:16:35 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 20 Feb 2017 15:16:35 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-337-gc6cc9a8 Message-ID: <20170220201635.68A75F9D7E@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via c6cc9a81c33e734135f2bac358adc6f73ad2194c (commit) via 41d379a8ebade12bf8b798b754ab13ea80629e04 (commit) from 23f45e62c9a7597f257b3da5f3cb82d15f6c167e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c6cc9a81c33e734135f2bac358adc6f73ad2194c commit c6cc9a81c33e734135f2bac358adc6f73ad2194c Merge: 23f45e6 41d379a Author: Brad King AuthorDate: Mon Feb 20 15:16:34 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 20 15:16:34 2017 -0500 Merge topic 'autogen_json' into next 41d379a8 fixup! Autogen: Overhaul and simplify AutogenInfo.cmake file generation https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=41d379a8ebade12bf8b798b754ab13ea80629e04 commit 41d379a8ebade12bf8b798b754ab13ea80629e04 Author: Brad King AuthorDate: Mon Feb 20 15:15:34 2017 -0500 Commit: Brad King CommitDate: Mon Feb 20 15:15:34 2017 -0500 fixup! Autogen: Overhaul and simplify AutogenInfo.cmake file generation diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index cad0911..c9d1c24 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -133,7 +133,7 @@ static void AddDefinitionEscaped(cmMakefile* makefile, const char* key, } static void AddDefinitionEscaped(cmMakefile* makefile, const char* key, - const std::vector values) + const std::vector& values) { makefile->AddDefinition( key, cmOutputConverter::EscapeForCMake(cmJoin(values, ";")).c_str()); ----------------------------------------------------------------------- Summary of changes: Source/cmQtAutoGeneratorInitializer.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 20 15:17:24 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 20 Feb 2017 15:17:24 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-342-gc60b61b Message-ID: <20170220201724.59637F9E00@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via c60b61be56000aef36904fdc04eb5bde79b3e1dc (commit) via ca35b47fadaeb8c6a2bf3582fee10cc853e2f43d (commit) via ff4800b1f6f2f7041e76d85f41fb8104181ee23c (commit) via bbae069eea447504158176f7eb9fb7db7a44c7bf (commit) via 8571cca02d0ec9cd6b752038750e91a5c25ad259 (commit) from c6cc9a81c33e734135f2bac358adc6f73ad2194c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c60b61be56000aef36904fdc04eb5bde79b3e1dc commit c60b61be56000aef36904fdc04eb5bde79b3e1dc Merge: c6cc9a8 ca35b47 Author: Brad King AuthorDate: Mon Feb 20 15:17:23 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 20 15:17:23 2017 -0500 Merge topic 'autogen_json' into next ca35b47f Autogen: Documentation update ff4800b1 Autogen: Add release notes for Q_PLUGIN_METADATA support bbae069e Autogen: Tests: Set different compression levels in rcc test 8571cca0 Autogen: Overhaul and simplify AutogenInfo.cmake file generation https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ca35b47fadaeb8c6a2bf3582fee10cc853e2f43d commit ca35b47fadaeb8c6a2bf3582fee10cc853e2f43d Author: Sebastian Holtermann AuthorDate: Sun Feb 19 20:11:18 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:16:43 2017 -0500 Autogen: Documentation update Closes #15254 diff --git a/Help/manual/cmake-qt.7.rst b/Help/manual/cmake-qt.7.rst index 56d4ca7..e9da396 100644 --- a/Help/manual/cmake-qt.7.rst +++ b/Help/manual/cmake-qt.7.rst @@ -63,20 +63,24 @@ If a ``Q_OBJECT`` or ``Q_GADGET`` macro is found in a header file, ``moc`` will be run on the file. The result will be put into a file named according to ``moc_.cpp``. If the macro is found in a C++ implementation file, the moc output will be put into a file named according to -``.moc``, following the Qt conventions. The ``moc file`` may be -included by the user in the C++ implementation file with a preprocessor -``#include``. If it is not so included, it will be added to a separate file -which is compiled into the target. +``.moc``, following the Qt conventions. The ``.moc`` must +be included by the user in the C++ implementation file with a preprocessor +``#include``. -The ``moc`` command line will consume the :prop_tgt:`COMPILE_DEFINITIONS` and -:prop_tgt:`INCLUDE_DIRECTORIES` target properties from the target it is being -invoked for, and for the appropriate build configuration. - -The generated ``moc_*.cpp`` and ``*.moc`` files are placed in the +Included ``moc_*.cpp`` and ``*.moc`` files will be generated in the ``/_autogen/include`` directory which is automatically added to the target's :prop_tgt:`INCLUDE_DIRECTORIES`. (This differs from CMake 3.7 and below; see their documentation for details.) +Not included ``moc_.cpp`` files will be generated in custom +folders to avoid name collisions and included in a separate +``/_autogen/moc_compilation.cpp`` +file which is compiled into the target. + +The ``moc`` command line will consume the :prop_tgt:`COMPILE_DEFINITIONS` and +:prop_tgt:`INCLUDE_DIRECTORIES` target properties from the target it is being +invoked for, and for the appropriate build configuration. + The :prop_tgt:`AUTOMOC` target property may be pre-set for all following targets by setting the :variable:`CMAKE_AUTOMOC` variable. The :prop_tgt:`AUTOMOC_MOC_OPTIONS` target property may be populated to set diff --git a/Help/prop_tgt/AUTOMOC.rst b/Help/prop_tgt/AUTOMOC.rst index b42643f..4ac9b6e 100644 --- a/Help/prop_tgt/AUTOMOC.rst +++ b/Help/prop_tgt/AUTOMOC.rst @@ -8,31 +8,41 @@ preprocessor automatically, i.e. without having to use the :module:`QT4_WRAP_CPP() ` or QT5_WRAP_CPP() macro. Currently Qt4 and Qt5 are supported. -When this property is set ``ON``, CMake will scan the +When this property is set ``ON``, CMake will scan the header and source files at build time and invoke moc accordingly. -* If an ``#include`` statement like ``#include "moc_foo.cpp"`` is found, - the ``Q_OBJECT`` class declaration is expected in the header, and - ``moc`` is run on the header file. A ``moc_foo.cpp`` file will be - generated from the source's header into the - ``/_autogen/include`` - directory which is automatically added to the target's +* If an ``#include`` statement like ``#include "moc_.cpp"`` is found, + the ``Q_OBJECT`` or ``Q_GADGET`` macros are expected in an otherwise empty + line of the ``.h(xx)`` header file. ``moc`` is run on the header file to + generate ``moc_.cpp`` in the + ``/_autogen/include`` directory + which is automatically added to the target's :prop_tgt:`INCLUDE_DIRECTORIES`. This allows the compiler to find the - included ``moc_foo.cpp`` file regardless of the location the original source. - However, if multiple source files in different directories do this then their - generated moc files would collide. In this case a diagnostic will be issued. - -* If an ``#include`` statement like ``#include "foo.moc"`` is found, - then a ``Q_OBJECT`` is expected in the current source file and ``moc`` - is run on the file itself. Additionally, header files with the same - base name (like ``foo.h``) or ``_p`` appended to the base name (like - ``foo_p.h``) are parsed for ``Q_OBJECT`` macros, and if found, ``moc`` - is also executed on those files. ``AUTOMOC`` checks multiple header - alternative extensions, such as ``hpp``, ``hxx`` etc when searching - for headers. The resulting moc files, which are not included as shown - above in any of the source files are included in a generated - ``moc_compilation.cpp`` file, which is compiled as part of the - target. + included ``moc_.cpp`` file regardless of the location the + original source. + +* If an ``#include`` statement like ``#include ".moc"`` is found, + then ``Q_OBJECT`` or ``Q_GADGET`` macros are expected in the current source + file and ``moc`` is run on the source file itself. + +* Header files that are not included by an ``#include "moc_.cpp"`` + statement are nonetheless scanned for ``Q_OBJECT`` or ``Q_GADGET`` macros. + The resulting ``moc_.cpp`` files are generated in custom + directories and automatically included in the generated + ``/_autogen/moc_compilation.cpp`` file, + which is compiled as part of the target. The custom directories help to + avoid name collisions for moc files with the same ````. + +* Additionally, header files with the same base name as a source file, + (like ``.h``) or ``_p`` appended to the base name (like + ``_p.h``), are parsed for ``Q_OBJECT`` or ``Q_GADGET`` macros, + and if found, ``moc`` is also executed on those files. + +* ``AUTOMOC`` always checks multiple header alternative extensions, + such as ``hpp``, ``hxx``, etc. when searching for headers. + +* ``AUTOMOC`` looks for the ``Q_PLUGIN_METADATA`` macro and reruns the + ``moc`` when the file addressed by the ``FILE`` argument of the macro changes. This property is initialized by the value of the :variable:`CMAKE_AUTOMOC` variable if it is set when a target is created. https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ff4800b1f6f2f7041e76d85f41fb8104181ee23c commit ff4800b1f6f2f7041e76d85f41fb8104181ee23c Author: Sebastian Holtermann AuthorDate: Sun Feb 19 18:35:40 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:16:43 2017 -0500 Autogen: Add release notes for Q_PLUGIN_METADATA support diff --git a/Help/release/dev/Autogen_json.rst b/Help/release/dev/Autogen_json.rst new file mode 100644 index 0000000..73bbdf1 --- /dev/null +++ b/Help/release/dev/Autogen_json.rst @@ -0,0 +1,10 @@ +AutoGen json +------------ + +* When using :prop_tgt:`AUTOMOC`, CMake scans for the presence of the + ``Q_PLUGIN_METADATA`` macro and reruns moc when the file from the + macro's ``FILE`` argument changes. + +* When :prop_tgt:`AUTOMOC` detects an include statement of the form + ``#include "moc_.cpp"`` the respective header file is searched + for in the :prop_tgt:`INCLUDE_DIRECTORIES` of the target as well. https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=bbae069eea447504158176f7eb9fb7db7a44c7bf commit bbae069eea447504158176f7eb9fb7db7a44c7bf Author: Sebastian Holtermann AuthorDate: Sun Feb 19 17:24:30 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:16:42 2017 -0500 Autogen: Tests: Set different compression levels in rcc test diff --git a/Tests/QtAutogen/sameName/CMakeLists.txt b/Tests/QtAutogen/sameName/CMakeLists.txt index 9e47a3e..4d2dcd9 100644 --- a/Tests/QtAutogen/sameName/CMakeLists.txt +++ b/Tests/QtAutogen/sameName/CMakeLists.txt @@ -18,3 +18,14 @@ add_executable(sameName ) target_link_libraries(sameName ${QT_LIBRARIES}) set_target_properties(sameName PROPERTIES AUTOMOC TRUE AUTORCC TRUE) + +# Set different compression levels +if (QT_TEST_VERSION STREQUAL 4) + set(rccCompress "-compress") +else() + set(rccCompress "--compress") +endif() +set_target_properties(sameName PROPERTIES AUTORCC_OPTIONS "${rccCompress};0" ) +set_source_files_properties(aaa/data.qrc PROPERTIES AUTORCC_OPTIONS "${rccCompress};1" ) +set_source_files_properties(bbb/data.qrc PROPERTIES AUTORCC_OPTIONS "${rccCompress};2" ) +set_source_files_properties(ccc/data.qrc PROPERTIES AUTORCC_OPTIONS "${rccCompress};3" ) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8571cca02d0ec9cd6b752038750e91a5c25ad259 commit 8571cca02d0ec9cd6b752038750e91a5c25ad259 Author: Sebastian Holtermann AuthorDate: Sun Feb 19 16:46:47 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:16:42 2017 -0500 Autogen: Overhaul and simplify AutogenInfo.cmake file generation diff --git a/Modules/AutogenInfo.cmake.in b/Modules/AutogenInfo.cmake.in index 3135909..b647ecf 100644 --- a/Modules/AutogenInfo.cmake.in +++ b/Modules/AutogenInfo.cmake.in @@ -1,5 +1,5 @@ # Target names -set(AM_TARGET_NAME @_moc_target_name@) +set(AM_TARGET_NAME @_autogen_target_name@) set(AM_ORIGIN_TARGET_NAME @_origin_target_name@) # Directories and files set(AM_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@/") @@ -10,16 +10,16 @@ set(AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE "@CMAKE_INCLUDE_DIRECTORIES_PROJ set(AM_SOURCES @_sources@) set(AM_HEADERS @_headers@) # Qt environment -set(AM_QT_VERSION_MAJOR "@_target_qt_version@") -set(AM_QT_MOC_EXECUTABLE "@_qt_moc_executable@") -set(AM_QT_UIC_EXECUTABLE "@_qt_uic_executable@") -set(AM_QT_RCC_EXECUTABLE "@_qt_rcc_executable@") +set(AM_QT_VERSION_MAJOR @_qt_version_major@) +set(AM_QT_MOC_EXECUTABLE @_qt_moc_executable@) +set(AM_QT_UIC_EXECUTABLE @_qt_uic_executable@) +set(AM_QT_RCC_EXECUTABLE @_qt_rcc_executable@) # MOC settings set(AM_MOC_SKIP @_moc_skip@) set(AM_MOC_COMPILE_DEFINITIONS @_moc_compile_defs@) set(AM_MOC_INCLUDES @_moc_incs@) set(AM_MOC_OPTIONS @_moc_options@) -set(AM_MOC_RELAXED_MODE "@_moc_relaxed_mode@") +set(AM_MOC_RELAXED_MODE @_moc_relaxed_mode@) # UIC settings set(AM_UIC_SKIP @_uic_skip@) set(AM_UIC_TARGET_OPTIONS @_uic_target_options@) diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index c201023..c9d1c24 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -55,6 +55,13 @@ static std::string utilStripCR(std::string const& line) return line; } +static std::string GetSafeProperty(cmGeneratorTarget const* target, + const char* key) +{ + const char* tmp = target->GetProperty(key); + return std::string((tmp != CM_NULLPTR) ? tmp : ""); +} + static std::string GetAutogenTargetName(cmGeneratorTarget const* target) { std::string autogenTargetName = target->GetName(); @@ -118,19 +125,33 @@ static void GetCompileDefinitionsAndDirectories( } } +static void AddDefinitionEscaped(cmMakefile* makefile, const char* key, + const std::string& value) +{ + makefile->AddDefinition(key, + cmOutputConverter::EscapeForCMake(value).c_str()); +} + +static void AddDefinitionEscaped(cmMakefile* makefile, const char* key, + const std::vector& values) +{ + makefile->AddDefinition( + key, cmOutputConverter::EscapeForCMake(cmJoin(values, ";")).c_str()); +} + static void SetupSourceFiles(cmGeneratorTarget const* target, std::vector& mocUicSources, std::vector& mocUicHeaders, - std::vector& skipMocList, - std::vector& skipUicList) + std::vector& mocSkipList, + std::vector& uicSkipList) { cmMakefile* makefile = target->Target->GetMakefile(); std::vector srcFiles; target->GetConfigCommonSourceFiles(srcFiles); - const bool targetMoc = target->GetPropertyAsBool("AUTOMOC"); - const bool targetUic = target->GetPropertyAsBool("AUTOUIC"); + const bool mocTarget = target->GetPropertyAsBool("AUTOMOC"); + const bool uicTarget = target->GetPropertyAsBool("AUTOUIC"); cmFilePathChecksum fpathCheckSum(makefile); for (std::vector::const_iterator fileIt = srcFiles.begin(); @@ -151,22 +172,22 @@ static void SetupSourceFiles(cmGeneratorTarget const* target, // Skip flags const bool skipAll = cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOGEN")); - const bool skipMoc = + const bool mocSkip = skipAll || cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOMOC")); - const bool skipUic = + const bool uicSkip = skipAll || cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOUIC")); // 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 // processing - if (skipMoc) { - skipMocList.push_back(absFile); + if (mocSkip) { + mocSkipList.push_back(absFile); } - if (skipUic) { - skipUicList.push_back(absFile); + if (uicSkip) { + uicSkipList.push_back(absFile); } - if ((targetMoc && !skipMoc) || (targetUic && !skipUic)) { + if ((mocTarget && !mocSkip) || (uicTarget && !uicSkip)) { // Add file name to sources or headers list switch (fileType) { case cmSystemTools::CXX_FILE_FORMAT: @@ -184,80 +205,85 @@ static void SetupSourceFiles(cmGeneratorTarget const* target, static void MocSetupAutoTarget( cmGeneratorTarget const* target, const std::string& autogenTargetName, - std::vector const& skipMoc, + const std::string& qtMajorVersion, + std::vector const& mocSkipList, std::map& configIncludes, std::map& configDefines) { cmLocalGenerator* lg = target->GetLocalGenerator(); cmMakefile* makefile = target->Target->GetMakefile(); - const char* tmp = target->GetProperty("AUTOMOC_MOC_OPTIONS"); - std::string _moc_options = (tmp != CM_NULLPTR ? tmp : ""); - makefile->AddDefinition( - "_moc_options", cmOutputConverter::EscapeForCMake(_moc_options).c_str()); - makefile->AddDefinition( - "_moc_skip", - cmOutputConverter::EscapeForCMake(cmJoin(skipMoc, ";")).c_str()); - bool relaxedMode = makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE"); - makefile->AddDefinition("_moc_relaxed_mode", relaxedMode ? "TRUE" : "FALSE"); - - std::string _moc_incs; - std::string _moc_compile_defs; - std::vector configs; - const std::string& config = makefile->GetConfigurations(configs); - GetCompileDefinitionsAndDirectories(target, config, _moc_incs, - _moc_compile_defs); + AddDefinitionEscaped(makefile, "_moc_options", + GetSafeProperty(target, "AUTOMOC_MOC_OPTIONS")); + AddDefinitionEscaped(makefile, "_moc_skip", mocSkipList); + AddDefinitionEscaped(makefile, "_moc_relaxed_mode", + makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE") ? "TRUE" + : "FALSE"); - makefile->AddDefinition( - "_moc_incs", cmOutputConverter::EscapeForCMake(_moc_incs).c_str()); - makefile->AddDefinition( - "_moc_compile_defs", - cmOutputConverter::EscapeForCMake(_moc_compile_defs).c_str()); - - for (std::vector::const_iterator li = configs.begin(); - li != configs.end(); ++li) { - std::string config_moc_incs; - std::string config_moc_compile_defs; - GetCompileDefinitionsAndDirectories(target, *li, config_moc_incs, - config_moc_compile_defs); - if (config_moc_incs != _moc_incs) { - configIncludes[*li] = cmOutputConverter::EscapeForCMake(config_moc_incs); - if (_moc_incs.empty()) { - _moc_incs = config_moc_incs; + // Moc includes and compile definitions + { + std::string _moc_incs; + std::string _moc_compile_defs; + std::vector configs; + { + const std::string& config = makefile->GetConfigurations(configs); + GetCompileDefinitionsAndDirectories(target, config, _moc_incs, + _moc_compile_defs); + AddDefinitionEscaped(makefile, "_moc_incs", _moc_incs); + AddDefinitionEscaped(makefile, "_moc_compile_defs", _moc_compile_defs); + } + for (std::vector::const_iterator li = configs.begin(); + li != configs.end(); ++li) { + std::string config_moc_incs; + std::string config_moc_compile_defs; + GetCompileDefinitionsAndDirectories(target, *li, config_moc_incs, + config_moc_compile_defs); + if (config_moc_incs != _moc_incs) { + configIncludes[*li] = + cmOutputConverter::EscapeForCMake(config_moc_incs); + if (_moc_incs.empty()) { + _moc_incs = config_moc_incs; + } } - } - if (config_moc_compile_defs != _moc_compile_defs) { - configDefines[*li] = - cmOutputConverter::EscapeForCMake(config_moc_compile_defs); - if (_moc_compile_defs.empty()) { - _moc_compile_defs = config_moc_compile_defs; + if (config_moc_compile_defs != _moc_compile_defs) { + configDefines[*li] = + cmOutputConverter::EscapeForCMake(config_moc_compile_defs); + if (_moc_compile_defs.empty()) { + _moc_compile_defs = config_moc_compile_defs; + } } } } - const char* qtVersion = makefile->GetDefinition("_target_qt_version"); - if (strcmp(qtVersion, "5") == 0) { - cmGeneratorTarget* qt5Moc = lg->FindGeneratorTargetToUse("Qt5::moc"); - if (!qt5Moc) { - cmSystemTools::Error("Qt5::moc target not found ", - autogenTargetName.c_str()); - return; + // Moc executable + { + std::string err; + const char* mocExec = CM_NULLPTR; + if (qtMajorVersion == "5") { + cmGeneratorTarget* qt5Moc = lg->FindGeneratorTargetToUse("Qt5::moc"); + if (qt5Moc != CM_NULLPTR) { + mocExec = qt5Moc->ImportedGetLocation(""); + } else { + err = "Qt5::moc target not found " + autogenTargetName; + } + } else if (qtMajorVersion == "4") { + cmGeneratorTarget* qt4Moc = lg->FindGeneratorTargetToUse("Qt4::moc"); + if (qt4Moc != CM_NULLPTR) { + mocExec = qt4Moc->ImportedGetLocation(""); + } else { + err = "Qt4::moc target not found " + autogenTargetName; + } + } else { + err = "The CMAKE_AUTOMOC feature supports only Qt 4 and Qt 5 "; + err += autogenTargetName; } - makefile->AddDefinition("_qt_moc_executable", - qt5Moc->ImportedGetLocation("")); - } else if (strcmp(qtVersion, "4") == 0) { - cmGeneratorTarget* qt4Moc = lg->FindGeneratorTargetToUse("Qt4::moc"); - if (!qt4Moc) { - cmSystemTools::Error("Qt4::moc target not found ", - autogenTargetName.c_str()); - return; + // Add definition or error + if (err.empty()) { + AddDefinitionEscaped(makefile, "_qt_moc_executable", + mocExec ? mocExec : ""); + } else { + cmSystemTools::Error(err.c_str()); } - makefile->AddDefinition("_qt_moc_executable", - qt4Moc->ImportedGetLocation("")); - } else { - cmSystemTools::Error("The CMAKE_AUTOMOC feature supports only Qt 4 and " - "Qt 5 ", - autogenTargetName.c_str()); } } @@ -270,126 +296,126 @@ static void UicGetOpts(cmGeneratorTarget const* target, } static void UicSetupAutoTarget( - cmGeneratorTarget const* target, std::vector const& skipUic, + cmGeneratorTarget const* target, const std::string& qtMajorVersion, + std::vector const& uicSkipList, std::map& configUicOptions) { cmLocalGenerator* lg = target->GetLocalGenerator(); cmMakefile* makefile = target->Target->GetMakefile(); - std::set skipped; - skipped.insert(skipUic.begin(), skipUic.end()); + AddDefinitionEscaped(makefile, "_uic_skip", uicSkipList); - makefile->AddDefinition( - "_uic_skip", - cmOutputConverter::EscapeForCMake(cmJoin(skipUic, ";")).c_str()); - - std::vector uiFilesWithOptions = - makefile->GetQtUiFilesWithOptions(); - - const char* qtVersion = makefile->GetDefinition("_target_qt_version"); - - std::string _uic_opts; - std::vector configs; - const std::string& config = makefile->GetConfigurations(configs); - UicGetOpts(target, config, _uic_opts); - - if (!_uic_opts.empty()) { - _uic_opts = cmOutputConverter::EscapeForCMake(_uic_opts); - makefile->AddDefinition("_uic_target_options", _uic_opts.c_str()); - } - for (std::vector::const_iterator li = configs.begin(); - li != configs.end(); ++li) { - std::string config_uic_opts; - UicGetOpts(target, *li, config_uic_opts); - if (config_uic_opts != _uic_opts) { - configUicOptions[*li] = - cmOutputConverter::EscapeForCMake(config_uic_opts); - if (_uic_opts.empty()) { - _uic_opts = config_uic_opts; + // Uic target options + { + std::string _uic_opts; + std::vector configs; + UicGetOpts(target, makefile->GetConfigurations(configs), _uic_opts); + + AddDefinitionEscaped(makefile, "_uic_target_options", _uic_opts); + + for (std::vector::const_iterator li = configs.begin(); + li != configs.end(); ++li) { + std::string config_uic_opts; + UicGetOpts(target, *li, config_uic_opts); + if (config_uic_opts != _uic_opts) { + configUicOptions[*li] = + cmOutputConverter::EscapeForCMake(config_uic_opts); + if (_uic_opts.empty()) { + _uic_opts = config_uic_opts; + } } } } - - std::string uiFileFiles; - std::string uiFileOptions; - const char* sep = ""; - - for (std::vector::const_iterator fileIt = - uiFilesWithOptions.begin(); - fileIt != uiFilesWithOptions.end(); ++fileIt) { - cmSourceFile* sf = *fileIt; - std::string absFile = cmsys::SystemTools::GetRealPath(sf->GetFullPath()); - - if (!skipped.insert(absFile).second) { - continue; + // Uic files options + { + std::vector uiFileFiles; + std::vector uiFileOptions; + { + std::set skipped; + skipped.insert(uicSkipList.begin(), uicSkipList.end()); + + const std::vector uiFilesWithOptions = + makefile->GetQtUiFilesWithOptions(); + for (std::vector::const_iterator fileIt = + uiFilesWithOptions.begin(); + fileIt != uiFilesWithOptions.end(); ++fileIt) { + cmSourceFile* sf = *fileIt; + const std::string absFile = + cmsys::SystemTools::GetRealPath(sf->GetFullPath()); + if (skipped.insert(absFile).second) { + // The file wasn't skipped + uiFileFiles.push_back(absFile); + { + std::string opts = sf->GetProperty("AUTOUIC_OPTIONS"); + cmSystemTools::ReplaceString(opts, ";", "@list_sep@"); + uiFileOptions.push_back(opts); + } + } + } } - uiFileFiles += sep; - uiFileFiles += absFile; - uiFileOptions += sep; - std::string opts = sf->GetProperty("AUTOUIC_OPTIONS"); - cmSystemTools::ReplaceString(opts, ";", "@list_sep@"); - uiFileOptions += opts; - sep = ";"; + AddDefinitionEscaped(makefile, "_qt_uic_options_files", uiFileFiles); + AddDefinitionEscaped(makefile, "_qt_uic_options_options", uiFileOptions); } - makefile->AddDefinition( - "_qt_uic_options_files", - cmOutputConverter::EscapeForCMake(uiFileFiles).c_str()); - makefile->AddDefinition( - "_qt_uic_options_options", - cmOutputConverter::EscapeForCMake(uiFileOptions).c_str()); - - std::string targetName = target->GetName(); - if (strcmp(qtVersion, "5") == 0) { - cmGeneratorTarget* qt5Uic = lg->FindGeneratorTargetToUse("Qt5::uic"); - if (!qt5Uic) { - // Project does not use Qt5Widgets, but has AUTOUIC ON anyway + // Uic executable + { + std::string err; + const char* uicExec = CM_NULLPTR; + if (qtMajorVersion == "5") { + cmGeneratorTarget* qt5Uic = lg->FindGeneratorTargetToUse("Qt5::uic"); + if (qt5Uic != CM_NULLPTR) { + uicExec = qt5Uic->ImportedGetLocation(""); + } else { + // Project does not use Qt5Widgets, but has AUTOUIC ON anyway + } + } else if (qtMajorVersion == "4") { + cmGeneratorTarget* qt4Uic = lg->FindGeneratorTargetToUse("Qt4::uic"); + if (qt4Uic != CM_NULLPTR) { + uicExec = qt4Uic->ImportedGetLocation(""); + } else { + err = "Qt4::uic target not found " + target->GetName(); + } } else { - makefile->AddDefinition("_qt_uic_executable", - qt5Uic->ImportedGetLocation("")); + err = "The CMAKE_AUTOUIC feature supports only Qt 4 and Qt 5 "; + err += target->GetName(); } - } else if (strcmp(qtVersion, "4") == 0) { - cmGeneratorTarget* qt4Uic = lg->FindGeneratorTargetToUse("Qt4::uic"); - if (!qt4Uic) { - cmSystemTools::Error("Qt4::uic target not found ", targetName.c_str()); - return; + // Add definition or error + if (err.empty()) { + AddDefinitionEscaped(makefile, "_qt_uic_executable", + uicExec ? uicExec : ""); + } else { + cmSystemTools::Error(err.c_str()); } - makefile->AddDefinition("_qt_uic_executable", - qt4Uic->ImportedGetLocation("")); - } else { - cmSystemTools::Error("The CMAKE_AUTOUIC feature supports only Qt 4 and " - "Qt 5 ", - targetName.c_str()); } } static std::string RccGetExecutable(cmGeneratorTarget const* target, const std::string& qtMajorVersion) { + std::string rccExec; cmLocalGenerator* lg = target->GetLocalGenerator(); - - std::string const& targetName = target->GetName(); if (qtMajorVersion == "5") { cmGeneratorTarget* qt5Rcc = lg->FindGeneratorTargetToUse("Qt5::rcc"); - if (!qt5Rcc) { - cmSystemTools::Error("Qt5::rcc target not found ", targetName.c_str()); - return std::string(); + if (qt5Rcc != CM_NULLPTR) { + rccExec = qt5Rcc->ImportedGetLocation(""); + } else { + cmSystemTools::Error("Qt5::rcc target not found ", + target->GetName().c_str()); } - return qt5Rcc->ImportedGetLocation(""); - } - if (qtMajorVersion == "4") { + } else if (qtMajorVersion == "4") { cmGeneratorTarget* qt4Rcc = lg->FindGeneratorTargetToUse("Qt4::rcc"); - if (!qt4Rcc) { - cmSystemTools::Error("Qt4::rcc target not found ", targetName.c_str()); - return std::string(); + if (qt4Rcc != CM_NULLPTR) { + rccExec = qt4Rcc->ImportedGetLocation(""); + } else { + cmSystemTools::Error("Qt4::rcc target not found ", + target->GetName().c_str()); } - return qt4Rcc->ImportedGetLocation(""); + } else { + cmSystemTools::Error( + "The CMAKE_AUTORCC feature supports only Qt 4 and Qt 5 ", + target->GetName().c_str()); } - - cmSystemTools::Error("The CMAKE_AUTORCC feature supports only Qt 4 and " - "Qt 5 ", - targetName.c_str()); - return std::string(); + return rccExec; } static void RccMergeOptions(std::vector& opts, @@ -399,26 +425,31 @@ static void RccMergeOptions(std::vector& opts, static const char* valueOptions[] = { "name", "root", "compress", "threshold" }; std::vector extraOpts; - for (std::vector::const_iterator it = fileOpts.begin(); - it != fileOpts.end(); ++it) { + for (std::vector::const_iterator fit = fileOpts.begin(); + fit != fileOpts.end(); ++fit) { std::vector::iterator existingIt = - std::find(opts.begin(), opts.end(), *it); + std::find(opts.begin(), opts.end(), *fit); if (existingIt != opts.end()) { - const char* o = it->c_str(); - if (*o == '-') { - ++o; - } - if (isQt5 && *o == '-') { - ++o; + const char* optName = fit->c_str(); + if (*optName == '-') { + ++optName; + if (isQt5 && *optName == '-') { + ++optName; + } } - if (std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions), - cmStrCmp(*it)) != cmArrayEnd(valueOptions)) { - assert(existingIt + 1 != opts.end()); - *(existingIt + 1) = *(it + 1); - ++it; + // Test if this is a value option and change the existing value + if ((optName != fit->c_str()) && + std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions), + cmStrCmp(optName)) != cmArrayEnd(valueOptions)) { + const std::vector::iterator existValueIt(existingIt + 1); + const std::vector::const_iterator fileValueIt(fit + 1); + if ((existValueIt != opts.end()) && (fileValueIt != fileOpts.end())) { + *existValueIt = *fileValueIt; + ++fit; + } } } else { - extraOpts.push_back(*it); + extraOpts.push_back(*fit); } } opts.insert(opts.end(), extraOpts.begin(), extraOpts.end()); @@ -528,23 +559,20 @@ static bool RccListInputsQt4(cmSourceFile* sf, } cmsys::RegularExpression fileMatchRegex("(]*>)"); size_t offset = 0; while (fileMatchRegex.find(qrcContents.c_str() + offset)) { std::string qrcEntry = fileMatchRegex.match(1); - offset += qrcEntry.size(); - - cmsys::RegularExpression fileReplaceRegex("(^]*>)"); - fileReplaceRegex.find(qrcEntry); - std::string tag = fileReplaceRegex.match(1); - - qrcEntry = qrcEntry.substr(tag.size()); - + { + fileReplaceRegex.find(qrcEntry); + std::string tag = fileReplaceRegex.match(1); + qrcEntry = qrcEntry.substr(tag.size()); + } if (!cmSystemTools::FileIsFullPath(qrcEntry.c_str())) { qrcEntry = sf->GetLocation().GetDirectory() + "/" + qrcEntry; } - depends.push_back(qrcEntry); } return true; @@ -565,89 +593,69 @@ static bool RccListInputs(const std::string& qtMajorVersion, cmSourceFile* sf, static void RccSetupAutoTarget(cmGeneratorTarget const* target, const std::string& qtMajorVersion) { - std::string _rcc_files; - const char* sepRccFiles = ""; cmMakefile* makefile = target->Target->GetMakefile(); - - std::vector srcFiles; - target->GetConfigCommonSourceFiles(srcFiles); - - std::string qrcInputs; - const char* qrcInputsSep = ""; - - std::string rccFileFiles; - std::string rccFileOptions; - const char* optionSep = ""; - const bool qtMajorVersion5 = (qtMajorVersion == "5"); - - std::vector rccOptions; + std::vector _rcc_files; + std::vector _rcc_inputs; + std::vector rccFileFiles; + std::vector rccFileOptions; + std::vector rccOptionsTarget; if (const char* opts = target->GetProperty("AUTORCC_OPTIONS")) { - cmSystemTools::ExpandListArgument(opts, rccOptions); + cmSystemTools::ExpandListArgument(opts, rccOptionsTarget); } + std::vector srcFiles; + target->GetConfigCommonSourceFiles(srcFiles); for (std::vector::const_iterator fileIt = srcFiles.begin(); fileIt != srcFiles.end(); ++fileIt) { cmSourceFile* sf = *fileIt; - std::string ext = sf->GetExtension(); - if (ext == "qrc") { - std::string absFile = cmsys::SystemTools::GetRealPath(sf->GetFullPath()); + if (sf->GetExtension() == "qrc") { const bool skip = cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOGEN")) || cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC")); - if (!skip) { - _rcc_files += sepRccFiles; - _rcc_files += absFile; - sepRccFiles = ";"; - - if (const char* prop = sf->GetProperty("AUTORCC_OPTIONS")) { - std::vector optsVec; - cmSystemTools::ExpandListArgument(prop, optsVec); - RccMergeOptions(rccOptions, optsVec, qtMajorVersion5); - } - - if (!rccOptions.empty()) { - rccFileFiles += optionSep; - rccFileFiles += absFile; - rccFileOptions += optionSep; - } - const char* listSep = ""; - for (std::vector::const_iterator it = rccOptions.begin(); - it != rccOptions.end(); ++it) { - rccFileOptions += listSep; - rccFileOptions += *it; - listSep = "@list_sep@"; + const std::string absFile = + cmsys::SystemTools::GetRealPath(sf->GetFullPath()); + // qrc file + _rcc_files.push_back(absFile); + // qrc file entries + { + std::string entriesList; + if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) { + std::vector depends; + if (RccListInputs(qtMajorVersion, sf, target, depends)) { + entriesList = cmJoin(depends, "@list_sep@"); + } else { + return; + } + } + _rcc_inputs.push_back(entriesList); } - optionSep = ";"; - - std::string entriesList; - if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) { - std::vector depends; - if (RccListInputs(qtMajorVersion, sf, target, depends)) { - entriesList = cmJoin(depends, "@list_sep@"); - } else { - return; + // rcc options for this qrc file + { + // Merged target and file options + std::vector rccOptions(rccOptionsTarget); + if (const char* prop = sf->GetProperty("AUTORCC_OPTIONS")) { + std::vector optsVec; + cmSystemTools::ExpandListArgument(prop, optsVec); + RccMergeOptions(rccOptions, optsVec, qtMajorVersion5); + } + // Only store non empty options lists + if (!rccOptions.empty()) { + rccFileFiles.push_back(absFile); + rccFileOptions.push_back(cmJoin(rccOptions, "@list_sep@")); } } - qrcInputs += qrcInputsSep; - qrcInputs += entriesList; - qrcInputsSep = ";"; } } } - makefile->AddDefinition( - "_rcc_inputs", cmOutputConverter::EscapeForCMake(qrcInputs).c_str()); - makefile->AddDefinition( - "_rcc_files", cmOutputConverter::EscapeForCMake(_rcc_files).c_str()); - makefile->AddDefinition( - "_rcc_options_files", - cmOutputConverter::EscapeForCMake(rccFileFiles).c_str()); - makefile->AddDefinition( - "_rcc_options_options", - cmOutputConverter::EscapeForCMake(rccFileOptions).c_str()); - makefile->AddDefinition("_qt_rcc_executable", - RccGetExecutable(target, qtMajorVersion).c_str()); + + AddDefinitionEscaped(makefile, "_rcc_files", _rcc_files); + AddDefinitionEscaped(makefile, "_rcc_inputs", _rcc_inputs); + AddDefinitionEscaped(makefile, "_rcc_options_files", rccFileFiles); + AddDefinitionEscaped(makefile, "_rcc_options_options", rccFileOptions); + AddDefinitionEscaped(makefile, "_qt_rcc_executable", + RccGetExecutable(target, qtMajorVersion)); } void cmQtAutoGeneratorInitializer::InitializeAutogenSources( @@ -874,47 +882,42 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( cmMakefile::ScopePushPop varScope(makefile); static_cast(varScope); - // create a custom target for running generators at buildtime: - const std::string autogenTargetName = GetAutogenTargetName(target); - const std::string qtMajorVersion = GetQtMajorVersion(target); - - makefile->AddDefinition( - "_moc_target_name", - cmOutputConverter::EscapeForCMake(autogenTargetName).c_str()); - makefile->AddDefinition( - "_origin_target_name", - cmOutputConverter::EscapeForCMake(target->GetName()).c_str()); - makefile->AddDefinition("_target_qt_version", qtMajorVersion.c_str()); - - std::vector mocUicSources; - std::vector mocUicHeaders; - std::vector skipMoc; - std::vector skipUic; std::map configMocIncludes; std::map configMocDefines; std::map configUicOptions; + { + // create a custom target for running generators at buildtime: + const std::string autogenTargetName = GetAutogenTargetName(target); + const std::string qtMajorVersion = GetQtMajorVersion(target); - if (target->GetPropertyAsBool("AUTOMOC") || - target->GetPropertyAsBool("AUTOUIC") || - target->GetPropertyAsBool("AUTORCC")) { - SetupSourceFiles(target, mocUicSources, mocUicHeaders, skipMoc, skipUic); - } - makefile->AddDefinition( - "_sources", - cmOutputConverter::EscapeForCMake(cmJoin(mocUicSources, ";")).c_str()); - makefile->AddDefinition( - "_headers", - cmOutputConverter::EscapeForCMake(cmJoin(mocUicHeaders, ";")).c_str()); + AddDefinitionEscaped(makefile, "_autogen_target_name", autogenTargetName); + AddDefinitionEscaped(makefile, "_origin_target_name", target->GetName()); + AddDefinitionEscaped(makefile, "_qt_version_major", qtMajorVersion); - if (target->GetPropertyAsBool("AUTOMOC")) { - MocSetupAutoTarget(target, autogenTargetName, skipMoc, configMocIncludes, - configMocDefines); - } - if (target->GetPropertyAsBool("AUTOUIC")) { - UicSetupAutoTarget(target, skipUic, configUicOptions); - } - if (target->GetPropertyAsBool("AUTORCC")) { - RccSetupAutoTarget(target, qtMajorVersion); + std::vector _sources; + std::vector _headers; + std::vector mocSkipList; + std::vector uicSkipList; + + if (target->GetPropertyAsBool("AUTOMOC") || + target->GetPropertyAsBool("AUTOUIC") || + target->GetPropertyAsBool("AUTORCC")) { + SetupSourceFiles(target, _sources, _headers, mocSkipList, uicSkipList); + } + AddDefinitionEscaped(makefile, "_sources", _sources); + AddDefinitionEscaped(makefile, "_headers", _headers); + + if (target->GetPropertyAsBool("AUTOMOC")) { + MocSetupAutoTarget(target, autogenTargetName, qtMajorVersion, + mocSkipList, configMocIncludes, configMocDefines); + } + if (target->GetPropertyAsBool("AUTOUIC")) { + UicSetupAutoTarget(target, qtMajorVersion, uicSkipList, + configUicOptions); + } + if (target->GetPropertyAsBool("AUTORCC")) { + RccSetupAutoTarget(target, qtMajorVersion); + } } // Generate config file @@ -926,7 +929,7 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( makefile->ConfigureFile(inputFile.c_str(), outputFile.c_str(), false, true, false); - // Append custom definitions to config file + // Append custom config definitions to info file if (!configMocDefines.empty() || !configMocIncludes.empty() || !configUicOptions.empty()) { @@ -948,33 +951,34 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( error += outputFile; error += " for writing."; cmSystemTools::Error(error.c_str()); - return; - } - if (!configMocDefines.empty()) { - for (std::map::iterator - it = configMocDefines.begin(), - end = configMocDefines.end(); - it != end; ++it) { - infoFile << "set(AM_MOC_COMPILE_DEFINITIONS_" << it->first << " " - << it->second << ")\n"; + } else { + infoFile << "# Configuration specific options\n"; + if (!configMocDefines.empty()) { + for (std::map::iterator + it = configMocDefines.begin(), + end = configMocDefines.end(); + it != end; ++it) { + infoFile << "set(AM_MOC_COMPILE_DEFINITIONS_" << it->first << " " + << it->second << ")\n"; + } } - } - if (!configMocIncludes.empty()) { - for (std::map::iterator - it = configMocIncludes.begin(), - end = configMocIncludes.end(); - it != end; ++it) { - infoFile << "set(AM_MOC_INCLUDES_" << it->first << " " << it->second - << ")\n"; + if (!configMocIncludes.empty()) { + for (std::map::iterator + it = configMocIncludes.begin(), + end = configMocIncludes.end(); + it != end; ++it) { + infoFile << "set(AM_MOC_INCLUDES_" << it->first << " " << it->second + << ")\n"; + } } - } - if (!configUicOptions.empty()) { - for (std::map::iterator - it = configUicOptions.begin(), - end = configUicOptions.end(); - it != end; ++it) { - infoFile << "set(AM_UIC_TARGET_OPTIONS_" << it->first << " " - << it->second << ")\n"; + if (!configUicOptions.empty()) { + for (std::map::iterator + it = configUicOptions.begin(), + end = configUicOptions.end(); + it != end; ++it) { + infoFile << "set(AM_UIC_TARGET_OPTIONS_" << it->first << " " + << it->second << ")\n"; + } } } } ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 20 15:51:55 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 20 Feb 2017 15:51:55 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-345-g917c6f2 Message-ID: <20170220205155.AA278F9A16@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 917c6f27af57d87800cdcd066350e4bdce16027c (commit) via 377cd92a1705a3e75e218f25941f9009816c6182 (commit) via f50ac2dd0f3d3776f062487722cb1f86d7dbfd31 (commit) from c60b61be56000aef36904fdc04eb5bde79b3e1dc (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=917c6f27af57d87800cdcd066350e4bdce16027c commit 917c6f27af57d87800cdcd066350e4bdce16027c Merge: c60b61b 377cd92 Author: Brad King AuthorDate: Mon Feb 20 15:51:55 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 20 15:51:55 2017 -0500 Merge topic 'autogen_json' into next 377cd92a fixup! Autogen: Overhaul and simplify AutogenInfo.cmake file generation f50ac2dd fixup! Autogen: Overhaul moc include list generation https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=377cd92a1705a3e75e218f25941f9009816c6182 commit 377cd92a1705a3e75e218f25941f9009816c6182 Author: Brad King AuthorDate: Mon Feb 20 15:50:29 2017 -0500 Commit: Brad King CommitDate: Mon Feb 20 15:50:29 2017 -0500 fixup! Autogen: Overhaul and simplify AutogenInfo.cmake file generation diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index c9d1c24..52112ff 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -22,7 +22,6 @@ #endif #include -#include #include #include #include https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f50ac2dd0f3d3776f062487722cb1f86d7dbfd31 commit f50ac2dd0f3d3776f062487722cb1f86d7dbfd31 Author: Brad King AuthorDate: Mon Feb 20 15:49:30 2017 -0500 Commit: Brad King CommitDate: Mon Feb 20 15:49:30 2017 -0500 fixup! Autogen: Overhaul moc include list generation diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 2021e4a..236d4c5 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -7,7 +7,6 @@ #include #include -#include #include #include #include ----------------------------------------------------------------------- Summary of changes: Source/cmQtAutoGeneratorInitializer.cxx | 1 - Source/cmQtAutoGenerators.h | 1 - 2 files changed, 2 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 20 15:52:09 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 20 Feb 2017 15:52:09 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-373-g8e7033c Message-ID: <20170220205209.51616F9A40@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 8e7033c85264288c840edff511a03643f167e09c (commit) via a1b8afd2e4fd26d425f5dd197fd308cd8f8d853e (commit) via 11ad7564ba2834d170240d37883ffdd7b3327a65 (commit) via ca386093ae307dfd25917a520dca68319ce861a3 (commit) via 359cfdc68c2d606c32c15c0a3a68f8dacf7834eb (commit) via b0a44ed354fe3eea20fc7dbc7c467794ebea6593 (commit) via 928564fb8610e508448d5972c6dc83f4dfb64d7f (commit) via aee6c5b3d38b7150a3276d69e28b2705dc20d586 (commit) via 917af10b53626fabe9a833546450ac5d6af8b3ea (commit) via 4be7c81272e559b1ff572df5f5b274234a04a286 (commit) via 0136d1354b5957a1d583526dfdb74f176939f56c (commit) via 1fc9fe74dab4276b22abfd1a79fc344945350227 (commit) via 698a94c0d95ac865d40ed5caaac1a5e10194adf4 (commit) via 58ac0c6209b627137636e0feac6f4d59321dae54 (commit) via 1508ed9c65f1515313bca00790710820974cd7cc (commit) via e4f61a211b960d3eab0253a2986ac3aa705a2661 (commit) via 1224e67a0fd059aea194ad9a797e31a74d891618 (commit) via 20ed0f59e4bbd5850d1271f99b53dcaa22cac417 (commit) via f8125e7bee39b4b853fb9ea650a397dfb984a5e0 (commit) via 58699513c2248da7277b968d729bef5ba3471677 (commit) via d3980d2a959734370d2f7cf2f76d705ddf2da6e3 (commit) via d26601ec0897eec870fe95413362d242202d7f2b (commit) via c84bca1030332d23d0fc6d06050e7a174f39d78a (commit) via 78031e7cdcead6a348191158c674ec341fdd43be (commit) via c7f3bdedde2a38c8f2e46ca42f47efbde6252f1d (commit) via 17a2cfbcdd41ee607556794e5210744b90005dfb (commit) via 7111b59f020c3b6fa01136b608ce6777969f92e7 (commit) via 82e0d0642a42b0592be27ed20efb43e34aaa2091 (commit) from 917c6f27af57d87800cdcd066350e4bdce16027c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8e7033c85264288c840edff511a03643f167e09c commit 8e7033c85264288c840edff511a03643f167e09c Merge: 917c6f2 a1b8afd Author: Brad King AuthorDate: Mon Feb 20 15:52:07 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 20 15:52:07 2017 -0500 Merge topic 'autogen_json' into next a1b8afd2 Autogen: Documentation update 11ad7564 Autogen: Add release notes for Q_PLUGIN_METADATA support ca386093 Autogen: Tests: Set different compression levels in rcc test 359cfdc6 Autogen: Overhaul and simplify AutogenInfo.cmake file generation b0a44ed3 Autogen: Optimize GetCompileDefinitionsAndDirectories function 928564fb Autogen: Sort AutogenInfo.cmake.in aee6c5b3 Autogen: Tests: Add Q_PLUGIN_METADATA test 917af10b Autogen: Tests: Add moc include tests 4be7c812 Autogen: Tests: Clean comments 0136d135 Autogen: Log simplifications 1fc9fe74 Autogen: Only touch an unchanged moc_compilation.cpp 698a94c0 Autogen: Rebuild moc when Q_PLUGIN_METADATA json file changes 58ac0c62 Autogen: Use GetRealPath in central places only 1508ed9c Autogen: Search moc includes in include directories e4f61a21 Autogen: Sort includes before composing include options 1224e67a Autogen: Add FindInIncludeDirectories method ... https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a1b8afd2e4fd26d425f5dd197fd308cd8f8d853e commit a1b8afd2e4fd26d425f5dd197fd308cd8f8d853e Author: Sebastian Holtermann AuthorDate: Sun Feb 19 20:11:18 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:51:29 2017 -0500 Autogen: Documentation update Closes #15254 diff --git a/Help/manual/cmake-qt.7.rst b/Help/manual/cmake-qt.7.rst index 56d4ca7..e9da396 100644 --- a/Help/manual/cmake-qt.7.rst +++ b/Help/manual/cmake-qt.7.rst @@ -63,20 +63,24 @@ If a ``Q_OBJECT`` or ``Q_GADGET`` macro is found in a header file, ``moc`` will be run on the file. The result will be put into a file named according to ``moc_.cpp``. If the macro is found in a C++ implementation file, the moc output will be put into a file named according to -``.moc``, following the Qt conventions. The ``moc file`` may be -included by the user in the C++ implementation file with a preprocessor -``#include``. If it is not so included, it will be added to a separate file -which is compiled into the target. +``.moc``, following the Qt conventions. The ``.moc`` must +be included by the user in the C++ implementation file with a preprocessor +``#include``. -The ``moc`` command line will consume the :prop_tgt:`COMPILE_DEFINITIONS` and -:prop_tgt:`INCLUDE_DIRECTORIES` target properties from the target it is being -invoked for, and for the appropriate build configuration. - -The generated ``moc_*.cpp`` and ``*.moc`` files are placed in the +Included ``moc_*.cpp`` and ``*.moc`` files will be generated in the ``/_autogen/include`` directory which is automatically added to the target's :prop_tgt:`INCLUDE_DIRECTORIES`. (This differs from CMake 3.7 and below; see their documentation for details.) +Not included ``moc_.cpp`` files will be generated in custom +folders to avoid name collisions and included in a separate +``/_autogen/moc_compilation.cpp`` +file which is compiled into the target. + +The ``moc`` command line will consume the :prop_tgt:`COMPILE_DEFINITIONS` and +:prop_tgt:`INCLUDE_DIRECTORIES` target properties from the target it is being +invoked for, and for the appropriate build configuration. + The :prop_tgt:`AUTOMOC` target property may be pre-set for all following targets by setting the :variable:`CMAKE_AUTOMOC` variable. The :prop_tgt:`AUTOMOC_MOC_OPTIONS` target property may be populated to set diff --git a/Help/prop_tgt/AUTOMOC.rst b/Help/prop_tgt/AUTOMOC.rst index b42643f..4ac9b6e 100644 --- a/Help/prop_tgt/AUTOMOC.rst +++ b/Help/prop_tgt/AUTOMOC.rst @@ -8,31 +8,41 @@ preprocessor automatically, i.e. without having to use the :module:`QT4_WRAP_CPP() ` or QT5_WRAP_CPP() macro. Currently Qt4 and Qt5 are supported. -When this property is set ``ON``, CMake will scan the +When this property is set ``ON``, CMake will scan the header and source files at build time and invoke moc accordingly. -* If an ``#include`` statement like ``#include "moc_foo.cpp"`` is found, - the ``Q_OBJECT`` class declaration is expected in the header, and - ``moc`` is run on the header file. A ``moc_foo.cpp`` file will be - generated from the source's header into the - ``/_autogen/include`` - directory which is automatically added to the target's +* If an ``#include`` statement like ``#include "moc_.cpp"`` is found, + the ``Q_OBJECT`` or ``Q_GADGET`` macros are expected in an otherwise empty + line of the ``.h(xx)`` header file. ``moc`` is run on the header file to + generate ``moc_.cpp`` in the + ``/_autogen/include`` directory + which is automatically added to the target's :prop_tgt:`INCLUDE_DIRECTORIES`. This allows the compiler to find the - included ``moc_foo.cpp`` file regardless of the location the original source. - However, if multiple source files in different directories do this then their - generated moc files would collide. In this case a diagnostic will be issued. - -* If an ``#include`` statement like ``#include "foo.moc"`` is found, - then a ``Q_OBJECT`` is expected in the current source file and ``moc`` - is run on the file itself. Additionally, header files with the same - base name (like ``foo.h``) or ``_p`` appended to the base name (like - ``foo_p.h``) are parsed for ``Q_OBJECT`` macros, and if found, ``moc`` - is also executed on those files. ``AUTOMOC`` checks multiple header - alternative extensions, such as ``hpp``, ``hxx`` etc when searching - for headers. The resulting moc files, which are not included as shown - above in any of the source files are included in a generated - ``moc_compilation.cpp`` file, which is compiled as part of the - target. + included ``moc_.cpp`` file regardless of the location the + original source. + +* If an ``#include`` statement like ``#include ".moc"`` is found, + then ``Q_OBJECT`` or ``Q_GADGET`` macros are expected in the current source + file and ``moc`` is run on the source file itself. + +* Header files that are not included by an ``#include "moc_.cpp"`` + statement are nonetheless scanned for ``Q_OBJECT`` or ``Q_GADGET`` macros. + The resulting ``moc_.cpp`` files are generated in custom + directories and automatically included in the generated + ``/_autogen/moc_compilation.cpp`` file, + which is compiled as part of the target. The custom directories help to + avoid name collisions for moc files with the same ````. + +* Additionally, header files with the same base name as a source file, + (like ``.h``) or ``_p`` appended to the base name (like + ``_p.h``), are parsed for ``Q_OBJECT`` or ``Q_GADGET`` macros, + and if found, ``moc`` is also executed on those files. + +* ``AUTOMOC`` always checks multiple header alternative extensions, + such as ``hpp``, ``hxx``, etc. when searching for headers. + +* ``AUTOMOC`` looks for the ``Q_PLUGIN_METADATA`` macro and reruns the + ``moc`` when the file addressed by the ``FILE`` argument of the macro changes. This property is initialized by the value of the :variable:`CMAKE_AUTOMOC` variable if it is set when a target is created. https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=11ad7564ba2834d170240d37883ffdd7b3327a65 commit 11ad7564ba2834d170240d37883ffdd7b3327a65 Author: Sebastian Holtermann AuthorDate: Sun Feb 19 18:35:40 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:51:29 2017 -0500 Autogen: Add release notes for Q_PLUGIN_METADATA support diff --git a/Help/release/dev/Autogen_json.rst b/Help/release/dev/Autogen_json.rst new file mode 100644 index 0000000..73bbdf1 --- /dev/null +++ b/Help/release/dev/Autogen_json.rst @@ -0,0 +1,10 @@ +AutoGen json +------------ + +* When using :prop_tgt:`AUTOMOC`, CMake scans for the presence of the + ``Q_PLUGIN_METADATA`` macro and reruns moc when the file from the + macro's ``FILE`` argument changes. + +* When :prop_tgt:`AUTOMOC` detects an include statement of the form + ``#include "moc_.cpp"`` the respective header file is searched + for in the :prop_tgt:`INCLUDE_DIRECTORIES` of the target as well. https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ca386093ae307dfd25917a520dca68319ce861a3 commit ca386093ae307dfd25917a520dca68319ce861a3 Author: Sebastian Holtermann AuthorDate: Sun Feb 19 17:24:30 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:51:28 2017 -0500 Autogen: Tests: Set different compression levels in rcc test diff --git a/Tests/QtAutogen/sameName/CMakeLists.txt b/Tests/QtAutogen/sameName/CMakeLists.txt index 9e47a3e..4d2dcd9 100644 --- a/Tests/QtAutogen/sameName/CMakeLists.txt +++ b/Tests/QtAutogen/sameName/CMakeLists.txt @@ -18,3 +18,14 @@ add_executable(sameName ) target_link_libraries(sameName ${QT_LIBRARIES}) set_target_properties(sameName PROPERTIES AUTOMOC TRUE AUTORCC TRUE) + +# Set different compression levels +if (QT_TEST_VERSION STREQUAL 4) + set(rccCompress "-compress") +else() + set(rccCompress "--compress") +endif() +set_target_properties(sameName PROPERTIES AUTORCC_OPTIONS "${rccCompress};0" ) +set_source_files_properties(aaa/data.qrc PROPERTIES AUTORCC_OPTIONS "${rccCompress};1" ) +set_source_files_properties(bbb/data.qrc PROPERTIES AUTORCC_OPTIONS "${rccCompress};2" ) +set_source_files_properties(ccc/data.qrc PROPERTIES AUTORCC_OPTIONS "${rccCompress};3" ) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=359cfdc68c2d606c32c15c0a3a68f8dacf7834eb commit 359cfdc68c2d606c32c15c0a3a68f8dacf7834eb Author: Sebastian Holtermann AuthorDate: Sun Feb 19 16:46:47 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:51:28 2017 -0500 Autogen: Overhaul and simplify AutogenInfo.cmake file generation diff --git a/Modules/AutogenInfo.cmake.in b/Modules/AutogenInfo.cmake.in index 3135909..b647ecf 100644 --- a/Modules/AutogenInfo.cmake.in +++ b/Modules/AutogenInfo.cmake.in @@ -1,5 +1,5 @@ # Target names -set(AM_TARGET_NAME @_moc_target_name@) +set(AM_TARGET_NAME @_autogen_target_name@) set(AM_ORIGIN_TARGET_NAME @_origin_target_name@) # Directories and files set(AM_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@/") @@ -10,16 +10,16 @@ set(AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE "@CMAKE_INCLUDE_DIRECTORIES_PROJ set(AM_SOURCES @_sources@) set(AM_HEADERS @_headers@) # Qt environment -set(AM_QT_VERSION_MAJOR "@_target_qt_version@") -set(AM_QT_MOC_EXECUTABLE "@_qt_moc_executable@") -set(AM_QT_UIC_EXECUTABLE "@_qt_uic_executable@") -set(AM_QT_RCC_EXECUTABLE "@_qt_rcc_executable@") +set(AM_QT_VERSION_MAJOR @_qt_version_major@) +set(AM_QT_MOC_EXECUTABLE @_qt_moc_executable@) +set(AM_QT_UIC_EXECUTABLE @_qt_uic_executable@) +set(AM_QT_RCC_EXECUTABLE @_qt_rcc_executable@) # MOC settings set(AM_MOC_SKIP @_moc_skip@) set(AM_MOC_COMPILE_DEFINITIONS @_moc_compile_defs@) set(AM_MOC_INCLUDES @_moc_incs@) set(AM_MOC_OPTIONS @_moc_options@) -set(AM_MOC_RELAXED_MODE "@_moc_relaxed_mode@") +set(AM_MOC_RELAXED_MODE @_moc_relaxed_mode@) # UIC settings set(AM_UIC_SKIP @_uic_skip@) set(AM_UIC_TARGET_OPTIONS @_uic_target_options@) diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index c201023..52112ff 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -22,7 +22,6 @@ #endif #include -#include #include #include #include @@ -55,6 +54,13 @@ static std::string utilStripCR(std::string const& line) return line; } +static std::string GetSafeProperty(cmGeneratorTarget const* target, + const char* key) +{ + const char* tmp = target->GetProperty(key); + return std::string((tmp != CM_NULLPTR) ? tmp : ""); +} + static std::string GetAutogenTargetName(cmGeneratorTarget const* target) { std::string autogenTargetName = target->GetName(); @@ -118,19 +124,33 @@ static void GetCompileDefinitionsAndDirectories( } } +static void AddDefinitionEscaped(cmMakefile* makefile, const char* key, + const std::string& value) +{ + makefile->AddDefinition(key, + cmOutputConverter::EscapeForCMake(value).c_str()); +} + +static void AddDefinitionEscaped(cmMakefile* makefile, const char* key, + const std::vector& values) +{ + makefile->AddDefinition( + key, cmOutputConverter::EscapeForCMake(cmJoin(values, ";")).c_str()); +} + static void SetupSourceFiles(cmGeneratorTarget const* target, std::vector& mocUicSources, std::vector& mocUicHeaders, - std::vector& skipMocList, - std::vector& skipUicList) + std::vector& mocSkipList, + std::vector& uicSkipList) { cmMakefile* makefile = target->Target->GetMakefile(); std::vector srcFiles; target->GetConfigCommonSourceFiles(srcFiles); - const bool targetMoc = target->GetPropertyAsBool("AUTOMOC"); - const bool targetUic = target->GetPropertyAsBool("AUTOUIC"); + const bool mocTarget = target->GetPropertyAsBool("AUTOMOC"); + const bool uicTarget = target->GetPropertyAsBool("AUTOUIC"); cmFilePathChecksum fpathCheckSum(makefile); for (std::vector::const_iterator fileIt = srcFiles.begin(); @@ -151,22 +171,22 @@ static void SetupSourceFiles(cmGeneratorTarget const* target, // Skip flags const bool skipAll = cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOGEN")); - const bool skipMoc = + const bool mocSkip = skipAll || cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOMOC")); - const bool skipUic = + const bool uicSkip = skipAll || cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOUIC")); // 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 // processing - if (skipMoc) { - skipMocList.push_back(absFile); + if (mocSkip) { + mocSkipList.push_back(absFile); } - if (skipUic) { - skipUicList.push_back(absFile); + if (uicSkip) { + uicSkipList.push_back(absFile); } - if ((targetMoc && !skipMoc) || (targetUic && !skipUic)) { + if ((mocTarget && !mocSkip) || (uicTarget && !uicSkip)) { // Add file name to sources or headers list switch (fileType) { case cmSystemTools::CXX_FILE_FORMAT: @@ -184,80 +204,85 @@ static void SetupSourceFiles(cmGeneratorTarget const* target, static void MocSetupAutoTarget( cmGeneratorTarget const* target, const std::string& autogenTargetName, - std::vector const& skipMoc, + const std::string& qtMajorVersion, + std::vector const& mocSkipList, std::map& configIncludes, std::map& configDefines) { cmLocalGenerator* lg = target->GetLocalGenerator(); cmMakefile* makefile = target->Target->GetMakefile(); - const char* tmp = target->GetProperty("AUTOMOC_MOC_OPTIONS"); - std::string _moc_options = (tmp != CM_NULLPTR ? tmp : ""); - makefile->AddDefinition( - "_moc_options", cmOutputConverter::EscapeForCMake(_moc_options).c_str()); - makefile->AddDefinition( - "_moc_skip", - cmOutputConverter::EscapeForCMake(cmJoin(skipMoc, ";")).c_str()); - bool relaxedMode = makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE"); - makefile->AddDefinition("_moc_relaxed_mode", relaxedMode ? "TRUE" : "FALSE"); - - std::string _moc_incs; - std::string _moc_compile_defs; - std::vector configs; - const std::string& config = makefile->GetConfigurations(configs); - GetCompileDefinitionsAndDirectories(target, config, _moc_incs, - _moc_compile_defs); + AddDefinitionEscaped(makefile, "_moc_options", + GetSafeProperty(target, "AUTOMOC_MOC_OPTIONS")); + AddDefinitionEscaped(makefile, "_moc_skip", mocSkipList); + AddDefinitionEscaped(makefile, "_moc_relaxed_mode", + makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE") ? "TRUE" + : "FALSE"); - makefile->AddDefinition( - "_moc_incs", cmOutputConverter::EscapeForCMake(_moc_incs).c_str()); - makefile->AddDefinition( - "_moc_compile_defs", - cmOutputConverter::EscapeForCMake(_moc_compile_defs).c_str()); - - for (std::vector::const_iterator li = configs.begin(); - li != configs.end(); ++li) { - std::string config_moc_incs; - std::string config_moc_compile_defs; - GetCompileDefinitionsAndDirectories(target, *li, config_moc_incs, - config_moc_compile_defs); - if (config_moc_incs != _moc_incs) { - configIncludes[*li] = cmOutputConverter::EscapeForCMake(config_moc_incs); - if (_moc_incs.empty()) { - _moc_incs = config_moc_incs; + // Moc includes and compile definitions + { + std::string _moc_incs; + std::string _moc_compile_defs; + std::vector configs; + { + const std::string& config = makefile->GetConfigurations(configs); + GetCompileDefinitionsAndDirectories(target, config, _moc_incs, + _moc_compile_defs); + AddDefinitionEscaped(makefile, "_moc_incs", _moc_incs); + AddDefinitionEscaped(makefile, "_moc_compile_defs", _moc_compile_defs); + } + for (std::vector::const_iterator li = configs.begin(); + li != configs.end(); ++li) { + std::string config_moc_incs; + std::string config_moc_compile_defs; + GetCompileDefinitionsAndDirectories(target, *li, config_moc_incs, + config_moc_compile_defs); + if (config_moc_incs != _moc_incs) { + configIncludes[*li] = + cmOutputConverter::EscapeForCMake(config_moc_incs); + if (_moc_incs.empty()) { + _moc_incs = config_moc_incs; + } } - } - if (config_moc_compile_defs != _moc_compile_defs) { - configDefines[*li] = - cmOutputConverter::EscapeForCMake(config_moc_compile_defs); - if (_moc_compile_defs.empty()) { - _moc_compile_defs = config_moc_compile_defs; + if (config_moc_compile_defs != _moc_compile_defs) { + configDefines[*li] = + cmOutputConverter::EscapeForCMake(config_moc_compile_defs); + if (_moc_compile_defs.empty()) { + _moc_compile_defs = config_moc_compile_defs; + } } } } - const char* qtVersion = makefile->GetDefinition("_target_qt_version"); - if (strcmp(qtVersion, "5") == 0) { - cmGeneratorTarget* qt5Moc = lg->FindGeneratorTargetToUse("Qt5::moc"); - if (!qt5Moc) { - cmSystemTools::Error("Qt5::moc target not found ", - autogenTargetName.c_str()); - return; + // Moc executable + { + std::string err; + const char* mocExec = CM_NULLPTR; + if (qtMajorVersion == "5") { + cmGeneratorTarget* qt5Moc = lg->FindGeneratorTargetToUse("Qt5::moc"); + if (qt5Moc != CM_NULLPTR) { + mocExec = qt5Moc->ImportedGetLocation(""); + } else { + err = "Qt5::moc target not found " + autogenTargetName; + } + } else if (qtMajorVersion == "4") { + cmGeneratorTarget* qt4Moc = lg->FindGeneratorTargetToUse("Qt4::moc"); + if (qt4Moc != CM_NULLPTR) { + mocExec = qt4Moc->ImportedGetLocation(""); + } else { + err = "Qt4::moc target not found " + autogenTargetName; + } + } else { + err = "The CMAKE_AUTOMOC feature supports only Qt 4 and Qt 5 "; + err += autogenTargetName; } - makefile->AddDefinition("_qt_moc_executable", - qt5Moc->ImportedGetLocation("")); - } else if (strcmp(qtVersion, "4") == 0) { - cmGeneratorTarget* qt4Moc = lg->FindGeneratorTargetToUse("Qt4::moc"); - if (!qt4Moc) { - cmSystemTools::Error("Qt4::moc target not found ", - autogenTargetName.c_str()); - return; + // Add definition or error + if (err.empty()) { + AddDefinitionEscaped(makefile, "_qt_moc_executable", + mocExec ? mocExec : ""); + } else { + cmSystemTools::Error(err.c_str()); } - makefile->AddDefinition("_qt_moc_executable", - qt4Moc->ImportedGetLocation("")); - } else { - cmSystemTools::Error("The CMAKE_AUTOMOC feature supports only Qt 4 and " - "Qt 5 ", - autogenTargetName.c_str()); } } @@ -270,126 +295,126 @@ static void UicGetOpts(cmGeneratorTarget const* target, } static void UicSetupAutoTarget( - cmGeneratorTarget const* target, std::vector const& skipUic, + cmGeneratorTarget const* target, const std::string& qtMajorVersion, + std::vector const& uicSkipList, std::map& configUicOptions) { cmLocalGenerator* lg = target->GetLocalGenerator(); cmMakefile* makefile = target->Target->GetMakefile(); - std::set skipped; - skipped.insert(skipUic.begin(), skipUic.end()); + AddDefinitionEscaped(makefile, "_uic_skip", uicSkipList); - makefile->AddDefinition( - "_uic_skip", - cmOutputConverter::EscapeForCMake(cmJoin(skipUic, ";")).c_str()); - - std::vector uiFilesWithOptions = - makefile->GetQtUiFilesWithOptions(); - - const char* qtVersion = makefile->GetDefinition("_target_qt_version"); - - std::string _uic_opts; - std::vector configs; - const std::string& config = makefile->GetConfigurations(configs); - UicGetOpts(target, config, _uic_opts); - - if (!_uic_opts.empty()) { - _uic_opts = cmOutputConverter::EscapeForCMake(_uic_opts); - makefile->AddDefinition("_uic_target_options", _uic_opts.c_str()); - } - for (std::vector::const_iterator li = configs.begin(); - li != configs.end(); ++li) { - std::string config_uic_opts; - UicGetOpts(target, *li, config_uic_opts); - if (config_uic_opts != _uic_opts) { - configUicOptions[*li] = - cmOutputConverter::EscapeForCMake(config_uic_opts); - if (_uic_opts.empty()) { - _uic_opts = config_uic_opts; + // Uic target options + { + std::string _uic_opts; + std::vector configs; + UicGetOpts(target, makefile->GetConfigurations(configs), _uic_opts); + + AddDefinitionEscaped(makefile, "_uic_target_options", _uic_opts); + + for (std::vector::const_iterator li = configs.begin(); + li != configs.end(); ++li) { + std::string config_uic_opts; + UicGetOpts(target, *li, config_uic_opts); + if (config_uic_opts != _uic_opts) { + configUicOptions[*li] = + cmOutputConverter::EscapeForCMake(config_uic_opts); + if (_uic_opts.empty()) { + _uic_opts = config_uic_opts; + } } } } - - std::string uiFileFiles; - std::string uiFileOptions; - const char* sep = ""; - - for (std::vector::const_iterator fileIt = - uiFilesWithOptions.begin(); - fileIt != uiFilesWithOptions.end(); ++fileIt) { - cmSourceFile* sf = *fileIt; - std::string absFile = cmsys::SystemTools::GetRealPath(sf->GetFullPath()); - - if (!skipped.insert(absFile).second) { - continue; + // Uic files options + { + std::vector uiFileFiles; + std::vector uiFileOptions; + { + std::set skipped; + skipped.insert(uicSkipList.begin(), uicSkipList.end()); + + const std::vector uiFilesWithOptions = + makefile->GetQtUiFilesWithOptions(); + for (std::vector::const_iterator fileIt = + uiFilesWithOptions.begin(); + fileIt != uiFilesWithOptions.end(); ++fileIt) { + cmSourceFile* sf = *fileIt; + const std::string absFile = + cmsys::SystemTools::GetRealPath(sf->GetFullPath()); + if (skipped.insert(absFile).second) { + // The file wasn't skipped + uiFileFiles.push_back(absFile); + { + std::string opts = sf->GetProperty("AUTOUIC_OPTIONS"); + cmSystemTools::ReplaceString(opts, ";", "@list_sep@"); + uiFileOptions.push_back(opts); + } + } + } } - uiFileFiles += sep; - uiFileFiles += absFile; - uiFileOptions += sep; - std::string opts = sf->GetProperty("AUTOUIC_OPTIONS"); - cmSystemTools::ReplaceString(opts, ";", "@list_sep@"); - uiFileOptions += opts; - sep = ";"; + AddDefinitionEscaped(makefile, "_qt_uic_options_files", uiFileFiles); + AddDefinitionEscaped(makefile, "_qt_uic_options_options", uiFileOptions); } - makefile->AddDefinition( - "_qt_uic_options_files", - cmOutputConverter::EscapeForCMake(uiFileFiles).c_str()); - makefile->AddDefinition( - "_qt_uic_options_options", - cmOutputConverter::EscapeForCMake(uiFileOptions).c_str()); - - std::string targetName = target->GetName(); - if (strcmp(qtVersion, "5") == 0) { - cmGeneratorTarget* qt5Uic = lg->FindGeneratorTargetToUse("Qt5::uic"); - if (!qt5Uic) { - // Project does not use Qt5Widgets, but has AUTOUIC ON anyway + // Uic executable + { + std::string err; + const char* uicExec = CM_NULLPTR; + if (qtMajorVersion == "5") { + cmGeneratorTarget* qt5Uic = lg->FindGeneratorTargetToUse("Qt5::uic"); + if (qt5Uic != CM_NULLPTR) { + uicExec = qt5Uic->ImportedGetLocation(""); + } else { + // Project does not use Qt5Widgets, but has AUTOUIC ON anyway + } + } else if (qtMajorVersion == "4") { + cmGeneratorTarget* qt4Uic = lg->FindGeneratorTargetToUse("Qt4::uic"); + if (qt4Uic != CM_NULLPTR) { + uicExec = qt4Uic->ImportedGetLocation(""); + } else { + err = "Qt4::uic target not found " + target->GetName(); + } } else { - makefile->AddDefinition("_qt_uic_executable", - qt5Uic->ImportedGetLocation("")); + err = "The CMAKE_AUTOUIC feature supports only Qt 4 and Qt 5 "; + err += target->GetName(); } - } else if (strcmp(qtVersion, "4") == 0) { - cmGeneratorTarget* qt4Uic = lg->FindGeneratorTargetToUse("Qt4::uic"); - if (!qt4Uic) { - cmSystemTools::Error("Qt4::uic target not found ", targetName.c_str()); - return; + // Add definition or error + if (err.empty()) { + AddDefinitionEscaped(makefile, "_qt_uic_executable", + uicExec ? uicExec : ""); + } else { + cmSystemTools::Error(err.c_str()); } - makefile->AddDefinition("_qt_uic_executable", - qt4Uic->ImportedGetLocation("")); - } else { - cmSystemTools::Error("The CMAKE_AUTOUIC feature supports only Qt 4 and " - "Qt 5 ", - targetName.c_str()); } } static std::string RccGetExecutable(cmGeneratorTarget const* target, const std::string& qtMajorVersion) { + std::string rccExec; cmLocalGenerator* lg = target->GetLocalGenerator(); - - std::string const& targetName = target->GetName(); if (qtMajorVersion == "5") { cmGeneratorTarget* qt5Rcc = lg->FindGeneratorTargetToUse("Qt5::rcc"); - if (!qt5Rcc) { - cmSystemTools::Error("Qt5::rcc target not found ", targetName.c_str()); - return std::string(); + if (qt5Rcc != CM_NULLPTR) { + rccExec = qt5Rcc->ImportedGetLocation(""); + } else { + cmSystemTools::Error("Qt5::rcc target not found ", + target->GetName().c_str()); } - return qt5Rcc->ImportedGetLocation(""); - } - if (qtMajorVersion == "4") { + } else if (qtMajorVersion == "4") { cmGeneratorTarget* qt4Rcc = lg->FindGeneratorTargetToUse("Qt4::rcc"); - if (!qt4Rcc) { - cmSystemTools::Error("Qt4::rcc target not found ", targetName.c_str()); - return std::string(); + if (qt4Rcc != CM_NULLPTR) { + rccExec = qt4Rcc->ImportedGetLocation(""); + } else { + cmSystemTools::Error("Qt4::rcc target not found ", + target->GetName().c_str()); } - return qt4Rcc->ImportedGetLocation(""); + } else { + cmSystemTools::Error( + "The CMAKE_AUTORCC feature supports only Qt 4 and Qt 5 ", + target->GetName().c_str()); } - - cmSystemTools::Error("The CMAKE_AUTORCC feature supports only Qt 4 and " - "Qt 5 ", - targetName.c_str()); - return std::string(); + return rccExec; } static void RccMergeOptions(std::vector& opts, @@ -399,26 +424,31 @@ static void RccMergeOptions(std::vector& opts, static const char* valueOptions[] = { "name", "root", "compress", "threshold" }; std::vector extraOpts; - for (std::vector::const_iterator it = fileOpts.begin(); - it != fileOpts.end(); ++it) { + for (std::vector::const_iterator fit = fileOpts.begin(); + fit != fileOpts.end(); ++fit) { std::vector::iterator existingIt = - std::find(opts.begin(), opts.end(), *it); + std::find(opts.begin(), opts.end(), *fit); if (existingIt != opts.end()) { - const char* o = it->c_str(); - if (*o == '-') { - ++o; - } - if (isQt5 && *o == '-') { - ++o; + const char* optName = fit->c_str(); + if (*optName == '-') { + ++optName; + if (isQt5 && *optName == '-') { + ++optName; + } } - if (std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions), - cmStrCmp(*it)) != cmArrayEnd(valueOptions)) { - assert(existingIt + 1 != opts.end()); - *(existingIt + 1) = *(it + 1); - ++it; + // Test if this is a value option and change the existing value + if ((optName != fit->c_str()) && + std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions), + cmStrCmp(optName)) != cmArrayEnd(valueOptions)) { + const std::vector::iterator existValueIt(existingIt + 1); + const std::vector::const_iterator fileValueIt(fit + 1); + if ((existValueIt != opts.end()) && (fileValueIt != fileOpts.end())) { + *existValueIt = *fileValueIt; + ++fit; + } } } else { - extraOpts.push_back(*it); + extraOpts.push_back(*fit); } } opts.insert(opts.end(), extraOpts.begin(), extraOpts.end()); @@ -528,23 +558,20 @@ static bool RccListInputsQt4(cmSourceFile* sf, } cmsys::RegularExpression fileMatchRegex("(]*>)"); size_t offset = 0; while (fileMatchRegex.find(qrcContents.c_str() + offset)) { std::string qrcEntry = fileMatchRegex.match(1); - offset += qrcEntry.size(); - - cmsys::RegularExpression fileReplaceRegex("(^]*>)"); - fileReplaceRegex.find(qrcEntry); - std::string tag = fileReplaceRegex.match(1); - - qrcEntry = qrcEntry.substr(tag.size()); - + { + fileReplaceRegex.find(qrcEntry); + std::string tag = fileReplaceRegex.match(1); + qrcEntry = qrcEntry.substr(tag.size()); + } if (!cmSystemTools::FileIsFullPath(qrcEntry.c_str())) { qrcEntry = sf->GetLocation().GetDirectory() + "/" + qrcEntry; } - depends.push_back(qrcEntry); } return true; @@ -565,89 +592,69 @@ static bool RccListInputs(const std::string& qtMajorVersion, cmSourceFile* sf, static void RccSetupAutoTarget(cmGeneratorTarget const* target, const std::string& qtMajorVersion) { - std::string _rcc_files; - const char* sepRccFiles = ""; cmMakefile* makefile = target->Target->GetMakefile(); - - std::vector srcFiles; - target->GetConfigCommonSourceFiles(srcFiles); - - std::string qrcInputs; - const char* qrcInputsSep = ""; - - std::string rccFileFiles; - std::string rccFileOptions; - const char* optionSep = ""; - const bool qtMajorVersion5 = (qtMajorVersion == "5"); - - std::vector rccOptions; + std::vector _rcc_files; + std::vector _rcc_inputs; + std::vector rccFileFiles; + std::vector rccFileOptions; + std::vector rccOptionsTarget; if (const char* opts = target->GetProperty("AUTORCC_OPTIONS")) { - cmSystemTools::ExpandListArgument(opts, rccOptions); + cmSystemTools::ExpandListArgument(opts, rccOptionsTarget); } + std::vector srcFiles; + target->GetConfigCommonSourceFiles(srcFiles); for (std::vector::const_iterator fileIt = srcFiles.begin(); fileIt != srcFiles.end(); ++fileIt) { cmSourceFile* sf = *fileIt; - std::string ext = sf->GetExtension(); - if (ext == "qrc") { - std::string absFile = cmsys::SystemTools::GetRealPath(sf->GetFullPath()); + if (sf->GetExtension() == "qrc") { const bool skip = cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOGEN")) || cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC")); - if (!skip) { - _rcc_files += sepRccFiles; - _rcc_files += absFile; - sepRccFiles = ";"; - - if (const char* prop = sf->GetProperty("AUTORCC_OPTIONS")) { - std::vector optsVec; - cmSystemTools::ExpandListArgument(prop, optsVec); - RccMergeOptions(rccOptions, optsVec, qtMajorVersion5); - } - - if (!rccOptions.empty()) { - rccFileFiles += optionSep; - rccFileFiles += absFile; - rccFileOptions += optionSep; - } - const char* listSep = ""; - for (std::vector::const_iterator it = rccOptions.begin(); - it != rccOptions.end(); ++it) { - rccFileOptions += listSep; - rccFileOptions += *it; - listSep = "@list_sep@"; + const std::string absFile = + cmsys::SystemTools::GetRealPath(sf->GetFullPath()); + // qrc file + _rcc_files.push_back(absFile); + // qrc file entries + { + std::string entriesList; + if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) { + std::vector depends; + if (RccListInputs(qtMajorVersion, sf, target, depends)) { + entriesList = cmJoin(depends, "@list_sep@"); + } else { + return; + } + } + _rcc_inputs.push_back(entriesList); } - optionSep = ";"; - - std::string entriesList; - if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) { - std::vector depends; - if (RccListInputs(qtMajorVersion, sf, target, depends)) { - entriesList = cmJoin(depends, "@list_sep@"); - } else { - return; + // rcc options for this qrc file + { + // Merged target and file options + std::vector rccOptions(rccOptionsTarget); + if (const char* prop = sf->GetProperty("AUTORCC_OPTIONS")) { + std::vector optsVec; + cmSystemTools::ExpandListArgument(prop, optsVec); + RccMergeOptions(rccOptions, optsVec, qtMajorVersion5); + } + // Only store non empty options lists + if (!rccOptions.empty()) { + rccFileFiles.push_back(absFile); + rccFileOptions.push_back(cmJoin(rccOptions, "@list_sep@")); } } - qrcInputs += qrcInputsSep; - qrcInputs += entriesList; - qrcInputsSep = ";"; } } } - makefile->AddDefinition( - "_rcc_inputs", cmOutputConverter::EscapeForCMake(qrcInputs).c_str()); - makefile->AddDefinition( - "_rcc_files", cmOutputConverter::EscapeForCMake(_rcc_files).c_str()); - makefile->AddDefinition( - "_rcc_options_files", - cmOutputConverter::EscapeForCMake(rccFileFiles).c_str()); - makefile->AddDefinition( - "_rcc_options_options", - cmOutputConverter::EscapeForCMake(rccFileOptions).c_str()); - makefile->AddDefinition("_qt_rcc_executable", - RccGetExecutable(target, qtMajorVersion).c_str()); + + AddDefinitionEscaped(makefile, "_rcc_files", _rcc_files); + AddDefinitionEscaped(makefile, "_rcc_inputs", _rcc_inputs); + AddDefinitionEscaped(makefile, "_rcc_options_files", rccFileFiles); + AddDefinitionEscaped(makefile, "_rcc_options_options", rccFileOptions); + AddDefinitionEscaped(makefile, "_qt_rcc_executable", + RccGetExecutable(target, qtMajorVersion)); } void cmQtAutoGeneratorInitializer::InitializeAutogenSources( @@ -874,47 +881,42 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( cmMakefile::ScopePushPop varScope(makefile); static_cast(varScope); - // create a custom target for running generators at buildtime: - const std::string autogenTargetName = GetAutogenTargetName(target); - const std::string qtMajorVersion = GetQtMajorVersion(target); - - makefile->AddDefinition( - "_moc_target_name", - cmOutputConverter::EscapeForCMake(autogenTargetName).c_str()); - makefile->AddDefinition( - "_origin_target_name", - cmOutputConverter::EscapeForCMake(target->GetName()).c_str()); - makefile->AddDefinition("_target_qt_version", qtMajorVersion.c_str()); - - std::vector mocUicSources; - std::vector mocUicHeaders; - std::vector skipMoc; - std::vector skipUic; std::map configMocIncludes; std::map configMocDefines; std::map configUicOptions; + { + // create a custom target for running generators at buildtime: + const std::string autogenTargetName = GetAutogenTargetName(target); + const std::string qtMajorVersion = GetQtMajorVersion(target); - if (target->GetPropertyAsBool("AUTOMOC") || - target->GetPropertyAsBool("AUTOUIC") || - target->GetPropertyAsBool("AUTORCC")) { - SetupSourceFiles(target, mocUicSources, mocUicHeaders, skipMoc, skipUic); - } - makefile->AddDefinition( - "_sources", - cmOutputConverter::EscapeForCMake(cmJoin(mocUicSources, ";")).c_str()); - makefile->AddDefinition( - "_headers", - cmOutputConverter::EscapeForCMake(cmJoin(mocUicHeaders, ";")).c_str()); + AddDefinitionEscaped(makefile, "_autogen_target_name", autogenTargetName); + AddDefinitionEscaped(makefile, "_origin_target_name", target->GetName()); + AddDefinitionEscaped(makefile, "_qt_version_major", qtMajorVersion); - if (target->GetPropertyAsBool("AUTOMOC")) { - MocSetupAutoTarget(target, autogenTargetName, skipMoc, configMocIncludes, - configMocDefines); - } - if (target->GetPropertyAsBool("AUTOUIC")) { - UicSetupAutoTarget(target, skipUic, configUicOptions); - } - if (target->GetPropertyAsBool("AUTORCC")) { - RccSetupAutoTarget(target, qtMajorVersion); + std::vector _sources; + std::vector _headers; + std::vector mocSkipList; + std::vector uicSkipList; + + if (target->GetPropertyAsBool("AUTOMOC") || + target->GetPropertyAsBool("AUTOUIC") || + target->GetPropertyAsBool("AUTORCC")) { + SetupSourceFiles(target, _sources, _headers, mocSkipList, uicSkipList); + } + AddDefinitionEscaped(makefile, "_sources", _sources); + AddDefinitionEscaped(makefile, "_headers", _headers); + + if (target->GetPropertyAsBool("AUTOMOC")) { + MocSetupAutoTarget(target, autogenTargetName, qtMajorVersion, + mocSkipList, configMocIncludes, configMocDefines); + } + if (target->GetPropertyAsBool("AUTOUIC")) { + UicSetupAutoTarget(target, qtMajorVersion, uicSkipList, + configUicOptions); + } + if (target->GetPropertyAsBool("AUTORCC")) { + RccSetupAutoTarget(target, qtMajorVersion); + } } // Generate config file @@ -926,7 +928,7 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( makefile->ConfigureFile(inputFile.c_str(), outputFile.c_str(), false, true, false); - // Append custom definitions to config file + // Append custom config definitions to info file if (!configMocDefines.empty() || !configMocIncludes.empty() || !configUicOptions.empty()) { @@ -948,33 +950,34 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( error += outputFile; error += " for writing."; cmSystemTools::Error(error.c_str()); - return; - } - if (!configMocDefines.empty()) { - for (std::map::iterator - it = configMocDefines.begin(), - end = configMocDefines.end(); - it != end; ++it) { - infoFile << "set(AM_MOC_COMPILE_DEFINITIONS_" << it->first << " " - << it->second << ")\n"; + } else { + infoFile << "# Configuration specific options\n"; + if (!configMocDefines.empty()) { + for (std::map::iterator + it = configMocDefines.begin(), + end = configMocDefines.end(); + it != end; ++it) { + infoFile << "set(AM_MOC_COMPILE_DEFINITIONS_" << it->first << " " + << it->second << ")\n"; + } } - } - if (!configMocIncludes.empty()) { - for (std::map::iterator - it = configMocIncludes.begin(), - end = configMocIncludes.end(); - it != end; ++it) { - infoFile << "set(AM_MOC_INCLUDES_" << it->first << " " << it->second - << ")\n"; + if (!configMocIncludes.empty()) { + for (std::map::iterator + it = configMocIncludes.begin(), + end = configMocIncludes.end(); + it != end; ++it) { + infoFile << "set(AM_MOC_INCLUDES_" << it->first << " " << it->second + << ")\n"; + } } - } - if (!configUicOptions.empty()) { - for (std::map::iterator - it = configUicOptions.begin(), - end = configUicOptions.end(); - it != end; ++it) { - infoFile << "set(AM_UIC_TARGET_OPTIONS_" << it->first << " " - << it->second << ")\n"; + if (!configUicOptions.empty()) { + for (std::map::iterator + it = configUicOptions.begin(), + end = configUicOptions.end(); + it != end; ++it) { + infoFile << "set(AM_UIC_TARGET_OPTIONS_" << it->first << " " + << it->second << ")\n"; + } } } } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b0a44ed354fe3eea20fc7dbc7c467794ebea6593 commit b0a44ed354fe3eea20fc7dbc7c467794ebea6593 Author: Sebastian Holtermann AuthorDate: Sun Feb 19 13:17:42 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:51:27 2017 -0500 Autogen: Optimize GetCompileDefinitionsAndDirectories function diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index d17faf6..c201023 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -98,6 +98,26 @@ static std::string GetQtMajorVersion(cmGeneratorTarget const* target) return qtMajorVersion; } +static void GetCompileDefinitionsAndDirectories( + cmGeneratorTarget const* target, const std::string& config, + std::string& incs, std::string& defs) +{ + cmLocalGenerator* localGen = target->GetLocalGenerator(); + { + std::vector includeDirs; + // Get the include dirs for this target, without stripping the implicit + // include dirs off, see + // https://gitlab.kitware.com/cmake/cmake/issues/13667 + localGen->GetIncludeDirectories(includeDirs, target, "CXX", config, false); + incs = cmJoin(includeDirs, ";"); + } + { + std::set defines; + localGen->AddCompileDefinitions(defines, target, config, "CXX"); + defs += cmJoin(defines, ";"); + } +} + static void SetupSourceFiles(cmGeneratorTarget const* target, std::vector& mocUicSources, std::vector& mocUicHeaders, @@ -162,24 +182,6 @@ static void SetupSourceFiles(cmGeneratorTarget const* target, } } -static void GetCompileDefinitionsAndDirectories( - cmGeneratorTarget const* target, const std::string& config, - std::string& incs, std::string& defs) -{ - std::vector includeDirs; - cmLocalGenerator* localGen = target->GetLocalGenerator(); - // Get the include dirs for this target, without stripping the implicit - // include dirs off, see https://gitlab.kitware.com/cmake/cmake/issues/13667 - localGen->GetIncludeDirectories(includeDirs, target, "CXX", config, false); - - incs = cmJoin(includeDirs, ";"); - - std::set defines; - localGen->AddCompileDefinitions(defines, target, config, "CXX"); - - defs += cmJoin(defines, ";"); -} - static void MocSetupAutoTarget( cmGeneratorTarget const* target, const std::string& autogenTargetName, std::vector const& skipMoc, https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=928564fb8610e508448d5972c6dc83f4dfb64d7f commit 928564fb8610e508448d5972c6dc83f4dfb64d7f Author: Sebastian Holtermann AuthorDate: Sun Feb 19 12:57:47 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:51:27 2017 -0500 Autogen: Sort AutogenInfo.cmake.in Also rename AM_SKIP_MOC to AM_MOC_SKIP and AM_SKIP_UIC to AM_UIC_SKIP diff --git a/Modules/AutogenInfo.cmake.in b/Modules/AutogenInfo.cmake.in index 3fafaff..3135909 100644 --- a/Modules/AutogenInfo.cmake.in +++ b/Modules/AutogenInfo.cmake.in @@ -1,25 +1,31 @@ -set(AM_SOURCES @_moc_uic_sources@) -set(AM_HEADERS @_moc_uic_headers@) -set(AM_SKIP_MOC @_skip_moc@) -set(AM_SKIP_UIC @_skip_uic@) -set(AM_MOC_COMPILE_DEFINITIONS @_moc_compile_defs@) -set(AM_MOC_INCLUDES @_moc_incs@) -set(AM_MOC_OPTIONS @_moc_options@) -set(AM_MOC_RELAXED_MODE "@_moc_relaxed_mode@") -set(AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE "@CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE@") +# Target names +set(AM_TARGET_NAME @_moc_target_name@) +set(AM_ORIGIN_TARGET_NAME @_origin_target_name@) +# Directories and files set(AM_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@/") set(AM_CMAKE_SOURCE_DIR "@CMAKE_SOURCE_DIR@/") -set(AM_QT_MOC_EXECUTABLE "@_qt_moc_executable@") -set(AM_QT_UIC_EXECUTABLE "@_qt_uic_executable@") -set(AM_QT_RCC_EXECUTABLE "@_qt_rcc_executable@") set(AM_CMAKE_CURRENT_SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@/") set(AM_CMAKE_CURRENT_BINARY_DIR "@CMAKE_CURRENT_BINARY_DIR@/") +set(AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE "@CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE@") +set(AM_SOURCES @_sources@) +set(AM_HEADERS @_headers@) +# Qt environment set(AM_QT_VERSION_MAJOR "@_target_qt_version@") -set(AM_TARGET_NAME @_moc_target_name@) -set(AM_ORIGIN_TARGET_NAME @_origin_target_name@) +set(AM_QT_MOC_EXECUTABLE "@_qt_moc_executable@") +set(AM_QT_UIC_EXECUTABLE "@_qt_uic_executable@") +set(AM_QT_RCC_EXECUTABLE "@_qt_rcc_executable@") +# MOC settings +set(AM_MOC_SKIP @_moc_skip@) +set(AM_MOC_COMPILE_DEFINITIONS @_moc_compile_defs@) +set(AM_MOC_INCLUDES @_moc_incs@) +set(AM_MOC_OPTIONS @_moc_options@) +set(AM_MOC_RELAXED_MODE "@_moc_relaxed_mode@") +# UIC settings +set(AM_UIC_SKIP @_uic_skip@) set(AM_UIC_TARGET_OPTIONS @_uic_target_options@) set(AM_UIC_OPTIONS_FILES @_qt_uic_options_files@) set(AM_UIC_OPTIONS_OPTIONS @_qt_uic_options_options@) +# RCC settings set(AM_RCC_SOURCES @_rcc_files@ ) set(AM_RCC_INPUTS @_rcc_inputs@) set(AM_RCC_OPTIONS_FILES @_rcc_options_files@) diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index 825eba0..d17faf6 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -194,7 +194,7 @@ static void MocSetupAutoTarget( makefile->AddDefinition( "_moc_options", cmOutputConverter::EscapeForCMake(_moc_options).c_str()); makefile->AddDefinition( - "_skip_moc", + "_moc_skip", cmOutputConverter::EscapeForCMake(cmJoin(skipMoc, ";")).c_str()); bool relaxedMode = makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE"); makefile->AddDefinition("_moc_relaxed_mode", relaxedMode ? "TRUE" : "FALSE"); @@ -278,7 +278,7 @@ static void UicSetupAutoTarget( skipped.insert(skipUic.begin(), skipUic.end()); makefile->AddDefinition( - "_skip_uic", + "_uic_skip", cmOutputConverter::EscapeForCMake(cmJoin(skipUic, ";")).c_str()); std::vector uiFilesWithOptions = @@ -898,10 +898,10 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( SetupSourceFiles(target, mocUicSources, mocUicHeaders, skipMoc, skipUic); } makefile->AddDefinition( - "_moc_uic_sources", + "_sources", cmOutputConverter::EscapeForCMake(cmJoin(mocUicSources, ";")).c_str()); makefile->AddDefinition( - "_moc_uic_headers", + "_headers", cmOutputConverter::EscapeForCMake(cmJoin(mocUicHeaders, ";")).c_str()); if (target->GetPropertyAsBool("AUTOMOC")) { diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 199e5cc..1d120d7 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -306,7 +306,7 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( this->Headers); // - Moc - cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_SKIP_MOC"), + cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_MOC_SKIP"), this->MocSkipList); cmSystemTools::ExpandListArgument( GetConfigDefinition(makefile, "AM_MOC_COMPILE_DEFINITIONS", config), @@ -318,7 +318,7 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( makefile->GetSafeDefinition("AM_MOC_OPTIONS"), this->MocOptions); // - Uic - cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_SKIP_UIC"), + cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_UIC_SKIP"), this->UicSkipList); cmSystemTools::ExpandListArgument( GetConfigDefinition(makefile, "AM_UIC_TARGET_OPTIONS", config), https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=aee6c5b3d38b7150a3276d69e28b2705dc20d586 commit aee6c5b3d38b7150a3276d69e28b2705dc20d586 Author: Sebastian Holtermann AuthorDate: Fri Feb 17 13:50:33 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:51:27 2017 -0500 Autogen: Tests: Add Q_PLUGIN_METADATA test diff --git a/Tests/QtAutogen/CMakeLists.txt b/Tests/QtAutogen/CMakeLists.txt index 40c23fa..260331b 100644 --- a/Tests/QtAutogen/CMakeLists.txt +++ b/Tests/QtAutogen/CMakeLists.txt @@ -86,7 +86,8 @@ try_compile(RCC_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/autorcc_depends" "${CMAKE_CURRENT_SOURCE_DIR}/autorcc_depends" autorcc_depends - CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" "-DQT_TEST_VERSION=${QT_TEST_VERSION}" + CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" + "-DQT_TEST_VERSION=${QT_TEST_VERSION}" "-DCMAKE_PREFIX_PATH=${Qt_PREFIX_DIR}" OUTPUT_VARIABLE output ) @@ -121,7 +122,8 @@ try_compile(MOC_RERUN "${CMAKE_CURRENT_BINARY_DIR}/automoc_rerun" "${CMAKE_CURRENT_SOURCE_DIR}/automoc_rerun" automoc_rerun - CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" "-DQT_TEST_VERSION=${QT_TEST_VERSION}" + CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" + "-DQT_TEST_VERSION=${QT_TEST_VERSION}" "-DCMAKE_PREFIX_PATH=${Qt_PREFIX_DIR}" OUTPUT_VARIABLE output ) @@ -215,5 +217,60 @@ add_subdirectory(mocIncludeStrict) add_subdirectory(mocIncludeRelaxed) # -- 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(mocPluginBinDir "${CMAKE_CURRENT_BINARY_DIR}/mocPlugin") + find_library(style_a_file "PluginStyleA" "${mocPluginBinDir}") + find_library(style_b_file "PluginStyleB" "${mocPluginBinDir}") + find_library(style_c_file "PluginStyleC" "${mocPluginBinDir}") + find_library(style_d_file "PluginStyleD" "${mocPluginBinDir}") + + file(TIMESTAMP "${style_a_file}" style_a_before "${timeformat}") + file(TIMESTAMP "${style_b_file}" style_b_before "${timeformat}") + file(TIMESTAMP "${style_c_file}" style_c_before "${timeformat}") + file(TIMESTAMP "${style_d_file}" style_d_before "${timeformat}") + + # Ensure that the timestamp will change and touch the json files + execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) + execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${mocPluginBinDir}/jsonFiles/StyleC.json") + execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${mocPluginBinDir}/jsonFiles/sub/StyleD.json") + + execute_process(COMMAND "${CMAKE_COMMAND}" --build . + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mocPlugin" + ) + + file(TIMESTAMP "${style_a_file}" style_a_after "${timeformat}") + file(TIMESTAMP "${style_b_file}" style_b_after "${timeformat}") + file(TIMESTAMP "${style_c_file}" style_c_after "${timeformat}") + file(TIMESTAMP "${style_d_file}" style_d_after "${timeformat}") + + if (style_a_after GREATER style_a_before) + message(SEND_ERROR "file (${style_a_file}) should not have changed!") + endif() + if (style_b_after GREATER style_b_before) + message(SEND_ERROR "file (${style_b_file}) should not have changed!") + endif() + if (NOT style_c_after GREATER style_c_before) + message(SEND_ERROR "file (${style_c_file}) should have changed!") + endif() + if (NOT style_d_after GREATER style_d_before) + message(SEND_ERROR "file (${style_d_file}) should have changed!") + endif() +endif() + +# -- Test # Complex test case add_subdirectory(complex) diff --git a/Tests/QtAutogen/mocPlugin/CMakeLists.txt b/Tests/QtAutogen/mocPlugin/CMakeLists.txt new file mode 100644 index 0000000..eed7d39 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 3.8) + +if (NOT QT_TEST_VERSION STREQUAL 5) + message(SEND_ERROR "Invalid Qt version specified.") +endif() +find_package(Qt5Widgets REQUIRED) + +if(Qt5_POSITION_INDEPENDENT_CODE AND CMAKE_CXX_COMPILE_OPTIONS_PIC) + add_definitions(${CMAKE_CXX_COMPILE_OPTIONS_PIC}) +endif() + +configure_file(jsonIn/StyleC.json jsonFiles/StyleC.json @ONLY) +configure_file(jsonIn/StyleD.json jsonFiles/sub/StyleD.json @ONLY) + +# Enable automoc +set(CMAKE_AUTOMOC TRUE) + +include_directories("${CMAKE_CURRENT_BINARY_DIR}/jsonFiles") +link_libraries(Qt5::Widgets) + +add_library(PluginStyleA MODULE StyleA.cpp) +add_library(PluginStyleB MODULE StyleB.cpp) +add_library(PluginStyleC MODULE StyleC.cpp) +add_library(PluginStyleD MODULE StyleD.cpp) +add_library(PluginStyleE MODULE StyleE.cpp) diff --git a/Tests/QtAutogen/mocPlugin/StyleA.cpp b/Tests/QtAutogen/mocPlugin/StyleA.cpp new file mode 100644 index 0000000..b5e8753 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleA.cpp @@ -0,0 +1,6 @@ +#include "StyleA.hpp" + +QStyle* StyleA::create(const QString& key) +{ + return 0; +} diff --git a/Tests/QtAutogen/mocPlugin/StyleA.hpp b/Tests/QtAutogen/mocPlugin/StyleA.hpp new file mode 100644 index 0000000..b105b02 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleA.hpp @@ -0,0 +1,15 @@ +#ifndef STYLEA_HPP +#define STYLEA_HPP + +#include + +class StyleA : public QStylePlugin +{ + Q_OBJECT + // Json file in local directory + Q_PLUGIN_METADATA(IID "org.styles.A" FILE "StyleA.json") +public: + QStyle* create(const QString& key); +}; + +#endif diff --git a/Tests/QtAutogen/mocPlugin/StyleA.json b/Tests/QtAutogen/mocPlugin/StyleA.json new file mode 100644 index 0000000..cc33953 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleA.json @@ -0,0 +1 @@ +{ "Keys": [ "Rocket", "Starbuster" ] } diff --git a/Tests/QtAutogen/mocPlugin/StyleB.cpp b/Tests/QtAutogen/mocPlugin/StyleB.cpp new file mode 100644 index 0000000..17d4400 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleB.cpp @@ -0,0 +1,6 @@ +#include "StyleB.hpp" + +QStyle* StyleB::create(const QString& key) +{ + return 0; +} diff --git a/Tests/QtAutogen/mocPlugin/StyleB.hpp b/Tests/QtAutogen/mocPlugin/StyleB.hpp new file mode 100644 index 0000000..ba89127 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleB.hpp @@ -0,0 +1,15 @@ +#ifndef STYLEB_HPP +#define STYLEB_HPP + +#include + +class StyleB : public QStylePlugin +{ + Q_OBJECT + // Json file in local subdirectory + Q_PLUGIN_METADATA(IID "org.styles.B" FILE "jsonIn/StyleB.json") +public: + QStyle* create(const QString& key); +}; + +#endif diff --git a/Tests/QtAutogen/mocPlugin/StyleC.cpp b/Tests/QtAutogen/mocPlugin/StyleC.cpp new file mode 100644 index 0000000..37e7564 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleC.cpp @@ -0,0 +1,6 @@ +#include "StyleC.hpp" + +QStyle* StyleC::create(const QString& key) +{ + return 0; +} diff --git a/Tests/QtAutogen/mocPlugin/StyleC.hpp b/Tests/QtAutogen/mocPlugin/StyleC.hpp new file mode 100644 index 0000000..9f71d75 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleC.hpp @@ -0,0 +1,15 @@ +#ifndef STYLEC_HPP +#define STYLEC_HPP + +#include + +class StyleC : public QStylePlugin +{ + Q_OBJECT + // Json file in global root directory + Q_PLUGIN_METADATA(IID "org.styles.C" FILE "StyleC.json") +public: + QStyle* create(const QString& key); +}; + +#endif diff --git a/Tests/QtAutogen/mocPlugin/StyleD.cpp b/Tests/QtAutogen/mocPlugin/StyleD.cpp new file mode 100644 index 0000000..48398bb --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleD.cpp @@ -0,0 +1,17 @@ +#include "StyleD.hpp" + +class StyleD : public QStylePlugin +{ + Q_OBJECT + // Json file in global sub director + Q_PLUGIN_METADATA(IID "org.styles.D" FILE "sub/StyleD.json") +public: + QStyle* create(const QString& key); +}; + +QStyle* StyleD::create(const QString& key) +{ + return 0; +} + +#include "StyleD.moc" diff --git a/Tests/QtAutogen/mocPlugin/StyleD.hpp b/Tests/QtAutogen/mocPlugin/StyleD.hpp new file mode 100644 index 0000000..2afe055 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleD.hpp @@ -0,0 +1,8 @@ +#ifndef STYLED_HPP +#define STYLED_HPP + +#include + +class StyleD; + +#endif diff --git a/Tests/QtAutogen/mocPlugin/StyleE.cpp b/Tests/QtAutogen/mocPlugin/StyleE.cpp new file mode 100644 index 0000000..8fc9a7f --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleE.cpp @@ -0,0 +1,6 @@ +#include "StyleE.hpp" + +QStyle* StyleE::create(const QString& key) +{ + return 0; +} diff --git a/Tests/QtAutogen/mocPlugin/StyleE.hpp b/Tests/QtAutogen/mocPlugin/StyleE.hpp new file mode 100644 index 0000000..80e0b79 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleE.hpp @@ -0,0 +1,15 @@ +#ifndef STYLEE_HPP +#define STYLEE_HPP + +#include + +class StyleE : public QStylePlugin +{ + Q_OBJECT + // No Json file + Q_PLUGIN_METADATA(IID "org.styles.E") +public: + QStyle* create(const QString& key); +}; + +#endif diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleB.json b/Tests/QtAutogen/mocPlugin/jsonIn/StyleB.json new file mode 100644 index 0000000..129cac4 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/jsonIn/StyleB.json @@ -0,0 +1 @@ +{ "Keys": [ "Rocket", "StarbusterB" ] } diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json b/Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json new file mode 100644 index 0000000..bf17580 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json @@ -0,0 +1 @@ +{ "Keys": [ "Rocket", "StarbusterC" ] } diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json b/Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json new file mode 100644 index 0000000..f7fcc19 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json @@ -0,0 +1 @@ +{ "Keys": [ "Rocket", "StarbusterD" ] } diff --git a/Tests/QtAutogen/mocPlugin/main.cpp b/Tests/QtAutogen/mocPlugin/main.cpp new file mode 100644 index 0000000..3ba2ddc --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/main.cpp @@ -0,0 +1,6 @@ +#include "StyleA.hpp" + +int main(int argv, char** args) +{ + return 0; +} https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=917af10b53626fabe9a833546450ac5d6af8b3ea commit 917af10b53626fabe9a833546450ac5d6af8b3ea Author: Sebastian Holtermann AuthorDate: Thu Feb 16 15:59:56 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:51:26 2017 -0500 Autogen: Tests: Add moc include tests diff --git a/Tests/QtAutogen/CMakeLists.txt b/Tests/QtAutogen/CMakeLists.txt index c1cdee2..40c23fa 100644 --- a/Tests/QtAutogen/CMakeLists.txt +++ b/Tests/QtAutogen/CMakeLists.txt @@ -207,5 +207,13 @@ target_link_libraries(skipRccB ${QT_LIBRARIES}) add_subdirectory(sameName) # -- Test +# Tests various include moc patterns +add_subdirectory(mocIncludeStrict) + +# -- Test +# Tests various include moc patterns +add_subdirectory(mocIncludeRelaxed) + +# -- Test # Complex test case add_subdirectory(complex) diff --git a/Tests/QtAutogen/mocInclude/ObjA.cpp b/Tests/QtAutogen/mocInclude/ObjA.cpp new file mode 100644 index 0000000..2ee47ec --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjA.cpp @@ -0,0 +1,24 @@ +#include "ObjA.hpp" + +class SubObjA : public QObject +{ + Q_OBJECT + +public: + SubObjA() = default; + ~SubObjA() = default; + + Q_SLOT + void aSlot(); +}; + +void SubObjA::aSlot() +{ +} + +void ObjA::go() +{ + SubObjA subObj; +} + +#include "ObjA.moc" diff --git a/Tests/QtAutogen/mocInclude/ObjA.hpp b/Tests/QtAutogen/mocInclude/ObjA.hpp new file mode 100644 index 0000000..281e90d --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjA.hpp @@ -0,0 +1,13 @@ +#ifndef OBJA_HPP +#define OBJA_HPP + +#include + +class ObjA : public QObject +{ + Q_OBJECT + Q_SLOT + void go(); +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/ObjB.cpp b/Tests/QtAutogen/mocInclude/ObjB.cpp new file mode 100644 index 0000000..abec06a --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjB.cpp @@ -0,0 +1,25 @@ +#include "ObjB.hpp" + +class SubObjB : public QObject +{ + Q_OBJECT + +public: + SubObjB() = default; + ~SubObjB() = default; + + Q_SLOT + void aSlot(); +}; + +void SubObjB::aSlot() +{ +} + +void ObjB::go() +{ + SubObjB subObj; +} + +#include "ObjB.moc" +#include "moc_ObjB.cpp" diff --git a/Tests/QtAutogen/mocInclude/ObjB.hpp b/Tests/QtAutogen/mocInclude/ObjB.hpp new file mode 100644 index 0000000..94f3d49 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjB.hpp @@ -0,0 +1,13 @@ +#ifndef OBJB_HPP +#define OBJB_HPP + +#include + +class ObjB : public QObject +{ + Q_OBJECT + Q_SLOT + void go(); +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/ObjC.cpp b/Tests/QtAutogen/mocInclude/ObjC.cpp new file mode 100644 index 0000000..bdcdb13 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjC.cpp @@ -0,0 +1,26 @@ +#include "ObjC.hpp" + +class SubObjC : public QObject +{ + Q_OBJECT + +public: + SubObjC() = default; + ~SubObjC() = default; + + 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 new file mode 100644 index 0000000..a8e98eb --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjC.hpp @@ -0,0 +1,13 @@ +#ifndef OBJC_HPP +#define OBJC_HPP + +#include + +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 new file mode 100644 index 0000000..9145ba3 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjD.cpp @@ -0,0 +1,26 @@ +#include "ObjD.hpp" + +class SubObjD : public QObject +{ + Q_OBJECT + +public: + SubObjD() = default; + ~SubObjD() = default; + + 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 new file mode 100644 index 0000000..b6ee098 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjD.hpp @@ -0,0 +1,13 @@ +#ifndef OBJD_HPP +#define OBJD_HPP + +#include + +class ObjD : public QObject +{ + Q_OBJECT + Q_SLOT + void go(); +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/subA/SubObjA.cpp b/Tests/QtAutogen/mocInclude/subA/SubObjA.cpp new file mode 100644 index 0000000..d780942 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subA/SubObjA.cpp @@ -0,0 +1,27 @@ +#include "SubObjA.hpp" + +namespace subA { + +class SubObjA : public QObject +{ + Q_OBJECT + +public: + SubObjA() = default; + ~SubObjA() = default; + + 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 new file mode 100644 index 0000000..31a18b6 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subA/SubObjA.hpp @@ -0,0 +1,16 @@ +#ifndef SUBOBJA_HPP +#define SUBOBJA_HPP + +#include + +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 new file mode 100644 index 0000000..e602e06 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subB/SubObjB.cpp @@ -0,0 +1,27 @@ +#include "SubObjB.hpp" + +namespace subB { + +class SubObjB : public QObject +{ + Q_OBJECT + +public: + SubObjB() = default; + ~SubObjB() = default; + + 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 new file mode 100644 index 0000000..3f29fa2 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subB/SubObjB.hpp @@ -0,0 +1,16 @@ +#ifndef SUBOBJB_HPP +#define SUBOBJB_HPP + +#include + +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 new file mode 100644 index 0000000..fb2d1ec --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subC/SubObjC.cpp @@ -0,0 +1,27 @@ +#include "SubObjC.hpp" + +namespace subC { + +class SubObjC : public QObject +{ + Q_OBJECT + +public: + SubObjC() = default; + ~SubObjC() = default; + + 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 new file mode 100644 index 0000000..dc251fd --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subC/SubObjC.hpp @@ -0,0 +1,16 @@ +#ifndef SUBOBJC_HPP +#define SUBOBJC_HPP + +#include + +namespace subC { + +class ObjC : public QObject +{ + Q_OBJECT + Q_SLOT + void go(); +}; +} + +#endif diff --git a/Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt b/Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt new file mode 100644 index 0000000..6a0829d --- /dev/null +++ b/Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt @@ -0,0 +1,18 @@ +# Test moc include patterns + +set(CMAKE_AUTOMOC_RELAXED_MODE TRUE) + +include_directories("../mocInclude") + +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 +) +target_link_libraries(mocIncludeRelaxed ${QT_LIBRARIES}) +set_target_properties(mocIncludeRelaxed PROPERTIES AUTOMOC ON) diff --git a/Tests/QtAutogen/mocIncludeRelaxed/main.cpp b/Tests/QtAutogen/mocIncludeRelaxed/main.cpp new file mode 100644 index 0000000..142d59e --- /dev/null +++ b/Tests/QtAutogen/mocIncludeRelaxed/main.cpp @@ -0,0 +1,14 @@ +#include "ObjA.hpp" +#include "ObjB.hpp" +#include "ObjC.hpp" + +int main(int argv, char** args) +{ + ObjA objA; + ObjB objB; + ObjC objC; + return 0; +} + +// Header in global subdirectory +#include "subB/moc_SubObjB.cpp" diff --git a/Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt b/Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt new file mode 100644 index 0000000..22e93a8 --- /dev/null +++ b/Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt @@ -0,0 +1,18 @@ +# Test moc include patterns + +set(CMAKE_AUTOMOC_RELAXED_MODE FALSE) + +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) diff --git a/Tests/QtAutogen/mocIncludeStrict/main.cpp b/Tests/QtAutogen/mocIncludeStrict/main.cpp new file mode 100644 index 0000000..142d59e --- /dev/null +++ b/Tests/QtAutogen/mocIncludeStrict/main.cpp @@ -0,0 +1,14 @@ +#include "ObjA.hpp" +#include "ObjB.hpp" +#include "ObjC.hpp" + +int main(int argv, char** args) +{ + ObjA objA; + ObjB objB; + ObjC objC; + return 0; +} + +// Header in global subdirectory +#include "subB/moc_SubObjB.cpp" https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4be7c81272e559b1ff572df5f5b274234a04a286 commit 4be7c81272e559b1ff572df5f5b274234a04a286 Author: Sebastian Holtermann AuthorDate: Thu Feb 16 15:05:11 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:51:26 2017 -0500 Autogen: Tests: Clean comments diff --git a/Tests/QtAutogen/CMakeLists.txt b/Tests/QtAutogen/CMakeLists.txt index 4b90ad8..c1cdee2 100644 --- a/Tests/QtAutogen/CMakeLists.txt +++ b/Tests/QtAutogen/CMakeLists.txt @@ -46,26 +46,26 @@ endif() get_property(QT_COMPILE_FEATURES TARGET ${QT_QTCORE_TARGET} PROPERTY INTERFACE_COMPILE_FEATURES) -# -- Test: AUTORCC +# -- Test # RCC only add_executable(rccOnly rccOnly.cpp rccOnlyRes.qrc) set_property(TARGET rccOnly PROPERTY AUTORCC ON) target_link_libraries(rccOnly ${QT_QTCORE_TARGET}) -# -- Test: AUTORCC +# -- Test # RCC empty add_executable(rccEmpty rccEmpty.cpp rccEmptyRes.qrc) set_property(TARGET rccEmpty PROPERTY AUTORCC ON) target_link_libraries(rccEmpty ${QT_QTCORE_TARGET}) -# -- Test: AUTOUIC +# -- Test # UIC only qtx_wrap_cpp(uicOnlyMoc uicOnlySource/uiconly.h) add_executable(uicOnly uicOnlySource/uiconly.cpp ${uicOnlyMoc}) set_property(TARGET uicOnly PROPERTY AUTOUIC ON) target_link_libraries(uicOnly ${QT_LIBRARIES}) -# -- Test: AUTOMOC, AUTORCC +# -- Test # Add not_generated_file.qrc to the source list to get the file-level # dependency, but don't generate a c++ file from it. Disable the AUTORCC # feature for this target. This tests that qrc files in the sources don't @@ -80,7 +80,7 @@ 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: AUTORCC +# -- Test # When a file listed in a .qrc file changes the target must be rebuilt try_compile(RCC_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/autorcc_depends" @@ -115,7 +115,7 @@ if (NOT file1_step1 GREATER file1_before) message(SEND_ERROR "file1 (${qrc_file1}) should have changed in the first step!") endif() -# -- Test: AUTOMOC +# -- Test # Ensure a repeated build succeeds when a header containing a QObject changes try_compile(MOC_RERUN "${CMAKE_CURRENT_BINARY_DIR}/automoc_rerun" @@ -139,7 +139,7 @@ if (automoc_rerun_result) message(SEND_ERROR "Second build of automoc_rerun failed.") endif() -# -- Test: AUTOMOC, SKIP_AUTOMOC +# -- Test # Test for SKIP_AUTOMOC and SKIP_AUTOGEN on an AUTOMOC enabled target qtx_wrap_cpp(skipMocWrapMoc skipSource/qItemA.hpp @@ -161,7 +161,7 @@ set_property(TARGET skipMocB PROPERTY AUTOMOC ON) set_property(TARGET skipMocB PROPERTY AUTOUIC ON) target_link_libraries(skipMocB ${QT_LIBRARIES}) -# -- Test: AUTOUIC, SKIP_AUTOUIC +# -- Test # Test for SKIP_AUTOUIC and SKIP_AUTOGEN on an AUTOUIC enabled target set(skipUicSources skipUic.cpp @@ -181,7 +181,7 @@ set_property(TARGET skipUicB PROPERTY AUTOUIC ON) set_property(TARGET skipUicB PROPERTY AUTOMOC ON) target_link_libraries(skipUicB ${QT_LIBRARIES}) -# -- Test: AUTORCC, SKIP_AUTORCC +# -- Test # Test for SKIP_AUTORCC and SKIP_AUTOGEN on an AUTORCC enabled target set(skipRccSources skipRcc.cpp @@ -202,10 +202,10 @@ set_property(TARGET skipRccB PROPERTY AUTOUIC ON) set_property(TARGET skipRccB PROPERTY AUTOMOC ON) target_link_libraries(skipRccB ${QT_LIBRARIES}) -# -- Test: AUTOMOC AUTORCC +# -- Test # Source files with the same basename in different subdirectories add_subdirectory(sameName) -# -- Test: AUTOMOC AUTORCC AUTOUIC +# -- Test # Complex test case add_subdirectory(complex) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0136d1354b5957a1d583526dfdb74f176939f56c commit 0136d1354b5957a1d583526dfdb74f176939f56c Author: Sebastian Holtermann AuthorDate: Fri Feb 17 18:44:10 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:51:26 2017 -0500 Autogen: Log simplifications The logging methods now automatically add an end-of-line to the message if it is missing. diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 7c7ad83..199e5cc 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -464,9 +464,7 @@ bool cmQtAutoGenerators::SettingsFileWrite(const std::string& targetDirectory) if (this->GenerateAllAny()) { const std::string filename = SettingsFile(targetDirectory); if (this->Verbose) { - std::ostringstream err; - err << "AutoGen: Writing settings file " << filename << "\n"; - this->LogInfo(err.str()); + this->LogInfo("AutoGen: Writing settings file " + filename); } cmsys::ofstream outfile; outfile.open(filename.c_str(), std::ios::trunc); @@ -482,8 +480,8 @@ bool cmQtAutoGenerators::SettingsFileWrite(const std::string& targetDirectory) cmSystemTools::RemoveFile(filename); { std::ostringstream err; - err << "AutoGen: Error: Writing old settings file failed: " << filename - << std::endl; + err << "AutoGen: Error: Writing old settings file failed: " + << filename; this->LogError(err.str()); } } @@ -685,12 +683,12 @@ void cmQtAutoGenerators::MocFindDepends( mocDepends[absFilename].insert(incFile); if (this->Verbose) { this->LogInfo("AutoMoc: Found dependency:\n \"" + absFilename + - "\"\n \"" + incFile + "\"\n"); + "\"\n \"" + incFile + "\""); } } else { this->LogWarning("AutoMoc: Warning: \"" + absFilename + "\"\n" + "Could not find dependency file \"" + match + - "\"\n"); + "\""); } } contentChars += filter.regExp.end(); @@ -740,10 +738,10 @@ bool cmQtAutoGenerators::ParseSourceFile( bool success = true; const std::string contentText = ReadAll(absFilename); if (contentText.empty()) { - std::ostringstream err; - err << "AutoGen: Warning: " << absFilename << "\n" + std::ostringstream ost; + ost << "AutoGen: Warning: " << absFilename << "\n" << "The file is empty\n"; - this->LogWarning(err.str()); + this->LogWarning(ost.str()); } else { // Parse source contents for MOC if (success && !this->MocSkip(absFilename)) { @@ -763,9 +761,7 @@ void cmQtAutoGenerators::UicParseContent( std::map >& uisIncluded) { if (this->Verbose) { - std::ostringstream err; - err << "AutoUic: Checking " << absFilename << "\n"; - this->LogInfo(err.str()); + this->LogInfo("AutoUic: Checking " + absFilename); } const char* contentChars = contentText.c_str(); @@ -791,9 +787,7 @@ bool cmQtAutoGenerators::MocParseSourceContent( std::map >& mocDepends, bool relaxed) { if (this->Verbose) { - std::ostringstream err; - err << "AutoMoc: Checking " << absFilename << "\n"; - this->LogInfo(err.str()); + this->LogInfo("AutoMoc: Checking " + absFilename); } const std::string scannedFileAbsPath = @@ -845,12 +839,12 @@ bool cmQtAutoGenerators::MocParseSourceContent( ownMocUnderscoreHeader = headerToMoc; } } else { - std::ostringstream err; - err << "AutoMoc: Error: " << absFilename << "\n" + std::ostringstream ost; + ost << "AutoMoc: Error: " << absFilename << "\n" << "The file includes the moc file \"" << incString << "\", but could not find header \"" << incRealBasename << '{' << JoinExts(this->HeaderExtensions) << "}\"\n"; - this->LogError(err.str()); + this->LogError(ost.str()); return false; } } else { @@ -870,34 +864,34 @@ bool cmQtAutoGenerators::MocParseSourceContent( // This is for KDE4 compatibility: fileToMoc = headerToMoc; if (!requiresMoc && (incBasename == scannedFileBasename)) { - std::ostringstream err; - err << "AutoMoc: Warning: " << absFilename << "\n" + std::ostringstream ost; + ost << "AutoMoc: Warning: " << absFilename << "\n" << "The file includes the moc file \"" << incString << "\"" << ", but does not contain a Q_OBJECT or Q_GADGET macro.\n" << "Running moc on \"" << headerToMoc << "\"!\n" << "Include \"moc_" << incBasename << ".cpp\" for a compatibility with " "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; - this->LogWarning(err.str()); + this->LogWarning(ost.str()); } else { - std::ostringstream err; - err << "AutoMoc: Warning: " << absFilename << "\n" + std::ostringstream ost; + ost << "AutoMoc: Warning: " << absFilename << "\n" << "The file includes the moc file \"" << incString << "\" instead of \"moc_" << incBasename << ".cpp\".\n" << "Running moc on \"" << headerToMoc << "\"!\n" << "Include \"moc_" << incBasename << ".cpp\" for compatibility with " "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; - this->LogWarning(err.str()); + this->LogWarning(ost.str()); } } else { - std::ostringstream err; - err << "AutoMoc: Error: " << absFilename << "\n" + std::ostringstream ost; + ost << "AutoMoc: Error: " << absFilename << "\n" << "The file includes the moc file \"" << incString << "\", which seems to be the moc file from a different " "source file. CMake also could not find a matching " "header.\n"; - this->LogError(err.str()); + this->LogError(ost.str()); return false; } } @@ -909,23 +903,23 @@ bool cmQtAutoGenerators::MocParseSourceContent( ownDotMocIncluded = true; // Accept but issue a warning if moc isn't required if (!requiresMoc) { - std::ostringstream err; - err << "AutoMoc: Error: " << absFilename << "\n" + std::ostringstream ost; + ost << "AutoMoc: Error: " << absFilename << "\n" << "The file includes the moc file \"" << incString << "\"" << ", but does not contain a Q_OBJECT or Q_GADGET " "macro.\n"; - this->LogWarning(err.str()); + this->LogWarning(ost.str()); } } else { // Don't allow FOO.moc include other than self in strict mode - std::ostringstream err; - err << "AutoMoc: Error: " << absFilename << "\n" + std::ostringstream ost; + ost << "AutoMoc: Error: " << absFilename << "\n" << "The file includes the moc file \"" << incString << "\", which seems to be the moc file from a different " "source file. This is not supported. Include \"" << scannedFileBasename << ".moc\" to run moc on this source file.\n"; - this->LogError(err.str()); + this->LogError(ost.str()); return false; } } @@ -946,8 +940,8 @@ bool cmQtAutoGenerators::MocParseSourceContent( // But warn, since this is not how it is supposed to be used. if (relaxed && !ownMocUnderscoreInclude.empty()) { // This is for KDE4 compatibility: - std::ostringstream err; - err << "AutoMoc: Warning: " << absFilename << "\n" + std::ostringstream ost; + ost << "AutoMoc: Warning: " << absFilename << "\n" << "The file contains a " << macroName << " macro, but does not include " << "\"" << scannedFileBasename << ".moc\", but instead includes " @@ -956,7 +950,7 @@ bool cmQtAutoGenerators::MocParseSourceContent( << "Better include \"" << scannedFileBasename << ".moc\" for compatibility with " "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; - this->LogWarning(err.str()); + this->LogWarning(ost.str()); // Use scanned source file instead of scanned header file as moc source mocsIncluded[absFilename] = ownMocUnderscoreInclude; @@ -965,12 +959,12 @@ bool cmQtAutoGenerators::MocParseSourceContent( mocsIncluded.erase(ownMocUnderscoreHeader); } else { // Otherwise always error out since it will not compile: - std::ostringstream err; - err << "AutoMoc: Error: " << absFilename << "\n" + std::ostringstream ost; + ost << "AutoMoc: Error: " << absFilename << "\n" << "The file contains a " << macroName << " macro, but does not include " << "\"" << scannedFileBasename << ".moc\"!\n"; - this->LogError(err.str()); + this->LogError(ost.str()); return false; } } @@ -985,9 +979,7 @@ void cmQtAutoGenerators::MocParseHeaderContent( { // Log if (this->Verbose) { - std::ostringstream err; - err << "AutoMoc: Checking " << absFilename << "\n"; - this->LogInfo(err.str()); + this->LogInfo("AutoMoc: Checking " + absFilename); } if (this->MocRequired(contentText)) { // Register moc job @@ -1079,15 +1071,14 @@ bool cmQtAutoGenerators::MocGenerateAll( std::map mergedMocs(mocsIncluded); mergedMocs.insert(mocsNotIncluded.begin(), mocsNotIncluded.end()); if (this->NameCollisionTest(mergedMocs, collisions)) { - std::ostringstream err; - err << "AutoMoc: Error: " + std::ostringstream ost; + ost << "AutoMoc: Error: " "The same moc file will be generated " - "from different sources." - << std::endl - << "To avoid this error either" << std::endl - << "- rename the source files or" << std::endl - << "- do not include the (moc_NAME.cpp|NAME.moc) file" << std::endl; - this->LogErrorNameCollision(err.str(), collisions); + "from different sources.\n" + "To avoid this error either\n" + "- rename the source files or\n" + "- do not include the (moc_NAME.cpp|NAME.moc) file"; + this->LogErrorNameCollision(ost.str(), collisions); return false; } } @@ -1123,21 +1114,20 @@ bool cmQtAutoGenerators::MocGenerateAll( // Compose moc_compilation.cpp content std::string automocSource; { - std::ostringstream outStream; - outStream << "/* This file is autogenerated, do not edit*/\n"; + std::ostringstream ost; + ost << "/* This file is autogenerated, do not edit*/\n"; if (mocsNotIncluded.empty()) { // Dummy content - outStream << "enum some_compilers { need_more_than_nothing };\n"; + ost << "enum some_compilers { need_more_than_nothing };\n"; } else { // Valid content for (std::map::const_iterator it = mocsNotIncluded.begin(); it != mocsNotIncluded.end(); ++it) { - outStream << "#include \"" << it->second << "\"\n"; + ost << "#include \"" << it->second << "\"\n"; } } - outStream.flush(); - automocSource = outStream.str(); + automocSource = ost.str(); } // Check if the content of moc_compilation.cpp changed @@ -1158,25 +1148,20 @@ bool cmQtAutoGenerators::MocGenerateAll( outfile.open(this->MocCppFilenameAbs.c_str(), std::ios::trunc); if (!outfile) { success = false; - std::ostringstream err; - err << "AutoMoc: error opening " << this->MocCppFilenameAbs << "\n"; - this->LogError(err.str()); + this->LogError("AutoMoc: error opening " + this->MocCppFilenameAbs); } else { outfile << automocSource; // Check for write errors if (!outfile.good()) { success = false; - std::ostringstream err; - err << "AutoMoc: error writing " << this->MocCppFilenameAbs << "\n"; - this->LogError(err.str()); + this->LogError("AutoMoc: error writing " + this->MocCppFilenameAbs); } } } } else if (mocCompFileGenerated) { // Only touch moc_compilation.cpp if (this->Verbose) { - this->LogInfo("Touching MOC compilation " + this->MocCppFilenameRel + - "\n"); + this->LogInfo("Touching MOC compilation " + this->MocCppFilenameRel); } cmSystemTools::Touch(this->MocCppFilenameAbs, false); } @@ -1256,12 +1241,12 @@ bool cmQtAutoGenerators::MocGenerateFile( if (!res || (retVal != 0)) { // Command failed { - std::ostringstream err; - err << "AutoMoc: Error: moc process failed for\n"; - err << "\"" << mocFileRel << "\"\n"; - err << "AutoMoc: Command:\n" << cmJoin(cmd, " ") << "\n"; - err << "AutoMoc: Command output:\n" << output << "\n"; - this->LogError(err.str()); + std::ostringstream ost; + ost << "AutoMoc: Error: moc process failed for\n"; + ost << "\"" << mocFileRel << "\"\n"; + ost << "AutoMoc: Command:\n" << cmJoin(cmd, " ") << "\n"; + ost << "AutoMoc: Command output:\n" << output << "\n"; + this->LogError(ost.str()); } cmSystemTools::RemoveFile(mocFileAbs); this->RunMocFailed = true; @@ -1310,12 +1295,11 @@ bool cmQtAutoGenerators::UicGenerateAll( { std::multimap collisions; if (this->NameCollisionTest(testMap, collisions)) { - std::ostringstream err; - err << "AutoUic: Error: The same ui_NAME.h file will be generated " - "from different sources." - << std::endl - << "To avoid this error rename the source files." << std::endl; - this->LogErrorNameCollision(err.str(), collisions); + std::ostringstream ost; + ost << "AutoUic: Error: The same ui_NAME.h file will be generated " + "from different sources.\n" + "To avoid this error rename the source files.\n"; + this->LogErrorNameCollision(ost.str(), collisions); return false; } } @@ -1396,13 +1380,13 @@ bool cmQtAutoGenerators::UicGenerateFile(const std::string& realName, if (!res || (retVal != 0)) { // Command failed { - std::ostringstream err; - err << "AutoUic: Error: uic process failed for\n"; - err << "\"" << uicFileRel << "\" needed by\n"; - err << "\"" << realName << "\"\n"; - err << "AutoUic: Command:\n" << cmJoin(cmd, " ") << "\n"; - err << "AutoUic: Command output:\n" << output << "\n"; - this->LogError(err.str()); + std::ostringstream ost; + ost << "AutoUic: Error: uic process failed for\n"; + ost << "\"" << uicFileRel << "\" needed by\n"; + ost << "\"" << realName << "\"\n"; + ost << "AutoUic: Command:\n" << cmJoin(cmd, " ") << "\n"; + ost << "AutoUic: Command output:\n" << output << "\n"; + this->LogError(ost.str()); } cmSystemTools::RemoveFile(uicFileAbs); this->RunUicFailed = true; @@ -1439,12 +1423,11 @@ bool cmQtAutoGenerators::RccGenerateAll() { std::multimap collisions; if (this->NameCollisionTest(qrcGenMap, collisions)) { - std::ostringstream err; - err << "AutoRcc: Error: The same qrc_NAME.cpp file" - " will be generated from different sources." - << std::endl - << "To avoid this error rename the source .qrc files." << std::endl; - this->LogErrorNameCollision(err.str(), collisions); + std::ostringstream ost; + ost << "AutoRcc: Error: The same qrc_NAME.cpp file" + " will be generated from different sources.\n" + "To avoid this error rename the source .qrc files.\n"; + this->LogErrorNameCollision(ost.str(), collisions); return false; } } @@ -1536,12 +1519,12 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile, if (!res || (retVal != 0)) { // Command failed { - std::ostringstream err; - err << "AutoRcc: Error: rcc process failed for\n"; - err << "\"" << rccOutputFile << "\"\n"; - err << "AutoRcc: Command:\n" << cmJoin(cmd, " ") << "\n"; - err << "AutoRcc: Command output:\n" << output << "\n"; - this->LogError(err.str()); + std::ostringstream ost; + ost << "AutoRcc: Error: rcc process failed for\n"; + ost << "\"" << rccOutputFile << "\"\n"; + ost << "AutoRcc: Command:\n" << cmJoin(cmd, " ") << "\n"; + ost << "AutoRcc: Command output:\n" << output << "\n"; + this->LogError(ost.str()); } cmSystemTools::RemoveFile(rccBuildFile); this->RunRccFailed = true; @@ -1559,18 +1542,23 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile, void cmQtAutoGenerators::LogErrorNameCollision( const std::string& message, - const std::multimap& collisions) + const std::multimap& collisions) const { typedef std::multimap::const_iterator Iter; - std::ostringstream err; + std::ostringstream ost; // Add message - err << message; + if (!message.empty()) { + ost << message; + if (message[message.size() - 1] != '\n') { + ost << '\n'; + } + } // Append collision list for (Iter it = collisions.begin(); it != collisions.end(); ++it) { - err << it->first << " : " << it->second << std::endl; + ost << it->first << " : " << it->second << '\n'; } - this->LogError(err.str()); + this->LogError(ost.str()); } void cmQtAutoGenerators::LogBold(const std::string& message) const @@ -1582,38 +1570,45 @@ void cmQtAutoGenerators::LogBold(const std::string& message) const void cmQtAutoGenerators::LogInfo(const std::string& message) const { - cmSystemTools::Stdout(message.c_str(), message.size()); + std::string msg(message); + if (!msg.empty()) { + if (msg[msg.size() - 1] != '\n') { + msg.push_back('\n'); + } + cmSystemTools::Stdout(msg.c_str(), msg.size()); + } } void cmQtAutoGenerators::LogWarning(const std::string& message) const { std::string msg(message); - msg += "\n"; - cmSystemTools::Stdout(msg.c_str(), msg.size()); + if (!msg.empty()) { + if (msg[msg.size() - 1] != '\n') { + msg.push_back('\n'); + } + // Append empty line + msg.push_back('\n'); + cmSystemTools::Stdout(msg.c_str(), msg.size()); + } } void cmQtAutoGenerators::LogError(const std::string& message) const { std::string msg(message); - msg += "\n"; - cmSystemTools::Stderr(msg.c_str(), msg.size()); + if (!msg.empty()) { + if (msg[msg.size() - 1] != '\n') { + msg.push_back('\n'); + } + // Append empty line + msg.push_back('\n'); + cmSystemTools::Stderr(msg.c_str(), msg.size()); + } } void cmQtAutoGenerators::LogCommand( const std::vector& command) const { - std::ostringstream sbuf; - for (std::vector::const_iterator cmdIt = command.begin(); - cmdIt != command.end(); ++cmdIt) { - if (cmdIt != command.begin()) { - sbuf << " "; - } - sbuf << *cmdIt; - } - if (!sbuf.str().empty()) { - sbuf << std::endl; - this->LogInfo(sbuf.str()); - } + this->LogInfo(cmJoin(command, " ")); } /** @@ -1736,7 +1731,7 @@ std::string cmQtAutoGenerators::FindIncludedFile( return cmsys::SystemTools::GetRealPath(testPath); } } - // Search globaly + // Search globally return FindInIncludeDirectories(includeString); } @@ -1764,16 +1759,14 @@ std::string cmQtAutoGenerators::FindInIncludeDirectories( * @brief Generates the parent directory of the given file on demand * @return True on success */ -bool cmQtAutoGenerators::MakeParentDirectory(const std::string& filename) +bool cmQtAutoGenerators::MakeParentDirectory(const std::string& filename) const { bool success = true; const std::string dirName = cmSystemTools::GetFilenamePath(filename); if (!dirName.empty()) { success = cmsys::SystemTools::MakeDirectory(dirName); if (!success) { - std::ostringstream err; - err << "AutoGen: Directory creation failed: " << dirName << std::endl; - this->LogError(err.str()); + this->LogError("AutoGen: Directory creation failed: " + dirName); } } return success; diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 9fd5c58..236d4c5 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -123,7 +123,7 @@ private: // - Logging void LogErrorNameCollision( const std::string& message, - const std::multimap& collisions); + const std::multimap& collisions) const; void LogBold(const std::string& message) const; void LogInfo(const std::string& message) const; void LogWarning(const std::string& message) const; @@ -137,7 +137,7 @@ private: std::string ChecksumedPath(const std::string& sourceFile, const char* basePrefix, const char* baseSuffix) const; - bool MakeParentDirectory(const std::string& filename); + bool MakeParentDirectory(const std::string& filename) const; bool FindHeader(std::string& header, const std::string& testBasePath) const; bool FindHeaderGlobal(std::string& header, https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1fc9fe74dab4276b22abfd1a79fc344945350227 commit 1fc9fe74dab4276b22abfd1a79fc344945350227 Author: Sebastian Holtermann AuthorDate: Fri Feb 17 14:47:20 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:51:25 2017 -0500 Autogen: Only touch an unchanged moc_compilation.cpp diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index e0e6d61..7c7ad83 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -1069,6 +1069,9 @@ bool cmQtAutoGenerators::MocGenerateAll( return true; } + bool mocCompFileGenerated = false; + bool mocCompChanged = false; + // look for name collisions { std::multimap collisions; @@ -1088,8 +1091,7 @@ bool cmQtAutoGenerators::MocGenerateAll( return false; } } - - // generate moc files that are included by source files. + // Generate moc files that are included by source files. { const std::string subDir = "include/"; for (std::map::const_iterator it = @@ -1102,16 +1104,14 @@ bool cmQtAutoGenerators::MocGenerateAll( } } } - - // generate moc files that are _not_ included by source files. - bool automocCppChanged = false; + // Generate moc files that are _not_ included by source files. { const std::string subDir; for (std::map::const_iterator it = mocsNotIncluded.begin(); it != mocsNotIncluded.end(); ++it) { if (this->MocGenerateFile(it->first, it->second, subDir, mocDepends)) { - automocCppChanged = true; + mocCompFileGenerated = true; } else { if (this->RunMocFailed) { return false; @@ -1140,46 +1140,47 @@ bool cmQtAutoGenerators::MocGenerateAll( automocSource = outStream.str(); } - // Check if we even need to update moc_compilation.cpp - if (!automocCppChanged) { - // compare contents of the moc_compilation.cpp file + // Check if the content of moc_compilation.cpp changed + { const std::string oldContents = ReadAll(this->MocCppFilenameAbs); - if (oldContents == automocSource) { - // nothing changed: don't touch the moc_compilation.cpp file - if (this->Verbose) { - std::ostringstream err; - err << "AutoMoc: " << this->MocCppFilenameRel << " still up to date" - << std::endl; - this->LogInfo(err.str()); - } - return true; - } + mocCompChanged = (oldContents != automocSource); } - // Actually write moc_compilation.cpp - this->LogBold("Generating MOC compilation " + this->MocCppFilenameRel); + bool success = true; + if (mocCompChanged) { + // Actually write moc_compilation.cpp + this->LogBold("Generating MOC compilation " + this->MocCppFilenameRel); - // Make sure the parent directory exists - bool success = this->MakeParentDirectory(this->MocCppFilenameAbs); - if (success) { - cmsys::ofstream outfile; - outfile.open(this->MocCppFilenameAbs.c_str(), std::ios::trunc); - if (!outfile) { - success = false; - std::ostringstream err; - err << "AutoMoc: error opening " << this->MocCppFilenameAbs << "\n"; - this->LogError(err.str()); - } else { - outfile << automocSource; - // Check for write errors - if (!outfile.good()) { + // Make sure the parent directory exists + success = this->MakeParentDirectory(this->MocCppFilenameAbs); + if (success) { + cmsys::ofstream outfile; + outfile.open(this->MocCppFilenameAbs.c_str(), std::ios::trunc); + if (!outfile) { success = false; std::ostringstream err; - err << "AutoMoc: error writing " << this->MocCppFilenameAbs << "\n"; + err << "AutoMoc: error opening " << this->MocCppFilenameAbs << "\n"; this->LogError(err.str()); + } else { + outfile << automocSource; + // Check for write errors + if (!outfile.good()) { + success = false; + std::ostringstream err; + err << "AutoMoc: error writing " << this->MocCppFilenameAbs << "\n"; + this->LogError(err.str()); + } } } + } else if (mocCompFileGenerated) { + // Only touch moc_compilation.cpp + if (this->Verbose) { + this->LogInfo("Touching MOC compilation " + this->MocCppFilenameRel + + "\n"); + } + cmSystemTools::Touch(this->MocCppFilenameAbs, false); } + return success; } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=698a94c0d95ac865d40ed5caaac1a5e10194adf4 commit 698a94c0d95ac865d40ed5caaac1a5e10194adf4 Author: Sebastian Holtermann AuthorDate: Fri Feb 17 11:56:02 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:51:25 2017 -0500 Autogen: Rebuild moc when Q_PLUGIN_METADATA json file changes Closes #15419 diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index e2d5f9b..e0e6d61 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -564,6 +564,16 @@ void cmQtAutoGenerators::Init(cmMakefile* makefile) this->MocIncludes.push_back(*it); } } + + // Insert MocDependFilter for Q_PLUGIN_METADATA + if (QtMajorVersion != "4") { + MocDependFilter filter; + filter.key = "Q_PLUGIN_METADATA"; + filter.regExp.compile("[\n][ \t]*" + "Q_PLUGIN_METADATA[ \t]*\\(" + "[^\\)]*FILE[ \t]*\"([^\"]+)\""); + this->MocDependFilters.push_back(filter); + } } bool cmQtAutoGenerators::RunAutogen() @@ -579,6 +589,7 @@ bool cmQtAutoGenerators::RunAutogen() // key = moc source filepath, value = moc output filepath std::map mocsIncluded; std::map mocsNotIncluded; + std::map > mocDepends; std::map > uisIncluded; // collects all headers which may need to be mocced std::set mocHeaderFiles; @@ -589,8 +600,8 @@ bool cmQtAutoGenerators::RunAutogen() it != this->Sources.end(); ++it) { const std::string& absFilename = cmsys::SystemTools::GetRealPath(*it); // Parse source file for MOC/UIC - if (!this->ParseSourceFile(absFilename, mocsIncluded, uisIncluded, - this->MocRelaxedMode)) { + if (!this->ParseSourceFile(absFilename, mocsIncluded, mocDepends, + uisIncluded, this->MocRelaxedMode)) { return false; } // Find additional headers @@ -610,10 +621,10 @@ bool cmQtAutoGenerators::RunAutogen() } } this->ParseHeaders(mocHeaderFiles, uicHeaderFiles, mocsIncluded, - mocsNotIncluded, uisIncluded); + mocsNotIncluded, mocDepends, uisIncluded); // Generate files - if (!this->MocGenerateAll(mocsIncluded, mocsNotIncluded)) { + if (!this->MocGenerateAll(mocsIncluded, mocsNotIncluded, mocDepends)) { return false; } if (!this->UicGenerateAll(uisIncluded)) { @@ -630,17 +641,18 @@ bool cmQtAutoGenerators::RunAutogen() * @brief Tests if the C++ content requires moc processing * @return True if moc is required */ -bool cmQtAutoGenerators::MocRequired(const std::string& text, +bool cmQtAutoGenerators::MocRequired(const std::string& contentText, std::string* macroName) { for (unsigned int ii = 0; ii != cmArraySize(this->MacroFilters); ++ii) { - MacroFilter& macroFilter = this->MacroFilters[ii]; - // Run a simple check before an expensive regular expression check - if (text.find(macroFilter.first) != std::string::npos) { - if (macroFilter.second.find(text)) { + MacroFilter& filter = this->MacroFilters[ii]; + // Run a simple find string operation before the expensive + // regular expression check + if (contentText.find(filter.first) != std::string::npos) { + if (filter.second.find(contentText)) { // Return macro name on demand if (macroName != CM_NULLPTR) { - *macroName = macroFilter.first; + *macroName = filter.first; } return true; } @@ -649,6 +661,44 @@ bool cmQtAutoGenerators::MocRequired(const std::string& text, return false; } +void cmQtAutoGenerators::MocFindDepends( + const std::string& absFilename, const std::string& contentText, + std::map >& mocDepends) +{ + for (std::vector::iterator fit = + this->MocDependFilters.begin(); + fit != this->MocDependFilters.end(); ++fit) { + MocDependFilter& filter = *fit; + // Run a simple find string operation before the expensive + // regular expression check + if (contentText.find(filter.key) != std::string::npos) { + // Run regular expression check loop + const char* contentChars = contentText.c_str(); + while (filter.regExp.find(contentChars)) { + // Evaluate match + const std::string match = filter.regExp.match(1); + if (!match.empty()) { + // Find the dependency file + const std::string incFile = + this->FindIncludedFile(absFilename, match); + if (!incFile.empty()) { + mocDepends[absFilename].insert(incFile); + if (this->Verbose) { + this->LogInfo("AutoMoc: Found dependency:\n \"" + absFilename + + "\"\n \"" + incFile + "\"\n"); + } + } else { + this->LogWarning("AutoMoc: Warning: \"" + absFilename + "\"\n" + + "Could not find dependency file \"" + match + + "\"\n"); + } + } + contentChars += filter.regExp.end(); + } + } + } +} + /** * @brief Tests if the file should be ignored for moc scanning * @return True if the file should be ignored @@ -684,11 +734,12 @@ bool cmQtAutoGenerators::UicSkip(const std::string& absFilename) const bool cmQtAutoGenerators::ParseSourceFile( const std::string& absFilename, std::map& mocsIncluded, + std::map >& mocDepends, std::map >& uisIncluded, bool relaxed) { bool success = true; - const std::string contentsString = ReadAll(absFilename); - if (contentsString.empty()) { + const std::string contentText = ReadAll(absFilename); + if (contentText.empty()) { std::ostringstream err; err << "AutoGen: Warning: " << absFilename << "\n" << "The file is empty\n"; @@ -696,19 +747,19 @@ bool cmQtAutoGenerators::ParseSourceFile( } else { // Parse source contents for MOC if (success && !this->MocSkip(absFilename)) { - success = this->ParseContentForMoc(absFilename, contentsString, - mocsIncluded, relaxed); + success = this->MocParseSourceContent(absFilename, contentText, + mocsIncluded, mocDepends, relaxed); } // Parse source contents for UIC if (success && !this->UicSkip(absFilename)) { - this->ParseContentForUic(absFilename, contentsString, uisIncluded); + this->UicParseContent(absFilename, contentText, uisIncluded); } } return success; } -void cmQtAutoGenerators::ParseContentForUic( - const std::string& absFilename, const std::string& contentsString, +void cmQtAutoGenerators::UicParseContent( + const std::string& absFilename, const std::string& contentText, std::map >& uisIncluded) { if (this->Verbose) { @@ -717,7 +768,7 @@ void cmQtAutoGenerators::ParseContentForUic( this->LogInfo(err.str()); } - const char* contentChars = contentsString.c_str(); + const char* contentChars = contentText.c_str(); if (strstr(contentChars, "ui_") != CM_NULLPTR) { while (this->RegExpUicInclude.find(contentChars)) { const std::string currentUi = this->RegExpUicInclude.match(1); @@ -734,9 +785,10 @@ void cmQtAutoGenerators::ParseContentForUic( /** * @return True on success */ -bool cmQtAutoGenerators::ParseContentForMoc( - const std::string& absFilename, const std::string& contentsString, - std::map& mocsIncluded, bool relaxed) +bool cmQtAutoGenerators::MocParseSourceContent( + const std::string& absFilename, const std::string& contentText, + std::map& mocsIncluded, + std::map >& mocDepends, bool relaxed) { if (this->Verbose) { std::ostringstream err; @@ -750,16 +802,15 @@ bool cmQtAutoGenerators::ParseContentForMoc( cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename); std::string macroName; - const bool requiresMoc = this->MocRequired(contentsString, ¯oName); + const bool requiresMoc = this->MocRequired(contentText, ¯oName); bool ownDotMocIncluded = false; - bool ownMocUnderscoreIncluded = false; - std::string ownMocUnderscoreFile; - std::string ownMocHeaderFile; + std::string ownMocUnderscoreInclude; + std::string ownMocUnderscoreHeader; // first a simple string check for "moc" is *much* faster than the regexp, // and if the string search already fails, we don't have to try the // expensive regexp - const char* contentChars = contentsString.c_str(); + const char* contentChars = contentText.c_str(); if (strstr(contentChars, "moc") != CM_NULLPTR) { // Iterate over all included moc files while (this->RegExpMocInclude.find(contentChars)) { @@ -785,11 +836,13 @@ bool cmQtAutoGenerators::ParseContentForMoc( const std::string headerToMoc = this->FindMocHeader(scannedFileAbsPath, incRealBasename, incSubDir); if (!headerToMoc.empty()) { + // Register moc job mocsIncluded[headerToMoc] = incString; + this->MocFindDepends(headerToMoc, contentText, mocDepends); + // Store meta information for relaxed mode if (relaxed && (incRealBasename == scannedFileBasename)) { - ownMocUnderscoreIncluded = true; - ownMocUnderscoreFile = incString; - ownMocHeaderFile = headerToMoc; + ownMocUnderscoreInclude = incString; + ownMocUnderscoreHeader = headerToMoc; } } else { std::ostringstream err; @@ -878,6 +931,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( } if (!fileToMoc.empty()) { mocsIncluded[fileToMoc] = incString; + this->MocFindDepends(fileToMoc, contentText, mocDepends); } } // Forward content pointer @@ -890,14 +944,14 @@ bool cmQtAutoGenerators::ParseContentForMoc( // If this is the case, the moc_foo.cpp should probably be generated from // foo.cpp instead of foo.h, because otherwise it won't build. // But warn, since this is not how it is supposed to be used. - if (relaxed && ownMocUnderscoreIncluded) { + if (relaxed && !ownMocUnderscoreInclude.empty()) { // This is for KDE4 compatibility: std::ostringstream err; err << "AutoMoc: Warning: " << absFilename << "\n" << "The file contains a " << macroName << " macro, but does not include " << "\"" << scannedFileBasename << ".moc\", but instead includes " - << "\"" << ownMocUnderscoreFile << "\".\n" + << "\"" << ownMocUnderscoreInclude << "\".\n" << "Running moc on \"" << absFilename << "\"!\n" << "Better include \"" << scannedFileBasename << ".moc\" for compatibility with " @@ -905,8 +959,10 @@ bool cmQtAutoGenerators::ParseContentForMoc( this->LogWarning(err.str()); // Use scanned source file instead of scanned header file as moc source - mocsIncluded[absFilename] = ownMocUnderscoreFile; - mocsIncluded.erase(ownMocHeaderFile); + mocsIncluded[absFilename] = ownMocUnderscoreInclude; + this->MocFindDepends(absFilename, contentText, mocDepends); + // Remove + mocsIncluded.erase(ownMocUnderscoreHeader); } else { // Otherwise always error out since it will not compile: std::ostringstream err; @@ -922,6 +978,25 @@ bool cmQtAutoGenerators::ParseContentForMoc( return true; } +void cmQtAutoGenerators::MocParseHeaderContent( + const std::string& absFilename, const std::string& contentText, + std::map& mocsNotIncluded, + std::map >& mocDepends) +{ + // Log + if (this->Verbose) { + std::ostringstream err; + err << "AutoMoc: Checking " << absFilename << "\n"; + this->LogInfo(err.str()); + } + if (this->MocRequired(contentText)) { + // Register moc job + mocsNotIncluded[absFilename] = + this->ChecksumedPath(absFilename, "moc_", ".cpp"); + this->MocFindDepends(absFilename, contentText, mocDepends); + } +} + void cmQtAutoGenerators::SearchHeadersForSourceFile( const std::string& absFilename, std::set& mocHeaderFiles, std::set& uicHeaderFiles) const @@ -958,6 +1033,7 @@ void cmQtAutoGenerators::ParseHeaders( const std::set& uicHeaderFiles, const std::map& mocsIncluded, std::map& mocsNotIncluded, + std::map >& mocDepends, std::map >& uisIncluded) { // Merged header files list to read files only once @@ -968,33 +1044,26 @@ void cmQtAutoGenerators::ParseHeaders( for (std::set::const_iterator hIt = headerFiles.begin(); hIt != headerFiles.end(); ++hIt) { const std::string& headerName = *hIt; - const std::string contents = ReadAll(headerName); + const std::string contentText = ReadAll(headerName); // Parse header content for MOC if ((mocHeaderFiles.find(headerName) != mocHeaderFiles.end()) && (mocsIncluded.find(headerName) == mocsIncluded.end())) { - // Log - if (this->Verbose) { - std::ostringstream err; - err << "AutoMoc: Checking " << headerName << "\n"; - this->LogInfo(err.str()); - } - if (this->MocRequired(contents)) { - mocsNotIncluded[headerName] = - this->ChecksumedPath(headerName, "moc_", ".cpp"); - } + this->MocParseHeaderContent(headerName, contentText, mocsNotIncluded, + mocDepends); } // Parse header content for UIC if (uicHeaderFiles.find(headerName) != uicHeaderFiles.end()) { - this->ParseContentForUic(headerName, contents, uisIncluded); + this->UicParseContent(headerName, contentText, uisIncluded); } } } bool cmQtAutoGenerators::MocGenerateAll( const std::map& mocsIncluded, - const std::map& mocsNotIncluded) + const std::map& mocsNotIncluded, + const std::map >& mocDepends) { if (!this->MocEnabled()) { return true; @@ -1022,11 +1091,11 @@ bool cmQtAutoGenerators::MocGenerateAll( // generate moc files that are included by source files. { - const std::string subDirPrefix = "include/"; + const std::string subDir = "include/"; for (std::map::const_iterator it = mocsIncluded.begin(); it != mocsIncluded.end(); ++it) { - if (!this->MocGenerateFile(it->first, it->second, subDirPrefix)) { + if (!this->MocGenerateFile(it->first, it->second, subDir, mocDepends)) { if (this->RunMocFailed) { return false; } @@ -1037,11 +1106,11 @@ bool cmQtAutoGenerators::MocGenerateAll( // generate moc files that are _not_ included by source files. bool automocCppChanged = false; { - const std::string subDirPrefix; + const std::string subDir; for (std::map::const_iterator it = mocsNotIncluded.begin(); it != mocsNotIncluded.end(); ++it) { - if (this->MocGenerateFile(it->first, it->second, subDirPrefix)) { + if (this->MocGenerateFile(it->first, it->second, subDir, mocDepends)) { automocCppChanged = true; } else { if (this->RunMocFailed) { @@ -1117,9 +1186,10 @@ bool cmQtAutoGenerators::MocGenerateAll( /** * @return True if a moc file was created. False may indicate an error. */ -bool cmQtAutoGenerators::MocGenerateFile(const std::string& sourceFile, - const std::string& mocFileName, - const std::string& subDirPrefix) +bool cmQtAutoGenerators::MocGenerateFile( + const std::string& sourceFile, const std::string& mocFileName, + const std::string& subDirPrefix, + const std::map >& mocDepends) { bool mocGenerated = false; bool generateMoc = this->GenerateAllMoc; @@ -1131,6 +1201,20 @@ bool cmQtAutoGenerators::MocGenerateFile(const std::string& sourceFile, if (!generateMoc) { // Test if the source file is newer that the build file generateMoc = FileAbsentOrOlder(mocFileAbs, sourceFile); + if (!generateMoc) { + // Test if a dependency file changed + std::map >::const_iterator dit = + mocDepends.find(sourceFile); + if (dit != mocDepends.end()) { + for (std::set::const_iterator fit = dit->second.begin(); + fit != dit->second.end(); ++fit) { + if (FileAbsentOrOlder(mocFileAbs, *fit)) { + generateMoc = true; + break; + } + } + } + } } if (generateMoc) { // Log @@ -1488,33 +1572,34 @@ void cmQtAutoGenerators::LogErrorNameCollision( this->LogError(err.str()); } -void cmQtAutoGenerators::LogBold(const std::string& message) +void cmQtAutoGenerators::LogBold(const std::string& message) const { cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue | cmsysTerminal_Color_ForegroundBold, message.c_str(), true, this->ColorOutput); } -void cmQtAutoGenerators::LogInfo(const std::string& message) +void cmQtAutoGenerators::LogInfo(const std::string& message) const { cmSystemTools::Stdout(message.c_str(), message.size()); } -void cmQtAutoGenerators::LogWarning(const std::string& message) +void cmQtAutoGenerators::LogWarning(const std::string& message) const { std::string msg(message); msg += "\n"; cmSystemTools::Stdout(msg.c_str(), msg.size()); } -void cmQtAutoGenerators::LogError(const std::string& message) +void cmQtAutoGenerators::LogError(const std::string& message) const { std::string msg(message); msg += "\n"; cmSystemTools::Stderr(msg.c_str(), msg.size()); } -void cmQtAutoGenerators::LogCommand(const std::vector& command) +void cmQtAutoGenerators::LogCommand( + const std::vector& command) const { std::ostringstream sbuf; for (std::vector::const_iterator cmdIt = command.begin(); @@ -1638,23 +1723,40 @@ std::string cmQtAutoGenerators::FindMocHeader(const std::string& basePath, return header; } +std::string cmQtAutoGenerators::FindIncludedFile( + const std::string& sourceFile, const std::string& includeString) const +{ + // Search in vicinity of the source + { + std::string testPath = cmSystemTools::GetFilenamePath(sourceFile); + testPath += '/'; + testPath += includeString; + if (cmsys::SystemTools::FileExists(testPath.c_str())) { + return cmsys::SystemTools::GetRealPath(testPath); + } + } + // Search globaly + return FindInIncludeDirectories(includeString); +} + /** * @brief Tries to find a file in the include directories * @return True on success */ -bool cmQtAutoGenerators::FindInIncludeDirectories( - std::string& file_n, const std::string& searchString) const +std::string cmQtAutoGenerators::FindInIncludeDirectories( + const std::string& includeString) const { + std::string res; for (std::vector::const_iterator iit = this->MocIncludePaths.begin(); iit != this->MocIncludePaths.end(); ++iit) { - const std::string fullPath = ((*iit) + '/' + searchString); + const std::string fullPath = ((*iit) + '/' + includeString); if (cmsys::SystemTools::FileExists(fullPath.c_str())) { - file_n = fullPath; - return true; + res = cmsys::SystemTools::GetRealPath(fullPath); + break; } } - return false; + return res; } /** diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 66f11c5..9fd5c58 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -21,6 +21,16 @@ public: bool Run(const std::string& targetDirectory, const std::string& config); private: + // - Types + + /// @brief Used to extract additional dependencies from content text + struct MocDependFilter + { + std::string key; + cmsys::RegularExpression regExp; + }; + typedef std::pair MacroFilter; + // - Configuration bool ReadAutogenInfoFile(cmMakefile* makefile, const std::string& targetDirectory, @@ -46,14 +56,19 @@ private: bool RunAutogen(); // - Content analysis - bool MocRequired(const std::string& text, + bool MocRequired(const std::string& contentText, std::string* macroName = CM_NULLPTR); + void MocFindDepends( + const std::string& absFilename, const std::string& contentText, + std::map >& mocDepends); + bool MocSkip(const std::string& absFilename) const; bool UicSkip(const std::string& absFilename) const; bool ParseSourceFile( const std::string& absFilename, std::map& mocsIncluded, + std::map >& mocDepends, std::map >& includedUis, bool relaxed); @@ -66,24 +81,32 @@ private: const std::set& uicHeaderFiles, const std::map& mocsIncluded, std::map& mocsNotIncluded, + std::map >& mocDepends, std::map >& includedUis); - void ParseContentForUic( - const std::string& fileName, const std::string& contentsString, + void UicParseContent( + const std::string& fileName, const std::string& contentText, std::map >& includedUis); - bool ParseContentForMoc(const std::string& absFilename, - const std::string& contentsString, - std::map& mocsIncluded, - bool relaxed); + bool MocParseSourceContent( + const std::string& absFilename, const std::string& contentText, + std::map& mocsIncluded, + std::map >& mocDepends, bool relaxed); + + void MocParseHeaderContent( + const std::string& absFilename, const std::string& contentText, + std::map& mocsNotIncluded, + std::map >& mocDepends); // - Moc file generation bool MocGenerateAll( const std::map& mocsIncluded, - const std::map& mocsNotIncluded); - bool MocGenerateFile(const std::string& sourceFile, - const std::string& mocFileName, - const std::string& subDirPrefix); + const std::map& mocsNotIncluded, + const std::map >& mocDepends); + bool MocGenerateFile( + const std::string& sourceFile, const std::string& mocFileName, + const std::string& subDirPrefix, + const std::map >& mocDepends); // - Uic file generation bool UicGenerateAll( @@ -101,11 +124,11 @@ private: void LogErrorNameCollision( const std::string& message, const std::multimap& collisions); - void LogBold(const std::string& message); - void LogInfo(const std::string& message); - void LogWarning(const std::string& message); - void LogError(const std::string& message); - void LogCommand(const std::vector& command); + void LogBold(const std::string& message) const; + void LogInfo(const std::string& message) const; + void LogWarning(const std::string& message) const; + void LogError(const std::string& message) const; + void LogCommand(const std::vector& command) const; // - Utility bool NameCollisionTest( @@ -122,8 +145,9 @@ private: std::string FindMocHeader(const std::string& basePath, const std::string& baseName, const std::string& subDir) const; - bool FindInIncludeDirectories(std::string& file_n, - const std::string& searchString) const; + std::string FindIncludedFile(const std::string& sourceFile, + const std::string& includeString) const; + std::string FindInIncludeDirectories(const std::string& includeString) const; // - Target names std::string OriginTargetName; @@ -154,6 +178,7 @@ private: std::vector MocIncludes; std::vector MocDefinitions; std::vector MocOptions; + std::vector MocDependFilters; // - Uic std::vector UicSkipList; std::vector UicTargetOptions; @@ -165,7 +190,6 @@ private: // - Utility cmFilePathChecksum fpathCheckSum; std::vector HeaderExtensions; - typedef std::pair MacroFilter; MacroFilter MacroFilters[2]; cmsys::RegularExpression RegExpMocInclude; cmsys::RegularExpression RegExpUicInclude; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=58ac0c6209b627137636e0feac6f4d59321dae54 commit 58ac0c6209b627137636e0feac6f4d59321dae54 Author: Sebastian Holtermann AuthorDate: Thu Feb 16 23:55:59 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:51:25 2017 -0500 Autogen: Use GetRealPath in central places only diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index a0cac68..e2d5f9b 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -587,7 +587,7 @@ bool cmQtAutoGenerators::RunAutogen() // Parse sources for (std::vector::const_iterator it = this->Sources.begin(); it != this->Sources.end(); ++it) { - const std::string& absFilename = *it; + const std::string& absFilename = cmsys::SystemTools::GetRealPath(*it); // Parse source file for MOC/UIC if (!this->ParseSourceFile(absFilename, mocsIncluded, uisIncluded, this->MocRelaxedMode)) { @@ -601,7 +601,7 @@ bool cmQtAutoGenerators::RunAutogen() // Parse headers for (std::vector::const_iterator it = this->Headers.begin(); it != this->Headers.end(); ++it) { - const std::string& headerName = *it; + const std::string& headerName = cmsys::SystemTools::GetRealPath(*it); if (!this->MocSkip(headerName)) { mocHeaderFiles.insert(headerName); } @@ -717,7 +717,6 @@ void cmQtAutoGenerators::ParseContentForUic( this->LogInfo(err.str()); } - const std::string realName = cmsys::SystemTools::GetRealPath(absFilename); const char* contentChars = contentsString.c_str(); if (strstr(contentChars, "ui_") != CM_NULLPTR) { while (this->RegExpUicInclude.find(contentChars)) { @@ -726,7 +725,7 @@ void cmQtAutoGenerators::ParseContentForUic( cmsys::SystemTools::GetFilenameWithoutLastExtension(currentUi); // basename should be the part of the ui filename used for // finding the correct header, so we need to remove the ui_ part - uisIncluded[realName].push_back(basename.substr(3)); + uisIncluded[absFilename].push_back(basename.substr(3)); contentChars += this->RegExpUicInclude.end(); } } @@ -746,9 +745,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( } const std::string scannedFileAbsPath = - cmsys::SystemTools::GetFilenamePath( - cmsys::SystemTools::GetRealPath(absFilename)) + - '/'; + cmsys::SystemTools::GetFilenamePath(absFilename) + '/'; const std::string scannedFileBasename = cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename); @@ -931,33 +928,27 @@ void cmQtAutoGenerators::SearchHeadersForSourceFile( { std::string basepaths[2]; { - std::string bpath = cmsys::SystemTools::GetFilenamePath( - cmsys::SystemTools::GetRealPath(absFilename)); + std::string bpath = cmsys::SystemTools::GetFilenamePath(absFilename); bpath += '/'; bpath += cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename); - // search for default header files and private header files - basepaths[0] = (bpath + "."); - basepaths[1] = (bpath + "_p."); + basepaths[0] = bpath; + basepaths[1] = bpath + "_p"; } for (const std::string* bpit = cmArrayBegin(basepaths); bpit != cmArrayEnd(basepaths); ++bpit) { - for (std::vector::const_iterator heit = - this->HeaderExtensions.begin(); - heit != this->HeaderExtensions.end(); ++heit) { - const std::string hname = (*bpit) + (*heit); - if (cmsys::SystemTools::FileExists(hname.c_str())) { - // Moc headers - if (!this->MocSkip(absFilename) && !this->MocSkip(hname)) { - mocHeaderFiles.insert(hname); - } - // Uic headers - if (!this->UicSkip(absFilename) && !this->UicSkip(hname)) { - uicHeaderFiles.insert(hname); - } - break; + std::string headerName; + if (this->FindHeader(headerName, *bpit)) { + // Moc headers + if (!this->MocSkip(absFilename) && !this->MocSkip(headerName)) { + mocHeaderFiles.insert(headerName); + } + // Uic headers + if (!this->UicSkip(absFilename) && !this->UicSkip(headerName)) { + uicHeaderFiles.insert(headerName); } + break; } } } @@ -1642,7 +1633,7 @@ std::string cmQtAutoGenerators::FindMocHeader(const std::string& basePath, } while (false); // Sanitize if (!header.empty()) { - header = cmSystemTools::CollapseFullPath(header); + header = cmsys::SystemTools::GetRealPath(header); } return header; } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1508ed9c65f1515313bca00790710820974cd7cc commit 1508ed9c65f1515313bca00790710820974cd7cc Author: Sebastian Holtermann AuthorDate: Thu Feb 16 22:03:43 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:51:24 2017 -0500 Autogen: Search moc includes in include directories diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index a98ae09..a0cac68 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -772,7 +772,8 @@ bool cmQtAutoGenerators::ParseContentForMoc( cmsys::SystemTools::GetFilenameWithoutLastExtension(incString); std::string incSubDir; if (incString.find_first_of('/') != std::string::npos) { - incSubDir = cmsys::SystemTools::GetFilenamePath(incString) + '/'; + incSubDir = cmsys::SystemTools::GetFilenamePath(incString); + incSubDir += '/'; } // If the moc include is of the moc_foo.cpp style we expect @@ -784,8 +785,8 @@ bool cmQtAutoGenerators::ParseContentForMoc( // Include: moc_FOO.cxx // Remove the moc_ part const std::string incRealBasename = incBasename.substr(4); - const std::string headerToMoc = this->FindMatchingHeader( - scannedFileAbsPath, incRealBasename, incSubDir); + const std::string headerToMoc = + this->FindMocHeader(scannedFileAbsPath, incRealBasename, incSubDir); if (!headerToMoc.empty()) { mocsIncluded[headerToMoc] = incString; if (relaxed && (incRealBasename == scannedFileBasename)) { @@ -813,8 +814,8 @@ bool cmQtAutoGenerators::ParseContentForMoc( ownDotMocIncluded = true; } else { // In relaxed mode try to find a header instead but issue a warning - const std::string headerToMoc = this->FindMatchingHeader( - scannedFileAbsPath, incBasename, incSubDir); + const std::string headerToMoc = + this->FindMocHeader(scannedFileAbsPath, incBasename, incSubDir); if (!headerToMoc.empty()) { // This is for KDE4 compatibility: fileToMoc = headerToMoc; @@ -1606,9 +1607,23 @@ bool cmQtAutoGenerators::FindHeader(std::string& header, return false; } -std::string cmQtAutoGenerators::FindMatchingHeader( - const std::string& basePath, const std::string& baseName, - const std::string& subDir) const +bool cmQtAutoGenerators::FindHeaderGlobal( + std::string& header, const std::string& testBasePath) const +{ + for (std::vector::const_iterator iit = + this->MocIncludePaths.begin(); + iit != this->MocIncludePaths.end(); ++iit) { + const std::string fullPath = ((*iit) + '/' + testBasePath); + if (FindHeader(header, fullPath)) { + return true; + } + } + return false; +} + +std::string cmQtAutoGenerators::FindMocHeader(const std::string& basePath, + const std::string& baseName, + const std::string& subDir) const { std::string header; do { @@ -1620,7 +1635,15 @@ std::string cmQtAutoGenerators::FindMatchingHeader( if (this->FindHeader(header, basePath + baseName)) { break; } + // Try include directories + if (this->FindHeaderGlobal(header, subDir + baseName)) { + break; + } } while (false); + // Sanitize + if (!header.empty()) { + header = cmSystemTools::CollapseFullPath(header); + } return header; } diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 1ab205d..66f11c5 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -117,9 +117,11 @@ private: bool MakeParentDirectory(const std::string& filename); bool FindHeader(std::string& header, const std::string& testBasePath) const; - std::string FindMatchingHeader(const std::string& basePath, - const std::string& baseName, - const std::string& subDir) const; + bool FindHeaderGlobal(std::string& header, + const std::string& testBasePath) const; + std::string FindMocHeader(const std::string& basePath, + const std::string& baseName, + const std::string& subDir) const; bool FindInIncludeDirectories(std::string& file_n, const std::string& searchString) const; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e4f61a211b960d3eab0253a2986ac3aa705a2661 commit e4f61a211b960d3eab0253a2986ac3aa705a2661 Author: Sebastian Holtermann AuthorDate: Thu Feb 16 21:09:04 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:51:24 2017 -0500 Autogen: Sort includes before composing include options diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 444acdb..a98ae09 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -509,15 +509,44 @@ void cmQtAutoGenerators::Init(cmMakefile* makefile) // Acquire header extensions this->HeaderExtensions = makefile->GetCMakeInstance()->GetHeaderExtensions(); + // Sort include directories on demand + if (this->IncludeProjectDirsBefore) { + // Move strings to temporary list + std::list includes; + includes.insert(includes.end(), this->MocIncludePaths.begin(), + this->MocIncludePaths.end()); + this->MocIncludePaths.clear(); + this->MocIncludePaths.reserve(includes.size()); + // Append project directories only + { + const char* movePaths[2] = { this->ProjectBinaryDir.c_str(), + this->ProjectSourceDir.c_str() }; + for (const char* const* mpit = cmArrayBegin(movePaths); + mpit != cmArrayEnd(movePaths); ++mpit) { + std::list::iterator it = includes.begin(); + while (it != includes.end()) { + const std::string& path = *it; + if (cmsys::SystemTools::StringStartsWith(path, *mpit)) { + this->MocIncludePaths.push_back(path); + it = includes.erase(it); + } else { + ++it; + } + } + } + } + // Append remaining directories + this->MocIncludePaths.insert(this->MocIncludePaths.end(), includes.begin(), + includes.end()); + } // Compose moc includes list - std::list mocIncludes; { std::set frameworkPaths; for (std::vector::const_iterator it = this->MocIncludePaths.begin(); it != this->MocIncludePaths.end(); ++it) { const std::string& path = *it; - mocIncludes.push_back("-I" + path); + this->MocIncludes.push_back("-I" + path); // Extract framework path if (cmHasLiteralSuffix(path, ".framework/Headers")) { // Go up twice to get to the framework root @@ -531,40 +560,10 @@ void cmQtAutoGenerators::Init(cmMakefile* makefile) // Append framework includes for (std::set::const_iterator it = frameworkPaths.begin(); it != frameworkPaths.end(); ++it) { - mocIncludes.push_back("-F"); - mocIncludes.push_back(*it); + this->MocIncludes.push_back("-F"); + this->MocIncludes.push_back(*it); } } - if (this->IncludeProjectDirsBefore) { - // Extract project includes - std::vector mocSortedIncludes; - { - std::vector movePaths; - movePaths.push_back("-I" + this->ProjectBinaryDir); - movePaths.push_back("-I" + this->ProjectSourceDir); - - for (std::vector::const_iterator mpit = movePaths.begin(); - mpit != movePaths.end(); ++mpit) { - std::list::iterator it = mocIncludes.begin(); - while (it != mocIncludes.end()) { - const std::string& path = *it; - if (cmsys::SystemTools::StringStartsWith(path, mpit->c_str())) { - mocSortedIncludes.push_back(path); - it = mocIncludes.erase(it); - } else { - ++it; - } - } - } - } - // Place extracted includes at the begin - this->MocIncludes.insert(this->MocIncludes.end(), - mocSortedIncludes.begin(), - mocSortedIncludes.end()); - } - // Append remaining includes - this->MocIncludes.insert(this->MocIncludes.end(), mocIncludes.begin(), - mocIncludes.end()); } bool cmQtAutoGenerators::RunAutogen() https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1224e67a0fd059aea194ad9a797e31a74d891618 commit 1224e67a0fd059aea194ad9a797e31a74d891618 Author: Sebastian Holtermann AuthorDate: Thu Feb 16 19:47:40 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:51:24 2017 -0500 Autogen: Add FindInIncludeDirectories method diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 8db7754..444acdb 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -1626,6 +1626,25 @@ std::string cmQtAutoGenerators::FindMatchingHeader( } /** + * @brief Tries to find a file in the include directories + * @return True on success + */ +bool cmQtAutoGenerators::FindInIncludeDirectories( + std::string& file_n, const std::string& searchString) const +{ + for (std::vector::const_iterator iit = + this->MocIncludePaths.begin(); + iit != this->MocIncludePaths.end(); ++iit) { + const std::string fullPath = ((*iit) + '/' + searchString); + if (cmsys::SystemTools::FileExists(fullPath.c_str())) { + file_n = fullPath; + return true; + } + } + return false; +} + +/** * @brief Generates the parent directory of the given file on demand * @return True on success */ diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index df555ad..1ab205d 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -120,6 +120,8 @@ private: std::string FindMatchingHeader(const std::string& basePath, const std::string& baseName, const std::string& subDir) const; + bool FindInIncludeDirectories(std::string& file_n, + const std::string& searchString) const; // - Target names std::string OriginTargetName; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=20ed0f59e4bbd5850d1271f99b53dcaa22cac417 commit 20ed0f59e4bbd5850d1271f99b53dcaa22cac417 Author: Sebastian Holtermann AuthorDate: Thu Feb 16 17:53:19 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:51:23 2017 -0500 Autogen: Synchronize header/source argument names diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 94be95e..df555ad 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -53,19 +53,19 @@ private: bool ParseSourceFile( const std::string& absFilename, - std::map& includedMocs, + std::map& mocsIncluded, std::map >& includedUis, bool relaxed); void SearchHeadersForSourceFile(const std::string& absFilename, - std::set& absHeadersMoc, - std::set& absHeadersUic) const; + std::set& mocHeaderFiles, + std::set& uicHeaderFiles) const; void ParseHeaders( - const std::set& absHeadersMoc, - const std::set& absHeadersUic, - const std::map& includedMocs, - std::map& notIncludedMocs, + const std::set& mocHeaderFiles, + const std::set& uicHeaderFiles, + const std::map& mocsIncluded, + std::map& mocsNotIncluded, std::map >& includedUis); void ParseContentForUic( @@ -74,13 +74,13 @@ private: bool ParseContentForMoc(const std::string& absFilename, const std::string& contentsString, - std::map& includedMocs, + std::map& mocsIncluded, bool relaxed); // - Moc file generation bool MocGenerateAll( - const std::map& includedMocs, - const std::map& notIncludedMocs); + const std::map& mocsIncluded, + const std::map& mocsNotIncluded); bool MocGenerateFile(const std::string& sourceFile, const std::string& mocFileName, const std::string& subDirPrefix); https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f8125e7bee39b4b853fb9ea650a397dfb984a5e0 commit f8125e7bee39b4b853fb9ea650a397dfb984a5e0 Author: Sebastian Holtermann AuthorDate: Thu Feb 16 11:10:46 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:51:23 2017 -0500 Autogen: Split moc include paths on info reading diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 8daf4c1..8db7754 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -311,8 +311,9 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( cmSystemTools::ExpandListArgument( GetConfigDefinition(makefile, "AM_MOC_COMPILE_DEFINITIONS", config), this->MocDefinitions); - this->MocInfoIncludes = - GetConfigDefinition(makefile, "AM_MOC_INCLUDES", config); + cmSystemTools::ExpandListArgument( + GetConfigDefinition(makefile, "AM_MOC_INCLUDES", config), + this->MocIncludePaths); cmSystemTools::ExpandListArgument( makefile->GetSafeDefinition("AM_MOC_OPTIONS"), this->MocOptions); @@ -410,7 +411,7 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile, std::string& str = this->SettingsStringMoc; str += JoinOptionsList(this->MocDefinitions); str += " ~~~ "; - str += this->MocInfoIncludes; + str += JoinOptionsList(this->MocIncludePaths); str += " ~~~ "; str += JoinOptionsList(this->MocOptions); str += " ~~~ "; @@ -512,22 +513,19 @@ void cmQtAutoGenerators::Init(cmMakefile* makefile) std::list mocIncludes; { std::set frameworkPaths; - { - std::vector incPaths; - cmSystemTools::ExpandListArgument(this->MocInfoIncludes, incPaths); - for (std::vector::const_iterator it = incPaths.begin(); - it != incPaths.end(); ++it) { - const std::string& path = *it; - mocIncludes.push_back("-I" + path); - // Extract framework path - if (cmHasLiteralSuffix(path, ".framework/Headers")) { - // Go up twice to get to the framework root - std::vector pathComponents; - cmsys::SystemTools::SplitPath(path, pathComponents); - std::string frameworkPath = cmsys::SystemTools::JoinPath( - pathComponents.begin(), pathComponents.end() - 2); - frameworkPaths.insert(frameworkPath); - } + for (std::vector::const_iterator it = + this->MocIncludePaths.begin(); + it != this->MocIncludePaths.end(); ++it) { + const std::string& path = *it; + mocIncludes.push_back("-I" + path); + // Extract framework path + if (cmHasLiteralSuffix(path, ".framework/Headers")) { + // Go up twice to get to the framework root + std::vector pathComponents; + cmsys::SystemTools::SplitPath(path, pathComponents); + std::string frameworkPath = cmsys::SystemTools::JoinPath( + pathComponents.begin(), pathComponents.end() - 2); + frameworkPaths.insert(frameworkPath); } } // Append framework includes diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 12710b0..94be95e 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -143,10 +143,10 @@ private: std::string SettingsStringUic; std::string SettingsStringRcc; // - Moc - std::string MocInfoIncludes; std::string MocCppFilenameRel; std::string MocCppFilenameAbs; std::vector MocSkipList; + std::vector MocIncludePaths; std::vector MocIncludes; std::vector MocDefinitions; std::vector MocOptions; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=58699513c2248da7277b968d729bef5ba3471677 commit 58699513c2248da7277b968d729bef5ba3471677 Author: Sebastian Holtermann AuthorDate: Thu Feb 16 10:31:03 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:51:23 2017 -0500 Autogen: Loop based macro detection instead of code duplication diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 27b99af..8daf4c1 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -213,9 +213,12 @@ cmQtAutoGenerators::cmQtAutoGenerators() } } + this->MacroFilters[0].first = "Q_OBJECT"; + this->MacroFilters[0].second.compile("[\n][ \t]*Q_OBJECT[^a-zA-Z0-9_]"); + this->MacroFilters[1].first = "Q_GADGET"; + this->MacroFilters[1].second.compile("[\n][ \t]*Q_GADGET[^a-zA-Z0-9_]"); + // Precompile regular expressions - this->RegExpQObject.compile("[\n][ \t]*Q_OBJECT[^a-zA-Z0-9_]"); - this->RegExpQGadget.compile("[\n][ \t]*Q_GADGET[^a-zA-Z0-9_]"); this->RegExpMocInclude.compile( "[\n][ \t]*#[ \t]*include[ \t]+" "[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]"); @@ -631,19 +634,19 @@ bool cmQtAutoGenerators::RunAutogen() * @return True if moc is required */ bool cmQtAutoGenerators::MocRequired(const std::string& text, - std::string& macroName) + std::string* macroName) { - // Run a simple check before an expensive regular expression check - if (strstr(text.c_str(), "Q_OBJECT") != CM_NULLPTR) { - if (this->RegExpQObject.find(text)) { - macroName = "Q_OBJECT"; - return true; - } - } - if (strstr(text.c_str(), "Q_GADGET") != CM_NULLPTR) { - if (this->RegExpQGadget.find(text)) { - macroName = "Q_GADGET"; - return true; + for (unsigned int ii = 0; ii != cmArraySize(this->MacroFilters); ++ii) { + MacroFilter& macroFilter = this->MacroFilters[ii]; + // Run a simple check before an expensive regular expression check + if (text.find(macroFilter.first) != std::string::npos) { + if (macroFilter.second.find(text)) { + // Return macro name on demand + if (macroName != CM_NULLPTR) { + *macroName = macroFilter.first; + } + return true; + } } } return false; @@ -753,7 +756,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename); std::string macroName; - const bool requiresMoc = this->MocRequired(contentsString, macroName); + const bool requiresMoc = this->MocRequired(contentsString, ¯oName); bool ownDotMocIncluded = false; bool ownMocUnderscoreIncluded = false; std::string ownMocUnderscoreFile; @@ -987,8 +990,7 @@ void cmQtAutoGenerators::ParseHeaders( err << "AutoMoc: Checking " << headerName << "\n"; this->LogInfo(err.str()); } - std::string macroName; - if (this->MocRequired(contents, macroName)) { + if (this->MocRequired(contents)) { mocsNotIncluded[headerName] = this->ChecksumedPath(headerName, "moc_", ".cpp"); } diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index e6f9160..12710b0 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -46,7 +46,8 @@ private: bool RunAutogen(); // - Content analysis - bool MocRequired(const std::string& text, std::string& macroName); + bool MocRequired(const std::string& text, + std::string* macroName = CM_NULLPTR); bool MocSkip(const std::string& absFilename) const; bool UicSkip(const std::string& absFilename) const; @@ -160,8 +161,8 @@ private: // - Utility cmFilePathChecksum fpathCheckSum; std::vector HeaderExtensions; - cmsys::RegularExpression RegExpQObject; - cmsys::RegularExpression RegExpQGadget; + typedef std::pair MacroFilter; + MacroFilter MacroFilters[2]; cmsys::RegularExpression RegExpMocInclude; cmsys::RegularExpression RegExpUicInclude; // - Flags https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d3980d2a959734370d2f7cf2f76d705ddf2da6e3 commit d3980d2a959734370d2f7cf2f76d705ddf2da6e3 Author: Sebastian Holtermann AuthorDate: Wed Feb 15 20:47:58 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:51:23 2017 -0500 Autogen: Issue a warning if moc isn't required in strict mode diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index f86a24b..27b99af 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -856,6 +856,15 @@ bool cmQtAutoGenerators::ParseContentForMoc( // Include self fileToMoc = absFilename; ownDotMocIncluded = true; + // Accept but issue a warning if moc isn't required + if (!requiresMoc) { + std::ostringstream err; + err << "AutoMoc: Error: " << absFilename << "\n" + << "The file includes the moc file \"" << incString << "\"" + << ", but does not contain a Q_OBJECT or Q_GADGET " + "macro.\n"; + this->LogWarning(err.str()); + } } else { // Don't allow FOO.moc include other than self in strict mode std::ostringstream err; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d26601ec0897eec870fe95413362d242202d7f2b commit d26601ec0897eec870fe95413362d242202d7f2b Author: Sebastian Holtermann AuthorDate: Wed Feb 15 20:36:39 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:51:22 2017 -0500 Autogen: Error message tweaks diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 7fb7bfb..f86a24b 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -807,7 +807,12 @@ bool cmQtAutoGenerators::ParseContentForMoc( std::string fileToMoc; if (relaxed) { // Mode: Relaxed - if (!requiresMoc || (incBasename != scannedFileBasename)) { + if (requiresMoc && (incBasename == scannedFileBasename)) { + // Include self + fileToMoc = absFilename; + ownDotMocIncluded = true; + } else { + // In relaxed mode try to find a header instead but issue a warning const std::string headerToMoc = this->FindMatchingHeader( scannedFileAbsPath, incBasename, incSubDir); if (!headerToMoc.empty()) { @@ -816,11 +821,10 @@ bool cmQtAutoGenerators::ParseContentForMoc( if (!requiresMoc && (incBasename == scannedFileBasename)) { std::ostringstream err; err << "AutoMoc: Warning: " << absFilename << "\n" - << "The file includes the moc file \"" << incString - << "\", but does not contain a " << macroName - << " macro. Running moc on " - << "\"" << headerToMoc << "\" ! Include \"moc_" - << incBasename + << "The file includes the moc file \"" << incString << "\"" + << ", but does not contain a Q_OBJECT or Q_GADGET macro.\n" + << "Running moc on \"" << headerToMoc << "\"!\n" + << "Include \"moc_" << incBasename << ".cpp\" for a compatibility with " "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; this->LogWarning(err.str()); @@ -828,10 +832,9 @@ bool cmQtAutoGenerators::ParseContentForMoc( std::ostringstream err; err << "AutoMoc: Warning: " << absFilename << "\n" << "The file includes the moc file \"" << incString - << "\" instead of \"moc_" << incBasename - << ".cpp\". Running moc on " - << "\"" << headerToMoc << "\" ! Include \"moc_" - << incBasename + << "\" instead of \"moc_" << incBasename << ".cpp\".\n" + << "Running moc on \"" << headerToMoc << "\"!\n" + << "Include \"moc_" << incBasename << ".cpp\" for compatibility with " "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; this->LogWarning(err.str()); @@ -846,10 +849,6 @@ bool cmQtAutoGenerators::ParseContentForMoc( this->LogError(err.str()); return false; } - } else { - // Include self - fileToMoc = absFilename; - ownDotMocIncluded = true; } } else { // Mode: Strict @@ -891,9 +890,9 @@ bool cmQtAutoGenerators::ParseContentForMoc( << "The file contains a " << macroName << " macro, but does not include " << "\"" << scannedFileBasename << ".moc\", but instead includes " - << "\"" << ownMocUnderscoreFile << "\". Running moc on " - << "\"" << absFilename << "\" ! Better include \"" - << scannedFileBasename + << "\"" << ownMocUnderscoreFile << "\".\n" + << "Running moc on \"" << absFilename << "\"!\n" + << "Better include \"" << scannedFileBasename << ".moc\" for compatibility with " "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; this->LogWarning(err.str()); @@ -907,7 +906,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( err << "AutoMoc: Error: " << absFilename << "\n" << "The file contains a " << macroName << " macro, but does not include " - << "\"" << scannedFileBasename << ".moc\" !\n"; + << "\"" << scannedFileBasename << ".moc\"!\n"; this->LogError(err.str()); return false; } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c84bca1030332d23d0fc6d06050e7a174f39d78a commit c84bca1030332d23d0fc6d06050e7a174f39d78a Author: Sebastian Holtermann AuthorDate: Wed Feb 15 19:30:08 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:51:22 2017 -0500 Autogen: Acquire and store header extensions in Init() diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 129a04e..7fb7bfb 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -245,9 +245,9 @@ bool cmQtAutoGenerators::Run(const std::string& targetDirectory, // Read old settings this->SettingsFileRead(mf.get(), targetDirectory); // Init and run - this->Init(); + this->Init(mf.get()); if (this->QtMajorVersion == "4" || this->QtMajorVersion == "5") { - if (!this->RunAutogen(mf.get())) { + if (!this->RunAutogen()) { return false; } } @@ -487,7 +487,7 @@ bool cmQtAutoGenerators::SettingsFileWrite(const std::string& targetDirectory) return success; } -void cmQtAutoGenerators::Init() +void cmQtAutoGenerators::Init(cmMakefile* makefile) { this->AutogenBuildSubDir = this->AutogenTargetName; this->AutogenBuildSubDir += "/"; @@ -502,6 +502,9 @@ void cmQtAutoGenerators::Init() this->ProjectSourceDir, this->ProjectBinaryDir); + // Acquire header extensions + this->HeaderExtensions = makefile->GetCMakeInstance()->GetHeaderExtensions(); + // Compose moc includes list std::list mocIncludes; { @@ -563,7 +566,7 @@ void cmQtAutoGenerators::Init() mocIncludes.end()); } -bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) +bool cmQtAutoGenerators::RunAutogen() { // the program goes through all .cpp files to see which moc files are // included. It is not really interesting how the moc file is named, but @@ -582,22 +585,17 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) std::set uicHeaderFiles; // Parse sources - { - const std::vector& headerExtensions = - makefile->GetCMakeInstance()->GetHeaderExtensions(); - - for (std::vector::const_iterator it = this->Sources.begin(); - it != this->Sources.end(); ++it) { - const std::string& absFilename = *it; - // Parse source file for MOC/UIC - if (!this->ParseSourceFile(absFilename, headerExtensions, mocsIncluded, - uisIncluded, this->MocRelaxedMode)) { - return false; - } - // Find additional headers - this->SearchHeadersForSourceFile(absFilename, headerExtensions, - mocHeaderFiles, uicHeaderFiles); + for (std::vector::const_iterator it = this->Sources.begin(); + it != this->Sources.end(); ++it) { + const std::string& absFilename = *it; + // Parse source file for MOC/UIC + if (!this->ParseSourceFile(absFilename, mocsIncluded, uisIncluded, + this->MocRelaxedMode)) { + return false; } + // Find additional headers + this->SearchHeadersForSourceFile(absFilename, mocHeaderFiles, + uicHeaderFiles); } // Parse headers @@ -655,7 +653,7 @@ bool cmQtAutoGenerators::MocRequired(const std::string& text, * @brief Tests if the file should be ignored for moc scanning * @return True if the file should be ignored */ -bool cmQtAutoGenerators::MocSkip(const std::string& absFilename) +bool cmQtAutoGenerators::MocSkip(const std::string& absFilename) const { if (this->MocEnabled()) { // Test if the file name is on the skip list @@ -669,7 +667,7 @@ bool cmQtAutoGenerators::MocSkip(const std::string& absFilename) /** * @brief Tests if the file name is in the skip list */ -bool cmQtAutoGenerators::UicSkip(const std::string& absFilename) +bool cmQtAutoGenerators::UicSkip(const std::string& absFilename) const { if (this->UicEnabled()) { // Test if the file name is on the skip list @@ -685,7 +683,6 @@ bool cmQtAutoGenerators::UicSkip(const std::string& absFilename) */ bool cmQtAutoGenerators::ParseSourceFile( const std::string& absFilename, - const std::vector& headerExtensions, std::map& mocsIncluded, std::map >& uisIncluded, bool relaxed) { @@ -699,8 +696,8 @@ bool cmQtAutoGenerators::ParseSourceFile( } else { // Parse source contents for MOC if (success && !this->MocSkip(absFilename)) { - success = this->ParseContentForMoc( - absFilename, contentsString, headerExtensions, mocsIncluded, relaxed); + success = this->ParseContentForMoc(absFilename, contentsString, + mocsIncluded, relaxed); } // Parse source contents for UIC if (success && !this->UicSkip(absFilename)) { @@ -740,7 +737,6 @@ void cmQtAutoGenerators::ParseContentForUic( */ bool cmQtAutoGenerators::ParseContentForMoc( const std::string& absFilename, const std::string& contentsString, - const std::vector& headerExtensions, std::map& mocsIncluded, bool relaxed) { if (this->Verbose) { @@ -788,8 +784,8 @@ bool cmQtAutoGenerators::ParseContentForMoc( // Include: moc_FOO.cxx // Remove the moc_ part const std::string incRealBasename = incBasename.substr(4); - const std::string headerToMoc = FindMatchingHeader( - scannedFileAbsPath, incRealBasename, incSubDir, headerExtensions); + const std::string headerToMoc = this->FindMatchingHeader( + scannedFileAbsPath, incRealBasename, incSubDir); if (!headerToMoc.empty()) { mocsIncluded[headerToMoc] = incString; if (relaxed && (incRealBasename == scannedFileBasename)) { @@ -802,7 +798,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( err << "AutoMoc: Error: " << absFilename << "\n" << "The file includes the moc file \"" << incString << "\", but could not find header \"" << incRealBasename << '{' - << JoinExts(headerExtensions) << "}\"\n"; + << JoinExts(this->HeaderExtensions) << "}\"\n"; this->LogError(err.str()); return false; } @@ -812,8 +808,8 @@ bool cmQtAutoGenerators::ParseContentForMoc( if (relaxed) { // Mode: Relaxed if (!requiresMoc || (incBasename != scannedFileBasename)) { - const std::string headerToMoc = FindMatchingHeader( - scannedFileAbsPath, incBasename, incSubDir, headerExtensions); + const std::string headerToMoc = this->FindMatchingHeader( + scannedFileAbsPath, incBasename, incSubDir); if (!headerToMoc.empty()) { // This is for KDE4 compatibility: fileToMoc = headerToMoc; @@ -921,9 +917,8 @@ bool cmQtAutoGenerators::ParseContentForMoc( } void cmQtAutoGenerators::SearchHeadersForSourceFile( - const std::string& absFilename, - const std::vector& headerExtensions, - std::set& mocHeaderFiles, std::set& uicHeaderFiles) + const std::string& absFilename, std::set& mocHeaderFiles, + std::set& uicHeaderFiles) const { std::string basepaths[2]; { @@ -940,8 +935,8 @@ void cmQtAutoGenerators::SearchHeadersForSourceFile( for (const std::string* bpit = cmArrayBegin(basepaths); bpit != cmArrayEnd(basepaths); ++bpit) { for (std::vector::const_iterator heit = - headerExtensions.begin(); - heit != headerExtensions.end(); ++heit) { + this->HeaderExtensions.begin(); + heit != this->HeaderExtensions.end(); ++heit) { const std::string hname = (*bpit) + (*heit); if (cmsys::SystemTools::FileExists(hname.c_str())) { // Moc headers @@ -1587,12 +1582,12 @@ std::string cmQtAutoGenerators::ChecksumedPath(const std::string& sourceFile, * appending different header extensions * @return True on success */ -bool cmQtAutoGenerators::FindHeader( - std::string& header, const std::string& testBasePath, - const std::vector& headerExtensions) const +bool cmQtAutoGenerators::FindHeader(std::string& header, + const std::string& testBasePath) const { - for (std::vector::const_iterator ext = headerExtensions.begin(); - ext != headerExtensions.end(); ++ext) { + for (std::vector::const_iterator ext = + this->HeaderExtensions.begin(); + ext != this->HeaderExtensions.end(); ++ext) { std::string testFilePath(testBasePath); testFilePath += '.'; testFilePath += (*ext); @@ -1606,17 +1601,16 @@ bool cmQtAutoGenerators::FindHeader( std::string cmQtAutoGenerators::FindMatchingHeader( const std::string& basePath, const std::string& baseName, - const std::string& subDir, - const std::vector& headerExtensions) const + const std::string& subDir) const { std::string header; do { if (!subDir.empty()) { - if (FindHeader(header, basePath + subDir + baseName, headerExtensions)) { + if (this->FindHeader(header, basePath + subDir + baseName)) { break; } } - if (FindHeader(header, basePath + baseName, headerExtensions)) { + if (this->FindHeader(header, basePath + baseName)) { break; } } while (false); diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 50df9f8..e6f9160 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -42,26 +42,23 @@ private: } // - Init and run - void Init(); - bool RunAutogen(cmMakefile* makefile); + void Init(cmMakefile* makefile); + bool RunAutogen(); // - Content analysis bool MocRequired(const std::string& text, std::string& macroName); - bool MocSkip(const std::string& absFilename); - bool UicSkip(const std::string& absFilename); + bool MocSkip(const std::string& absFilename) const; + bool UicSkip(const std::string& absFilename) const; bool ParseSourceFile( const std::string& absFilename, - const std::vector& headerExtensions, std::map& includedMocs, std::map >& includedUis, bool relaxed); - void SearchHeadersForSourceFile( - const std::string& absFilename, - const std::vector& headerExtensions, - std::set& absHeadersMoc, - std::set& absHeadersUic); + void SearchHeadersForSourceFile(const std::string& absFilename, + std::set& absHeadersMoc, + std::set& absHeadersUic) const; void ParseHeaders( const std::set& absHeadersMoc, @@ -76,7 +73,6 @@ private: bool ParseContentForMoc(const std::string& absFilename, const std::string& contentsString, - const std::vector& headerExtensions, std::map& includedMocs, bool relaxed); @@ -119,12 +115,10 @@ private: const char* baseSuffix) const; bool MakeParentDirectory(const std::string& filename); - bool FindHeader(std::string& header, const std::string& testBasePath, - const std::vector& headerExtensions) const; - std::string FindMatchingHeader( - const std::string& basePath, const std::string& baseName, - const std::string& subDir, - const std::vector& headerExtensions) const; + bool FindHeader(std::string& header, const std::string& testBasePath) const; + std::string FindMatchingHeader(const std::string& basePath, + const std::string& baseName, + const std::string& subDir) const; // - Target names std::string OriginTargetName; @@ -165,6 +159,7 @@ private: std::map > RccInputs; // - Utility cmFilePathChecksum fpathCheckSum; + std::vector HeaderExtensions; cmsys::RegularExpression RegExpQObject; cmsys::RegularExpression RegExpQGadget; cmsys::RegularExpression RegExpMocInclude; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=78031e7cdcead6a348191158c674ec341fdd43be commit 78031e7cdcead6a348191158c674ec341fdd43be Author: Sebastian Holtermann AuthorDate: Wed Feb 15 19:19:37 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:51:22 2017 -0500 Autogen: Overhaul FindMatchingHeader function diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 0605418..129a04e 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -73,42 +73,6 @@ static void SettingWrite(std::ostream& ostr, const char* key, } } -static std::string FindMatchingHeader( - const std::string& absPath, const std::string& mocSubDir, - const std::string& basename, - const std::vector& headerExtensions) -{ - std::string header; - for (std::vector::const_iterator ext = headerExtensions.begin(); - ext != headerExtensions.end(); ++ext) { - std::string sourceFilePath = absPath + basename + "." + (*ext); - if (cmsys::SystemTools::FileExists(sourceFilePath.c_str())) { - header = sourceFilePath; - break; - } - // Try subdirectory instead - if (!mocSubDir.empty()) { - sourceFilePath = mocSubDir + basename + "." + (*ext); - if (cmsys::SystemTools::FileExists(sourceFilePath.c_str())) { - header = sourceFilePath; - break; - } - } - } - - return header; -} - -static std::string ExtractSubDir(const std::string& absPath, - const std::string& currentMoc) -{ - std::string subDir; - if (currentMoc.find_first_of('/') != std::string::npos) { - subDir = absPath + cmsys::SystemTools::GetFilenamePath(currentMoc) + '/'; - } - return subDir; -} - static bool FileNameIsUnique(const std::string& filePath, const std::map& fileMap) { @@ -806,38 +770,38 @@ bool cmQtAutoGenerators::ParseContentForMoc( if (strstr(contentChars, "moc") != CM_NULLPTR) { // Iterate over all included moc files while (this->RegExpMocInclude.find(contentChars)) { - const std::string currentMoc = this->RegExpMocInclude.match(1); - // Basename of the current moc include - std::string basename = - cmsys::SystemTools::GetFilenameWithoutLastExtension(currentMoc); + const std::string incString = this->RegExpMocInclude.match(1); + // Basename of the moc include + const std::string incBasename = + cmsys::SystemTools::GetFilenameWithoutLastExtension(incString); + std::string incSubDir; + if (incString.find_first_of('/') != std::string::npos) { + incSubDir = cmsys::SystemTools::GetFilenamePath(incString) + '/'; + } // If the moc include is of the moc_foo.cpp style we expect // the Q_OBJECT class declaration in a header file. // If the moc include is of the foo.moc style we need to look for // a Q_OBJECT macro in the current source file, if it contains the // macro we generate the moc file from the source file. - if (cmHasLiteralPrefix(basename, "moc_")) { + if (cmHasLiteralPrefix(incBasename, "moc_")) { // Include: moc_FOO.cxx - // basename should be the part of the moc filename used for - // finding the correct header, so we need to remove the moc_ part - basename = basename.substr(4); - const std::string mocSubDir = - ExtractSubDir(scannedFileAbsPath, currentMoc); + // Remove the moc_ part + const std::string incRealBasename = incBasename.substr(4); const std::string headerToMoc = FindMatchingHeader( - scannedFileAbsPath, mocSubDir, basename, headerExtensions); - + scannedFileAbsPath, incRealBasename, incSubDir, headerExtensions); if (!headerToMoc.empty()) { - mocsIncluded[headerToMoc] = currentMoc; - if (relaxed && (basename == scannedFileBasename)) { + mocsIncluded[headerToMoc] = incString; + if (relaxed && (incRealBasename == scannedFileBasename)) { ownMocUnderscoreIncluded = true; - ownMocUnderscoreFile = currentMoc; + ownMocUnderscoreFile = incString; ownMocHeaderFile = headerToMoc; } } else { std::ostringstream err; err << "AutoMoc: Error: " << absFilename << "\n" - << "The file includes the moc file \"" << currentMoc - << "\", but could not find header \"" << basename << '{' + << "The file includes the moc file \"" << incString + << "\", but could not find header \"" << incRealBasename << '{' << JoinExts(headerExtensions) << "}\"\n"; this->LogError(err.str()); return false; @@ -847,31 +811,31 @@ bool cmQtAutoGenerators::ParseContentForMoc( std::string fileToMoc; if (relaxed) { // Mode: Relaxed - if (!requiresMoc || basename != scannedFileBasename) { - const std::string mocSubDir = - ExtractSubDir(scannedFileAbsPath, currentMoc); + if (!requiresMoc || (incBasename != scannedFileBasename)) { const std::string headerToMoc = FindMatchingHeader( - scannedFileAbsPath, mocSubDir, basename, headerExtensions); + scannedFileAbsPath, incBasename, incSubDir, headerExtensions); if (!headerToMoc.empty()) { // This is for KDE4 compatibility: fileToMoc = headerToMoc; - if (!requiresMoc && basename == scannedFileBasename) { + if (!requiresMoc && (incBasename == scannedFileBasename)) { std::ostringstream err; err << "AutoMoc: Warning: " << absFilename << "\n" - << "The file includes the moc file \"" << currentMoc + << "The file includes the moc file \"" << incString << "\", but does not contain a " << macroName << " macro. Running moc on " - << "\"" << headerToMoc << "\" ! Include \"moc_" << basename + << "\"" << headerToMoc << "\" ! Include \"moc_" + << incBasename << ".cpp\" for a compatibility with " "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; this->LogWarning(err.str()); } else { std::ostringstream err; err << "AutoMoc: Warning: " << absFilename << "\n" - << "The file includes the moc file \"" << currentMoc - << "\" instead of \"moc_" << basename + << "The file includes the moc file \"" << incString + << "\" instead of \"moc_" << incBasename << ".cpp\". Running moc on " - << "\"" << headerToMoc << "\" ! Include \"moc_" << basename + << "\"" << headerToMoc << "\" ! Include \"moc_" + << incBasename << ".cpp\" for compatibility with " "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; this->LogWarning(err.str()); @@ -879,7 +843,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( } else { std::ostringstream err; err << "AutoMoc: Error: " << absFilename << "\n" - << "The file includes the moc file \"" << currentMoc + << "The file includes the moc file \"" << incString << "\", which seems to be the moc file from a different " "source file. CMake also could not find a matching " "header.\n"; @@ -893,7 +857,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( } } else { // Mode: Strict - if (basename == scannedFileBasename) { + if (incBasename == scannedFileBasename) { // Include self fileToMoc = absFilename; ownDotMocIncluded = true; @@ -901,7 +865,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( // Don't allow FOO.moc include other than self in strict mode std::ostringstream err; err << "AutoMoc: Error: " << absFilename << "\n" - << "The file includes the moc file \"" << currentMoc + << "The file includes the moc file \"" << incString << "\", which seems to be the moc file from a different " "source file. This is not supported. Include \"" << scannedFileBasename @@ -911,7 +875,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( } } if (!fileToMoc.empty()) { - mocsIncluded[fileToMoc] = currentMoc; + mocsIncluded[fileToMoc] = incString; } } // Forward content pointer @@ -919,11 +883,11 @@ bool cmQtAutoGenerators::ParseContentForMoc( } } - // In this case, check whether the scanned file itself contains a Q_OBJECT. - // If this is the case, the moc_foo.cpp should probably be generated from - // foo.cpp instead of foo.h, because otherwise it won't build. - // But warn, since this is not how it is supposed to be used. if (requiresMoc && !ownDotMocIncluded) { + // In this case, check whether the scanned file itself contains a Q_OBJECT. + // If this is the case, the moc_foo.cpp should probably be generated from + // foo.cpp instead of foo.h, because otherwise it won't build. + // But warn, since this is not how it is supposed to be used. if (relaxed && ownMocUnderscoreIncluded) { // This is for KDE4 compatibility: std::ostringstream err; @@ -1619,6 +1583,47 @@ std::string cmQtAutoGenerators::ChecksumedPath(const std::string& sourceFile, } /** + * @brief Tries to find the header file to the given file base path by + * appending different header extensions + * @return True on success + */ +bool cmQtAutoGenerators::FindHeader( + std::string& header, const std::string& testBasePath, + const std::vector& headerExtensions) const +{ + for (std::vector::const_iterator ext = headerExtensions.begin(); + ext != headerExtensions.end(); ++ext) { + std::string testFilePath(testBasePath); + testFilePath += '.'; + testFilePath += (*ext); + if (cmsys::SystemTools::FileExists(testFilePath.c_str())) { + header = testFilePath; + return true; + } + } + return false; +} + +std::string cmQtAutoGenerators::FindMatchingHeader( + const std::string& basePath, const std::string& baseName, + const std::string& subDir, + const std::vector& headerExtensions) const +{ + std::string header; + do { + if (!subDir.empty()) { + if (FindHeader(header, basePath + subDir + baseName, headerExtensions)) { + break; + } + } + if (FindHeader(header, basePath + baseName, headerExtensions)) { + break; + } + } while (false); + return header; +} + +/** * @brief Generates the parent directory of the given file on demand * @return True on success */ diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index a466b77..50df9f8 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -119,6 +119,13 @@ private: const char* baseSuffix) const; bool MakeParentDirectory(const std::string& filename); + bool FindHeader(std::string& header, const std::string& testBasePath, + const std::vector& headerExtensions) const; + std::string FindMatchingHeader( + const std::string& basePath, const std::string& baseName, + const std::string& subDir, + const std::vector& headerExtensions) const; + // - Target names std::string OriginTargetName; std::string AutogenTargetName; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c7f3bdedde2a38c8f2e46ca42f47efbde6252f1d commit c7f3bdedde2a38c8f2e46ca42f47efbde6252f1d Author: Sebastian Holtermann AuthorDate: Wed Feb 15 17:36:58 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:51:21 2017 -0500 Autogen: Don't list all search paths in error message diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index ebe9f28..0605418 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -838,13 +838,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( err << "AutoMoc: Error: " << absFilename << "\n" << "The file includes the moc file \"" << currentMoc << "\", but could not find header \"" << basename << '{' - << JoinExts(headerExtensions) << "}\" "; - if (mocSubDir.empty()) { - err << "in " << scannedFileAbsPath << "\n"; - } else { - err << "neither in " << scannedFileAbsPath << " nor in " - << mocSubDir << "\n"; - } + << JoinExts(headerExtensions) << "}\"\n"; this->LogError(err.str()); return false; } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=17a2cfbcdd41ee607556794e5210744b90005dfb commit 17a2cfbcdd41ee607556794e5210744b90005dfb Author: Sebastian Holtermann AuthorDate: Wed Feb 15 13:43:19 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:51:21 2017 -0500 Autogen: Indentation fix diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 1453711..ebe9f28 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -607,8 +607,7 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) // may not be included in the moc_compilation.cpp file anymore. OTOH if // there's a header containing Q_OBJECT where no corresponding moc file // is included anywhere a moc_.cpp file is created and included - // in - // the moc_compilation.cpp file. + // in the moc_compilation.cpp file. // key = moc source filepath, value = moc output filepath std::map mocsIncluded; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7111b59f020c3b6fa01136b608ce6777969f92e7 commit 7111b59f020c3b6fa01136b608ce6777969f92e7 Author: Sebastian Holtermann AuthorDate: Wed Feb 15 13:23:27 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:51:21 2017 -0500 Autogen: Rename moc related variables diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index f2a4174..1453711 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -528,11 +528,10 @@ void cmQtAutoGenerators::Init() this->AutogenBuildSubDir = this->AutogenTargetName; this->AutogenBuildSubDir += "/"; - this->OutMocCppFilenameRel = this->AutogenBuildSubDir; - this->OutMocCppFilenameRel += "moc_compilation.cpp"; + this->MocCppFilenameRel = this->AutogenBuildSubDir; + this->MocCppFilenameRel += "moc_compilation.cpp"; - this->OutMocCppFilenameAbs = - this->CurrentBinaryDir + this->OutMocCppFilenameRel; + this->MocCppFilenameAbs = this->CurrentBinaryDir + this->MocCppFilenameRel; // Init file path checksum generator fpathCheckSum.setupParentDirs(this->CurrentSourceDir, this->CurrentBinaryDir, @@ -1124,12 +1123,12 @@ bool cmQtAutoGenerators::MocGenerateAll( // Check if we even need to update moc_compilation.cpp if (!automocCppChanged) { // compare contents of the moc_compilation.cpp file - const std::string oldContents = ReadAll(this->OutMocCppFilenameAbs); + const std::string oldContents = ReadAll(this->MocCppFilenameAbs); if (oldContents == automocSource) { // nothing changed: don't touch the moc_compilation.cpp file if (this->Verbose) { std::ostringstream err; - err << "AutoMoc: " << this->OutMocCppFilenameRel << " still up to date" + err << "AutoMoc: " << this->MocCppFilenameRel << " still up to date" << std::endl; this->LogInfo(err.str()); } @@ -1138,17 +1137,17 @@ bool cmQtAutoGenerators::MocGenerateAll( } // Actually write moc_compilation.cpp - this->LogBold("Generating MOC compilation " + this->OutMocCppFilenameRel); + this->LogBold("Generating MOC compilation " + this->MocCppFilenameRel); // Make sure the parent directory exists - bool success = this->MakeParentDirectory(this->OutMocCppFilenameAbs); + bool success = this->MakeParentDirectory(this->MocCppFilenameAbs); if (success) { cmsys::ofstream outfile; - outfile.open(this->OutMocCppFilenameAbs.c_str(), std::ios::trunc); + outfile.open(this->MocCppFilenameAbs.c_str(), std::ios::trunc); if (!outfile) { success = false; std::ostringstream err; - err << "AutoMoc: error opening " << this->OutMocCppFilenameAbs << "\n"; + err << "AutoMoc: error opening " << this->MocCppFilenameAbs << "\n"; this->LogError(err.str()); } else { outfile << automocSource; @@ -1156,7 +1155,7 @@ bool cmQtAutoGenerators::MocGenerateAll( if (!outfile.good()) { success = false; std::ostringstream err; - err << "AutoMoc: error writing " << this->OutMocCppFilenameAbs << "\n"; + err << "AutoMoc: error writing " << this->MocCppFilenameAbs << "\n"; this->LogError(err.str()); } } diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index f6caed9..a466b77 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -141,10 +141,10 @@ private: std::string SettingsStringUic; std::string SettingsStringRcc; // - Moc - std::vector MocSkipList; std::string MocInfoIncludes; - std::string OutMocCppFilenameRel; - std::string OutMocCppFilenameAbs; + std::string MocCppFilenameRel; + std::string MocCppFilenameAbs; + std::vector MocSkipList; std::vector MocIncludes; std::vector MocDefinitions; std::vector MocOptions; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=82e0d0642a42b0592be27ed20efb43e34aaa2091 commit 82e0d0642a42b0592be27ed20efb43e34aaa2091 Author: Sebastian Holtermann AuthorDate: Wed Feb 15 12:53:39 2017 +0100 Commit: Brad King CommitDate: Mon Feb 20 15:51:20 2017 -0500 Autogen: Overhaul moc include list generation diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index a167705..f2a4174 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -539,58 +539,65 @@ void cmQtAutoGenerators::Init() this->ProjectSourceDir, this->ProjectBinaryDir); - std::vector incPaths; - cmSystemTools::ExpandListArgument(this->MocInfoIncludes, incPaths); - - std::set frameworkPaths; - for (std::vector::const_iterator it = incPaths.begin(); - it != incPaths.end(); ++it) { - const std::string& path = *it; - this->MocIncludes.push_back("-I" + path); - if (cmHasLiteralSuffix(path, ".framework/Headers")) { - // Go up twice to get to the framework root - std::vector pathComponents; - cmsys::SystemTools::SplitPath(path, pathComponents); - std::string frameworkPath = cmsys::SystemTools::JoinPath( - pathComponents.begin(), pathComponents.end() - 2); - frameworkPaths.insert(frameworkPath); + // Compose moc includes list + std::list mocIncludes; + { + std::set frameworkPaths; + { + std::vector incPaths; + cmSystemTools::ExpandListArgument(this->MocInfoIncludes, incPaths); + for (std::vector::const_iterator it = incPaths.begin(); + it != incPaths.end(); ++it) { + const std::string& path = *it; + mocIncludes.push_back("-I" + path); + // Extract framework path + if (cmHasLiteralSuffix(path, ".framework/Headers")) { + // Go up twice to get to the framework root + std::vector pathComponents; + cmsys::SystemTools::SplitPath(path, pathComponents); + std::string frameworkPath = cmsys::SystemTools::JoinPath( + pathComponents.begin(), pathComponents.end() - 2); + frameworkPaths.insert(frameworkPath); + } + } + } + // Append framework includes + for (std::set::const_iterator it = frameworkPaths.begin(); + it != frameworkPaths.end(); ++it) { + mocIncludes.push_back("-F"); + mocIncludes.push_back(*it); } } - - for (std::set::const_iterator it = frameworkPaths.begin(); - it != frameworkPaths.end(); ++it) { - this->MocIncludes.push_back("-F"); - this->MocIncludes.push_back(*it); - } - if (this->IncludeProjectDirsBefore) { - const std::string binDir = "-I" + this->ProjectBinaryDir; - const std::string srcDir = "-I" + this->ProjectSourceDir; - - std::list sortedMocIncludes; - std::list::iterator it = this->MocIncludes.begin(); - while (it != this->MocIncludes.end()) { - if (cmsys::SystemTools::StringStartsWith(*it, binDir.c_str())) { - sortedMocIncludes.push_back(*it); - it = this->MocIncludes.erase(it); - } else { - ++it; - } - } - it = this->MocIncludes.begin(); - while (it != this->MocIncludes.end()) { - if (cmsys::SystemTools::StringStartsWith(*it, srcDir.c_str())) { - sortedMocIncludes.push_back(*it); - it = this->MocIncludes.erase(it); - } else { - ++it; + // Extract project includes + std::vector mocSortedIncludes; + { + std::vector movePaths; + movePaths.push_back("-I" + this->ProjectBinaryDir); + movePaths.push_back("-I" + this->ProjectSourceDir); + + for (std::vector::const_iterator mpit = movePaths.begin(); + mpit != movePaths.end(); ++mpit) { + std::list::iterator it = mocIncludes.begin(); + while (it != mocIncludes.end()) { + const std::string& path = *it; + if (cmsys::SystemTools::StringStartsWith(path, mpit->c_str())) { + mocSortedIncludes.push_back(path); + it = mocIncludes.erase(it); + } else { + ++it; + } + } } } - sortedMocIncludes.insert(sortedMocIncludes.end(), - this->MocIncludes.begin(), - this->MocIncludes.end()); - this->MocIncludes = sortedMocIncludes; - } + // Place extracted includes at the begin + this->MocIncludes.insert(this->MocIncludes.end(), + mocSortedIncludes.begin(), + mocSortedIncludes.end()); + } + // Append remaining includes + this->MocIncludes.insert(this->MocIncludes.end(), mocIncludes.begin(), + mocIncludes.end()); } bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index e60320b..f6caed9 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -7,7 +7,6 @@ #include #include -#include #include #include #include @@ -146,7 +145,7 @@ private: std::string MocInfoIncludes; std::string OutMocCppFilenameRel; std::string OutMocCppFilenameAbs; - std::list MocIncludes; + std::vector MocIncludes; std::vector MocDefinitions; std::vector MocOptions; // - Uic ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 20 16:52:15 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 20 Feb 2017 16:52:15 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-376-g0829afd Message-ID: <20170220215215.79EB3F9C77@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 0829afd56fc3c04fe714cbb28d2f6bcefbe573c9 (commit) via 574f4ddb9f5b18ae67665cc08b6dbb7e4609b86b (commit) via 534c9e9fc0adcbe0cda11bfa869a448511af05c6 (commit) from 8e7033c85264288c840edff511a03643f167e09c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0829afd56fc3c04fe714cbb28d2f6bcefbe573c9 commit 0829afd56fc3c04fe714cbb28d2f6bcefbe573c9 Merge: 8e7033c 574f4dd Author: Brad King AuthorDate: Mon Feb 20 16:52:14 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 20 16:52:14 2017 -0500 Merge topic 'autogen_json' into next 574f4ddb fixup! Autogen: Overhaul moc include list generation 534c9e9f fixup! Autogen: Loop based macro detection instead of code duplication https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=574f4ddb9f5b18ae67665cc08b6dbb7e4609b86b commit 574f4ddb9f5b18ae67665cc08b6dbb7e4609b86b Author: Brad King AuthorDate: Mon Feb 20 16:50:42 2017 -0500 Commit: Brad King CommitDate: Mon Feb 20 16:50:42 2017 -0500 fixup! Autogen: Overhaul moc include list generation diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 1d120d7..4149e55 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=534c9e9fc0adcbe0cda11bfa869a448511af05c6 commit 534c9e9fc0adcbe0cda11bfa869a448511af05c6 Author: Brad King AuthorDate: Mon Feb 20 16:49:02 2017 -0500 Commit: Brad King CommitDate: Mon Feb 20 16:49:02 2017 -0500 fixup! Autogen: Loop based macro detection instead of code duplication diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 236d4c5..c20b83c 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -10,6 +10,7 @@ #include #include #include +#include #include class cmMakefile; ----------------------------------------------------------------------- Summary of changes: Source/cmQtAutoGenerators.cxx | 1 + Source/cmQtAutoGenerators.h | 1 + 2 files changed, 2 insertions(+) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 20 17:13:40 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 20 Feb 2017 17:13:40 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-378-g7d99813 Message-ID: <20170220221340.55221D788E@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 7d99813287edba3d73d85f479347a23996bc0ae6 (commit) via 08fa0b4595566a6e4c29c182865a6ec7e41d9e2e (commit) from 0829afd56fc3c04fe714cbb28d2f6bcefbe573c9 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7d99813287edba3d73d85f479347a23996bc0ae6 commit 7d99813287edba3d73d85f479347a23996bc0ae6 Merge: 0829afd 08fa0b4 Author: Brad King AuthorDate: Mon Feb 20 17:13:39 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 20 17:13:39 2017 -0500 Merge topic 'cuda-separable-bool' into next 08fa0b45 CUDA: Fix boolean interpretation of CUDA_SEPARABLE_COMPILATION https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=08fa0b4595566a6e4c29c182865a6ec7e41d9e2e commit 08fa0b4595566a6e4c29c182865a6ec7e41d9e2e Author: Brad King AuthorDate: Mon Feb 20 17:05:35 2017 -0500 Commit: Brad King CommitDate: Mon Feb 20 17:05:35 2017 -0500 CUDA: Fix boolean interpretation of CUDA_SEPARABLE_COMPILATION If the property is explicitly set to a non-true value we should not treat it as true. diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 866c132..54b3f36 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -590,7 +590,8 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( std::vector compileCommands; if (lang == "CUDA") { std::string cmdVar; - if (this->GeneratorTarget->GetProperty("CUDA_SEPARABLE_COMPILATION")) { + if (this->GeneratorTarget->GetPropertyAsBool( + "CUDA_SEPARABLE_COMPILATION")) { cmdVar = std::string("CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION"); } else { cmdVar = std::string("CMAKE_CUDA_COMPILE_WHOLE_COMPILATION"); diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 0b33b19..f096416 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -580,7 +580,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) std::vector compileCmds; if (lang == "CUDA") { std::string cmdVar; - if (this->GeneratorTarget->GetProperty("CUDA_SEPARABLE_COMPILATION")) { + if (this->GeneratorTarget->GetPropertyAsBool( + "CUDA_SEPARABLE_COMPILATION")) { cmdVar = std::string("CMAKE_CUDA_COMPILE_SEPARABLE_COMPILATION"); } else { cmdVar = std::string("CMAKE_CUDA_COMPILE_WHOLE_COMPILATION"); ----------------------------------------------------------------------- Summary of changes: Source/cmMakefileTargetGenerator.cxx | 3 ++- Source/cmNinjaTargetGenerator.cxx | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) hooks/post-receive -- CMake From kwrobot at kitware.com Tue Feb 21 00:01:06 2017 From: kwrobot at kitware.com (Kitware Robot) Date: Tue, 21 Feb 2017 00:01:06 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-166-g8209b32 Message-ID: <20170221050106.60897F9F84@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 8209b3238f07f5f4e8bd52d9e7f9b7c8af6ac7ba (commit) from 3c0de6db2d9e0580f23cc95c4a1e00a8f66108c9 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8209b3238f07f5f4e8bd52d9e7f9b7c8af6ac7ba commit 8209b3238f07f5f4e8bd52d9e7f9b7c8af6ac7ba Author: Kitware Robot AuthorDate: Tue Feb 21 00:01:03 2017 -0500 Commit: Kitware Robot CommitDate: Tue Feb 21 00:01:03 2017 -0500 CMake Nightly Date Stamp diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 5dda9d0..5e71120 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 8) -set(CMake_VERSION_PATCH 20170220) +set(CMake_VERSION_PATCH 20170221) #set(CMake_VERSION_RC 1) ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 21 10:12:17 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 21 Feb 2017 10:12:17 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-380-g061f28d Message-ID: <20170221151217.70D19E0773@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 061f28d1f29a84f6d5b479e504bad89f63d565f7 (commit) via 8a3114147f430b09ccb788de5f60279afb2bfc26 (commit) from 7d99813287edba3d73d85f479347a23996bc0ae6 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=061f28d1f29a84f6d5b479e504bad89f63d565f7 commit 061f28d1f29a84f6d5b479e504bad89f63d565f7 Merge: 7d99813 8a31141 Author: Brad King AuthorDate: Tue Feb 21 10:12:16 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 21 10:12:16 2017 -0500 Merge topic 'autogen_json' into next 8a311414 Autogen: Don't use .moc include in Q_PLUGIN_METADATA test https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8a3114147f430b09ccb788de5f60279afb2bfc26 commit 8a3114147f430b09ccb788de5f60279afb2bfc26 Author: Sebastian Holtermann AuthorDate: Tue Feb 21 11:27:02 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:11:22 2017 -0500 Autogen: Don't use .moc include in Q_PLUGIN_METADATA test diff --git a/Tests/QtAutogen/mocPlugin/StyleD.cpp b/Tests/QtAutogen/mocPlugin/StyleD.cpp index 48398bb..7e4b121 100644 --- a/Tests/QtAutogen/mocPlugin/StyleD.cpp +++ b/Tests/QtAutogen/mocPlugin/StyleD.cpp @@ -1,17 +1,6 @@ #include "StyleD.hpp" -class StyleD : public QStylePlugin -{ - Q_OBJECT - // Json file in global sub director - Q_PLUGIN_METADATA(IID "org.styles.D" FILE "sub/StyleD.json") -public: - QStyle* create(const QString& key); -}; - QStyle* StyleD::create(const QString& key) { return 0; } - -#include "StyleD.moc" diff --git a/Tests/QtAutogen/mocPlugin/StyleD.hpp b/Tests/QtAutogen/mocPlugin/StyleD.hpp index 2afe055..e58444d 100644 --- a/Tests/QtAutogen/mocPlugin/StyleD.hpp +++ b/Tests/QtAutogen/mocPlugin/StyleD.hpp @@ -3,6 +3,13 @@ #include -class StyleD; +class StyleD : public QStylePlugin +{ + Q_OBJECT + // Json file in global sub director + Q_PLUGIN_METADATA(IID "org.styles.D" FILE "sub/StyleD.json") +public: + QStyle* create(const QString& key); +}; #endif ----------------------------------------------------------------------- Summary of changes: Tests/QtAutogen/mocPlugin/StyleD.cpp | 11 ----------- Tests/QtAutogen/mocPlugin/StyleD.hpp | 9 ++++++++- 2 files changed, 8 insertions(+), 12 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 21 10:13:52 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 21 Feb 2017 10:13:52 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-409-g1376688 Message-ID: <20170221151352.EB8A2E7038@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 1376688a01bfcf28d31d6a9a79703502d5027ca9 (commit) via 401700852e368569ea4f641ccceafbda9306b744 (commit) via 52708851a885d32f0b523cb20fc30a482956edeb (commit) via d056533bb56b6cd46bd9aab72463239e035a52cf (commit) via bdab9b52b752085cc6f48d089f13760ec246fe29 (commit) via 7b950873b245a70509c792aacaee5b2b56d05767 (commit) via 1f7f92b83efbaf8685b5db71c073f6e3779893f4 (commit) via 8dad7d6a668c14cf0395872b22ee533961d3facf (commit) via 4f4cdccdd4c59a7af1e87e88b783bcbf42923fc8 (commit) via c7c1ac85de53a1fce5c0b1bdded27598109cc4be (commit) via 50805693ba987fbf86bb5e8263d7b427cd4da0c2 (commit) via c23206b6c17a5c70580355904fc12fd64c26ef79 (commit) via 347572cf5ea2c653cba6150b5e6d6fa083a68cb0 (commit) via 03df033bfa551e83c2a265cc22f6f5278c80528b (commit) via 3ec230de1f45f48a8bbb8eca49674f0e0c99dfa1 (commit) via 41fb64e719817ce877565e6e11198df2f7e7e63d (commit) via 175c89004425cdbb151d4e85876e2a2076432f28 (commit) via 80a007534f6287cd2e88c1b8fd72b68fc688da4e (commit) via f379fdbb9ee17b62ac8b4a8d4b9fab562ba37253 (commit) via ddf940725e8af095b1c02606aeea64cc9baaf572 (commit) via 71c5ae253cb5498da319e36bcf49869509b6603c (commit) via 5308f954c9ad13cfc6cc84f1f1255fb5faff48c6 (commit) via 887e40034161589b63fdb14bfaee7f66374b9b83 (commit) via 4c60099fea2b06229900cc16fed907185c4fe2ef (commit) via 815a05cf12499b42acea70b5a9534e10e1701417 (commit) via 3270091210c0cfdddb133209b232a1d0a1fa48da (commit) via 793c9a7925dfa3aaa2b15212f4ba0246d1fbf83c (commit) via 25dbfbc2a937379ca78328dfabdf54043340dbd3 (commit) via 3cc42863a43cd4256efdeb2eda2d235d5533bad9 (commit) from 061f28d1f29a84f6d5b479e504bad89f63d565f7 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1376688a01bfcf28d31d6a9a79703502d5027ca9 commit 1376688a01bfcf28d31d6a9a79703502d5027ca9 Merge: 061f28d 4017008 Author: Brad King AuthorDate: Tue Feb 21 10:13:50 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 21 10:13:50 2017 -0500 Merge topic 'autogen_json' into next 40170085 Autogen: Don't use .moc include in Q_PLUGIN_METADATA test 52708851 Autogen: Documentation update d056533b Autogen: Add release notes for Q_PLUGIN_METADATA support bdab9b52 Autogen: Tests: Set different compression levels in rcc test 7b950873 Autogen: Overhaul and simplify AutogenInfo.cmake file generation 1f7f92b8 Autogen: Optimize GetCompileDefinitionsAndDirectories function 8dad7d6a Autogen: Sort AutogenInfo.cmake.in 4f4cdccd Autogen: Tests: Add Q_PLUGIN_METADATA test c7c1ac85 Autogen: Tests: Add moc include tests 50805693 Autogen: Tests: Clean comments c23206b6 Autogen: Log simplifications 347572cf Autogen: Only touch an unchanged moc_compilation.cpp 03df033b Autogen: Rebuild moc when Q_PLUGIN_METADATA json file changes 3ec230de Autogen: Use GetRealPath in central places only 41fb64e7 Autogen: Search moc includes in include directories 175c8900 Autogen: Sort includes before composing include options ... https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=401700852e368569ea4f641ccceafbda9306b744 commit 401700852e368569ea4f641ccceafbda9306b744 Author: Sebastian Holtermann AuthorDate: Tue Feb 21 11:27:02 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:12:58 2017 -0500 Autogen: Don't use .moc include in Q_PLUGIN_METADATA test diff --git a/Tests/QtAutogen/mocPlugin/StyleD.cpp b/Tests/QtAutogen/mocPlugin/StyleD.cpp index 48398bb..7e4b121 100644 --- a/Tests/QtAutogen/mocPlugin/StyleD.cpp +++ b/Tests/QtAutogen/mocPlugin/StyleD.cpp @@ -1,17 +1,6 @@ #include "StyleD.hpp" -class StyleD : public QStylePlugin -{ - Q_OBJECT - // Json file in global sub director - Q_PLUGIN_METADATA(IID "org.styles.D" FILE "sub/StyleD.json") -public: - QStyle* create(const QString& key); -}; - QStyle* StyleD::create(const QString& key) { return 0; } - -#include "StyleD.moc" diff --git a/Tests/QtAutogen/mocPlugin/StyleD.hpp b/Tests/QtAutogen/mocPlugin/StyleD.hpp index 2afe055..e58444d 100644 --- a/Tests/QtAutogen/mocPlugin/StyleD.hpp +++ b/Tests/QtAutogen/mocPlugin/StyleD.hpp @@ -3,6 +3,13 @@ #include -class StyleD; +class StyleD : public QStylePlugin +{ + Q_OBJECT + // Json file in global sub director + Q_PLUGIN_METADATA(IID "org.styles.D" FILE "sub/StyleD.json") +public: + QStyle* create(const QString& key); +}; #endif https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=52708851a885d32f0b523cb20fc30a482956edeb commit 52708851a885d32f0b523cb20fc30a482956edeb Author: Sebastian Holtermann AuthorDate: Sun Feb 19 20:11:18 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:12:58 2017 -0500 Autogen: Documentation update Closes #15254 diff --git a/Help/manual/cmake-qt.7.rst b/Help/manual/cmake-qt.7.rst index 56d4ca7..e9da396 100644 --- a/Help/manual/cmake-qt.7.rst +++ b/Help/manual/cmake-qt.7.rst @@ -63,20 +63,24 @@ If a ``Q_OBJECT`` or ``Q_GADGET`` macro is found in a header file, ``moc`` will be run on the file. The result will be put into a file named according to ``moc_.cpp``. If the macro is found in a C++ implementation file, the moc output will be put into a file named according to -``.moc``, following the Qt conventions. The ``moc file`` may be -included by the user in the C++ implementation file with a preprocessor -``#include``. If it is not so included, it will be added to a separate file -which is compiled into the target. +``.moc``, following the Qt conventions. The ``.moc`` must +be included by the user in the C++ implementation file with a preprocessor +``#include``. -The ``moc`` command line will consume the :prop_tgt:`COMPILE_DEFINITIONS` and -:prop_tgt:`INCLUDE_DIRECTORIES` target properties from the target it is being -invoked for, and for the appropriate build configuration. - -The generated ``moc_*.cpp`` and ``*.moc`` files are placed in the +Included ``moc_*.cpp`` and ``*.moc`` files will be generated in the ``/_autogen/include`` directory which is automatically added to the target's :prop_tgt:`INCLUDE_DIRECTORIES`. (This differs from CMake 3.7 and below; see their documentation for details.) +Not included ``moc_.cpp`` files will be generated in custom +folders to avoid name collisions and included in a separate +``/_autogen/moc_compilation.cpp`` +file which is compiled into the target. + +The ``moc`` command line will consume the :prop_tgt:`COMPILE_DEFINITIONS` and +:prop_tgt:`INCLUDE_DIRECTORIES` target properties from the target it is being +invoked for, and for the appropriate build configuration. + The :prop_tgt:`AUTOMOC` target property may be pre-set for all following targets by setting the :variable:`CMAKE_AUTOMOC` variable. The :prop_tgt:`AUTOMOC_MOC_OPTIONS` target property may be populated to set diff --git a/Help/prop_tgt/AUTOMOC.rst b/Help/prop_tgt/AUTOMOC.rst index b42643f..4ac9b6e 100644 --- a/Help/prop_tgt/AUTOMOC.rst +++ b/Help/prop_tgt/AUTOMOC.rst @@ -8,31 +8,41 @@ preprocessor automatically, i.e. without having to use the :module:`QT4_WRAP_CPP() ` or QT5_WRAP_CPP() macro. Currently Qt4 and Qt5 are supported. -When this property is set ``ON``, CMake will scan the +When this property is set ``ON``, CMake will scan the header and source files at build time and invoke moc accordingly. -* If an ``#include`` statement like ``#include "moc_foo.cpp"`` is found, - the ``Q_OBJECT`` class declaration is expected in the header, and - ``moc`` is run on the header file. A ``moc_foo.cpp`` file will be - generated from the source's header into the - ``/_autogen/include`` - directory which is automatically added to the target's +* If an ``#include`` statement like ``#include "moc_.cpp"`` is found, + the ``Q_OBJECT`` or ``Q_GADGET`` macros are expected in an otherwise empty + line of the ``.h(xx)`` header file. ``moc`` is run on the header file to + generate ``moc_.cpp`` in the + ``/_autogen/include`` directory + which is automatically added to the target's :prop_tgt:`INCLUDE_DIRECTORIES`. This allows the compiler to find the - included ``moc_foo.cpp`` file regardless of the location the original source. - However, if multiple source files in different directories do this then their - generated moc files would collide. In this case a diagnostic will be issued. - -* If an ``#include`` statement like ``#include "foo.moc"`` is found, - then a ``Q_OBJECT`` is expected in the current source file and ``moc`` - is run on the file itself. Additionally, header files with the same - base name (like ``foo.h``) or ``_p`` appended to the base name (like - ``foo_p.h``) are parsed for ``Q_OBJECT`` macros, and if found, ``moc`` - is also executed on those files. ``AUTOMOC`` checks multiple header - alternative extensions, such as ``hpp``, ``hxx`` etc when searching - for headers. The resulting moc files, which are not included as shown - above in any of the source files are included in a generated - ``moc_compilation.cpp`` file, which is compiled as part of the - target. + included ``moc_.cpp`` file regardless of the location the + original source. + +* If an ``#include`` statement like ``#include ".moc"`` is found, + then ``Q_OBJECT`` or ``Q_GADGET`` macros are expected in the current source + file and ``moc`` is run on the source file itself. + +* Header files that are not included by an ``#include "moc_.cpp"`` + statement are nonetheless scanned for ``Q_OBJECT`` or ``Q_GADGET`` macros. + The resulting ``moc_.cpp`` files are generated in custom + directories and automatically included in the generated + ``/_autogen/moc_compilation.cpp`` file, + which is compiled as part of the target. The custom directories help to + avoid name collisions for moc files with the same ````. + +* Additionally, header files with the same base name as a source file, + (like ``.h``) or ``_p`` appended to the base name (like + ``_p.h``), are parsed for ``Q_OBJECT`` or ``Q_GADGET`` macros, + and if found, ``moc`` is also executed on those files. + +* ``AUTOMOC`` always checks multiple header alternative extensions, + such as ``hpp``, ``hxx``, etc. when searching for headers. + +* ``AUTOMOC`` looks for the ``Q_PLUGIN_METADATA`` macro and reruns the + ``moc`` when the file addressed by the ``FILE`` argument of the macro changes. This property is initialized by the value of the :variable:`CMAKE_AUTOMOC` variable if it is set when a target is created. https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d056533bb56b6cd46bd9aab72463239e035a52cf commit d056533bb56b6cd46bd9aab72463239e035a52cf Author: Sebastian Holtermann AuthorDate: Sun Feb 19 18:35:40 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:12:57 2017 -0500 Autogen: Add release notes for Q_PLUGIN_METADATA support diff --git a/Help/release/dev/Autogen_json.rst b/Help/release/dev/Autogen_json.rst new file mode 100644 index 0000000..73bbdf1 --- /dev/null +++ b/Help/release/dev/Autogen_json.rst @@ -0,0 +1,10 @@ +AutoGen json +------------ + +* When using :prop_tgt:`AUTOMOC`, CMake scans for the presence of the + ``Q_PLUGIN_METADATA`` macro and reruns moc when the file from the + macro's ``FILE`` argument changes. + +* When :prop_tgt:`AUTOMOC` detects an include statement of the form + ``#include "moc_.cpp"`` the respective header file is searched + for in the :prop_tgt:`INCLUDE_DIRECTORIES` of the target as well. https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=bdab9b52b752085cc6f48d089f13760ec246fe29 commit bdab9b52b752085cc6f48d089f13760ec246fe29 Author: Sebastian Holtermann AuthorDate: Sun Feb 19 17:24:30 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:12:57 2017 -0500 Autogen: Tests: Set different compression levels in rcc test diff --git a/Tests/QtAutogen/sameName/CMakeLists.txt b/Tests/QtAutogen/sameName/CMakeLists.txt index 9e47a3e..4d2dcd9 100644 --- a/Tests/QtAutogen/sameName/CMakeLists.txt +++ b/Tests/QtAutogen/sameName/CMakeLists.txt @@ -18,3 +18,14 @@ add_executable(sameName ) target_link_libraries(sameName ${QT_LIBRARIES}) set_target_properties(sameName PROPERTIES AUTOMOC TRUE AUTORCC TRUE) + +# Set different compression levels +if (QT_TEST_VERSION STREQUAL 4) + set(rccCompress "-compress") +else() + set(rccCompress "--compress") +endif() +set_target_properties(sameName PROPERTIES AUTORCC_OPTIONS "${rccCompress};0" ) +set_source_files_properties(aaa/data.qrc PROPERTIES AUTORCC_OPTIONS "${rccCompress};1" ) +set_source_files_properties(bbb/data.qrc PROPERTIES AUTORCC_OPTIONS "${rccCompress};2" ) +set_source_files_properties(ccc/data.qrc PROPERTIES AUTORCC_OPTIONS "${rccCompress};3" ) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7b950873b245a70509c792aacaee5b2b56d05767 commit 7b950873b245a70509c792aacaee5b2b56d05767 Author: Sebastian Holtermann AuthorDate: Sun Feb 19 16:46:47 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:12:57 2017 -0500 Autogen: Overhaul and simplify AutogenInfo.cmake file generation diff --git a/Modules/AutogenInfo.cmake.in b/Modules/AutogenInfo.cmake.in index 3135909..b647ecf 100644 --- a/Modules/AutogenInfo.cmake.in +++ b/Modules/AutogenInfo.cmake.in @@ -1,5 +1,5 @@ # Target names -set(AM_TARGET_NAME @_moc_target_name@) +set(AM_TARGET_NAME @_autogen_target_name@) set(AM_ORIGIN_TARGET_NAME @_origin_target_name@) # Directories and files set(AM_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@/") @@ -10,16 +10,16 @@ set(AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE "@CMAKE_INCLUDE_DIRECTORIES_PROJ set(AM_SOURCES @_sources@) set(AM_HEADERS @_headers@) # Qt environment -set(AM_QT_VERSION_MAJOR "@_target_qt_version@") -set(AM_QT_MOC_EXECUTABLE "@_qt_moc_executable@") -set(AM_QT_UIC_EXECUTABLE "@_qt_uic_executable@") -set(AM_QT_RCC_EXECUTABLE "@_qt_rcc_executable@") +set(AM_QT_VERSION_MAJOR @_qt_version_major@) +set(AM_QT_MOC_EXECUTABLE @_qt_moc_executable@) +set(AM_QT_UIC_EXECUTABLE @_qt_uic_executable@) +set(AM_QT_RCC_EXECUTABLE @_qt_rcc_executable@) # MOC settings set(AM_MOC_SKIP @_moc_skip@) set(AM_MOC_COMPILE_DEFINITIONS @_moc_compile_defs@) set(AM_MOC_INCLUDES @_moc_incs@) set(AM_MOC_OPTIONS @_moc_options@) -set(AM_MOC_RELAXED_MODE "@_moc_relaxed_mode@") +set(AM_MOC_RELAXED_MODE @_moc_relaxed_mode@) # UIC settings set(AM_UIC_SKIP @_uic_skip@) set(AM_UIC_TARGET_OPTIONS @_uic_target_options@) diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index c201023..52112ff 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -22,7 +22,6 @@ #endif #include -#include #include #include #include @@ -55,6 +54,13 @@ static std::string utilStripCR(std::string const& line) return line; } +static std::string GetSafeProperty(cmGeneratorTarget const* target, + const char* key) +{ + const char* tmp = target->GetProperty(key); + return std::string((tmp != CM_NULLPTR) ? tmp : ""); +} + static std::string GetAutogenTargetName(cmGeneratorTarget const* target) { std::string autogenTargetName = target->GetName(); @@ -118,19 +124,33 @@ static void GetCompileDefinitionsAndDirectories( } } +static void AddDefinitionEscaped(cmMakefile* makefile, const char* key, + const std::string& value) +{ + makefile->AddDefinition(key, + cmOutputConverter::EscapeForCMake(value).c_str()); +} + +static void AddDefinitionEscaped(cmMakefile* makefile, const char* key, + const std::vector& values) +{ + makefile->AddDefinition( + key, cmOutputConverter::EscapeForCMake(cmJoin(values, ";")).c_str()); +} + static void SetupSourceFiles(cmGeneratorTarget const* target, std::vector& mocUicSources, std::vector& mocUicHeaders, - std::vector& skipMocList, - std::vector& skipUicList) + std::vector& mocSkipList, + std::vector& uicSkipList) { cmMakefile* makefile = target->Target->GetMakefile(); std::vector srcFiles; target->GetConfigCommonSourceFiles(srcFiles); - const bool targetMoc = target->GetPropertyAsBool("AUTOMOC"); - const bool targetUic = target->GetPropertyAsBool("AUTOUIC"); + const bool mocTarget = target->GetPropertyAsBool("AUTOMOC"); + const bool uicTarget = target->GetPropertyAsBool("AUTOUIC"); cmFilePathChecksum fpathCheckSum(makefile); for (std::vector::const_iterator fileIt = srcFiles.begin(); @@ -151,22 +171,22 @@ static void SetupSourceFiles(cmGeneratorTarget const* target, // Skip flags const bool skipAll = cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOGEN")); - const bool skipMoc = + const bool mocSkip = skipAll || cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOMOC")); - const bool skipUic = + const bool uicSkip = skipAll || cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOUIC")); // 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 // processing - if (skipMoc) { - skipMocList.push_back(absFile); + if (mocSkip) { + mocSkipList.push_back(absFile); } - if (skipUic) { - skipUicList.push_back(absFile); + if (uicSkip) { + uicSkipList.push_back(absFile); } - if ((targetMoc && !skipMoc) || (targetUic && !skipUic)) { + if ((mocTarget && !mocSkip) || (uicTarget && !uicSkip)) { // Add file name to sources or headers list switch (fileType) { case cmSystemTools::CXX_FILE_FORMAT: @@ -184,80 +204,85 @@ static void SetupSourceFiles(cmGeneratorTarget const* target, static void MocSetupAutoTarget( cmGeneratorTarget const* target, const std::string& autogenTargetName, - std::vector const& skipMoc, + const std::string& qtMajorVersion, + std::vector const& mocSkipList, std::map& configIncludes, std::map& configDefines) { cmLocalGenerator* lg = target->GetLocalGenerator(); cmMakefile* makefile = target->Target->GetMakefile(); - const char* tmp = target->GetProperty("AUTOMOC_MOC_OPTIONS"); - std::string _moc_options = (tmp != CM_NULLPTR ? tmp : ""); - makefile->AddDefinition( - "_moc_options", cmOutputConverter::EscapeForCMake(_moc_options).c_str()); - makefile->AddDefinition( - "_moc_skip", - cmOutputConverter::EscapeForCMake(cmJoin(skipMoc, ";")).c_str()); - bool relaxedMode = makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE"); - makefile->AddDefinition("_moc_relaxed_mode", relaxedMode ? "TRUE" : "FALSE"); - - std::string _moc_incs; - std::string _moc_compile_defs; - std::vector configs; - const std::string& config = makefile->GetConfigurations(configs); - GetCompileDefinitionsAndDirectories(target, config, _moc_incs, - _moc_compile_defs); + AddDefinitionEscaped(makefile, "_moc_options", + GetSafeProperty(target, "AUTOMOC_MOC_OPTIONS")); + AddDefinitionEscaped(makefile, "_moc_skip", mocSkipList); + AddDefinitionEscaped(makefile, "_moc_relaxed_mode", + makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE") ? "TRUE" + : "FALSE"); - makefile->AddDefinition( - "_moc_incs", cmOutputConverter::EscapeForCMake(_moc_incs).c_str()); - makefile->AddDefinition( - "_moc_compile_defs", - cmOutputConverter::EscapeForCMake(_moc_compile_defs).c_str()); - - for (std::vector::const_iterator li = configs.begin(); - li != configs.end(); ++li) { - std::string config_moc_incs; - std::string config_moc_compile_defs; - GetCompileDefinitionsAndDirectories(target, *li, config_moc_incs, - config_moc_compile_defs); - if (config_moc_incs != _moc_incs) { - configIncludes[*li] = cmOutputConverter::EscapeForCMake(config_moc_incs); - if (_moc_incs.empty()) { - _moc_incs = config_moc_incs; + // Moc includes and compile definitions + { + std::string _moc_incs; + std::string _moc_compile_defs; + std::vector configs; + { + const std::string& config = makefile->GetConfigurations(configs); + GetCompileDefinitionsAndDirectories(target, config, _moc_incs, + _moc_compile_defs); + AddDefinitionEscaped(makefile, "_moc_incs", _moc_incs); + AddDefinitionEscaped(makefile, "_moc_compile_defs", _moc_compile_defs); + } + for (std::vector::const_iterator li = configs.begin(); + li != configs.end(); ++li) { + std::string config_moc_incs; + std::string config_moc_compile_defs; + GetCompileDefinitionsAndDirectories(target, *li, config_moc_incs, + config_moc_compile_defs); + if (config_moc_incs != _moc_incs) { + configIncludes[*li] = + cmOutputConverter::EscapeForCMake(config_moc_incs); + if (_moc_incs.empty()) { + _moc_incs = config_moc_incs; + } } - } - if (config_moc_compile_defs != _moc_compile_defs) { - configDefines[*li] = - cmOutputConverter::EscapeForCMake(config_moc_compile_defs); - if (_moc_compile_defs.empty()) { - _moc_compile_defs = config_moc_compile_defs; + if (config_moc_compile_defs != _moc_compile_defs) { + configDefines[*li] = + cmOutputConverter::EscapeForCMake(config_moc_compile_defs); + if (_moc_compile_defs.empty()) { + _moc_compile_defs = config_moc_compile_defs; + } } } } - const char* qtVersion = makefile->GetDefinition("_target_qt_version"); - if (strcmp(qtVersion, "5") == 0) { - cmGeneratorTarget* qt5Moc = lg->FindGeneratorTargetToUse("Qt5::moc"); - if (!qt5Moc) { - cmSystemTools::Error("Qt5::moc target not found ", - autogenTargetName.c_str()); - return; + // Moc executable + { + std::string err; + const char* mocExec = CM_NULLPTR; + if (qtMajorVersion == "5") { + cmGeneratorTarget* qt5Moc = lg->FindGeneratorTargetToUse("Qt5::moc"); + if (qt5Moc != CM_NULLPTR) { + mocExec = qt5Moc->ImportedGetLocation(""); + } else { + err = "Qt5::moc target not found " + autogenTargetName; + } + } else if (qtMajorVersion == "4") { + cmGeneratorTarget* qt4Moc = lg->FindGeneratorTargetToUse("Qt4::moc"); + if (qt4Moc != CM_NULLPTR) { + mocExec = qt4Moc->ImportedGetLocation(""); + } else { + err = "Qt4::moc target not found " + autogenTargetName; + } + } else { + err = "The CMAKE_AUTOMOC feature supports only Qt 4 and Qt 5 "; + err += autogenTargetName; } - makefile->AddDefinition("_qt_moc_executable", - qt5Moc->ImportedGetLocation("")); - } else if (strcmp(qtVersion, "4") == 0) { - cmGeneratorTarget* qt4Moc = lg->FindGeneratorTargetToUse("Qt4::moc"); - if (!qt4Moc) { - cmSystemTools::Error("Qt4::moc target not found ", - autogenTargetName.c_str()); - return; + // Add definition or error + if (err.empty()) { + AddDefinitionEscaped(makefile, "_qt_moc_executable", + mocExec ? mocExec : ""); + } else { + cmSystemTools::Error(err.c_str()); } - makefile->AddDefinition("_qt_moc_executable", - qt4Moc->ImportedGetLocation("")); - } else { - cmSystemTools::Error("The CMAKE_AUTOMOC feature supports only Qt 4 and " - "Qt 5 ", - autogenTargetName.c_str()); } } @@ -270,126 +295,126 @@ static void UicGetOpts(cmGeneratorTarget const* target, } static void UicSetupAutoTarget( - cmGeneratorTarget const* target, std::vector const& skipUic, + cmGeneratorTarget const* target, const std::string& qtMajorVersion, + std::vector const& uicSkipList, std::map& configUicOptions) { cmLocalGenerator* lg = target->GetLocalGenerator(); cmMakefile* makefile = target->Target->GetMakefile(); - std::set skipped; - skipped.insert(skipUic.begin(), skipUic.end()); + AddDefinitionEscaped(makefile, "_uic_skip", uicSkipList); - makefile->AddDefinition( - "_uic_skip", - cmOutputConverter::EscapeForCMake(cmJoin(skipUic, ";")).c_str()); - - std::vector uiFilesWithOptions = - makefile->GetQtUiFilesWithOptions(); - - const char* qtVersion = makefile->GetDefinition("_target_qt_version"); - - std::string _uic_opts; - std::vector configs; - const std::string& config = makefile->GetConfigurations(configs); - UicGetOpts(target, config, _uic_opts); - - if (!_uic_opts.empty()) { - _uic_opts = cmOutputConverter::EscapeForCMake(_uic_opts); - makefile->AddDefinition("_uic_target_options", _uic_opts.c_str()); - } - for (std::vector::const_iterator li = configs.begin(); - li != configs.end(); ++li) { - std::string config_uic_opts; - UicGetOpts(target, *li, config_uic_opts); - if (config_uic_opts != _uic_opts) { - configUicOptions[*li] = - cmOutputConverter::EscapeForCMake(config_uic_opts); - if (_uic_opts.empty()) { - _uic_opts = config_uic_opts; + // Uic target options + { + std::string _uic_opts; + std::vector configs; + UicGetOpts(target, makefile->GetConfigurations(configs), _uic_opts); + + AddDefinitionEscaped(makefile, "_uic_target_options", _uic_opts); + + for (std::vector::const_iterator li = configs.begin(); + li != configs.end(); ++li) { + std::string config_uic_opts; + UicGetOpts(target, *li, config_uic_opts); + if (config_uic_opts != _uic_opts) { + configUicOptions[*li] = + cmOutputConverter::EscapeForCMake(config_uic_opts); + if (_uic_opts.empty()) { + _uic_opts = config_uic_opts; + } } } } - - std::string uiFileFiles; - std::string uiFileOptions; - const char* sep = ""; - - for (std::vector::const_iterator fileIt = - uiFilesWithOptions.begin(); - fileIt != uiFilesWithOptions.end(); ++fileIt) { - cmSourceFile* sf = *fileIt; - std::string absFile = cmsys::SystemTools::GetRealPath(sf->GetFullPath()); - - if (!skipped.insert(absFile).second) { - continue; + // Uic files options + { + std::vector uiFileFiles; + std::vector uiFileOptions; + { + std::set skipped; + skipped.insert(uicSkipList.begin(), uicSkipList.end()); + + const std::vector uiFilesWithOptions = + makefile->GetQtUiFilesWithOptions(); + for (std::vector::const_iterator fileIt = + uiFilesWithOptions.begin(); + fileIt != uiFilesWithOptions.end(); ++fileIt) { + cmSourceFile* sf = *fileIt; + const std::string absFile = + cmsys::SystemTools::GetRealPath(sf->GetFullPath()); + if (skipped.insert(absFile).second) { + // The file wasn't skipped + uiFileFiles.push_back(absFile); + { + std::string opts = sf->GetProperty("AUTOUIC_OPTIONS"); + cmSystemTools::ReplaceString(opts, ";", "@list_sep@"); + uiFileOptions.push_back(opts); + } + } + } } - uiFileFiles += sep; - uiFileFiles += absFile; - uiFileOptions += sep; - std::string opts = sf->GetProperty("AUTOUIC_OPTIONS"); - cmSystemTools::ReplaceString(opts, ";", "@list_sep@"); - uiFileOptions += opts; - sep = ";"; + AddDefinitionEscaped(makefile, "_qt_uic_options_files", uiFileFiles); + AddDefinitionEscaped(makefile, "_qt_uic_options_options", uiFileOptions); } - makefile->AddDefinition( - "_qt_uic_options_files", - cmOutputConverter::EscapeForCMake(uiFileFiles).c_str()); - makefile->AddDefinition( - "_qt_uic_options_options", - cmOutputConverter::EscapeForCMake(uiFileOptions).c_str()); - - std::string targetName = target->GetName(); - if (strcmp(qtVersion, "5") == 0) { - cmGeneratorTarget* qt5Uic = lg->FindGeneratorTargetToUse("Qt5::uic"); - if (!qt5Uic) { - // Project does not use Qt5Widgets, but has AUTOUIC ON anyway + // Uic executable + { + std::string err; + const char* uicExec = CM_NULLPTR; + if (qtMajorVersion == "5") { + cmGeneratorTarget* qt5Uic = lg->FindGeneratorTargetToUse("Qt5::uic"); + if (qt5Uic != CM_NULLPTR) { + uicExec = qt5Uic->ImportedGetLocation(""); + } else { + // Project does not use Qt5Widgets, but has AUTOUIC ON anyway + } + } else if (qtMajorVersion == "4") { + cmGeneratorTarget* qt4Uic = lg->FindGeneratorTargetToUse("Qt4::uic"); + if (qt4Uic != CM_NULLPTR) { + uicExec = qt4Uic->ImportedGetLocation(""); + } else { + err = "Qt4::uic target not found " + target->GetName(); + } } else { - makefile->AddDefinition("_qt_uic_executable", - qt5Uic->ImportedGetLocation("")); + err = "The CMAKE_AUTOUIC feature supports only Qt 4 and Qt 5 "; + err += target->GetName(); } - } else if (strcmp(qtVersion, "4") == 0) { - cmGeneratorTarget* qt4Uic = lg->FindGeneratorTargetToUse("Qt4::uic"); - if (!qt4Uic) { - cmSystemTools::Error("Qt4::uic target not found ", targetName.c_str()); - return; + // Add definition or error + if (err.empty()) { + AddDefinitionEscaped(makefile, "_qt_uic_executable", + uicExec ? uicExec : ""); + } else { + cmSystemTools::Error(err.c_str()); } - makefile->AddDefinition("_qt_uic_executable", - qt4Uic->ImportedGetLocation("")); - } else { - cmSystemTools::Error("The CMAKE_AUTOUIC feature supports only Qt 4 and " - "Qt 5 ", - targetName.c_str()); } } static std::string RccGetExecutable(cmGeneratorTarget const* target, const std::string& qtMajorVersion) { + std::string rccExec; cmLocalGenerator* lg = target->GetLocalGenerator(); - - std::string const& targetName = target->GetName(); if (qtMajorVersion == "5") { cmGeneratorTarget* qt5Rcc = lg->FindGeneratorTargetToUse("Qt5::rcc"); - if (!qt5Rcc) { - cmSystemTools::Error("Qt5::rcc target not found ", targetName.c_str()); - return std::string(); + if (qt5Rcc != CM_NULLPTR) { + rccExec = qt5Rcc->ImportedGetLocation(""); + } else { + cmSystemTools::Error("Qt5::rcc target not found ", + target->GetName().c_str()); } - return qt5Rcc->ImportedGetLocation(""); - } - if (qtMajorVersion == "4") { + } else if (qtMajorVersion == "4") { cmGeneratorTarget* qt4Rcc = lg->FindGeneratorTargetToUse("Qt4::rcc"); - if (!qt4Rcc) { - cmSystemTools::Error("Qt4::rcc target not found ", targetName.c_str()); - return std::string(); + if (qt4Rcc != CM_NULLPTR) { + rccExec = qt4Rcc->ImportedGetLocation(""); + } else { + cmSystemTools::Error("Qt4::rcc target not found ", + target->GetName().c_str()); } - return qt4Rcc->ImportedGetLocation(""); + } else { + cmSystemTools::Error( + "The CMAKE_AUTORCC feature supports only Qt 4 and Qt 5 ", + target->GetName().c_str()); } - - cmSystemTools::Error("The CMAKE_AUTORCC feature supports only Qt 4 and " - "Qt 5 ", - targetName.c_str()); - return std::string(); + return rccExec; } static void RccMergeOptions(std::vector& opts, @@ -399,26 +424,31 @@ static void RccMergeOptions(std::vector& opts, static const char* valueOptions[] = { "name", "root", "compress", "threshold" }; std::vector extraOpts; - for (std::vector::const_iterator it = fileOpts.begin(); - it != fileOpts.end(); ++it) { + for (std::vector::const_iterator fit = fileOpts.begin(); + fit != fileOpts.end(); ++fit) { std::vector::iterator existingIt = - std::find(opts.begin(), opts.end(), *it); + std::find(opts.begin(), opts.end(), *fit); if (existingIt != opts.end()) { - const char* o = it->c_str(); - if (*o == '-') { - ++o; - } - if (isQt5 && *o == '-') { - ++o; + const char* optName = fit->c_str(); + if (*optName == '-') { + ++optName; + if (isQt5 && *optName == '-') { + ++optName; + } } - if (std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions), - cmStrCmp(*it)) != cmArrayEnd(valueOptions)) { - assert(existingIt + 1 != opts.end()); - *(existingIt + 1) = *(it + 1); - ++it; + // Test if this is a value option and change the existing value + if ((optName != fit->c_str()) && + std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions), + cmStrCmp(optName)) != cmArrayEnd(valueOptions)) { + const std::vector::iterator existValueIt(existingIt + 1); + const std::vector::const_iterator fileValueIt(fit + 1); + if ((existValueIt != opts.end()) && (fileValueIt != fileOpts.end())) { + *existValueIt = *fileValueIt; + ++fit; + } } } else { - extraOpts.push_back(*it); + extraOpts.push_back(*fit); } } opts.insert(opts.end(), extraOpts.begin(), extraOpts.end()); @@ -528,23 +558,20 @@ static bool RccListInputsQt4(cmSourceFile* sf, } cmsys::RegularExpression fileMatchRegex("(]*>)"); size_t offset = 0; while (fileMatchRegex.find(qrcContents.c_str() + offset)) { std::string qrcEntry = fileMatchRegex.match(1); - offset += qrcEntry.size(); - - cmsys::RegularExpression fileReplaceRegex("(^]*>)"); - fileReplaceRegex.find(qrcEntry); - std::string tag = fileReplaceRegex.match(1); - - qrcEntry = qrcEntry.substr(tag.size()); - + { + fileReplaceRegex.find(qrcEntry); + std::string tag = fileReplaceRegex.match(1); + qrcEntry = qrcEntry.substr(tag.size()); + } if (!cmSystemTools::FileIsFullPath(qrcEntry.c_str())) { qrcEntry = sf->GetLocation().GetDirectory() + "/" + qrcEntry; } - depends.push_back(qrcEntry); } return true; @@ -565,89 +592,69 @@ static bool RccListInputs(const std::string& qtMajorVersion, cmSourceFile* sf, static void RccSetupAutoTarget(cmGeneratorTarget const* target, const std::string& qtMajorVersion) { - std::string _rcc_files; - const char* sepRccFiles = ""; cmMakefile* makefile = target->Target->GetMakefile(); - - std::vector srcFiles; - target->GetConfigCommonSourceFiles(srcFiles); - - std::string qrcInputs; - const char* qrcInputsSep = ""; - - std::string rccFileFiles; - std::string rccFileOptions; - const char* optionSep = ""; - const bool qtMajorVersion5 = (qtMajorVersion == "5"); - - std::vector rccOptions; + std::vector _rcc_files; + std::vector _rcc_inputs; + std::vector rccFileFiles; + std::vector rccFileOptions; + std::vector rccOptionsTarget; if (const char* opts = target->GetProperty("AUTORCC_OPTIONS")) { - cmSystemTools::ExpandListArgument(opts, rccOptions); + cmSystemTools::ExpandListArgument(opts, rccOptionsTarget); } + std::vector srcFiles; + target->GetConfigCommonSourceFiles(srcFiles); for (std::vector::const_iterator fileIt = srcFiles.begin(); fileIt != srcFiles.end(); ++fileIt) { cmSourceFile* sf = *fileIt; - std::string ext = sf->GetExtension(); - if (ext == "qrc") { - std::string absFile = cmsys::SystemTools::GetRealPath(sf->GetFullPath()); + if (sf->GetExtension() == "qrc") { const bool skip = cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOGEN")) || cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC")); - if (!skip) { - _rcc_files += sepRccFiles; - _rcc_files += absFile; - sepRccFiles = ";"; - - if (const char* prop = sf->GetProperty("AUTORCC_OPTIONS")) { - std::vector optsVec; - cmSystemTools::ExpandListArgument(prop, optsVec); - RccMergeOptions(rccOptions, optsVec, qtMajorVersion5); - } - - if (!rccOptions.empty()) { - rccFileFiles += optionSep; - rccFileFiles += absFile; - rccFileOptions += optionSep; - } - const char* listSep = ""; - for (std::vector::const_iterator it = rccOptions.begin(); - it != rccOptions.end(); ++it) { - rccFileOptions += listSep; - rccFileOptions += *it; - listSep = "@list_sep@"; + const std::string absFile = + cmsys::SystemTools::GetRealPath(sf->GetFullPath()); + // qrc file + _rcc_files.push_back(absFile); + // qrc file entries + { + std::string entriesList; + if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) { + std::vector depends; + if (RccListInputs(qtMajorVersion, sf, target, depends)) { + entriesList = cmJoin(depends, "@list_sep@"); + } else { + return; + } + } + _rcc_inputs.push_back(entriesList); } - optionSep = ";"; - - std::string entriesList; - if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) { - std::vector depends; - if (RccListInputs(qtMajorVersion, sf, target, depends)) { - entriesList = cmJoin(depends, "@list_sep@"); - } else { - return; + // rcc options for this qrc file + { + // Merged target and file options + std::vector rccOptions(rccOptionsTarget); + if (const char* prop = sf->GetProperty("AUTORCC_OPTIONS")) { + std::vector optsVec; + cmSystemTools::ExpandListArgument(prop, optsVec); + RccMergeOptions(rccOptions, optsVec, qtMajorVersion5); + } + // Only store non empty options lists + if (!rccOptions.empty()) { + rccFileFiles.push_back(absFile); + rccFileOptions.push_back(cmJoin(rccOptions, "@list_sep@")); } } - qrcInputs += qrcInputsSep; - qrcInputs += entriesList; - qrcInputsSep = ";"; } } } - makefile->AddDefinition( - "_rcc_inputs", cmOutputConverter::EscapeForCMake(qrcInputs).c_str()); - makefile->AddDefinition( - "_rcc_files", cmOutputConverter::EscapeForCMake(_rcc_files).c_str()); - makefile->AddDefinition( - "_rcc_options_files", - cmOutputConverter::EscapeForCMake(rccFileFiles).c_str()); - makefile->AddDefinition( - "_rcc_options_options", - cmOutputConverter::EscapeForCMake(rccFileOptions).c_str()); - makefile->AddDefinition("_qt_rcc_executable", - RccGetExecutable(target, qtMajorVersion).c_str()); + + AddDefinitionEscaped(makefile, "_rcc_files", _rcc_files); + AddDefinitionEscaped(makefile, "_rcc_inputs", _rcc_inputs); + AddDefinitionEscaped(makefile, "_rcc_options_files", rccFileFiles); + AddDefinitionEscaped(makefile, "_rcc_options_options", rccFileOptions); + AddDefinitionEscaped(makefile, "_qt_rcc_executable", + RccGetExecutable(target, qtMajorVersion)); } void cmQtAutoGeneratorInitializer::InitializeAutogenSources( @@ -874,47 +881,42 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( cmMakefile::ScopePushPop varScope(makefile); static_cast(varScope); - // create a custom target for running generators at buildtime: - const std::string autogenTargetName = GetAutogenTargetName(target); - const std::string qtMajorVersion = GetQtMajorVersion(target); - - makefile->AddDefinition( - "_moc_target_name", - cmOutputConverter::EscapeForCMake(autogenTargetName).c_str()); - makefile->AddDefinition( - "_origin_target_name", - cmOutputConverter::EscapeForCMake(target->GetName()).c_str()); - makefile->AddDefinition("_target_qt_version", qtMajorVersion.c_str()); - - std::vector mocUicSources; - std::vector mocUicHeaders; - std::vector skipMoc; - std::vector skipUic; std::map configMocIncludes; std::map configMocDefines; std::map configUicOptions; + { + // create a custom target for running generators at buildtime: + const std::string autogenTargetName = GetAutogenTargetName(target); + const std::string qtMajorVersion = GetQtMajorVersion(target); - if (target->GetPropertyAsBool("AUTOMOC") || - target->GetPropertyAsBool("AUTOUIC") || - target->GetPropertyAsBool("AUTORCC")) { - SetupSourceFiles(target, mocUicSources, mocUicHeaders, skipMoc, skipUic); - } - makefile->AddDefinition( - "_sources", - cmOutputConverter::EscapeForCMake(cmJoin(mocUicSources, ";")).c_str()); - makefile->AddDefinition( - "_headers", - cmOutputConverter::EscapeForCMake(cmJoin(mocUicHeaders, ";")).c_str()); + AddDefinitionEscaped(makefile, "_autogen_target_name", autogenTargetName); + AddDefinitionEscaped(makefile, "_origin_target_name", target->GetName()); + AddDefinitionEscaped(makefile, "_qt_version_major", qtMajorVersion); - if (target->GetPropertyAsBool("AUTOMOC")) { - MocSetupAutoTarget(target, autogenTargetName, skipMoc, configMocIncludes, - configMocDefines); - } - if (target->GetPropertyAsBool("AUTOUIC")) { - UicSetupAutoTarget(target, skipUic, configUicOptions); - } - if (target->GetPropertyAsBool("AUTORCC")) { - RccSetupAutoTarget(target, qtMajorVersion); + std::vector _sources; + std::vector _headers; + std::vector mocSkipList; + std::vector uicSkipList; + + if (target->GetPropertyAsBool("AUTOMOC") || + target->GetPropertyAsBool("AUTOUIC") || + target->GetPropertyAsBool("AUTORCC")) { + SetupSourceFiles(target, _sources, _headers, mocSkipList, uicSkipList); + } + AddDefinitionEscaped(makefile, "_sources", _sources); + AddDefinitionEscaped(makefile, "_headers", _headers); + + if (target->GetPropertyAsBool("AUTOMOC")) { + MocSetupAutoTarget(target, autogenTargetName, qtMajorVersion, + mocSkipList, configMocIncludes, configMocDefines); + } + if (target->GetPropertyAsBool("AUTOUIC")) { + UicSetupAutoTarget(target, qtMajorVersion, uicSkipList, + configUicOptions); + } + if (target->GetPropertyAsBool("AUTORCC")) { + RccSetupAutoTarget(target, qtMajorVersion); + } } // Generate config file @@ -926,7 +928,7 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( makefile->ConfigureFile(inputFile.c_str(), outputFile.c_str(), false, true, false); - // Append custom definitions to config file + // Append custom config definitions to info file if (!configMocDefines.empty() || !configMocIncludes.empty() || !configUicOptions.empty()) { @@ -948,33 +950,34 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( error += outputFile; error += " for writing."; cmSystemTools::Error(error.c_str()); - return; - } - if (!configMocDefines.empty()) { - for (std::map::iterator - it = configMocDefines.begin(), - end = configMocDefines.end(); - it != end; ++it) { - infoFile << "set(AM_MOC_COMPILE_DEFINITIONS_" << it->first << " " - << it->second << ")\n"; + } else { + infoFile << "# Configuration specific options\n"; + if (!configMocDefines.empty()) { + for (std::map::iterator + it = configMocDefines.begin(), + end = configMocDefines.end(); + it != end; ++it) { + infoFile << "set(AM_MOC_COMPILE_DEFINITIONS_" << it->first << " " + << it->second << ")\n"; + } } - } - if (!configMocIncludes.empty()) { - for (std::map::iterator - it = configMocIncludes.begin(), - end = configMocIncludes.end(); - it != end; ++it) { - infoFile << "set(AM_MOC_INCLUDES_" << it->first << " " << it->second - << ")\n"; + if (!configMocIncludes.empty()) { + for (std::map::iterator + it = configMocIncludes.begin(), + end = configMocIncludes.end(); + it != end; ++it) { + infoFile << "set(AM_MOC_INCLUDES_" << it->first << " " << it->second + << ")\n"; + } } - } - if (!configUicOptions.empty()) { - for (std::map::iterator - it = configUicOptions.begin(), - end = configUicOptions.end(); - it != end; ++it) { - infoFile << "set(AM_UIC_TARGET_OPTIONS_" << it->first << " " - << it->second << ")\n"; + if (!configUicOptions.empty()) { + for (std::map::iterator + it = configUicOptions.begin(), + end = configUicOptions.end(); + it != end; ++it) { + infoFile << "set(AM_UIC_TARGET_OPTIONS_" << it->first << " " + << it->second << ")\n"; + } } } } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1f7f92b83efbaf8685b5db71c073f6e3779893f4 commit 1f7f92b83efbaf8685b5db71c073f6e3779893f4 Author: Sebastian Holtermann AuthorDate: Sun Feb 19 13:17:42 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:12:57 2017 -0500 Autogen: Optimize GetCompileDefinitionsAndDirectories function diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index d17faf6..c201023 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -98,6 +98,26 @@ static std::string GetQtMajorVersion(cmGeneratorTarget const* target) return qtMajorVersion; } +static void GetCompileDefinitionsAndDirectories( + cmGeneratorTarget const* target, const std::string& config, + std::string& incs, std::string& defs) +{ + cmLocalGenerator* localGen = target->GetLocalGenerator(); + { + std::vector includeDirs; + // Get the include dirs for this target, without stripping the implicit + // include dirs off, see + // https://gitlab.kitware.com/cmake/cmake/issues/13667 + localGen->GetIncludeDirectories(includeDirs, target, "CXX", config, false); + incs = cmJoin(includeDirs, ";"); + } + { + std::set defines; + localGen->AddCompileDefinitions(defines, target, config, "CXX"); + defs += cmJoin(defines, ";"); + } +} + static void SetupSourceFiles(cmGeneratorTarget const* target, std::vector& mocUicSources, std::vector& mocUicHeaders, @@ -162,24 +182,6 @@ static void SetupSourceFiles(cmGeneratorTarget const* target, } } -static void GetCompileDefinitionsAndDirectories( - cmGeneratorTarget const* target, const std::string& config, - std::string& incs, std::string& defs) -{ - std::vector includeDirs; - cmLocalGenerator* localGen = target->GetLocalGenerator(); - // Get the include dirs for this target, without stripping the implicit - // include dirs off, see https://gitlab.kitware.com/cmake/cmake/issues/13667 - localGen->GetIncludeDirectories(includeDirs, target, "CXX", config, false); - - incs = cmJoin(includeDirs, ";"); - - std::set defines; - localGen->AddCompileDefinitions(defines, target, config, "CXX"); - - defs += cmJoin(defines, ";"); -} - static void MocSetupAutoTarget( cmGeneratorTarget const* target, const std::string& autogenTargetName, std::vector const& skipMoc, https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8dad7d6a668c14cf0395872b22ee533961d3facf commit 8dad7d6a668c14cf0395872b22ee533961d3facf Author: Sebastian Holtermann AuthorDate: Sun Feb 19 12:57:47 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:12:56 2017 -0500 Autogen: Sort AutogenInfo.cmake.in Also rename AM_SKIP_MOC to AM_MOC_SKIP and AM_SKIP_UIC to AM_UIC_SKIP diff --git a/Modules/AutogenInfo.cmake.in b/Modules/AutogenInfo.cmake.in index 3fafaff..3135909 100644 --- a/Modules/AutogenInfo.cmake.in +++ b/Modules/AutogenInfo.cmake.in @@ -1,25 +1,31 @@ -set(AM_SOURCES @_moc_uic_sources@) -set(AM_HEADERS @_moc_uic_headers@) -set(AM_SKIP_MOC @_skip_moc@) -set(AM_SKIP_UIC @_skip_uic@) -set(AM_MOC_COMPILE_DEFINITIONS @_moc_compile_defs@) -set(AM_MOC_INCLUDES @_moc_incs@) -set(AM_MOC_OPTIONS @_moc_options@) -set(AM_MOC_RELAXED_MODE "@_moc_relaxed_mode@") -set(AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE "@CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE@") +# Target names +set(AM_TARGET_NAME @_moc_target_name@) +set(AM_ORIGIN_TARGET_NAME @_origin_target_name@) +# Directories and files set(AM_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@/") set(AM_CMAKE_SOURCE_DIR "@CMAKE_SOURCE_DIR@/") -set(AM_QT_MOC_EXECUTABLE "@_qt_moc_executable@") -set(AM_QT_UIC_EXECUTABLE "@_qt_uic_executable@") -set(AM_QT_RCC_EXECUTABLE "@_qt_rcc_executable@") set(AM_CMAKE_CURRENT_SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@/") set(AM_CMAKE_CURRENT_BINARY_DIR "@CMAKE_CURRENT_BINARY_DIR@/") +set(AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE "@CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE@") +set(AM_SOURCES @_sources@) +set(AM_HEADERS @_headers@) +# Qt environment set(AM_QT_VERSION_MAJOR "@_target_qt_version@") -set(AM_TARGET_NAME @_moc_target_name@) -set(AM_ORIGIN_TARGET_NAME @_origin_target_name@) +set(AM_QT_MOC_EXECUTABLE "@_qt_moc_executable@") +set(AM_QT_UIC_EXECUTABLE "@_qt_uic_executable@") +set(AM_QT_RCC_EXECUTABLE "@_qt_rcc_executable@") +# MOC settings +set(AM_MOC_SKIP @_moc_skip@) +set(AM_MOC_COMPILE_DEFINITIONS @_moc_compile_defs@) +set(AM_MOC_INCLUDES @_moc_incs@) +set(AM_MOC_OPTIONS @_moc_options@) +set(AM_MOC_RELAXED_MODE "@_moc_relaxed_mode@") +# UIC settings +set(AM_UIC_SKIP @_uic_skip@) set(AM_UIC_TARGET_OPTIONS @_uic_target_options@) set(AM_UIC_OPTIONS_FILES @_qt_uic_options_files@) set(AM_UIC_OPTIONS_OPTIONS @_qt_uic_options_options@) +# RCC settings set(AM_RCC_SOURCES @_rcc_files@ ) set(AM_RCC_INPUTS @_rcc_inputs@) set(AM_RCC_OPTIONS_FILES @_rcc_options_files@) diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index 825eba0..d17faf6 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -194,7 +194,7 @@ static void MocSetupAutoTarget( makefile->AddDefinition( "_moc_options", cmOutputConverter::EscapeForCMake(_moc_options).c_str()); makefile->AddDefinition( - "_skip_moc", + "_moc_skip", cmOutputConverter::EscapeForCMake(cmJoin(skipMoc, ";")).c_str()); bool relaxedMode = makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE"); makefile->AddDefinition("_moc_relaxed_mode", relaxedMode ? "TRUE" : "FALSE"); @@ -278,7 +278,7 @@ static void UicSetupAutoTarget( skipped.insert(skipUic.begin(), skipUic.end()); makefile->AddDefinition( - "_skip_uic", + "_uic_skip", cmOutputConverter::EscapeForCMake(cmJoin(skipUic, ";")).c_str()); std::vector uiFilesWithOptions = @@ -898,10 +898,10 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( SetupSourceFiles(target, mocUicSources, mocUicHeaders, skipMoc, skipUic); } makefile->AddDefinition( - "_moc_uic_sources", + "_sources", cmOutputConverter::EscapeForCMake(cmJoin(mocUicSources, ";")).c_str()); makefile->AddDefinition( - "_moc_uic_headers", + "_headers", cmOutputConverter::EscapeForCMake(cmJoin(mocUicHeaders, ";")).c_str()); if (target->GetPropertyAsBool("AUTOMOC")) { diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index ccdebbb..4149e55 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -307,7 +307,7 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( this->Headers); // - Moc - cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_SKIP_MOC"), + cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_MOC_SKIP"), this->MocSkipList); cmSystemTools::ExpandListArgument( GetConfigDefinition(makefile, "AM_MOC_COMPILE_DEFINITIONS", config), @@ -319,7 +319,7 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( makefile->GetSafeDefinition("AM_MOC_OPTIONS"), this->MocOptions); // - Uic - cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_SKIP_UIC"), + cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_UIC_SKIP"), this->UicSkipList); cmSystemTools::ExpandListArgument( GetConfigDefinition(makefile, "AM_UIC_TARGET_OPTIONS", config), https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4f4cdccdd4c59a7af1e87e88b783bcbf42923fc8 commit 4f4cdccdd4c59a7af1e87e88b783bcbf42923fc8 Author: Sebastian Holtermann AuthorDate: Fri Feb 17 13:50:33 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:12:56 2017 -0500 Autogen: Tests: Add Q_PLUGIN_METADATA test diff --git a/Tests/QtAutogen/CMakeLists.txt b/Tests/QtAutogen/CMakeLists.txt index 40c23fa..260331b 100644 --- a/Tests/QtAutogen/CMakeLists.txt +++ b/Tests/QtAutogen/CMakeLists.txt @@ -86,7 +86,8 @@ try_compile(RCC_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/autorcc_depends" "${CMAKE_CURRENT_SOURCE_DIR}/autorcc_depends" autorcc_depends - CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" "-DQT_TEST_VERSION=${QT_TEST_VERSION}" + CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" + "-DQT_TEST_VERSION=${QT_TEST_VERSION}" "-DCMAKE_PREFIX_PATH=${Qt_PREFIX_DIR}" OUTPUT_VARIABLE output ) @@ -121,7 +122,8 @@ try_compile(MOC_RERUN "${CMAKE_CURRENT_BINARY_DIR}/automoc_rerun" "${CMAKE_CURRENT_SOURCE_DIR}/automoc_rerun" automoc_rerun - CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" "-DQT_TEST_VERSION=${QT_TEST_VERSION}" + CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" + "-DQT_TEST_VERSION=${QT_TEST_VERSION}" "-DCMAKE_PREFIX_PATH=${Qt_PREFIX_DIR}" OUTPUT_VARIABLE output ) @@ -215,5 +217,60 @@ add_subdirectory(mocIncludeStrict) add_subdirectory(mocIncludeRelaxed) # -- 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(mocPluginBinDir "${CMAKE_CURRENT_BINARY_DIR}/mocPlugin") + find_library(style_a_file "PluginStyleA" "${mocPluginBinDir}") + find_library(style_b_file "PluginStyleB" "${mocPluginBinDir}") + find_library(style_c_file "PluginStyleC" "${mocPluginBinDir}") + find_library(style_d_file "PluginStyleD" "${mocPluginBinDir}") + + file(TIMESTAMP "${style_a_file}" style_a_before "${timeformat}") + file(TIMESTAMP "${style_b_file}" style_b_before "${timeformat}") + file(TIMESTAMP "${style_c_file}" style_c_before "${timeformat}") + file(TIMESTAMP "${style_d_file}" style_d_before "${timeformat}") + + # Ensure that the timestamp will change and touch the json files + execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) + execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${mocPluginBinDir}/jsonFiles/StyleC.json") + execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${mocPluginBinDir}/jsonFiles/sub/StyleD.json") + + execute_process(COMMAND "${CMAKE_COMMAND}" --build . + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mocPlugin" + ) + + file(TIMESTAMP "${style_a_file}" style_a_after "${timeformat}") + file(TIMESTAMP "${style_b_file}" style_b_after "${timeformat}") + file(TIMESTAMP "${style_c_file}" style_c_after "${timeformat}") + file(TIMESTAMP "${style_d_file}" style_d_after "${timeformat}") + + if (style_a_after GREATER style_a_before) + message(SEND_ERROR "file (${style_a_file}) should not have changed!") + endif() + if (style_b_after GREATER style_b_before) + message(SEND_ERROR "file (${style_b_file}) should not have changed!") + endif() + if (NOT style_c_after GREATER style_c_before) + message(SEND_ERROR "file (${style_c_file}) should have changed!") + endif() + if (NOT style_d_after GREATER style_d_before) + message(SEND_ERROR "file (${style_d_file}) should have changed!") + endif() +endif() + +# -- Test # Complex test case add_subdirectory(complex) diff --git a/Tests/QtAutogen/mocPlugin/CMakeLists.txt b/Tests/QtAutogen/mocPlugin/CMakeLists.txt new file mode 100644 index 0000000..eed7d39 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 3.8) + +if (NOT QT_TEST_VERSION STREQUAL 5) + message(SEND_ERROR "Invalid Qt version specified.") +endif() +find_package(Qt5Widgets REQUIRED) + +if(Qt5_POSITION_INDEPENDENT_CODE AND CMAKE_CXX_COMPILE_OPTIONS_PIC) + add_definitions(${CMAKE_CXX_COMPILE_OPTIONS_PIC}) +endif() + +configure_file(jsonIn/StyleC.json jsonFiles/StyleC.json @ONLY) +configure_file(jsonIn/StyleD.json jsonFiles/sub/StyleD.json @ONLY) + +# Enable automoc +set(CMAKE_AUTOMOC TRUE) + +include_directories("${CMAKE_CURRENT_BINARY_DIR}/jsonFiles") +link_libraries(Qt5::Widgets) + +add_library(PluginStyleA MODULE StyleA.cpp) +add_library(PluginStyleB MODULE StyleB.cpp) +add_library(PluginStyleC MODULE StyleC.cpp) +add_library(PluginStyleD MODULE StyleD.cpp) +add_library(PluginStyleE MODULE StyleE.cpp) diff --git a/Tests/QtAutogen/mocPlugin/StyleA.cpp b/Tests/QtAutogen/mocPlugin/StyleA.cpp new file mode 100644 index 0000000..b5e8753 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleA.cpp @@ -0,0 +1,6 @@ +#include "StyleA.hpp" + +QStyle* StyleA::create(const QString& key) +{ + return 0; +} diff --git a/Tests/QtAutogen/mocPlugin/StyleA.hpp b/Tests/QtAutogen/mocPlugin/StyleA.hpp new file mode 100644 index 0000000..b105b02 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleA.hpp @@ -0,0 +1,15 @@ +#ifndef STYLEA_HPP +#define STYLEA_HPP + +#include + +class StyleA : public QStylePlugin +{ + Q_OBJECT + // Json file in local directory + Q_PLUGIN_METADATA(IID "org.styles.A" FILE "StyleA.json") +public: + QStyle* create(const QString& key); +}; + +#endif diff --git a/Tests/QtAutogen/mocPlugin/StyleA.json b/Tests/QtAutogen/mocPlugin/StyleA.json new file mode 100644 index 0000000..cc33953 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleA.json @@ -0,0 +1 @@ +{ "Keys": [ "Rocket", "Starbuster" ] } diff --git a/Tests/QtAutogen/mocPlugin/StyleB.cpp b/Tests/QtAutogen/mocPlugin/StyleB.cpp new file mode 100644 index 0000000..17d4400 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleB.cpp @@ -0,0 +1,6 @@ +#include "StyleB.hpp" + +QStyle* StyleB::create(const QString& key) +{ + return 0; +} diff --git a/Tests/QtAutogen/mocPlugin/StyleB.hpp b/Tests/QtAutogen/mocPlugin/StyleB.hpp new file mode 100644 index 0000000..ba89127 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleB.hpp @@ -0,0 +1,15 @@ +#ifndef STYLEB_HPP +#define STYLEB_HPP + +#include + +class StyleB : public QStylePlugin +{ + Q_OBJECT + // Json file in local subdirectory + Q_PLUGIN_METADATA(IID "org.styles.B" FILE "jsonIn/StyleB.json") +public: + QStyle* create(const QString& key); +}; + +#endif diff --git a/Tests/QtAutogen/mocPlugin/StyleC.cpp b/Tests/QtAutogen/mocPlugin/StyleC.cpp new file mode 100644 index 0000000..37e7564 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleC.cpp @@ -0,0 +1,6 @@ +#include "StyleC.hpp" + +QStyle* StyleC::create(const QString& key) +{ + return 0; +} diff --git a/Tests/QtAutogen/mocPlugin/StyleC.hpp b/Tests/QtAutogen/mocPlugin/StyleC.hpp new file mode 100644 index 0000000..9f71d75 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleC.hpp @@ -0,0 +1,15 @@ +#ifndef STYLEC_HPP +#define STYLEC_HPP + +#include + +class StyleC : public QStylePlugin +{ + Q_OBJECT + // Json file in global root directory + Q_PLUGIN_METADATA(IID "org.styles.C" FILE "StyleC.json") +public: + QStyle* create(const QString& key); +}; + +#endif diff --git a/Tests/QtAutogen/mocPlugin/StyleD.cpp b/Tests/QtAutogen/mocPlugin/StyleD.cpp new file mode 100644 index 0000000..48398bb --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleD.cpp @@ -0,0 +1,17 @@ +#include "StyleD.hpp" + +class StyleD : public QStylePlugin +{ + Q_OBJECT + // Json file in global sub director + Q_PLUGIN_METADATA(IID "org.styles.D" FILE "sub/StyleD.json") +public: + QStyle* create(const QString& key); +}; + +QStyle* StyleD::create(const QString& key) +{ + return 0; +} + +#include "StyleD.moc" diff --git a/Tests/QtAutogen/mocPlugin/StyleD.hpp b/Tests/QtAutogen/mocPlugin/StyleD.hpp new file mode 100644 index 0000000..2afe055 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleD.hpp @@ -0,0 +1,8 @@ +#ifndef STYLED_HPP +#define STYLED_HPP + +#include + +class StyleD; + +#endif diff --git a/Tests/QtAutogen/mocPlugin/StyleE.cpp b/Tests/QtAutogen/mocPlugin/StyleE.cpp new file mode 100644 index 0000000..8fc9a7f --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleE.cpp @@ -0,0 +1,6 @@ +#include "StyleE.hpp" + +QStyle* StyleE::create(const QString& key) +{ + return 0; +} diff --git a/Tests/QtAutogen/mocPlugin/StyleE.hpp b/Tests/QtAutogen/mocPlugin/StyleE.hpp new file mode 100644 index 0000000..80e0b79 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleE.hpp @@ -0,0 +1,15 @@ +#ifndef STYLEE_HPP +#define STYLEE_HPP + +#include + +class StyleE : public QStylePlugin +{ + Q_OBJECT + // No Json file + Q_PLUGIN_METADATA(IID "org.styles.E") +public: + QStyle* create(const QString& key); +}; + +#endif diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleB.json b/Tests/QtAutogen/mocPlugin/jsonIn/StyleB.json new file mode 100644 index 0000000..129cac4 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/jsonIn/StyleB.json @@ -0,0 +1 @@ +{ "Keys": [ "Rocket", "StarbusterB" ] } diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json b/Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json new file mode 100644 index 0000000..bf17580 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json @@ -0,0 +1 @@ +{ "Keys": [ "Rocket", "StarbusterC" ] } diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json b/Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json new file mode 100644 index 0000000..f7fcc19 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json @@ -0,0 +1 @@ +{ "Keys": [ "Rocket", "StarbusterD" ] } diff --git a/Tests/QtAutogen/mocPlugin/main.cpp b/Tests/QtAutogen/mocPlugin/main.cpp new file mode 100644 index 0000000..3ba2ddc --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/main.cpp @@ -0,0 +1,6 @@ +#include "StyleA.hpp" + +int main(int argv, char** args) +{ + return 0; +} https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c7c1ac85de53a1fce5c0b1bdded27598109cc4be commit c7c1ac85de53a1fce5c0b1bdded27598109cc4be Author: Sebastian Holtermann AuthorDate: Thu Feb 16 15:59:56 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:12:56 2017 -0500 Autogen: Tests: Add moc include tests diff --git a/Tests/QtAutogen/CMakeLists.txt b/Tests/QtAutogen/CMakeLists.txt index c1cdee2..40c23fa 100644 --- a/Tests/QtAutogen/CMakeLists.txt +++ b/Tests/QtAutogen/CMakeLists.txt @@ -207,5 +207,13 @@ target_link_libraries(skipRccB ${QT_LIBRARIES}) add_subdirectory(sameName) # -- Test +# Tests various include moc patterns +add_subdirectory(mocIncludeStrict) + +# -- Test +# Tests various include moc patterns +add_subdirectory(mocIncludeRelaxed) + +# -- Test # Complex test case add_subdirectory(complex) diff --git a/Tests/QtAutogen/mocInclude/ObjA.cpp b/Tests/QtAutogen/mocInclude/ObjA.cpp new file mode 100644 index 0000000..2ee47ec --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjA.cpp @@ -0,0 +1,24 @@ +#include "ObjA.hpp" + +class SubObjA : public QObject +{ + Q_OBJECT + +public: + SubObjA() = default; + ~SubObjA() = default; + + Q_SLOT + void aSlot(); +}; + +void SubObjA::aSlot() +{ +} + +void ObjA::go() +{ + SubObjA subObj; +} + +#include "ObjA.moc" diff --git a/Tests/QtAutogen/mocInclude/ObjA.hpp b/Tests/QtAutogen/mocInclude/ObjA.hpp new file mode 100644 index 0000000..281e90d --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjA.hpp @@ -0,0 +1,13 @@ +#ifndef OBJA_HPP +#define OBJA_HPP + +#include + +class ObjA : public QObject +{ + Q_OBJECT + Q_SLOT + void go(); +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/ObjB.cpp b/Tests/QtAutogen/mocInclude/ObjB.cpp new file mode 100644 index 0000000..abec06a --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjB.cpp @@ -0,0 +1,25 @@ +#include "ObjB.hpp" + +class SubObjB : public QObject +{ + Q_OBJECT + +public: + SubObjB() = default; + ~SubObjB() = default; + + Q_SLOT + void aSlot(); +}; + +void SubObjB::aSlot() +{ +} + +void ObjB::go() +{ + SubObjB subObj; +} + +#include "ObjB.moc" +#include "moc_ObjB.cpp" diff --git a/Tests/QtAutogen/mocInclude/ObjB.hpp b/Tests/QtAutogen/mocInclude/ObjB.hpp new file mode 100644 index 0000000..94f3d49 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjB.hpp @@ -0,0 +1,13 @@ +#ifndef OBJB_HPP +#define OBJB_HPP + +#include + +class ObjB : public QObject +{ + Q_OBJECT + Q_SLOT + void go(); +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/ObjC.cpp b/Tests/QtAutogen/mocInclude/ObjC.cpp new file mode 100644 index 0000000..bdcdb13 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjC.cpp @@ -0,0 +1,26 @@ +#include "ObjC.hpp" + +class SubObjC : public QObject +{ + Q_OBJECT + +public: + SubObjC() = default; + ~SubObjC() = default; + + 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 new file mode 100644 index 0000000..a8e98eb --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjC.hpp @@ -0,0 +1,13 @@ +#ifndef OBJC_HPP +#define OBJC_HPP + +#include + +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 new file mode 100644 index 0000000..9145ba3 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjD.cpp @@ -0,0 +1,26 @@ +#include "ObjD.hpp" + +class SubObjD : public QObject +{ + Q_OBJECT + +public: + SubObjD() = default; + ~SubObjD() = default; + + 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 new file mode 100644 index 0000000..b6ee098 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjD.hpp @@ -0,0 +1,13 @@ +#ifndef OBJD_HPP +#define OBJD_HPP + +#include + +class ObjD : public QObject +{ + Q_OBJECT + Q_SLOT + void go(); +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/subA/SubObjA.cpp b/Tests/QtAutogen/mocInclude/subA/SubObjA.cpp new file mode 100644 index 0000000..d780942 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subA/SubObjA.cpp @@ -0,0 +1,27 @@ +#include "SubObjA.hpp" + +namespace subA { + +class SubObjA : public QObject +{ + Q_OBJECT + +public: + SubObjA() = default; + ~SubObjA() = default; + + 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 new file mode 100644 index 0000000..31a18b6 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subA/SubObjA.hpp @@ -0,0 +1,16 @@ +#ifndef SUBOBJA_HPP +#define SUBOBJA_HPP + +#include + +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 new file mode 100644 index 0000000..e602e06 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subB/SubObjB.cpp @@ -0,0 +1,27 @@ +#include "SubObjB.hpp" + +namespace subB { + +class SubObjB : public QObject +{ + Q_OBJECT + +public: + SubObjB() = default; + ~SubObjB() = default; + + 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 new file mode 100644 index 0000000..3f29fa2 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subB/SubObjB.hpp @@ -0,0 +1,16 @@ +#ifndef SUBOBJB_HPP +#define SUBOBJB_HPP + +#include + +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 new file mode 100644 index 0000000..fb2d1ec --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subC/SubObjC.cpp @@ -0,0 +1,27 @@ +#include "SubObjC.hpp" + +namespace subC { + +class SubObjC : public QObject +{ + Q_OBJECT + +public: + SubObjC() = default; + ~SubObjC() = default; + + 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 new file mode 100644 index 0000000..dc251fd --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subC/SubObjC.hpp @@ -0,0 +1,16 @@ +#ifndef SUBOBJC_HPP +#define SUBOBJC_HPP + +#include + +namespace subC { + +class ObjC : public QObject +{ + Q_OBJECT + Q_SLOT + void go(); +}; +} + +#endif diff --git a/Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt b/Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt new file mode 100644 index 0000000..6a0829d --- /dev/null +++ b/Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt @@ -0,0 +1,18 @@ +# Test moc include patterns + +set(CMAKE_AUTOMOC_RELAXED_MODE TRUE) + +include_directories("../mocInclude") + +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 +) +target_link_libraries(mocIncludeRelaxed ${QT_LIBRARIES}) +set_target_properties(mocIncludeRelaxed PROPERTIES AUTOMOC ON) diff --git a/Tests/QtAutogen/mocIncludeRelaxed/main.cpp b/Tests/QtAutogen/mocIncludeRelaxed/main.cpp new file mode 100644 index 0000000..142d59e --- /dev/null +++ b/Tests/QtAutogen/mocIncludeRelaxed/main.cpp @@ -0,0 +1,14 @@ +#include "ObjA.hpp" +#include "ObjB.hpp" +#include "ObjC.hpp" + +int main(int argv, char** args) +{ + ObjA objA; + ObjB objB; + ObjC objC; + return 0; +} + +// Header in global subdirectory +#include "subB/moc_SubObjB.cpp" diff --git a/Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt b/Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt new file mode 100644 index 0000000..22e93a8 --- /dev/null +++ b/Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt @@ -0,0 +1,18 @@ +# Test moc include patterns + +set(CMAKE_AUTOMOC_RELAXED_MODE FALSE) + +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) diff --git a/Tests/QtAutogen/mocIncludeStrict/main.cpp b/Tests/QtAutogen/mocIncludeStrict/main.cpp new file mode 100644 index 0000000..142d59e --- /dev/null +++ b/Tests/QtAutogen/mocIncludeStrict/main.cpp @@ -0,0 +1,14 @@ +#include "ObjA.hpp" +#include "ObjB.hpp" +#include "ObjC.hpp" + +int main(int argv, char** args) +{ + ObjA objA; + ObjB objB; + ObjC objC; + return 0; +} + +// Header in global subdirectory +#include "subB/moc_SubObjB.cpp" https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=50805693ba987fbf86bb5e8263d7b427cd4da0c2 commit 50805693ba987fbf86bb5e8263d7b427cd4da0c2 Author: Sebastian Holtermann AuthorDate: Thu Feb 16 15:05:11 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:12:55 2017 -0500 Autogen: Tests: Clean comments diff --git a/Tests/QtAutogen/CMakeLists.txt b/Tests/QtAutogen/CMakeLists.txt index 4b90ad8..c1cdee2 100644 --- a/Tests/QtAutogen/CMakeLists.txt +++ b/Tests/QtAutogen/CMakeLists.txt @@ -46,26 +46,26 @@ endif() get_property(QT_COMPILE_FEATURES TARGET ${QT_QTCORE_TARGET} PROPERTY INTERFACE_COMPILE_FEATURES) -# -- Test: AUTORCC +# -- Test # RCC only add_executable(rccOnly rccOnly.cpp rccOnlyRes.qrc) set_property(TARGET rccOnly PROPERTY AUTORCC ON) target_link_libraries(rccOnly ${QT_QTCORE_TARGET}) -# -- Test: AUTORCC +# -- Test # RCC empty add_executable(rccEmpty rccEmpty.cpp rccEmptyRes.qrc) set_property(TARGET rccEmpty PROPERTY AUTORCC ON) target_link_libraries(rccEmpty ${QT_QTCORE_TARGET}) -# -- Test: AUTOUIC +# -- Test # UIC only qtx_wrap_cpp(uicOnlyMoc uicOnlySource/uiconly.h) add_executable(uicOnly uicOnlySource/uiconly.cpp ${uicOnlyMoc}) set_property(TARGET uicOnly PROPERTY AUTOUIC ON) target_link_libraries(uicOnly ${QT_LIBRARIES}) -# -- Test: AUTOMOC, AUTORCC +# -- Test # Add not_generated_file.qrc to the source list to get the file-level # dependency, but don't generate a c++ file from it. Disable the AUTORCC # feature for this target. This tests that qrc files in the sources don't @@ -80,7 +80,7 @@ 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: AUTORCC +# -- Test # When a file listed in a .qrc file changes the target must be rebuilt try_compile(RCC_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/autorcc_depends" @@ -115,7 +115,7 @@ if (NOT file1_step1 GREATER file1_before) message(SEND_ERROR "file1 (${qrc_file1}) should have changed in the first step!") endif() -# -- Test: AUTOMOC +# -- Test # Ensure a repeated build succeeds when a header containing a QObject changes try_compile(MOC_RERUN "${CMAKE_CURRENT_BINARY_DIR}/automoc_rerun" @@ -139,7 +139,7 @@ if (automoc_rerun_result) message(SEND_ERROR "Second build of automoc_rerun failed.") endif() -# -- Test: AUTOMOC, SKIP_AUTOMOC +# -- Test # Test for SKIP_AUTOMOC and SKIP_AUTOGEN on an AUTOMOC enabled target qtx_wrap_cpp(skipMocWrapMoc skipSource/qItemA.hpp @@ -161,7 +161,7 @@ set_property(TARGET skipMocB PROPERTY AUTOMOC ON) set_property(TARGET skipMocB PROPERTY AUTOUIC ON) target_link_libraries(skipMocB ${QT_LIBRARIES}) -# -- Test: AUTOUIC, SKIP_AUTOUIC +# -- Test # Test for SKIP_AUTOUIC and SKIP_AUTOGEN on an AUTOUIC enabled target set(skipUicSources skipUic.cpp @@ -181,7 +181,7 @@ set_property(TARGET skipUicB PROPERTY AUTOUIC ON) set_property(TARGET skipUicB PROPERTY AUTOMOC ON) target_link_libraries(skipUicB ${QT_LIBRARIES}) -# -- Test: AUTORCC, SKIP_AUTORCC +# -- Test # Test for SKIP_AUTORCC and SKIP_AUTOGEN on an AUTORCC enabled target set(skipRccSources skipRcc.cpp @@ -202,10 +202,10 @@ set_property(TARGET skipRccB PROPERTY AUTOUIC ON) set_property(TARGET skipRccB PROPERTY AUTOMOC ON) target_link_libraries(skipRccB ${QT_LIBRARIES}) -# -- Test: AUTOMOC AUTORCC +# -- Test # Source files with the same basename in different subdirectories add_subdirectory(sameName) -# -- Test: AUTOMOC AUTORCC AUTOUIC +# -- Test # Complex test case add_subdirectory(complex) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c23206b6c17a5c70580355904fc12fd64c26ef79 commit c23206b6c17a5c70580355904fc12fd64c26ef79 Author: Sebastian Holtermann AuthorDate: Fri Feb 17 18:44:10 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:12:55 2017 -0500 Autogen: Log simplifications The logging methods now automatically add an end-of-line to the message if it is missing. diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index cd39984..ccdebbb 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -465,9 +465,7 @@ bool cmQtAutoGenerators::SettingsFileWrite(const std::string& targetDirectory) if (this->GenerateAllAny()) { const std::string filename = SettingsFile(targetDirectory); if (this->Verbose) { - std::ostringstream err; - err << "AutoGen: Writing settings file " << filename << "\n"; - this->LogInfo(err.str()); + this->LogInfo("AutoGen: Writing settings file " + filename); } cmsys::ofstream outfile; outfile.open(filename.c_str(), std::ios::trunc); @@ -483,8 +481,8 @@ bool cmQtAutoGenerators::SettingsFileWrite(const std::string& targetDirectory) cmSystemTools::RemoveFile(filename); { std::ostringstream err; - err << "AutoGen: Error: Writing old settings file failed: " << filename - << std::endl; + err << "AutoGen: Error: Writing old settings file failed: " + << filename; this->LogError(err.str()); } } @@ -686,12 +684,12 @@ void cmQtAutoGenerators::MocFindDepends( mocDepends[absFilename].insert(incFile); if (this->Verbose) { this->LogInfo("AutoMoc: Found dependency:\n \"" + absFilename + - "\"\n \"" + incFile + "\"\n"); + "\"\n \"" + incFile + "\""); } } else { this->LogWarning("AutoMoc: Warning: \"" + absFilename + "\"\n" + "Could not find dependency file \"" + match + - "\"\n"); + "\""); } } contentChars += filter.regExp.end(); @@ -741,10 +739,10 @@ bool cmQtAutoGenerators::ParseSourceFile( bool success = true; const std::string contentText = ReadAll(absFilename); if (contentText.empty()) { - std::ostringstream err; - err << "AutoGen: Warning: " << absFilename << "\n" + std::ostringstream ost; + ost << "AutoGen: Warning: " << absFilename << "\n" << "The file is empty\n"; - this->LogWarning(err.str()); + this->LogWarning(ost.str()); } else { // Parse source contents for MOC if (success && !this->MocSkip(absFilename)) { @@ -764,9 +762,7 @@ void cmQtAutoGenerators::UicParseContent( std::map >& uisIncluded) { if (this->Verbose) { - std::ostringstream err; - err << "AutoUic: Checking " << absFilename << "\n"; - this->LogInfo(err.str()); + this->LogInfo("AutoUic: Checking " + absFilename); } const char* contentChars = contentText.c_str(); @@ -792,9 +788,7 @@ bool cmQtAutoGenerators::MocParseSourceContent( std::map >& mocDepends, bool relaxed) { if (this->Verbose) { - std::ostringstream err; - err << "AutoMoc: Checking " << absFilename << "\n"; - this->LogInfo(err.str()); + this->LogInfo("AutoMoc: Checking " + absFilename); } const std::string scannedFileAbsPath = @@ -846,12 +840,12 @@ bool cmQtAutoGenerators::MocParseSourceContent( ownMocUnderscoreHeader = headerToMoc; } } else { - std::ostringstream err; - err << "AutoMoc: Error: " << absFilename << "\n" + std::ostringstream ost; + ost << "AutoMoc: Error: " << absFilename << "\n" << "The file includes the moc file \"" << incString << "\", but could not find header \"" << incRealBasename << '{' << JoinExts(this->HeaderExtensions) << "}\"\n"; - this->LogError(err.str()); + this->LogError(ost.str()); return false; } } else { @@ -871,34 +865,34 @@ bool cmQtAutoGenerators::MocParseSourceContent( // This is for KDE4 compatibility: fileToMoc = headerToMoc; if (!requiresMoc && (incBasename == scannedFileBasename)) { - std::ostringstream err; - err << "AutoMoc: Warning: " << absFilename << "\n" + std::ostringstream ost; + ost << "AutoMoc: Warning: " << absFilename << "\n" << "The file includes the moc file \"" << incString << "\"" << ", but does not contain a Q_OBJECT or Q_GADGET macro.\n" << "Running moc on \"" << headerToMoc << "\"!\n" << "Include \"moc_" << incBasename << ".cpp\" for a compatibility with " "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; - this->LogWarning(err.str()); + this->LogWarning(ost.str()); } else { - std::ostringstream err; - err << "AutoMoc: Warning: " << absFilename << "\n" + std::ostringstream ost; + ost << "AutoMoc: Warning: " << absFilename << "\n" << "The file includes the moc file \"" << incString << "\" instead of \"moc_" << incBasename << ".cpp\".\n" << "Running moc on \"" << headerToMoc << "\"!\n" << "Include \"moc_" << incBasename << ".cpp\" for compatibility with " "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; - this->LogWarning(err.str()); + this->LogWarning(ost.str()); } } else { - std::ostringstream err; - err << "AutoMoc: Error: " << absFilename << "\n" + std::ostringstream ost; + ost << "AutoMoc: Error: " << absFilename << "\n" << "The file includes the moc file \"" << incString << "\", which seems to be the moc file from a different " "source file. CMake also could not find a matching " "header.\n"; - this->LogError(err.str()); + this->LogError(ost.str()); return false; } } @@ -910,23 +904,23 @@ bool cmQtAutoGenerators::MocParseSourceContent( ownDotMocIncluded = true; // Accept but issue a warning if moc isn't required if (!requiresMoc) { - std::ostringstream err; - err << "AutoMoc: Error: " << absFilename << "\n" + std::ostringstream ost; + ost << "AutoMoc: Error: " << absFilename << "\n" << "The file includes the moc file \"" << incString << "\"" << ", but does not contain a Q_OBJECT or Q_GADGET " "macro.\n"; - this->LogWarning(err.str()); + this->LogWarning(ost.str()); } } else { // Don't allow FOO.moc include other than self in strict mode - std::ostringstream err; - err << "AutoMoc: Error: " << absFilename << "\n" + std::ostringstream ost; + ost << "AutoMoc: Error: " << absFilename << "\n" << "The file includes the moc file \"" << incString << "\", which seems to be the moc file from a different " "source file. This is not supported. Include \"" << scannedFileBasename << ".moc\" to run moc on this source file.\n"; - this->LogError(err.str()); + this->LogError(ost.str()); return false; } } @@ -947,8 +941,8 @@ bool cmQtAutoGenerators::MocParseSourceContent( // But warn, since this is not how it is supposed to be used. if (relaxed && !ownMocUnderscoreInclude.empty()) { // This is for KDE4 compatibility: - std::ostringstream err; - err << "AutoMoc: Warning: " << absFilename << "\n" + std::ostringstream ost; + ost << "AutoMoc: Warning: " << absFilename << "\n" << "The file contains a " << macroName << " macro, but does not include " << "\"" << scannedFileBasename << ".moc\", but instead includes " @@ -957,7 +951,7 @@ bool cmQtAutoGenerators::MocParseSourceContent( << "Better include \"" << scannedFileBasename << ".moc\" for compatibility with " "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; - this->LogWarning(err.str()); + this->LogWarning(ost.str()); // Use scanned source file instead of scanned header file as moc source mocsIncluded[absFilename] = ownMocUnderscoreInclude; @@ -966,12 +960,12 @@ bool cmQtAutoGenerators::MocParseSourceContent( mocsIncluded.erase(ownMocUnderscoreHeader); } else { // Otherwise always error out since it will not compile: - std::ostringstream err; - err << "AutoMoc: Error: " << absFilename << "\n" + std::ostringstream ost; + ost << "AutoMoc: Error: " << absFilename << "\n" << "The file contains a " << macroName << " macro, but does not include " << "\"" << scannedFileBasename << ".moc\"!\n"; - this->LogError(err.str()); + this->LogError(ost.str()); return false; } } @@ -986,9 +980,7 @@ void cmQtAutoGenerators::MocParseHeaderContent( { // Log if (this->Verbose) { - std::ostringstream err; - err << "AutoMoc: Checking " << absFilename << "\n"; - this->LogInfo(err.str()); + this->LogInfo("AutoMoc: Checking " + absFilename); } if (this->MocRequired(contentText)) { // Register moc job @@ -1080,15 +1072,14 @@ bool cmQtAutoGenerators::MocGenerateAll( std::map mergedMocs(mocsIncluded); mergedMocs.insert(mocsNotIncluded.begin(), mocsNotIncluded.end()); if (this->NameCollisionTest(mergedMocs, collisions)) { - std::ostringstream err; - err << "AutoMoc: Error: " + std::ostringstream ost; + ost << "AutoMoc: Error: " "The same moc file will be generated " - "from different sources." - << std::endl - << "To avoid this error either" << std::endl - << "- rename the source files or" << std::endl - << "- do not include the (moc_NAME.cpp|NAME.moc) file" << std::endl; - this->LogErrorNameCollision(err.str(), collisions); + "from different sources.\n" + "To avoid this error either\n" + "- rename the source files or\n" + "- do not include the (moc_NAME.cpp|NAME.moc) file"; + this->LogErrorNameCollision(ost.str(), collisions); return false; } } @@ -1124,21 +1115,20 @@ bool cmQtAutoGenerators::MocGenerateAll( // Compose moc_compilation.cpp content std::string automocSource; { - std::ostringstream outStream; - outStream << "/* This file is autogenerated, do not edit*/\n"; + std::ostringstream ost; + ost << "/* This file is autogenerated, do not edit*/\n"; if (mocsNotIncluded.empty()) { // Dummy content - outStream << "enum some_compilers { need_more_than_nothing };\n"; + ost << "enum some_compilers { need_more_than_nothing };\n"; } else { // Valid content for (std::map::const_iterator it = mocsNotIncluded.begin(); it != mocsNotIncluded.end(); ++it) { - outStream << "#include \"" << it->second << "\"\n"; + ost << "#include \"" << it->second << "\"\n"; } } - outStream.flush(); - automocSource = outStream.str(); + automocSource = ost.str(); } // Check if the content of moc_compilation.cpp changed @@ -1159,25 +1149,20 @@ bool cmQtAutoGenerators::MocGenerateAll( outfile.open(this->MocCppFilenameAbs.c_str(), std::ios::trunc); if (!outfile) { success = false; - std::ostringstream err; - err << "AutoMoc: error opening " << this->MocCppFilenameAbs << "\n"; - this->LogError(err.str()); + this->LogError("AutoMoc: error opening " + this->MocCppFilenameAbs); } else { outfile << automocSource; // Check for write errors if (!outfile.good()) { success = false; - std::ostringstream err; - err << "AutoMoc: error writing " << this->MocCppFilenameAbs << "\n"; - this->LogError(err.str()); + this->LogError("AutoMoc: error writing " + this->MocCppFilenameAbs); } } } } else if (mocCompFileGenerated) { // Only touch moc_compilation.cpp if (this->Verbose) { - this->LogInfo("Touching MOC compilation " + this->MocCppFilenameRel + - "\n"); + this->LogInfo("Touching MOC compilation " + this->MocCppFilenameRel); } cmSystemTools::Touch(this->MocCppFilenameAbs, false); } @@ -1257,12 +1242,12 @@ bool cmQtAutoGenerators::MocGenerateFile( if (!res || (retVal != 0)) { // Command failed { - std::ostringstream err; - err << "AutoMoc: Error: moc process failed for\n"; - err << "\"" << mocFileRel << "\"\n"; - err << "AutoMoc: Command:\n" << cmJoin(cmd, " ") << "\n"; - err << "AutoMoc: Command output:\n" << output << "\n"; - this->LogError(err.str()); + std::ostringstream ost; + ost << "AutoMoc: Error: moc process failed for\n"; + ost << "\"" << mocFileRel << "\"\n"; + ost << "AutoMoc: Command:\n" << cmJoin(cmd, " ") << "\n"; + ost << "AutoMoc: Command output:\n" << output << "\n"; + this->LogError(ost.str()); } cmSystemTools::RemoveFile(mocFileAbs); this->RunMocFailed = true; @@ -1311,12 +1296,11 @@ bool cmQtAutoGenerators::UicGenerateAll( { std::multimap collisions; if (this->NameCollisionTest(testMap, collisions)) { - std::ostringstream err; - err << "AutoUic: Error: The same ui_NAME.h file will be generated " - "from different sources." - << std::endl - << "To avoid this error rename the source files." << std::endl; - this->LogErrorNameCollision(err.str(), collisions); + std::ostringstream ost; + ost << "AutoUic: Error: The same ui_NAME.h file will be generated " + "from different sources.\n" + "To avoid this error rename the source files.\n"; + this->LogErrorNameCollision(ost.str(), collisions); return false; } } @@ -1397,13 +1381,13 @@ bool cmQtAutoGenerators::UicGenerateFile(const std::string& realName, if (!res || (retVal != 0)) { // Command failed { - std::ostringstream err; - err << "AutoUic: Error: uic process failed for\n"; - err << "\"" << uicFileRel << "\" needed by\n"; - err << "\"" << realName << "\"\n"; - err << "AutoUic: Command:\n" << cmJoin(cmd, " ") << "\n"; - err << "AutoUic: Command output:\n" << output << "\n"; - this->LogError(err.str()); + std::ostringstream ost; + ost << "AutoUic: Error: uic process failed for\n"; + ost << "\"" << uicFileRel << "\" needed by\n"; + ost << "\"" << realName << "\"\n"; + ost << "AutoUic: Command:\n" << cmJoin(cmd, " ") << "\n"; + ost << "AutoUic: Command output:\n" << output << "\n"; + this->LogError(ost.str()); } cmSystemTools::RemoveFile(uicFileAbs); this->RunUicFailed = true; @@ -1440,12 +1424,11 @@ bool cmQtAutoGenerators::RccGenerateAll() { std::multimap collisions; if (this->NameCollisionTest(qrcGenMap, collisions)) { - std::ostringstream err; - err << "AutoRcc: Error: The same qrc_NAME.cpp file" - " will be generated from different sources." - << std::endl - << "To avoid this error rename the source .qrc files." << std::endl; - this->LogErrorNameCollision(err.str(), collisions); + std::ostringstream ost; + ost << "AutoRcc: Error: The same qrc_NAME.cpp file" + " will be generated from different sources.\n" + "To avoid this error rename the source .qrc files.\n"; + this->LogErrorNameCollision(ost.str(), collisions); return false; } } @@ -1537,12 +1520,12 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile, if (!res || (retVal != 0)) { // Command failed { - std::ostringstream err; - err << "AutoRcc: Error: rcc process failed for\n"; - err << "\"" << rccOutputFile << "\"\n"; - err << "AutoRcc: Command:\n" << cmJoin(cmd, " ") << "\n"; - err << "AutoRcc: Command output:\n" << output << "\n"; - this->LogError(err.str()); + std::ostringstream ost; + ost << "AutoRcc: Error: rcc process failed for\n"; + ost << "\"" << rccOutputFile << "\"\n"; + ost << "AutoRcc: Command:\n" << cmJoin(cmd, " ") << "\n"; + ost << "AutoRcc: Command output:\n" << output << "\n"; + this->LogError(ost.str()); } cmSystemTools::RemoveFile(rccBuildFile); this->RunRccFailed = true; @@ -1560,18 +1543,23 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile, void cmQtAutoGenerators::LogErrorNameCollision( const std::string& message, - const std::multimap& collisions) + const std::multimap& collisions) const { typedef std::multimap::const_iterator Iter; - std::ostringstream err; + std::ostringstream ost; // Add message - err << message; + if (!message.empty()) { + ost << message; + if (message[message.size() - 1] != '\n') { + ost << '\n'; + } + } // Append collision list for (Iter it = collisions.begin(); it != collisions.end(); ++it) { - err << it->first << " : " << it->second << std::endl; + ost << it->first << " : " << it->second << '\n'; } - this->LogError(err.str()); + this->LogError(ost.str()); } void cmQtAutoGenerators::LogBold(const std::string& message) const @@ -1583,38 +1571,45 @@ void cmQtAutoGenerators::LogBold(const std::string& message) const void cmQtAutoGenerators::LogInfo(const std::string& message) const { - cmSystemTools::Stdout(message.c_str(), message.size()); + std::string msg(message); + if (!msg.empty()) { + if (msg[msg.size() - 1] != '\n') { + msg.push_back('\n'); + } + cmSystemTools::Stdout(msg.c_str(), msg.size()); + } } void cmQtAutoGenerators::LogWarning(const std::string& message) const { std::string msg(message); - msg += "\n"; - cmSystemTools::Stdout(msg.c_str(), msg.size()); + if (!msg.empty()) { + if (msg[msg.size() - 1] != '\n') { + msg.push_back('\n'); + } + // Append empty line + msg.push_back('\n'); + cmSystemTools::Stdout(msg.c_str(), msg.size()); + } } void cmQtAutoGenerators::LogError(const std::string& message) const { std::string msg(message); - msg += "\n"; - cmSystemTools::Stderr(msg.c_str(), msg.size()); + if (!msg.empty()) { + if (msg[msg.size() - 1] != '\n') { + msg.push_back('\n'); + } + // Append empty line + msg.push_back('\n'); + cmSystemTools::Stderr(msg.c_str(), msg.size()); + } } void cmQtAutoGenerators::LogCommand( const std::vector& command) const { - std::ostringstream sbuf; - for (std::vector::const_iterator cmdIt = command.begin(); - cmdIt != command.end(); ++cmdIt) { - if (cmdIt != command.begin()) { - sbuf << " "; - } - sbuf << *cmdIt; - } - if (!sbuf.str().empty()) { - sbuf << std::endl; - this->LogInfo(sbuf.str()); - } + this->LogInfo(cmJoin(command, " ")); } /** @@ -1737,7 +1732,7 @@ std::string cmQtAutoGenerators::FindIncludedFile( return cmsys::SystemTools::GetRealPath(testPath); } } - // Search globaly + // Search globally return FindInIncludeDirectories(includeString); } @@ -1765,16 +1760,14 @@ std::string cmQtAutoGenerators::FindInIncludeDirectories( * @brief Generates the parent directory of the given file on demand * @return True on success */ -bool cmQtAutoGenerators::MakeParentDirectory(const std::string& filename) +bool cmQtAutoGenerators::MakeParentDirectory(const std::string& filename) const { bool success = true; const std::string dirName = cmSystemTools::GetFilenamePath(filename); if (!dirName.empty()) { success = cmsys::SystemTools::MakeDirectory(dirName); if (!success) { - std::ostringstream err; - err << "AutoGen: Directory creation failed: " << dirName << std::endl; - this->LogError(err.str()); + this->LogError("AutoGen: Directory creation failed: " + dirName); } } return success; diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 2242e13..c20b83c 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -124,7 +124,7 @@ private: // - Logging void LogErrorNameCollision( const std::string& message, - const std::multimap& collisions); + const std::multimap& collisions) const; void LogBold(const std::string& message) const; void LogInfo(const std::string& message) const; void LogWarning(const std::string& message) const; @@ -138,7 +138,7 @@ private: std::string ChecksumedPath(const std::string& sourceFile, const char* basePrefix, const char* baseSuffix) const; - bool MakeParentDirectory(const std::string& filename); + bool MakeParentDirectory(const std::string& filename) const; bool FindHeader(std::string& header, const std::string& testBasePath) const; bool FindHeaderGlobal(std::string& header, https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=347572cf5ea2c653cba6150b5e6d6fa083a68cb0 commit 347572cf5ea2c653cba6150b5e6d6fa083a68cb0 Author: Sebastian Holtermann AuthorDate: Fri Feb 17 14:47:20 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:12:55 2017 -0500 Autogen: Only touch an unchanged moc_compilation.cpp diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 3965503..cd39984 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -1070,6 +1070,9 @@ bool cmQtAutoGenerators::MocGenerateAll( return true; } + bool mocCompFileGenerated = false; + bool mocCompChanged = false; + // look for name collisions { std::multimap collisions; @@ -1089,8 +1092,7 @@ bool cmQtAutoGenerators::MocGenerateAll( return false; } } - - // generate moc files that are included by source files. + // Generate moc files that are included by source files. { const std::string subDir = "include/"; for (std::map::const_iterator it = @@ -1103,16 +1105,14 @@ bool cmQtAutoGenerators::MocGenerateAll( } } } - - // generate moc files that are _not_ included by source files. - bool automocCppChanged = false; + // Generate moc files that are _not_ included by source files. { const std::string subDir; for (std::map::const_iterator it = mocsNotIncluded.begin(); it != mocsNotIncluded.end(); ++it) { if (this->MocGenerateFile(it->first, it->second, subDir, mocDepends)) { - automocCppChanged = true; + mocCompFileGenerated = true; } else { if (this->RunMocFailed) { return false; @@ -1141,46 +1141,47 @@ bool cmQtAutoGenerators::MocGenerateAll( automocSource = outStream.str(); } - // Check if we even need to update moc_compilation.cpp - if (!automocCppChanged) { - // compare contents of the moc_compilation.cpp file + // Check if the content of moc_compilation.cpp changed + { const std::string oldContents = ReadAll(this->MocCppFilenameAbs); - if (oldContents == automocSource) { - // nothing changed: don't touch the moc_compilation.cpp file - if (this->Verbose) { - std::ostringstream err; - err << "AutoMoc: " << this->MocCppFilenameRel << " still up to date" - << std::endl; - this->LogInfo(err.str()); - } - return true; - } + mocCompChanged = (oldContents != automocSource); } - // Actually write moc_compilation.cpp - this->LogBold("Generating MOC compilation " + this->MocCppFilenameRel); + bool success = true; + if (mocCompChanged) { + // Actually write moc_compilation.cpp + this->LogBold("Generating MOC compilation " + this->MocCppFilenameRel); - // Make sure the parent directory exists - bool success = this->MakeParentDirectory(this->MocCppFilenameAbs); - if (success) { - cmsys::ofstream outfile; - outfile.open(this->MocCppFilenameAbs.c_str(), std::ios::trunc); - if (!outfile) { - success = false; - std::ostringstream err; - err << "AutoMoc: error opening " << this->MocCppFilenameAbs << "\n"; - this->LogError(err.str()); - } else { - outfile << automocSource; - // Check for write errors - if (!outfile.good()) { + // Make sure the parent directory exists + success = this->MakeParentDirectory(this->MocCppFilenameAbs); + if (success) { + cmsys::ofstream outfile; + outfile.open(this->MocCppFilenameAbs.c_str(), std::ios::trunc); + if (!outfile) { success = false; std::ostringstream err; - err << "AutoMoc: error writing " << this->MocCppFilenameAbs << "\n"; + err << "AutoMoc: error opening " << this->MocCppFilenameAbs << "\n"; this->LogError(err.str()); + } else { + outfile << automocSource; + // Check for write errors + if (!outfile.good()) { + success = false; + std::ostringstream err; + err << "AutoMoc: error writing " << this->MocCppFilenameAbs << "\n"; + this->LogError(err.str()); + } } } + } else if (mocCompFileGenerated) { + // Only touch moc_compilation.cpp + if (this->Verbose) { + this->LogInfo("Touching MOC compilation " + this->MocCppFilenameRel + + "\n"); + } + cmSystemTools::Touch(this->MocCppFilenameAbs, false); } + return success; } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=03df033bfa551e83c2a265cc22f6f5278c80528b commit 03df033bfa551e83c2a265cc22f6f5278c80528b Author: Sebastian Holtermann AuthorDate: Fri Feb 17 11:56:02 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:12:54 2017 -0500 Autogen: Rebuild moc when Q_PLUGIN_METADATA json file changes Closes #15419 diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 25a0f87..3965503 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -565,6 +565,16 @@ void cmQtAutoGenerators::Init(cmMakefile* makefile) this->MocIncludes.push_back(*it); } } + + // Insert MocDependFilter for Q_PLUGIN_METADATA + if (QtMajorVersion != "4") { + MocDependFilter filter; + filter.key = "Q_PLUGIN_METADATA"; + filter.regExp.compile("[\n][ \t]*" + "Q_PLUGIN_METADATA[ \t]*\\(" + "[^\\)]*FILE[ \t]*\"([^\"]+)\""); + this->MocDependFilters.push_back(filter); + } } bool cmQtAutoGenerators::RunAutogen() @@ -580,6 +590,7 @@ bool cmQtAutoGenerators::RunAutogen() // key = moc source filepath, value = moc output filepath std::map mocsIncluded; std::map mocsNotIncluded; + std::map > mocDepends; std::map > uisIncluded; // collects all headers which may need to be mocced std::set mocHeaderFiles; @@ -590,8 +601,8 @@ bool cmQtAutoGenerators::RunAutogen() it != this->Sources.end(); ++it) { const std::string& absFilename = cmsys::SystemTools::GetRealPath(*it); // Parse source file for MOC/UIC - if (!this->ParseSourceFile(absFilename, mocsIncluded, uisIncluded, - this->MocRelaxedMode)) { + if (!this->ParseSourceFile(absFilename, mocsIncluded, mocDepends, + uisIncluded, this->MocRelaxedMode)) { return false; } // Find additional headers @@ -611,10 +622,10 @@ bool cmQtAutoGenerators::RunAutogen() } } this->ParseHeaders(mocHeaderFiles, uicHeaderFiles, mocsIncluded, - mocsNotIncluded, uisIncluded); + mocsNotIncluded, mocDepends, uisIncluded); // Generate files - if (!this->MocGenerateAll(mocsIncluded, mocsNotIncluded)) { + if (!this->MocGenerateAll(mocsIncluded, mocsNotIncluded, mocDepends)) { return false; } if (!this->UicGenerateAll(uisIncluded)) { @@ -631,17 +642,18 @@ bool cmQtAutoGenerators::RunAutogen() * @brief Tests if the C++ content requires moc processing * @return True if moc is required */ -bool cmQtAutoGenerators::MocRequired(const std::string& text, +bool cmQtAutoGenerators::MocRequired(const std::string& contentText, std::string* macroName) { for (unsigned int ii = 0; ii != cmArraySize(this->MacroFilters); ++ii) { - MacroFilter& macroFilter = this->MacroFilters[ii]; - // Run a simple check before an expensive regular expression check - if (text.find(macroFilter.first) != std::string::npos) { - if (macroFilter.second.find(text)) { + MacroFilter& filter = this->MacroFilters[ii]; + // Run a simple find string operation before the expensive + // regular expression check + if (contentText.find(filter.first) != std::string::npos) { + if (filter.second.find(contentText)) { // Return macro name on demand if (macroName != CM_NULLPTR) { - *macroName = macroFilter.first; + *macroName = filter.first; } return true; } @@ -650,6 +662,44 @@ bool cmQtAutoGenerators::MocRequired(const std::string& text, return false; } +void cmQtAutoGenerators::MocFindDepends( + const std::string& absFilename, const std::string& contentText, + std::map >& mocDepends) +{ + for (std::vector::iterator fit = + this->MocDependFilters.begin(); + fit != this->MocDependFilters.end(); ++fit) { + MocDependFilter& filter = *fit; + // Run a simple find string operation before the expensive + // regular expression check + if (contentText.find(filter.key) != std::string::npos) { + // Run regular expression check loop + const char* contentChars = contentText.c_str(); + while (filter.regExp.find(contentChars)) { + // Evaluate match + const std::string match = filter.regExp.match(1); + if (!match.empty()) { + // Find the dependency file + const std::string incFile = + this->FindIncludedFile(absFilename, match); + if (!incFile.empty()) { + mocDepends[absFilename].insert(incFile); + if (this->Verbose) { + this->LogInfo("AutoMoc: Found dependency:\n \"" + absFilename + + "\"\n \"" + incFile + "\"\n"); + } + } else { + this->LogWarning("AutoMoc: Warning: \"" + absFilename + "\"\n" + + "Could not find dependency file \"" + match + + "\"\n"); + } + } + contentChars += filter.regExp.end(); + } + } + } +} + /** * @brief Tests if the file should be ignored for moc scanning * @return True if the file should be ignored @@ -685,11 +735,12 @@ bool cmQtAutoGenerators::UicSkip(const std::string& absFilename) const bool cmQtAutoGenerators::ParseSourceFile( const std::string& absFilename, std::map& mocsIncluded, + std::map >& mocDepends, std::map >& uisIncluded, bool relaxed) { bool success = true; - const std::string contentsString = ReadAll(absFilename); - if (contentsString.empty()) { + const std::string contentText = ReadAll(absFilename); + if (contentText.empty()) { std::ostringstream err; err << "AutoGen: Warning: " << absFilename << "\n" << "The file is empty\n"; @@ -697,19 +748,19 @@ bool cmQtAutoGenerators::ParseSourceFile( } else { // Parse source contents for MOC if (success && !this->MocSkip(absFilename)) { - success = this->ParseContentForMoc(absFilename, contentsString, - mocsIncluded, relaxed); + success = this->MocParseSourceContent(absFilename, contentText, + mocsIncluded, mocDepends, relaxed); } // Parse source contents for UIC if (success && !this->UicSkip(absFilename)) { - this->ParseContentForUic(absFilename, contentsString, uisIncluded); + this->UicParseContent(absFilename, contentText, uisIncluded); } } return success; } -void cmQtAutoGenerators::ParseContentForUic( - const std::string& absFilename, const std::string& contentsString, +void cmQtAutoGenerators::UicParseContent( + const std::string& absFilename, const std::string& contentText, std::map >& uisIncluded) { if (this->Verbose) { @@ -718,7 +769,7 @@ void cmQtAutoGenerators::ParseContentForUic( this->LogInfo(err.str()); } - const char* contentChars = contentsString.c_str(); + const char* contentChars = contentText.c_str(); if (strstr(contentChars, "ui_") != CM_NULLPTR) { while (this->RegExpUicInclude.find(contentChars)) { const std::string currentUi = this->RegExpUicInclude.match(1); @@ -735,9 +786,10 @@ void cmQtAutoGenerators::ParseContentForUic( /** * @return True on success */ -bool cmQtAutoGenerators::ParseContentForMoc( - const std::string& absFilename, const std::string& contentsString, - std::map& mocsIncluded, bool relaxed) +bool cmQtAutoGenerators::MocParseSourceContent( + const std::string& absFilename, const std::string& contentText, + std::map& mocsIncluded, + std::map >& mocDepends, bool relaxed) { if (this->Verbose) { std::ostringstream err; @@ -751,16 +803,15 @@ bool cmQtAutoGenerators::ParseContentForMoc( cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename); std::string macroName; - const bool requiresMoc = this->MocRequired(contentsString, ¯oName); + const bool requiresMoc = this->MocRequired(contentText, ¯oName); bool ownDotMocIncluded = false; - bool ownMocUnderscoreIncluded = false; - std::string ownMocUnderscoreFile; - std::string ownMocHeaderFile; + std::string ownMocUnderscoreInclude; + std::string ownMocUnderscoreHeader; // first a simple string check for "moc" is *much* faster than the regexp, // and if the string search already fails, we don't have to try the // expensive regexp - const char* contentChars = contentsString.c_str(); + const char* contentChars = contentText.c_str(); if (strstr(contentChars, "moc") != CM_NULLPTR) { // Iterate over all included moc files while (this->RegExpMocInclude.find(contentChars)) { @@ -786,11 +837,13 @@ bool cmQtAutoGenerators::ParseContentForMoc( const std::string headerToMoc = this->FindMocHeader(scannedFileAbsPath, incRealBasename, incSubDir); if (!headerToMoc.empty()) { + // Register moc job mocsIncluded[headerToMoc] = incString; + this->MocFindDepends(headerToMoc, contentText, mocDepends); + // Store meta information for relaxed mode if (relaxed && (incRealBasename == scannedFileBasename)) { - ownMocUnderscoreIncluded = true; - ownMocUnderscoreFile = incString; - ownMocHeaderFile = headerToMoc; + ownMocUnderscoreInclude = incString; + ownMocUnderscoreHeader = headerToMoc; } } else { std::ostringstream err; @@ -879,6 +932,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( } if (!fileToMoc.empty()) { mocsIncluded[fileToMoc] = incString; + this->MocFindDepends(fileToMoc, contentText, mocDepends); } } // Forward content pointer @@ -891,14 +945,14 @@ bool cmQtAutoGenerators::ParseContentForMoc( // If this is the case, the moc_foo.cpp should probably be generated from // foo.cpp instead of foo.h, because otherwise it won't build. // But warn, since this is not how it is supposed to be used. - if (relaxed && ownMocUnderscoreIncluded) { + if (relaxed && !ownMocUnderscoreInclude.empty()) { // This is for KDE4 compatibility: std::ostringstream err; err << "AutoMoc: Warning: " << absFilename << "\n" << "The file contains a " << macroName << " macro, but does not include " << "\"" << scannedFileBasename << ".moc\", but instead includes " - << "\"" << ownMocUnderscoreFile << "\".\n" + << "\"" << ownMocUnderscoreInclude << "\".\n" << "Running moc on \"" << absFilename << "\"!\n" << "Better include \"" << scannedFileBasename << ".moc\" for compatibility with " @@ -906,8 +960,10 @@ bool cmQtAutoGenerators::ParseContentForMoc( this->LogWarning(err.str()); // Use scanned source file instead of scanned header file as moc source - mocsIncluded[absFilename] = ownMocUnderscoreFile; - mocsIncluded.erase(ownMocHeaderFile); + mocsIncluded[absFilename] = ownMocUnderscoreInclude; + this->MocFindDepends(absFilename, contentText, mocDepends); + // Remove + mocsIncluded.erase(ownMocUnderscoreHeader); } else { // Otherwise always error out since it will not compile: std::ostringstream err; @@ -923,6 +979,25 @@ bool cmQtAutoGenerators::ParseContentForMoc( return true; } +void cmQtAutoGenerators::MocParseHeaderContent( + const std::string& absFilename, const std::string& contentText, + std::map& mocsNotIncluded, + std::map >& mocDepends) +{ + // Log + if (this->Verbose) { + std::ostringstream err; + err << "AutoMoc: Checking " << absFilename << "\n"; + this->LogInfo(err.str()); + } + if (this->MocRequired(contentText)) { + // Register moc job + mocsNotIncluded[absFilename] = + this->ChecksumedPath(absFilename, "moc_", ".cpp"); + this->MocFindDepends(absFilename, contentText, mocDepends); + } +} + void cmQtAutoGenerators::SearchHeadersForSourceFile( const std::string& absFilename, std::set& mocHeaderFiles, std::set& uicHeaderFiles) const @@ -959,6 +1034,7 @@ void cmQtAutoGenerators::ParseHeaders( const std::set& uicHeaderFiles, const std::map& mocsIncluded, std::map& mocsNotIncluded, + std::map >& mocDepends, std::map >& uisIncluded) { // Merged header files list to read files only once @@ -969,33 +1045,26 @@ void cmQtAutoGenerators::ParseHeaders( for (std::set::const_iterator hIt = headerFiles.begin(); hIt != headerFiles.end(); ++hIt) { const std::string& headerName = *hIt; - const std::string contents = ReadAll(headerName); + const std::string contentText = ReadAll(headerName); // Parse header content for MOC if ((mocHeaderFiles.find(headerName) != mocHeaderFiles.end()) && (mocsIncluded.find(headerName) == mocsIncluded.end())) { - // Log - if (this->Verbose) { - std::ostringstream err; - err << "AutoMoc: Checking " << headerName << "\n"; - this->LogInfo(err.str()); - } - if (this->MocRequired(contents)) { - mocsNotIncluded[headerName] = - this->ChecksumedPath(headerName, "moc_", ".cpp"); - } + this->MocParseHeaderContent(headerName, contentText, mocsNotIncluded, + mocDepends); } // Parse header content for UIC if (uicHeaderFiles.find(headerName) != uicHeaderFiles.end()) { - this->ParseContentForUic(headerName, contents, uisIncluded); + this->UicParseContent(headerName, contentText, uisIncluded); } } } bool cmQtAutoGenerators::MocGenerateAll( const std::map& mocsIncluded, - const std::map& mocsNotIncluded) + const std::map& mocsNotIncluded, + const std::map >& mocDepends) { if (!this->MocEnabled()) { return true; @@ -1023,11 +1092,11 @@ bool cmQtAutoGenerators::MocGenerateAll( // generate moc files that are included by source files. { - const std::string subDirPrefix = "include/"; + const std::string subDir = "include/"; for (std::map::const_iterator it = mocsIncluded.begin(); it != mocsIncluded.end(); ++it) { - if (!this->MocGenerateFile(it->first, it->second, subDirPrefix)) { + if (!this->MocGenerateFile(it->first, it->second, subDir, mocDepends)) { if (this->RunMocFailed) { return false; } @@ -1038,11 +1107,11 @@ bool cmQtAutoGenerators::MocGenerateAll( // generate moc files that are _not_ included by source files. bool automocCppChanged = false; { - const std::string subDirPrefix; + const std::string subDir; for (std::map::const_iterator it = mocsNotIncluded.begin(); it != mocsNotIncluded.end(); ++it) { - if (this->MocGenerateFile(it->first, it->second, subDirPrefix)) { + if (this->MocGenerateFile(it->first, it->second, subDir, mocDepends)) { automocCppChanged = true; } else { if (this->RunMocFailed) { @@ -1118,9 +1187,10 @@ bool cmQtAutoGenerators::MocGenerateAll( /** * @return True if a moc file was created. False may indicate an error. */ -bool cmQtAutoGenerators::MocGenerateFile(const std::string& sourceFile, - const std::string& mocFileName, - const std::string& subDirPrefix) +bool cmQtAutoGenerators::MocGenerateFile( + const std::string& sourceFile, const std::string& mocFileName, + const std::string& subDirPrefix, + const std::map >& mocDepends) { bool mocGenerated = false; bool generateMoc = this->GenerateAllMoc; @@ -1132,6 +1202,20 @@ bool cmQtAutoGenerators::MocGenerateFile(const std::string& sourceFile, if (!generateMoc) { // Test if the source file is newer that the build file generateMoc = FileAbsentOrOlder(mocFileAbs, sourceFile); + if (!generateMoc) { + // Test if a dependency file changed + std::map >::const_iterator dit = + mocDepends.find(sourceFile); + if (dit != mocDepends.end()) { + for (std::set::const_iterator fit = dit->second.begin(); + fit != dit->second.end(); ++fit) { + if (FileAbsentOrOlder(mocFileAbs, *fit)) { + generateMoc = true; + break; + } + } + } + } } if (generateMoc) { // Log @@ -1489,33 +1573,34 @@ void cmQtAutoGenerators::LogErrorNameCollision( this->LogError(err.str()); } -void cmQtAutoGenerators::LogBold(const std::string& message) +void cmQtAutoGenerators::LogBold(const std::string& message) const { cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue | cmsysTerminal_Color_ForegroundBold, message.c_str(), true, this->ColorOutput); } -void cmQtAutoGenerators::LogInfo(const std::string& message) +void cmQtAutoGenerators::LogInfo(const std::string& message) const { cmSystemTools::Stdout(message.c_str(), message.size()); } -void cmQtAutoGenerators::LogWarning(const std::string& message) +void cmQtAutoGenerators::LogWarning(const std::string& message) const { std::string msg(message); msg += "\n"; cmSystemTools::Stdout(msg.c_str(), msg.size()); } -void cmQtAutoGenerators::LogError(const std::string& message) +void cmQtAutoGenerators::LogError(const std::string& message) const { std::string msg(message); msg += "\n"; cmSystemTools::Stderr(msg.c_str(), msg.size()); } -void cmQtAutoGenerators::LogCommand(const std::vector& command) +void cmQtAutoGenerators::LogCommand( + const std::vector& command) const { std::ostringstream sbuf; for (std::vector::const_iterator cmdIt = command.begin(); @@ -1639,23 +1724,40 @@ std::string cmQtAutoGenerators::FindMocHeader(const std::string& basePath, return header; } +std::string cmQtAutoGenerators::FindIncludedFile( + const std::string& sourceFile, const std::string& includeString) const +{ + // Search in vicinity of the source + { + std::string testPath = cmSystemTools::GetFilenamePath(sourceFile); + testPath += '/'; + testPath += includeString; + if (cmsys::SystemTools::FileExists(testPath.c_str())) { + return cmsys::SystemTools::GetRealPath(testPath); + } + } + // Search globaly + return FindInIncludeDirectories(includeString); +} + /** * @brief Tries to find a file in the include directories * @return True on success */ -bool cmQtAutoGenerators::FindInIncludeDirectories( - std::string& file_n, const std::string& searchString) const +std::string cmQtAutoGenerators::FindInIncludeDirectories( + const std::string& includeString) const { + std::string res; for (std::vector::const_iterator iit = this->MocIncludePaths.begin(); iit != this->MocIncludePaths.end(); ++iit) { - const std::string fullPath = ((*iit) + '/' + searchString); + const std::string fullPath = ((*iit) + '/' + includeString); if (cmsys::SystemTools::FileExists(fullPath.c_str())) { - file_n = fullPath; - return true; + res = cmsys::SystemTools::GetRealPath(fullPath); + break; } } - return false; + return res; } /** diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 6c9c3a8..2242e13 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -22,6 +22,16 @@ public: bool Run(const std::string& targetDirectory, const std::string& config); private: + // - Types + + /// @brief Used to extract additional dependencies from content text + struct MocDependFilter + { + std::string key; + cmsys::RegularExpression regExp; + }; + typedef std::pair MacroFilter; + // - Configuration bool ReadAutogenInfoFile(cmMakefile* makefile, const std::string& targetDirectory, @@ -47,14 +57,19 @@ private: bool RunAutogen(); // - Content analysis - bool MocRequired(const std::string& text, + bool MocRequired(const std::string& contentText, std::string* macroName = CM_NULLPTR); + void MocFindDepends( + const std::string& absFilename, const std::string& contentText, + std::map >& mocDepends); + bool MocSkip(const std::string& absFilename) const; bool UicSkip(const std::string& absFilename) const; bool ParseSourceFile( const std::string& absFilename, std::map& mocsIncluded, + std::map >& mocDepends, std::map >& includedUis, bool relaxed); @@ -67,24 +82,32 @@ private: const std::set& uicHeaderFiles, const std::map& mocsIncluded, std::map& mocsNotIncluded, + std::map >& mocDepends, std::map >& includedUis); - void ParseContentForUic( - const std::string& fileName, const std::string& contentsString, + void UicParseContent( + const std::string& fileName, const std::string& contentText, std::map >& includedUis); - bool ParseContentForMoc(const std::string& absFilename, - const std::string& contentsString, - std::map& mocsIncluded, - bool relaxed); + bool MocParseSourceContent( + const std::string& absFilename, const std::string& contentText, + std::map& mocsIncluded, + std::map >& mocDepends, bool relaxed); + + void MocParseHeaderContent( + const std::string& absFilename, const std::string& contentText, + std::map& mocsNotIncluded, + std::map >& mocDepends); // - Moc file generation bool MocGenerateAll( const std::map& mocsIncluded, - const std::map& mocsNotIncluded); - bool MocGenerateFile(const std::string& sourceFile, - const std::string& mocFileName, - const std::string& subDirPrefix); + const std::map& mocsNotIncluded, + const std::map >& mocDepends); + bool MocGenerateFile( + const std::string& sourceFile, const std::string& mocFileName, + const std::string& subDirPrefix, + const std::map >& mocDepends); // - Uic file generation bool UicGenerateAll( @@ -102,11 +125,11 @@ private: void LogErrorNameCollision( const std::string& message, const std::multimap& collisions); - void LogBold(const std::string& message); - void LogInfo(const std::string& message); - void LogWarning(const std::string& message); - void LogError(const std::string& message); - void LogCommand(const std::vector& command); + void LogBold(const std::string& message) const; + void LogInfo(const std::string& message) const; + void LogWarning(const std::string& message) const; + void LogError(const std::string& message) const; + void LogCommand(const std::vector& command) const; // - Utility bool NameCollisionTest( @@ -123,8 +146,9 @@ private: std::string FindMocHeader(const std::string& basePath, const std::string& baseName, const std::string& subDir) const; - bool FindInIncludeDirectories(std::string& file_n, - const std::string& searchString) const; + std::string FindIncludedFile(const std::string& sourceFile, + const std::string& includeString) const; + std::string FindInIncludeDirectories(const std::string& includeString) const; // - Target names std::string OriginTargetName; @@ -155,6 +179,7 @@ private: std::vector MocIncludes; std::vector MocDefinitions; std::vector MocOptions; + std::vector MocDependFilters; // - Uic std::vector UicSkipList; std::vector UicTargetOptions; @@ -166,7 +191,6 @@ private: // - Utility cmFilePathChecksum fpathCheckSum; std::vector HeaderExtensions; - typedef std::pair MacroFilter; MacroFilter MacroFilters[2]; cmsys::RegularExpression RegExpMocInclude; cmsys::RegularExpression RegExpUicInclude; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3ec230de1f45f48a8bbb8eca49674f0e0c99dfa1 commit 3ec230de1f45f48a8bbb8eca49674f0e0c99dfa1 Author: Sebastian Holtermann AuthorDate: Thu Feb 16 23:55:59 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:12:54 2017 -0500 Autogen: Use GetRealPath in central places only diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index fcc49d4..25a0f87 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -588,7 +588,7 @@ bool cmQtAutoGenerators::RunAutogen() // Parse sources for (std::vector::const_iterator it = this->Sources.begin(); it != this->Sources.end(); ++it) { - const std::string& absFilename = *it; + const std::string& absFilename = cmsys::SystemTools::GetRealPath(*it); // Parse source file for MOC/UIC if (!this->ParseSourceFile(absFilename, mocsIncluded, uisIncluded, this->MocRelaxedMode)) { @@ -602,7 +602,7 @@ bool cmQtAutoGenerators::RunAutogen() // Parse headers for (std::vector::const_iterator it = this->Headers.begin(); it != this->Headers.end(); ++it) { - const std::string& headerName = *it; + const std::string& headerName = cmsys::SystemTools::GetRealPath(*it); if (!this->MocSkip(headerName)) { mocHeaderFiles.insert(headerName); } @@ -718,7 +718,6 @@ void cmQtAutoGenerators::ParseContentForUic( this->LogInfo(err.str()); } - const std::string realName = cmsys::SystemTools::GetRealPath(absFilename); const char* contentChars = contentsString.c_str(); if (strstr(contentChars, "ui_") != CM_NULLPTR) { while (this->RegExpUicInclude.find(contentChars)) { @@ -727,7 +726,7 @@ void cmQtAutoGenerators::ParseContentForUic( cmsys::SystemTools::GetFilenameWithoutLastExtension(currentUi); // basename should be the part of the ui filename used for // finding the correct header, so we need to remove the ui_ part - uisIncluded[realName].push_back(basename.substr(3)); + uisIncluded[absFilename].push_back(basename.substr(3)); contentChars += this->RegExpUicInclude.end(); } } @@ -747,9 +746,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( } const std::string scannedFileAbsPath = - cmsys::SystemTools::GetFilenamePath( - cmsys::SystemTools::GetRealPath(absFilename)) + - '/'; + cmsys::SystemTools::GetFilenamePath(absFilename) + '/'; const std::string scannedFileBasename = cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename); @@ -932,33 +929,27 @@ void cmQtAutoGenerators::SearchHeadersForSourceFile( { std::string basepaths[2]; { - std::string bpath = cmsys::SystemTools::GetFilenamePath( - cmsys::SystemTools::GetRealPath(absFilename)); + std::string bpath = cmsys::SystemTools::GetFilenamePath(absFilename); bpath += '/'; bpath += cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename); - // search for default header files and private header files - basepaths[0] = (bpath + "."); - basepaths[1] = (bpath + "_p."); + basepaths[0] = bpath; + basepaths[1] = bpath + "_p"; } for (const std::string* bpit = cmArrayBegin(basepaths); bpit != cmArrayEnd(basepaths); ++bpit) { - for (std::vector::const_iterator heit = - this->HeaderExtensions.begin(); - heit != this->HeaderExtensions.end(); ++heit) { - const std::string hname = (*bpit) + (*heit); - if (cmsys::SystemTools::FileExists(hname.c_str())) { - // Moc headers - if (!this->MocSkip(absFilename) && !this->MocSkip(hname)) { - mocHeaderFiles.insert(hname); - } - // Uic headers - if (!this->UicSkip(absFilename) && !this->UicSkip(hname)) { - uicHeaderFiles.insert(hname); - } - break; + std::string headerName; + if (this->FindHeader(headerName, *bpit)) { + // Moc headers + if (!this->MocSkip(absFilename) && !this->MocSkip(headerName)) { + mocHeaderFiles.insert(headerName); + } + // Uic headers + if (!this->UicSkip(absFilename) && !this->UicSkip(headerName)) { + uicHeaderFiles.insert(headerName); } + break; } } } @@ -1643,7 +1634,7 @@ std::string cmQtAutoGenerators::FindMocHeader(const std::string& basePath, } while (false); // Sanitize if (!header.empty()) { - header = cmSystemTools::CollapseFullPath(header); + header = cmsys::SystemTools::GetRealPath(header); } return header; } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=41fb64e719817ce877565e6e11198df2f7e7e63d commit 41fb64e719817ce877565e6e11198df2f7e7e63d Author: Sebastian Holtermann AuthorDate: Thu Feb 16 22:03:43 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:12:54 2017 -0500 Autogen: Search moc includes in include directories diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 0eda4bc..fcc49d4 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -773,7 +773,8 @@ bool cmQtAutoGenerators::ParseContentForMoc( cmsys::SystemTools::GetFilenameWithoutLastExtension(incString); std::string incSubDir; if (incString.find_first_of('/') != std::string::npos) { - incSubDir = cmsys::SystemTools::GetFilenamePath(incString) + '/'; + incSubDir = cmsys::SystemTools::GetFilenamePath(incString); + incSubDir += '/'; } // If the moc include is of the moc_foo.cpp style we expect @@ -785,8 +786,8 @@ bool cmQtAutoGenerators::ParseContentForMoc( // Include: moc_FOO.cxx // Remove the moc_ part const std::string incRealBasename = incBasename.substr(4); - const std::string headerToMoc = this->FindMatchingHeader( - scannedFileAbsPath, incRealBasename, incSubDir); + const std::string headerToMoc = + this->FindMocHeader(scannedFileAbsPath, incRealBasename, incSubDir); if (!headerToMoc.empty()) { mocsIncluded[headerToMoc] = incString; if (relaxed && (incRealBasename == scannedFileBasename)) { @@ -814,8 +815,8 @@ bool cmQtAutoGenerators::ParseContentForMoc( ownDotMocIncluded = true; } else { // In relaxed mode try to find a header instead but issue a warning - const std::string headerToMoc = this->FindMatchingHeader( - scannedFileAbsPath, incBasename, incSubDir); + const std::string headerToMoc = + this->FindMocHeader(scannedFileAbsPath, incBasename, incSubDir); if (!headerToMoc.empty()) { // This is for KDE4 compatibility: fileToMoc = headerToMoc; @@ -1607,9 +1608,23 @@ bool cmQtAutoGenerators::FindHeader(std::string& header, return false; } -std::string cmQtAutoGenerators::FindMatchingHeader( - const std::string& basePath, const std::string& baseName, - const std::string& subDir) const +bool cmQtAutoGenerators::FindHeaderGlobal( + std::string& header, const std::string& testBasePath) const +{ + for (std::vector::const_iterator iit = + this->MocIncludePaths.begin(); + iit != this->MocIncludePaths.end(); ++iit) { + const std::string fullPath = ((*iit) + '/' + testBasePath); + if (FindHeader(header, fullPath)) { + return true; + } + } + return false; +} + +std::string cmQtAutoGenerators::FindMocHeader(const std::string& basePath, + const std::string& baseName, + const std::string& subDir) const { std::string header; do { @@ -1621,7 +1636,15 @@ std::string cmQtAutoGenerators::FindMatchingHeader( if (this->FindHeader(header, basePath + baseName)) { break; } + // Try include directories + if (this->FindHeaderGlobal(header, subDir + baseName)) { + break; + } } while (false); + // Sanitize + if (!header.empty()) { + header = cmSystemTools::CollapseFullPath(header); + } return header; } diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index b3c7a3c..6c9c3a8 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -118,9 +118,11 @@ private: bool MakeParentDirectory(const std::string& filename); bool FindHeader(std::string& header, const std::string& testBasePath) const; - std::string FindMatchingHeader(const std::string& basePath, - const std::string& baseName, - const std::string& subDir) const; + bool FindHeaderGlobal(std::string& header, + const std::string& testBasePath) const; + std::string FindMocHeader(const std::string& basePath, + const std::string& baseName, + const std::string& subDir) const; bool FindInIncludeDirectories(std::string& file_n, const std::string& searchString) const; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=175c89004425cdbb151d4e85876e2a2076432f28 commit 175c89004425cdbb151d4e85876e2a2076432f28 Author: Sebastian Holtermann AuthorDate: Thu Feb 16 21:09:04 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:12:53 2017 -0500 Autogen: Sort includes before composing include options diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 62fbe18..0eda4bc 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -510,15 +510,44 @@ void cmQtAutoGenerators::Init(cmMakefile* makefile) // Acquire header extensions this->HeaderExtensions = makefile->GetCMakeInstance()->GetHeaderExtensions(); + // Sort include directories on demand + if (this->IncludeProjectDirsBefore) { + // Move strings to temporary list + std::list includes; + includes.insert(includes.end(), this->MocIncludePaths.begin(), + this->MocIncludePaths.end()); + this->MocIncludePaths.clear(); + this->MocIncludePaths.reserve(includes.size()); + // Append project directories only + { + const char* movePaths[2] = { this->ProjectBinaryDir.c_str(), + this->ProjectSourceDir.c_str() }; + for (const char* const* mpit = cmArrayBegin(movePaths); + mpit != cmArrayEnd(movePaths); ++mpit) { + std::list::iterator it = includes.begin(); + while (it != includes.end()) { + const std::string& path = *it; + if (cmsys::SystemTools::StringStartsWith(path, *mpit)) { + this->MocIncludePaths.push_back(path); + it = includes.erase(it); + } else { + ++it; + } + } + } + } + // Append remaining directories + this->MocIncludePaths.insert(this->MocIncludePaths.end(), includes.begin(), + includes.end()); + } // Compose moc includes list - std::list mocIncludes; { std::set frameworkPaths; for (std::vector::const_iterator it = this->MocIncludePaths.begin(); it != this->MocIncludePaths.end(); ++it) { const std::string& path = *it; - mocIncludes.push_back("-I" + path); + this->MocIncludes.push_back("-I" + path); // Extract framework path if (cmHasLiteralSuffix(path, ".framework/Headers")) { // Go up twice to get to the framework root @@ -532,40 +561,10 @@ void cmQtAutoGenerators::Init(cmMakefile* makefile) // Append framework includes for (std::set::const_iterator it = frameworkPaths.begin(); it != frameworkPaths.end(); ++it) { - mocIncludes.push_back("-F"); - mocIncludes.push_back(*it); + this->MocIncludes.push_back("-F"); + this->MocIncludes.push_back(*it); } } - if (this->IncludeProjectDirsBefore) { - // Extract project includes - std::vector mocSortedIncludes; - { - std::vector movePaths; - movePaths.push_back("-I" + this->ProjectBinaryDir); - movePaths.push_back("-I" + this->ProjectSourceDir); - - for (std::vector::const_iterator mpit = movePaths.begin(); - mpit != movePaths.end(); ++mpit) { - std::list::iterator it = mocIncludes.begin(); - while (it != mocIncludes.end()) { - const std::string& path = *it; - if (cmsys::SystemTools::StringStartsWith(path, mpit->c_str())) { - mocSortedIncludes.push_back(path); - it = mocIncludes.erase(it); - } else { - ++it; - } - } - } - } - // Place extracted includes at the begin - this->MocIncludes.insert(this->MocIncludes.end(), - mocSortedIncludes.begin(), - mocSortedIncludes.end()); - } - // Append remaining includes - this->MocIncludes.insert(this->MocIncludes.end(), mocIncludes.begin(), - mocIncludes.end()); } bool cmQtAutoGenerators::RunAutogen() https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=80a007534f6287cd2e88c1b8fd72b68fc688da4e commit 80a007534f6287cd2e88c1b8fd72b68fc688da4e Author: Sebastian Holtermann AuthorDate: Thu Feb 16 19:47:40 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:12:53 2017 -0500 Autogen: Add FindInIncludeDirectories method diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index e3d20cf..62fbe18 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -1627,6 +1627,25 @@ std::string cmQtAutoGenerators::FindMatchingHeader( } /** + * @brief Tries to find a file in the include directories + * @return True on success + */ +bool cmQtAutoGenerators::FindInIncludeDirectories( + std::string& file_n, const std::string& searchString) const +{ + for (std::vector::const_iterator iit = + this->MocIncludePaths.begin(); + iit != this->MocIncludePaths.end(); ++iit) { + const std::string fullPath = ((*iit) + '/' + searchString); + if (cmsys::SystemTools::FileExists(fullPath.c_str())) { + file_n = fullPath; + return true; + } + } + return false; +} + +/** * @brief Generates the parent directory of the given file on demand * @return True on success */ diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 895c50a..b3c7a3c 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -121,6 +121,8 @@ private: std::string FindMatchingHeader(const std::string& basePath, const std::string& baseName, const std::string& subDir) const; + bool FindInIncludeDirectories(std::string& file_n, + const std::string& searchString) const; // - Target names std::string OriginTargetName; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f379fdbb9ee17b62ac8b4a8d4b9fab562ba37253 commit f379fdbb9ee17b62ac8b4a8d4b9fab562ba37253 Author: Sebastian Holtermann AuthorDate: Thu Feb 16 17:53:19 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:12:53 2017 -0500 Autogen: Synchronize header/source argument names diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 8206f23..895c50a 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -54,19 +54,19 @@ private: bool ParseSourceFile( const std::string& absFilename, - std::map& includedMocs, + std::map& mocsIncluded, std::map >& includedUis, bool relaxed); void SearchHeadersForSourceFile(const std::string& absFilename, - std::set& absHeadersMoc, - std::set& absHeadersUic) const; + std::set& mocHeaderFiles, + std::set& uicHeaderFiles) const; void ParseHeaders( - const std::set& absHeadersMoc, - const std::set& absHeadersUic, - const std::map& includedMocs, - std::map& notIncludedMocs, + const std::set& mocHeaderFiles, + const std::set& uicHeaderFiles, + const std::map& mocsIncluded, + std::map& mocsNotIncluded, std::map >& includedUis); void ParseContentForUic( @@ -75,13 +75,13 @@ private: bool ParseContentForMoc(const std::string& absFilename, const std::string& contentsString, - std::map& includedMocs, + std::map& mocsIncluded, bool relaxed); // - Moc file generation bool MocGenerateAll( - const std::map& includedMocs, - const std::map& notIncludedMocs); + const std::map& mocsIncluded, + const std::map& mocsNotIncluded); bool MocGenerateFile(const std::string& sourceFile, const std::string& mocFileName, const std::string& subDirPrefix); https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ddf940725e8af095b1c02606aeea64cc9baaf572 commit ddf940725e8af095b1c02606aeea64cc9baaf572 Author: Sebastian Holtermann AuthorDate: Thu Feb 16 11:10:46 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:12:53 2017 -0500 Autogen: Split moc include paths on info reading diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 8bf41f8..e3d20cf 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -312,8 +312,9 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( cmSystemTools::ExpandListArgument( GetConfigDefinition(makefile, "AM_MOC_COMPILE_DEFINITIONS", config), this->MocDefinitions); - this->MocInfoIncludes = - GetConfigDefinition(makefile, "AM_MOC_INCLUDES", config); + cmSystemTools::ExpandListArgument( + GetConfigDefinition(makefile, "AM_MOC_INCLUDES", config), + this->MocIncludePaths); cmSystemTools::ExpandListArgument( makefile->GetSafeDefinition("AM_MOC_OPTIONS"), this->MocOptions); @@ -411,7 +412,7 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile, std::string& str = this->SettingsStringMoc; str += JoinOptionsList(this->MocDefinitions); str += " ~~~ "; - str += this->MocInfoIncludes; + str += JoinOptionsList(this->MocIncludePaths); str += " ~~~ "; str += JoinOptionsList(this->MocOptions); str += " ~~~ "; @@ -513,22 +514,19 @@ void cmQtAutoGenerators::Init(cmMakefile* makefile) std::list mocIncludes; { std::set frameworkPaths; - { - std::vector incPaths; - cmSystemTools::ExpandListArgument(this->MocInfoIncludes, incPaths); - for (std::vector::const_iterator it = incPaths.begin(); - it != incPaths.end(); ++it) { - const std::string& path = *it; - mocIncludes.push_back("-I" + path); - // Extract framework path - if (cmHasLiteralSuffix(path, ".framework/Headers")) { - // Go up twice to get to the framework root - std::vector pathComponents; - cmsys::SystemTools::SplitPath(path, pathComponents); - std::string frameworkPath = cmsys::SystemTools::JoinPath( - pathComponents.begin(), pathComponents.end() - 2); - frameworkPaths.insert(frameworkPath); - } + for (std::vector::const_iterator it = + this->MocIncludePaths.begin(); + it != this->MocIncludePaths.end(); ++it) { + const std::string& path = *it; + mocIncludes.push_back("-I" + path); + // Extract framework path + if (cmHasLiteralSuffix(path, ".framework/Headers")) { + // Go up twice to get to the framework root + std::vector pathComponents; + cmsys::SystemTools::SplitPath(path, pathComponents); + std::string frameworkPath = cmsys::SystemTools::JoinPath( + pathComponents.begin(), pathComponents.end() - 2); + frameworkPaths.insert(frameworkPath); } } // Append framework includes diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 2842660..8206f23 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -144,10 +144,10 @@ private: std::string SettingsStringUic; std::string SettingsStringRcc; // - Moc - std::string MocInfoIncludes; std::string MocCppFilenameRel; std::string MocCppFilenameAbs; std::vector MocSkipList; + std::vector MocIncludePaths; std::vector MocIncludes; std::vector MocDefinitions; std::vector MocOptions; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=71c5ae253cb5498da319e36bcf49869509b6603c commit 71c5ae253cb5498da319e36bcf49869509b6603c Author: Sebastian Holtermann AuthorDate: Thu Feb 16 10:31:03 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:12:52 2017 -0500 Autogen: Loop based macro detection instead of code duplication diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 4e4ab30..8bf41f8 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -214,9 +214,12 @@ cmQtAutoGenerators::cmQtAutoGenerators() } } + this->MacroFilters[0].first = "Q_OBJECT"; + this->MacroFilters[0].second.compile("[\n][ \t]*Q_OBJECT[^a-zA-Z0-9_]"); + this->MacroFilters[1].first = "Q_GADGET"; + this->MacroFilters[1].second.compile("[\n][ \t]*Q_GADGET[^a-zA-Z0-9_]"); + // Precompile regular expressions - this->RegExpQObject.compile("[\n][ \t]*Q_OBJECT[^a-zA-Z0-9_]"); - this->RegExpQGadget.compile("[\n][ \t]*Q_GADGET[^a-zA-Z0-9_]"); this->RegExpMocInclude.compile( "[\n][ \t]*#[ \t]*include[ \t]+" "[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]"); @@ -632,19 +635,19 @@ bool cmQtAutoGenerators::RunAutogen() * @return True if moc is required */ bool cmQtAutoGenerators::MocRequired(const std::string& text, - std::string& macroName) + std::string* macroName) { - // Run a simple check before an expensive regular expression check - if (strstr(text.c_str(), "Q_OBJECT") != CM_NULLPTR) { - if (this->RegExpQObject.find(text)) { - macroName = "Q_OBJECT"; - return true; - } - } - if (strstr(text.c_str(), "Q_GADGET") != CM_NULLPTR) { - if (this->RegExpQGadget.find(text)) { - macroName = "Q_GADGET"; - return true; + for (unsigned int ii = 0; ii != cmArraySize(this->MacroFilters); ++ii) { + MacroFilter& macroFilter = this->MacroFilters[ii]; + // Run a simple check before an expensive regular expression check + if (text.find(macroFilter.first) != std::string::npos) { + if (macroFilter.second.find(text)) { + // Return macro name on demand + if (macroName != CM_NULLPTR) { + *macroName = macroFilter.first; + } + return true; + } } } return false; @@ -754,7 +757,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename); std::string macroName; - const bool requiresMoc = this->MocRequired(contentsString, macroName); + const bool requiresMoc = this->MocRequired(contentsString, ¯oName); bool ownDotMocIncluded = false; bool ownMocUnderscoreIncluded = false; std::string ownMocUnderscoreFile; @@ -988,8 +991,7 @@ void cmQtAutoGenerators::ParseHeaders( err << "AutoMoc: Checking " << headerName << "\n"; this->LogInfo(err.str()); } - std::string macroName; - if (this->MocRequired(contents, macroName)) { + if (this->MocRequired(contents)) { mocsNotIncluded[headerName] = this->ChecksumedPath(headerName, "moc_", ".cpp"); } diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index e6f9160..2842660 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -10,6 +10,7 @@ #include #include #include +#include #include class cmMakefile; @@ -46,7 +47,8 @@ private: bool RunAutogen(); // - Content analysis - bool MocRequired(const std::string& text, std::string& macroName); + bool MocRequired(const std::string& text, + std::string* macroName = CM_NULLPTR); bool MocSkip(const std::string& absFilename) const; bool UicSkip(const std::string& absFilename) const; @@ -160,8 +162,8 @@ private: // - Utility cmFilePathChecksum fpathCheckSum; std::vector HeaderExtensions; - cmsys::RegularExpression RegExpQObject; - cmsys::RegularExpression RegExpQGadget; + typedef std::pair MacroFilter; + MacroFilter MacroFilters[2]; cmsys::RegularExpression RegExpMocInclude; cmsys::RegularExpression RegExpUicInclude; // - Flags https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=5308f954c9ad13cfc6cc84f1f1255fb5faff48c6 commit 5308f954c9ad13cfc6cc84f1f1255fb5faff48c6 Author: Sebastian Holtermann AuthorDate: Wed Feb 15 20:47:58 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:12:52 2017 -0500 Autogen: Issue a warning if moc isn't required in strict mode diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 859b2de..4e4ab30 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -857,6 +857,15 @@ bool cmQtAutoGenerators::ParseContentForMoc( // Include self fileToMoc = absFilename; ownDotMocIncluded = true; + // Accept but issue a warning if moc isn't required + if (!requiresMoc) { + std::ostringstream err; + err << "AutoMoc: Error: " << absFilename << "\n" + << "The file includes the moc file \"" << incString << "\"" + << ", but does not contain a Q_OBJECT or Q_GADGET " + "macro.\n"; + this->LogWarning(err.str()); + } } else { // Don't allow FOO.moc include other than self in strict mode std::ostringstream err; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=887e40034161589b63fdb14bfaee7f66374b9b83 commit 887e40034161589b63fdb14bfaee7f66374b9b83 Author: Sebastian Holtermann AuthorDate: Wed Feb 15 20:36:39 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:12:51 2017 -0500 Autogen: Error message tweaks diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index e84b04d..859b2de 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -808,7 +808,12 @@ bool cmQtAutoGenerators::ParseContentForMoc( std::string fileToMoc; if (relaxed) { // Mode: Relaxed - if (!requiresMoc || (incBasename != scannedFileBasename)) { + if (requiresMoc && (incBasename == scannedFileBasename)) { + // Include self + fileToMoc = absFilename; + ownDotMocIncluded = true; + } else { + // In relaxed mode try to find a header instead but issue a warning const std::string headerToMoc = this->FindMatchingHeader( scannedFileAbsPath, incBasename, incSubDir); if (!headerToMoc.empty()) { @@ -817,11 +822,10 @@ bool cmQtAutoGenerators::ParseContentForMoc( if (!requiresMoc && (incBasename == scannedFileBasename)) { std::ostringstream err; err << "AutoMoc: Warning: " << absFilename << "\n" - << "The file includes the moc file \"" << incString - << "\", but does not contain a " << macroName - << " macro. Running moc on " - << "\"" << headerToMoc << "\" ! Include \"moc_" - << incBasename + << "The file includes the moc file \"" << incString << "\"" + << ", but does not contain a Q_OBJECT or Q_GADGET macro.\n" + << "Running moc on \"" << headerToMoc << "\"!\n" + << "Include \"moc_" << incBasename << ".cpp\" for a compatibility with " "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; this->LogWarning(err.str()); @@ -829,10 +833,9 @@ bool cmQtAutoGenerators::ParseContentForMoc( std::ostringstream err; err << "AutoMoc: Warning: " << absFilename << "\n" << "The file includes the moc file \"" << incString - << "\" instead of \"moc_" << incBasename - << ".cpp\". Running moc on " - << "\"" << headerToMoc << "\" ! Include \"moc_" - << incBasename + << "\" instead of \"moc_" << incBasename << ".cpp\".\n" + << "Running moc on \"" << headerToMoc << "\"!\n" + << "Include \"moc_" << incBasename << ".cpp\" for compatibility with " "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; this->LogWarning(err.str()); @@ -847,10 +850,6 @@ bool cmQtAutoGenerators::ParseContentForMoc( this->LogError(err.str()); return false; } - } else { - // Include self - fileToMoc = absFilename; - ownDotMocIncluded = true; } } else { // Mode: Strict @@ -892,9 +891,9 @@ bool cmQtAutoGenerators::ParseContentForMoc( << "The file contains a " << macroName << " macro, but does not include " << "\"" << scannedFileBasename << ".moc\", but instead includes " - << "\"" << ownMocUnderscoreFile << "\". Running moc on " - << "\"" << absFilename << "\" ! Better include \"" - << scannedFileBasename + << "\"" << ownMocUnderscoreFile << "\".\n" + << "Running moc on \"" << absFilename << "\"!\n" + << "Better include \"" << scannedFileBasename << ".moc\" for compatibility with " "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; this->LogWarning(err.str()); @@ -908,7 +907,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( err << "AutoMoc: Error: " << absFilename << "\n" << "The file contains a " << macroName << " macro, but does not include " - << "\"" << scannedFileBasename << ".moc\" !\n"; + << "\"" << scannedFileBasename << ".moc\"!\n"; this->LogError(err.str()); return false; } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4c60099fea2b06229900cc16fed907185c4fe2ef commit 4c60099fea2b06229900cc16fed907185c4fe2ef Author: Sebastian Holtermann AuthorDate: Wed Feb 15 19:30:08 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:12:51 2017 -0500 Autogen: Acquire and store header extensions in Init() diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 97d1299..e84b04d 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -246,9 +246,9 @@ bool cmQtAutoGenerators::Run(const std::string& targetDirectory, // Read old settings this->SettingsFileRead(mf.get(), targetDirectory); // Init and run - this->Init(); + this->Init(mf.get()); if (this->QtMajorVersion == "4" || this->QtMajorVersion == "5") { - if (!this->RunAutogen(mf.get())) { + if (!this->RunAutogen()) { return false; } } @@ -488,7 +488,7 @@ bool cmQtAutoGenerators::SettingsFileWrite(const std::string& targetDirectory) return success; } -void cmQtAutoGenerators::Init() +void cmQtAutoGenerators::Init(cmMakefile* makefile) { this->AutogenBuildSubDir = this->AutogenTargetName; this->AutogenBuildSubDir += "/"; @@ -503,6 +503,9 @@ void cmQtAutoGenerators::Init() this->ProjectSourceDir, this->ProjectBinaryDir); + // Acquire header extensions + this->HeaderExtensions = makefile->GetCMakeInstance()->GetHeaderExtensions(); + // Compose moc includes list std::list mocIncludes; { @@ -564,7 +567,7 @@ void cmQtAutoGenerators::Init() mocIncludes.end()); } -bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) +bool cmQtAutoGenerators::RunAutogen() { // the program goes through all .cpp files to see which moc files are // included. It is not really interesting how the moc file is named, but @@ -583,22 +586,17 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) std::set uicHeaderFiles; // Parse sources - { - const std::vector& headerExtensions = - makefile->GetCMakeInstance()->GetHeaderExtensions(); - - for (std::vector::const_iterator it = this->Sources.begin(); - it != this->Sources.end(); ++it) { - const std::string& absFilename = *it; - // Parse source file for MOC/UIC - if (!this->ParseSourceFile(absFilename, headerExtensions, mocsIncluded, - uisIncluded, this->MocRelaxedMode)) { - return false; - } - // Find additional headers - this->SearchHeadersForSourceFile(absFilename, headerExtensions, - mocHeaderFiles, uicHeaderFiles); + for (std::vector::const_iterator it = this->Sources.begin(); + it != this->Sources.end(); ++it) { + const std::string& absFilename = *it; + // Parse source file for MOC/UIC + if (!this->ParseSourceFile(absFilename, mocsIncluded, uisIncluded, + this->MocRelaxedMode)) { + return false; } + // Find additional headers + this->SearchHeadersForSourceFile(absFilename, mocHeaderFiles, + uicHeaderFiles); } // Parse headers @@ -656,7 +654,7 @@ bool cmQtAutoGenerators::MocRequired(const std::string& text, * @brief Tests if the file should be ignored for moc scanning * @return True if the file should be ignored */ -bool cmQtAutoGenerators::MocSkip(const std::string& absFilename) +bool cmQtAutoGenerators::MocSkip(const std::string& absFilename) const { if (this->MocEnabled()) { // Test if the file name is on the skip list @@ -670,7 +668,7 @@ bool cmQtAutoGenerators::MocSkip(const std::string& absFilename) /** * @brief Tests if the file name is in the skip list */ -bool cmQtAutoGenerators::UicSkip(const std::string& absFilename) +bool cmQtAutoGenerators::UicSkip(const std::string& absFilename) const { if (this->UicEnabled()) { // Test if the file name is on the skip list @@ -686,7 +684,6 @@ bool cmQtAutoGenerators::UicSkip(const std::string& absFilename) */ bool cmQtAutoGenerators::ParseSourceFile( const std::string& absFilename, - const std::vector& headerExtensions, std::map& mocsIncluded, std::map >& uisIncluded, bool relaxed) { @@ -700,8 +697,8 @@ bool cmQtAutoGenerators::ParseSourceFile( } else { // Parse source contents for MOC if (success && !this->MocSkip(absFilename)) { - success = this->ParseContentForMoc( - absFilename, contentsString, headerExtensions, mocsIncluded, relaxed); + success = this->ParseContentForMoc(absFilename, contentsString, + mocsIncluded, relaxed); } // Parse source contents for UIC if (success && !this->UicSkip(absFilename)) { @@ -741,7 +738,6 @@ void cmQtAutoGenerators::ParseContentForUic( */ bool cmQtAutoGenerators::ParseContentForMoc( const std::string& absFilename, const std::string& contentsString, - const std::vector& headerExtensions, std::map& mocsIncluded, bool relaxed) { if (this->Verbose) { @@ -789,8 +785,8 @@ bool cmQtAutoGenerators::ParseContentForMoc( // Include: moc_FOO.cxx // Remove the moc_ part const std::string incRealBasename = incBasename.substr(4); - const std::string headerToMoc = FindMatchingHeader( - scannedFileAbsPath, incRealBasename, incSubDir, headerExtensions); + const std::string headerToMoc = this->FindMatchingHeader( + scannedFileAbsPath, incRealBasename, incSubDir); if (!headerToMoc.empty()) { mocsIncluded[headerToMoc] = incString; if (relaxed && (incRealBasename == scannedFileBasename)) { @@ -803,7 +799,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( err << "AutoMoc: Error: " << absFilename << "\n" << "The file includes the moc file \"" << incString << "\", but could not find header \"" << incRealBasename << '{' - << JoinExts(headerExtensions) << "}\"\n"; + << JoinExts(this->HeaderExtensions) << "}\"\n"; this->LogError(err.str()); return false; } @@ -813,8 +809,8 @@ bool cmQtAutoGenerators::ParseContentForMoc( if (relaxed) { // Mode: Relaxed if (!requiresMoc || (incBasename != scannedFileBasename)) { - const std::string headerToMoc = FindMatchingHeader( - scannedFileAbsPath, incBasename, incSubDir, headerExtensions); + const std::string headerToMoc = this->FindMatchingHeader( + scannedFileAbsPath, incBasename, incSubDir); if (!headerToMoc.empty()) { // This is for KDE4 compatibility: fileToMoc = headerToMoc; @@ -922,9 +918,8 @@ bool cmQtAutoGenerators::ParseContentForMoc( } void cmQtAutoGenerators::SearchHeadersForSourceFile( - const std::string& absFilename, - const std::vector& headerExtensions, - std::set& mocHeaderFiles, std::set& uicHeaderFiles) + const std::string& absFilename, std::set& mocHeaderFiles, + std::set& uicHeaderFiles) const { std::string basepaths[2]; { @@ -941,8 +936,8 @@ void cmQtAutoGenerators::SearchHeadersForSourceFile( for (const std::string* bpit = cmArrayBegin(basepaths); bpit != cmArrayEnd(basepaths); ++bpit) { for (std::vector::const_iterator heit = - headerExtensions.begin(); - heit != headerExtensions.end(); ++heit) { + this->HeaderExtensions.begin(); + heit != this->HeaderExtensions.end(); ++heit) { const std::string hname = (*bpit) + (*heit); if (cmsys::SystemTools::FileExists(hname.c_str())) { // Moc headers @@ -1588,12 +1583,12 @@ std::string cmQtAutoGenerators::ChecksumedPath(const std::string& sourceFile, * appending different header extensions * @return True on success */ -bool cmQtAutoGenerators::FindHeader( - std::string& header, const std::string& testBasePath, - const std::vector& headerExtensions) const +bool cmQtAutoGenerators::FindHeader(std::string& header, + const std::string& testBasePath) const { - for (std::vector::const_iterator ext = headerExtensions.begin(); - ext != headerExtensions.end(); ++ext) { + for (std::vector::const_iterator ext = + this->HeaderExtensions.begin(); + ext != this->HeaderExtensions.end(); ++ext) { std::string testFilePath(testBasePath); testFilePath += '.'; testFilePath += (*ext); @@ -1607,17 +1602,16 @@ bool cmQtAutoGenerators::FindHeader( std::string cmQtAutoGenerators::FindMatchingHeader( const std::string& basePath, const std::string& baseName, - const std::string& subDir, - const std::vector& headerExtensions) const + const std::string& subDir) const { std::string header; do { if (!subDir.empty()) { - if (FindHeader(header, basePath + subDir + baseName, headerExtensions)) { + if (this->FindHeader(header, basePath + subDir + baseName)) { break; } } - if (FindHeader(header, basePath + baseName, headerExtensions)) { + if (this->FindHeader(header, basePath + baseName)) { break; } } while (false); diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index 50df9f8..e6f9160 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -42,26 +42,23 @@ private: } // - Init and run - void Init(); - bool RunAutogen(cmMakefile* makefile); + void Init(cmMakefile* makefile); + bool RunAutogen(); // - Content analysis bool MocRequired(const std::string& text, std::string& macroName); - bool MocSkip(const std::string& absFilename); - bool UicSkip(const std::string& absFilename); + bool MocSkip(const std::string& absFilename) const; + bool UicSkip(const std::string& absFilename) const; bool ParseSourceFile( const std::string& absFilename, - const std::vector& headerExtensions, std::map& includedMocs, std::map >& includedUis, bool relaxed); - void SearchHeadersForSourceFile( - const std::string& absFilename, - const std::vector& headerExtensions, - std::set& absHeadersMoc, - std::set& absHeadersUic); + void SearchHeadersForSourceFile(const std::string& absFilename, + std::set& absHeadersMoc, + std::set& absHeadersUic) const; void ParseHeaders( const std::set& absHeadersMoc, @@ -76,7 +73,6 @@ private: bool ParseContentForMoc(const std::string& absFilename, const std::string& contentsString, - const std::vector& headerExtensions, std::map& includedMocs, bool relaxed); @@ -119,12 +115,10 @@ private: const char* baseSuffix) const; bool MakeParentDirectory(const std::string& filename); - bool FindHeader(std::string& header, const std::string& testBasePath, - const std::vector& headerExtensions) const; - std::string FindMatchingHeader( - const std::string& basePath, const std::string& baseName, - const std::string& subDir, - const std::vector& headerExtensions) const; + bool FindHeader(std::string& header, const std::string& testBasePath) const; + std::string FindMatchingHeader(const std::string& basePath, + const std::string& baseName, + const std::string& subDir) const; // - Target names std::string OriginTargetName; @@ -165,6 +159,7 @@ private: std::map > RccInputs; // - Utility cmFilePathChecksum fpathCheckSum; + std::vector HeaderExtensions; cmsys::RegularExpression RegExpQObject; cmsys::RegularExpression RegExpQGadget; cmsys::RegularExpression RegExpMocInclude; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=815a05cf12499b42acea70b5a9534e10e1701417 commit 815a05cf12499b42acea70b5a9534e10e1701417 Author: Sebastian Holtermann AuthorDate: Wed Feb 15 19:19:37 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:12:51 2017 -0500 Autogen: Overhaul FindMatchingHeader function diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 580265b..97d1299 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -74,42 +74,6 @@ static void SettingWrite(std::ostream& ostr, const char* key, } } -static std::string FindMatchingHeader( - const std::string& absPath, const std::string& mocSubDir, - const std::string& basename, - const std::vector& headerExtensions) -{ - std::string header; - for (std::vector::const_iterator ext = headerExtensions.begin(); - ext != headerExtensions.end(); ++ext) { - std::string sourceFilePath = absPath + basename + "." + (*ext); - if (cmsys::SystemTools::FileExists(sourceFilePath.c_str())) { - header = sourceFilePath; - break; - } - // Try subdirectory instead - if (!mocSubDir.empty()) { - sourceFilePath = mocSubDir + basename + "." + (*ext); - if (cmsys::SystemTools::FileExists(sourceFilePath.c_str())) { - header = sourceFilePath; - break; - } - } - } - - return header; -} - -static std::string ExtractSubDir(const std::string& absPath, - const std::string& currentMoc) -{ - std::string subDir; - if (currentMoc.find_first_of('/') != std::string::npos) { - subDir = absPath + cmsys::SystemTools::GetFilenamePath(currentMoc) + '/'; - } - return subDir; -} - static bool FileNameIsUnique(const std::string& filePath, const std::map& fileMap) { @@ -807,38 +771,38 @@ bool cmQtAutoGenerators::ParseContentForMoc( if (strstr(contentChars, "moc") != CM_NULLPTR) { // Iterate over all included moc files while (this->RegExpMocInclude.find(contentChars)) { - const std::string currentMoc = this->RegExpMocInclude.match(1); - // Basename of the current moc include - std::string basename = - cmsys::SystemTools::GetFilenameWithoutLastExtension(currentMoc); + const std::string incString = this->RegExpMocInclude.match(1); + // Basename of the moc include + const std::string incBasename = + cmsys::SystemTools::GetFilenameWithoutLastExtension(incString); + std::string incSubDir; + if (incString.find_first_of('/') != std::string::npos) { + incSubDir = cmsys::SystemTools::GetFilenamePath(incString) + '/'; + } // If the moc include is of the moc_foo.cpp style we expect // the Q_OBJECT class declaration in a header file. // If the moc include is of the foo.moc style we need to look for // a Q_OBJECT macro in the current source file, if it contains the // macro we generate the moc file from the source file. - if (cmHasLiteralPrefix(basename, "moc_")) { + if (cmHasLiteralPrefix(incBasename, "moc_")) { // Include: moc_FOO.cxx - // basename should be the part of the moc filename used for - // finding the correct header, so we need to remove the moc_ part - basename = basename.substr(4); - const std::string mocSubDir = - ExtractSubDir(scannedFileAbsPath, currentMoc); + // Remove the moc_ part + const std::string incRealBasename = incBasename.substr(4); const std::string headerToMoc = FindMatchingHeader( - scannedFileAbsPath, mocSubDir, basename, headerExtensions); - + scannedFileAbsPath, incRealBasename, incSubDir, headerExtensions); if (!headerToMoc.empty()) { - mocsIncluded[headerToMoc] = currentMoc; - if (relaxed && (basename == scannedFileBasename)) { + mocsIncluded[headerToMoc] = incString; + if (relaxed && (incRealBasename == scannedFileBasename)) { ownMocUnderscoreIncluded = true; - ownMocUnderscoreFile = currentMoc; + ownMocUnderscoreFile = incString; ownMocHeaderFile = headerToMoc; } } else { std::ostringstream err; err << "AutoMoc: Error: " << absFilename << "\n" - << "The file includes the moc file \"" << currentMoc - << "\", but could not find header \"" << basename << '{' + << "The file includes the moc file \"" << incString + << "\", but could not find header \"" << incRealBasename << '{' << JoinExts(headerExtensions) << "}\"\n"; this->LogError(err.str()); return false; @@ -848,31 +812,31 @@ bool cmQtAutoGenerators::ParseContentForMoc( std::string fileToMoc; if (relaxed) { // Mode: Relaxed - if (!requiresMoc || basename != scannedFileBasename) { - const std::string mocSubDir = - ExtractSubDir(scannedFileAbsPath, currentMoc); + if (!requiresMoc || (incBasename != scannedFileBasename)) { const std::string headerToMoc = FindMatchingHeader( - scannedFileAbsPath, mocSubDir, basename, headerExtensions); + scannedFileAbsPath, incBasename, incSubDir, headerExtensions); if (!headerToMoc.empty()) { // This is for KDE4 compatibility: fileToMoc = headerToMoc; - if (!requiresMoc && basename == scannedFileBasename) { + if (!requiresMoc && (incBasename == scannedFileBasename)) { std::ostringstream err; err << "AutoMoc: Warning: " << absFilename << "\n" - << "The file includes the moc file \"" << currentMoc + << "The file includes the moc file \"" << incString << "\", but does not contain a " << macroName << " macro. Running moc on " - << "\"" << headerToMoc << "\" ! Include \"moc_" << basename + << "\"" << headerToMoc << "\" ! Include \"moc_" + << incBasename << ".cpp\" for a compatibility with " "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; this->LogWarning(err.str()); } else { std::ostringstream err; err << "AutoMoc: Warning: " << absFilename << "\n" - << "The file includes the moc file \"" << currentMoc - << "\" instead of \"moc_" << basename + << "The file includes the moc file \"" << incString + << "\" instead of \"moc_" << incBasename << ".cpp\". Running moc on " - << "\"" << headerToMoc << "\" ! Include \"moc_" << basename + << "\"" << headerToMoc << "\" ! Include \"moc_" + << incBasename << ".cpp\" for compatibility with " "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; this->LogWarning(err.str()); @@ -880,7 +844,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( } else { std::ostringstream err; err << "AutoMoc: Error: " << absFilename << "\n" - << "The file includes the moc file \"" << currentMoc + << "The file includes the moc file \"" << incString << "\", which seems to be the moc file from a different " "source file. CMake also could not find a matching " "header.\n"; @@ -894,7 +858,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( } } else { // Mode: Strict - if (basename == scannedFileBasename) { + if (incBasename == scannedFileBasename) { // Include self fileToMoc = absFilename; ownDotMocIncluded = true; @@ -902,7 +866,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( // Don't allow FOO.moc include other than self in strict mode std::ostringstream err; err << "AutoMoc: Error: " << absFilename << "\n" - << "The file includes the moc file \"" << currentMoc + << "The file includes the moc file \"" << incString << "\", which seems to be the moc file from a different " "source file. This is not supported. Include \"" << scannedFileBasename @@ -912,7 +876,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( } } if (!fileToMoc.empty()) { - mocsIncluded[fileToMoc] = currentMoc; + mocsIncluded[fileToMoc] = incString; } } // Forward content pointer @@ -920,11 +884,11 @@ bool cmQtAutoGenerators::ParseContentForMoc( } } - // In this case, check whether the scanned file itself contains a Q_OBJECT. - // If this is the case, the moc_foo.cpp should probably be generated from - // foo.cpp instead of foo.h, because otherwise it won't build. - // But warn, since this is not how it is supposed to be used. if (requiresMoc && !ownDotMocIncluded) { + // In this case, check whether the scanned file itself contains a Q_OBJECT. + // If this is the case, the moc_foo.cpp should probably be generated from + // foo.cpp instead of foo.h, because otherwise it won't build. + // But warn, since this is not how it is supposed to be used. if (relaxed && ownMocUnderscoreIncluded) { // This is for KDE4 compatibility: std::ostringstream err; @@ -1620,6 +1584,47 @@ std::string cmQtAutoGenerators::ChecksumedPath(const std::string& sourceFile, } /** + * @brief Tries to find the header file to the given file base path by + * appending different header extensions + * @return True on success + */ +bool cmQtAutoGenerators::FindHeader( + std::string& header, const std::string& testBasePath, + const std::vector& headerExtensions) const +{ + for (std::vector::const_iterator ext = headerExtensions.begin(); + ext != headerExtensions.end(); ++ext) { + std::string testFilePath(testBasePath); + testFilePath += '.'; + testFilePath += (*ext); + if (cmsys::SystemTools::FileExists(testFilePath.c_str())) { + header = testFilePath; + return true; + } + } + return false; +} + +std::string cmQtAutoGenerators::FindMatchingHeader( + const std::string& basePath, const std::string& baseName, + const std::string& subDir, + const std::vector& headerExtensions) const +{ + std::string header; + do { + if (!subDir.empty()) { + if (FindHeader(header, basePath + subDir + baseName, headerExtensions)) { + break; + } + } + if (FindHeader(header, basePath + baseName, headerExtensions)) { + break; + } + } while (false); + return header; +} + +/** * @brief Generates the parent directory of the given file on demand * @return True on success */ diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index a466b77..50df9f8 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -119,6 +119,13 @@ private: const char* baseSuffix) const; bool MakeParentDirectory(const std::string& filename); + bool FindHeader(std::string& header, const std::string& testBasePath, + const std::vector& headerExtensions) const; + std::string FindMatchingHeader( + const std::string& basePath, const std::string& baseName, + const std::string& subDir, + const std::vector& headerExtensions) const; + // - Target names std::string OriginTargetName; std::string AutogenTargetName; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3270091210c0cfdddb133209b232a1d0a1fa48da commit 3270091210c0cfdddb133209b232a1d0a1fa48da Author: Sebastian Holtermann AuthorDate: Wed Feb 15 17:36:58 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:12:50 2017 -0500 Autogen: Don't list all search paths in error message diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index ddf8bf1..580265b 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -839,13 +839,7 @@ bool cmQtAutoGenerators::ParseContentForMoc( err << "AutoMoc: Error: " << absFilename << "\n" << "The file includes the moc file \"" << currentMoc << "\", but could not find header \"" << basename << '{' - << JoinExts(headerExtensions) << "}\" "; - if (mocSubDir.empty()) { - err << "in " << scannedFileAbsPath << "\n"; - } else { - err << "neither in " << scannedFileAbsPath << " nor in " - << mocSubDir << "\n"; - } + << JoinExts(headerExtensions) << "}\"\n"; this->LogError(err.str()); return false; } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=793c9a7925dfa3aaa2b15212f4ba0246d1fbf83c commit 793c9a7925dfa3aaa2b15212f4ba0246d1fbf83c Author: Sebastian Holtermann AuthorDate: Wed Feb 15 13:43:19 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:12:50 2017 -0500 Autogen: Indentation fix diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index ee3dc10..ddf8bf1 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -608,8 +608,7 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) // may not be included in the moc_compilation.cpp file anymore. OTOH if // there's a header containing Q_OBJECT where no corresponding moc file // is included anywhere a moc_.cpp file is created and included - // in - // the moc_compilation.cpp file. + // in the moc_compilation.cpp file. // key = moc source filepath, value = moc output filepath std::map mocsIncluded; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=25dbfbc2a937379ca78328dfabdf54043340dbd3 commit 25dbfbc2a937379ca78328dfabdf54043340dbd3 Author: Sebastian Holtermann AuthorDate: Wed Feb 15 13:23:27 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:12:50 2017 -0500 Autogen: Rename moc related variables diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index f67543f..ee3dc10 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -529,11 +529,10 @@ void cmQtAutoGenerators::Init() this->AutogenBuildSubDir = this->AutogenTargetName; this->AutogenBuildSubDir += "/"; - this->OutMocCppFilenameRel = this->AutogenBuildSubDir; - this->OutMocCppFilenameRel += "moc_compilation.cpp"; + this->MocCppFilenameRel = this->AutogenBuildSubDir; + this->MocCppFilenameRel += "moc_compilation.cpp"; - this->OutMocCppFilenameAbs = - this->CurrentBinaryDir + this->OutMocCppFilenameRel; + this->MocCppFilenameAbs = this->CurrentBinaryDir + this->MocCppFilenameRel; // Init file path checksum generator fpathCheckSum.setupParentDirs(this->CurrentSourceDir, this->CurrentBinaryDir, @@ -1125,12 +1124,12 @@ bool cmQtAutoGenerators::MocGenerateAll( // Check if we even need to update moc_compilation.cpp if (!automocCppChanged) { // compare contents of the moc_compilation.cpp file - const std::string oldContents = ReadAll(this->OutMocCppFilenameAbs); + const std::string oldContents = ReadAll(this->MocCppFilenameAbs); if (oldContents == automocSource) { // nothing changed: don't touch the moc_compilation.cpp file if (this->Verbose) { std::ostringstream err; - err << "AutoMoc: " << this->OutMocCppFilenameRel << " still up to date" + err << "AutoMoc: " << this->MocCppFilenameRel << " still up to date" << std::endl; this->LogInfo(err.str()); } @@ -1139,17 +1138,17 @@ bool cmQtAutoGenerators::MocGenerateAll( } // Actually write moc_compilation.cpp - this->LogBold("Generating MOC compilation " + this->OutMocCppFilenameRel); + this->LogBold("Generating MOC compilation " + this->MocCppFilenameRel); // Make sure the parent directory exists - bool success = this->MakeParentDirectory(this->OutMocCppFilenameAbs); + bool success = this->MakeParentDirectory(this->MocCppFilenameAbs); if (success) { cmsys::ofstream outfile; - outfile.open(this->OutMocCppFilenameAbs.c_str(), std::ios::trunc); + outfile.open(this->MocCppFilenameAbs.c_str(), std::ios::trunc); if (!outfile) { success = false; std::ostringstream err; - err << "AutoMoc: error opening " << this->OutMocCppFilenameAbs << "\n"; + err << "AutoMoc: error opening " << this->MocCppFilenameAbs << "\n"; this->LogError(err.str()); } else { outfile << automocSource; @@ -1157,7 +1156,7 @@ bool cmQtAutoGenerators::MocGenerateAll( if (!outfile.good()) { success = false; std::ostringstream err; - err << "AutoMoc: error writing " << this->OutMocCppFilenameAbs << "\n"; + err << "AutoMoc: error writing " << this->MocCppFilenameAbs << "\n"; this->LogError(err.str()); } } diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index f6caed9..a466b77 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -141,10 +141,10 @@ private: std::string SettingsStringUic; std::string SettingsStringRcc; // - Moc - std::vector MocSkipList; std::string MocInfoIncludes; - std::string OutMocCppFilenameRel; - std::string OutMocCppFilenameAbs; + std::string MocCppFilenameRel; + std::string MocCppFilenameAbs; + std::vector MocSkipList; std::vector MocIncludes; std::vector MocDefinitions; std::vector MocOptions; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3cc42863a43cd4256efdeb2eda2d235d5533bad9 commit 3cc42863a43cd4256efdeb2eda2d235d5533bad9 Author: Sebastian Holtermann AuthorDate: Wed Feb 15 12:53:39 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:12:49 2017 -0500 Autogen: Overhaul moc include list generation diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index a167705..f67543f 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -539,58 +540,65 @@ void cmQtAutoGenerators::Init() this->ProjectSourceDir, this->ProjectBinaryDir); - std::vector incPaths; - cmSystemTools::ExpandListArgument(this->MocInfoIncludes, incPaths); - - std::set frameworkPaths; - for (std::vector::const_iterator it = incPaths.begin(); - it != incPaths.end(); ++it) { - const std::string& path = *it; - this->MocIncludes.push_back("-I" + path); - if (cmHasLiteralSuffix(path, ".framework/Headers")) { - // Go up twice to get to the framework root - std::vector pathComponents; - cmsys::SystemTools::SplitPath(path, pathComponents); - std::string frameworkPath = cmsys::SystemTools::JoinPath( - pathComponents.begin(), pathComponents.end() - 2); - frameworkPaths.insert(frameworkPath); + // Compose moc includes list + std::list mocIncludes; + { + std::set frameworkPaths; + { + std::vector incPaths; + cmSystemTools::ExpandListArgument(this->MocInfoIncludes, incPaths); + for (std::vector::const_iterator it = incPaths.begin(); + it != incPaths.end(); ++it) { + const std::string& path = *it; + mocIncludes.push_back("-I" + path); + // Extract framework path + if (cmHasLiteralSuffix(path, ".framework/Headers")) { + // Go up twice to get to the framework root + std::vector pathComponents; + cmsys::SystemTools::SplitPath(path, pathComponents); + std::string frameworkPath = cmsys::SystemTools::JoinPath( + pathComponents.begin(), pathComponents.end() - 2); + frameworkPaths.insert(frameworkPath); + } + } + } + // Append framework includes + for (std::set::const_iterator it = frameworkPaths.begin(); + it != frameworkPaths.end(); ++it) { + mocIncludes.push_back("-F"); + mocIncludes.push_back(*it); } } - - for (std::set::const_iterator it = frameworkPaths.begin(); - it != frameworkPaths.end(); ++it) { - this->MocIncludes.push_back("-F"); - this->MocIncludes.push_back(*it); - } - if (this->IncludeProjectDirsBefore) { - const std::string binDir = "-I" + this->ProjectBinaryDir; - const std::string srcDir = "-I" + this->ProjectSourceDir; - - std::list sortedMocIncludes; - std::list::iterator it = this->MocIncludes.begin(); - while (it != this->MocIncludes.end()) { - if (cmsys::SystemTools::StringStartsWith(*it, binDir.c_str())) { - sortedMocIncludes.push_back(*it); - it = this->MocIncludes.erase(it); - } else { - ++it; - } - } - it = this->MocIncludes.begin(); - while (it != this->MocIncludes.end()) { - if (cmsys::SystemTools::StringStartsWith(*it, srcDir.c_str())) { - sortedMocIncludes.push_back(*it); - it = this->MocIncludes.erase(it); - } else { - ++it; + // Extract project includes + std::vector mocSortedIncludes; + { + std::vector movePaths; + movePaths.push_back("-I" + this->ProjectBinaryDir); + movePaths.push_back("-I" + this->ProjectSourceDir); + + for (std::vector::const_iterator mpit = movePaths.begin(); + mpit != movePaths.end(); ++mpit) { + std::list::iterator it = mocIncludes.begin(); + while (it != mocIncludes.end()) { + const std::string& path = *it; + if (cmsys::SystemTools::StringStartsWith(path, mpit->c_str())) { + mocSortedIncludes.push_back(path); + it = mocIncludes.erase(it); + } else { + ++it; + } + } } } - sortedMocIncludes.insert(sortedMocIncludes.end(), - this->MocIncludes.begin(), - this->MocIncludes.end()); - this->MocIncludes = sortedMocIncludes; - } + // Place extracted includes at the begin + this->MocIncludes.insert(this->MocIncludes.end(), + mocSortedIncludes.begin(), + mocSortedIncludes.end()); + } + // Append remaining includes + this->MocIncludes.insert(this->MocIncludes.end(), mocIncludes.begin(), + mocIncludes.end()); } bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index e60320b..f6caed9 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -7,7 +7,6 @@ #include #include -#include #include #include #include @@ -146,7 +145,7 @@ private: std::string MocInfoIncludes; std::string OutMocCppFilenameRel; std::string OutMocCppFilenameAbs; - std::list MocIncludes; + std::vector MocIncludes; std::vector MocDefinitions; std::vector MocOptions; // - Uic ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 21 10:33:02 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 21 Feb 2017 10:33:02 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-412-g3d40fcd Message-ID: <20170221153302.46098FA6CC@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 3d40fcd01487700b8130d03e0b247bb1fe6ea9d6 (commit) via c95d017f9c221f309a4b74d8a033c1e99e784f90 (commit) via 4b21290e204d02dd39f6ac404ba923d546f40925 (commit) from 1376688a01bfcf28d31d6a9a79703502d5027ca9 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3d40fcd01487700b8130d03e0b247bb1fe6ea9d6 commit 3d40fcd01487700b8130d03e0b247bb1fe6ea9d6 Merge: 1376688 c95d017 Author: Brad King AuthorDate: Tue Feb 21 10:33:01 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 21 10:33:01 2017 -0500 Merge topic 'ExternalProject-update-docs' into next c95d017f ExternalProject: Clarify documented role of `INSTALL_DIR` 4b21290e ExternalProject: Clarify documented role of `INSTALL_COMMAND` https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c95d017f9c221f309a4b74d8a033c1e99e784f90 commit c95d017f9c221f309a4b74d8a033c1e99e784f90 Author: Brad King AuthorDate: Tue Feb 21 10:31:24 2017 -0500 Commit: Brad King CommitDate: Tue Feb 21 10:32:26 2017 -0500 ExternalProject: Clarify documented role of `INSTALL_DIR` It does not actually configure the project to install to the given location. That must be done by passing the `` placeholder to the external project configuration step. diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake index 325fbc3..c3fd3c6 100644 --- a/Modules/ExternalProject.cmake +++ b/Modules/ExternalProject.cmake @@ -174,7 +174,10 @@ Create custom targets to build projects in external trees Install step options are: ``INSTALL_DIR `` - Installation prefix + Installation prefix to be placed in the ```` 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_COMMAND ...`` Command to drive installation of the external project after it has been built. This only happens at the *build* time of the calling project. https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4b21290e204d02dd39f6ac404ba923d546f40925 commit 4b21290e204d02dd39f6ac404ba923d546f40925 Author: Wilfried Goesgens AuthorDate: Tue Feb 21 15:33:06 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:32:25 2017 -0500 ExternalProject: Clarify documented role of `INSTALL_COMMAND` It is for the install step of the external project and does not affect installation of the calling project. diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake index 458c114..325fbc3 100644 --- a/Modules/ExternalProject.cmake +++ b/Modules/ExternalProject.cmake @@ -176,7 +176,11 @@ Create custom targets to build projects in external trees ``INSTALL_DIR `` Installation prefix ``INSTALL_COMMAND ...`` - Command to drive install after build + 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: ----------------------------------------------------------------------- Summary of changes: Modules/ExternalProject.cmake | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 21 10:40:09 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 21 Feb 2017 10:40:09 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-414-g0df414a Message-ID: <20170221154009.C2FD2ACE1C@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 0df414a55acaa3bc4a9aaeb655980cf80c1606fa (commit) via 88df3416e65ddbc849da08d1b7a920380a578749 (commit) from 3d40fcd01487700b8130d03e0b247bb1fe6ea9d6 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0df414a55acaa3bc4a9aaeb655980cf80c1606fa commit 0df414a55acaa3bc4a9aaeb655980cf80c1606fa Merge: 3d40fcd 88df341 Author: Brad King AuthorDate: Tue Feb 21 10:40:09 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 21 10:40:09 2017 -0500 Merge topic 'autogen_json' into next 88df3416 Autogen: Make tests C++98 compatible https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=88df3416e65ddbc849da08d1b7a920380a578749 commit 88df3416e65ddbc849da08d1b7a920380a578749 Author: Sebastian Holtermann AuthorDate: Tue Feb 21 16:27:42 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:39:32 2017 -0500 Autogen: Make tests C++98 compatible diff --git a/Tests/QtAutogen/mocInclude/ObjA.cpp b/Tests/QtAutogen/mocInclude/ObjA.cpp index 2ee47ec..1b0311d 100644 --- a/Tests/QtAutogen/mocInclude/ObjA.cpp +++ b/Tests/QtAutogen/mocInclude/ObjA.cpp @@ -5,8 +5,8 @@ class SubObjA : public QObject Q_OBJECT public: - SubObjA() = default; - ~SubObjA() = default; + SubObjA() {} + ~SubObjA() {} Q_SLOT void aSlot(); diff --git a/Tests/QtAutogen/mocInclude/ObjB.cpp b/Tests/QtAutogen/mocInclude/ObjB.cpp index abec06a..5ff315d 100644 --- a/Tests/QtAutogen/mocInclude/ObjB.cpp +++ b/Tests/QtAutogen/mocInclude/ObjB.cpp @@ -5,8 +5,8 @@ class SubObjB : public QObject Q_OBJECT public: - SubObjB() = default; - ~SubObjB() = default; + SubObjB() {} + ~SubObjB() {} Q_SLOT void aSlot(); diff --git a/Tests/QtAutogen/mocInclude/ObjC.cpp b/Tests/QtAutogen/mocInclude/ObjC.cpp index bdcdb13..8ca34cb 100644 --- a/Tests/QtAutogen/mocInclude/ObjC.cpp +++ b/Tests/QtAutogen/mocInclude/ObjC.cpp @@ -5,8 +5,8 @@ class SubObjC : public QObject Q_OBJECT public: - SubObjC() = default; - ~SubObjC() = default; + SubObjC() {} + ~SubObjC() {} Q_SLOT void aSlot(); diff --git a/Tests/QtAutogen/mocInclude/ObjD.cpp b/Tests/QtAutogen/mocInclude/ObjD.cpp index 9145ba3..c18aec1 100644 --- a/Tests/QtAutogen/mocInclude/ObjD.cpp +++ b/Tests/QtAutogen/mocInclude/ObjD.cpp @@ -5,8 +5,8 @@ class SubObjD : public QObject Q_OBJECT public: - SubObjD() = default; - ~SubObjD() = default; + SubObjD() {} + ~SubObjD() {} Q_SLOT void aSlot(); diff --git a/Tests/QtAutogen/mocInclude/subA/SubObjA.cpp b/Tests/QtAutogen/mocInclude/subA/SubObjA.cpp index d780942..a05f6e3 100644 --- a/Tests/QtAutogen/mocInclude/subA/SubObjA.cpp +++ b/Tests/QtAutogen/mocInclude/subA/SubObjA.cpp @@ -7,8 +7,8 @@ class SubObjA : public QObject Q_OBJECT public: - SubObjA() = default; - ~SubObjA() = default; + SubObjA() {} + ~SubObjA() {} Q_SLOT void aSlot(); diff --git a/Tests/QtAutogen/mocInclude/subB/SubObjB.cpp b/Tests/QtAutogen/mocInclude/subB/SubObjB.cpp index e602e06..1e77639 100644 --- a/Tests/QtAutogen/mocInclude/subB/SubObjB.cpp +++ b/Tests/QtAutogen/mocInclude/subB/SubObjB.cpp @@ -7,8 +7,8 @@ class SubObjB : public QObject Q_OBJECT public: - SubObjB() = default; - ~SubObjB() = default; + SubObjB() {} + ~SubObjB() {} Q_SLOT void aSlot(); diff --git a/Tests/QtAutogen/mocInclude/subC/SubObjC.cpp b/Tests/QtAutogen/mocInclude/subC/SubObjC.cpp index fb2d1ec..c2d94ef 100644 --- a/Tests/QtAutogen/mocInclude/subC/SubObjC.cpp +++ b/Tests/QtAutogen/mocInclude/subC/SubObjC.cpp @@ -7,8 +7,8 @@ class SubObjC : public QObject Q_OBJECT public: - SubObjC() = default; - ~SubObjC() = default; + SubObjC() {} + ~SubObjC() {} Q_SLOT void aSlot(); ----------------------------------------------------------------------- Summary of changes: Tests/QtAutogen/mocInclude/ObjA.cpp | 4 ++-- Tests/QtAutogen/mocInclude/ObjB.cpp | 4 ++-- Tests/QtAutogen/mocInclude/ObjC.cpp | 4 ++-- Tests/QtAutogen/mocInclude/ObjD.cpp | 4 ++-- Tests/QtAutogen/mocInclude/subA/SubObjA.cpp | 4 ++-- Tests/QtAutogen/mocInclude/subB/SubObjB.cpp | 4 ++-- Tests/QtAutogen/mocInclude/subC/SubObjC.cpp | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 21 10:40:36 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 21 Feb 2017 10:40:36 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-424-g7f97438 Message-ID: <20170221154036.47047AFF17@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 7f974380cfe9e5d4501ef72d5694ff97bf82aa74 (commit) via 29d96633a405c2848a70ce5931973be2d518b56f (commit) via d60f1ddc39e55f0d2e9d073fe5cca19ced6d08f6 (commit) via cdb72127dcd281fdce8e349118d7de717b7154b2 (commit) via 8b13a52c4964b09f663e462af7882cbd01b8202a (commit) via 9d1db7d7c3696108fd0fa1162893076d9a59b652 (commit) via 0ab817fa1e1c9bae8aa63c331d4483d9d9b190c5 (commit) via 754d431813fb4726ca2460641d826240387eb718 (commit) via cd74daf06f3b12f78bf7aed95ed06ff221a28da3 (commit) via 39c4819eaa4f680411a63701b1303d79a088aece (commit) from 0df414a55acaa3bc4a9aaeb655980cf80c1606fa (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7f974380cfe9e5d4501ef72d5694ff97bf82aa74 commit 7f974380cfe9e5d4501ef72d5694ff97bf82aa74 Merge: 0df414a 29d9663 Author: Brad King AuthorDate: Tue Feb 21 10:40:35 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 21 10:40:35 2017 -0500 Merge topic 'autogen_json' into next 29d96633 Autogen: Don't use .moc include in Q_PLUGIN_METADATA test d60f1ddc Autogen: Documentation update cdb72127 Autogen: Add release notes for Q_PLUGIN_METADATA support 8b13a52c Autogen: Tests: Set different compression levels in rcc test 9d1db7d7 Autogen: Overhaul and simplify AutogenInfo.cmake file generation 0ab817fa Autogen: Optimize GetCompileDefinitionsAndDirectories function 754d4318 Autogen: Sort AutogenInfo.cmake.in cd74daf0 Autogen: Tests: Add Q_PLUGIN_METADATA test 39c4819e Autogen: Tests: Add moc include tests https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=29d96633a405c2848a70ce5931973be2d518b56f commit 29d96633a405c2848a70ce5931973be2d518b56f Author: Sebastian Holtermann AuthorDate: Tue Feb 21 11:27:02 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:38:51 2017 -0500 Autogen: Don't use .moc include in Q_PLUGIN_METADATA test diff --git a/Tests/QtAutogen/mocPlugin/StyleD.cpp b/Tests/QtAutogen/mocPlugin/StyleD.cpp index 48398bb..7e4b121 100644 --- a/Tests/QtAutogen/mocPlugin/StyleD.cpp +++ b/Tests/QtAutogen/mocPlugin/StyleD.cpp @@ -1,17 +1,6 @@ #include "StyleD.hpp" -class StyleD : public QStylePlugin -{ - Q_OBJECT - // Json file in global sub director - Q_PLUGIN_METADATA(IID "org.styles.D" FILE "sub/StyleD.json") -public: - QStyle* create(const QString& key); -}; - QStyle* StyleD::create(const QString& key) { return 0; } - -#include "StyleD.moc" diff --git a/Tests/QtAutogen/mocPlugin/StyleD.hpp b/Tests/QtAutogen/mocPlugin/StyleD.hpp index 2afe055..e58444d 100644 --- a/Tests/QtAutogen/mocPlugin/StyleD.hpp +++ b/Tests/QtAutogen/mocPlugin/StyleD.hpp @@ -3,6 +3,13 @@ #include -class StyleD; +class StyleD : public QStylePlugin +{ + Q_OBJECT + // Json file in global sub director + Q_PLUGIN_METADATA(IID "org.styles.D" FILE "sub/StyleD.json") +public: + QStyle* create(const QString& key); +}; #endif https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d60f1ddc39e55f0d2e9d073fe5cca19ced6d08f6 commit d60f1ddc39e55f0d2e9d073fe5cca19ced6d08f6 Author: Sebastian Holtermann AuthorDate: Sun Feb 19 20:11:18 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:38:51 2017 -0500 Autogen: Documentation update Closes #15254 diff --git a/Help/manual/cmake-qt.7.rst b/Help/manual/cmake-qt.7.rst index 56d4ca7..e9da396 100644 --- a/Help/manual/cmake-qt.7.rst +++ b/Help/manual/cmake-qt.7.rst @@ -63,20 +63,24 @@ If a ``Q_OBJECT`` or ``Q_GADGET`` macro is found in a header file, ``moc`` will be run on the file. The result will be put into a file named according to ``moc_.cpp``. If the macro is found in a C++ implementation file, the moc output will be put into a file named according to -``.moc``, following the Qt conventions. The ``moc file`` may be -included by the user in the C++ implementation file with a preprocessor -``#include``. If it is not so included, it will be added to a separate file -which is compiled into the target. +``.moc``, following the Qt conventions. The ``.moc`` must +be included by the user in the C++ implementation file with a preprocessor +``#include``. -The ``moc`` command line will consume the :prop_tgt:`COMPILE_DEFINITIONS` and -:prop_tgt:`INCLUDE_DIRECTORIES` target properties from the target it is being -invoked for, and for the appropriate build configuration. - -The generated ``moc_*.cpp`` and ``*.moc`` files are placed in the +Included ``moc_*.cpp`` and ``*.moc`` files will be generated in the ``/_autogen/include`` directory which is automatically added to the target's :prop_tgt:`INCLUDE_DIRECTORIES`. (This differs from CMake 3.7 and below; see their documentation for details.) +Not included ``moc_.cpp`` files will be generated in custom +folders to avoid name collisions and included in a separate +``/_autogen/moc_compilation.cpp`` +file which is compiled into the target. + +The ``moc`` command line will consume the :prop_tgt:`COMPILE_DEFINITIONS` and +:prop_tgt:`INCLUDE_DIRECTORIES` target properties from the target it is being +invoked for, and for the appropriate build configuration. + The :prop_tgt:`AUTOMOC` target property may be pre-set for all following targets by setting the :variable:`CMAKE_AUTOMOC` variable. The :prop_tgt:`AUTOMOC_MOC_OPTIONS` target property may be populated to set diff --git a/Help/prop_tgt/AUTOMOC.rst b/Help/prop_tgt/AUTOMOC.rst index b42643f..4ac9b6e 100644 --- a/Help/prop_tgt/AUTOMOC.rst +++ b/Help/prop_tgt/AUTOMOC.rst @@ -8,31 +8,41 @@ preprocessor automatically, i.e. without having to use the :module:`QT4_WRAP_CPP() ` or QT5_WRAP_CPP() macro. Currently Qt4 and Qt5 are supported. -When this property is set ``ON``, CMake will scan the +When this property is set ``ON``, CMake will scan the header and source files at build time and invoke moc accordingly. -* If an ``#include`` statement like ``#include "moc_foo.cpp"`` is found, - the ``Q_OBJECT`` class declaration is expected in the header, and - ``moc`` is run on the header file. A ``moc_foo.cpp`` file will be - generated from the source's header into the - ``/_autogen/include`` - directory which is automatically added to the target's +* If an ``#include`` statement like ``#include "moc_.cpp"`` is found, + the ``Q_OBJECT`` or ``Q_GADGET`` macros are expected in an otherwise empty + line of the ``.h(xx)`` header file. ``moc`` is run on the header file to + generate ``moc_.cpp`` in the + ``/_autogen/include`` directory + which is automatically added to the target's :prop_tgt:`INCLUDE_DIRECTORIES`. This allows the compiler to find the - included ``moc_foo.cpp`` file regardless of the location the original source. - However, if multiple source files in different directories do this then their - generated moc files would collide. In this case a diagnostic will be issued. - -* If an ``#include`` statement like ``#include "foo.moc"`` is found, - then a ``Q_OBJECT`` is expected in the current source file and ``moc`` - is run on the file itself. Additionally, header files with the same - base name (like ``foo.h``) or ``_p`` appended to the base name (like - ``foo_p.h``) are parsed for ``Q_OBJECT`` macros, and if found, ``moc`` - is also executed on those files. ``AUTOMOC`` checks multiple header - alternative extensions, such as ``hpp``, ``hxx`` etc when searching - for headers. The resulting moc files, which are not included as shown - above in any of the source files are included in a generated - ``moc_compilation.cpp`` file, which is compiled as part of the - target. + included ``moc_.cpp`` file regardless of the location the + original source. + +* If an ``#include`` statement like ``#include ".moc"`` is found, + then ``Q_OBJECT`` or ``Q_GADGET`` macros are expected in the current source + file and ``moc`` is run on the source file itself. + +* Header files that are not included by an ``#include "moc_.cpp"`` + statement are nonetheless scanned for ``Q_OBJECT`` or ``Q_GADGET`` macros. + The resulting ``moc_.cpp`` files are generated in custom + directories and automatically included in the generated + ``/_autogen/moc_compilation.cpp`` file, + which is compiled as part of the target. The custom directories help to + avoid name collisions for moc files with the same ````. + +* Additionally, header files with the same base name as a source file, + (like ``.h``) or ``_p`` appended to the base name (like + ``_p.h``), are parsed for ``Q_OBJECT`` or ``Q_GADGET`` macros, + and if found, ``moc`` is also executed on those files. + +* ``AUTOMOC`` always checks multiple header alternative extensions, + such as ``hpp``, ``hxx``, etc. when searching for headers. + +* ``AUTOMOC`` looks for the ``Q_PLUGIN_METADATA`` macro and reruns the + ``moc`` when the file addressed by the ``FILE`` argument of the macro changes. This property is initialized by the value of the :variable:`CMAKE_AUTOMOC` variable if it is set when a target is created. https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=cdb72127dcd281fdce8e349118d7de717b7154b2 commit cdb72127dcd281fdce8e349118d7de717b7154b2 Author: Sebastian Holtermann AuthorDate: Sun Feb 19 18:35:40 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:38:51 2017 -0500 Autogen: Add release notes for Q_PLUGIN_METADATA support diff --git a/Help/release/dev/Autogen_json.rst b/Help/release/dev/Autogen_json.rst new file mode 100644 index 0000000..73bbdf1 --- /dev/null +++ b/Help/release/dev/Autogen_json.rst @@ -0,0 +1,10 @@ +AutoGen json +------------ + +* When using :prop_tgt:`AUTOMOC`, CMake scans for the presence of the + ``Q_PLUGIN_METADATA`` macro and reruns moc when the file from the + macro's ``FILE`` argument changes. + +* When :prop_tgt:`AUTOMOC` detects an include statement of the form + ``#include "moc_.cpp"`` the respective header file is searched + for in the :prop_tgt:`INCLUDE_DIRECTORIES` of the target as well. https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8b13a52c4964b09f663e462af7882cbd01b8202a commit 8b13a52c4964b09f663e462af7882cbd01b8202a Author: Sebastian Holtermann AuthorDate: Sun Feb 19 17:24:30 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:38:50 2017 -0500 Autogen: Tests: Set different compression levels in rcc test diff --git a/Tests/QtAutogen/sameName/CMakeLists.txt b/Tests/QtAutogen/sameName/CMakeLists.txt index 9e47a3e..4d2dcd9 100644 --- a/Tests/QtAutogen/sameName/CMakeLists.txt +++ b/Tests/QtAutogen/sameName/CMakeLists.txt @@ -18,3 +18,14 @@ add_executable(sameName ) target_link_libraries(sameName ${QT_LIBRARIES}) set_target_properties(sameName PROPERTIES AUTOMOC TRUE AUTORCC TRUE) + +# Set different compression levels +if (QT_TEST_VERSION STREQUAL 4) + set(rccCompress "-compress") +else() + set(rccCompress "--compress") +endif() +set_target_properties(sameName PROPERTIES AUTORCC_OPTIONS "${rccCompress};0" ) +set_source_files_properties(aaa/data.qrc PROPERTIES AUTORCC_OPTIONS "${rccCompress};1" ) +set_source_files_properties(bbb/data.qrc PROPERTIES AUTORCC_OPTIONS "${rccCompress};2" ) +set_source_files_properties(ccc/data.qrc PROPERTIES AUTORCC_OPTIONS "${rccCompress};3" ) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9d1db7d7c3696108fd0fa1162893076d9a59b652 commit 9d1db7d7c3696108fd0fa1162893076d9a59b652 Author: Sebastian Holtermann AuthorDate: Sun Feb 19 16:46:47 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:38:50 2017 -0500 Autogen: Overhaul and simplify AutogenInfo.cmake file generation diff --git a/Modules/AutogenInfo.cmake.in b/Modules/AutogenInfo.cmake.in index 3135909..b647ecf 100644 --- a/Modules/AutogenInfo.cmake.in +++ b/Modules/AutogenInfo.cmake.in @@ -1,5 +1,5 @@ # Target names -set(AM_TARGET_NAME @_moc_target_name@) +set(AM_TARGET_NAME @_autogen_target_name@) set(AM_ORIGIN_TARGET_NAME @_origin_target_name@) # Directories and files set(AM_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@/") @@ -10,16 +10,16 @@ set(AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE "@CMAKE_INCLUDE_DIRECTORIES_PROJ set(AM_SOURCES @_sources@) set(AM_HEADERS @_headers@) # Qt environment -set(AM_QT_VERSION_MAJOR "@_target_qt_version@") -set(AM_QT_MOC_EXECUTABLE "@_qt_moc_executable@") -set(AM_QT_UIC_EXECUTABLE "@_qt_uic_executable@") -set(AM_QT_RCC_EXECUTABLE "@_qt_rcc_executable@") +set(AM_QT_VERSION_MAJOR @_qt_version_major@) +set(AM_QT_MOC_EXECUTABLE @_qt_moc_executable@) +set(AM_QT_UIC_EXECUTABLE @_qt_uic_executable@) +set(AM_QT_RCC_EXECUTABLE @_qt_rcc_executable@) # MOC settings set(AM_MOC_SKIP @_moc_skip@) set(AM_MOC_COMPILE_DEFINITIONS @_moc_compile_defs@) set(AM_MOC_INCLUDES @_moc_incs@) set(AM_MOC_OPTIONS @_moc_options@) -set(AM_MOC_RELAXED_MODE "@_moc_relaxed_mode@") +set(AM_MOC_RELAXED_MODE @_moc_relaxed_mode@) # UIC settings set(AM_UIC_SKIP @_uic_skip@) set(AM_UIC_TARGET_OPTIONS @_uic_target_options@) diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index c201023..52112ff 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -22,7 +22,6 @@ #endif #include -#include #include #include #include @@ -55,6 +54,13 @@ static std::string utilStripCR(std::string const& line) return line; } +static std::string GetSafeProperty(cmGeneratorTarget const* target, + const char* key) +{ + const char* tmp = target->GetProperty(key); + return std::string((tmp != CM_NULLPTR) ? tmp : ""); +} + static std::string GetAutogenTargetName(cmGeneratorTarget const* target) { std::string autogenTargetName = target->GetName(); @@ -118,19 +124,33 @@ static void GetCompileDefinitionsAndDirectories( } } +static void AddDefinitionEscaped(cmMakefile* makefile, const char* key, + const std::string& value) +{ + makefile->AddDefinition(key, + cmOutputConverter::EscapeForCMake(value).c_str()); +} + +static void AddDefinitionEscaped(cmMakefile* makefile, const char* key, + const std::vector& values) +{ + makefile->AddDefinition( + key, cmOutputConverter::EscapeForCMake(cmJoin(values, ";")).c_str()); +} + static void SetupSourceFiles(cmGeneratorTarget const* target, std::vector& mocUicSources, std::vector& mocUicHeaders, - std::vector& skipMocList, - std::vector& skipUicList) + std::vector& mocSkipList, + std::vector& uicSkipList) { cmMakefile* makefile = target->Target->GetMakefile(); std::vector srcFiles; target->GetConfigCommonSourceFiles(srcFiles); - const bool targetMoc = target->GetPropertyAsBool("AUTOMOC"); - const bool targetUic = target->GetPropertyAsBool("AUTOUIC"); + const bool mocTarget = target->GetPropertyAsBool("AUTOMOC"); + const bool uicTarget = target->GetPropertyAsBool("AUTOUIC"); cmFilePathChecksum fpathCheckSum(makefile); for (std::vector::const_iterator fileIt = srcFiles.begin(); @@ -151,22 +171,22 @@ static void SetupSourceFiles(cmGeneratorTarget const* target, // Skip flags const bool skipAll = cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOGEN")); - const bool skipMoc = + const bool mocSkip = skipAll || cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOMOC")); - const bool skipUic = + const bool uicSkip = skipAll || cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOUIC")); // 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 // processing - if (skipMoc) { - skipMocList.push_back(absFile); + if (mocSkip) { + mocSkipList.push_back(absFile); } - if (skipUic) { - skipUicList.push_back(absFile); + if (uicSkip) { + uicSkipList.push_back(absFile); } - if ((targetMoc && !skipMoc) || (targetUic && !skipUic)) { + if ((mocTarget && !mocSkip) || (uicTarget && !uicSkip)) { // Add file name to sources or headers list switch (fileType) { case cmSystemTools::CXX_FILE_FORMAT: @@ -184,80 +204,85 @@ static void SetupSourceFiles(cmGeneratorTarget const* target, static void MocSetupAutoTarget( cmGeneratorTarget const* target, const std::string& autogenTargetName, - std::vector const& skipMoc, + const std::string& qtMajorVersion, + std::vector const& mocSkipList, std::map& configIncludes, std::map& configDefines) { cmLocalGenerator* lg = target->GetLocalGenerator(); cmMakefile* makefile = target->Target->GetMakefile(); - const char* tmp = target->GetProperty("AUTOMOC_MOC_OPTIONS"); - std::string _moc_options = (tmp != CM_NULLPTR ? tmp : ""); - makefile->AddDefinition( - "_moc_options", cmOutputConverter::EscapeForCMake(_moc_options).c_str()); - makefile->AddDefinition( - "_moc_skip", - cmOutputConverter::EscapeForCMake(cmJoin(skipMoc, ";")).c_str()); - bool relaxedMode = makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE"); - makefile->AddDefinition("_moc_relaxed_mode", relaxedMode ? "TRUE" : "FALSE"); - - std::string _moc_incs; - std::string _moc_compile_defs; - std::vector configs; - const std::string& config = makefile->GetConfigurations(configs); - GetCompileDefinitionsAndDirectories(target, config, _moc_incs, - _moc_compile_defs); + AddDefinitionEscaped(makefile, "_moc_options", + GetSafeProperty(target, "AUTOMOC_MOC_OPTIONS")); + AddDefinitionEscaped(makefile, "_moc_skip", mocSkipList); + AddDefinitionEscaped(makefile, "_moc_relaxed_mode", + makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE") ? "TRUE" + : "FALSE"); - makefile->AddDefinition( - "_moc_incs", cmOutputConverter::EscapeForCMake(_moc_incs).c_str()); - makefile->AddDefinition( - "_moc_compile_defs", - cmOutputConverter::EscapeForCMake(_moc_compile_defs).c_str()); - - for (std::vector::const_iterator li = configs.begin(); - li != configs.end(); ++li) { - std::string config_moc_incs; - std::string config_moc_compile_defs; - GetCompileDefinitionsAndDirectories(target, *li, config_moc_incs, - config_moc_compile_defs); - if (config_moc_incs != _moc_incs) { - configIncludes[*li] = cmOutputConverter::EscapeForCMake(config_moc_incs); - if (_moc_incs.empty()) { - _moc_incs = config_moc_incs; + // Moc includes and compile definitions + { + std::string _moc_incs; + std::string _moc_compile_defs; + std::vector configs; + { + const std::string& config = makefile->GetConfigurations(configs); + GetCompileDefinitionsAndDirectories(target, config, _moc_incs, + _moc_compile_defs); + AddDefinitionEscaped(makefile, "_moc_incs", _moc_incs); + AddDefinitionEscaped(makefile, "_moc_compile_defs", _moc_compile_defs); + } + for (std::vector::const_iterator li = configs.begin(); + li != configs.end(); ++li) { + std::string config_moc_incs; + std::string config_moc_compile_defs; + GetCompileDefinitionsAndDirectories(target, *li, config_moc_incs, + config_moc_compile_defs); + if (config_moc_incs != _moc_incs) { + configIncludes[*li] = + cmOutputConverter::EscapeForCMake(config_moc_incs); + if (_moc_incs.empty()) { + _moc_incs = config_moc_incs; + } } - } - if (config_moc_compile_defs != _moc_compile_defs) { - configDefines[*li] = - cmOutputConverter::EscapeForCMake(config_moc_compile_defs); - if (_moc_compile_defs.empty()) { - _moc_compile_defs = config_moc_compile_defs; + if (config_moc_compile_defs != _moc_compile_defs) { + configDefines[*li] = + cmOutputConverter::EscapeForCMake(config_moc_compile_defs); + if (_moc_compile_defs.empty()) { + _moc_compile_defs = config_moc_compile_defs; + } } } } - const char* qtVersion = makefile->GetDefinition("_target_qt_version"); - if (strcmp(qtVersion, "5") == 0) { - cmGeneratorTarget* qt5Moc = lg->FindGeneratorTargetToUse("Qt5::moc"); - if (!qt5Moc) { - cmSystemTools::Error("Qt5::moc target not found ", - autogenTargetName.c_str()); - return; + // Moc executable + { + std::string err; + const char* mocExec = CM_NULLPTR; + if (qtMajorVersion == "5") { + cmGeneratorTarget* qt5Moc = lg->FindGeneratorTargetToUse("Qt5::moc"); + if (qt5Moc != CM_NULLPTR) { + mocExec = qt5Moc->ImportedGetLocation(""); + } else { + err = "Qt5::moc target not found " + autogenTargetName; + } + } else if (qtMajorVersion == "4") { + cmGeneratorTarget* qt4Moc = lg->FindGeneratorTargetToUse("Qt4::moc"); + if (qt4Moc != CM_NULLPTR) { + mocExec = qt4Moc->ImportedGetLocation(""); + } else { + err = "Qt4::moc target not found " + autogenTargetName; + } + } else { + err = "The CMAKE_AUTOMOC feature supports only Qt 4 and Qt 5 "; + err += autogenTargetName; } - makefile->AddDefinition("_qt_moc_executable", - qt5Moc->ImportedGetLocation("")); - } else if (strcmp(qtVersion, "4") == 0) { - cmGeneratorTarget* qt4Moc = lg->FindGeneratorTargetToUse("Qt4::moc"); - if (!qt4Moc) { - cmSystemTools::Error("Qt4::moc target not found ", - autogenTargetName.c_str()); - return; + // Add definition or error + if (err.empty()) { + AddDefinitionEscaped(makefile, "_qt_moc_executable", + mocExec ? mocExec : ""); + } else { + cmSystemTools::Error(err.c_str()); } - makefile->AddDefinition("_qt_moc_executable", - qt4Moc->ImportedGetLocation("")); - } else { - cmSystemTools::Error("The CMAKE_AUTOMOC feature supports only Qt 4 and " - "Qt 5 ", - autogenTargetName.c_str()); } } @@ -270,126 +295,126 @@ static void UicGetOpts(cmGeneratorTarget const* target, } static void UicSetupAutoTarget( - cmGeneratorTarget const* target, std::vector const& skipUic, + cmGeneratorTarget const* target, const std::string& qtMajorVersion, + std::vector const& uicSkipList, std::map& configUicOptions) { cmLocalGenerator* lg = target->GetLocalGenerator(); cmMakefile* makefile = target->Target->GetMakefile(); - std::set skipped; - skipped.insert(skipUic.begin(), skipUic.end()); + AddDefinitionEscaped(makefile, "_uic_skip", uicSkipList); - makefile->AddDefinition( - "_uic_skip", - cmOutputConverter::EscapeForCMake(cmJoin(skipUic, ";")).c_str()); - - std::vector uiFilesWithOptions = - makefile->GetQtUiFilesWithOptions(); - - const char* qtVersion = makefile->GetDefinition("_target_qt_version"); - - std::string _uic_opts; - std::vector configs; - const std::string& config = makefile->GetConfigurations(configs); - UicGetOpts(target, config, _uic_opts); - - if (!_uic_opts.empty()) { - _uic_opts = cmOutputConverter::EscapeForCMake(_uic_opts); - makefile->AddDefinition("_uic_target_options", _uic_opts.c_str()); - } - for (std::vector::const_iterator li = configs.begin(); - li != configs.end(); ++li) { - std::string config_uic_opts; - UicGetOpts(target, *li, config_uic_opts); - if (config_uic_opts != _uic_opts) { - configUicOptions[*li] = - cmOutputConverter::EscapeForCMake(config_uic_opts); - if (_uic_opts.empty()) { - _uic_opts = config_uic_opts; + // Uic target options + { + std::string _uic_opts; + std::vector configs; + UicGetOpts(target, makefile->GetConfigurations(configs), _uic_opts); + + AddDefinitionEscaped(makefile, "_uic_target_options", _uic_opts); + + for (std::vector::const_iterator li = configs.begin(); + li != configs.end(); ++li) { + std::string config_uic_opts; + UicGetOpts(target, *li, config_uic_opts); + if (config_uic_opts != _uic_opts) { + configUicOptions[*li] = + cmOutputConverter::EscapeForCMake(config_uic_opts); + if (_uic_opts.empty()) { + _uic_opts = config_uic_opts; + } } } } - - std::string uiFileFiles; - std::string uiFileOptions; - const char* sep = ""; - - for (std::vector::const_iterator fileIt = - uiFilesWithOptions.begin(); - fileIt != uiFilesWithOptions.end(); ++fileIt) { - cmSourceFile* sf = *fileIt; - std::string absFile = cmsys::SystemTools::GetRealPath(sf->GetFullPath()); - - if (!skipped.insert(absFile).second) { - continue; + // Uic files options + { + std::vector uiFileFiles; + std::vector uiFileOptions; + { + std::set skipped; + skipped.insert(uicSkipList.begin(), uicSkipList.end()); + + const std::vector uiFilesWithOptions = + makefile->GetQtUiFilesWithOptions(); + for (std::vector::const_iterator fileIt = + uiFilesWithOptions.begin(); + fileIt != uiFilesWithOptions.end(); ++fileIt) { + cmSourceFile* sf = *fileIt; + const std::string absFile = + cmsys::SystemTools::GetRealPath(sf->GetFullPath()); + if (skipped.insert(absFile).second) { + // The file wasn't skipped + uiFileFiles.push_back(absFile); + { + std::string opts = sf->GetProperty("AUTOUIC_OPTIONS"); + cmSystemTools::ReplaceString(opts, ";", "@list_sep@"); + uiFileOptions.push_back(opts); + } + } + } } - uiFileFiles += sep; - uiFileFiles += absFile; - uiFileOptions += sep; - std::string opts = sf->GetProperty("AUTOUIC_OPTIONS"); - cmSystemTools::ReplaceString(opts, ";", "@list_sep@"); - uiFileOptions += opts; - sep = ";"; + AddDefinitionEscaped(makefile, "_qt_uic_options_files", uiFileFiles); + AddDefinitionEscaped(makefile, "_qt_uic_options_options", uiFileOptions); } - makefile->AddDefinition( - "_qt_uic_options_files", - cmOutputConverter::EscapeForCMake(uiFileFiles).c_str()); - makefile->AddDefinition( - "_qt_uic_options_options", - cmOutputConverter::EscapeForCMake(uiFileOptions).c_str()); - - std::string targetName = target->GetName(); - if (strcmp(qtVersion, "5") == 0) { - cmGeneratorTarget* qt5Uic = lg->FindGeneratorTargetToUse("Qt5::uic"); - if (!qt5Uic) { - // Project does not use Qt5Widgets, but has AUTOUIC ON anyway + // Uic executable + { + std::string err; + const char* uicExec = CM_NULLPTR; + if (qtMajorVersion == "5") { + cmGeneratorTarget* qt5Uic = lg->FindGeneratorTargetToUse("Qt5::uic"); + if (qt5Uic != CM_NULLPTR) { + uicExec = qt5Uic->ImportedGetLocation(""); + } else { + // Project does not use Qt5Widgets, but has AUTOUIC ON anyway + } + } else if (qtMajorVersion == "4") { + cmGeneratorTarget* qt4Uic = lg->FindGeneratorTargetToUse("Qt4::uic"); + if (qt4Uic != CM_NULLPTR) { + uicExec = qt4Uic->ImportedGetLocation(""); + } else { + err = "Qt4::uic target not found " + target->GetName(); + } } else { - makefile->AddDefinition("_qt_uic_executable", - qt5Uic->ImportedGetLocation("")); + err = "The CMAKE_AUTOUIC feature supports only Qt 4 and Qt 5 "; + err += target->GetName(); } - } else if (strcmp(qtVersion, "4") == 0) { - cmGeneratorTarget* qt4Uic = lg->FindGeneratorTargetToUse("Qt4::uic"); - if (!qt4Uic) { - cmSystemTools::Error("Qt4::uic target not found ", targetName.c_str()); - return; + // Add definition or error + if (err.empty()) { + AddDefinitionEscaped(makefile, "_qt_uic_executable", + uicExec ? uicExec : ""); + } else { + cmSystemTools::Error(err.c_str()); } - makefile->AddDefinition("_qt_uic_executable", - qt4Uic->ImportedGetLocation("")); - } else { - cmSystemTools::Error("The CMAKE_AUTOUIC feature supports only Qt 4 and " - "Qt 5 ", - targetName.c_str()); } } static std::string RccGetExecutable(cmGeneratorTarget const* target, const std::string& qtMajorVersion) { + std::string rccExec; cmLocalGenerator* lg = target->GetLocalGenerator(); - - std::string const& targetName = target->GetName(); if (qtMajorVersion == "5") { cmGeneratorTarget* qt5Rcc = lg->FindGeneratorTargetToUse("Qt5::rcc"); - if (!qt5Rcc) { - cmSystemTools::Error("Qt5::rcc target not found ", targetName.c_str()); - return std::string(); + if (qt5Rcc != CM_NULLPTR) { + rccExec = qt5Rcc->ImportedGetLocation(""); + } else { + cmSystemTools::Error("Qt5::rcc target not found ", + target->GetName().c_str()); } - return qt5Rcc->ImportedGetLocation(""); - } - if (qtMajorVersion == "4") { + } else if (qtMajorVersion == "4") { cmGeneratorTarget* qt4Rcc = lg->FindGeneratorTargetToUse("Qt4::rcc"); - if (!qt4Rcc) { - cmSystemTools::Error("Qt4::rcc target not found ", targetName.c_str()); - return std::string(); + if (qt4Rcc != CM_NULLPTR) { + rccExec = qt4Rcc->ImportedGetLocation(""); + } else { + cmSystemTools::Error("Qt4::rcc target not found ", + target->GetName().c_str()); } - return qt4Rcc->ImportedGetLocation(""); + } else { + cmSystemTools::Error( + "The CMAKE_AUTORCC feature supports only Qt 4 and Qt 5 ", + target->GetName().c_str()); } - - cmSystemTools::Error("The CMAKE_AUTORCC feature supports only Qt 4 and " - "Qt 5 ", - targetName.c_str()); - return std::string(); + return rccExec; } static void RccMergeOptions(std::vector& opts, @@ -399,26 +424,31 @@ static void RccMergeOptions(std::vector& opts, static const char* valueOptions[] = { "name", "root", "compress", "threshold" }; std::vector extraOpts; - for (std::vector::const_iterator it = fileOpts.begin(); - it != fileOpts.end(); ++it) { + for (std::vector::const_iterator fit = fileOpts.begin(); + fit != fileOpts.end(); ++fit) { std::vector::iterator existingIt = - std::find(opts.begin(), opts.end(), *it); + std::find(opts.begin(), opts.end(), *fit); if (existingIt != opts.end()) { - const char* o = it->c_str(); - if (*o == '-') { - ++o; - } - if (isQt5 && *o == '-') { - ++o; + const char* optName = fit->c_str(); + if (*optName == '-') { + ++optName; + if (isQt5 && *optName == '-') { + ++optName; + } } - if (std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions), - cmStrCmp(*it)) != cmArrayEnd(valueOptions)) { - assert(existingIt + 1 != opts.end()); - *(existingIt + 1) = *(it + 1); - ++it; + // Test if this is a value option and change the existing value + if ((optName != fit->c_str()) && + std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions), + cmStrCmp(optName)) != cmArrayEnd(valueOptions)) { + const std::vector::iterator existValueIt(existingIt + 1); + const std::vector::const_iterator fileValueIt(fit + 1); + if ((existValueIt != opts.end()) && (fileValueIt != fileOpts.end())) { + *existValueIt = *fileValueIt; + ++fit; + } } } else { - extraOpts.push_back(*it); + extraOpts.push_back(*fit); } } opts.insert(opts.end(), extraOpts.begin(), extraOpts.end()); @@ -528,23 +558,20 @@ static bool RccListInputsQt4(cmSourceFile* sf, } cmsys::RegularExpression fileMatchRegex("(]*>)"); size_t offset = 0; while (fileMatchRegex.find(qrcContents.c_str() + offset)) { std::string qrcEntry = fileMatchRegex.match(1); - offset += qrcEntry.size(); - - cmsys::RegularExpression fileReplaceRegex("(^]*>)"); - fileReplaceRegex.find(qrcEntry); - std::string tag = fileReplaceRegex.match(1); - - qrcEntry = qrcEntry.substr(tag.size()); - + { + fileReplaceRegex.find(qrcEntry); + std::string tag = fileReplaceRegex.match(1); + qrcEntry = qrcEntry.substr(tag.size()); + } if (!cmSystemTools::FileIsFullPath(qrcEntry.c_str())) { qrcEntry = sf->GetLocation().GetDirectory() + "/" + qrcEntry; } - depends.push_back(qrcEntry); } return true; @@ -565,89 +592,69 @@ static bool RccListInputs(const std::string& qtMajorVersion, cmSourceFile* sf, static void RccSetupAutoTarget(cmGeneratorTarget const* target, const std::string& qtMajorVersion) { - std::string _rcc_files; - const char* sepRccFiles = ""; cmMakefile* makefile = target->Target->GetMakefile(); - - std::vector srcFiles; - target->GetConfigCommonSourceFiles(srcFiles); - - std::string qrcInputs; - const char* qrcInputsSep = ""; - - std::string rccFileFiles; - std::string rccFileOptions; - const char* optionSep = ""; - const bool qtMajorVersion5 = (qtMajorVersion == "5"); - - std::vector rccOptions; + std::vector _rcc_files; + std::vector _rcc_inputs; + std::vector rccFileFiles; + std::vector rccFileOptions; + std::vector rccOptionsTarget; if (const char* opts = target->GetProperty("AUTORCC_OPTIONS")) { - cmSystemTools::ExpandListArgument(opts, rccOptions); + cmSystemTools::ExpandListArgument(opts, rccOptionsTarget); } + std::vector srcFiles; + target->GetConfigCommonSourceFiles(srcFiles); for (std::vector::const_iterator fileIt = srcFiles.begin(); fileIt != srcFiles.end(); ++fileIt) { cmSourceFile* sf = *fileIt; - std::string ext = sf->GetExtension(); - if (ext == "qrc") { - std::string absFile = cmsys::SystemTools::GetRealPath(sf->GetFullPath()); + if (sf->GetExtension() == "qrc") { const bool skip = cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOGEN")) || cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC")); - if (!skip) { - _rcc_files += sepRccFiles; - _rcc_files += absFile; - sepRccFiles = ";"; - - if (const char* prop = sf->GetProperty("AUTORCC_OPTIONS")) { - std::vector optsVec; - cmSystemTools::ExpandListArgument(prop, optsVec); - RccMergeOptions(rccOptions, optsVec, qtMajorVersion5); - } - - if (!rccOptions.empty()) { - rccFileFiles += optionSep; - rccFileFiles += absFile; - rccFileOptions += optionSep; - } - const char* listSep = ""; - for (std::vector::const_iterator it = rccOptions.begin(); - it != rccOptions.end(); ++it) { - rccFileOptions += listSep; - rccFileOptions += *it; - listSep = "@list_sep@"; + const std::string absFile = + cmsys::SystemTools::GetRealPath(sf->GetFullPath()); + // qrc file + _rcc_files.push_back(absFile); + // qrc file entries + { + std::string entriesList; + if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) { + std::vector depends; + if (RccListInputs(qtMajorVersion, sf, target, depends)) { + entriesList = cmJoin(depends, "@list_sep@"); + } else { + return; + } + } + _rcc_inputs.push_back(entriesList); } - optionSep = ";"; - - std::string entriesList; - if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) { - std::vector depends; - if (RccListInputs(qtMajorVersion, sf, target, depends)) { - entriesList = cmJoin(depends, "@list_sep@"); - } else { - return; + // rcc options for this qrc file + { + // Merged target and file options + std::vector rccOptions(rccOptionsTarget); + if (const char* prop = sf->GetProperty("AUTORCC_OPTIONS")) { + std::vector optsVec; + cmSystemTools::ExpandListArgument(prop, optsVec); + RccMergeOptions(rccOptions, optsVec, qtMajorVersion5); + } + // Only store non empty options lists + if (!rccOptions.empty()) { + rccFileFiles.push_back(absFile); + rccFileOptions.push_back(cmJoin(rccOptions, "@list_sep@")); } } - qrcInputs += qrcInputsSep; - qrcInputs += entriesList; - qrcInputsSep = ";"; } } } - makefile->AddDefinition( - "_rcc_inputs", cmOutputConverter::EscapeForCMake(qrcInputs).c_str()); - makefile->AddDefinition( - "_rcc_files", cmOutputConverter::EscapeForCMake(_rcc_files).c_str()); - makefile->AddDefinition( - "_rcc_options_files", - cmOutputConverter::EscapeForCMake(rccFileFiles).c_str()); - makefile->AddDefinition( - "_rcc_options_options", - cmOutputConverter::EscapeForCMake(rccFileOptions).c_str()); - makefile->AddDefinition("_qt_rcc_executable", - RccGetExecutable(target, qtMajorVersion).c_str()); + + AddDefinitionEscaped(makefile, "_rcc_files", _rcc_files); + AddDefinitionEscaped(makefile, "_rcc_inputs", _rcc_inputs); + AddDefinitionEscaped(makefile, "_rcc_options_files", rccFileFiles); + AddDefinitionEscaped(makefile, "_rcc_options_options", rccFileOptions); + AddDefinitionEscaped(makefile, "_qt_rcc_executable", + RccGetExecutable(target, qtMajorVersion)); } void cmQtAutoGeneratorInitializer::InitializeAutogenSources( @@ -874,47 +881,42 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( cmMakefile::ScopePushPop varScope(makefile); static_cast(varScope); - // create a custom target for running generators at buildtime: - const std::string autogenTargetName = GetAutogenTargetName(target); - const std::string qtMajorVersion = GetQtMajorVersion(target); - - makefile->AddDefinition( - "_moc_target_name", - cmOutputConverter::EscapeForCMake(autogenTargetName).c_str()); - makefile->AddDefinition( - "_origin_target_name", - cmOutputConverter::EscapeForCMake(target->GetName()).c_str()); - makefile->AddDefinition("_target_qt_version", qtMajorVersion.c_str()); - - std::vector mocUicSources; - std::vector mocUicHeaders; - std::vector skipMoc; - std::vector skipUic; std::map configMocIncludes; std::map configMocDefines; std::map configUicOptions; + { + // create a custom target for running generators at buildtime: + const std::string autogenTargetName = GetAutogenTargetName(target); + const std::string qtMajorVersion = GetQtMajorVersion(target); - if (target->GetPropertyAsBool("AUTOMOC") || - target->GetPropertyAsBool("AUTOUIC") || - target->GetPropertyAsBool("AUTORCC")) { - SetupSourceFiles(target, mocUicSources, mocUicHeaders, skipMoc, skipUic); - } - makefile->AddDefinition( - "_sources", - cmOutputConverter::EscapeForCMake(cmJoin(mocUicSources, ";")).c_str()); - makefile->AddDefinition( - "_headers", - cmOutputConverter::EscapeForCMake(cmJoin(mocUicHeaders, ";")).c_str()); + AddDefinitionEscaped(makefile, "_autogen_target_name", autogenTargetName); + AddDefinitionEscaped(makefile, "_origin_target_name", target->GetName()); + AddDefinitionEscaped(makefile, "_qt_version_major", qtMajorVersion); - if (target->GetPropertyAsBool("AUTOMOC")) { - MocSetupAutoTarget(target, autogenTargetName, skipMoc, configMocIncludes, - configMocDefines); - } - if (target->GetPropertyAsBool("AUTOUIC")) { - UicSetupAutoTarget(target, skipUic, configUicOptions); - } - if (target->GetPropertyAsBool("AUTORCC")) { - RccSetupAutoTarget(target, qtMajorVersion); + std::vector _sources; + std::vector _headers; + std::vector mocSkipList; + std::vector uicSkipList; + + if (target->GetPropertyAsBool("AUTOMOC") || + target->GetPropertyAsBool("AUTOUIC") || + target->GetPropertyAsBool("AUTORCC")) { + SetupSourceFiles(target, _sources, _headers, mocSkipList, uicSkipList); + } + AddDefinitionEscaped(makefile, "_sources", _sources); + AddDefinitionEscaped(makefile, "_headers", _headers); + + if (target->GetPropertyAsBool("AUTOMOC")) { + MocSetupAutoTarget(target, autogenTargetName, qtMajorVersion, + mocSkipList, configMocIncludes, configMocDefines); + } + if (target->GetPropertyAsBool("AUTOUIC")) { + UicSetupAutoTarget(target, qtMajorVersion, uicSkipList, + configUicOptions); + } + if (target->GetPropertyAsBool("AUTORCC")) { + RccSetupAutoTarget(target, qtMajorVersion); + } } // Generate config file @@ -926,7 +928,7 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( makefile->ConfigureFile(inputFile.c_str(), outputFile.c_str(), false, true, false); - // Append custom definitions to config file + // Append custom config definitions to info file if (!configMocDefines.empty() || !configMocIncludes.empty() || !configUicOptions.empty()) { @@ -948,33 +950,34 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( error += outputFile; error += " for writing."; cmSystemTools::Error(error.c_str()); - return; - } - if (!configMocDefines.empty()) { - for (std::map::iterator - it = configMocDefines.begin(), - end = configMocDefines.end(); - it != end; ++it) { - infoFile << "set(AM_MOC_COMPILE_DEFINITIONS_" << it->first << " " - << it->second << ")\n"; + } else { + infoFile << "# Configuration specific options\n"; + if (!configMocDefines.empty()) { + for (std::map::iterator + it = configMocDefines.begin(), + end = configMocDefines.end(); + it != end; ++it) { + infoFile << "set(AM_MOC_COMPILE_DEFINITIONS_" << it->first << " " + << it->second << ")\n"; + } } - } - if (!configMocIncludes.empty()) { - for (std::map::iterator - it = configMocIncludes.begin(), - end = configMocIncludes.end(); - it != end; ++it) { - infoFile << "set(AM_MOC_INCLUDES_" << it->first << " " << it->second - << ")\n"; + if (!configMocIncludes.empty()) { + for (std::map::iterator + it = configMocIncludes.begin(), + end = configMocIncludes.end(); + it != end; ++it) { + infoFile << "set(AM_MOC_INCLUDES_" << it->first << " " << it->second + << ")\n"; + } } - } - if (!configUicOptions.empty()) { - for (std::map::iterator - it = configUicOptions.begin(), - end = configUicOptions.end(); - it != end; ++it) { - infoFile << "set(AM_UIC_TARGET_OPTIONS_" << it->first << " " - << it->second << ")\n"; + if (!configUicOptions.empty()) { + for (std::map::iterator + it = configUicOptions.begin(), + end = configUicOptions.end(); + it != end; ++it) { + infoFile << "set(AM_UIC_TARGET_OPTIONS_" << it->first << " " + << it->second << ")\n"; + } } } } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0ab817fa1e1c9bae8aa63c331d4483d9d9b190c5 commit 0ab817fa1e1c9bae8aa63c331d4483d9d9b190c5 Author: Sebastian Holtermann AuthorDate: Sun Feb 19 13:17:42 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:38:50 2017 -0500 Autogen: Optimize GetCompileDefinitionsAndDirectories function diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index d17faf6..c201023 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -98,6 +98,26 @@ static std::string GetQtMajorVersion(cmGeneratorTarget const* target) return qtMajorVersion; } +static void GetCompileDefinitionsAndDirectories( + cmGeneratorTarget const* target, const std::string& config, + std::string& incs, std::string& defs) +{ + cmLocalGenerator* localGen = target->GetLocalGenerator(); + { + std::vector includeDirs; + // Get the include dirs for this target, without stripping the implicit + // include dirs off, see + // https://gitlab.kitware.com/cmake/cmake/issues/13667 + localGen->GetIncludeDirectories(includeDirs, target, "CXX", config, false); + incs = cmJoin(includeDirs, ";"); + } + { + std::set defines; + localGen->AddCompileDefinitions(defines, target, config, "CXX"); + defs += cmJoin(defines, ";"); + } +} + static void SetupSourceFiles(cmGeneratorTarget const* target, std::vector& mocUicSources, std::vector& mocUicHeaders, @@ -162,24 +182,6 @@ static void SetupSourceFiles(cmGeneratorTarget const* target, } } -static void GetCompileDefinitionsAndDirectories( - cmGeneratorTarget const* target, const std::string& config, - std::string& incs, std::string& defs) -{ - std::vector includeDirs; - cmLocalGenerator* localGen = target->GetLocalGenerator(); - // Get the include dirs for this target, without stripping the implicit - // include dirs off, see https://gitlab.kitware.com/cmake/cmake/issues/13667 - localGen->GetIncludeDirectories(includeDirs, target, "CXX", config, false); - - incs = cmJoin(includeDirs, ";"); - - std::set defines; - localGen->AddCompileDefinitions(defines, target, config, "CXX"); - - defs += cmJoin(defines, ";"); -} - static void MocSetupAutoTarget( cmGeneratorTarget const* target, const std::string& autogenTargetName, std::vector const& skipMoc, https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=754d431813fb4726ca2460641d826240387eb718 commit 754d431813fb4726ca2460641d826240387eb718 Author: Sebastian Holtermann AuthorDate: Sun Feb 19 12:57:47 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:38:49 2017 -0500 Autogen: Sort AutogenInfo.cmake.in Also rename AM_SKIP_MOC to AM_MOC_SKIP and AM_SKIP_UIC to AM_UIC_SKIP diff --git a/Modules/AutogenInfo.cmake.in b/Modules/AutogenInfo.cmake.in index 3fafaff..3135909 100644 --- a/Modules/AutogenInfo.cmake.in +++ b/Modules/AutogenInfo.cmake.in @@ -1,25 +1,31 @@ -set(AM_SOURCES @_moc_uic_sources@) -set(AM_HEADERS @_moc_uic_headers@) -set(AM_SKIP_MOC @_skip_moc@) -set(AM_SKIP_UIC @_skip_uic@) -set(AM_MOC_COMPILE_DEFINITIONS @_moc_compile_defs@) -set(AM_MOC_INCLUDES @_moc_incs@) -set(AM_MOC_OPTIONS @_moc_options@) -set(AM_MOC_RELAXED_MODE "@_moc_relaxed_mode@") -set(AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE "@CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE@") +# Target names +set(AM_TARGET_NAME @_moc_target_name@) +set(AM_ORIGIN_TARGET_NAME @_origin_target_name@) +# Directories and files set(AM_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@/") set(AM_CMAKE_SOURCE_DIR "@CMAKE_SOURCE_DIR@/") -set(AM_QT_MOC_EXECUTABLE "@_qt_moc_executable@") -set(AM_QT_UIC_EXECUTABLE "@_qt_uic_executable@") -set(AM_QT_RCC_EXECUTABLE "@_qt_rcc_executable@") set(AM_CMAKE_CURRENT_SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@/") set(AM_CMAKE_CURRENT_BINARY_DIR "@CMAKE_CURRENT_BINARY_DIR@/") +set(AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE "@CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE@") +set(AM_SOURCES @_sources@) +set(AM_HEADERS @_headers@) +# Qt environment set(AM_QT_VERSION_MAJOR "@_target_qt_version@") -set(AM_TARGET_NAME @_moc_target_name@) -set(AM_ORIGIN_TARGET_NAME @_origin_target_name@) +set(AM_QT_MOC_EXECUTABLE "@_qt_moc_executable@") +set(AM_QT_UIC_EXECUTABLE "@_qt_uic_executable@") +set(AM_QT_RCC_EXECUTABLE "@_qt_rcc_executable@") +# MOC settings +set(AM_MOC_SKIP @_moc_skip@) +set(AM_MOC_COMPILE_DEFINITIONS @_moc_compile_defs@) +set(AM_MOC_INCLUDES @_moc_incs@) +set(AM_MOC_OPTIONS @_moc_options@) +set(AM_MOC_RELAXED_MODE "@_moc_relaxed_mode@") +# UIC settings +set(AM_UIC_SKIP @_uic_skip@) set(AM_UIC_TARGET_OPTIONS @_uic_target_options@) set(AM_UIC_OPTIONS_FILES @_qt_uic_options_files@) set(AM_UIC_OPTIONS_OPTIONS @_qt_uic_options_options@) +# RCC settings set(AM_RCC_SOURCES @_rcc_files@ ) set(AM_RCC_INPUTS @_rcc_inputs@) set(AM_RCC_OPTIONS_FILES @_rcc_options_files@) diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index 825eba0..d17faf6 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -194,7 +194,7 @@ static void MocSetupAutoTarget( makefile->AddDefinition( "_moc_options", cmOutputConverter::EscapeForCMake(_moc_options).c_str()); makefile->AddDefinition( - "_skip_moc", + "_moc_skip", cmOutputConverter::EscapeForCMake(cmJoin(skipMoc, ";")).c_str()); bool relaxedMode = makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE"); makefile->AddDefinition("_moc_relaxed_mode", relaxedMode ? "TRUE" : "FALSE"); @@ -278,7 +278,7 @@ static void UicSetupAutoTarget( skipped.insert(skipUic.begin(), skipUic.end()); makefile->AddDefinition( - "_skip_uic", + "_uic_skip", cmOutputConverter::EscapeForCMake(cmJoin(skipUic, ";")).c_str()); std::vector uiFilesWithOptions = @@ -898,10 +898,10 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( SetupSourceFiles(target, mocUicSources, mocUicHeaders, skipMoc, skipUic); } makefile->AddDefinition( - "_moc_uic_sources", + "_sources", cmOutputConverter::EscapeForCMake(cmJoin(mocUicSources, ";")).c_str()); makefile->AddDefinition( - "_moc_uic_headers", + "_headers", cmOutputConverter::EscapeForCMake(cmJoin(mocUicHeaders, ";")).c_str()); if (target->GetPropertyAsBool("AUTOMOC")) { diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index ccdebbb..4149e55 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -307,7 +307,7 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( this->Headers); // - Moc - cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_SKIP_MOC"), + cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_MOC_SKIP"), this->MocSkipList); cmSystemTools::ExpandListArgument( GetConfigDefinition(makefile, "AM_MOC_COMPILE_DEFINITIONS", config), @@ -319,7 +319,7 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( makefile->GetSafeDefinition("AM_MOC_OPTIONS"), this->MocOptions); // - Uic - cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_SKIP_UIC"), + cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_UIC_SKIP"), this->UicSkipList); cmSystemTools::ExpandListArgument( GetConfigDefinition(makefile, "AM_UIC_TARGET_OPTIONS", config), https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=cd74daf06f3b12f78bf7aed95ed06ff221a28da3 commit cd74daf06f3b12f78bf7aed95ed06ff221a28da3 Author: Sebastian Holtermann AuthorDate: Fri Feb 17 13:50:33 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:38:49 2017 -0500 Autogen: Tests: Add Q_PLUGIN_METADATA test diff --git a/Tests/QtAutogen/CMakeLists.txt b/Tests/QtAutogen/CMakeLists.txt index 40c23fa..260331b 100644 --- a/Tests/QtAutogen/CMakeLists.txt +++ b/Tests/QtAutogen/CMakeLists.txt @@ -86,7 +86,8 @@ try_compile(RCC_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/autorcc_depends" "${CMAKE_CURRENT_SOURCE_DIR}/autorcc_depends" autorcc_depends - CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" "-DQT_TEST_VERSION=${QT_TEST_VERSION}" + CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" + "-DQT_TEST_VERSION=${QT_TEST_VERSION}" "-DCMAKE_PREFIX_PATH=${Qt_PREFIX_DIR}" OUTPUT_VARIABLE output ) @@ -121,7 +122,8 @@ try_compile(MOC_RERUN "${CMAKE_CURRENT_BINARY_DIR}/automoc_rerun" "${CMAKE_CURRENT_SOURCE_DIR}/automoc_rerun" automoc_rerun - CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" "-DQT_TEST_VERSION=${QT_TEST_VERSION}" + CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" + "-DQT_TEST_VERSION=${QT_TEST_VERSION}" "-DCMAKE_PREFIX_PATH=${Qt_PREFIX_DIR}" OUTPUT_VARIABLE output ) @@ -215,5 +217,60 @@ add_subdirectory(mocIncludeStrict) add_subdirectory(mocIncludeRelaxed) # -- 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(mocPluginBinDir "${CMAKE_CURRENT_BINARY_DIR}/mocPlugin") + find_library(style_a_file "PluginStyleA" "${mocPluginBinDir}") + find_library(style_b_file "PluginStyleB" "${mocPluginBinDir}") + find_library(style_c_file "PluginStyleC" "${mocPluginBinDir}") + find_library(style_d_file "PluginStyleD" "${mocPluginBinDir}") + + file(TIMESTAMP "${style_a_file}" style_a_before "${timeformat}") + file(TIMESTAMP "${style_b_file}" style_b_before "${timeformat}") + file(TIMESTAMP "${style_c_file}" style_c_before "${timeformat}") + file(TIMESTAMP "${style_d_file}" style_d_before "${timeformat}") + + # Ensure that the timestamp will change and touch the json files + execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) + execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${mocPluginBinDir}/jsonFiles/StyleC.json") + execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${mocPluginBinDir}/jsonFiles/sub/StyleD.json") + + execute_process(COMMAND "${CMAKE_COMMAND}" --build . + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mocPlugin" + ) + + file(TIMESTAMP "${style_a_file}" style_a_after "${timeformat}") + file(TIMESTAMP "${style_b_file}" style_b_after "${timeformat}") + file(TIMESTAMP "${style_c_file}" style_c_after "${timeformat}") + file(TIMESTAMP "${style_d_file}" style_d_after "${timeformat}") + + if (style_a_after GREATER style_a_before) + message(SEND_ERROR "file (${style_a_file}) should not have changed!") + endif() + if (style_b_after GREATER style_b_before) + message(SEND_ERROR "file (${style_b_file}) should not have changed!") + endif() + if (NOT style_c_after GREATER style_c_before) + message(SEND_ERROR "file (${style_c_file}) should have changed!") + endif() + if (NOT style_d_after GREATER style_d_before) + message(SEND_ERROR "file (${style_d_file}) should have changed!") + endif() +endif() + +# -- Test # Complex test case add_subdirectory(complex) diff --git a/Tests/QtAutogen/mocPlugin/CMakeLists.txt b/Tests/QtAutogen/mocPlugin/CMakeLists.txt new file mode 100644 index 0000000..eed7d39 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 3.8) + +if (NOT QT_TEST_VERSION STREQUAL 5) + message(SEND_ERROR "Invalid Qt version specified.") +endif() +find_package(Qt5Widgets REQUIRED) + +if(Qt5_POSITION_INDEPENDENT_CODE AND CMAKE_CXX_COMPILE_OPTIONS_PIC) + add_definitions(${CMAKE_CXX_COMPILE_OPTIONS_PIC}) +endif() + +configure_file(jsonIn/StyleC.json jsonFiles/StyleC.json @ONLY) +configure_file(jsonIn/StyleD.json jsonFiles/sub/StyleD.json @ONLY) + +# Enable automoc +set(CMAKE_AUTOMOC TRUE) + +include_directories("${CMAKE_CURRENT_BINARY_DIR}/jsonFiles") +link_libraries(Qt5::Widgets) + +add_library(PluginStyleA MODULE StyleA.cpp) +add_library(PluginStyleB MODULE StyleB.cpp) +add_library(PluginStyleC MODULE StyleC.cpp) +add_library(PluginStyleD MODULE StyleD.cpp) +add_library(PluginStyleE MODULE StyleE.cpp) diff --git a/Tests/QtAutogen/mocPlugin/StyleA.cpp b/Tests/QtAutogen/mocPlugin/StyleA.cpp new file mode 100644 index 0000000..b5e8753 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleA.cpp @@ -0,0 +1,6 @@ +#include "StyleA.hpp" + +QStyle* StyleA::create(const QString& key) +{ + return 0; +} diff --git a/Tests/QtAutogen/mocPlugin/StyleA.hpp b/Tests/QtAutogen/mocPlugin/StyleA.hpp new file mode 100644 index 0000000..b105b02 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleA.hpp @@ -0,0 +1,15 @@ +#ifndef STYLEA_HPP +#define STYLEA_HPP + +#include + +class StyleA : public QStylePlugin +{ + Q_OBJECT + // Json file in local directory + Q_PLUGIN_METADATA(IID "org.styles.A" FILE "StyleA.json") +public: + QStyle* create(const QString& key); +}; + +#endif diff --git a/Tests/QtAutogen/mocPlugin/StyleA.json b/Tests/QtAutogen/mocPlugin/StyleA.json new file mode 100644 index 0000000..cc33953 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleA.json @@ -0,0 +1 @@ +{ "Keys": [ "Rocket", "Starbuster" ] } diff --git a/Tests/QtAutogen/mocPlugin/StyleB.cpp b/Tests/QtAutogen/mocPlugin/StyleB.cpp new file mode 100644 index 0000000..17d4400 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleB.cpp @@ -0,0 +1,6 @@ +#include "StyleB.hpp" + +QStyle* StyleB::create(const QString& key) +{ + return 0; +} diff --git a/Tests/QtAutogen/mocPlugin/StyleB.hpp b/Tests/QtAutogen/mocPlugin/StyleB.hpp new file mode 100644 index 0000000..ba89127 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleB.hpp @@ -0,0 +1,15 @@ +#ifndef STYLEB_HPP +#define STYLEB_HPP + +#include + +class StyleB : public QStylePlugin +{ + Q_OBJECT + // Json file in local subdirectory + Q_PLUGIN_METADATA(IID "org.styles.B" FILE "jsonIn/StyleB.json") +public: + QStyle* create(const QString& key); +}; + +#endif diff --git a/Tests/QtAutogen/mocPlugin/StyleC.cpp b/Tests/QtAutogen/mocPlugin/StyleC.cpp new file mode 100644 index 0000000..37e7564 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleC.cpp @@ -0,0 +1,6 @@ +#include "StyleC.hpp" + +QStyle* StyleC::create(const QString& key) +{ + return 0; +} diff --git a/Tests/QtAutogen/mocPlugin/StyleC.hpp b/Tests/QtAutogen/mocPlugin/StyleC.hpp new file mode 100644 index 0000000..9f71d75 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleC.hpp @@ -0,0 +1,15 @@ +#ifndef STYLEC_HPP +#define STYLEC_HPP + +#include + +class StyleC : public QStylePlugin +{ + Q_OBJECT + // Json file in global root directory + Q_PLUGIN_METADATA(IID "org.styles.C" FILE "StyleC.json") +public: + QStyle* create(const QString& key); +}; + +#endif diff --git a/Tests/QtAutogen/mocPlugin/StyleD.cpp b/Tests/QtAutogen/mocPlugin/StyleD.cpp new file mode 100644 index 0000000..48398bb --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleD.cpp @@ -0,0 +1,17 @@ +#include "StyleD.hpp" + +class StyleD : public QStylePlugin +{ + Q_OBJECT + // Json file in global sub director + Q_PLUGIN_METADATA(IID "org.styles.D" FILE "sub/StyleD.json") +public: + QStyle* create(const QString& key); +}; + +QStyle* StyleD::create(const QString& key) +{ + return 0; +} + +#include "StyleD.moc" diff --git a/Tests/QtAutogen/mocPlugin/StyleD.hpp b/Tests/QtAutogen/mocPlugin/StyleD.hpp new file mode 100644 index 0000000..2afe055 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleD.hpp @@ -0,0 +1,8 @@ +#ifndef STYLED_HPP +#define STYLED_HPP + +#include + +class StyleD; + +#endif diff --git a/Tests/QtAutogen/mocPlugin/StyleE.cpp b/Tests/QtAutogen/mocPlugin/StyleE.cpp new file mode 100644 index 0000000..8fc9a7f --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleE.cpp @@ -0,0 +1,6 @@ +#include "StyleE.hpp" + +QStyle* StyleE::create(const QString& key) +{ + return 0; +} diff --git a/Tests/QtAutogen/mocPlugin/StyleE.hpp b/Tests/QtAutogen/mocPlugin/StyleE.hpp new file mode 100644 index 0000000..80e0b79 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleE.hpp @@ -0,0 +1,15 @@ +#ifndef STYLEE_HPP +#define STYLEE_HPP + +#include + +class StyleE : public QStylePlugin +{ + Q_OBJECT + // No Json file + Q_PLUGIN_METADATA(IID "org.styles.E") +public: + QStyle* create(const QString& key); +}; + +#endif diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleB.json b/Tests/QtAutogen/mocPlugin/jsonIn/StyleB.json new file mode 100644 index 0000000..129cac4 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/jsonIn/StyleB.json @@ -0,0 +1 @@ +{ "Keys": [ "Rocket", "StarbusterB" ] } diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json b/Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json new file mode 100644 index 0000000..bf17580 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json @@ -0,0 +1 @@ +{ "Keys": [ "Rocket", "StarbusterC" ] } diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json b/Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json new file mode 100644 index 0000000..f7fcc19 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json @@ -0,0 +1 @@ +{ "Keys": [ "Rocket", "StarbusterD" ] } diff --git a/Tests/QtAutogen/mocPlugin/main.cpp b/Tests/QtAutogen/mocPlugin/main.cpp new file mode 100644 index 0000000..3ba2ddc --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/main.cpp @@ -0,0 +1,6 @@ +#include "StyleA.hpp" + +int main(int argv, char** args) +{ + return 0; +} https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=39c4819eaa4f680411a63701b1303d79a088aece commit 39c4819eaa4f680411a63701b1303d79a088aece Author: Sebastian Holtermann AuthorDate: Thu Feb 16 15:59:56 2017 +0100 Commit: Brad King CommitDate: Tue Feb 21 10:38:49 2017 -0500 Autogen: Tests: Add moc include tests diff --git a/Tests/QtAutogen/CMakeLists.txt b/Tests/QtAutogen/CMakeLists.txt index c1cdee2..40c23fa 100644 --- a/Tests/QtAutogen/CMakeLists.txt +++ b/Tests/QtAutogen/CMakeLists.txt @@ -207,5 +207,13 @@ target_link_libraries(skipRccB ${QT_LIBRARIES}) add_subdirectory(sameName) # -- Test +# Tests various include moc patterns +add_subdirectory(mocIncludeStrict) + +# -- Test +# Tests various include moc patterns +add_subdirectory(mocIncludeRelaxed) + +# -- Test # Complex test case add_subdirectory(complex) diff --git a/Tests/QtAutogen/mocInclude/ObjA.cpp b/Tests/QtAutogen/mocInclude/ObjA.cpp new file mode 100644 index 0000000..1b0311d --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjA.cpp @@ -0,0 +1,24 @@ +#include "ObjA.hpp" + +class SubObjA : public QObject +{ + Q_OBJECT + +public: + SubObjA() {} + ~SubObjA() {} + + Q_SLOT + void aSlot(); +}; + +void SubObjA::aSlot() +{ +} + +void ObjA::go() +{ + SubObjA subObj; +} + +#include "ObjA.moc" diff --git a/Tests/QtAutogen/mocInclude/ObjA.hpp b/Tests/QtAutogen/mocInclude/ObjA.hpp new file mode 100644 index 0000000..281e90d --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjA.hpp @@ -0,0 +1,13 @@ +#ifndef OBJA_HPP +#define OBJA_HPP + +#include + +class ObjA : public QObject +{ + Q_OBJECT + Q_SLOT + void go(); +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/ObjB.cpp b/Tests/QtAutogen/mocInclude/ObjB.cpp new file mode 100644 index 0000000..5ff315d --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjB.cpp @@ -0,0 +1,25 @@ +#include "ObjB.hpp" + +class SubObjB : public QObject +{ + Q_OBJECT + +public: + SubObjB() {} + ~SubObjB() {} + + Q_SLOT + void aSlot(); +}; + +void SubObjB::aSlot() +{ +} + +void ObjB::go() +{ + SubObjB subObj; +} + +#include "ObjB.moc" +#include "moc_ObjB.cpp" diff --git a/Tests/QtAutogen/mocInclude/ObjB.hpp b/Tests/QtAutogen/mocInclude/ObjB.hpp new file mode 100644 index 0000000..94f3d49 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjB.hpp @@ -0,0 +1,13 @@ +#ifndef OBJB_HPP +#define OBJB_HPP + +#include + +class ObjB : public QObject +{ + Q_OBJECT + Q_SLOT + void go(); +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/ObjC.cpp b/Tests/QtAutogen/mocInclude/ObjC.cpp new file mode 100644 index 0000000..8ca34cb --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjC.cpp @@ -0,0 +1,26 @@ +#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 new file mode 100644 index 0000000..a8e98eb --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjC.hpp @@ -0,0 +1,13 @@ +#ifndef OBJC_HPP +#define OBJC_HPP + +#include + +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 new file mode 100644 index 0000000..c18aec1 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjD.cpp @@ -0,0 +1,26 @@ +#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 new file mode 100644 index 0000000..b6ee098 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/ObjD.hpp @@ -0,0 +1,13 @@ +#ifndef OBJD_HPP +#define OBJD_HPP + +#include + +class ObjD : public QObject +{ + Q_OBJECT + Q_SLOT + void go(); +}; + +#endif diff --git a/Tests/QtAutogen/mocInclude/subA/SubObjA.cpp b/Tests/QtAutogen/mocInclude/subA/SubObjA.cpp new file mode 100644 index 0000000..a05f6e3 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subA/SubObjA.cpp @@ -0,0 +1,27 @@ +#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 new file mode 100644 index 0000000..31a18b6 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subA/SubObjA.hpp @@ -0,0 +1,16 @@ +#ifndef SUBOBJA_HPP +#define SUBOBJA_HPP + +#include + +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 new file mode 100644 index 0000000..1e77639 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subB/SubObjB.cpp @@ -0,0 +1,27 @@ +#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 new file mode 100644 index 0000000..3f29fa2 --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subB/SubObjB.hpp @@ -0,0 +1,16 @@ +#ifndef SUBOBJB_HPP +#define SUBOBJB_HPP + +#include + +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 new file mode 100644 index 0000000..c2d94ef --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subC/SubObjC.cpp @@ -0,0 +1,27 @@ +#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 new file mode 100644 index 0000000..dc251fd --- /dev/null +++ b/Tests/QtAutogen/mocInclude/subC/SubObjC.hpp @@ -0,0 +1,16 @@ +#ifndef SUBOBJC_HPP +#define SUBOBJC_HPP + +#include + +namespace subC { + +class ObjC : public QObject +{ + Q_OBJECT + Q_SLOT + void go(); +}; +} + +#endif diff --git a/Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt b/Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt new file mode 100644 index 0000000..6a0829d --- /dev/null +++ b/Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt @@ -0,0 +1,18 @@ +# Test moc include patterns + +set(CMAKE_AUTOMOC_RELAXED_MODE TRUE) + +include_directories("../mocInclude") + +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 +) +target_link_libraries(mocIncludeRelaxed ${QT_LIBRARIES}) +set_target_properties(mocIncludeRelaxed PROPERTIES AUTOMOC ON) diff --git a/Tests/QtAutogen/mocIncludeRelaxed/main.cpp b/Tests/QtAutogen/mocIncludeRelaxed/main.cpp new file mode 100644 index 0000000..142d59e --- /dev/null +++ b/Tests/QtAutogen/mocIncludeRelaxed/main.cpp @@ -0,0 +1,14 @@ +#include "ObjA.hpp" +#include "ObjB.hpp" +#include "ObjC.hpp" + +int main(int argv, char** args) +{ + ObjA objA; + ObjB objB; + ObjC objC; + return 0; +} + +// Header in global subdirectory +#include "subB/moc_SubObjB.cpp" diff --git a/Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt b/Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt new file mode 100644 index 0000000..22e93a8 --- /dev/null +++ b/Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt @@ -0,0 +1,18 @@ +# Test moc include patterns + +set(CMAKE_AUTOMOC_RELAXED_MODE FALSE) + +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) diff --git a/Tests/QtAutogen/mocIncludeStrict/main.cpp b/Tests/QtAutogen/mocIncludeStrict/main.cpp new file mode 100644 index 0000000..142d59e --- /dev/null +++ b/Tests/QtAutogen/mocIncludeStrict/main.cpp @@ -0,0 +1,14 @@ +#include "ObjA.hpp" +#include "ObjB.hpp" +#include "ObjC.hpp" + +int main(int argv, char** args) +{ + ObjA objA; + ObjB objB; + ObjC objC; + return 0; +} + +// Header in global subdirectory +#include "subB/moc_SubObjB.cpp" ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 21 11:14:00 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 21 Feb 2017 11:14:00 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-168-g48ef9c5 Message-ID: <20170221161400.B00CDE644F@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 48ef9c5ae64da6cfe1470f4420abd29263ec2c92 (commit) via 08fa0b4595566a6e4c29c182865a6ec7e41d9e2e (commit) from 8209b3238f07f5f4e8bd52d9e7f9b7c8af6ac7ba (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=48ef9c5ae64da6cfe1470f4420abd29263ec2c92 commit 48ef9c5ae64da6cfe1470f4420abd29263ec2c92 Merge: 8209b32 08fa0b4 Author: Brad King AuthorDate: Tue Feb 21 11:13:58 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 21 11:13:58 2017 -0500 Merge topic 'cuda-separable-bool' 08fa0b45 CUDA: Fix boolean interpretation of CUDA_SEPARABLE_COMPILATION ----------------------------------------------------------------------- Summary of changes: Source/cmMakefileTargetGenerator.cxx | 3 ++- Source/cmNinjaTargetGenerator.cxx | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 21 11:14:03 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 21 Feb 2017 11:14:03 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-170-gf5d6d27 Message-ID: <20170221161403.23D6DF3720@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via f5d6d27168fefe3ef05bd1863c25c3e9505e4b04 (commit) via 2ab118a8591d8b27ae89de8f3c65b5797fd01dc2 (commit) from 48ef9c5ae64da6cfe1470f4420abd29263ec2c92 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f5d6d27168fefe3ef05bd1863c25c3e9505e4b04 commit f5d6d27168fefe3ef05bd1863c25c3e9505e4b04 Merge: 48ef9c5 2ab118a Author: Brad King AuthorDate: Tue Feb 21 11:14:01 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 21 11:14:01 2017 -0500 Merge topic 'FindGTK2-old-sigc++' 2ab118a8 FindGTK2: handle old libsigc++ versions ----------------------------------------------------------------------- Summary of changes: Modules/FindGTK2.cmake | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 21 11:14:05 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 21 Feb 2017 11:14:05 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-173-g3ccad39 Message-ID: <20170221161405.9237FF3E81@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 3ccad39000281c40e2a7a5e078adc4f977e462dd (commit) via 717e1f3056b45e79dcb433b1098e8b6fd813d07b (commit) via 0bbd993f618e4ded1d949e64ba778dfab3106262 (commit) from f5d6d27168fefe3ef05bd1863c25c3e9505e4b04 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3ccad39000281c40e2a7a5e078adc4f977e462dd commit 3ccad39000281c40e2a7a5e078adc4f977e462dd Merge: f5d6d27 717e1f3 Author: Brad King AuthorDate: Tue Feb 21 11:14:03 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 21 11:14:03 2017 -0500 Merge topic 'cmake-host-system-name' 717e1f30 Use looked up uname path for command execution 0bbd993f Make CMAKE_HOST_SYSTEM_NAME available in scripting context ----------------------------------------------------------------------- Summary of changes: Modules/CMakeDetermineSystem.cmake | 10 ++++------ Source/cmStateSnapshot.cxx | 10 ++++++++++ Tests/CMakeTests/ToolchainTest.cmake.in | 1 - 3 files changed, 14 insertions(+), 7 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 21 11:14:20 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 21 Feb 2017 11:14:20 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-429-gbdf7094 Message-ID: <20170221161420.DA16EE644E@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via bdf70944426e26a269e8930fe7a3bbb4d1590119 (commit) via 3ccad39000281c40e2a7a5e078adc4f977e462dd (commit) via f5d6d27168fefe3ef05bd1863c25c3e9505e4b04 (commit) via 48ef9c5ae64da6cfe1470f4420abd29263ec2c92 (commit) via 8209b3238f07f5f4e8bd52d9e7f9b7c8af6ac7ba (commit) from 7f974380cfe9e5d4501ef72d5694ff97bf82aa74 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=bdf70944426e26a269e8930fe7a3bbb4d1590119 commit bdf70944426e26a269e8930fe7a3bbb4d1590119 Merge: 7f97438 3ccad39 Author: Brad King AuthorDate: Tue Feb 21 11:14:13 2017 -0500 Commit: Brad King CommitDate: Tue Feb 21 11:14:13 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 21 13:47:29 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 21 Feb 2017 13:47:29 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-431-g83f2188 Message-ID: <20170221184729.CC97FF5609@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 83f21887f75b66c99a61e7e1deeabf89d78229d1 (commit) via 4a7321a56fd00ec82a25f250828e7621f3c9d9f9 (commit) from bdf70944426e26a269e8930fe7a3bbb4d1590119 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=83f21887f75b66c99a61e7e1deeabf89d78229d1 commit 83f21887f75b66c99a61e7e1deeabf89d78229d1 Merge: bdf7094 4a7321a Author: Brad King AuthorDate: Tue Feb 21 13:47:29 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 21 13:47:29 2017 -0500 Merge topic 'vs2017-fallback-sdk' into next 4a7321a5 Revert "VS2017: If Win 8.1 SDK is not available, use Win 10 SDK" https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4a7321a56fd00ec82a25f250828e7621f3c9d9f9 commit 4a7321a56fd00ec82a25f250828e7621f3c9d9f9 Author: Brad King AuthorDate: Tue Feb 21 13:47:14 2017 -0500 Commit: Brad King CommitDate: Tue Feb 21 13:47:14 2017 -0500 Revert "VS2017: If Win 8.1 SDK is not available, use Win 10 SDK" This reverts commit f582eb753eb746086ef29f6249040f1d7d7e35f9. diff --git a/Source/cmGlobalVisualStudio15Generator.cxx b/Source/cmGlobalVisualStudio15Generator.cxx index ac67051..d11ee7c 100644 --- a/Source/cmGlobalVisualStudio15Generator.cxx +++ b/Source/cmGlobalVisualStudio15Generator.cxx @@ -109,18 +109,6 @@ void cmGlobalVisualStudio15Generator::WriteSLNHeader(std::ostream& fout) } } -bool cmGlobalVisualStudio15Generator::InitializeWindows(cmMakefile* mf) -{ - // If the Win 8.1 SDK is installed then we can select a SDK matching - // the target Windows version. - if (vsSetupAPIHelper.IsWin81SDKInstalled()) { - return cmGlobalVisualStudio14Generator::InitializeWindows(mf); - } - // Otherwise we must choose a Win 10 SDK even if we are not targeting - // Windows 10. - return this->SelectWindows10SDK(mf, false); -} - bool cmGlobalVisualStudio15Generator::SelectWindowsStoreToolset( std::string& toolset) const { diff --git a/Source/cmGlobalVisualStudio15Generator.h b/Source/cmGlobalVisualStudio15Generator.h index 7240e1a..781b41e 100644 --- a/Source/cmGlobalVisualStudio15Generator.h +++ b/Source/cmGlobalVisualStudio15Generator.h @@ -28,7 +28,6 @@ public: virtual const char* GetToolsVersion() { return "15.0"; } protected: - bool InitializeWindows(cmMakefile* mf) CM_OVERRIDE; virtual bool SelectWindowsStoreToolset(std::string& toolset) const; virtual const char* GetIDEVersion() { return "15.0"; } ----------------------------------------------------------------------- Summary of changes: Source/cmGlobalVisualStudio15Generator.cxx | 12 ------------ Source/cmGlobalVisualStudio15Generator.h | 1 - 2 files changed, 13 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 21 14:06:28 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 21 Feb 2017 14:06:28 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-433-gaa1fd4f Message-ID: <20170221190629.62593FA65F@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via aa1fd4f3d25da106c6db053a01d479b065a7eaaf (commit) via 2da0838c64b6d43fd12eecb5d65ac458a335b266 (commit) from 83f21887f75b66c99a61e7e1deeabf89d78229d1 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=aa1fd4f3d25da106c6db053a01d479b065a7eaaf commit aa1fd4f3d25da106c6db053a01d479b065a7eaaf Merge: 83f2188 2da0838 Author: Brad King AuthorDate: Tue Feb 21 14:06:27 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 21 14:06:27 2017 -0500 Merge topic 'vs2017-fallback-sdk' into next 2da0838c VS2017: If Win 8.1 SDK is not available, use Win 10 SDK https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=2da0838c64b6d43fd12eecb5d65ac458a335b266 commit 2da0838c64b6d43fd12eecb5d65ac458a335b266 Author: Brad King AuthorDate: Mon Feb 20 09:46:58 2017 -0500 Commit: Brad King CommitDate: Tue Feb 21 13:47:54 2017 -0500 VS2017: If Win 8.1 SDK is not available, use Win 10 SDK We try to choose the Windows SDK version based on the version of Windows targeted by the build. However, if using VS 2017 without the Windows 8.1 SDK installed then we must fall back to the Windows 10 SDK even when targeting an older version of Windows. Inspired-by: gnaggnoyil diff --git a/Source/cmGlobalVisualStudio15Generator.cxx b/Source/cmGlobalVisualStudio15Generator.cxx index d11ee7c..2312bc0 100644 --- a/Source/cmGlobalVisualStudio15Generator.cxx +++ b/Source/cmGlobalVisualStudio15Generator.cxx @@ -109,6 +109,18 @@ void cmGlobalVisualStudio15Generator::WriteSLNHeader(std::ostream& fout) } } +bool cmGlobalVisualStudio15Generator::InitializeWindows(cmMakefile* mf) +{ + // If the Win 8.1 SDK is installed then we can select a SDK matching + // the target Windows version. + if (this->IsWin81SDKInstalled()) { + return cmGlobalVisualStudio14Generator::InitializeWindows(mf); + } + // Otherwise we must choose a Win 10 SDK even if we are not targeting + // Windows 10. + return this->SelectWindows10SDK(mf, false); +} + bool cmGlobalVisualStudio15Generator::SelectWindowsStoreToolset( std::string& toolset) const { @@ -135,6 +147,28 @@ bool cmGlobalVisualStudio15Generator::IsWindowsStoreToolsetInstalled() const return vsSetupAPIHelper.IsWin10SDKInstalled(); } +bool cmGlobalVisualStudio15Generator::IsWin81SDKInstalled() const +{ + // Does the VS installer tool know about one? + if (vsSetupAPIHelper.IsWin81SDKInstalled()) { + return true; + } + + // Does the registry know about one (e.g. from VS 2015)? + std::string win81Root; + if (cmSystemTools::ReadRegistryValue( + "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\" + "Windows Kits\\Installed Roots;KitsRoot81", + win81Root, cmSystemTools::KeyWOW64_32) || + cmSystemTools::ReadRegistryValue( + "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\" + "Windows Kits\\Installed Roots;KitsRoot81", + win81Root, cmSystemTools::KeyWOW64_32)) { + return true; + } + return false; +} + std::string cmGlobalVisualStudio15Generator::FindMSBuildCommand() { std::string msbuild; diff --git a/Source/cmGlobalVisualStudio15Generator.h b/Source/cmGlobalVisualStudio15Generator.h index 781b41e..f979b65 100644 --- a/Source/cmGlobalVisualStudio15Generator.h +++ b/Source/cmGlobalVisualStudio15Generator.h @@ -28,6 +28,7 @@ public: virtual const char* GetToolsVersion() { return "15.0"; } protected: + bool InitializeWindows(cmMakefile* mf) CM_OVERRIDE; virtual bool SelectWindowsStoreToolset(std::string& toolset) const; virtual const char* GetIDEVersion() { return "15.0"; } @@ -40,6 +41,9 @@ protected: // of the toolset is installed bool IsWindowsStoreToolsetInstalled() const; + // Check for a Win 8 SDK known to the registry or VS installer tool. + bool IsWin81SDKInstalled() const; + std::string FindMSBuildCommand() CM_OVERRIDE; std::string FindDevEnvCommand() CM_OVERRIDE; ----------------------------------------------------------------------- Summary of changes: Source/cmGlobalVisualStudio15Generator.cxx | 34 ++++++++++++++++++++++++++++ Source/cmGlobalVisualStudio15Generator.h | 4 ++++ 2 files changed, 38 insertions(+) hooks/post-receive -- CMake From kwrobot at kitware.com Wed Feb 22 00:01:05 2017 From: kwrobot at kitware.com (Kitware Robot) Date: Wed, 22 Feb 2017 00:01:05 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-174-g28df39c Message-ID: <20170222050105.C6A42FA393@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 28df39ca8efbd3380e81977954aeda93ce53db10 (commit) from 3ccad39000281c40e2a7a5e078adc4f977e462dd (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=28df39ca8efbd3380e81977954aeda93ce53db10 commit 28df39ca8efbd3380e81977954aeda93ce53db10 Author: Kitware Robot AuthorDate: Wed Feb 22 00:01:03 2017 -0500 Commit: Kitware Robot CommitDate: Wed Feb 22 00:01:03 2017 -0500 CMake Nightly Date Stamp diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 5e71120..d8261b7 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 8) -set(CMake_VERSION_PATCH 20170221) +set(CMake_VERSION_PATCH 20170222) #set(CMake_VERSION_RC 1) ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 22 10:15:33 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 22 Feb 2017 10:15:33 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-177-g8aac0ae Message-ID: <20170222151534.85F0EF5E2E@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 8aac0ae7c52c6f1937f6192620933f546574c730 (commit) via c95d017f9c221f309a4b74d8a033c1e99e784f90 (commit) via 4b21290e204d02dd39f6ac404ba923d546f40925 (commit) from 28df39ca8efbd3380e81977954aeda93ce53db10 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8aac0ae7c52c6f1937f6192620933f546574c730 commit 8aac0ae7c52c6f1937f6192620933f546574c730 Merge: 28df39c c95d017 Author: Brad King AuthorDate: Wed Feb 22 10:15:29 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 22 10:15:29 2017 -0500 Merge topic 'ExternalProject-update-docs' c95d017f ExternalProject: Clarify documented role of `INSTALL_DIR` 4b21290e ExternalProject: Clarify documented role of `INSTALL_COMMAND` ----------------------------------------------------------------------- Summary of changes: Modules/ExternalProject.cmake | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 22 10:15:37 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 22 Feb 2017 10:15:37 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-179-gdc32ad1 Message-ID: <20170222151539.06FBBF9DC8@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via dc32ad198819a1f25487daa1787f08825bbafef8 (commit) via 2da0838c64b6d43fd12eecb5d65ac458a335b266 (commit) from 8aac0ae7c52c6f1937f6192620933f546574c730 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=dc32ad198819a1f25487daa1787f08825bbafef8 commit dc32ad198819a1f25487daa1787f08825bbafef8 Merge: 8aac0ae 2da0838 Author: Brad King AuthorDate: Wed Feb 22 10:15:35 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 22 10:15:35 2017 -0500 Merge topic 'vs2017-fallback-sdk' 2da0838c VS2017: If Win 8.1 SDK is not available, use Win 10 SDK ----------------------------------------------------------------------- Summary of changes: Source/cmGlobalVisualStudio15Generator.cxx | 34 ++++++++++++++++++++++++++++ Source/cmGlobalVisualStudio15Generator.h | 4 ++++ 2 files changed, 38 insertions(+) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 22 10:15:51 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 22 Feb 2017 10:15:51 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-237-gdfebdd6 Message-ID: <20170222151552.1A7A0F9DB6@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via dfebdd6218d8f146277d75597fccde74b45cdbd2 (commit) via 29d96633a405c2848a70ce5931973be2d518b56f (commit) via d60f1ddc39e55f0d2e9d073fe5cca19ced6d08f6 (commit) via cdb72127dcd281fdce8e349118d7de717b7154b2 (commit) via 8b13a52c4964b09f663e462af7882cbd01b8202a (commit) via 9d1db7d7c3696108fd0fa1162893076d9a59b652 (commit) via 0ab817fa1e1c9bae8aa63c331d4483d9d9b190c5 (commit) via 754d431813fb4726ca2460641d826240387eb718 (commit) via cd74daf06f3b12f78bf7aed95ed06ff221a28da3 (commit) via 39c4819eaa4f680411a63701b1303d79a088aece (commit) via 50805693ba987fbf86bb5e8263d7b427cd4da0c2 (commit) via c23206b6c17a5c70580355904fc12fd64c26ef79 (commit) via 347572cf5ea2c653cba6150b5e6d6fa083a68cb0 (commit) via 03df033bfa551e83c2a265cc22f6f5278c80528b (commit) via 3ec230de1f45f48a8bbb8eca49674f0e0c99dfa1 (commit) via 41fb64e719817ce877565e6e11198df2f7e7e63d (commit) via 175c89004425cdbb151d4e85876e2a2076432f28 (commit) via 80a007534f6287cd2e88c1b8fd72b68fc688da4e (commit) via f379fdbb9ee17b62ac8b4a8d4b9fab562ba37253 (commit) via ddf940725e8af095b1c02606aeea64cc9baaf572 (commit) via 71c5ae253cb5498da319e36bcf49869509b6603c (commit) via 5308f954c9ad13cfc6cc84f1f1255fb5faff48c6 (commit) via 887e40034161589b63fdb14bfaee7f66374b9b83 (commit) via 4c60099fea2b06229900cc16fed907185c4fe2ef (commit) via 815a05cf12499b42acea70b5a9534e10e1701417 (commit) via 3270091210c0cfdddb133209b232a1d0a1fa48da (commit) via 793c9a7925dfa3aaa2b15212f4ba0246d1fbf83c (commit) via 25dbfbc2a937379ca78328dfabdf54043340dbd3 (commit) via 3cc42863a43cd4256efdeb2eda2d235d5533bad9 (commit) via 074534a56d4d6146c2389fd256299197e5bad027 (commit) via a51f1a91d9733c596113f799154ef45d647e7764 (commit) via b2063fd70fa6955acb2b9f02507097d03e2011a7 (commit) via 10beb4a0345f673feaeec798d452a48797c6820a (commit) via f37f1a647d5aba4de5903a3a3dc7700be55c99ec (commit) via 5bb997c24a7ba8b6f252cc7914858f5c12a543b6 (commit) via a9e3c903b6f74d181c76d1a2014a3af2babe6e41 (commit) via 2f3ecd4ea9518b2a110b995fe9ac171f026ccad5 (commit) via 739592c9256fb6f89ee15081c3944d42515ef8db (commit) via ad1f21313f553ecc7064accf582986112dc678d1 (commit) via 2296a2e9ee04fc83a294d51421038dca40b3150f (commit) via d3a9887149d638dd23df2b46ff67a90cd91d33fe (commit) via 6ae09b7c1473836236275e553fe9ff77f48306c1 (commit) via 9a7c9efeea0c2c2dfa20eb46dc75359c7f787629 (commit) via 86c2b552ad7bb3af97bb3c59576ddc7cac841d26 (commit) via 2fed7bcc1f4a19f4942cddfdd42278f1c20feccc (commit) via c29950cc1f532d78158b146c50b0c49b8d41c47a (commit) via 74a2fcff50356dcdcd4004664a2b2b81a8142660 (commit) via 21886ff66a8a84c20a3c7f24601b5a353d8c7d06 (commit) via 22faeef2626e10b281c82d10ba2653ecd940f398 (commit) via 32d0ee3576c9203104a17c6a75bfc1bf13192045 (commit) via 119876e6d5e71fb8a3f72ba35593ee43fd124203 (commit) via c88a3f72289a1fdfb9b47cdea025d50efee94501 (commit) via 25f0c2e14b0285d81ad0c6be401398e12e7ea89e (commit) via 763f717ce2251a7237e85a0ad9a4c86c94942642 (commit) via 3ee2b1623ecbef3164c412bb6a1d826ba788002b (commit) via ec24dcdb36db7b460113b2ce3f7a954800d41e90 (commit) via 6b31416d6c9bdc8b89a918f217a6678cc6083fed (commit) via 1bd74130f2a804d073081f7e3e4f307c3fecb07c (commit) from dc32ad198819a1f25487daa1787f08825bbafef8 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=dfebdd6218d8f146277d75597fccde74b45cdbd2 commit dfebdd6218d8f146277d75597fccde74b45cdbd2 Merge: dc32ad1 29d9663 Author: Brad King AuthorDate: Wed Feb 22 10:15:48 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 22 10:15:48 2017 -0500 Merge topic 'autogen_json' 29d96633 Autogen: Don't use .moc include in Q_PLUGIN_METADATA test d60f1ddc Autogen: Documentation update cdb72127 Autogen: Add release notes for Q_PLUGIN_METADATA support 8b13a52c Autogen: Tests: Set different compression levels in rcc test 9d1db7d7 Autogen: Overhaul and simplify AutogenInfo.cmake file generation 0ab817fa Autogen: Optimize GetCompileDefinitionsAndDirectories function 754d4318 Autogen: Sort AutogenInfo.cmake.in cd74daf0 Autogen: Tests: Add Q_PLUGIN_METADATA test 39c4819e Autogen: Tests: Add moc include tests 50805693 Autogen: Tests: Clean comments c23206b6 Autogen: Log simplifications 347572cf Autogen: Only touch an unchanged moc_compilation.cpp 03df033b Autogen: Rebuild moc when Q_PLUGIN_METADATA json file changes 3ec230de Autogen: Use GetRealPath in central places only 41fb64e7 Autogen: Search moc includes in include directories 175c8900 Autogen: Sort includes before composing include options ... ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-qt.7.rst | 22 +- Help/prop_tgt/AUTOMOC.rst | 54 +- Help/release/dev/Autogen_json.rst | 10 + Modules/AutogenInfo.cmake.in | 36 +- Source/cmFilePathChecksum.cxx | 4 +- Source/cmFilePathChecksum.h | 4 +- Source/cmQtAutoGeneratorInitializer.cxx | 671 ++++----- Source/cmQtAutoGenerators.cxx | 1576 ++++++++++++---------- Source/cmQtAutoGenerators.h | 170 ++- Tests/QtAutogen/CMakeLists.txt | 91 +- Tests/QtAutogen/mocInclude/ObjA.cpp | 24 + Tests/QtAutogen/mocInclude/ObjA.hpp | 13 + Tests/QtAutogen/mocInclude/ObjB.cpp | 25 + Tests/QtAutogen/mocInclude/ObjB.hpp | 13 + Tests/QtAutogen/mocInclude/ObjC.cpp | 26 + Tests/QtAutogen/mocInclude/ObjC.hpp | 13 + Tests/QtAutogen/mocInclude/ObjD.cpp | 26 + Tests/QtAutogen/mocInclude/ObjD.hpp | 13 + Tests/QtAutogen/mocInclude/subA/SubObjA.cpp | 27 + Tests/QtAutogen/mocInclude/subA/SubObjA.hpp | 16 + Tests/QtAutogen/mocInclude/subB/SubObjB.cpp | 27 + Tests/QtAutogen/mocInclude/subB/SubObjB.hpp | 16 + Tests/QtAutogen/mocInclude/subC/SubObjC.cpp | 27 + Tests/QtAutogen/mocInclude/subC/SubObjC.hpp | 16 + Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt | 18 + Tests/QtAutogen/mocIncludeRelaxed/main.cpp | 14 + Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt | 18 + Tests/QtAutogen/mocIncludeStrict/main.cpp | 14 + Tests/QtAutogen/mocPlugin/CMakeLists.txt | 25 + Tests/QtAutogen/mocPlugin/StyleA.cpp | 6 + Tests/QtAutogen/mocPlugin/StyleA.hpp | 15 + Tests/QtAutogen/mocPlugin/StyleA.json | 1 + Tests/QtAutogen/mocPlugin/StyleB.cpp | 6 + Tests/QtAutogen/mocPlugin/StyleB.hpp | 15 + Tests/QtAutogen/mocPlugin/StyleC.cpp | 6 + Tests/QtAutogen/mocPlugin/StyleC.hpp | 15 + Tests/QtAutogen/mocPlugin/StyleD.cpp | 6 + Tests/QtAutogen/mocPlugin/StyleD.hpp | 15 + Tests/QtAutogen/mocPlugin/StyleE.cpp | 6 + Tests/QtAutogen/mocPlugin/StyleE.hpp | 15 + Tests/QtAutogen/mocPlugin/jsonIn/StyleB.json | 1 + Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json | 1 + Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json | 1 + Tests/QtAutogen/mocPlugin/main.cpp | 6 + Tests/QtAutogen/sameName/CMakeLists.txt | 11 + 45 files changed, 1960 insertions(+), 1175 deletions(-) create mode 100644 Help/release/dev/Autogen_json.rst create mode 100644 Tests/QtAutogen/mocInclude/ObjA.cpp create mode 100644 Tests/QtAutogen/mocInclude/ObjA.hpp create mode 100644 Tests/QtAutogen/mocInclude/ObjB.cpp create mode 100644 Tests/QtAutogen/mocInclude/ObjB.hpp create mode 100644 Tests/QtAutogen/mocInclude/ObjC.cpp create mode 100644 Tests/QtAutogen/mocInclude/ObjC.hpp create mode 100644 Tests/QtAutogen/mocInclude/ObjD.cpp create mode 100644 Tests/QtAutogen/mocInclude/ObjD.hpp create mode 100644 Tests/QtAutogen/mocInclude/subA/SubObjA.cpp create mode 100644 Tests/QtAutogen/mocInclude/subA/SubObjA.hpp create mode 100644 Tests/QtAutogen/mocInclude/subB/SubObjB.cpp create mode 100644 Tests/QtAutogen/mocInclude/subB/SubObjB.hpp create mode 100644 Tests/QtAutogen/mocInclude/subC/SubObjC.cpp create mode 100644 Tests/QtAutogen/mocInclude/subC/SubObjC.hpp create mode 100644 Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt create mode 100644 Tests/QtAutogen/mocIncludeRelaxed/main.cpp create mode 100644 Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt create mode 100644 Tests/QtAutogen/mocIncludeStrict/main.cpp create mode 100644 Tests/QtAutogen/mocPlugin/CMakeLists.txt create mode 100644 Tests/QtAutogen/mocPlugin/StyleA.cpp create mode 100644 Tests/QtAutogen/mocPlugin/StyleA.hpp create mode 100644 Tests/QtAutogen/mocPlugin/StyleA.json create mode 100644 Tests/QtAutogen/mocPlugin/StyleB.cpp create mode 100644 Tests/QtAutogen/mocPlugin/StyleB.hpp create mode 100644 Tests/QtAutogen/mocPlugin/StyleC.cpp create mode 100644 Tests/QtAutogen/mocPlugin/StyleC.hpp create mode 100644 Tests/QtAutogen/mocPlugin/StyleD.cpp create mode 100644 Tests/QtAutogen/mocPlugin/StyleD.hpp create mode 100644 Tests/QtAutogen/mocPlugin/StyleE.cpp create mode 100644 Tests/QtAutogen/mocPlugin/StyleE.hpp create mode 100644 Tests/QtAutogen/mocPlugin/jsonIn/StyleB.json create mode 100644 Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json create mode 100644 Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json create mode 100644 Tests/QtAutogen/mocPlugin/main.cpp hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 22 10:16:13 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 22 Feb 2017 10:16:13 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-438-g3879ac0 Message-ID: <20170222151614.53598F6162@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 3879ac06c57abcea65fd5a2ebfa36ee7a3ad1f9e (commit) via dfebdd6218d8f146277d75597fccde74b45cdbd2 (commit) via dc32ad198819a1f25487daa1787f08825bbafef8 (commit) via 8aac0ae7c52c6f1937f6192620933f546574c730 (commit) via 28df39ca8efbd3380e81977954aeda93ce53db10 (commit) from aa1fd4f3d25da106c6db053a01d479b065a7eaaf (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3879ac06c57abcea65fd5a2ebfa36ee7a3ad1f9e commit 3879ac06c57abcea65fd5a2ebfa36ee7a3ad1f9e Merge: aa1fd4f dfebdd6 Author: Brad King AuthorDate: Wed Feb 22 10:16:05 2017 -0500 Commit: Brad King CommitDate: Wed Feb 22 10:16:05 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 22 10:18:14 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 22 Feb 2017 10:18:14 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-244-gb803d00 Message-ID: <20170222151815.BD133F9FB9@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via b803d00bc1a6b5ff37867ea70cc3c0bda018ee2c (commit) via e9e8a5dc084b470a50ab4a16008db30022068fb0 (commit) via fe8f5b54f561de6fa8fed1186aa7ef3ce721b7d9 (commit) via 0f6ebb5c0fac9def6d7388e55960b92ab8f2644f (commit) via 0b6afec62bbc66052035207ce3b6a0516144c12d (commit) via 4caa0e7e75cb06a99c31a23500ae8e821ca6e13f (commit) via 2cffea3c72a18a19c4eb4950699c478af16fc5a7 (commit) from dfebdd6218d8f146277d75597fccde74b45cdbd2 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 22 10:18:15 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 22 Feb 2017 10:18:15 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-446-g656e565 Message-ID: <20170222151816.6FA4BF9FB4@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 656e56592b9aa049af9f2b9a06bf2c7fd0024cb2 (commit) via b803d00bc1a6b5ff37867ea70cc3c0bda018ee2c (commit) via e9e8a5dc084b470a50ab4a16008db30022068fb0 (commit) via fe8f5b54f561de6fa8fed1186aa7ef3ce721b7d9 (commit) via 0f6ebb5c0fac9def6d7388e55960b92ab8f2644f (commit) via 0b6afec62bbc66052035207ce3b6a0516144c12d (commit) via 4caa0e7e75cb06a99c31a23500ae8e821ca6e13f (commit) via 2cffea3c72a18a19c4eb4950699c478af16fc5a7 (commit) from 3879ac06c57abcea65fd5a2ebfa36ee7a3ad1f9e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=656e56592b9aa049af9f2b9a06bf2c7fd0024cb2 commit 656e56592b9aa049af9f2b9a06bf2c7fd0024cb2 Merge: 3879ac0 b803d00 Author: Brad King AuthorDate: Wed Feb 22 10:18:00 2017 -0500 Commit: Brad King CommitDate: Wed Feb 22 10:18:00 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 22 10:18:17 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 22 Feb 2017 10:18:17 -0500 (EST) Subject: [Cmake-commits] CMake branch, release, updated. v3.8.0-rc1-39-ge9e8a5d Message-ID: <20170222151819.28821F9FB4@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, release has been updated via e9e8a5dc084b470a50ab4a16008db30022068fb0 (commit) via 2da0838c64b6d43fd12eecb5d65ac458a335b266 (commit) via fe8f5b54f561de6fa8fed1186aa7ef3ce721b7d9 (commit) via 0f6ebb5c0fac9def6d7388e55960b92ab8f2644f (commit) via 0b6afec62bbc66052035207ce3b6a0516144c12d (commit) via c95d017f9c221f309a4b74d8a033c1e99e784f90 (commit) via 4b21290e204d02dd39f6ac404ba923d546f40925 (commit) via 08fa0b4595566a6e4c29c182865a6ec7e41d9e2e (commit) via 2ab118a8591d8b27ae89de8f3c65b5797fd01dc2 (commit) via 4caa0e7e75cb06a99c31a23500ae8e821ca6e13f (commit) via e2d78f7535951adc505014d3afde59b52caf35f1 (commit) via 2cffea3c72a18a19c4eb4950699c478af16fc5a7 (commit) via 96d6139386e22f672f14071eae3911fd7200f079 (commit) via 28bb68e3472a9f8c6d8eec894e85de74b976ff02 (commit) from 2c354f4ee44e9690ca6ed6c7266283bda1070ca4 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- Summary of changes: Modules/ExternalProject.cmake | 11 +++++++-- Modules/FindGTK2.cmake | 5 +++- Modules/FindHDF5.cmake | 6 ++--- Source/cmGlobalVisualStudio15Generator.cxx | 34 ++++++++++++++++++++++++++++ Source/cmGlobalVisualStudio15Generator.h | 4 ++++ Source/cmMakefile.cxx | 2 +- Source/cmMakefileTargetGenerator.cxx | 3 ++- Source/cmNinjaTargetGenerator.cxx | 3 ++- 8 files changed, 59 insertions(+), 9 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 22 10:36:20 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 22 Feb 2017 10:36:20 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-448-gd30e66c Message-ID: <20170222153620.A8225FA64F@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via d30e66c0e3e078fe43aa85db09449260226611db (commit) via 934eb497f211b2e48ba070041ba775e1ac55d01d (commit) from 656e56592b9aa049af9f2b9a06bf2c7fd0024cb2 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d30e66c0e3e078fe43aa85db09449260226611db commit d30e66c0e3e078fe43aa85db09449260226611db Merge: 656e565 934eb49 Author: Brad King AuthorDate: Wed Feb 22 10:36:18 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 22 10:36:18 2017 -0500 Merge topic 'FindCUDA-fix-init' into next 934eb497 FindCUDA: Fix PTX selection with multiple architectures https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=934eb497f211b2e48ba070041ba775e1ac55d01d commit 934eb497f211b2e48ba070041ba775e1ac55d01d Author: Bjoern Thiel AuthorDate: Wed Feb 22 09:11:34 2017 +0100 Commit: Brad King CommitDate: Wed Feb 22 10:35:44 2017 -0500 FindCUDA: Fix PTX selection with multiple architectures diff --git a/Modules/FindCUDA/select_compute_arch.cmake b/Modules/FindCUDA/select_compute_arch.cmake index a96a8ca..8fb44d8 100644 --- a/Modules/FindCUDA/select_compute_arch.cmake +++ b/Modules/FindCUDA/select_compute_arch.cmake @@ -112,6 +112,7 @@ function(CUDA_SELECT_NVCC_ARCH_FLAGS out_variable) list(REMOVE_DUPLICATES CUDA_ARCH_LIST) foreach(arch_name ${CUDA_ARCH_LIST}) set(arch_bin) + set(arch_ptx) set(add_ptx FALSE) # Check to see if we are compiling PTX if(arch_name MATCHES "(.*)\\+PTX$") ----------------------------------------------------------------------- Summary of changes: Modules/FindCUDA/select_compute_arch.cmake | 1 + 1 file changed, 1 insertion(+) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 22 10:40:57 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 22 Feb 2017 10:40:57 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-451-g1925f8b Message-ID: <20170222154057.A5138BB365@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 1925f8bc2a517c051c44b29021300de2238489a2 (commit) via 741b7621b3c71406359d75098f9bdf8d3567662f (commit) via 1f661e87a6a8304edb77bd30b546e5d113477c59 (commit) from d30e66c0e3e078fe43aa85db09449260226611db (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1925f8bc2a517c051c44b29021300de2238489a2 commit 1925f8bc2a517c051c44b29021300de2238489a2 Merge: d30e66c 741b762 Author: Brad King AuthorDate: Wed Feb 22 10:40:48 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 22 10:40:48 2017 -0500 Merge topic 'update-libuv' into next 741b7621 Merge branch 'upstream-libuv' into update-libuv 1f661e87 libuv 2017-02-21 (52ae8264) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=741b7621b3c71406359d75098f9bdf8d3567662f commit 741b7621b3c71406359d75098f9bdf8d3567662f Merge: 3ccad39 1f661e8 Author: Brad King AuthorDate: Tue Feb 21 19:38:46 2017 -0500 Commit: Brad King CommitDate: Tue Feb 21 19:40:27 2017 -0500 Merge branch 'upstream-libuv' into update-libuv * upstream-libuv: libuv 2017-02-21 (52ae8264) diff --cc Utilities/cmlibuv/include/uv-win.h index 89ee09a,0000000..d3e32a5 mode 100644,000000..100644 --- a/Utilities/cmlibuv/include/uv-win.h +++ b/Utilities/cmlibuv/include/uv-win.h @@@ -1,660 -1,0 +1,661 @@@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x0502 +#endif + +#if !defined(_SSIZE_T_) && !defined(_SSIZE_T_DEFINED) +typedef intptr_t ssize_t; +# define _SSIZE_T_ +# define _SSIZE_T_DEFINED +#endif + +#include + +#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) +typedef struct pollfd { + SOCKET fd; + short events; + short revents; +} WSAPOLLFD, *PWSAPOLLFD, *LPWSAPOLLFD; +#endif + +#ifndef LOCALE_INVARIANT +# define LOCALE_INVARIANT 0x007f +#endif + +#include +#include +#include + +#include +#include ++#include +#include + +#if defined(_MSC_VER) && _MSC_VER < 1600 +# include "stdint-msvc2008.h" +#else +# include +#endif + +#include "tree.h" +#include "uv-threadpool.h" + +#define MAX_PIPENAME_LEN 256 + +#ifndef S_IFLNK +# define S_IFLNK 0xA000 +#endif + +/* Additional signals supported by uv_signal and or uv_kill. The CRT defines + * the following signals already: + * + * #define SIGINT 2 + * #define SIGILL 4 + * #define SIGABRT_COMPAT 6 + * #define SIGFPE 8 + * #define SIGSEGV 11 + * #define SIGTERM 15 + * #define SIGBREAK 21 + * #define SIGABRT 22 + * + * The additional signals have values that are common on other Unix + * variants (Linux and Darwin) + */ +#define SIGHUP 1 +#define SIGKILL 9 +#define SIGWINCH 28 + +/* The CRT defines SIGABRT_COMPAT as 6, which equals SIGABRT on many */ +/* unix-like platforms. However MinGW doesn't define it, so we do. */ +#ifndef SIGABRT_COMPAT +# define SIGABRT_COMPAT 6 +#endif + +/* + * Guids and typedefs for winsock extension functions + * Mingw32 doesn't have these :-( + */ +#ifndef WSAID_ACCEPTEX +# define WSAID_ACCEPTEX \ + {0xb5367df1, 0xcbac, 0x11cf, \ + {0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}} +#endif + +#ifndef WSAID_CONNECTEX +# define WSAID_CONNECTEX \ + {0x25a207b9, 0xddf3, 0x4660, \ + {0x8e, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e}} +#endif + +#ifndef WSAID_GETACCEPTEXSOCKADDRS +# define WSAID_GETACCEPTEXSOCKADDRS \ + {0xb5367df2, 0xcbac, 0x11cf, \ + {0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}} +#endif + +#ifndef WSAID_DISCONNECTEX +# define WSAID_DISCONNECTEX \ + {0x7fda2e11, 0x8630, 0x436f, \ + {0xa0, 0x31, 0xf5, 0x36, 0xa6, 0xee, 0xc1, 0x57}} +#endif + +#ifndef WSAID_TRANSMITFILE +# define WSAID_TRANSMITFILE \ + {0xb5367df0, 0xcbac, 0x11cf, \ + {0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}} +#endif + +#if (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)) \ + || (defined(_MSC_VER) && _MSC_VER < 1500) + typedef BOOL (PASCAL *LPFN_ACCEPTEX) + (SOCKET sListenSocket, + SOCKET sAcceptSocket, + PVOID lpOutputBuffer, + DWORD dwReceiveDataLength, + DWORD dwLocalAddressLength, + DWORD dwRemoteAddressLength, + LPDWORD lpdwBytesReceived, + LPOVERLAPPED lpOverlapped); + + typedef BOOL (PASCAL *LPFN_CONNECTEX) + (SOCKET s, + const struct sockaddr* name, + int namelen, + PVOID lpSendBuffer, + DWORD dwSendDataLength, + LPDWORD lpdwBytesSent, + LPOVERLAPPED lpOverlapped); + + typedef void (PASCAL *LPFN_GETACCEPTEXSOCKADDRS) + (PVOID lpOutputBuffer, + DWORD dwReceiveDataLength, + DWORD dwLocalAddressLength, + DWORD dwRemoteAddressLength, + LPSOCKADDR* LocalSockaddr, + LPINT LocalSockaddrLength, + LPSOCKADDR* RemoteSockaddr, + LPINT RemoteSockaddrLength); + + typedef BOOL (PASCAL *LPFN_DISCONNECTEX) + (SOCKET hSocket, + LPOVERLAPPED lpOverlapped, + DWORD dwFlags, + DWORD reserved); + + typedef BOOL (PASCAL *LPFN_TRANSMITFILE) + (SOCKET hSocket, + HANDLE hFile, + DWORD nNumberOfBytesToWrite, + DWORD nNumberOfBytesPerSend, + LPOVERLAPPED lpOverlapped, + LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers, + DWORD dwFlags); + + typedef PVOID RTL_SRWLOCK; + typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK; +#endif + +typedef int (WSAAPI* LPFN_WSARECV) + (SOCKET socket, + LPWSABUF buffers, + DWORD buffer_count, + LPDWORD bytes, + LPDWORD flags, + LPWSAOVERLAPPED overlapped, + LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine); + +typedef int (WSAAPI* LPFN_WSARECVFROM) + (SOCKET socket, + LPWSABUF buffers, + DWORD buffer_count, + LPDWORD bytes, + LPDWORD flags, + struct sockaddr* addr, + LPINT addr_len, + LPWSAOVERLAPPED overlapped, + LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine); + +#ifndef _NTDEF_ + typedef LONG NTSTATUS; + typedef NTSTATUS *PNTSTATUS; +#endif + +#ifndef RTL_CONDITION_VARIABLE_INIT + typedef PVOID CONDITION_VARIABLE, *PCONDITION_VARIABLE; +#endif + +typedef struct _AFD_POLL_HANDLE_INFO { + HANDLE Handle; + ULONG Events; + NTSTATUS Status; +} AFD_POLL_HANDLE_INFO, *PAFD_POLL_HANDLE_INFO; + +typedef struct _AFD_POLL_INFO { + LARGE_INTEGER Timeout; + ULONG NumberOfHandles; + ULONG Exclusive; + AFD_POLL_HANDLE_INFO Handles[1]; +} AFD_POLL_INFO, *PAFD_POLL_INFO; + +#define UV_MSAFD_PROVIDER_COUNT 3 + + +/** + * It should be possible to cast uv_buf_t[] to WSABUF[] + * see http://msdn.microsoft.com/en-us/library/ms741542(v=vs.85).aspx + */ +typedef struct uv_buf_t { + ULONG len; + char* base; +} uv_buf_t; + +typedef int uv_file; +typedef SOCKET uv_os_sock_t; +typedef HANDLE uv_os_fd_t; + +typedef HANDLE uv_thread_t; + +typedef HANDLE uv_sem_t; + +typedef CRITICAL_SECTION uv_mutex_t; + +/* This condition variable implementation is based on the SetEvent solution + * (section 3.2) at http://www.cs.wustl.edu/~schmidt/win32-cv-1.html + * We could not use the SignalObjectAndWait solution (section 3.4) because + * it want the 2nd argument (type uv_mutex_t) of uv_cond_wait() and + * uv_cond_timedwait() to be HANDLEs, but we use CRITICAL_SECTIONs. + */ + +typedef union { + CONDITION_VARIABLE cond_var; + struct { + unsigned int waiters_count; + CRITICAL_SECTION waiters_count_lock; + HANDLE signal_event; + HANDLE broadcast_event; + } fallback; +} uv_cond_t; + +typedef union { + struct { + unsigned int num_readers_; + CRITICAL_SECTION num_readers_lock_; + HANDLE write_semaphore_; + } state_; + /* TODO: remove me in v2.x. */ + struct { + SRWLOCK unused_; + } unused1_; + /* TODO: remove me in v2.x. */ + struct { + uv_mutex_t unused1_; + uv_mutex_t unused2_; + } unused2_; +} uv_rwlock_t; + +typedef struct { + unsigned int n; + unsigned int count; + uv_mutex_t mutex; + uv_sem_t turnstile1; + uv_sem_t turnstile2; +} uv_barrier_t; + +typedef struct { + DWORD tls_index; +} uv_key_t; + +#define UV_ONCE_INIT { 0, NULL } + +typedef struct uv_once_s { + unsigned char ran; + HANDLE event; +} uv_once_t; + +/* Platform-specific definitions for uv_spawn support. */ +typedef unsigned char uv_uid_t; +typedef unsigned char uv_gid_t; + +typedef struct uv__dirent_s { + int d_type; + char d_name[1]; +} uv__dirent_t; + +#define HAVE_DIRENT_TYPES +#define UV__DT_DIR UV_DIRENT_DIR +#define UV__DT_FILE UV_DIRENT_FILE +#define UV__DT_LINK UV_DIRENT_LINK +#define UV__DT_FIFO UV_DIRENT_FIFO +#define UV__DT_SOCKET UV_DIRENT_SOCKET +#define UV__DT_CHAR UV_DIRENT_CHAR +#define UV__DT_BLOCK UV_DIRENT_BLOCK + +/* Platform-specific definitions for uv_dlopen support. */ +#define UV_DYNAMIC FAR WINAPI +typedef struct { + HMODULE handle; + char* errmsg; +} uv_lib_t; + +RB_HEAD(uv_timer_tree_s, uv_timer_s); + +#define UV_LOOP_PRIVATE_FIELDS \ + /* The loop's I/O completion port */ \ + HANDLE iocp; \ + /* The current time according to the event loop. in msecs. */ \ + uint64_t time; \ + /* Tail of a single-linked circular queue of pending reqs. If the queue */ \ + /* is empty, tail_ is NULL. If there is only one item, */ \ + /* tail_->next_req == tail_ */ \ + uv_req_t* pending_reqs_tail; \ + /* Head of a single-linked list of closed handles */ \ + uv_handle_t* endgame_handles; \ + /* The head of the timers tree */ \ + struct uv_timer_tree_s timers; \ + /* Lists of active loop (prepare / check / idle) watchers */ \ + uv_prepare_t* prepare_handles; \ + uv_check_t* check_handles; \ + uv_idle_t* idle_handles; \ + /* This pointer will refer to the prepare/check/idle handle whose */ \ + /* callback is scheduled to be called next. This is needed to allow */ \ + /* safe removal from one of the lists above while that list being */ \ + /* iterated over. */ \ + uv_prepare_t* next_prepare_handle; \ + uv_check_t* next_check_handle; \ + uv_idle_t* next_idle_handle; \ + /* This handle holds the peer sockets for the fast variant of uv_poll_t */ \ + SOCKET poll_peer_sockets[UV_MSAFD_PROVIDER_COUNT]; \ + /* Counter to keep track of active tcp streams */ \ + unsigned int active_tcp_streams; \ + /* Counter to keep track of active udp streams */ \ + unsigned int active_udp_streams; \ + /* Counter to started timer */ \ + uint64_t timer_counter; \ + /* Threadpool */ \ + void* wq[2]; \ + uv_mutex_t wq_mutex; \ + uv_async_t wq_async; + +#define UV_REQ_TYPE_PRIVATE \ + /* TODO: remove the req suffix */ \ + UV_ACCEPT, \ + UV_FS_EVENT_REQ, \ + UV_POLL_REQ, \ + UV_PROCESS_EXIT, \ + UV_READ, \ + UV_UDP_RECV, \ + UV_WAKEUP, \ + UV_SIGNAL_REQ, + +#define UV_REQ_PRIVATE_FIELDS \ + union { \ + /* Used by I/O operations */ \ + struct { \ + OVERLAPPED overlapped; \ + size_t queued_bytes; \ + } io; \ + } u; \ + struct uv_req_s* next_req; + +#define UV_WRITE_PRIVATE_FIELDS \ + int ipc_header; \ + uv_buf_t write_buffer; \ + HANDLE event_handle; \ + HANDLE wait_handle; + +#define UV_CONNECT_PRIVATE_FIELDS \ + /* empty */ + +#define UV_SHUTDOWN_PRIVATE_FIELDS \ + /* empty */ + +#define UV_UDP_SEND_PRIVATE_FIELDS \ + /* empty */ + +#define UV_PRIVATE_REQ_TYPES \ + typedef struct uv_pipe_accept_s { \ + UV_REQ_FIELDS \ + HANDLE pipeHandle; \ + struct uv_pipe_accept_s* next_pending; \ + } uv_pipe_accept_t; \ + \ + typedef struct uv_tcp_accept_s { \ + UV_REQ_FIELDS \ + SOCKET accept_socket; \ + char accept_buffer[sizeof(struct sockaddr_storage) * 2 + 32]; \ + HANDLE event_handle; \ + HANDLE wait_handle; \ + struct uv_tcp_accept_s* next_pending; \ + } uv_tcp_accept_t; \ + \ + typedef struct uv_read_s { \ + UV_REQ_FIELDS \ + HANDLE event_handle; \ + HANDLE wait_handle; \ + } uv_read_t; + +#define uv_stream_connection_fields \ + unsigned int write_reqs_pending; \ + uv_shutdown_t* shutdown_req; + +#define uv_stream_server_fields \ + uv_connection_cb connection_cb; + +#define UV_STREAM_PRIVATE_FIELDS \ + unsigned int reqs_pending; \ + int activecnt; \ + uv_read_t read_req; \ + union { \ + struct { uv_stream_connection_fields } conn; \ + struct { uv_stream_server_fields } serv; \ + } stream; + +#define uv_tcp_server_fields \ + uv_tcp_accept_t* accept_reqs; \ + unsigned int processed_accepts; \ + uv_tcp_accept_t* pending_accepts; \ + LPFN_ACCEPTEX func_acceptex; + +#define uv_tcp_connection_fields \ + uv_buf_t read_buffer; \ + LPFN_CONNECTEX func_connectex; + +#define UV_TCP_PRIVATE_FIELDS \ + SOCKET socket; \ + int delayed_error; \ + union { \ + struct { uv_tcp_server_fields } serv; \ + struct { uv_tcp_connection_fields } conn; \ + } tcp; + +#define UV_UDP_PRIVATE_FIELDS \ + SOCKET socket; \ + unsigned int reqs_pending; \ + int activecnt; \ + uv_req_t recv_req; \ + uv_buf_t recv_buffer; \ + struct sockaddr_storage recv_from; \ + int recv_from_len; \ + uv_udp_recv_cb recv_cb; \ + uv_alloc_cb alloc_cb; \ + LPFN_WSARECV func_wsarecv; \ + LPFN_WSARECVFROM func_wsarecvfrom; + +#define uv_pipe_server_fields \ + int pending_instances; \ + uv_pipe_accept_t* accept_reqs; \ + uv_pipe_accept_t* pending_accepts; + +#define uv_pipe_connection_fields \ + uv_timer_t* eof_timer; \ + uv_write_t ipc_header_write_req; \ + int ipc_pid; \ + uint64_t remaining_ipc_rawdata_bytes; \ + struct { \ + void* queue[2]; \ + int queue_len; \ + } pending_ipc_info; \ + uv_write_t* non_overlapped_writes_tail; \ + uv_mutex_t readfile_mutex; \ + volatile HANDLE readfile_thread; + +#define UV_PIPE_PRIVATE_FIELDS \ + HANDLE handle; \ + WCHAR* name; \ + union { \ + struct { uv_pipe_server_fields } serv; \ + struct { uv_pipe_connection_fields } conn; \ + } pipe; + +/* TODO: put the parser states in an union - TTY handles are always */ +/* half-duplex so read-state can safely overlap write-state. */ +#define UV_TTY_PRIVATE_FIELDS \ + HANDLE handle; \ + union { \ + struct { \ + /* Used for readable TTY handles */ \ + /* TODO: remove me in v2.x. */ \ + HANDLE unused_; \ + uv_buf_t read_line_buffer; \ + HANDLE read_raw_wait; \ + /* Fields used for translating win keystrokes into vt100 characters */ \ + char last_key[8]; \ + unsigned char last_key_offset; \ + unsigned char last_key_len; \ + WCHAR last_utf16_high_surrogate; \ + INPUT_RECORD last_input_record; \ + } rd; \ + struct { \ + /* Used for writable TTY handles */ \ + /* utf8-to-utf16 conversion state */ \ + unsigned int utf8_codepoint; \ + unsigned char utf8_bytes_left; \ + /* eol conversion state */ \ + unsigned char previous_eol; \ + /* ansi parser state */ \ + unsigned char ansi_parser_state; \ + unsigned char ansi_csi_argc; \ + unsigned short ansi_csi_argv[4]; \ + COORD saved_position; \ + WORD saved_attributes; \ + } wr; \ + } tty; + +#define UV_POLL_PRIVATE_FIELDS \ + SOCKET socket; \ + /* Used in fast mode */ \ + SOCKET peer_socket; \ + AFD_POLL_INFO afd_poll_info_1; \ + AFD_POLL_INFO afd_poll_info_2; \ + /* Used in fast and slow mode. */ \ + uv_req_t poll_req_1; \ + uv_req_t poll_req_2; \ + unsigned char submitted_events_1; \ + unsigned char submitted_events_2; \ + unsigned char mask_events_1; \ + unsigned char mask_events_2; \ + unsigned char events; + +#define UV_TIMER_PRIVATE_FIELDS \ + RB_ENTRY(uv_timer_s) tree_entry; \ + uint64_t due; \ + uint64_t repeat; \ + uint64_t start_id; \ + uv_timer_cb timer_cb; + +#define UV_ASYNC_PRIVATE_FIELDS \ + struct uv_req_s async_req; \ + uv_async_cb async_cb; \ + /* char to avoid alignment issues */ \ + char volatile async_sent; + +#define UV_PREPARE_PRIVATE_FIELDS \ + uv_prepare_t* prepare_prev; \ + uv_prepare_t* prepare_next; \ + uv_prepare_cb prepare_cb; + +#define UV_CHECK_PRIVATE_FIELDS \ + uv_check_t* check_prev; \ + uv_check_t* check_next; \ + uv_check_cb check_cb; + +#define UV_IDLE_PRIVATE_FIELDS \ + uv_idle_t* idle_prev; \ + uv_idle_t* idle_next; \ + uv_idle_cb idle_cb; + +#define UV_HANDLE_PRIVATE_FIELDS \ + uv_handle_t* endgame_next; \ + unsigned int flags; + +#define UV_GETADDRINFO_PRIVATE_FIELDS \ + struct uv__work work_req; \ + uv_getaddrinfo_cb getaddrinfo_cb; \ + void* alloc; \ + WCHAR* node; \ + WCHAR* service; \ + /* The addrinfoW field is used to store a pointer to the hints, and */ \ + /* later on to store the result of GetAddrInfoW. The final result will */ \ + /* be converted to struct addrinfo* and stored in the addrinfo field. */ \ + struct addrinfoW* addrinfow; \ + struct addrinfo* addrinfo; \ + int retcode; + +#define UV_GETNAMEINFO_PRIVATE_FIELDS \ + struct uv__work work_req; \ + uv_getnameinfo_cb getnameinfo_cb; \ + struct sockaddr_storage storage; \ + int flags; \ + char host[NI_MAXHOST]; \ + char service[NI_MAXSERV]; \ + int retcode; + +#define UV_PROCESS_PRIVATE_FIELDS \ + struct uv_process_exit_s { \ + UV_REQ_FIELDS \ + } exit_req; \ + BYTE* child_stdio_buffer; \ + int exit_signal; \ + HANDLE wait_handle; \ + HANDLE process_handle; \ + volatile char exit_cb_pending; + +#define UV_FS_PRIVATE_FIELDS \ + struct uv__work work_req; \ + int flags; \ + DWORD sys_errno_; \ + union { \ + /* TODO: remove me in 0.9. */ \ + WCHAR* pathw; \ + int fd; \ + } file; \ + union { \ + struct { \ + int mode; \ + WCHAR* new_pathw; \ + int file_flags; \ + int fd_out; \ + unsigned int nbufs; \ + uv_buf_t* bufs; \ + int64_t offset; \ + uv_buf_t bufsml[4]; \ + } info; \ + struct { \ + double atime; \ + double mtime; \ + } time; \ + } fs; + +#define UV_WORK_PRIVATE_FIELDS \ + struct uv__work work_req; + +#define UV_FS_EVENT_PRIVATE_FIELDS \ + struct uv_fs_event_req_s { \ + UV_REQ_FIELDS \ + } req; \ + HANDLE dir_handle; \ + int req_pending; \ + uv_fs_event_cb cb; \ + WCHAR* filew; \ + WCHAR* short_filew; \ + WCHAR* dirw; \ + char* buffer; + +#define UV_SIGNAL_PRIVATE_FIELDS \ + RB_ENTRY(uv_signal_s) tree_entry; \ + struct uv_req_s signal_req; \ + unsigned long pending_signum; + +#ifndef F_OK +#define F_OK 0 +#endif +#ifndef R_OK +#define R_OK 4 +#endif +#ifndef W_OK +#define W_OK 2 +#endif +#ifndef X_OK +#define X_OK 1 +#endif diff --cc Utilities/cmlibuv/include/uv.h index e3e20dc,0000000..5879764 mode 100644,000000..100644 --- a/Utilities/cmlibuv/include/uv.h +++ b/Utilities/cmlibuv/include/uv.h @@@ -1,1499 -1,0 +1,1501 @@@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/* See https://github.com/libuv/libuv#documentation for documentation. */ + +#ifndef UV_H +#define UV_H + +/* Include KWSys Large File Support configuration. */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _WIN32 + /* Windows - set up dll import/export decorators. */ +# if defined(BUILDING_UV_SHARED) + /* Building shared library. */ +# define UV_EXTERN __declspec(dllexport) +# elif defined(USING_UV_SHARED) + /* Using shared library. */ +# define UV_EXTERN __declspec(dllimport) +# else + /* Building static library. */ +# define UV_EXTERN /* nothing */ +# endif +#elif __GNUC__ >= 4 +# define UV_EXTERN __attribute__((visibility("default"))) +#else +# define UV_EXTERN /* nothing */ +#endif + +#include "uv-errno.h" +#include "uv-version.h" +#include +#include + +#if defined(_MSC_VER) && _MSC_VER < 1600 +# include "stdint-msvc2008.h" +#else +# include +#endif + +#if defined(_WIN32) +# include "uv-win.h" +#else +# include "uv-unix.h" +#endif + +/* Expand this list if necessary. */ +#define UV_ERRNO_MAP(XX) \ + XX(E2BIG, "argument list too long") \ + XX(EACCES, "permission denied") \ + XX(EADDRINUSE, "address already in use") \ + XX(EADDRNOTAVAIL, "address not available") \ + XX(EAFNOSUPPORT, "address family not supported") \ + XX(EAGAIN, "resource temporarily unavailable") \ + XX(EAI_ADDRFAMILY, "address family not supported") \ + XX(EAI_AGAIN, "temporary failure") \ + XX(EAI_BADFLAGS, "bad ai_flags value") \ + XX(EAI_BADHINTS, "invalid value for hints") \ + XX(EAI_CANCELED, "request canceled") \ + XX(EAI_FAIL, "permanent failure") \ + XX(EAI_FAMILY, "ai_family not supported") \ + XX(EAI_MEMORY, "out of memory") \ + XX(EAI_NODATA, "no address") \ + XX(EAI_NONAME, "unknown node or service") \ + XX(EAI_OVERFLOW, "argument buffer overflow") \ + XX(EAI_PROTOCOL, "resolved protocol is unknown") \ + XX(EAI_SERVICE, "service not available for socket type") \ + XX(EAI_SOCKTYPE, "socket type not supported") \ + XX(EALREADY, "connection already in progress") \ + XX(EBADF, "bad file descriptor") \ + XX(EBUSY, "resource busy or locked") \ + XX(ECANCELED, "operation canceled") \ + XX(ECHARSET, "invalid Unicode character") \ + XX(ECONNABORTED, "software caused connection abort") \ + XX(ECONNREFUSED, "connection refused") \ + XX(ECONNRESET, "connection reset by peer") \ + XX(EDESTADDRREQ, "destination address required") \ + XX(EEXIST, "file already exists") \ + XX(EFAULT, "bad address in system call argument") \ + XX(EFBIG, "file too large") \ + XX(EHOSTUNREACH, "host is unreachable") \ + XX(EINTR, "interrupted system call") \ + XX(EINVAL, "invalid argument") \ + XX(EIO, "i/o error") \ + XX(EISCONN, "socket is already connected") \ + XX(EISDIR, "illegal operation on a directory") \ + XX(ELOOP, "too many symbolic links encountered") \ + XX(EMFILE, "too many open files") \ + XX(EMSGSIZE, "message too long") \ + XX(ENAMETOOLONG, "name too long") \ + XX(ENETDOWN, "network is down") \ + XX(ENETUNREACH, "network is unreachable") \ + XX(ENFILE, "file table overflow") \ + XX(ENOBUFS, "no buffer space available") \ + XX(ENODEV, "no such device") \ + XX(ENOENT, "no such file or directory") \ + XX(ENOMEM, "not enough memory") \ + XX(ENONET, "machine is not on the network") \ + XX(ENOPROTOOPT, "protocol not available") \ + XX(ENOSPC, "no space left on device") \ + XX(ENOSYS, "function not implemented") \ + XX(ENOTCONN, "socket is not connected") \ + XX(ENOTDIR, "not a directory") \ + XX(ENOTEMPTY, "directory not empty") \ + XX(ENOTSOCK, "socket operation on non-socket") \ + XX(ENOTSUP, "operation not supported on socket") \ + XX(EPERM, "operation not permitted") \ + XX(EPIPE, "broken pipe") \ + XX(EPROTO, "protocol error") \ + XX(EPROTONOSUPPORT, "protocol not supported") \ + XX(EPROTOTYPE, "protocol wrong type for socket") \ + XX(ERANGE, "result too large") \ + XX(EROFS, "read-only file system") \ + XX(ESHUTDOWN, "cannot send after transport endpoint shutdown") \ + XX(ESPIPE, "invalid seek") \ + XX(ESRCH, "no such process") \ + XX(ETIMEDOUT, "connection timed out") \ + XX(ETXTBSY, "text file is busy") \ + XX(EXDEV, "cross-device link not permitted") \ + XX(UNKNOWN, "unknown error") \ + XX(EOF, "end of file") \ + XX(ENXIO, "no such device or address") \ + XX(EMLINK, "too many links") \ + XX(EHOSTDOWN, "host is down") \ + +#define UV_HANDLE_TYPE_MAP(XX) \ + XX(ASYNC, async) \ + XX(CHECK, check) \ + XX(FS_EVENT, fs_event) \ + XX(FS_POLL, fs_poll) \ + XX(HANDLE, handle) \ + XX(IDLE, idle) \ + XX(NAMED_PIPE, pipe) \ + XX(POLL, poll) \ + XX(PREPARE, prepare) \ + XX(PROCESS, process) \ + XX(STREAM, stream) \ + XX(TCP, tcp) \ + XX(TIMER, timer) \ + XX(TTY, tty) \ + XX(UDP, udp) \ + XX(SIGNAL, signal) \ + +#define UV_REQ_TYPE_MAP(XX) \ + XX(REQ, req) \ + XX(CONNECT, connect) \ + XX(WRITE, write) \ + XX(SHUTDOWN, shutdown) \ + XX(UDP_SEND, udp_send) \ + XX(FS, fs) \ + XX(WORK, work) \ + XX(GETADDRINFO, getaddrinfo) \ + XX(GETNAMEINFO, getnameinfo) \ + +typedef enum { +#define XX(code, _) UV_ ## code = UV__ ## code, + UV_ERRNO_MAP(XX) +#undef XX + UV_ERRNO_MAX = UV__EOF - 1 +} uv_errno_t; + +typedef enum { + UV_UNKNOWN_HANDLE = 0, +#define XX(uc, lc) UV_##uc, + UV_HANDLE_TYPE_MAP(XX) +#undef XX + UV_FILE, + UV_HANDLE_TYPE_MAX +} uv_handle_type; + +typedef enum { + UV_UNKNOWN_REQ = 0, +#define XX(uc, lc) UV_##uc, + UV_REQ_TYPE_MAP(XX) +#undef XX + UV_REQ_TYPE_PRIVATE + UV_REQ_TYPE_MAX +} uv_req_type; + + +/* Handle types. */ +typedef struct uv_loop_s uv_loop_t; +typedef struct uv_handle_s uv_handle_t; +typedef struct uv_stream_s uv_stream_t; +typedef struct uv_tcp_s uv_tcp_t; +typedef struct uv_udp_s uv_udp_t; +typedef struct uv_pipe_s uv_pipe_t; +typedef struct uv_tty_s uv_tty_t; +typedef struct uv_poll_s uv_poll_t; +typedef struct uv_timer_s uv_timer_t; +typedef struct uv_prepare_s uv_prepare_t; +typedef struct uv_check_s uv_check_t; +typedef struct uv_idle_s uv_idle_t; +typedef struct uv_async_s uv_async_t; +typedef struct uv_process_s uv_process_t; +typedef struct uv_fs_event_s uv_fs_event_t; +typedef struct uv_fs_poll_s uv_fs_poll_t; +typedef struct uv_signal_s uv_signal_t; + +/* Request types. */ +typedef struct uv_req_s uv_req_t; +typedef struct uv_getaddrinfo_s uv_getaddrinfo_t; +typedef struct uv_getnameinfo_s uv_getnameinfo_t; +typedef struct uv_shutdown_s uv_shutdown_t; +typedef struct uv_write_s uv_write_t; +typedef struct uv_connect_s uv_connect_t; +typedef struct uv_udp_send_s uv_udp_send_t; +typedef struct uv_fs_s uv_fs_t; +typedef struct uv_work_s uv_work_t; + +/* None of the above. */ +typedef struct uv_cpu_info_s uv_cpu_info_t; +typedef struct uv_interface_address_s uv_interface_address_t; +typedef struct uv_dirent_s uv_dirent_t; +typedef struct uv_passwd_s uv_passwd_t; + +typedef enum { + UV_LOOP_BLOCK_SIGNAL +} uv_loop_option; + +typedef enum { + UV_RUN_DEFAULT = 0, + UV_RUN_ONCE, + UV_RUN_NOWAIT +} uv_run_mode; + + +UV_EXTERN unsigned int uv_version(void); +UV_EXTERN const char* uv_version_string(void); + +typedef void* (*uv_malloc_func)(size_t size); +typedef void* (*uv_realloc_func)(void* ptr, size_t size); +typedef void* (*uv_calloc_func)(size_t count, size_t size); +typedef void (*uv_free_func)(void* ptr); + +UV_EXTERN int uv_replace_allocator(uv_malloc_func malloc_func, + uv_realloc_func realloc_func, + uv_calloc_func calloc_func, + uv_free_func free_func); + +UV_EXTERN uv_loop_t* uv_default_loop(void); +UV_EXTERN int uv_loop_init(uv_loop_t* loop); +UV_EXTERN int uv_loop_close(uv_loop_t* loop); +/* + * NOTE: + * This function is DEPRECATED (to be removed after 0.12), users should + * allocate the loop manually and use uv_loop_init instead. + */ +UV_EXTERN uv_loop_t* uv_loop_new(void); +/* + * NOTE: + * This function is DEPRECATED (to be removed after 0.12). Users should use + * uv_loop_close and free the memory manually instead. + */ +UV_EXTERN void uv_loop_delete(uv_loop_t*); +UV_EXTERN size_t uv_loop_size(void); +UV_EXTERN int uv_loop_alive(const uv_loop_t* loop); +UV_EXTERN int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...); + +UV_EXTERN int uv_run(uv_loop_t*, uv_run_mode mode); +UV_EXTERN void uv_stop(uv_loop_t*); + +UV_EXTERN void uv_ref(uv_handle_t*); +UV_EXTERN void uv_unref(uv_handle_t*); +UV_EXTERN int uv_has_ref(const uv_handle_t*); + +UV_EXTERN void uv_update_time(uv_loop_t*); +UV_EXTERN uint64_t uv_now(const uv_loop_t*); + +UV_EXTERN int uv_backend_fd(const uv_loop_t*); +UV_EXTERN int uv_backend_timeout(const uv_loop_t*); + +typedef void (*uv_alloc_cb)(uv_handle_t* handle, + size_t suggested_size, + uv_buf_t* buf); +typedef void (*uv_read_cb)(uv_stream_t* stream, + ssize_t nread, + const uv_buf_t* buf); +typedef void (*uv_write_cb)(uv_write_t* req, int status); +typedef void (*uv_connect_cb)(uv_connect_t* req, int status); +typedef void (*uv_shutdown_cb)(uv_shutdown_t* req, int status); +typedef void (*uv_connection_cb)(uv_stream_t* server, int status); +typedef void (*uv_close_cb)(uv_handle_t* handle); +typedef void (*uv_poll_cb)(uv_poll_t* handle, int status, int events); +typedef void (*uv_timer_cb)(uv_timer_t* handle); +typedef void (*uv_async_cb)(uv_async_t* handle); +typedef void (*uv_prepare_cb)(uv_prepare_t* handle); +typedef void (*uv_check_cb)(uv_check_t* handle); +typedef void (*uv_idle_cb)(uv_idle_t* handle); +typedef void (*uv_exit_cb)(uv_process_t*, int64_t exit_status, int term_signal); +typedef void (*uv_walk_cb)(uv_handle_t* handle, void* arg); +typedef void (*uv_fs_cb)(uv_fs_t* req); +typedef void (*uv_work_cb)(uv_work_t* req); +typedef void (*uv_after_work_cb)(uv_work_t* req, int status); +typedef void (*uv_getaddrinfo_cb)(uv_getaddrinfo_t* req, + int status, + struct addrinfo* res); +typedef void (*uv_getnameinfo_cb)(uv_getnameinfo_t* req, + int status, + const char* hostname, + const char* service); + +typedef struct { + long tv_sec; + long tv_nsec; +} uv_timespec_t; + + +typedef struct { + uint64_t st_dev; + uint64_t st_mode; + uint64_t st_nlink; + uint64_t st_uid; + uint64_t st_gid; + uint64_t st_rdev; + uint64_t st_ino; + uint64_t st_size; + uint64_t st_blksize; + uint64_t st_blocks; + uint64_t st_flags; + uint64_t st_gen; + uv_timespec_t st_atim; + uv_timespec_t st_mtim; + uv_timespec_t st_ctim; + uv_timespec_t st_birthtim; +} uv_stat_t; + + +typedef void (*uv_fs_event_cb)(uv_fs_event_t* handle, + const char* filename, + int events, + int status); + +typedef void (*uv_fs_poll_cb)(uv_fs_poll_t* handle, + int status, + const uv_stat_t* prev, + const uv_stat_t* curr); + +typedef void (*uv_signal_cb)(uv_signal_t* handle, int signum); + + +typedef enum { + UV_LEAVE_GROUP = 0, + UV_JOIN_GROUP +} uv_membership; + + ++UV_EXTERN int uv_translate_sys_error(int sys_errno); ++ +UV_EXTERN const char* uv_strerror(int err); +UV_EXTERN const char* uv_err_name(int err); + + +#define UV_REQ_FIELDS \ + /* public */ \ + void* data; \ + /* read-only */ \ + uv_req_type type; \ + /* private */ \ + void* active_queue[2]; \ + void* reserved[4]; \ + UV_REQ_PRIVATE_FIELDS \ + +/* Abstract base class of all requests. */ +struct uv_req_s { + UV_REQ_FIELDS +}; + + +/* Platform-specific request types. */ +UV_PRIVATE_REQ_TYPES + + +UV_EXTERN int uv_shutdown(uv_shutdown_t* req, + uv_stream_t* handle, + uv_shutdown_cb cb); + +struct uv_shutdown_s { + UV_REQ_FIELDS + uv_stream_t* handle; + uv_shutdown_cb cb; + UV_SHUTDOWN_PRIVATE_FIELDS +}; + + +#define UV_HANDLE_FIELDS \ + /* public */ \ + void* data; \ + /* read-only */ \ + uv_loop_t* loop; \ + uv_handle_type type; \ + /* private */ \ + uv_close_cb close_cb; \ + void* handle_queue[2]; \ + union { \ + int fd; \ + void* reserved[4]; \ + } u; \ + UV_HANDLE_PRIVATE_FIELDS \ + +/* The abstract base class of all handles. */ +struct uv_handle_s { + UV_HANDLE_FIELDS +}; + +UV_EXTERN size_t uv_handle_size(uv_handle_type type); +UV_EXTERN size_t uv_req_size(uv_req_type type); + +UV_EXTERN int uv_is_active(const uv_handle_t* handle); + +UV_EXTERN void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg); + +/* Helpers for ad hoc debugging, no API/ABI stability guaranteed. */ +UV_EXTERN void uv_print_all_handles(uv_loop_t* loop, FILE* stream); +UV_EXTERN void uv_print_active_handles(uv_loop_t* loop, FILE* stream); + +UV_EXTERN void uv_close(uv_handle_t* handle, uv_close_cb close_cb); + +UV_EXTERN int uv_send_buffer_size(uv_handle_t* handle, int* value); +UV_EXTERN int uv_recv_buffer_size(uv_handle_t* handle, int* value); + +UV_EXTERN int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd); + +UV_EXTERN uv_buf_t uv_buf_init(char* base, unsigned int len); + + +#define UV_STREAM_FIELDS \ + /* number of bytes queued for writing */ \ + size_t write_queue_size; \ + uv_alloc_cb alloc_cb; \ + uv_read_cb read_cb; \ + /* private */ \ + UV_STREAM_PRIVATE_FIELDS + +/* + * uv_stream_t is a subclass of uv_handle_t. + * + * uv_stream is an abstract class. + * + * uv_stream_t is the parent class of uv_tcp_t, uv_pipe_t and uv_tty_t. + */ +struct uv_stream_s { + UV_HANDLE_FIELDS + UV_STREAM_FIELDS +}; + +UV_EXTERN int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb); +UV_EXTERN int uv_accept(uv_stream_t* server, uv_stream_t* client); + +UV_EXTERN int uv_read_start(uv_stream_t*, + uv_alloc_cb alloc_cb, + uv_read_cb read_cb); +UV_EXTERN int uv_read_stop(uv_stream_t*); + +UV_EXTERN int uv_write(uv_write_t* req, + uv_stream_t* handle, + const uv_buf_t bufs[], + unsigned int nbufs, + uv_write_cb cb); +UV_EXTERN int uv_write2(uv_write_t* req, + uv_stream_t* handle, + const uv_buf_t bufs[], + unsigned int nbufs, + uv_stream_t* send_handle, + uv_write_cb cb); +UV_EXTERN int uv_try_write(uv_stream_t* handle, + const uv_buf_t bufs[], + unsigned int nbufs); + +/* uv_write_t is a subclass of uv_req_t. */ +struct uv_write_s { + UV_REQ_FIELDS + uv_write_cb cb; + uv_stream_t* send_handle; + uv_stream_t* handle; + UV_WRITE_PRIVATE_FIELDS +}; + + +UV_EXTERN int uv_is_readable(const uv_stream_t* handle); +UV_EXTERN int uv_is_writable(const uv_stream_t* handle); + +UV_EXTERN int uv_stream_set_blocking(uv_stream_t* handle, int blocking); + +UV_EXTERN int uv_is_closing(const uv_handle_t* handle); + + +/* + * uv_tcp_t is a subclass of uv_stream_t. + * + * Represents a TCP stream or TCP server. + */ +struct uv_tcp_s { + UV_HANDLE_FIELDS + UV_STREAM_FIELDS + UV_TCP_PRIVATE_FIELDS +}; + +UV_EXTERN int uv_tcp_init(uv_loop_t*, uv_tcp_t* handle); +UV_EXTERN int uv_tcp_init_ex(uv_loop_t*, uv_tcp_t* handle, unsigned int flags); +UV_EXTERN int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock); +UV_EXTERN int uv_tcp_nodelay(uv_tcp_t* handle, int enable); +UV_EXTERN int uv_tcp_keepalive(uv_tcp_t* handle, + int enable, + unsigned int delay); +UV_EXTERN int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable); + +enum uv_tcp_flags { + /* Used with uv_tcp_bind, when an IPv6 address is used. */ + UV_TCP_IPV6ONLY = 1 +}; + +UV_EXTERN int uv_tcp_bind(uv_tcp_t* handle, + const struct sockaddr* addr, + unsigned int flags); +UV_EXTERN int uv_tcp_getsockname(const uv_tcp_t* handle, + struct sockaddr* name, + int* namelen); +UV_EXTERN int uv_tcp_getpeername(const uv_tcp_t* handle, + struct sockaddr* name, + int* namelen); +UV_EXTERN int uv_tcp_connect(uv_connect_t* req, + uv_tcp_t* handle, + const struct sockaddr* addr, + uv_connect_cb cb); + +/* uv_connect_t is a subclass of uv_req_t. */ +struct uv_connect_s { + UV_REQ_FIELDS + uv_connect_cb cb; + uv_stream_t* handle; + UV_CONNECT_PRIVATE_FIELDS +}; + + +/* + * UDP support. + */ + +enum uv_udp_flags { + /* Disables dual stack mode. */ + UV_UDP_IPV6ONLY = 1, + /* + * Indicates message was truncated because read buffer was too small. The + * remainder was discarded by the OS. Used in uv_udp_recv_cb. + */ + UV_UDP_PARTIAL = 2, + /* + * Indicates if SO_REUSEADDR will be set when binding the handle. + * This sets the SO_REUSEPORT socket flag on the BSDs and OS X. On other + * Unix platforms, it sets the SO_REUSEADDR flag. What that means is that + * multiple threads or processes can bind to the same address without error + * (provided they all set the flag) but only the last one to bind will receive + * any traffic, in effect "stealing" the port from the previous listener. + */ + UV_UDP_REUSEADDR = 4 +}; + +typedef void (*uv_udp_send_cb)(uv_udp_send_t* req, int status); +typedef void (*uv_udp_recv_cb)(uv_udp_t* handle, + ssize_t nread, + const uv_buf_t* buf, + const struct sockaddr* addr, + unsigned flags); + +/* uv_udp_t is a subclass of uv_handle_t. */ +struct uv_udp_s { + UV_HANDLE_FIELDS + /* read-only */ + /* + * Number of bytes queued for sending. This field strictly shows how much + * information is currently queued. + */ + size_t send_queue_size; + /* + * Number of send requests currently in the queue awaiting to be processed. + */ + size_t send_queue_count; + UV_UDP_PRIVATE_FIELDS +}; + +/* uv_udp_send_t is a subclass of uv_req_t. */ +struct uv_udp_send_s { + UV_REQ_FIELDS + uv_udp_t* handle; + uv_udp_send_cb cb; + UV_UDP_SEND_PRIVATE_FIELDS +}; + +UV_EXTERN int uv_udp_init(uv_loop_t*, uv_udp_t* handle); +UV_EXTERN int uv_udp_init_ex(uv_loop_t*, uv_udp_t* handle, unsigned int flags); +UV_EXTERN int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock); +UV_EXTERN int uv_udp_bind(uv_udp_t* handle, + const struct sockaddr* addr, + unsigned int flags); + +UV_EXTERN int uv_udp_getsockname(const uv_udp_t* handle, + struct sockaddr* name, + int* namelen); +UV_EXTERN int uv_udp_set_membership(uv_udp_t* handle, + const char* multicast_addr, + const char* interface_addr, + uv_membership membership); +UV_EXTERN int uv_udp_set_multicast_loop(uv_udp_t* handle, int on); +UV_EXTERN int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl); +UV_EXTERN int uv_udp_set_multicast_interface(uv_udp_t* handle, + const char* interface_addr); +UV_EXTERN int uv_udp_set_broadcast(uv_udp_t* handle, int on); +UV_EXTERN int uv_udp_set_ttl(uv_udp_t* handle, int ttl); +UV_EXTERN int uv_udp_send(uv_udp_send_t* req, + uv_udp_t* handle, + const uv_buf_t bufs[], + unsigned int nbufs, + const struct sockaddr* addr, + uv_udp_send_cb send_cb); +UV_EXTERN int uv_udp_try_send(uv_udp_t* handle, + const uv_buf_t bufs[], + unsigned int nbufs, + const struct sockaddr* addr); +UV_EXTERN int uv_udp_recv_start(uv_udp_t* handle, + uv_alloc_cb alloc_cb, + uv_udp_recv_cb recv_cb); +UV_EXTERN int uv_udp_recv_stop(uv_udp_t* handle); + + +/* + * uv_tty_t is a subclass of uv_stream_t. + * + * Representing a stream for the console. + */ +struct uv_tty_s { + UV_HANDLE_FIELDS + UV_STREAM_FIELDS + UV_TTY_PRIVATE_FIELDS +}; + +typedef enum { + /* Initial/normal terminal mode */ + UV_TTY_MODE_NORMAL, + /* Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also enabled) */ + UV_TTY_MODE_RAW, + /* Binary-safe I/O mode for IPC (Unix-only) */ + UV_TTY_MODE_IO +} uv_tty_mode_t; + +UV_EXTERN int uv_tty_init(uv_loop_t*, uv_tty_t*, uv_file fd, int readable); +UV_EXTERN int uv_tty_set_mode(uv_tty_t*, uv_tty_mode_t mode); +UV_EXTERN int uv_tty_reset_mode(void); +UV_EXTERN int uv_tty_get_winsize(uv_tty_t*, int* width, int* height); + +#ifdef __cplusplus +extern "C++" { + +inline int uv_tty_set_mode(uv_tty_t* handle, int mode) { + return uv_tty_set_mode(handle, static_cast(mode)); +} + +} +#endif + +UV_EXTERN uv_handle_type uv_guess_handle(uv_file file); + +/* + * uv_pipe_t is a subclass of uv_stream_t. + * + * Representing a pipe stream or pipe server. On Windows this is a Named + * Pipe. On Unix this is a Unix domain socket. + */ +struct uv_pipe_s { + UV_HANDLE_FIELDS + UV_STREAM_FIELDS + int ipc; /* non-zero if this pipe is used for passing handles */ + UV_PIPE_PRIVATE_FIELDS +}; + +UV_EXTERN int uv_pipe_init(uv_loop_t*, uv_pipe_t* handle, int ipc); +UV_EXTERN int uv_pipe_open(uv_pipe_t*, uv_file file); +UV_EXTERN int uv_pipe_bind(uv_pipe_t* handle, const char* name); +UV_EXTERN void uv_pipe_connect(uv_connect_t* req, + uv_pipe_t* handle, + const char* name, + uv_connect_cb cb); +UV_EXTERN int uv_pipe_getsockname(const uv_pipe_t* handle, + char* buffer, + size_t* size); +UV_EXTERN int uv_pipe_getpeername(const uv_pipe_t* handle, + char* buffer, + size_t* size); +UV_EXTERN void uv_pipe_pending_instances(uv_pipe_t* handle, int count); +UV_EXTERN int uv_pipe_pending_count(uv_pipe_t* handle); +UV_EXTERN uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle); + + +struct uv_poll_s { + UV_HANDLE_FIELDS + uv_poll_cb poll_cb; + UV_POLL_PRIVATE_FIELDS +}; + +enum uv_poll_event { + UV_READABLE = 1, + UV_WRITABLE = 2, + UV_DISCONNECT = 4 +}; + +UV_EXTERN int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd); +UV_EXTERN int uv_poll_init_socket(uv_loop_t* loop, + uv_poll_t* handle, + uv_os_sock_t socket); +UV_EXTERN int uv_poll_start(uv_poll_t* handle, int events, uv_poll_cb cb); +UV_EXTERN int uv_poll_stop(uv_poll_t* handle); + + +struct uv_prepare_s { + UV_HANDLE_FIELDS + UV_PREPARE_PRIVATE_FIELDS +}; + +UV_EXTERN int uv_prepare_init(uv_loop_t*, uv_prepare_t* prepare); +UV_EXTERN int uv_prepare_start(uv_prepare_t* prepare, uv_prepare_cb cb); +UV_EXTERN int uv_prepare_stop(uv_prepare_t* prepare); + + +struct uv_check_s { + UV_HANDLE_FIELDS + UV_CHECK_PRIVATE_FIELDS +}; + +UV_EXTERN int uv_check_init(uv_loop_t*, uv_check_t* check); +UV_EXTERN int uv_check_start(uv_check_t* check, uv_check_cb cb); +UV_EXTERN int uv_check_stop(uv_check_t* check); + + +struct uv_idle_s { + UV_HANDLE_FIELDS + UV_IDLE_PRIVATE_FIELDS +}; + +UV_EXTERN int uv_idle_init(uv_loop_t*, uv_idle_t* idle); +UV_EXTERN int uv_idle_start(uv_idle_t* idle, uv_idle_cb cb); +UV_EXTERN int uv_idle_stop(uv_idle_t* idle); + + +struct uv_async_s { + UV_HANDLE_FIELDS + UV_ASYNC_PRIVATE_FIELDS +}; + +UV_EXTERN int uv_async_init(uv_loop_t*, + uv_async_t* async, + uv_async_cb async_cb); +UV_EXTERN int uv_async_send(uv_async_t* async); + + +/* + * uv_timer_t is a subclass of uv_handle_t. + * + * Used to get woken up at a specified time in the future. + */ +struct uv_timer_s { + UV_HANDLE_FIELDS + UV_TIMER_PRIVATE_FIELDS +}; + +UV_EXTERN int uv_timer_init(uv_loop_t*, uv_timer_t* handle); +UV_EXTERN int uv_timer_start(uv_timer_t* handle, + uv_timer_cb cb, + uint64_t timeout, + uint64_t repeat); +UV_EXTERN int uv_timer_stop(uv_timer_t* handle); +UV_EXTERN int uv_timer_again(uv_timer_t* handle); +UV_EXTERN void uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat); +UV_EXTERN uint64_t uv_timer_get_repeat(const uv_timer_t* handle); + + +/* + * uv_getaddrinfo_t is a subclass of uv_req_t. + * + * Request object for uv_getaddrinfo. + */ +struct uv_getaddrinfo_s { + UV_REQ_FIELDS + /* read-only */ + uv_loop_t* loop; + /* struct addrinfo* addrinfo is marked as private, but it really isn't. */ + UV_GETADDRINFO_PRIVATE_FIELDS +}; + + +UV_EXTERN int uv_getaddrinfo(uv_loop_t* loop, + uv_getaddrinfo_t* req, + uv_getaddrinfo_cb getaddrinfo_cb, + const char* node, + const char* service, + const struct addrinfo* hints); +UV_EXTERN void uv_freeaddrinfo(struct addrinfo* ai); + + +/* +* uv_getnameinfo_t is a subclass of uv_req_t. +* +* Request object for uv_getnameinfo. +*/ +struct uv_getnameinfo_s { + UV_REQ_FIELDS + /* read-only */ + uv_loop_t* loop; + /* host and service are marked as private, but they really aren't. */ + UV_GETNAMEINFO_PRIVATE_FIELDS +}; + +UV_EXTERN int uv_getnameinfo(uv_loop_t* loop, + uv_getnameinfo_t* req, + uv_getnameinfo_cb getnameinfo_cb, + const struct sockaddr* addr, + int flags); + + +/* uv_spawn() options. */ +typedef enum { + UV_IGNORE = 0x00, + UV_CREATE_PIPE = 0x01, + UV_INHERIT_FD = 0x02, + UV_INHERIT_STREAM = 0x04, + + /* + * When UV_CREATE_PIPE is specified, UV_READABLE_PIPE and UV_WRITABLE_PIPE + * determine the direction of flow, from the child process' perspective. Both + * flags may be specified to create a duplex data stream. + */ + UV_READABLE_PIPE = 0x10, + UV_WRITABLE_PIPE = 0x20 +} uv_stdio_flags; + +typedef struct uv_stdio_container_s { + uv_stdio_flags flags; + + union { + uv_stream_t* stream; + int fd; + } data; +} uv_stdio_container_t; + +typedef struct uv_process_options_s { + uv_exit_cb exit_cb; /* Called after the process exits. */ + const char* file; /* Path to program to execute. */ + /* + * Command line arguments. args[0] should be the path to the program. On + * Windows this uses CreateProcess which concatenates the arguments into a + * string this can cause some strange errors. See the note at + * windows_verbatim_arguments. + */ + char** args; + /* + * This will be set as the environ variable in the subprocess. If this is + * NULL then the parents environ will be used. + */ + char** env; + /* + * If non-null this represents a directory the subprocess should execute + * in. Stands for current working directory. + */ + const char* cwd; + /* + * Various flags that control how uv_spawn() behaves. See the definition of + * `enum uv_process_flags` below. + */ + unsigned int flags; + /* + * The `stdio` field points to an array of uv_stdio_container_t structs that + * describe the file descriptors that will be made available to the child + * process. The convention is that stdio[0] points to stdin, fd 1 is used for + * stdout, and fd 2 is stderr. + * + * Note that on windows file descriptors greater than 2 are available to the + * child process only if the child processes uses the MSVCRT runtime. + */ + int stdio_count; + uv_stdio_container_t* stdio; + /* + * Libuv can change the child process' user/group id. This happens only when + * the appropriate bits are set in the flags fields. This is not supported on + * windows; uv_spawn() will fail and set the error to UV_ENOTSUP. + */ + uv_uid_t uid; + uv_gid_t gid; +} uv_process_options_t; + +/* + * These are the flags that can be used for the uv_process_options.flags field. + */ +enum uv_process_flags { + /* + * Set the child process' user id. The user id is supplied in the `uid` field + * of the options struct. This does not work on windows; setting this flag + * will cause uv_spawn() to fail. + */ + UV_PROCESS_SETUID = (1 << 0), + /* + * Set the child process' group id. The user id is supplied in the `gid` + * field of the options struct. This does not work on windows; setting this + * flag will cause uv_spawn() to fail. + */ + UV_PROCESS_SETGID = (1 << 1), + /* + * Do not wrap any arguments in quotes, or perform any other escaping, when + * converting the argument list into a command line string. This option is + * only meaningful on Windows systems. On Unix it is silently ignored. + */ + UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS = (1 << 2), + /* + * Spawn the child process in a detached state - this will make it a process + * group leader, and will effectively enable the child to keep running after + * the parent exits. Note that the child process will still keep the + * parent's event loop alive unless the parent process calls uv_unref() on + * the child's process handle. + */ + UV_PROCESS_DETACHED = (1 << 3), + /* + * Hide the subprocess console window that would normally be created. This + * option is only meaningful on Windows systems. On Unix it is silently + * ignored. + */ + UV_PROCESS_WINDOWS_HIDE = (1 << 4) +}; + +/* + * uv_process_t is a subclass of uv_handle_t. + */ +struct uv_process_s { + UV_HANDLE_FIELDS + uv_exit_cb exit_cb; + int pid; + UV_PROCESS_PRIVATE_FIELDS +}; + +UV_EXTERN int uv_spawn(uv_loop_t* loop, + uv_process_t* handle, + const uv_process_options_t* options); +UV_EXTERN int uv_process_kill(uv_process_t*, int signum); +UV_EXTERN int uv_kill(int pid, int signum); + + +/* + * uv_work_t is a subclass of uv_req_t. + */ +struct uv_work_s { + UV_REQ_FIELDS + uv_loop_t* loop; + uv_work_cb work_cb; + uv_after_work_cb after_work_cb; + UV_WORK_PRIVATE_FIELDS +}; + +UV_EXTERN int uv_queue_work(uv_loop_t* loop, + uv_work_t* req, + uv_work_cb work_cb, + uv_after_work_cb after_work_cb); + +UV_EXTERN int uv_cancel(uv_req_t* req); + + +struct uv_cpu_info_s { + char* model; + int speed; + struct uv_cpu_times_s { + uint64_t user; + uint64_t nice; + uint64_t sys; + uint64_t idle; + uint64_t irq; + } cpu_times; +}; + +struct uv_interface_address_s { + char* name; + char phys_addr[6]; + int is_internal; + union { + struct sockaddr_in address4; + struct sockaddr_in6 address6; + } address; + union { + struct sockaddr_in netmask4; + struct sockaddr_in6 netmask6; + } netmask; +}; + +struct uv_passwd_s { + char* username; + long uid; + long gid; + char* shell; + char* homedir; +}; + +typedef enum { + UV_DIRENT_UNKNOWN, + UV_DIRENT_FILE, + UV_DIRENT_DIR, + UV_DIRENT_LINK, + UV_DIRENT_FIFO, + UV_DIRENT_SOCKET, + UV_DIRENT_CHAR, + UV_DIRENT_BLOCK +} uv_dirent_type_t; + +struct uv_dirent_s { + const char* name; + uv_dirent_type_t type; +}; + +UV_EXTERN char** uv_setup_args(int argc, char** argv); +UV_EXTERN int uv_get_process_title(char* buffer, size_t size); +UV_EXTERN int uv_set_process_title(const char* title); +UV_EXTERN int uv_resident_set_memory(size_t* rss); +UV_EXTERN int uv_uptime(double* uptime); + +typedef struct { + long tv_sec; + long tv_usec; +} uv_timeval_t; + +typedef struct { + uv_timeval_t ru_utime; /* user CPU time used */ + uv_timeval_t ru_stime; /* system CPU time used */ + uint64_t ru_maxrss; /* maximum resident set size */ + uint64_t ru_ixrss; /* integral shared memory size */ + uint64_t ru_idrss; /* integral unshared data size */ + uint64_t ru_isrss; /* integral unshared stack size */ + uint64_t ru_minflt; /* page reclaims (soft page faults) */ + uint64_t ru_majflt; /* page faults (hard page faults) */ + uint64_t ru_nswap; /* swaps */ + uint64_t ru_inblock; /* block input operations */ + uint64_t ru_oublock; /* block output operations */ + uint64_t ru_msgsnd; /* IPC messages sent */ + uint64_t ru_msgrcv; /* IPC messages received */ + uint64_t ru_nsignals; /* signals received */ + uint64_t ru_nvcsw; /* voluntary context switches */ + uint64_t ru_nivcsw; /* involuntary context switches */ +} uv_rusage_t; + +UV_EXTERN int uv_getrusage(uv_rusage_t* rusage); + +UV_EXTERN int uv_os_homedir(char* buffer, size_t* size); +UV_EXTERN int uv_os_tmpdir(char* buffer, size_t* size); +UV_EXTERN int uv_os_get_passwd(uv_passwd_t* pwd); +UV_EXTERN void uv_os_free_passwd(uv_passwd_t* pwd); + +UV_EXTERN int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count); +UV_EXTERN void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count); + +UV_EXTERN int uv_interface_addresses(uv_interface_address_t** addresses, + int* count); +UV_EXTERN void uv_free_interface_addresses(uv_interface_address_t* addresses, + int count); + + +typedef enum { + UV_FS_UNKNOWN = -1, + UV_FS_CUSTOM, + UV_FS_OPEN, + UV_FS_CLOSE, + UV_FS_READ, + UV_FS_WRITE, + UV_FS_SENDFILE, + UV_FS_STAT, + UV_FS_LSTAT, + UV_FS_FSTAT, + UV_FS_FTRUNCATE, + UV_FS_UTIME, + UV_FS_FUTIME, + UV_FS_ACCESS, + UV_FS_CHMOD, + UV_FS_FCHMOD, + UV_FS_FSYNC, + UV_FS_FDATASYNC, + UV_FS_UNLINK, + UV_FS_RMDIR, + UV_FS_MKDIR, + UV_FS_MKDTEMP, + UV_FS_RENAME, + UV_FS_SCANDIR, + UV_FS_LINK, + UV_FS_SYMLINK, + UV_FS_READLINK, + UV_FS_CHOWN, + UV_FS_FCHOWN, + UV_FS_REALPATH +} uv_fs_type; + +/* uv_fs_t is a subclass of uv_req_t. */ +struct uv_fs_s { + UV_REQ_FIELDS + uv_fs_type fs_type; + uv_loop_t* loop; + uv_fs_cb cb; + ssize_t result; + void* ptr; + const char* path; + uv_stat_t statbuf; /* Stores the result of uv_fs_stat() and uv_fs_fstat(). */ + UV_FS_PRIVATE_FIELDS +}; + +UV_EXTERN void uv_fs_req_cleanup(uv_fs_t* req); +UV_EXTERN int uv_fs_close(uv_loop_t* loop, + uv_fs_t* req, + uv_file file, + uv_fs_cb cb); +UV_EXTERN int uv_fs_open(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + int flags, + int mode, + uv_fs_cb cb); +UV_EXTERN int uv_fs_read(uv_loop_t* loop, + uv_fs_t* req, + uv_file file, + const uv_buf_t bufs[], + unsigned int nbufs, + int64_t offset, + uv_fs_cb cb); +UV_EXTERN int uv_fs_unlink(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + uv_fs_cb cb); +UV_EXTERN int uv_fs_write(uv_loop_t* loop, + uv_fs_t* req, + uv_file file, + const uv_buf_t bufs[], + unsigned int nbufs, + int64_t offset, + uv_fs_cb cb); +UV_EXTERN int uv_fs_mkdir(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + int mode, + uv_fs_cb cb); +UV_EXTERN int uv_fs_mkdtemp(uv_loop_t* loop, + uv_fs_t* req, + const char* tpl, + uv_fs_cb cb); +UV_EXTERN int uv_fs_rmdir(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + uv_fs_cb cb); +UV_EXTERN int uv_fs_scandir(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + int flags, + uv_fs_cb cb); +UV_EXTERN int uv_fs_scandir_next(uv_fs_t* req, + uv_dirent_t* ent); +UV_EXTERN int uv_fs_stat(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + uv_fs_cb cb); +UV_EXTERN int uv_fs_fstat(uv_loop_t* loop, + uv_fs_t* req, + uv_file file, + uv_fs_cb cb); +UV_EXTERN int uv_fs_rename(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + const char* new_path, + uv_fs_cb cb); +UV_EXTERN int uv_fs_fsync(uv_loop_t* loop, + uv_fs_t* req, + uv_file file, + uv_fs_cb cb); +UV_EXTERN int uv_fs_fdatasync(uv_loop_t* loop, + uv_fs_t* req, + uv_file file, + uv_fs_cb cb); +UV_EXTERN int uv_fs_ftruncate(uv_loop_t* loop, + uv_fs_t* req, + uv_file file, + int64_t offset, + uv_fs_cb cb); +UV_EXTERN int uv_fs_sendfile(uv_loop_t* loop, + uv_fs_t* req, + uv_file out_fd, + uv_file in_fd, + int64_t in_offset, + size_t length, + uv_fs_cb cb); +UV_EXTERN int uv_fs_access(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + int mode, + uv_fs_cb cb); +UV_EXTERN int uv_fs_chmod(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + int mode, + uv_fs_cb cb); +UV_EXTERN int uv_fs_utime(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + double atime, + double mtime, + uv_fs_cb cb); +UV_EXTERN int uv_fs_futime(uv_loop_t* loop, + uv_fs_t* req, + uv_file file, + double atime, + double mtime, + uv_fs_cb cb); +UV_EXTERN int uv_fs_lstat(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + uv_fs_cb cb); +UV_EXTERN int uv_fs_link(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + const char* new_path, + uv_fs_cb cb); + +/* + * This flag can be used with uv_fs_symlink() on Windows to specify whether + * path argument points to a directory. + */ +#define UV_FS_SYMLINK_DIR 0x0001 + +/* + * This flag can be used with uv_fs_symlink() on Windows to specify whether + * the symlink is to be created using junction points. + */ +#define UV_FS_SYMLINK_JUNCTION 0x0002 + +UV_EXTERN int uv_fs_symlink(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + const char* new_path, + int flags, + uv_fs_cb cb); +UV_EXTERN int uv_fs_readlink(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + uv_fs_cb cb); +UV_EXTERN int uv_fs_realpath(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + uv_fs_cb cb); +UV_EXTERN int uv_fs_fchmod(uv_loop_t* loop, + uv_fs_t* req, + uv_file file, + int mode, + uv_fs_cb cb); +UV_EXTERN int uv_fs_chown(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + uv_uid_t uid, + uv_gid_t gid, + uv_fs_cb cb); +UV_EXTERN int uv_fs_fchown(uv_loop_t* loop, + uv_fs_t* req, + uv_file file, + uv_uid_t uid, + uv_gid_t gid, + uv_fs_cb cb); + + +enum uv_fs_event { + UV_RENAME = 1, + UV_CHANGE = 2 +}; + + +struct uv_fs_event_s { + UV_HANDLE_FIELDS + /* private */ + char* path; + UV_FS_EVENT_PRIVATE_FIELDS +}; + + +/* + * uv_fs_stat() based polling file watcher. + */ +struct uv_fs_poll_s { + UV_HANDLE_FIELDS + /* Private, don't touch. */ + void* poll_ctx; +}; + +UV_EXTERN int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle); +UV_EXTERN int uv_fs_poll_start(uv_fs_poll_t* handle, + uv_fs_poll_cb poll_cb, + const char* path, + unsigned int interval); +UV_EXTERN int uv_fs_poll_stop(uv_fs_poll_t* handle); +UV_EXTERN int uv_fs_poll_getpath(uv_fs_poll_t* handle, + char* buffer, + size_t* size); + + +struct uv_signal_s { + UV_HANDLE_FIELDS + uv_signal_cb signal_cb; + int signum; + UV_SIGNAL_PRIVATE_FIELDS +}; + +UV_EXTERN int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle); +UV_EXTERN int uv_signal_start(uv_signal_t* handle, + uv_signal_cb signal_cb, + int signum); +UV_EXTERN int uv_signal_stop(uv_signal_t* handle); + +UV_EXTERN void uv_loadavg(double avg[3]); + + +/* + * Flags to be passed to uv_fs_event_start(). + */ +enum uv_fs_event_flags { + /* + * By default, if the fs event watcher is given a directory name, we will + * watch for all events in that directory. This flags overrides this behavior + * and makes fs_event report only changes to the directory entry itself. This + * flag does not affect individual files watched. + * This flag is currently not implemented yet on any backend. + */ + UV_FS_EVENT_WATCH_ENTRY = 1, + + /* + * By default uv_fs_event will try to use a kernel interface such as inotify + * or kqueue to detect events. This may not work on remote filesystems such + * as NFS mounts. This flag makes fs_event fall back to calling stat() on a + * regular interval. + * This flag is currently not implemented yet on any backend. + */ + UV_FS_EVENT_STAT = 2, + + /* + * By default, event watcher, when watching directory, is not registering + * (is ignoring) changes in it's subdirectories. + * This flag will override this behaviour on platforms that support it. + */ + UV_FS_EVENT_RECURSIVE = 4 +}; + + +UV_EXTERN int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle); +UV_EXTERN int uv_fs_event_start(uv_fs_event_t* handle, + uv_fs_event_cb cb, + const char* path, + unsigned int flags); +UV_EXTERN int uv_fs_event_stop(uv_fs_event_t* handle); +UV_EXTERN int uv_fs_event_getpath(uv_fs_event_t* handle, + char* buffer, + size_t* size); + +UV_EXTERN int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr); +UV_EXTERN int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr); + +UV_EXTERN int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size); +UV_EXTERN int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size); + +UV_EXTERN int uv_inet_ntop(int af, const void* src, char* dst, size_t size); +UV_EXTERN int uv_inet_pton(int af, const char* src, void* dst); + +UV_EXTERN int uv_exepath(char* buffer, size_t* size); + +UV_EXTERN int uv_cwd(char* buffer, size_t* size); + +UV_EXTERN int uv_chdir(const char* dir); + +UV_EXTERN uint64_t uv_get_free_memory(void); +UV_EXTERN uint64_t uv_get_total_memory(void); + +UV_EXTERN uint64_t uv_hrtime(void); + +UV_EXTERN void uv_disable_stdio_inheritance(void); + +UV_EXTERN int uv_dlopen(const char* filename, uv_lib_t* lib); +UV_EXTERN void uv_dlclose(uv_lib_t* lib); +UV_EXTERN int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr); +UV_EXTERN const char* uv_dlerror(const uv_lib_t* lib); + +UV_EXTERN int uv_mutex_init(uv_mutex_t* handle); +UV_EXTERN void uv_mutex_destroy(uv_mutex_t* handle); +UV_EXTERN void uv_mutex_lock(uv_mutex_t* handle); +UV_EXTERN int uv_mutex_trylock(uv_mutex_t* handle); +UV_EXTERN void uv_mutex_unlock(uv_mutex_t* handle); + +UV_EXTERN int uv_rwlock_init(uv_rwlock_t* rwlock); +UV_EXTERN void uv_rwlock_destroy(uv_rwlock_t* rwlock); +UV_EXTERN void uv_rwlock_rdlock(uv_rwlock_t* rwlock); +UV_EXTERN int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock); +UV_EXTERN void uv_rwlock_rdunlock(uv_rwlock_t* rwlock); +UV_EXTERN void uv_rwlock_wrlock(uv_rwlock_t* rwlock); +UV_EXTERN int uv_rwlock_trywrlock(uv_rwlock_t* rwlock); +UV_EXTERN void uv_rwlock_wrunlock(uv_rwlock_t* rwlock); + +UV_EXTERN int uv_sem_init(uv_sem_t* sem, unsigned int value); +UV_EXTERN void uv_sem_destroy(uv_sem_t* sem); +UV_EXTERN void uv_sem_post(uv_sem_t* sem); +UV_EXTERN void uv_sem_wait(uv_sem_t* sem); +UV_EXTERN int uv_sem_trywait(uv_sem_t* sem); + +UV_EXTERN int uv_cond_init(uv_cond_t* cond); +UV_EXTERN void uv_cond_destroy(uv_cond_t* cond); +UV_EXTERN void uv_cond_signal(uv_cond_t* cond); +UV_EXTERN void uv_cond_broadcast(uv_cond_t* cond); + +UV_EXTERN int uv_barrier_init(uv_barrier_t* barrier, unsigned int count); +UV_EXTERN void uv_barrier_destroy(uv_barrier_t* barrier); +UV_EXTERN int uv_barrier_wait(uv_barrier_t* barrier); + +UV_EXTERN void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex); +UV_EXTERN int uv_cond_timedwait(uv_cond_t* cond, + uv_mutex_t* mutex, + uint64_t timeout); + +UV_EXTERN void uv_once(uv_once_t* guard, void (*callback)(void)); + +UV_EXTERN int uv_key_create(uv_key_t* key); +UV_EXTERN void uv_key_delete(uv_key_t* key); +UV_EXTERN void* uv_key_get(uv_key_t* key); +UV_EXTERN void uv_key_set(uv_key_t* key, void* value); + +typedef void (*uv_thread_cb)(void* arg); + +UV_EXTERN int uv_thread_create(uv_thread_t* tid, uv_thread_cb entry, void* arg); +UV_EXTERN uv_thread_t uv_thread_self(void); +UV_EXTERN int uv_thread_join(uv_thread_t *tid); +UV_EXTERN int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2); + +/* The presence of these unions force similar struct layout. */ +#define XX(_, name) uv_ ## name ## _t name; +union uv_any_handle { + UV_HANDLE_TYPE_MAP(XX) +}; + +union uv_any_req { + UV_REQ_TYPE_MAP(XX) +}; +#undef XX + + +struct uv_loop_s { + /* User data - use this for whatever. */ + void* data; + /* Loop reference counting. */ + unsigned int active_handles; + void* handle_queue[2]; + void* active_reqs[2]; + /* Internal flag to signal loop stop. */ + unsigned int stop_flag; + UV_LOOP_PRIVATE_FIELDS +}; + + +/* Don't export the private CPP symbols. */ +#undef UV_HANDLE_TYPE_PRIVATE +#undef UV_REQ_TYPE_PRIVATE +#undef UV_REQ_PRIVATE_FIELDS +#undef UV_STREAM_PRIVATE_FIELDS +#undef UV_TCP_PRIVATE_FIELDS +#undef UV_PREPARE_PRIVATE_FIELDS +#undef UV_CHECK_PRIVATE_FIELDS +#undef UV_IDLE_PRIVATE_FIELDS +#undef UV_ASYNC_PRIVATE_FIELDS +#undef UV_TIMER_PRIVATE_FIELDS +#undef UV_GETADDRINFO_PRIVATE_FIELDS +#undef UV_GETNAMEINFO_PRIVATE_FIELDS +#undef UV_FS_REQ_PRIVATE_FIELDS +#undef UV_WORK_PRIVATE_FIELDS +#undef UV_FS_EVENT_PRIVATE_FIELDS +#undef UV_SIGNAL_PRIVATE_FIELDS +#undef UV_LOOP_PRIVATE_FIELDS +#undef UV_LOOP_PRIVATE_PLATFORM_FIELDS + +#ifdef __cplusplus +} +#endif +#endif /* UV_H */ diff --cc Utilities/cmlibuv/src/unix/os390-syscalls.c index 0000000,2bf3b73..2bf3b73 mode 000000,100644..100644 --- a/Utilities/cmlibuv/src/unix/os390-syscalls.c +++ b/Utilities/cmlibuv/src/unix/os390-syscalls.c diff --cc Utilities/cmlibuv/src/unix/os390-syscalls.h index 0000000,61a7cee..61a7cee mode 000000,100644..100644 --- a/Utilities/cmlibuv/src/unix/os390-syscalls.h +++ b/Utilities/cmlibuv/src/unix/os390-syscalls.h diff --cc Utilities/cmlibuv/src/win/winapi.h index 597a93d,0000000..4b0eeca mode 100644,000000..100644 --- a/Utilities/cmlibuv/src/win/winapi.h +++ b/Utilities/cmlibuv/src/win/winapi.h @@@ -1,4757 -1,0 +1,4761 @@@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef UV_WIN_WINAPI_H_ +#define UV_WIN_WINAPI_H_ + +#include + + +/* + * Ntdll headers + */ +#ifndef STATUS_SEVERITY_SUCCESS +# define STATUS_SEVERITY_SUCCESS 0x0 +#endif + +#ifndef STATUS_SEVERITY_INFORMATIONAL +# define STATUS_SEVERITY_INFORMATIONAL 0x1 +#endif + +#ifndef STATUS_SEVERITY_WARNING +# define STATUS_SEVERITY_WARNING 0x2 +#endif + +#ifndef STATUS_SEVERITY_ERROR +# define STATUS_SEVERITY_ERROR 0x3 +#endif + +#ifndef FACILITY_NTWIN32 +# define FACILITY_NTWIN32 0x7 +#endif + +#ifndef NT_SUCCESS +# define NT_SUCCESS(status) (((NTSTATUS) (status)) >= 0) +#endif + +#ifndef NT_INFORMATION +# define NT_INFORMATION(status) ((((ULONG) (status)) >> 30) == 1) +#endif + +#ifndef NT_WARNING +# define NT_WARNING(status) ((((ULONG) (status)) >> 30) == 2) +#endif + +#ifndef NT_ERROR +# define NT_ERROR(status) ((((ULONG) (status)) >> 30) == 3) +#endif + +#ifndef STATUS_SUCCESS +# define STATUS_SUCCESS ((NTSTATUS) 0x00000000L) +#endif + +#ifndef STATUS_WAIT_0 +# define STATUS_WAIT_0 ((NTSTATUS) 0x00000000L) +#endif + +#ifndef STATUS_WAIT_1 +# define STATUS_WAIT_1 ((NTSTATUS) 0x00000001L) +#endif + +#ifndef STATUS_WAIT_2 +# define STATUS_WAIT_2 ((NTSTATUS) 0x00000002L) +#endif + +#ifndef STATUS_WAIT_3 +# define STATUS_WAIT_3 ((NTSTATUS) 0x00000003L) +#endif + +#ifndef STATUS_WAIT_63 +# define STATUS_WAIT_63 ((NTSTATUS) 0x0000003FL) +#endif + +#ifndef STATUS_ABANDONED +# define STATUS_ABANDONED ((NTSTATUS) 0x00000080L) +#endif + +#ifndef STATUS_ABANDONED_WAIT_0 +# define STATUS_ABANDONED_WAIT_0 ((NTSTATUS) 0x00000080L) +#endif + +#ifndef STATUS_ABANDONED_WAIT_63 +# define STATUS_ABANDONED_WAIT_63 ((NTSTATUS) 0x000000BFL) +#endif + +#ifndef STATUS_USER_APC +# define STATUS_USER_APC ((NTSTATUS) 0x000000C0L) +#endif + +#ifndef STATUS_KERNEL_APC +# define STATUS_KERNEL_APC ((NTSTATUS) 0x00000100L) +#endif + +#ifndef STATUS_ALERTED +# define STATUS_ALERTED ((NTSTATUS) 0x00000101L) +#endif + +#ifndef STATUS_TIMEOUT +# define STATUS_TIMEOUT ((NTSTATUS) 0x00000102L) +#endif + +#ifndef STATUS_PENDING +# define STATUS_PENDING ((NTSTATUS) 0x00000103L) +#endif + +#ifndef STATUS_REPARSE +# define STATUS_REPARSE ((NTSTATUS) 0x00000104L) +#endif + +#ifndef STATUS_MORE_ENTRIES +# define STATUS_MORE_ENTRIES ((NTSTATUS) 0x00000105L) +#endif + +#ifndef STATUS_NOT_ALL_ASSIGNED +# define STATUS_NOT_ALL_ASSIGNED ((NTSTATUS) 0x00000106L) +#endif + +#ifndef STATUS_SOME_NOT_MAPPED +# define STATUS_SOME_NOT_MAPPED ((NTSTATUS) 0x00000107L) +#endif + +#ifndef STATUS_OPLOCK_BREAK_IN_PROGRESS +# define STATUS_OPLOCK_BREAK_IN_PROGRESS ((NTSTATUS) 0x00000108L) +#endif + +#ifndef STATUS_VOLUME_MOUNTED +# define STATUS_VOLUME_MOUNTED ((NTSTATUS) 0x00000109L) +#endif + +#ifndef STATUS_RXACT_COMMITTED +# define STATUS_RXACT_COMMITTED ((NTSTATUS) 0x0000010AL) +#endif + +#ifndef STATUS_NOTIFY_CLEANUP +# define STATUS_NOTIFY_CLEANUP ((NTSTATUS) 0x0000010BL) +#endif + +#ifndef STATUS_NOTIFY_ENUM_DIR +# define STATUS_NOTIFY_ENUM_DIR ((NTSTATUS) 0x0000010CL) +#endif + +#ifndef STATUS_NO_QUOTAS_FOR_ACCOUNT +# define STATUS_NO_QUOTAS_FOR_ACCOUNT ((NTSTATUS) 0x0000010DL) +#endif + +#ifndef STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED +# define STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED ((NTSTATUS) 0x0000010EL) +#endif + +#ifndef STATUS_PAGE_FAULT_TRANSITION +# define STATUS_PAGE_FAULT_TRANSITION ((NTSTATUS) 0x00000110L) +#endif + +#ifndef STATUS_PAGE_FAULT_DEMAND_ZERO +# define STATUS_PAGE_FAULT_DEMAND_ZERO ((NTSTATUS) 0x00000111L) +#endif + +#ifndef STATUS_PAGE_FAULT_COPY_ON_WRITE +# define STATUS_PAGE_FAULT_COPY_ON_WRITE ((NTSTATUS) 0x00000112L) +#endif + +#ifndef STATUS_PAGE_FAULT_GUARD_PAGE +# define STATUS_PAGE_FAULT_GUARD_PAGE ((NTSTATUS) 0x00000113L) +#endif + +#ifndef STATUS_PAGE_FAULT_PAGING_FILE +# define STATUS_PAGE_FAULT_PAGING_FILE ((NTSTATUS) 0x00000114L) +#endif + +#ifndef STATUS_CACHE_PAGE_LOCKED +# define STATUS_CACHE_PAGE_LOCKED ((NTSTATUS) 0x00000115L) +#endif + +#ifndef STATUS_CRASH_DUMP +# define STATUS_CRASH_DUMP ((NTSTATUS) 0x00000116L) +#endif + +#ifndef STATUS_BUFFER_ALL_ZEROS +# define STATUS_BUFFER_ALL_ZEROS ((NTSTATUS) 0x00000117L) +#endif + +#ifndef STATUS_REPARSE_OBJECT +# define STATUS_REPARSE_OBJECT ((NTSTATUS) 0x00000118L) +#endif + +#ifndef STATUS_RESOURCE_REQUIREMENTS_CHANGED +# define STATUS_RESOURCE_REQUIREMENTS_CHANGED ((NTSTATUS) 0x00000119L) +#endif + +#ifndef STATUS_TRANSLATION_COMPLETE +# define STATUS_TRANSLATION_COMPLETE ((NTSTATUS) 0x00000120L) +#endif + +#ifndef STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY +# define STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY ((NTSTATUS) 0x00000121L) +#endif + +#ifndef STATUS_NOTHING_TO_TERMINATE +# define STATUS_NOTHING_TO_TERMINATE ((NTSTATUS) 0x00000122L) +#endif + +#ifndef STATUS_PROCESS_NOT_IN_JOB +# define STATUS_PROCESS_NOT_IN_JOB ((NTSTATUS) 0x00000123L) +#endif + +#ifndef STATUS_PROCESS_IN_JOB +# define STATUS_PROCESS_IN_JOB ((NTSTATUS) 0x00000124L) +#endif + +#ifndef STATUS_VOLSNAP_HIBERNATE_READY +# define STATUS_VOLSNAP_HIBERNATE_READY ((NTSTATUS) 0x00000125L) +#endif + +#ifndef STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY +# define STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY ((NTSTATUS) 0x00000126L) +#endif + +#ifndef STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED +# define STATUS_INTERRUPT_VECTOR_ALREADY_CONNECTED ((NTSTATUS) 0x00000127L) +#endif + +#ifndef STATUS_INTERRUPT_STILL_CONNECTED +# define STATUS_INTERRUPT_STILL_CONNECTED ((NTSTATUS) 0x00000128L) +#endif + +#ifndef STATUS_PROCESS_CLONED +# define STATUS_PROCESS_CLONED ((NTSTATUS) 0x00000129L) +#endif + +#ifndef STATUS_FILE_LOCKED_WITH_ONLY_READERS +# define STATUS_FILE_LOCKED_WITH_ONLY_READERS ((NTSTATUS) 0x0000012AL) +#endif + +#ifndef STATUS_FILE_LOCKED_WITH_WRITERS +# define STATUS_FILE_LOCKED_WITH_WRITERS ((NTSTATUS) 0x0000012BL) +#endif + +#ifndef STATUS_RESOURCEMANAGER_READ_ONLY +# define STATUS_RESOURCEMANAGER_READ_ONLY ((NTSTATUS) 0x00000202L) +#endif + +#ifndef STATUS_RING_PREVIOUSLY_EMPTY +# define STATUS_RING_PREVIOUSLY_EMPTY ((NTSTATUS) 0x00000210L) +#endif + +#ifndef STATUS_RING_PREVIOUSLY_FULL +# define STATUS_RING_PREVIOUSLY_FULL ((NTSTATUS) 0x00000211L) +#endif + +#ifndef STATUS_RING_PREVIOUSLY_ABOVE_QUOTA +# define STATUS_RING_PREVIOUSLY_ABOVE_QUOTA ((NTSTATUS) 0x00000212L) +#endif + +#ifndef STATUS_RING_NEWLY_EMPTY +# define STATUS_RING_NEWLY_EMPTY ((NTSTATUS) 0x00000213L) +#endif + +#ifndef STATUS_RING_SIGNAL_OPPOSITE_ENDPOINT +# define STATUS_RING_SIGNAL_OPPOSITE_ENDPOINT ((NTSTATUS) 0x00000214L) +#endif + +#ifndef STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE +# define STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE ((NTSTATUS) 0x00000215L) +#endif + +#ifndef STATUS_OPLOCK_HANDLE_CLOSED +# define STATUS_OPLOCK_HANDLE_CLOSED ((NTSTATUS) 0x00000216L) +#endif + +#ifndef STATUS_WAIT_FOR_OPLOCK +# define STATUS_WAIT_FOR_OPLOCK ((NTSTATUS) 0x00000367L) +#endif + +#ifndef STATUS_OBJECT_NAME_EXISTS +# define STATUS_OBJECT_NAME_EXISTS ((NTSTATUS) 0x40000000L) +#endif + +#ifndef STATUS_THREAD_WAS_SUSPENDED +# define STATUS_THREAD_WAS_SUSPENDED ((NTSTATUS) 0x40000001L) +#endif + +#ifndef STATUS_WORKING_SET_LIMIT_RANGE +# define STATUS_WORKING_SET_LIMIT_RANGE ((NTSTATUS) 0x40000002L) +#endif + +#ifndef STATUS_IMAGE_NOT_AT_BASE +# define STATUS_IMAGE_NOT_AT_BASE ((NTSTATUS) 0x40000003L) +#endif + +#ifndef STATUS_RXACT_STATE_CREATED +# define STATUS_RXACT_STATE_CREATED ((NTSTATUS) 0x40000004L) +#endif + +#ifndef STATUS_SEGMENT_NOTIFICATION +# define STATUS_SEGMENT_NOTIFICATION ((NTSTATUS) 0x40000005L) +#endif + +#ifndef STATUS_LOCAL_USER_SESSION_KEY +# define STATUS_LOCAL_USER_SESSION_KEY ((NTSTATUS) 0x40000006L) +#endif + +#ifndef STATUS_BAD_CURRENT_DIRECTORY +# define STATUS_BAD_CURRENT_DIRECTORY ((NTSTATUS) 0x40000007L) +#endif + +#ifndef STATUS_SERIAL_MORE_WRITES +# define STATUS_SERIAL_MORE_WRITES ((NTSTATUS) 0x40000008L) +#endif + +#ifndef STATUS_REGISTRY_RECOVERED +# define STATUS_REGISTRY_RECOVERED ((NTSTATUS) 0x40000009L) +#endif + +#ifndef STATUS_FT_READ_RECOVERY_FROM_BACKUP +# define STATUS_FT_READ_RECOVERY_FROM_BACKUP ((NTSTATUS) 0x4000000AL) +#endif + +#ifndef STATUS_FT_WRITE_RECOVERY +# define STATUS_FT_WRITE_RECOVERY ((NTSTATUS) 0x4000000BL) +#endif + +#ifndef STATUS_SERIAL_COUNTER_TIMEOUT +# define STATUS_SERIAL_COUNTER_TIMEOUT ((NTSTATUS) 0x4000000CL) +#endif + +#ifndef STATUS_NULL_LM_PASSWORD +# define STATUS_NULL_LM_PASSWORD ((NTSTATUS) 0x4000000DL) +#endif + +#ifndef STATUS_IMAGE_MACHINE_TYPE_MISMATCH +# define STATUS_IMAGE_MACHINE_TYPE_MISMATCH ((NTSTATUS) 0x4000000EL) +#endif + +#ifndef STATUS_RECEIVE_PARTIAL +# define STATUS_RECEIVE_PARTIAL ((NTSTATUS) 0x4000000FL) +#endif + +#ifndef STATUS_RECEIVE_EXPEDITED +# define STATUS_RECEIVE_EXPEDITED ((NTSTATUS) 0x40000010L) +#endif + +#ifndef STATUS_RECEIVE_PARTIAL_EXPEDITED +# define STATUS_RECEIVE_PARTIAL_EXPEDITED ((NTSTATUS) 0x40000011L) +#endif + +#ifndef STATUS_EVENT_DONE +# define STATUS_EVENT_DONE ((NTSTATUS) 0x40000012L) +#endif + +#ifndef STATUS_EVENT_PENDING +# define STATUS_EVENT_PENDING ((NTSTATUS) 0x40000013L) +#endif + +#ifndef STATUS_CHECKING_FILE_SYSTEM +# define STATUS_CHECKING_FILE_SYSTEM ((NTSTATUS) 0x40000014L) +#endif + +#ifndef STATUS_FATAL_APP_EXIT +# define STATUS_FATAL_APP_EXIT ((NTSTATUS) 0x40000015L) +#endif + +#ifndef STATUS_PREDEFINED_HANDLE +# define STATUS_PREDEFINED_HANDLE ((NTSTATUS) 0x40000016L) +#endif + +#ifndef STATUS_WAS_UNLOCKED +# define STATUS_WAS_UNLOCKED ((NTSTATUS) 0x40000017L) +#endif + +#ifndef STATUS_SERVICE_NOTIFICATION +# define STATUS_SERVICE_NOTIFICATION ((NTSTATUS) 0x40000018L) +#endif + +#ifndef STATUS_WAS_LOCKED +# define STATUS_WAS_LOCKED ((NTSTATUS) 0x40000019L) +#endif + +#ifndef STATUS_LOG_HARD_ERROR +# define STATUS_LOG_HARD_ERROR ((NTSTATUS) 0x4000001AL) +#endif + +#ifndef STATUS_ALREADY_WIN32 +# define STATUS_ALREADY_WIN32 ((NTSTATUS) 0x4000001BL) +#endif + +#ifndef STATUS_WX86_UNSIMULATE +# define STATUS_WX86_UNSIMULATE ((NTSTATUS) 0x4000001CL) +#endif + +#ifndef STATUS_WX86_CONTINUE +# define STATUS_WX86_CONTINUE ((NTSTATUS) 0x4000001DL) +#endif + +#ifndef STATUS_WX86_SINGLE_STEP +# define STATUS_WX86_SINGLE_STEP ((NTSTATUS) 0x4000001EL) +#endif + +#ifndef STATUS_WX86_BREAKPOINT +# define STATUS_WX86_BREAKPOINT ((NTSTATUS) 0x4000001FL) +#endif + +#ifndef STATUS_WX86_EXCEPTION_CONTINUE +# define STATUS_WX86_EXCEPTION_CONTINUE ((NTSTATUS) 0x40000020L) +#endif + +#ifndef STATUS_WX86_EXCEPTION_LASTCHANCE +# define STATUS_WX86_EXCEPTION_LASTCHANCE ((NTSTATUS) 0x40000021L) +#endif + +#ifndef STATUS_WX86_EXCEPTION_CHAIN +# define STATUS_WX86_EXCEPTION_CHAIN ((NTSTATUS) 0x40000022L) +#endif + +#ifndef STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE +# define STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE ((NTSTATUS) 0x40000023L) +#endif + +#ifndef STATUS_NO_YIELD_PERFORMED +# define STATUS_NO_YIELD_PERFORMED ((NTSTATUS) 0x40000024L) +#endif + +#ifndef STATUS_TIMER_RESUME_IGNORED +# define STATUS_TIMER_RESUME_IGNORED ((NTSTATUS) 0x40000025L) +#endif + +#ifndef STATUS_ARBITRATION_UNHANDLED +# define STATUS_ARBITRATION_UNHANDLED ((NTSTATUS) 0x40000026L) +#endif + +#ifndef STATUS_CARDBUS_NOT_SUPPORTED +# define STATUS_CARDBUS_NOT_SUPPORTED ((NTSTATUS) 0x40000027L) +#endif + +#ifndef STATUS_WX86_CREATEWX86TIB +# define STATUS_WX86_CREATEWX86TIB ((NTSTATUS) 0x40000028L) +#endif + +#ifndef STATUS_MP_PROCESSOR_MISMATCH +# define STATUS_MP_PROCESSOR_MISMATCH ((NTSTATUS) 0x40000029L) +#endif + +#ifndef STATUS_HIBERNATED +# define STATUS_HIBERNATED ((NTSTATUS) 0x4000002AL) +#endif + +#ifndef STATUS_RESUME_HIBERNATION +# define STATUS_RESUME_HIBERNATION ((NTSTATUS) 0x4000002BL) +#endif + +#ifndef STATUS_FIRMWARE_UPDATED +# define STATUS_FIRMWARE_UPDATED ((NTSTATUS) 0x4000002CL) +#endif + +#ifndef STATUS_DRIVERS_LEAKING_LOCKED_PAGES +# define STATUS_DRIVERS_LEAKING_LOCKED_PAGES ((NTSTATUS) 0x4000002DL) +#endif + +#ifndef STATUS_MESSAGE_RETRIEVED +# define STATUS_MESSAGE_RETRIEVED ((NTSTATUS) 0x4000002EL) +#endif + +#ifndef STATUS_SYSTEM_POWERSTATE_TRANSITION +# define STATUS_SYSTEM_POWERSTATE_TRANSITION ((NTSTATUS) 0x4000002FL) +#endif + +#ifndef STATUS_ALPC_CHECK_COMPLETION_LIST +# define STATUS_ALPC_CHECK_COMPLETION_LIST ((NTSTATUS) 0x40000030L) +#endif + +#ifndef STATUS_SYSTEM_POWERSTATE_COMPLEX_TRANSITION +# define STATUS_SYSTEM_POWERSTATE_COMPLEX_TRANSITION ((NTSTATUS) 0x40000031L) +#endif + +#ifndef STATUS_ACCESS_AUDIT_BY_POLICY +# define STATUS_ACCESS_AUDIT_BY_POLICY ((NTSTATUS) 0x40000032L) +#endif + +#ifndef STATUS_ABANDON_HIBERFILE +# define STATUS_ABANDON_HIBERFILE ((NTSTATUS) 0x40000033L) +#endif + +#ifndef STATUS_BIZRULES_NOT_ENABLED +# define STATUS_BIZRULES_NOT_ENABLED ((NTSTATUS) 0x40000034L) +#endif + +#ifndef STATUS_GUARD_PAGE_VIOLATION +# define STATUS_GUARD_PAGE_VIOLATION ((NTSTATUS) 0x80000001L) +#endif + +#ifndef STATUS_DATATYPE_MISALIGNMENT +# define STATUS_DATATYPE_MISALIGNMENT ((NTSTATUS) 0x80000002L) +#endif + +#ifndef STATUS_BREAKPOINT +# define STATUS_BREAKPOINT ((NTSTATUS) 0x80000003L) +#endif + +#ifndef STATUS_SINGLE_STEP +# define STATUS_SINGLE_STEP ((NTSTATUS) 0x80000004L) +#endif + +#ifndef STATUS_BUFFER_OVERFLOW +# define STATUS_BUFFER_OVERFLOW ((NTSTATUS) 0x80000005L) +#endif + +#ifndef STATUS_NO_MORE_FILES +# define STATUS_NO_MORE_FILES ((NTSTATUS) 0x80000006L) +#endif + +#ifndef STATUS_WAKE_SYSTEM_DEBUGGER +# define STATUS_WAKE_SYSTEM_DEBUGGER ((NTSTATUS) 0x80000007L) +#endif + +#ifndef STATUS_HANDLES_CLOSED +# define STATUS_HANDLES_CLOSED ((NTSTATUS) 0x8000000AL) +#endif + +#ifndef STATUS_NO_INHERITANCE +# define STATUS_NO_INHERITANCE ((NTSTATUS) 0x8000000BL) +#endif + +#ifndef STATUS_GUID_SUBSTITUTION_MADE +# define STATUS_GUID_SUBSTITUTION_MADE ((NTSTATUS) 0x8000000CL) +#endif + +#ifndef STATUS_PARTIAL_COPY +# define STATUS_PARTIAL_COPY ((NTSTATUS) 0x8000000DL) +#endif + +#ifndef STATUS_DEVICE_PAPER_EMPTY +# define STATUS_DEVICE_PAPER_EMPTY ((NTSTATUS) 0x8000000EL) +#endif + +#ifndef STATUS_DEVICE_POWERED_OFF +# define STATUS_DEVICE_POWERED_OFF ((NTSTATUS) 0x8000000FL) +#endif + +#ifndef STATUS_DEVICE_OFF_LINE +# define STATUS_DEVICE_OFF_LINE ((NTSTATUS) 0x80000010L) +#endif + +#ifndef STATUS_DEVICE_BUSY +# define STATUS_DEVICE_BUSY ((NTSTATUS) 0x80000011L) +#endif + +#ifndef STATUS_NO_MORE_EAS +# define STATUS_NO_MORE_EAS ((NTSTATUS) 0x80000012L) +#endif + +#ifndef STATUS_INVALID_EA_NAME +# define STATUS_INVALID_EA_NAME ((NTSTATUS) 0x80000013L) +#endif + +#ifndef STATUS_EA_LIST_INCONSISTENT +# define STATUS_EA_LIST_INCONSISTENT ((NTSTATUS) 0x80000014L) +#endif + +#ifndef STATUS_INVALID_EA_FLAG +# define STATUS_INVALID_EA_FLAG ((NTSTATUS) 0x80000015L) +#endif + +#ifndef STATUS_VERIFY_REQUIRED +# define STATUS_VERIFY_REQUIRED ((NTSTATUS) 0x80000016L) +#endif + +#ifndef STATUS_EXTRANEOUS_INFORMATION +# define STATUS_EXTRANEOUS_INFORMATION ((NTSTATUS) 0x80000017L) +#endif + +#ifndef STATUS_RXACT_COMMIT_NECESSARY +# define STATUS_RXACT_COMMIT_NECESSARY ((NTSTATUS) 0x80000018L) +#endif + +#ifndef STATUS_NO_MORE_ENTRIES +# define STATUS_NO_MORE_ENTRIES ((NTSTATUS) 0x8000001AL) +#endif + +#ifndef STATUS_FILEMARK_DETECTED +# define STATUS_FILEMARK_DETECTED ((NTSTATUS) 0x8000001BL) +#endif + +#ifndef STATUS_MEDIA_CHANGED +# define STATUS_MEDIA_CHANGED ((NTSTATUS) 0x8000001CL) +#endif + +#ifndef STATUS_BUS_RESET +# define STATUS_BUS_RESET ((NTSTATUS) 0x8000001DL) +#endif + +#ifndef STATUS_END_OF_MEDIA +# define STATUS_END_OF_MEDIA ((NTSTATUS) 0x8000001EL) +#endif + +#ifndef STATUS_BEGINNING_OF_MEDIA +# define STATUS_BEGINNING_OF_MEDIA ((NTSTATUS) 0x8000001FL) +#endif + +#ifndef STATUS_MEDIA_CHECK +# define STATUS_MEDIA_CHECK ((NTSTATUS) 0x80000020L) +#endif + +#ifndef STATUS_SETMARK_DETECTED +# define STATUS_SETMARK_DETECTED ((NTSTATUS) 0x80000021L) +#endif + +#ifndef STATUS_NO_DATA_DETECTED +# define STATUS_NO_DATA_DETECTED ((NTSTATUS) 0x80000022L) +#endif + +#ifndef STATUS_REDIRECTOR_HAS_OPEN_HANDLES +# define STATUS_REDIRECTOR_HAS_OPEN_HANDLES ((NTSTATUS) 0x80000023L) +#endif + +#ifndef STATUS_SERVER_HAS_OPEN_HANDLES +# define STATUS_SERVER_HAS_OPEN_HANDLES ((NTSTATUS) 0x80000024L) +#endif + +#ifndef STATUS_ALREADY_DISCONNECTED +# define STATUS_ALREADY_DISCONNECTED ((NTSTATUS) 0x80000025L) +#endif + +#ifndef STATUS_LONGJUMP +# define STATUS_LONGJUMP ((NTSTATUS) 0x80000026L) +#endif + +#ifndef STATUS_CLEANER_CARTRIDGE_INSTALLED +# define STATUS_CLEANER_CARTRIDGE_INSTALLED ((NTSTATUS) 0x80000027L) +#endif + +#ifndef STATUS_PLUGPLAY_QUERY_VETOED +# define STATUS_PLUGPLAY_QUERY_VETOED ((NTSTATUS) 0x80000028L) +#endif + +#ifndef STATUS_UNWIND_CONSOLIDATE +# define STATUS_UNWIND_CONSOLIDATE ((NTSTATUS) 0x80000029L) +#endif + +#ifndef STATUS_REGISTRY_HIVE_RECOVERED +# define STATUS_REGISTRY_HIVE_RECOVERED ((NTSTATUS) 0x8000002AL) +#endif + +#ifndef STATUS_DLL_MIGHT_BE_INSECURE +# define STATUS_DLL_MIGHT_BE_INSECURE ((NTSTATUS) 0x8000002BL) +#endif + +#ifndef STATUS_DLL_MIGHT_BE_INCOMPATIBLE +# define STATUS_DLL_MIGHT_BE_INCOMPATIBLE ((NTSTATUS) 0x8000002CL) +#endif + +#ifndef STATUS_STOPPED_ON_SYMLINK +# define STATUS_STOPPED_ON_SYMLINK ((NTSTATUS) 0x8000002DL) +#endif + +#ifndef STATUS_CANNOT_GRANT_REQUESTED_OPLOCK +# define STATUS_CANNOT_GRANT_REQUESTED_OPLOCK ((NTSTATUS) 0x8000002EL) +#endif + +#ifndef STATUS_NO_ACE_CONDITION +# define STATUS_NO_ACE_CONDITION ((NTSTATUS) 0x8000002FL) +#endif + +#ifndef STATUS_UNSUCCESSFUL +# define STATUS_UNSUCCESSFUL ((NTSTATUS) 0xC0000001L) +#endif + +#ifndef STATUS_NOT_IMPLEMENTED +# define STATUS_NOT_IMPLEMENTED ((NTSTATUS) 0xC0000002L) +#endif + +#ifndef STATUS_INVALID_INFO_CLASS +# define STATUS_INVALID_INFO_CLASS ((NTSTATUS) 0xC0000003L) +#endif + +#ifndef STATUS_INFO_LENGTH_MISMATCH +# define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS) 0xC0000004L) +#endif + +#ifndef STATUS_ACCESS_VIOLATION +# define STATUS_ACCESS_VIOLATION ((NTSTATUS) 0xC0000005L) +#endif + +#ifndef STATUS_IN_PAGE_ERROR +# define STATUS_IN_PAGE_ERROR ((NTSTATUS) 0xC0000006L) +#endif + +#ifndef STATUS_PAGEFILE_QUOTA +# define STATUS_PAGEFILE_QUOTA ((NTSTATUS) 0xC0000007L) +#endif + +#ifndef STATUS_INVALID_HANDLE +# define STATUS_INVALID_HANDLE ((NTSTATUS) 0xC0000008L) +#endif + +#ifndef STATUS_BAD_INITIAL_STACK +# define STATUS_BAD_INITIAL_STACK ((NTSTATUS) 0xC0000009L) +#endif + +#ifndef STATUS_BAD_INITIAL_PC +# define STATUS_BAD_INITIAL_PC ((NTSTATUS) 0xC000000AL) +#endif + +#ifndef STATUS_INVALID_CID +# define STATUS_INVALID_CID ((NTSTATUS) 0xC000000BL) +#endif + +#ifndef STATUS_TIMER_NOT_CANCELED +# define STATUS_TIMER_NOT_CANCELED ((NTSTATUS) 0xC000000CL) +#endif + +#ifndef STATUS_INVALID_PARAMETER +# define STATUS_INVALID_PARAMETER ((NTSTATUS) 0xC000000DL) +#endif + +#ifndef STATUS_NO_SUCH_DEVICE +# define STATUS_NO_SUCH_DEVICE ((NTSTATUS) 0xC000000EL) +#endif + +#ifndef STATUS_NO_SUCH_FILE +# define STATUS_NO_SUCH_FILE ((NTSTATUS) 0xC000000FL) +#endif + +#ifndef STATUS_INVALID_DEVICE_REQUEST +# define STATUS_INVALID_DEVICE_REQUEST ((NTSTATUS) 0xC0000010L) +#endif + +#ifndef STATUS_END_OF_FILE +# define STATUS_END_OF_FILE ((NTSTATUS) 0xC0000011L) +#endif + +#ifndef STATUS_WRONG_VOLUME +# define STATUS_WRONG_VOLUME ((NTSTATUS) 0xC0000012L) +#endif + +#ifndef STATUS_NO_MEDIA_IN_DEVICE +# define STATUS_NO_MEDIA_IN_DEVICE ((NTSTATUS) 0xC0000013L) +#endif + +#ifndef STATUS_UNRECOGNIZED_MEDIA +# define STATUS_UNRECOGNIZED_MEDIA ((NTSTATUS) 0xC0000014L) +#endif + +#ifndef STATUS_NONEXISTENT_SECTOR +# define STATUS_NONEXISTENT_SECTOR ((NTSTATUS) 0xC0000015L) +#endif + +#ifndef STATUS_MORE_PROCESSING_REQUIRED +# define STATUS_MORE_PROCESSING_REQUIRED ((NTSTATUS) 0xC0000016L) +#endif + +#ifndef STATUS_NO_MEMORY +# define STATUS_NO_MEMORY ((NTSTATUS) 0xC0000017L) +#endif + +#ifndef STATUS_CONFLICTING_ADDRESSES +# define STATUS_CONFLICTING_ADDRESSES ((NTSTATUS) 0xC0000018L) +#endif + +#ifndef STATUS_NOT_MAPPED_VIEW +# define STATUS_NOT_MAPPED_VIEW ((NTSTATUS) 0xC0000019L) +#endif + +#ifndef STATUS_UNABLE_TO_FREE_VM +# define STATUS_UNABLE_TO_FREE_VM ((NTSTATUS) 0xC000001AL) +#endif + +#ifndef STATUS_UNABLE_TO_DELETE_SECTION +# define STATUS_UNABLE_TO_DELETE_SECTION ((NTSTATUS) 0xC000001BL) +#endif + +#ifndef STATUS_INVALID_SYSTEM_SERVICE +# define STATUS_INVALID_SYSTEM_SERVICE ((NTSTATUS) 0xC000001CL) +#endif + +#ifndef STATUS_ILLEGAL_INSTRUCTION +# define STATUS_ILLEGAL_INSTRUCTION ((NTSTATUS) 0xC000001DL) +#endif + +#ifndef STATUS_INVALID_LOCK_SEQUENCE +# define STATUS_INVALID_LOCK_SEQUENCE ((NTSTATUS) 0xC000001EL) +#endif + +#ifndef STATUS_INVALID_VIEW_SIZE +# define STATUS_INVALID_VIEW_SIZE ((NTSTATUS) 0xC000001FL) +#endif + +#ifndef STATUS_INVALID_FILE_FOR_SECTION +# define STATUS_INVALID_FILE_FOR_SECTION ((NTSTATUS) 0xC0000020L) +#endif + +#ifndef STATUS_ALREADY_COMMITTED +# define STATUS_ALREADY_COMMITTED ((NTSTATUS) 0xC0000021L) +#endif + +#ifndef STATUS_ACCESS_DENIED +# define STATUS_ACCESS_DENIED ((NTSTATUS) 0xC0000022L) +#endif + +#ifndef STATUS_BUFFER_TOO_SMALL +# define STATUS_BUFFER_TOO_SMALL ((NTSTATUS) 0xC0000023L) +#endif + +#ifndef STATUS_OBJECT_TYPE_MISMATCH +# define STATUS_OBJECT_TYPE_MISMATCH ((NTSTATUS) 0xC0000024L) +#endif + +#ifndef STATUS_NONCONTINUABLE_EXCEPTION +# define STATUS_NONCONTINUABLE_EXCEPTION ((NTSTATUS) 0xC0000025L) +#endif + +#ifndef STATUS_INVALID_DISPOSITION +# define STATUS_INVALID_DISPOSITION ((NTSTATUS) 0xC0000026L) +#endif + +#ifndef STATUS_UNWIND +# define STATUS_UNWIND ((NTSTATUS) 0xC0000027L) +#endif + +#ifndef STATUS_BAD_STACK +# define STATUS_BAD_STACK ((NTSTATUS) 0xC0000028L) +#endif + +#ifndef STATUS_INVALID_UNWIND_TARGET +# define STATUS_INVALID_UNWIND_TARGET ((NTSTATUS) 0xC0000029L) +#endif + +#ifndef STATUS_NOT_LOCKED +# define STATUS_NOT_LOCKED ((NTSTATUS) 0xC000002AL) +#endif + +#ifndef STATUS_PARITY_ERROR +# define STATUS_PARITY_ERROR ((NTSTATUS) 0xC000002BL) +#endif + +#ifndef STATUS_UNABLE_TO_DECOMMIT_VM +# define STATUS_UNABLE_TO_DECOMMIT_VM ((NTSTATUS) 0xC000002CL) +#endif + +#ifndef STATUS_NOT_COMMITTED +# define STATUS_NOT_COMMITTED ((NTSTATUS) 0xC000002DL) +#endif + +#ifndef STATUS_INVALID_PORT_ATTRIBUTES +# define STATUS_INVALID_PORT_ATTRIBUTES ((NTSTATUS) 0xC000002EL) +#endif + +#ifndef STATUS_PORT_MESSAGE_TOO_LONG +# define STATUS_PORT_MESSAGE_TOO_LONG ((NTSTATUS) 0xC000002FL) +#endif + +#ifndef STATUS_INVALID_PARAMETER_MIX +# define STATUS_INVALID_PARAMETER_MIX ((NTSTATUS) 0xC0000030L) +#endif + +#ifndef STATUS_INVALID_QUOTA_LOWER +# define STATUS_INVALID_QUOTA_LOWER ((NTSTATUS) 0xC0000031L) +#endif + +#ifndef STATUS_DISK_CORRUPT_ERROR +# define STATUS_DISK_CORRUPT_ERROR ((NTSTATUS) 0xC0000032L) +#endif + +#ifndef STATUS_OBJECT_NAME_INVALID +# define STATUS_OBJECT_NAME_INVALID ((NTSTATUS) 0xC0000033L) +#endif + +#ifndef STATUS_OBJECT_NAME_NOT_FOUND +# define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS) 0xC0000034L) +#endif + +#ifndef STATUS_OBJECT_NAME_COLLISION +# define STATUS_OBJECT_NAME_COLLISION ((NTSTATUS) 0xC0000035L) +#endif + +#ifndef STATUS_PORT_DISCONNECTED +# define STATUS_PORT_DISCONNECTED ((NTSTATUS) 0xC0000037L) +#endif + +#ifndef STATUS_DEVICE_ALREADY_ATTACHED +# define STATUS_DEVICE_ALREADY_ATTACHED ((NTSTATUS) 0xC0000038L) +#endif + +#ifndef STATUS_OBJECT_PATH_INVALID +# define STATUS_OBJECT_PATH_INVALID ((NTSTATUS) 0xC0000039L) +#endif + +#ifndef STATUS_OBJECT_PATH_NOT_FOUND +# define STATUS_OBJECT_PATH_NOT_FOUND ((NTSTATUS) 0xC000003AL) +#endif + +#ifndef STATUS_OBJECT_PATH_SYNTAX_BAD +# define STATUS_OBJECT_PATH_SYNTAX_BAD ((NTSTATUS) 0xC000003BL) +#endif + +#ifndef STATUS_DATA_OVERRUN +# define STATUS_DATA_OVERRUN ((NTSTATUS) 0xC000003CL) +#endif + +#ifndef STATUS_DATA_LATE_ERROR +# define STATUS_DATA_LATE_ERROR ((NTSTATUS) 0xC000003DL) +#endif + +#ifndef STATUS_DATA_ERROR +# define STATUS_DATA_ERROR ((NTSTATUS) 0xC000003EL) +#endif + +#ifndef STATUS_CRC_ERROR +# define STATUS_CRC_ERROR ((NTSTATUS) 0xC000003FL) +#endif + +#ifndef STATUS_SECTION_TOO_BIG +# define STATUS_SECTION_TOO_BIG ((NTSTATUS) 0xC0000040L) +#endif + +#ifndef STATUS_PORT_CONNECTION_REFUSED +# define STATUS_PORT_CONNECTION_REFUSED ((NTSTATUS) 0xC0000041L) +#endif + +#ifndef STATUS_INVALID_PORT_HANDLE +# define STATUS_INVALID_PORT_HANDLE ((NTSTATUS) 0xC0000042L) +#endif + +#ifndef STATUS_SHARING_VIOLATION +# define STATUS_SHARING_VIOLATION ((NTSTATUS) 0xC0000043L) +#endif + +#ifndef STATUS_QUOTA_EXCEEDED +# define STATUS_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000044L) +#endif + +#ifndef STATUS_INVALID_PAGE_PROTECTION +# define STATUS_INVALID_PAGE_PROTECTION ((NTSTATUS) 0xC0000045L) +#endif + +#ifndef STATUS_MUTANT_NOT_OWNED +# define STATUS_MUTANT_NOT_OWNED ((NTSTATUS) 0xC0000046L) +#endif + +#ifndef STATUS_SEMAPHORE_LIMIT_EXCEEDED +# define STATUS_SEMAPHORE_LIMIT_EXCEEDED ((NTSTATUS) 0xC0000047L) +#endif + +#ifndef STATUS_PORT_ALREADY_SET +# define STATUS_PORT_ALREADY_SET ((NTSTATUS) 0xC0000048L) +#endif + +#ifndef STATUS_SECTION_NOT_IMAGE +# define STATUS_SECTION_NOT_IMAGE ((NTSTATUS) 0xC0000049L) +#endif + +#ifndef STATUS_SUSPEND_COUNT_EXCEEDED +# define STATUS_SUSPEND_COUNT_EXCEEDED ((NTSTATUS) 0xC000004AL) +#endif + +#ifndef STATUS_THREAD_IS_TERMINATING +# define STATUS_THREAD_IS_TERMINATING ((NTSTATUS) 0xC000004BL) +#endif + +#ifndef STATUS_BAD_WORKING_SET_LIMIT +# define STATUS_BAD_WORKING_SET_LIMIT ((NTSTATUS) 0xC000004CL) +#endif + +#ifndef STATUS_INCOMPATIBLE_FILE_MAP +# define STATUS_INCOMPATIBLE_FILE_MAP ((NTSTATUS) 0xC000004DL) +#endif + +#ifndef STATUS_SECTION_PROTECTION +# define STATUS_SECTION_PROTECTION ((NTSTATUS) 0xC000004EL) +#endif + +#ifndef STATUS_EAS_NOT_SUPPORTED +# define STATUS_EAS_NOT_SUPPORTED ((NTSTATUS) 0xC000004FL) +#endif + +#ifndef STATUS_EA_TOO_LARGE +# define STATUS_EA_TOO_LARGE ((NTSTATUS) 0xC0000050L) +#endif + +#ifndef STATUS_NONEXISTENT_EA_ENTRY +# define STATUS_NONEXISTENT_EA_ENTRY ((NTSTATUS) 0xC0000051L) +#endif + +#ifndef STATUS_NO_EAS_ON_FILE +# define STATUS_NO_EAS_ON_FILE ((NTSTATUS) 0xC0000052L) +#endif + +#ifndef STATUS_EA_CORRUPT_ERROR +# define STATUS_EA_CORRUPT_ERROR ((NTSTATUS) 0xC0000053L) +#endif + +#ifndef STATUS_FILE_LOCK_CONFLICT +# define STATUS_FILE_LOCK_CONFLICT ((NTSTATUS) 0xC0000054L) +#endif + +#ifndef STATUS_LOCK_NOT_GRANTED +# define STATUS_LOCK_NOT_GRANTED ((NTSTATUS) 0xC0000055L) +#endif + +#ifndef STATUS_DELETE_PENDING +# define STATUS_DELETE_PENDING ((NTSTATUS) 0xC0000056L) +#endif + +#ifndef STATUS_CTL_FILE_NOT_SUPPORTED +# define STATUS_CTL_FILE_NOT_SUPPORTED ((NTSTATUS) 0xC0000057L) +#endif + +#ifndef STATUS_UNKNOWN_REVISION +# define STATUS_UNKNOWN_REVISION ((NTSTATUS) 0xC0000058L) +#endif + +#ifndef STATUS_REVISION_MISMATCH +# define STATUS_REVISION_MISMATCH ((NTSTATUS) 0xC0000059L) +#endif + +#ifndef STATUS_INVALID_OWNER +# define STATUS_INVALID_OWNER ((NTSTATUS) 0xC000005AL) +#endif + +#ifndef STATUS_INVALID_PRIMARY_GROUP +# define STATUS_INVALID_PRIMARY_GROUP ((NTSTATUS) 0xC000005BL) +#endif + +#ifndef STATUS_NO_IMPERSONATION_TOKEN +# define STATUS_NO_IMPERSONATION_TOKEN ((NTSTATUS) 0xC000005CL) +#endif + +#ifndef STATUS_CANT_DISABLE_MANDATORY +# define STATUS_CANT_DISABLE_MANDATORY ((NTSTATUS) 0xC000005DL) +#endif + +#ifndef STATUS_NO_LOGON_SERVERS +# define STATUS_NO_LOGON_SERVERS ((NTSTATUS) 0xC000005EL) +#endif + +#ifndef STATUS_NO_SUCH_LOGON_SESSION +# define STATUS_NO_SUCH_LOGON_SESSION ((NTSTATUS) 0xC000005FL) +#endif + +#ifndef STATUS_NO_SUCH_PRIVILEGE +# define STATUS_NO_SUCH_PRIVILEGE ((NTSTATUS) 0xC0000060L) +#endif + +#ifndef STATUS_PRIVILEGE_NOT_HELD +# define STATUS_PRIVILEGE_NOT_HELD ((NTSTATUS) 0xC0000061L) +#endif + +#ifndef STATUS_INVALID_ACCOUNT_NAME +# define STATUS_INVALID_ACCOUNT_NAME ((NTSTATUS) 0xC0000062L) +#endif + +#ifndef STATUS_USER_EXISTS +# define STATUS_USER_EXISTS ((NTSTATUS) 0xC0000063L) +#endif + +#ifndef STATUS_NO_SUCH_USER +# define STATUS_NO_SUCH_USER ((NTSTATUS) 0xC0000064L) +#endif + +#ifndef STATUS_GROUP_EXISTS +# define STATUS_GROUP_EXISTS ((NTSTATUS) 0xC0000065L) +#endif + +#ifndef STATUS_NO_SUCH_GROUP +# define STATUS_NO_SUCH_GROUP ((NTSTATUS) 0xC0000066L) +#endif + +#ifndef STATUS_MEMBER_IN_GROUP +# define STATUS_MEMBER_IN_GROUP ((NTSTATUS) 0xC0000067L) +#endif + +#ifndef STATUS_MEMBER_NOT_IN_GROUP +# define STATUS_MEMBER_NOT_IN_GROUP ((NTSTATUS) 0xC0000068L) +#endif + +#ifndef STATUS_LAST_ADMIN +# define STATUS_LAST_ADMIN ((NTSTATUS) 0xC0000069L) +#endif + +#ifndef STATUS_WRONG_PASSWORD +# define STATUS_WRONG_PASSWORD ((NTSTATUS) 0xC000006AL) +#endif + +#ifndef STATUS_ILL_FORMED_PASSWORD +# define STATUS_ILL_FORMED_PASSWORD ((NTSTATUS) 0xC000006BL) +#endif + +#ifndef STATUS_PASSWORD_RESTRICTION +# define STATUS_PASSWORD_RESTRICTION ((NTSTATUS) 0xC000006CL) +#endif + +#ifndef STATUS_LOGON_FAILURE +# define STATUS_LOGON_FAILURE ((NTSTATUS) 0xC000006DL) +#endif + +#ifndef STATUS_ACCOUNT_RESTRICTION +# define STATUS_ACCOUNT_RESTRICTION ((NTSTATUS) 0xC000006EL) +#endif + +#ifndef STATUS_INVALID_LOGON_HOURS +# define STATUS_INVALID_LOGON_HOURS ((NTSTATUS) 0xC000006FL) +#endif + +#ifndef STATUS_INVALID_WORKSTATION +# define STATUS_INVALID_WORKSTATION ((NTSTATUS) 0xC0000070L) +#endif + +#ifndef STATUS_PASSWORD_EXPIRED +# define STATUS_PASSWORD_EXPIRED ((NTSTATUS) 0xC0000071L) +#endif + +#ifndef STATUS_ACCOUNT_DISABLED +# define STATUS_ACCOUNT_DISABLED ((NTSTATUS) 0xC0000072L) +#endif + +#ifndef STATUS_NONE_MAPPED +# define STATUS_NONE_MAPPED ((NTSTATUS) 0xC0000073L) +#endif + +#ifndef STATUS_TOO_MANY_LUIDS_REQUESTED +# define STATUS_TOO_MANY_LUIDS_REQUESTED ((NTSTATUS) 0xC0000074L) +#endif + +#ifndef STATUS_LUIDS_EXHAUSTED +# define STATUS_LUIDS_EXHAUSTED ((NTSTATUS) 0xC0000075L) +#endif + +#ifndef STATUS_INVALID_SUB_AUTHORITY +# define STATUS_INVALID_SUB_AUTHORITY ((NTSTATUS) 0xC0000076L) +#endif + +#ifndef STATUS_INVALID_ACL +# define STATUS_INVALID_ACL ((NTSTATUS) 0xC0000077L) +#endif + +#ifndef STATUS_INVALID_SID +# define STATUS_INVALID_SID ((NTSTATUS) 0xC0000078L) +#endif + +#ifndef STATUS_INVALID_SECURITY_DESCR +# define STATUS_INVALID_SECURITY_DESCR ((NTSTATUS) 0xC0000079L) +#endif + +#ifndef STATUS_PROCEDURE_NOT_FOUND +# define STATUS_PROCEDURE_NOT_FOUND ((NTSTATUS) 0xC000007AL) +#endif + +#ifndef STATUS_INVALID_IMAGE_FORMAT +# define STATUS_INVALID_IMAGE_FORMAT ((NTSTATUS) 0xC000007BL) +#endif + +#ifndef STATUS_NO_TOKEN +# define STATUS_NO_TOKEN ((NTSTATUS) 0xC000007CL) +#endif + +#ifndef STATUS_BAD_INHERITANCE_ACL +# define STATUS_BAD_INHERITANCE_ACL ((NTSTATUS) 0xC000007DL) +#endif + +#ifndef STATUS_RANGE_NOT_LOCKED +# define STATUS_RANGE_NOT_LOCKED ((NTSTATUS) 0xC000007EL) +#endif + +#ifndef STATUS_DISK_FULL +# define STATUS_DISK_FULL ((NTSTATUS) 0xC000007FL) +#endif + +#ifndef STATUS_SERVER_DISABLED +# define STATUS_SERVER_DISABLED ((NTSTATUS) 0xC0000080L) +#endif + +#ifndef STATUS_SERVER_NOT_DISABLED +# define STATUS_SERVER_NOT_DISABLED ((NTSTATUS) 0xC0000081L) +#endif + +#ifndef STATUS_TOO_MANY_GUIDS_REQUESTED +# define STATUS_TOO_MANY_GUIDS_REQUESTED ((NTSTATUS) 0xC0000082L) +#endif + +#ifndef STATUS_GUIDS_EXHAUSTED +# define STATUS_GUIDS_EXHAUSTED ((NTSTATUS) 0xC0000083L) +#endif + +#ifndef STATUS_INVALID_ID_AUTHORITY +# define STATUS_INVALID_ID_AUTHORITY ((NTSTATUS) 0xC0000084L) +#endif + +#ifndef STATUS_AGENTS_EXHAUSTED +# define STATUS_AGENTS_EXHAUSTED ((NTSTATUS) 0xC0000085L) +#endif + +#ifndef STATUS_INVALID_VOLUME_LABEL +# define STATUS_INVALID_VOLUME_LABEL ((NTSTATUS) 0xC0000086L) +#endif + +#ifndef STATUS_SECTION_NOT_EXTENDED +# define STATUS_SECTION_NOT_EXTENDED ((NTSTATUS) 0xC0000087L) +#endif + +#ifndef STATUS_NOT_MAPPED_DATA +# define STATUS_NOT_MAPPED_DATA ((NTSTATUS) 0xC0000088L) +#endif + +#ifndef STATUS_RESOURCE_DATA_NOT_FOUND +# define STATUS_RESOURCE_DATA_NOT_FOUND ((NTSTATUS) 0xC0000089L) +#endif + +#ifndef STATUS_RESOURCE_TYPE_NOT_FOUND +# define STATUS_RESOURCE_TYPE_NOT_FOUND ((NTSTATUS) 0xC000008AL) +#endif + +#ifndef STATUS_RESOURCE_NAME_NOT_FOUND +# define STATUS_RESOURCE_NAME_NOT_FOUND ((NTSTATUS) 0xC000008BL) +#endif + +#ifndef STATUS_ARRAY_BOUNDS_EXCEEDED +# define STATUS_ARRAY_BOUNDS_EXCEEDED ((NTSTATUS) 0xC000008CL) +#endif + +#ifndef STATUS_FLOAT_DENORMAL_OPERAND +# define STATUS_FLOAT_DENORMAL_OPERAND ((NTSTATUS) 0xC000008DL) +#endif + +#ifndef STATUS_FLOAT_DIVIDE_BY_ZERO +# define STATUS_FLOAT_DIVIDE_BY_ZERO ((NTSTATUS) 0xC000008EL) +#endif + +#ifndef STATUS_FLOAT_INEXACT_RESULT +# define STATUS_FLOAT_INEXACT_RESULT ((NTSTATUS) 0xC000008FL) +#endif + +#ifndef STATUS_FLOAT_INVALID_OPERATION +# define STATUS_FLOAT_INVALID_OPERATION ((NTSTATUS) 0xC0000090L) +#endif + +#ifndef STATUS_FLOAT_OVERFLOW +# define STATUS_FLOAT_OVERFLOW ((NTSTATUS) 0xC0000091L) +#endif + +#ifndef STATUS_FLOAT_STACK_CHECK +# define STATUS_FLOAT_STACK_CHECK ((NTSTATUS) 0xC0000092L) +#endif + +#ifndef STATUS_FLOAT_UNDERFLOW +# define STATUS_FLOAT_UNDERFLOW ((NTSTATUS) 0xC0000093L) +#endif + +#ifndef STATUS_INTEGER_DIVIDE_BY_ZERO +# define STATUS_INTEGER_DIVIDE_BY_ZERO ((NTSTATUS) 0xC0000094L) +#endif + +#ifndef STATUS_INTEGER_OVERFLOW +# define STATUS_INTEGER_OVERFLOW ((NTSTATUS) 0xC0000095L) +#endif + +#ifndef STATUS_PRIVILEGED_INSTRUCTION +# define STATUS_PRIVILEGED_INSTRUCTION ((NTSTATUS) 0xC0000096L) +#endif + +#ifndef STATUS_TOO_MANY_PAGING_FILES +# define STATUS_TOO_MANY_PAGING_FILES ((NTSTATUS) 0xC0000097L) +#endif + +#ifndef STATUS_FILE_INVALID +# define STATUS_FILE_INVALID ((NTSTATUS) 0xC0000098L) +#endif + +#ifndef STATUS_ALLOTTED_SPACE_EXCEEDED +# define STATUS_ALLOTTED_SPACE_EXCEEDED ((NTSTATUS) 0xC0000099L) +#endif + +#ifndef STATUS_INSUFFICIENT_RESOURCES +# define STATUS_INSUFFICIENT_RESOURCES ((NTSTATUS) 0xC000009AL) +#endif + +#ifndef STATUS_DFS_EXIT_PATH_FOUND +# define STATUS_DFS_EXIT_PATH_FOUND ((NTSTATUS) 0xC000009BL) +#endif + +#ifndef STATUS_DEVICE_DATA_ERROR +# define STATUS_DEVICE_DATA_ERROR ((NTSTATUS) 0xC000009CL) +#endif + +#ifndef STATUS_DEVICE_NOT_CONNECTED +# define STATUS_DEVICE_NOT_CONNECTED ((NTSTATUS) 0xC000009DL) +#endif + +#ifndef STATUS_DEVICE_POWER_FAILURE +# define STATUS_DEVICE_POWER_FAILURE ((NTSTATUS) 0xC000009EL) +#endif + +#ifndef STATUS_FREE_VM_NOT_AT_BASE +# define STATUS_FREE_VM_NOT_AT_BASE ((NTSTATUS) 0xC000009FL) +#endif + +#ifndef STATUS_MEMORY_NOT_ALLOCATED +# define STATUS_MEMORY_NOT_ALLOCATED ((NTSTATUS) 0xC00000A0L) +#endif + +#ifndef STATUS_WORKING_SET_QUOTA +# define STATUS_WORKING_SET_QUOTA ((NTSTATUS) 0xC00000A1L) +#endif + +#ifndef STATUS_MEDIA_WRITE_PROTECTED +# define STATUS_MEDIA_WRITE_PROTECTED ((NTSTATUS) 0xC00000A2L) +#endif + +#ifndef STATUS_DEVICE_NOT_READY +# define STATUS_DEVICE_NOT_READY ((NTSTATUS) 0xC00000A3L) +#endif + +#ifndef STATUS_INVALID_GROUP_ATTRIBUTES +# define STATUS_INVALID_GROUP_ATTRIBUTES ((NTSTATUS) 0xC00000A4L) +#endif + +#ifndef STATUS_BAD_IMPERSONATION_LEVEL +# define STATUS_BAD_IMPERSONATION_LEVEL ((NTSTATUS) 0xC00000A5L) +#endif + +#ifndef STATUS_CANT_OPEN_ANONYMOUS +# define STATUS_CANT_OPEN_ANONYMOUS ((NTSTATUS) 0xC00000A6L) +#endif + +#ifndef STATUS_BAD_VALIDATION_CLASS +# define STATUS_BAD_VALIDATION_CLASS ((NTSTATUS) 0xC00000A7L) +#endif + +#ifndef STATUS_BAD_TOKEN_TYPE +# define STATUS_BAD_TOKEN_TYPE ((NTSTATUS) 0xC00000A8L) +#endif + +#ifndef STATUS_BAD_MASTER_BOOT_RECORD +# define STATUS_BAD_MASTER_BOOT_RECORD ((NTSTATUS) 0xC00000A9L) +#endif + +#ifndef STATUS_INSTRUCTION_MISALIGNMENT +# define STATUS_INSTRUCTION_MISALIGNMENT ((NTSTATUS) 0xC00000AAL) +#endif + +#ifndef STATUS_INSTANCE_NOT_AVAILABLE +# define STATUS_INSTANCE_NOT_AVAILABLE ((NTSTATUS) 0xC00000ABL) +#endif + +#ifndef STATUS_PIPE_NOT_AVAILABLE +# define STATUS_PIPE_NOT_AVAILABLE ((NTSTATUS) 0xC00000ACL) +#endif + +#ifndef STATUS_INVALID_PIPE_STATE +# define STATUS_INVALID_PIPE_STATE ((NTSTATUS) 0xC00000ADL) +#endif + +#ifndef STATUS_PIPE_BUSY +# define STATUS_PIPE_BUSY ((NTSTATUS) 0xC00000AEL) +#endif + +#ifndef STATUS_ILLEGAL_FUNCTION +# define STATUS_ILLEGAL_FUNCTION ((NTSTATUS) 0xC00000AFL) +#endif + +#ifndef STATUS_PIPE_DISCONNECTED +# define STATUS_PIPE_DISCONNECTED ((NTSTATUS) 0xC00000B0L) +#endif + +#ifndef STATUS_PIPE_CLOSING +# define STATUS_PIPE_CLOSING ((NTSTATUS) 0xC00000B1L) +#endif + +#ifndef STATUS_PIPE_CONNECTED +# define STATUS_PIPE_CONNECTED ((NTSTATUS) 0xC00000B2L) +#endif + +#ifndef STATUS_PIPE_LISTENING +# define STATUS_PIPE_LISTENING ((NTSTATUS) 0xC00000B3L) +#endif + +#ifndef STATUS_INVALID_READ_MODE +# define STATUS_INVALID_READ_MODE ((NTSTATUS) 0xC00000B4L) +#endif + +#ifndef STATUS_IO_TIMEOUT +# define STATUS_IO_TIMEOUT ((NTSTATUS) 0xC00000B5L) +#endif + +#ifndef STATUS_FILE_FORCED_CLOSED +# define STATUS_FILE_FORCED_CLOSED ((NTSTATUS) 0xC00000B6L) +#endif + +#ifndef STATUS_PROFILING_NOT_STARTED +# define STATUS_PROFILING_NOT_STARTED ((NTSTATUS) 0xC00000B7L) +#endif + +#ifndef STATUS_PROFILING_NOT_STOPPED +# define STATUS_PROFILING_NOT_STOPPED ((NTSTATUS) 0xC00000B8L) +#endif + +#ifndef STATUS_COULD_NOT_INTERPRET +# define STATUS_COULD_NOT_INTERPRET ((NTSTATUS) 0xC00000B9L) +#endif + +#ifndef STATUS_FILE_IS_A_DIRECTORY +# define STATUS_FILE_IS_A_DIRECTORY ((NTSTATUS) 0xC00000BAL) +#endif + +#ifndef STATUS_NOT_SUPPORTED +# define STATUS_NOT_SUPPORTED ((NTSTATUS) 0xC00000BBL) +#endif + +#ifndef STATUS_REMOTE_NOT_LISTENING +# define STATUS_REMOTE_NOT_LISTENING ((NTSTATUS) 0xC00000BCL) +#endif + +#ifndef STATUS_DUPLICATE_NAME +# define STATUS_DUPLICATE_NAME ((NTSTATUS) 0xC00000BDL) +#endif + +#ifndef STATUS_BAD_NETWORK_PATH +# define STATUS_BAD_NETWORK_PATH ((NTSTATUS) 0xC00000BEL) +#endif + +#ifndef STATUS_NETWORK_BUSY +# define STATUS_NETWORK_BUSY ((NTSTATUS) 0xC00000BFL) +#endif + +#ifndef STATUS_DEVICE_DOES_NOT_EXIST +# define STATUS_DEVICE_DOES_NOT_EXIST ((NTSTATUS) 0xC00000C0L) +#endif + +#ifndef STATUS_TOO_MANY_COMMANDS +# define STATUS_TOO_MANY_COMMANDS ((NTSTATUS) 0xC00000C1L) +#endif + +#ifndef STATUS_ADAPTER_HARDWARE_ERROR +# define STATUS_ADAPTER_HARDWARE_ERROR ((NTSTATUS) 0xC00000C2L) +#endif + +#ifndef STATUS_INVALID_NETWORK_RESPONSE +# define STATUS_INVALID_NETWORK_RESPONSE ((NTSTATUS) 0xC00000C3L) +#endif + +#ifndef STATUS_UNEXPECTED_NETWORK_ERROR +# define STATUS_UNEXPECTED_NETWORK_ERROR ((NTSTATUS) 0xC00000C4L) +#endif + +#ifndef STATUS_BAD_REMOTE_ADAPTER +# define STATUS_BAD_REMOTE_ADAPTER ((NTSTATUS) 0xC00000C5L) +#endif + +#ifndef STATUS_PRINT_QUEUE_FULL +# define STATUS_PRINT_QUEUE_FULL ((NTSTATUS) 0xC00000C6L) +#endif + +#ifndef STATUS_NO_SPOOL_SPACE +# define STATUS_NO_SPOOL_SPACE ((NTSTATUS) 0xC00000C7L) +#endif + +#ifndef STATUS_PRINT_CANCELLED +# define STATUS_PRINT_CANCELLED ((NTSTATUS) 0xC00000C8L) +#endif + +#ifndef STATUS_NETWORK_NAME_DELETED +# define STATUS_NETWORK_NAME_DELETED ((NTSTATUS) 0xC00000C9L) +#endif + +#ifndef STATUS_NETWORK_ACCESS_DENIED +# define STATUS_NETWORK_ACCESS_DENIED ((NTSTATUS) 0xC00000CAL) +#endif + +#ifndef STATUS_BAD_DEVICE_TYPE +# define STATUS_BAD_DEVICE_TYPE ((NTSTATUS) 0xC00000CBL) +#endif + +#ifndef STATUS_BAD_NETWORK_NAME +# define STATUS_BAD_NETWORK_NAME ((NTSTATUS) 0xC00000CCL) +#endif + +#ifndef STATUS_TOO_MANY_NAMES +# define STATUS_TOO_MANY_NAMES ((NTSTATUS) 0xC00000CDL) +#endif + +#ifndef STATUS_TOO_MANY_SESSIONS +# define STATUS_TOO_MANY_SESSIONS ((NTSTATUS) 0xC00000CEL) +#endif + +#ifndef STATUS_SHARING_PAUSED +# define STATUS_SHARING_PAUSED ((NTSTATUS) 0xC00000CFL) +#endif + +#ifndef STATUS_REQUEST_NOT_ACCEPTED +# define STATUS_REQUEST_NOT_ACCEPTED ((NTSTATUS) 0xC00000D0L) +#endif + +#ifndef STATUS_REDIRECTOR_PAUSED +# define STATUS_REDIRECTOR_PAUSED ((NTSTATUS) 0xC00000D1L) +#endif + +#ifndef STATUS_NET_WRITE_FAULT +# define STATUS_NET_WRITE_FAULT ((NTSTATUS) 0xC00000D2L) +#endif + +#ifndef STATUS_PROFILING_AT_LIMIT +# define STATUS_PROFILING_AT_LIMIT ((NTSTATUS) 0xC00000D3L) +#endif + +#ifndef STATUS_NOT_SAME_DEVICE +# define STATUS_NOT_SAME_DEVICE ((NTSTATUS) 0xC00000D4L) +#endif + +#ifndef STATUS_FILE_RENAMED +# define STATUS_FILE_RENAMED ((NTSTATUS) 0xC00000D5L) +#endif + +#ifndef STATUS_VIRTUAL_CIRCUIT_CLOSED +# define STATUS_VIRTUAL_CIRCUIT_CLOSED ((NTSTATUS) 0xC00000D6L) +#endif + +#ifndef STATUS_NO_SECURITY_ON_OBJECT +# define STATUS_NO_SECURITY_ON_OBJECT ((NTSTATUS) 0xC00000D7L) +#endif + +#ifndef STATUS_CANT_WAIT +# define STATUS_CANT_WAIT ((NTSTATUS) 0xC00000D8L) +#endif + +#ifndef STATUS_PIPE_EMPTY +# define STATUS_PIPE_EMPTY ((NTSTATUS) 0xC00000D9L) +#endif + +#ifndef STATUS_CANT_ACCESS_DOMAIN_INFO +# define STATUS_CANT_ACCESS_DOMAIN_INFO ((NTSTATUS) 0xC00000DAL) +#endif + +#ifndef STATUS_CANT_TERMINATE_SELF +# define STATUS_CANT_TERMINATE_SELF ((NTSTATUS) 0xC00000DBL) +#endif + +#ifndef STATUS_INVALID_SERVER_STATE +# define STATUS_INVALID_SERVER_STATE ((NTSTATUS) 0xC00000DCL) +#endif + +#ifndef STATUS_INVALID_DOMAIN_STATE +# define STATUS_INVALID_DOMAIN_STATE ((NTSTATUS) 0xC00000DDL) +#endif + +#ifndef STATUS_INVALID_DOMAIN_ROLE +# define STATUS_INVALID_DOMAIN_ROLE ((NTSTATUS) 0xC00000DEL) +#endif + +#ifndef STATUS_NO_SUCH_DOMAIN +# define STATUS_NO_SUCH_DOMAIN ((NTSTATUS) 0xC00000DFL) +#endif + +#ifndef STATUS_DOMAIN_EXISTS +# define STATUS_DOMAIN_EXISTS ((NTSTATUS) 0xC00000E0L) +#endif + +#ifndef STATUS_DOMAIN_LIMIT_EXCEEDED +# define STATUS_DOMAIN_LIMIT_EXCEEDED ((NTSTATUS) 0xC00000E1L) +#endif + +#ifndef STATUS_OPLOCK_NOT_GRANTED +# define STATUS_OPLOCK_NOT_GRANTED ((NTSTATUS) 0xC00000E2L) +#endif + +#ifndef STATUS_INVALID_OPLOCK_PROTOCOL +# define STATUS_INVALID_OPLOCK_PROTOCOL ((NTSTATUS) 0xC00000E3L) +#endif + +#ifndef STATUS_INTERNAL_DB_CORRUPTION +# define STATUS_INTERNAL_DB_CORRUPTION ((NTSTATUS) 0xC00000E4L) +#endif + +#ifndef STATUS_INTERNAL_ERROR +# define STATUS_INTERNAL_ERROR ((NTSTATUS) 0xC00000E5L) +#endif + +#ifndef STATUS_GENERIC_NOT_MAPPED +# define STATUS_GENERIC_NOT_MAPPED ((NTSTATUS) 0xC00000E6L) +#endif + +#ifndef STATUS_BAD_DESCRIPTOR_FORMAT +# define STATUS_BAD_DESCRIPTOR_FORMAT ((NTSTATUS) 0xC00000E7L) +#endif + +#ifndef STATUS_INVALID_USER_BUFFER +# define STATUS_INVALID_USER_BUFFER ((NTSTATUS) 0xC00000E8L) +#endif + +#ifndef STATUS_UNEXPECTED_IO_ERROR +# define STATUS_UNEXPECTED_IO_ERROR ((NTSTATUS) 0xC00000E9L) +#endif + +#ifndef STATUS_UNEXPECTED_MM_CREATE_ERR +# define STATUS_UNEXPECTED_MM_CREATE_ERR ((NTSTATUS) 0xC00000EAL) +#endif + +#ifndef STATUS_UNEXPECTED_MM_MAP_ERROR +# define STATUS_UNEXPECTED_MM_MAP_ERROR ((NTSTATUS) 0xC00000EBL) +#endif + +#ifndef STATUS_UNEXPECTED_MM_EXTEND_ERR +# define STATUS_UNEXPECTED_MM_EXTEND_ERR ((NTSTATUS) 0xC00000ECL) +#endif + +#ifndef STATUS_NOT_LOGON_PROCESS +# define STATUS_NOT_LOGON_PROCESS ((NTSTATUS) 0xC00000EDL) +#endif + +#ifndef STATUS_LOGON_SESSION_EXISTS +# define STATUS_LOGON_SESSION_EXISTS ((NTSTATUS) 0xC00000EEL) +#endif + +#ifndef STATUS_INVALID_PARAMETER_1 +# define STATUS_INVALID_PARAMETER_1 ((NTSTATUS) 0xC00000EFL) +#endif + +#ifndef STATUS_INVALID_PARAMETER_2 +# define STATUS_INVALID_PARAMETER_2 ((NTSTATUS) 0xC00000F0L) +#endif + +#ifndef STATUS_INVALID_PARAMETER_3 +# define STATUS_INVALID_PARAMETER_3 ((NTSTATUS) 0xC00000F1L) +#endif + +#ifndef STATUS_INVALID_PARAMETER_4 +# define STATUS_INVALID_PARAMETER_4 ((NTSTATUS) 0xC00000F2L) +#endif + +#ifndef STATUS_INVALID_PARAMETER_5 +# define STATUS_INVALID_PARAMETER_5 ((NTSTATUS) 0xC00000F3L) +#endif + +#ifndef STATUS_INVALID_PARAMETER_6 +# define STATUS_INVALID_PARAMETER_6 ((NTSTATUS) 0xC00000F4L) +#endif + +#ifndef STATUS_INVALID_PARAMETER_7 +# define STATUS_INVALID_PARAMETER_7 ((NTSTATUS) 0xC00000F5L) +#endif + +#ifndef STATUS_INVALID_PARAMETER_8 +# define STATUS_INVALID_PARAMETER_8 ((NTSTATUS) 0xC00000F6L) +#endif + +#ifndef STATUS_INVALID_PARAMETER_9 +# define STATUS_INVALID_PARAMETER_9 ((NTSTATUS) 0xC00000F7L) +#endif + +#ifndef STATUS_INVALID_PARAMETER_10 +# define STATUS_INVALID_PARAMETER_10 ((NTSTATUS) 0xC00000F8L) +#endif + +#ifndef STATUS_INVALID_PARAMETER_11 +# define STATUS_INVALID_PARAMETER_11 ((NTSTATUS) 0xC00000F9L) +#endif + +#ifndef STATUS_INVALID_PARAMETER_12 +# define STATUS_INVALID_PARAMETER_12 ((NTSTATUS) 0xC00000FAL) +#endif + +#ifndef STATUS_REDIRECTOR_NOT_STARTED +# define STATUS_REDIRECTOR_NOT_STARTED ((NTSTATUS) 0xC00000FBL) +#endif + +#ifndef STATUS_REDIRECTOR_STARTED +# define STATUS_REDIRECTOR_STARTED ((NTSTATUS) 0xC00000FCL) +#endif + +#ifndef STATUS_STACK_OVERFLOW +# define STATUS_STACK_OVERFLOW ((NTSTATUS) 0xC00000FDL) +#endif + +#ifndef STATUS_NO_SUCH_PACKAGE +# define STATUS_NO_SUCH_PACKAGE ((NTSTATUS) 0xC00000FEL) +#endif + +#ifndef STATUS_BAD_FUNCTION_TABLE +# define STATUS_BAD_FUNCTION_TABLE ((NTSTATUS) 0xC00000FFL) +#endif + +#ifndef STATUS_VARIABLE_NOT_FOUND +# define STATUS_VARIABLE_NOT_FOUND ((NTSTATUS) 0xC0000100L) +#endif + +#ifndef STATUS_DIRECTORY_NOT_EMPTY +# define STATUS_DIRECTORY_NOT_EMPTY ((NTSTATUS) 0xC0000101L) +#endif + +#ifndef STATUS_FILE_CORRUPT_ERROR +# define STATUS_FILE_CORRUPT_ERROR ((NTSTATUS) 0xC0000102L) +#endif + +#ifndef STATUS_NOT_A_DIRECTORY +# define STATUS_NOT_A_DIRECTORY ((NTSTATUS) 0xC0000103L) +#endif + +#ifndef STATUS_BAD_LOGON_SESSION_STATE +# define STATUS_BAD_LOGON_SESSION_STATE ((NTSTATUS) 0xC0000104L) +#endif + +#ifndef STATUS_LOGON_SESSION_COLLISION +# define STATUS_LOGON_SESSION_COLLISION ((NTSTATUS) 0xC0000105L) +#endif + +#ifndef STATUS_NAME_TOO_LONG +# define STATUS_NAME_TOO_LONG ((NTSTATUS) 0xC0000106L) +#endif + +#ifndef STATUS_FILES_OPEN +# define STATUS_FILES_OPEN ((NTSTATUS) 0xC0000107L) +#endif + +#ifndef STATUS_CONNECTION_IN_USE +# define STATUS_CONNECTION_IN_USE ((NTSTATUS) 0xC0000108L) +#endif + +#ifndef STATUS_MESSAGE_NOT_FOUND +# define STATUS_MESSAGE_NOT_FOUND ((NTSTATUS) 0xC0000109L) +#endif + +#ifndef STATUS_PROCESS_IS_TERMINATING +# define STATUS_PROCESS_IS_TERMINATING ((NTSTATUS) 0xC000010AL) +#endif + +#ifndef STATUS_INVALID_LOGON_TYPE +# define STATUS_INVALID_LOGON_TYPE ((NTSTATUS) 0xC000010BL) +#endif + +#ifndef STATUS_NO_GUID_TRANSLATION +# define STATUS_NO_GUID_TRANSLATION ((NTSTATUS) 0xC000010CL) +#endif + +#ifndef STATUS_CANNOT_IMPERSONATE +# define STATUS_CANNOT_IMPERSONATE ((NTSTATUS) 0xC000010DL) +#endif + +#ifndef STATUS_IMAGE_ALREADY_LOADED +# define STATUS_IMAGE_ALREADY_LOADED ((NTSTATUS) 0xC000010EL) +#endif + +#ifndef STATUS_ABIOS_NOT_PRESENT +# define STATUS_ABIOS_NOT_PRESENT ((NTSTATUS) 0xC000010FL) +#endif + +#ifndef STATUS_ABIOS_LID_NOT_EXIST +# define STATUS_ABIOS_LID_NOT_EXIST ((NTSTATUS) 0xC0000110L) +#endif + +#ifndef STATUS_ABIOS_LID_ALREADY_OWNED +# define STATUS_ABIOS_LID_ALREADY_OWNED ((NTSTATUS) 0xC0000111L) +#endif + +#ifndef STATUS_ABIOS_NOT_LID_OWNER +# define STATUS_ABIOS_NOT_LID_OWNER ((NTSTATUS) 0xC0000112L) +#endif + +#ifndef STATUS_ABIOS_INVALID_COMMAND +# define STATUS_ABIOS_INVALID_COMMAND ((NTSTATUS) 0xC0000113L) +#endif + +#ifndef STATUS_ABIOS_INVALID_LID +# define STATUS_ABIOS_INVALID_LID ((NTSTATUS) 0xC0000114L) +#endif + +#ifndef STATUS_ABIOS_SELECTOR_NOT_AVAILABLE +# define STATUS_ABIOS_SELECTOR_NOT_AVAILABLE ((NTSTATUS) 0xC0000115L) +#endif + +#ifndef STATUS_ABIOS_INVALID_SELECTOR +# define STATUS_ABIOS_INVALID_SELECTOR ((NTSTATUS) 0xC0000116L) +#endif + +#ifndef STATUS_NO_LDT +# define STATUS_NO_LDT ((NTSTATUS) 0xC0000117L) +#endif + +#ifndef STATUS_INVALID_LDT_SIZE +# define STATUS_INVALID_LDT_SIZE ((NTSTATUS) 0xC0000118L) +#endif + +#ifndef STATUS_INVALID_LDT_OFFSET +# define STATUS_INVALID_LDT_OFFSET ((NTSTATUS) 0xC0000119L) +#endif + +#ifndef STATUS_INVALID_LDT_DESCRIPTOR +# define STATUS_INVALID_LDT_DESCRIPTOR ((NTSTATUS) 0xC000011AL) +#endif + +#ifndef STATUS_INVALID_IMAGE_NE_FORMAT +# define STATUS_INVALID_IMAGE_NE_FORMAT ((NTSTATUS) 0xC000011BL) +#endif + +#ifndef STATUS_RXACT_INVALID_STATE +# define STATUS_RXACT_INVALID_STATE ((NTSTATUS) 0xC000011CL) +#endif + +#ifndef STATUS_RXACT_COMMIT_FAILURE +# define STATUS_RXACT_COMMIT_FAILURE ((NTSTATUS) 0xC000011DL) +#endif + +#ifndef STATUS_MAPPED_FILE_SIZE_ZERO +# define STATUS_MAPPED_FILE_SIZE_ZERO ((NTSTATUS) 0xC000011EL) +#endif + +#ifndef STATUS_TOO_MANY_OPENED_FILES +# define STATUS_TOO_MANY_OPENED_FILES ((NTSTATUS) 0xC000011FL) +#endif + +#ifndef STATUS_CANCELLED +# define STATUS_CANCELLED ((NTSTATUS) 0xC0000120L) +#endif + +#ifndef STATUS_CANNOT_DELETE +# define STATUS_CANNOT_DELETE ((NTSTATUS) 0xC0000121L) +#endif + +#ifndef STATUS_INVALID_COMPUTER_NAME +# define STATUS_INVALID_COMPUTER_NAME ((NTSTATUS) 0xC0000122L) +#endif + +#ifndef STATUS_FILE_DELETED +# define STATUS_FILE_DELETED ((NTSTATUS) 0xC0000123L) +#endif + +#ifndef STATUS_SPECIAL_ACCOUNT +# define STATUS_SPECIAL_ACCOUNT ((NTSTATUS) 0xC0000124L) +#endif + +#ifndef STATUS_SPECIAL_GROUP +# define STATUS_SPECIAL_GROUP ((NTSTATUS) 0xC0000125L) +#endif + +#ifndef STATUS_SPECIAL_USER +# define STATUS_SPECIAL_USER ((NTSTATUS) 0xC0000126L) +#endif + +#ifndef STATUS_MEMBERS_PRIMARY_GROUP +# define STATUS_MEMBERS_PRIMARY_GROUP ((NTSTATUS) 0xC0000127L) +#endif + +#ifndef STATUS_FILE_CLOSED +# define STATUS_FILE_CLOSED ((NTSTATUS) 0xC0000128L) +#endif + +#ifndef STATUS_TOO_MANY_THREADS +# define STATUS_TOO_MANY_THREADS ((NTSTATUS) 0xC0000129L) +#endif + +#ifndef STATUS_THREAD_NOT_IN_PROCESS +# define STATUS_THREAD_NOT_IN_PROCESS ((NTSTATUS) 0xC000012AL) +#endif + +#ifndef STATUS_TOKEN_ALREADY_IN_USE +# define STATUS_TOKEN_ALREADY_IN_USE ((NTSTATUS) 0xC000012BL) +#endif + +#ifndef STATUS_PAGEFILE_QUOTA_EXCEEDED +# define STATUS_PAGEFILE_QUOTA_EXCEEDED ((NTSTATUS) 0xC000012CL) +#endif + +#ifndef STATUS_COMMITMENT_LIMIT +# define STATUS_COMMITMENT_LIMIT ((NTSTATUS) 0xC000012DL) +#endif + +#ifndef STATUS_INVALID_IMAGE_LE_FORMAT +# define STATUS_INVALID_IMAGE_LE_FORMAT ((NTSTATUS) 0xC000012EL) +#endif + +#ifndef STATUS_INVALID_IMAGE_NOT_MZ +# define STATUS_INVALID_IMAGE_NOT_MZ ((NTSTATUS) 0xC000012FL) +#endif + +#ifndef STATUS_INVALID_IMAGE_PROTECT +# define STATUS_INVALID_IMAGE_PROTECT ((NTSTATUS) 0xC0000130L) +#endif + +#ifndef STATUS_INVALID_IMAGE_WIN_16 +# define STATUS_INVALID_IMAGE_WIN_16 ((NTSTATUS) 0xC0000131L) +#endif + +#ifndef STATUS_LOGON_SERVER_CONFLICT +# define STATUS_LOGON_SERVER_CONFLICT ((NTSTATUS) 0xC0000132L) +#endif + +#ifndef STATUS_TIME_DIFFERENCE_AT_DC +# define STATUS_TIME_DIFFERENCE_AT_DC ((NTSTATUS) 0xC0000133L) +#endif + +#ifndef STATUS_SYNCHRONIZATION_REQUIRED +# define STATUS_SYNCHRONIZATION_REQUIRED ((NTSTATUS) 0xC0000134L) +#endif + +#ifndef STATUS_DLL_NOT_FOUND +# define STATUS_DLL_NOT_FOUND ((NTSTATUS) 0xC0000135L) +#endif + +#ifndef STATUS_OPEN_FAILED +# define STATUS_OPEN_FAILED ((NTSTATUS) 0xC0000136L) +#endif + +#ifndef STATUS_IO_PRIVILEGE_FAILED +# define STATUS_IO_PRIVILEGE_FAILED ((NTSTATUS) 0xC0000137L) +#endif + +#ifndef STATUS_ORDINAL_NOT_FOUND +# define STATUS_ORDINAL_NOT_FOUND ((NTSTATUS) 0xC0000138L) +#endif + +#ifndef STATUS_ENTRYPOINT_NOT_FOUND +# define STATUS_ENTRYPOINT_NOT_FOUND ((NTSTATUS) 0xC0000139L) +#endif + +#ifndef STATUS_CONTROL_C_EXIT +# define STATUS_CONTROL_C_EXIT ((NTSTATUS) 0xC000013AL) +#endif + +#ifndef STATUS_LOCAL_DISCONNECT +# define STATUS_LOCAL_DISCONNECT ((NTSTATUS) 0xC000013BL) +#endif + +#ifndef STATUS_REMOTE_DISCONNECT +# define STATUS_REMOTE_DISCONNECT ((NTSTATUS) 0xC000013CL) +#endif + +#ifndef STATUS_REMOTE_RESOURCES +# define STATUS_REMOTE_RESOURCES ((NTSTATUS) 0xC000013DL) +#endif + +#ifndef STATUS_LINK_FAILED +# define STATUS_LINK_FAILED ((NTSTATUS) 0xC000013EL) +#endif + +#ifndef STATUS_LINK_TIMEOUT +# define STATUS_LINK_TIMEOUT ((NTSTATUS) 0xC000013FL) +#endif + +#ifndef STATUS_INVALID_CONNECTION +# define STATUS_INVALID_CONNECTION ((NTSTATUS) 0xC0000140L) +#endif + +#ifndef STATUS_INVALID_ADDRESS +# define STATUS_INVALID_ADDRESS ((NTSTATUS) 0xC0000141L) +#endif + +#ifndef STATUS_DLL_INIT_FAILED +# define STATUS_DLL_INIT_FAILED ((NTSTATUS) 0xC0000142L) +#endif + +#ifndef STATUS_MISSING_SYSTEMFILE +# define STATUS_MISSING_SYSTEMFILE ((NTSTATUS) 0xC0000143L) +#endif + +#ifndef STATUS_UNHANDLED_EXCEPTION +# define STATUS_UNHANDLED_EXCEPTION ((NTSTATUS) 0xC0000144L) +#endif + +#ifndef STATUS_APP_INIT_FAILURE +# define STATUS_APP_INIT_FAILURE ((NTSTATUS) 0xC0000145L) +#endif + +#ifndef STATUS_PAGEFILE_CREATE_FAILED +# define STATUS_PAGEFILE_CREATE_FAILED ((NTSTATUS) 0xC0000146L) +#endif + +#ifndef STATUS_NO_PAGEFILE +# define STATUS_NO_PAGEFILE ((NTSTATUS) 0xC0000147L) +#endif + +#ifndef STATUS_INVALID_LEVEL +# define STATUS_INVALID_LEVEL ((NTSTATUS) 0xC0000148L) +#endif + +#ifndef STATUS_WRONG_PASSWORD_CORE +# define STATUS_WRONG_PASSWORD_CORE ((NTSTATUS) 0xC0000149L) +#endif + +#ifndef STATUS_ILLEGAL_FLOAT_CONTEXT +# define STATUS_ILLEGAL_FLOAT_CONTEXT ((NTSTATUS) 0xC000014AL) +#endif + +#ifndef STATUS_PIPE_BROKEN +# define STATUS_PIPE_BROKEN ((NTSTATUS) 0xC000014BL) +#endif + +#ifndef STATUS_REGISTRY_CORRUPT +# define STATUS_REGISTRY_CORRUPT ((NTSTATUS) 0xC000014CL) +#endif + +#ifndef STATUS_REGISTRY_IO_FAILED +# define STATUS_REGISTRY_IO_FAILED ((NTSTATUS) 0xC000014DL) +#endif + +#ifndef STATUS_NO_EVENT_PAIR +# define STATUS_NO_EVENT_PAIR ((NTSTATUS) 0xC000014EL) +#endif + +#ifndef STATUS_UNRECOGNIZED_VOLUME +# define STATUS_UNRECOGNIZED_VOLUME ((NTSTATUS) 0xC000014FL) +#endif + +#ifndef STATUS_SERIAL_NO_DEVICE_INITED +# define STATUS_SERIAL_NO_DEVICE_INITED ((NTSTATUS) 0xC0000150L) +#endif + +#ifndef STATUS_NO_SUCH_ALIAS +# define STATUS_NO_SUCH_ALIAS ((NTSTATUS) 0xC0000151L) +#endif + +#ifndef STATUS_MEMBER_NOT_IN_ALIAS +# define STATUS_MEMBER_NOT_IN_ALIAS ((NTSTATUS) 0xC0000152L) +#endif + +#ifndef STATUS_MEMBER_IN_ALIAS +# define STATUS_MEMBER_IN_ALIAS ((NTSTATUS) 0xC0000153L) +#endif + +#ifndef STATUS_ALIAS_EXISTS +# define STATUS_ALIAS_EXISTS ((NTSTATUS) 0xC0000154L) +#endif + +#ifndef STATUS_LOGON_NOT_GRANTED +# define STATUS_LOGON_NOT_GRANTED ((NTSTATUS) 0xC0000155L) +#endif + +#ifndef STATUS_TOO_MANY_SECRETS +# define STATUS_TOO_MANY_SECRETS ((NTSTATUS) 0xC0000156L) +#endif + +#ifndef STATUS_SECRET_TOO_LONG +# define STATUS_SECRET_TOO_LONG ((NTSTATUS) 0xC0000157L) +#endif + +#ifndef STATUS_INTERNAL_DB_ERROR +# define STATUS_INTERNAL_DB_ERROR ((NTSTATUS) 0xC0000158L) +#endif + +#ifndef STATUS_FULLSCREEN_MODE +# define STATUS_FULLSCREEN_MODE ((NTSTATUS) 0xC0000159L) +#endif + +#ifndef STATUS_TOO_MANY_CONTEXT_IDS +# define STATUS_TOO_MANY_CONTEXT_IDS ((NTSTATUS) 0xC000015AL) +#endif + +#ifndef STATUS_LOGON_TYPE_NOT_GRANTED +# define STATUS_LOGON_TYPE_NOT_GRANTED ((NTSTATUS) 0xC000015BL) +#endif + +#ifndef STATUS_NOT_REGISTRY_FILE +# define STATUS_NOT_REGISTRY_FILE ((NTSTATUS) 0xC000015CL) +#endif + +#ifndef STATUS_NT_CROSS_ENCRYPTION_REQUIRED +# define STATUS_NT_CROSS_ENCRYPTION_REQUIRED ((NTSTATUS) 0xC000015DL) +#endif + +#ifndef STATUS_DOMAIN_CTRLR_CONFIG_ERROR +# define STATUS_DOMAIN_CTRLR_CONFIG_ERROR ((NTSTATUS) 0xC000015EL) +#endif + +#ifndef STATUS_FT_MISSING_MEMBER +# define STATUS_FT_MISSING_MEMBER ((NTSTATUS) 0xC000015FL) +#endif + +#ifndef STATUS_ILL_FORMED_SERVICE_ENTRY +# define STATUS_ILL_FORMED_SERVICE_ENTRY ((NTSTATUS) 0xC0000160L) +#endif + +#ifndef STATUS_ILLEGAL_CHARACTER +# define STATUS_ILLEGAL_CHARACTER ((NTSTATUS) 0xC0000161L) +#endif + +#ifndef STATUS_UNMAPPABLE_CHARACTER +# define STATUS_UNMAPPABLE_CHARACTER ((NTSTATUS) 0xC0000162L) +#endif + +#ifndef STATUS_UNDEFINED_CHARACTER +# define STATUS_UNDEFINED_CHARACTER ((NTSTATUS) 0xC0000163L) +#endif + +#ifndef STATUS_FLOPPY_VOLUME +# define STATUS_FLOPPY_VOLUME ((NTSTATUS) 0xC0000164L) +#endif + +#ifndef STATUS_FLOPPY_ID_MARK_NOT_FOUND +# define STATUS_FLOPPY_ID_MARK_NOT_FOUND ((NTSTATUS) 0xC0000165L) +#endif + +#ifndef STATUS_FLOPPY_WRONG_CYLINDER +# define STATUS_FLOPPY_WRONG_CYLINDER ((NTSTATUS) 0xC0000166L) +#endif + +#ifndef STATUS_FLOPPY_UNKNOWN_ERROR +# define STATUS_FLOPPY_UNKNOWN_ERROR ((NTSTATUS) 0xC0000167L) +#endif + +#ifndef STATUS_FLOPPY_BAD_REGISTERS +# define STATUS_FLOPPY_BAD_REGISTERS ((NTSTATUS) 0xC0000168L) +#endif + +#ifndef STATUS_DISK_RECALIBRATE_FAILED +# define STATUS_DISK_RECALIBRATE_FAILED ((NTSTATUS) 0xC0000169L) +#endif + +#ifndef STATUS_DISK_OPERATION_FAILED +# define STATUS_DISK_OPERATION_FAILED ((NTSTATUS) 0xC000016AL) +#endif + +#ifndef STATUS_DISK_RESET_FAILED +# define STATUS_DISK_RESET_FAILED ((NTSTATUS) 0xC000016BL) +#endif + +#ifndef STATUS_SHARED_IRQ_BUSY +# define STATUS_SHARED_IRQ_BUSY ((NTSTATUS) 0xC000016CL) +#endif + +#ifndef STATUS_FT_ORPHANING +# define STATUS_FT_ORPHANING ((NTSTATUS) 0xC000016DL) +#endif + +#ifndef STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT +# define STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT ((NTSTATUS) 0xC000016EL) +#endif + +#ifndef STATUS_PARTITION_FAILURE +# define STATUS_PARTITION_FAILURE ((NTSTATUS) 0xC0000172L) +#endif + +#ifndef STATUS_INVALID_BLOCK_LENGTH +# define STATUS_INVALID_BLOCK_LENGTH ((NTSTATUS) 0xC0000173L) +#endif + +#ifndef STATUS_DEVICE_NOT_PARTITIONED +# define STATUS_DEVICE_NOT_PARTITIONED ((NTSTATUS) 0xC0000174L) +#endif + +#ifndef STATUS_UNABLE_TO_LOCK_MEDIA +# define STATUS_UNABLE_TO_LOCK_MEDIA ((NTSTATUS) 0xC0000175L) +#endif + +#ifndef STATUS_UNABLE_TO_UNLOAD_MEDIA +# define STATUS_UNABLE_TO_UNLOAD_MEDIA ((NTSTATUS) 0xC0000176L) +#endif + +#ifndef STATUS_EOM_OVERFLOW +# define STATUS_EOM_OVERFLOW ((NTSTATUS) 0xC0000177L) +#endif + +#ifndef STATUS_NO_MEDIA +# define STATUS_NO_MEDIA ((NTSTATUS) 0xC0000178L) +#endif + +#ifndef STATUS_NO_SUCH_MEMBER +# define STATUS_NO_SUCH_MEMBER ((NTSTATUS) 0xC000017AL) +#endif + +#ifndef STATUS_INVALID_MEMBER +# define STATUS_INVALID_MEMBER ((NTSTATUS) 0xC000017BL) +#endif + +#ifndef STATUS_KEY_DELETED +# define STATUS_KEY_DELETED ((NTSTATUS) 0xC000017CL) +#endif + +#ifndef STATUS_NO_LOG_SPACE +# define STATUS_NO_LOG_SPACE ((NTSTATUS) 0xC000017DL) +#endif + +#ifndef STATUS_TOO_MANY_SIDS +# define STATUS_TOO_MANY_SIDS ((NTSTATUS) 0xC000017EL) +#endif + +#ifndef STATUS_LM_CROSS_ENCRYPTION_REQUIRED +# define STATUS_LM_CROSS_ENCRYPTION_REQUIRED ((NTSTATUS) 0xC000017FL) +#endif + +#ifndef STATUS_KEY_HAS_CHILDREN +# define STATUS_KEY_HAS_CHILDREN ((NTSTATUS) 0xC0000180L) +#endif + +#ifndef STATUS_CHILD_MUST_BE_VOLATILE +# define STATUS_CHILD_MUST_BE_VOLATILE ((NTSTATUS) 0xC0000181L) +#endif + +#ifndef STATUS_DEVICE_CONFIGURATION_ERROR +# define STATUS_DEVICE_CONFIGURATION_ERROR ((NTSTATUS) 0xC0000182L) +#endif + +#ifndef STATUS_DRIVER_INTERNAL_ERROR +# define STATUS_DRIVER_INTERNAL_ERROR ((NTSTATUS) 0xC0000183L) +#endif + +#ifndef STATUS_INVALID_DEVICE_STATE +# define STATUS_INVALID_DEVICE_STATE ((NTSTATUS) 0xC0000184L) +#endif + +#ifndef STATUS_IO_DEVICE_ERROR +# define STATUS_IO_DEVICE_ERROR ((NTSTATUS) 0xC0000185L) +#endif + +#ifndef STATUS_DEVICE_PROTOCOL_ERROR +# define STATUS_DEVICE_PROTOCOL_ERROR ((NTSTATUS) 0xC0000186L) +#endif + +#ifndef STATUS_BACKUP_CONTROLLER +# define STATUS_BACKUP_CONTROLLER ((NTSTATUS) 0xC0000187L) +#endif + +#ifndef STATUS_LOG_FILE_FULL +# define STATUS_LOG_FILE_FULL ((NTSTATUS) 0xC0000188L) +#endif + +#ifndef STATUS_TOO_LATE +# define STATUS_TOO_LATE ((NTSTATUS) 0xC0000189L) +#endif + +#ifndef STATUS_NO_TRUST_LSA_SECRET +# define STATUS_NO_TRUST_LSA_SECRET ((NTSTATUS) 0xC000018AL) +#endif + +#ifndef STATUS_NO_TRUST_SAM_ACCOUNT +# define STATUS_NO_TRUST_SAM_ACCOUNT ((NTSTATUS) 0xC000018BL) +#endif + +#ifndef STATUS_TRUSTED_DOMAIN_FAILURE +# define STATUS_TRUSTED_DOMAIN_FAILURE ((NTSTATUS) 0xC000018CL) +#endif + +#ifndef STATUS_TRUSTED_RELATIONSHIP_FAILURE +# define STATUS_TRUSTED_RELATIONSHIP_FAILURE ((NTSTATUS) 0xC000018DL) +#endif + +#ifndef STATUS_EVENTLOG_FILE_CORRUPT +# define STATUS_EVENTLOG_FILE_CORRUPT ((NTSTATUS) 0xC000018EL) +#endif + +#ifndef STATUS_EVENTLOG_CANT_START +# define STATUS_EVENTLOG_CANT_START ((NTSTATUS) 0xC000018FL) +#endif + +#ifndef STATUS_TRUST_FAILURE +# define STATUS_TRUST_FAILURE ((NTSTATUS) 0xC0000190L) +#endif + +#ifndef STATUS_MUTANT_LIMIT_EXCEEDED +# define STATUS_MUTANT_LIMIT_EXCEEDED ((NTSTATUS) 0xC0000191L) +#endif + +#ifndef STATUS_NETLOGON_NOT_STARTED +# define STATUS_NETLOGON_NOT_STARTED ((NTSTATUS) 0xC0000192L) +#endif + +#ifndef STATUS_ACCOUNT_EXPIRED +# define STATUS_ACCOUNT_EXPIRED ((NTSTATUS) 0xC0000193L) +#endif + +#ifndef STATUS_POSSIBLE_DEADLOCK +# define STATUS_POSSIBLE_DEADLOCK ((NTSTATUS) 0xC0000194L) +#endif + +#ifndef STATUS_NETWORK_CREDENTIAL_CONFLICT +# define STATUS_NETWORK_CREDENTIAL_CONFLICT ((NTSTATUS) 0xC0000195L) +#endif + +#ifndef STATUS_REMOTE_SESSION_LIMIT +# define STATUS_REMOTE_SESSION_LIMIT ((NTSTATUS) 0xC0000196L) +#endif + +#ifndef STATUS_EVENTLOG_FILE_CHANGED +# define STATUS_EVENTLOG_FILE_CHANGED ((NTSTATUS) 0xC0000197L) +#endif + +#ifndef STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT +# define STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT ((NTSTATUS) 0xC0000198L) +#endif + +#ifndef STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT +# define STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT ((NTSTATUS) 0xC0000199L) +#endif + +#ifndef STATUS_NOLOGON_SERVER_TRUST_ACCOUNT +# define STATUS_NOLOGON_SERVER_TRUST_ACCOUNT ((NTSTATUS) 0xC000019AL) +#endif + +#ifndef STATUS_DOMAIN_TRUST_INCONSISTENT +# define STATUS_DOMAIN_TRUST_INCONSISTENT ((NTSTATUS) 0xC000019BL) +#endif + +#ifndef STATUS_FS_DRIVER_REQUIRED +# define STATUS_FS_DRIVER_REQUIRED ((NTSTATUS) 0xC000019CL) +#endif + +#ifndef STATUS_IMAGE_ALREADY_LOADED_AS_DLL +# define STATUS_IMAGE_ALREADY_LOADED_AS_DLL ((NTSTATUS) 0xC000019DL) +#endif + +#ifndef STATUS_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING +# define STATUS_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING ((NTSTATUS) 0xC000019EL) +#endif + +#ifndef STATUS_SHORT_NAMES_NOT_ENABLED_ON_VOLUME +# define STATUS_SHORT_NAMES_NOT_ENABLED_ON_VOLUME ((NTSTATUS) 0xC000019FL) +#endif + +#ifndef STATUS_SECURITY_STREAM_IS_INCONSISTENT +# define STATUS_SECURITY_STREAM_IS_INCONSISTENT ((NTSTATUS) 0xC00001A0L) +#endif + +#ifndef STATUS_INVALID_LOCK_RANGE +# define STATUS_INVALID_LOCK_RANGE ((NTSTATUS) 0xC00001A1L) +#endif + +#ifndef STATUS_INVALID_ACE_CONDITION +# define STATUS_INVALID_ACE_CONDITION ((NTSTATUS) 0xC00001A2L) +#endif + +#ifndef STATUS_IMAGE_SUBSYSTEM_NOT_PRESENT +# define STATUS_IMAGE_SUBSYSTEM_NOT_PRESENT ((NTSTATUS) 0xC00001A3L) +#endif + +#ifndef STATUS_NOTIFICATION_GUID_ALREADY_DEFINED +# define STATUS_NOTIFICATION_GUID_ALREADY_DEFINED ((NTSTATUS) 0xC00001A4L) +#endif + +#ifndef STATUS_NETWORK_OPEN_RESTRICTION +# define STATUS_NETWORK_OPEN_RESTRICTION ((NTSTATUS) 0xC0000201L) +#endif + +#ifndef STATUS_NO_USER_SESSION_KEY +# define STATUS_NO_USER_SESSION_KEY ((NTSTATUS) 0xC0000202L) +#endif + +#ifndef STATUS_USER_SESSION_DELETED +# define STATUS_USER_SESSION_DELETED ((NTSTATUS) 0xC0000203L) +#endif + +#ifndef STATUS_RESOURCE_LANG_NOT_FOUND +# define STATUS_RESOURCE_LANG_NOT_FOUND ((NTSTATUS) 0xC0000204L) +#endif + +#ifndef STATUS_INSUFF_SERVER_RESOURCES +# define STATUS_INSUFF_SERVER_RESOURCES ((NTSTATUS) 0xC0000205L) +#endif + +#ifndef STATUS_INVALID_BUFFER_SIZE +# define STATUS_INVALID_BUFFER_SIZE ((NTSTATUS) 0xC0000206L) +#endif + +#ifndef STATUS_INVALID_ADDRESS_COMPONENT +# define STATUS_INVALID_ADDRESS_COMPONENT ((NTSTATUS) 0xC0000207L) +#endif + +#ifndef STATUS_INVALID_ADDRESS_WILDCARD +# define STATUS_INVALID_ADDRESS_WILDCARD ((NTSTATUS) 0xC0000208L) +#endif + +#ifndef STATUS_TOO_MANY_ADDRESSES +# define STATUS_TOO_MANY_ADDRESSES ((NTSTATUS) 0xC0000209L) +#endif + +#ifndef STATUS_ADDRESS_ALREADY_EXISTS +# define STATUS_ADDRESS_ALREADY_EXISTS ((NTSTATUS) 0xC000020AL) +#endif + +#ifndef STATUS_ADDRESS_CLOSED +# define STATUS_ADDRESS_CLOSED ((NTSTATUS) 0xC000020BL) +#endif + +#ifndef STATUS_CONNECTION_DISCONNECTED +# define STATUS_CONNECTION_DISCONNECTED ((NTSTATUS) 0xC000020CL) +#endif + +#ifndef STATUS_CONNECTION_RESET +# define STATUS_CONNECTION_RESET ((NTSTATUS) 0xC000020DL) +#endif + +#ifndef STATUS_TOO_MANY_NODES +# define STATUS_TOO_MANY_NODES ((NTSTATUS) 0xC000020EL) +#endif + +#ifndef STATUS_TRANSACTION_ABORTED +# define STATUS_TRANSACTION_ABORTED ((NTSTATUS) 0xC000020FL) +#endif + +#ifndef STATUS_TRANSACTION_TIMED_OUT +# define STATUS_TRANSACTION_TIMED_OUT ((NTSTATUS) 0xC0000210L) +#endif + +#ifndef STATUS_TRANSACTION_NO_RELEASE +# define STATUS_TRANSACTION_NO_RELEASE ((NTSTATUS) 0xC0000211L) +#endif + +#ifndef STATUS_TRANSACTION_NO_MATCH +# define STATUS_TRANSACTION_NO_MATCH ((NTSTATUS) 0xC0000212L) +#endif + +#ifndef STATUS_TRANSACTION_RESPONDED +# define STATUS_TRANSACTION_RESPONDED ((NTSTATUS) 0xC0000213L) +#endif + +#ifndef STATUS_TRANSACTION_INVALID_ID +# define STATUS_TRANSACTION_INVALID_ID ((NTSTATUS) 0xC0000214L) +#endif + +#ifndef STATUS_TRANSACTION_INVALID_TYPE +# define STATUS_TRANSACTION_INVALID_TYPE ((NTSTATUS) 0xC0000215L) +#endif + +#ifndef STATUS_NOT_SERVER_SESSION +# define STATUS_NOT_SERVER_SESSION ((NTSTATUS) 0xC0000216L) +#endif + +#ifndef STATUS_NOT_CLIENT_SESSION +# define STATUS_NOT_CLIENT_SESSION ((NTSTATUS) 0xC0000217L) +#endif + +#ifndef STATUS_CANNOT_LOAD_REGISTRY_FILE +# define STATUS_CANNOT_LOAD_REGISTRY_FILE ((NTSTATUS) 0xC0000218L) +#endif + +#ifndef STATUS_DEBUG_ATTACH_FAILED +# define STATUS_DEBUG_ATTACH_FAILED ((NTSTATUS) 0xC0000219L) +#endif + +#ifndef STATUS_SYSTEM_PROCESS_TERMINATED +# define STATUS_SYSTEM_PROCESS_TERMINATED ((NTSTATUS) 0xC000021AL) +#endif + +#ifndef STATUS_DATA_NOT_ACCEPTED +# define STATUS_DATA_NOT_ACCEPTED ((NTSTATUS) 0xC000021BL) +#endif + +#ifndef STATUS_NO_BROWSER_SERVERS_FOUND +# define STATUS_NO_BROWSER_SERVERS_FOUND ((NTSTATUS) 0xC000021CL) +#endif + +#ifndef STATUS_VDM_HARD_ERROR +# define STATUS_VDM_HARD_ERROR ((NTSTATUS) 0xC000021DL) +#endif + +#ifndef STATUS_DRIVER_CANCEL_TIMEOUT +# define STATUS_DRIVER_CANCEL_TIMEOUT ((NTSTATUS) 0xC000021EL) +#endif + +#ifndef STATUS_REPLY_MESSAGE_MISMATCH +# define STATUS_REPLY_MESSAGE_MISMATCH ((NTSTATUS) 0xC000021FL) +#endif + +#ifndef STATUS_MAPPED_ALIGNMENT +# define STATUS_MAPPED_ALIGNMENT ((NTSTATUS) 0xC0000220L) +#endif + +#ifndef STATUS_IMAGE_CHECKSUM_MISMATCH +# define STATUS_IMAGE_CHECKSUM_MISMATCH ((NTSTATUS) 0xC0000221L) +#endif + +#ifndef STATUS_LOST_WRITEBEHIND_DATA +# define STATUS_LOST_WRITEBEHIND_DATA ((NTSTATUS) 0xC0000222L) +#endif + +#ifndef STATUS_CLIENT_SERVER_PARAMETERS_INVALID +# define STATUS_CLIENT_SERVER_PARAMETERS_INVALID ((NTSTATUS) 0xC0000223L) +#endif + +#ifndef STATUS_PASSWORD_MUST_CHANGE +# define STATUS_PASSWORD_MUST_CHANGE ((NTSTATUS) 0xC0000224L) +#endif + +#ifndef STATUS_NOT_FOUND +# define STATUS_NOT_FOUND ((NTSTATUS) 0xC0000225L) +#endif + +#ifndef STATUS_NOT_TINY_STREAM +# define STATUS_NOT_TINY_STREAM ((NTSTATUS) 0xC0000226L) +#endif + +#ifndef STATUS_RECOVERY_FAILURE +# define STATUS_RECOVERY_FAILURE ((NTSTATUS) 0xC0000227L) +#endif + +#ifndef STATUS_STACK_OVERFLOW_READ +# define STATUS_STACK_OVERFLOW_READ ((NTSTATUS) 0xC0000228L) +#endif + +#ifndef STATUS_FAIL_CHECK +# define STATUS_FAIL_CHECK ((NTSTATUS) 0xC0000229L) +#endif + +#ifndef STATUS_DUPLICATE_OBJECTID +# define STATUS_DUPLICATE_OBJECTID ((NTSTATUS) 0xC000022AL) +#endif + +#ifndef STATUS_OBJECTID_EXISTS +# define STATUS_OBJECTID_EXISTS ((NTSTATUS) 0xC000022BL) +#endif + +#ifndef STATUS_CONVERT_TO_LARGE +# define STATUS_CONVERT_TO_LARGE ((NTSTATUS) 0xC000022CL) +#endif + +#ifndef STATUS_RETRY +# define STATUS_RETRY ((NTSTATUS) 0xC000022DL) +#endif + +#ifndef STATUS_FOUND_OUT_OF_SCOPE +# define STATUS_FOUND_OUT_OF_SCOPE ((NTSTATUS) 0xC000022EL) +#endif + +#ifndef STATUS_ALLOCATE_BUCKET +# define STATUS_ALLOCATE_BUCKET ((NTSTATUS) 0xC000022FL) +#endif + +#ifndef STATUS_PROPSET_NOT_FOUND +# define STATUS_PROPSET_NOT_FOUND ((NTSTATUS) 0xC0000230L) +#endif + +#ifndef STATUS_MARSHALL_OVERFLOW +# define STATUS_MARSHALL_OVERFLOW ((NTSTATUS) 0xC0000231L) +#endif + +#ifndef STATUS_INVALID_VARIANT +# define STATUS_INVALID_VARIANT ((NTSTATUS) 0xC0000232L) +#endif + +#ifndef STATUS_DOMAIN_CONTROLLER_NOT_FOUND +# define STATUS_DOMAIN_CONTROLLER_NOT_FOUND ((NTSTATUS) 0xC0000233L) +#endif + +#ifndef STATUS_ACCOUNT_LOCKED_OUT +# define STATUS_ACCOUNT_LOCKED_OUT ((NTSTATUS) 0xC0000234L) +#endif + +#ifndef STATUS_HANDLE_NOT_CLOSABLE +# define STATUS_HANDLE_NOT_CLOSABLE ((NTSTATUS) 0xC0000235L) +#endif + +#ifndef STATUS_CONNECTION_REFUSED +# define STATUS_CONNECTION_REFUSED ((NTSTATUS) 0xC0000236L) +#endif + +#ifndef STATUS_GRACEFUL_DISCONNECT +# define STATUS_GRACEFUL_DISCONNECT ((NTSTATUS) 0xC0000237L) +#endif + +#ifndef STATUS_ADDRESS_ALREADY_ASSOCIATED +# define STATUS_ADDRESS_ALREADY_ASSOCIATED ((NTSTATUS) 0xC0000238L) +#endif + +#ifndef STATUS_ADDRESS_NOT_ASSOCIATED +# define STATUS_ADDRESS_NOT_ASSOCIATED ((NTSTATUS) 0xC0000239L) +#endif + +#ifndef STATUS_CONNECTION_INVALID +# define STATUS_CONNECTION_INVALID ((NTSTATUS) 0xC000023AL) +#endif + +#ifndef STATUS_CONNECTION_ACTIVE +# define STATUS_CONNECTION_ACTIVE ((NTSTATUS) 0xC000023BL) +#endif + +#ifndef STATUS_NETWORK_UNREACHABLE +# define STATUS_NETWORK_UNREACHABLE ((NTSTATUS) 0xC000023CL) +#endif + +#ifndef STATUS_HOST_UNREACHABLE +# define STATUS_HOST_UNREACHABLE ((NTSTATUS) 0xC000023DL) +#endif + +#ifndef STATUS_PROTOCOL_UNREACHABLE +# define STATUS_PROTOCOL_UNREACHABLE ((NTSTATUS) 0xC000023EL) +#endif + +#ifndef STATUS_PORT_UNREACHABLE +# define STATUS_PORT_UNREACHABLE ((NTSTATUS) 0xC000023FL) +#endif + +#ifndef STATUS_REQUEST_ABORTED +# define STATUS_REQUEST_ABORTED ((NTSTATUS) 0xC0000240L) +#endif + +#ifndef STATUS_CONNECTION_ABORTED +# define STATUS_CONNECTION_ABORTED ((NTSTATUS) 0xC0000241L) +#endif + +#ifndef STATUS_BAD_COMPRESSION_BUFFER +# define STATUS_BAD_COMPRESSION_BUFFER ((NTSTATUS) 0xC0000242L) +#endif + +#ifndef STATUS_USER_MAPPED_FILE +# define STATUS_USER_MAPPED_FILE ((NTSTATUS) 0xC0000243L) +#endif + +#ifndef STATUS_AUDIT_FAILED +# define STATUS_AUDIT_FAILED ((NTSTATUS) 0xC0000244L) +#endif + +#ifndef STATUS_TIMER_RESOLUTION_NOT_SET +# define STATUS_TIMER_RESOLUTION_NOT_SET ((NTSTATUS) 0xC0000245L) +#endif + +#ifndef STATUS_CONNECTION_COUNT_LIMIT +# define STATUS_CONNECTION_COUNT_LIMIT ((NTSTATUS) 0xC0000246L) +#endif + +#ifndef STATUS_LOGIN_TIME_RESTRICTION +# define STATUS_LOGIN_TIME_RESTRICTION ((NTSTATUS) 0xC0000247L) +#endif + +#ifndef STATUS_LOGIN_WKSTA_RESTRICTION +# define STATUS_LOGIN_WKSTA_RESTRICTION ((NTSTATUS) 0xC0000248L) +#endif + +#ifndef STATUS_IMAGE_MP_UP_MISMATCH +# define STATUS_IMAGE_MP_UP_MISMATCH ((NTSTATUS) 0xC0000249L) +#endif + +#ifndef STATUS_INSUFFICIENT_LOGON_INFO +# define STATUS_INSUFFICIENT_LOGON_INFO ((NTSTATUS) 0xC0000250L) +#endif + +#ifndef STATUS_BAD_DLL_ENTRYPOINT +# define STATUS_BAD_DLL_ENTRYPOINT ((NTSTATUS) 0xC0000251L) +#endif + +#ifndef STATUS_BAD_SERVICE_ENTRYPOINT +# define STATUS_BAD_SERVICE_ENTRYPOINT ((NTSTATUS) 0xC0000252L) +#endif + +#ifndef STATUS_LPC_REPLY_LOST +# define STATUS_LPC_REPLY_LOST ((NTSTATUS) 0xC0000253L) +#endif + +#ifndef STATUS_IP_ADDRESS_CONFLICT1 +# define STATUS_IP_ADDRESS_CONFLICT1 ((NTSTATUS) 0xC0000254L) +#endif + +#ifndef STATUS_IP_ADDRESS_CONFLICT2 +# define STATUS_IP_ADDRESS_CONFLICT2 ((NTSTATUS) 0xC0000255L) +#endif + +#ifndef STATUS_REGISTRY_QUOTA_LIMIT +# define STATUS_REGISTRY_QUOTA_LIMIT ((NTSTATUS) 0xC0000256L) +#endif + +#ifndef STATUS_PATH_NOT_COVERED +# define STATUS_PATH_NOT_COVERED ((NTSTATUS) 0xC0000257L) +#endif + +#ifndef STATUS_NO_CALLBACK_ACTIVE +# define STATUS_NO_CALLBACK_ACTIVE ((NTSTATUS) 0xC0000258L) +#endif + +#ifndef STATUS_LICENSE_QUOTA_EXCEEDED +# define STATUS_LICENSE_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000259L) +#endif + +#ifndef STATUS_PWD_TOO_SHORT +# define STATUS_PWD_TOO_SHORT ((NTSTATUS) 0xC000025AL) +#endif + +#ifndef STATUS_PWD_TOO_RECENT +# define STATUS_PWD_TOO_RECENT ((NTSTATUS) 0xC000025BL) +#endif + +#ifndef STATUS_PWD_HISTORY_CONFLICT +# define STATUS_PWD_HISTORY_CONFLICT ((NTSTATUS) 0xC000025CL) +#endif + +#ifndef STATUS_PLUGPLAY_NO_DEVICE +# define STATUS_PLUGPLAY_NO_DEVICE ((NTSTATUS) 0xC000025EL) +#endif + +#ifndef STATUS_UNSUPPORTED_COMPRESSION +# define STATUS_UNSUPPORTED_COMPRESSION ((NTSTATUS) 0xC000025FL) +#endif + +#ifndef STATUS_INVALID_HW_PROFILE +# define STATUS_INVALID_HW_PROFILE ((NTSTATUS) 0xC0000260L) +#endif + +#ifndef STATUS_INVALID_PLUGPLAY_DEVICE_PATH +# define STATUS_INVALID_PLUGPLAY_DEVICE_PATH ((NTSTATUS) 0xC0000261L) +#endif + +#ifndef STATUS_DRIVER_ORDINAL_NOT_FOUND +# define STATUS_DRIVER_ORDINAL_NOT_FOUND ((NTSTATUS) 0xC0000262L) +#endif + +#ifndef STATUS_DRIVER_ENTRYPOINT_NOT_FOUND +# define STATUS_DRIVER_ENTRYPOINT_NOT_FOUND ((NTSTATUS) 0xC0000263L) +#endif + +#ifndef STATUS_RESOURCE_NOT_OWNED +# define STATUS_RESOURCE_NOT_OWNED ((NTSTATUS) 0xC0000264L) +#endif + +#ifndef STATUS_TOO_MANY_LINKS +# define STATUS_TOO_MANY_LINKS ((NTSTATUS) 0xC0000265L) +#endif + +#ifndef STATUS_QUOTA_LIST_INCONSISTENT +# define STATUS_QUOTA_LIST_INCONSISTENT ((NTSTATUS) 0xC0000266L) +#endif + +#ifndef STATUS_FILE_IS_OFFLINE +# define STATUS_FILE_IS_OFFLINE ((NTSTATUS) 0xC0000267L) +#endif + +#ifndef STATUS_EVALUATION_EXPIRATION +# define STATUS_EVALUATION_EXPIRATION ((NTSTATUS) 0xC0000268L) +#endif + +#ifndef STATUS_ILLEGAL_DLL_RELOCATION +# define STATUS_ILLEGAL_DLL_RELOCATION ((NTSTATUS) 0xC0000269L) +#endif + +#ifndef STATUS_LICENSE_VIOLATION +# define STATUS_LICENSE_VIOLATION ((NTSTATUS) 0xC000026AL) +#endif + +#ifndef STATUS_DLL_INIT_FAILED_LOGOFF +# define STATUS_DLL_INIT_FAILED_LOGOFF ((NTSTATUS) 0xC000026BL) +#endif + +#ifndef STATUS_DRIVER_UNABLE_TO_LOAD +# define STATUS_DRIVER_UNABLE_TO_LOAD ((NTSTATUS) 0xC000026CL) +#endif + +#ifndef STATUS_DFS_UNAVAILABLE +# define STATUS_DFS_UNAVAILABLE ((NTSTATUS) 0xC000026DL) +#endif + +#ifndef STATUS_VOLUME_DISMOUNTED +# define STATUS_VOLUME_DISMOUNTED ((NTSTATUS) 0xC000026EL) +#endif + +#ifndef STATUS_WX86_INTERNAL_ERROR +# define STATUS_WX86_INTERNAL_ERROR ((NTSTATUS) 0xC000026FL) +#endif + +#ifndef STATUS_WX86_FLOAT_STACK_CHECK +# define STATUS_WX86_FLOAT_STACK_CHECK ((NTSTATUS) 0xC0000270L) +#endif + +#ifndef STATUS_VALIDATE_CONTINUE +# define STATUS_VALIDATE_CONTINUE ((NTSTATUS) 0xC0000271L) +#endif + +#ifndef STATUS_NO_MATCH +# define STATUS_NO_MATCH ((NTSTATUS) 0xC0000272L) +#endif + +#ifndef STATUS_NO_MORE_MATCHES +# define STATUS_NO_MORE_MATCHES ((NTSTATUS) 0xC0000273L) +#endif + +#ifndef STATUS_NOT_A_REPARSE_POINT +# define STATUS_NOT_A_REPARSE_POINT ((NTSTATUS) 0xC0000275L) +#endif + +#ifndef STATUS_IO_REPARSE_TAG_INVALID +# define STATUS_IO_REPARSE_TAG_INVALID ((NTSTATUS) 0xC0000276L) +#endif + +#ifndef STATUS_IO_REPARSE_TAG_MISMATCH +# define STATUS_IO_REPARSE_TAG_MISMATCH ((NTSTATUS) 0xC0000277L) +#endif + +#ifndef STATUS_IO_REPARSE_DATA_INVALID +# define STATUS_IO_REPARSE_DATA_INVALID ((NTSTATUS) 0xC0000278L) +#endif + +#ifndef STATUS_IO_REPARSE_TAG_NOT_HANDLED +# define STATUS_IO_REPARSE_TAG_NOT_HANDLED ((NTSTATUS) 0xC0000279L) +#endif + +#ifndef STATUS_REPARSE_POINT_NOT_RESOLVED +# define STATUS_REPARSE_POINT_NOT_RESOLVED ((NTSTATUS) 0xC0000280L) +#endif + +#ifndef STATUS_DIRECTORY_IS_A_REPARSE_POINT +# define STATUS_DIRECTORY_IS_A_REPARSE_POINT ((NTSTATUS) 0xC0000281L) +#endif + +#ifndef STATUS_RANGE_LIST_CONFLICT +# define STATUS_RANGE_LIST_CONFLICT ((NTSTATUS) 0xC0000282L) +#endif + +#ifndef STATUS_SOURCE_ELEMENT_EMPTY +# define STATUS_SOURCE_ELEMENT_EMPTY ((NTSTATUS) 0xC0000283L) +#endif + +#ifndef STATUS_DESTINATION_ELEMENT_FULL +# define STATUS_DESTINATION_ELEMENT_FULL ((NTSTATUS) 0xC0000284L) +#endif + +#ifndef STATUS_ILLEGAL_ELEMENT_ADDRESS +# define STATUS_ILLEGAL_ELEMENT_ADDRESS ((NTSTATUS) 0xC0000285L) +#endif + +#ifndef STATUS_MAGAZINE_NOT_PRESENT +# define STATUS_MAGAZINE_NOT_PRESENT ((NTSTATUS) 0xC0000286L) +#endif + +#ifndef STATUS_REINITIALIZATION_NEEDED +# define STATUS_REINITIALIZATION_NEEDED ((NTSTATUS) 0xC0000287L) +#endif + +#ifndef STATUS_DEVICE_REQUIRES_CLEANING +# define STATUS_DEVICE_REQUIRES_CLEANING ((NTSTATUS) 0x80000288L) +#endif + +#ifndef STATUS_DEVICE_DOOR_OPEN +# define STATUS_DEVICE_DOOR_OPEN ((NTSTATUS) 0x80000289L) +#endif + +#ifndef STATUS_ENCRYPTION_FAILED +# define STATUS_ENCRYPTION_FAILED ((NTSTATUS) 0xC000028AL) +#endif + +#ifndef STATUS_DECRYPTION_FAILED +# define STATUS_DECRYPTION_FAILED ((NTSTATUS) 0xC000028BL) +#endif + +#ifndef STATUS_RANGE_NOT_FOUND +# define STATUS_RANGE_NOT_FOUND ((NTSTATUS) 0xC000028CL) +#endif + +#ifndef STATUS_NO_RECOVERY_POLICY +# define STATUS_NO_RECOVERY_POLICY ((NTSTATUS) 0xC000028DL) +#endif + +#ifndef STATUS_NO_EFS +# define STATUS_NO_EFS ((NTSTATUS) 0xC000028EL) +#endif + +#ifndef STATUS_WRONG_EFS +# define STATUS_WRONG_EFS ((NTSTATUS) 0xC000028FL) +#endif + +#ifndef STATUS_NO_USER_KEYS +# define STATUS_NO_USER_KEYS ((NTSTATUS) 0xC0000290L) +#endif + +#ifndef STATUS_FILE_NOT_ENCRYPTED +# define STATUS_FILE_NOT_ENCRYPTED ((NTSTATUS) 0xC0000291L) +#endif + +#ifndef STATUS_NOT_EXPORT_FORMAT +# define STATUS_NOT_EXPORT_FORMAT ((NTSTATUS) 0xC0000292L) +#endif + +#ifndef STATUS_FILE_ENCRYPTED +# define STATUS_FILE_ENCRYPTED ((NTSTATUS) 0xC0000293L) +#endif + +#ifndef STATUS_WAKE_SYSTEM +# define STATUS_WAKE_SYSTEM ((NTSTATUS) 0x40000294L) +#endif + +#ifndef STATUS_WMI_GUID_NOT_FOUND +# define STATUS_WMI_GUID_NOT_FOUND ((NTSTATUS) 0xC0000295L) +#endif + +#ifndef STATUS_WMI_INSTANCE_NOT_FOUND +# define STATUS_WMI_INSTANCE_NOT_FOUND ((NTSTATUS) 0xC0000296L) +#endif + +#ifndef STATUS_WMI_ITEMID_NOT_FOUND +# define STATUS_WMI_ITEMID_NOT_FOUND ((NTSTATUS) 0xC0000297L) +#endif + +#ifndef STATUS_WMI_TRY_AGAIN +# define STATUS_WMI_TRY_AGAIN ((NTSTATUS) 0xC0000298L) +#endif + +#ifndef STATUS_SHARED_POLICY +# define STATUS_SHARED_POLICY ((NTSTATUS) 0xC0000299L) +#endif + +#ifndef STATUS_POLICY_OBJECT_NOT_FOUND +# define STATUS_POLICY_OBJECT_NOT_FOUND ((NTSTATUS) 0xC000029AL) +#endif + +#ifndef STATUS_POLICY_ONLY_IN_DS +# define STATUS_POLICY_ONLY_IN_DS ((NTSTATUS) 0xC000029BL) +#endif + +#ifndef STATUS_VOLUME_NOT_UPGRADED +# define STATUS_VOLUME_NOT_UPGRADED ((NTSTATUS) 0xC000029CL) +#endif + +#ifndef STATUS_REMOTE_STORAGE_NOT_ACTIVE +# define STATUS_REMOTE_STORAGE_NOT_ACTIVE ((NTSTATUS) 0xC000029DL) +#endif + +#ifndef STATUS_REMOTE_STORAGE_MEDIA_ERROR +# define STATUS_REMOTE_STORAGE_MEDIA_ERROR ((NTSTATUS) 0xC000029EL) +#endif + +#ifndef STATUS_NO_TRACKING_SERVICE +# define STATUS_NO_TRACKING_SERVICE ((NTSTATUS) 0xC000029FL) +#endif + +#ifndef STATUS_SERVER_SID_MISMATCH +# define STATUS_SERVER_SID_MISMATCH ((NTSTATUS) 0xC00002A0L) +#endif + +#ifndef STATUS_DS_NO_ATTRIBUTE_OR_VALUE +# define STATUS_DS_NO_ATTRIBUTE_OR_VALUE ((NTSTATUS) 0xC00002A1L) +#endif + +#ifndef STATUS_DS_INVALID_ATTRIBUTE_SYNTAX +# define STATUS_DS_INVALID_ATTRIBUTE_SYNTAX ((NTSTATUS) 0xC00002A2L) +#endif + +#ifndef STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED +# define STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED ((NTSTATUS) 0xC00002A3L) +#endif + +#ifndef STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS +# define STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS ((NTSTATUS) 0xC00002A4L) +#endif + +#ifndef STATUS_DS_BUSY +# define STATUS_DS_BUSY ((NTSTATUS) 0xC00002A5L) +#endif + +#ifndef STATUS_DS_UNAVAILABLE +# define STATUS_DS_UNAVAILABLE ((NTSTATUS) 0xC00002A6L) +#endif + +#ifndef STATUS_DS_NO_RIDS_ALLOCATED +# define STATUS_DS_NO_RIDS_ALLOCATED ((NTSTATUS) 0xC00002A7L) +#endif + +#ifndef STATUS_DS_NO_MORE_RIDS +# define STATUS_DS_NO_MORE_RIDS ((NTSTATUS) 0xC00002A8L) +#endif + +#ifndef STATUS_DS_INCORRECT_ROLE_OWNER +# define STATUS_DS_INCORRECT_ROLE_OWNER ((NTSTATUS) 0xC00002A9L) +#endif + +#ifndef STATUS_DS_RIDMGR_INIT_ERROR +# define STATUS_DS_RIDMGR_INIT_ERROR ((NTSTATUS) 0xC00002AAL) +#endif + +#ifndef STATUS_DS_OBJ_CLASS_VIOLATION +# define STATUS_DS_OBJ_CLASS_VIOLATION ((NTSTATUS) 0xC00002ABL) +#endif + +#ifndef STATUS_DS_CANT_ON_NON_LEAF +# define STATUS_DS_CANT_ON_NON_LEAF ((NTSTATUS) 0xC00002ACL) +#endif + +#ifndef STATUS_DS_CANT_ON_RDN +# define STATUS_DS_CANT_ON_RDN ((NTSTATUS) 0xC00002ADL) +#endif + +#ifndef STATUS_DS_CANT_MOD_OBJ_CLASS +# define STATUS_DS_CANT_MOD_OBJ_CLASS ((NTSTATUS) 0xC00002AEL) +#endif + +#ifndef STATUS_DS_CROSS_DOM_MOVE_FAILED +# define STATUS_DS_CROSS_DOM_MOVE_FAILED ((NTSTATUS) 0xC00002AFL) +#endif + +#ifndef STATUS_DS_GC_NOT_AVAILABLE +# define STATUS_DS_GC_NOT_AVAILABLE ((NTSTATUS) 0xC00002B0L) +#endif + +#ifndef STATUS_DIRECTORY_SERVICE_REQUIRED +# define STATUS_DIRECTORY_SERVICE_REQUIRED ((NTSTATUS) 0xC00002B1L) +#endif + +#ifndef STATUS_REPARSE_ATTRIBUTE_CONFLICT +# define STATUS_REPARSE_ATTRIBUTE_CONFLICT ((NTSTATUS) 0xC00002B2L) +#endif + +#ifndef STATUS_CANT_ENABLE_DENY_ONLY +# define STATUS_CANT_ENABLE_DENY_ONLY ((NTSTATUS) 0xC00002B3L) +#endif + +#ifndef STATUS_FLOAT_MULTIPLE_FAULTS +# define STATUS_FLOAT_MULTIPLE_FAULTS ((NTSTATUS) 0xC00002B4L) +#endif + +#ifndef STATUS_FLOAT_MULTIPLE_TRAPS +# define STATUS_FLOAT_MULTIPLE_TRAPS ((NTSTATUS) 0xC00002B5L) +#endif + +#ifndef STATUS_DEVICE_REMOVED +# define STATUS_DEVICE_REMOVED ((NTSTATUS) 0xC00002B6L) +#endif + +#ifndef STATUS_JOURNAL_DELETE_IN_PROGRESS +# define STATUS_JOURNAL_DELETE_IN_PROGRESS ((NTSTATUS) 0xC00002B7L) +#endif + +#ifndef STATUS_JOURNAL_NOT_ACTIVE +# define STATUS_JOURNAL_NOT_ACTIVE ((NTSTATUS) 0xC00002B8L) +#endif + +#ifndef STATUS_NOINTERFACE +# define STATUS_NOINTERFACE ((NTSTATUS) 0xC00002B9L) +#endif + +#ifndef STATUS_DS_ADMIN_LIMIT_EXCEEDED +# define STATUS_DS_ADMIN_LIMIT_EXCEEDED ((NTSTATUS) 0xC00002C1L) +#endif + +#ifndef STATUS_DRIVER_FAILED_SLEEP +# define STATUS_DRIVER_FAILED_SLEEP ((NTSTATUS) 0xC00002C2L) +#endif + +#ifndef STATUS_MUTUAL_AUTHENTICATION_FAILED +# define STATUS_MUTUAL_AUTHENTICATION_FAILED ((NTSTATUS) 0xC00002C3L) +#endif + +#ifndef STATUS_CORRUPT_SYSTEM_FILE +# define STATUS_CORRUPT_SYSTEM_FILE ((NTSTATUS) 0xC00002C4L) +#endif + +#ifndef STATUS_DATATYPE_MISALIGNMENT_ERROR +# define STATUS_DATATYPE_MISALIGNMENT_ERROR ((NTSTATUS) 0xC00002C5L) +#endif + +#ifndef STATUS_WMI_READ_ONLY +# define STATUS_WMI_READ_ONLY ((NTSTATUS) 0xC00002C6L) +#endif + +#ifndef STATUS_WMI_SET_FAILURE +# define STATUS_WMI_SET_FAILURE ((NTSTATUS) 0xC00002C7L) +#endif + +#ifndef STATUS_COMMITMENT_MINIMUM +# define STATUS_COMMITMENT_MINIMUM ((NTSTATUS) 0xC00002C8L) +#endif + +#ifndef STATUS_REG_NAT_CONSUMPTION +# define STATUS_REG_NAT_CONSUMPTION ((NTSTATUS) 0xC00002C9L) +#endif + +#ifndef STATUS_TRANSPORT_FULL +# define STATUS_TRANSPORT_FULL ((NTSTATUS) 0xC00002CAL) +#endif + +#ifndef STATUS_DS_SAM_INIT_FAILURE +# define STATUS_DS_SAM_INIT_FAILURE ((NTSTATUS) 0xC00002CBL) +#endif + +#ifndef STATUS_ONLY_IF_CONNECTED +# define STATUS_ONLY_IF_CONNECTED ((NTSTATUS) 0xC00002CCL) +#endif + +#ifndef STATUS_DS_SENSITIVE_GROUP_VIOLATION +# define STATUS_DS_SENSITIVE_GROUP_VIOLATION ((NTSTATUS) 0xC00002CDL) +#endif + +#ifndef STATUS_PNP_RESTART_ENUMERATION +# define STATUS_PNP_RESTART_ENUMERATION ((NTSTATUS) 0xC00002CEL) +#endif + +#ifndef STATUS_JOURNAL_ENTRY_DELETED +# define STATUS_JOURNAL_ENTRY_DELETED ((NTSTATUS) 0xC00002CFL) +#endif + +#ifndef STATUS_DS_CANT_MOD_PRIMARYGROUPID +# define STATUS_DS_CANT_MOD_PRIMARYGROUPID ((NTSTATUS) 0xC00002D0L) +#endif + +#ifndef STATUS_SYSTEM_IMAGE_BAD_SIGNATURE +# define STATUS_SYSTEM_IMAGE_BAD_SIGNATURE ((NTSTATUS) 0xC00002D1L) +#endif + +#ifndef STATUS_PNP_REBOOT_REQUIRED +# define STATUS_PNP_REBOOT_REQUIRED ((NTSTATUS) 0xC00002D2L) +#endif + +#ifndef STATUS_POWER_STATE_INVALID +# define STATUS_POWER_STATE_INVALID ((NTSTATUS) 0xC00002D3L) +#endif + +#ifndef STATUS_DS_INVALID_GROUP_TYPE +# define STATUS_DS_INVALID_GROUP_TYPE ((NTSTATUS) 0xC00002D4L) +#endif + +#ifndef STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN +# define STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN ((NTSTATUS) 0xC00002D5L) +#endif + +#ifndef STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN +# define STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN ((NTSTATUS) 0xC00002D6L) +#endif + +#ifndef STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER +# define STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER ((NTSTATUS) 0xC00002D7L) +#endif + +#ifndef STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER +# define STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER ((NTSTATUS) 0xC00002D8L) +#endif + +#ifndef STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER +# define STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER ((NTSTATUS) 0xC00002D9L) +#endif + +#ifndef STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER +# define STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER ((NTSTATUS) 0xC00002DAL) +#endif + +#ifndef STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER +# define STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER ((NTSTATUS) 0xC00002DBL) +#endif + +#ifndef STATUS_DS_HAVE_PRIMARY_MEMBERS +# define STATUS_DS_HAVE_PRIMARY_MEMBERS ((NTSTATUS) 0xC00002DCL) +#endif + +#ifndef STATUS_WMI_NOT_SUPPORTED +# define STATUS_WMI_NOT_SUPPORTED ((NTSTATUS) 0xC00002DDL) +#endif + +#ifndef STATUS_INSUFFICIENT_POWER +# define STATUS_INSUFFICIENT_POWER ((NTSTATUS) 0xC00002DEL) +#endif + +#ifndef STATUS_SAM_NEED_BOOTKEY_PASSWORD +# define STATUS_SAM_NEED_BOOTKEY_PASSWORD ((NTSTATUS) 0xC00002DFL) +#endif + +#ifndef STATUS_SAM_NEED_BOOTKEY_FLOPPY +# define STATUS_SAM_NEED_BOOTKEY_FLOPPY ((NTSTATUS) 0xC00002E0L) +#endif + +#ifndef STATUS_DS_CANT_START +# define STATUS_DS_CANT_START ((NTSTATUS) 0xC00002E1L) +#endif + +#ifndef STATUS_DS_INIT_FAILURE +# define STATUS_DS_INIT_FAILURE ((NTSTATUS) 0xC00002E2L) +#endif + +#ifndef STATUS_SAM_INIT_FAILURE +# define STATUS_SAM_INIT_FAILURE ((NTSTATUS) 0xC00002E3L) +#endif + +#ifndef STATUS_DS_GC_REQUIRED +# define STATUS_DS_GC_REQUIRED ((NTSTATUS) 0xC00002E4L) +#endif + +#ifndef STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY +# define STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY ((NTSTATUS) 0xC00002E5L) +#endif + +#ifndef STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS +# define STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS ((NTSTATUS) 0xC00002E6L) +#endif + +#ifndef STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED +# define STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED ((NTSTATUS) 0xC00002E7L) +#endif + +#ifndef STATUS_MULTIPLE_FAULT_VIOLATION +# define STATUS_MULTIPLE_FAULT_VIOLATION ((NTSTATUS) 0xC00002E8L) +#endif + +#ifndef STATUS_CURRENT_DOMAIN_NOT_ALLOWED +# define STATUS_CURRENT_DOMAIN_NOT_ALLOWED ((NTSTATUS) 0xC00002E9L) +#endif + +#ifndef STATUS_CANNOT_MAKE +# define STATUS_CANNOT_MAKE ((NTSTATUS) 0xC00002EAL) +#endif + +#ifndef STATUS_SYSTEM_SHUTDOWN +# define STATUS_SYSTEM_SHUTDOWN ((NTSTATUS) 0xC00002EBL) +#endif + +#ifndef STATUS_DS_INIT_FAILURE_CONSOLE +# define STATUS_DS_INIT_FAILURE_CONSOLE ((NTSTATUS) 0xC00002ECL) +#endif + +#ifndef STATUS_DS_SAM_INIT_FAILURE_CONSOLE +# define STATUS_DS_SAM_INIT_FAILURE_CONSOLE ((NTSTATUS) 0xC00002EDL) +#endif + +#ifndef STATUS_UNFINISHED_CONTEXT_DELETED +# define STATUS_UNFINISHED_CONTEXT_DELETED ((NTSTATUS) 0xC00002EEL) +#endif + +#ifndef STATUS_NO_TGT_REPLY +# define STATUS_NO_TGT_REPLY ((NTSTATUS) 0xC00002EFL) +#endif + +#ifndef STATUS_OBJECTID_NOT_FOUND +# define STATUS_OBJECTID_NOT_FOUND ((NTSTATUS) 0xC00002F0L) +#endif + +#ifndef STATUS_NO_IP_ADDRESSES +# define STATUS_NO_IP_ADDRESSES ((NTSTATUS) 0xC00002F1L) +#endif + +#ifndef STATUS_WRONG_CREDENTIAL_HANDLE +# define STATUS_WRONG_CREDENTIAL_HANDLE ((NTSTATUS) 0xC00002F2L) +#endif + +#ifndef STATUS_CRYPTO_SYSTEM_INVALID +# define STATUS_CRYPTO_SYSTEM_INVALID ((NTSTATUS) 0xC00002F3L) +#endif + +#ifndef STATUS_MAX_REFERRALS_EXCEEDED +# define STATUS_MAX_REFERRALS_EXCEEDED ((NTSTATUS) 0xC00002F4L) +#endif + +#ifndef STATUS_MUST_BE_KDC +# define STATUS_MUST_BE_KDC ((NTSTATUS) 0xC00002F5L) +#endif + +#ifndef STATUS_STRONG_CRYPTO_NOT_SUPPORTED +# define STATUS_STRONG_CRYPTO_NOT_SUPPORTED ((NTSTATUS) 0xC00002F6L) +#endif + +#ifndef STATUS_TOO_MANY_PRINCIPALS +# define STATUS_TOO_MANY_PRINCIPALS ((NTSTATUS) 0xC00002F7L) +#endif + +#ifndef STATUS_NO_PA_DATA +# define STATUS_NO_PA_DATA ((NTSTATUS) 0xC00002F8L) +#endif + +#ifndef STATUS_PKINIT_NAME_MISMATCH +# define STATUS_PKINIT_NAME_MISMATCH ((NTSTATUS) 0xC00002F9L) +#endif + +#ifndef STATUS_SMARTCARD_LOGON_REQUIRED +# define STATUS_SMARTCARD_LOGON_REQUIRED ((NTSTATUS) 0xC00002FAL) +#endif + +#ifndef STATUS_KDC_INVALID_REQUEST +# define STATUS_KDC_INVALID_REQUEST ((NTSTATUS) 0xC00002FBL) +#endif + +#ifndef STATUS_KDC_UNABLE_TO_REFER +# define STATUS_KDC_UNABLE_TO_REFER ((NTSTATUS) 0xC00002FCL) +#endif + +#ifndef STATUS_KDC_UNKNOWN_ETYPE +# define STATUS_KDC_UNKNOWN_ETYPE ((NTSTATUS) 0xC00002FDL) +#endif + +#ifndef STATUS_SHUTDOWN_IN_PROGRESS +# define STATUS_SHUTDOWN_IN_PROGRESS ((NTSTATUS) 0xC00002FEL) +#endif + +#ifndef STATUS_SERVER_SHUTDOWN_IN_PROGRESS +# define STATUS_SERVER_SHUTDOWN_IN_PROGRESS ((NTSTATUS) 0xC00002FFL) +#endif + +#ifndef STATUS_NOT_SUPPORTED_ON_SBS +# define STATUS_NOT_SUPPORTED_ON_SBS ((NTSTATUS) 0xC0000300L) +#endif + +#ifndef STATUS_WMI_GUID_DISCONNECTED +# define STATUS_WMI_GUID_DISCONNECTED ((NTSTATUS) 0xC0000301L) +#endif + +#ifndef STATUS_WMI_ALREADY_DISABLED +# define STATUS_WMI_ALREADY_DISABLED ((NTSTATUS) 0xC0000302L) +#endif + +#ifndef STATUS_WMI_ALREADY_ENABLED +# define STATUS_WMI_ALREADY_ENABLED ((NTSTATUS) 0xC0000303L) +#endif + +#ifndef STATUS_MFT_TOO_FRAGMENTED +# define STATUS_MFT_TOO_FRAGMENTED ((NTSTATUS) 0xC0000304L) +#endif + +#ifndef STATUS_COPY_PROTECTION_FAILURE +# define STATUS_COPY_PROTECTION_FAILURE ((NTSTATUS) 0xC0000305L) +#endif + +#ifndef STATUS_CSS_AUTHENTICATION_FAILURE +# define STATUS_CSS_AUTHENTICATION_FAILURE ((NTSTATUS) 0xC0000306L) +#endif + +#ifndef STATUS_CSS_KEY_NOT_PRESENT +# define STATUS_CSS_KEY_NOT_PRESENT ((NTSTATUS) 0xC0000307L) +#endif + +#ifndef STATUS_CSS_KEY_NOT_ESTABLISHED +# define STATUS_CSS_KEY_NOT_ESTABLISHED ((NTSTATUS) 0xC0000308L) +#endif + +#ifndef STATUS_CSS_SCRAMBLED_SECTOR +# define STATUS_CSS_SCRAMBLED_SECTOR ((NTSTATUS) 0xC0000309L) +#endif + +#ifndef STATUS_CSS_REGION_MISMATCH +# define STATUS_CSS_REGION_MISMATCH ((NTSTATUS) 0xC000030AL) +#endif + +#ifndef STATUS_CSS_RESETS_EXHAUSTED +# define STATUS_CSS_RESETS_EXHAUSTED ((NTSTATUS) 0xC000030BL) +#endif + +#ifndef STATUS_PKINIT_FAILURE +# define STATUS_PKINIT_FAILURE ((NTSTATUS) 0xC0000320L) +#endif + +#ifndef STATUS_SMARTCARD_SUBSYSTEM_FAILURE +# define STATUS_SMARTCARD_SUBSYSTEM_FAILURE ((NTSTATUS) 0xC0000321L) +#endif + +#ifndef STATUS_NO_KERB_KEY +# define STATUS_NO_KERB_KEY ((NTSTATUS) 0xC0000322L) +#endif + +#ifndef STATUS_HOST_DOWN +# define STATUS_HOST_DOWN ((NTSTATUS) 0xC0000350L) +#endif + +#ifndef STATUS_UNSUPPORTED_PREAUTH +# define STATUS_UNSUPPORTED_PREAUTH ((NTSTATUS) 0xC0000351L) +#endif + +#ifndef STATUS_EFS_ALG_BLOB_TOO_BIG +# define STATUS_EFS_ALG_BLOB_TOO_BIG ((NTSTATUS) 0xC0000352L) +#endif + +#ifndef STATUS_PORT_NOT_SET +# define STATUS_PORT_NOT_SET ((NTSTATUS) 0xC0000353L) +#endif + +#ifndef STATUS_DEBUGGER_INACTIVE +# define STATUS_DEBUGGER_INACTIVE ((NTSTATUS) 0xC0000354L) +#endif + +#ifndef STATUS_DS_VERSION_CHECK_FAILURE +# define STATUS_DS_VERSION_CHECK_FAILURE ((NTSTATUS) 0xC0000355L) +#endif + +#ifndef STATUS_AUDITING_DISABLED +# define STATUS_AUDITING_DISABLED ((NTSTATUS) 0xC0000356L) +#endif + +#ifndef STATUS_PRENT4_MACHINE_ACCOUNT +# define STATUS_PRENT4_MACHINE_ACCOUNT ((NTSTATUS) 0xC0000357L) +#endif + +#ifndef STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER +# define STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER ((NTSTATUS) 0xC0000358L) +#endif + +#ifndef STATUS_INVALID_IMAGE_WIN_32 +# define STATUS_INVALID_IMAGE_WIN_32 ((NTSTATUS) 0xC0000359L) +#endif + +#ifndef STATUS_INVALID_IMAGE_WIN_64 +# define STATUS_INVALID_IMAGE_WIN_64 ((NTSTATUS) 0xC000035AL) +#endif + +#ifndef STATUS_BAD_BINDINGS +# define STATUS_BAD_BINDINGS ((NTSTATUS) 0xC000035BL) +#endif + +#ifndef STATUS_NETWORK_SESSION_EXPIRED +# define STATUS_NETWORK_SESSION_EXPIRED ((NTSTATUS) 0xC000035CL) +#endif + +#ifndef STATUS_APPHELP_BLOCK +# define STATUS_APPHELP_BLOCK ((NTSTATUS) 0xC000035DL) +#endif + +#ifndef STATUS_ALL_SIDS_FILTERED +# define STATUS_ALL_SIDS_FILTERED ((NTSTATUS) 0xC000035EL) +#endif + +#ifndef STATUS_NOT_SAFE_MODE_DRIVER +# define STATUS_NOT_SAFE_MODE_DRIVER ((NTSTATUS) 0xC000035FL) +#endif + +#ifndef STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT +# define STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT ((NTSTATUS) 0xC0000361L) +#endif + +#ifndef STATUS_ACCESS_DISABLED_BY_POLICY_PATH +# define STATUS_ACCESS_DISABLED_BY_POLICY_PATH ((NTSTATUS) 0xC0000362L) +#endif + +#ifndef STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER +# define STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER ((NTSTATUS) 0xC0000363L) +#endif + +#ifndef STATUS_ACCESS_DISABLED_BY_POLICY_OTHER +# define STATUS_ACCESS_DISABLED_BY_POLICY_OTHER ((NTSTATUS) 0xC0000364L) +#endif + +#ifndef STATUS_FAILED_DRIVER_ENTRY +# define STATUS_FAILED_DRIVER_ENTRY ((NTSTATUS) 0xC0000365L) +#endif + +#ifndef STATUS_DEVICE_ENUMERATION_ERROR +# define STATUS_DEVICE_ENUMERATION_ERROR ((NTSTATUS) 0xC0000366L) +#endif + +#ifndef STATUS_MOUNT_POINT_NOT_RESOLVED +# define STATUS_MOUNT_POINT_NOT_RESOLVED ((NTSTATUS) 0xC0000368L) +#endif + +#ifndef STATUS_INVALID_DEVICE_OBJECT_PARAMETER +# define STATUS_INVALID_DEVICE_OBJECT_PARAMETER ((NTSTATUS) 0xC0000369L) +#endif + +#ifndef STATUS_MCA_OCCURED +# define STATUS_MCA_OCCURED ((NTSTATUS) 0xC000036AL) +#endif + +#ifndef STATUS_DRIVER_BLOCKED_CRITICAL +# define STATUS_DRIVER_BLOCKED_CRITICAL ((NTSTATUS) 0xC000036BL) +#endif + +#ifndef STATUS_DRIVER_BLOCKED +# define STATUS_DRIVER_BLOCKED ((NTSTATUS) 0xC000036CL) +#endif + +#ifndef STATUS_DRIVER_DATABASE_ERROR +# define STATUS_DRIVER_DATABASE_ERROR ((NTSTATUS) 0xC000036DL) +#endif + +#ifndef STATUS_SYSTEM_HIVE_TOO_LARGE +# define STATUS_SYSTEM_HIVE_TOO_LARGE ((NTSTATUS) 0xC000036EL) +#endif + +#ifndef STATUS_INVALID_IMPORT_OF_NON_DLL +# define STATUS_INVALID_IMPORT_OF_NON_DLL ((NTSTATUS) 0xC000036FL) +#endif + +#ifndef STATUS_DS_SHUTTING_DOWN +# define STATUS_DS_SHUTTING_DOWN ((NTSTATUS) 0x40000370L) +#endif + +#ifndef STATUS_NO_SECRETS +# define STATUS_NO_SECRETS ((NTSTATUS) 0xC0000371L) +#endif + +#ifndef STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY +# define STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY ((NTSTATUS) 0xC0000372L) +#endif + +#ifndef STATUS_FAILED_STACK_SWITCH +# define STATUS_FAILED_STACK_SWITCH ((NTSTATUS) 0xC0000373L) +#endif + +#ifndef STATUS_HEAP_CORRUPTION +# define STATUS_HEAP_CORRUPTION ((NTSTATUS) 0xC0000374L) +#endif + +#ifndef STATUS_SMARTCARD_WRONG_PIN +# define STATUS_SMARTCARD_WRONG_PIN ((NTSTATUS) 0xC0000380L) +#endif + +#ifndef STATUS_SMARTCARD_CARD_BLOCKED +# define STATUS_SMARTCARD_CARD_BLOCKED ((NTSTATUS) 0xC0000381L) +#endif + +#ifndef STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED +# define STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED ((NTSTATUS) 0xC0000382L) +#endif + +#ifndef STATUS_SMARTCARD_NO_CARD +# define STATUS_SMARTCARD_NO_CARD ((NTSTATUS) 0xC0000383L) +#endif + +#ifndef STATUS_SMARTCARD_NO_KEY_CONTAINER +# define STATUS_SMARTCARD_NO_KEY_CONTAINER ((NTSTATUS) 0xC0000384L) +#endif + +#ifndef STATUS_SMARTCARD_NO_CERTIFICATE +# define STATUS_SMARTCARD_NO_CERTIFICATE ((NTSTATUS) 0xC0000385L) +#endif + +#ifndef STATUS_SMARTCARD_NO_KEYSET +# define STATUS_SMARTCARD_NO_KEYSET ((NTSTATUS) 0xC0000386L) +#endif + +#ifndef STATUS_SMARTCARD_IO_ERROR +# define STATUS_SMARTCARD_IO_ERROR ((NTSTATUS) 0xC0000387L) +#endif + +#ifndef STATUS_DOWNGRADE_DETECTED +# define STATUS_DOWNGRADE_DETECTED ((NTSTATUS) 0xC0000388L) +#endif + +#ifndef STATUS_SMARTCARD_CERT_REVOKED +# define STATUS_SMARTCARD_CERT_REVOKED ((NTSTATUS) 0xC0000389L) +#endif + +#ifndef STATUS_ISSUING_CA_UNTRUSTED +# define STATUS_ISSUING_CA_UNTRUSTED ((NTSTATUS) 0xC000038AL) +#endif + +#ifndef STATUS_REVOCATION_OFFLINE_C +# define STATUS_REVOCATION_OFFLINE_C ((NTSTATUS) 0xC000038BL) +#endif + +#ifndef STATUS_PKINIT_CLIENT_FAILURE +# define STATUS_PKINIT_CLIENT_FAILURE ((NTSTATUS) 0xC000038CL) +#endif + +#ifndef STATUS_SMARTCARD_CERT_EXPIRED +# define STATUS_SMARTCARD_CERT_EXPIRED ((NTSTATUS) 0xC000038DL) +#endif + +#ifndef STATUS_DRIVER_FAILED_PRIOR_UNLOAD +# define STATUS_DRIVER_FAILED_PRIOR_UNLOAD ((NTSTATUS) 0xC000038EL) +#endif + +#ifndef STATUS_SMARTCARD_SILENT_CONTEXT +# define STATUS_SMARTCARD_SILENT_CONTEXT ((NTSTATUS) 0xC000038FL) +#endif + +#ifndef STATUS_PER_USER_TRUST_QUOTA_EXCEEDED +# define STATUS_PER_USER_TRUST_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000401L) +#endif + +#ifndef STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED +# define STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000402L) +#endif + +#ifndef STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED +# define STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000403L) +#endif + +#ifndef STATUS_DS_NAME_NOT_UNIQUE +# define STATUS_DS_NAME_NOT_UNIQUE ((NTSTATUS) 0xC0000404L) +#endif + +#ifndef STATUS_DS_DUPLICATE_ID_FOUND +# define STATUS_DS_DUPLICATE_ID_FOUND ((NTSTATUS) 0xC0000405L) +#endif + +#ifndef STATUS_DS_GROUP_CONVERSION_ERROR +# define STATUS_DS_GROUP_CONVERSION_ERROR ((NTSTATUS) 0xC0000406L) +#endif + +#ifndef STATUS_VOLSNAP_PREPARE_HIBERNATE +# define STATUS_VOLSNAP_PREPARE_HIBERNATE ((NTSTATUS) 0xC0000407L) +#endif + +#ifndef STATUS_USER2USER_REQUIRED +# define STATUS_USER2USER_REQUIRED ((NTSTATUS) 0xC0000408L) +#endif + +#ifndef STATUS_STACK_BUFFER_OVERRUN +# define STATUS_STACK_BUFFER_OVERRUN ((NTSTATUS) 0xC0000409L) +#endif + +#ifndef STATUS_NO_S4U_PROT_SUPPORT +# define STATUS_NO_S4U_PROT_SUPPORT ((NTSTATUS) 0xC000040AL) +#endif + +#ifndef STATUS_CROSSREALM_DELEGATION_FAILURE +# define STATUS_CROSSREALM_DELEGATION_FAILURE ((NTSTATUS) 0xC000040BL) +#endif + +#ifndef STATUS_REVOCATION_OFFLINE_KDC +# define STATUS_REVOCATION_OFFLINE_KDC ((NTSTATUS) 0xC000040CL) +#endif + +#ifndef STATUS_ISSUING_CA_UNTRUSTED_KDC +# define STATUS_ISSUING_CA_UNTRUSTED_KDC ((NTSTATUS) 0xC000040DL) +#endif + +#ifndef STATUS_KDC_CERT_EXPIRED +# define STATUS_KDC_CERT_EXPIRED ((NTSTATUS) 0xC000040EL) +#endif + +#ifndef STATUS_KDC_CERT_REVOKED +# define STATUS_KDC_CERT_REVOKED ((NTSTATUS) 0xC000040FL) +#endif + +#ifndef STATUS_PARAMETER_QUOTA_EXCEEDED +# define STATUS_PARAMETER_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000410L) +#endif + +#ifndef STATUS_HIBERNATION_FAILURE +# define STATUS_HIBERNATION_FAILURE ((NTSTATUS) 0xC0000411L) +#endif + +#ifndef STATUS_DELAY_LOAD_FAILED +# define STATUS_DELAY_LOAD_FAILED ((NTSTATUS) 0xC0000412L) +#endif + +#ifndef STATUS_AUTHENTICATION_FIREWALL_FAILED +# define STATUS_AUTHENTICATION_FIREWALL_FAILED ((NTSTATUS) 0xC0000413L) +#endif + +#ifndef STATUS_VDM_DISALLOWED +# define STATUS_VDM_DISALLOWED ((NTSTATUS) 0xC0000414L) +#endif + +#ifndef STATUS_HUNG_DISPLAY_DRIVER_THREAD +# define STATUS_HUNG_DISPLAY_DRIVER_THREAD ((NTSTATUS) 0xC0000415L) +#endif + +#ifndef STATUS_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE +# define STATUS_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE ((NTSTATUS) 0xC0000416L) +#endif + +#ifndef STATUS_INVALID_CRUNTIME_PARAMETER +# define STATUS_INVALID_CRUNTIME_PARAMETER ((NTSTATUS) 0xC0000417L) +#endif + +#ifndef STATUS_NTLM_BLOCKED +# define STATUS_NTLM_BLOCKED ((NTSTATUS) 0xC0000418L) +#endif + +#ifndef STATUS_DS_SRC_SID_EXISTS_IN_FOREST +# define STATUS_DS_SRC_SID_EXISTS_IN_FOREST ((NTSTATUS) 0xC0000419L) +#endif + +#ifndef STATUS_DS_DOMAIN_NAME_EXISTS_IN_FOREST +# define STATUS_DS_DOMAIN_NAME_EXISTS_IN_FOREST ((NTSTATUS) 0xC000041AL) +#endif + +#ifndef STATUS_DS_FLAT_NAME_EXISTS_IN_FOREST +# define STATUS_DS_FLAT_NAME_EXISTS_IN_FOREST ((NTSTATUS) 0xC000041BL) +#endif + +#ifndef STATUS_INVALID_USER_PRINCIPAL_NAME +# define STATUS_INVALID_USER_PRINCIPAL_NAME ((NTSTATUS) 0xC000041CL) +#endif + +#ifndef STATUS_FATAL_USER_CALLBACK_EXCEPTION +# define STATUS_FATAL_USER_CALLBACK_EXCEPTION ((NTSTATUS) 0xC000041DL) +#endif + +#ifndef STATUS_ASSERTION_FAILURE +# define STATUS_ASSERTION_FAILURE ((NTSTATUS) 0xC0000420L) +#endif + +#ifndef STATUS_VERIFIER_STOP +# define STATUS_VERIFIER_STOP ((NTSTATUS) 0xC0000421L) +#endif + +#ifndef STATUS_CALLBACK_POP_STACK +# define STATUS_CALLBACK_POP_STACK ((NTSTATUS) 0xC0000423L) +#endif + +#ifndef STATUS_INCOMPATIBLE_DRIVER_BLOCKED +# define STATUS_INCOMPATIBLE_DRIVER_BLOCKED ((NTSTATUS) 0xC0000424L) +#endif + +#ifndef STATUS_HIVE_UNLOADED +# define STATUS_HIVE_UNLOADED ((NTSTATUS) 0xC0000425L) +#endif + +#ifndef STATUS_COMPRESSION_DISABLED +# define STATUS_COMPRESSION_DISABLED ((NTSTATUS) 0xC0000426L) +#endif + +#ifndef STATUS_FILE_SYSTEM_LIMITATION +# define STATUS_FILE_SYSTEM_LIMITATION ((NTSTATUS) 0xC0000427L) +#endif + +#ifndef STATUS_INVALID_IMAGE_HASH +# define STATUS_INVALID_IMAGE_HASH ((NTSTATUS) 0xC0000428L) +#endif + +#ifndef STATUS_NOT_CAPABLE +# define STATUS_NOT_CAPABLE ((NTSTATUS) 0xC0000429L) +#endif + +#ifndef STATUS_REQUEST_OUT_OF_SEQUENCE +# define STATUS_REQUEST_OUT_OF_SEQUENCE ((NTSTATUS) 0xC000042AL) +#endif + +#ifndef STATUS_IMPLEMENTATION_LIMIT +# define STATUS_IMPLEMENTATION_LIMIT ((NTSTATUS) 0xC000042BL) +#endif + +#ifndef STATUS_ELEVATION_REQUIRED +# define STATUS_ELEVATION_REQUIRED ((NTSTATUS) 0xC000042CL) +#endif + +#ifndef STATUS_NO_SECURITY_CONTEXT +# define STATUS_NO_SECURITY_CONTEXT ((NTSTATUS) 0xC000042DL) +#endif + +#ifndef STATUS_PKU2U_CERT_FAILURE +# define STATUS_PKU2U_CERT_FAILURE ((NTSTATUS) 0xC000042FL) +#endif + +#ifndef STATUS_BEYOND_VDL +# define STATUS_BEYOND_VDL ((NTSTATUS) 0xC0000432L) +#endif + +#ifndef STATUS_ENCOUNTERED_WRITE_IN_PROGRESS +# define STATUS_ENCOUNTERED_WRITE_IN_PROGRESS ((NTSTATUS) 0xC0000433L) +#endif + +#ifndef STATUS_PTE_CHANGED +# define STATUS_PTE_CHANGED ((NTSTATUS) 0xC0000434L) +#endif + +#ifndef STATUS_PURGE_FAILED +# define STATUS_PURGE_FAILED ((NTSTATUS) 0xC0000435L) +#endif + +#ifndef STATUS_CRED_REQUIRES_CONFIRMATION +# define STATUS_CRED_REQUIRES_CONFIRMATION ((NTSTATUS) 0xC0000440L) +#endif + +#ifndef STATUS_CS_ENCRYPTION_INVALID_SERVER_RESPONSE +# define STATUS_CS_ENCRYPTION_INVALID_SERVER_RESPONSE ((NTSTATUS) 0xC0000441L) +#endif + +#ifndef STATUS_CS_ENCRYPTION_UNSUPPORTED_SERVER +# define STATUS_CS_ENCRYPTION_UNSUPPORTED_SERVER ((NTSTATUS) 0xC0000442L) +#endif + +#ifndef STATUS_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE +# define STATUS_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE ((NTSTATUS) 0xC0000443L) +#endif + +#ifndef STATUS_CS_ENCRYPTION_NEW_ENCRYPTED_FILE +# define STATUS_CS_ENCRYPTION_NEW_ENCRYPTED_FILE ((NTSTATUS) 0xC0000444L) +#endif + +#ifndef STATUS_CS_ENCRYPTION_FILE_NOT_CSE +# define STATUS_CS_ENCRYPTION_FILE_NOT_CSE ((NTSTATUS) 0xC0000445L) +#endif + +#ifndef STATUS_INVALID_LABEL +# define STATUS_INVALID_LABEL ((NTSTATUS) 0xC0000446L) +#endif + +#ifndef STATUS_DRIVER_PROCESS_TERMINATED +# define STATUS_DRIVER_PROCESS_TERMINATED ((NTSTATUS) 0xC0000450L) +#endif + +#ifndef STATUS_AMBIGUOUS_SYSTEM_DEVICE +# define STATUS_AMBIGUOUS_SYSTEM_DEVICE ((NTSTATUS) 0xC0000451L) +#endif + +#ifndef STATUS_SYSTEM_DEVICE_NOT_FOUND +# define STATUS_SYSTEM_DEVICE_NOT_FOUND ((NTSTATUS) 0xC0000452L) +#endif + +#ifndef STATUS_RESTART_BOOT_APPLICATION +# define STATUS_RESTART_BOOT_APPLICATION ((NTSTATUS) 0xC0000453L) +#endif + +#ifndef STATUS_INSUFFICIENT_NVRAM_RESOURCES +# define STATUS_INSUFFICIENT_NVRAM_RESOURCES ((NTSTATUS) 0xC0000454L) +#endif + +#ifndef STATUS_INVALID_TASK_NAME +# define STATUS_INVALID_TASK_NAME ((NTSTATUS) 0xC0000500L) +#endif + +#ifndef STATUS_INVALID_TASK_INDEX +# define STATUS_INVALID_TASK_INDEX ((NTSTATUS) 0xC0000501L) +#endif + +#ifndef STATUS_THREAD_ALREADY_IN_TASK +# define STATUS_THREAD_ALREADY_IN_TASK ((NTSTATUS) 0xC0000502L) +#endif + +#ifndef STATUS_CALLBACK_BYPASS +# define STATUS_CALLBACK_BYPASS ((NTSTATUS) 0xC0000503L) +#endif + +#ifndef STATUS_FAIL_FAST_EXCEPTION +# define STATUS_FAIL_FAST_EXCEPTION ((NTSTATUS) 0xC0000602L) +#endif + +#ifndef STATUS_IMAGE_CERT_REVOKED +# define STATUS_IMAGE_CERT_REVOKED ((NTSTATUS) 0xC0000603L) +#endif + +#ifndef STATUS_PORT_CLOSED +# define STATUS_PORT_CLOSED ((NTSTATUS) 0xC0000700L) +#endif + +#ifndef STATUS_MESSAGE_LOST +# define STATUS_MESSAGE_LOST ((NTSTATUS) 0xC0000701L) +#endif + +#ifndef STATUS_INVALID_MESSAGE +# define STATUS_INVALID_MESSAGE ((NTSTATUS) 0xC0000702L) +#endif + +#ifndef STATUS_REQUEST_CANCELED +# define STATUS_REQUEST_CANCELED ((NTSTATUS) 0xC0000703L) +#endif + +#ifndef STATUS_RECURSIVE_DISPATCH +# define STATUS_RECURSIVE_DISPATCH ((NTSTATUS) 0xC0000704L) +#endif + +#ifndef STATUS_LPC_RECEIVE_BUFFER_EXPECTED +# define STATUS_LPC_RECEIVE_BUFFER_EXPECTED ((NTSTATUS) 0xC0000705L) +#endif + +#ifndef STATUS_LPC_INVALID_CONNECTION_USAGE +# define STATUS_LPC_INVALID_CONNECTION_USAGE ((NTSTATUS) 0xC0000706L) +#endif + +#ifndef STATUS_LPC_REQUESTS_NOT_ALLOWED +# define STATUS_LPC_REQUESTS_NOT_ALLOWED ((NTSTATUS) 0xC0000707L) +#endif + +#ifndef STATUS_RESOURCE_IN_USE +# define STATUS_RESOURCE_IN_USE ((NTSTATUS) 0xC0000708L) +#endif + +#ifndef STATUS_HARDWARE_MEMORY_ERROR +# define STATUS_HARDWARE_MEMORY_ERROR ((NTSTATUS) 0xC0000709L) +#endif + +#ifndef STATUS_THREADPOOL_HANDLE_EXCEPTION +# define STATUS_THREADPOOL_HANDLE_EXCEPTION ((NTSTATUS) 0xC000070AL) +#endif + +#ifndef STATUS_THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED +# define STATUS_THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED ((NTSTATUS) 0xC000070BL) +#endif + +#ifndef STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED +# define STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED ((NTSTATUS) 0xC000070CL) +#endif + +#ifndef STATUS_THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED +# define STATUS_THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED ((NTSTATUS) 0xC000070DL) +#endif + +#ifndef STATUS_THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED +# define STATUS_THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED ((NTSTATUS) 0xC000070EL) +#endif + +#ifndef STATUS_THREADPOOL_RELEASED_DURING_OPERATION +# define STATUS_THREADPOOL_RELEASED_DURING_OPERATION ((NTSTATUS) 0xC000070FL) +#endif + +#ifndef STATUS_CALLBACK_RETURNED_WHILE_IMPERSONATING +# define STATUS_CALLBACK_RETURNED_WHILE_IMPERSONATING ((NTSTATUS) 0xC0000710L) +#endif + +#ifndef STATUS_APC_RETURNED_WHILE_IMPERSONATING +# define STATUS_APC_RETURNED_WHILE_IMPERSONATING ((NTSTATUS) 0xC0000711L) +#endif + +#ifndef STATUS_PROCESS_IS_PROTECTED +# define STATUS_PROCESS_IS_PROTECTED ((NTSTATUS) 0xC0000712L) +#endif + +#ifndef STATUS_MCA_EXCEPTION +# define STATUS_MCA_EXCEPTION ((NTSTATUS) 0xC0000713L) +#endif + +#ifndef STATUS_CERTIFICATE_MAPPING_NOT_UNIQUE +# define STATUS_CERTIFICATE_MAPPING_NOT_UNIQUE ((NTSTATUS) 0xC0000714L) +#endif + +#ifndef STATUS_SYMLINK_CLASS_DISABLED +# define STATUS_SYMLINK_CLASS_DISABLED ((NTSTATUS) 0xC0000715L) +#endif + +#ifndef STATUS_INVALID_IDN_NORMALIZATION +# define STATUS_INVALID_IDN_NORMALIZATION ((NTSTATUS) 0xC0000716L) +#endif + +#ifndef STATUS_NO_UNICODE_TRANSLATION +# define STATUS_NO_UNICODE_TRANSLATION ((NTSTATUS) 0xC0000717L) +#endif + +#ifndef STATUS_ALREADY_REGISTERED +# define STATUS_ALREADY_REGISTERED ((NTSTATUS) 0xC0000718L) +#endif + +#ifndef STATUS_CONTEXT_MISMATCH +# define STATUS_CONTEXT_MISMATCH ((NTSTATUS) 0xC0000719L) +#endif + +#ifndef STATUS_PORT_ALREADY_HAS_COMPLETION_LIST +# define STATUS_PORT_ALREADY_HAS_COMPLETION_LIST ((NTSTATUS) 0xC000071AL) +#endif + +#ifndef STATUS_CALLBACK_RETURNED_THREAD_PRIORITY +# define STATUS_CALLBACK_RETURNED_THREAD_PRIORITY ((NTSTATUS) 0xC000071BL) +#endif + +#ifndef STATUS_INVALID_THREAD +# define STATUS_INVALID_THREAD ((NTSTATUS) 0xC000071CL) +#endif + +#ifndef STATUS_CALLBACK_RETURNED_TRANSACTION +# define STATUS_CALLBACK_RETURNED_TRANSACTION ((NTSTATUS) 0xC000071DL) +#endif + +#ifndef STATUS_CALLBACK_RETURNED_LDR_LOCK +# define STATUS_CALLBACK_RETURNED_LDR_LOCK ((NTSTATUS) 0xC000071EL) +#endif + +#ifndef STATUS_CALLBACK_RETURNED_LANG +# define STATUS_CALLBACK_RETURNED_LANG ((NTSTATUS) 0xC000071FL) +#endif + +#ifndef STATUS_CALLBACK_RETURNED_PRI_BACK +# define STATUS_CALLBACK_RETURNED_PRI_BACK ((NTSTATUS) 0xC0000720L) +#endif + +#ifndef STATUS_CALLBACK_RETURNED_THREAD_AFFINITY +# define STATUS_CALLBACK_RETURNED_THREAD_AFFINITY ((NTSTATUS) 0xC0000721L) +#endif + +#ifndef STATUS_DISK_REPAIR_DISABLED +# define STATUS_DISK_REPAIR_DISABLED ((NTSTATUS) 0xC0000800L) +#endif + +#ifndef STATUS_DS_DOMAIN_RENAME_IN_PROGRESS +# define STATUS_DS_DOMAIN_RENAME_IN_PROGRESS ((NTSTATUS) 0xC0000801L) +#endif + +#ifndef STATUS_DISK_QUOTA_EXCEEDED +# define STATUS_DISK_QUOTA_EXCEEDED ((NTSTATUS) 0xC0000802L) +#endif + +#ifndef STATUS_DATA_LOST_REPAIR +# define STATUS_DATA_LOST_REPAIR ((NTSTATUS) 0x80000803L) +#endif + +#ifndef STATUS_CONTENT_BLOCKED +# define STATUS_CONTENT_BLOCKED ((NTSTATUS) 0xC0000804L) +#endif + +#ifndef STATUS_BAD_CLUSTERS +# define STATUS_BAD_CLUSTERS ((NTSTATUS) 0xC0000805L) +#endif + +#ifndef STATUS_VOLUME_DIRTY +# define STATUS_VOLUME_DIRTY ((NTSTATUS) 0xC0000806L) +#endif + +#ifndef STATUS_FILE_CHECKED_OUT +# define STATUS_FILE_CHECKED_OUT ((NTSTATUS) 0xC0000901L) +#endif + +#ifndef STATUS_CHECKOUT_REQUIRED +# define STATUS_CHECKOUT_REQUIRED ((NTSTATUS) 0xC0000902L) +#endif + +#ifndef STATUS_BAD_FILE_TYPE +# define STATUS_BAD_FILE_TYPE ((NTSTATUS) 0xC0000903L) +#endif + +#ifndef STATUS_FILE_TOO_LARGE +# define STATUS_FILE_TOO_LARGE ((NTSTATUS) 0xC0000904L) +#endif + +#ifndef STATUS_FORMS_AUTH_REQUIRED +# define STATUS_FORMS_AUTH_REQUIRED ((NTSTATUS) 0xC0000905L) +#endif + +#ifndef STATUS_VIRUS_INFECTED +# define STATUS_VIRUS_INFECTED ((NTSTATUS) 0xC0000906L) +#endif + +#ifndef STATUS_VIRUS_DELETED +# define STATUS_VIRUS_DELETED ((NTSTATUS) 0xC0000907L) +#endif + +#ifndef STATUS_BAD_MCFG_TABLE +# define STATUS_BAD_MCFG_TABLE ((NTSTATUS) 0xC0000908L) +#endif + +#ifndef STATUS_CANNOT_BREAK_OPLOCK +# define STATUS_CANNOT_BREAK_OPLOCK ((NTSTATUS) 0xC0000909L) +#endif + +#ifndef STATUS_WOW_ASSERTION +# define STATUS_WOW_ASSERTION ((NTSTATUS) 0xC0009898L) +#endif + +#ifndef STATUS_INVALID_SIGNATURE +# define STATUS_INVALID_SIGNATURE ((NTSTATUS) 0xC000A000L) +#endif + +#ifndef STATUS_HMAC_NOT_SUPPORTED +# define STATUS_HMAC_NOT_SUPPORTED ((NTSTATUS) 0xC000A001L) +#endif + +#ifndef STATUS_AUTH_TAG_MISMATCH +# define STATUS_AUTH_TAG_MISMATCH ((NTSTATUS) 0xC000A002L) +#endif + +#ifndef STATUS_IPSEC_QUEUE_OVERFLOW +# define STATUS_IPSEC_QUEUE_OVERFLOW ((NTSTATUS) 0xC000A010L) +#endif + +#ifndef STATUS_ND_QUEUE_OVERFLOW +# define STATUS_ND_QUEUE_OVERFLOW ((NTSTATUS) 0xC000A011L) +#endif + +#ifndef STATUS_HOPLIMIT_EXCEEDED +# define STATUS_HOPLIMIT_EXCEEDED ((NTSTATUS) 0xC000A012L) +#endif + +#ifndef STATUS_PROTOCOL_NOT_SUPPORTED +# define STATUS_PROTOCOL_NOT_SUPPORTED ((NTSTATUS) 0xC000A013L) +#endif + +#ifndef STATUS_FASTPATH_REJECTED +# define STATUS_FASTPATH_REJECTED ((NTSTATUS) 0xC000A014L) +#endif + +#ifndef STATUS_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED +# define STATUS_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED ((NTSTATUS) 0xC000A080L) +#endif + +#ifndef STATUS_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR +# define STATUS_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR ((NTSTATUS) 0xC000A081L) +#endif + +#ifndef STATUS_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR +# define STATUS_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR ((NTSTATUS) 0xC000A082L) +#endif + +#ifndef STATUS_XML_PARSE_ERROR +# define STATUS_XML_PARSE_ERROR ((NTSTATUS) 0xC000A083L) +#endif + +#ifndef STATUS_XMLDSIG_ERROR +# define STATUS_XMLDSIG_ERROR ((NTSTATUS) 0xC000A084L) +#endif + +#ifndef STATUS_WRONG_COMPARTMENT +# define STATUS_WRONG_COMPARTMENT ((NTSTATUS) 0xC000A085L) +#endif + +#ifndef STATUS_AUTHIP_FAILURE +# define STATUS_AUTHIP_FAILURE ((NTSTATUS) 0xC000A086L) +#endif + +#ifndef STATUS_DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS +# define STATUS_DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS ((NTSTATUS) 0xC000A087L) +#endif + +#ifndef STATUS_DS_OID_NOT_FOUND +# define STATUS_DS_OID_NOT_FOUND ((NTSTATUS) 0xC000A088L) +#endif + +#ifndef STATUS_HASH_NOT_SUPPORTED +# define STATUS_HASH_NOT_SUPPORTED ((NTSTATUS) 0xC000A100L) +#endif + +#ifndef STATUS_HASH_NOT_PRESENT +# define STATUS_HASH_NOT_PRESENT ((NTSTATUS) 0xC000A101L) +#endif + +/* This is not the NTSTATUS_FROM_WIN32 that the DDK provides, because the */ +/* DDK got it wrong! */ +#ifdef NTSTATUS_FROM_WIN32 +# undef NTSTATUS_FROM_WIN32 +#endif +#define NTSTATUS_FROM_WIN32(error) ((NTSTATUS) (error) <= 0 ? \ + ((NTSTATUS) (error)) : ((NTSTATUS) (((error) & 0x0000FFFF) | \ + (FACILITY_NTWIN32 << 16) | ERROR_SEVERITY_WARNING))) + +#ifndef JOB_OBJECT_LIMIT_PROCESS_MEMORY +# define JOB_OBJECT_LIMIT_PROCESS_MEMORY 0x00000100 +#endif +#ifndef JOB_OBJECT_LIMIT_JOB_MEMORY +# define JOB_OBJECT_LIMIT_JOB_MEMORY 0x00000200 +#endif +#ifndef JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION +# define JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION 0x00000400 +#endif +#ifndef JOB_OBJECT_LIMIT_BREAKAWAY_OK +# define JOB_OBJECT_LIMIT_BREAKAWAY_OK 0x00000800 +#endif +#ifndef JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK +# define JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK 0x00001000 +#endif +#ifndef JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE +# define JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE 0x00002000 +#endif + +/* from winternl.h */ +typedef struct _UNICODE_STRING { + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +} UNICODE_STRING, *PUNICODE_STRING; + +typedef const UNICODE_STRING *PCUNICODE_STRING; + +/* from ntifs.h */ +#ifndef DEVICE_TYPE +# define DEVICE_TYPE DWORD +#endif + +#ifndef VOLUME_NAME_DOS +# define VOLUME_NAME_DOS 0x0 +#endif + +#ifndef MAPVK_VK_TO_VSC +# define MAPVK_VK_TO_VSC (0) +#endif + +/* MinGW already has a definition for REPARSE_DATA_BUFFER, but mingw-w64 does + * not. + */ +#if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR) + typedef struct _REPARSE_DATA_BUFFER { + ULONG ReparseTag; + USHORT ReparseDataLength; + USHORT Reserved; + union { + struct { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + ULONG Flags; + WCHAR PathBuffer[1]; + } SymbolicLinkReparseBuffer; + struct { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + WCHAR PathBuffer[1]; + } MountPointReparseBuffer; + struct { + UCHAR DataBuffer[1]; + } GenericReparseBuffer; + }; + } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; +#endif + +typedef struct _IO_STATUS_BLOCK { + union { + NTSTATUS Status; + PVOID Pointer; + }; + ULONG_PTR Information; +} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; + +typedef enum _FILE_INFORMATION_CLASS { + FileDirectoryInformation = 1, + FileFullDirectoryInformation, + FileBothDirectoryInformation, + FileBasicInformation, + FileStandardInformation, + FileInternalInformation, + FileEaInformation, + FileAccessInformation, + FileNameInformation, + FileRenameInformation, + FileLinkInformation, + FileNamesInformation, + FileDispositionInformation, + FilePositionInformation, + FileFullEaInformation, + FileModeInformation, + FileAlignmentInformation, + FileAllInformation, + FileAllocationInformation, + FileEndOfFileInformation, + FileAlternateNameInformation, + FileStreamInformation, + FilePipeInformation, + FilePipeLocalInformation, + FilePipeRemoteInformation, + FileMailslotQueryInformation, + FileMailslotSetInformation, + FileCompressionInformation, + FileObjectIdInformation, + FileCompletionInformation, + FileMoveClusterInformation, + FileQuotaInformation, + FileReparsePointInformation, + FileNetworkOpenInformation, + FileAttributeTagInformation, + FileTrackingInformation, + FileIdBothDirectoryInformation, + FileIdFullDirectoryInformation, + FileValidDataLengthInformation, + FileShortNameInformation, + FileIoCompletionNotificationInformation, + FileIoStatusBlockRangeInformation, + FileIoPriorityHintInformation, + FileSfioReserveInformation, + FileSfioVolumeInformation, + FileHardLinkInformation, + FileProcessIdsUsingFileInformation, + FileNormalizedNameInformation, + FileNetworkPhysicalNameInformation, + FileIdGlobalTxDirectoryInformation, + FileIsRemoteDeviceInformation, + FileAttributeCacheInformation, + FileNumaNodeInformation, + FileStandardLinkInformation, + FileRemoteProtocolInformation, + FileMaximumInformation +} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS; + +typedef struct _FILE_DIRECTORY_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION; + +typedef struct _FILE_BOTH_DIR_INFORMATION { + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + ULONG EaSize; + CCHAR ShortNameLength; + WCHAR ShortName[12]; + WCHAR FileName[1]; +} FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION; + +typedef struct _FILE_BASIC_INFORMATION { + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + DWORD FileAttributes; +} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION; + +typedef struct _FILE_STANDARD_INFORMATION { + LARGE_INTEGER AllocationSize; + LARGE_INTEGER EndOfFile; + ULONG NumberOfLinks; + BOOLEAN DeletePending; + BOOLEAN Directory; +} FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION; + +typedef struct _FILE_INTERNAL_INFORMATION { + LARGE_INTEGER IndexNumber; +} FILE_INTERNAL_INFORMATION, *PFILE_INTERNAL_INFORMATION; + +typedef struct _FILE_EA_INFORMATION { + ULONG EaSize; +} FILE_EA_INFORMATION, *PFILE_EA_INFORMATION; + +typedef struct _FILE_ACCESS_INFORMATION { + ACCESS_MASK AccessFlags; +} FILE_ACCESS_INFORMATION, *PFILE_ACCESS_INFORMATION; + +typedef struct _FILE_POSITION_INFORMATION { + LARGE_INTEGER CurrentByteOffset; +} FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION; + +typedef struct _FILE_MODE_INFORMATION { + ULONG Mode; +} FILE_MODE_INFORMATION, *PFILE_MODE_INFORMATION; + +typedef struct _FILE_ALIGNMENT_INFORMATION { + ULONG AlignmentRequirement; +} FILE_ALIGNMENT_INFORMATION, *PFILE_ALIGNMENT_INFORMATION; + +typedef struct _FILE_NAME_INFORMATION { + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION; + +typedef struct _FILE_END_OF_FILE_INFORMATION { + LARGE_INTEGER EndOfFile; +} FILE_END_OF_FILE_INFORMATION, *PFILE_END_OF_FILE_INFORMATION; + +typedef struct _FILE_ALL_INFORMATION { + FILE_BASIC_INFORMATION BasicInformation; + FILE_STANDARD_INFORMATION StandardInformation; + FILE_INTERNAL_INFORMATION InternalInformation; + FILE_EA_INFORMATION EaInformation; + FILE_ACCESS_INFORMATION AccessInformation; + FILE_POSITION_INFORMATION PositionInformation; + FILE_MODE_INFORMATION ModeInformation; + FILE_ALIGNMENT_INFORMATION AlignmentInformation; + FILE_NAME_INFORMATION NameInformation; +} FILE_ALL_INFORMATION, *PFILE_ALL_INFORMATION; + +typedef struct _FILE_DISPOSITION_INFORMATION { + BOOLEAN DeleteFile; +} FILE_DISPOSITION_INFORMATION, *PFILE_DISPOSITION_INFORMATION; + +typedef struct _FILE_PIPE_LOCAL_INFORMATION { + ULONG NamedPipeType; + ULONG NamedPipeConfiguration; + ULONG MaximumInstances; + ULONG CurrentInstances; + ULONG InboundQuota; + ULONG ReadDataAvailable; + ULONG OutboundQuota; + ULONG WriteQuotaAvailable; + ULONG NamedPipeState; + ULONG NamedPipeEnd; +} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION; + +#define FILE_SYNCHRONOUS_IO_ALERT 0x00000010 +#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020 + +typedef enum _FS_INFORMATION_CLASS { + FileFsVolumeInformation = 1, + FileFsLabelInformation = 2, + FileFsSizeInformation = 3, + FileFsDeviceInformation = 4, + FileFsAttributeInformation = 5, + FileFsControlInformation = 6, + FileFsFullSizeInformation = 7, + FileFsObjectIdInformation = 8, + FileFsDriverPathInformation = 9, + FileFsVolumeFlagsInformation = 10, + FileFsSectorSizeInformation = 11 +} FS_INFORMATION_CLASS, *PFS_INFORMATION_CLASS; + +typedef struct _FILE_FS_VOLUME_INFORMATION { + LARGE_INTEGER VolumeCreationTime; + ULONG VolumeSerialNumber; + ULONG VolumeLabelLength; + BOOLEAN SupportsObjects; + WCHAR VolumeLabel[1]; +} FILE_FS_VOLUME_INFORMATION, *PFILE_FS_VOLUME_INFORMATION; + +typedef struct _FILE_FS_LABEL_INFORMATION { + ULONG VolumeLabelLength; + WCHAR VolumeLabel[1]; +} FILE_FS_LABEL_INFORMATION, *PFILE_FS_LABEL_INFORMATION; + +typedef struct _FILE_FS_SIZE_INFORMATION { + LARGE_INTEGER TotalAllocationUnits; + LARGE_INTEGER AvailableAllocationUnits; + ULONG SectorsPerAllocationUnit; + ULONG BytesPerSector; +} FILE_FS_SIZE_INFORMATION, *PFILE_FS_SIZE_INFORMATION; + +typedef struct _FILE_FS_DEVICE_INFORMATION { + DEVICE_TYPE DeviceType; + ULONG Characteristics; +} FILE_FS_DEVICE_INFORMATION, *PFILE_FS_DEVICE_INFORMATION; + +typedef struct _FILE_FS_ATTRIBUTE_INFORMATION { + ULONG FileSystemAttributes; + LONG MaximumComponentNameLength; + ULONG FileSystemNameLength; + WCHAR FileSystemName[1]; +} FILE_FS_ATTRIBUTE_INFORMATION, *PFILE_FS_ATTRIBUTE_INFORMATION; + +typedef struct _FILE_FS_CONTROL_INFORMATION { + LARGE_INTEGER FreeSpaceStartFiltering; + LARGE_INTEGER FreeSpaceThreshold; + LARGE_INTEGER FreeSpaceStopFiltering; + LARGE_INTEGER DefaultQuotaThreshold; + LARGE_INTEGER DefaultQuotaLimit; + ULONG FileSystemControlFlags; +} FILE_FS_CONTROL_INFORMATION, *PFILE_FS_CONTROL_INFORMATION; + +typedef struct _FILE_FS_FULL_SIZE_INFORMATION { + LARGE_INTEGER TotalAllocationUnits; + LARGE_INTEGER CallerAvailableAllocationUnits; + LARGE_INTEGER ActualAvailableAllocationUnits; + ULONG SectorsPerAllocationUnit; + ULONG BytesPerSector; +} FILE_FS_FULL_SIZE_INFORMATION, *PFILE_FS_FULL_SIZE_INFORMATION; + +typedef struct _FILE_FS_OBJECTID_INFORMATION { + UCHAR ObjectId[16]; + UCHAR ExtendedInfo[48]; +} FILE_FS_OBJECTID_INFORMATION, *PFILE_FS_OBJECTID_INFORMATION; + +typedef struct _FILE_FS_DRIVER_PATH_INFORMATION { + BOOLEAN DriverInPath; + ULONG DriverNameLength; + WCHAR DriverName[1]; +} FILE_FS_DRIVER_PATH_INFORMATION, *PFILE_FS_DRIVER_PATH_INFORMATION; + +typedef struct _FILE_FS_VOLUME_FLAGS_INFORMATION { + ULONG Flags; +} FILE_FS_VOLUME_FLAGS_INFORMATION, *PFILE_FS_VOLUME_FLAGS_INFORMATION; + +typedef struct _FILE_FS_SECTOR_SIZE_INFORMATION { + ULONG LogicalBytesPerSector; + ULONG PhysicalBytesPerSectorForAtomicity; + ULONG PhysicalBytesPerSectorForPerformance; + ULONG FileSystemEffectivePhysicalBytesPerSectorForAtomicity; + ULONG Flags; + ULONG ByteOffsetForSectorAlignment; + ULONG ByteOffsetForPartitionAlignment; +} FILE_FS_SECTOR_SIZE_INFORMATION, *PFILE_FS_SECTOR_SIZE_INFORMATION; + +typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION { + LARGE_INTEGER IdleTime; + LARGE_INTEGER KernelTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER DpcTime; + LARGE_INTEGER InterruptTime; + ULONG InterruptCount; +} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, *PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION; + +#ifndef SystemProcessorPerformanceInformation +# define SystemProcessorPerformanceInformation 8 +#endif + +#ifndef FILE_DEVICE_FILE_SYSTEM +# define FILE_DEVICE_FILE_SYSTEM 0x00000009 +#endif + +#ifndef FILE_DEVICE_NETWORK +# define FILE_DEVICE_NETWORK 0x00000012 +#endif + +#ifndef METHOD_BUFFERED +# define METHOD_BUFFERED 0 +#endif + +#ifndef METHOD_IN_DIRECT +# define METHOD_IN_DIRECT 1 +#endif + +#ifndef METHOD_OUT_DIRECT +# define METHOD_OUT_DIRECT 2 +#endif + +#ifndef METHOD_NEITHER +#define METHOD_NEITHER 3 +#endif + +#ifndef METHOD_DIRECT_TO_HARDWARE +# define METHOD_DIRECT_TO_HARDWARE METHOD_IN_DIRECT +#endif + +#ifndef METHOD_DIRECT_FROM_HARDWARE +# define METHOD_DIRECT_FROM_HARDWARE METHOD_OUT_DIRECT +#endif + +#ifndef FILE_ANY_ACCESS +# define FILE_ANY_ACCESS 0 +#endif + +#ifndef FILE_SPECIAL_ACCESS +# define FILE_SPECIAL_ACCESS (FILE_ANY_ACCESS) +#endif + +#ifndef FILE_READ_ACCESS +# define FILE_READ_ACCESS 0x0001 +#endif + +#ifndef FILE_WRITE_ACCESS +# define FILE_WRITE_ACCESS 0x0002 +#endif + +#ifndef CTL_CODE +# define CTL_CODE(device_type, function, method, access) \ + (((device_type) << 16) | ((access) << 14) | ((function) << 2) | (method)) +#endif + +#ifndef FSCTL_SET_REPARSE_POINT +# define FSCTL_SET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, \ + 41, \ + METHOD_BUFFERED, \ + FILE_SPECIAL_ACCESS) +#endif + +#ifndef FSCTL_GET_REPARSE_POINT +# define FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, \ + 42, \ + METHOD_BUFFERED, \ + FILE_ANY_ACCESS) +#endif + +#ifndef FSCTL_DELETE_REPARSE_POINT +# define FSCTL_DELETE_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, \ + 43, \ + METHOD_BUFFERED, \ + FILE_SPECIAL_ACCESS) +#endif + +#ifndef IO_REPARSE_TAG_SYMLINK +# define IO_REPARSE_TAG_SYMLINK (0xA000000CL) +#endif + +typedef VOID (NTAPI *PIO_APC_ROUTINE) + (PVOID ApcContext, + PIO_STATUS_BLOCK IoStatusBlock, + ULONG Reserved); + +typedef ULONG (NTAPI *sRtlNtStatusToDosError) + (NTSTATUS Status); + +typedef NTSTATUS (NTAPI *sNtDeviceIoControlFile) + (HANDLE FileHandle, + HANDLE Event, + PIO_APC_ROUTINE ApcRoutine, + PVOID ApcContext, + PIO_STATUS_BLOCK IoStatusBlock, + ULONG IoControlCode, + PVOID InputBuffer, + ULONG InputBufferLength, + PVOID OutputBuffer, + ULONG OutputBufferLength); + +typedef NTSTATUS (NTAPI *sNtQueryInformationFile) + (HANDLE FileHandle, + PIO_STATUS_BLOCK IoStatusBlock, + PVOID FileInformation, + ULONG Length, + FILE_INFORMATION_CLASS FileInformationClass); + +typedef NTSTATUS (NTAPI *sNtSetInformationFile) + (HANDLE FileHandle, + PIO_STATUS_BLOCK IoStatusBlock, + PVOID FileInformation, + ULONG Length, + FILE_INFORMATION_CLASS FileInformationClass); + +typedef NTSTATUS (NTAPI *sNtQueryVolumeInformationFile) + (HANDLE FileHandle, + PIO_STATUS_BLOCK IoStatusBlock, + PVOID FsInformation, + ULONG Length, + FS_INFORMATION_CLASS FsInformationClass); + +typedef NTSTATUS (NTAPI *sNtQuerySystemInformation) + (UINT SystemInformationClass, + PVOID SystemInformation, + ULONG SystemInformationLength, + PULONG ReturnLength); + +typedef NTSTATUS (NTAPI *sNtQueryDirectoryFile) + (HANDLE FileHandle, + HANDLE Event, + PIO_APC_ROUTINE ApcRoutine, + PVOID ApcContext, + PIO_STATUS_BLOCK IoStatusBlock, + PVOID FileInformation, + ULONG Length, + FILE_INFORMATION_CLASS FileInformationClass, + BOOLEAN ReturnSingleEntry, + PUNICODE_STRING FileName, + BOOLEAN RestartScan + ); + +/* + * Kernel32 headers + */ +#ifndef FILE_SKIP_COMPLETION_PORT_ON_SUCCESS +# define FILE_SKIP_COMPLETION_PORT_ON_SUCCESS 0x1 +#endif + +#ifndef FILE_SKIP_SET_EVENT_ON_HANDLE +# define FILE_SKIP_SET_EVENT_ON_HANDLE 0x2 +#endif + +#ifndef SYMBOLIC_LINK_FLAG_DIRECTORY +# define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1 +#endif + +#if (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)) \ + || (defined(_MSC_VER) && _MSC_VER < 1500) + typedef struct _OVERLAPPED_ENTRY { + ULONG_PTR lpCompletionKey; + LPOVERLAPPED lpOverlapped; + ULONG_PTR Internal; + DWORD dwNumberOfBytesTransferred; + } OVERLAPPED_ENTRY, *LPOVERLAPPED_ENTRY; +#endif + +/* from wincon.h */ +#ifndef ENABLE_INSERT_MODE +# define ENABLE_INSERT_MODE 0x20 +#endif + +#ifndef ENABLE_QUICK_EDIT_MODE +# define ENABLE_QUICK_EDIT_MODE 0x40 +#endif + +#ifndef ENABLE_EXTENDED_FLAGS +# define ENABLE_EXTENDED_FLAGS 0x80 +#endif + +/* from winerror.h */ ++#ifndef ERROR_ELEVATION_REQUIRED ++# define ERROR_ELEVATION_REQUIRED 740 ++#endif ++ +#ifndef ERROR_SYMLINK_NOT_SUPPORTED +# define ERROR_SYMLINK_NOT_SUPPORTED 1464 +#endif + +#ifndef ERROR_MUI_FILE_NOT_FOUND +# define ERROR_MUI_FILE_NOT_FOUND 15100 +#endif + +#ifndef ERROR_MUI_INVALID_FILE +# define ERROR_MUI_INVALID_FILE 15101 +#endif + +#ifndef ERROR_MUI_INVALID_RC_CONFIG +# define ERROR_MUI_INVALID_RC_CONFIG 15102 +#endif + +#ifndef ERROR_MUI_INVALID_LOCALE_NAME +# define ERROR_MUI_INVALID_LOCALE_NAME 15103 +#endif + +#ifndef ERROR_MUI_INVALID_ULTIMATEFALLBACK_NAME +# define ERROR_MUI_INVALID_ULTIMATEFALLBACK_NAME 15104 +#endif + +#ifndef ERROR_MUI_FILE_NOT_LOADED +# define ERROR_MUI_FILE_NOT_LOADED 15105 +#endif + +typedef BOOL (WINAPI *sGetQueuedCompletionStatusEx) + (HANDLE CompletionPort, + LPOVERLAPPED_ENTRY lpCompletionPortEntries, + ULONG ulCount, + PULONG ulNumEntriesRemoved, + DWORD dwMilliseconds, + BOOL fAlertable); + +typedef BOOL (WINAPI* sSetFileCompletionNotificationModes) + (HANDLE FileHandle, + UCHAR Flags); + +typedef BOOLEAN (WINAPI* sCreateSymbolicLinkW) + (LPCWSTR lpSymlinkFileName, + LPCWSTR lpTargetFileName, + DWORD dwFlags); + +typedef BOOL (WINAPI* sCancelIoEx) + (HANDLE hFile, + LPOVERLAPPED lpOverlapped); + +typedef VOID (WINAPI* sInitializeConditionVariable) + (PCONDITION_VARIABLE ConditionVariable); + +typedef BOOL (WINAPI* sSleepConditionVariableCS) + (PCONDITION_VARIABLE ConditionVariable, + PCRITICAL_SECTION CriticalSection, + DWORD dwMilliseconds); + +typedef BOOL (WINAPI* sSleepConditionVariableSRW) + (PCONDITION_VARIABLE ConditionVariable, + PSRWLOCK SRWLock, + DWORD dwMilliseconds, + ULONG Flags); + +typedef VOID (WINAPI* sWakeAllConditionVariable) + (PCONDITION_VARIABLE ConditionVariable); + +typedef VOID (WINAPI* sWakeConditionVariable) + (PCONDITION_VARIABLE ConditionVariable); + +typedef BOOL (WINAPI* sCancelSynchronousIo) + (HANDLE hThread); + +typedef DWORD (WINAPI* sGetFinalPathNameByHandleW) + (HANDLE hFile, + LPWSTR lpszFilePath, + DWORD cchFilePath, + DWORD dwFlags); + +/* from powerbase.h */ +#ifndef DEVICE_NOTIFY_CALLBACK +# define DEVICE_NOTIFY_CALLBACK 2 +#endif + +#ifndef PBT_APMRESUMEAUTOMATIC +# define PBT_APMRESUMEAUTOMATIC 18 +#endif + +#ifndef PBT_APMRESUMESUSPEND +# define PBT_APMRESUMESUSPEND 7 +#endif + +typedef ULONG CALLBACK _DEVICE_NOTIFY_CALLBACK_ROUTINE( + PVOID Context, + ULONG Type, + PVOID Setting +); +typedef _DEVICE_NOTIFY_CALLBACK_ROUTINE* _PDEVICE_NOTIFY_CALLBACK_ROUTINE; + +typedef struct _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS { + _PDEVICE_NOTIFY_CALLBACK_ROUTINE Callback; + PVOID Context; +} _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS, *_PDEVICE_NOTIFY_SUBSCRIBE_PARAMETERS; + +typedef PVOID _HPOWERNOTIFY; +typedef _HPOWERNOTIFY *_PHPOWERNOTIFY; + +typedef DWORD (WINAPI *sPowerRegisterSuspendResumeNotification) + (DWORD Flags, + HANDLE Recipient, + _PHPOWERNOTIFY RegistrationHandle); + + +/* Ntdll function pointers */ +extern sRtlNtStatusToDosError pRtlNtStatusToDosError; +extern sNtDeviceIoControlFile pNtDeviceIoControlFile; +extern sNtQueryInformationFile pNtQueryInformationFile; +extern sNtSetInformationFile pNtSetInformationFile; +extern sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile; +extern sNtQueryDirectoryFile pNtQueryDirectoryFile; +extern sNtQuerySystemInformation pNtQuerySystemInformation; + + +/* Kernel32 function pointers */ +extern sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx; +extern sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes; +extern sCreateSymbolicLinkW pCreateSymbolicLinkW; +extern sCancelIoEx pCancelIoEx; +extern sInitializeConditionVariable pInitializeConditionVariable; +extern sSleepConditionVariableCS pSleepConditionVariableCS; +extern sSleepConditionVariableSRW pSleepConditionVariableSRW; +extern sWakeAllConditionVariable pWakeAllConditionVariable; +extern sWakeConditionVariable pWakeConditionVariable; +extern sCancelSynchronousIo pCancelSynchronousIo; +extern sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW; + + +/* Powrprof.dll function pointer */ +extern sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification; + +#endif /* UV_WIN_WINAPI_H_ */ https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1f661e87a6a8304edb77bd30b546e5d113477c59 commit 1f661e87a6a8304edb77bd30b546e5d113477c59 Author: libuv upstream AuthorDate: Tue Feb 21 15:36:43 2017 -0500 Commit: Brad King CommitDate: Tue Feb 21 19:36:08 2017 -0500 libuv 2017-02-21 (52ae8264) Code extracted from: https://github.com/libuv/libuv.git at commit 52ae826492f50f151138ed115faa5e0ac8c803ce (v1.x). diff --git a/include/pthread-barrier.h b/include/pthread-barrier.h index 3e01705..900ebed 100644 --- a/include/pthread-barrier.h +++ b/include/pthread-barrier.h @@ -18,7 +18,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #define _UV_PTHREAD_BARRIER_ #include #include +#if !defined(__MVS__) #include /* sem_t */ +#endif #define PTHREAD_BARRIER_SERIAL_THREAD 0x12345 diff --git a/include/uv-os390.h b/include/uv-os390.h index b0b068f..58f9261 100644 --- a/include/uv-os390.h +++ b/include/uv-os390.h @@ -24,4 +24,7 @@ #define UV_PLATFORM_SEM_T int +#define UV_PLATFORM_LOOP_FIELDS \ + void* ep; \ + #endif /* UV_MVS_H */ diff --git a/include/uv-unix.h b/include/uv-unix.h index bca2714..3030f71 100644 --- a/include/uv-unix.h +++ b/include/uv-unix.h @@ -36,7 +36,9 @@ #include #include +#if !defined(__MVS__) #include +#endif #include #include @@ -44,6 +46,8 @@ #if defined(__linux__) # include "uv-linux.h" +#elif defined (__MVS__) +# include "uv-os390.h" #elif defined(_AIX) # include "uv-aix.h" #elif defined(__sun) diff --git a/include/uv-version.h b/include/uv-version.h index 3cb9b5f..e165809 100644 --- a/include/uv-version.h +++ b/include/uv-version.h @@ -31,8 +31,8 @@ */ #define UV_VERSION_MAJOR 1 -#define UV_VERSION_MINOR 9 -#define UV_VERSION_PATCH 2 +#define UV_VERSION_MINOR 11 +#define UV_VERSION_PATCH 1 #define UV_VERSION_IS_RELEASE 0 #define UV_VERSION_SUFFIX "dev" diff --git a/include/uv-win.h b/include/uv-win.h index a75dba8..9677ff1 100644 --- a/include/uv-win.h +++ b/include/uv-win.h @@ -49,6 +49,7 @@ typedef struct pollfd { #include #include +#include #include #if defined(_MSC_VER) && _MSC_VER < 1600 @@ -116,7 +117,7 @@ typedef struct pollfd { {0xb5367df0, 0xcbac, 0x11cf, \ {0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}} - typedef BOOL PASCAL (*LPFN_ACCEPTEX) + typedef BOOL (PASCAL *LPFN_ACCEPTEX) (SOCKET sListenSocket, SOCKET sAcceptSocket, PVOID lpOutputBuffer, @@ -126,7 +127,7 @@ typedef struct pollfd { LPDWORD lpdwBytesReceived, LPOVERLAPPED lpOverlapped); - typedef BOOL PASCAL (*LPFN_CONNECTEX) + typedef BOOL (PASCAL *LPFN_CONNECTEX) (SOCKET s, const struct sockaddr* name, int namelen, @@ -135,7 +136,7 @@ typedef struct pollfd { LPDWORD lpdwBytesSent, LPOVERLAPPED lpOverlapped); - typedef void PASCAL (*LPFN_GETACCEPTEXSOCKADDRS) + typedef void (PASCAL *LPFN_GETACCEPTEXSOCKADDRS) (PVOID lpOutputBuffer, DWORD dwReceiveDataLength, DWORD dwLocalAddressLength, @@ -145,13 +146,13 @@ typedef struct pollfd { LPSOCKADDR* RemoteSockaddr, LPINT RemoteSockaddrLength); - typedef BOOL PASCAL (*LPFN_DISCONNECTEX) + typedef BOOL (PASCAL *LPFN_DISCONNECTEX) (SOCKET hSocket, LPOVERLAPPED lpOverlapped, DWORD dwFlags, DWORD reserved); - typedef BOOL PASCAL (*LPFN_TRANSMITFILE) + typedef BOOL (PASCAL *LPFN_TRANSMITFILE) (SOCKET hSocket, HANDLE hFile, DWORD nNumberOfBytesToWrite, diff --git a/include/uv.h b/include/uv.h index baa0b28..31f09f0 100644 --- a/include/uv.h +++ b/include/uv.h @@ -363,6 +363,8 @@ typedef enum { } uv_membership; +UV_EXTERN int uv_translate_sys_error(int sys_errno); + UV_EXTERN const char* uv_strerror(int err); UV_EXTERN const char* uv_err_name(int err); diff --git a/src/unix/aix.c b/src/unix/aix.c index 652cd98..1d2cd4a 100644 --- a/src/unix/aix.c +++ b/src/unix/aix.c @@ -64,6 +64,11 @@ #define RDWR_BUF_SIZE 4096 #define EQ(a,b) (strcmp(a,b) == 0) +static void* args_mem = NULL; +static char** process_argv = NULL; +static int process_argc = 0; +static char* process_title_ptr = NULL; + int uv__platform_loop_init(uv_loop_t* loop) { loop->fs_fd = -1; @@ -753,6 +758,13 @@ static void uv__ahafs_event(uv_loop_t* loop, uv__io_t* event_watch, unsigned int assert((bytes >= 0) && "uv__ahafs_event - Error reading monitor file"); + /* In file / directory move cases, AIX Event infrastructure + * produces a second event with no data. + * Ignore it and return gracefully. + */ + if(bytes == 0) + return; + /* Parse the data */ if(bytes > 0) rc = uv__parse_data(result_data, &events, handle); @@ -881,24 +893,94 @@ void uv__fs_event_close(uv_fs_event_t* handle) { char** uv_setup_args(int argc, char** argv) { - return argv; + char** new_argv; + size_t size; + char* s; + int i; + + if (argc <= 0) + return argv; + + /* Save the original pointer to argv. + * AIX uses argv to read the process name. + * (Not the memory pointed to by argv[0..n] as on Linux.) + */ + process_argv = argv; + process_argc = argc; + + /* Calculate how much memory we need for the argv strings. */ + size = 0; + for (i = 0; i < argc; i++) + size += strlen(argv[i]) + 1; + + /* Add space for the argv pointers. */ + size += (argc + 1) * sizeof(char*); + + new_argv = uv__malloc(size); + if (new_argv == NULL) + return argv; + args_mem = new_argv; + + /* Copy over the strings and set up the pointer table. */ + s = (char*) &new_argv[argc + 1]; + for (i = 0; i < argc; i++) { + size = strlen(argv[i]) + 1; + memcpy(s, argv[i], size); + new_argv[i] = s; + s += size; + } + new_argv[i] = NULL; + + return new_argv; } int uv_set_process_title(const char* title) { + char* new_title; + + /* We cannot free this pointer when libuv shuts down, + * the process may still be using it. + */ + new_title = uv__strdup(title); + if (new_title == NULL) + return -ENOMEM; + + /* If this is the first time this is set, + * don't free and set argv[1] to NULL. + */ + if (process_title_ptr != NULL) + uv__free(process_title_ptr); + + process_title_ptr = new_title; + + process_argv[0] = process_title_ptr; + if (process_argc > 1) + process_argv[1] = NULL; + return 0; } int uv_get_process_title(char* buffer, size_t size) { + size_t len; + len = strlen(process_argv[0]); if (buffer == NULL || size == 0) return -EINVAL; + else if (size <= len) + return -ENOBUFS; + + memcpy(buffer, process_argv[0], len + 1); - buffer[0] = '\0'; return 0; } +UV_DESTRUCTOR(static void free_args_mem(void)) { + uv__free(args_mem); /* Keep valgrind happy. */ + args_mem = NULL; +} + + int uv_resident_set_memory(size_t* rss) { char pp[64]; psinfo_t psinfo; diff --git a/src/unix/atomic-ops.h b/src/unix/atomic-ops.h index 815e355..9dac255 100644 --- a/src/unix/atomic-ops.h +++ b/src/unix/atomic-ops.h @@ -43,8 +43,12 @@ UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) { __compare_and_swap(ptr, &oldval, newval); return out; #elif defined(__MVS__) - return __plo_CS(ptr, (unsigned int*) ptr, - oldval, (unsigned int*) &newval); + unsigned int op4; + if (__plo_CSST(ptr, (unsigned int*) &oldval, newval, + (unsigned int*) ptr, *ptr, &op4)) + return oldval; + else + return op4; #else return __sync_val_compare_and_swap(ptr, oldval, newval); #endif @@ -67,13 +71,18 @@ UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)) { # endif /* if defined(__64BIT__) */ return out; #elif defined (__MVS__) -# ifdef _LP64 - return __plo_CSGR(ptr, (unsigned long long*) ptr, - oldval, (unsigned long long*) &newval); -# else - return __plo_CS(ptr, (unsigned int*) ptr, - oldval, (unsigned int*) &newval); -# endif +#ifdef _LP64 + unsigned long long op4; + if (__plo_CSSTGR(ptr, (unsigned long long*) &oldval, newval, + (unsigned long long*) ptr, *ptr, &op4)) +#else + unsigned long op4; + if (__plo_CSST(ptr, (unsigned int*) &oldval, newval, + (unsigned int*) ptr, *ptr, &op4)) +#endif + return oldval; + else + return op4; #else return __sync_val_compare_and_swap(ptr, oldval, newval); #endif diff --git a/src/unix/core.c b/src/unix/core.c index d88fc1d..9ef7134 100644 --- a/src/unix/core.c +++ b/src/unix/core.c @@ -98,7 +98,7 @@ uint64_t uv_hrtime(void) { void uv_close(uv_handle_t* handle, uv_close_cb close_cb) { - assert(!(handle->flags & (UV_CLOSING | UV_CLOSED))); + assert(!uv__is_closing(handle)); handle->flags |= UV_CLOSING; handle->close_cb = close_cb; @@ -517,6 +517,9 @@ int uv__close_nocheckstdio(int fd) { int uv__close(int fd) { assert(fd > STDERR_FILENO); /* Catch stdio close bugs. */ +#if defined(__MVS__) + epoll_file_close(fd); +#endif return uv__close_nocheckstdio(fd); } @@ -836,13 +839,8 @@ void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) { * every tick of the event loop but the other backends allow us to * short-circuit here if the event mask is unchanged. */ - if (w->events == w->pevents) { - if (w->events == 0 && !QUEUE_EMPTY(&w->watcher_queue)) { - QUEUE_REMOVE(&w->watcher_queue); - QUEUE_INIT(&w->watcher_queue); - } + if (w->events == w->pevents) return; - } #endif if (QUEUE_EMPTY(&w->watcher_queue)) @@ -1236,3 +1234,9 @@ void uv_os_free_passwd(uv_passwd_t* pwd) { int uv_os_get_passwd(uv_passwd_t* pwd) { return uv__getpwuid_r(pwd); } + + +int uv_translate_sys_error(int sys_errno) { + /* If < 0 then it's already a libuv error. */ + return sys_errno <= 0 ? sys_errno : -sys_errno; +} diff --git a/src/unix/fs.c b/src/unix/fs.c index 3d478b7..f9513ea 100644 --- a/src/unix/fs.c +++ b/src/unix/fs.c @@ -129,8 +129,23 @@ static ssize_t uv__fs_fdatasync(uv_fs_t* req) { #if defined(__linux__) || defined(__sun) || defined(__NetBSD__) return fdatasync(req->file); -#elif defined(__APPLE__) && defined(SYS_fdatasync) - return syscall(SYS_fdatasync, req->file); +#elif defined(__APPLE__) + /* Apple's fdatasync and fsync explicitly do NOT flush the drive write cache + * to the drive platters. This is in contrast to Linux's fdatasync and fsync + * which do, according to recent man pages. F_FULLFSYNC is Apple's equivalent + * for flushing buffered data to permanent storage. + */ + return fcntl(req->file, F_FULLFSYNC); +#else + return fsync(req->file); +#endif +} + + +static ssize_t uv__fs_fsync(uv_fs_t* req) { +#if defined(__APPLE__) + /* See the comment in uv__fs_fdatasync. */ + return fcntl(req->file, F_FULLFSYNC); #else return fsync(req->file); #endif @@ -365,7 +380,6 @@ static int uv__fs_scandir_sort(UV_CONST_DIRENT** a, UV_CONST_DIRENT** b) { static ssize_t uv__fs_scandir(uv_fs_t* req) { uv__dirent_t **dents; - int saved_errno; int n; dents = NULL; @@ -374,28 +388,17 @@ static ssize_t uv__fs_scandir(uv_fs_t* req) { /* NOTE: We will use nbufs as an index field */ req->nbufs = 0; - if (n == 0) - goto out; /* osx still needs to deallocate some memory */ - else if (n == -1) - return n; - - req->ptr = dents; - - return n; - -out: - saved_errno = errno; - if (dents != NULL) { - int i; - - /* Memory was allocated using the system allocator, so use free() here. */ - for (i = 0; i < n; i++) - free(dents[i]); + if (n == 0) { + /* OS X still needs to deallocate some memory. + * Memory was allocated using the system allocator, so use free() here. + */ free(dents); + dents = NULL; + } else if (n == -1) { + return n; } - errno = saved_errno; - req->ptr = NULL; + req->ptr = dents; return n; } @@ -798,6 +801,10 @@ static void uv__to_stat(struct stat* src, uv_stat_t* dst) { dst->st_flags = 0; dst->st_gen = 0; #elif !defined(_AIX) && ( \ + defined(__DragonFly__) || \ + defined(__FreeBSD__) || \ + defined(__OpenBSD__) || \ + defined(__NetBSD__) || \ defined(_GNU_SOURCE) || \ defined(_BSD_SOURCE) || \ defined(_SVID_SOURCE) || \ @@ -809,9 +816,7 @@ static void uv__to_stat(struct stat* src, uv_stat_t* dst) { dst->st_mtim.tv_nsec = src->st_mtim.tv_nsec; dst->st_ctim.tv_sec = src->st_ctim.tv_sec; dst->st_ctim.tv_nsec = src->st_ctim.tv_nsec; -# if defined(__DragonFly__) || \ - defined(__FreeBSD__) || \ - defined(__OpenBSD__) || \ +# if defined(__FreeBSD__) || \ defined(__NetBSD__) dst->st_birthtim.tv_sec = src->st_birthtim.tv_sec; dst->st_birthtim.tv_nsec = src->st_birthtim.tv_nsec; @@ -945,7 +950,7 @@ static void uv__fs_work(struct uv__work* w) { X(FCHOWN, fchown(req->file, req->uid, req->gid)); X(FDATASYNC, uv__fs_fdatasync(req)); X(FSTAT, uv__fs_fstat(req->file, &req->statbuf)); - X(FSYNC, fsync(req->file)); + X(FSYNC, uv__fs_fsync(req)); X(FTRUNCATE, ftruncate(req->file, req->off)); X(FUTIME, uv__fs_futime(req)); X(LSTAT, uv__fs_lstat(req->path, &req->statbuf)); diff --git a/src/unix/internal.h b/src/unix/internal.h index c7b6019..b48f8fa 100644 --- a/src/unix/internal.h +++ b/src/unix/internal.h @@ -38,6 +38,10 @@ # include "linux-syscalls.h" #endif /* __linux__ */ +#if defined(__MVS__) +# include "os390-syscalls.h" +#endif /* __MVS__ */ + #if defined(__sun) # include # include @@ -52,7 +56,7 @@ #endif /* _AIX */ #if defined(__APPLE__) && !TARGET_OS_IPHONE -# include +# include #endif #if defined(__ANDROID__) @@ -158,7 +162,8 @@ struct uv__stream_queued_fds_s { defined(__DragonFly__) || \ defined(__FreeBSD__) || \ defined(__FreeBSD_kernel__) || \ - defined(__linux__) + defined(__linux__) || \ + defined(__OpenBSD__) #define uv__cloexec uv__cloexec_ioctl #define uv__nonblock uv__nonblock_ioctl #else diff --git a/src/unix/openbsd.c b/src/unix/openbsd.c index 909288c..ac28b69 100644 --- a/src/unix/openbsd.c +++ b/src/unix/openbsd.c @@ -163,7 +163,7 @@ char** uv_setup_args(int argc, char** argv) { int uv_set_process_title(const char* title) { uv__free(process_title); process_title = uv__strdup(title); - setproctitle(title); + setproctitle("%s", title); return 0; } diff --git a/src/unix/os390-syscalls.c b/src/unix/os390-syscalls.c new file mode 100644 index 0000000..2bf3b73 --- /dev/null +++ b/src/unix/os390-syscalls.c @@ -0,0 +1,334 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + + +#include "os390-syscalls.h" +#include +#include +#include +#include + +#define CW_CONDVAR 32 + +#pragma linkage(BPX4CTW, OS) +#pragma linkage(BPX1CTW, OS) + +static int number_of_epolls; +static QUEUE global_epoll_queue; +static uv_mutex_t global_epoll_lock; +static uv_once_t once = UV_ONCE_INIT; + +int scandir(const char* maindir, struct dirent*** namelist, + int (*filter)(const struct dirent*), + int (*compar)(const struct dirent**, + const struct dirent **)) { + struct dirent** nl; + struct dirent* dirent; + unsigned count; + size_t allocated; + DIR* mdir; + + nl = NULL; + count = 0; + allocated = 0; + mdir = opendir(maindir); + if (!mdir) + return -1; + + while (1) { + dirent = readdir(mdir); + if (!dirent) + break; + if (!filter || filter(dirent)) { + struct dirent* copy; + copy = uv__malloc(sizeof(*copy)); + if (!copy) { + while (count) { + dirent = nl[--count]; + uv__free(dirent); + } + uv__free(nl); + closedir(mdir); + errno = ENOMEM; + return -1; + } + memcpy(copy, dirent, sizeof(*copy)); + + nl = uv__realloc(nl, sizeof(*copy) * (count + 1)); + nl[count++] = copy; + } + } + + qsort(nl, count, sizeof(struct dirent *), + (int (*)(const void *, const void *)) compar); + + closedir(mdir); + + *namelist = nl; + return count; +} + + +static unsigned int next_power_of_two(unsigned int val) { + val -= 1; + val |= val >> 1; + val |= val >> 2; + val |= val >> 4; + val |= val >> 8; + val |= val >> 16; + val += 1; + return val; +} + + +static void maybe_resize(uv__os390_epoll* lst, unsigned int len) { + unsigned int newsize; + unsigned int i; + struct pollfd* newlst; + + if (len <= lst->size) + return; + + newsize = next_power_of_two(len); + newlst = uv__realloc(lst->items, newsize * sizeof(lst->items[0])); + + if (newlst == NULL) + abort(); + for (i = lst->size; i < newsize; ++i) + newlst[i].fd = -1; + + lst->items = newlst; + lst->size = newsize; +} + + +static void epoll_init() { + QUEUE_INIT(&global_epoll_queue); + if (uv_mutex_init(&global_epoll_lock)) + abort(); +} + + +uv__os390_epoll* epoll_create1(int flags) { + uv__os390_epoll* lst; + + uv_once(&once, epoll_init); + uv_mutex_lock(&global_epoll_lock); + lst = uv__malloc(sizeof(*lst)); + if (lst == -1) + return NULL; + QUEUE_INSERT_TAIL(&global_epoll_queue, &lst->member); + uv_mutex_unlock(&global_epoll_lock); + + /* initialize list */ + lst->size = 0; + lst->items = NULL; + return lst; +} + + +int epoll_ctl(uv__os390_epoll* lst, + int op, + int fd, + struct epoll_event *event) { + if(op == EPOLL_CTL_DEL) { + if (fd >= lst->size || lst->items[fd].fd == -1) { + errno = ENOENT; + return -1; + } + lst->items[fd].fd = -1; + } else if(op == EPOLL_CTL_ADD) { + maybe_resize(lst, fd + 1); + if (lst->items[fd].fd != -1) { + errno = EEXIST; + return -1; + } + lst->items[fd].fd = fd; + lst->items[fd].events = event->events; + } else if(op == EPOLL_CTL_MOD) { + if (fd >= lst->size || lst->items[fd].fd == -1) { + errno = ENOENT; + return -1; + } + lst->items[fd].events = event->events; + } else + abort(); + + return 0; +} + + +int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events, + int maxevents, int timeout) { + size_t size; + struct pollfd* pfds; + int pollret; + int reventcount; + + uv_mutex_lock(&global_epoll_lock); + uv_mutex_unlock(&global_epoll_lock); + size = lst->size; + pfds = lst->items; + pollret = poll(pfds, size, timeout); + if(pollret == -1) + return pollret; + + reventcount = 0; + for (int i = 0; i < lst->size && i < maxevents; ++i) { + struct epoll_event ev; + + ev.events = 0; + ev.fd = pfds[i].fd; + if(!pfds[i].revents) + continue; + + if(pfds[i].revents & POLLRDNORM) + ev.events = ev.events | POLLIN; + + if(pfds[i].revents & POLLWRNORM) + ev.events = ev.events | POLLOUT; + + if(pfds[i].revents & POLLHUP) + ev.events = ev.events | POLLHUP; + + pfds[i].revents = 0; + events[reventcount++] = ev; + } + + return reventcount; +} + + +int epoll_file_close(int fd) { + QUEUE* q; + + uv_once(&once, epoll_init); + uv_mutex_lock(&global_epoll_lock); + QUEUE_FOREACH(q, &global_epoll_queue) { + uv__os390_epoll* lst; + + lst = QUEUE_DATA(q, uv__os390_epoll, member); + if (fd < lst->size && lst->items != NULL && lst->items[fd].fd != -1) + lst->items[fd].fd = -1; + } + + uv_mutex_unlock(&global_epoll_lock); + return 0; +} + +void epoll_queue_close(uv__os390_epoll* lst) { + uv_mutex_lock(&global_epoll_lock); + QUEUE_REMOVE(&lst->member); + uv_mutex_unlock(&global_epoll_lock); + uv__free(lst->items); + lst->items = NULL; +} + + +int nanosleep(const struct timespec* req, struct timespec* rem) { + unsigned nano; + unsigned seconds; + unsigned events; + unsigned secrem; + unsigned nanorem; + int rv; + int rc; + int rsn; + + nano = (int)req->tv_nsec; + seconds = req->tv_sec; + events = CW_CONDVAR; + +#if defined(_LP64) + BPX4CTW(&seconds, &nano, &events, &secrem, &nanorem, &rv, &rc, &rsn); +#else + BPX1CTW(&seconds, &nano, &events, &secrem, &nanorem, &rv, &rc, &rsn); +#endif + + assert(rv == -1 && errno == EAGAIN); + + if(rem != NULL) { + rem->tv_nsec = nanorem; + rem->tv_sec = secrem; + } + + return 0; +} + + +char* mkdtemp(char* path) { + static const char* tempchars = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + static const size_t num_chars = 62; + static const size_t num_x = 6; + char *ep, *cp; + unsigned int tries, i; + size_t len; + uint64_t v; + int fd; + int retval; + int saved_errno; + + len = strlen(path); + ep = path + len; + if (len < num_x || strncmp(ep - num_x, "XXXXXX", num_x)) { + errno = EINVAL; + return NULL; + } + + fd = open("/dev/urandom", O_RDONLY); + if (fd == -1) + return NULL; + + tries = TMP_MAX; + retval = -1; + do { + if (read(fd, &v, sizeof(v)) != sizeof(v)) + break; + + cp = ep - num_x; + for (i = 0; i < num_x; i++) { + *cp++ = tempchars[v % num_chars]; + v /= num_chars; + } + + if (mkdir(path, S_IRWXU) == 0) { + retval = 0; + break; + } + else if (errno != EEXIST) + break; + } while (--tries); + + saved_errno = errno; + uv__close(fd); + if (tries == 0) { + errno = EEXIST; + return NULL; + } + + if (retval == -1) { + errno = saved_errno; + return NULL; + } + + return path; +} diff --git a/src/unix/os390-syscalls.h b/src/unix/os390-syscalls.h new file mode 100644 index 0000000..61a7cee --- /dev/null +++ b/src/unix/os390-syscalls.h @@ -0,0 +1,69 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + + +#ifndef UV_OS390_SYSCALL_H_ +#define UV_OS390_SYSCALL_H_ + +#include "uv.h" +#include "internal.h" +#include +#include +#include + +#define EPOLL_CTL_ADD 1 +#define EPOLL_CTL_DEL 2 +#define EPOLL_CTL_MOD 3 +#define MAX_EPOLL_INSTANCES 256 +#define MAX_ITEMS_PER_EPOLL 1024 + +#define UV__O_CLOEXEC 0x80000 +#define UV__EPOLL_CLOEXEC UV__O_CLOEXEC +#define UV__EPOLL_CTL_ADD EPOLL_CTL_ADD +#define UV__EPOLL_CTL_DEL EPOLL_CTL_DEL +#define UV__EPOLL_CTL_MOD EPOLL_CTL_MOD + +struct epoll_event { + int events; + int fd; +}; + +typedef struct { + QUEUE member; + struct pollfd* items; + unsigned long size; +} uv__os390_epoll; + +/* epoll api */ +uv__os390_epoll* epoll_create1(int flags); +int epoll_ctl(uv__os390_epoll* ep, int op, int fd, struct epoll_event *event); +int epoll_wait(uv__os390_epoll* ep, struct epoll_event *events, int maxevents, int timeout); +int epoll_file_close(int fd); + +/* utility functions */ +int nanosleep(const struct timespec* req, struct timespec* rem); +int scandir(const char* maindir, struct dirent*** namelist, + int (*filter)(const struct dirent *), + int (*compar)(const struct dirent **, + const struct dirent **)); +char *mkdtemp(char* path); + +#endif /* UV_OS390_SYSCALL_H_ */ diff --git a/src/unix/os390.c b/src/unix/os390.c index bcdbc4b..be325a9 100644 --- a/src/unix/os390.c +++ b/src/unix/os390.c @@ -20,6 +20,628 @@ */ #include "internal.h" +#include +#include +#include +#include +#include +#if defined(__clang__) +#include "csrsic.h" +#else +#include "//'SYS1.SAMPLIB(CSRSIC)'" +#endif + +#define CVT_PTR 0x10 +#define CSD_OFFSET 0x294 + +/* + Long-term average CPU service used by this logical partition, + in millions of service units per hour. If this value is above + the partition's defined capacity, the partition will be capped. + It is calculated using the physical CPU adjustment factor + (RCTPCPUA) so it may not match other measures of service which + are based on the logical CPU adjustment factor. It is available + if the hardware supports LPAR cluster. +*/ +#define RCTLACS_OFFSET 0xC4 + +/* 32-bit count of alive CPUs. This includes both CPs and IFAs */ +#define CSD_NUMBER_ONLINE_CPUS 0xD4 + +/* Address of system resources manager (SRM) control table */ +#define CVTOPCTP_OFFSET 0x25C + +/* Address of the RCT table */ +#define RMCTRCT_OFFSET 0xE4 + +/* Address of the rsm control and enumeration area. */ +#define CVTRCEP_OFFSET 0x490 + +/* + Number of frames currently available to system. + Excluded are frames backing perm storage, frames offline, and bad frames. +*/ +#define RCEPOOL_OFFSET 0x004 + +/* Total number of frames currently on all available frame queues. */ +#define RCEAFC_OFFSET 0x088 + +/* CPC model length from the CSRSI Service. */ +#define CPCMODEL_LENGTH 16 + +/* Thread Entry constants */ +#define PGTH_CURRENT 1 +#define PGTH_LEN 26 +#define PGTHAPATH 0x20 +#pragma linkage(BPX4GTH, OS) +#pragma linkage(BPX1GTH, OS) + +typedef unsigned data_area_ptr_assign_type; + +typedef union { + struct { +#if defined(_LP64) + data_area_ptr_assign_type lower; +#endif + data_area_ptr_assign_type assign; + }; + char* deref; +} data_area_ptr; + + +void uv_loadavg(double avg[3]) { + /* TODO: implement the following */ + avg[0] = 0; + avg[1] = 0; + avg[2] = 0; +} + + +int uv__platform_loop_init(uv_loop_t* loop) { + uv__os390_epoll* ep; + + ep = epoll_create1(UV__EPOLL_CLOEXEC); + loop->ep = ep; + if (ep == NULL) + return -errno; + + return 0; +} + + +void uv__platform_loop_delete(uv_loop_t* loop) { + if (loop->ep != NULL) { + epoll_queue_close(loop->ep); + loop->ep = NULL; + } +} + + +uint64_t uv__hrtime(uv_clocktype_t type) { + struct timeval time; + gettimeofday(&time, NULL); + return (uint64_t) time.tv_sec * 1e9 + time.tv_usec * 1e3; +} + + +/* + Get the exe path using the thread entry information + in the address space. +*/ +static int getexe(const int pid, char* buf, size_t len) { + struct { + int pid; + int thid[2]; + char accesspid; + char accessthid; + char asid[2]; + char loginname[8]; + char flag; + char len; + } Input_data; + + union { + struct { + char gthb[4]; + int pid; + int thid[2]; + char accesspid; + char accessthid[3]; + int lenused; + int offsetProcess; + int offsetConTTY; + int offsetPath; + int offsetCommand; + int offsetFileData; + int offsetThread; + } Output_data; + char buf[2048]; + } Output_buf; + + struct Output_path_type { + char gthe[4]; + short int len; + char path[1024]; + }; + + int Input_length; + int Output_length; + void* Input_address; + void* Output_address; + struct Output_path_type* Output_path; + int rv; + int rc; + int rsn; + + Input_length = PGTH_LEN; + Output_length = sizeof(Output_buf); + Output_address = &Output_buf; + Input_address = &Input_data; + memset(&Input_data, 0, sizeof Input_data); + Input_data.flag |= PGTHAPATH; + Input_data.pid = pid; + Input_data.accesspid = PGTH_CURRENT; + +#ifdef _LP64 + BPX4GTH(&Input_length, + &Input_address, + &Output_length, + &Output_address, + &rv, + &rc, + &rsn); +#else + BPX1GTH(&Input_length, + &Input_address, + &Output_length, + &Output_address, + &rv, + &rc, + &rsn); +#endif + + if (rv == -1) { + errno = rc; + return -1; + } + + /* Check highest byte to ensure data availability */ + assert(((Output_buf.Output_data.offsetPath >>24) & 0xFF) == 'A'); + + /* Get the offset from the lowest 3 bytes */ + Output_path = (char*)(&Output_buf) + + (Output_buf.Output_data.offsetPath & 0x00FFFFFF); + + if (Output_path->len >= len) { + errno = ENOBUFS; + return -1; + } + + strncpy(buf, Output_path->path, len); + + return 0; +} + + +/* + * We could use a static buffer for the path manipulations that we need outside + * of the function, but this function could be called by multiple consumers and + * we don't want to potentially create a race condition in the use of snprintf. + * There is no direct way of getting the exe path in zOS - either through /procfs + * or through some libc APIs. The below approach is to parse the argv[0]'s pattern + * and use it in conjunction with PATH environment variable to craft one. + */ +int uv_exepath(char* buffer, size_t* size) { + int res; + char args[PATH_MAX]; + char abspath[PATH_MAX]; + size_t abspath_size; + int pid; + + if (buffer == NULL || size == NULL || *size == 0) + return -EINVAL; + + pid = getpid(); + res = getexe(pid, args, sizeof(args)); + if (res < 0) + return -EINVAL; + + /* + * Possibilities for args: + * i) an absolute path such as: /home/user/myprojects/nodejs/node + * ii) a relative path such as: ./node or ../myprojects/nodejs/node + * iii) a bare filename such as "node", after exporting PATH variable + * to its location. + */ + + /* Case i) and ii) absolute or relative paths */ + if (strchr(args, '/') != NULL) { + if (realpath(args, abspath) != abspath) + return -errno; + + abspath_size = strlen(abspath); + + *size -= 1; + if (*size > abspath_size) + *size = abspath_size; + + memcpy(buffer, abspath, *size); + buffer[*size] = '\0'; + + return 0; + } else { + /* Case iii). Search PATH environment variable */ + char trypath[PATH_MAX]; + char* clonedpath = NULL; + char* token = NULL; + char* path = getenv("PATH"); + + if (path == NULL) + return -EINVAL; + + clonedpath = uv__strdup(path); + if (clonedpath == NULL) + return -ENOMEM; + + token = strtok(clonedpath, ":"); + while (token != NULL) { + snprintf(trypath, sizeof(trypath) - 1, "%s/%s", token, args); + if (realpath(trypath, abspath) == abspath) { + /* Check the match is executable */ + if (access(abspath, X_OK) == 0) { + abspath_size = strlen(abspath); + + *size -= 1; + if (*size > abspath_size) + *size = abspath_size; + + memcpy(buffer, abspath, *size); + buffer[*size] = '\0'; + + uv__free(clonedpath); + return 0; + } + } + token = strtok(NULL, ":"); + } + uv__free(clonedpath); + + /* Out of tokens (path entries), and no match found */ + return -EINVAL; + } +} + + +uint64_t uv_get_free_memory(void) { + uint64_t freeram; + + data_area_ptr cvt = {0}; + data_area_ptr rcep = {0}; + cvt.assign = *(data_area_ptr_assign_type*)(CVT_PTR); + rcep.assign = *(data_area_ptr_assign_type*)(cvt.deref + CVTRCEP_OFFSET); + freeram = *((uint64_t*)(rcep.deref + RCEAFC_OFFSET)) * 4; + return freeram; +} + + +uint64_t uv_get_total_memory(void) { + uint64_t totalram; + + data_area_ptr cvt = {0}; + data_area_ptr rcep = {0}; + cvt.assign = *(data_area_ptr_assign_type*)(CVT_PTR); + rcep.assign = *(data_area_ptr_assign_type*)(cvt.deref + CVTRCEP_OFFSET); + totalram = *((uint64_t*)(rcep.deref + RCEPOOL_OFFSET)) * 4; + return totalram; +} + + +int uv_resident_set_memory(size_t* rss) { + W_PSPROC buf; + + memset(&buf, 0, sizeof(buf)); + if (w_getpsent(0, &buf, sizeof(W_PSPROC)) == -1) + return -EINVAL; + + *rss = buf.ps_size; + return 0; +} + + +int uv_uptime(double* uptime) { + struct utmpx u ; + struct utmpx *v; + time64_t t; + + u.ut_type = BOOT_TIME; + v = getutxid(&u); + if (v == NULL) + return -1; + *uptime = difftime64(time64(&t), v->ut_tv.tv_sec); + return 0; +} + + +int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { + uv_cpu_info_t* cpu_info; + int result; + int idx; + siv1v2 info; + data_area_ptr cvt = {0}; + data_area_ptr csd = {0}; + data_area_ptr rmctrct = {0}; + data_area_ptr cvtopctp = {0}; + int cpu_usage_avg; + + cvt.assign = *(data_area_ptr_assign_type*)(CVT_PTR); + + csd.assign = *((data_area_ptr_assign_type *) (cvt.deref + CSD_OFFSET)); + cvtopctp.assign = *((data_area_ptr_assign_type *) (cvt.deref + CVTOPCTP_OFFSET)); + rmctrct.assign = *((data_area_ptr_assign_type *) (cvtopctp.deref + RMCTRCT_OFFSET)); + + *count = *((int*) (csd.deref + CSD_NUMBER_ONLINE_CPUS)); + cpu_usage_avg = *((unsigned short int*) (rmctrct.deref + RCTLACS_OFFSET)); + + *cpu_infos = uv__malloc(*count * sizeof(uv_cpu_info_t)); + if (!*cpu_infos) + return -ENOMEM; + + cpu_info = *cpu_infos; + idx = 0; + while (idx < *count) { + cpu_info->speed = *(int*)(info.siv1v2si22v1.si22v1cpucapability); + cpu_info->model = uv__malloc(CPCMODEL_LENGTH + 1); + memset(cpu_info->model, '\0', CPCMODEL_LENGTH + 1); + memcpy(cpu_info->model, info.siv1v2si11v1.si11v1cpcmodel, CPCMODEL_LENGTH); + cpu_info->cpu_times.user = cpu_usage_avg; + /* TODO: implement the following */ + cpu_info->cpu_times.sys = 0; + cpu_info->cpu_times.idle = 0; + cpu_info->cpu_times.irq = 0; + cpu_info->cpu_times.nice = 0; + ++cpu_info; + ++idx; + } + + return 0; +} + + +void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { + for (int i = 0; i < count; ++i) + uv__free(cpu_infos[i].model); + uv__free(cpu_infos); +} + + +static int uv__interface_addresses_v6(uv_interface_address_t** addresses, + int* count) { + uv_interface_address_t* address; + int sockfd; + int maxsize; + __net_ifconf6header_t ifc; + __net_ifconf6entry_t* ifr; + __net_ifconf6entry_t* p; + __net_ifconf6entry_t flg; + + *count = 0; + /* Assume maximum buffer size allowable */ + maxsize = 16384; + + if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) + return -errno; + + ifc.__nif6h_version = 1; + ifc.__nif6h_buflen = maxsize; + ifc.__nif6h_buffer = uv__calloc(1, maxsize);; + + if (ioctl(sockfd, SIOCGIFCONF6, &ifc) == -1) { + uv__close(sockfd); + return -errno; + } + + + *count = 0; + ifr = (__net_ifconf6entry_t*)(ifc.__nif6h_buffer); + while ((char*)ifr < (char*)ifc.__nif6h_buffer + ifc.__nif6h_buflen) { + p = ifr; + ifr = (__net_ifconf6entry_t*)((char*)ifr + ifc.__nif6h_entrylen); + + if (!(p->__nif6e_addr.sin6_family == AF_INET6 || + p->__nif6e_addr.sin6_family == AF_INET)) + continue; + + if (!(p->__nif6e_flags & _NIF6E_FLAGS_ON_LINK_ACTIVE)) + continue; + + ++(*count); + } + + /* Alloc the return interface structs */ + *addresses = uv__malloc(*count * sizeof(uv_interface_address_t)); + if (!(*addresses)) { + uv__close(sockfd); + return -ENOMEM; + } + address = *addresses; + + ifr = (__net_ifconf6entry_t*)(ifc.__nif6h_buffer); + while ((char*)ifr < (char*)ifc.__nif6h_buffer + ifc.__nif6h_buflen) { + p = ifr; + ifr = (__net_ifconf6entry_t*)((char*)ifr + ifc.__nif6h_entrylen); + + if (!(p->__nif6e_addr.sin6_family == AF_INET6 || + p->__nif6e_addr.sin6_family == AF_INET)) + continue; + + if (!(p->__nif6e_flags & _NIF6E_FLAGS_ON_LINK_ACTIVE)) + continue; + + /* All conditions above must match count loop */ + + address->name = uv__strdup(p->__nif6e_name); + + if (p->__nif6e_addr.sin6_family == AF_INET6) + address->address.address6 = *((struct sockaddr_in6*) &p->__nif6e_addr); + else + address->address.address4 = *((struct sockaddr_in*) &p->__nif6e_addr); + + /* TODO: Retrieve netmask using SIOCGIFNETMASK ioctl */ + + address->is_internal = flg.__nif6e_flags & _NIF6E_FLAGS_LOOPBACK ? 1 : 0; + + address++; + } + + uv__close(sockfd); + return 0; +} + + +int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { + uv_interface_address_t* address; + int sockfd; + int maxsize; + struct ifconf ifc; + struct ifreq flg; + struct ifreq* ifr; + struct ifreq* p; + int count_v6; + + /* get the ipv6 addresses first */ + uv_interface_address_t* addresses_v6; + uv__interface_addresses_v6(&addresses_v6, &count_v6); + + /* now get the ipv4 addresses */ + *count = 0; + + /* Assume maximum buffer size allowable */ + maxsize = 16384; + + sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); + if (0 > sockfd) + return -errno; + + ifc.ifc_req = uv__calloc(1, maxsize); + ifc.ifc_len = maxsize; + if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) { + uv__close(sockfd); + return -errno; + } + +#define MAX(a,b) (((a)>(b))?(a):(b)) +#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p)) + + /* Count all up and running ipv4/ipv6 addresses */ + ifr = ifc.ifc_req; + while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { + p = ifr; + ifr = (struct ifreq*) + ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); + + if (!(p->ifr_addr.sa_family == AF_INET6 || + p->ifr_addr.sa_family == AF_INET)) + continue; + + memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); + if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { + uv__close(sockfd); + return -errno; + } + + if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING)) + continue; + + (*count)++; + } + + /* Alloc the return interface structs */ + *addresses = uv__malloc((*count + count_v6) * + sizeof(uv_interface_address_t)); + + if (!(*addresses)) { + uv__close(sockfd); + return -ENOMEM; + } + address = *addresses; + + /* copy over the ipv6 addresses */ + memcpy(address, addresses_v6, count_v6 * sizeof(uv_interface_address_t)); + address += count_v6; + *count += count_v6; + uv__free(addresses_v6); + + ifr = ifc.ifc_req; + while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { + p = ifr; + ifr = (struct ifreq*) + ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); + + if (!(p->ifr_addr.sa_family == AF_INET6 || + p->ifr_addr.sa_family == AF_INET)) + continue; + + memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); + if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { + uv__close(sockfd); + return -ENOSYS; + } + + if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING)) + continue; + + /* All conditions above must match count loop */ + + address->name = uv__strdup(p->ifr_name); + + if (p->ifr_addr.sa_family == AF_INET6) { + address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr); + } else { + address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr); + } + + address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0; + address++; + } + +#undef ADDR_SIZE +#undef MAX + + uv__close(sockfd); + return 0; +} + + +void uv_free_interface_addresses(uv_interface_address_t* addresses, + int count) { + int i; + for (i = 0; i < count; ++i) + uv__free(addresses[i].name); + uv__free(addresses); +} + + +void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { + struct epoll_event* events; + struct epoll_event dummy; + uintptr_t i; + uintptr_t nfds; + + assert(loop->watchers != NULL); + + events = (struct epoll_event*) loop->watchers[loop->nwatchers]; + nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1]; + if (events != NULL) + /* Invalidate events with same file descriptor */ + for (i = 0; i < nfds; i++) + if ((int) events[i].fd == fd) + events[i].fd = -1; + + /* Remove the file descriptor from the epoll. */ + if (loop->ep != NULL) + epoll_ctl(loop->ep, UV__EPOLL_CTL_DEL, fd, &dummy); +} + int uv__io_check_fd(uv_loop_t* loop, int fd) { struct pollfd p[1]; @@ -40,3 +662,204 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) { return 0; } + + +void uv__fs_event_close(uv_fs_event_t* handle) { + UNREACHABLE(); +} + + +int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { + return -ENOSYS; +} + + +int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb, + const char* filename, unsigned int flags) { + return -ENOSYS; +} + + +int uv_fs_event_stop(uv_fs_event_t* handle) { + return -ENOSYS; +} + + +void uv__io_poll(uv_loop_t* loop, int timeout) { + static const int max_safe_timeout = 1789569; + struct epoll_event events[1024]; + struct epoll_event* pe; + struct epoll_event e; + int real_timeout; + QUEUE* q; + uv__io_t* w; + uint64_t base; + int count; + int nfds; + int fd; + int op; + int i; + + if (loop->nfds == 0) { + assert(QUEUE_EMPTY(&loop->watcher_queue)); + return; + } + + while (!QUEUE_EMPTY(&loop->watcher_queue)) { + uv_stream_t* stream; + + q = QUEUE_HEAD(&loop->watcher_queue); + QUEUE_REMOVE(q); + QUEUE_INIT(q); + w = QUEUE_DATA(q, uv__io_t, watcher_queue); + + assert(w->pevents != 0); + assert(w->fd >= 0); + + stream= container_of(w, uv_stream_t, io_watcher); + + assert(w->fd < (int) loop->nwatchers); + + e.events = w->pevents; + e.fd = w->fd; + + if (w->events == 0) + op = UV__EPOLL_CTL_ADD; + else + op = UV__EPOLL_CTL_MOD; + + /* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching + * events, skip the syscall and squelch the events after epoll_wait(). + */ + if (epoll_ctl(loop->ep, op, w->fd, &e)) { + if (errno != EEXIST) + abort(); + + assert(op == UV__EPOLL_CTL_ADD); + + /* We've reactivated a file descriptor that's been watched before. */ + if (epoll_ctl(loop->ep, UV__EPOLL_CTL_MOD, w->fd, &e)) + abort(); + } + + w->events = w->pevents; + } + + assert(timeout >= -1); + base = loop->time; + count = 48; /* Benchmarks suggest this gives the best throughput. */ + real_timeout = timeout; + int nevents = 0; + + nfds = 0; + for (;;) { + if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout) + timeout = max_safe_timeout; + + nfds = epoll_wait(loop->ep, events, + ARRAY_SIZE(events), timeout); + + /* Update loop->time unconditionally. It's tempting to skip the update when + * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the + * operating system didn't reschedule our process while in the syscall. + */ + base = loop->time; + SAVE_ERRNO(uv__update_time(loop)); + if (nfds == 0) { + assert(timeout != -1); + timeout = real_timeout - timeout; + if (timeout > 0) + continue; + + return; + } + + if (nfds == -1) { + + if (errno != EINTR) + abort(); + + if (timeout == -1) + continue; + + if (timeout == 0) + return; + + /* Interrupted by a signal. Update timeout and poll again. */ + goto update_timeout; + } + + + assert(loop->watchers != NULL); + loop->watchers[loop->nwatchers] = (void*) events; + loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds; + for (i = 0; i < nfds; i++) { + pe = events + i; + fd = pe->fd; + + /* Skip invalidated events, see uv__platform_invalidate_fd */ + if (fd == -1) + continue; + + assert(fd >= 0); + assert((unsigned) fd < loop->nwatchers); + + w = loop->watchers[fd]; + + if (w == NULL) { + /* File descriptor that we've stopped watching, disarm it. + * + * Ignore all errors because we may be racing with another thread + * when the file descriptor is closed. + */ + epoll_ctl(loop->ep, UV__EPOLL_CTL_DEL, fd, pe); + continue; + } + + /* Give users only events they're interested in. Prevents spurious + * callbacks when previous callback invocation in this loop has stopped + * the current watcher. Also, filters out events that users has not + * requested us to watch. + */ + pe->events &= w->pevents | POLLERR | POLLHUP; + + if (pe->events == POLLERR || pe->events == POLLHUP) + pe->events |= w->pevents & (POLLIN | POLLOUT); + + if (pe->events != 0) { + w->cb(loop, w, pe->events); + nevents++; + } + } + loop->watchers[loop->nwatchers] = NULL; + loop->watchers[loop->nwatchers + 1] = NULL; + + if (nevents != 0) { + if (nfds == ARRAY_SIZE(events) && --count != 0) { + /* Poll for more events but don't block this time. */ + timeout = 0; + continue; + } + return; + } + + if (timeout == 0) + return; + + if (timeout == -1) + continue; + +update_timeout: + assert(timeout > 0); + + real_timeout -= (loop->time - base); + if (real_timeout <= 0) + return; + + timeout = real_timeout; + } +} + +void uv__set_process_title(const char* title) { + /* do nothing */ +} diff --git a/src/unix/poll.c b/src/unix/poll.c index 4c0d478..370994b 100644 --- a/src/unix/poll.c +++ b/src/unix/poll.c @@ -92,7 +92,7 @@ static void uv__poll_stop(uv_poll_t* handle) { int uv_poll_stop(uv_poll_t* handle) { - assert(!(handle->flags & (UV_CLOSING | UV_CLOSED))); + assert(!uv__is_closing(handle)); uv__poll_stop(handle); return 0; } @@ -102,7 +102,7 @@ int uv_poll_start(uv_poll_t* handle, int pevents, uv_poll_cb poll_cb) { int events; assert((pevents & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0); - assert(!(handle->flags & (UV_CLOSING | UV_CLOSED))); + assert(!uv__is_closing(handle)); uv__poll_stop(handle); diff --git a/src/unix/process.c b/src/unix/process.c index 45f5b45..f2fe305 100644 --- a/src/unix/process.c +++ b/src/unix/process.c @@ -323,7 +323,7 @@ static void uv__process_child_init(const uv_process_options_t* options, } if (fd == use_fd) - uv__cloexec(use_fd, 0); + uv__cloexec_fcntl(use_fd, 0); else fd = dup2(use_fd, fd); @@ -333,7 +333,7 @@ static void uv__process_child_init(const uv_process_options_t* options, } if (fd <= 2) - uv__nonblock(fd, 0); + uv__nonblock_fcntl(fd, 0); if (close_fd >= stdio_count) uv__close(close_fd); diff --git a/src/unix/proctitle.c b/src/unix/proctitle.c index 08d875f..9160f7e 100644 --- a/src/unix/proctitle.c +++ b/src/unix/proctitle.c @@ -48,9 +48,15 @@ char** uv_setup_args(int argc, char** argv) { for (i = 0; i < argc; i++) size += strlen(argv[i]) + 1; +#if defined(__MVS__) + /* argv is not adjacent. So just use argv[0] */ + process_title.str = argv[0]; + process_title.len = strlen(argv[0]); +#else process_title.str = argv[0]; process_title.len = argv[argc - 1] + strlen(argv[argc - 1]) - argv[0]; assert(process_title.len + 1 == size); /* argv memory should be adjacent. */ +#endif /* Add space for the argv pointers. */ size += (argc + 1) * sizeof(char*); diff --git a/src/unix/pthread-barrier.c b/src/unix/pthread-barrier.c index f57bf25..b6e604d 100644 --- a/src/unix/pthread-barrier.c +++ b/src/unix/pthread-barrier.c @@ -73,7 +73,8 @@ int pthread_barrier_wait(pthread_barrier_t* barrier) { if (++b->in == b->threshold) { b->in = 0; b->out = b->threshold - 1; - assert(pthread_cond_signal(&b->cond) == 0); + rc = pthread_cond_signal(&b->cond); + assert(rc == 0); pthread_mutex_unlock(&b->mutex); return PTHREAD_BARRIER_SERIAL_THREAD; diff --git a/src/unix/signal.c b/src/unix/signal.c index d82b9b7..dbd8f86 100644 --- a/src/unix/signal.c +++ b/src/unix/signal.c @@ -43,7 +43,7 @@ static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2); static void uv__signal_stop(uv_signal_t* handle); -static pthread_once_t uv__signal_global_init_guard = PTHREAD_ONCE_INIT; +static uv_once_t uv__signal_global_init_guard = UV_ONCE_INIT; static struct uv__signal_tree_s uv__signal_tree = RB_INITIALIZER(uv__signal_tree); static int uv__signal_lock_pipefd[2]; @@ -64,7 +64,7 @@ static void uv__signal_global_init(void) { void uv__signal_global_once_init(void) { - pthread_once(&uv__signal_global_init_guard, uv__signal_global_init); + uv_once(&uv__signal_global_init_guard, uv__signal_global_init); } @@ -290,7 +290,7 @@ int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) { sigset_t saved_sigmask; int err; - assert(!(handle->flags & (UV_CLOSING | UV_CLOSED))); + assert(!uv__is_closing(handle)); /* If the user supplies signum == 0, then return an error already. If the * signum is otherwise invalid then uv__signal_register will find out @@ -434,7 +434,7 @@ static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) { int uv_signal_stop(uv_signal_t* handle) { - assert(!(handle->flags & (UV_CLOSING | UV_CLOSED))); + assert(!uv__is_closing(handle)); uv__signal_stop(handle); return 0; } diff --git a/src/unix/stream.c b/src/unix/stream.c index d20d0bc..7059df1 100644 --- a/src/unix/stream.c +++ b/src/unix/stream.c @@ -390,7 +390,7 @@ failed_malloc: int uv__stream_open(uv_stream_t* stream, int fd, int flags) { -#if defined(__APPLE__) +#if defined(__APPLE__) || defined(__MVS__) int enable; #endif @@ -409,7 +409,7 @@ int uv__stream_open(uv_stream_t* stream, int fd, int flags) { return -errno; } -#if defined(__APPLE__) +#if defined(__APPLE__) || defined(__MVS__) enable = 1; if (setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, &enable, sizeof(enable)) && errno != ENOTSOCK && @@ -1194,6 +1194,30 @@ static void uv__read(uv_stream_t* stream) { return; } } + +#if defined(__MVS__) + if (is_ipc && msg.msg_controllen > 0) { + uv_buf_t blankbuf; + int nread; + struct iovec *old; + + blankbuf.base = 0; + blankbuf.len = 0; + old = msg.msg_iov; + msg.msg_iov = (struct iovec*) &blankbuf; + nread = 0; + do { + nread = uv__recvmsg(uv__stream_fd(stream), &msg, 0); + err = uv__stream_recv_cmsg(stream, &msg); + if (err != 0) { + stream->read_cb(stream, err, &buf); + msg.msg_iov = old; + return; + } + } while (nread == 0 && msg.msg_controllen > 0); + msg.msg_iov = old; + } +#endif stream->read_cb(stream, nread, &buf); /* Return if we didn't fill the buffer, there is no more data to read. */ @@ -1221,8 +1245,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) { if (!(stream->flags & UV_STREAM_WRITABLE) || stream->flags & UV_STREAM_SHUT || stream->flags & UV_STREAM_SHUTTING || - stream->flags & UV_CLOSED || - stream->flags & UV_CLOSING) { + uv__is_closing(stream)) { return -ENOTCONN; } diff --git a/src/unix/sunos.c b/src/unix/sunos.c index 3e7a759..a43f7f1 100644 --- a/src/unix/sunos.c +++ b/src/unix/sunos.c @@ -695,6 +695,11 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { uv__free(cpu_infos); } +#ifdef SUNOS_NO_IFADDRS +int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { + return -ENOSYS; +} +#else /* SUNOS_NO_IFADDRS */ /* * Inspired By: * https://blogs.oracle.com/paulie/entry/retrieving_mac_address_in_solaris @@ -742,9 +747,6 @@ static int uv__set_phys_addr(uv_interface_address_t* address, } int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { -#ifdef SUNOS_NO_IFADDRS - return -ENOSYS; -#else uv_interface_address_t* address; struct ifaddrs* addrs; struct ifaddrs* ent; @@ -805,9 +807,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { freeifaddrs(addrs); return 0; -#endif /* SUNOS_NO_IFADDRS */ } - +#endif /* SUNOS_NO_IFADDRS */ void uv_free_interface_addresses(uv_interface_address_t* addresses, int count) { diff --git a/src/unix/thread.c b/src/unix/thread.c index 52989f7..a9b5e4c 100644 --- a/src/unix/thread.c +++ b/src/unix/thread.c @@ -40,28 +40,8 @@ #undef NANOSEC #define NANOSEC ((uint64_t) 1e9) -struct thread_ctx { - void (*entry)(void* arg); - void* arg; -}; - - -static void* uv__thread_start(void *arg) -{ - struct thread_ctx *ctx_p; - struct thread_ctx ctx; - - ctx_p = arg; - ctx = *ctx_p; - uv__free(ctx_p); - ctx.entry(ctx.arg); - - return 0; -} - int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) { - struct thread_ctx* ctx; int err; pthread_attr_t* attr; #if defined(__APPLE__) @@ -69,13 +49,6 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) { struct rlimit lim; #endif - ctx = uv__malloc(sizeof(*ctx)); - if (ctx == NULL) - return UV_ENOMEM; - - ctx->entry = entry; - ctx->arg = arg; - /* On OSX threads other than the main thread are created with a reduced stack * size by default, adjust it to RLIMIT_STACK. */ @@ -99,14 +72,11 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) { attr = NULL; #endif - err = pthread_create(tid, attr, uv__thread_start, ctx); + err = pthread_create(tid, attr, (void*(*)(void*)) entry, arg); if (attr != NULL) pthread_attr_destroy(attr); - if (err) - uv__free(ctx); - return -err; } diff --git a/src/uv-common.c b/src/uv-common.c index 434a502..bc7d137 100644 --- a/src/uv-common.c +++ b/src/uv-common.c @@ -512,8 +512,18 @@ void uv__fs_scandir_cleanup(uv_fs_t* req) { int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) { uv__dirent_t** dents; uv__dirent_t* dent; + unsigned int* nbufs; - unsigned int* nbufs = uv__get_nbufs(req); + /* Check to see if req passed */ + if (req->result < 0) + return req->result; + + /* Ptr will be null if req was canceled or no files found */ + if (!req->ptr) + return UV_EOF; + + nbufs = uv__get_nbufs(req); + assert(nbufs); dents = req->ptr; @@ -613,7 +623,9 @@ uv_loop_t* uv_loop_new(void) { int uv_loop_close(uv_loop_t* loop) { QUEUE* q; uv_handle_t* h; +#ifndef NDEBUG void* saved_data; +#endif if (!QUEUE_EMPTY(&(loop)->active_reqs)) return UV_EBUSY; diff --git a/src/win/core.c b/src/win/core.c index 9d00afc..e84186d 100644 --- a/src/win/core.c +++ b/src/win/core.c @@ -35,10 +35,6 @@ #include "handle-inl.h" #include "req-inl.h" - -static uv_loop_t default_loop_struct; -static uv_loop_t* default_loop_ptr; - /* uv_once initialization guards */ static uv_once_t uv_init_guard_ = UV_ONCE_INIT; diff --git a/src/win/error.c b/src/win/error.c index c512f35..642d111 100644 --- a/src/win/error.c +++ b/src/win/error.c @@ -71,6 +71,7 @@ int uv_translate_sys_error(int sys_errno) { switch (sys_errno) { case ERROR_NOACCESS: return UV_EACCES; case WSAEACCES: return UV_EACCES; + case ERROR_ELEVATION_REQUIRED: return UV_EACCES; case ERROR_ADDRESS_ALREADY_ASSOCIATED: return UV_EADDRINUSE; case WSAEADDRINUSE: return UV_EADDRINUSE; case WSAEADDRNOTAVAIL: return UV_EADDRNOTAVAIL; diff --git a/src/win/fs-event.c b/src/win/fs-event.c index 03e4adc..05fc1d0 100644 --- a/src/win/fs-event.c +++ b/src/win/fs-event.c @@ -188,7 +188,6 @@ int uv_fs_event_start(uv_fs_event_t* handle, if (is_path_dir) { /* path is a directory, so that's the directory that we will watch. */ - handle->dirw = pathw; dir_to_watch = pathw; } else { /* @@ -274,6 +273,8 @@ int uv_fs_event_start(uv_fs_event_t* handle, goto error; } + assert(is_path_dir ? pathw != NULL : pathw == NULL); + handle->dirw = pathw; handle->req_pending = 1; return 0; diff --git a/src/win/fs.c b/src/win/fs.c index f1711ac..6902d4f 100644 --- a/src/win/fs.c +++ b/src/win/fs.c @@ -123,7 +123,7 @@ INLINE static int fs__capture_path(uv_fs_t* req, const char* path, const char* new_path, const int copy_path) { char* buf; char* pos; - ssize_t buf_sz = 0, path_len, pathw_len = 0, new_pathw_len = 0; + ssize_t buf_sz = 0, path_len = 0, pathw_len = 0, new_pathw_len = 0; /* new_path can only be set if path is also set. */ assert(new_path == NULL || path != NULL); @@ -403,7 +403,6 @@ void fs__open(uv_fs_t* req) { switch (flags & (_O_RDONLY | _O_WRONLY | _O_RDWR)) { case _O_RDONLY: access = FILE_GENERIC_READ; - attributes |= FILE_FLAG_BACKUP_SEMANTICS; break; case _O_WRONLY: access = FILE_GENERIC_WRITE; @@ -418,7 +417,6 @@ void fs__open(uv_fs_t* req) { if (flags & _O_APPEND) { access &= ~FILE_WRITE_DATA; access |= FILE_APPEND_DATA; - attributes &= ~FILE_FLAG_BACKUP_SEMANTICS; } /* diff --git a/src/win/getaddrinfo.c b/src/win/getaddrinfo.c index 744f8e0..c13bfec 100644 --- a/src/win/getaddrinfo.c +++ b/src/win/getaddrinfo.c @@ -262,8 +262,7 @@ int uv_getaddrinfo(uv_loop_t* loop, int err; if (req == NULL || (node == NULL && service == NULL)) { - err = WSAEINVAL; - goto error; + return UV_EINVAL; } uv_req_init(loop, (uv_req_t*)req); diff --git a/src/win/process-stdio.c b/src/win/process-stdio.c index e3c06f5..032e309 100644 --- a/src/win/process-stdio.c +++ b/src/win/process-stdio.c @@ -372,6 +372,7 @@ int uv__stdio_create(uv_loop_t* loop, case FILE_TYPE_PIPE: CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FPIPE; + break; case FILE_TYPE_CHAR: case FILE_TYPE_REMOTE: diff --git a/src/win/process.c b/src/win/process.c index 855c374..bdf88d2 100644 --- a/src/win/process.c +++ b/src/win/process.c @@ -492,7 +492,7 @@ WCHAR* quote_cmd_arg(const WCHAR *source, WCHAR *target) { * input : hello\\"world * output: "hello\\\\\"world" * input : hello world\ - * output: "hello world\" + * output: "hello world\\" */ *(target++) = L'"'; diff --git a/src/win/signal.c b/src/win/signal.c index 2c64a55..af7974c 100644 --- a/src/win/signal.c +++ b/src/win/signal.c @@ -30,12 +30,14 @@ RB_HEAD(uv_signal_tree_s, uv_signal_s); static struct uv_signal_tree_s uv__signal_tree = RB_INITIALIZER(uv__signal_tree); -static ssize_t volatile uv__signal_control_handler_refs = 0; static CRITICAL_SECTION uv__signal_lock; +static BOOL WINAPI uv__signal_control_handler(DWORD type); void uv_signals_init() { InitializeCriticalSection(&uv__signal_lock); + if (!SetConsoleCtrlHandler(uv__signal_control_handler, TRUE)) + abort(); } @@ -125,102 +127,6 @@ static BOOL WINAPI uv__signal_control_handler(DWORD type) { } -static int uv__signal_register_control_handler() { - /* When this function is called, the uv__signal_lock must be held. */ - - /* If the console control handler has already been hooked, just add a */ - /* reference. */ - if (uv__signal_control_handler_refs > 0) { - uv__signal_control_handler_refs++; - return 0; - } - - if (!SetConsoleCtrlHandler(uv__signal_control_handler, TRUE)) - return GetLastError(); - - uv__signal_control_handler_refs++; - - return 0; -} - - -static void uv__signal_unregister_control_handler() { - /* When this function is called, the uv__signal_lock must be held. */ - BOOL r; - - /* Don't unregister if the number of console control handlers exceeds one. */ - /* Just remove a reference in that case. */ - if (uv__signal_control_handler_refs > 1) { - uv__signal_control_handler_refs--; - return; - } - - assert(uv__signal_control_handler_refs == 1); - - r = SetConsoleCtrlHandler(uv__signal_control_handler, FALSE); - /* This should never fail; if it does it is probably a bug in libuv. */ - assert(r); - - uv__signal_control_handler_refs--; -} - - -static int uv__signal_register(int signum) { - switch (signum) { - case SIGINT: - case SIGBREAK: - case SIGHUP: - return uv__signal_register_control_handler(); - - case SIGWINCH: - /* SIGWINCH is generated in tty.c. No need to register anything. */ - return 0; - - case SIGILL: - case SIGABRT_COMPAT: - case SIGFPE: - case SIGSEGV: - case SIGTERM: - case SIGABRT: - /* Signal is never raised. */ - return 0; - - default: - /* Invalid signal. */ - return ERROR_INVALID_PARAMETER; - } -} - - -static void uv__signal_unregister(int signum) { - switch (signum) { - case SIGINT: - case SIGBREAK: - case SIGHUP: - uv__signal_unregister_control_handler(); - return; - - case SIGWINCH: - /* SIGWINCH is generated in tty.c. No need to unregister anything. */ - return; - - case SIGILL: - case SIGABRT_COMPAT: - case SIGFPE: - case SIGSEGV: - case SIGTERM: - case SIGABRT: - /* Nothing is registered for this signal. */ - return; - - default: - /* Libuv bug. */ - assert(0 && "Invalid signum"); - return; - } -} - - int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle) { uv_req_t* req; @@ -247,8 +153,6 @@ int uv_signal_stop(uv_signal_t* handle) { EnterCriticalSection(&uv__signal_lock); - uv__signal_unregister(handle->signum); - removed_handle = RB_REMOVE(uv_signal_tree_s, &uv__signal_tree, handle); assert(removed_handle == handle); @@ -262,14 +166,9 @@ int uv_signal_stop(uv_signal_t* handle) { int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) { - int err; - - /* If the user supplies signum == 0, then return an error already. If the */ - /* signum is otherwise invalid then uv__signal_register will find out */ - /* eventually. */ - if (signum == 0) { + /* Test for invalid signal values. */ + if (signum != SIGWINCH && (signum <= 0 || signum >= NSIG)) return UV_EINVAL; - } /* Short circuit: if the signal watcher is already watching {signum} don't */ /* go through the process of deregistering and registering the handler. */ @@ -289,13 +188,6 @@ int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) { EnterCriticalSection(&uv__signal_lock); - err = uv__signal_register(signum); - if (err) { - /* Uh-oh, didn't work. */ - LeaveCriticalSection(&uv__signal_lock); - return uv_translate_sys_error(err); - } - handle->signum = signum; RB_INSERT(uv_signal_tree_s, &uv__signal_tree, handle); diff --git a/src/win/tty.c b/src/win/tty.c index 18d68d0..1b7adf6 100644 --- a/src/win/tty.c +++ b/src/win/tty.c @@ -56,6 +56,7 @@ #define ANSI_BACKSLASH_SEEN 0x80 #define MAX_INPUT_BUFFER_LENGTH 8192 +#define MAX_CONSOLE_CHAR 8192 #ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 @@ -1003,6 +1004,9 @@ int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb, if (handle->tty.rd.last_key_len > 0) { SET_REQ_SUCCESS(&handle->read_req); uv_insert_pending_req(handle->loop, (uv_req_t*) &handle->read_req); + /* Make sure no attempt is made to insert it again until it's handled. */ + handle->flags |= UV_HANDLE_READ_PENDING; + handle->reqs_pending++; return 0; } @@ -1616,17 +1620,29 @@ static int uv_tty_write_bufs(uv_tty_t* handle, DWORD* error) { /* We can only write 8k characters at a time. Windows can't handle */ /* much more characters in a single console write anyway. */ - WCHAR utf16_buf[8192]; + WCHAR utf16_buf[MAX_CONSOLE_CHAR]; + WCHAR* utf16_buffer; DWORD utf16_buf_used = 0; - unsigned int i; - -#define FLUSH_TEXT() \ - do { \ - if (utf16_buf_used > 0) { \ - uv_tty_emit_text(handle, utf16_buf, utf16_buf_used, error); \ - utf16_buf_used = 0; \ - } \ - } while (0) + unsigned int i, len, max_len, pos; + int allocate = 0; + +#define FLUSH_TEXT() \ + do { \ + pos = 0; \ + do { \ + len = utf16_buf_used - pos; \ + if (len > MAX_CONSOLE_CHAR) \ + len = MAX_CONSOLE_CHAR; \ + uv_tty_emit_text(handle, &utf16_buffer[pos], len, error); \ + pos += len; \ + } while (pos < utf16_buf_used); \ + if (allocate) { \ + uv__free(utf16_buffer); \ + allocate = 0; \ + utf16_buffer = utf16_buf; \ + } \ + utf16_buf_used = 0; \ + } while (0) #define ENSURE_BUFFER_SPACE(wchars_needed) \ if (wchars_needed > ARRAY_SIZE(utf16_buf) - utf16_buf_used) { \ @@ -1644,38 +1660,47 @@ static int uv_tty_write_bufs(uv_tty_t* handle, /* state. */ *error = ERROR_SUCCESS; + utf16_buffer = utf16_buf; + uv_sem_wait(&uv_tty_output_lock); for (i = 0; i < nbufs; i++) { uv_buf_t buf = bufs[i]; unsigned int j; - if (uv__vterm_state == UV_SUPPORTED) { - utf16_buf_used = MultiByteToWideChar(CP_UTF8, - 0, - buf.base, - buf.len, - NULL, - 0); + if (uv__vterm_state == UV_SUPPORTED && buf.len > 0) { + utf16_buf_used = MultiByteToWideChar(CP_UTF8, + 0, + buf.base, + buf.len, + NULL, + 0); + + if (utf16_buf_used == 0) { + *error = GetLastError(); + break; + } - if (utf16_buf_used == 0) { - *error = GetLastError(); - break; - } + max_len = (utf16_buf_used + 1) * sizeof(WCHAR); + allocate = max_len > MAX_CONSOLE_CHAR; + if (allocate) + utf16_buffer = uv__malloc(max_len); + if (!MultiByteToWideChar(CP_UTF8, + 0, + buf.base, + buf.len, + utf16_buffer, + utf16_buf_used)) { + if (allocate) + uv__free(utf16_buffer); + *error = GetLastError(); + break; + } - if (!MultiByteToWideChar(CP_UTF8, - 0, - buf.base, - buf.len, - utf16_buf, - utf16_buf_used)) { - *error = GetLastError(); - break; - } + FLUSH_TEXT(); - FLUSH_TEXT(); - continue; - } + continue; + } for (j = 0; j < buf.len; j++) { unsigned char c = buf.base[j]; diff --git a/src/win/winapi.h b/src/win/winapi.h index 16d9365..9401676 100644 --- a/src/win/winapi.h +++ b/src/win/winapi.h @@ -4145,7 +4145,7 @@ typedef const UNICODE_STRING *PCUNICODE_STRING; struct { UCHAR DataBuffer[1]; } GenericReparseBuffer; - } DUMMYUNIONNAME; + }; } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; #endif @@ -4153,7 +4153,7 @@ typedef struct _IO_STATUS_BLOCK { union { NTSTATUS Status; PVOID Pointer; - } DUMMYUNIONNAME; + }; ULONG_PTR Information; } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; @@ -4606,6 +4606,10 @@ typedef NTSTATUS (NTAPI *sNtQueryDirectoryFile) #endif /* from winerror.h */ +#ifndef ERROR_ELEVATION_REQUIRED +# define ERROR_ELEVATION_REQUIRED 740 +#endif + #ifndef ERROR_SYMLINK_NOT_SUPPORTED # define ERROR_SYMLINK_NOT_SUPPORTED 1464 #endif ----------------------------------------------------------------------- Summary of changes: Utilities/cmlibuv/include/pthread-barrier.h | 2 + Utilities/cmlibuv/include/uv-os390.h | 3 + Utilities/cmlibuv/include/uv-unix.h | 4 + Utilities/cmlibuv/include/uv-version.h | 4 +- Utilities/cmlibuv/include/uv-win.h | 1 + Utilities/cmlibuv/include/uv.h | 2 + Utilities/cmlibuv/src/unix/aix.c | 86 ++- Utilities/cmlibuv/src/unix/atomic-ops.h | 27 +- Utilities/cmlibuv/src/unix/core.c | 18 +- Utilities/cmlibuv/src/unix/fs.c | 57 +- Utilities/cmlibuv/src/unix/internal.h | 12 +- Utilities/cmlibuv/src/unix/openbsd.c | 2 +- Utilities/cmlibuv/src/unix/os390-syscalls.c | 334 +++++++++++ Utilities/cmlibuv/src/unix/os390-syscalls.h | 69 +++ Utilities/cmlibuv/src/unix/os390.c | 823 ++++++++++++++++++++++++++ Utilities/cmlibuv/src/unix/poll.c | 4 +- Utilities/cmlibuv/src/unix/process.c | 4 +- Utilities/cmlibuv/src/unix/proctitle.c | 6 + Utilities/cmlibuv/src/unix/pthread-barrier.c | 3 +- Utilities/cmlibuv/src/unix/signal.c | 8 +- Utilities/cmlibuv/src/unix/stream.c | 31 +- Utilities/cmlibuv/src/unix/sunos.c | 11 +- Utilities/cmlibuv/src/unix/thread.c | 32 +- Utilities/cmlibuv/src/uv-common.c | 12 +- Utilities/cmlibuv/src/win/core.c | 4 - Utilities/cmlibuv/src/win/error.c | 1 + Utilities/cmlibuv/src/win/fs-event.c | 3 +- Utilities/cmlibuv/src/win/fs.c | 4 +- Utilities/cmlibuv/src/win/getaddrinfo.c | 3 +- Utilities/cmlibuv/src/win/process-stdio.c | 1 + Utilities/cmlibuv/src/win/process.c | 2 +- Utilities/cmlibuv/src/win/signal.c | 118 +--- Utilities/cmlibuv/src/win/tty.c | 91 +-- Utilities/cmlibuv/src/win/winapi.h | 4 + 34 files changed, 1530 insertions(+), 256 deletions(-) create mode 100644 Utilities/cmlibuv/src/unix/os390-syscalls.c create mode 100644 Utilities/cmlibuv/src/unix/os390-syscalls.h hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 22 10:52:51 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 22 Feb 2017 10:52:51 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-458-gc42f62b Message-ID: <20170222155252.7A2CDFA24F@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via c42f62b6bed8248fd99a48737c14054d09f973a7 (commit) via 6ab467b03702929b346cb1136092dd9417cc74fd (commit) via 3f92980773c8f2106f0ee2986a89fa958fc73acf (commit) via 0a4094564dadfd15e0daa1e95927c343cfc616a2 (commit) via a59a7ee95601f3496ec9ba9ae1283a8d980460bf (commit) via c206211af647dd1f7039da91c34c9c72e50aefdf (commit) via cdce7c619c58ec0947c036b93013445bb93e4be8 (commit) from 1925f8bc2a517c051c44b29021300de2238489a2 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c42f62b6bed8248fd99a48737c14054d09f973a7 commit c42f62b6bed8248fd99a48737c14054d09f973a7 Merge: 1925f8b 6ab467b Author: Brad King AuthorDate: Wed Feb 22 10:52:45 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 22 10:52:45 2017 -0500 Merge topic 'update-libarchive' into next 6ab467b0 Update CMake pre-cached values for libarchive 3.3.0 3f929807 libarchive: Fix use of ssize_t in archive_entry.h 0a409456 libarchive: Define __LA_DEPRECATED consistently a59a7ee9 Merge branch 'upstream-LibArchive' into update-libarchive c206211a LibArchive 2017-02-19 (100ee75a) cdce7c61 libarchive: Update script to get 3.3.0 https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6ab467b03702929b346cb1136092dd9417cc74fd commit 6ab467b03702929b346cb1136092dd9417cc74fd Author: Brad King AuthorDate: Mon Feb 20 09:10:11 2017 -0500 Commit: Brad King CommitDate: Mon Feb 20 09:10:14 2017 -0500 Update CMake pre-cached values for libarchive 3.3.0 diff --git a/CMakeLists.txt b/CMakeLists.txt index bec81a3..e613224 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -421,14 +421,15 @@ macro (CMAKE_BUILD_UTILITIES) if(NOT LIBLZMA_FOUND) message(FATAL_ERROR "CMAKE_USE_SYSTEM_LIBLZMA is ON but LibLZMA is not found!") endif() - set(LZMA_INCLUDE_DIR ${LIBLZMA_INCLUDE_DIRS}) - set(LZMA_LIBRARY ${LIBLZMA_LIBRARIES}) else() add_subdirectory(Utilities/cmliblzma) CMAKE_SET_TARGET_FOLDER(cmliblzma "Utilities/3rdParty") - set(LZMA_INCLUDE_DIR + set(LIBLZMA_HAS_AUTO_DECODER 1) + set(LIBLZMA_HAS_EASY_ENCODER 1) + set(LIBLZMA_HAS_LZMA_PRESET 1) + set(LIBLZMA_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Utilities/cmliblzma/liblzma/api") - set(LZMA_LIBRARY cmliblzma) + set(LIBLZMA_LIBRARY cmliblzma) endif() endif() @@ -449,13 +450,14 @@ macro (CMAKE_BUILD_UTILITIES) add_definitions(-DLIBARCHIVE_STATIC) set(ENABLE_NETTLE OFF CACHE INTERNAL "Enable use of Nettle") set(ENABLE_OPENSSL ${CMAKE_USE_OPENSSL} CACHE INTERNAL "Enable use of OpenSSL") - set(ENABLE_LZMA ON CACHE INTERNAL "Enable the use of the system found LZMA library if found") - set(ENABLE_ZLIB ON CACHE INTERNAL "Enable the use of the system found ZLIB library if found") - set(ENABLE_BZip2 ON CACHE INTERNAL "Enable the use of the system found BZip2 library if found") - set(ENABLE_LIBXML2 OFF CACHE INTERNAL "Enable the use of the system found libxml2 library if found") - set(ENABLE_EXPAT ON CACHE INTERNAL "Enable the use of the system found EXPAT library if found") - set(ENABLE_PCREPOSIX OFF CACHE INTERNAL "Enable the use of the system found PCREPOSIX library if found") - set(ENABLE_LibGCC OFF CACHE INTERNAL "Enable the use of the system found LibGCC library if found") + set(ENABLE_LZMA ON CACHE INTERNAL "Enable the use of the system LZMA library if found") + set(ENABLE_LZO OFF CACHE INTERNAL "Enable the use of the system LZO library if found") + set(ENABLE_ZLIB ON CACHE INTERNAL "Enable the use of the system ZLIB library if found") + set(ENABLE_BZip2 ON CACHE INTERNAL "Enable the use of the system BZip2 library if found") + set(ENABLE_LIBXML2 OFF CACHE INTERNAL "Enable the use of the system libxml2 library if found") + set(ENABLE_EXPAT ON CACHE INTERNAL "Enable the use of the system EXPAT library if found") + set(ENABLE_PCREPOSIX OFF CACHE INTERNAL "Enable the use of the system PCREPOSIX library if found") + set(ENABLE_LibGCC OFF CACHE INTERNAL "Enable the use of the system LibGCC library if found") set(ENABLE_XATTR OFF CACHE INTERNAL "Enable extended attribute support") set(ENABLE_ACL OFF CACHE INTERNAL "Enable ACL support") set(ENABLE_ICONV OFF CACHE INTERNAL "Enable iconv support") https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3f92980773c8f2106f0ee2986a89fa958fc73acf commit 3f92980773c8f2106f0ee2986a89fa958fc73acf Author: Brad King AuthorDate: Mon Feb 20 09:08:29 2017 -0500 Commit: Brad King CommitDate: Mon Feb 20 09:10:09 2017 -0500 libarchive: Fix use of ssize_t in archive_entry.h This type is not available on Windows compilers so for clients including this header we need to use `la_ssize_t` instead as we do in `archive.h`. diff --git a/Utilities/cmlibarchive/libarchive/archive_entry.h b/Utilities/cmlibarchive/libarchive/archive_entry.h index fe86ee3..c331117 100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry.h +++ b/Utilities/cmlibarchive/libarchive/archive_entry.h @@ -66,6 +66,27 @@ typedef int64_t la_int64_t; # endif #endif +/* The la_ssize_t should match the type used in 'struct stat' */ +#if !defined(__LA_SSIZE_T_DEFINED) +/* Older code relied on the __LA_SSIZE_T macro; after 4.0 we'll switch to the typedef exclusively. */ +# if ARCHIVE_VERSION_NUMBER < 4000000 +#define __LA_SSIZE_T la_ssize_t +# endif +#define __LA_SSIZE_T_DEFINED +# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__) +# if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_) +typedef ssize_t la_ssize_t; +# elif defined(_WIN64) +typedef __int64 la_ssize_t; +# else +typedef long la_ssize_t; +# endif +# else +# include /* ssize_t */ +typedef ssize_t la_ssize_t; +# endif +#endif + /* Get a suitable definition for mode_t */ #if ARCHIVE_VERSION_NUMBER >= 3999000 /* Switch to plain 'int' for libarchive 4.0. It's less broken than 'mode_t' */ @@ -523,9 +544,9 @@ __LA_DECL int archive_entry_acl_next_w(struct archive_entry *, int /* want_type #define ARCHIVE_ENTRY_ACL_STYLE_COMPACT 0x00000010 __LA_DECL wchar_t *archive_entry_acl_to_text_w(struct archive_entry *, - ssize_t * /* len */, int /* flags */); + la_ssize_t * /* len */, int /* flags */); __LA_DECL char *archive_entry_acl_to_text(struct archive_entry *, - ssize_t * /* len */, int /* flags */); + la_ssize_t * /* len */, int /* flags */); __LA_DECL int archive_entry_acl_from_text_w(struct archive_entry *, const wchar_t * /* wtext */, int /* type */); __LA_DECL int archive_entry_acl_from_text(struct archive_entry *, https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0a4094564dadfd15e0daa1e95927c343cfc616a2 commit 0a4094564dadfd15e0daa1e95927c343cfc616a2 Author: Brad King AuthorDate: Mon Feb 20 08:10:33 2017 -0500 Commit: Brad King CommitDate: Mon Feb 20 08:14:31 2017 -0500 libarchive: Define __LA_DEPRECATED consistently Upstream libarchive now defines this macro in two places with the same logic in both. However, CMake's bundled copy disables this macro, so we need to update the new location of its definition to be consistent. diff --git a/Utilities/cmlibarchive/libarchive/archive_entry.h b/Utilities/cmlibarchive/libarchive/archive_entry.h index 9427413..fe86ee3 100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry.h +++ b/Utilities/cmlibarchive/libarchive/archive_entry.h @@ -105,11 +105,8 @@ typedef int64_t la_int64_t; # define __LA_DECL #endif -#if defined(__GNUC__) && __GNUC__ >= 3 && __GNUC_MINOR__ >= 1 -# define __LA_DEPRECATED __attribute__((deprecated)) -#else -# define __LA_DEPRECATED -#endif +/* CMake uses some deprecated APIs to build with old libarchive versions. */ +#define __LA_DEPRECATED #ifdef __cplusplus extern "C" { https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a59a7ee95601f3496ec9ba9ae1283a8d980460bf commit a59a7ee95601f3496ec9ba9ae1283a8d980460bf Merge: cdce7c6 c206211 Author: Brad King AuthorDate: Mon Feb 20 08:04:00 2017 -0500 Commit: Brad King CommitDate: Mon Feb 20 08:04:00 2017 -0500 Merge branch 'upstream-LibArchive' into update-libarchive * upstream-LibArchive: LibArchive 2017-02-19 (100ee75a) diff --cc Utilities/cmlibarchive/CMakeLists.txt index 09bef51,0000000..56811b6 mode 100644,000000..100644 --- a/Utilities/cmlibarchive/CMakeLists.txt +++ b/Utilities/cmlibarchive/CMakeLists.txt @@@ -1,1407 -1,0 +1,1447 @@@ +PROJECT(libarchive C) +# +SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/build/cmake") +if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${libarchive_BINARY_DIR}/bin) +endif() + +# On MacOS, prefer MacPorts libraries to system libraries. +# I haven't come up with a compelling argument for this to be conditional. +list(APPEND CMAKE_PREFIX_PATH /opt/local) +# Enable @rpath in the install name. +# detail in "cmake --help-policy CMP0042" +SET(CMAKE_MACOSX_RPATH ON) + +# +# Version - read from 'version' file. +# +FILE(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/build/version _version) +STRING(REGEX REPLACE + "^([0-9])[0-9][0-9][0-9][0-9][0-9][0-9][a-z]?$" "\\1" _major ${_version}) +STRING(REGEX REPLACE + "^[0-9]([0-9][0-9][0-9])[0-9][0-9][0-9][a-z]?$" "\\1" _minor ${_version}) +STRING(REGEX REPLACE + "^[0-9][0-9][0-9][0-9]([0-9][0-9][0-9])[a-z]?$" "\\1" _revision ${_version}) +STRING(REGEX REPLACE + "^[0-9][0-9][0-9][0-9][0-9][0-9][0-9]([a-z]?)$" "\\1" _quality ${_version}) +SET(_version_number ${_major}${_minor}${_revision}) +STRING(REGEX REPLACE "[0]*([^0]*[0-9])$" "\\1" _trimmed_minor ${_minor}) +STRING(REGEX REPLACE "[0]*([^0]*[0-9])$" "\\1" _trimmed_revision ${_revision}) +# +SET(VERSION "${_major}.${_trimmed_minor}.${_trimmed_revision}${_quality}") +SET(BSDCPIO_VERSION_STRING "${VERSION}") +SET(BSDTAR_VERSION_STRING "${VERSION}") +SET(BSDCAT_VERSION_STRING "${VERSION}") +SET(LIBARCHIVE_VERSION_NUMBER "${_version_number}") +SET(LIBARCHIVE_VERSION_STRING "${VERSION}") + +# INTERFACE_VERSION increments with every release +# libarchive 2.7 == interface version 9 = 2 + 7 +# libarchive 2.8 == interface version 10 = 2 + 8 +# libarchive 2.9 == interface version 11 = 2 + 9 +# libarchive 3.0 == interface version 12 +# libarchive 3.1 == interface version 13 +math(EXPR INTERFACE_VERSION "13 + ${_minor}") + +# Set SOVERSION == Interface version +# ?? Should there be more here ?? +SET(SOVERSION "${INTERFACE_VERSION}") + +# Enalbe CMAKE_PUSH_CHECK_STATE() and CMAKE_POP_CHECK_STATE() macros +# saving and restoring the state of the variables. +INCLUDE(${CMake_SOURCE_DIR}/Modules/CMakePushCheckState.cmake) + +# Initialize the state of the variables. This initialization is not +# necessary but this shows you what value the variables initially have. +SET(CMAKE_REQUIRED_DEFINITIONS) +SET(CMAKE_REQUIRED_INCLUDES) +SET(CMAKE_REQUIRED_LIBRARIES) +SET(CMAKE_REQUIRED_FLAGS) + +# Disable warnings to avoid changing 3rd party code. +IF(CMAKE_C_COMPILER_ID MATCHES + "^(GNU|Clang|AppleClang|XL|VisualAge|SunPro|MIPSpro|HP|Intel)$") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w") +ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "PathScale") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall") +ENDIF() + +# Enable CTest/CDash support +include(CTest) + +OPTION(ENABLE_NETTLE "Enable use of Nettle" ON) +OPTION(ENABLE_OPENSSL "Enable use of OpenSSL" ON) - OPTION(ENABLE_LZMA "Enable the use of the system found LZMA library if found" ON) - OPTION(ENABLE_ZLIB "Enable the use of the system found ZLIB library if found" ON) - OPTION(ENABLE_BZip2 "Enable the use of the system found BZip2 library if found" ON) - OPTION(ENABLE_LIBXML2 "Enable the use of the system found libxml2 library if found" ON) - OPTION(ENABLE_EXPAT "Enable the use of the system found EXPAT library if found" ON) - OPTION(ENABLE_PCREPOSIX "Enable the use of the system found PCREPOSIX library if found" ON) - OPTION(ENABLE_LibGCC "Enable the use of the system found LibGCC library if found" ON) ++OPTION(ENABLE_LZO "Enable the use of the system LZO library if found" OFF) ++OPTION(ENABLE_LZMA "Enable the use of the system LZMA library if found" ON) ++ ++OPTION(ENABLE_ZLIB "Enable the use of the system ZLIB library if found" ON) ++OPTION(ENABLE_BZip2 "Enable the use of the system BZip2 library if found" ON) ++OPTION(ENABLE_LIBXML2 "Enable the use of the system libxml2 library if found" ON) ++OPTION(ENABLE_EXPAT "Enable the use of the system EXPAT library if found" ON) ++OPTION(ENABLE_PCREPOSIX "Enable the use of the system PCREPOSIX library if found" ON) ++OPTION(ENABLE_LibGCC "Enable the use of the system LibGCC library if found" ON) +# CNG is used for encrypt/decrypt Zip archives on Windows. +OPTION(ENABLE_CNG "Enable the use of CNG(Crypto Next Generation)" ON) + +OPTION(ENABLE_XATTR "Enable extended attribute support" ON) +OPTION(ENABLE_ACL "Enable ACL support" ON) +OPTION(ENABLE_ICONV "Enable iconv support" ON) + +IF(WIN32) + #ELSEIF(WINDOWS_VERSION STREQUAL "WINXP") + SET(NTDDI_VERSION 0x05010000) + SET(_WIN32_WINNT 0x0501) + SET(WINVER 0x0501) +ENDIF(WIN32) + +set(HAVE_PTHREAD_H 0) # no threads in CMake + +IF("${CMAKE_C_PLATFORM_ID}" MATCHES "^(HP-UX)$") + ADD_DEFINITIONS(-D_XOPEN_SOURCE=500) # Ask wchar.h for mbstate_t +ENDIF() + +# +INCLUDE(CheckCSourceCompiles) +INCLUDE(CheckCSourceRuns) +INCLUDE(CheckFileOffsetBits) +INCLUDE(CheckFuncs) +INCLUDE(CheckHeaderDirent) +INCLUDE(CheckIncludeFile) +INCLUDE(CheckIncludeFiles) +INCLUDE(CheckLibraryExists) - INCLUDE(CheckStructMember) ++INCLUDE(CheckStructHasMember) +INCLUDE(CheckSymbolExists) +INCLUDE(CheckTypeExists) +INCLUDE(CheckTypeSize) + +# +# Generate list.h +# +MACRO (GENERATE_LIST_H _listfile _cmlist __list_sources) + SET(_argv ${ARGV}) + # Remove _listfile and _cmlist from _argv + LIST(REMOVE_AT _argv 0 1) + IF (NOT EXISTS "${_listfile}" OR + ${_cmlist} IS_NEWER_THAN "${_listfile}") + + MESSAGE(STATUS "Generating ${_listfile}") + FILE(WRITE ${_listfile} "") + FOREACH (testfile ${_argv}) + IF (testfile MATCHES "^test_[^/]+[.]c$") + FILE(STRINGS ${testfile} testvar REGEX "^DEFINE_TEST") + FOREACH (deftest ${testvar}) + FILE(APPEND ${_listfile} "${deftest}\n") + ENDFOREACH (deftest) + ENDIF (testfile MATCHES "^test_[^/]+[.]c$") + ENDFOREACH (testfile) + + ENDIF (NOT EXISTS "${_listfile}" OR + ${_cmlist} IS_NEWER_THAN "${_listfile}") +ENDMACRO (GENERATE_LIST_H) +# +# Generate installation rules for man pages. +# +MACRO (INSTALL_MAN __mans) + FOREACH (_man ${ARGV}) + STRING(REGEX REPLACE "^.+[.]([1-9])" "\\1" _mansect ${_man}) + INSTALL(FILES ${_man} DESTINATION "share/man/man${_mansect}") + ENDFOREACH (_man) +ENDMACRO (INSTALL_MAN __mans) +# +# Find out what macro is needed to use libraries on Windows. +# +MACRO (TRY_MACRO_FOR_LIBRARY INCLUDES LIBRARIES + TRY_TYPE SAMPLE_SOURCE MACRO_LIST) + IF(WIN32 AND NOT CYGWIN) + CMAKE_PUSH_CHECK_STATE() # Save the state of the variables + SET(CMAKE_REQUIRED_INCLUDES ${INCLUDES}) + SET(CMAKE_REQUIRED_LIBRARIES ${LIBRARIES}) + FOREACH(VAR ${MACRO_LIST}) + # Clear ${VAR} from CACHE If the libraries which ${VAR} was + # checked with are changed. + SET(VAR_WITH_LIB "${VAR}_WITH_LIB") + GET_PROPERTY(PREV_VAR_WITH_LIB VARIABLE PROPERTY ${VAR_WITH_LIB}) + IF(NOT "${PREV_VAR_WITH_LIB}" STREQUAL "${LIBRARIES}") + UNSET(${VAR} CACHE) + ENDIF(NOT "${PREV_VAR_WITH_LIB}" STREQUAL "${LIBRARIES}") + # Check if the library can be used with the macro. + IF("${TRY_TYPE}" MATCHES "COMPILES") + CHECK_C_SOURCE_COMPILES("${SAMPLE_SOURCE}" ${VAR}) + ELSEIF("${TRY_TYPE}" MATCHES "RUNS") + CHECK_C_SOURCE_RUNS("${SAMPLE_SOURCE}" ${VAR}) + ELSE("${TRY_TYPE}" MATCHES "COMPILES") + MESSAGE(FATAL_ERROR "UNKNOWN KEYWORD \"${TRY_TYPE}\" FOR TRY_TYPE") + ENDIF("${TRY_TYPE}" MATCHES "COMPILES") + # Save the libraries which ${VAR} is checked with. + SET(${VAR_WITH_LIB} "${LIBRARIES}" CACHE INTERNAL + "Macro ${VAR} is checked with") + ENDFOREACH(VAR) + CMAKE_POP_CHECK_STATE() # Restore the state of the variables + ENDIF(WIN32 AND NOT CYGWIN) +ENDMACRO (TRY_MACRO_FOR_LIBRARY) +# +# Check compress/decompress libraries +# +IF(WIN32 AND NOT CMAKE_CL_64 AND NOT CYGWIN) + # GnuWin32 is only for Win32, not Win64. + SET(__GNUWIN32PATH "C:/Program Files/GnuWin32") +ENDIF(WIN32 AND NOT CMAKE_CL_64 AND NOT CYGWIN) +IF(DEFINED __GNUWIN32PATH AND EXISTS "${__GNUWIN32PATH}") + # You have to add a path availabel DLL file into PATH environment variable. + # Maybe DLL path is "C:/Program Files/GnuWin32/bin". + # The zlib and the bzip2 Setup program have installed programs and DLLs into + # "C:/Program Files/GnuWin32" by default. + # This is convenience setting for Windows. + SET(CMAKE_PREFIX_PATH ${__GNUWIN32PATH} $(CMAKE_PREFIX_PATH)) + # + # If you didn't use Setup program or installed into nonstandard path, + # cmake cannot find out your zlib or bzip2 libraries and include files, + # you should execute cmake with -DCMAKE_PREFIX_PATH option. + # e.g. + # cmake -DCMAKE_PREFIX_PATH= + # + # If compiling error occurred in zconf.h, You may need patch to zconf.h. + #--- zconf.h.orig 2005-07-21 00:40:26.000000000 + #+++ zconf.h 2009-01-19 11:39:10.093750000 + #@@ -286,7 +286,7 @@ + # + # #if 1 /* HAVE_UNISTD_H -- this line is updated by ./configure */ + # # include /* for off_t */ + #-# include /* for SEEK_* and off_t */ + #+# include /* for SEEK_* and off_t */ + # # ifdef VMS + # # include /* for off_t */ + # # endif +ENDIF(DEFINED __GNUWIN32PATH AND EXISTS "${__GNUWIN32PATH}") + +SET(ADDITIONAL_LIBS "") +# +# Find ZLIB +# +IF(ENABLE_ZLIB) + FIND_PACKAGE(ZLIB) +ELSE() + SET(ZLIB_FOUND FALSE) # Override cached value +ENDIF() +IF(ZLIB_FOUND) + SET(HAVE_LIBZ 1) + SET(HAVE_ZLIB_H 1) + INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR}) + LIST(APPEND ADDITIONAL_LIBS ${ZLIB_LIBRARIES}) + IF(WIN32 AND NOT CYGWIN) + # + # Test if ZLIB_WINAPI macro is needed to use. + # + TRY_MACRO_FOR_LIBRARY( + "${ZLIB_INCLUDE_DIR}" "${ZLIB_LIBRARIES}" + RUNS + "#include \nint main() {uLong f = zlibCompileFlags(); return (f&(1U<<10))?0:-1; }" + ZLIB_WINAPI) + IF(ZLIB_WINAPI) + ADD_DEFINITIONS(-DZLIB_WINAPI) + ELSE(ZLIB_WINAPI) + # Test if a macro is needed for the library. + TRY_MACRO_FOR_LIBRARY( + "${ZLIB_INCLUDE_DIR}" "${ZLIB_LIBRARIES}" + COMPILES + "#include \nint main() {return zlibVersion()?1:0; }" + "ZLIB_DLL;WITHOUT_ZLIB_DLL") + IF(ZLIB_DLL) + ADD_DEFINITIONS(-DZLIB_DLL) + ENDIF(ZLIB_DLL) + ENDIF(ZLIB_WINAPI) + ENDIF(WIN32 AND NOT CYGWIN) +ELSE(ZLIB_FOUND) + MESSAGE(FATAL_ERROR "CMake requires zlib to be available to libarchive") +ENDIF(ZLIB_FOUND) +# +# Find BZip2 +# +IF(ENABLE_BZip2) + FIND_PACKAGE(BZip2) +ELSE() + SET(BZIP2_FOUND FALSE) # Override cached value +ENDIF() +IF(BZIP2_FOUND) + SET(HAVE_LIBBZ2 1) + SET(HAVE_BZLIB_H 1) + INCLUDE_DIRECTORIES(${BZIP2_INCLUDE_DIR}) + LIST(APPEND ADDITIONAL_LIBS ${BZIP2_LIBRARIES}) + # Test if a macro is needed for the library. + TRY_MACRO_FOR_LIBRARY( + "${BZIP2_INCLUDE_DIR}" "${BZIP2_LIBRARIES}" + COMPILES + "#include \nint main() {return BZ2_bzlibVersion()?1:0; }" + "USE_BZIP2_DLL;USE_BZIP2_STATIC") + IF(USE_BZIP2_DLL) + ADD_DEFINITIONS(-DUSE_BZIP2_DLL) + ELSEIF(USE_BZIP2_STATIC) + ADD_DEFINITIONS(-DUSE_BZIP2_STATIC) + ENDIF(USE_BZIP2_DLL) +ENDIF(BZIP2_FOUND) +MARK_AS_ADVANCED(CLEAR BZIP2_INCLUDE_DIR) +MARK_AS_ADVANCED(CLEAR BZIP2_LIBRARIES) + + +# +# Find LZMA +# +IF(ENABLE_LZMA) - FIND_PACKAGE(LZMA) ++ FIND_PACKAGE(LibLZMA) +ELSE() - SET(LZMA_FOUND FALSE) # Override cached value - SET(LZMADEC_FOUND FALSE) # Override cached value ++ SET(LIBZMA_FOUND FALSE) # Override cached value +ENDIF() + - IF(LZMA_FOUND) ++IF(LIBLZMA_FOUND) + SET(HAVE_LIBLZMA 1) + SET(HAVE_LZMA_H 1) - INCLUDE_DIRECTORIES(${LZMA_INCLUDE_DIR}) - LIST(APPEND ADDITIONAL_LIBS ${LZMA_LIBRARIES}) ++ INCLUDE_DIRECTORIES(${LIBLZMA_INCLUDE_DIRS}) ++ LIST(APPEND ADDITIONAL_LIBS ${LIBLZMA_LIBRARIES}) + IF(CMAKE_USE_SYSTEM_LIBLZMA) + # Test if a macro is needed for the library. + TRY_MACRO_FOR_LIBRARY( - "${LZMA_INCLUDE_DIR}" "${LZMA_LIBRARIES}" ++ "${LIBLZMA_INCLUDE_DIRS}" "${LIBLZMA_LIBRARIES}" + COMPILES + "#include \nint main() {return (int)lzma_version_number(); }" + "WITHOUT_LZMA_API_STATIC;LZMA_API_STATIC") + IF(NOT WITHOUT_LZMA_API_STATIC AND LZMA_API_STATIC) + ADD_DEFINITIONS(-DLZMA_API_STATIC) + ENDIF(NOT WITHOUT_LZMA_API_STATIC AND LZMA_API_STATIC) + ELSE() + ADD_DEFINITIONS(-DLZMA_API_STATIC) + ENDIF() - ELSEIF(LZMADEC_FOUND) - SET(HAVE_LIBLZMADEC 1) - SET(HAVE_LZMADEC_H 1) - INCLUDE_DIRECTORIES(${LZMADEC_INCLUDE_DIR}) - LIST(APPEND ADDITIONAL_LIBS ${LZMADEC_LIBRARIES}) - ELSE(LZMA_FOUND) ++ELSE(LIBLZMA_FOUND) +# LZMA not found and will not be used. - ENDIF(LZMA_FOUND) ++ENDIF(LIBLZMA_FOUND) +IF(0) # CMake does not need LZO2 support in libarchive +# +# Find LZO2 +# - IF (LZO2_INCLUDE_DIR) - # Already in cache, be silent - SET(LZO2_FIND_QUIETLY TRUE) - ENDIF (LZO2_INCLUDE_DIR) - - FIND_PATH(LZO2_INCLUDE_DIR lzo/lzoconf.h) - FIND_LIBRARY(LZO2_LIBRARY NAMES lzo2 liblzo2) - INCLUDE(FindPackageHandleStandardArgs) - FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZO2 DEFAULT_MSG LZO2_LIBRARY LZO2_INCLUDE_DIR) ++IF(ENABLE_LZO) ++ IF (LZO2_INCLUDE_DIR) ++ # Already in cache, be silent ++ SET(LZO2_FIND_QUIETLY TRUE) ++ ENDIF (LZO2_INCLUDE_DIR) ++ ++ FIND_PATH(LZO2_INCLUDE_DIR lzo/lzoconf.h) ++ FIND_LIBRARY(LZO2_LIBRARY NAMES lzo2 liblzo2) ++ INCLUDE(FindPackageHandleStandardArgs) ++ FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZO2 DEFAULT_MSG LZO2_LIBRARY LZO2_INCLUDE_DIR) ++ELSE(ENABLE_LZO) ++ SET(LIBZMA_FOUND FALSE) # Override cached value ++ENDIF(ENABLE_LZO) +IF(LZO2_FOUND) + SET(HAVE_LIBLZO2 1) + SET(HAVE_LZO_LZOCONF_H 1) + SET(HAVE_LZO_LZO1X_H 1) + INCLUDE_DIRECTORIES(${LZO2_INCLUDE_DIR}) + LIST(APPEND ADDITIONAL_LIBS ${LZO2_LIBRARY}) + # + # TODO: test for static library. + # +ENDIF(LZO2_FOUND) +MARK_AS_ADVANCED(CLEAR LZO2_INCLUDE_DIR) +MARK_AS_ADVANCED(CLEAR LZO2_LIBRARY) +ENDIF() +IF(0) # CMake does not need LZ4 support in libarchive +# +# Find LZ4 +# +IF (LZ4_INCLUDE_DIR) + # Already in cache, be silent + SET(LZ4_FIND_QUIETLY TRUE) +ENDIF (LZ4_INCLUDE_DIR) + +FIND_PATH(LZ4_INCLUDE_DIR lz4.h) +FIND_LIBRARY(LZ4_LIBRARY NAMES lz4 liblz4) +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZ4 DEFAULT_MSG LZ4_LIBRARY LZ4_INCLUDE_DIR) +IF(LZ4_FOUND) + SET(HAVE_LIBLZ4 1) + SET(HAVE_LZ4_H 1) + CMAKE_PUSH_CHECK_STATE() # Save the state of the variables + SET(CMAKE_REQUIRED_INCLUDES ${LZ4_INCLUDE_DIR}) + CHECK_INCLUDE_FILES("lz4hc.h" HAVE_LZ4HC_H) + CMAKE_POP_CHECK_STATE() # Restore the state of the variables + INCLUDE_DIRECTORIES(${LZ4_INCLUDE_DIR}) + LIST(APPEND ADDITIONAL_LIBS ${LZ4_LIBRARY}) + # + # TODO: test for static library. + # +ENDIF(LZ4_FOUND) +MARK_AS_ADVANCED(CLEAR LZ4_INCLUDE_DIR) +MARK_AS_ADVANCED(CLEAR LZ4_LIBRARY) +ENDIF() + +# +# Check headers +# +CHECK_HEADER_DIRENT() + +SET(INCLUDES "") +MACRO (LA_CHECK_INCLUDE_FILE header var) + CHECK_INCLUDE_FILES("${INCLUDES};${header}" ${var}) + IF (${var}) + SET(INCLUDES ${INCLUDES} ${header}) + ENDIF (${var}) +ENDMACRO (LA_CHECK_INCLUDE_FILE) + +# Some FreeBSD headers assume sys/types.h was already included. +LA_CHECK_INCLUDE_FILE("sys/types.h" HAVE_SYS_TYPES_H) + +# Alphabetize the rest unless there's a compelling reason +IF(ENABLE_ACL) + LA_CHECK_INCLUDE_FILE("acl/libacl.h" HAVE_ACL_LIBACL_H) +ELSE(ENABLE_ACL) + SET(HAVE_ACL_LIBACL_H FALSE) +ENDIF(ENABLE_ACL) +LA_CHECK_INCLUDE_FILE("ctype.h" HAVE_CTYPE_H) +LA_CHECK_INCLUDE_FILE("copyfile.h" HAVE_COPYFILE_H) +LA_CHECK_INCLUDE_FILE("direct.h" HAVE_DIRECT_H) +LA_CHECK_INCLUDE_FILE("dlfcn.h" HAVE_DLFCN_H) +LA_CHECK_INCLUDE_FILE("errno.h" HAVE_ERRNO_H) +LA_CHECK_INCLUDE_FILE("ext2fs/ext2_fs.h" HAVE_EXT2FS_EXT2_FS_H) + +CHECK_C_SOURCE_COMPILES("#include +#include +int main(void) { return EXT2_IOC_GETFLAGS; }" HAVE_WORKING_EXT2_IOC_GETFLAGS) + +LA_CHECK_INCLUDE_FILE("fcntl.h" HAVE_FCNTL_H) +LA_CHECK_INCLUDE_FILE("grp.h" HAVE_GRP_H) +LA_CHECK_INCLUDE_FILE("inttypes.h" HAVE_INTTYPES_H) +LA_CHECK_INCLUDE_FILE("io.h" HAVE_IO_H) +LA_CHECK_INCLUDE_FILE("langinfo.h" HAVE_LANGINFO_H) +LA_CHECK_INCLUDE_FILE("limits.h" HAVE_LIMITS_H) +LA_CHECK_INCLUDE_FILE("linux/types.h" HAVE_LINUX_TYPES_H) +LA_CHECK_INCLUDE_FILE("linux/fiemap.h" HAVE_LINUX_FIEMAP_H) +LA_CHECK_INCLUDE_FILE("linux/fs.h" HAVE_LINUX_FS_H) +LA_CHECK_INCLUDE_FILE("linux/magic.h" HAVE_LINUX_MAGIC_H) +LA_CHECK_INCLUDE_FILE("locale.h" HAVE_LOCALE_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) +LA_CHECK_INCLUDE_FILE("process.h" HAVE_PROCESS_H) +LA_CHECK_INCLUDE_FILE("pthread.h" HAVE_PTHREAD_H) +LA_CHECK_INCLUDE_FILE("pwd.h" HAVE_PWD_H) +LA_CHECK_INCLUDE_FILE("readpassphrase.h" HAVE_READPASSPHRASE_H) +LA_CHECK_INCLUDE_FILE("regex.h" HAVE_REGEX_H) +LA_CHECK_INCLUDE_FILE("signal.h" HAVE_SIGNAL_H) +LA_CHECK_INCLUDE_FILE("spawn.h" HAVE_SPAWN_H) +LA_CHECK_INCLUDE_FILE("stdarg.h" HAVE_STDARG_H) +LA_CHECK_INCLUDE_FILE("stdint.h" HAVE_STDINT_H) +LA_CHECK_INCLUDE_FILE("stdlib.h" HAVE_STDLIB_H) +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/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/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) +LA_CHECK_INCLUDE_FILE("sys/statvfs.h" HAVE_SYS_STATVFS_H) +LA_CHECK_INCLUDE_FILE("sys/time.h" HAVE_SYS_TIME_H) +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("time.h" HAVE_TIME_H) +LA_CHECK_INCLUDE_FILE("unistd.h" HAVE_UNISTD_H) +LA_CHECK_INCLUDE_FILE("utime.h" HAVE_UTIME_H) +LA_CHECK_INCLUDE_FILE("wchar.h" HAVE_WCHAR_H) +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) +ELSE(ENABLE_CNG) + UNSET(HAVE_BCRYPT_H CACHE) +ENDIF(ENABLE_CNG) - # Following files need windwos.h, so we should test it after windows.h test. ++# Following files need windows.h, so we should test it after windows.h test. +LA_CHECK_INCLUDE_FILE("wincrypt.h" HAVE_WINCRYPT_H) +LA_CHECK_INCLUDE_FILE("winioctl.h" HAVE_WINIOCTL_H) + +# +# Check whether use of __EXTENSIONS__ is safe. +# We need some macro such as _GNU_SOURCE to use extension functions. +# +SET(_INCLUDE_FILES) +FOREACH (it ${_HEADER}) + SET(_INCLUDE_FILES "${_INCLUDE_FILES}#include <${it}>\n") +ENDFOREACH (it) + +CHECK_C_SOURCE_COMPILES( + "#define __EXTENSIONS__ 1 + ${_INCLUDE_FILES} + int main() { return 0;}" + SAFE_TO_DEFINE_EXTENSIONS) + +# +# Find Nettle +# +IF(ENABLE_NETTLE) + FIND_PACKAGE(Nettle) + IF(NETTLE_FOUND) + SET(HAVE_LIBNETTLE 1) + LIST(APPEND ADDITIONAL_LIBS ${NETTLE_LIBRARIES}) + INCLUDE_DIRECTORIES(${NETTLE_INCLUDE_DIR}) + + LIST(APPEND CMAKE_REQUIRED_INCLUDES ${NETTLE_INCLUDE_DIR}) + LA_CHECK_INCLUDE_FILE("nettle/aes.h" HAVE_NETTLE_AES_H) + LA_CHECK_INCLUDE_FILE("nettle/hmac.h" HAVE_NETTLE_HMAC_H) + LA_CHECK_INCLUDE_FILE("nettle/md5.h" HAVE_NETTLE_MD5_H) + LA_CHECK_INCLUDE_FILE("nettle/pbkdf2.h" HAVE_NETTLE_PBKDF2_H) + LA_CHECK_INCLUDE_FILE("nettle/ripemd160.h" HAVE_NETTLE_RIPEMD160_H) + LA_CHECK_INCLUDE_FILE("nettle/sha.h" HAVE_NETTLE_SHA_H) + + ENDIF(NETTLE_FOUND) + MARK_AS_ADVANCED(CLEAR NETTLE_INCLUDE_DIR) + MARK_AS_ADVANCED(CLEAR NETTLE_LIBRARIES) +ENDIF(ENABLE_NETTLE) + +# +# Find OpenSSL +# (Except on Mac, where OpenSSL is deprecated.) +# +IF(ENABLE_OPENSSL AND NOT CMAKE_SYSTEM_NAME MATCHES "Darwin") + FIND_PACKAGE(OpenSSL) + IF(OPENSSL_FOUND) + SET(HAVE_LIBCRYPTO 1) + INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR}) + ENDIF(OPENSSL_FOUND) +ELSE() + SET(OPENSSL_FOUND FALSE) # Override cached value +ENDIF() + +# FreeBSD libmd +IF(NOT OPENSSL_FOUND) + CHECK_LIBRARY_EXISTS(md "MD5Init" "" LIBMD_FOUND) + IF(LIBMD_FOUND) + CMAKE_PUSH_CHECK_STATE() # Save the state of the variables + SET(CMAKE_REQUIRED_LIBRARIES "md") + FIND_LIBRARY(LIBMD_LIBRARY NAMES md) + LIST(APPEND ADDITIONAL_LIBS ${LIBMD_LIBRARY}) + CMAKE_POP_CHECK_STATE() # Restore the state of the variables + ENDIF(LIBMD_FOUND) +ENDIF(NOT OPENSSL_FOUND) + +# +# How to prove that CRYPTO functions, which have several names on various +# platforms, just see if archive_digest.c can compile and link against +# required libraries. +# +MACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION) + FOREACH(ALGORITHM ${ALGORITHMS}) + IF(NOT ARCHIVE_CRYPTO_${ALGORITHM}) + STRING(TOLOWER "${ALGORITHM}" lower_algorithm) + STRING(TOUPPER "${ALGORITHM}" algorithm) + IF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND NOT OPENSSL_FOUND) + SET(ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} FALSE) + ELSEIF("${IMPLEMENTATION}" MATCHES "^NETTLE$" AND NOT NETTLE_FOUND) + SET(ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} FALSE) + ENDIF("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND NOT OPENSSL_FOUND) + + IF(NOT DEFINED ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}) + # Probe the local implementation for whether this + # crypto implementation is available on this platform. + SET(TRY_CRYPTO_REQUIRED_INCLUDES + "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}/libarchive;${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp") + SET(TRY_CRYPTO_REQUIRED_LIBS) + IF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND) + SET(TRY_CRYPTO_REQUIRED_INCLUDES + "${TRY_CRYPTO_REQUIRED_INCLUDES};${OPENSSL_INCLUDE_DIR}") + SET(TRY_CRYPTO_REQUIRED_LIBS + "-DLINK_LIBRARIES:STRING=${OPENSSL_LIBRARIES}") + ELSEIF("${IMPLEMENTATION}" MATCHES "^NETTLE$" AND NETTLE_FOUND) + SET(TRY_CRYPTO_REQUIRED_INCLUDES + "${TRY_CRYPTO_REQUIRED_INCLUDES};${NETTLE_INCLUDE_DIR}") + SET(TRY_CRYPTO_REQUIRED_LIBS + "-DLINK_LIBRARIES:STRING=${NETTLE_LIBRARY}") + ELSEIF("${IMPLEMENTATION}" MATCHES "^LIBMD$" AND LIBMD_FOUND) + SET(TRY_CRYPTO_REQUIRED_LIBS + "-DLINK_LIBRARIES:STRING=${LIBMD_LIBRARY}") + ENDIF("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND) + + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.h.in + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h) + FILE(READ "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h" + CONFDEFS_H) + FILE(READ "${CMAKE_CURRENT_SOURCE_DIR}/libarchive/archive_digest.c" + ARCHIVE_CRYPTO_C) + + SET(SOURCE "${CONFDEFS_H} + +#define ARCHIVE_${algorithm}_COMPILE_TEST +#define ARCHIVE_CRYPTO_${algorithm}_${IMPLEMENTATION} +#define PLATFORM_CONFIG_H \"check_crypto_md.h\" + +${ARCHIVE_CRYPTO_C} + +int +main(int argc, char **argv) +{ + archive_${lower_algorithm}_ctx ctx; + archive_${lower_algorithm}_init(&ctx); + archive_${lower_algorithm}_update(&ctx, *argv, argc); + archive_${lower_algorithm}_final(&ctx, NULL); + return 0; +} +") + + FILE(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_md.h" "") + FILE(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_md.c" "${SOURCE}") + MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}") + + TRY_COMPILE(ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} + ${CMAKE_BINARY_DIR} + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_md.c + CMAKE_FLAGS + "${TRY_CRYPTO_REQUIRED_LIBS}" + "${TRY_CRYPTO_REQUIRED_INCLUDES}" + OUTPUT_VARIABLE OUTPUT) + + # Inform user whether or not we found it; if not, log why we didn't. + IF (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}) + MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} -- found") + SET(ARCHIVE_CRYPTO_${ALGORITHM} 1) + ELSE (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}) + MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} -- not found") + FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Checking support for ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} failed with the following output:\n" + "${OUTPUT}\n" + "Source file was:\n${SOURCE}\n") + ENDIF (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}) + ENDIF(NOT DEFINED ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}) + + # Add appropriate libs/includes depending on whether the implementation + # was found on this platform. + IF (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}) + IF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND) + INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR}) + LIST(APPEND ADDITIONAL_LIBS ${OPENSSL_LIBRARIES}) + LIST(REMOVE_DUPLICATES ADDITIONAL_LIBS) + ENDIF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND) + ENDIF (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}) + ENDIF(NOT ARCHIVE_CRYPTO_${ALGORITHM}) + ENDFOREACH(ALGORITHM ${ALGORITHMS}) +ENDMACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION) + +# +# CRYPTO functions on Windows is defined at archive_windows.c, thus we do not +# need the test what the functions can be mapped to archive_{crypto name}_init, +# archive_{crypto name}_update and archive_{crypto name}_final. +# The functions on Windows use CALG_{crypto name} macro to create a crypt object +# and then we need to know what CALG_{crypto name} macros is available to show +# ARCHIVE_CRYPTO_{crypto name}_WIN macros because Windows 2000 and earlier version +# of Windows XP do not support SHA256, SHA384 and SHA512. +# +MACRO(CHECK_CRYPTO_WIN CRYPTO_LIST) + IF(WIN32 AND NOT CYGWIN) + FOREACH(CRYPTO ${CRYPTO_LIST}) + IF(NOT ARCHIVE_CRYPTO_${CRYPTO}) + IF(NOT DEFINED ARCHIVE_CRYPTO_${CRYPTO}_WIN) + STRING(TOUPPER "${CRYPTO}" crypto) + SET(ALGID "") + IF ("${CRYPTO}" MATCHES "^MD5$") + SET(ALGID "CALG_MD5") + ENDIF ("${CRYPTO}" MATCHES "^MD5$") + IF ("${CRYPTO}" MATCHES "^SHA1$") + SET(ALGID "CALG_SHA1") + ENDIF ("${CRYPTO}" MATCHES "^SHA1$") + IF ("${CRYPTO}" MATCHES "^SHA256$") + SET(ALGID "CALG_SHA_256") + ENDIF ("${CRYPTO}" MATCHES "^SHA256$") + IF ("${CRYPTO}" MATCHES "^SHA384$") + SET(ALGID "CALG_SHA_384") + ENDIF ("${CRYPTO}" MATCHES "^SHA384$") + IF ("${CRYPTO}" MATCHES "^SHA512$") + SET(ALGID "CALG_SHA_512") + ENDIF ("${CRYPTO}" MATCHES "^SHA512$") + + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.h.in + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h) + FILE(READ "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h" + CONFDEFS_H) + + SET(SOURCE "${CONFDEFS_H} + +#define ${crypto}_COMPILE_TEST +#include +#include + +int +main(int argc, char **argv) +{ + return ${ALGID}; +} +") + SET(SOURCE_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_win.c") + + FILE(WRITE "${SOURCE_FILE}" "${SOURCE}") + MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN") + + TRY_COMPILE(ARCHIVE_CRYPTO_${CRYPTO}_WIN + ${CMAKE_BINARY_DIR} + ${SOURCE_FILE} + CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}/libarchive" + OUTPUT_VARIABLE OUTPUT) + + IF (ARCHIVE_CRYPTO_${CRYPTO}_WIN) + MESSAGE(STATUS + "Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN -- found") + SET(ARCHIVE_CRYPTO_${CRYPTO} 1) + ELSE (ARCHIVE_CRYPTO_${CRYPTO}_WIN) + MESSAGE(STATUS + "Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN -- not found") + FILE(APPEND + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN failed with the following output:\n" + "${OUTPUT}\n" + "Source file was:\n${SOURCE}\n") + ENDIF (ARCHIVE_CRYPTO_${CRYPTO}_WIN) + + ENDIF(NOT DEFINED ARCHIVE_CRYPTO_${CRYPTO}_WIN) + ENDIF(NOT ARCHIVE_CRYPTO_${CRYPTO}) + ENDFOREACH(CRYPTO) + ENDIF(WIN32 AND NOT CYGWIN) +ENDMACRO(CHECK_CRYPTO_WIN CRYPTO_LIST) + +# +# Find iconv +# POSIX defines the second arg as const char ** +# and requires it to be in libc. But we can accept +# a non-const argument here and can support iconv() +# being in libiconv. +# +MACRO(CHECK_ICONV LIB TRY_ICONV_CONST) + IF(NOT HAVE_ICONV) + CMAKE_PUSH_CHECK_STATE() # Save the state of the variables + IF (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR + CMAKE_C_COMPILER_ID STREQUAL "Clang") + # + # During checking iconv proto type, we should use -Werror to avoid the + # success of iconv detection with a warnig which success is a miss + # detection. So this needs for all build mode(even it's a release mode). + # + SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror") + ENDIF () + IF (CMAKE_C_COMPILER_ID STREQUAL "XL") + SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -qhalt=w -qflag=w:w") + ENDIF () + IF (MSVC) + # NOTE: /WX option is the same as gcc's -Werror option. + SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} /WX") + ENDIF (MSVC) + # + CHECK_C_SOURCE_COMPILES( + "#include + #include + int main() { + ${TRY_ICONV_CONST} char *ccp; + iconv_t cd = iconv_open(\"\", \"\"); + iconv(cd, &ccp, (size_t *)0, (char **)0, (size_t *)0); + iconv_close(cd); + return 0; + }" + HAVE_ICONV_${LIB}_${TRY_ICONV_CONST}) + IF(HAVE_ICONV_${LIB}_${TRY_ICONV_CONST}) + SET(HAVE_ICONV true) + SET(ICONV_CONST ${TRY_ICONV_CONST}) + ENDIF(HAVE_ICONV_${LIB}_${TRY_ICONV_CONST}) + CMAKE_POP_CHECK_STATE() # Restore the state of the variables + ENDIF(NOT HAVE_ICONV) +ENDMACRO(CHECK_ICONV TRY_ICONV_CONST) + +IF(ENABLE_ICONV) + CMAKE_PUSH_CHECK_STATE() # Save the state of the variables + FIND_PATH(ICONV_INCLUDE_DIR iconv.h) + MARK_AS_ADVANCED(ICONV_INCLUDE_DIR) + IF(ICONV_INCLUDE_DIR) + #SET(INCLUDES ${INCLUDES} "iconv.h") + SET(HAVE_ICONV_H 1) + INCLUDE_DIRECTORIES(${ICONV_INCLUDE_DIR}) + SET(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR}) + CHECK_ICONV("libc" "const") + CHECK_ICONV("libc" "") + + # If iconv isn't in libc and we have a libiconv, try that. + FIND_LIBRARY(LIBICONV_PATH NAMES iconv libiconv) + IF(NOT HAVE_ICONV AND LIBICONV_PATH) + LIST(APPEND CMAKE_REQUIRED_LIBRARIES ${LIBICONV_PATH}) + # Test if a macro is needed for the library. + TRY_MACRO_FOR_LIBRARY( + "${ICONV_INCLUDE_DIR}" "${LIBICONV_PATH}" + COMPILES + "#include \nint main() {return iconv_close((iconv_t)0);}" + "WITHOUT_LIBICONV_STATIC;LIBICONV_STATIC") + IF(NOT WITHOUT_LIBICONV_STATIC AND LIBICONV_STATIC) + ADD_DEFINITIONS(-DLIBICONV_STATIC) + ENDIF(NOT WITHOUT_LIBICONV_STATIC AND LIBICONV_STATIC) + # + # Set up CMAKE_REQUIRED_* for CHECK_ICONV + # + SET(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR}) + SET(CMAKE_REQUIRED_LIBRARIES ${LIBICONV_PATH}) + IF(LIBICONV_STATIC) + # LIBICONV_STATIC is necessary for the success of CHECK_ICONV + # on Windows. + SET(CMAKE_REQUIRED_DEFINITIONS "-DLIBICONV_STATIC") + ELSE(LIBICONV_STATIC) + SET(CMAKE_REQUIRED_DEFINITIONS) + ENDIF(LIBICONV_STATIC) + CHECK_ICONV("libiconv" "const") + CHECK_ICONV("libiconv" "") + IF (HAVE_ICONV) + LIST(APPEND ADDITIONAL_LIBS ${LIBICONV_PATH}) + ENDIF(HAVE_ICONV) + ENDIF(NOT HAVE_ICONV AND LIBICONV_PATH) + ENDIF(ICONV_INCLUDE_DIR) + # + # Find locale_charset() for libiconv. + # + IF(LIBICONV_PATH) + SET(CMAKE_REQUIRED_DEFINITIONS) + SET(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR}) + SET(CMAKE_REQUIRED_LIBRARIES) + CHECK_INCLUDE_FILES("localcharset.h" HAVE_LOCALCHARSET_H) + FIND_LIBRARY(LIBCHARSET_PATH NAMES charset libcharset) + IF(LIBCHARSET_PATH) + SET(CMAKE_REQUIRED_LIBRARIES ${LIBCHARSET_PATH}) + IF(WIN32 AND NOT CYGWIN) + # Test if a macro is needed for the library. + TRY_MACRO_FOR_LIBRARY( + "${ICONV_INCLUDE_DIR}" "${LIBCHARSET_PATH}" + COMPILES + "#include \nint main() {return locale_charset()?1:0;}" + "WITHOUT_LIBCHARSET_STATIC;LIBCHARSET_STATIC") + IF(NOT WITHOUT_LIBCHARSET_STATIC AND LIBCHARSET_STATIC) + ADD_DEFINITIONS(-DLIBCHARSET_STATIC) + ENDIF(NOT WITHOUT_LIBCHARSET_STATIC AND LIBCHARSET_STATIC) + IF(WITHOUT_LIBCHARSET_STATIC OR LIBCHARSET_STATIC) + SET(HAVE_LOCALE_CHARSET ON CACHE INTERNAL + "Have function locale_charset") + ENDIF(WITHOUT_LIBCHARSET_STATIC OR LIBCHARSET_STATIC) + ELSE(WIN32 AND NOT CYGWIN) + CHECK_FUNCTION_EXISTS_GLIBC(locale_charset HAVE_LOCALE_CHARSET) + ENDIF(WIN32 AND NOT CYGWIN) + IF(HAVE_LOCALE_CHARSET) + LIST(APPEND ADDITIONAL_LIBS ${LIBCHARSET_PATH}) + ENDIF(HAVE_LOCALE_CHARSET) + ENDIF(LIBCHARSET_PATH) + ENDIF(LIBICONV_PATH) + CMAKE_POP_CHECK_STATE() # Restore the state of the variables +ELSE(ENABLE_ICONV) + # Make sure ICONV variables are not in CACHE after ENABLE_ICONV disabled + # (once enabled). + UNSET(HAVE_LOCALE_CHARSET CACHE) + UNSET(HAVE_ICONV CACHE) + UNSET(HAVE_ICONV_libc_ CACHE) + UNSET(HAVE_ICONV_libc_const CACHE) + UNSET(HAVE_ICONV_libiconv_ CACHE) + UNSET(HAVE_ICONV_libiconv_const CACHE) + UNSET(ICONV_INCLUDE_DIR CACHE) + UNSET(LIBICONV_PATH CACHE) + UNSET(LIBICONV_DLL CACHE) + UNSET(LIBICONV_STATIC CACHE) + UNSET(LIBCHARSET_DLL CACHE) + UNSET(LIBCHARSET_STATIC CACHE) +ENDIF(ENABLE_ICONV) + +IF(0) # CMake does not need XML support in libarchive +# +# Find Libxml2 +# +IF(ENABLE_LIBXML2) + FIND_PACKAGE(LibXml2) +ELSE() + SET(LIBXML2_FOUND FALSE) +ENDIF() +IF(LIBXML2_FOUND) + CMAKE_PUSH_CHECK_STATE() # Save the state of the variables + INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR}) + LIST(APPEND ADDITIONAL_LIBS ${LIBXML2_LIBRARIES}) + SET(HAVE_LIBXML2 1) + # libxml2's include files use iconv.h + SET(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR}) + CHECK_INCLUDE_FILES("libxml/xmlreader.h" HAVE_LIBXML_XMLREADER_H) + CHECK_INCLUDE_FILES("libxml/xmlwriter.h" HAVE_LIBXML_XMLWRITER_H) + # Test if a macro is needed for the library. + TRY_MACRO_FOR_LIBRARY( + "${ICONV_INCLUDE_DIR};${LIBXML2_INCLUDE_DIR}" + "ws2_32.lib;${ZLIB_LIBRARIES};${LIBICONV_PATH};${LIBXML2_LIBRARIES}" + COMPILES + "#include \n#include \nint main() {return xmlTextReaderRead((xmlTextReaderPtr)(void *)0);}" + "WITHOUT_LIBXML_STATIC;LIBXML_STATIC") + IF(NOT WITHOUT_LIBXML_STATIC AND LIBXML_STATIC) + ADD_DEFINITIONS(-DLIBXML_STATIC) + ENDIF(NOT WITHOUT_LIBXML_STATIC AND LIBXML_STATIC) + CMAKE_POP_CHECK_STATE() # Restore the state of the variables +ELSE(LIBXML2_FOUND) + # + # Find Expat + # + IF(ENABLE_EXPAT) + FIND_PACKAGE(EXPAT) + ELSE() + SET(EXPAT_FOUND FALSE) + ENDIF() + IF(EXPAT_FOUND) + CMAKE_PUSH_CHECK_STATE() # Save the state of the variables + INCLUDE_DIRECTORIES(${EXPAT_INCLUDE_DIR}) + LIST(APPEND ADDITIONAL_LIBS ${EXPAT_LIBRARIES}) + SET(HAVE_LIBEXPAT 1) + LA_CHECK_INCLUDE_FILE("expat.h" HAVE_EXPAT_H) + CMAKE_POP_CHECK_STATE() # Restore the state of the variables + ENDIF(EXPAT_FOUND) +ENDIF(LIBXML2_FOUND) +MARK_AS_ADVANCED(CLEAR LIBXML2_INCLUDE_DIR) +MARK_AS_ADVANCED(CLEAR LIBXML2_LIBRARIES) +ENDIF() + +# +# Check functions +# +CMAKE_PUSH_CHECK_STATE() # Save the state of the variables +IF (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR + CMAKE_C_COMPILER_ID STREQUAL "Clang") + # + # During checking functions, we should use -fno-builtin to avoid the + # failure of function detection which failure is an error "conflicting + # types for built-in function" caused by using -Werror option. + # + SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fno-builtin") +ENDIF () +CHECK_SYMBOL_EXISTS(_CrtSetReportMode "crtdbg.h" HAVE__CrtSetReportMode) +CHECK_FUNCTION_EXISTS_GLIBC(arc4random_buf HAVE_ARC4RANDOM_BUF) +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) +CHECK_FUNCTION_EXISTS_GLIBC(fchown HAVE_FCHOWN) +CHECK_FUNCTION_EXISTS_GLIBC(fcntl HAVE_FCNTL) +CHECK_FUNCTION_EXISTS_GLIBC(fdopendir HAVE_FDOPENDIR) +CHECK_FUNCTION_EXISTS_GLIBC(fork HAVE_FORK) +CHECK_FUNCTION_EXISTS_GLIBC(fstat HAVE_FSTAT) +CHECK_FUNCTION_EXISTS_GLIBC(fstatat HAVE_FSTATAT) +CHECK_FUNCTION_EXISTS_GLIBC(fstatfs HAVE_FSTATFS) +CHECK_FUNCTION_EXISTS_GLIBC(fstatvfs HAVE_FSTATVFS) +CHECK_FUNCTION_EXISTS_GLIBC(ftruncate HAVE_FTRUNCATE) +CHECK_FUNCTION_EXISTS_GLIBC(futimens HAVE_FUTIMENS) +CHECK_FUNCTION_EXISTS_GLIBC(futimes HAVE_FUTIMES) +CHECK_FUNCTION_EXISTS_GLIBC(futimesat HAVE_FUTIMESAT) +CHECK_FUNCTION_EXISTS_GLIBC(geteuid HAVE_GETEUID) +CHECK_FUNCTION_EXISTS_GLIBC(getgrgid_r HAVE_GETGRGID_R) +CHECK_FUNCTION_EXISTS_GLIBC(getgrnam_r HAVE_GETGRNAM_R) +CHECK_FUNCTION_EXISTS_GLIBC(getpwnam_r HAVE_GETPWNAM_R) +CHECK_FUNCTION_EXISTS_GLIBC(getpwuid_r HAVE_GETPWUID_R) +CHECK_FUNCTION_EXISTS_GLIBC(getpid HAVE_GETPID) +CHECK_FUNCTION_EXISTS_GLIBC(getvfsbyname HAVE_GETVFSBYNAME) +CHECK_FUNCTION_EXISTS_GLIBC(gmtime_r HAVE_GMTIME_R) +CHECK_FUNCTION_EXISTS_GLIBC(lchflags HAVE_LCHFLAGS) +CHECK_FUNCTION_EXISTS_GLIBC(lchmod HAVE_LCHMOD) +CHECK_FUNCTION_EXISTS_GLIBC(lchown HAVE_LCHOWN) +CHECK_FUNCTION_EXISTS_GLIBC(link HAVE_LINK) +CHECK_FUNCTION_EXISTS_GLIBC(localtime_r HAVE_LOCALTIME_R) +CHECK_FUNCTION_EXISTS_GLIBC(lstat HAVE_LSTAT) +CHECK_FUNCTION_EXISTS_GLIBC(lutimes HAVE_LUTIMES) +CHECK_FUNCTION_EXISTS_GLIBC(mbrtowc HAVE_MBRTOWC) +CHECK_FUNCTION_EXISTS_GLIBC(memmove HAVE_MEMMOVE) +CHECK_FUNCTION_EXISTS_GLIBC(mkdir HAVE_MKDIR) +CHECK_FUNCTION_EXISTS_GLIBC(mkfifo HAVE_MKFIFO) +CHECK_FUNCTION_EXISTS_GLIBC(mknod HAVE_MKNOD) +CHECK_FUNCTION_EXISTS_GLIBC(mkstemp HAVE_MKSTEMP) +CHECK_FUNCTION_EXISTS_GLIBC(nl_langinfo HAVE_NL_LANGINFO) +CHECK_FUNCTION_EXISTS_GLIBC(openat HAVE_OPENAT) +CHECK_FUNCTION_EXISTS_GLIBC(pipe HAVE_PIPE) +CHECK_FUNCTION_EXISTS_GLIBC(poll HAVE_POLL) +CHECK_FUNCTION_EXISTS_GLIBC(posix_spawnp HAVE_POSIX_SPAWNP) +CHECK_FUNCTION_EXISTS_GLIBC(readlink HAVE_READLINK) +CHECK_FUNCTION_EXISTS_GLIBC(readpassphrase HAVE_READPASSPHRASE) +CHECK_FUNCTION_EXISTS_GLIBC(select HAVE_SELECT) +CHECK_FUNCTION_EXISTS_GLIBC(setenv HAVE_SETENV) +CHECK_FUNCTION_EXISTS_GLIBC(setlocale HAVE_SETLOCALE) +CHECK_FUNCTION_EXISTS_GLIBC(sigaction HAVE_SIGACTION) +CHECK_FUNCTION_EXISTS_GLIBC(statfs HAVE_STATFS) +CHECK_FUNCTION_EXISTS_GLIBC(statvfs HAVE_STATVFS) +CHECK_FUNCTION_EXISTS_GLIBC(strchr HAVE_STRCHR) +CHECK_FUNCTION_EXISTS_GLIBC(strdup HAVE_STRDUP) +CHECK_FUNCTION_EXISTS_GLIBC(strerror HAVE_STRERROR) +CHECK_FUNCTION_EXISTS_GLIBC(strncpy_s HAVE_STRNCPY_S) +CHECK_FUNCTION_EXISTS_GLIBC(strrchr HAVE_STRRCHR) +CHECK_FUNCTION_EXISTS_GLIBC(symlink HAVE_SYMLINK) +CHECK_FUNCTION_EXISTS_GLIBC(timegm HAVE_TIMEGM) +CHECK_FUNCTION_EXISTS_GLIBC(tzset HAVE_TZSET) +CHECK_FUNCTION_EXISTS_GLIBC(unsetenv HAVE_UNSETENV) +CHECK_FUNCTION_EXISTS_GLIBC(utime HAVE_UTIME) +CHECK_FUNCTION_EXISTS_GLIBC(utimes HAVE_UTIMES) +CHECK_FUNCTION_EXISTS_GLIBC(utimensat HAVE_UTIMENSAT) +CHECK_FUNCTION_EXISTS_GLIBC(vfork HAVE_VFORK) +CHECK_FUNCTION_EXISTS_GLIBC(wcrtomb HAVE_WCRTOMB) +CHECK_FUNCTION_EXISTS_GLIBC(wcscmp HAVE_WCSCMP) +CHECK_FUNCTION_EXISTS_GLIBC(wcscpy HAVE_WCSCPY) +CHECK_FUNCTION_EXISTS_GLIBC(wcslen HAVE_WCSLEN) +CHECK_FUNCTION_EXISTS_GLIBC(wctomb HAVE_WCTOMB) +CHECK_FUNCTION_EXISTS_GLIBC(_ctime64_s HAVE__CTIME64_S) +CHECK_FUNCTION_EXISTS_GLIBC(_fseeki64 HAVE__FSEEKI64) +CHECK_FUNCTION_EXISTS_GLIBC(_get_timezone HAVE__GET_TIMEZONE) +CHECK_FUNCTION_EXISTS_GLIBC(_localtime64_s HAVE__LOCALTIME64_S) +CHECK_FUNCTION_EXISTS_GLIBC(_mkgmtime64 HAVE__MKGMTIME64) + +SET(CMAKE_REQUIRED_LIBRARIES "") +CHECK_FUNCTION_EXISTS(cygwin_conv_path HAVE_CYGWIN_CONV_PATH) +CHECK_FUNCTION_EXISTS(fseeko HAVE_FSEEKO) +CHECK_FUNCTION_EXISTS(strerror_r HAVE_STRERROR_R) +CHECK_FUNCTION_EXISTS(strftime HAVE_STRFTIME) +CHECK_FUNCTION_EXISTS(vprintf HAVE_VPRINTF) +CHECK_FUNCTION_EXISTS(wmemcmp HAVE_WMEMCMP) +CHECK_FUNCTION_EXISTS(wmemcpy HAVE_WMEMCPY) +CHECK_FUNCTION_EXISTS(wmemmove HAVE_WMEMMOVE) + +CMAKE_POP_CHECK_STATE() # Restore the state of the variables + ++CHECK_C_SOURCE_COMPILES( ++ "#include \n#include \nint main(void) { struct vfsconf v; return sizeof(v);}" ++ HAVE_STRUCT_VFSCONF) ++ ++CHECK_C_SOURCE_COMPILES( ++ "#include \n#include \nint main(void) { struct xvfsconf v; return sizeof(v);}" ++ HAVE_STRUCT_XVFSCONF) ++ +# Make sure we have the POSIX version of readdir_r, not the +# older 2-argument version. +CHECK_C_SOURCE_COMPILES( + "#include \nint main() {DIR *d = opendir(\".\"); struct dirent e,*r; return readdir_r(d,&e,&r);}" + HAVE_READDIR_R) + + +# Only detect readlinkat() if we also have AT_FDCWD in unistd.h. +# NOTE: linux requires fcntl.h for AT_FDCWD. +CHECK_C_SOURCE_COMPILES( + "#include \n#include \nint main() {char buf[10]; return readlinkat(AT_FDCWD, \"\", buf, 0);}" + HAVE_READLINKAT) + + +# To verify major(), we need to both include the header +# of interest and verify that the result can be linked. +# CHECK_FUNCTION_EXISTS doesn't accept a header argument, +# CHECK_SYMBOL_EXISTS doesn't test linkage. +CHECK_C_SOURCE_COMPILES( + "#include \nint main() { return major(256); }" + MAJOR_IN_MKDEV) +CHECK_C_SOURCE_COMPILES( + "#include \nint main() { return major(256); }" + MAJOR_IN_SYSMACROS) + ++CHECK_C_SOURCE_COMPILES( ++ "#include \n#if LZMA_VERSION < 50020000\n#error unsupported\n#endif\nint main(void){lzma_stream_encoder_mt(0, 0); return 0;}" ++ HAVE_LZMA_STREAM_ENCODER_MT) ++ +IF(HAVE_STRERROR_R) + SET(HAVE_DECL_STRERROR_R 1) +ENDIF(HAVE_STRERROR_R) + +# +# Check defines +# +SET(headers "limits.h") +IF(HAVE_STDINT_H) + LIST(APPEND headers "stdint.h") +ENDIF(HAVE_STDINT_H) +IF(HAVE_INTTYPES_H) + LIST(APPEND headers "inttypes.h") +ENDIF(HAVE_INTTYPES_H) +CHECK_SYMBOL_EXISTS(EFTYPE "errno.h" HAVE_EFTYPE) +CHECK_SYMBOL_EXISTS(EILSEQ "errno.h" HAVE_EILSEQ) +CHECK_SYMBOL_EXISTS(D_MD_ORDER "langinfo.h" HAVE_D_MD_ORDER) +CHECK_SYMBOL_EXISTS(INT32_MAX "${headers}" HAVE_DECL_INT32_MAX) +CHECK_SYMBOL_EXISTS(INT32_MIN "${headers}" HAVE_DECL_INT32_MIN) +CHECK_SYMBOL_EXISTS(INT64_MAX "${headers}" HAVE_DECL_INT64_MAX) +CHECK_SYMBOL_EXISTS(INT64_MIN "${headers}" HAVE_DECL_INT64_MIN) +CHECK_SYMBOL_EXISTS(INTMAX_MAX "${headers}" HAVE_DECL_INTMAX_MAX) +CHECK_SYMBOL_EXISTS(INTMAX_MIN "${headers}" HAVE_DECL_INTMAX_MIN) +CHECK_SYMBOL_EXISTS(UINT32_MAX "${headers}" HAVE_DECL_UINT32_MAX) +CHECK_SYMBOL_EXISTS(UINT64_MAX "${headers}" HAVE_DECL_UINT64_MAX) +CHECK_SYMBOL_EXISTS(UINTMAX_MAX "${headers}" HAVE_DECL_UINTMAX_MAX) +CHECK_SYMBOL_EXISTS(SIZE_MAX "${headers}" HAVE_DECL_SIZE_MAX) +CHECK_SYMBOL_EXISTS(SSIZE_MAX "limits.h" HAVE_DECL_SSIZE_MAX) + +# +# Check struct members +# +# Check for tm_gmtoff in struct tm - CHECK_STRUCT_MEMBER("struct tm" tm_gmtoff ++CHECK_STRUCT_HAS_MEMBER("struct tm" tm_gmtoff + "time.h" HAVE_STRUCT_TM_TM_GMTOFF) - CHECK_STRUCT_MEMBER("struct tm" __tm_gmtoff ++CHECK_STRUCT_HAS_MEMBER("struct tm" __tm_gmtoff + "time.h" HAVE_STRUCT_TM___TM_GMTOFF) + +# Check for f_namemax in struct statfs - CHECK_STRUCT_MEMBER("struct statfs" f_namemax ++CHECK_STRUCT_HAS_MEMBER("struct statfs" f_namemax + "sys/param.h;sys/mount.h" HAVE_STRUCT_STATFS_F_NAMEMAX) + +# Check for birthtime in struct stat - CHECK_STRUCT_MEMBER("struct stat" st_birthtime ++CHECK_STRUCT_HAS_MEMBER("struct stat" st_birthtime + "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_BIRTHTIME) + +# Check for high-resolution timestamps in struct stat - CHECK_STRUCT_MEMBER("struct stat" st_birthtimespec.tv_nsec ++CHECK_STRUCT_HAS_MEMBER("struct stat" st_birthtimespec.tv_nsec + "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC) - CHECK_STRUCT_MEMBER("struct stat" st_mtimespec.tv_nsec ++CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtimespec.tv_nsec + "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC) - CHECK_STRUCT_MEMBER("struct stat" st_mtim.tv_nsec ++CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtim.tv_nsec + "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC) - CHECK_STRUCT_MEMBER("struct stat" st_mtime_n ++CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtime_n + "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIME_N) - CHECK_STRUCT_MEMBER("struct stat" st_umtime ++CHECK_STRUCT_HAS_MEMBER("struct stat" st_umtime + "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_UMTIME) - CHECK_STRUCT_MEMBER("struct stat" st_mtime_usec ++CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtime_usec + "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIME_USEC) +# Check for block size support in struct stat - CHECK_STRUCT_MEMBER("struct stat" st_blksize ++CHECK_STRUCT_HAS_MEMBER("struct stat" st_blksize + "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_BLKSIZE) +# Check for st_flags in struct stat (BSD fflags) - CHECK_STRUCT_MEMBER("struct stat" st_flags ++CHECK_STRUCT_HAS_MEMBER("struct stat" st_flags + "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_FLAGS) + +IF(HAVE_SYS_STATVFS_H) - CHECK_STRUCT_MEMBER("struct statvfs" f_iosize ++ CHECK_STRUCT_HAS_MEMBER("struct statvfs" f_iosize + "sys/types.h;sys/statvfs.h" HAVE_STRUCT_STATVFS_F_IOSIZE) +ENDIF() + +# +# - CHECK_STRUCT_MEMBER("struct tm" tm_sec ++CHECK_STRUCT_HAS_MEMBER("struct tm" tm_sec + "sys/types.h;sys/time.h;time.h" TIME_WITH_SYS_TIME) + +# +# Check for integer types +# +# +CHECK_TYPE_SIZE("short" SIZE_OF_SHORT) +CHECK_TYPE_SIZE("int" SIZE_OF_INT) +CHECK_TYPE_SIZE("long" SIZE_OF_LONG) +CHECK_TYPE_SIZE("long long" SIZE_OF_LONG_LONG) + +CHECK_TYPE_SIZE("unsigned short" SIZE_OF_UNSIGNED_SHORT) +CHECK_TYPE_SIZE("unsigned" SIZE_OF_UNSIGNED) +CHECK_TYPE_SIZE("unsigned long" SIZE_OF_UNSIGNED_LONG) +CHECK_TYPE_SIZE("unsigned long long" SIZE_OF_UNSIGNED_LONG_LONG) + +CHECK_TYPE_SIZE("__int64" __INT64) +CHECK_TYPE_SIZE("unsigned __int64" UNSIGNED___INT64) + +CHECK_TYPE_SIZE(int16_t INT16_T) +CHECK_TYPE_SIZE(int32_t INT32_T) +CHECK_TYPE_SIZE(int64_t INT64_T) +CHECK_TYPE_SIZE(intmax_t INTMAX_T) +CHECK_TYPE_SIZE(uint8_t UINT8_T) +CHECK_TYPE_SIZE(uint16_t UINT16_T) +CHECK_TYPE_SIZE(uint32_t UINT32_T) +CHECK_TYPE_SIZE(uint64_t UINT64_T) +CHECK_TYPE_SIZE(uintmax_t UINTMAX_T) + +CHECK_TYPE_SIZE(dev_t DEV_T) +IF(NOT HAVE_DEV_T) + IF(MSVC) + SET(dev_t "unsigned int") + ENDIF(MSVC) +ENDIF(NOT HAVE_DEV_T) +# +CHECK_TYPE_SIZE(gid_t GID_T) +IF(NOT HAVE_GID_T) + IF(WIN32) + SET(gid_t "short") + ELSE(WIN32) + SET(gid_t "unsigned int") + ENDIF(WIN32) +ENDIF(NOT HAVE_GID_T) +# +CHECK_TYPE_SIZE(id_t ID_T) +IF(NOT HAVE_ID_T) + IF(WIN32) + SET(id_t "short") + ELSE(WIN32) + SET(id_t "unsigned int") + ENDIF(WIN32) +ENDIF(NOT HAVE_ID_T) +# +CHECK_TYPE_SIZE(mode_t MODE_T) +IF(NOT HAVE_MODE_T) + IF(WIN32) + SET(mode_t "unsigned short") + ELSE(WIN32) + SET(mode_t "int") + ENDIF(WIN32) +ENDIF(NOT HAVE_MODE_T) +# +CHECK_TYPE_SIZE(off_t OFF_T) +IF(NOT HAVE_OFF_T) + SET(off_t "__int64") +ENDIF(NOT HAVE_OFF_T) +# +CHECK_TYPE_SIZE(size_t SIZE_T) +IF(NOT HAVE_SIZE_T) + IF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) + SET(size_t "uint64_t") + ELSE("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) + SET(size_t "uint32_t") + ENDIF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) +ENDIF(NOT HAVE_SIZE_T) +# +CHECK_TYPE_SIZE(ssize_t SSIZE_T) +IF(NOT HAVE_SSIZE_T) + IF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) + SET(ssize_t "int64_t") + ELSE("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) + SET(ssize_t "long") + ENDIF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) +ENDIF(NOT HAVE_SSIZE_T) +# +CHECK_TYPE_SIZE(uid_t UID_T) +IF(NOT HAVE_UID_T) + IF(WIN32) + SET(uid_t "short") + ELSE(WIN32) + SET(uid_t "unsigned int") + ENDIF(WIN32) +ENDIF(NOT HAVE_UID_T) +# +CHECK_TYPE_SIZE(pid_t PID_T) +IF(NOT HAVE_PID_T) + IF(WIN32) + SET(pid_t "int") + ELSE(WIN32) + MESSAGE(FATAL_ERROR "pid_t doesn't exist on this platform?") + ENDIF(WIN32) +ENDIF(NOT HAVE_PID_T) +# +CHECK_TYPE_SIZE(intptr_t INTPTR_T) +IF(NOT HAVE_INTPTR_T) + IF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) + SET(intptr_t "int64_t") + ELSE() + SET(intptr_t "int32_t") + ENDIF() +ENDIF(NOT HAVE_INTPTR_T) +# +CHECK_TYPE_SIZE(uintptr_t UINTPTR_T) +IF(NOT HAVE_UINTPTR_T) + IF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) + SET(uintptr_t "uint64_t") + ELSE() + SET(uintptr_t "uint32_t") + ENDIF() +ENDIF(NOT HAVE_UINTPTR_T) +# +CHECK_TYPE_SIZE(wchar_t SIZEOF_WCHAR_T) +IF(HAVE_SIZEOF_WCHAR_T) + SET(HAVE_WCHAR_T 1) +ENDIF(HAVE_SIZEOF_WCHAR_T) +# +# Check if _FILE_OFFSET_BITS macro needed for large files +# +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) +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) +ENDIF(ENABLE_XATTR) + +# +# Check for ACL libraries, headers, and functions +# +# The ACL support in libarchive is written against the POSIX1e draft, +# which was never officially approved and varies quite a bit across +# platforms. Worse, some systems have completely non-POSIX acl functions, +# which makes the following checks rather more complex than I would like. +# +IF(ENABLE_ACL) + 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 ++#include ++int main(void) { return ACL_TYPE_EXTENDED; }" HAVE_ACL_TYPE_EXTENDED) ++ ++ # 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) +ENDIF(ENABLE_ACL) + +# +# Check MD5/RMD160/SHA support +# NOTE: Crypto checks must be run last before generating config.h +# +CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA384;SHA512" LIBC) +CHECK_CRYPTO("SHA256;SHA384;SHA512" LIBC2) +CHECK_CRYPTO("SHA256;SHA384;SHA512" LIBC3) +CHECK_CRYPTO("MD5;SHA1;SHA256;SHA384;SHA512" LIBSYSTEM) +CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA384;SHA512" NETTLE) +CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA384;SHA512" OPENSSL) + +# Libmd has to be probed after OpenSSL. +CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA512" LIBMD) + +CHECK_CRYPTO_WIN("MD5;SHA1;SHA256;SHA384;SHA512") + +# Generate "config.h" from "build/cmake/config.h.in" +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.h.in + ${CMAKE_CURRENT_BINARY_DIR}/config.h) +INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_BINARY_DIR}) +ADD_DEFINITIONS(-DHAVE_CONFIG_H) + +# +# Register installation of PDF documents. +# +IF(WIN32 AND NOT CYGWIN) + # + # On Windows platform, It's better that we install PDF documents + # on one's computer. + # These PDF documents are available in the release package. + # + IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/doc/pdf) + INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc/pdf + DESTINATION share/man + FILES_MATCHING PATTERN "*.pdf" + ) + ENDIF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/doc/pdf) +ENDIF(WIN32 AND NOT CYGWIN) +# +# +# +INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/libarchive) +# +IF(MSVC) + ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE) +ENDIF(MSVC) + +# We need CoreServices on Mac OS. +IF(APPLE) + LIST(APPEND ADDITIONAL_LIBS "-framework CoreServices") +ENDIF(APPLE) + +add_subdirectory(libarchive) + +install(FILES COPYING DESTINATION ${CMAKE_DOC_DIR}/cmlibarchive) diff --cc Utilities/cmlibarchive/build/cmake/config.h.in index 9843875,0000000..fc248b3 mode 100644,000000..100644 --- a/Utilities/cmlibarchive/build/cmake/config.h.in +++ b/Utilities/cmlibarchive/build/cmake/config.h.in @@@ -1,1224 -1,0 +1,1242 @@@ +/* config.h. Generated from build/cmake/config.h.in by cmake configure */ +#if defined(__osf__) +# define _OSF_SOURCE +#endif + +/* + * Ensure we have C99-style int64_t, etc, all defined. + */ + +/* First, we need to know if the system has already defined them. */ +#cmakedefine HAVE_INT16_T +#cmakedefine HAVE_INT32_T +#cmakedefine HAVE_INT64_T +#cmakedefine HAVE_INTMAX_T + +#cmakedefine HAVE_UINT8_T +#cmakedefine HAVE_UINT16_T +#cmakedefine HAVE_UINT32_T +#cmakedefine HAVE_UINT64_T +#cmakedefine HAVE_UINTMAX_T + +/* We might have the types we want under other spellings. */ +#cmakedefine HAVE___INT64 +#cmakedefine HAVE_U_INT64_T +#cmakedefine HAVE_UNSIGNED___INT64 + +/* The sizes of various standard integer types. */ + at SIZE_OF_SHORT_CODE@ + at SIZE_OF_INT_CODE@ + at SIZE_OF_LONG_CODE@ + at SIZE_OF_LONG_LONG_CODE@ + at SIZE_OF_UNSIGNED_SHORT_CODE@ + at SIZE_OF_UNSIGNED_CODE@ + at SIZE_OF_UNSIGNED_LONG_CODE@ + at SIZE_OF_UNSIGNED_LONG_LONG_CODE@ + +/* + * If we lack int64_t, define it to the first of __int64, int, long, and long long + * that exists and is the right size. + */ +#if !defined(HAVE_INT64_T) && defined(HAVE___INT64) +typedef __int64 int64_t; +#define HAVE_INT64_T +#endif + +#if !defined(HAVE_INT64_T) && SIZE_OF_INT == 8 +typedef int int64_t; +#define HAVE_INT64_T +#endif + +#if !defined(HAVE_INT64_T) && SIZE_OF_LONG == 8 +typedef long int64_t; +#define HAVE_INT64_T +#endif + +#if !defined(HAVE_INT64_T) && SIZE_OF_LONG_LONG == 8 +typedef long long int64_t; +#define HAVE_INT64_T +#endif + +#if !defined(HAVE_INT64_T) +#error No 64-bit integer type was found. +#endif + +/* + * Similarly for int32_t + */ +#if !defined(HAVE_INT32_T) && SIZE_OF_INT == 4 +typedef int int32_t; +#define HAVE_INT32_T +#endif + +#if !defined(HAVE_INT32_T) && SIZE_OF_LONG == 4 +typedef long int32_t; +#define HAVE_INT32_T +#endif + +#if !defined(HAVE_INT32_T) +#error No 32-bit integer type was found. +#endif + +/* + * Similarly for int16_t + */ +#if !defined(HAVE_INT16_T) && SIZE_OF_INT == 2 +typedef int int16_t; +#define HAVE_INT16_T +#endif + +#if !defined(HAVE_INT16_T) && SIZE_OF_SHORT == 2 +typedef short int16_t; +#define HAVE_INT16_T +#endif + +#if !defined(HAVE_INT16_T) +#error No 16-bit integer type was found. +#endif + +/* + * Similarly for uint64_t + */ +#if !defined(HAVE_UINT64_T) && defined(HAVE_UNSIGNED___INT64) +typedef unsigned __int64 uint64_t; +#define HAVE_UINT64_T +#endif + +#if !defined(HAVE_UINT64_T) && SIZE_OF_UNSIGNED == 8 +typedef unsigned uint64_t; +#define HAVE_UINT64_T +#endif + +#if !defined(HAVE_UINT64_T) && SIZE_OF_UNSIGNED_LONG == 8 +typedef unsigned long uint64_t; +#define HAVE_UINT64_T +#endif + +#if !defined(HAVE_UINT64_T) && SIZE_OF_UNSIGNED_LONG_LONG == 8 +typedef unsigned long long uint64_t; +#define HAVE_UINT64_T +#endif + +#if !defined(HAVE_UINT64_T) +#error No 64-bit unsigned integer type was found. +#endif + + +/* + * Similarly for uint32_t + */ +#if !defined(HAVE_UINT32_T) && SIZE_OF_UNSIGNED == 4 +typedef unsigned uint32_t; +#define HAVE_UINT32_T +#endif + +#if !defined(HAVE_UINT32_T) && SIZE_OF_UNSIGNED_LONG == 4 +typedef unsigned long uint32_t; +#define HAVE_UINT32_T +#endif + +#if !defined(HAVE_UINT32_T) +#error No 32-bit unsigned integer type was found. +#endif + +/* + * Similarly for uint16_t + */ +#if !defined(HAVE_UINT16_T) && SIZE_OF_UNSIGNED == 2 +typedef unsigned uint16_t; +#define HAVE_UINT16_T +#endif + +#if !defined(HAVE_UINT16_T) && SIZE_OF_UNSIGNED_SHORT == 2 +typedef unsigned short uint16_t; +#define HAVE_UINT16_T +#endif + +#if !defined(HAVE_UINT16_T) +#error No 16-bit unsigned integer type was found. +#endif + +/* + * Similarly for uint8_t + */ +#if !defined(HAVE_UINT8_T) +typedef unsigned char uint8_t; +#define HAVE_UINT8_T +#endif + +#if !defined(HAVE_UINT16_T) +#error No 8-bit unsigned integer type was found. +#endif + +/* Define intmax_t and uintmax_t if they are not already defined. */ +#if !defined(HAVE_INTMAX_T) +typedef int64_t intmax_t; +#endif + +#if !defined(HAVE_UINTMAX_T) +typedef uint64_t uintmax_t; +#endif + +/* Define ZLIB_WINAPI if zlib was built on Visual Studio. */ +#cmakedefine ZLIB_WINAPI 1 + +/* MD5 via ARCHIVE_CRYPTO_MD5_LIBC supported. */ +#cmakedefine ARCHIVE_CRYPTO_MD5_LIBC 1 + +/* MD5 via ARCHIVE_CRYPTO_MD5_LIBSYSTEM supported. */ +#cmakedefine ARCHIVE_CRYPTO_MD5_LIBSYSTEM 1 + +/* MD5 via ARCHIVE_CRYPTO_MD5_NETTLE supported. */ +#cmakedefine ARCHIVE_CRYPTO_MD5_NETTLE 1 + +/* MD5 via ARCHIVE_CRYPTO_MD5_OPENSSL supported. */ +#cmakedefine ARCHIVE_CRYPTO_MD5_OPENSSL 1 + +/* MD5 via ARCHIVE_CRYPTO_MD5_WIN supported. */ +#cmakedefine ARCHIVE_CRYPTO_MD5_WIN 1 + +/* RMD160 via ARCHIVE_CRYPTO_RMD160_LIBC supported. */ +#cmakedefine ARCHIVE_CRYPTO_RMD160_LIBC 1 + +/* RMD160 via ARCHIVE_CRYPTO_RMD160_NETTLE supported. */ +#cmakedefine ARCHIVE_CRYPTO_RMD160_NETTLE 1 + +/* RMD160 via ARCHIVE_CRYPTO_RMD160_OPENSSL supported. */ +#cmakedefine ARCHIVE_CRYPTO_RMD160_OPENSSL 1 + +/* SHA1 via ARCHIVE_CRYPTO_SHA1_LIBC supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA1_LIBC 1 + +/* SHA1 via ARCHIVE_CRYPTO_SHA1_LIBSYSTEM supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA1_LIBSYSTEM 1 + +/* SHA1 via ARCHIVE_CRYPTO_SHA1_NETTLE supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA1_NETTLE 1 + +/* SHA1 via ARCHIVE_CRYPTO_SHA1_OPENSSL supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA1_OPENSSL 1 + +/* SHA1 via ARCHIVE_CRYPTO_SHA1_WIN supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA1_WIN 1 + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBC supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA256_LIBC 1 + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBC2 supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA256_LIBC2 1 + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBC3 supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA256_LIBC3 1 + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBSYSTEM supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA256_LIBSYSTEM 1 + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_NETTLE supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA256_NETTLE 1 + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_OPENSSL supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA256_OPENSSL 1 + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_WIN supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA256_WIN 1 + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBC supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA384_LIBC 1 + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBC2 supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA384_LIBC2 1 + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBC3 supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA384_LIBC3 1 + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBSYSTEM supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA384_LIBSYSTEM 1 + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_NETTLE supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA384_NETTLE 1 + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_OPENSSL supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA384_OPENSSL 1 + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_WIN supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA384_WIN 1 + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBC supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA512_LIBC 1 + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBC2 supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA512_LIBC2 1 + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBC3 supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA512_LIBC3 1 + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBSYSTEM supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA512_LIBSYSTEM 1 + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_NETTLE supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA512_NETTLE 1 + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_OPENSSL supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA512_OPENSSL 1 + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_WIN supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA512_WIN 1 + +/* Version number of bsdcpio */ +#cmakedefine BSDCPIO_VERSION_STRING "${BSDCPIO_VERSION_STRING}" + +/* Version number of bsdtar */ +#cmakedefine BSDTAR_VERSION_STRING "${BSDTAR_VERSION_STRING}" + +/* Version number of bsdcat */ +#cmakedefine BSDCAT_VERSION_STRING "${BSDCAT_VERSION_STRING}" + +/* Define to 1 if you have the `acl_create_entry' function. */ +#cmakedefine HAVE_ACL_CREATE_ENTRY 1 + ++/* Define to 1 if you have the `acl_get_fd_np' function. */ ++#cmakedefine HAVE_ACL_GET_FD_NP 1 ++ +/* Define to 1 if you have the `acl_get_link' function. */ +#cmakedefine HAVE_ACL_GET_LINK 1 + +/* Define to 1 if you have the `acl_get_link_np' function. */ +#cmakedefine HAVE_ACL_GET_LINK_NP 1 + +/* Define to 1 if you have the `acl_get_perm' function. */ +#cmakedefine HAVE_ACL_GET_PERM 1 + +/* Define to 1 if you have the `acl_get_perm_np' function. */ +#cmakedefine HAVE_ACL_GET_PERM_NP 1 + +/* Define to 1 if you have the `acl_init' function. */ +#cmakedefine HAVE_ACL_INIT 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ACL_LIBACL_H 1 + +/* Define to 1 if the system has the type `acl_permset_t'. */ +#cmakedefine HAVE_ACL_PERMSET_T 1 + +/* Define to 1 if you have the `acl_set_fd' function. */ +#cmakedefine HAVE_ACL_SET_FD 1 + +/* Define to 1 if you have the `acl_set_fd_np' function. */ +#cmakedefine HAVE_ACL_SET_FD_NP 1 + +/* 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 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ATTR_XATTR_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_BCRYPT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_BSDXML_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_BZLIB_H 1 + +/* Define to 1 if you have the `chflags' function. */ +#cmakedefine HAVE_CHFLAGS 1 + +/* Define to 1 if you have the `chown' function. */ +#cmakedefine HAVE_CHOWN 1 + +/* Define to 1 if you have the `chroot' function. */ +#cmakedefine HAVE_CHROOT 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_COPYFILE_H 1 + +/* Define to 1 if you have the `ctime_r' function. */ +#cmakedefine HAVE_CTIME_R 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_CTYPE_H 1 + +/* 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 `INT32_MAX', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_INT32_MAX 1 + +/* Define to 1 if you have the declaration of `INT32_MIN', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_INT32_MIN 1 + +/* Define to 1 if you have the declaration of `INT64_MAX', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_INT64_MAX 1 + +/* Define to 1 if you have the declaration of `INT64_MIN', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_INT64_MIN 1 + +/* Define to 1 if you have the declaration of `INTMAX_MAX', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_INTMAX_MAX 1 + +/* Define to 1 if you have the declaration of `INTMAX_MIN', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_INTMAX_MIN 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 + +/* Define to 1 if you have the declaration of `SSIZE_MAX', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_SSIZE_MAX 1 + +/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_STRERROR_R 1 + +/* Define to 1 if you have the declaration of `UINT32_MAX', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_UINT32_MAX 1 + +/* Define to 1 if you have the declaration of `UINT64_MAX', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_UINT64_MAX 1 + +/* Define to 1 if you have the declaration of `UINTMAX_MAX', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_UINTMAX_MAX 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_DIRECT_H 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#cmakedefine HAVE_DIRENT_H 1 + +/* Define to 1 if you have the `dirfd' function. */ +#cmakedefine HAVE_DIRFD 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_DLFCN_H 1 + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +#cmakedefine HAVE_DOPRNT 1 + +/* Define to 1 if nl_langinfo supports D_MD_ORDER */ +#cmakedefine HAVE_D_MD_ORDER 1 + +/* A possible errno value for invalid file format errors */ +#cmakedefine HAVE_EFTYPE 1 + +/* A possible errno value for invalid file format errors */ +#cmakedefine HAVE_EILSEQ 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ERRNO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_EXPAT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_EXT2FS_EXT2_FS_H 1 + +/* Define to 1 if you have the `extattr_get_file' function. */ +#cmakedefine HAVE_EXTATTR_GET_FILE 1 + +/* Define to 1 if you have the `extattr_list_file' function. */ +#cmakedefine HAVE_EXTATTR_LIST_FILE 1 + +/* Define to 1 if you have the `extattr_set_fd' function. */ +#cmakedefine HAVE_EXTATTR_SET_FD 1 + +/* Define to 1 if you have the `extattr_set_file' function. */ +#cmakedefine HAVE_EXTATTR_SET_FILE 1 + +/* 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 `fchdir' function. */ +#cmakedefine HAVE_FCHDIR 1 + +/* Define to 1 if you have the `fchflags' function. */ +#cmakedefine HAVE_FCHFLAGS 1 + +/* Define to 1 if you have the `fchmod' function. */ +#cmakedefine HAVE_FCHMOD 1 + +/* Define to 1 if you have the `fchown' function. */ +#cmakedefine HAVE_FCHOWN 1 + +/* Define to 1 if you have the `fcntl' function. */ +#cmakedefine HAVE_FCNTL 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `fdopendir' function. */ +#cmakedefine HAVE_FDOPENDIR 1 + +/* Define to 1 if you have the `fgetea' function. */ +#cmakedefine HAVE_FGETEA 1 + +/* Define to 1 if you have the `fgetxattr' function. */ +#cmakedefine HAVE_FGETXATTR 1 + +/* Define to 1 if you have the `flistea' function. */ +#cmakedefine HAVE_FLISTEA 1 + +/* Define to 1 if you have the `flistxattr' function. */ +#cmakedefine HAVE_FLISTXATTR 1 + +/* Define to 1 if you have the `fork' function. */ +#cmakedefine HAVE_FORK 1 + +/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ +#cmakedefine HAVE_FSEEKO 1 + +/* Define to 1 if you have the `fsetea' function. */ +#cmakedefine HAVE_FSETEA 1 + +/* Define to 1 if you have the `fsetxattr' function. */ +#cmakedefine HAVE_FSETXATTR 1 + +/* Define to 1 if you have the `fstat' function. */ +#cmakedefine HAVE_FSTAT 1 + +/* Define to 1 if you have the `fstatat' function. */ +#cmakedefine HAVE_FSTATAT 1 + +/* Define to 1 if you have the `fstatfs' function. */ +#cmakedefine HAVE_FSTATFS 1 + +/* Define to 1 if you have the `fstatvfs' function. */ +#cmakedefine HAVE_FSTATVFS 1 + +/* Define to 1 if you have the `ftruncate' function. */ +#cmakedefine HAVE_FTRUNCATE 1 + +/* Define to 1 if you have the `futimens' function. */ +#cmakedefine HAVE_FUTIMENS 1 + +/* Define to 1 if you have the `futimes' function. */ +#cmakedefine HAVE_FUTIMES 1 + +/* Define to 1 if you have the `futimesat' function. */ +#cmakedefine HAVE_FUTIMESAT 1 + +/* Define to 1 if you have the `getea' function. */ +#cmakedefine HAVE_GETEA 1 + +/* Define to 1 if you have the `geteuid' function. */ +#cmakedefine HAVE_GETEUID 1 + +/* Define to 1 if you have the `getgrgid_r' function. */ +#cmakedefine HAVE_GETGRGID_R 1 + +/* Define to 1 if you have the `getgrnam_r' function. */ +#cmakedefine HAVE_GETGRNAM_R 1 + +/* Define to 1 if you have the `getpid' function. */ +#cmakedefine HAVE_GETPID 1 + +/* Define to 1 if you have the `getpwnam_r' function. */ +#cmakedefine HAVE_GETPWNAM_R 1 + +/* Define to 1 if you have the `getpwuid_r' function. */ +#cmakedefine HAVE_GETPWUID_R 1 + +/* Define to 1 if you have the `getvfsbyname' function. */ +#cmakedefine HAVE_GETVFSBYNAME 1 + +/* Define to 1 if you have the `getxattr' function. */ +#cmakedefine HAVE_GETXATTR 1 + +/* Define to 1 if you have the `gmtime_r' function. */ +#cmakedefine HAVE_GMTIME_R 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_GRP_H 1 + +/* Define to 1 if you have the `iconv' function. */ +#cmakedefine HAVE_ICONV 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ICONV_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_IO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LANGINFO_H 1 + +/* Define to 1 if you have the `lchflags' function. */ +#cmakedefine HAVE_LCHFLAGS 1 + +/* Define to 1 if you have the `lchmod' function. */ +#cmakedefine HAVE_LCHMOD 1 + +/* Define to 1 if you have the `lchown' function. */ +#cmakedefine HAVE_LCHOWN 1 + +/* Define to 1 if you have the `lgetea' function. */ +#cmakedefine HAVE_LGETEA 1 + +/* Define to 1 if you have the `lgetxattr' function. */ +#cmakedefine HAVE_LGETXATTR 1 + +/* Define to 1 if you have the `acl' library (-lacl). */ +#cmakedefine HAVE_LIBACL 1 + +/* Define to 1 if you have the `attr' library (-lattr). */ +#cmakedefine HAVE_LIBATTR 1 + +/* Define to 1 if you have the `bsdxml' library (-lbsdxml). */ +#cmakedefine HAVE_LIBBSDXML 1 + +/* Define to 1 if you have the `bz2' library (-lbz2). */ +#cmakedefine HAVE_LIBBZ2 1 + +/* Define to 1 if you have the `charset' library (-lcharset). */ +#cmakedefine HAVE_LIBCHARSET 1 + +/* Define to 1 if you have the `crypto' library (-lcrypto). */ +#cmakedefine HAVE_LIBCRYPTO 1 + +/* Define to 1 if you have the `expat' library (-lexpat). */ +#cmakedefine HAVE_LIBEXPAT 1 + +/* Define to 1 if you have the `gcc' library (-lgcc). */ +#cmakedefine HAVE_LIBGCC 1 + +/* Define to 1 if you have the `lz4' library (-llz4). */ +#cmakedefine HAVE_LIBLZ4 1 + +/* Define to 1 if you have the `lzma' library (-llzma). */ +#cmakedefine HAVE_LIBLZMA 1 + +/* Define to 1 if you have the `lzmadec' library (-llzmadec). */ +#cmakedefine HAVE_LIBLZMADEC 1 + +/* Define to 1 if you have the `lzo2' library (-llzo2). */ +#cmakedefine HAVE_LIBLZO2 1 + +/* Define to 1 if you have the `nettle' library (-lnettle). */ +#cmakedefine HAVE_LIBNETTLE 1 + +/* Define to 1 if you have the `pcre' library (-lpcre). */ +#cmakedefine HAVE_LIBPCRE 1 + +/* Define to 1 if you have the `pcreposix' library (-lpcreposix). */ +#cmakedefine HAVE_LIBPCREPOSIX 1 + +/* Define to 1 if you have the `xml2' library (-lxml2). */ +#cmakedefine HAVE_LIBXML2 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LIBXML_XMLREADER_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LIBXML_XMLWRITER_H 1 + +/* Define to 1 if you have the `z' library (-lz). */ +#cmakedefine HAVE_LIBZ 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LIMITS_H 1 + +/* Define to 1 if you have the `link' function. */ +#cmakedefine HAVE_LINK 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LINUX_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LINUX_FIEMAP_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LINUX_FS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LINUX_MAGIC_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LINUX_TYPES_H 1 + +/* Define to 1 if you have the `listea' function. */ +#cmakedefine HAVE_LISTEA 1 + +/* Define to 1 if you have the `listxattr' function. */ +#cmakedefine HAVE_LISTXATTR 1 + +/* Define to 1 if you have the `llistea' function. */ +#cmakedefine HAVE_LLISTEA 1 + +/* Define to 1 if you have the `llistxattr' function. */ +#cmakedefine HAVE_LLISTXATTR 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LOCALCHARSET_H 1 + +/* Define to 1 if you have the `locale_charset' function. */ +#cmakedefine HAVE_LOCALE_CHARSET 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LOCALE_H 1 + +/* Define to 1 if you have the `localtime_r' function. */ +#cmakedefine HAVE_LOCALTIME_R 1 + +/* Define to 1 if the system has the type `long long int'. */ +#cmakedefine HAVE_LONG_LONG_INT 1 + +/* Define to 1 if you have the `lsetea' function. */ +#cmakedefine HAVE_LSETEA 1 + +/* Define to 1 if you have the `lsetxattr' function. */ +#cmakedefine HAVE_LSETXATTR 1 + +/* Define to 1 if you have the `lstat' function. */ +#cmakedefine HAVE_LSTAT 1 + +/* Define to 1 if `lstat' has the bug that it succeeds when given the + zero-length file name argument. */ +#cmakedefine HAVE_LSTAT_EMPTY_STRING_BUG 1 + +/* Define to 1 if you have the `lutimes' function. */ +#cmakedefine HAVE_LUTIMES 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LZ4HC_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LZ4_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LZMADEC_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LZMA_H 1 + ++/* Define to 1 if you have a working `lzma_stream_encoder_mt' function. */ ++#cmakedefine HAVE_LZMA_STREAM_ENCODER_MT 1 ++ +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LZO_LZO1X_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LZO_LZOCONF_H 1 + +/* Define to 1 if you have the `mbrtowc' function. */ +#cmakedefine HAVE_MBRTOWC 1 + +/* Define to 1 if you have the `memmove' function. */ +#cmakedefine HAVE_MEMMOVE 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mkdir' function. */ +#cmakedefine HAVE_MKDIR 1 + +/* Define to 1 if you have the `mkfifo' function. */ +#cmakedefine HAVE_MKFIFO 1 + +/* Define to 1 if you have the `mknod' function. */ +#cmakedefine HAVE_MKNOD 1 + +/* Define to 1 if you have the `mkstemp' function. */ +#cmakedefine HAVE_MKSTEMP 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +#cmakedefine HAVE_NDIR_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETTLE_AES_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETTLE_HMAC_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETTLE_MD5_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETTLE_PBKDF2_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETTLE_RIPEMD160_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETTLE_SHA_H 1 + +/* Define to 1 if you have the `nl_langinfo' function. */ +#cmakedefine HAVE_NL_LANGINFO 1 + +/* Define to 1 if you have the `openat' function. */ +#cmakedefine HAVE_OPENAT 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_PATHS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_PCREPOSIX_H 1 + +/* Define to 1 if you have the `pipe' function. */ +#cmakedefine HAVE_PIPE 1 + +/* Define to 1 if you have the `PKCS5_PBKDF2_HMAC_SHA1' function. */ +#cmakedefine HAVE_PKCS5_PBKDF2_HMAC_SHA1 1 + +/* Define to 1 if you have the `poll' function. */ +#cmakedefine HAVE_POLL 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_POLL_H 1 + +/* Define to 1 if you have the `posix_spawnp' function. */ +#cmakedefine HAVE_POSIX_SPAWNP 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_PROCESS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_PTHREAD_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_PWD_H 1 + +/* Define to 1 if you have the `readdir_r' function. */ +#cmakedefine HAVE_READDIR_R 1 + +/* Define to 1 if you have the `readlink' function. */ +#cmakedefine HAVE_READLINK 1 + +/* Define to 1 if you have the `readlinkat' function. */ +#cmakedefine HAVE_READLINKAT 1 + +/* Define to 1 if you have the `readpassphrase' function. */ +#cmakedefine HAVE_READPASSPHRASE 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_READPASSPHRASE_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_REGEX_H 1 + +/* Define to 1 if you have the `select' function. */ +#cmakedefine HAVE_SELECT 1 + +/* Define to 1 if you have the `setenv' function. */ +#cmakedefine HAVE_SETENV 1 + +/* Define to 1 if you have the `setlocale' function. */ +#cmakedefine HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `sigaction' function. */ +#cmakedefine HAVE_SIGACTION 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SPAWN_H 1 + +/* Define to 1 if you have the `statfs' function. */ +#cmakedefine HAVE_STATFS 1 + +/* Define to 1 if you have the `statvfs' function. */ +#cmakedefine HAVE_STATVFS 1 + +/* Define to 1 if `stat' has the bug that it succeeds when given the + zero-length file name argument. */ +#cmakedefine HAVE_STAT_EMPTY_STRING_BUG 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDARG_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strchr' function. */ +#cmakedefine HAVE_STRCHR 1 + +/* Define to 1 if you have the `strdup' function. */ +#cmakedefine HAVE_STRDUP 1 + +/* Define to 1 if you have the `strerror' function. */ +#cmakedefine HAVE_STRERROR 1 + +/* Define to 1 if you have the `strerror_r' function. */ +#cmakedefine HAVE_STRERROR_R 1 + +/* Define to 1 if you have the `strftime' function. */ +#cmakedefine HAVE_STRFTIME 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRING_H 1 + +/* Define to 1 if you have the `strrchr' function. */ +#cmakedefine HAVE_STRRCHR 1 + +/* Define to 1 if `f_namemax' is a member of `struct statfs'. */ +#cmakedefine HAVE_STRUCT_STATFS_F_NAMEMAX 1 + +/* Define to 1 if `f_iosize' is a member of `struct statvfs'. */ +#cmakedefine HAVE_STRUCT_STATVFS_F_IOSIZE 1 + +/* Define to 1 if `st_birthtime' is a member of `struct stat'. */ +#cmakedefine HAVE_STRUCT_STAT_ST_BIRTHTIME 1 + +/* Define to 1 if `st_birthtimespec.tv_nsec' is a member of `struct stat'. */ +#cmakedefine HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC 1 + +/* Define to 1 if `st_blksize' is a member of `struct stat'. */ +#cmakedefine HAVE_STRUCT_STAT_ST_BLKSIZE 1 + +/* Define to 1 if `st_flags' is a member of `struct stat'. */ +#cmakedefine HAVE_STRUCT_STAT_ST_FLAGS 1 + +/* Define to 1 if `st_mtimespec.tv_nsec' is a member of `struct stat'. */ +#cmakedefine HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1 + +/* Define to 1 if `st_mtime_n' is a member of `struct stat'. */ +#cmakedefine HAVE_STRUCT_STAT_ST_MTIME_N 1 + +/* Define to 1 if `st_mtime_usec' is a member of `struct stat'. */ +#cmakedefine HAVE_STRUCT_STAT_ST_MTIME_USEC 1 + +/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */ +#cmakedefine HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 1 + +/* Define to 1 if `st_umtime' is a member of `struct stat'. */ +#cmakedefine HAVE_STRUCT_STAT_ST_UMTIME 1 + +/* Define to 1 if `tm_gmtoff' is a member of `struct tm'. */ +#cmakedefine HAVE_STRUCT_TM_TM_GMTOFF 1 + +/* Define to 1 if `__tm_gmtoff' is a member of `struct tm'. */ +#cmakedefine HAVE_STRUCT_TM___TM_GMTOFF 1 + ++/* Define to 1 if you have `struct vfsconf'. */ ++#cmakedefine HAVE_STRUCT_VFSCONF 1 ++ ++/* Define to 1 if you have `struct xvfsconf'. */ ++#cmakedefine HAVE_STRUCT_XVFSCONF 1 ++ +/* Define to 1 if you have the `symlink' function. */ +#cmakedefine HAVE_SYMLINK 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_ACL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_CDEFS_H 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#cmakedefine HAVE_SYS_DIR_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_EA_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_EXTATTR_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_MKDEV_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_MOUNT_H 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#cmakedefine HAVE_SYS_NDIR_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_POLL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_STATFS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_STATVFS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_UTIME_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_UTSNAME_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_VFS_H 1 + +/* Define to 1 if you have that is POSIX.1 compatible. */ +#cmakedefine HAVE_SYS_WAIT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_XATTR_H 1 + +/* Define to 1 if you have the `timegm' function. */ +#cmakedefine HAVE_TIMEGM 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_TIME_H 1 + +/* Define to 1 if you have the `tzset' function. */ +#cmakedefine HAVE_TZSET 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `unsetenv' function. */ +#cmakedefine HAVE_UNSETENV 1 + +/* Define to 1 if the system has the type `unsigned long long'. */ +#cmakedefine HAVE_UNSIGNED_LONG_LONG 1 + +/* Define to 1 if the system has the type `unsigned long long int'. */ +#cmakedefine HAVE_UNSIGNED_LONG_LONG_INT 1 + +/* Define to 1 if you have the `utime' function. */ +#cmakedefine HAVE_UTIME 1 + +/* Define to 1 if you have the `utimensat' function. */ +#cmakedefine HAVE_UTIMENSAT 1 + +/* Define to 1 if you have the `utimes' function. */ +#cmakedefine HAVE_UTIMES 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UTIME_H 1 + +/* Define to 1 if you have the `vfork' function. */ +#cmakedefine HAVE_VFORK 1 + +/* Define to 1 if you have the `vprintf' function. */ +#cmakedefine HAVE_VPRINTF 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_WCHAR_H 1 + +/* Define to 1 if the system has the type `wchar_t'. */ +#cmakedefine HAVE_WCHAR_T 1 + +/* Define to 1 if you have the `wcrtomb' function. */ +#cmakedefine HAVE_WCRTOMB 1 + +/* Define to 1 if you have the `wcscmp' function. */ +#cmakedefine HAVE_WCSCMP 1 + +/* Define to 1 if you have the `wcscpy' function. */ +#cmakedefine HAVE_WCSCPY 1 + +/* Define to 1 if you have the `wcslen' function. */ +#cmakedefine HAVE_WCSLEN 1 + +/* Define to 1 if you have the `wctomb' function. */ +#cmakedefine HAVE_WCTOMB 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_WCTYPE_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_WINCRYPT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_WINDOWS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_WINIOCTL_H 1 + +/* Define to 1 if you have _CrtSetReportMode in */ +#cmakedefine HAVE__CrtSetReportMode 1 + +/* Define to 1 if you have the `wmemcmp' function. */ +#cmakedefine HAVE_WMEMCMP 1 + +/* Define to 1 if you have the `wmemcpy' function. */ +#cmakedefine HAVE_WMEMCPY 1 + +/* Define to 1 if you have the `wmemmove' function. */ +#cmakedefine HAVE_WMEMMOVE 1 + +/* Define to 1 if you have a working EXT2_IOC_GETFLAGS */ +#cmakedefine HAVE_WORKING_EXT2_IOC_GETFLAGS 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ZLIB_H 1 + +/* Define to 1 if you have the `_ctime64_s' function. */ +#cmakedefine HAVE__CTIME64_S 1 + +/* Define to 1 if you have the `_fseeki64' function. */ +#cmakedefine HAVE__FSEEKI64 1 + +/* Define to 1 if you have the `_get_timezone' function. */ +#cmakedefine HAVE__GET_TIMEZONE 1 + +/* Define to 1 if you have the `_localtime64_s' function. */ +#cmakedefine HAVE__LOCALTIME64_S 1 + +/* Define to 1 if you have the `_mkgmtime64' function. */ +#cmakedefine HAVE__MKGMTIME64 1 + +/* Define as const if the declaration of iconv() needs const. */ +#define ICONV_CONST ${ICONV_CONST} + +/* Version number of libarchive as a single integer */ +#cmakedefine LIBARCHIVE_VERSION_NUMBER "${LIBARCHIVE_VERSION_NUMBER}" + +/* Version number of libarchive */ +#cmakedefine LIBARCHIVE_VERSION_STRING "${LIBARCHIVE_VERSION_STRING}" + +/* Define to 1 if `lstat' dereferences a symlink specified with a trailing + slash. */ +#cmakedefine LSTAT_FOLLOWS_SLASHED_SYMLINK 1 + +/* Define to 1 if `major', `minor', and `makedev' are declared in . + */ +#cmakedefine MAJOR_IN_MKDEV 1 + +/* Define to 1 if `major', `minor', and `makedev' are declared in + . */ +#cmakedefine MAJOR_IN_SYSMACROS 1 + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +#cmakedefine NO_MINUS_C_MINUS_O 1 + +/* The size of `wchar_t', as computed by sizeof. */ +#cmakedefine SIZEOF_WCHAR_T ${SIZEOF_WCHAR_T} + +/* Define to 1 if strerror_r returns char *. */ +#cmakedefine STRERROR_R_CHAR_P 1 + +/* Define to 1 if you can safely include both and . */ +#cmakedefine TIME_WITH_SYS_TIME 1 + +/* + * Some platform requires a macro to use extension functions. + */ +#cmakedefine SAFE_TO_DEFINE_EXTENSIONS 1 +#ifdef SAFE_TO_DEFINE_EXTENSIONS +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# define _ALL_SOURCE 1 +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# define _POSIX_PTHREAD_SEMANTICS 1 +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# define _TANDEM_SOURCE 1 +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# define __EXTENSIONS__ 1 +#endif +#endif /* SAFE_TO_DEFINE_EXTENSIONS */ + +/* Version number of package */ +#cmakedefine VERSION "${VERSION}" + +/* Number of bits in a file offset, on hosts where this is settable. */ +#cmakedefine _FILE_OFFSET_BITS ${_FILE_OFFSET_BITS} + +/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ +#cmakedefine _LARGEFILE_SOURCE 1 + +/* Define for large files, on AIX-style hosts. */ +#cmakedefine _LARGE_FILES ${_LARGE_FILES} + +/* Define to control Windows SDK version */ +#ifndef NTDDI_VERSION +#cmakedefine NTDDI_VERSION ${NTDDI_VERSION} +#endif // NTDDI_VERSION + +#ifndef _WIN32_WINNT +#cmakedefine _WIN32_WINNT ${_WIN32_WINNT} +#endif // _WIN32_WINNT + +#ifndef WINVER +#cmakedefine WINVER ${WINVER} +#endif // WINVER + +/* Define to empty if `const' does not conform to ANSI C. */ +#cmakedefine const ${const} + +/* Define to `int' if doesn't define. */ +#cmakedefine gid_t ${gid_t} + +/* Define to `unsigned long' if does not define. */ +#cmakedefine id_t ${id_t} + +/* Define to `int' if does not define. */ +#cmakedefine mode_t ${mode_t} + +/* Define to `long long' if does not define. */ +#cmakedefine off_t ${off_t} + +/* Define to `int' if doesn't define. */ +#cmakedefine pid_t ${pid_t} + +/* Define to `unsigned int' if does not define. */ +#cmakedefine size_t ${size_t} + +/* Define to `int' if does not define. */ +#cmakedefine ssize_t ${ssize_t} + +/* Define to `int' if doesn't define. */ +#cmakedefine uid_t ${uid_t} + +/* Define to `int' if does not define. */ +#cmakedefine intptr_t ${intptr_t} + +/* Define to `unsigned int' if does not define. */ +#cmakedefine uintptr_t ${uintptr_t} diff --cc Utilities/cmlibarchive/libarchive/CMakeLists.txt index eaa7b20,0000000..d412c80 mode 100644,000000..100644 --- a/Utilities/cmlibarchive/libarchive/CMakeLists.txt +++ b/Utilities/cmlibarchive/libarchive/CMakeLists.txt @@@ -1,197 -1,0 +1,215 @@@ + +############################################ +# +# How to build libarchive +# +############################################ + +# Public headers +SET(include_HEADERS + archive.h + archive_entry.h +) + +# Sources and private headers +SET(libarchive_SOURCES + archive_acl.c + archive_check_magic.c + archive_cmdline.c + archive_cmdline_private.h + archive_crc32.h + archive_cryptor.c + archive_cryptor_private.h + archive_digest.c + archive_digest_private.h + archive_endian.h + archive_entry.c + archive_entry.h + archive_entry_copy_stat.c + archive_entry_link_resolver.c + archive_entry_locale.h + archive_entry_private.h + archive_entry_sparse.c + archive_entry_stat.c + archive_entry_strmode.c + archive_entry_xattr.c + archive_getdate.c + archive_getdate.h + archive_hmac.c + archive_hmac_private.h + archive_match.c + archive_openssl_evp_private.h + archive_openssl_hmac_private.h + archive_options.c + archive_options_private.h + archive_pack_dev.h + archive_pack_dev.c + archive_pathmatch.c + archive_pathmatch.h + archive_platform.h + archive_ppmd_private.h + archive_ppmd7.c + archive_ppmd7_private.h + archive_private.h + archive_random.c + archive_random_private.h + archive_rb.c + archive_rb.h + archive_read.c + archive_read_add_passphrase.c + archive_read_append_filter.c + archive_read_data_into_fd.c + archive_read_disk_entry_from_file.c + archive_read_disk_posix.c + archive_read_disk_private.h + archive_read_disk_set_standard_lookup.c + archive_read_extract.c + archive_read_extract2.c + archive_read_open_fd.c + archive_read_open_file.c + archive_read_open_filename.c + archive_read_open_memory.c + archive_read_private.h + archive_read_set_format.c + archive_read_set_options.c + archive_read_support_filter_all.c + archive_read_support_filter_bzip2.c + archive_read_support_filter_compress.c + archive_read_support_filter_gzip.c + archive_read_support_filter_grzip.c + archive_read_support_filter_lrzip.c + archive_read_support_filter_lz4.c + archive_read_support_filter_lzop.c + archive_read_support_filter_none.c + archive_read_support_filter_program.c + archive_read_support_filter_rpm.c + archive_read_support_filter_uu.c + archive_read_support_filter_xz.c + archive_read_support_format_7zip.c + archive_read_support_format_all.c + archive_read_support_format_ar.c + archive_read_support_format_by_code.c + archive_read_support_format_cab.c + archive_read_support_format_cpio.c + archive_read_support_format_empty.c + archive_read_support_format_iso9660.c + archive_read_support_format_lha.c + archive_read_support_format_mtree.c + archive_read_support_format_rar.c + archive_read_support_format_raw.c + archive_read_support_format_tar.c + archive_read_support_format_warc.c + archive_read_support_format_xar.c + archive_read_support_format_zip.c + archive_string.c + archive_string.h + archive_string_composition.h + archive_string_sprintf.c + archive_util.c + archive_virtual.c + archive_write.c + archive_write_disk_acl.c + archive_write_disk_posix.c + archive_write_disk_private.h + archive_write_disk_set_standard_lookup.c + archive_write_private.h + archive_write_open_fd.c + archive_write_open_file.c + archive_write_open_filename.c + archive_write_open_memory.c + archive_write_add_filter.c + archive_write_add_filter_b64encode.c + archive_write_add_filter_by_name.c + archive_write_add_filter_bzip2.c + archive_write_add_filter_compress.c + archive_write_add_filter_grzip.c + archive_write_add_filter_gzip.c + archive_write_add_filter_lrzip.c + archive_write_add_filter_lz4.c + archive_write_add_filter_lzop.c + archive_write_add_filter_none.c + archive_write_add_filter_program.c + archive_write_add_filter_uuencode.c + archive_write_add_filter_xz.c + archive_write_set_format.c + archive_write_set_format_7zip.c + archive_write_set_format_ar.c + archive_write_set_format_by_name.c + archive_write_set_format_cpio.c + archive_write_set_format_cpio_newc.c + archive_write_set_format_filter_by_ext.c + archive_write_set_format_gnutar.c + archive_write_set_format_iso9660.c + archive_write_set_format_mtree.c + archive_write_set_format_pax.c + archive_write_set_format_raw.c + archive_write_set_format_shar.c + archive_write_set_format_ustar.c + archive_write_set_format_v7tar.c + archive_write_set_format_warc.c + archive_write_set_format_xar.c + archive_write_set_format_zip.c + archive_write_set_options.c + archive_write_set_passphrase.c + archive_xxhash.h + filter_fork_posix.c + filter_fork.h + xxhash.c +) + +# Man pages +SET(libarchive_MANS + archive_entry.3 + archive_entry_acl.3 + archive_entry_linkify.3 + archive_entry_paths.3 + archive_entry_perms.3 + archive_entry_stat.3 + archive_entry_time.3 + archive_read.3 + archive_read_add_passphrase.3 ++ archive_read_data.3 + archive_read_disk.3 ++ archive_read_extract.3 ++ archive_read_filter.3 ++ archive_read_format.3 ++ archive_read_free.3 ++ archive_read_header.3 ++ archive_read_new.3 ++ archive_read_open.3 + archive_read_set_options.3 + archive_util.3 + archive_write.3 ++ archive_write_blocksize.3 ++ archive_write_data.3 + archive_write_disk.3 ++ archive_write_filter.3 ++ archive_write_finish_entry.3 ++ archive_write_format.3 ++ archive_write_free.3 ++ archive_write_header.3 ++ archive_write_new.3 ++ archive_write_open.3 + archive_write_set_options.3 + archive_write_set_passphrase.3 + cpio.5 + libarchive.3 ++ libarchive_changes.3 + libarchive_internals.3 + libarchive-formats.5 + mtree.5 + tar.5 +) + +IF(WIN32 AND NOT CYGWIN) + LIST(APPEND libarchive_SOURCES archive_entry_copy_bhfi.c) + LIST(APPEND libarchive_SOURCES archive_read_disk_windows.c) + LIST(APPEND libarchive_SOURCES archive_windows.c) + LIST(APPEND libarchive_SOURCES archive_windows.h) + LIST(APPEND libarchive_SOURCES archive_write_disk_windows.c) + LIST(APPEND libarchive_SOURCES filter_fork_windows.c) +ENDIF(WIN32 AND NOT CYGWIN) + +# CMake needs just one static "cmlibarchive" library. +ADD_LIBRARY(cmlibarchive STATIC ${libarchive_SOURCES} ${include_HEADERS}) +TARGET_LINK_LIBRARIES(cmlibarchive ${ADDITIONAL_LIBS}) diff --cc Utilities/cmlibarchive/libarchive/archive.h index 3b5104b,0000000..040f151 mode 100644,000000..100644 --- a/Utilities/cmlibarchive/libarchive/archive.h +++ b/Utilities/cmlibarchive/libarchive/archive.h @@@ -1,1180 -1,0 +1,1180 @@@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: src/lib/libarchive/archive.h.in,v 1.50 2008/05/26 17:00:22 kientzle Exp $ + */ + +#ifndef ARCHIVE_H_INCLUDED +#define ARCHIVE_H_INCLUDED + +/* + * The version number is expressed as a single integer that makes it + * easy to compare versions at build time: for version a.b.c, the + * version number is printf("%d%03d%03d",a,b,c). For example, if you + * know your application requires version 2.12.108 or later, you can + * assert that ARCHIVE_VERSION_NUMBER >= 2012108. + */ +/* Note: Compiler will complain if this does not match archive_entry.h! */ - #define ARCHIVE_VERSION_NUMBER 3002001 ++#define ARCHIVE_VERSION_NUMBER 3003000 + +#include +#include /* for wchar_t */ +#include /* For FILE * */ +#include /* For time_t */ + +/* + * Note: archive.h is for use outside of libarchive; the configuration + * headers (config.h, archive_platform.h, etc.) are purely internal. + * Do NOT use HAVE_XXX configuration macros to control the behavior of + * this header! If you must conditionalize, use predefined compiler and/or + * platform macros. + */ +#if defined(__BORLANDC__) && __BORLANDC__ >= 0x560 +# include +#elif !defined(__WATCOMC__) && !defined(_MSC_VER) && !defined(__INTERIX) && !defined(__BORLANDC__) && !defined(_SCO_DS) && !defined(__osf__) +# include +#endif + +/* Get appropriate definitions of 64-bit integer */ +#if !defined(__LA_INT64_T_DEFINED) +/* Older code relied on the __LA_INT64_T macro; after 4.0 we'll switch to the typedef exclusively. */ +# if ARCHIVE_VERSION_NUMBER < 4000000 +#define __LA_INT64_T la_int64_t +# endif +#define __LA_INT64_T_DEFINED +# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__) +typedef __int64 la_int64_t; +# else +# include /* ssize_t */ +# if defined(_SCO_DS) || defined(__osf__) +typedef long long la_int64_t; +# else +typedef int64_t la_int64_t; +# endif +# endif +#endif + +/* The la_ssize_t should match the type used in 'struct stat' */ +#if !defined(__LA_SSIZE_T_DEFINED) +/* Older code relied on the __LA_SSIZE_T macro; after 4.0 we'll switch to the typedef exclusively. */ +# if ARCHIVE_VERSION_NUMBER < 4000000 +#define __LA_SSIZE_T la_ssize_t +# endif +#define __LA_SSIZE_T_DEFINED +# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__) +# if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_) +typedef ssize_t la_ssize_t; +# elif defined(_WIN64) +typedef __int64 la_ssize_t; +# else +typedef long la_ssize_t; +# endif +# else +# include /* ssize_t */ +typedef ssize_t la_ssize_t; +# endif +#endif + +/* Large file support for Android */ +#ifdef __ANDROID__ +#include "android_lf.h" +#endif + +/* + * On Windows, define LIBARCHIVE_STATIC if you're building or using a + * .lib. The default here assumes you're building a DLL. Only + * libarchive source should ever define __LIBARCHIVE_BUILD. + */ +#if ((defined __WIN32__) || (defined _WIN32) || defined(__CYGWIN__)) && (!defined LIBARCHIVE_STATIC) +# ifdef __LIBARCHIVE_BUILD +# ifdef __GNUC__ +# define __LA_DECL __attribute__((dllexport)) extern +# else +# define __LA_DECL __declspec(dllexport) +# endif +# else +# ifdef __GNUC__ +# define __LA_DECL +# else +# define __LA_DECL __declspec(dllimport) +# endif +# endif +#else +/* Static libraries or non-Windows needs no special declaration. */ +# define __LA_DECL +#endif + +#if defined(__GNUC__) && __GNUC__ >= 3 && !defined(__MINGW32__) +#define __LA_PRINTF(fmtarg, firstvararg) \ + __attribute__((__format__ (__printf__, fmtarg, firstvararg))) +#else +#define __LA_PRINTF(fmtarg, firstvararg) /* nothing */ +#endif + +/* CMake uses some deprecated APIs to build with old libarchive versions. */ +#define __LA_DEPRECATED + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The version number is provided as both a macro and a function. + * The macro identifies the installed header; the function identifies + * the library version (which may not be the same if you're using a + * dynamically-linked version of the library). Of course, if the + * header and library are very different, you should expect some + * strangeness. Don't do that. + */ +__LA_DECL int archive_version_number(void); + +/* + * Textual name/version of the library, useful for version displays. + */ - #define ARCHIVE_VERSION_ONLY_STRING "3.2.1" ++#define ARCHIVE_VERSION_ONLY_STRING "3.3.0" +#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING +__LA_DECL const char * archive_version_string(void); + +/* + * Detailed textual name/version of the library and its dependencies. + * This has the form: + * "libarchive x.y.z zlib/a.b.c liblzma/d.e.f ... etc ..." + * the list of libraries described here will vary depending on how + * libarchive was compiled. + */ +__LA_DECL const char * archive_version_details(void); + +/* + * Returns NULL if libarchive was compiled without the associated library. + * Otherwise, returns the version number that libarchive was compiled + * against. + */ +__LA_DECL const char * archive_zlib_version(void); +__LA_DECL const char * archive_liblzma_version(void); +__LA_DECL const char * archive_bzlib_version(void); +__LA_DECL const char * archive_liblz4_version(void); + +/* Declare our basic types. */ +struct archive; +struct archive_entry; + +/* + * Error codes: Use archive_errno() and archive_error_string() + * to retrieve details. Unless specified otherwise, all functions + * that return 'int' use these codes. + */ +#define ARCHIVE_EOF 1 /* Found end of archive. */ +#define ARCHIVE_OK 0 /* Operation was successful. */ +#define ARCHIVE_RETRY (-10) /* Retry might succeed. */ +#define ARCHIVE_WARN (-20) /* Partial success. */ +/* For example, if write_header "fails", then you can't push data. */ +#define ARCHIVE_FAILED (-25) /* Current operation cannot complete. */ +/* But if write_header is "fatal," then this archive is dead and useless. */ +#define ARCHIVE_FATAL (-30) /* No more operations are possible. */ + +/* + * As far as possible, archive_errno returns standard platform errno codes. + * Of course, the details vary by platform, so the actual definitions + * here are stored in "archive_platform.h". The symbols are listed here + * for reference; as a rule, clients should not need to know the exact + * platform-dependent error code. + */ +/* Unrecognized or invalid file format. */ +/* #define ARCHIVE_ERRNO_FILE_FORMAT */ +/* Illegal usage of the library. */ +/* #define ARCHIVE_ERRNO_PROGRAMMER_ERROR */ +/* Unknown or unclassified error. */ +/* #define ARCHIVE_ERRNO_MISC */ + +/* + * Callbacks are invoked to automatically read/skip/write/open/close the + * archive. You can provide your own for complex tasks (like breaking + * archives across multiple tapes) or use standard ones built into the + * library. + */ + +/* Returns pointer and size of next block of data from archive. */ +typedef la_ssize_t archive_read_callback(struct archive *, + void *_client_data, const void **_buffer); + +/* Skips at most request bytes from archive and returns the skipped amount. + * This may skip fewer bytes than requested; it may even skip zero bytes. + * If you do skip fewer bytes than requested, libarchive will invoke your + * read callback and discard data as necessary to make up the full skip. + */ +typedef la_int64_t archive_skip_callback(struct archive *, + void *_client_data, la_int64_t request); + +/* Seeks to specified location in the file and returns the position. + * Whence values are SEEK_SET, SEEK_CUR, SEEK_END from stdio.h. + * Return ARCHIVE_FATAL if the seek fails for any reason. + */ +typedef la_int64_t archive_seek_callback(struct archive *, + void *_client_data, la_int64_t offset, int whence); + +/* Returns size actually written, zero on EOF, -1 on error. */ +typedef la_ssize_t archive_write_callback(struct archive *, + void *_client_data, + const void *_buffer, size_t _length); + +typedef int archive_open_callback(struct archive *, void *_client_data); + +typedef int archive_close_callback(struct archive *, void *_client_data); + +/* Switches from one client data object to the next/prev client data object. + * This is useful for reading from different data blocks such as a set of files + * that make up one large file. + */ +typedef int archive_switch_callback(struct archive *, void *_client_data1, + void *_client_data2); + +/* + * Returns a passphrase used for encryption or decryption, NULL on nothing + * to do and give it up. + */ +typedef const char *archive_passphrase_callback(struct archive *, + void *_client_data); + +/* + * Codes to identify various stream filters. + */ +#define ARCHIVE_FILTER_NONE 0 +#define ARCHIVE_FILTER_GZIP 1 +#define ARCHIVE_FILTER_BZIP2 2 +#define ARCHIVE_FILTER_COMPRESS 3 +#define ARCHIVE_FILTER_PROGRAM 4 +#define ARCHIVE_FILTER_LZMA 5 +#define ARCHIVE_FILTER_XZ 6 +#define ARCHIVE_FILTER_UU 7 +#define ARCHIVE_FILTER_RPM 8 +#define ARCHIVE_FILTER_LZIP 9 +#define ARCHIVE_FILTER_LRZIP 10 +#define ARCHIVE_FILTER_LZOP 11 +#define ARCHIVE_FILTER_GRZIP 12 +#define ARCHIVE_FILTER_LZ4 13 + +#if ARCHIVE_VERSION_NUMBER < 4000000 +#define ARCHIVE_COMPRESSION_NONE ARCHIVE_FILTER_NONE +#define ARCHIVE_COMPRESSION_GZIP ARCHIVE_FILTER_GZIP +#define ARCHIVE_COMPRESSION_BZIP2 ARCHIVE_FILTER_BZIP2 +#define ARCHIVE_COMPRESSION_COMPRESS ARCHIVE_FILTER_COMPRESS +#define ARCHIVE_COMPRESSION_PROGRAM ARCHIVE_FILTER_PROGRAM +#define ARCHIVE_COMPRESSION_LZMA ARCHIVE_FILTER_LZMA +#define ARCHIVE_COMPRESSION_XZ ARCHIVE_FILTER_XZ +#define ARCHIVE_COMPRESSION_UU ARCHIVE_FILTER_UU +#define ARCHIVE_COMPRESSION_RPM ARCHIVE_FILTER_RPM +#define ARCHIVE_COMPRESSION_LZIP ARCHIVE_FILTER_LZIP +#define ARCHIVE_COMPRESSION_LRZIP ARCHIVE_FILTER_LRZIP +#endif + +/* + * Codes returned by archive_format. + * + * Top 16 bits identifies the format family (e.g., "tar"); lower + * 16 bits indicate the variant. This is updated by read_next_header. + * Note that the lower 16 bits will often vary from entry to entry. + * In some cases, this variation occurs as libarchive learns more about + * the archive (for example, later entries might utilize extensions that + * weren't necessary earlier in the archive; in this case, libarchive + * will change the format code to indicate the extended format that + * was used). In other cases, it's because different tools have + * modified the archive and so different parts of the archive + * actually have slightly different formats. (Both tar and cpio store + * format codes in each entry, so it is quite possible for each + * entry to be in a different format.) + */ +#define ARCHIVE_FORMAT_BASE_MASK 0xff0000 +#define ARCHIVE_FORMAT_CPIO 0x10000 +#define ARCHIVE_FORMAT_CPIO_POSIX (ARCHIVE_FORMAT_CPIO | 1) +#define ARCHIVE_FORMAT_CPIO_BIN_LE (ARCHIVE_FORMAT_CPIO | 2) +#define ARCHIVE_FORMAT_CPIO_BIN_BE (ARCHIVE_FORMAT_CPIO | 3) +#define ARCHIVE_FORMAT_CPIO_SVR4_NOCRC (ARCHIVE_FORMAT_CPIO | 4) +#define ARCHIVE_FORMAT_CPIO_SVR4_CRC (ARCHIVE_FORMAT_CPIO | 5) +#define ARCHIVE_FORMAT_CPIO_AFIO_LARGE (ARCHIVE_FORMAT_CPIO | 6) +#define ARCHIVE_FORMAT_SHAR 0x20000 +#define ARCHIVE_FORMAT_SHAR_BASE (ARCHIVE_FORMAT_SHAR | 1) +#define ARCHIVE_FORMAT_SHAR_DUMP (ARCHIVE_FORMAT_SHAR | 2) +#define ARCHIVE_FORMAT_TAR 0x30000 +#define ARCHIVE_FORMAT_TAR_USTAR (ARCHIVE_FORMAT_TAR | 1) +#define ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE (ARCHIVE_FORMAT_TAR | 2) +#define ARCHIVE_FORMAT_TAR_PAX_RESTRICTED (ARCHIVE_FORMAT_TAR | 3) +#define ARCHIVE_FORMAT_TAR_GNUTAR (ARCHIVE_FORMAT_TAR | 4) +#define ARCHIVE_FORMAT_ISO9660 0x40000 +#define ARCHIVE_FORMAT_ISO9660_ROCKRIDGE (ARCHIVE_FORMAT_ISO9660 | 1) +#define ARCHIVE_FORMAT_ZIP 0x50000 +#define ARCHIVE_FORMAT_EMPTY 0x60000 +#define ARCHIVE_FORMAT_AR 0x70000 +#define ARCHIVE_FORMAT_AR_GNU (ARCHIVE_FORMAT_AR | 1) +#define ARCHIVE_FORMAT_AR_BSD (ARCHIVE_FORMAT_AR | 2) +#define ARCHIVE_FORMAT_MTREE 0x80000 +#define ARCHIVE_FORMAT_RAW 0x90000 +#define ARCHIVE_FORMAT_XAR 0xA0000 +#define ARCHIVE_FORMAT_LHA 0xB0000 +#define ARCHIVE_FORMAT_CAB 0xC0000 +#define ARCHIVE_FORMAT_RAR 0xD0000 +#define ARCHIVE_FORMAT_7ZIP 0xE0000 +#define ARCHIVE_FORMAT_WARC 0xF0000 + +/* + * Codes returned by archive_read_format_capabilities(). + * + * This list can be extended with values between 0 and 0xffff. + * The original purpose of this list was to let different archive + * format readers expose their general capabilities in terms of + * encryption. + */ +#define ARCHIVE_READ_FORMAT_CAPS_NONE (0) /* no special capabilities */ +#define ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA (1<<0) /* reader can detect encrypted data */ +#define ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA (1<<1) /* reader can detect encryptable metadata (pathname, mtime, etc.) */ + +/* + * Codes returned by archive_read_has_encrypted_entries(). + * + * In case the archive does not support encryption detection at all + * ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED is returned. If the reader + * for some other reason (e.g. not enough bytes read) cannot say if + * there are encrypted entries, ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW + * is returned. + */ +#define ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED -2 +#define ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW -1 + +/*- + * Basic outline for reading an archive: + * 1) Ask archive_read_new for an archive reader object. + * 2) Update any global properties as appropriate. + * In particular, you'll certainly want to call appropriate + * archive_read_support_XXX functions. + * 3) Call archive_read_open_XXX to open the archive + * 4) Repeatedly call archive_read_next_header to get information about + * successive archive entries. Call archive_read_data to extract + * data for entries of interest. - * 5) Call archive_read_finish to end processing. ++ * 5) Call archive_read_free to end processing. + */ +__LA_DECL struct archive *archive_read_new(void); + +/* + * The archive_read_support_XXX calls enable auto-detect for this + * archive handle. They also link in the necessary support code. + * For example, if you don't want bzlib linked in, don't invoke + * support_compression_bzip2(). The "all" functions provide the + * obvious shorthand. + */ + +#if ARCHIVE_VERSION_NUMBER < 4000000 +__LA_DECL int archive_read_support_compression_all(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_bzip2(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_compress(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_gzip(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_lzip(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_lzma(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_none(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_program(struct archive *, + const char *command) __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_program_signature + (struct archive *, const char *, + const void * /* match */, size_t) __LA_DEPRECATED; + +__LA_DECL int archive_read_support_compression_rpm(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_uu(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_xz(struct archive *) + __LA_DEPRECATED; +#endif + +__LA_DECL int archive_read_support_filter_all(struct archive *); +__LA_DECL int archive_read_support_filter_bzip2(struct archive *); +__LA_DECL int archive_read_support_filter_compress(struct archive *); +__LA_DECL int archive_read_support_filter_gzip(struct archive *); +__LA_DECL int archive_read_support_filter_grzip(struct archive *); +__LA_DECL int archive_read_support_filter_lrzip(struct archive *); +__LA_DECL int archive_read_support_filter_lz4(struct archive *); +__LA_DECL int archive_read_support_filter_lzip(struct archive *); +__LA_DECL int archive_read_support_filter_lzma(struct archive *); +__LA_DECL int archive_read_support_filter_lzop(struct archive *); +__LA_DECL int archive_read_support_filter_none(struct archive *); +__LA_DECL int archive_read_support_filter_program(struct archive *, + const char *command); +__LA_DECL int archive_read_support_filter_program_signature + (struct archive *, const char * /* cmd */, + const void * /* match */, size_t); +__LA_DECL int archive_read_support_filter_rpm(struct archive *); +__LA_DECL int archive_read_support_filter_uu(struct archive *); +__LA_DECL int archive_read_support_filter_xz(struct archive *); + +__LA_DECL int archive_read_support_format_7zip(struct archive *); +__LA_DECL int archive_read_support_format_all(struct archive *); +__LA_DECL int archive_read_support_format_ar(struct archive *); +__LA_DECL int archive_read_support_format_by_code(struct archive *, int); +__LA_DECL int archive_read_support_format_cab(struct archive *); +__LA_DECL int archive_read_support_format_cpio(struct archive *); +__LA_DECL int archive_read_support_format_empty(struct archive *); +__LA_DECL int archive_read_support_format_gnutar(struct archive *); +__LA_DECL int archive_read_support_format_iso9660(struct archive *); +__LA_DECL int archive_read_support_format_lha(struct archive *); +__LA_DECL int archive_read_support_format_mtree(struct archive *); +__LA_DECL int archive_read_support_format_rar(struct archive *); +__LA_DECL int archive_read_support_format_raw(struct archive *); +__LA_DECL int archive_read_support_format_tar(struct archive *); +__LA_DECL int archive_read_support_format_warc(struct archive *); +__LA_DECL int archive_read_support_format_xar(struct archive *); +/* archive_read_support_format_zip() enables both streamable and seekable + * zip readers. */ +__LA_DECL int archive_read_support_format_zip(struct archive *); +/* Reads Zip archives as stream from beginning to end. Doesn't + * correctly handle SFX ZIP files or ZIP archives that have been modified + * in-place. */ +__LA_DECL int archive_read_support_format_zip_streamable(struct archive *); +/* Reads starting from central directory; requires seekable input. */ +__LA_DECL int archive_read_support_format_zip_seekable(struct archive *); + +/* Functions to manually set the format and filters to be used. This is + * useful to bypass the bidding process when the format and filters to use + * is known in advance. + */ +__LA_DECL int archive_read_set_format(struct archive *, int); +__LA_DECL int archive_read_append_filter(struct archive *, int); +__LA_DECL int archive_read_append_filter_program(struct archive *, + const char *); +__LA_DECL int archive_read_append_filter_program_signature + (struct archive *, const char *, const void * /* match */, size_t); + +/* Set various callbacks. */ +__LA_DECL int archive_read_set_open_callback(struct archive *, + archive_open_callback *); +__LA_DECL int archive_read_set_read_callback(struct archive *, + archive_read_callback *); +__LA_DECL int archive_read_set_seek_callback(struct archive *, + archive_seek_callback *); +__LA_DECL int archive_read_set_skip_callback(struct archive *, + archive_skip_callback *); +__LA_DECL int archive_read_set_close_callback(struct archive *, + archive_close_callback *); +/* Callback used to switch between one data object to the next */ +__LA_DECL int archive_read_set_switch_callback(struct archive *, + archive_switch_callback *); + +/* This sets the first data object. */ +__LA_DECL int archive_read_set_callback_data(struct archive *, void *); +/* This sets data object at specified index */ +__LA_DECL int archive_read_set_callback_data2(struct archive *, void *, + unsigned int); +/* This adds a data object at the specified index. */ +__LA_DECL int archive_read_add_callback_data(struct archive *, void *, + unsigned int); +/* This appends a data object to the end of list */ +__LA_DECL int archive_read_append_callback_data(struct archive *, void *); +/* This prepends a data object to the beginning of list */ +__LA_DECL int archive_read_prepend_callback_data(struct archive *, void *); + +/* Opening freezes the callbacks. */ +__LA_DECL int archive_read_open1(struct archive *); + +/* Convenience wrappers around the above. */ +__LA_DECL int archive_read_open(struct archive *, void *_client_data, + archive_open_callback *, archive_read_callback *, + archive_close_callback *); +__LA_DECL int archive_read_open2(struct archive *, void *_client_data, + archive_open_callback *, archive_read_callback *, + archive_skip_callback *, archive_close_callback *); + +/* + * A variety of shortcuts that invoke archive_read_open() with + * canned callbacks suitable for common situations. The ones that + * accept a block size handle tape blocking correctly. + */ +/* Use this if you know the filename. Note: NULL indicates stdin. */ +__LA_DECL int archive_read_open_filename(struct archive *, + const char *_filename, size_t _block_size); +/* Use this for reading multivolume files by filenames. + * NOTE: Must be NULL terminated. Sorting is NOT done. */ +__LA_DECL int archive_read_open_filenames(struct archive *, + const char **_filenames, size_t _block_size); +__LA_DECL int archive_read_open_filename_w(struct archive *, + const wchar_t *_filename, size_t _block_size); +/* archive_read_open_file() is a deprecated synonym for ..._open_filename(). */ +__LA_DECL int archive_read_open_file(struct archive *, + const char *_filename, size_t _block_size) __LA_DEPRECATED; +/* Read an archive that's stored in memory. */ +__LA_DECL int archive_read_open_memory(struct archive *, + const void * buff, size_t size); +/* A more involved version that is only used for internal testing. */ +__LA_DECL int archive_read_open_memory2(struct archive *a, const void *buff, + size_t size, size_t read_size); +/* Read an archive that's already open, using the file descriptor. */ +__LA_DECL int archive_read_open_fd(struct archive *, int _fd, + size_t _block_size); +/* Read an archive that's already open, using a FILE *. */ +/* Note: DO NOT use this with tape drives. */ +__LA_DECL int archive_read_open_FILE(struct archive *, FILE *_file); + +/* Parses and returns next entry header. */ +__LA_DECL int archive_read_next_header(struct archive *, + struct archive_entry **); + +/* Parses and returns next entry header using the archive_entry passed in */ +__LA_DECL int archive_read_next_header2(struct archive *, + struct archive_entry *); + +/* + * Retrieve the byte offset in UNCOMPRESSED data where last-read + * header started. + */ +__LA_DECL la_int64_t archive_read_header_position(struct archive *); + +/* + * Returns 1 if the archive contains at least one encrypted entry. + * If the archive format not support encryption at all + * ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED is returned. + * If for any other reason (e.g. not enough data read so far) + * we cannot say whether there are encrypted entries, then + * ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned. + * In general, this function will return values below zero when the - * reader is uncertain or totally uncapable of encryption support. ++ * reader is uncertain or totally incapable of encryption support. + * When this function returns 0 you can be sure that the reader + * supports encryption detection but no encrypted entries have + * been found yet. + * + * NOTE: If the metadata/header of an archive is also encrypted, you + * cannot rely on the number of encrypted entries. That is why this + * function does not return the number of encrypted entries but# + * just shows that there are some. + */ +__LA_DECL int archive_read_has_encrypted_entries(struct archive *); + +/* + * Returns a bitmask of capabilities that are supported by the archive format reader. + * If the reader has no special capabilities, ARCHIVE_READ_FORMAT_CAPS_NONE is returned. + */ +__LA_DECL int archive_read_format_capabilities(struct archive *); + +/* Read data from the body of an entry. Similar to read(2). */ +__LA_DECL la_ssize_t archive_read_data(struct archive *, + void *, size_t); + +/* Seek within the body of an entry. Similar to lseek(2). */ +__LA_DECL la_int64_t archive_seek_data(struct archive *, la_int64_t, int); + +/* + * A zero-copy version of archive_read_data that also exposes the file offset + * of each returned block. Note that the client has no way to specify + * the desired size of the block. The API does guarantee that offsets will + * be strictly increasing and that returned blocks will not overlap. + */ +__LA_DECL int archive_read_data_block(struct archive *a, + const void **buff, size_t *size, la_int64_t *offset); + +/*- + * Some convenience functions that are built on archive_read_data: + * 'skip': skips entire entry + * 'into_buffer': writes data into memory buffer that you provide + * 'into_fd': writes data to specified filedes + */ +__LA_DECL int archive_read_data_skip(struct archive *); +__LA_DECL int archive_read_data_into_fd(struct archive *, int fd); + +/* + * Set read options. + */ +/* Apply option to the format only. */ +__LA_DECL int archive_read_set_format_option(struct archive *_a, + const char *m, const char *o, + const char *v); +/* Apply option to the filter only. */ +__LA_DECL int archive_read_set_filter_option(struct archive *_a, + const char *m, const char *o, + const char *v); +/* Apply option to both the format and the filter. */ +__LA_DECL int archive_read_set_option(struct archive *_a, + const char *m, const char *o, + const char *v); +/* Apply option string to both the format and the filter. */ +__LA_DECL int archive_read_set_options(struct archive *_a, + const char *opts); + +/* + * Add a decryption passphrase. + */ +__LA_DECL int archive_read_add_passphrase(struct archive *, const char *); +__LA_DECL int archive_read_set_passphrase_callback(struct archive *, + void *client_data, archive_passphrase_callback *); + + +/*- + * Convenience function to recreate the current entry (whose header + * has just been read) on disk. + * + * This does quite a bit more than just copy data to disk. It also: + * - Creates intermediate directories as required. + * - Manages directory permissions: non-writable directories will + * be initially created with write permission enabled; when the + * archive is closed, dir permissions are edited to the values specified + * in the archive. + * - Checks hardlinks: hardlinks will not be extracted unless the + * linked-to file was also extracted within the same session. (TODO) + */ + +/* The "flags" argument selects optional behavior, 'OR' the flags you want. */ + +/* Default: Do not try to set owner/group. */ +#define ARCHIVE_EXTRACT_OWNER (0x0001) +/* Default: Do obey umask, do not restore SUID/SGID/SVTX bits. */ +#define ARCHIVE_EXTRACT_PERM (0x0002) +/* Default: Do not restore mtime/atime. */ +#define ARCHIVE_EXTRACT_TIME (0x0004) +/* Default: Replace existing files. */ +#define ARCHIVE_EXTRACT_NO_OVERWRITE (0x0008) +/* Default: Try create first, unlink only if create fails with EEXIST. */ +#define ARCHIVE_EXTRACT_UNLINK (0x0010) +/* Default: Do not restore ACLs. */ +#define ARCHIVE_EXTRACT_ACL (0x0020) +/* Default: Do not restore fflags. */ +#define ARCHIVE_EXTRACT_FFLAGS (0x0040) +/* Default: Do not restore xattrs. */ +#define ARCHIVE_EXTRACT_XATTR (0x0080) +/* Default: Do not try to guard against extracts redirected by symlinks. */ +/* Note: With ARCHIVE_EXTRACT_UNLINK, will remove any intermediate symlink. */ +#define ARCHIVE_EXTRACT_SECURE_SYMLINKS (0x0100) +/* Default: Do not reject entries with '..' as path elements. */ +#define ARCHIVE_EXTRACT_SECURE_NODOTDOT (0x0200) +/* Default: Create parent directories as needed. */ +#define ARCHIVE_EXTRACT_NO_AUTODIR (0x0400) +/* Default: Overwrite files, even if one on disk is newer. */ +#define ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER (0x0800) +/* Detect blocks of 0 and write holes instead. */ +#define ARCHIVE_EXTRACT_SPARSE (0x1000) +/* Default: Do not restore Mac extended metadata. */ +/* This has no effect except on Mac OS. */ +#define ARCHIVE_EXTRACT_MAC_METADATA (0x2000) +/* Default: Use HFS+ compression if it was compressed. */ +/* This has no effect except on Mac OS v10.6 or later. */ +#define ARCHIVE_EXTRACT_NO_HFS_COMPRESSION (0x4000) +/* Default: Do not use HFS+ compression if it was not compressed. */ +/* This has no effect except on Mac OS v10.6 or later. */ +#define ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED (0x8000) +/* Default: Do not reject entries with absolute paths */ +#define ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS (0x10000) +/* Default: Do not clear no-change flags when unlinking object */ +#define ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS (0x20000) + +__LA_DECL int archive_read_extract(struct archive *, struct archive_entry *, + int flags); +__LA_DECL int archive_read_extract2(struct archive *, struct archive_entry *, + struct archive * /* dest */); +__LA_DECL void archive_read_extract_set_progress_callback(struct archive *, + void (*_progress_func)(void *), void *_user_data); + +/* Record the dev/ino of a file that will not be written. This is + * generally set to the dev/ino of the archive being read. */ +__LA_DECL void archive_read_extract_set_skip_file(struct archive *, + la_int64_t, la_int64_t); + +/* Close the file and release most resources. */ +__LA_DECL int archive_read_close(struct archive *); +/* Release all resources and destroy the object. */ +/* Note that archive_read_free will call archive_read_close for you. */ +__LA_DECL int archive_read_free(struct archive *); +#if ARCHIVE_VERSION_NUMBER < 4000000 +/* Synonym for archive_read_free() for backwards compatibility. */ +__LA_DECL int archive_read_finish(struct archive *) __LA_DEPRECATED; +#endif + +/*- + * To create an archive: + * 1) Ask archive_write_new for an archive writer object. + * 2) Set any global properties. In particular, you should set + * the compression and format to use. + * 3) Call archive_write_open to open the file (most people + * will use archive_write_open_file or archive_write_open_fd, + * which provide convenient canned I/O callbacks for you). + * 4) For each entry: + * - construct an appropriate struct archive_entry structure + * - archive_write_header to write the header + * - archive_write_data to write the entry data + * 5) archive_write_close to close the output + * 6) archive_write_free to cleanup the writer and release resources + */ +__LA_DECL struct archive *archive_write_new(void); +__LA_DECL int archive_write_set_bytes_per_block(struct archive *, + int bytes_per_block); +__LA_DECL int archive_write_get_bytes_per_block(struct archive *); +/* XXX This is badly misnamed; suggestions appreciated. XXX */ +__LA_DECL int archive_write_set_bytes_in_last_block(struct archive *, + int bytes_in_last_block); +__LA_DECL int archive_write_get_bytes_in_last_block(struct archive *); + +/* The dev/ino of a file that won't be archived. This is used + * to avoid recursively adding an archive to itself. */ +__LA_DECL int archive_write_set_skip_file(struct archive *, + la_int64_t, la_int64_t); + +#if ARCHIVE_VERSION_NUMBER < 4000000 +__LA_DECL int archive_write_set_compression_bzip2(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_compress(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_gzip(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_lzip(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_lzma(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_none(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_program(struct archive *, + const char *cmd) __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_xz(struct archive *) + __LA_DEPRECATED; +#endif + +/* A convenience function to set the filter based on the code. */ +__LA_DECL int archive_write_add_filter(struct archive *, int filter_code); +__LA_DECL int archive_write_add_filter_by_name(struct archive *, + const char *name); +__LA_DECL int archive_write_add_filter_b64encode(struct archive *); +__LA_DECL int archive_write_add_filter_bzip2(struct archive *); +__LA_DECL int archive_write_add_filter_compress(struct archive *); +__LA_DECL int archive_write_add_filter_grzip(struct archive *); +__LA_DECL int archive_write_add_filter_gzip(struct archive *); +__LA_DECL int archive_write_add_filter_lrzip(struct archive *); +__LA_DECL int archive_write_add_filter_lz4(struct archive *); +__LA_DECL int archive_write_add_filter_lzip(struct archive *); +__LA_DECL int archive_write_add_filter_lzma(struct archive *); +__LA_DECL int archive_write_add_filter_lzop(struct archive *); +__LA_DECL int archive_write_add_filter_none(struct archive *); +__LA_DECL int archive_write_add_filter_program(struct archive *, + const char *cmd); +__LA_DECL int archive_write_add_filter_uuencode(struct archive *); +__LA_DECL int archive_write_add_filter_xz(struct archive *); + + +/* A convenience function to set the format based on the code or name. */ +__LA_DECL int archive_write_set_format(struct archive *, int format_code); +__LA_DECL int archive_write_set_format_by_name(struct archive *, + const char *name); +/* To minimize link pollution, use one or more of the following. */ +__LA_DECL int archive_write_set_format_7zip(struct archive *); +__LA_DECL int archive_write_set_format_ar_bsd(struct archive *); +__LA_DECL int archive_write_set_format_ar_svr4(struct archive *); +__LA_DECL int archive_write_set_format_cpio(struct archive *); +__LA_DECL int archive_write_set_format_cpio_newc(struct archive *); +__LA_DECL int archive_write_set_format_gnutar(struct archive *); +__LA_DECL int archive_write_set_format_iso9660(struct archive *); +__LA_DECL int archive_write_set_format_mtree(struct archive *); +__LA_DECL int archive_write_set_format_mtree_classic(struct archive *); +/* TODO: int archive_write_set_format_old_tar(struct archive *); */ +__LA_DECL int archive_write_set_format_pax(struct archive *); +__LA_DECL int archive_write_set_format_pax_restricted(struct archive *); +__LA_DECL int archive_write_set_format_raw(struct archive *); +__LA_DECL int archive_write_set_format_shar(struct archive *); +__LA_DECL int archive_write_set_format_shar_dump(struct archive *); +__LA_DECL int archive_write_set_format_ustar(struct archive *); +__LA_DECL int archive_write_set_format_v7tar(struct archive *); +__LA_DECL int archive_write_set_format_warc(struct archive *); +__LA_DECL int archive_write_set_format_xar(struct archive *); +__LA_DECL int archive_write_set_format_zip(struct archive *); +__LA_DECL int archive_write_set_format_filter_by_ext(struct archive *a, const char *filename); +__LA_DECL int archive_write_set_format_filter_by_ext_def(struct archive *a, const char *filename, const char * def_ext); +__LA_DECL int archive_write_zip_set_compression_deflate(struct archive *); +__LA_DECL int archive_write_zip_set_compression_store(struct archive *); +__LA_DECL int archive_write_open(struct archive *, void *, + archive_open_callback *, archive_write_callback *, + archive_close_callback *); +__LA_DECL int archive_write_open_fd(struct archive *, int _fd); +__LA_DECL int archive_write_open_filename(struct archive *, const char *_file); +__LA_DECL int archive_write_open_filename_w(struct archive *, + const wchar_t *_file); +/* A deprecated synonym for archive_write_open_filename() */ +__LA_DECL int archive_write_open_file(struct archive *, const char *_file) + __LA_DEPRECATED; +__LA_DECL int archive_write_open_FILE(struct archive *, FILE *); +/* _buffSize is the size of the buffer, _used refers to a variable that + * will be updated after each write into the buffer. */ +__LA_DECL int archive_write_open_memory(struct archive *, + void *_buffer, size_t _buffSize, size_t *_used); + +/* + * Note that the library will truncate writes beyond the size provided + * to archive_write_header or pad if the provided data is short. + */ +__LA_DECL int archive_write_header(struct archive *, + struct archive_entry *); +__LA_DECL la_ssize_t archive_write_data(struct archive *, + const void *, size_t); + +/* This interface is currently only available for archive_write_disk handles. */ +__LA_DECL la_ssize_t archive_write_data_block(struct archive *, + const void *, size_t, la_int64_t); + +__LA_DECL int archive_write_finish_entry(struct archive *); +__LA_DECL int archive_write_close(struct archive *); +/* Marks the archive as FATAL so that a subsequent free() operation + * won't try to close() cleanly. Provides a fast abort capability + * when the client discovers that things have gone wrong. */ +__LA_DECL int archive_write_fail(struct archive *); +/* This can fail if the archive wasn't already closed, in which case + * archive_write_free() will implicitly call archive_write_close(). */ +__LA_DECL int archive_write_free(struct archive *); +#if ARCHIVE_VERSION_NUMBER < 4000000 +/* Synonym for archive_write_free() for backwards compatibility. */ +__LA_DECL int archive_write_finish(struct archive *) __LA_DEPRECATED; +#endif + +/* + * Set write options. + */ +/* Apply option to the format only. */ +__LA_DECL int archive_write_set_format_option(struct archive *_a, + const char *m, const char *o, + const char *v); +/* Apply option to the filter only. */ +__LA_DECL int archive_write_set_filter_option(struct archive *_a, + const char *m, const char *o, + const char *v); +/* Apply option to both the format and the filter. */ +__LA_DECL int archive_write_set_option(struct archive *_a, + const char *m, const char *o, + const char *v); +/* Apply option string to both the format and the filter. */ +__LA_DECL int archive_write_set_options(struct archive *_a, + const char *opts); + +/* + * Set a encryption passphrase. + */ +__LA_DECL int archive_write_set_passphrase(struct archive *_a, const char *p); +__LA_DECL int archive_write_set_passphrase_callback(struct archive *, + void *client_data, archive_passphrase_callback *); + +/*- + * ARCHIVE_WRITE_DISK API + * + * To create objects on disk: + * 1) Ask archive_write_disk_new for a new archive_write_disk object. + * 2) Set any global properties. In particular, you probably + * want to set the options. + * 3) For each entry: + * - construct an appropriate struct archive_entry structure + * - archive_write_header to create the file/dir/etc on disk + * - archive_write_data to write the entry data + * 4) archive_write_free to cleanup the writer and release resources + * + * In particular, you can use this in conjunction with archive_read() + * to pull entries out of an archive and create them on disk. + */ +__LA_DECL struct archive *archive_write_disk_new(void); +/* This file will not be overwritten. */ +__LA_DECL int archive_write_disk_set_skip_file(struct archive *, + la_int64_t, la_int64_t); +/* Set flags to control how the next item gets created. + * This accepts a bitmask of ARCHIVE_EXTRACT_XXX flags defined above. */ +__LA_DECL int archive_write_disk_set_options(struct archive *, + int flags); +/* + * The lookup functions are given uname/uid (or gname/gid) pairs and + * return a uid (gid) suitable for this system. These are used for + * restoring ownership and for setting ACLs. The default functions + * are naive, they just return the uid/gid. These are small, so reasonable + * for applications that don't need to preserve ownership; they + * are probably also appropriate for applications that are doing + * same-system backup and restore. + */ +/* + * The "standard" lookup functions use common system calls to lookup + * the uname/gname, falling back to the uid/gid if the names can't be + * found. They cache lookups and are reasonably fast, but can be very + * large, so they are not used unless you ask for them. In + * particular, these match the specifications of POSIX "pax" and old + * POSIX "tar". + */ +__LA_DECL int archive_write_disk_set_standard_lookup(struct archive *); +/* + * If neither the default (naive) nor the standard (big) functions suit + * your needs, you can write your own and register them. Be sure to + * include a cleanup function if you have allocated private data. + */ +__LA_DECL int archive_write_disk_set_group_lookup(struct archive *, + void * /* private_data */, + la_int64_t (*)(void *, const char *, la_int64_t), + void (* /* cleanup */)(void *)); +__LA_DECL int archive_write_disk_set_user_lookup(struct archive *, + void * /* private_data */, + la_int64_t (*)(void *, const char *, la_int64_t), + void (* /* cleanup */)(void *)); +__LA_DECL la_int64_t archive_write_disk_gid(struct archive *, const char *, la_int64_t); +__LA_DECL la_int64_t archive_write_disk_uid(struct archive *, const char *, la_int64_t); + +/* + * ARCHIVE_READ_DISK API + * + * This is still evolving and somewhat experimental. + */ +__LA_DECL struct archive *archive_read_disk_new(void); +/* The names for symlink modes here correspond to an old BSD + * command-line argument convention: -L, -P, -H */ +/* Follow all symlinks. */ +__LA_DECL int archive_read_disk_set_symlink_logical(struct archive *); +/* Follow no symlinks. */ +__LA_DECL int archive_read_disk_set_symlink_physical(struct archive *); +/* Follow symlink initially, then not. */ +__LA_DECL int archive_read_disk_set_symlink_hybrid(struct archive *); +/* TODO: Handle Linux stat32/stat64 ugliness. */ +__LA_DECL int archive_read_disk_entry_from_file(struct archive *, + struct archive_entry *, int /* fd */, const struct stat *); +/* Look up gname for gid or uname for uid. */ +/* Default implementations are very, very stupid. */ +__LA_DECL const char *archive_read_disk_gname(struct archive *, la_int64_t); +__LA_DECL const char *archive_read_disk_uname(struct archive *, la_int64_t); +/* "Standard" implementation uses getpwuid_r, getgrgid_r and caches the + * results for performance. */ +__LA_DECL int archive_read_disk_set_standard_lookup(struct archive *); +/* You can install your own lookups if you like. */ +__LA_DECL int archive_read_disk_set_gname_lookup(struct archive *, + void * /* private_data */, + const char *(* /* lookup_fn */)(void *, la_int64_t), + void (* /* cleanup_fn */)(void *)); +__LA_DECL int archive_read_disk_set_uname_lookup(struct archive *, + void * /* private_data */, + const char *(* /* lookup_fn */)(void *, la_int64_t), + void (* /* cleanup_fn */)(void *)); +/* Start traversal. */ +__LA_DECL int archive_read_disk_open(struct archive *, const char *); +__LA_DECL int archive_read_disk_open_w(struct archive *, const wchar_t *); +/* + * Request that current entry be visited. If you invoke it on every + * directory, you'll get a physical traversal. This is ignored if the + * current entry isn't a directory or a link to a directory. So, if + * you invoke this on every returned path, you'll get a full logical + * traversal. + */ +__LA_DECL int archive_read_disk_descend(struct archive *); +__LA_DECL int archive_read_disk_can_descend(struct archive *); +__LA_DECL int archive_read_disk_current_filesystem(struct archive *); +__LA_DECL int archive_read_disk_current_filesystem_is_synthetic(struct archive *); +__LA_DECL int archive_read_disk_current_filesystem_is_remote(struct archive *); - /* Request that the access time of the entry visited by travesal be restored. */ ++/* Request that the access time of the entry visited by traversal be restored. */ +__LA_DECL int archive_read_disk_set_atime_restored(struct archive *); +/* + * Set behavior. The "flags" argument selects optional behavior. + */ - /* Request that the access time of the entry visited by travesal be restored. ++/* Request that the access time of the entry visited by traversal be restored. + * This is the same as archive_read_disk_set_atime_restored. */ +#define ARCHIVE_READDISK_RESTORE_ATIME (0x0001) +/* Default: Do not skip an entry which has nodump flags. */ +#define ARCHIVE_READDISK_HONOR_NODUMP (0x0002) +/* Default: Skip a mac resource fork file whose prefix is "._" because of + * using copyfile. */ +#define ARCHIVE_READDISK_MAC_COPYFILE (0x0004) +/* Default: Traverse mount points. */ +#define ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS (0x0008) +/* Default: Xattrs are read from disk. */ +#define ARCHIVE_READDISK_NO_XATTR (0x0010) + +__LA_DECL int archive_read_disk_set_behavior(struct archive *, + int flags); + +/* + * Set archive_match object that will be used in archive_read_disk to + * know whether an entry should be skipped. The callback function + * _excluded_func will be invoked when an entry is skipped by the result + * of archive_match. + */ +__LA_DECL int archive_read_disk_set_matching(struct archive *, + struct archive *_matching, void (*_excluded_func) + (struct archive *, void *, struct archive_entry *), + void *_client_data); +__LA_DECL int archive_read_disk_set_metadata_filter_callback(struct archive *, + int (*_metadata_filter_func)(struct archive *, void *, + struct archive_entry *), void *_client_data); + +/* Simplified cleanup interface; + * This calls archive_read_free() or archive_write_free() as needed. */ +__LA_DECL int archive_free(struct archive *); + +/* + * Accessor functions to read/set various information in + * the struct archive object: + */ + +/* Number of filters in the current filter pipeline. */ +/* Filter #0 is the one closest to the format, -1 is a synonym for the + * last filter, which is always the pseudo-filter that wraps the + * client callbacks. */ +__LA_DECL int archive_filter_count(struct archive *); +__LA_DECL la_int64_t archive_filter_bytes(struct archive *, int); +__LA_DECL int archive_filter_code(struct archive *, int); +__LA_DECL const char * archive_filter_name(struct archive *, int); + +#if ARCHIVE_VERSION_NUMBER < 4000000 +/* These don't properly handle multiple filters, so are deprecated and + * will eventually be removed. */ +/* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, -1); */ +__LA_DECL la_int64_t archive_position_compressed(struct archive *) + __LA_DEPRECATED; +/* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, 0); */ +__LA_DECL la_int64_t archive_position_uncompressed(struct archive *) + __LA_DEPRECATED; +/* As of libarchive 3.0, this is an alias for archive_filter_name(a, 0); */ +__LA_DECL const char *archive_compression_name(struct archive *) + __LA_DEPRECATED; +/* As of libarchive 3.0, this is an alias for archive_filter_code(a, 0); */ +__LA_DECL int archive_compression(struct archive *) + __LA_DEPRECATED; +#endif + +__LA_DECL int archive_errno(struct archive *); +__LA_DECL const char *archive_error_string(struct archive *); +__LA_DECL const char *archive_format_name(struct archive *); +__LA_DECL int archive_format(struct archive *); +__LA_DECL void archive_clear_error(struct archive *); +__LA_DECL void archive_set_error(struct archive *, int _err, + const char *fmt, ...) __LA_PRINTF(3, 4); +__LA_DECL void archive_copy_error(struct archive *dest, + struct archive *src); +__LA_DECL int archive_file_count(struct archive *); + +/* + * ARCHIVE_MATCH API + */ +__LA_DECL struct archive *archive_match_new(void); +__LA_DECL int archive_match_free(struct archive *); + +/* + * Test if archive_entry is excluded. + * This is a convenience function. This is the same as calling all + * archive_match_path_excluded, archive_match_time_excluded + * and archive_match_owner_excluded. + */ +__LA_DECL int archive_match_excluded(struct archive *, + struct archive_entry *); + +/* + * Test if pathname is excluded. The conditions are set by following functions. + */ +__LA_DECL int archive_match_path_excluded(struct archive *, + struct archive_entry *); +/* Add exclusion pathname pattern. */ +__LA_DECL int archive_match_exclude_pattern(struct archive *, const char *); +__LA_DECL int archive_match_exclude_pattern_w(struct archive *, + const wchar_t *); +/* Add exclusion pathname pattern from file. */ +__LA_DECL int archive_match_exclude_pattern_from_file(struct archive *, + const char *, int _nullSeparator); +__LA_DECL int archive_match_exclude_pattern_from_file_w(struct archive *, + const wchar_t *, int _nullSeparator); +/* Add inclusion pathname pattern. */ +__LA_DECL int archive_match_include_pattern(struct archive *, const char *); +__LA_DECL int archive_match_include_pattern_w(struct archive *, + const wchar_t *); +/* Add inclusion pathname pattern from file. */ +__LA_DECL int archive_match_include_pattern_from_file(struct archive *, + const char *, int _nullSeparator); +__LA_DECL int archive_match_include_pattern_from_file_w(struct archive *, + const wchar_t *, int _nullSeparator); +/* + * How to get statistic information for inclusion patterns. + */ +/* Return the amount number of unmatched inclusion patterns. */ +__LA_DECL int archive_match_path_unmatched_inclusions(struct archive *); +/* Return the pattern of unmatched inclusion with ARCHIVE_OK. + * Return ARCHIVE_EOF if there is no inclusion pattern. */ +__LA_DECL int archive_match_path_unmatched_inclusions_next( + struct archive *, const char **); +__LA_DECL int archive_match_path_unmatched_inclusions_next_w( + struct archive *, const wchar_t **); + +/* + * Test if a file is excluded by its time stamp. + * The conditions are set by following functions. + */ +__LA_DECL int archive_match_time_excluded(struct archive *, + struct archive_entry *); + +/* + * Flags to tell a matching type of time stamps. These are used for - * following functinos. ++ * following functions. + */ +/* Time flag: mtime to be tested. */ +#define ARCHIVE_MATCH_MTIME (0x0100) +/* Time flag: ctime to be tested. */ +#define ARCHIVE_MATCH_CTIME (0x0200) +/* Comparison flag: Match the time if it is newer than. */ +#define ARCHIVE_MATCH_NEWER (0x0001) +/* Comparison flag: Match the time if it is older than. */ +#define ARCHIVE_MATCH_OLDER (0x0002) +/* Comparison flag: Match the time if it is equal to. */ +#define ARCHIVE_MATCH_EQUAL (0x0010) +/* Set inclusion time. */ +__LA_DECL int archive_match_include_time(struct archive *, int _flag, + time_t _sec, long _nsec); +/* Set inclusion time by a date string. */ +__LA_DECL int archive_match_include_date(struct archive *, int _flag, + const char *_datestr); +__LA_DECL int archive_match_include_date_w(struct archive *, int _flag, + const wchar_t *_datestr); - /* Set inclusion time by a particluar file. */ ++/* Set inclusion time by a particular file. */ +__LA_DECL int archive_match_include_file_time(struct archive *, + int _flag, const char *_pathname); +__LA_DECL int archive_match_include_file_time_w(struct archive *, + int _flag, const wchar_t *_pathname); +/* Add exclusion entry. */ +__LA_DECL int archive_match_exclude_entry(struct archive *, + int _flag, struct archive_entry *); + +/* + * Test if a file is excluded by its uid ,gid, uname or gname. + * The conditions are set by following functions. + */ +__LA_DECL int archive_match_owner_excluded(struct archive *, + struct archive_entry *); +/* Add inclusion uid, gid, uname and gname. */ +__LA_DECL int archive_match_include_uid(struct archive *, la_int64_t); +__LA_DECL int archive_match_include_gid(struct archive *, la_int64_t); +__LA_DECL int archive_match_include_uname(struct archive *, const char *); +__LA_DECL int archive_match_include_uname_w(struct archive *, + const wchar_t *); +__LA_DECL int archive_match_include_gname(struct archive *, const char *); +__LA_DECL int archive_match_include_gname_w(struct archive *, + const wchar_t *); + +/* Utility functions */ +/* Convenience function to sort a NULL terminated list of strings */ +__LA_DECL int archive_utility_string_sort(char **); + +#ifdef __cplusplus +} +#endif + +/* These are meaningless outside of this header. */ +#undef __LA_DECL + +#endif /* !ARCHIVE_H_INCLUDED */ diff --cc Utilities/cmlibarchive/libarchive/archive_entry.h index 81cd425,0000000..9427413 mode 100644,000000..100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry.h +++ b/Utilities/cmlibarchive/libarchive/archive_entry.h @@@ -1,642 -1,0 +1,681 @@@ +/*- + * Copyright (c) 2003-2008 Tim Kientzle ++ * Copyright (c) 2016 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: head/lib/libarchive/archive_entry.h 201096 2009-12-28 02:41:27Z kientzle $ + */ + +#ifndef ARCHIVE_ENTRY_H_INCLUDED +#define ARCHIVE_ENTRY_H_INCLUDED + +/* Note: Compiler will complain if this does not match archive.h! */ - #define ARCHIVE_VERSION_NUMBER 3002001 ++#define ARCHIVE_VERSION_NUMBER 3003000 + +/* + * Note: archive_entry.h is for use outside of libarchive; the + * configuration headers (config.h, archive_platform.h, etc.) are + * purely internal. Do NOT use HAVE_XXX configuration macros to + * control the behavior of this header! If you must conditionalize, + * use predefined compiler and/or platform macros. + */ + +#include +#include /* for wchar_t */ +#include + +#if defined(_WIN32) && !defined(__CYGWIN__) +#include +#endif + +/* Get a suitable 64-bit integer type. */ +#if !defined(__LA_INT64_T_DEFINED) +# if ARCHIVE_VERSION_NUMBER < 4000000 +#define __LA_INT64_T la_int64_t +# endif +#define __LA_INT64_T_DEFINED +# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__) +typedef __int64 la_int64_t; +# else +#include +# if defined(_SCO_DS) || defined(__osf__) +typedef long long la_int64_t; +# else +typedef int64_t la_int64_t; +# endif +# endif +#endif + +/* Get a suitable definition for mode_t */ +#if ARCHIVE_VERSION_NUMBER >= 3999000 +/* Switch to plain 'int' for libarchive 4.0. It's less broken than 'mode_t' */ +# define __LA_MODE_T int +#elif defined(_WIN32) && !defined(__CYGWIN__) && !defined(__BORLANDC__) && !defined(__WATCOMC__) +# define __LA_MODE_T unsigned short +#else +# define __LA_MODE_T mode_t +#endif + +/* Large file support for Android */ +#ifdef __ANDROID__ +#include "android_lf.h" +#endif + +/* + * On Windows, define LIBARCHIVE_STATIC if you're building or using a + * .lib. The default here assumes you're building a DLL. Only + * libarchive source should ever define __LIBARCHIVE_BUILD. + */ +#if ((defined __WIN32__) || (defined _WIN32) || defined(__CYGWIN__)) && (!defined LIBARCHIVE_STATIC) +# ifdef __LIBARCHIVE_BUILD +# ifdef __GNUC__ +# define __LA_DECL __attribute__((dllexport)) extern +# else +# define __LA_DECL __declspec(dllexport) +# endif +# else +# ifdef __GNUC__ +# define __LA_DECL +# else +# define __LA_DECL __declspec(dllimport) +# endif +# endif +#else +/* Static libraries on all platforms and shared libraries on non-Windows. */ +# define __LA_DECL +#endif + ++#if defined(__GNUC__) && __GNUC__ >= 3 && __GNUC_MINOR__ >= 1 ++# define __LA_DEPRECATED __attribute__((deprecated)) ++#else ++# define __LA_DEPRECATED ++#endif ++ +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Description of an archive entry. + * + * You can think of this as "struct stat" with some text fields added in. + * + * TODO: Add "comment", "charset", and possibly other entries that are + * supported by "pax interchange" format. However, GNU, ustar, cpio, + * and other variants don't support these features, so they're not an + * excruciatingly high priority right now. + * + * TODO: "pax interchange" format allows essentially arbitrary + * key/value attributes to be attached to any entry. Supporting + * such extensions may make this library useful for special + * applications (e.g., a package manager could attach special + * package-management attributes to each entry). + */ +struct archive; +struct archive_entry; + +/* + * File-type constants. These are returned from archive_entry_filetype() + * and passed to archive_entry_set_filetype(). + * + * These values match S_XXX defines on every platform I've checked, + * including Windows, AIX, Linux, Solaris, and BSD. They're + * (re)defined here because platforms generally don't define the ones + * they don't support. For example, Windows doesn't define S_IFLNK or + * S_IFBLK. Instead of having a mass of conditional logic and system + * checks to define any S_XXX values that aren't supported locally, + * I've just defined a new set of such constants so that + * libarchive-based applications can manipulate and identify archive + * entries properly even if the hosting platform can't store them on + * disk. + * + * These values are also used directly within some portable formats, + * such as cpio. If you find a platform that varies from these, the + * correct solution is to leave these alone and translate from these + * portable values to platform-native values when entries are read from + * or written to disk. + */ +/* + * In libarchive 4.0, we can drop the casts here. + * They're needed to work around Borland C's broken mode_t. + */ +#define AE_IFMT ((__LA_MODE_T)0170000) +#define AE_IFREG ((__LA_MODE_T)0100000) +#define AE_IFLNK ((__LA_MODE_T)0120000) +#define AE_IFSOCK ((__LA_MODE_T)0140000) +#define AE_IFCHR ((__LA_MODE_T)0020000) +#define AE_IFBLK ((__LA_MODE_T)0060000) +#define AE_IFDIR ((__LA_MODE_T)0040000) +#define AE_IFIFO ((__LA_MODE_T)0010000) + +/* + * Basic object manipulation + */ + +__LA_DECL struct archive_entry *archive_entry_clear(struct archive_entry *); +/* The 'clone' function does a deep copy; all of the strings are copied too. */ +__LA_DECL struct archive_entry *archive_entry_clone(struct archive_entry *); +__LA_DECL void archive_entry_free(struct archive_entry *); +__LA_DECL struct archive_entry *archive_entry_new(void); + +/* + * This form of archive_entry_new2() will pull character-set + * conversion information from the specified archive handle. The + * older archive_entry_new(void) form is equivalent to calling + * archive_entry_new2(NULL) and will result in the use of an internal + * default character-set conversion. + */ +__LA_DECL struct archive_entry *archive_entry_new2(struct archive *); + +/* + * Retrieve fields from an archive_entry. + * + * There are a number of implicit conversions among these fields. For + * example, if a regular string field is set and you read the _w wide + * character field, the entry will implicitly convert narrow-to-wide + * using the current locale. Similarly, dev values are automatically + * updated when you write devmajor or devminor and vice versa. + * + * In addition, fields can be "set" or "unset." Unset string fields + * return NULL, non-string fields have _is_set() functions to test + * whether they've been set. You can "unset" a string field by + * assigning NULL; non-string fields have _unset() functions to + * unset them. + * + * Note: There is one ambiguity in the above; string fields will + * also return NULL when implicit character set conversions fail. + * This is usually what you want. + */ +__LA_DECL time_t archive_entry_atime(struct archive_entry *); +__LA_DECL long archive_entry_atime_nsec(struct archive_entry *); +__LA_DECL int archive_entry_atime_is_set(struct archive_entry *); +__LA_DECL time_t archive_entry_birthtime(struct archive_entry *); +__LA_DECL long archive_entry_birthtime_nsec(struct archive_entry *); +__LA_DECL int archive_entry_birthtime_is_set(struct archive_entry *); +__LA_DECL time_t archive_entry_ctime(struct archive_entry *); +__LA_DECL long archive_entry_ctime_nsec(struct archive_entry *); +__LA_DECL int archive_entry_ctime_is_set(struct archive_entry *); +__LA_DECL dev_t archive_entry_dev(struct archive_entry *); +__LA_DECL int archive_entry_dev_is_set(struct archive_entry *); +__LA_DECL dev_t archive_entry_devmajor(struct archive_entry *); +__LA_DECL dev_t archive_entry_devminor(struct archive_entry *); +__LA_DECL __LA_MODE_T archive_entry_filetype(struct archive_entry *); +__LA_DECL void archive_entry_fflags(struct archive_entry *, + unsigned long * /* set */, + unsigned long * /* clear */); +__LA_DECL const char *archive_entry_fflags_text(struct archive_entry *); +__LA_DECL la_int64_t archive_entry_gid(struct archive_entry *); +__LA_DECL const char *archive_entry_gname(struct archive_entry *); +__LA_DECL const char *archive_entry_gname_utf8(struct archive_entry *); +__LA_DECL const wchar_t *archive_entry_gname_w(struct archive_entry *); +__LA_DECL const char *archive_entry_hardlink(struct archive_entry *); +__LA_DECL const char *archive_entry_hardlink_utf8(struct archive_entry *); +__LA_DECL const wchar_t *archive_entry_hardlink_w(struct archive_entry *); +__LA_DECL la_int64_t archive_entry_ino(struct archive_entry *); +__LA_DECL la_int64_t archive_entry_ino64(struct archive_entry *); +__LA_DECL int archive_entry_ino_is_set(struct archive_entry *); +__LA_DECL __LA_MODE_T archive_entry_mode(struct archive_entry *); +__LA_DECL time_t archive_entry_mtime(struct archive_entry *); +__LA_DECL long archive_entry_mtime_nsec(struct archive_entry *); +__LA_DECL int archive_entry_mtime_is_set(struct archive_entry *); +__LA_DECL unsigned int archive_entry_nlink(struct archive_entry *); +__LA_DECL const char *archive_entry_pathname(struct archive_entry *); +__LA_DECL const char *archive_entry_pathname_utf8(struct archive_entry *); +__LA_DECL const wchar_t *archive_entry_pathname_w(struct archive_entry *); +__LA_DECL __LA_MODE_T archive_entry_perm(struct archive_entry *); +__LA_DECL dev_t archive_entry_rdev(struct archive_entry *); +__LA_DECL dev_t archive_entry_rdevmajor(struct archive_entry *); +__LA_DECL dev_t archive_entry_rdevminor(struct archive_entry *); +__LA_DECL const char *archive_entry_sourcepath(struct archive_entry *); +__LA_DECL const wchar_t *archive_entry_sourcepath_w(struct archive_entry *); +__LA_DECL la_int64_t archive_entry_size(struct archive_entry *); +__LA_DECL int archive_entry_size_is_set(struct archive_entry *); +__LA_DECL const char *archive_entry_strmode(struct archive_entry *); +__LA_DECL const char *archive_entry_symlink(struct archive_entry *); +__LA_DECL const char *archive_entry_symlink_utf8(struct archive_entry *); +__LA_DECL const wchar_t *archive_entry_symlink_w(struct archive_entry *); +__LA_DECL la_int64_t archive_entry_uid(struct archive_entry *); +__LA_DECL const char *archive_entry_uname(struct archive_entry *); +__LA_DECL const char *archive_entry_uname_utf8(struct archive_entry *); +__LA_DECL const wchar_t *archive_entry_uname_w(struct archive_entry *); +__LA_DECL int archive_entry_is_data_encrypted(struct archive_entry *); +__LA_DECL int archive_entry_is_metadata_encrypted(struct archive_entry *); +__LA_DECL int archive_entry_is_encrypted(struct archive_entry *); + +/* + * Set fields in an archive_entry. + * + * Note: Before libarchive 2.4, there were 'set' and 'copy' versions + * of the string setters. 'copy' copied the actual string, 'set' just + * stored the pointer. In libarchive 2.4 and later, strings are + * always copied. + */ + +__LA_DECL void archive_entry_set_atime(struct archive_entry *, time_t, long); +__LA_DECL void archive_entry_unset_atime(struct archive_entry *); +#if defined(_WIN32) && !defined(__CYGWIN__) +__LA_DECL void archive_entry_copy_bhfi(struct archive_entry *, struct _BY_HANDLE_FILE_INFORMATION *); +#endif +__LA_DECL void archive_entry_set_birthtime(struct archive_entry *, time_t, long); +__LA_DECL void archive_entry_unset_birthtime(struct archive_entry *); +__LA_DECL void archive_entry_set_ctime(struct archive_entry *, time_t, long); +__LA_DECL void archive_entry_unset_ctime(struct archive_entry *); +__LA_DECL void archive_entry_set_dev(struct archive_entry *, dev_t); +__LA_DECL void archive_entry_set_devmajor(struct archive_entry *, dev_t); +__LA_DECL void archive_entry_set_devminor(struct archive_entry *, dev_t); +__LA_DECL void archive_entry_set_filetype(struct archive_entry *, unsigned int); +__LA_DECL void archive_entry_set_fflags(struct archive_entry *, + unsigned long /* set */, unsigned long /* clear */); +/* Returns pointer to start of first invalid token, or NULL if none. */ +/* Note that all recognized tokens are processed, regardless. */ +__LA_DECL const char *archive_entry_copy_fflags_text(struct archive_entry *, + const char *); +__LA_DECL const wchar_t *archive_entry_copy_fflags_text_w(struct archive_entry *, + const wchar_t *); +__LA_DECL void archive_entry_set_gid(struct archive_entry *, la_int64_t); +__LA_DECL void archive_entry_set_gname(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_gname_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_gname(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_gname_w(struct archive_entry *, const wchar_t *); +__LA_DECL int archive_entry_update_gname_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_hardlink(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_hardlink_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_hardlink(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_hardlink_w(struct archive_entry *, const wchar_t *); +__LA_DECL int archive_entry_update_hardlink_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_ino(struct archive_entry *, la_int64_t); +__LA_DECL void archive_entry_set_ino64(struct archive_entry *, la_int64_t); +__LA_DECL void archive_entry_set_link(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_link_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_link(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_link_w(struct archive_entry *, const wchar_t *); +__LA_DECL int archive_entry_update_link_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_mode(struct archive_entry *, __LA_MODE_T); +__LA_DECL void archive_entry_set_mtime(struct archive_entry *, time_t, long); +__LA_DECL void archive_entry_unset_mtime(struct archive_entry *); +__LA_DECL void archive_entry_set_nlink(struct archive_entry *, unsigned int); +__LA_DECL void archive_entry_set_pathname(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_pathname_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_pathname(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_pathname_w(struct archive_entry *, const wchar_t *); +__LA_DECL int archive_entry_update_pathname_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_perm(struct archive_entry *, __LA_MODE_T); +__LA_DECL void archive_entry_set_rdev(struct archive_entry *, dev_t); +__LA_DECL void archive_entry_set_rdevmajor(struct archive_entry *, dev_t); +__LA_DECL void archive_entry_set_rdevminor(struct archive_entry *, dev_t); +__LA_DECL void archive_entry_set_size(struct archive_entry *, la_int64_t); +__LA_DECL void archive_entry_unset_size(struct archive_entry *); +__LA_DECL void archive_entry_copy_sourcepath(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_sourcepath_w(struct archive_entry *, const wchar_t *); +__LA_DECL void archive_entry_set_symlink(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_symlink_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_symlink(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_symlink_w(struct archive_entry *, const wchar_t *); +__LA_DECL int archive_entry_update_symlink_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_uid(struct archive_entry *, la_int64_t); +__LA_DECL void archive_entry_set_uname(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_uname_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_uname(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_uname_w(struct archive_entry *, const wchar_t *); +__LA_DECL int archive_entry_update_uname_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_is_data_encrypted(struct archive_entry *, char is_encrypted); +__LA_DECL void archive_entry_set_is_metadata_encrypted(struct archive_entry *, char is_encrypted); +/* + * Routines to bulk copy fields to/from a platform-native "struct + * stat." Libarchive used to just store a struct stat inside of each + * archive_entry object, but this created issues when trying to + * manipulate archives on systems different than the ones they were + * created on. + * + * TODO: On Linux and other LFS systems, provide both stat32 and + * stat64 versions of these functions and all of the macro glue so + * that archive_entry_stat is magically defined to + * archive_entry_stat32 or archive_entry_stat64 as appropriate. + */ +__LA_DECL const struct stat *archive_entry_stat(struct archive_entry *); +__LA_DECL void archive_entry_copy_stat(struct archive_entry *, const struct stat *); + +/* + * Storage for Mac OS-specific AppleDouble metadata information. + * Apple-format tar files store a separate binary blob containing + * encoded metadata with ACL, extended attributes, etc. + * This provides a place to store that blob. + */ + +__LA_DECL const void * archive_entry_mac_metadata(struct archive_entry *, size_t *); +__LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const void *, size_t); + +/* + * ACL routines. This used to simply store and return text-format ACL + * strings, but that proved insufficient for a number of reasons: + * = clients need control over uname/uid and gname/gid mappings + * = there are many different ACL text formats + * = would like to be able to read/convert archives containing ACLs + * on platforms that lack ACL libraries + * + * This last point, in particular, forces me to implement a reasonably + * complete set of ACL support routines. + */ + +/* + * Permission bits. + */ +#define ARCHIVE_ENTRY_ACL_EXECUTE 0x00000001 +#define ARCHIVE_ENTRY_ACL_WRITE 0x00000002 +#define ARCHIVE_ENTRY_ACL_READ 0x00000004 +#define ARCHIVE_ENTRY_ACL_READ_DATA 0x00000008 +#define ARCHIVE_ENTRY_ACL_LIST_DIRECTORY 0x00000008 +#define ARCHIVE_ENTRY_ACL_WRITE_DATA 0x00000010 +#define ARCHIVE_ENTRY_ACL_ADD_FILE 0x00000010 +#define ARCHIVE_ENTRY_ACL_APPEND_DATA 0x00000020 +#define ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY 0x00000020 +#define ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS 0x00000040 +#define ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS 0x00000080 +#define ARCHIVE_ENTRY_ACL_DELETE_CHILD 0x00000100 +#define ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES 0x00000200 +#define ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES 0x00000400 +#define ARCHIVE_ENTRY_ACL_DELETE 0x00000800 +#define ARCHIVE_ENTRY_ACL_READ_ACL 0x00001000 +#define ARCHIVE_ENTRY_ACL_WRITE_ACL 0x00002000 +#define ARCHIVE_ENTRY_ACL_WRITE_OWNER 0x00004000 +#define ARCHIVE_ENTRY_ACL_SYNCHRONIZE 0x00008000 + +#define ARCHIVE_ENTRY_ACL_PERMS_POSIX1E \ + (ARCHIVE_ENTRY_ACL_EXECUTE \ + | ARCHIVE_ENTRY_ACL_WRITE \ + | ARCHIVE_ENTRY_ACL_READ) + +#define ARCHIVE_ENTRY_ACL_PERMS_NFS4 \ + (ARCHIVE_ENTRY_ACL_EXECUTE \ + | ARCHIVE_ENTRY_ACL_READ_DATA \ + | ARCHIVE_ENTRY_ACL_LIST_DIRECTORY \ + | ARCHIVE_ENTRY_ACL_WRITE_DATA \ + | ARCHIVE_ENTRY_ACL_ADD_FILE \ + | ARCHIVE_ENTRY_ACL_APPEND_DATA \ + | ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY \ + | ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS \ + | ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS \ + | ARCHIVE_ENTRY_ACL_DELETE_CHILD \ + | ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES \ + | ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES \ + | ARCHIVE_ENTRY_ACL_DELETE \ + | ARCHIVE_ENTRY_ACL_READ_ACL \ + | ARCHIVE_ENTRY_ACL_WRITE_ACL \ + | ARCHIVE_ENTRY_ACL_WRITE_OWNER \ + | ARCHIVE_ENTRY_ACL_SYNCHRONIZE) + +/* + * Inheritance values (NFS4 ACLs only); included in permset. + */ ++#define ARCHIVE_ENTRY_ACL_ENTRY_INHERITED 0x01000000 +#define ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT 0x02000000 +#define ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT 0x04000000 +#define ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT 0x08000000 +#define ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY 0x10000000 +#define ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS 0x20000000 +#define ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS 0x40000000 + +#define ARCHIVE_ENTRY_ACL_INHERITANCE_NFS4 \ + (ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT \ + | ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT \ + | ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT \ + | ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY \ + | ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS \ - | ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS) ++ | ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS \ ++ | ARCHIVE_ENTRY_ACL_ENTRY_INHERITED) + +/* We need to be able to specify combinations of these. */ - #define ARCHIVE_ENTRY_ACL_TYPE_ACCESS 256 /* POSIX.1e only */ - #define ARCHIVE_ENTRY_ACL_TYPE_DEFAULT 512 /* POSIX.1e only */ - #define ARCHIVE_ENTRY_ACL_TYPE_ALLOW 1024 /* NFS4 only */ - #define ARCHIVE_ENTRY_ACL_TYPE_DENY 2048 /* NFS4 only */ - #define ARCHIVE_ENTRY_ACL_TYPE_AUDIT 4096 /* NFS4 only */ - #define ARCHIVE_ENTRY_ACL_TYPE_ALARM 8192 /* NFS4 only */ ++#define ARCHIVE_ENTRY_ACL_TYPE_ACCESS 0x00000100 /* POSIX.1e only */ ++#define ARCHIVE_ENTRY_ACL_TYPE_DEFAULT 0x00000200 /* POSIX.1e only */ ++#define ARCHIVE_ENTRY_ACL_TYPE_ALLOW 0x00000400 /* NFS4 only */ ++#define ARCHIVE_ENTRY_ACL_TYPE_DENY 0x00000800 /* NFS4 only */ ++#define ARCHIVE_ENTRY_ACL_TYPE_AUDIT 0x00001000 /* NFS4 only */ ++#define ARCHIVE_ENTRY_ACL_TYPE_ALARM 0x00002000 /* NFS4 only */ +#define ARCHIVE_ENTRY_ACL_TYPE_POSIX1E (ARCHIVE_ENTRY_ACL_TYPE_ACCESS \ + | ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) +#define ARCHIVE_ENTRY_ACL_TYPE_NFS4 (ARCHIVE_ENTRY_ACL_TYPE_ALLOW \ + | ARCHIVE_ENTRY_ACL_TYPE_DENY \ + | ARCHIVE_ENTRY_ACL_TYPE_AUDIT \ + | ARCHIVE_ENTRY_ACL_TYPE_ALARM) + +/* Tag values mimic POSIX.1e */ +#define ARCHIVE_ENTRY_ACL_USER 10001 /* Specified user. */ +#define ARCHIVE_ENTRY_ACL_USER_OBJ 10002 /* User who owns the file. */ +#define ARCHIVE_ENTRY_ACL_GROUP 10003 /* Specified group. */ +#define ARCHIVE_ENTRY_ACL_GROUP_OBJ 10004 /* Group who owns the file. */ +#define ARCHIVE_ENTRY_ACL_MASK 10005 /* Modify group access (POSIX.1e only) */ +#define ARCHIVE_ENTRY_ACL_OTHER 10006 /* Public (POSIX.1e only) */ +#define ARCHIVE_ENTRY_ACL_EVERYONE 10107 /* Everyone (NFS4 only) */ + +/* + * Set the ACL by clearing it and adding entries one at a time. + * Unlike the POSIX.1e ACL routines, you must specify the type + * (access/default) for each entry. Internally, the ACL data is just + * a soup of entries. API calls here allow you to retrieve just the + * entries of interest. This design (which goes against the spirit of + * POSIX.1e) is useful for handling archive formats that combine + * default and access information in a single ACL list. + */ +__LA_DECL void archive_entry_acl_clear(struct archive_entry *); +__LA_DECL int archive_entry_acl_add_entry(struct archive_entry *, + int /* type */, int /* permset */, int /* tag */, + int /* qual */, const char * /* name */); +__LA_DECL int archive_entry_acl_add_entry_w(struct archive_entry *, + int /* type */, int /* permset */, int /* tag */, + int /* qual */, const wchar_t * /* name */); + +/* + * To retrieve the ACL, first "reset", then repeatedly ask for the + * "next" entry. The want_type parameter allows you to request only + * certain types of entries. + */ +__LA_DECL int archive_entry_acl_reset(struct archive_entry *, int /* want_type */); +__LA_DECL int archive_entry_acl_next(struct archive_entry *, int /* want_type */, + int * /* type */, int * /* permset */, int * /* tag */, + int * /* qual */, const char ** /* name */); +__LA_DECL int archive_entry_acl_next_w(struct archive_entry *, int /* want_type */, + int * /* type */, int * /* permset */, int * /* tag */, + int * /* qual */, const wchar_t ** /* name */); + +/* + * Construct a text-format ACL. The flags argument is a bitmask that + * can include any of the following: + * ++ * Flags only for archive entries with POSIX.1e ACL: + * ARCHIVE_ENTRY_ACL_TYPE_ACCESS - Include POSIX.1e "access" entries. + * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - Include POSIX.1e "default" entries. - * ARCHIVE_ENTRY_ACL_TYPE_NFS4 - Include NFS4 entries. - * ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID - Include extra numeric ID field in - * each ACL entry. ('star' introduced this for POSIX.1e, this flag - * also applies to NFS4.) + * ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT - Include "default:" before each - * default ACL entry, as used in old Solaris ACLs. ++ * default ACL entry. ++ * ARCHIVE_ENTRY_ACL_STYLE_SOLARIS - Output only one colon after "other" and ++ * "mask" entries. ++ * ++ * Flags only for archive entries with NFSv4 ACL: ++ * ARCHIVE_ENTRY_ACL_STYLE_COMPACT - Do not output the minus character for ++ * unset permissions and flags in NFSv4 ACL permission and flag fields ++ * ++ * Flags for for archive entries with POSIX.1e ACL or NFSv4 ACL: ++ * ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID - Include extra numeric ID field in ++ * each ACL entry. ++ * ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA - Separate entries with comma ++ * instead of newline. + */ - #define ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 1024 - #define ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 2048 ++#define ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 0x00000001 ++#define ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 0x00000002 ++#define ARCHIVE_ENTRY_ACL_STYLE_SOLARIS 0x00000004 ++#define ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA 0x00000008 ++#define ARCHIVE_ENTRY_ACL_STYLE_COMPACT 0x00000010 ++ ++__LA_DECL wchar_t *archive_entry_acl_to_text_w(struct archive_entry *, ++ ssize_t * /* len */, int /* flags */); ++__LA_DECL char *archive_entry_acl_to_text(struct archive_entry *, ++ ssize_t * /* len */, int /* flags */); ++__LA_DECL int archive_entry_acl_from_text_w(struct archive_entry *, ++ const wchar_t * /* wtext */, int /* type */); ++__LA_DECL int archive_entry_acl_from_text(struct archive_entry *, ++ const char * /* text */, int /* type */); ++ ++/* Deprecated constants */ ++#define OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 1024 ++#define OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 2048 ++ ++/* Deprecated functions */ +__LA_DECL const wchar_t *archive_entry_acl_text_w(struct archive_entry *, - int /* flags */); ++ int /* flags */) __LA_DEPRECATED; +__LA_DECL const char *archive_entry_acl_text(struct archive_entry *, - int /* flags */); ++ int /* flags */) __LA_DEPRECATED; ++ ++/* Return bitmask of ACL types in an archive entry */ ++__LA_DECL int archive_entry_acl_types(struct archive_entry *); + +/* Return a count of entries matching 'want_type' */ +__LA_DECL int archive_entry_acl_count(struct archive_entry *, int /* want_type */); + +/* Return an opaque ACL object. */ +/* There's not yet anything clients can actually do with this... */ +struct archive_acl; +__LA_DECL struct archive_acl *archive_entry_acl(struct archive_entry *); + +/* + * extended attributes + */ + +__LA_DECL void archive_entry_xattr_clear(struct archive_entry *); +__LA_DECL void archive_entry_xattr_add_entry(struct archive_entry *, + const char * /* name */, const void * /* value */, + size_t /* size */); + +/* + * To retrieve the xattr list, first "reset", then repeatedly ask for the + * "next" entry. + */ + +__LA_DECL int archive_entry_xattr_count(struct archive_entry *); +__LA_DECL int archive_entry_xattr_reset(struct archive_entry *); +__LA_DECL int archive_entry_xattr_next(struct archive_entry *, + const char ** /* name */, const void ** /* value */, size_t *); + +/* + * sparse + */ + +__LA_DECL void archive_entry_sparse_clear(struct archive_entry *); +__LA_DECL void archive_entry_sparse_add_entry(struct archive_entry *, + la_int64_t /* offset */, la_int64_t /* length */); + +/* + * To retrieve the xattr list, first "reset", then repeatedly ask for the + * "next" entry. + */ + +__LA_DECL int archive_entry_sparse_count(struct archive_entry *); +__LA_DECL int archive_entry_sparse_reset(struct archive_entry *); +__LA_DECL int archive_entry_sparse_next(struct archive_entry *, + la_int64_t * /* offset */, la_int64_t * /* length */); + +/* + * Utility to match up hardlinks. + * + * The 'struct archive_entry_linkresolver' is a cache of archive entries + * for files with multiple links. Here's how to use it: + * 1. Create a lookup object with archive_entry_linkresolver_new() + * 2. Tell it the archive format you're using. + * 3. Hand each archive_entry to archive_entry_linkify(). + * That function will return 0, 1, or 2 entries that should + * be written. + * 4. Call archive_entry_linkify(resolver, NULL) until + * no more entries are returned. + * 5. Call archive_entry_linkresolver_free(resolver) to free resources. + * + * The entries returned have their hardlink and size fields updated + * appropriately. If an entry is passed in that does not refer to + * a file with multiple links, it is returned unchanged. The intention + * is that you should be able to simply filter all entries through + * this machine. + * + * To make things more efficient, be sure that each entry has a valid + * nlinks value. The hardlink cache uses this to track when all links + * have been found. If the nlinks value is zero, it will keep every + * name in the cache indefinitely, which can use a lot of memory. + * + * Note that archive_entry_size() is reset to zero if the file + * body should not be written to the archive. Pay attention! + */ +struct archive_entry_linkresolver; + +/* + * There are three different strategies for marking hardlinks. + * The descriptions below name them after the best-known + * formats that rely on each strategy: + * + * "Old cpio" is the simplest, it always returns any entry unmodified. + * As far as I know, only cpio formats use this. Old cpio archives + * store every link with the full body; the onus is on the dearchiver + * to detect and properly link the files as they are restored. + * "tar" is also pretty simple; it caches a copy the first time it sees + * any link. Subsequent appearances are modified to be hardlink + * references to the first one without any body. Used by all tar + * formats, although the newest tar formats permit the "old cpio" strategy + * as well. This strategy is very simple for the dearchiver, + * and reasonably straightforward for the archiver. + * "new cpio" is trickier. It stores the body only with the last + * occurrence. The complication is that we might not + * see every link to a particular file in a single session, so + * there's no easy way to know when we've seen the last occurrence. + * The solution here is to queue one link until we see the next. + * At the end of the session, you can enumerate any remaining + * entries by calling archive_entry_linkify(NULL) and store those + * bodies. If you have a file with three links l1, l2, and l3, + * you'll get the following behavior if you see all three links: + * linkify(l1) => NULL (the resolver stores l1 internally) + * linkify(l2) => l1 (resolver stores l2, you write l1) + * linkify(l3) => l2, l3 (all links seen, you can write both). + * If you only see l1 and l2, you'll get this behavior: + * linkify(l1) => NULL + * linkify(l2) => l1 + * linkify(NULL) => l2 (at end, you retrieve remaining links) + * As the name suggests, this strategy is used by newer cpio variants. + * It's noticeably more complex for the archiver, slightly more complex + * for the dearchiver than the tar strategy, but makes it straightforward + * to restore a file using any link by simply continuing to scan until + * you see a link that is stored with a body. In contrast, the tar + * strategy requires you to rescan the archive from the beginning to + * correctly extract an arbitrary link. + */ + +__LA_DECL struct archive_entry_linkresolver *archive_entry_linkresolver_new(void); +__LA_DECL void archive_entry_linkresolver_set_strategy( + struct archive_entry_linkresolver *, int /* format_code */); +__LA_DECL void archive_entry_linkresolver_free(struct archive_entry_linkresolver *); +__LA_DECL void archive_entry_linkify(struct archive_entry_linkresolver *, + struct archive_entry **, struct archive_entry **); +__LA_DECL struct archive_entry *archive_entry_partial_links( + struct archive_entry_linkresolver *res, unsigned int *links); + +#ifdef __cplusplus +} +#endif + +/* This is meaningless outside of this header. */ +#undef __LA_DECL + +#endif /* !ARCHIVE_ENTRY_H_INCLUDED */ diff --cc Utilities/cmlibarchive/libarchive/archive_platform.h index 08a384c,0000000..47d144b mode 100644,000000..100644 --- a/Utilities/cmlibarchive/libarchive/archive_platform.h +++ b/Utilities/cmlibarchive/libarchive/archive_platform.h @@@ -1,188 -1,0 +1,214 @@@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: head/lib/libarchive/archive_platform.h 201090 2009-12-28 02:22:04Z kientzle $ + */ + +/* !!ONLY FOR USE INTERNALLY TO LIBARCHIVE!! */ + +/* + * This header is the first thing included in any of the libarchive + * source files. As far as possible, platform-specific issues should + * be dealt with here and not within individual source files. I'm + * actively trying to minimize #if blocks within the main source, + * since they obfuscate the code. + */ + +#ifndef ARCHIVE_PLATFORM_H_INCLUDED +#define ARCHIVE_PLATFORM_H_INCLUDED + +/* archive.h and archive_entry.h require this. */ +#define __LIBARCHIVE_BUILD 1 + +#if defined(PLATFORM_CONFIG_H) +/* Use hand-built config.h in environments that need it. */ +#include PLATFORM_CONFIG_H +#elif defined(HAVE_CONFIG_H) +/* Most POSIX platforms use the 'configure' script to build config.h */ +#include "config.h" +#else +/* Warn if the library hasn't been (automatically or manually) configured. */ +#error Oops: No config.h and no pre-built configuration in archive_platform.h. +#endif + +/* It should be possible to get rid of this by extending the feature-test + * macros to cover Windows API functions, probably along with non-trivial + * refactoring of code to find structures that sit more cleanly on top of + * either Windows or Posix APIs. */ +#if (defined(__WIN32__) || defined(_WIN32) || defined(__WIN32)) && !defined(__CYGWIN__) +#include "archive_windows.h" +#endif + +/* + * The config files define a lot of feature macros. The following + * uses those macros to select/define replacements and include key + * headers as required. + */ + +/* Get a real definition for __FBSDID or __RCSID if we can */ +#if HAVE_SYS_CDEFS_H +#include +#endif + +/* If not, define them so as to avoid dangling semicolons. */ +#ifndef __FBSDID +#define __FBSDID(a) struct _undefined_hack +#endif +#ifndef __RCSID +#define __RCSID(a) struct _undefined_hack +#endif + +/* Old glibc mbsnrtowcs fails assertions in our use case. */ +#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ <= 1 +# undef HAVE_MBSNRTOWCS +#endif + +/* Try to get standard C99-style integer type definitions. */ +#if HAVE_INTTYPES_H +#include +#endif +#if HAVE_STDINT_H +#include +#endif + +/* Borland warns about its own constants! */ +#if defined(__BORLANDC__) +# if HAVE_DECL_UINT64_MAX +# undef UINT64_MAX +# undef HAVE_DECL_UINT64_MAX +# endif +# if HAVE_DECL_UINT64_MIN +# undef UINT64_MIN +# undef HAVE_DECL_UINT64_MIN +# endif +# if HAVE_DECL_INT64_MAX +# undef INT64_MAX +# undef HAVE_DECL_INT64_MAX +# endif +# if HAVE_DECL_INT64_MIN +# undef INT64_MIN +# undef HAVE_DECL_INT64_MIN +# endif +#endif + +/* Some platforms lack the standard *_MAX definitions. */ +#if !HAVE_DECL_SIZE_MAX +#define SIZE_MAX (~(size_t)0) +#endif +#if !HAVE_DECL_SSIZE_MAX +#define SSIZE_MAX ((ssize_t)(SIZE_MAX >> 1)) +#endif +#if !HAVE_DECL_UINT32_MAX +#define UINT32_MAX (~(uint32_t)0) +#endif +#if !HAVE_DECL_INT32_MAX +#define INT32_MAX ((int32_t)(UINT32_MAX >> 1)) +#endif +#if !HAVE_DECL_INT32_MIN +#define INT32_MIN ((int32_t)(~INT32_MAX)) +#endif +#if !HAVE_DECL_UINT64_MAX +#define UINT64_MAX (~(uint64_t)0) +#endif +#if !HAVE_DECL_INT64_MAX +#define INT64_MAX ((int64_t)(UINT64_MAX >> 1)) +#endif +#if !HAVE_DECL_INT64_MIN +#define INT64_MIN ((int64_t)(~INT64_MAX)) +#endif +#if !HAVE_DECL_UINTMAX_MAX +#define UINTMAX_MAX (~(uintmax_t)0) +#endif +#if !HAVE_DECL_INTMAX_MAX +#define INTMAX_MAX ((intmax_t)(UINTMAX_MAX >> 1)) +#endif +#if !HAVE_DECL_INTMAX_MIN +#define INTMAX_MIN ((intmax_t)(~INTMAX_MAX)) +#endif + +/* + * If this platform has , acl_create(), acl_init(), + * acl_set_file(), and ACL_USER, we assume it has the rest of the + * POSIX.1e draft functions used in archive_read_extract.c. + */ - #if HAVE_SYS_ACL_H && HAVE_ACL_CREATE_ENTRY && HAVE_ACL_INIT && HAVE_ACL_SET_FILE && HAVE_ACL_USER ++#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 , 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. + */ +#if defined(HAVE_FCHMOD) || defined(HAVE_FUTIMES) || defined(HAVE_ACL_SET_FD) || defined(HAVE_ACL_SET_FD_NP) || defined(HAVE_FCHOWN) +#define CAN_RESTORE_METADATA_FD +#endif + ++/* ++ * glibc 2.24 deprecates readdir_r ++ */ ++#if defined(HAVE_READDIR_R) && (!defined(__GLIBC__) || !defined(__GLIBC_MINOR__) || __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 24)) ++#define USE_READDIR_R 1 ++#else ++#undef USE_READDIR_R ++#endif ++ +/* Set up defaults for internal error codes. */ +#ifndef ARCHIVE_ERRNO_FILE_FORMAT +#if HAVE_EFTYPE +#define ARCHIVE_ERRNO_FILE_FORMAT EFTYPE +#else +#if HAVE_EILSEQ +#define ARCHIVE_ERRNO_FILE_FORMAT EILSEQ +#else +#define ARCHIVE_ERRNO_FILE_FORMAT EINVAL +#endif +#endif +#endif + +#ifndef ARCHIVE_ERRNO_PROGRAMMER +#define ARCHIVE_ERRNO_PROGRAMMER EINVAL +#endif + +#ifndef ARCHIVE_ERRNO_MISC +#define ARCHIVE_ERRNO_MISC (-1) +#endif + +#endif /* !ARCHIVE_PLATFORM_H_INCLUDED */ diff --cc Utilities/cmlibarchive/libarchive/archive_read_support_filter_lzop.c index 23c18c7,0000000..4356b82 mode 100644,000000..100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lzop.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_lzop.c @@@ -1,494 -1,0 +1,494 @@@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_LZO_LZOCONF_H +#include +#endif +#ifdef HAVE_LZO_LZO1X_H +#include +#endif +#ifdef HAVE_ZLIB_H +#include /* for crc32 and adler32 */ +#endif + +#include "archive.h" +#if !defined(HAVE_ZLIB_H) &&\ + defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H) +#include "archive_crc32.h" +#endif +#include "archive_endian.h" +#include "archive_private.h" +#include "archive_read_private.h" + +#ifndef HAVE_ZLIB_H +#define adler32 lzo_adler32 +#endif + +#define LZOP_HEADER_MAGIC "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a" +#define LZOP_HEADER_MAGIC_LEN 9 + +#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H) +struct read_lzop { + unsigned char *out_block; + size_t out_block_size; + int64_t total_out; + int flags; + uint32_t compressed_cksum; + uint32_t uncompressed_cksum; + size_t compressed_size; + size_t uncompressed_size; + size_t unconsumed_bytes; + char in_stream; + char eof; /* True = found end of compressed data. */ +}; + +#define FILTER 0x0800 +#define CRC32_HEADER 0x1000 +#define EXTRA_FIELD 0x0040 +#define ADLER32_UNCOMPRESSED 0x0001 +#define ADLER32_COMPRESSED 0x0002 +#define CRC32_UNCOMPRESSED 0x0100 +#define CRC32_COMPRESSED 0x0200 +#define MAX_BLOCK_SIZE (64 * 1024 * 1024) + +static ssize_t lzop_filter_read(struct archive_read_filter *, const void **); +static int lzop_filter_close(struct archive_read_filter *); +#endif + +static int lzop_bidder_bid(struct archive_read_filter_bidder *, + struct archive_read_filter *); +static int lzop_bidder_init(struct archive_read_filter *); + +int +archive_read_support_filter_lzop(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct archive_read_filter_bidder *reader; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_filter_lzop"); + + if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + reader->data = NULL; + reader->bid = lzop_bidder_bid; + reader->init = lzop_bidder_init; + reader->options = NULL; + reader->free = NULL; + /* Signal the extent of lzop support with the return value here. */ +#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H) + return (ARCHIVE_OK); +#else + /* Return ARCHIVE_WARN since this always uses an external program. */ + archive_set_error(_a, ARCHIVE_ERRNO_MISC, + "Using external lzop program for lzop decompression"); + return (ARCHIVE_WARN); +#endif +} + +/* + * Bidder just verifies the header and returns the number of verified bits. + */ +static int +lzop_bidder_bid(struct archive_read_filter_bidder *self, + struct archive_read_filter *filter) +{ + const unsigned char *p; + ssize_t avail; + + (void)self; /* UNUSED */ + + p = __archive_read_filter_ahead(filter, LZOP_HEADER_MAGIC_LEN, &avail); + if (p == NULL || avail == 0) + return (0); + + if (memcmp(p, LZOP_HEADER_MAGIC, LZOP_HEADER_MAGIC_LEN)) + return (0); + + return (LZOP_HEADER_MAGIC_LEN * 8); +} + +#if !defined(HAVE_LZO_LZOCONF_H) || !defined(HAVE_LZO_LZO1X_H) +/* + * If we don't have the library on this system, we can't do the + * decompression directly. We can, however, try to run "lzop -d" + * in case that's available. + */ +static int +lzop_bidder_init(struct archive_read_filter *self) +{ + int r; + + r = __archive_read_program(self, "lzop -d"); + /* Note: We set the format here even if __archive_read_program() + * above fails. We do, after all, know what the format is + * even if we weren't able to read it. */ + self->code = ARCHIVE_FILTER_LZOP; + self->name = "lzop"; + return (r); +} +#else +/* + * Initialize the filter object. + */ +static int +lzop_bidder_init(struct archive_read_filter *self) +{ + struct read_lzop *state; + + self->code = ARCHIVE_FILTER_LZOP; + self->name = "lzop"; + + state = (struct read_lzop *)calloc(sizeof(*state), 1); + if (state == NULL) { + archive_set_error(&self->archive->archive, ENOMEM, + "Can't allocate data for lzop decompression"); + return (ARCHIVE_FATAL); + } + + self->data = state; + self->read = lzop_filter_read; + self->skip = NULL; /* not supported */ + self->close = lzop_filter_close; + + return (ARCHIVE_OK); +} + +static int +consume_header(struct archive_read_filter *self) +{ + struct read_lzop *state = (struct read_lzop *)self->data; + const unsigned char *p, *_p; + unsigned checksum, flags, len, method, version; + + /* + * Check LZOP magic code. + */ + p = __archive_read_filter_ahead(self->upstream, + LZOP_HEADER_MAGIC_LEN, NULL); + if (p == NULL) + return (ARCHIVE_EOF); + + if (memcmp(p, LZOP_HEADER_MAGIC, LZOP_HEADER_MAGIC_LEN)) + return (ARCHIVE_EOF); + __archive_read_filter_consume(self->upstream, + LZOP_HEADER_MAGIC_LEN); + + p = __archive_read_filter_ahead(self->upstream, 29, NULL); + if (p == NULL) + goto truncated; + _p = p; + version = archive_be16dec(p); + p += 4;/* version(2 bytes) + library version(2 bytes) */ + + if (version >= 0x940) { + unsigned reqversion = archive_be16dec(p); p += 2; + if (reqversion < 0x900) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, "Invalid required version"); + return (ARCHIVE_FAILED); + } + } + + method = *p++; + if (method < 1 || method > 3) { + archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, + "Unsupported method"); + return (ARCHIVE_FAILED); + } + + if (version >= 0x940) { + unsigned level = *p++; +#if 0 + unsigned default_level[] = {0, 3, 1, 9}; +#endif + if (level == 0) + /* Method is 1..3 here due to check above. */ +#if 0 /* Avoid an error Clang Static Analyzer claims + "Value stored to 'level' is never read". */ + level = default_level[method]; +#else + ;/* NOP */ +#endif + else if (level > 9) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, "Invalid level"); + return (ARCHIVE_FAILED); + } + } + + flags = archive_be32dec(p); p += 4; + + if (flags & FILTER) + p += 4; /* Skip filter */ + p += 4; /* Skip mode */ + if (version >= 0x940) + p += 8; /* Skip mtime */ + else + p += 4; /* Skip mtime */ + len = *p++; /* Read filename length */ + len += p - _p; + /* Make sure we have all bytes we need to calculate checksum. */ + p = __archive_read_filter_ahead(self->upstream, len + 4, NULL); + if (p == NULL) + goto truncated; + if (flags & CRC32_HEADER) + checksum = crc32(crc32(0, NULL, 0), p, len); + else + checksum = adler32(adler32(0, NULL, 0), p, len); + if (archive_be32dec(p + len) != checksum) + goto corrupted; + __archive_read_filter_consume(self->upstream, len + 4); + if (flags & EXTRA_FIELD) { + /* Skip extra field */ + p = __archive_read_filter_ahead(self->upstream, 4, NULL); + if (p == NULL) + goto truncated; + len = archive_be32dec(p); + __archive_read_filter_consume(self->upstream, len + 4 + 4); + } + state->flags = flags; + state->in_stream = 1; + return (ARCHIVE_OK); +truncated: + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data"); + return (ARCHIVE_FAILED); +corrupted: + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Corrupted lzop header"); + return (ARCHIVE_FAILED); +} + +static int +consume_block_info(struct archive_read_filter *self) +{ + struct read_lzop *state = (struct read_lzop *)self->data; + const unsigned char *p; + unsigned flags = state->flags; + + p = __archive_read_filter_ahead(self->upstream, 4, NULL); + if (p == NULL) + goto truncated; + state->uncompressed_size = archive_be32dec(p); + __archive_read_filter_consume(self->upstream, 4); + if (state->uncompressed_size == 0) + return (ARCHIVE_EOF); + if (state->uncompressed_size > MAX_BLOCK_SIZE) + goto corrupted; + + p = __archive_read_filter_ahead(self->upstream, 4, NULL); + if (p == NULL) + goto truncated; + state->compressed_size = archive_be32dec(p); + __archive_read_filter_consume(self->upstream, 4); + if (state->compressed_size > state->uncompressed_size) + goto corrupted; + + if (flags & (CRC32_UNCOMPRESSED | ADLER32_UNCOMPRESSED)) { + p = __archive_read_filter_ahead(self->upstream, 4, NULL); + if (p == NULL) + goto truncated; + state->compressed_cksum = state->uncompressed_cksum = + archive_be32dec(p); + __archive_read_filter_consume(self->upstream, 4); + } + if ((flags & (CRC32_COMPRESSED | ADLER32_COMPRESSED)) && + state->compressed_size < state->uncompressed_size) { + p = __archive_read_filter_ahead(self->upstream, 4, NULL); + if (p == NULL) + goto truncated; + state->compressed_cksum = archive_be32dec(p); + __archive_read_filter_consume(self->upstream, 4); + } + return (ARCHIVE_OK); +truncated: + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data"); + return (ARCHIVE_FAILED); +corrupted: + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Corrupted lzop header"); + return (ARCHIVE_FAILED); +} + +static ssize_t +lzop_filter_read(struct archive_read_filter *self, const void **p) +{ + struct read_lzop *state = (struct read_lzop *)self->data; + const void *b; + lzo_uint out_size; + uint32_t cksum; + int ret, r; + + if (state->unconsumed_bytes) { + __archive_read_filter_consume(self->upstream, + state->unconsumed_bytes); + state->unconsumed_bytes = 0; + } + if (state->eof) + return (0); + + for (;;) { + if (!state->in_stream) { + ret = consume_header(self); + if (ret < ARCHIVE_OK) + return (ret); + if (ret == ARCHIVE_EOF) { + state->eof = 1; + return (0); + } + } + ret = consume_block_info(self); + if (ret < ARCHIVE_OK) + return (ret); + if (ret == ARCHIVE_EOF) + state->in_stream = 0; + else + break; + } + + if (state->out_block == NULL || + state->out_block_size < state->uncompressed_size) { + void *new_block; + + new_block = realloc(state->out_block, state->uncompressed_size); + if (new_block == NULL) { + archive_set_error(&self->archive->archive, ENOMEM, + "Can't allocate data for lzop decompression"); + return (ARCHIVE_FATAL); + } + state->out_block = new_block; + state->out_block_size = state->uncompressed_size; + } + + b = __archive_read_filter_ahead(self->upstream, + state->compressed_size, NULL); + if (b == NULL) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data"); + return (ARCHIVE_FATAL); + } + if (state->flags & CRC32_COMPRESSED) + cksum = crc32(crc32(0, NULL, 0), b, state->compressed_size); + else if (state->flags & ADLER32_COMPRESSED) + cksum = adler32(adler32(0, NULL, 0), b, state->compressed_size); + else + cksum = state->compressed_cksum; + if (cksum != state->compressed_cksum) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, "Corrupted data"); + return (ARCHIVE_FATAL); + } + + /* + * If the both uncompressed size and compressed size are the same, + * we do not decompress this block. + */ + if (state->uncompressed_size == state->compressed_size) { + *p = b; + state->total_out += state->compressed_size; + state->unconsumed_bytes = state->compressed_size; + return ((ssize_t)state->uncompressed_size); + } + + /* - * Drive lzo uncompresison. ++ * Drive lzo uncompression. + */ + out_size = (lzo_uint)state->uncompressed_size; + r = lzo1x_decompress_safe(b, (lzo_uint)state->compressed_size, + state->out_block, &out_size, NULL); + switch (r) { + case LZO_E_OK: + if (out_size == state->uncompressed_size) + break; + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, "Corrupted data"); + return (ARCHIVE_FATAL); + case LZO_E_OUT_OF_MEMORY: + archive_set_error(&self->archive->archive, ENOMEM, + "lzop decompression failed: out of memory"); + return (ARCHIVE_FATAL); + default: + archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, + "lzop decompression failed: %d", r); + return (ARCHIVE_FATAL); + } + + if (state->flags & CRC32_UNCOMPRESSED) + cksum = crc32(crc32(0, NULL, 0), state->out_block, + state->uncompressed_size); + else if (state->flags & ADLER32_UNCOMPRESSED) + cksum = adler32(adler32(0, NULL, 0), state->out_block, + state->uncompressed_size); + else + cksum = state->uncompressed_cksum; + if (cksum != state->uncompressed_cksum) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, "Corrupted data"); + return (ARCHIVE_FATAL); + } + + __archive_read_filter_consume(self->upstream, state->compressed_size); + *p = state->out_block; + state->total_out += out_size; + return ((ssize_t)out_size); +} + +/* + * Clean up the decompressor. + */ +static int +lzop_filter_close(struct archive_read_filter *self) +{ + struct read_lzop *state = (struct read_lzop *)self->data; + + free(state->out_block); + free(state); + return (ARCHIVE_OK); +} + +#endif diff --cc Utilities/cmlibarchive/libarchive/archive_read_support_filter_xz.c index 8f48273,0000000..a188186 mode 100644,000000..100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_filter_xz.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_filter_xz.c @@@ -1,988 -1,0 +1,796 @@@ +/*- + * Copyright (c) 2009-2011 Michihiro NAKAJIMA + * Copyright (c) 2003-2008 Tim Kientzle and Miklos Vajna + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#if HAVE_LZMA_H +#include - #elif HAVE_LZMADEC_H - #include +#endif + +#include "archive.h" +#include "archive_endian.h" +#include "archive_private.h" +#include "archive_read_private.h" + +#if HAVE_LZMA_H && HAVE_LIBLZMA + +struct private_data { + lzma_stream stream; + unsigned char *out_block; + size_t out_block_size; + int64_t total_out; + char eof; /* True = found end of compressed data. */ + char in_stream; + + /* Following variables are used for lzip only. */ + char lzip_ver; + uint32_t crc32; + int64_t member_in; + int64_t member_out; +}; + +#if LZMA_VERSION_MAJOR >= 5 +/* Effectively disable the limiter. */ +#define LZMA_MEMLIMIT UINT64_MAX +#else +/* NOTE: This needs to check memory size which running system has. */ +#define LZMA_MEMLIMIT (1U << 30) +#endif + +/* Combined lzip/lzma/xz filter */ +static ssize_t xz_filter_read(struct archive_read_filter *, const void **); +static int xz_filter_close(struct archive_read_filter *); +static int xz_lzma_bidder_init(struct archive_read_filter *); + - #elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC - - struct private_data { - lzmadec_stream stream; - unsigned char *out_block; - size_t out_block_size; - int64_t total_out; - char eof; /* True = found end of compressed data. */ - }; - - /* Lzma-only filter */ - static ssize_t lzma_filter_read(struct archive_read_filter *, const void **); - static int lzma_filter_close(struct archive_read_filter *); +#endif + +/* + * Note that we can detect xz and lzma compressed files even if we + * can't decompress them. (In fact, we like detecting them because we + * can give better error messages.) So the bid framework here gets + * compiled even if no lzma library is available. + */ +static int xz_bidder_bid(struct archive_read_filter_bidder *, + struct archive_read_filter *); +static int xz_bidder_init(struct archive_read_filter *); +static int lzma_bidder_bid(struct archive_read_filter_bidder *, + struct archive_read_filter *); +static int lzma_bidder_init(struct archive_read_filter *); +static int lzip_has_member(struct archive_read_filter *); +static int lzip_bidder_bid(struct archive_read_filter_bidder *, + struct archive_read_filter *); +static int lzip_bidder_init(struct archive_read_filter *); + +#if ARCHIVE_VERSION_NUMBER < 4000000 +/* Deprecated; remove in libarchive 4.0 */ +int +archive_read_support_compression_xz(struct archive *a) +{ + return archive_read_support_filter_xz(a); +} +#endif + +int +archive_read_support_filter_xz(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct archive_read_filter_bidder *bidder; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_filter_xz"); + + if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + bidder->data = NULL; + bidder->name = "xz"; + bidder->bid = xz_bidder_bid; + bidder->init = xz_bidder_init; + bidder->options = NULL; + bidder->free = NULL; +#if HAVE_LZMA_H && HAVE_LIBLZMA + return (ARCHIVE_OK); +#else + archive_set_error(_a, ARCHIVE_ERRNO_MISC, + "Using external xz program for xz decompression"); + return (ARCHIVE_WARN); +#endif +} + +#if ARCHIVE_VERSION_NUMBER < 4000000 +int +archive_read_support_compression_lzma(struct archive *a) +{ + return archive_read_support_filter_lzma(a); +} +#endif + +int +archive_read_support_filter_lzma(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct archive_read_filter_bidder *bidder; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_filter_lzma"); + + if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + bidder->data = NULL; + bidder->name = "lzma"; + bidder->bid = lzma_bidder_bid; + bidder->init = lzma_bidder_init; + bidder->options = NULL; + bidder->free = NULL; +#if HAVE_LZMA_H && HAVE_LIBLZMA + return (ARCHIVE_OK); - #elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC - return (ARCHIVE_OK); +#else + archive_set_error(_a, ARCHIVE_ERRNO_MISC, + "Using external lzma program for lzma decompression"); + return (ARCHIVE_WARN); +#endif +} + + +#if ARCHIVE_VERSION_NUMBER < 4000000 +int +archive_read_support_compression_lzip(struct archive *a) +{ + return archive_read_support_filter_lzip(a); +} +#endif + +int +archive_read_support_filter_lzip(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct archive_read_filter_bidder *bidder; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_filter_lzip"); + + if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + bidder->data = NULL; + bidder->name = "lzip"; + bidder->bid = lzip_bidder_bid; + bidder->init = lzip_bidder_init; + bidder->options = NULL; + bidder->free = NULL; +#if HAVE_LZMA_H && HAVE_LIBLZMA + return (ARCHIVE_OK); +#else + archive_set_error(_a, ARCHIVE_ERRNO_MISC, + "Using external lzip program for lzip decompression"); + return (ARCHIVE_WARN); +#endif +} + +/* + * Test whether we can handle this data. + */ +static int +xz_bidder_bid(struct archive_read_filter_bidder *self, + struct archive_read_filter *filter) +{ + const unsigned char *buffer; + ssize_t avail; + + (void)self; /* UNUSED */ + + buffer = __archive_read_filter_ahead(filter, 6, &avail); + if (buffer == NULL) + return (0); + + /* + * Verify Header Magic Bytes : FD 37 7A 58 5A 00 + */ + if (memcmp(buffer, "\xFD\x37\x7A\x58\x5A\x00", 6) != 0) + return (0); + + return (48); +} + +/* + * Test whether we can handle this data. + * + * LZMA has a rather poor file signature. Zeros do not + * make good signature bytes as a rule, and the only non-zero byte + * here is an ASCII character. For example, an uncompressed tar + * archive whose first file is ']' would satisfy this check. It may + * be necessary to exclude LZMA from compression_all() because of + * this. Clients of libarchive would then have to explicitly enable + * LZMA checking instead of (or in addition to) compression_all() when + * they have other evidence (file name, command-line option) to go on. + */ +static int +lzma_bidder_bid(struct archive_read_filter_bidder *self, + struct archive_read_filter *filter) +{ + const unsigned char *buffer; + ssize_t avail; + uint32_t dicsize; + uint64_t uncompressed_size; + int bits_checked; + + (void)self; /* UNUSED */ + + buffer = __archive_read_filter_ahead(filter, 14, &avail); + if (buffer == NULL) + return (0); + + /* First byte of raw LZMA stream is commonly 0x5d. + * The first byte is a special number, which consists of + * three parameters of LZMA compression, a number of literal + * context bits(which is from 0 to 8, default is 3), a number + * of literal pos bits(which is from 0 to 4, default is 0), + * a number of pos bits(which is from 0 to 4, default is 2). + * The first byte is made by + * (pos bits * 5 + literal pos bit) * 9 + * literal contest bit, + * and so the default value in this field is + * (2 * 5 + 0) * 9 + 3 = 0x5d. + * lzma of LZMA SDK has options to change those parameters. + * It means a range of this field is from 0 to 224. And lzma of + * XZ Utils with option -e records 0x5e in this field. */ + /* NOTE: If this checking of the first byte increases false + * recognition, we should allow only 0x5d and 0x5e for the first + * byte of LZMA stream. */ + bits_checked = 0; + if (buffer[0] > (4 * 5 + 4) * 9 + 8) + return (0); + /* Most likely value in the first byte of LZMA stream. */ + if (buffer[0] == 0x5d || buffer[0] == 0x5e) + bits_checked += 8; + + /* Sixth through fourteenth bytes are uncompressed size, + * stored in little-endian order. `-1' means uncompressed + * size is unknown and lzma of XZ Utils always records `-1' + * in this field. */ + uncompressed_size = archive_le64dec(buffer+5); + if (uncompressed_size == (uint64_t)ARCHIVE_LITERAL_LL(-1)) + bits_checked += 64; + + /* Second through fifth bytes are dictionary size, stored in + * little-endian order. The minimum dictionary size is + * 1 << 12(4KiB) which the lzma of LZMA SDK uses with option - * -d12 and the maxinam dictionary size is 1 << 27(128MiB) ++ * -d12 and the maximum dictionary size is 1 << 27(128MiB) + * which the one uses with option -d27. + * NOTE: A comment of LZMA SDK source code says this dictionary + * range is from 1 << 12 to 1 << 30. */ + dicsize = archive_le32dec(buffer+1); + switch (dicsize) { + case 0x00001000:/* lzma of LZMA SDK option -d12. */ + case 0x00002000:/* lzma of LZMA SDK option -d13. */ + case 0x00004000:/* lzma of LZMA SDK option -d14. */ + case 0x00008000:/* lzma of LZMA SDK option -d15. */ + case 0x00010000:/* lzma of XZ Utils option -0 and -1. + * lzma of LZMA SDK option -d16. */ + case 0x00020000:/* lzma of LZMA SDK option -d17. */ + case 0x00040000:/* lzma of LZMA SDK option -d18. */ + case 0x00080000:/* lzma of XZ Utils option -2. + * lzma of LZMA SDK option -d19. */ + case 0x00100000:/* lzma of XZ Utils option -3. + * lzma of LZMA SDK option -d20. */ + case 0x00200000:/* lzma of XZ Utils option -4. + * lzma of LZMA SDK option -d21. */ + case 0x00400000:/* lzma of XZ Utils option -5. + * lzma of LZMA SDK option -d22. */ + case 0x00800000:/* lzma of XZ Utils option -6. + * lzma of LZMA SDK option -d23. */ + case 0x01000000:/* lzma of XZ Utils option -7. + * lzma of LZMA SDK option -d24. */ + case 0x02000000:/* lzma of XZ Utils option -8. + * lzma of LZMA SDK option -d25. */ + case 0x04000000:/* lzma of XZ Utils option -9. + * lzma of LZMA SDK option -d26. */ + case 0x08000000:/* lzma of LZMA SDK option -d27. */ + bits_checked += 32; + break; + default: + /* If a memory usage for encoding was not enough on + * the platform where LZMA stream was made, lzma of + * XZ Utils automatically decreased the dictionary + * size to enough memory for encoding by 1Mi bytes + * (1 << 20).*/ + if (dicsize <= 0x03F00000 && dicsize >= 0x00300000 && + (dicsize & ((1 << 20)-1)) == 0 && + bits_checked == 8 + 64) { + bits_checked += 32; + break; + } + /* Otherwise dictionary size is unlikely. But it is + * possible that someone makes lzma stream with + * liblzma/LZMA SDK in one's dictionary size. */ + return (0); + } + + /* TODO: The above test is still very weak. It would be + * good to do better. */ + + return (bits_checked); +} + +static int +lzip_has_member(struct archive_read_filter *filter) +{ + const unsigned char *buffer; + ssize_t avail; + int bits_checked; + int log2dic; + + buffer = __archive_read_filter_ahead(filter, 6, &avail); + if (buffer == NULL) + return (0); + + /* + * Verify Header Magic Bytes : 4C 5A 49 50 (`LZIP') + */ + bits_checked = 0; + if (memcmp(buffer, "LZIP", 4) != 0) + return (0); + bits_checked += 32; + + /* A version number must be 0 or 1 */ + if (buffer[4] != 0 && buffer[4] != 1) + return (0); + bits_checked += 8; + + /* Dictionary size. */ + log2dic = buffer[5] & 0x1f; + if (log2dic < 12 || log2dic > 27) + return (0); + bits_checked += 8; + + return (bits_checked); +} + +static int +lzip_bidder_bid(struct archive_read_filter_bidder *self, + struct archive_read_filter *filter) +{ + + (void)self; /* UNUSED */ + return (lzip_has_member(filter)); +} + +#if HAVE_LZMA_H && HAVE_LIBLZMA + +/* + * liblzma 4.999.7 and later support both lzma and xz streams. + */ +static int +xz_bidder_init(struct archive_read_filter *self) +{ + self->code = ARCHIVE_FILTER_XZ; + self->name = "xz"; + return (xz_lzma_bidder_init(self)); +} + +static int +lzma_bidder_init(struct archive_read_filter *self) +{ + self->code = ARCHIVE_FILTER_LZMA; + self->name = "lzma"; + return (xz_lzma_bidder_init(self)); +} + +static int +lzip_bidder_init(struct archive_read_filter *self) +{ + self->code = ARCHIVE_FILTER_LZIP; + self->name = "lzip"; + return (xz_lzma_bidder_init(self)); +} + +/* + * Set an error code and choose an error message + */ +static void +set_error(struct archive_read_filter *self, int ret) +{ + + switch (ret) { + case LZMA_STREAM_END: /* Found end of stream. */ + case LZMA_OK: /* Decompressor made some progress. */ + break; + case LZMA_MEM_ERROR: + archive_set_error(&self->archive->archive, ENOMEM, + "Lzma library error: Cannot allocate memory"); + break; + case LZMA_MEMLIMIT_ERROR: + archive_set_error(&self->archive->archive, ENOMEM, + "Lzma library error: Out of memory"); + break; + case LZMA_FORMAT_ERROR: + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "Lzma library error: format not recognized"); + break; + case LZMA_OPTIONS_ERROR: + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "Lzma library error: Invalid options"); + break; + case LZMA_DATA_ERROR: + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "Lzma library error: Corrupted input data"); + break; + case LZMA_BUF_ERROR: + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "Lzma library error: No progress is possible"); + break; + default: + /* Return an error. */ + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "Lzma decompression failed: Unknown error"); + break; + } +} + +/* + * Setup the callbacks. + */ +static int +xz_lzma_bidder_init(struct archive_read_filter *self) +{ + static const size_t out_block_size = 64 * 1024; + void *out_block; + struct private_data *state; + int ret; + + state = (struct private_data *)calloc(sizeof(*state), 1); + out_block = (unsigned char *)malloc(out_block_size); + if (state == NULL || out_block == NULL) { + archive_set_error(&self->archive->archive, ENOMEM, + "Can't allocate data for xz decompression"); + free(out_block); + free(state); + return (ARCHIVE_FATAL); + } + + self->data = state; + state->out_block_size = out_block_size; + state->out_block = out_block; + self->read = xz_filter_read; + self->skip = NULL; /* not supported */ + self->close = xz_filter_close; + + state->stream.avail_in = 0; + + state->stream.next_out = state->out_block; + state->stream.avail_out = state->out_block_size; + + state->crc32 = 0; + if (self->code == ARCHIVE_FILTER_LZIP) { + /* + * We have to read a lzip header and use it to initialize + * compression library, thus we cannot initialize the + * library for lzip here. + */ + state->in_stream = 0; + return (ARCHIVE_OK); + } else + state->in_stream = 1; + + /* Initialize compression library. */ + if (self->code == ARCHIVE_FILTER_XZ) + ret = lzma_stream_decoder(&(state->stream), + LZMA_MEMLIMIT,/* memlimit */ + LZMA_CONCATENATED); + else + ret = lzma_alone_decoder(&(state->stream), + LZMA_MEMLIMIT);/* memlimit */ + + if (ret == LZMA_OK) + return (ARCHIVE_OK); + + /* Library setup failed: Choose an error message and clean up. */ + set_error(self, ret); + + free(state->out_block); + free(state); + self->data = NULL; + return (ARCHIVE_FATAL); +} + +static int +lzip_init(struct archive_read_filter *self) +{ + struct private_data *state; + const unsigned char *h; + lzma_filter filters[2]; + unsigned char props[5]; + ssize_t avail_in; + uint32_t dicsize; + int log2dic, ret; + + state = (struct private_data *)self->data; + h = __archive_read_filter_ahead(self->upstream, 6, &avail_in); + if (h == NULL) + return (ARCHIVE_FATAL); + + /* Get a version number. */ + state->lzip_ver = h[4]; + + /* + * Setup lzma property. + */ + props[0] = 0x5d; + + /* Get dictionary size. */ + log2dic = h[5] & 0x1f; + if (log2dic < 12 || log2dic > 27) + return (ARCHIVE_FATAL); + dicsize = 1U << log2dic; + if (log2dic > 12) + dicsize -= (dicsize / 16) * (h[5] >> 5); + archive_le32enc(props+1, dicsize); + + /* Consume lzip header. */ + __archive_read_filter_consume(self->upstream, 6); + state->member_in = 6; + + filters[0].id = LZMA_FILTER_LZMA1; + filters[0].options = NULL; + filters[1].id = LZMA_VLI_UNKNOWN; + filters[1].options = NULL; + + ret = lzma_properties_decode(&filters[0], NULL, props, sizeof(props)); + if (ret != LZMA_OK) { + set_error(self, ret); + return (ARCHIVE_FATAL); + } + ret = lzma_raw_decoder(&(state->stream), filters); - #if LZMA_VERSION < 50010000 + free(filters[0].options); - #endif + if (ret != LZMA_OK) { + set_error(self, ret); + return (ARCHIVE_FATAL); + } + return (ARCHIVE_OK); +} + +static int +lzip_tail(struct archive_read_filter *self) +{ + struct private_data *state; + const unsigned char *f; + ssize_t avail_in; + int tail; + + state = (struct private_data *)self->data; + if (state->lzip_ver == 0) + tail = 12; + else + tail = 20; + f = __archive_read_filter_ahead(self->upstream, tail, &avail_in); + if (f == NULL && avail_in < 0) + return (ARCHIVE_FATAL); + if (f == NULL || avail_in < tail) { + archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, + "Lzip: Remaining data is less bytes"); + return (ARCHIVE_FAILED); + } + + /* Check the crc32 value of the uncompressed data of the current + * member */ + if (state->crc32 != archive_le32dec(f)) { + archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, + "Lzip: CRC32 error"); + return (ARCHIVE_FAILED); + } + + /* Check the uncompressed size of the current member */ + if ((uint64_t)state->member_out != archive_le64dec(f + 4)) { + archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, + "Lzip: Uncompressed size error"); + return (ARCHIVE_FAILED); + } + + /* Check the total size of the current member */ + if (state->lzip_ver == 1 && + (uint64_t)state->member_in + tail != archive_le64dec(f + 12)) { + archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, + "Lzip: Member size error"); + return (ARCHIVE_FAILED); + } + __archive_read_filter_consume(self->upstream, tail); + + /* If current lzip data consists of multi member, try decompressing + * a next member. */ + if (lzip_has_member(self->upstream) != 0) { + state->in_stream = 0; + state->crc32 = 0; + state->member_out = 0; + state->member_in = 0; + state->eof = 0; + } + return (ARCHIVE_OK); +} + +/* + * Return the next block of decompressed data. + */ +static ssize_t +xz_filter_read(struct archive_read_filter *self, const void **p) +{ + struct private_data *state; + size_t decompressed; + ssize_t avail_in; + int ret; + + state = (struct private_data *)self->data; + + /* Empty our output buffer. */ + state->stream.next_out = state->out_block; + state->stream.avail_out = state->out_block_size; + + /* Try to fill the output buffer. */ + while (state->stream.avail_out > 0 && !state->eof) { + if (!state->in_stream) { + /* + * Initialize liblzma for lzip + */ + ret = lzip_init(self); + if (ret != ARCHIVE_OK) + return (ret); + state->in_stream = 1; + } + state->stream.next_in = + __archive_read_filter_ahead(self->upstream, 1, &avail_in); + if (state->stream.next_in == NULL && avail_in < 0) { + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_MISC, + "truncated input"); + return (ARCHIVE_FATAL); + } + state->stream.avail_in = avail_in; + + /* Decompress as much as we can in one pass. */ + ret = lzma_code(&(state->stream), + (state->stream.avail_in == 0)? LZMA_FINISH: LZMA_RUN); + switch (ret) { + case LZMA_STREAM_END: /* Found end of stream. */ + state->eof = 1; + /* FALL THROUGH */ + case LZMA_OK: /* Decompressor made some progress. */ + __archive_read_filter_consume(self->upstream, + avail_in - state->stream.avail_in); + state->member_in += + avail_in - state->stream.avail_in; + break; + default: + set_error(self, ret); + return (ARCHIVE_FATAL); + } + } + + decompressed = state->stream.next_out - state->out_block; + state->total_out += decompressed; + state->member_out += decompressed; + if (decompressed == 0) + *p = NULL; + else { + *p = state->out_block; + if (self->code == ARCHIVE_FILTER_LZIP) { + state->crc32 = lzma_crc32(state->out_block, + decompressed, state->crc32); + if (state->eof) { + ret = lzip_tail(self); + if (ret != ARCHIVE_OK) + return (ret); + } + } + } + return (decompressed); +} + +/* + * Clean up the decompressor. + */ +static int +xz_filter_close(struct archive_read_filter *self) +{ + struct private_data *state; + + state = (struct private_data *)self->data; + lzma_end(&(state->stream)); + free(state->out_block); + free(state); + return (ARCHIVE_OK); +} + +#else + - #if HAVE_LZMADEC_H && HAVE_LIBLZMADEC - - /* - * If we have the older liblzmadec library, then we can handle - * LZMA streams but not XZ streams. - */ - - /* - * Setup the callbacks. - */ - static int - lzma_bidder_init(struct archive_read_filter *self) - { - static const size_t out_block_size = 64 * 1024; - void *out_block; - struct private_data *state; - ssize_t ret, avail_in; - - self->code = ARCHIVE_FILTER_LZMA; - self->name = "lzma"; - - state = (struct private_data *)calloc(sizeof(*state), 1); - out_block = (unsigned char *)malloc(out_block_size); - if (state == NULL || out_block == NULL) { - archive_set_error(&self->archive->archive, ENOMEM, - "Can't allocate data for lzma decompression"); - free(out_block); - free(state); - return (ARCHIVE_FATAL); - } - - self->data = state; - state->out_block_size = out_block_size; - state->out_block = out_block; - self->read = lzma_filter_read; - self->skip = NULL; /* not supported */ - self->close = lzma_filter_close; - - /* Prime the lzma library with 18 bytes of input. */ - state->stream.next_in = (unsigned char *)(uintptr_t) - __archive_read_filter_ahead(self->upstream, 18, &avail_in); - if (state->stream.next_in == NULL) - return (ARCHIVE_FATAL); - state->stream.avail_in = avail_in; - state->stream.next_out = state->out_block; - state->stream.avail_out = state->out_block_size; - - /* Initialize compression library. */ - ret = lzmadec_init(&(state->stream)); - __archive_read_filter_consume(self->upstream, - avail_in - state->stream.avail_in); - if (ret == LZMADEC_OK) - return (ARCHIVE_OK); - - /* Library setup failed: Clean up. */ - archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, - "Internal error initializing lzma library"); - - /* Override the error message if we know what really went wrong. */ - switch (ret) { - case LZMADEC_HEADER_ERROR: - archive_set_error(&self->archive->archive, - ARCHIVE_ERRNO_MISC, - "Internal error initializing compression library: " - "invalid header"); - break; - case LZMADEC_MEM_ERROR: - archive_set_error(&self->archive->archive, ENOMEM, - "Internal error initializing compression library: " - "out of memory"); - break; - } - - free(state->out_block); - free(state); - self->data = NULL; - return (ARCHIVE_FATAL); - } - - /* - * Return the next block of decompressed data. - */ - static ssize_t - lzma_filter_read(struct archive_read_filter *self, const void **p) - { - struct private_data *state; - size_t decompressed; - ssize_t avail_in, ret; - - state = (struct private_data *)self->data; - - /* Empty our output buffer. */ - state->stream.next_out = state->out_block; - state->stream.avail_out = state->out_block_size; - - /* Try to fill the output buffer. */ - while (state->stream.avail_out > 0 && !state->eof) { - state->stream.next_in = (unsigned char *)(uintptr_t) - __archive_read_filter_ahead(self->upstream, 1, &avail_in); - if (state->stream.next_in == NULL && avail_in < 0) { - archive_set_error(&self->archive->archive, - ARCHIVE_ERRNO_MISC, - "truncated lzma input"); - return (ARCHIVE_FATAL); - } - state->stream.avail_in = avail_in; - - /* Decompress as much as we can in one pass. */ - ret = lzmadec_decode(&(state->stream), avail_in == 0); - switch (ret) { - case LZMADEC_STREAM_END: /* Found end of stream. */ - state->eof = 1; - /* FALL THROUGH */ - case LZMADEC_OK: /* Decompressor made some progress. */ - __archive_read_filter_consume(self->upstream, - avail_in - state->stream.avail_in); - break; - case LZMADEC_BUF_ERROR: /* Insufficient input data? */ - archive_set_error(&self->archive->archive, - ARCHIVE_ERRNO_MISC, - "Insufficient compressed data"); - return (ARCHIVE_FATAL); - default: - /* Return an error. */ - archive_set_error(&self->archive->archive, - ARCHIVE_ERRNO_MISC, - "Lzma decompression failed"); - return (ARCHIVE_FATAL); - } - } - - decompressed = state->stream.next_out - state->out_block; - state->total_out += decompressed; - if (decompressed == 0) - *p = NULL; - else - *p = state->out_block; - return (decompressed); - } - - /* - * Clean up the decompressor. - */ - static int - lzma_filter_close(struct archive_read_filter *self) - { - struct private_data *state; - int ret; - - state = (struct private_data *)self->data; - ret = ARCHIVE_OK; - switch (lzmadec_end(&(state->stream))) { - case LZMADEC_OK: - break; - default: - archive_set_error(&(self->archive->archive), - ARCHIVE_ERRNO_MISC, - "Failed to clean up %s compressor", - self->archive->archive.compression_name); - ret = ARCHIVE_FATAL; - } - - free(state->out_block); - free(state); - return (ret); - } - - #else - +/* + * + * If we have no suitable library on this system, we can't actually do + * the decompression. We can, however, still detect compressed + * archives and emit a useful message. + * + */ +static int +lzma_bidder_init(struct archive_read_filter *self) +{ + int r; + + r = __archive_read_program(self, "lzma -d -qq"); + /* Note: We set the format here even if __archive_read_program() + * above fails. We do, after all, know what the format is + * even if we weren't able to read it. */ + self->code = ARCHIVE_FILTER_LZMA; + self->name = "lzma"; + return (r); +} + - #endif /* HAVE_LZMADEC_H */ - - +static int +xz_bidder_init(struct archive_read_filter *self) +{ + int r; + + r = __archive_read_program(self, "xz -d -qq"); + /* Note: We set the format here even if __archive_read_program() + * above fails. We do, after all, know what the format is + * even if we weren't able to read it. */ + self->code = ARCHIVE_FILTER_XZ; + self->name = "xz"; + return (r); +} + +static int +lzip_bidder_init(struct archive_read_filter *self) +{ + int r; + + r = __archive_read_program(self, "lzip -d -q"); + /* Note: We set the format here even if __archive_read_program() + * above fails. We do, after all, know what the format is + * even if we weren't able to read it. */ + self->code = ARCHIVE_FILTER_LZIP; + self->name = "lzip"; + return (r); +} + - +#endif /* HAVE_LZMA_H */ diff --cc Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c index a33ea4f,0000000..96774f4 mode 100644,000000..100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_7zip.c @@@ -1,3883 -1,0 +1,3886 @@@ +/*- + * Copyright (c) 2011 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_BZLIB_H +#include +#endif +#ifdef HAVE_LZMA_H +#include +#endif +#ifdef HAVE_ZLIB_H +#include +#endif + +#include "archive.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_ppmd7_private.h" +#include "archive_private.h" +#include "archive_read_private.h" +#include "archive_endian.h" + +#ifndef HAVE_ZLIB_H +#include "archive_crc32.h" +#endif + +#define _7ZIP_SIGNATURE "7z\xBC\xAF\x27\x1C" +#define SFX_MIN_ADDR 0x27000 +#define SFX_MAX_ADDR 0x60000 + + +/* + * Codec ID + */ +#define _7Z_COPY 0 +#define _7Z_LZMA 0x030101 +#define _7Z_LZMA2 0x21 +#define _7Z_DEFLATE 0x040108 +#define _7Z_BZ2 0x040202 +#define _7Z_PPMD 0x030401 +#define _7Z_DELTA 0x03 +#define _7Z_CRYPTO_MAIN_ZIP 0x06F10101 /* Main Zip crypto algo */ +#define _7Z_CRYPTO_RAR_29 0x06F10303 /* Rar29 AES-128 + (modified SHA-1) */ +#define _7Z_CRYPTO_AES_256_SHA_256 0x06F10701 /* AES-256 + SHA-256 */ + + +#define _7Z_X86 0x03030103 +#define _7Z_X86_BCJ2 0x0303011B +#define _7Z_POWERPC 0x03030205 +#define _7Z_IA64 0x03030401 +#define _7Z_ARM 0x03030501 +#define _7Z_ARMTHUMB 0x03030701 +#define _7Z_SPARC 0x03030805 + +/* + * 7-Zip header property IDs. + */ +#define kEnd 0x00 +#define kHeader 0x01 +#define kArchiveProperties 0x02 +#define kAdditionalStreamsInfo 0x03 +#define kMainStreamsInfo 0x04 +#define kFilesInfo 0x05 +#define kPackInfo 0x06 +#define kUnPackInfo 0x07 +#define kSubStreamsInfo 0x08 +#define kSize 0x09 +#define kCRC 0x0A +#define kFolder 0x0B +#define kCodersUnPackSize 0x0C +#define kNumUnPackStream 0x0D +#define kEmptyStream 0x0E +#define kEmptyFile 0x0F +#define kAnti 0x10 +#define kName 0x11 +#define kCTime 0x12 +#define kATime 0x13 +#define kMTime 0x14 +#define kAttributes 0x15 +#define kEncodedHeader 0x17 +#define kDummy 0x19 + +struct _7z_digests { + unsigned char *defineds; + uint32_t *digests; +}; + + +struct _7z_folder { + uint64_t numCoders; + struct _7z_coder { + unsigned long codec; + uint64_t numInStreams; + uint64_t numOutStreams; + uint64_t propertiesSize; + unsigned char *properties; + } *coders; + uint64_t numBindPairs; + struct { + uint64_t inIndex; + uint64_t outIndex; + } *bindPairs; + uint64_t numPackedStreams; + uint64_t *packedStreams; + uint64_t numInStreams; + uint64_t numOutStreams; + uint64_t *unPackSize; + unsigned char digest_defined; + uint32_t digest; + uint64_t numUnpackStreams; + uint32_t packIndex; + /* Unoperated bytes. */ + uint64_t skipped_bytes; +}; + +struct _7z_coders_info { + uint64_t numFolders; + struct _7z_folder *folders; + uint64_t dataStreamIndex; +}; + +struct _7z_pack_info { + uint64_t pos; + uint64_t numPackStreams; + uint64_t *sizes; + struct _7z_digests digest; + /* Calculated from pos and numPackStreams. */ + uint64_t *positions; +}; + +struct _7z_substream_info { + size_t unpack_streams; + uint64_t *unpackSizes; + unsigned char *digestsDefined; + uint32_t *digests; +}; + +struct _7z_stream_info { + struct _7z_pack_info pi; + struct _7z_coders_info ci; + struct _7z_substream_info ss; +}; + +struct _7z_header_info { + uint64_t dataIndex; + + unsigned char *emptyStreamBools; + unsigned char *emptyFileBools; + unsigned char *antiBools; + unsigned char *attrBools; +}; + +struct _7zip_entry { + size_t name_len; + unsigned char *utf16name; +#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG) + const wchar_t *wname; +#endif + uint32_t folderIndex; + uint32_t ssIndex; + unsigned flg; +#define MTIME_IS_SET (1<<0) +#define ATIME_IS_SET (1<<1) +#define CTIME_IS_SET (1<<2) +#define CRC32_IS_SET (1<<3) +#define HAS_STREAM (1<<4) + + time_t mtime; + time_t atime; + time_t ctime; + long mtime_ns; + long atime_ns; + long ctime_ns; + uint32_t mode; + uint32_t attr; +}; + +struct _7zip { + /* Structural information about the archive. */ + struct _7z_stream_info si; + + int header_is_being_read; + int header_is_encoded; + uint64_t header_bytes_remaining; + unsigned long header_crc32; - /* Header offset to check that reading pointes of the file contens ++ /* Header offset to check that reading points of the file contents + * will not exceed the header. */ + uint64_t header_offset; + /* Base offset of the archive file for a seek in case reading SFX. */ + uint64_t seek_base; + + /* List of entries */ + size_t entries_remaining; + uint64_t numFiles; + struct _7zip_entry *entries; + struct _7zip_entry *entry; + unsigned char *entry_names; + + /* entry_bytes_remaining is the number of bytes we expect. */ + int64_t entry_offset; + uint64_t entry_bytes_remaining; + + /* Running CRC32 of the decompressed data */ + unsigned long entry_crc32; + + /* Flags to mark progress of decompression. */ + char end_of_entry; + + /* Uncompressed buffer control. */ +#define UBUFF_SIZE (64 * 1024) + unsigned char *uncompressed_buffer; + unsigned char *uncompressed_buffer_pointer; + size_t uncompressed_buffer_size; + size_t uncompressed_buffer_bytes_remaining; + + /* Offset of the compressed data. */ + int64_t stream_offset; + + /* + * Decompressing control data. + */ + unsigned folder_index; + uint64_t folder_outbytes_remaining; + unsigned pack_stream_index; + unsigned pack_stream_remaining; + uint64_t pack_stream_inbytes_remaining; + size_t pack_stream_bytes_unconsumed; + + /* The codec information of a folder. */ + unsigned long codec; + unsigned long codec2; + + /* + * Decompressor controllers. + */ - /* Decording LZMA1 and LZMA2 data. */ ++ /* Decoding LZMA1 and LZMA2 data. */ +#ifdef HAVE_LZMA_H + lzma_stream lzstream; + int lzstream_valid; +#endif - /* Decording bzip2 data. */ ++ /* Decoding bzip2 data. */ +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) + bz_stream bzstream; + int bzstream_valid; +#endif - /* Decording deflate data. */ ++ /* Decoding deflate data. */ +#ifdef HAVE_ZLIB_H + z_stream stream; + int stream_valid; +#endif - /* Decording PPMd data. */ ++ /* Decoding PPMd data. */ + int ppmd7_stat; + CPpmd7 ppmd7_context; + CPpmd7z_RangeDec range_dec; + IByteIn bytein; + struct { + const unsigned char *next_in; + int64_t avail_in; + int64_t total_in; + unsigned char *next_out; + int64_t avail_out; + int64_t total_out; + int overconsumed; + } ppstream; + int ppmd7_valid; + + /* Decoding BCJ and BCJ2 data. */ + uint32_t bcj_state; + size_t odd_bcj_size; + unsigned char odd_bcj[4]; + /* Decoding BCJ data. */ + size_t bcj_prevPosT; + uint32_t bcj_prevMask; + uint32_t bcj_ip; + + /* Decoding BCJ2 data. */ + size_t main_stream_bytes_remaining; + unsigned char *sub_stream_buff[3]; + size_t sub_stream_size[3]; + size_t sub_stream_bytes_remaining[3]; + unsigned char *tmp_stream_buff; + size_t tmp_stream_buff_size; + size_t tmp_stream_bytes_avail; + size_t tmp_stream_bytes_remaining; +#ifdef _LZMA_PROB32 +#define CProb uint32_t +#else +#define CProb uint16_t +#endif + CProb bcj2_p[256 + 2]; + uint8_t bcj2_prevByte; + uint32_t bcj2_range; + uint32_t bcj2_code; + uint64_t bcj2_outPos; + + /* Filename character-set conversion data. */ + struct archive_string_conv *sconv; + + char format_name[64]; + + /* Custom value that is non-zero if this archive contains encrypted entries. */ + int has_encrypted_entries; +}; + +/* Maximum entry size. This limitation prevents reading intentional + * corrupted 7-zip files on assuming there are not so many entries in + * the files. */ +#define UMAX_ENTRY ARCHIVE_LITERAL_ULL(100000000) + +static int archive_read_format_7zip_has_encrypted_entries(struct archive_read *); +static int archive_read_support_format_7zip_capabilities(struct archive_read *a); +static int archive_read_format_7zip_bid(struct archive_read *, int); +static int archive_read_format_7zip_cleanup(struct archive_read *); +static int archive_read_format_7zip_read_data(struct archive_read *, + const void **, size_t *, int64_t *); +static int archive_read_format_7zip_read_data_skip(struct archive_read *); +static int archive_read_format_7zip_read_header(struct archive_read *, + struct archive_entry *); +static int check_7zip_header_in_sfx(const char *); +static unsigned long decode_codec_id(const unsigned char *, size_t); +static int decode_encoded_header_info(struct archive_read *, + struct _7z_stream_info *); +static int decompress(struct archive_read *, struct _7zip *, + void *, size_t *, const void *, size_t *); +static ssize_t extract_pack_stream(struct archive_read *, size_t); +static void fileTimeToUtc(uint64_t, time_t *, long *); +static uint64_t folder_uncompressed_size(struct _7z_folder *); +static void free_CodersInfo(struct _7z_coders_info *); +static void free_Digest(struct _7z_digests *); +static void free_Folder(struct _7z_folder *); +static void free_Header(struct _7z_header_info *); +static void free_PackInfo(struct _7z_pack_info *); +static void free_StreamsInfo(struct _7z_stream_info *); +static void free_SubStreamsInfo(struct _7z_substream_info *); +static int free_decompression(struct archive_read *, struct _7zip *); +static ssize_t get_uncompressed_data(struct archive_read *, const void **, + size_t, size_t); +static const unsigned char * header_bytes(struct archive_read *, size_t); +static int init_decompression(struct archive_read *, struct _7zip *, + const struct _7z_coder *, const struct _7z_coder *); +static int parse_7zip_uint64(struct archive_read *, uint64_t *); +static int read_Bools(struct archive_read *, unsigned char *, size_t); +static int read_CodersInfo(struct archive_read *, + struct _7z_coders_info *); +static int read_Digests(struct archive_read *, struct _7z_digests *, + size_t); +static int read_Folder(struct archive_read *, struct _7z_folder *); +static int read_Header(struct archive_read *, struct _7z_header_info *, + int); +static int read_PackInfo(struct archive_read *, struct _7z_pack_info *); +static int read_StreamsInfo(struct archive_read *, + struct _7z_stream_info *); +static int read_SubStreamsInfo(struct archive_read *, + struct _7z_substream_info *, struct _7z_folder *, size_t); +static int read_Times(struct archive_read *, struct _7z_header_info *, + int); +static void read_consume(struct archive_read *); +static ssize_t read_stream(struct archive_read *, const void **, size_t, + size_t); +static int seek_pack(struct archive_read *); +static int64_t skip_stream(struct archive_read *, size_t); +static int skip_sfx(struct archive_read *, ssize_t); +static int slurp_central_directory(struct archive_read *, struct _7zip *, + struct _7z_header_info *); +static int setup_decode_folder(struct archive_read *, struct _7z_folder *, + int); +static void x86_Init(struct _7zip *); +static size_t x86_Convert(struct _7zip *, uint8_t *, size_t); +static ssize_t Bcj2_Decode(struct _7zip *, uint8_t *, size_t); + + +int +archive_read_support_format_7zip(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct _7zip *zip; + int r; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_format_7zip"); + + zip = calloc(1, sizeof(*zip)); + if (zip == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate 7zip data"); + return (ARCHIVE_FATAL); + } + + /* + * Until enough data has been read, we cannot tell about + * any encrypted entries yet. + */ + zip->has_encrypted_entries = ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW; + + + r = __archive_read_register_format(a, + zip, + "7zip", + archive_read_format_7zip_bid, + NULL, + archive_read_format_7zip_read_header, + archive_read_format_7zip_read_data, + archive_read_format_7zip_read_data_skip, + NULL, + archive_read_format_7zip_cleanup, + archive_read_support_format_7zip_capabilities, + archive_read_format_7zip_has_encrypted_entries); + + if (r != ARCHIVE_OK) + free(zip); + return (ARCHIVE_OK); +} + +static int +archive_read_support_format_7zip_capabilities(struct archive_read * a) +{ + (void)a; /* UNUSED */ + return (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA | + ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA); +} + + +static int +archive_read_format_7zip_has_encrypted_entries(struct archive_read *_a) +{ + if (_a && _a->format) { + struct _7zip * zip = (struct _7zip *)_a->format->data; + if (zip) { + return zip->has_encrypted_entries; + } + } + return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW; +} + +static int +archive_read_format_7zip_bid(struct archive_read *a, int best_bid) +{ + const char *p; + + /* If someone has already bid more than 32, then avoid + trashing the look-ahead buffers with a seek. */ + if (best_bid > 32) + return (-1); + + if ((p = __archive_read_ahead(a, 6, NULL)) == NULL) + return (0); + + /* If first six bytes are the 7-Zip signature, + * return the bid right now. */ + if (memcmp(p, _7ZIP_SIGNATURE, 6) == 0) + return (48); + + /* + * It may a 7-Zip SFX archive file. If first two bytes are + * 'M' and 'Z' available on Windows or first four bytes are + * "\x7F\x45LF" available on posix like system, seek the 7-Zip + * signature. Although we will perform a seek when reading + * a header, what we do not use __archive_read_seek() here is + * due to a bidding performance. + */ + if ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0) { + ssize_t offset = SFX_MIN_ADDR; + ssize_t window = 4096; + ssize_t bytes_avail; + while (offset + window <= (SFX_MAX_ADDR)) { + const char *buff = __archive_read_ahead(a, + offset + window, &bytes_avail); + if (buff == NULL) { + /* Remaining bytes are less than window. */ + window >>= 1; + if (window < 0x40) + return (0); + continue; + } + p = buff + offset; + while (p + 32 < buff + bytes_avail) { + int step = check_7zip_header_in_sfx(p); + if (step == 0) + return (48); + p += step; + } + offset = p - buff; + } + } + return (0); +} + +static int +check_7zip_header_in_sfx(const char *p) +{ + switch ((unsigned char)p[5]) { + case 0x1C: + if (memcmp(p, _7ZIP_SIGNATURE, 6) != 0) + return (6); + /* + * Test the CRC because its extraction code has 7-Zip + * Magic Code, so we should do this in order not to + * make a mis-detection. + */ + if (crc32(0, (const unsigned char *)p + 12, 20) + != archive_le32dec(p + 8)) + return (6); + /* Hit the header! */ + return (0); + case 0x37: return (5); + case 0x7A: return (4); + case 0xBC: return (3); + case 0xAF: return (2); + case 0x27: return (1); + default: return (6); + } +} + +static int +skip_sfx(struct archive_read *a, ssize_t bytes_avail) +{ + const void *h; + const char *p, *q; + size_t skip, offset; + ssize_t bytes, window; + + /* + * If bytes_avail > SFX_MIN_ADDR we do not have to call + * __archive_read_seek() at this time since we have - * alredy had enough data. ++ * already had enough data. + */ + if (bytes_avail > SFX_MIN_ADDR) + __archive_read_consume(a, SFX_MIN_ADDR); + else if (__archive_read_seek(a, SFX_MIN_ADDR, SEEK_SET) < 0) + return (ARCHIVE_FATAL); + + offset = 0; + window = 1; + while (offset + window <= SFX_MAX_ADDR - SFX_MIN_ADDR) { + h = __archive_read_ahead(a, window, &bytes); + if (h == NULL) { + /* Remaining bytes are less than window. */ + window >>= 1; + if (window < 0x40) + goto fatal; + continue; + } + if (bytes < 6) { + /* This case might happen when window == 1. */ + window = 4096; + continue; + } + p = (const char *)h; + q = p + bytes; + + /* + * Scan ahead until we find something that looks + * like the 7-Zip header. + */ + while (p + 32 < q) { + int step = check_7zip_header_in_sfx(p); + if (step == 0) { + struct _7zip *zip = + (struct _7zip *)a->format->data; + skip = p - (const char *)h; + __archive_read_consume(a, skip); + zip->seek_base = SFX_MIN_ADDR + offset + skip; + return (ARCHIVE_OK); + } + p += step; + } + skip = p - (const char *)h; + __archive_read_consume(a, skip); + offset += skip; + if (window == 1) + window = 4096; + } +fatal: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Couldn't find out 7-Zip header"); + return (ARCHIVE_FATAL); +} + +static int +archive_read_format_7zip_read_header(struct archive_read *a, + struct archive_entry *entry) +{ + struct _7zip *zip = (struct _7zip *)a->format->data; + struct _7zip_entry *zip_entry; + int r, ret = ARCHIVE_OK; + struct _7z_folder *folder = 0; + uint64_t fidx = 0; + + /* + * It should be sufficient to call archive_read_next_header() for + * a reader to determine if an entry is encrypted or not. If the + * encryption of an entry is only detectable when calling + * archive_read_data(), so be it. We'll do the same check there + * as well. + */ + if (zip->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) { + zip->has_encrypted_entries = 0; + } + + a->archive.archive_format = ARCHIVE_FORMAT_7ZIP; + if (a->archive.archive_format_name == NULL) + a->archive.archive_format_name = "7-Zip"; + + if (zip->entries == NULL) { + struct _7z_header_info header; + + memset(&header, 0, sizeof(header)); + r = slurp_central_directory(a, zip, &header); + free_Header(&header); + if (r != ARCHIVE_OK) + return (r); + zip->entries_remaining = (size_t)zip->numFiles; + zip->entry = zip->entries; + } else { + ++zip->entry; + } + zip_entry = zip->entry; + + if (zip->entries_remaining <= 0 || zip_entry == NULL) + return ARCHIVE_EOF; + --zip->entries_remaining; + + zip->entry_offset = 0; + zip->end_of_entry = 0; + zip->entry_crc32 = crc32(0, NULL, 0); + + /* Setup a string conversion for a filename. */ + if (zip->sconv == NULL) { + zip->sconv = archive_string_conversion_from_charset( + &a->archive, "UTF-16LE", 1); + if (zip->sconv == NULL) + return (ARCHIVE_FATAL); + } + + /* Figure out if the entry is encrypted by looking at the folder + that is associated to the current 7zip entry. If the folder + has a coder with a _7Z_CRYPTO codec then the folder is encrypted. + Hence the entry must also be encrypted. */ + if (zip_entry && zip_entry->folderIndex < zip->si.ci.numFolders) { + folder = &(zip->si.ci.folders[zip_entry->folderIndex]); + for (fidx=0; folder && fidxnumCoders; fidx++) { + switch(folder->coders[fidx].codec) { + case _7Z_CRYPTO_MAIN_ZIP: + case _7Z_CRYPTO_RAR_29: + case _7Z_CRYPTO_AES_256_SHA_256: { + archive_entry_set_is_data_encrypted(entry, 1); + zip->has_encrypted_entries = 1; + break; + } + } + } + } + + /* Now that we've checked for encryption, if there were still no + * encrypted entries found we can say for sure that there are none. + */ + if (zip->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) { + zip->has_encrypted_entries = 0; + } + + if (archive_entry_copy_pathname_l(entry, + (const char *)zip_entry->utf16name, + zip_entry->name_len, zip->sconv) != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Pathname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Pathname cannot be converted " + "from %s to current locale.", + archive_string_conversion_charset_name(zip->sconv)); + ret = ARCHIVE_WARN; + } + + /* Populate some additional entry fields: */ + archive_entry_set_mode(entry, zip_entry->mode); + if (zip_entry->flg & MTIME_IS_SET) + archive_entry_set_mtime(entry, zip_entry->mtime, + zip_entry->mtime_ns); + if (zip_entry->flg & CTIME_IS_SET) + archive_entry_set_ctime(entry, zip_entry->ctime, + zip_entry->ctime_ns); + if (zip_entry->flg & ATIME_IS_SET) + archive_entry_set_atime(entry, zip_entry->atime, + zip_entry->atime_ns); + if (zip_entry->ssIndex != (uint32_t)-1) { + zip->entry_bytes_remaining = + zip->si.ss.unpackSizes[zip_entry->ssIndex]; + archive_entry_set_size(entry, zip->entry_bytes_remaining); + } else { + zip->entry_bytes_remaining = 0; + archive_entry_set_size(entry, 0); + } + + /* If there's no body, force read_data() to return EOF immediately. */ + if (zip->entry_bytes_remaining < 1) + zip->end_of_entry = 1; + + if ((zip_entry->mode & AE_IFMT) == AE_IFLNK) { + unsigned char *symname = NULL; + size_t symsize = 0; + + /* + * Symbolic-name is recorded as its contents. We have to + * read the contents at this time. + */ + while (zip->entry_bytes_remaining > 0) { + const void *buff; + unsigned char *mem; + size_t size; + int64_t offset; + + r = archive_read_format_7zip_read_data(a, &buff, + &size, &offset); + if (r < ARCHIVE_WARN) { + free(symname); + return (r); + } + mem = realloc(symname, symsize + size + 1); + if (mem == NULL) { + free(symname); + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Symname"); + return (ARCHIVE_FATAL); + } + symname = mem; + memcpy(symname+symsize, buff, size); + symsize += size; + } + if (symsize == 0) { - /* If there is no synname, handle it as a regular ++ /* If there is no symname, handle it as a regular + * file. */ + zip_entry->mode &= ~AE_IFMT; + zip_entry->mode |= AE_IFREG; + archive_entry_set_mode(entry, zip_entry->mode); + } else { + symname[symsize] = '\0'; + archive_entry_copy_symlink(entry, + (const char *)symname); + } + free(symname); + archive_entry_set_size(entry, 0); + } + + /* Set up a more descriptive format name. */ + sprintf(zip->format_name, "7-Zip"); + a->archive.archive_format_name = zip->format_name; + + return (ret); +} + +static int +archive_read_format_7zip_read_data(struct archive_read *a, + const void **buff, size_t *size, int64_t *offset) +{ + struct _7zip *zip; + ssize_t bytes; + int ret = ARCHIVE_OK; + + zip = (struct _7zip *)(a->format->data); + + if (zip->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) { + zip->has_encrypted_entries = 0; + } + + if (zip->pack_stream_bytes_unconsumed) + read_consume(a); + + *offset = zip->entry_offset; + *size = 0; + *buff = NULL; + /* + * If we hit end-of-entry last time, clean up and return + * ARCHIVE_EOF this time. + */ + if (zip->end_of_entry) + return (ARCHIVE_EOF); + + bytes = read_stream(a, buff, + (size_t)zip->entry_bytes_remaining, 0); + if (bytes < 0) + return ((int)bytes); + if (bytes == 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated 7-Zip file body"); + return (ARCHIVE_FATAL); + } + zip->entry_bytes_remaining -= bytes; + if (zip->entry_bytes_remaining == 0) + zip->end_of_entry = 1; + + /* Update checksum */ + if ((zip->entry->flg & CRC32_IS_SET) && bytes) + zip->entry_crc32 = crc32(zip->entry_crc32, *buff, + (unsigned)bytes); + + /* If we hit the end, swallow any end-of-data marker. */ + if (zip->end_of_entry) { + /* Check computed CRC against file contents. */ + if ((zip->entry->flg & CRC32_IS_SET) && + zip->si.ss.digests[zip->entry->ssIndex] != + zip->entry_crc32) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "7-Zip bad CRC: 0x%lx should be 0x%lx", + (unsigned long)zip->entry_crc32, + (unsigned long)zip->si.ss.digests[ + zip->entry->ssIndex]); + ret = ARCHIVE_WARN; + } + } + + *size = bytes; + *offset = zip->entry_offset; + zip->entry_offset += bytes; + + return (ret); +} + +static int +archive_read_format_7zip_read_data_skip(struct archive_read *a) +{ + struct _7zip *zip; + int64_t bytes_skipped; + + zip = (struct _7zip *)(a->format->data); + + if (zip->pack_stream_bytes_unconsumed) + read_consume(a); + + /* If we've already read to end of data, we're done. */ + if (zip->end_of_entry) + return (ARCHIVE_OK); + + /* + * If the length is at the beginning, we can skip the + * compressed data much more quickly. + */ + bytes_skipped = skip_stream(a, (size_t)zip->entry_bytes_remaining); + if (bytes_skipped < 0) + return (ARCHIVE_FATAL); + zip->entry_bytes_remaining = 0; + + /* This entry is finished and done. */ + zip->end_of_entry = 1; + return (ARCHIVE_OK); +} + +static int +archive_read_format_7zip_cleanup(struct archive_read *a) +{ + struct _7zip *zip; + + zip = (struct _7zip *)(a->format->data); + free_StreamsInfo(&(zip->si)); + free(zip->entries); + free(zip->entry_names); + free_decompression(a, zip); + free(zip->uncompressed_buffer); + free(zip->sub_stream_buff[0]); + free(zip->sub_stream_buff[1]); + free(zip->sub_stream_buff[2]); + free(zip->tmp_stream_buff); + free(zip); + (a->format->data) = NULL; + return (ARCHIVE_OK); +} + +static void +read_consume(struct archive_read *a) +{ + struct _7zip *zip = (struct _7zip *)a->format->data; + + if (zip->pack_stream_bytes_unconsumed) { + __archive_read_consume(a, zip->pack_stream_bytes_unconsumed); + zip->stream_offset += zip->pack_stream_bytes_unconsumed; + zip->pack_stream_bytes_unconsumed = 0; + } +} + +#ifdef HAVE_LZMA_H + +/* + * Set an error code and choose an error message for liblzma. + */ +static void +set_error(struct archive_read *a, int ret) +{ + + switch (ret) { + case LZMA_STREAM_END: /* Found end of stream. */ + case LZMA_OK: /* Decompressor made some progress. */ + break; + case LZMA_MEM_ERROR: + archive_set_error(&a->archive, ENOMEM, + "Lzma library error: Cannot allocate memory"); + break; + case LZMA_MEMLIMIT_ERROR: + archive_set_error(&a->archive, ENOMEM, + "Lzma library error: Out of memory"); + break; + case LZMA_FORMAT_ERROR: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Lzma library error: format not recognized"); + break; + case LZMA_OPTIONS_ERROR: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Lzma library error: Invalid options"); + break; + case LZMA_DATA_ERROR: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Lzma library error: Corrupted input data"); + break; + case LZMA_BUF_ERROR: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Lzma library error: No progress is possible"); + break; + default: + /* Return an error. */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Lzma decompression failed: Unknown error"); + break; + } +} + +#endif + +static unsigned long +decode_codec_id(const unsigned char *codecId, size_t id_size) +{ + unsigned i; + unsigned long id = 0; + + for (i = 0; i < id_size; i++) { + id <<= 8; + id += codecId[i]; + } + return (id); +} + +static void * +ppmd_alloc(void *p, size_t size) +{ + (void)p; + return malloc(size); +} +static void +ppmd_free(void *p, void *address) +{ + (void)p; + free(address); +} +static Byte +ppmd_read(void *p) +{ + struct archive_read *a = ((IByteIn*)p)->a; + struct _7zip *zip = (struct _7zip *)(a->format->data); + Byte b; + + if (zip->ppstream.avail_in == 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated RAR file data"); + zip->ppstream.overconsumed = 1; + return (0); + } + b = *zip->ppstream.next_in++; + zip->ppstream.avail_in--; + zip->ppstream.total_in++; + return (b); +} + +static ISzAlloc g_szalloc = { ppmd_alloc, ppmd_free }; + +static int +init_decompression(struct archive_read *a, struct _7zip *zip, + const struct _7z_coder *coder1, const struct _7z_coder *coder2) +{ + int r; + + zip->codec = coder1->codec; + zip->codec2 = -1; + + switch (zip->codec) { + case _7Z_COPY: + case _7Z_BZ2: + case _7Z_DEFLATE: + case _7Z_PPMD: + if (coder2 != NULL) { + if (coder2->codec != _7Z_X86 && + coder2->codec != _7Z_X86_BCJ2) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Unsupported filter %lx for %lx", + coder2->codec, coder1->codec); + return (ARCHIVE_FAILED); + } + zip->codec2 = coder2->codec; + zip->bcj_state = 0; + if (coder2->codec == _7Z_X86) + x86_Init(zip); + } + break; + default: + break; + } + + switch (zip->codec) { + case _7Z_COPY: + break; + + case _7Z_LZMA: case _7Z_LZMA2: +#ifdef HAVE_LZMA_H +#if LZMA_VERSION_MAJOR >= 5 +/* Effectively disable the limiter. */ +#define LZMA_MEMLIMIT UINT64_MAX +#else +/* NOTE: This needs to check memory size which running system has. */ +#define LZMA_MEMLIMIT (1U << 30) +#endif + { + lzma_options_delta delta_opt; - lzma_filter filters[LZMA_FILTERS_MAX]; - #if LZMA_VERSION < 50010000 - lzma_filter *ff; - #endif ++ lzma_filter filters[LZMA_FILTERS_MAX], *ff; + int fi = 0; + + if (zip->lzstream_valid) { + lzma_end(&(zip->lzstream)); + zip->lzstream_valid = 0; + } + + /* + * NOTE: liblzma incompletely handle the BCJ+LZMA compressed + * data made by 7-Zip because 7-Zip does not add End-Of- + * Payload Marker(EOPM) at the end of LZMA compressed data, + * and so liblzma cannot know the end of the compressed data + * without EOPM. So consequently liblzma will not return last + * three or four bytes of uncompressed data because + * LZMA_FILTER_X86 filter does not handle input data if its + * data size is less than five bytes. If liblzma detect EOPM + * or know the uncompressed data size, liblzma will flush out + * the remaining that three or four bytes of uncompressed + * data. That is why we have to use our converting program + * for BCJ+LZMA. If we were able to tell the uncompressed + * size to liblzma when using lzma_raw_decoder() liblzma + * could correctly deal with BCJ+LZMA. But unfortunately + * there is no way to do that. + * Discussion about this can be found at XZ Utils forum. + */ + if (coder2 != NULL) { + zip->codec2 = coder2->codec; + + filters[fi].options = NULL; + switch (zip->codec2) { + case _7Z_X86: + if (zip->codec == _7Z_LZMA2) { + filters[fi].id = LZMA_FILTER_X86; + fi++; + } else + /* Use our filter. */ + x86_Init(zip); + break; + case _7Z_X86_BCJ2: + /* Use our filter. */ + zip->bcj_state = 0; + break; + case _7Z_DELTA: + filters[fi].id = LZMA_FILTER_DELTA; + memset(&delta_opt, 0, sizeof(delta_opt)); + delta_opt.type = LZMA_DELTA_TYPE_BYTE; + delta_opt.dist = 1; + filters[fi].options = &delta_opt; + fi++; + break; + /* Following filters have not been tested yet. */ + case _7Z_POWERPC: + filters[fi].id = LZMA_FILTER_POWERPC; + fi++; + break; + case _7Z_IA64: + filters[fi].id = LZMA_FILTER_IA64; + fi++; + break; + case _7Z_ARM: + filters[fi].id = LZMA_FILTER_ARM; + fi++; + break; + case _7Z_ARMTHUMB: + filters[fi].id = LZMA_FILTER_ARMTHUMB; + fi++; + break; + case _7Z_SPARC: + filters[fi].id = LZMA_FILTER_SPARC; + fi++; + break; + default: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Unexpected codec ID: %lX", zip->codec2); + return (ARCHIVE_FAILED); + } + } + + if (zip->codec == _7Z_LZMA2) + filters[fi].id = LZMA_FILTER_LZMA2; + else + filters[fi].id = LZMA_FILTER_LZMA1; + filters[fi].options = NULL; - #if LZMA_VERSION < 50010000 + ff = &filters[fi]; - #endif + r = lzma_properties_decode(&filters[fi], NULL, + coder1->properties, (size_t)coder1->propertiesSize); + if (r != LZMA_OK) { + set_error(a, r); + return (ARCHIVE_FAILED); + } + fi++; + + filters[fi].id = LZMA_VLI_UNKNOWN; + filters[fi].options = NULL; + r = lzma_raw_decoder(&(zip->lzstream), filters); - #if LZMA_VERSION < 50010000 + free(ff->options); - #endif + if (r != LZMA_OK) { + set_error(a, r); + return (ARCHIVE_FAILED); + } + zip->lzstream_valid = 1; + zip->lzstream.total_in = 0; + zip->lzstream.total_out = 0; + break; + } +#else + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "LZMA codec is unsupported"); + return (ARCHIVE_FAILED); +#endif + case _7Z_BZ2: +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) + if (zip->bzstream_valid) { + BZ2_bzDecompressEnd(&(zip->bzstream)); + zip->bzstream_valid = 0; + } + r = BZ2_bzDecompressInit(&(zip->bzstream), 0, 0); + if (r == BZ_MEM_ERROR) + r = BZ2_bzDecompressInit(&(zip->bzstream), 0, 1); + if (r != BZ_OK) { + int err = ARCHIVE_ERRNO_MISC; + const char *detail = NULL; + switch (r) { + case BZ_PARAM_ERROR: + detail = "invalid setup parameter"; + break; + case BZ_MEM_ERROR: + err = ENOMEM; + detail = "out of memory"; + break; + case BZ_CONFIG_ERROR: + detail = "mis-compiled library"; + break; + } + archive_set_error(&a->archive, err, + "Internal error initializing decompressor: %s", + detail != NULL ? detail : "??"); + zip->bzstream_valid = 0; + return (ARCHIVE_FAILED); + } + zip->bzstream_valid = 1; + zip->bzstream.total_in_lo32 = 0; + zip->bzstream.total_in_hi32 = 0; + zip->bzstream.total_out_lo32 = 0; + zip->bzstream.total_out_hi32 = 0; + break; +#else + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "BZ2 codec is unsupported"); + return (ARCHIVE_FAILED); +#endif + case _7Z_DEFLATE: +#ifdef HAVE_ZLIB_H + if (zip->stream_valid) + r = inflateReset(&(zip->stream)); + else + r = inflateInit2(&(zip->stream), + -15 /* Don't check for zlib header */); + if (r != Z_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Couldn't initialize zlib stream."); + return (ARCHIVE_FAILED); + } + zip->stream_valid = 1; + zip->stream.total_in = 0; + zip->stream.total_out = 0; + break; +#else + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "DEFLATE codec is unsupported"); + return (ARCHIVE_FAILED); +#endif + case _7Z_PPMD: + { + unsigned order; + uint32_t msize; + + if (zip->ppmd7_valid) { + __archive_ppmd7_functions.Ppmd7_Free( + &zip->ppmd7_context, &g_szalloc); + zip->ppmd7_valid = 0; + } + + if (coder1->propertiesSize < 5) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Malformed PPMd parameter"); + return (ARCHIVE_FAILED); + } + order = coder1->properties[0]; + msize = archive_le32dec(&(coder1->properties[1])); + if (order < PPMD7_MIN_ORDER || order > PPMD7_MAX_ORDER || + msize < PPMD7_MIN_MEM_SIZE || msize > PPMD7_MAX_MEM_SIZE) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Malformed PPMd parameter"); + return (ARCHIVE_FAILED); + } + __archive_ppmd7_functions.Ppmd7_Construct(&zip->ppmd7_context); + r = __archive_ppmd7_functions.Ppmd7_Alloc( + &zip->ppmd7_context, msize, &g_szalloc); + if (r == 0) { + archive_set_error(&a->archive, ENOMEM, + "Coludn't allocate memory for PPMd"); + return (ARCHIVE_FATAL); + } + __archive_ppmd7_functions.Ppmd7_Init( + &zip->ppmd7_context, order); + __archive_ppmd7_functions.Ppmd7z_RangeDec_CreateVTable( + &zip->range_dec); + zip->ppmd7_valid = 1; + zip->ppmd7_stat = 0; + zip->ppstream.overconsumed = 0; + zip->ppstream.total_in = 0; + zip->ppstream.total_out = 0; + break; + } + case _7Z_X86: + case _7Z_X86_BCJ2: + case _7Z_POWERPC: + case _7Z_IA64: + case _7Z_ARM: + case _7Z_ARMTHUMB: + case _7Z_SPARC: + case _7Z_DELTA: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Unexpected codec ID: %lX", zip->codec); + return (ARCHIVE_FAILED); + case _7Z_CRYPTO_MAIN_ZIP: + case _7Z_CRYPTO_RAR_29: + case _7Z_CRYPTO_AES_256_SHA_256: + if (a->entry) { + archive_entry_set_is_metadata_encrypted(a->entry, 1); + archive_entry_set_is_data_encrypted(a->entry, 1); + zip->has_encrypted_entries = 1; + } + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Crypto codec not supported yet (ID: 0x%lX)", zip->codec); + return (ARCHIVE_FAILED); + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Unknown codec ID: %lX", zip->codec); + return (ARCHIVE_FAILED); + } + + return (ARCHIVE_OK); +} + +static int +decompress(struct archive_read *a, struct _7zip *zip, + void *buff, size_t *outbytes, const void *b, size_t *used) +{ + const uint8_t *t_next_in; + uint8_t *t_next_out; + size_t o_avail_in, o_avail_out; + size_t t_avail_in, t_avail_out; + uint8_t *bcj2_next_out; + size_t bcj2_avail_out; + int r, ret = ARCHIVE_OK; + + t_avail_in = o_avail_in = *used; + t_avail_out = o_avail_out = *outbytes; + t_next_in = b; + t_next_out = buff; + + if (zip->codec != _7Z_LZMA2 && zip->codec2 == _7Z_X86) { + int i; + + /* Do not copy out the BCJ remaining bytes when the output + * buffer size is less than five bytes. */ + if (o_avail_in != 0 && t_avail_out < 5 && zip->odd_bcj_size) { + *used = 0; + *outbytes = 0; + return (ret); + } + for (i = 0; zip->odd_bcj_size > 0 && t_avail_out; i++) { + *t_next_out++ = zip->odd_bcj[i]; + t_avail_out--; + zip->odd_bcj_size--; + } + if (o_avail_in == 0 || t_avail_out == 0) { + *used = o_avail_in - t_avail_in; + *outbytes = o_avail_out - t_avail_out; + if (o_avail_in == 0) + ret = ARCHIVE_EOF; + return (ret); + } + } + + bcj2_next_out = t_next_out; + bcj2_avail_out = t_avail_out; + if (zip->codec2 == _7Z_X86_BCJ2) { + /* + * Decord a remaining decompressed main stream for BCJ2. + */ + if (zip->tmp_stream_bytes_remaining) { + ssize_t bytes; + size_t remaining = zip->tmp_stream_bytes_remaining; + bytes = Bcj2_Decode(zip, t_next_out, t_avail_out); + if (bytes < 0) { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "BCJ2 conversion Failed"); + return (ARCHIVE_FAILED); + } + zip->main_stream_bytes_remaining -= + remaining - zip->tmp_stream_bytes_remaining; + t_avail_out -= bytes; + if (o_avail_in == 0 || t_avail_out == 0) { + *used = 0; + *outbytes = o_avail_out - t_avail_out; + if (o_avail_in == 0 && + zip->tmp_stream_bytes_remaining) + ret = ARCHIVE_EOF; + return (ret); + } + t_next_out += bytes; + bcj2_next_out = t_next_out; + bcj2_avail_out = t_avail_out; + } + t_next_out = zip->tmp_stream_buff; + t_avail_out = zip->tmp_stream_buff_size; + } + + switch (zip->codec) { + case _7Z_COPY: + { + size_t bytes = + (t_avail_in > t_avail_out)?t_avail_out:t_avail_in; + + memcpy(t_next_out, t_next_in, bytes); + t_avail_in -= bytes; + t_avail_out -= bytes; + if (o_avail_in == 0) + ret = ARCHIVE_EOF; + break; + } +#ifdef HAVE_LZMA_H + case _7Z_LZMA: case _7Z_LZMA2: + zip->lzstream.next_in = t_next_in; + zip->lzstream.avail_in = t_avail_in; + zip->lzstream.next_out = t_next_out; + zip->lzstream.avail_out = t_avail_out; + + r = lzma_code(&(zip->lzstream), LZMA_RUN); + switch (r) { + case LZMA_STREAM_END: /* Found end of stream. */ + lzma_end(&(zip->lzstream)); + zip->lzstream_valid = 0; + ret = ARCHIVE_EOF; + break; + case LZMA_OK: /* Decompressor made some progress. */ + break; + default: + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "Decompression failed(%d)", + r); + return (ARCHIVE_FAILED); + } + t_avail_in = zip->lzstream.avail_in; + t_avail_out = zip->lzstream.avail_out; + break; +#endif +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) + case _7Z_BZ2: + zip->bzstream.next_in = (char *)(uintptr_t)t_next_in; + zip->bzstream.avail_in = t_avail_in; + zip->bzstream.next_out = (char *)(uintptr_t)t_next_out; + zip->bzstream.avail_out = t_avail_out; + r = BZ2_bzDecompress(&(zip->bzstream)); + switch (r) { + case BZ_STREAM_END: /* Found end of stream. */ + switch (BZ2_bzDecompressEnd(&(zip->bzstream))) { + case BZ_OK: + break; + default: + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "Failed to clean up decompressor"); + return (ARCHIVE_FAILED); + } + zip->bzstream_valid = 0; + ret = ARCHIVE_EOF; + break; + case BZ_OK: /* Decompressor made some progress. */ + break; + default: + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "bzip decompression failed"); + return (ARCHIVE_FAILED); + } + t_avail_in = zip->bzstream.avail_in; + t_avail_out = zip->bzstream.avail_out; + break; +#endif +#ifdef HAVE_ZLIB_H + case _7Z_DEFLATE: + zip->stream.next_in = (Bytef *)(uintptr_t)t_next_in; + zip->stream.avail_in = (uInt)t_avail_in; + zip->stream.next_out = t_next_out; + zip->stream.avail_out = (uInt)t_avail_out; + r = inflate(&(zip->stream), 0); + switch (r) { + case Z_STREAM_END: /* Found end of stream. */ + ret = ARCHIVE_EOF; + break; + case Z_OK: /* Decompressor made some progress.*/ + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "File decompression failed (%d)", r); + return (ARCHIVE_FAILED); + } + t_avail_in = zip->stream.avail_in; + t_avail_out = zip->stream.avail_out; + break; +#endif + case _7Z_PPMD: + { + uint64_t flush_bytes; + + if (!zip->ppmd7_valid || zip->ppmd7_stat < 0 || + t_avail_out <= 0) { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "Decompression internal error"); + return (ARCHIVE_FAILED); + } + zip->ppstream.next_in = t_next_in; + zip->ppstream.avail_in = t_avail_in; + zip->ppstream.next_out = t_next_out; + zip->ppstream.avail_out = t_avail_out; + if (zip->ppmd7_stat == 0) { + zip->bytein.a = a; + zip->bytein.Read = &ppmd_read; + zip->range_dec.Stream = &zip->bytein; + r = __archive_ppmd7_functions.Ppmd7z_RangeDec_Init( + &(zip->range_dec)); + if (r == 0) { + zip->ppmd7_stat = -1; + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Failed to initialize PPMd range decorder"); + return (ARCHIVE_FAILED); + } + if (zip->ppstream.overconsumed) { + zip->ppmd7_stat = -1; + return (ARCHIVE_FAILED); + } + zip->ppmd7_stat = 1; + } + + if (t_avail_in == 0) + /* XXX Flush out remaining decoded data XXX */ + flush_bytes = zip->folder_outbytes_remaining; + else + flush_bytes = 0; + + do { + int sym; + + sym = __archive_ppmd7_functions.Ppmd7_DecodeSymbol( + &(zip->ppmd7_context), &(zip->range_dec.p)); + if (sym < 0) { + zip->ppmd7_stat = -1; + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Failed to decode PPMd"); + return (ARCHIVE_FAILED); + } + if (zip->ppstream.overconsumed) { + zip->ppmd7_stat = -1; + return (ARCHIVE_FAILED); + } + *zip->ppstream.next_out++ = (unsigned char)sym; + zip->ppstream.avail_out--; + zip->ppstream.total_out++; + if (flush_bytes) + flush_bytes--; + } while (zip->ppstream.avail_out && + (zip->ppstream.avail_in || flush_bytes)); + + t_avail_in = (size_t)zip->ppstream.avail_in; + t_avail_out = (size_t)zip->ppstream.avail_out; + break; + } + default: + archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, + "Decompression internal error"); + return (ARCHIVE_FAILED); + } + if (ret != ARCHIVE_OK && ret != ARCHIVE_EOF) + return (ret); + + *used = o_avail_in - t_avail_in; + *outbytes = o_avail_out - t_avail_out; + + /* + * Decord BCJ. + */ + if (zip->codec != _7Z_LZMA2 && zip->codec2 == _7Z_X86) { + size_t l = x86_Convert(zip, buff, *outbytes); + zip->odd_bcj_size = *outbytes - l; + if (zip->odd_bcj_size > 0 && zip->odd_bcj_size <= 4 && + o_avail_in && ret != ARCHIVE_EOF) { + memcpy(zip->odd_bcj, ((unsigned char *)buff) + l, + zip->odd_bcj_size); + *outbytes = l; + } else + zip->odd_bcj_size = 0; + } + + /* + * Decord BCJ2 with a decompressed main stream. + */ + if (zip->codec2 == _7Z_X86_BCJ2) { + ssize_t bytes; + + zip->tmp_stream_bytes_avail = + zip->tmp_stream_buff_size - t_avail_out; + if (zip->tmp_stream_bytes_avail > + zip->main_stream_bytes_remaining) + zip->tmp_stream_bytes_avail = + zip->main_stream_bytes_remaining; + zip->tmp_stream_bytes_remaining = zip->tmp_stream_bytes_avail; + bytes = Bcj2_Decode(zip, bcj2_next_out, bcj2_avail_out); + if (bytes < 0) { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, "BCJ2 conversion Failed"); + return (ARCHIVE_FAILED); + } + zip->main_stream_bytes_remaining -= + zip->tmp_stream_bytes_avail + - zip->tmp_stream_bytes_remaining; + bcj2_avail_out -= bytes; + *outbytes = o_avail_out - bcj2_avail_out; + } + + return (ret); +} + +static int +free_decompression(struct archive_read *a, struct _7zip *zip) +{ + int r = ARCHIVE_OK; + +#if !defined(HAVE_ZLIB_H) &&\ + !(defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)) + (void)a;/* UNUSED */ +#endif +#ifdef HAVE_LZMA_H + if (zip->lzstream_valid) + lzma_end(&(zip->lzstream)); +#endif +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) + if (zip->bzstream_valid) { + if (BZ2_bzDecompressEnd(&(zip->bzstream)) != BZ_OK) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Failed to clean up bzip2 decompressor"); + r = ARCHIVE_FATAL; + } + zip->bzstream_valid = 0; + } +#endif +#ifdef HAVE_ZLIB_H + if (zip->stream_valid) { + if (inflateEnd(&(zip->stream)) != Z_OK) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Failed to clean up zlib decompressor"); + r = ARCHIVE_FATAL; + } + zip->stream_valid = 0; + } +#endif + if (zip->ppmd7_valid) { + __archive_ppmd7_functions.Ppmd7_Free( + &zip->ppmd7_context, &g_szalloc); + zip->ppmd7_valid = 0; + } + return (r); +} + +static int +parse_7zip_uint64(struct archive_read *a, uint64_t *val) +{ + const unsigned char *p; + unsigned char avail, mask; + int i; + + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + avail = *p; + mask = 0x80; + *val = 0; + for (i = 0; i < 8; i++) { + if (avail & mask) { + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + *val |= ((uint64_t)*p) << (8 * i); + mask >>= 1; + continue; + } + *val += ((uint64_t)(avail & (mask -1))) << (8 * i); + break; + } + return (0); +} + +static int +read_Bools(struct archive_read *a, unsigned char *data, size_t num) +{ + const unsigned char *p; + unsigned i, mask = 0, avail = 0; + + for (i = 0; i < num; i++) { + if (mask == 0) { + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + avail = *p; + mask = 0x80; + } + data[i] = (avail & mask)?1:0; + mask >>= 1; + } + return (0); +} + +static void +free_Digest(struct _7z_digests *d) +{ + free(d->defineds); + free(d->digests); +} + +static int +read_Digests(struct archive_read *a, struct _7z_digests *d, size_t num) +{ + const unsigned char *p; + unsigned i; + + if (num == 0) + return (-1); + memset(d, 0, sizeof(*d)); + + d->defineds = malloc(num); + if (d->defineds == NULL) + return (-1); + /* + * Read Bools. + */ + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + if (*p == 0) { + if (read_Bools(a, d->defineds, num) < 0) + return (-1); + } else + /* All are defined */ + memset(d->defineds, 1, num); + + d->digests = calloc(num, sizeof(*d->digests)); + if (d->digests == NULL) + return (-1); + for (i = 0; i < num; i++) { + if (d->defineds[i]) { + if ((p = header_bytes(a, 4)) == NULL) + return (-1); + d->digests[i] = archive_le32dec(p); + } + } + + return (0); +} + +static void +free_PackInfo(struct _7z_pack_info *pi) +{ + free(pi->sizes); + free(pi->positions); + free_Digest(&(pi->digest)); +} + +static int +read_PackInfo(struct archive_read *a, struct _7z_pack_info *pi) +{ + const unsigned char *p; + unsigned i; + + memset(pi, 0, sizeof(*pi)); + + /* + * Read PackPos. + */ + if (parse_7zip_uint64(a, &(pi->pos)) < 0) + return (-1); + + /* + * Read NumPackStreams. + */ + if (parse_7zip_uint64(a, &(pi->numPackStreams)) < 0) + return (-1); + if (pi->numPackStreams == 0) + return (-1); + if (UMAX_ENTRY < pi->numPackStreams) + return (-1); + + /* + * Read PackSizes[num] + */ + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + if (*p == kEnd) + /* PackSizes[num] are not present. */ + return (0); + if (*p != kSize) + return (-1); + pi->sizes = calloc((size_t)pi->numPackStreams, sizeof(uint64_t)); + pi->positions = calloc((size_t)pi->numPackStreams, sizeof(uint64_t)); + if (pi->sizes == NULL || pi->positions == NULL) + return (-1); + + for (i = 0; i < pi->numPackStreams; i++) { + if (parse_7zip_uint64(a, &(pi->sizes[i])) < 0) + return (-1); + } + + /* + * Read PackStreamDigests[num] + */ + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + if (*p == kEnd) { + /* PackStreamDigests[num] are not present. */ + pi->digest.defineds = + calloc((size_t)pi->numPackStreams, sizeof(*pi->digest.defineds)); + pi->digest.digests = + calloc((size_t)pi->numPackStreams, sizeof(*pi->digest.digests)); + if (pi->digest.defineds == NULL || pi->digest.digests == NULL) + return (-1); + return (0); + } + + if (*p != kSize) + return (-1); + + if (read_Digests(a, &(pi->digest), (size_t)pi->numPackStreams) < 0) + return (-1); + + /* + * Must be marked by kEnd. + */ + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + if (*p != kEnd) + return (-1); + return (0); +} + +static void +free_Folder(struct _7z_folder *f) +{ + unsigned i; + + if (f->coders) { + for (i = 0; i< f->numCoders; i++) { + free(f->coders[i].properties); + } + free(f->coders); + } + free(f->bindPairs); + free(f->packedStreams); + free(f->unPackSize); +} + +static int +read_Folder(struct archive_read *a, struct _7z_folder *f) +{ + struct _7zip *zip = (struct _7zip *)a->format->data; + const unsigned char *p; + uint64_t numInStreamsTotal = 0; + uint64_t numOutStreamsTotal = 0; + unsigned i; + + memset(f, 0, sizeof(*f)); + + /* + * Read NumCoders. + */ + if (parse_7zip_uint64(a, &(f->numCoders)) < 0) + return (-1); + if (f->numCoders > 4) + /* Too many coders. */ + return (-1); + + f->coders = calloc((size_t)f->numCoders, sizeof(*f->coders)); + if (f->coders == NULL) + return (-1); + for (i = 0; i< f->numCoders; i++) { + size_t codec_size; + int simple, attr; + + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + /* + * 0:3 CodecIdSize + * 4: 0 - IsSimple + * 1 - Is not Simple + * 5: 0 - No Attributes + * 1 - There are Attributes; + * 7: Must be zero. + */ + codec_size = *p & 0xf; + simple = (*p & 0x10)?0:1; + attr = *p & 0x20; + if (*p & 0x80) + return (-1);/* Not supported. */ + + /* + * Read Decompression Method IDs. + */ + if ((p = header_bytes(a, codec_size)) == NULL) + return (-1); + + f->coders[i].codec = decode_codec_id(p, codec_size); + + if (simple) { + f->coders[i].numInStreams = 1; + f->coders[i].numOutStreams = 1; + } else { + if (parse_7zip_uint64( + a, &(f->coders[i].numInStreams)) < 0) + return (-1); + if (UMAX_ENTRY < f->coders[i].numInStreams) + return (-1); + if (parse_7zip_uint64( + a, &(f->coders[i].numOutStreams)) < 0) + return (-1); + if (UMAX_ENTRY < f->coders[i].numOutStreams) + return (-1); + } + + if (attr) { + if (parse_7zip_uint64( + a, &(f->coders[i].propertiesSize)) < 0) + return (-1); + if ((p = header_bytes( + a, (size_t)f->coders[i].propertiesSize)) == NULL) + return (-1); + f->coders[i].properties = + malloc((size_t)f->coders[i].propertiesSize); + if (f->coders[i].properties == NULL) + return (-1); + memcpy(f->coders[i].properties, p, + (size_t)f->coders[i].propertiesSize); + } + + numInStreamsTotal += f->coders[i].numInStreams; + numOutStreamsTotal += f->coders[i].numOutStreams; + } + + if (numOutStreamsTotal == 0 || + numInStreamsTotal < numOutStreamsTotal-1) + return (-1); + + f->numBindPairs = numOutStreamsTotal - 1; + if (zip->header_bytes_remaining < f->numBindPairs) + return (-1); + if (f->numBindPairs > 0) { + f->bindPairs = + calloc((size_t)f->numBindPairs, sizeof(*f->bindPairs)); + if (f->bindPairs == NULL) + return (-1); + } else + f->bindPairs = NULL; + for (i = 0; i < f->numBindPairs; i++) { + if (parse_7zip_uint64(a, &(f->bindPairs[i].inIndex)) < 0) + return (-1); + if (UMAX_ENTRY < f->bindPairs[i].inIndex) + return (-1); + if (parse_7zip_uint64(a, &(f->bindPairs[i].outIndex)) < 0) + return (-1); + if (UMAX_ENTRY < f->bindPairs[i].outIndex) + return (-1); + } + + f->numPackedStreams = numInStreamsTotal - f->numBindPairs; + f->packedStreams = + calloc((size_t)f->numPackedStreams, sizeof(*f->packedStreams)); + if (f->packedStreams == NULL) + return (-1); + if (f->numPackedStreams == 1) { + for (i = 0; i < numInStreamsTotal; i++) { + unsigned j; + for (j = 0; j < f->numBindPairs; j++) { + if (f->bindPairs[j].inIndex == i) + break; + } + if (j == f->numBindPairs) + break; + } + if (i == numInStreamsTotal) + return (-1); + f->packedStreams[0] = i; + } else { + for (i = 0; i < f->numPackedStreams; i++) { + if (parse_7zip_uint64(a, &(f->packedStreams[i])) < 0) + return (-1); + if (UMAX_ENTRY < f->packedStreams[i]) + return (-1); + } + } + f->numInStreams = numInStreamsTotal; + f->numOutStreams = numOutStreamsTotal; + + return (0); +} + +static void +free_CodersInfo(struct _7z_coders_info *ci) +{ + unsigned i; + + if (ci->folders) { + for (i = 0; i < ci->numFolders; i++) + free_Folder(&(ci->folders[i])); + free(ci->folders); + } +} + +static int +read_CodersInfo(struct archive_read *a, struct _7z_coders_info *ci) +{ + const unsigned char *p; + struct _7z_digests digest; + unsigned i; + + memset(ci, 0, sizeof(*ci)); + memset(&digest, 0, sizeof(digest)); + + if ((p = header_bytes(a, 1)) == NULL) + goto failed; + if (*p != kFolder) + goto failed; + + /* + * Read NumFolders. + */ + if (parse_7zip_uint64(a, &(ci->numFolders)) < 0) + goto failed; + if (UMAX_ENTRY < ci->numFolders) + return (-1); + + /* + * Read External. + */ + if ((p = header_bytes(a, 1)) == NULL) + goto failed; + switch (*p) { + case 0: + ci->folders = + calloc((size_t)ci->numFolders, sizeof(*ci->folders)); + if (ci->folders == NULL) + return (-1); + for (i = 0; i < ci->numFolders; i++) { + if (read_Folder(a, &(ci->folders[i])) < 0) + goto failed; + } + break; + case 1: + if (parse_7zip_uint64(a, &(ci->dataStreamIndex)) < 0) + return (-1); + if (UMAX_ENTRY < ci->dataStreamIndex) + return (-1); + if (ci->numFolders > 0) { + archive_set_error(&a->archive, -1, + "Malformed 7-Zip archive"); + goto failed; + } + break; + default: + archive_set_error(&a->archive, -1, + "Malformed 7-Zip archive"); + goto failed; + } + + if ((p = header_bytes(a, 1)) == NULL) + goto failed; + if (*p != kCodersUnPackSize) + goto failed; + + for (i = 0; i < ci->numFolders; i++) { + struct _7z_folder *folder = &(ci->folders[i]); + unsigned j; + + folder->unPackSize = + calloc((size_t)folder->numOutStreams, sizeof(*folder->unPackSize)); + if (folder->unPackSize == NULL) + goto failed; + for (j = 0; j < folder->numOutStreams; j++) { + if (parse_7zip_uint64(a, &(folder->unPackSize[j])) < 0) + goto failed; + } + } + + /* + * Read CRCs. + */ + if ((p = header_bytes(a, 1)) == NULL) + goto failed; + if (*p == kEnd) + return (0); + if (*p != kCRC) + goto failed; + if (read_Digests(a, &digest, (size_t)ci->numFolders) < 0) + goto failed; + for (i = 0; i < ci->numFolders; i++) { + ci->folders[i].digest_defined = digest.defineds[i]; + ci->folders[i].digest = digest.digests[i]; + } + + /* + * Must be kEnd. + */ + if ((p = header_bytes(a, 1)) == NULL) + goto failed; + if (*p != kEnd) + goto failed; + free_Digest(&digest); + return (0); +failed: + free_Digest(&digest); + return (-1); +} + +static uint64_t +folder_uncompressed_size(struct _7z_folder *f) +{ + int n = (int)f->numOutStreams; + unsigned pairs = (unsigned)f->numBindPairs; + + while (--n >= 0) { + unsigned i; + for (i = 0; i < pairs; i++) { + if (f->bindPairs[i].outIndex == (uint64_t)n) + break; + } + if (i >= pairs) + return (f->unPackSize[n]); + } + return (0); +} + +static void +free_SubStreamsInfo(struct _7z_substream_info *ss) +{ + free(ss->unpackSizes); + free(ss->digestsDefined); + free(ss->digests); +} + +static int +read_SubStreamsInfo(struct archive_read *a, struct _7z_substream_info *ss, + struct _7z_folder *f, size_t numFolders) +{ + const unsigned char *p; + uint64_t *usizes; + size_t unpack_streams; + int type; + unsigned i; + uint32_t numDigests; + + memset(ss, 0, sizeof(*ss)); + + for (i = 0; i < numFolders; i++) + f[i].numUnpackStreams = 1; + + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + type = *p; + + if (type == kNumUnPackStream) { + unpack_streams = 0; + for (i = 0; i < numFolders; i++) { + if (parse_7zip_uint64(a, &(f[i].numUnpackStreams)) < 0) + return (-1); + if (UMAX_ENTRY < f[i].numUnpackStreams) + return (-1); + if (unpack_streams > SIZE_MAX - UMAX_ENTRY) { + return (-1); + } + unpack_streams += (size_t)f[i].numUnpackStreams; + } + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + type = *p; + } else + unpack_streams = numFolders; + + ss->unpack_streams = unpack_streams; + if (unpack_streams) { + ss->unpackSizes = calloc(unpack_streams, + sizeof(*ss->unpackSizes)); + ss->digestsDefined = calloc(unpack_streams, + sizeof(*ss->digestsDefined)); + ss->digests = calloc(unpack_streams, + sizeof(*ss->digests)); + if (ss->unpackSizes == NULL || ss->digestsDefined == NULL || + ss->digests == NULL) + return (-1); + } + + usizes = ss->unpackSizes; + for (i = 0; i < numFolders; i++) { + unsigned pack; + uint64_t sum; + + if (f[i].numUnpackStreams == 0) + continue; + + sum = 0; + if (type == kSize) { + for (pack = 1; pack < f[i].numUnpackStreams; pack++) { + if (parse_7zip_uint64(a, usizes) < 0) + return (-1); + sum += *usizes++; + } + } + *usizes++ = folder_uncompressed_size(&f[i]) - sum; + } + + if (type == kSize) { + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + type = *p; + } + + for (i = 0; i < unpack_streams; i++) { + ss->digestsDefined[i] = 0; + ss->digests[i] = 0; + } + + numDigests = 0; + for (i = 0; i < numFolders; i++) { + if (f[i].numUnpackStreams != 1 || !f[i].digest_defined) + numDigests += (uint32_t)f[i].numUnpackStreams; + } + + if (type == kCRC) { + struct _7z_digests tmpDigests; + unsigned char *digestsDefined = ss->digestsDefined; + uint32_t * digests = ss->digests; + int di = 0; + + memset(&tmpDigests, 0, sizeof(tmpDigests)); + if (read_Digests(a, &(tmpDigests), numDigests) < 0) { + free_Digest(&tmpDigests); + return (-1); + } + for (i = 0; i < numFolders; i++) { + if (f[i].numUnpackStreams == 1 && f[i].digest_defined) { + *digestsDefined++ = 1; + *digests++ = f[i].digest; + } else { + unsigned j; + + for (j = 0; j < f[i].numUnpackStreams; + j++, di++) { + *digestsDefined++ = + tmpDigests.defineds[di]; + *digests++ = + tmpDigests.digests[di]; + } + } + } + free_Digest(&tmpDigests); + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + type = *p; + } + + /* + * Must be kEnd. + */ + if (type != kEnd) + return (-1); + return (0); +} + +static void +free_StreamsInfo(struct _7z_stream_info *si) +{ + free_PackInfo(&(si->pi)); + free_CodersInfo(&(si->ci)); + free_SubStreamsInfo(&(si->ss)); +} + +static int +read_StreamsInfo(struct archive_read *a, struct _7z_stream_info *si) +{ + struct _7zip *zip = (struct _7zip *)a->format->data; + const unsigned char *p; + unsigned i; + + memset(si, 0, sizeof(*si)); + + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + if (*p == kPackInfo) { + uint64_t packPos; + + if (read_PackInfo(a, &(si->pi)) < 0) + return (-1); + + if (si->pi.positions == NULL || si->pi.sizes == NULL) + return (-1); + /* + * Calculate packed stream positions. + */ + packPos = si->pi.pos; + for (i = 0; i < si->pi.numPackStreams; i++) { + si->pi.positions[i] = packPos; + packPos += si->pi.sizes[i]; + if (packPos > zip->header_offset) + return (-1); + } + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + } + if (*p == kUnPackInfo) { + uint32_t packIndex; + struct _7z_folder *f; + + if (read_CodersInfo(a, &(si->ci)) < 0) + return (-1); + + /* + * Calculate packed stream indexes. + */ + packIndex = 0; + f = si->ci.folders; + for (i = 0; i < si->ci.numFolders; i++) { + f[i].packIndex = packIndex; + packIndex += (uint32_t)f[i].numPackedStreams; + if (packIndex > si->pi.numPackStreams) + return (-1); + } + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + } + + if (*p == kSubStreamsInfo) { + if (read_SubStreamsInfo(a, &(si->ss), + si->ci.folders, (size_t)si->ci.numFolders) < 0) + return (-1); + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + } + + /* + * Must be kEnd. + */ + if (*p != kEnd) + return (-1); + return (0); +} + +static void +free_Header(struct _7z_header_info *h) +{ + free(h->emptyStreamBools); + free(h->emptyFileBools); + free(h->antiBools); + free(h->attrBools); +} + +static int +read_Header(struct archive_read *a, struct _7z_header_info *h, + int check_header_id) +{ + struct _7zip *zip = (struct _7zip *)a->format->data; + const unsigned char *p; + struct _7z_folder *folders; + struct _7z_stream_info *si = &(zip->si); + struct _7zip_entry *entries; + uint32_t folderIndex, indexInFolder; + unsigned i; + int eindex, empty_streams, sindex; + + if (check_header_id) { + /* + * Read Header. + */ + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + if (*p != kHeader) + return (-1); + } + + /* + * Read ArchiveProperties. + */ + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + if (*p == kArchiveProperties) { + for (;;) { + uint64_t size; + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + if (*p == 0) + break; + if (parse_7zip_uint64(a, &size) < 0) + return (-1); + } + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + } + + /* + * Read MainStreamsInfo. + */ + if (*p == kMainStreamsInfo) { + if (read_StreamsInfo(a, &(zip->si)) < 0) + return (-1); + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + } + if (*p == kEnd) + return (0); + + /* + * Read FilesInfo. + */ + if (*p != kFilesInfo) + return (-1); + + if (parse_7zip_uint64(a, &(zip->numFiles)) < 0) + return (-1); + if (UMAX_ENTRY < zip->numFiles) + return (-1); + + zip->entries = calloc((size_t)zip->numFiles, sizeof(*zip->entries)); + if (zip->entries == NULL) + return (-1); + entries = zip->entries; + + empty_streams = 0; + for (;;) { + int type; + uint64_t size; + size_t ll; + + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + type = *p; + if (type == kEnd) + break; + + if (parse_7zip_uint64(a, &size) < 0) + return (-1); + if (zip->header_bytes_remaining < size) + return (-1); + ll = (size_t)size; + + switch (type) { + case kEmptyStream: ++ if (h->emptyStreamBools != NULL) ++ return (-1); + h->emptyStreamBools = calloc((size_t)zip->numFiles, + sizeof(*h->emptyStreamBools)); + if (h->emptyStreamBools == NULL) + return (-1); + if (read_Bools( + a, h->emptyStreamBools, (size_t)zip->numFiles) < 0) + return (-1); + empty_streams = 0; + for (i = 0; i < zip->numFiles; i++) { + if (h->emptyStreamBools[i]) + empty_streams++; + } + break; + case kEmptyFile: + if (empty_streams <= 0) { + /* Unexcepted sequence. Skip this. */ + if (header_bytes(a, ll) == NULL) + return (-1); + break; + } ++ if (h->emptyFileBools != NULL) ++ return (-1); + h->emptyFileBools = calloc(empty_streams, + sizeof(*h->emptyFileBools)); + if (h->emptyFileBools == NULL) + return (-1); + if (read_Bools(a, h->emptyFileBools, empty_streams) < 0) + return (-1); + break; + case kAnti: + if (empty_streams <= 0) { + /* Unexcepted sequence. Skip this. */ + if (header_bytes(a, ll) == NULL) + return (-1); + break; + } ++ if (h->antiBools != NULL) ++ return (-1); + h->antiBools = calloc(empty_streams, + sizeof(*h->antiBools)); + if (h->antiBools == NULL) + return (-1); + if (read_Bools(a, h->antiBools, empty_streams) < 0) + return (-1); + break; + case kCTime: + case kATime: + case kMTime: + if (read_Times(a, h, type) < 0) + return (-1); + break; + case kName: + { + unsigned char *np; + size_t nl, nb; + + /* Skip one byte. */ + if ((p = header_bytes(a, 1)) == NULL) + return (-1); + ll--; + + if ((ll & 1) || ll < zip->numFiles * 4) + return (-1); + ++ if (zip->entry_names != NULL) ++ return (-1); + zip->entry_names = malloc(ll); + if (zip->entry_names == NULL) + return (-1); + np = zip->entry_names; + nb = ll; + /* + * Copy whole file names. + * NOTE: This loop prevents from expanding + * the uncompressed buffer in order not to + * use extra memory resource. + */ + while (nb) { + size_t b; + if (nb > UBUFF_SIZE) + b = UBUFF_SIZE; + else + b = nb; + if ((p = header_bytes(a, b)) == NULL) + return (-1); + memcpy(np, p, b); + np += b; + nb -= b; + } + np = zip->entry_names; + nl = ll; + + for (i = 0; i < zip->numFiles; i++) { + entries[i].utf16name = np; +#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG) + entries[i].wname = (wchar_t *)np; +#endif + + /* Find a terminator. */ + while (nl >= 2 && (np[0] || np[1])) { + np += 2; + nl -= 2; + } + if (nl < 2) + return (-1);/* Terminator not found */ + entries[i].name_len = np - entries[i].utf16name; + np += 2; + nl -= 2; + } + break; + } + case kAttributes: + { + int allAreDefined; + + if ((p = header_bytes(a, 2)) == NULL) + return (-1); + allAreDefined = *p; ++ if (h->attrBools != NULL) ++ return (-1); + h->attrBools = calloc((size_t)zip->numFiles, + sizeof(*h->attrBools)); + if (h->attrBools == NULL) + return (-1); + if (allAreDefined) + memset(h->attrBools, 1, (size_t)zip->numFiles); + else { + if (read_Bools(a, h->attrBools, + (size_t)zip->numFiles) < 0) + return (-1); + } + for (i = 0; i < zip->numFiles; i++) { + if (h->attrBools[i]) { + if ((p = header_bytes(a, 4)) == NULL) + return (-1); + entries[i].attr = archive_le32dec(p); + } + } + break; + } + case kDummy: + if (ll == 0) + break; + default: + if (header_bytes(a, ll) == NULL) + return (-1); + break; + } + } + + /* + * Set up entry's attributes. + */ + folders = si->ci.folders; + eindex = sindex = 0; + folderIndex = indexInFolder = 0; + for (i = 0; i < zip->numFiles; i++) { + if (h->emptyStreamBools == NULL || h->emptyStreamBools[i] == 0) + entries[i].flg |= HAS_STREAM; + /* The high 16 bits of attributes is a posix file mode. */ + entries[i].mode = entries[i].attr >> 16; + if (entries[i].flg & HAS_STREAM) { + if ((size_t)sindex >= si->ss.unpack_streams) + return (-1); + if (entries[i].mode == 0) + entries[i].mode = AE_IFREG | 0666; + if (si->ss.digestsDefined[sindex]) + entries[i].flg |= CRC32_IS_SET; + entries[i].ssIndex = sindex; + sindex++; + } else { + int dir; + if (h->emptyFileBools == NULL) + dir = 1; + else { + if (h->emptyFileBools[eindex]) + dir = 0; + else + dir = 1; + eindex++; + } + if (entries[i].mode == 0) { + if (dir) + entries[i].mode = AE_IFDIR | 0777; + else + entries[i].mode = AE_IFREG | 0666; + } else if (dir && + (entries[i].mode & AE_IFMT) != AE_IFDIR) { + entries[i].mode &= ~AE_IFMT; + entries[i].mode |= AE_IFDIR; + } + if ((entries[i].mode & AE_IFMT) == AE_IFDIR && + entries[i].name_len >= 2 && + (entries[i].utf16name[entries[i].name_len-2] != '/' || + entries[i].utf16name[entries[i].name_len-1] != 0)) { + entries[i].utf16name[entries[i].name_len] = '/'; + entries[i].utf16name[entries[i].name_len+1] = 0; + entries[i].name_len += 2; + } + entries[i].ssIndex = -1; + } + if (entries[i].attr & 0x01) + entries[i].mode &= ~0222;/* Read only. */ + + if ((entries[i].flg & HAS_STREAM) == 0 && indexInFolder == 0) { + /* + * The entry is an empty file or a directory file, + * those both have no contents. + */ + entries[i].folderIndex = -1; + continue; + } + if (indexInFolder == 0) { + for (;;) { + if (folderIndex >= si->ci.numFolders) + return (-1); + if (folders[folderIndex].numUnpackStreams) + break; + folderIndex++; + } + } + entries[i].folderIndex = folderIndex; + if ((entries[i].flg & HAS_STREAM) == 0) + continue; + indexInFolder++; + if (indexInFolder >= folders[folderIndex].numUnpackStreams) { + folderIndex++; + indexInFolder = 0; + } + } + + return (0); +} + +#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) +static void +fileTimeToUtc(uint64_t fileTime, time_t *timep, long *ns) +{ + + if (fileTime >= EPOC_TIME) { + fileTime -= EPOC_TIME; + /* milli seconds base */ + *timep = (time_t)(fileTime / 10000000); + /* nano seconds base */ + *ns = (long)(fileTime % 10000000) * 100; + } else { + *timep = 0; + *ns = 0; + } +} + +static int +read_Times(struct archive_read *a, struct _7z_header_info *h, int type) +{ + struct _7zip *zip = (struct _7zip *)a->format->data; + const unsigned char *p; + struct _7zip_entry *entries = zip->entries; + unsigned char *timeBools; + int allAreDefined; + unsigned i; + + timeBools = calloc((size_t)zip->numFiles, sizeof(*timeBools)); + if (timeBools == NULL) + return (-1); + + /* Read allAreDefined. */ + if ((p = header_bytes(a, 1)) == NULL) + goto failed; + allAreDefined = *p; + if (allAreDefined) + memset(timeBools, 1, (size_t)zip->numFiles); + else { + if (read_Bools(a, timeBools, (size_t)zip->numFiles) < 0) + goto failed; + } + + /* Read external. */ + if ((p = header_bytes(a, 1)) == NULL) + goto failed; + if (*p) { + if (parse_7zip_uint64(a, &(h->dataIndex)) < 0) + goto failed; + if (UMAX_ENTRY < h->dataIndex) + goto failed; + } + + for (i = 0; i < zip->numFiles; i++) { + if (!timeBools[i]) + continue; + if ((p = header_bytes(a, 8)) == NULL) + goto failed; + switch (type) { + case kCTime: + fileTimeToUtc(archive_le64dec(p), + &(entries[i].ctime), + &(entries[i].ctime_ns)); + entries[i].flg |= CTIME_IS_SET; + break; + case kATime: + fileTimeToUtc(archive_le64dec(p), + &(entries[i].atime), + &(entries[i].atime_ns)); + entries[i].flg |= ATIME_IS_SET; + break; + case kMTime: + fileTimeToUtc(archive_le64dec(p), + &(entries[i].mtime), + &(entries[i].mtime_ns)); + entries[i].flg |= MTIME_IS_SET; + break; + } + } + + free(timeBools); + return (0); +failed: + free(timeBools); + return (-1); +} + +static int +decode_encoded_header_info(struct archive_read *a, struct _7z_stream_info *si) +{ + struct _7zip *zip = (struct _7zip *)a->format->data; + + errno = 0; + if (read_StreamsInfo(a, si) < 0) { + if (errno == ENOMEM) + archive_set_error(&a->archive, -1, + "Couldn't allocate memory"); + else + archive_set_error(&a->archive, -1, + "Malformed 7-Zip archive"); + return (ARCHIVE_FATAL); + } + + if (si->pi.numPackStreams == 0 || si->ci.numFolders == 0) { + archive_set_error(&a->archive, -1, "Malformed 7-Zip archive"); + return (ARCHIVE_FATAL); + } + + if (zip->header_offset < si->pi.pos + si->pi.sizes[0] || + (int64_t)(si->pi.pos + si->pi.sizes[0]) < 0 || + si->pi.sizes[0] == 0 || (int64_t)si->pi.pos < 0) { + archive_set_error(&a->archive, -1, "Malformed Header offset"); + return (ARCHIVE_FATAL); + } + + return (ARCHIVE_OK); +} + +static const unsigned char * +header_bytes(struct archive_read *a, size_t rbytes) +{ + struct _7zip *zip = (struct _7zip *)a->format->data; + const unsigned char *p; + + if (zip->header_bytes_remaining < rbytes) + return (NULL); + if (zip->pack_stream_bytes_unconsumed) + read_consume(a); + + if (zip->header_is_encoded == 0) { + p = __archive_read_ahead(a, rbytes, NULL); + if (p == NULL) + return (NULL); + zip->header_bytes_remaining -= rbytes; + zip->pack_stream_bytes_unconsumed = rbytes; + } else { + const void *buff; + ssize_t bytes; + + bytes = read_stream(a, &buff, rbytes, rbytes); + if (bytes <= 0) + return (NULL); + zip->header_bytes_remaining -= bytes; + p = buff; + } + + /* Update checksum */ + zip->header_crc32 = crc32(zip->header_crc32, p, (unsigned)rbytes); + return (p); +} + +static int +slurp_central_directory(struct archive_read *a, struct _7zip *zip, + struct _7z_header_info *header) +{ + const unsigned char *p; + uint64_t next_header_offset; + uint64_t next_header_size; + uint32_t next_header_crc; + ssize_t bytes_avail; + int check_header_crc, r; + + if ((p = __archive_read_ahead(a, 32, &bytes_avail)) == NULL) + return (ARCHIVE_FATAL); + + if ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0) { + /* This is an executable ? Must be self-extracting... */ + r = skip_sfx(a, bytes_avail); + if (r < ARCHIVE_WARN) + return (r); + if ((p = __archive_read_ahead(a, 32, &bytes_avail)) == NULL) + return (ARCHIVE_FATAL); + } + zip->seek_base += 32; + + if (memcmp(p, _7ZIP_SIGNATURE, 6) != 0) { + archive_set_error(&a->archive, -1, "Not 7-Zip archive file"); + return (ARCHIVE_FATAL); + } + + /* CRC check. */ + if (crc32(0, (const unsigned char *)p + 12, 20) + != archive_le32dec(p + 8)) { + archive_set_error(&a->archive, -1, "Header CRC error"); + return (ARCHIVE_FATAL); + } + + next_header_offset = archive_le64dec(p + 12); + next_header_size = archive_le64dec(p + 20); + next_header_crc = archive_le32dec(p + 28); + + if (next_header_size == 0) + /* There is no entry in an archive file. */ + return (ARCHIVE_EOF); + + if (((int64_t)next_header_offset) < 0) { + archive_set_error(&a->archive, -1, "Malformed 7-Zip archive"); + return (ARCHIVE_FATAL); + } + __archive_read_consume(a, 32); + if (next_header_offset != 0) { + if (bytes_avail >= (ssize_t)next_header_offset) + __archive_read_consume(a, next_header_offset); + else if (__archive_read_seek(a, + next_header_offset + zip->seek_base, SEEK_SET) < 0) + return (ARCHIVE_FATAL); + } + zip->stream_offset = next_header_offset; + zip->header_offset = next_header_offset; + zip->header_bytes_remaining = next_header_size; + zip->header_crc32 = 0; + zip->header_is_encoded = 0; + zip->header_is_being_read = 1; + zip->has_encrypted_entries = 0; + check_header_crc = 1; + + if ((p = header_bytes(a, 1)) == NULL) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated 7-Zip file body"); + return (ARCHIVE_FATAL); + } + /* Parse ArchiveProperties. */ + switch (p[0]) { + case kEncodedHeader: + /* + * The archive has an encoded header and we have to decode it + * in order to parse the header correctly. + */ + r = decode_encoded_header_info(a, &(zip->si)); + + /* Check the EncodedHeader CRC.*/ + if (r == 0 && zip->header_crc32 != next_header_crc) { + archive_set_error(&a->archive, -1, + "Damaged 7-Zip archive"); + r = -1; + } + if (r == 0) { + if (zip->si.ci.folders[0].digest_defined) + next_header_crc = zip->si.ci.folders[0].digest; + else + check_header_crc = 0; + if (zip->pack_stream_bytes_unconsumed) + read_consume(a); + r = setup_decode_folder(a, zip->si.ci.folders, 1); + if (r == 0) { + zip->header_bytes_remaining = + zip->folder_outbytes_remaining; + r = seek_pack(a); + } + } + /* Clean up StreamsInfo. */ + free_StreamsInfo(&(zip->si)); + memset(&(zip->si), 0, sizeof(zip->si)); + if (r < 0) + return (ARCHIVE_FATAL); + zip->header_is_encoded = 1; + zip->header_crc32 = 0; + /* FALL THROUGH */ + case kHeader: + /* + * Parse the header. + */ + errno = 0; + r = read_Header(a, header, zip->header_is_encoded); + if (r < 0) { + if (errno == ENOMEM) + archive_set_error(&a->archive, -1, + "Couldn't allocate memory"); + else + archive_set_error(&a->archive, -1, + "Damaged 7-Zip archive"); + return (ARCHIVE_FATAL); + } + + /* + * Must be kEnd. + */ + if ((p = header_bytes(a, 1)) == NULL ||*p != kEnd) { + archive_set_error(&a->archive, -1, + "Malformed 7-Zip archive"); + return (ARCHIVE_FATAL); + } + + /* Check the Header CRC.*/ + if (check_header_crc && zip->header_crc32 != next_header_crc) { + archive_set_error(&a->archive, -1, + "Malformed 7-Zip archive"); + return (ARCHIVE_FATAL); + } + break; + default: + archive_set_error(&a->archive, -1, + "Unexpected Property ID = %X", p[0]); + return (ARCHIVE_FATAL); + } + + /* Clean up variables be used for decoding the archive header */ + zip->pack_stream_remaining = 0; + zip->pack_stream_index = 0; + zip->folder_outbytes_remaining = 0; + zip->uncompressed_buffer_bytes_remaining = 0; + zip->pack_stream_bytes_unconsumed = 0; + zip->header_is_being_read = 0; + + return (ARCHIVE_OK); +} + +static ssize_t +get_uncompressed_data(struct archive_read *a, const void **buff, size_t size, + size_t minimum) +{ + struct _7zip *zip = (struct _7zip *)a->format->data; + ssize_t bytes_avail; + + if (zip->codec == _7Z_COPY && zip->codec2 == (unsigned long)-1) { + /* Copy mode. */ + + /* + * Note: '1' here is a performance optimization. + * Recall that the decompression layer returns a count of + * available bytes; asking for more than that forces the + * decompressor to combine reads by copying data. + */ + *buff = __archive_read_ahead(a, 1, &bytes_avail); + if (bytes_avail <= 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated 7-Zip file data"); + return (ARCHIVE_FATAL); + } + if ((size_t)bytes_avail > + zip->uncompressed_buffer_bytes_remaining) + bytes_avail = (ssize_t) + zip->uncompressed_buffer_bytes_remaining; + if ((size_t)bytes_avail > size) + bytes_avail = (ssize_t)size; + + zip->pack_stream_bytes_unconsumed = bytes_avail; + } else if (zip->uncompressed_buffer_pointer == NULL) { + /* Decompression has failed. */ + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, "Damaged 7-Zip archive"); + return (ARCHIVE_FATAL); + } else { + /* Packed mode. */ + if (minimum > zip->uncompressed_buffer_bytes_remaining) { + /* + * If remaining uncompressed data size is less than + * the minimum size, fill the buffer up to the + * minimum size. + */ + if (extract_pack_stream(a, minimum) < 0) + return (ARCHIVE_FATAL); + } + if (size > zip->uncompressed_buffer_bytes_remaining) + bytes_avail = (ssize_t) + zip->uncompressed_buffer_bytes_remaining; + else + bytes_avail = (ssize_t)size; + *buff = zip->uncompressed_buffer_pointer; + zip->uncompressed_buffer_pointer += bytes_avail; + } + zip->uncompressed_buffer_bytes_remaining -= bytes_avail; + return (bytes_avail); +} + +static ssize_t +extract_pack_stream(struct archive_read *a, size_t minimum) +{ + struct _7zip *zip = (struct _7zip *)a->format->data; + ssize_t bytes_avail; + int r; + + if (zip->codec == _7Z_COPY && zip->codec2 == (unsigned long)-1) { + if (minimum == 0) + minimum = 1; + if (__archive_read_ahead(a, minimum, &bytes_avail) == NULL + || bytes_avail <= 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated 7-Zip file body"); + return (ARCHIVE_FATAL); + } + if (bytes_avail > (ssize_t)zip->pack_stream_inbytes_remaining) + bytes_avail = (ssize_t)zip->pack_stream_inbytes_remaining; + zip->pack_stream_inbytes_remaining -= bytes_avail; + if (bytes_avail > (ssize_t)zip->folder_outbytes_remaining) + bytes_avail = (ssize_t)zip->folder_outbytes_remaining; + zip->folder_outbytes_remaining -= bytes_avail; + zip->uncompressed_buffer_bytes_remaining = bytes_avail; + return (ARCHIVE_OK); + } + + /* If the buffer hasn't been allocated, allocate it now. */ + if (zip->uncompressed_buffer == NULL) { + zip->uncompressed_buffer_size = UBUFF_SIZE; + if (zip->uncompressed_buffer_size < minimum) { + zip->uncompressed_buffer_size = minimum + 1023; + zip->uncompressed_buffer_size &= ~0x3ff; + } + zip->uncompressed_buffer = + malloc(zip->uncompressed_buffer_size); + if (zip->uncompressed_buffer == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory for 7-Zip decompression"); + return (ARCHIVE_FATAL); + } + zip->uncompressed_buffer_bytes_remaining = 0; + } else if (zip->uncompressed_buffer_size < minimum || + zip->uncompressed_buffer_bytes_remaining < minimum) { + /* + * Make sure the uncompressed buffer can have bytes + * at least `minimum' bytes. + * NOTE: This case happen when reading the header. + */ + size_t used; + if (zip->uncompressed_buffer_pointer != 0) + used = zip->uncompressed_buffer_pointer - + zip->uncompressed_buffer; + else + used = 0; + if (zip->uncompressed_buffer_size < minimum) { + /* + * Expand the uncompressed buffer up to + * the minimum size. + */ + void *p; + size_t new_size; + + new_size = minimum + 1023; + new_size &= ~0x3ff; + p = realloc(zip->uncompressed_buffer, new_size); + if (p == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory for 7-Zip decompression"); + return (ARCHIVE_FATAL); + } + zip->uncompressed_buffer = (unsigned char *)p; + zip->uncompressed_buffer_size = new_size; + } + /* + * Move unconsumed bytes to the head. + */ + if (used) { + memmove(zip->uncompressed_buffer, + zip->uncompressed_buffer + used, + zip->uncompressed_buffer_bytes_remaining); + } + } else + zip->uncompressed_buffer_bytes_remaining = 0; + zip->uncompressed_buffer_pointer = NULL; + for (;;) { + size_t bytes_in, bytes_out; + const void *buff_in; + unsigned char *buff_out; + int end_of_data; + + /* + * Note: '1' here is a performance optimization. + * Recall that the decompression layer returns a count of + * available bytes; asking for more than that forces the + * decompressor to combine reads by copying data. + */ + buff_in = __archive_read_ahead(a, 1, &bytes_avail); + if (bytes_avail <= 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated 7-Zip file body"); + return (ARCHIVE_FATAL); + } + + buff_out = zip->uncompressed_buffer + + zip->uncompressed_buffer_bytes_remaining; + bytes_out = zip->uncompressed_buffer_size + - zip->uncompressed_buffer_bytes_remaining; + bytes_in = bytes_avail; + if (bytes_in > zip->pack_stream_inbytes_remaining) + bytes_in = (size_t)zip->pack_stream_inbytes_remaining; + /* Drive decompression. */ + r = decompress(a, zip, buff_out, &bytes_out, + buff_in, &bytes_in); + switch (r) { + case ARCHIVE_OK: + end_of_data = 0; + break; + case ARCHIVE_EOF: + end_of_data = 1; + break; + default: + return (ARCHIVE_FATAL); + } + zip->pack_stream_inbytes_remaining -= bytes_in; + if (bytes_out > zip->folder_outbytes_remaining) + bytes_out = (size_t)zip->folder_outbytes_remaining; + zip->folder_outbytes_remaining -= bytes_out; + zip->uncompressed_buffer_bytes_remaining += bytes_out; + zip->pack_stream_bytes_unconsumed = bytes_in; + + /* + * Continue decompression until uncompressed_buffer is full. + */ + if (zip->uncompressed_buffer_bytes_remaining == + zip->uncompressed_buffer_size) + break; + if (zip->codec2 == _7Z_X86 && zip->odd_bcj_size && + zip->uncompressed_buffer_bytes_remaining + 5 > + zip->uncompressed_buffer_size) + break; + if (zip->pack_stream_inbytes_remaining == 0 && + zip->folder_outbytes_remaining == 0) + break; + if (end_of_data || (bytes_in == 0 && bytes_out == 0)) { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, "Damaged 7-Zip archive"); + return (ARCHIVE_FATAL); + } + read_consume(a); + } + if (zip->uncompressed_buffer_bytes_remaining < minimum) { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, "Damaged 7-Zip archive"); + return (ARCHIVE_FATAL); + } + zip->uncompressed_buffer_pointer = zip->uncompressed_buffer; + return (ARCHIVE_OK); +} + +static int +seek_pack(struct archive_read *a) +{ + struct _7zip *zip = (struct _7zip *)a->format->data; + int64_t pack_offset; + + if (zip->pack_stream_remaining <= 0) { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, "Damaged 7-Zip archive"); + return (ARCHIVE_FATAL); + } + zip->pack_stream_inbytes_remaining = + zip->si.pi.sizes[zip->pack_stream_index]; + pack_offset = zip->si.pi.positions[zip->pack_stream_index]; + if (zip->stream_offset != pack_offset) { + if (0 > __archive_read_seek(a, pack_offset + zip->seek_base, + SEEK_SET)) + return (ARCHIVE_FATAL); + zip->stream_offset = pack_offset; + } + zip->pack_stream_index++; + zip->pack_stream_remaining--; + return (ARCHIVE_OK); +} + +static ssize_t +read_stream(struct archive_read *a, const void **buff, size_t size, + size_t minimum) +{ + struct _7zip *zip = (struct _7zip *)a->format->data; + uint64_t skip_bytes = 0; + ssize_t r; + + if (zip->uncompressed_buffer_bytes_remaining == 0) { + if (zip->pack_stream_inbytes_remaining > 0) { + r = extract_pack_stream(a, 0); + if (r < 0) + return (r); + return (get_uncompressed_data(a, buff, size, minimum)); + } else if (zip->folder_outbytes_remaining > 0) { + /* Extract a remaining pack stream. */ + r = extract_pack_stream(a, 0); + if (r < 0) + return (r); + return (get_uncompressed_data(a, buff, size, minimum)); + } + } else + return (get_uncompressed_data(a, buff, size, minimum)); + + /* + * Current pack stream has been consumed. + */ + if (zip->pack_stream_remaining == 0) { + if (zip->header_is_being_read) { + /* Invalid sequence. This might happen when + * reading a malformed archive. */ + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, "Malformed 7-Zip archive"); + return (ARCHIVE_FATAL); + } + + /* + * All current folder's pack streams have been + * consumed. Switch to next folder. + */ + if (zip->folder_index == 0 && + (zip->si.ci.folders[zip->entry->folderIndex].skipped_bytes + || zip->folder_index != zip->entry->folderIndex)) { + zip->folder_index = zip->entry->folderIndex; + skip_bytes = + zip->si.ci.folders[zip->folder_index].skipped_bytes; + } + + if (zip->folder_index >= zip->si.ci.numFolders) { + /* + * We have consumed all folders and its pack streams. + */ + *buff = NULL; + return (0); + } + r = setup_decode_folder(a, + &(zip->si.ci.folders[zip->folder_index]), 0); + if (r != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + zip->folder_index++; + } + + /* + * Switch to next pack stream. + */ + r = seek_pack(a); + if (r < 0) + return (r); + + /* Extract a new pack stream. */ + r = extract_pack_stream(a, 0); + if (r < 0) + return (r); + + /* - * Skip the bytes we alrady has skipped in skip_stream(). ++ * Skip the bytes we already has skipped in skip_stream(). + */ + while (skip_bytes) { + ssize_t skipped; + + if (zip->uncompressed_buffer_bytes_remaining == 0) { + if (zip->pack_stream_inbytes_remaining > 0) { + r = extract_pack_stream(a, 0); + if (r < 0) + return (r); + } else if (zip->folder_outbytes_remaining > 0) { + /* Extract a remaining pack stream. */ + r = extract_pack_stream(a, 0); + if (r < 0) + return (r); + } else { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated 7-Zip file body"); + return (ARCHIVE_FATAL); + } + } + skipped = get_uncompressed_data( + a, buff, (size_t)skip_bytes, 0); + if (skipped < 0) + return (skipped); + skip_bytes -= skipped; + if (zip->pack_stream_bytes_unconsumed) + read_consume(a); + } + + return (get_uncompressed_data(a, buff, size, minimum)); +} + +static int +setup_decode_folder(struct archive_read *a, struct _7z_folder *folder, + int header) +{ + struct _7zip *zip = (struct _7zip *)a->format->data; + const struct _7z_coder *coder1, *coder2; + const char *cname = (header)?"archive header":"file content"; + unsigned i; + int r, found_bcj2 = 0; + + /* + * Release the memory which the previous folder used for BCJ2. + */ + for (i = 0; i < 3; i++) { + if (zip->sub_stream_buff[i] != NULL) + free(zip->sub_stream_buff[i]); + zip->sub_stream_buff[i] = NULL; + } + + /* + * Initialize a stream reader. + */ + zip->pack_stream_remaining = (unsigned)folder->numPackedStreams; + zip->pack_stream_index = (unsigned)folder->packIndex; + zip->folder_outbytes_remaining = folder_uncompressed_size(folder); + zip->uncompressed_buffer_bytes_remaining = 0; + + /* + * Check coder types. + */ + for (i = 0; i < folder->numCoders; i++) { + switch(folder->coders[i].codec) { + case _7Z_CRYPTO_MAIN_ZIP: + case _7Z_CRYPTO_RAR_29: + case _7Z_CRYPTO_AES_256_SHA_256: { + /* For entry that is associated with this folder, mark + it as encrypted (data+metadata). */ + zip->has_encrypted_entries = 1; + if (a->entry) { + archive_entry_set_is_data_encrypted(a->entry, 1); + archive_entry_set_is_metadata_encrypted(a->entry, 1); + } + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "The %s is encrypted, " + "but currently not supported", cname); + return (ARCHIVE_FATAL); + } + case _7Z_X86_BCJ2: { + found_bcj2++; + break; + } + } + } + /* Now that we've checked for encryption, if there were still no + * encrypted entries found we can say for sure that there are none. + */ + if (zip->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) { + zip->has_encrypted_entries = 0; + } + + if ((folder->numCoders > 2 && !found_bcj2) || found_bcj2 > 1) { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "The %s is encoded with many filters, " + "but currently not supported", cname); + return (ARCHIVE_FATAL); + } + coder1 = &(folder->coders[0]); + if (folder->numCoders == 2) + coder2 = &(folder->coders[1]); + else + coder2 = NULL; + + if (found_bcj2) { + /* + * Preparation to decode BCJ2. + * Decoding BCJ2 requires four sources. Those are at least, + * as far as I know, two types of the storage form. + */ + const struct _7z_coder *fc = folder->coders; + static const struct _7z_coder coder_copy = {0, 1, 1, 0, NULL}; + const struct _7z_coder *scoder[3] = + {&coder_copy, &coder_copy, &coder_copy}; + const void *buff; + ssize_t bytes; + unsigned char *b[3] = {NULL, NULL, NULL}; + uint64_t sunpack[3] ={-1, -1, -1}; + size_t s[3] = {0, 0, 0}; + int idx[3] = {0, 1, 2}; + + if (folder->numCoders == 4 && fc[3].codec == _7Z_X86_BCJ2 && + folder->numInStreams == 7 && folder->numOutStreams == 4 && + zip->pack_stream_remaining == 4) { + /* Source type 1 made by 7zr or 7z with -m options. */ + if (folder->bindPairs[0].inIndex == 5) { + /* The form made by 7zr */ + idx[0] = 1; idx[1] = 2; idx[2] = 0; + scoder[1] = &(fc[1]); + scoder[2] = &(fc[0]); + sunpack[1] = folder->unPackSize[1]; + sunpack[2] = folder->unPackSize[0]; + coder1 = &(fc[2]); + } else { + /* + * NOTE: Some patterns do not work. + * work: + * 7z a -m0=BCJ2 -m1=COPY -m2=COPY + * -m3=(any) + * 7z a -m0=BCJ2 -m1=COPY -m2=(any) + * -m3=COPY + * 7z a -m0=BCJ2 -m1=(any) -m2=COPY + * -m3=COPY + * not work: + * other patterns. + * + * We have to handle this like `pipe' or + * our libarchive7s filter frame work, + * decoding the BCJ2 main stream sequentially, + * m3 -> m2 -> m1 -> BCJ2. + * + */ + if (fc[0].codec == _7Z_COPY && + fc[1].codec == _7Z_COPY) + coder1 = &(folder->coders[2]); + else if (fc[0].codec == _7Z_COPY && + fc[2].codec == _7Z_COPY) + coder1 = &(folder->coders[1]); + else if (fc[1].codec == _7Z_COPY && + fc[2].codec == _7Z_COPY) + coder1 = &(folder->coders[0]); + else { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "Unsupported form of " + "BCJ2 streams"); + return (ARCHIVE_FATAL); + } + } + coder2 = &(fc[3]); + zip->main_stream_bytes_remaining = + (size_t)folder->unPackSize[2]; + } else if (coder2 != NULL && coder2->codec == _7Z_X86_BCJ2 && + zip->pack_stream_remaining == 4 && + folder->numInStreams == 5 && folder->numOutStreams == 2) { + /* Source type 0 made by 7z */ + zip->main_stream_bytes_remaining = + (size_t)folder->unPackSize[0]; + } else { + /* We got an unexpected form. */ + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "Unsupported form of BCJ2 streams"); + return (ARCHIVE_FATAL); + } + + /* Skip the main stream at this time. */ + if ((r = seek_pack(a)) < 0) + return (r); + zip->pack_stream_bytes_unconsumed = + (size_t)zip->pack_stream_inbytes_remaining; + read_consume(a); + + /* Read following three sub streams. */ + for (i = 0; i < 3; i++) { + const struct _7z_coder *coder = scoder[i]; + + if ((r = seek_pack(a)) < 0) { + free(b[0]); free(b[1]); free(b[2]); + return (r); + } + + if (sunpack[i] == (uint64_t)-1) + zip->folder_outbytes_remaining = + zip->pack_stream_inbytes_remaining; + else + zip->folder_outbytes_remaining = sunpack[i]; + + r = init_decompression(a, zip, coder, NULL); + if (r != ARCHIVE_OK) { + free(b[0]); free(b[1]); free(b[2]); + return (ARCHIVE_FATAL); + } + - /* Allocate memory for the decorded data of a sub ++ /* Allocate memory for the decoded data of a sub + * stream. */ + b[i] = malloc((size_t)zip->folder_outbytes_remaining); + if (b[i] == NULL) { + free(b[0]); free(b[1]); free(b[2]); + archive_set_error(&a->archive, ENOMEM, + "No memory for 7-Zip decompression"); + return (ARCHIVE_FATAL); + } + + /* Extract a sub stream. */ + while (zip->pack_stream_inbytes_remaining > 0) { + r = (int)extract_pack_stream(a, 0); + if (r < 0) { + free(b[0]); free(b[1]); free(b[2]); + return (r); + } + bytes = get_uncompressed_data(a, &buff, + zip->uncompressed_buffer_bytes_remaining, + 0); + if (bytes < 0) { + free(b[0]); free(b[1]); free(b[2]); + return ((int)bytes); + } + memcpy(b[i]+s[i], buff, bytes); + s[i] += bytes; + if (zip->pack_stream_bytes_unconsumed) + read_consume(a); + } + } + + /* Set the sub streams to the right place. */ + for (i = 0; i < 3; i++) { + zip->sub_stream_buff[i] = b[idx[i]]; + zip->sub_stream_size[i] = s[idx[i]]; + zip->sub_stream_bytes_remaining[i] = s[idx[i]]; + } + + /* Allocate memory used for decoded main stream bytes. */ + if (zip->tmp_stream_buff == NULL) { + zip->tmp_stream_buff_size = 32 * 1024; + zip->tmp_stream_buff = + malloc(zip->tmp_stream_buff_size); + if (zip->tmp_stream_buff == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory for 7-Zip decompression"); + return (ARCHIVE_FATAL); + } + } + zip->tmp_stream_bytes_avail = 0; + zip->tmp_stream_bytes_remaining = 0; + zip->odd_bcj_size = 0; + zip->bcj2_outPos = 0; + + /* + * Reset a stream reader in order to read the main stream + * of BCJ2. + */ + zip->pack_stream_remaining = 1; + zip->pack_stream_index = (unsigned)folder->packIndex; + zip->folder_outbytes_remaining = + folder_uncompressed_size(folder); + zip->uncompressed_buffer_bytes_remaining = 0; + } + + /* + * Initialize the decompressor for the new folder's pack streams. + */ + r = init_decompression(a, zip, coder1, coder2); + if (r != ARCHIVE_OK) + return (ARCHIVE_FATAL); + return (ARCHIVE_OK); +} + +static int64_t +skip_stream(struct archive_read *a, size_t skip_bytes) +{ + struct _7zip *zip = (struct _7zip *)a->format->data; + const void *p; + int64_t skipped_bytes; + size_t bytes = skip_bytes; + + if (zip->folder_index == 0) { + /* + * Optimization for a list mode. - * Avoid unncecessary decoding operations. ++ * Avoid unnecessary decoding operations. + */ + zip->si.ci.folders[zip->entry->folderIndex].skipped_bytes + += skip_bytes; + return (skip_bytes); + } + + while (bytes) { + skipped_bytes = read_stream(a, &p, bytes, 0); + if (skipped_bytes < 0) + return (skipped_bytes); + if (skipped_bytes == 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated 7-Zip file body"); + return (ARCHIVE_FATAL); + } + bytes -= (size_t)skipped_bytes; + if (zip->pack_stream_bytes_unconsumed) + read_consume(a); + } + return (skip_bytes); +} + +/* + * Brought from LZMA SDK. + * + * Bra86.c -- Converter for x86 code (BCJ) + * 2008-10-04 : Igor Pavlov : Public domain + * + */ + +#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) + +static void +x86_Init(struct _7zip *zip) +{ + zip->bcj_state = 0; + zip->bcj_prevPosT = (size_t)0 - 1; + zip->bcj_prevMask = 0; + zip->bcj_ip = 5; +} + +static size_t +x86_Convert(struct _7zip *zip, uint8_t *data, size_t size) +{ + static const uint8_t kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0}; + static const uint8_t kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3}; + size_t bufferPos, prevPosT; + uint32_t ip, prevMask; + + if (size < 5) + return 0; + + bufferPos = 0; + prevPosT = zip->bcj_prevPosT; + prevMask = zip->bcj_prevMask; + ip = zip->bcj_ip; + + for (;;) { + uint8_t *p = data + bufferPos; + uint8_t *limit = data + size - 4; + + for (; p < limit; p++) + if ((*p & 0xFE) == 0xE8) + break; + bufferPos = (size_t)(p - data); + if (p >= limit) + break; + prevPosT = bufferPos - prevPosT; + if (prevPosT > 3) + prevMask = 0; + else { + prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7; + if (prevMask != 0) { + unsigned char b = + p[4 - kMaskToBitNumber[prevMask]]; + if (!kMaskToAllowedStatus[prevMask] || + Test86MSByte(b)) { + prevPosT = bufferPos; + prevMask = ((prevMask << 1) & 0x7) | 1; + bufferPos++; + continue; + } + } + } + prevPosT = bufferPos; + + if (Test86MSByte(p[4])) { + uint32_t src = ((uint32_t)p[4] << 24) | + ((uint32_t)p[3] << 16) | ((uint32_t)p[2] << 8) | + ((uint32_t)p[1]); + uint32_t dest; + for (;;) { + uint8_t b; + int b_index; + + dest = src - (ip + (uint32_t)bufferPos); + if (prevMask == 0) + break; + b_index = kMaskToBitNumber[prevMask] * 8; + b = (uint8_t)(dest >> (24 - b_index)); + if (!Test86MSByte(b)) + break; + src = dest ^ ((1 << (32 - b_index)) - 1); + } + p[4] = (uint8_t)(~(((dest >> 24) & 1) - 1)); + p[3] = (uint8_t)(dest >> 16); + p[2] = (uint8_t)(dest >> 8); + p[1] = (uint8_t)dest; + bufferPos += 5; + } else { + prevMask = ((prevMask << 1) & 0x7) | 1; + bufferPos++; + } + } + zip->bcj_prevPosT = prevPosT; + zip->bcj_prevMask = prevMask; + zip->bcj_ip += (uint32_t)bufferPos; + return (bufferPos); +} + +/* + * Brought from LZMA SDK. + * + * Bcj2.c -- Converter for x86 code (BCJ2) + * 2008-10-04 : Igor Pavlov : Public domain + * + */ + +#define SZ_ERROR_DATA ARCHIVE_FAILED + +#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80) +#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)) + +#define kNumTopBits 24 +#define kTopValue ((uint32_t)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 + +#define RC_READ_BYTE (*buffer++) +#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; } +#define RC_INIT2 zip->bcj2_code = 0; zip->bcj2_range = 0xFFFFFFFF; \ + { int ii; for (ii = 0; ii < 5; ii++) { RC_TEST; zip->bcj2_code = (zip->bcj2_code << 8) | RC_READ_BYTE; }} + +#define NORMALIZE if (zip->bcj2_range < kTopValue) { RC_TEST; zip->bcj2_range <<= 8; zip->bcj2_code = (zip->bcj2_code << 8) | RC_READ_BYTE; } + +#define IF_BIT_0(p) ttt = *(p); bound = (zip->bcj2_range >> kNumBitModelTotalBits) * ttt; if (zip->bcj2_code < bound) +#define UPDATE_0(p) zip->bcj2_range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE; +#define UPDATE_1(p) zip->bcj2_range -= bound; zip->bcj2_code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE; + +static ssize_t +Bcj2_Decode(struct _7zip *zip, uint8_t *outBuf, size_t outSize) +{ + size_t inPos = 0, outPos = 0; + const uint8_t *buf0, *buf1, *buf2, *buf3; + size_t size0, size1, size2, size3; + const uint8_t *buffer, *bufferLim; + unsigned int i, j; + + size0 = zip->tmp_stream_bytes_remaining; + buf0 = zip->tmp_stream_buff + zip->tmp_stream_bytes_avail - size0; + size1 = zip->sub_stream_bytes_remaining[0]; + buf1 = zip->sub_stream_buff[0] + zip->sub_stream_size[0] - size1; + size2 = zip->sub_stream_bytes_remaining[1]; + buf2 = zip->sub_stream_buff[1] + zip->sub_stream_size[1] - size2; + size3 = zip->sub_stream_bytes_remaining[2]; + buf3 = zip->sub_stream_buff[2] + zip->sub_stream_size[2] - size3; + + buffer = buf3; + bufferLim = buffer + size3; + + if (zip->bcj_state == 0) { + /* + * Initialize. + */ + zip->bcj2_prevByte = 0; + for (i = 0; + i < sizeof(zip->bcj2_p) / sizeof(zip->bcj2_p[0]); i++) + zip->bcj2_p[i] = kBitModelTotal >> 1; + RC_INIT2; + zip->bcj_state = 1; + } + + /* + * Gather the odd bytes of a previous call. + */ + for (i = 0; zip->odd_bcj_size > 0 && outPos < outSize; i++) { + outBuf[outPos++] = zip->odd_bcj[i]; + zip->odd_bcj_size--; + } + + if (outSize == 0) { + zip->bcj2_outPos += outPos; + return (outPos); + } + + for (;;) { + uint8_t b; + CProb *prob; + uint32_t bound; + uint32_t ttt; + + size_t limit = size0 - inPos; + if (outSize - outPos < limit) + limit = outSize - outPos; + + if (zip->bcj_state == 1) { + while (limit != 0) { + uint8_t bb = buf0[inPos]; + outBuf[outPos++] = bb; + if (IsJ(zip->bcj2_prevByte, bb)) { + zip->bcj_state = 2; + break; + } + inPos++; + zip->bcj2_prevByte = bb; + limit--; + } + } + + if (limit == 0 || outPos == outSize) + break; + zip->bcj_state = 1; + + b = buf0[inPos++]; + + if (b == 0xE8) + prob = zip->bcj2_p + zip->bcj2_prevByte; + else if (b == 0xE9) + prob = zip->bcj2_p + 256; + else + prob = zip->bcj2_p + 257; + + IF_BIT_0(prob) { + UPDATE_0(prob) + zip->bcj2_prevByte = b; + } else { + uint32_t dest; + const uint8_t *v; + uint8_t out[4]; + + UPDATE_1(prob) + if (b == 0xE8) { + v = buf1; + if (size1 < 4) + return SZ_ERROR_DATA; + buf1 += 4; + size1 -= 4; + } else { + v = buf2; + if (size2 < 4) + return SZ_ERROR_DATA; + buf2 += 4; + size2 -= 4; + } + dest = (((uint32_t)v[0] << 24) | + ((uint32_t)v[1] << 16) | + ((uint32_t)v[2] << 8) | + ((uint32_t)v[3])) - + ((uint32_t)zip->bcj2_outPos + (uint32_t)outPos + 4); + out[0] = (uint8_t)dest; + out[1] = (uint8_t)(dest >> 8); + out[2] = (uint8_t)(dest >> 16); + out[3] = zip->bcj2_prevByte = (uint8_t)(dest >> 24); + + for (i = 0; i < 4 && outPos < outSize; i++) + outBuf[outPos++] = out[i]; + if (i < 4) { + /* + * Save odd bytes which we could not add into + * the output buffer because of out of space. + */ + zip->odd_bcj_size = 4 -i; + for (; i < 4; i++) { + j = i - 4 + (unsigned)zip->odd_bcj_size; + zip->odd_bcj[j] = out[i]; + } + break; + } + } + } + zip->tmp_stream_bytes_remaining -= inPos; + zip->sub_stream_bytes_remaining[0] = size1; + zip->sub_stream_bytes_remaining[1] = size2; + zip->sub_stream_bytes_remaining[2] = bufferLim - buffer; + zip->bcj2_outPos += outPos; + + return ((ssize_t)outPos); +} + diff --cc Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c index 6356963,0000000..20eb157 mode 100644,000000..100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_cab.c @@@ -1,3350 -1,0 +1,3353 @@@ +/*- + * Copyright (c) 2010-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_ZLIB_H +#include +#endif + +#include "archive.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_private.h" +#include "archive_read_private.h" +#include "archive_endian.h" + + +struct lzx_dec { + /* Decoding status. */ + int state; + + /* + * Window to see last decoded data, from 32KBi to 2MBi. + */ + int w_size; + int w_mask; + /* Window buffer, which is a loop buffer. */ + unsigned char *w_buff; + /* The insert position to the window. */ + int w_pos; + /* The position where we can copy decoded code from the window. */ + int copy_pos; + /* The length how many bytes we can copy decoded code from + * the window. */ + int copy_len; - /* Translation reversal for x86 proccessor CALL byte sequence(E8). ++ /* Translation reversal for x86 processor CALL byte sequence(E8). + * This is used for LZX only. */ + uint32_t translation_size; + char translation; + char block_type; +#define VERBATIM_BLOCK 1 +#define ALIGNED_OFFSET_BLOCK 2 +#define UNCOMPRESSED_BLOCK 3 + size_t block_size; + size_t block_bytes_avail; + /* Repeated offset. */ + int r0, r1, r2; + unsigned char rbytes[4]; + int rbytes_avail; + int length_header; + int position_slot; + int offset_bits; + + struct lzx_pos_tbl { + int base; + int footer_bits; + } *pos_tbl; + /* + * Bit stream reader. + */ + struct lzx_br { +#define CACHE_TYPE uint64_t +#define CACHE_BITS (8 * sizeof(CACHE_TYPE)) + /* Cache buffer. */ + CACHE_TYPE cache_buffer; + /* Indicates how many bits avail in cache_buffer. */ + int cache_avail; + unsigned char odd; + char have_odd; + } br; + + /* + * Huffman coding. + */ + struct huffman { + int len_size; + int freq[17]; + unsigned char *bitlen; + + /* + * Use a index table. It's faster than searching a huffman + * 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; + int error; +}; + +static const int slots[] = { + 30, 32, 34, 36, 38, 42, 50, 66, 98, 162, 290 +}; +#define SLOT_BASE 15 +#define SLOT_MAX 21/*->25*/ + +struct lzx_stream { + const unsigned char *next_in; + int64_t avail_in; + int64_t total_in; + unsigned char *next_out; + int64_t avail_out; + int64_t total_out; + struct lzx_dec *ds; +}; + +/* + * Cabinet file definitions. + */ +/* CFHEADER offset */ +#define CFHEADER_signature 0 +#define CFHEADER_cbCabinet 8 +#define CFHEADER_coffFiles 16 +#define CFHEADER_versionMinor 24 +#define CFHEADER_versionMajor 25 +#define CFHEADER_cFolders 26 +#define CFHEADER_cFiles 28 +#define CFHEADER_flags 30 +#define CFHEADER_setID 32 +#define CFHEADER_iCabinet 34 +#define CFHEADER_cbCFHeader 36 +#define CFHEADER_cbCFFolder 38 +#define CFHEADER_cbCFData 39 + +/* CFFOLDER offset */ +#define CFFOLDER_coffCabStart 0 +#define CFFOLDER_cCFData 4 +#define CFFOLDER_typeCompress 6 +#define CFFOLDER_abReserve 8 + +/* CFFILE offset */ +#define CFFILE_cbFile 0 +#define CFFILE_uoffFolderStart 4 +#define CFFILE_iFolder 8 +#define CFFILE_date_time 10 +#define CFFILE_attribs 14 + +/* CFDATA offset */ +#define CFDATA_csum 0 +#define CFDATA_cbData 4 +#define CFDATA_cbUncomp 6 + +static const char *compression_name[] = { + "NONE", + "MSZIP", + "Quantum", + "LZX", +}; + +struct cfdata { + /* Sum value of this CFDATA. */ + uint32_t sum; + uint16_t compressed_size; + uint16_t compressed_bytes_remaining; + uint16_t uncompressed_size; + uint16_t uncompressed_bytes_remaining; + /* To know how many bytes we have decompressed. */ + uint16_t uncompressed_avail; + /* Offset from the beginning of compressed data of this CFDATA */ + uint16_t read_offset; + int64_t unconsumed; + /* To keep memory image of this CFDATA to compute the sum. */ + size_t memimage_size; + unsigned char *memimage; + /* Result of calculation of sum. */ + uint32_t sum_calculated; + unsigned char sum_extra[4]; + int sum_extra_avail; + const void *sum_ptr; +}; + +struct cffolder { + uint32_t cfdata_offset_in_cab; + uint16_t cfdata_count; + uint16_t comptype; +#define COMPTYPE_NONE 0x0000 +#define COMPTYPE_MSZIP 0x0001 +#define COMPTYPE_QUANTUM 0x0002 +#define COMPTYPE_LZX 0x0003 + uint16_t compdata; + const char *compname; + /* At the time reading CFDATA */ + struct cfdata cfdata; + int cfdata_index; + /* Flags to mark progress of decompression. */ + char decompress_init; +}; + +struct cffile { + uint32_t uncompressed_size; + uint32_t offset; + time_t mtime; + uint16_t folder; +#define iFoldCONTINUED_FROM_PREV 0xFFFD +#define iFoldCONTINUED_TO_NEXT 0xFFFE +#define iFoldCONTINUED_PREV_AND_NEXT 0xFFFF + unsigned char attr; +#define ATTR_RDONLY 0x01 +#define ATTR_NAME_IS_UTF 0x80 + struct archive_string pathname; +}; + +struct cfheader { + /* Total bytes of all file size in a Cabinet. */ + uint32_t total_bytes; + uint32_t files_offset; + uint16_t folder_count; + uint16_t file_count; + uint16_t flags; +#define PREV_CABINET 0x0001 +#define NEXT_CABINET 0x0002 +#define RESERVE_PRESENT 0x0004 + uint16_t setid; + uint16_t cabinet; + /* Version number. */ + unsigned char major; + unsigned char minor; + unsigned char cffolder; + unsigned char cfdata; + /* All folders in a cabinet. */ + struct cffolder *folder_array; + /* All files in a cabinet. */ + struct cffile *file_array; + int file_index; +}; + +struct cab { + /* entry_bytes_remaining is the number of bytes we expect. */ + int64_t entry_offset; + int64_t entry_bytes_remaining; + int64_t entry_unconsumed; + int64_t entry_compressed_bytes_read; + int64_t entry_uncompressed_bytes_read; + struct cffolder *entry_cffolder; + struct cffile *entry_cffile; + struct cfdata *entry_cfdata; + + /* Offset from beginning of a cabinet file. */ + int64_t cab_offset; + struct cfheader cfheader; + struct archive_wstring ws; + + /* Flag to mark progress that an archive was read their first header.*/ + char found_header; + char end_of_archive; + char end_of_entry; + char end_of_entry_cleanup; + char read_data_invoked; + int64_t bytes_skipped; + + unsigned char *uncompressed_buffer; + size_t uncompressed_buffer_size; + + int init_default_conversion; + struct archive_string_conv *sconv; + struct archive_string_conv *sconv_default; + struct archive_string_conv *sconv_utf8; + char format_name[64]; + +#ifdef HAVE_ZLIB_H + z_stream stream; + char stream_valid; +#endif + struct lzx_stream xstrm; +}; + +static int archive_read_format_cab_bid(struct archive_read *, int); +static int archive_read_format_cab_options(struct archive_read *, + const char *, const char *); +static int archive_read_format_cab_read_header(struct archive_read *, + struct archive_entry *); +static int archive_read_format_cab_read_data(struct archive_read *, + const void **, size_t *, int64_t *); +static int archive_read_format_cab_read_data_skip(struct archive_read *); +static int archive_read_format_cab_cleanup(struct archive_read *); + +static int cab_skip_sfx(struct archive_read *); +static time_t cab_dos_time(const unsigned char *); +static int cab_read_data(struct archive_read *, const void **, + size_t *, int64_t *); +static int cab_read_header(struct archive_read *); +static uint32_t cab_checksum_cfdata_4(const void *, size_t bytes, uint32_t); +static uint32_t cab_checksum_cfdata(const void *, size_t bytes, uint32_t); +static void cab_checksum_update(struct archive_read *, size_t); +static int cab_checksum_finish(struct archive_read *); +static int cab_next_cfdata(struct archive_read *); +static const void *cab_read_ahead_cfdata(struct archive_read *, ssize_t *); +static const void *cab_read_ahead_cfdata_none(struct archive_read *, ssize_t *); +static const void *cab_read_ahead_cfdata_deflate(struct archive_read *, + ssize_t *); +static const void *cab_read_ahead_cfdata_lzx(struct archive_read *, + ssize_t *); +static int64_t cab_consume_cfdata(struct archive_read *, int64_t); +static int64_t cab_minimum_consume_cfdata(struct archive_read *, int64_t); +static int lzx_decode_init(struct lzx_stream *, int); +static int lzx_read_blocks(struct lzx_stream *, int); +static int lzx_decode_blocks(struct lzx_stream *, int); +static void lzx_decode_free(struct lzx_stream *); +static void lzx_translation(struct lzx_stream *, void *, size_t, uint32_t); +static void lzx_cleanup_bitstream(struct lzx_stream *); +static int lzx_decode(struct lzx_stream *, int); +static int lzx_read_pre_tree(struct lzx_stream *); +static int lzx_read_bitlen(struct lzx_stream *, struct huffman *, int); +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 +archive_read_support_format_cab(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct cab *cab; + int r; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_format_cab"); + + cab = (struct cab *)calloc(1, sizeof(*cab)); + if (cab == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate CAB data"); + return (ARCHIVE_FATAL); + } + archive_string_init(&cab->ws); + archive_wstring_ensure(&cab->ws, 256); + + r = __archive_read_register_format(a, + cab, + "cab", + archive_read_format_cab_bid, + archive_read_format_cab_options, + archive_read_format_cab_read_header, + archive_read_format_cab_read_data, + archive_read_format_cab_read_data_skip, + NULL, + archive_read_format_cab_cleanup, + NULL, + NULL); + + if (r != ARCHIVE_OK) + free(cab); + return (ARCHIVE_OK); +} + +static int +find_cab_magic(const char *p) +{ + switch (p[4]) { + case 0: + /* + * Note: Self-Extraction program has 'MSCF' string in their + * program. If we were finding 'MSCF' string only, we got + * wrong place for Cabinet header, thus, we have to check + * following four bytes which are reserved and must be set + * to zero. + */ + if (memcmp(p, "MSCF\0\0\0\0", 8) == 0) + return 0; + return 5; + case 'F': return 1; + case 'C': return 2; + case 'S': return 3; + case 'M': return 4; + default: return 5; + } +} + +static int +archive_read_format_cab_bid(struct archive_read *a, int best_bid) +{ + const char *p; + ssize_t bytes_avail, offset, window; + + /* If there's already a better bid than we can ever + make, don't bother testing. */ + if (best_bid > 64) + return (-1); + + if ((p = __archive_read_ahead(a, 8, NULL)) == NULL) + return (-1); + + if (memcmp(p, "MSCF\0\0\0\0", 8) == 0) + return (64); + + /* + * Attempt to handle self-extracting archives + * by noting a PE header and searching forward + * up to 128k for a 'MSCF' marker. + */ + if (p[0] == 'M' && p[1] == 'Z') { + offset = 0; + window = 4096; + while (offset < (1024 * 128)) { + const char *h = __archive_read_ahead(a, offset + window, + &bytes_avail); + if (h == NULL) { + /* Remaining bytes are less than window. */ + window >>= 1; + if (window < 128) + return (0); + continue; + } + p = h + offset; + while (p + 8 < h + bytes_avail) { + int next; + if ((next = find_cab_magic(p)) == 0) + return (64); + p += next; + } + offset = p - h; + } + } + return (0); +} + +static int +archive_read_format_cab_options(struct archive_read *a, + const char *key, const char *val) +{ + struct cab *cab; + int ret = ARCHIVE_FAILED; + + cab = (struct cab *)(a->format->data); + if (strcmp(key, "hdrcharset") == 0) { + if (val == NULL || val[0] == 0) + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "cab: hdrcharset option needs a character-set name"); + else { + cab->sconv = archive_string_conversion_from_charset( + &a->archive, val, 0); + if (cab->sconv != NULL) + ret = ARCHIVE_OK; + else + ret = ARCHIVE_FATAL; + } + return (ret); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +static int +cab_skip_sfx(struct archive_read *a) +{ + const char *p, *q; + size_t skip; + ssize_t bytes, window; + + window = 4096; + for (;;) { + const char *h = __archive_read_ahead(a, window, &bytes); + if (h == NULL) { + /* Remaining size are less than window. */ + window >>= 1; + if (window < 128) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Couldn't find out CAB header"); + return (ARCHIVE_FATAL); + } + continue; + } + p = h; + q = p + bytes; + + /* + * Scan ahead until we find something that looks + * like the cab header. + */ + while (p + 8 < q) { + int next; + if ((next = find_cab_magic(p)) == 0) { + skip = p - h; + __archive_read_consume(a, skip); + return (ARCHIVE_OK); + } + p += next; + } + skip = p - h; + __archive_read_consume(a, skip); + } +} + +static int +truncated_error(struct archive_read *a) +{ + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated CAB header"); + return (ARCHIVE_FATAL); +} + +static ssize_t +cab_strnlen(const unsigned char *p, size_t maxlen) +{ + size_t i; + + for (i = 0; i <= maxlen; i++) { + if (p[i] == 0) + break; + } + if (i > maxlen) + return (-1);/* invalid */ + return ((ssize_t)i); +} + +/* Read bytes as much as remaining. */ +static const void * +cab_read_ahead_remaining(struct archive_read *a, size_t min, ssize_t *avail) +{ + const void *p; + + while (min > 0) { + p = __archive_read_ahead(a, min, avail); + if (p != NULL) + return (p); + min--; + } + return (NULL); +} + +/* Convert a path separator '\' -> '/' */ +static int +cab_convert_path_separator_1(struct archive_string *fn, unsigned char attr) +{ + size_t i; + int mb; + + /* Easy check if we have '\' in multi-byte string. */ + mb = 0; + for (i = 0; i < archive_strlen(fn); i++) { + if (fn->s[i] == '\\') { + if (mb) { + /* This may be second byte of multi-byte + * character. */ + break; + } + fn->s[i] = '/'; + mb = 0; + } else if ((fn->s[i] & 0x80) && !(attr & ATTR_NAME_IS_UTF)) + mb = 1; + else + mb = 0; + } + if (i == archive_strlen(fn)) + return (0); + return (-1); +} + +/* + * Replace a character '\' with '/' in wide character. + */ +static void +cab_convert_path_separator_2(struct cab *cab, struct archive_entry *entry) +{ + const wchar_t *wp; + size_t i; + + /* If a conversion to wide character failed, force the replacement. */ + if ((wp = archive_entry_pathname_w(entry)) != NULL) { + archive_wstrcpy(&(cab->ws), wp); + for (i = 0; i < archive_strlen(&(cab->ws)); i++) { + if (cab->ws.s[i] == L'\\') + cab->ws.s[i] = L'/'; + } + archive_entry_copy_pathname_w(entry, cab->ws.s); + } +} + +/* + * Read CFHEADER, CFFOLDER and CFFILE. + */ +static int +cab_read_header(struct archive_read *a) +{ + const unsigned char *p; + struct cab *cab; + struct cfheader *hd; + size_t bytes, used; + ssize_t len; + int64_t skip; + int err, i; + int cur_folder, prev_folder; + uint32_t offset32; + + a->archive.archive_format = ARCHIVE_FORMAT_CAB; + if (a->archive.archive_format_name == NULL) + a->archive.archive_format_name = "CAB"; + + if ((p = __archive_read_ahead(a, 42, NULL)) == NULL) + return (truncated_error(a)); + + cab = (struct cab *)(a->format->data); + if (cab->found_header == 0 && + p[0] == 'M' && p[1] == 'Z') { - /* This is an executable? Must be self-extracting... */ ++ /* This is an executable? Must be self-extracting... */ + err = cab_skip_sfx(a); + if (err < ARCHIVE_WARN) + return (err); + - if ((p = __archive_read_ahead(a, sizeof(*p), NULL)) == NULL) ++ /* Re-read header after processing the SFX. */ ++ if ((p = __archive_read_ahead(a, 42, NULL)) == NULL) + return (truncated_error(a)); + } + + cab->cab_offset = 0; + /* + * Read CFHEADER. + */ + hd = &cab->cfheader; + if (p[CFHEADER_signature+0] != 'M' || p[CFHEADER_signature+1] != 'S' || + p[CFHEADER_signature+2] != 'C' || p[CFHEADER_signature+3] != 'F') { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Couldn't find out CAB header"); + return (ARCHIVE_FATAL); + } + hd->total_bytes = archive_le32dec(p + CFHEADER_cbCabinet); + hd->files_offset = archive_le32dec(p + CFHEADER_coffFiles); + hd->minor = p[CFHEADER_versionMinor]; + hd->major = p[CFHEADER_versionMajor]; + hd->folder_count = archive_le16dec(p + CFHEADER_cFolders); + if (hd->folder_count == 0) + goto invalid; + hd->file_count = archive_le16dec(p + CFHEADER_cFiles); + if (hd->file_count == 0) + goto invalid; + hd->flags = archive_le16dec(p + CFHEADER_flags); + hd->setid = archive_le16dec(p + CFHEADER_setID); + hd->cabinet = archive_le16dec(p + CFHEADER_iCabinet); + used = CFHEADER_iCabinet + 2; + if (hd->flags & RESERVE_PRESENT) { + uint16_t cfheader; + cfheader = archive_le16dec(p + CFHEADER_cbCFHeader); + if (cfheader > 60000U) + goto invalid; + hd->cffolder = p[CFHEADER_cbCFFolder]; + hd->cfdata = p[CFHEADER_cbCFData]; + used += 4;/* cbCFHeader, cbCFFolder and cbCFData */ + used += cfheader;/* abReserve */ + } else + hd->cffolder = 0;/* Avoid compiling warning. */ + if (hd->flags & PREV_CABINET) { + /* How many bytes are used for szCabinetPrev. */ + if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL) + return (truncated_error(a)); + if ((len = cab_strnlen(p + used, 255)) <= 0) + goto invalid; + used += len + 1; + /* How many bytes are used for szDiskPrev. */ + if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL) + return (truncated_error(a)); + if ((len = cab_strnlen(p + used, 255)) <= 0) + goto invalid; + used += len + 1; + } + if (hd->flags & NEXT_CABINET) { + /* How many bytes are used for szCabinetNext. */ + if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL) + return (truncated_error(a)); + if ((len = cab_strnlen(p + used, 255)) <= 0) + goto invalid; + used += len + 1; + /* How many bytes are used for szDiskNext. */ + if ((p = __archive_read_ahead(a, used+256, NULL)) == NULL) + return (truncated_error(a)); + if ((len = cab_strnlen(p + used, 255)) <= 0) + goto invalid; + used += len + 1; + } + __archive_read_consume(a, used); + cab->cab_offset += used; + used = 0; + + /* + * Read CFFOLDER. + */ + hd->folder_array = (struct cffolder *)calloc( + hd->folder_count, sizeof(struct cffolder)); + if (hd->folder_array == NULL) + goto nomem; + + bytes = 8; + if (hd->flags & RESERVE_PRESENT) + bytes += hd->cffolder; + bytes *= hd->folder_count; + if ((p = __archive_read_ahead(a, bytes, NULL)) == NULL) + return (truncated_error(a)); + offset32 = 0; + for (i = 0; i < hd->folder_count; i++) { + struct cffolder *folder = &(hd->folder_array[i]); + folder->cfdata_offset_in_cab = + archive_le32dec(p + CFFOLDER_coffCabStart); + folder->cfdata_count = archive_le16dec(p+CFFOLDER_cCFData); + folder->comptype = + archive_le16dec(p+CFFOLDER_typeCompress) & 0x0F; + folder->compdata = + archive_le16dec(p+CFFOLDER_typeCompress) >> 8; + /* Get a compression name. */ + if (folder->comptype < + sizeof(compression_name) / sizeof(compression_name[0])) + folder->compname = compression_name[folder->comptype]; + else + folder->compname = "UNKNOWN"; + p += 8; + used += 8; + if (hd->flags & RESERVE_PRESENT) { + p += hd->cffolder;/* abReserve */ + used += hd->cffolder; + } + /* + * Sanity check if each data is acceptable. + */ + if (offset32 >= folder->cfdata_offset_in_cab) + goto invalid; + offset32 = folder->cfdata_offset_in_cab; + + /* Set a request to initialize zlib for the CFDATA of + * this folder. */ + folder->decompress_init = 0; + } + __archive_read_consume(a, used); + cab->cab_offset += used; + + /* + * Read CFFILE. + */ + /* Seek read pointer to the offset of CFFILE if needed. */ + skip = (int64_t)hd->files_offset - cab->cab_offset; + if (skip < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid offset of CFFILE %jd < %jd", + (intmax_t)hd->files_offset, (intmax_t)cab->cab_offset); + return (ARCHIVE_FATAL); + } + if (skip) { + __archive_read_consume(a, skip); + cab->cab_offset += skip; + } + /* Allocate memory for CFDATA */ + hd->file_array = (struct cffile *)calloc( + hd->file_count, sizeof(struct cffile)); + if (hd->file_array == NULL) + goto nomem; + + prev_folder = -1; + for (i = 0; i < hd->file_count; i++) { + struct cffile *file = &(hd->file_array[i]); + ssize_t avail; + + if ((p = __archive_read_ahead(a, 16, NULL)) == NULL) + return (truncated_error(a)); + file->uncompressed_size = archive_le32dec(p + CFFILE_cbFile); + file->offset = archive_le32dec(p + CFFILE_uoffFolderStart); + file->folder = archive_le16dec(p + CFFILE_iFolder); + file->mtime = cab_dos_time(p + CFFILE_date_time); + file->attr = (uint8_t)archive_le16dec(p + CFFILE_attribs); + __archive_read_consume(a, 16); + + cab->cab_offset += 16; + if ((p = cab_read_ahead_remaining(a, 256, &avail)) == NULL) + return (truncated_error(a)); + if ((len = cab_strnlen(p, avail-1)) <= 0) + goto invalid; + + /* Copy a pathname. */ + archive_string_init(&(file->pathname)); + archive_strncpy(&(file->pathname), p, len); + __archive_read_consume(a, len + 1); + cab->cab_offset += len + 1; + + /* + * Sanity check if each data is acceptable. + */ + if (file->uncompressed_size > 0x7FFF8000) + goto invalid;/* Too large */ + if ((int64_t)file->offset + (int64_t)file->uncompressed_size + > ARCHIVE_LITERAL_LL(0x7FFF8000)) + goto invalid;/* Too large */ + switch (file->folder) { + case iFoldCONTINUED_TO_NEXT: + /* This must be last file in a folder. */ + if (i != hd->file_count -1) + goto invalid; + cur_folder = hd->folder_count -1; + break; + case iFoldCONTINUED_PREV_AND_NEXT: + /* This must be only one file in a folder. */ + if (hd->file_count != 1) + goto invalid; + /* FALL THROUGH */ + case iFoldCONTINUED_FROM_PREV: + /* This must be first file in a folder. */ + if (i != 0) + goto invalid; + prev_folder = cur_folder = 0; + offset32 = file->offset; + break; + default: + if (file->folder >= hd->folder_count) + goto invalid; + cur_folder = file->folder; + break; + } + /* Dot not back track. */ + if (cur_folder < prev_folder) + goto invalid; + if (cur_folder != prev_folder) + offset32 = 0; + prev_folder = cur_folder; + + /* Make sure there are not any blanks from last file + * contents. */ + if (offset32 != file->offset) + goto invalid; + offset32 += file->uncompressed_size; + + /* CFDATA is available for file contents. */ + if (file->uncompressed_size > 0 && + hd->folder_array[cur_folder].cfdata_count == 0) + goto invalid; + } + + if (hd->cabinet != 0 || hd->flags & (PREV_CABINET | NEXT_CABINET)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Multivolume cabinet file is unsupported"); + return (ARCHIVE_WARN); + } + return (ARCHIVE_OK); +invalid: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid CAB header"); + return (ARCHIVE_FATAL); +nomem: + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for CAB data"); + return (ARCHIVE_FATAL); +} + +static int +archive_read_format_cab_read_header(struct archive_read *a, + struct archive_entry *entry) +{ + struct cab *cab; + struct cfheader *hd; + struct cffolder *prev_folder; + struct cffile *file; + struct archive_string_conv *sconv; + int err = ARCHIVE_OK, r; + + cab = (struct cab *)(a->format->data); + if (cab->found_header == 0) { + err = cab_read_header(a); + if (err < ARCHIVE_WARN) + return (err); + /* We've found the header. */ + cab->found_header = 1; + } + hd = &cab->cfheader; + + if (hd->file_index >= hd->file_count) { + cab->end_of_archive = 1; + return (ARCHIVE_EOF); + } + file = &hd->file_array[hd->file_index++]; + + cab->end_of_entry = 0; + cab->end_of_entry_cleanup = 0; + cab->entry_compressed_bytes_read = 0; + cab->entry_uncompressed_bytes_read = 0; + cab->entry_unconsumed = 0; + cab->entry_cffile = file; + + /* + * Choose a proper folder. + */ + prev_folder = cab->entry_cffolder; + switch (file->folder) { + case iFoldCONTINUED_FROM_PREV: + case iFoldCONTINUED_PREV_AND_NEXT: + cab->entry_cffolder = &hd->folder_array[0]; + break; + case iFoldCONTINUED_TO_NEXT: + cab->entry_cffolder = &hd->folder_array[hd->folder_count-1]; + break; + default: + cab->entry_cffolder = &hd->folder_array[file->folder]; + break; + } + /* If a cffolder of this file is changed, reset a cfdata to read + * file contents from next cfdata. */ + if (prev_folder != cab->entry_cffolder) + cab->entry_cfdata = NULL; + + /* If a pathname is UTF-8, prepare a string conversion object + * for UTF-8 and use it. */ + if (file->attr & ATTR_NAME_IS_UTF) { + if (cab->sconv_utf8 == NULL) { + cab->sconv_utf8 = + archive_string_conversion_from_charset( + &(a->archive), "UTF-8", 1); + if (cab->sconv_utf8 == NULL) + return (ARCHIVE_FATAL); + } + sconv = cab->sconv_utf8; + } else if (cab->sconv != NULL) { + /* Choose the conversion specified by the option. */ + sconv = cab->sconv; + } else { + /* Choose the default conversion. */ + if (!cab->init_default_conversion) { + cab->sconv_default = + archive_string_default_conversion_for_read( + &(a->archive)); + cab->init_default_conversion = 1; + } + sconv = cab->sconv_default; + } + + /* + * Set a default value and common data + */ + r = cab_convert_path_separator_1(&(file->pathname), file->attr); + if (archive_entry_copy_pathname_l(entry, file->pathname.s, + archive_strlen(&(file->pathname)), sconv) != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Pathname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Pathname cannot be converted " + "from %s to current locale.", + archive_string_conversion_charset_name(sconv)); + err = ARCHIVE_WARN; + } + if (r < 0) { + /* Convert a path separator '\' -> '/' */ + cab_convert_path_separator_2(cab, entry); + } + + archive_entry_set_size(entry, file->uncompressed_size); + if (file->attr & ATTR_RDONLY) + archive_entry_set_mode(entry, AE_IFREG | 0555); + else + archive_entry_set_mode(entry, AE_IFREG | 0666); + archive_entry_set_mtime(entry, file->mtime, 0); + + cab->entry_bytes_remaining = file->uncompressed_size; + cab->entry_offset = 0; + /* We don't need compress data. */ + if (file->uncompressed_size == 0) + cab->end_of_entry_cleanup = cab->end_of_entry = 1; + + /* Set up a more descriptive format name. */ + sprintf(cab->format_name, "CAB %d.%d (%s)", + hd->major, hd->minor, cab->entry_cffolder->compname); + a->archive.archive_format_name = cab->format_name; + + return (err); +} + +static int +archive_read_format_cab_read_data(struct archive_read *a, + const void **buff, size_t *size, int64_t *offset) +{ + struct cab *cab = (struct cab *)(a->format->data); + int r; + + switch (cab->entry_cffile->folder) { + case iFoldCONTINUED_FROM_PREV: + case iFoldCONTINUED_TO_NEXT: + case iFoldCONTINUED_PREV_AND_NEXT: + *buff = NULL; + *size = 0; + *offset = 0; + archive_clear_error(&a->archive); + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Cannot restore this file split in multivolume."); + return (ARCHIVE_FAILED); + default: + break; + } + if (cab->read_data_invoked == 0) { + if (cab->bytes_skipped) { + if (cab->entry_cfdata == NULL) { + r = cab_next_cfdata(a); + if (r < 0) + return (r); + } + if (cab_consume_cfdata(a, cab->bytes_skipped) < 0) + return (ARCHIVE_FATAL); + cab->bytes_skipped = 0; + } + cab->read_data_invoked = 1; + } + if (cab->entry_unconsumed) { + /* Consume as much as the compressor actually used. */ + r = (int)cab_consume_cfdata(a, cab->entry_unconsumed); + cab->entry_unconsumed = 0; + if (r < 0) + return (r); + } + if (cab->end_of_archive || cab->end_of_entry) { + if (!cab->end_of_entry_cleanup) { + /* End-of-entry cleanup done. */ + cab->end_of_entry_cleanup = 1; + } + *offset = cab->entry_offset; + *size = 0; + *buff = NULL; + return (ARCHIVE_EOF); + } + + return (cab_read_data(a, buff, size, offset)); +} + +static uint32_t +cab_checksum_cfdata_4(const void *p, size_t bytes, uint32_t seed) +{ + const unsigned char *b; + unsigned u32num; + uint32_t sum; + + u32num = (unsigned)bytes / 4; + sum = seed; + b = p; + for (;u32num > 0; --u32num) { + sum ^= archive_le32dec(b); + b += 4; + } + return (sum); +} + +static uint32_t +cab_checksum_cfdata(const void *p, size_t bytes, uint32_t seed) +{ + const unsigned char *b; + uint32_t sum; + uint32_t t; + + sum = cab_checksum_cfdata_4(p, bytes, seed); + b = p; + b += bytes & ~3; + t = 0; + switch (bytes & 3) { + case 3: + t |= ((uint32_t)(*b++)) << 16; + /* FALL THROUGH */ + case 2: + t |= ((uint32_t)(*b++)) << 8; + /* FALL THROUGH */ + case 1: + t |= *b; + /* FALL THROUGH */ + default: + break; + } + sum ^= t; + + return (sum); +} + +static void +cab_checksum_update(struct archive_read *a, size_t bytes) +{ + struct cab *cab = (struct cab *)(a->format->data); + struct cfdata *cfdata = cab->entry_cfdata; + const unsigned char *p; + size_t sumbytes; + + if (cfdata->sum == 0 || cfdata->sum_ptr == NULL) + return; + /* + * Calculate the sum of this CFDATA. + * Make sure CFDATA must be calculated in four bytes. + */ + p = cfdata->sum_ptr; + sumbytes = bytes; + if (cfdata->sum_extra_avail) { + while (cfdata->sum_extra_avail < 4 && sumbytes > 0) { + cfdata->sum_extra[ + cfdata->sum_extra_avail++] = *p++; + sumbytes--; + } + if (cfdata->sum_extra_avail == 4) { + cfdata->sum_calculated = cab_checksum_cfdata_4( + cfdata->sum_extra, 4, cfdata->sum_calculated); + cfdata->sum_extra_avail = 0; + } + } + if (sumbytes) { + int odd = sumbytes & 3; + if (sumbytes - odd > 0) + cfdata->sum_calculated = cab_checksum_cfdata_4( + p, sumbytes - odd, cfdata->sum_calculated); + if (odd) + memcpy(cfdata->sum_extra, p + sumbytes - odd, odd); + cfdata->sum_extra_avail = odd; + } + cfdata->sum_ptr = NULL; +} + +static int +cab_checksum_finish(struct archive_read *a) +{ + struct cab *cab = (struct cab *)(a->format->data); + struct cfdata *cfdata = cab->entry_cfdata; + int l; + + /* Do not need to compute a sum. */ + if (cfdata->sum == 0) + return (ARCHIVE_OK); + + /* + * Calculate the sum of remaining CFDATA. + */ + if (cfdata->sum_extra_avail) { + cfdata->sum_calculated = + cab_checksum_cfdata(cfdata->sum_extra, + cfdata->sum_extra_avail, cfdata->sum_calculated); + cfdata->sum_extra_avail = 0; + } + + l = 4; + if (cab->cfheader.flags & RESERVE_PRESENT) + l += cab->cfheader.cfdata; + cfdata->sum_calculated = cab_checksum_cfdata( + cfdata->memimage + CFDATA_cbData, l, cfdata->sum_calculated); + if (cfdata->sum_calculated != cfdata->sum) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Checksum error CFDATA[%d] %x:%x in %d bytes", + cab->entry_cffolder->cfdata_index -1, + cfdata->sum, cfdata->sum_calculated, + cfdata->compressed_size); + return (ARCHIVE_FAILED); + } + return (ARCHIVE_OK); +} + +/* + * Read CFDATA if needed. + */ +static int +cab_next_cfdata(struct archive_read *a) +{ + struct cab *cab = (struct cab *)(a->format->data); + struct cfdata *cfdata = cab->entry_cfdata; + + /* There are remaining bytes in current CFDATA, use it first. */ + if (cfdata != NULL && cfdata->uncompressed_bytes_remaining > 0) + return (ARCHIVE_OK); + + if (cfdata == NULL) { + int64_t skip; + + cab->entry_cffolder->cfdata_index = 0; + + /* Seek read pointer to the offset of CFDATA if needed. */ + skip = cab->entry_cffolder->cfdata_offset_in_cab + - cab->cab_offset; + if (skip < 0) { + int folder_index; + switch (cab->entry_cffile->folder) { + case iFoldCONTINUED_FROM_PREV: + case iFoldCONTINUED_PREV_AND_NEXT: + folder_index = 0; + break; + case iFoldCONTINUED_TO_NEXT: + folder_index = cab->cfheader.folder_count-1; + break; + default: + folder_index = cab->entry_cffile->folder; + break; + } + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid offset of CFDATA in folder(%d) %jd < %jd", + folder_index, + (intmax_t)cab->entry_cffolder->cfdata_offset_in_cab, + (intmax_t)cab->cab_offset); + return (ARCHIVE_FATAL); + } + if (skip > 0) { + if (__archive_read_consume(a, skip) < 0) + return (ARCHIVE_FATAL); + cab->cab_offset = + cab->entry_cffolder->cfdata_offset_in_cab; + } + } + + /* + * Read a CFDATA. + */ + if (cab->entry_cffolder->cfdata_index < + cab->entry_cffolder->cfdata_count) { + const unsigned char *p; + int l; + + cfdata = &(cab->entry_cffolder->cfdata); + cab->entry_cffolder->cfdata_index++; + cab->entry_cfdata = cfdata; + cfdata->sum_calculated = 0; + cfdata->sum_extra_avail = 0; + cfdata->sum_ptr = NULL; + l = 8; + if (cab->cfheader.flags & RESERVE_PRESENT) + l += cab->cfheader.cfdata; + if ((p = __archive_read_ahead(a, l, NULL)) == NULL) + return (truncated_error(a)); + cfdata->sum = archive_le32dec(p + CFDATA_csum); + cfdata->compressed_size = archive_le16dec(p + CFDATA_cbData); + cfdata->compressed_bytes_remaining = cfdata->compressed_size; + cfdata->uncompressed_size = + archive_le16dec(p + CFDATA_cbUncomp); + cfdata->uncompressed_bytes_remaining = + cfdata->uncompressed_size; + cfdata->uncompressed_avail = 0; + cfdata->read_offset = 0; + cfdata->unconsumed = 0; + + /* + * Sanity check if data size is acceptable. + */ + if (cfdata->compressed_size == 0 || + cfdata->compressed_size > (0x8000+6144)) + goto invalid; + if (cfdata->uncompressed_size > 0x8000) + goto invalid; + if (cfdata->uncompressed_size == 0) { + switch (cab->entry_cffile->folder) { + case iFoldCONTINUED_PREV_AND_NEXT: + case iFoldCONTINUED_TO_NEXT: + break; + case iFoldCONTINUED_FROM_PREV: + default: + goto invalid; + } + } + /* If CFDATA is not last in a folder, an uncompressed + * size must be 0x8000(32KBi) */ + if ((cab->entry_cffolder->cfdata_index < + cab->entry_cffolder->cfdata_count) && + cfdata->uncompressed_size != 0x8000) + goto invalid; + + /* A compressed data size and an uncompressed data size must + * be the same in no compression mode. */ + if (cab->entry_cffolder->comptype == COMPTYPE_NONE && + cfdata->compressed_size != cfdata->uncompressed_size) + goto invalid; + + /* + * Save CFDATA image for sum check. + */ + if (cfdata->memimage_size < (size_t)l) { + free(cfdata->memimage); + cfdata->memimage = malloc(l); + if (cfdata->memimage == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for CAB data"); + return (ARCHIVE_FATAL); + } + cfdata->memimage_size = l; + } + memcpy(cfdata->memimage, p, l); + + /* Consume bytes as much as we used. */ + __archive_read_consume(a, l); + cab->cab_offset += l; + } else if (cab->entry_cffolder->cfdata_count > 0) { + /* Run out of all CFDATA in a folder. */ + cfdata->compressed_size = 0; + cfdata->uncompressed_size = 0; + cfdata->compressed_bytes_remaining = 0; + cfdata->uncompressed_bytes_remaining = 0; + } else { + /* Current folder does not have any CFDATA. */ + cfdata = &(cab->entry_cffolder->cfdata); + cab->entry_cfdata = cfdata; + memset(cfdata, 0, sizeof(*cfdata)); + } + return (ARCHIVE_OK); +invalid: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid CFDATA"); + return (ARCHIVE_FATAL); +} + +/* + * Read ahead CFDATA. + */ +static const void * +cab_read_ahead_cfdata(struct archive_read *a, ssize_t *avail) +{ + struct cab *cab = (struct cab *)(a->format->data); + int err; + + err = cab_next_cfdata(a); + if (err < ARCHIVE_OK) { + *avail = err; + return (NULL); + } + + switch (cab->entry_cffolder->comptype) { + case COMPTYPE_NONE: + return (cab_read_ahead_cfdata_none(a, avail)); + case COMPTYPE_MSZIP: + return (cab_read_ahead_cfdata_deflate(a, avail)); + case COMPTYPE_LZX: + return (cab_read_ahead_cfdata_lzx(a, avail)); + default: /* Unsupported compression. */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Unsupported CAB compression : %s", + cab->entry_cffolder->compname); + *avail = ARCHIVE_FAILED; + return (NULL); + } +} + +/* + * Read ahead CFDATA as uncompressed data. + */ +static const void * +cab_read_ahead_cfdata_none(struct archive_read *a, ssize_t *avail) +{ + struct cab *cab = (struct cab *)(a->format->data); + struct cfdata *cfdata; + const void *d; + + cfdata = cab->entry_cfdata; + + /* + * Note: '1' here is a performance optimization. + * Recall that the decompression layer returns a count of + * available bytes; asking for more than that forces the + * decompressor to combine reads by copying data. + */ + d = __archive_read_ahead(a, 1, avail); + if (*avail <= 0) { + *avail = truncated_error(a); + return (NULL); + } + if (*avail > cfdata->uncompressed_bytes_remaining) + *avail = cfdata->uncompressed_bytes_remaining; + cfdata->uncompressed_avail = cfdata->uncompressed_size; + cfdata->unconsumed = *avail; + cfdata->sum_ptr = d; + return (d); +} + +/* + * Read ahead CFDATA as deflate data. + */ +#ifdef HAVE_ZLIB_H +static const void * +cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail) +{ + struct cab *cab = (struct cab *)(a->format->data); + struct cfdata *cfdata; + const void *d; + int r, mszip; + uint16_t uavail; + char eod = 0; + + cfdata = cab->entry_cfdata; + /* If the buffer hasn't been allocated, allocate it now. */ + if (cab->uncompressed_buffer == NULL) { + cab->uncompressed_buffer_size = 0x8000; + cab->uncompressed_buffer + = (unsigned char *)malloc(cab->uncompressed_buffer_size); + if (cab->uncompressed_buffer == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory for CAB reader"); + *avail = ARCHIVE_FATAL; + return (NULL); + } + } + + uavail = cfdata->uncompressed_avail; + if (uavail == cfdata->uncompressed_size) { + d = cab->uncompressed_buffer + cfdata->read_offset; + *avail = uavail - cfdata->read_offset; + return (d); + } + + if (!cab->entry_cffolder->decompress_init) { + cab->stream.next_in = NULL; + cab->stream.avail_in = 0; + cab->stream.total_in = 0; + cab->stream.next_out = NULL; + cab->stream.avail_out = 0; + cab->stream.total_out = 0; + if (cab->stream_valid) + r = inflateReset(&cab->stream); + else + r = inflateInit2(&cab->stream, + -15 /* Don't check for zlib header */); + if (r != Z_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can't initialize deflate decompression."); + *avail = ARCHIVE_FATAL; + return (NULL); + } + /* Stream structure has been set up. */ + cab->stream_valid = 1; + /* We've initialized decompression for this stream. */ + cab->entry_cffolder->decompress_init = 1; + } + + if (cfdata->compressed_bytes_remaining == cfdata->compressed_size) + mszip = 2; + else + mszip = 0; + eod = 0; + cab->stream.total_out = uavail; + /* + * We always uncompress all data in current CFDATA. + */ + while (!eod && cab->stream.total_out < cfdata->uncompressed_size) { + ssize_t bytes_avail; + + cab->stream.next_out = + cab->uncompressed_buffer + cab->stream.total_out; + cab->stream.avail_out = + cfdata->uncompressed_size - cab->stream.total_out; + + d = __archive_read_ahead(a, 1, &bytes_avail); + if (bytes_avail <= 0) { + *avail = truncated_error(a); + return (NULL); + } + if (bytes_avail > cfdata->compressed_bytes_remaining) + bytes_avail = cfdata->compressed_bytes_remaining; + /* + * A bug in zlib.h: stream.next_in should be marked 'const' + * but isn't (the library never alters data through the + * next_in pointer, only reads it). The result: this ugly + * cast to remove 'const'. + */ + cab->stream.next_in = (Bytef *)(uintptr_t)d; + cab->stream.avail_in = (uInt)bytes_avail; + cab->stream.total_in = 0; + + /* Cut out a tow-byte MSZIP signature(0x43, 0x4b). */ + if (mszip > 0) { ++ if (bytes_avail <= 0) ++ goto nomszip; + if (bytes_avail <= mszip) { + if (mszip == 2) { + if (cab->stream.next_in[0] != 0x43) + goto nomszip; + if (bytes_avail > 1 && + cab->stream.next_in[1] != 0x4b) + goto nomszip; + } else if (cab->stream.next_in[0] != 0x4b) + goto nomszip; + cfdata->unconsumed = bytes_avail; + cfdata->sum_ptr = d; + if (cab_minimum_consume_cfdata( + a, cfdata->unconsumed) < 0) { + *avail = ARCHIVE_FATAL; + return (NULL); + } + mszip -= (int)bytes_avail; + continue; + } + if (mszip == 1 && cab->stream.next_in[0] != 0x4b) + goto nomszip; + else if (cab->stream.next_in[0] != 0x43 || + cab->stream.next_in[1] != 0x4b) + goto nomszip; + cab->stream.next_in += mszip; + cab->stream.avail_in -= mszip; + cab->stream.total_in += mszip; + mszip = 0; + } + + r = inflate(&cab->stream, 0); + switch (r) { + case Z_OK: + break; + case Z_STREAM_END: + eod = 1; + break; + default: + goto zlibfailed; + } + cfdata->unconsumed = cab->stream.total_in; + cfdata->sum_ptr = d; + if (cab_minimum_consume_cfdata(a, cfdata->unconsumed) < 0) { + *avail = ARCHIVE_FATAL; + return (NULL); + } + } + uavail = (uint16_t)cab->stream.total_out; + + if (uavail < cfdata->uncompressed_size) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid uncompressed size (%d < %d)", + uavail, cfdata->uncompressed_size); + *avail = ARCHIVE_FATAL; + return (NULL); + } + + /* + * Note: I suspect there is a bug in makecab.exe because, in rare + * case, compressed bytes are still remaining regardless we have - * gotten all uncompressed bytes, which size is recoded in CFDATA, ++ * gotten all uncompressed bytes, which size is recorded in CFDATA, + * as much as we need, and we have to use the garbage so as to + * correctly compute the sum of CFDATA accordingly. + */ + if (cfdata->compressed_bytes_remaining > 0) { + ssize_t bytes_avail; + + d = __archive_read_ahead(a, cfdata->compressed_bytes_remaining, + &bytes_avail); + if (bytes_avail <= 0) { + *avail = truncated_error(a); + return (NULL); + } + cfdata->unconsumed = cfdata->compressed_bytes_remaining; + cfdata->sum_ptr = d; + if (cab_minimum_consume_cfdata(a, cfdata->unconsumed) < 0) { + *avail = ARCHIVE_FATAL; + return (NULL); + } + } + + /* + * Set dictionary data for decompressing of next CFDATA, which + * in the same folder. This is why we always do decompress CFDATA + * even if beginning CFDATA or some of CFDATA are not used in + * skipping file data. + */ + if (cab->entry_cffolder->cfdata_index < + cab->entry_cffolder->cfdata_count) { + r = inflateReset(&cab->stream); + if (r != Z_OK) + goto zlibfailed; + r = inflateSetDictionary(&cab->stream, + cab->uncompressed_buffer, cfdata->uncompressed_size); + if (r != Z_OK) + goto zlibfailed; + } + + d = cab->uncompressed_buffer + cfdata->read_offset; + *avail = uavail - cfdata->read_offset; + cfdata->uncompressed_avail = uavail; + + return (d); + +zlibfailed: + switch (r) { + case Z_MEM_ERROR: + archive_set_error(&a->archive, ENOMEM, + "Out of memory for deflate decompression"); + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Deflate decompression failed (%d)", r); + break; + } + *avail = ARCHIVE_FATAL; + return (NULL); +nomszip: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "CFDATA incorrect(no MSZIP signature)"); + *avail = ARCHIVE_FATAL; + return (NULL); +} + +#else /* HAVE_ZLIB_H */ + +static const void * +cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail) +{ + *avail = ARCHIVE_FATAL; + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "libarchive compiled without deflate support (no libz)"); + return (NULL); +} + +#endif /* HAVE_ZLIB_H */ + +static const void * +cab_read_ahead_cfdata_lzx(struct archive_read *a, ssize_t *avail) +{ + struct cab *cab = (struct cab *)(a->format->data); + struct cfdata *cfdata; + const void *d; + int r; + uint16_t uavail; + + cfdata = cab->entry_cfdata; + /* If the buffer hasn't been allocated, allocate it now. */ + if (cab->uncompressed_buffer == NULL) { + cab->uncompressed_buffer_size = 0x8000; + cab->uncompressed_buffer + = (unsigned char *)malloc(cab->uncompressed_buffer_size); + if (cab->uncompressed_buffer == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory for CAB reader"); + *avail = ARCHIVE_FATAL; + return (NULL); + } + } + + uavail = cfdata->uncompressed_avail; + if (uavail == cfdata->uncompressed_size) { + d = cab->uncompressed_buffer + cfdata->read_offset; + *avail = uavail - cfdata->read_offset; + return (d); + } + + if (!cab->entry_cffolder->decompress_init) { + r = lzx_decode_init(&cab->xstrm, + cab->entry_cffolder->compdata); + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can't initialize LZX decompression."); + *avail = ARCHIVE_FATAL; + return (NULL); + } + /* We've initialized decompression for this stream. */ + cab->entry_cffolder->decompress_init = 1; + } + + /* Clean up remaining bits of previous CFDATA. */ + lzx_cleanup_bitstream(&cab->xstrm); + cab->xstrm.total_out = uavail; + while (cab->xstrm.total_out < cfdata->uncompressed_size) { + ssize_t bytes_avail; + + cab->xstrm.next_out = + cab->uncompressed_buffer + cab->xstrm.total_out; + cab->xstrm.avail_out = + cfdata->uncompressed_size - cab->xstrm.total_out; + + d = __archive_read_ahead(a, 1, &bytes_avail); + if (bytes_avail <= 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated CAB file data"); + *avail = ARCHIVE_FATAL; + return (NULL); + } + if (bytes_avail > cfdata->compressed_bytes_remaining) + bytes_avail = cfdata->compressed_bytes_remaining; + + cab->xstrm.next_in = d; + cab->xstrm.avail_in = bytes_avail; + cab->xstrm.total_in = 0; + r = lzx_decode(&cab->xstrm, + cfdata->compressed_bytes_remaining == bytes_avail); + switch (r) { + case ARCHIVE_OK: + case ARCHIVE_EOF: + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "LZX decompression failed (%d)", r); + *avail = ARCHIVE_FATAL; + return (NULL); + } + cfdata->unconsumed = cab->xstrm.total_in; + cfdata->sum_ptr = d; + if (cab_minimum_consume_cfdata(a, cfdata->unconsumed) < 0) { + *avail = ARCHIVE_FATAL; + return (NULL); + } + } + + uavail = (uint16_t)cab->xstrm.total_out; + /* + * Make sure a read pointer advances to next CFDATA. + */ + if (cfdata->compressed_bytes_remaining > 0) { + ssize_t bytes_avail; + + d = __archive_read_ahead(a, cfdata->compressed_bytes_remaining, + &bytes_avail); + if (bytes_avail <= 0) { + *avail = truncated_error(a); + return (NULL); + } + cfdata->unconsumed = cfdata->compressed_bytes_remaining; + cfdata->sum_ptr = d; + if (cab_minimum_consume_cfdata(a, cfdata->unconsumed) < 0) { + *avail = ARCHIVE_FATAL; + return (NULL); + } + } + + /* - * Translation reversal of x86 proccessor CALL byte sequence(E8). ++ * Translation reversal of x86 processor CALL byte sequence(E8). + */ + lzx_translation(&cab->xstrm, cab->uncompressed_buffer, + cfdata->uncompressed_size, + (cab->entry_cffolder->cfdata_index-1) * 0x8000); + + d = cab->uncompressed_buffer + cfdata->read_offset; + *avail = uavail - cfdata->read_offset; + cfdata->uncompressed_avail = uavail; + + return (d); +} + +/* + * Consume CFDATA. + * We always decompress CFDATA to consume CFDATA as much as we need + * in uncompressed bytes because all CFDATA in a folder are related + * so we do not skip any CFDATA without decompressing. + * Note: If the folder of a CFFILE is iFoldCONTINUED_PREV_AND_NEXT or + * iFoldCONTINUED_FROM_PREV, we won't decompress because a CFDATA for + * the CFFILE is remaining bytes of previous Multivolume CAB file. + */ +static int64_t +cab_consume_cfdata(struct archive_read *a, int64_t consumed_bytes) +{ + struct cab *cab = (struct cab *)(a->format->data); + struct cfdata *cfdata; + int64_t cbytes, rbytes; + int err; + + rbytes = cab_minimum_consume_cfdata(a, consumed_bytes); + if (rbytes < 0) + return (ARCHIVE_FATAL); + + cfdata = cab->entry_cfdata; + while (rbytes > 0) { + ssize_t avail; + + if (cfdata->compressed_size == 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid CFDATA"); + return (ARCHIVE_FATAL); + } + cbytes = cfdata->uncompressed_bytes_remaining; + if (cbytes > rbytes) + cbytes = rbytes; + rbytes -= cbytes; + + if (cfdata->uncompressed_avail == 0 && + (cab->entry_cffile->folder == iFoldCONTINUED_PREV_AND_NEXT || + cab->entry_cffile->folder == iFoldCONTINUED_FROM_PREV)) { + /* We have not read any data yet. */ + if (cbytes == cfdata->uncompressed_bytes_remaining) { + /* Skip whole current CFDATA. */ + __archive_read_consume(a, + cfdata->compressed_size); + cab->cab_offset += cfdata->compressed_size; + cfdata->compressed_bytes_remaining = 0; + cfdata->uncompressed_bytes_remaining = 0; + err = cab_next_cfdata(a); + if (err < 0) + return (err); + cfdata = cab->entry_cfdata; + if (cfdata->uncompressed_size == 0) { + switch (cab->entry_cffile->folder) { + case iFoldCONTINUED_PREV_AND_NEXT: + case iFoldCONTINUED_TO_NEXT: + case iFoldCONTINUED_FROM_PREV: + rbytes = 0; + break; + default: + break; + } + } + continue; + } + cfdata->read_offset += (uint16_t)cbytes; + cfdata->uncompressed_bytes_remaining -= (uint16_t)cbytes; + break; + } else if (cbytes == 0) { + err = cab_next_cfdata(a); + if (err < 0) + return (err); + cfdata = cab->entry_cfdata; + if (cfdata->uncompressed_size == 0) { + switch (cab->entry_cffile->folder) { + case iFoldCONTINUED_PREV_AND_NEXT: + case iFoldCONTINUED_TO_NEXT: + case iFoldCONTINUED_FROM_PREV: + return (ARCHIVE_FATAL); + default: + break; + } + } + continue; + } + while (cbytes > 0) { + (void)cab_read_ahead_cfdata(a, &avail); + if (avail <= 0) + return (ARCHIVE_FATAL); + if (avail > cbytes) + avail = (ssize_t)cbytes; + if (cab_minimum_consume_cfdata(a, avail) < 0) + return (ARCHIVE_FATAL); + cbytes -= avail; + } + } + return (consumed_bytes); +} + +/* + * Consume CFDATA as much as we have already gotten and + * compute the sum of CFDATA. + */ +static int64_t +cab_minimum_consume_cfdata(struct archive_read *a, int64_t consumed_bytes) +{ + struct cab *cab = (struct cab *)(a->format->data); + struct cfdata *cfdata; + int64_t cbytes, rbytes; + int err; + + cfdata = cab->entry_cfdata; + rbytes = consumed_bytes; + if (cab->entry_cffolder->comptype == COMPTYPE_NONE) { + if (consumed_bytes < cfdata->unconsumed) + cbytes = consumed_bytes; + else + cbytes = cfdata->unconsumed; + rbytes -= cbytes; + cfdata->read_offset += (uint16_t)cbytes; + cfdata->uncompressed_bytes_remaining -= (uint16_t)cbytes; + cfdata->unconsumed -= cbytes; + } else { + cbytes = cfdata->uncompressed_avail - cfdata->read_offset; + if (cbytes > 0) { + if (consumed_bytes < cbytes) + cbytes = consumed_bytes; + rbytes -= cbytes; + cfdata->read_offset += (uint16_t)cbytes; + cfdata->uncompressed_bytes_remaining -= (uint16_t)cbytes; + } + + if (cfdata->unconsumed) { + cbytes = cfdata->unconsumed; + cfdata->unconsumed = 0; + } else + cbytes = 0; + } + if (cbytes) { + /* Compute the sum. */ + cab_checksum_update(a, (size_t)cbytes); + + /* Consume as much as the compressor actually used. */ + __archive_read_consume(a, cbytes); + cab->cab_offset += cbytes; + cfdata->compressed_bytes_remaining -= (uint16_t)cbytes; + if (cfdata->compressed_bytes_remaining == 0) { + err = cab_checksum_finish(a); + if (err < 0) + return (err); + } + } + return (rbytes); +} + +/* + * Returns ARCHIVE_OK if successful, ARCHIVE_FATAL otherwise, sets + * cab->end_of_entry if it consumes all of the data. + */ +static int +cab_read_data(struct archive_read *a, const void **buff, + size_t *size, int64_t *offset) +{ + struct cab *cab = (struct cab *)(a->format->data); + ssize_t bytes_avail; + + if (cab->entry_bytes_remaining == 0) { + *buff = NULL; + *size = 0; + *offset = cab->entry_offset; + cab->end_of_entry = 1; + return (ARCHIVE_OK); + } + + *buff = cab_read_ahead_cfdata(a, &bytes_avail); + if (bytes_avail <= 0) { + *buff = NULL; + *size = 0; + *offset = 0; + if (bytes_avail == 0 && + cab->entry_cfdata->uncompressed_size == 0) { + /* All of CFDATA in a folder has been handled. */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Invalid CFDATA"); + return (ARCHIVE_FATAL); + } else + return ((int)bytes_avail); + } + if (bytes_avail > cab->entry_bytes_remaining) + bytes_avail = (ssize_t)cab->entry_bytes_remaining; + + *size = bytes_avail; + *offset = cab->entry_offset; + cab->entry_offset += bytes_avail; + cab->entry_bytes_remaining -= bytes_avail; + if (cab->entry_bytes_remaining == 0) + cab->end_of_entry = 1; + cab->entry_unconsumed = bytes_avail; + if (cab->entry_cffolder->comptype == COMPTYPE_NONE) { + /* Don't consume more than current entry used. */ + if (cab->entry_cfdata->unconsumed > cab->entry_unconsumed) + cab->entry_cfdata->unconsumed = cab->entry_unconsumed; + } + return (ARCHIVE_OK); +} + +static int +archive_read_format_cab_read_data_skip(struct archive_read *a) +{ + struct cab *cab; + int64_t bytes_skipped; + int r; + + cab = (struct cab *)(a->format->data); + + if (cab->end_of_archive) + return (ARCHIVE_EOF); + + if (!cab->read_data_invoked) { + cab->bytes_skipped += cab->entry_bytes_remaining; + cab->entry_bytes_remaining = 0; + /* This entry is finished and done. */ + cab->end_of_entry_cleanup = cab->end_of_entry = 1; + return (ARCHIVE_OK); + } + + if (cab->entry_unconsumed) { + /* Consume as much as the compressor actually used. */ + r = (int)cab_consume_cfdata(a, cab->entry_unconsumed); + cab->entry_unconsumed = 0; + if (r < 0) + return (r); + } else if (cab->entry_cfdata == NULL) { + r = cab_next_cfdata(a); + if (r < 0) + return (r); + } + + /* if we've already read to end of data, we're done. */ + if (cab->end_of_entry_cleanup) + return (ARCHIVE_OK); + + /* + * If the length is at the beginning, we can skip the + * compressed data much more quickly. + */ + bytes_skipped = cab_consume_cfdata(a, cab->entry_bytes_remaining); + if (bytes_skipped < 0) + return (ARCHIVE_FATAL); + + /* If the compression type is none(uncompressed), we've already + * consumed data as much as the current entry size. */ + if (cab->entry_cffolder->comptype == COMPTYPE_NONE && + cab->entry_cfdata != NULL) + cab->entry_cfdata->unconsumed = 0; + + /* This entry is finished and done. */ + cab->end_of_entry_cleanup = cab->end_of_entry = 1; + return (ARCHIVE_OK); +} + +static int +archive_read_format_cab_cleanup(struct archive_read *a) +{ + struct cab *cab = (struct cab *)(a->format->data); + struct cfheader *hd = &cab->cfheader; + int i; + + if (hd->folder_array != NULL) { + for (i = 0; i < hd->folder_count; i++) + free(hd->folder_array[i].cfdata.memimage); + free(hd->folder_array); + } + if (hd->file_array != NULL) { + for (i = 0; i < cab->cfheader.file_count; i++) + archive_string_free(&(hd->file_array[i].pathname)); + free(hd->file_array); + } +#ifdef HAVE_ZLIB_H + if (cab->stream_valid) + inflateEnd(&cab->stream); +#endif + lzx_decode_free(&cab->xstrm); + archive_wstring_free(&cab->ws); + free(cab->uncompressed_buffer); + free(cab); + (a->format->data) = NULL; + return (ARCHIVE_OK); +} + +/* Convert an MSDOS-style date/time into Unix-style time. */ +static time_t +cab_dos_time(const unsigned char *p) +{ + int msTime, msDate; + struct tm ts; + + msDate = archive_le16dec(p); + msTime = archive_le16dec(p+2); + + memset(&ts, 0, sizeof(ts)); + ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */ + ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */ + ts.tm_mday = msDate & 0x1f; /* Day of month. */ + ts.tm_hour = (msTime >> 11) & 0x1f; + ts.tm_min = (msTime >> 5) & 0x3f; + ts.tm_sec = (msTime << 1) & 0x3e; + ts.tm_isdst = -1; + return (mktime(&ts)); +} + +/***************************************************************** + * + * LZX decompression code. + * + *****************************************************************/ + +/* + * Initialize LZX decoder. + * + * Returns ARCHIVE_OK if initialization was successful. + * Returns ARCHIVE_FAILED if w_bits has unsupported value. + * Returns ARCHIVE_FATAL if initialization failed; memory allocation + * error occurred. + */ +static int +lzx_decode_init(struct lzx_stream *strm, int w_bits) +{ + struct lzx_dec *ds; + int slot, w_size, w_slot; + int base, footer; + int base_inc[18]; + + if (strm->ds == NULL) { + strm->ds = calloc(1, sizeof(*strm->ds)); + if (strm->ds == NULL) + return (ARCHIVE_FATAL); + } + ds = strm->ds; + ds->error = ARCHIVE_FAILED; + + /* Allow bits from 15(32KBi) up to 21(2MBi) */ + if (w_bits < SLOT_BASE || w_bits > SLOT_MAX) + return (ARCHIVE_FAILED); + + ds->error = ARCHIVE_FATAL; + + /* + * Alloc window + */ + w_size = ds->w_size; + w_slot = slots[w_bits - SLOT_BASE]; + ds->w_size = 1U << w_bits; + ds->w_mask = ds->w_size -1; + if (ds->w_buff == NULL || w_size != ds->w_size) { + free(ds->w_buff); + ds->w_buff = malloc(ds->w_size); + if (ds->w_buff == NULL) + return (ARCHIVE_FATAL); + free(ds->pos_tbl); + ds->pos_tbl = malloc(sizeof(ds->pos_tbl[0]) * w_slot); + if (ds->pos_tbl == NULL) + return (ARCHIVE_FATAL); + lzx_huffman_free(&(ds->mt)); + } + + for (footer = 0; footer < 18; footer++) + base_inc[footer] = 1 << footer; + base = footer = 0; + for (slot = 0; slot < w_slot; slot++) { + int n; + if (footer == 0) + base = slot; + else + base += base_inc[footer]; + if (footer < 17) { + footer = -2; + for (n = base; n; n >>= 1) + footer++; + if (footer <= 0) + footer = 0; + } + ds->pos_tbl[slot].base = base; + ds->pos_tbl[slot].footer_bits = footer; + } + + ds->w_pos = 0; + ds->state = 0; + ds->br.cache_buffer = 0; + ds->br.cache_avail = 0; + ds->r0 = ds->r1 = ds->r2 = 1; + + /* Initialize aligned offset tree. */ + if (lzx_huffman_init(&(ds->at), 8, 8) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* Initialize pre-tree. */ + if (lzx_huffman_init(&(ds->pt), 20, 10) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* Initialize Main tree. */ + if (lzx_huffman_init(&(ds->mt), 256+(w_slot<<3), 16) + != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* Initialize Length tree. */ + if (lzx_huffman_init(&(ds->lt), 249, 16) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + ds->error = 0; + + return (ARCHIVE_OK); +} + +/* + * Release LZX decoder. + */ +static void +lzx_decode_free(struct lzx_stream *strm) +{ + + if (strm->ds == NULL) + return; + free(strm->ds->w_buff); + free(strm->ds->pos_tbl); + lzx_huffman_free(&(strm->ds->at)); + lzx_huffman_free(&(strm->ds->pt)); + lzx_huffman_free(&(strm->ds->mt)); + lzx_huffman_free(&(strm->ds->lt)); + free(strm->ds); + strm->ds = NULL; +} + +/* + * E8 Call Translation reversal. + */ +static void +lzx_translation(struct lzx_stream *strm, void *p, size_t size, uint32_t offset) +{ + struct lzx_dec *ds = strm->ds; + unsigned char *b, *end; + + if (!ds->translation || size <= 10) + return; + b = p; + end = b + size - 10; + while (b < end && (b = memchr(b, 0xE8, end - b)) != NULL) { + size_t i = b - (unsigned char *)p; + int32_t cp, displacement, value; + + cp = (int32_t)(offset + (uint32_t)i); + value = archive_le32dec(&b[1]); + if (value >= -cp && value < (int32_t)ds->translation_size) { + if (value >= 0) + displacement = value - cp; + else + displacement = value + ds->translation_size; + archive_le32enc(&b[1], (uint32_t)displacement); + } + b += 5; + } +} + +/* + * Bit stream reader. + */ +/* Check that the cache buffer has enough bits. */ +#define lzx_br_has(br, n) ((br)->cache_avail >= n) +/* Get compressed data by bit. */ +#define lzx_br_bits(br, n) \ + (((uint32_t)((br)->cache_buffer >> \ + ((br)->cache_avail - (n)))) & cache_masks[n]) +#define lzx_br_bits_forced(br, n) \ + (((uint32_t)((br)->cache_buffer << \ + ((n) - (br)->cache_avail))) & cache_masks[n]) +/* Read ahead to make sure the cache buffer has enough compressed data we + * will use. + * True : completed, there is enough data in the cache buffer. + * False : we met that strm->next_in is empty, we have to get following + * bytes. */ +#define lzx_br_read_ahead_0(strm, br, n) \ + (lzx_br_has((br), (n)) || lzx_br_fillup(strm, br)) +/* True : the cache buffer has some bits as much as we need. + * False : there are no enough bits in the cache buffer to be used, + * we have to get following bytes if we could. */ +#define lzx_br_read_ahead(strm, br, n) \ + (lzx_br_read_ahead_0((strm), (br), (n)) || lzx_br_has((br), (n))) + +/* Notify how many bits we consumed. */ +#define lzx_br_consume(br, n) ((br)->cache_avail -= (n)) +#define lzx_br_consume_unaligned_bits(br) ((br)->cache_avail &= ~0x0f) + +#define lzx_br_is_unaligned(br) ((br)->cache_avail & 0x0f) + +static const uint32_t cache_masks[] = { + 0x00000000, 0x00000001, 0x00000003, 0x00000007, + 0x0000000F, 0x0000001F, 0x0000003F, 0x0000007F, + 0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF, + 0x00000FFF, 0x00001FFF, 0x00003FFF, 0x00007FFF, + 0x0000FFFF, 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, + 0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, + 0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, + 0x0FFFFFFF, 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF +}; + +/* + * Shift away used bits in the cache data and fill it up with following bits. + * Call this when cache buffer does not have enough bits you need. + * + * Returns 1 if the cache buffer is full. + * Returns 0 if the cache buffer is not full; input buffer is empty. + */ +static int +lzx_br_fillup(struct lzx_stream *strm, struct lzx_br *br) +{ +/* - * x86 proccessor family can read misaligned data without an access error. ++ * x86 processor family can read misaligned data without an access error. + */ + int n = CACHE_BITS - br->cache_avail; + + for (;;) { + switch (n >> 4) { + case 4: + if (strm->avail_in >= 8) { + br->cache_buffer = + ((uint64_t)strm->next_in[1]) << 56 | + ((uint64_t)strm->next_in[0]) << 48 | + ((uint64_t)strm->next_in[3]) << 40 | + ((uint64_t)strm->next_in[2]) << 32 | + ((uint32_t)strm->next_in[5]) << 24 | + ((uint32_t)strm->next_in[4]) << 16 | + ((uint32_t)strm->next_in[7]) << 8 | + (uint32_t)strm->next_in[6]; + strm->next_in += 8; + strm->avail_in -= 8; + br->cache_avail += 8 * 8; + return (1); + } + break; + case 3: + if (strm->avail_in >= 6) { + br->cache_buffer = + (br->cache_buffer << 48) | + ((uint64_t)strm->next_in[1]) << 40 | + ((uint64_t)strm->next_in[0]) << 32 | + ((uint32_t)strm->next_in[3]) << 24 | + ((uint32_t)strm->next_in[2]) << 16 | + ((uint32_t)strm->next_in[5]) << 8 | + (uint32_t)strm->next_in[4]; + strm->next_in += 6; + strm->avail_in -= 6; + br->cache_avail += 6 * 8; + return (1); + } + break; + case 0: + /* We have enough compressed data in + * the cache buffer.*/ + return (1); + default: + break; + } + if (strm->avail_in < 2) { + /* There is not enough compressed data to + * fill up the cache buffer. */ + if (strm->avail_in == 1) { + br->odd = *strm->next_in++; + strm->avail_in--; + br->have_odd = 1; + } + return (0); + } + br->cache_buffer = + (br->cache_buffer << 16) | + archive_le16dec(strm->next_in); + strm->next_in += 2; + strm->avail_in -= 2; + br->cache_avail += 16; + n -= 16; + } +} + +static void +lzx_br_fixup(struct lzx_stream *strm, struct lzx_br *br) +{ + int n = CACHE_BITS - br->cache_avail; + + if (br->have_odd && n >= 16 && strm->avail_in > 0) { + br->cache_buffer = + (br->cache_buffer << 16) | + ((uint16_t)(*strm->next_in)) << 8 | br->odd; + strm->next_in++; + strm->avail_in--; + br->cache_avail += 16; + br->have_odd = 0; + } +} + +static void +lzx_cleanup_bitstream(struct lzx_stream *strm) +{ + strm->ds->br.cache_avail = 0; + strm->ds->br.have_odd = 0; +} + +/* + * Decode LZX. + * + * 1. Returns ARCHIVE_OK if output buffer or input buffer are empty. + * Please set available buffer and call this function again. + * 2. Returns ARCHIVE_EOF if decompression has been completed. + * 3. Returns ARCHIVE_FAILED if an error occurred; compressed data + * is broken or you do not set 'last' flag properly. + */ +#define ST_RD_TRANSLATION 0 +#define ST_RD_TRANSLATION_SIZE 1 +#define ST_RD_BLOCK_TYPE 2 +#define ST_RD_BLOCK_SIZE 3 +#define ST_RD_ALIGNMENT 4 +#define ST_RD_R0 5 +#define ST_RD_R1 6 +#define ST_RD_R2 7 +#define ST_COPY_UNCOMP1 8 +#define ST_COPY_UNCOMP2 9 +#define ST_RD_ALIGNED_OFFSET 10 +#define ST_RD_VERBATIM 11 +#define ST_RD_PRE_MAIN_TREE_256 12 +#define ST_MAIN_TREE_256 13 +#define ST_RD_PRE_MAIN_TREE_REM 14 +#define ST_MAIN_TREE_REM 15 +#define ST_RD_PRE_LENGTH_TREE 16 +#define ST_LENGTH_TREE 17 +#define ST_MAIN 18 +#define ST_LENGTH 19 +#define ST_OFFSET 20 +#define ST_REAL_POS 21 +#define ST_COPY 22 + +static int +lzx_decode(struct lzx_stream *strm, int last) +{ + struct lzx_dec *ds = strm->ds; + int64_t avail_in; + int r; + + if (ds->error) + return (ds->error); + + avail_in = strm->avail_in; + lzx_br_fixup(strm, &(ds->br)); + do { + if (ds->state < ST_MAIN) + r = lzx_read_blocks(strm, last); + else { + int64_t bytes_written = strm->avail_out; + r = lzx_decode_blocks(strm, last); + bytes_written -= strm->avail_out; + strm->next_out += bytes_written; + strm->total_out += bytes_written; + } + } while (r == 100); + strm->total_in += avail_in - strm->avail_in; + return (r); +} + +static int +lzx_read_blocks(struct lzx_stream *strm, int last) +{ + struct lzx_dec *ds = strm->ds; + struct lzx_br *br = &(ds->br); + int i, r; + + for (;;) { + switch (ds->state) { + case ST_RD_TRANSLATION: + if (!lzx_br_read_ahead(strm, br, 1)) { + ds->state = ST_RD_TRANSLATION; + if (last) + goto failed; + return (ARCHIVE_OK); + } + ds->translation = lzx_br_bits(br, 1); + lzx_br_consume(br, 1); + /* FALL THROUGH */ + case ST_RD_TRANSLATION_SIZE: + if (ds->translation) { + if (!lzx_br_read_ahead(strm, br, 32)) { + ds->state = ST_RD_TRANSLATION_SIZE; + if (last) + goto failed; + return (ARCHIVE_OK); + } + ds->translation_size = lzx_br_bits(br, 16); + lzx_br_consume(br, 16); + ds->translation_size <<= 16; + ds->translation_size |= lzx_br_bits(br, 16); + lzx_br_consume(br, 16); + } + /* FALL THROUGH */ + case ST_RD_BLOCK_TYPE: + if (!lzx_br_read_ahead(strm, br, 3)) { + ds->state = ST_RD_BLOCK_TYPE; + if (last) + goto failed; + return (ARCHIVE_OK); + } + ds->block_type = lzx_br_bits(br, 3); + lzx_br_consume(br, 3); + /* Check a block type. */ + switch (ds->block_type) { + case VERBATIM_BLOCK: + case ALIGNED_OFFSET_BLOCK: + case UNCOMPRESSED_BLOCK: + break; + default: + goto failed;/* Invalid */ + } + /* FALL THROUGH */ + case ST_RD_BLOCK_SIZE: + if (!lzx_br_read_ahead(strm, br, 24)) { + ds->state = ST_RD_BLOCK_SIZE; + if (last) + goto failed; + return (ARCHIVE_OK); + } + ds->block_size = lzx_br_bits(br, 8); + lzx_br_consume(br, 8); + ds->block_size <<= 16; + ds->block_size |= lzx_br_bits(br, 16); + lzx_br_consume(br, 16); + if (ds->block_size == 0) + goto failed; + ds->block_bytes_avail = ds->block_size; + if (ds->block_type != UNCOMPRESSED_BLOCK) { + if (ds->block_type == VERBATIM_BLOCK) + ds->state = ST_RD_VERBATIM; + else + ds->state = ST_RD_ALIGNED_OFFSET; + break; + } + /* FALL THROUGH */ + case ST_RD_ALIGNMENT: + /* + * Handle an Uncompressed Block. + */ + /* Skip padding to align following field on + * 16-bit boundary. */ + if (lzx_br_is_unaligned(br)) + lzx_br_consume_unaligned_bits(br); + else { + if (lzx_br_read_ahead(strm, br, 16)) + lzx_br_consume(br, 16); + else { + ds->state = ST_RD_ALIGNMENT; + if (last) + goto failed; + return (ARCHIVE_OK); + } + } + /* Preparation to read repeated offsets R0,R1 and R2. */ + ds->rbytes_avail = 0; + ds->state = ST_RD_R0; + /* FALL THROUGH */ + case ST_RD_R0: + case ST_RD_R1: + case ST_RD_R2: + do { + uint16_t u16; + /* Drain bits in the cache buffer of + * bit-stream. */ + if (lzx_br_has(br, 32)) { + u16 = lzx_br_bits(br, 16); + lzx_br_consume(br, 16); + archive_le16enc(ds->rbytes, u16); + u16 = lzx_br_bits(br, 16); + lzx_br_consume(br, 16); + archive_le16enc(ds->rbytes+2, u16); + ds->rbytes_avail = 4; + } else if (lzx_br_has(br, 16)) { + u16 = lzx_br_bits(br, 16); + lzx_br_consume(br, 16); + archive_le16enc(ds->rbytes, u16); + ds->rbytes_avail = 2; + } + if (ds->rbytes_avail < 4 && ds->br.have_odd) { + ds->rbytes[ds->rbytes_avail++] = + ds->br.odd; + ds->br.have_odd = 0; + } + while (ds->rbytes_avail < 4) { + if (strm->avail_in <= 0) { + if (last) + goto failed; + return (ARCHIVE_OK); + } + ds->rbytes[ds->rbytes_avail++] = + *strm->next_in++; + strm->avail_in--; + } + ds->rbytes_avail = 0; + if (ds->state == ST_RD_R0) { + ds->r0 = archive_le32dec(ds->rbytes); + if (ds->r0 < 0) + goto failed; + ds->state = ST_RD_R1; + } else if (ds->state == ST_RD_R1) { + ds->r1 = archive_le32dec(ds->rbytes); + if (ds->r1 < 0) + goto failed; + ds->state = ST_RD_R2; + } else if (ds->state == ST_RD_R2) { + ds->r2 = archive_le32dec(ds->rbytes); + if (ds->r2 < 0) + goto failed; + /* We've gotten all repeated offsets. */ + ds->state = ST_COPY_UNCOMP1; + } + } while (ds->state != ST_COPY_UNCOMP1); + /* FALL THROUGH */ + case ST_COPY_UNCOMP1: + /* + * Copy bytes form next_in to next_out directly. + */ + while (ds->block_bytes_avail) { + int l; + + if (strm->avail_out <= 0) + /* Output buffer is empty. */ + return (ARCHIVE_OK); + if (strm->avail_in <= 0) { + /* Input buffer is empty. */ + if (last) + goto failed; + return (ARCHIVE_OK); + } + l = (int)ds->block_bytes_avail; + if (l > ds->w_size - ds->w_pos) + l = ds->w_size - ds->w_pos; + if (l > strm->avail_out) + l = (int)strm->avail_out; + if (l > strm->avail_in) + l = (int)strm->avail_in; + memcpy(strm->next_out, strm->next_in, l); + memcpy(&(ds->w_buff[ds->w_pos]), + strm->next_in, l); + strm->next_in += l; + strm->avail_in -= l; + strm->next_out += l; + strm->avail_out -= l; + strm->total_out += l; + ds->w_pos = (ds->w_pos + l) & ds->w_mask; + ds->block_bytes_avail -= l; + } + /* FALL THROUGH */ + case ST_COPY_UNCOMP2: + /* Re-align; skip padding byte. */ + if (ds->block_size & 1) { + if (strm->avail_in <= 0) { + /* Input buffer is empty. */ + ds->state = ST_COPY_UNCOMP2; + if (last) + goto failed; + return (ARCHIVE_OK); + } + strm->next_in++; + strm->avail_in --; + } + /* This block ended. */ + ds->state = ST_RD_BLOCK_TYPE; + return (ARCHIVE_EOF); + /********************/ + case ST_RD_ALIGNED_OFFSET: + /* + * Read Aligned offset tree. + */ + if (!lzx_br_read_ahead(strm, br, 3 * ds->at.len_size)) { + ds->state = ST_RD_ALIGNED_OFFSET; + if (last) + goto failed; + return (ARCHIVE_OK); + } + memset(ds->at.freq, 0, sizeof(ds->at.freq)); + for (i = 0; i < ds->at.len_size; i++) { + ds->at.bitlen[i] = lzx_br_bits(br, 3); + ds->at.freq[ds->at.bitlen[i]]++; + lzx_br_consume(br, 3); + } + if (!lzx_make_huffman_table(&ds->at)) + goto failed; + /* FALL THROUGH */ + case ST_RD_VERBATIM: + ds->loop = 0; + /* FALL THROUGH */ + case ST_RD_PRE_MAIN_TREE_256: + /* + * Read Pre-tree for first 256 elements of main tree. + */ + if (!lzx_read_pre_tree(strm)) { + ds->state = ST_RD_PRE_MAIN_TREE_256; + if (last) + goto failed; + return (ARCHIVE_OK); + } + if (!lzx_make_huffman_table(&ds->pt)) + goto failed; + ds->loop = 0; + /* FALL THROUGH */ + case ST_MAIN_TREE_256: + /* + * Get path lengths of first 256 elements of main tree. + */ + r = lzx_read_bitlen(strm, &ds->mt, 256); + if (r < 0) + goto failed; + else if (!r) { + ds->state = ST_MAIN_TREE_256; + if (last) + goto failed; + return (ARCHIVE_OK); + } + ds->loop = 0; + /* FALL THROUGH */ + case ST_RD_PRE_MAIN_TREE_REM: + /* + * Read Pre-tree for remaining elements of main tree. + */ + if (!lzx_read_pre_tree(strm)) { + ds->state = ST_RD_PRE_MAIN_TREE_REM; + if (last) + goto failed; + return (ARCHIVE_OK); + } + if (!lzx_make_huffman_table(&ds->pt)) + goto failed; + ds->loop = 256; + /* FALL THROUGH */ + case ST_MAIN_TREE_REM: + /* + * Get path lengths of remaining elements of main tree. + */ + r = lzx_read_bitlen(strm, &ds->mt, -1); + if (r < 0) + goto failed; + else if (!r) { + ds->state = ST_MAIN_TREE_REM; + if (last) + goto failed; + return (ARCHIVE_OK); + } + if (!lzx_make_huffman_table(&ds->mt)) + goto failed; + ds->loop = 0; + /* FALL THROUGH */ + case ST_RD_PRE_LENGTH_TREE: + /* + * Read Pre-tree for remaining elements of main tree. + */ + if (!lzx_read_pre_tree(strm)) { + ds->state = ST_RD_PRE_LENGTH_TREE; + if (last) + goto failed; + return (ARCHIVE_OK); + } + if (!lzx_make_huffman_table(&ds->pt)) + goto failed; + ds->loop = 0; + /* FALL THROUGH */ + case ST_LENGTH_TREE: + /* + * Get path lengths of remaining elements of main tree. + */ + r = lzx_read_bitlen(strm, &ds->lt, -1); + if (r < 0) + goto failed; + else if (!r) { + ds->state = ST_LENGTH_TREE; + if (last) + goto failed; + return (ARCHIVE_OK); + } + if (!lzx_make_huffman_table(&ds->lt)) + goto failed; + ds->state = ST_MAIN; + return (100); + } + } +failed: + return (ds->error = ARCHIVE_FAILED); +} + +static int +lzx_decode_blocks(struct lzx_stream *strm, int last) +{ + struct lzx_dec *ds = strm->ds; + struct lzx_br bre = ds->br; + struct huffman *at = &(ds->at), *lt = &(ds->lt), *mt = &(ds->mt); + const struct lzx_pos_tbl *pos_tbl = ds->pos_tbl; + unsigned char *noutp = strm->next_out; + unsigned char *endp = noutp + strm->avail_out; + unsigned char *w_buff = ds->w_buff; + unsigned char *at_bitlen = at->bitlen; + unsigned char *lt_bitlen = lt->bitlen; + unsigned char *mt_bitlen = mt->bitlen; + size_t block_bytes_avail = ds->block_bytes_avail; + int at_max_bits = at->max_bits; + int lt_max_bits = lt->max_bits; + int mt_max_bits = mt->max_bits; + int c, copy_len = ds->copy_len, copy_pos = ds->copy_pos; + int w_pos = ds->w_pos, w_mask = ds->w_mask, w_size = ds->w_size; + int length_header = ds->length_header; + int offset_bits = ds->offset_bits; + int position_slot = ds->position_slot; + int r0 = ds->r0, r1 = ds->r1, r2 = ds->r2; + int state = ds->state; + char block_type = ds->block_type; + + for (;;) { + switch (state) { + case ST_MAIN: + for (;;) { + if (block_bytes_avail == 0) { + /* This block ended. */ + ds->state = ST_RD_BLOCK_TYPE; + ds->br = bre; + ds->block_bytes_avail = + block_bytes_avail; + ds->copy_len = copy_len; + ds->copy_pos = copy_pos; + ds->length_header = length_header; + ds->position_slot = position_slot; + ds->r0 = r0; ds->r1 = r1; ds->r2 = r2; + ds->w_pos = w_pos; + strm->avail_out = endp - noutp; + return (ARCHIVE_EOF); + } + if (noutp >= endp) + /* Output buffer is empty. */ + goto next_data; + + if (!lzx_br_read_ahead(strm, &bre, + mt_max_bits)) { + if (!last) + goto next_data; + /* Remaining bits are less than + * maximum bits(mt.max_bits) but maybe + * it still remains as much as we need, + * so we should try to use it with + * dummy bits. */ + c = lzx_decode_huffman(mt, + lzx_br_bits_forced( + &bre, mt_max_bits)); + lzx_br_consume(&bre, mt_bitlen[c]); + if (!lzx_br_has(&bre, 0)) + goto failed;/* Over read. */ + } else { + c = lzx_decode_huffman(mt, + lzx_br_bits(&bre, mt_max_bits)); + lzx_br_consume(&bre, mt_bitlen[c]); + } + if (c > UCHAR_MAX) + break; + /* + * 'c' is exactly literal code. + */ + /* Save a decoded code to reference it + * afterward. */ + w_buff[w_pos] = c; + w_pos = (w_pos + 1) & w_mask; + /* Store the decoded code to output buffer. */ + *noutp++ = c; + block_bytes_avail--; + } + /* + * Get a match code, its length and offset. + */ + c -= UCHAR_MAX + 1; + length_header = c & 7; + position_slot = c >> 3; + /* FALL THROUGH */ + case ST_LENGTH: + /* + * Get a length. + */ + if (length_header == 7) { + if (!lzx_br_read_ahead(strm, &bre, + lt_max_bits)) { + if (!last) { + state = ST_LENGTH; + goto next_data; + } + c = lzx_decode_huffman(lt, + lzx_br_bits_forced( + &bre, lt_max_bits)); + lzx_br_consume(&bre, lt_bitlen[c]); + if (!lzx_br_has(&bre, 0)) + goto failed;/* Over read. */ + } else { + c = lzx_decode_huffman(lt, + lzx_br_bits(&bre, lt_max_bits)); + lzx_br_consume(&bre, lt_bitlen[c]); + } + copy_len = c + 7 + 2; + } else + copy_len = length_header + 2; + if ((size_t)copy_len > block_bytes_avail) + goto failed; + /* + * Get an offset. + */ + switch (position_slot) { + case 0: /* Use repeated offset 0. */ + copy_pos = r0; + state = ST_REAL_POS; + continue; + case 1: /* Use repeated offset 1. */ + copy_pos = r1; + /* Swap repeated offset. */ + r1 = r0; + r0 = copy_pos; + state = ST_REAL_POS; + continue; + case 2: /* Use repeated offset 2. */ + copy_pos = r2; + /* Swap repeated offset. */ + r2 = r0; + r0 = copy_pos; + state = ST_REAL_POS; + continue; + default: + offset_bits = + pos_tbl[position_slot].footer_bits; + break; + } + /* FALL THROUGH */ + case ST_OFFSET: + /* + * Get the offset, which is a distance from + * current window position. + */ + if (block_type == ALIGNED_OFFSET_BLOCK && + offset_bits >= 3) { + int offbits = offset_bits - 3; + + if (!lzx_br_read_ahead(strm, &bre, offbits)) { + state = ST_OFFSET; + if (last) + goto failed; + goto next_data; + } + copy_pos = lzx_br_bits(&bre, offbits) << 3; + + /* Get an aligned number. */ + if (!lzx_br_read_ahead(strm, &bre, + offbits + at_max_bits)) { + if (!last) { + state = ST_OFFSET; + goto next_data; + } + lzx_br_consume(&bre, offbits); + c = lzx_decode_huffman(at, + lzx_br_bits_forced(&bre, + at_max_bits)); + lzx_br_consume(&bre, at_bitlen[c]); + if (!lzx_br_has(&bre, 0)) + goto failed;/* Over read. */ + } else { + lzx_br_consume(&bre, offbits); + c = lzx_decode_huffman(at, + lzx_br_bits(&bre, at_max_bits)); + lzx_br_consume(&bre, at_bitlen[c]); + } + /* Add an aligned number. */ + copy_pos += c; + } else { + if (!lzx_br_read_ahead(strm, &bre, + offset_bits)) { + state = ST_OFFSET; + if (last) + goto failed; + goto next_data; + } + copy_pos = lzx_br_bits(&bre, offset_bits); + lzx_br_consume(&bre, offset_bits); + } + copy_pos += pos_tbl[position_slot].base -2; + + /* Update repeated offset LRU queue. */ + r2 = r1; + r1 = r0; + r0 = copy_pos; + /* FALL THROUGH */ + case ST_REAL_POS: + /* + * Compute a real position in window. + */ + copy_pos = (w_pos - copy_pos) & w_mask; + /* FALL THROUGH */ + case ST_COPY: + /* + * Copy several bytes as extracted data from the window + * into the output buffer. + */ + for (;;) { + const unsigned char *s; + int l; + + l = copy_len; + if (copy_pos > w_pos) { + if (l > w_size - copy_pos) + l = w_size - copy_pos; + } else { + if (l > w_size - w_pos) + l = w_size - w_pos; + } + if (noutp + l >= endp) + l = (int)(endp - noutp); + s = w_buff + copy_pos; + if (l >= 8 && ((copy_pos + l < w_pos) + || (w_pos + l < copy_pos))) { + memcpy(w_buff + w_pos, s, l); + memcpy(noutp, s, l); + } else { + unsigned char *d; + int li; + + d = w_buff + w_pos; + for (li = 0; li < l; li++) + noutp[li] = d[li] = s[li]; + } + noutp += l; + copy_pos = (copy_pos + l) & w_mask; + w_pos = (w_pos + l) & w_mask; + block_bytes_avail -= l; + if (copy_len <= l) + /* A copy of current pattern ended. */ + break; + copy_len -= l; + if (noutp >= endp) { + /* Output buffer is empty. */ + state = ST_COPY; + goto next_data; + } + } + state = ST_MAIN; + break; + } + } +failed: + return (ds->error = ARCHIVE_FAILED); +next_data: + ds->br = bre; + ds->block_bytes_avail = block_bytes_avail; + ds->copy_len = copy_len; + ds->copy_pos = copy_pos; + ds->length_header = length_header; + ds->offset_bits = offset_bits; + ds->position_slot = position_slot; + ds->r0 = r0; ds->r1 = r1; ds->r2 = r2; + ds->state = state; + ds->w_pos = w_pos; + strm->avail_out = endp - noutp; + return (ARCHIVE_OK); +} + +static int +lzx_read_pre_tree(struct lzx_stream *strm) +{ + struct lzx_dec *ds = strm->ds; + struct lzx_br *br = &(ds->br); + int i; + + if (ds->loop == 0) + memset(ds->pt.freq, 0, sizeof(ds->pt.freq)); + for (i = ds->loop; i < ds->pt.len_size; i++) { + if (!lzx_br_read_ahead(strm, br, 4)) { + ds->loop = i; + return (0); + } + ds->pt.bitlen[i] = lzx_br_bits(br, 4); + ds->pt.freq[ds->pt.bitlen[i]]++; + lzx_br_consume(br, 4); + } + ds->loop = i; + return (1); +} + +/* + * Read a bunch of bit-lengths from pre-tree. + */ +static int +lzx_read_bitlen(struct lzx_stream *strm, struct huffman *d, int end) +{ + struct lzx_dec *ds = strm->ds; + struct lzx_br *br = &(ds->br); + int c, i, j, ret, same; + unsigned rbits; + + i = ds->loop; + if (i == 0) + memset(d->freq, 0, sizeof(d->freq)); + ret = 0; + if (end < 0) + end = d->len_size; + while (i < end) { + ds->loop = i; + if (!lzx_br_read_ahead(strm, br, ds->pt.max_bits)) + goto getdata; + rbits = lzx_br_bits(br, ds->pt.max_bits); + c = lzx_decode_huffman(&(ds->pt), rbits); + switch (c) { + case 17:/* several zero lengths, from 4 to 19. */ + if (!lzx_br_read_ahead(strm, br, ds->pt.bitlen[c]+4)) + goto getdata; + lzx_br_consume(br, ds->pt.bitlen[c]); + same = lzx_br_bits(br, 4) + 4; + if (i + same > end) + return (-1);/* Invalid */ + lzx_br_consume(br, 4); + for (j = 0; j < same; j++) + d->bitlen[i++] = 0; + break; + case 18:/* many zero lengths, from 20 to 51. */ + if (!lzx_br_read_ahead(strm, br, ds->pt.bitlen[c]+5)) + goto getdata; + lzx_br_consume(br, ds->pt.bitlen[c]); + same = lzx_br_bits(br, 5) + 20; + if (i + same > end) + return (-1);/* Invalid */ + lzx_br_consume(br, 5); + memset(d->bitlen + i, 0, same); + i += same; + break; + case 19:/* a few same lengths. */ + if (!lzx_br_read_ahead(strm, br, + ds->pt.bitlen[c]+1+ds->pt.max_bits)) + goto getdata; + lzx_br_consume(br, ds->pt.bitlen[c]); + same = lzx_br_bits(br, 1) + 4; + if (i + same > end) + return (-1); + lzx_br_consume(br, 1); + rbits = lzx_br_bits(br, ds->pt.max_bits); + c = lzx_decode_huffman(&(ds->pt), rbits); + lzx_br_consume(br, ds->pt.bitlen[c]); + c = (d->bitlen[i] - c + 17) % 17; + if (c < 0) + return (-1);/* Invalid */ + for (j = 0; j < same; j++) + d->bitlen[i++] = c; + d->freq[c] += same; + break; + default: + lzx_br_consume(br, ds->pt.bitlen[c]); + c = (d->bitlen[i] - c + 17) % 17; + if (c < 0) + return (-1);/* Invalid */ + d->freq[c]++; + d->bitlen[i++] = c; + break; + } + } + ret = 1; +getdata: + ds->loop = i; + return (ret); +} + +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); + hf->bitlen = calloc(len_size, sizeof(hf->bitlen[0])); + if (hf->bitlen == NULL) + return (ARCHIVE_FATAL); + hf->len_size = (int)len_size; + } 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])); + 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); +} + +static void +lzx_huffman_free(struct huffman *hf) +{ + free(hf->bitlen); + free(hf->tbl); + free(hf->tree); +} + +/* + * Make a huffman coding table. + */ +static int +lzx_make_huffman_table(struct huffman *hf) +{ + uint16_t *tbl; + const unsigned char *bitlen; + int bitptn[17], weight[17]; + int i, maxbits = 0, ptn, tbl_size, w; + int diffbits, len_avail; + + /* + * Initialize bit patterns. + */ + ptn = 0; + for (i = 1, w = 1 << 15; i <= 16; i++, w >>= 1) { + bitptn[i] = ptn; + weight[i] = w; + if (hf->freq[i]) { + ptn += hf->freq[i] * w; + maxbits = i; + } + } + if ((ptn & 0xffff) != 0 || maxbits > hf->tbl_bits) + return (0);/* Invalid */ + + hf->max_bits = maxbits; + + /* + * Cut out extra bits which we won't house in the table. + * This preparation reduces the same calculation in the for-loop + * making the table. + */ + if (maxbits < 16) { + int ebits = 16 - maxbits; + for (i = 1; i <= maxbits; i++) { + bitptn[i] >>= ebits; + 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<shift_bits = diffbits; + + /* + * Make the table. + */ + tbl_size = 1 << HTBL_BITS; + tbl = hf->tbl; + bitlen = hf->bitlen; + len_avail = hf->len_size; + hf->tree_used = 0; + 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]; + 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; + } + } + 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]; + 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)); +} + diff --cc Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c index c19614a,0000000..3541330 mode 100644,000000..100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_iso9660.c @@@ -1,3263 -1,0 +1,3265 @@@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2009 Andreas Henriksson + * Copyright (c) 2009-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_iso9660.c 201246 2009-12-30 05:30:35Z kientzle $"); + +#ifdef HAVE_ERRNO_H +#include +#endif +/* #include */ /* See archive_platform.h */ +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#include +#ifdef HAVE_ZLIB_H +#include +#endif + +#include "archive.h" +#include "archive_endian.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_private.h" +#include "archive_read_private.h" +#include "archive_string.h" + +/* + * An overview of ISO 9660 format: + * + * Each disk is laid out as follows: + * * 32k reserved for private use + * * Volume descriptor table. Each volume descriptor + * is 2k and specifies basic format information. + * The "Primary Volume Descriptor" (PVD) is defined by the + * standard and should always be present; other volume + * descriptors include various vendor-specific extensions. + * * Files and directories. Each file/dir is specified by + * an "extent" (starting sector and length in bytes). + * Dirs are just files with directory records packed one + * after another. The PVD contains a single dir entry + * specifying the location of the root directory. Everything + * else follows from there. + * + * This module works by first reading the volume descriptors, then + * building a list of directory entries, sorted by starting + * sector. At each step, I look for the earliest dir entry that + * hasn't yet been read, seek forward to that location and read + * that entry. If it's a dir, I slurp in the new dir entries and + * add them to the heap; if it's a regular file, I return the + * corresponding archive_entry and wait for the client to request + * the file body. This strategy allows us to read most compliant + * CDs with a single pass through the data, as required by libarchive. + */ +#define LOGICAL_BLOCK_SIZE 2048 +#define SYSTEM_AREA_BLOCK 16 + +/* Structure of on-disk primary volume descriptor. */ +#define PVD_type_offset 0 +#define PVD_type_size 1 +#define PVD_id_offset (PVD_type_offset + PVD_type_size) +#define PVD_id_size 5 +#define PVD_version_offset (PVD_id_offset + PVD_id_size) +#define PVD_version_size 1 +#define PVD_reserved1_offset (PVD_version_offset + PVD_version_size) +#define PVD_reserved1_size 1 +#define PVD_system_id_offset (PVD_reserved1_offset + PVD_reserved1_size) +#define PVD_system_id_size 32 +#define PVD_volume_id_offset (PVD_system_id_offset + PVD_system_id_size) +#define PVD_volume_id_size 32 +#define PVD_reserved2_offset (PVD_volume_id_offset + PVD_volume_id_size) +#define PVD_reserved2_size 8 +#define PVD_volume_space_size_offset (PVD_reserved2_offset + PVD_reserved2_size) +#define PVD_volume_space_size_size 8 +#define PVD_reserved3_offset (PVD_volume_space_size_offset + PVD_volume_space_size_size) +#define PVD_reserved3_size 32 +#define PVD_volume_set_size_offset (PVD_reserved3_offset + PVD_reserved3_size) +#define PVD_volume_set_size_size 4 +#define PVD_volume_sequence_number_offset (PVD_volume_set_size_offset + PVD_volume_set_size_size) +#define PVD_volume_sequence_number_size 4 +#define PVD_logical_block_size_offset (PVD_volume_sequence_number_offset + PVD_volume_sequence_number_size) +#define PVD_logical_block_size_size 4 +#define PVD_path_table_size_offset (PVD_logical_block_size_offset + PVD_logical_block_size_size) +#define PVD_path_table_size_size 8 +#define PVD_type_1_path_table_offset (PVD_path_table_size_offset + PVD_path_table_size_size) +#define PVD_type_1_path_table_size 4 +#define PVD_opt_type_1_path_table_offset (PVD_type_1_path_table_offset + PVD_type_1_path_table_size) +#define PVD_opt_type_1_path_table_size 4 +#define PVD_type_m_path_table_offset (PVD_opt_type_1_path_table_offset + PVD_opt_type_1_path_table_size) +#define PVD_type_m_path_table_size 4 +#define PVD_opt_type_m_path_table_offset (PVD_type_m_path_table_offset + PVD_type_m_path_table_size) +#define PVD_opt_type_m_path_table_size 4 +#define PVD_root_directory_record_offset (PVD_opt_type_m_path_table_offset + PVD_opt_type_m_path_table_size) +#define PVD_root_directory_record_size 34 +#define PVD_volume_set_id_offset (PVD_root_directory_record_offset + PVD_root_directory_record_size) +#define PVD_volume_set_id_size 128 +#define PVD_publisher_id_offset (PVD_volume_set_id_offset + PVD_volume_set_id_size) +#define PVD_publisher_id_size 128 +#define PVD_preparer_id_offset (PVD_publisher_id_offset + PVD_publisher_id_size) +#define PVD_preparer_id_size 128 +#define PVD_application_id_offset (PVD_preparer_id_offset + PVD_preparer_id_size) +#define PVD_application_id_size 128 +#define PVD_copyright_file_id_offset (PVD_application_id_offset + PVD_application_id_size) +#define PVD_copyright_file_id_size 37 +#define PVD_abstract_file_id_offset (PVD_copyright_file_id_offset + PVD_copyright_file_id_size) +#define PVD_abstract_file_id_size 37 +#define PVD_bibliographic_file_id_offset (PVD_abstract_file_id_offset + PVD_abstract_file_id_size) +#define PVD_bibliographic_file_id_size 37 +#define PVD_creation_date_offset (PVD_bibliographic_file_id_offset + PVD_bibliographic_file_id_size) +#define PVD_creation_date_size 17 +#define PVD_modification_date_offset (PVD_creation_date_offset + PVD_creation_date_size) +#define PVD_modification_date_size 17 +#define PVD_expiration_date_offset (PVD_modification_date_offset + PVD_modification_date_size) +#define PVD_expiration_date_size 17 +#define PVD_effective_date_offset (PVD_expiration_date_offset + PVD_expiration_date_size) +#define PVD_effective_date_size 17 +#define PVD_file_structure_version_offset (PVD_effective_date_offset + PVD_effective_date_size) +#define PVD_file_structure_version_size 1 +#define PVD_reserved4_offset (PVD_file_structure_version_offset + PVD_file_structure_version_size) +#define PVD_reserved4_size 1 +#define PVD_application_data_offset (PVD_reserved4_offset + PVD_reserved4_size) +#define PVD_application_data_size 512 +#define PVD_reserved5_offset (PVD_application_data_offset + PVD_application_data_size) +#define PVD_reserved5_size (2048 - PVD_reserved5_offset) + +/* TODO: It would make future maintenance easier to just hardcode the + * above values. In particular, ECMA119 states the offsets as part of + * the standard. That would eliminate the need for the following check.*/ +#if PVD_reserved5_offset != 1395 +#error PVD offset and size definitions are wrong. +#endif + + +/* Structure of optional on-disk supplementary volume descriptor. */ +#define SVD_type_offset 0 +#define SVD_type_size 1 +#define SVD_id_offset (SVD_type_offset + SVD_type_size) +#define SVD_id_size 5 +#define SVD_version_offset (SVD_id_offset + SVD_id_size) +#define SVD_version_size 1 +/* ... */ +#define SVD_reserved1_offset 72 +#define SVD_reserved1_size 8 +#define SVD_volume_space_size_offset 80 +#define SVD_volume_space_size_size 8 +#define SVD_escape_sequences_offset (SVD_volume_space_size_offset + SVD_volume_space_size_size) +#define SVD_escape_sequences_size 32 +/* ... */ +#define SVD_logical_block_size_offset 128 +#define SVD_logical_block_size_size 4 +#define SVD_type_L_path_table_offset 140 +#define SVD_type_M_path_table_offset 148 +/* ... */ +#define SVD_root_directory_record_offset 156 +#define SVD_root_directory_record_size 34 +#define SVD_file_structure_version_offset 881 +#define SVD_reserved2_offset 882 +#define SVD_reserved2_size 1 +#define SVD_reserved3_offset 1395 +#define SVD_reserved3_size 653 +/* ... */ +/* FIXME: validate correctness of last SVD entry offset. */ + +/* Structure of an on-disk directory record. */ +/* Note: ISO9660 stores each multi-byte integer twice, once in + * each byte order. The sizes here are the size of just one + * of the two integers. (This is why the offset of a field isn't + * the same as the offset+size of the previous field.) */ +#define DR_length_offset 0 +#define DR_length_size 1 +#define DR_ext_attr_length_offset 1 +#define DR_ext_attr_length_size 1 +#define DR_extent_offset 2 +#define DR_extent_size 4 +#define DR_size_offset 10 +#define DR_size_size 4 +#define DR_date_offset 18 +#define DR_date_size 7 +#define DR_flags_offset 25 +#define DR_flags_size 1 +#define DR_file_unit_size_offset 26 +#define DR_file_unit_size_size 1 +#define DR_interleave_offset 27 +#define DR_interleave_size 1 +#define DR_volume_sequence_number_offset 28 +#define DR_volume_sequence_number_size 2 +#define DR_name_len_offset 32 +#define DR_name_len_size 1 +#define DR_name_offset 33 + +#ifdef HAVE_ZLIB_H +static const unsigned char zisofs_magic[8] = { + 0x37, 0xE4, 0x53, 0x96, 0xC9, 0xDB, 0xD6, 0x07 +}; + +struct zisofs { + /* Set 1 if this file compressed by paged zlib */ + int pz; + int pz_log2_bs; /* Log2 of block size */ + uint64_t pz_uncompressed_size; + + int initialized; + unsigned char *uncompressed_buffer; + size_t uncompressed_buffer_size; + + uint32_t pz_offset; + unsigned char header[16]; + size_t header_avail; + int header_passed; + unsigned char *block_pointers; + size_t block_pointers_alloc; + size_t block_pointers_size; + size_t block_pointers_avail; + size_t block_off; + uint32_t block_avail; + + z_stream stream; + int stream_valid; +}; +#else +struct zisofs { + /* Set 1 if this file compressed by paged zlib */ + int pz; +}; +#endif + +struct content { + uint64_t offset;/* Offset on disk. */ + uint64_t size; /* File size in bytes. */ + struct content *next; +}; + +/* In-memory storage for a directory record. */ +struct file_info { + struct file_info *use_next; + struct file_info *parent; + struct file_info *next; + struct file_info *re_next; + int subdirs; + uint64_t key; /* Heap Key. */ + uint64_t offset; /* Offset on disk. */ + uint64_t size; /* File size in bytes. */ + uint32_t ce_offset; /* Offset of CE. */ + uint32_t ce_size; /* Size of CE. */ + char rr_moved; /* Flag to rr_moved. */ + char rr_moved_has_re_only; + char re; /* Having RRIP "RE" extension. */ + char re_descendant; + uint64_t cl_offset; /* Having RRIP "CL" extension. */ + int birthtime_is_set; + time_t birthtime; /* File created time. */ + time_t mtime; /* File last modified time. */ + time_t atime; /* File last accessed time. */ + time_t ctime; /* File attribute change time. */ + uint64_t rdev; /* Device number. */ + mode_t mode; + uid_t uid; + gid_t gid; + int64_t number; + int nlinks; + struct archive_string name; /* Pathname */ + unsigned char *utf16be_name; + size_t utf16be_bytes; + char name_continues; /* Non-zero if name continues */ + struct archive_string symlink; + char symlink_continues; /* Non-zero if link continues */ + /* Set 1 if this file compressed by paged zlib(zisofs) */ + int pz; + int pz_log2_bs; /* Log2 of block size */ + uint64_t pz_uncompressed_size; + /* Set 1 if this file is multi extent. */ + int multi_extent; + struct { + struct content *first; + struct content **last; + } contents; + struct { + struct file_info *first; + struct file_info **last; + } rede_files; +}; + +struct heap_queue { + struct file_info **files; + int allocated; + int used; +}; + +struct iso9660 { + int magic; +#define ISO9660_MAGIC 0x96609660 + + int opt_support_joliet; + int opt_support_rockridge; + + struct archive_string pathname; + char seenRockridge; /* Set true if RR extensions are used. */ - char seenSUSP; /* Set true if SUSP is beging used. */ ++ char seenSUSP; /* Set true if SUSP is being used. */ + char seenJoliet; + + unsigned char suspOffset; + struct file_info *rr_moved; + struct read_ce_queue { + struct read_ce_req { + uint64_t offset;/* Offset of CE on disk. */ + struct file_info *file; + } *reqs; + int cnt; + int allocated; + } read_ce_req; + + int64_t previous_number; + struct archive_string previous_pathname; + + struct file_info *use_files; + struct heap_queue pending_files; + struct { + struct file_info *first; + struct file_info **last; + } cache_files; + struct { + struct file_info *first; + struct file_info **last; + } re_files; + + uint64_t current_position; + ssize_t logical_block_size; + uint64_t volume_size; /* Total size of volume in bytes. */ + int32_t volume_block;/* Total size of volume in logical blocks. */ + + struct vd { + int location; /* Location of Extent. */ + uint32_t size; + } primary, joliet; + + int64_t entry_sparse_offset; + int64_t entry_bytes_remaining; + size_t entry_bytes_unconsumed; + struct zisofs entry_zisofs; + struct content *entry_content; + struct archive_string_conv *sconv_utf16be; + /* + * Buffers for a full pathname in UTF-16BE in Joliet extensions. + */ +#define UTF16_NAME_MAX 1024 + unsigned char *utf16be_path; + size_t utf16be_path_len; + unsigned char *utf16be_previous_path; + size_t utf16be_previous_path_len; - /* Null buufer used in bidder to improve its performance. */ ++ /* Null buffer used in bidder to improve its performance. */ + unsigned char null[2048]; +}; + +static int archive_read_format_iso9660_bid(struct archive_read *, int); +static int archive_read_format_iso9660_options(struct archive_read *, + const char *, const char *); +static int archive_read_format_iso9660_cleanup(struct archive_read *); +static int archive_read_format_iso9660_read_data(struct archive_read *, + const void **, size_t *, int64_t *); +static int archive_read_format_iso9660_read_data_skip(struct archive_read *); +static int archive_read_format_iso9660_read_header(struct archive_read *, + struct archive_entry *); +static const char *build_pathname(struct archive_string *, struct file_info *, int); +static int build_pathname_utf16be(unsigned char *, size_t, size_t *, + struct file_info *); +#if DEBUG +static void dump_isodirrec(FILE *, const unsigned char *isodirrec); +#endif +static time_t time_from_tm(struct tm *); +static time_t isodate17(const unsigned char *); +static time_t isodate7(const unsigned char *); +static int isBootRecord(struct iso9660 *, const unsigned char *); +static int isVolumePartition(struct iso9660 *, const unsigned char *); +static int isVDSetTerminator(struct iso9660 *, const unsigned char *); +static int isJolietSVD(struct iso9660 *, const unsigned char *); +static int isSVD(struct iso9660 *, const unsigned char *); +static int isEVD(struct iso9660 *, const unsigned char *); +static int isPVD(struct iso9660 *, const unsigned char *); +static int next_cache_entry(struct archive_read *, struct iso9660 *, + struct file_info **); +static int next_entry_seek(struct archive_read *, struct iso9660 *, + struct file_info **); +static struct file_info * + parse_file_info(struct archive_read *a, + struct file_info *parent, const unsigned char *isodirrec); +static int parse_rockridge(struct archive_read *a, + struct file_info *file, const unsigned char *start, + const unsigned char *end); +static int register_CE(struct archive_read *a, int32_t location, + struct file_info *file); +static int read_CE(struct archive_read *a, struct iso9660 *iso9660); +static void parse_rockridge_NM1(struct file_info *, + const unsigned char *, int); +static void parse_rockridge_SL1(struct file_info *, + const unsigned char *, int); +static void parse_rockridge_TF1(struct file_info *, + const unsigned char *, int); +static void parse_rockridge_ZF1(struct file_info *, + const unsigned char *, int); +static void register_file(struct iso9660 *, struct file_info *); +static void release_files(struct iso9660 *); +static unsigned toi(const void *p, int n); +static inline void re_add_entry(struct iso9660 *, struct file_info *); +static inline struct file_info * re_get_entry(struct iso9660 *); +static inline int rede_add_entry(struct file_info *); +static inline struct file_info * rede_get_entry(struct file_info *); +static inline void cache_add_entry(struct iso9660 *iso9660, + struct file_info *file); +static inline struct file_info *cache_get_entry(struct iso9660 *iso9660); +static int heap_add_entry(struct archive_read *a, struct heap_queue *heap, + struct file_info *file, uint64_t key); +static struct file_info *heap_get_entry(struct heap_queue *heap); + +#define add_entry(arch, iso9660, file) \ + heap_add_entry(arch, &((iso9660)->pending_files), file, file->offset) +#define next_entry(iso9660) \ + heap_get_entry(&((iso9660)->pending_files)) + +int +archive_read_support_format_iso9660(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct iso9660 *iso9660; + int r; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_format_iso9660"); + + iso9660 = (struct iso9660 *)calloc(1, sizeof(*iso9660)); + if (iso9660 == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate iso9660 data"); + return (ARCHIVE_FATAL); + } + iso9660->magic = ISO9660_MAGIC; + iso9660->cache_files.first = NULL; + iso9660->cache_files.last = &(iso9660->cache_files.first); + iso9660->re_files.first = NULL; + iso9660->re_files.last = &(iso9660->re_files.first); + /* Enable to support Joliet extensions by default. */ + iso9660->opt_support_joliet = 1; + /* Enable to support Rock Ridge extensions by default. */ + iso9660->opt_support_rockridge = 1; + + r = __archive_read_register_format(a, + iso9660, + "iso9660", + archive_read_format_iso9660_bid, + archive_read_format_iso9660_options, + archive_read_format_iso9660_read_header, + archive_read_format_iso9660_read_data, + archive_read_format_iso9660_read_data_skip, + NULL, + archive_read_format_iso9660_cleanup, + NULL, + NULL); + + if (r != ARCHIVE_OK) { + free(iso9660); + return (r); + } + return (ARCHIVE_OK); +} + + +static int +archive_read_format_iso9660_bid(struct archive_read *a, int best_bid) +{ + struct iso9660 *iso9660; + ssize_t bytes_read; + const unsigned char *p; + int seenTerminator; + + /* If there's already a better bid than we can ever + make, don't bother testing. */ + if (best_bid > 48) + return (-1); + + iso9660 = (struct iso9660 *)(a->format->data); + + /* + * Skip the first 32k (reserved area) and get the first + * 8 sectors of the volume descriptor table. Of course, + * if the I/O layer gives us more, we'll take it. + */ +#define RESERVED_AREA (SYSTEM_AREA_BLOCK * LOGICAL_BLOCK_SIZE) + p = __archive_read_ahead(a, + RESERVED_AREA + 8 * LOGICAL_BLOCK_SIZE, + &bytes_read); + if (p == NULL) + return (-1); + + /* Skip the reserved area. */ + bytes_read -= RESERVED_AREA; + p += RESERVED_AREA; + + /* Check each volume descriptor. */ + seenTerminator = 0; + for (; bytes_read > LOGICAL_BLOCK_SIZE; + bytes_read -= LOGICAL_BLOCK_SIZE, p += LOGICAL_BLOCK_SIZE) { + /* Do not handle undefined Volume Descriptor Type. */ + if (p[0] >= 4 && p[0] <= 254) + return (0); + /* Standard Identifier must be "CD001" */ + if (memcmp(p + 1, "CD001", 5) != 0) + return (0); + if (isPVD(iso9660, p)) + continue; + if (!iso9660->joliet.location) { + if (isJolietSVD(iso9660, p)) + continue; + } + if (isBootRecord(iso9660, p)) + continue; + if (isEVD(iso9660, p)) + continue; + if (isSVD(iso9660, p)) + continue; + if (isVolumePartition(iso9660, p)) + continue; + if (isVDSetTerminator(iso9660, p)) { + seenTerminator = 1; + break; + } + return (0); + } + /* + * ISO 9660 format must have Primary Volume Descriptor and + * Volume Descriptor Set Terminator. + */ + if (seenTerminator && iso9660->primary.location > 16) + return (48); + + /* We didn't find a valid PVD; return a bid of zero. */ + return (0); +} + +static int +archive_read_format_iso9660_options(struct archive_read *a, + const char *key, const char *val) +{ + struct iso9660 *iso9660; + + iso9660 = (struct iso9660 *)(a->format->data); + + if (strcmp(key, "joliet") == 0) { + if (val == NULL || strcmp(val, "off") == 0 || + strcmp(val, "ignore") == 0 || + strcmp(val, "disable") == 0 || + strcmp(val, "0") == 0) + iso9660->opt_support_joliet = 0; + else + iso9660->opt_support_joliet = 1; + return (ARCHIVE_OK); + } + if (strcmp(key, "rockridge") == 0 || + strcmp(key, "Rockridge") == 0) { + iso9660->opt_support_rockridge = val != NULL; + return (ARCHIVE_OK); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +static int +isNull(struct iso9660 *iso9660, const unsigned char *h, unsigned offset, +unsigned bytes) +{ + + while (bytes >= sizeof(iso9660->null)) { + if (!memcmp(iso9660->null, h + offset, sizeof(iso9660->null))) + return (0); + offset += sizeof(iso9660->null); + bytes -= sizeof(iso9660->null); + } + if (bytes) + return memcmp(iso9660->null, h + offset, bytes) == 0; + else + return (1); +} + +static int +isBootRecord(struct iso9660 *iso9660, const unsigned char *h) +{ + (void)iso9660; /* UNUSED */ + + /* Type of the Volume Descriptor Boot Record must be 0. */ + if (h[0] != 0) + return (0); + + /* Volume Descriptor Version must be 1. */ + if (h[6] != 1) + return (0); + + return (1); +} + +static int +isVolumePartition(struct iso9660 *iso9660, const unsigned char *h) +{ + int32_t location; + + /* Type of the Volume Partition Descriptor must be 3. */ + if (h[0] != 3) + return (0); + + /* Volume Descriptor Version must be 1. */ + if (h[6] != 1) + return (0); + /* Unused Field */ + if (h[7] != 0) + return (0); + + location = archive_le32dec(h + 72); + if (location <= SYSTEM_AREA_BLOCK || + location >= iso9660->volume_block) + return (0); + if ((uint32_t)location != archive_be32dec(h + 76)) + return (0); + + return (1); +} + +static int +isVDSetTerminator(struct iso9660 *iso9660, const unsigned char *h) +{ + (void)iso9660; /* UNUSED */ + + /* Type of the Volume Descriptor Set Terminator must be 255. */ + if (h[0] != 255) + return (0); + + /* Volume Descriptor Version must be 1. */ + if (h[6] != 1) + return (0); + + /* Reserved field must be 0. */ + if (!isNull(iso9660, h, 7, 2048-7)) + return (0); + + return (1); +} + +static int +isJolietSVD(struct iso9660 *iso9660, const unsigned char *h) +{ + const unsigned char *p; + ssize_t logical_block_size; + int32_t volume_block; + + /* Check if current sector is a kind of Supplementary Volume + * Descriptor. */ + if (!isSVD(iso9660, h)) + return (0); + + /* FIXME: do more validations according to joliet spec. */ + + /* check if this SVD contains joliet extension! */ + p = h + SVD_escape_sequences_offset; + /* N.B. Joliet spec says p[1] == '\\', but.... */ + if (p[0] == '%' && p[1] == '/') { + int level = 0; + + if (p[2] == '@') + level = 1; + else if (p[2] == 'C') + level = 2; + else if (p[2] == 'E') + level = 3; + else /* not joliet */ + return (0); + + iso9660->seenJoliet = level; + + } else /* not joliet */ + return (0); + + logical_block_size = + archive_le16dec(h + SVD_logical_block_size_offset); + volume_block = archive_le32dec(h + SVD_volume_space_size_offset); + + iso9660->logical_block_size = logical_block_size; + iso9660->volume_block = volume_block; + iso9660->volume_size = logical_block_size * (uint64_t)volume_block; + /* Read Root Directory Record in Volume Descriptor. */ + p = h + SVD_root_directory_record_offset; + iso9660->joliet.location = archive_le32dec(p + DR_extent_offset); + iso9660->joliet.size = archive_le32dec(p + DR_size_offset); + + return (48); +} + +static int +isSVD(struct iso9660 *iso9660, const unsigned char *h) +{ + const unsigned char *p; + ssize_t logical_block_size; + int32_t volume_block; + int32_t location; + + (void)iso9660; /* UNUSED */ + + /* Type 2 means it's a SVD. */ + if (h[SVD_type_offset] != 2) + return (0); + + /* Reserved field must be 0. */ + if (!isNull(iso9660, h, SVD_reserved1_offset, SVD_reserved1_size)) + return (0); + if (!isNull(iso9660, h, SVD_reserved2_offset, SVD_reserved2_size)) + return (0); + if (!isNull(iso9660, h, SVD_reserved3_offset, SVD_reserved3_size)) + return (0); + + /* File structure version must be 1 for ISO9660/ECMA119. */ + if (h[SVD_file_structure_version_offset] != 1) + return (0); + + logical_block_size = + archive_le16dec(h + SVD_logical_block_size_offset); + if (logical_block_size <= 0) + return (0); + + volume_block = archive_le32dec(h + SVD_volume_space_size_offset); + if (volume_block <= SYSTEM_AREA_BLOCK+4) + return (0); + + /* Location of Occurrence of Type L Path Table must be + * available location, + * >= SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */ + location = archive_le32dec(h+SVD_type_L_path_table_offset); + if (location < SYSTEM_AREA_BLOCK+2 || location >= volume_block) + return (0); + + /* The Type M Path Table must be at a valid location (WinISO + * and probably other programs omit this, so we allow zero) + * + * >= SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */ + location = archive_be32dec(h+SVD_type_M_path_table_offset); + if ((location > 0 && location < SYSTEM_AREA_BLOCK+2) + || location >= volume_block) + return (0); + + /* Read Root Directory Record in Volume Descriptor. */ + p = h + SVD_root_directory_record_offset; + if (p[DR_length_offset] != 34) + return (0); + + return (48); +} + +static int +isEVD(struct iso9660 *iso9660, const unsigned char *h) +{ + const unsigned char *p; + ssize_t logical_block_size; + int32_t volume_block; + int32_t location; + + (void)iso9660; /* UNUSED */ + + /* Type of the Enhanced Volume Descriptor must be 2. */ + if (h[PVD_type_offset] != 2) + return (0); + + /* EVD version must be 2. */ + if (h[PVD_version_offset] != 2) + return (0); + + /* Reserved field must be 0. */ + if (h[PVD_reserved1_offset] != 0) + return (0); + + /* Reserved field must be 0. */ + if (!isNull(iso9660, h, PVD_reserved2_offset, PVD_reserved2_size)) + return (0); + + /* Reserved field must be 0. */ + if (!isNull(iso9660, h, PVD_reserved3_offset, PVD_reserved3_size)) + return (0); + + /* Logical block size must be > 0. */ + /* I've looked at Ecma 119 and can't find any stronger + * restriction on this field. */ + logical_block_size = + archive_le16dec(h + PVD_logical_block_size_offset); + if (logical_block_size <= 0) + return (0); + + volume_block = + archive_le32dec(h + PVD_volume_space_size_offset); + if (volume_block <= SYSTEM_AREA_BLOCK+4) + return (0); + + /* File structure version must be 2 for ISO9660:1999. */ + if (h[PVD_file_structure_version_offset] != 2) + return (0); + + /* Location of Occurrence of Type L Path Table must be + * available location, + * >= SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */ + location = archive_le32dec(h+PVD_type_1_path_table_offset); + if (location < SYSTEM_AREA_BLOCK+2 || location >= volume_block) + return (0); + + /* Location of Occurrence of Type M Path Table must be + * available location, + * >= SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */ + location = archive_be32dec(h+PVD_type_m_path_table_offset); + if ((location > 0 && location < SYSTEM_AREA_BLOCK+2) + || location >= volume_block) + return (0); + + /* Reserved field must be 0. */ + if (!isNull(iso9660, h, PVD_reserved4_offset, PVD_reserved4_size)) + return (0); + + /* Reserved field must be 0. */ + if (!isNull(iso9660, h, PVD_reserved5_offset, PVD_reserved5_size)) + return (0); + + /* Read Root Directory Record in Volume Descriptor. */ + p = h + PVD_root_directory_record_offset; + if (p[DR_length_offset] != 34) + return (0); + + return (48); +} + +static int +isPVD(struct iso9660 *iso9660, const unsigned char *h) +{ + const unsigned char *p; + ssize_t logical_block_size; + int32_t volume_block; + int32_t location; + int i; + + /* Type of the Primary Volume Descriptor must be 1. */ + if (h[PVD_type_offset] != 1) + return (0); + + /* PVD version must be 1. */ + if (h[PVD_version_offset] != 1) + return (0); + + /* Reserved field must be 0. */ + if (h[PVD_reserved1_offset] != 0) + return (0); + + /* Reserved field must be 0. */ + if (!isNull(iso9660, h, PVD_reserved2_offset, PVD_reserved2_size)) + return (0); + + /* Reserved field must be 0. */ + if (!isNull(iso9660, h, PVD_reserved3_offset, PVD_reserved3_size)) + return (0); + + /* Logical block size must be > 0. */ + /* I've looked at Ecma 119 and can't find any stronger + * restriction on this field. */ + logical_block_size = + archive_le16dec(h + PVD_logical_block_size_offset); + if (logical_block_size <= 0) + return (0); + + volume_block = archive_le32dec(h + PVD_volume_space_size_offset); + if (volume_block <= SYSTEM_AREA_BLOCK+4) + return (0); + + /* File structure version must be 1 for ISO9660/ECMA119. */ + if (h[PVD_file_structure_version_offset] != 1) + return (0); + + /* Location of Occurrence of Type L Path Table must be + * available location, + * > SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */ + location = archive_le32dec(h+PVD_type_1_path_table_offset); + if (location < SYSTEM_AREA_BLOCK+2 || location >= volume_block) + return (0); + + /* The Type M Path Table must also be at a valid location + * (although ECMA 119 requires a Type M Path Table, WinISO and + * probably other programs omit it, so we permit a zero here) + * + * >= SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */ + location = archive_be32dec(h+PVD_type_m_path_table_offset); + if ((location > 0 && location < SYSTEM_AREA_BLOCK+2) + || location >= volume_block) + return (0); + + /* Reserved field must be 0. */ + /* But accept NetBSD/FreeBSD "makefs" images with 0x20 here. */ + for (i = 0; i < PVD_reserved4_size; ++i) + if (h[PVD_reserved4_offset + i] != 0 + && h[PVD_reserved4_offset + i] != 0x20) + return (0); + + /* Reserved field must be 0. */ + if (!isNull(iso9660, h, PVD_reserved5_offset, PVD_reserved5_size)) + return (0); + + /* XXX TODO: Check other values for sanity; reject more + * malformed PVDs. XXX */ + + /* Read Root Directory Record in Volume Descriptor. */ + p = h + PVD_root_directory_record_offset; + if (p[DR_length_offset] != 34) + return (0); + + if (!iso9660->primary.location) { + iso9660->logical_block_size = logical_block_size; + iso9660->volume_block = volume_block; + iso9660->volume_size = + logical_block_size * (uint64_t)volume_block; + iso9660->primary.location = + archive_le32dec(p + DR_extent_offset); + iso9660->primary.size = archive_le32dec(p + DR_size_offset); + } + + return (48); +} + +static int +read_children(struct archive_read *a, struct file_info *parent) +{ + struct iso9660 *iso9660; + const unsigned char *b, *p; + struct file_info *multi; + size_t step, skip_size; + + iso9660 = (struct iso9660 *)(a->format->data); + /* flush any remaining bytes from the last round to ensure + * we're positioned */ + if (iso9660->entry_bytes_unconsumed) { + __archive_read_consume(a, iso9660->entry_bytes_unconsumed); + iso9660->entry_bytes_unconsumed = 0; + } + if (iso9660->current_position > parent->offset) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Ignoring out-of-order directory (%s) %jd > %jd", + parent->name.s, + (intmax_t)iso9660->current_position, + (intmax_t)parent->offset); + return (ARCHIVE_WARN); + } + if (parent->offset + parent->size > iso9660->volume_size) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Directory is beyond end-of-media: %s", + parent->name.s); + return (ARCHIVE_WARN); + } + if (iso9660->current_position < parent->offset) { + int64_t skipsize; + + skipsize = parent->offset - iso9660->current_position; + skipsize = __archive_read_consume(a, skipsize); + if (skipsize < 0) + return ((int)skipsize); + iso9660->current_position = parent->offset; + } + + step = (size_t)(((parent->size + iso9660->logical_block_size -1) / + iso9660->logical_block_size) * iso9660->logical_block_size); + b = __archive_read_ahead(a, step, NULL); + if (b == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to read full block when scanning " + "ISO9660 directory list"); + return (ARCHIVE_FATAL); + } + iso9660->current_position += step; + multi = NULL; + skip_size = step; + while (step) { + p = b; + b += iso9660->logical_block_size; + step -= iso9660->logical_block_size; + for (; *p != 0 && p < b && p + *p <= b; p += *p) { + struct file_info *child; + + /* N.B.: these special directory identifiers + * are 8 bit "values" even on a + * Joliet CD with UCS-2 (16bit) encoding. + */ + + /* Skip '.' entry. */ + if (*(p + DR_name_len_offset) == 1 + && *(p + DR_name_offset) == '\0') + continue; + /* Skip '..' entry. */ + if (*(p + DR_name_len_offset) == 1 + && *(p + DR_name_offset) == '\001') + continue; + child = parse_file_info(a, parent, p); + if (child == NULL) { + __archive_read_consume(a, skip_size); + return (ARCHIVE_FATAL); + } + if (child->cl_offset == 0 && + (child->multi_extent || multi != NULL)) { + struct content *con; + + if (multi == NULL) { + multi = child; + multi->contents.first = NULL; + multi->contents.last = + &(multi->contents.first); + } + con = malloc(sizeof(struct content)); + if (con == NULL) { + archive_set_error( + &a->archive, ENOMEM, + "No memory for multi extent"); + __archive_read_consume(a, skip_size); + return (ARCHIVE_FATAL); + } + con->offset = child->offset; + con->size = child->size; + con->next = NULL; + *multi->contents.last = con; + multi->contents.last = &(con->next); + if (multi == child) { + if (add_entry(a, iso9660, child) + != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } else { + multi->size += child->size; + if (!child->multi_extent) + multi = NULL; + } + } else + if (add_entry(a, iso9660, child) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + } + + __archive_read_consume(a, skip_size); + + /* Read data which recorded by RRIP "CE" extension. */ + if (read_CE(a, iso9660) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + return (ARCHIVE_OK); +} + +static int +choose_volume(struct archive_read *a, struct iso9660 *iso9660) +{ + struct file_info *file; + int64_t skipsize; + struct vd *vd; + const void *block; + char seenJoliet; + + vd = &(iso9660->primary); + if (!iso9660->opt_support_joliet) + iso9660->seenJoliet = 0; + if (iso9660->seenJoliet && + vd->location > iso9660->joliet.location) + /* This condition is unlikely; by way of caution. */ + vd = &(iso9660->joliet); + + skipsize = LOGICAL_BLOCK_SIZE * (int64_t)vd->location; + skipsize = __archive_read_consume(a, skipsize); + if (skipsize < 0) + return ((int)skipsize); + iso9660->current_position = skipsize; + + block = __archive_read_ahead(a, vd->size, NULL); + if (block == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to read full block when scanning " + "ISO9660 directory list"); + return (ARCHIVE_FATAL); + } + + /* + * While reading Root Directory, flag seenJoliet must be zero to + * avoid converting special name 0x00(Current Directory) and + * next byte to UCS2. + */ + seenJoliet = iso9660->seenJoliet;/* Save flag. */ + iso9660->seenJoliet = 0; + file = parse_file_info(a, NULL, block); + if (file == NULL) + return (ARCHIVE_FATAL); + iso9660->seenJoliet = seenJoliet; + + /* + * If the iso image has both RockRidge and Joliet, we preferentially + * use RockRidge Extensions rather than Joliet ones. + */ + if (vd == &(iso9660->primary) && iso9660->seenRockridge + && iso9660->seenJoliet) + iso9660->seenJoliet = 0; + + if (vd == &(iso9660->primary) && !iso9660->seenRockridge + && iso9660->seenJoliet) { + /* Switch reading data from primary to joliet. */ + vd = &(iso9660->joliet); + skipsize = LOGICAL_BLOCK_SIZE * (int64_t)vd->location; + skipsize -= iso9660->current_position; + skipsize = __archive_read_consume(a, skipsize); + if (skipsize < 0) + return ((int)skipsize); + iso9660->current_position += skipsize; + + block = __archive_read_ahead(a, vd->size, NULL); + if (block == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to read full block when scanning " + "ISO9660 directory list"); + return (ARCHIVE_FATAL); + } + iso9660->seenJoliet = 0; + file = parse_file_info(a, NULL, block); + if (file == NULL) + return (ARCHIVE_FATAL); + iso9660->seenJoliet = seenJoliet; + } + + /* Store the root directory in the pending list. */ + if (add_entry(a, iso9660, file) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + if (iso9660->seenRockridge) { + a->archive.archive_format = ARCHIVE_FORMAT_ISO9660_ROCKRIDGE; + a->archive.archive_format_name = + "ISO9660 with Rockridge extensions"; + } + + return (ARCHIVE_OK); +} + +static int +archive_read_format_iso9660_read_header(struct archive_read *a, + struct archive_entry *entry) +{ + struct iso9660 *iso9660; + struct file_info *file; + int r, rd_r = ARCHIVE_OK; + + iso9660 = (struct iso9660 *)(a->format->data); + + if (!a->archive.archive_format) { + a->archive.archive_format = ARCHIVE_FORMAT_ISO9660; + a->archive.archive_format_name = "ISO9660"; + } + + if (iso9660->current_position == 0) { + r = choose_volume(a, iso9660); + if (r != ARCHIVE_OK) + return (r); + } + + file = NULL;/* Eliminate a warning. */ + /* Get the next entry that appears after the current offset. */ + r = next_entry_seek(a, iso9660, &file); + if (r != ARCHIVE_OK) + return (r); + + if (iso9660->seenJoliet) { + /* + * Convert UTF-16BE of a filename to local locale MBS + * and store the result into a filename field. + */ + if (iso9660->sconv_utf16be == NULL) { + iso9660->sconv_utf16be = + archive_string_conversion_from_charset( + &(a->archive), "UTF-16BE", 1); + if (iso9660->sconv_utf16be == NULL) - /* Coundn't allocate memory */ ++ /* Couldn't allocate memory */ + return (ARCHIVE_FATAL); + } + if (iso9660->utf16be_path == NULL) { + iso9660->utf16be_path = malloc(UTF16_NAME_MAX); + if (iso9660->utf16be_path == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory"); + return (ARCHIVE_FATAL); + } + } + if (iso9660->utf16be_previous_path == NULL) { + iso9660->utf16be_previous_path = malloc(UTF16_NAME_MAX); + if (iso9660->utf16be_previous_path == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory"); + return (ARCHIVE_FATAL); + } + } + + iso9660->utf16be_path_len = 0; + if (build_pathname_utf16be(iso9660->utf16be_path, + UTF16_NAME_MAX, &(iso9660->utf16be_path_len), file) != 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Pathname is too long"); + return (ARCHIVE_FATAL); + } + + r = archive_entry_copy_pathname_l(entry, + (const char *)iso9660->utf16be_path, + iso9660->utf16be_path_len, + iso9660->sconv_utf16be); + if (r != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "No memory for Pathname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Pathname cannot be converted " + "from %s to current locale.", + archive_string_conversion_charset_name( + iso9660->sconv_utf16be)); + + rd_r = ARCHIVE_WARN; + } + } else { + const char *path = build_pathname(&iso9660->pathname, file, 0); + if (path == NULL) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Pathname is too long"); + return (ARCHIVE_FATAL); + } else { + archive_string_empty(&iso9660->pathname); + archive_entry_set_pathname(entry, path); + } + } + + iso9660->entry_bytes_remaining = file->size; + /* Offset for sparse-file-aware clients. */ + iso9660->entry_sparse_offset = 0; + + if (file->offset + file->size > iso9660->volume_size) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "File is beyond end-of-media: %s", + archive_entry_pathname(entry)); + iso9660->entry_bytes_remaining = 0; + return (ARCHIVE_WARN); + } + + /* Set up the entry structure with information about this entry. */ + archive_entry_set_mode(entry, file->mode); + archive_entry_set_uid(entry, file->uid); + archive_entry_set_gid(entry, file->gid); + archive_entry_set_nlink(entry, file->nlinks); + if (file->birthtime_is_set) + archive_entry_set_birthtime(entry, file->birthtime, 0); + else + archive_entry_unset_birthtime(entry); + archive_entry_set_mtime(entry, file->mtime, 0); + archive_entry_set_ctime(entry, file->ctime, 0); + archive_entry_set_atime(entry, file->atime, 0); + /* N.B.: Rock Ridge supports 64-bit device numbers. */ + archive_entry_set_rdev(entry, (dev_t)file->rdev); + archive_entry_set_size(entry, iso9660->entry_bytes_remaining); + if (file->symlink.s != NULL) + archive_entry_copy_symlink(entry, file->symlink.s); + + /* Note: If the input isn't seekable, we can't rewind to + * return the same body again, so if the next entry refers to + * the same data, we have to return it as a hardlink to the + * original entry. */ + if (file->number != -1 && + file->number == iso9660->previous_number) { + if (iso9660->seenJoliet) { + r = archive_entry_copy_hardlink_l(entry, + (const char *)iso9660->utf16be_previous_path, + iso9660->utf16be_previous_path_len, + iso9660->sconv_utf16be); + if (r != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "No memory for Linkname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Linkname cannot be converted " + "from %s to current locale.", + archive_string_conversion_charset_name( + iso9660->sconv_utf16be)); + rd_r = ARCHIVE_WARN; + } + } else + archive_entry_set_hardlink(entry, + iso9660->previous_pathname.s); + archive_entry_unset_size(entry); + iso9660->entry_bytes_remaining = 0; + return (rd_r); + } + + if ((file->mode & AE_IFMT) != AE_IFDIR && + file->offset < iso9660->current_position) { + int64_t r64; + + r64 = __archive_read_seek(a, file->offset, SEEK_SET); + if (r64 != (int64_t)file->offset) { + /* We can't seek backwards to extract it, so issue + * a warning. Note that this can only happen if + * this entry was added to the heap after we passed + * this offset, that is, only if the directory + * mentioning this entry is later than the body of + * the entry. Such layouts are very unusual; most + * ISO9660 writers lay out and record all directory + * information first, then store all file bodies. */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Ignoring out-of-order file @%jx (%s) %jd < %jd", + (intmax_t)file->number, + iso9660->pathname.s, + (intmax_t)file->offset, + (intmax_t)iso9660->current_position); + iso9660->entry_bytes_remaining = 0; + return (ARCHIVE_WARN); + } + iso9660->current_position = (uint64_t)r64; + } + + /* Initialize zisofs variables. */ + iso9660->entry_zisofs.pz = file->pz; + if (file->pz) { +#ifdef HAVE_ZLIB_H + struct zisofs *zisofs; + + zisofs = &iso9660->entry_zisofs; + zisofs->initialized = 0; + zisofs->pz_log2_bs = file->pz_log2_bs; + zisofs->pz_uncompressed_size = file->pz_uncompressed_size; + zisofs->pz_offset = 0; + zisofs->header_avail = 0; + zisofs->header_passed = 0; + zisofs->block_pointers_avail = 0; +#endif + archive_entry_set_size(entry, file->pz_uncompressed_size); + } + + iso9660->previous_number = file->number; + if (iso9660->seenJoliet) { + memcpy(iso9660->utf16be_previous_path, iso9660->utf16be_path, + iso9660->utf16be_path_len); + iso9660->utf16be_previous_path_len = iso9660->utf16be_path_len; + } else + archive_strcpy( + &iso9660->previous_pathname, iso9660->pathname.s); + + /* Reset entry_bytes_remaining if the file is multi extent. */ + iso9660->entry_content = file->contents.first; + if (iso9660->entry_content != NULL) + iso9660->entry_bytes_remaining = iso9660->entry_content->size; + + if (archive_entry_filetype(entry) == AE_IFDIR) { + /* Overwrite nlinks by proper link number which is + * calculated from number of sub directories. */ + archive_entry_set_nlink(entry, 2 + file->subdirs); + /* Directory data has been read completely. */ + iso9660->entry_bytes_remaining = 0; + } + + if (rd_r != ARCHIVE_OK) + return (rd_r); + return (ARCHIVE_OK); +} + +static int +archive_read_format_iso9660_read_data_skip(struct archive_read *a) +{ + /* Because read_next_header always does an explicit skip + * to the next entry, we don't need to do anything here. */ + (void)a; /* UNUSED */ + return (ARCHIVE_OK); +} + +#ifdef HAVE_ZLIB_H + +static int +zisofs_read_data(struct archive_read *a, + const void **buff, size_t *size, int64_t *offset) +{ + struct iso9660 *iso9660; + struct zisofs *zisofs; + const unsigned char *p; + size_t avail; + ssize_t bytes_read; + size_t uncompressed_size; + int r; + + iso9660 = (struct iso9660 *)(a->format->data); + zisofs = &iso9660->entry_zisofs; + + p = __archive_read_ahead(a, 1, &bytes_read); + if (bytes_read <= 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated zisofs file body"); + return (ARCHIVE_FATAL); + } + if (bytes_read > iso9660->entry_bytes_remaining) + bytes_read = (ssize_t)iso9660->entry_bytes_remaining; + avail = bytes_read; + uncompressed_size = 0; + + if (!zisofs->initialized) { + size_t ceil, xsize; + + /* Allocate block pointers buffer. */ + ceil = (size_t)((zisofs->pz_uncompressed_size + + (((int64_t)1) << zisofs->pz_log2_bs) - 1) + >> zisofs->pz_log2_bs); + xsize = (ceil + 1) * 4; + if (zisofs->block_pointers_alloc < xsize) { + size_t alloc; + + if (zisofs->block_pointers != NULL) + free(zisofs->block_pointers); + alloc = ((xsize >> 10) + 1) << 10; + zisofs->block_pointers = malloc(alloc); + if (zisofs->block_pointers == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory for zisofs decompression"); + return (ARCHIVE_FATAL); + } + zisofs->block_pointers_alloc = alloc; + } + zisofs->block_pointers_size = xsize; + + /* Allocate uncompressed data buffer. */ + xsize = (size_t)1UL << zisofs->pz_log2_bs; + if (zisofs->uncompressed_buffer_size < xsize) { + if (zisofs->uncompressed_buffer != NULL) + free(zisofs->uncompressed_buffer); + zisofs->uncompressed_buffer = malloc(xsize); + if (zisofs->uncompressed_buffer == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory for zisofs decompression"); + return (ARCHIVE_FATAL); + } + } + zisofs->uncompressed_buffer_size = xsize; + + /* + * Read the file header, and check the magic code of zisofs. + */ + if (zisofs->header_avail < sizeof(zisofs->header)) { + xsize = sizeof(zisofs->header) - zisofs->header_avail; + if (avail < xsize) + xsize = avail; + memcpy(zisofs->header + zisofs->header_avail, p, xsize); + zisofs->header_avail += xsize; + avail -= xsize; + p += xsize; + } + if (!zisofs->header_passed && + zisofs->header_avail == sizeof(zisofs->header)) { + int err = 0; + + if (memcmp(zisofs->header, zisofs_magic, + sizeof(zisofs_magic)) != 0) + err = 1; + if (archive_le32dec(zisofs->header + 8) + != zisofs->pz_uncompressed_size) + err = 1; + if (zisofs->header[12] != 4) + err = 1; + if (zisofs->header[13] != zisofs->pz_log2_bs) + err = 1; + if (err) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Illegal zisofs file body"); + return (ARCHIVE_FATAL); + } + zisofs->header_passed = 1; + } + /* + * Read block pointers. + */ + if (zisofs->header_passed && + zisofs->block_pointers_avail < zisofs->block_pointers_size) { + xsize = zisofs->block_pointers_size + - zisofs->block_pointers_avail; + if (avail < xsize) + xsize = avail; + memcpy(zisofs->block_pointers + + zisofs->block_pointers_avail, p, xsize); + zisofs->block_pointers_avail += xsize; + avail -= xsize; + p += xsize; + if (zisofs->block_pointers_avail + == zisofs->block_pointers_size) { + /* We've got all block pointers and initialize + * related variables. */ + zisofs->block_off = 0; + zisofs->block_avail = 0; + /* Complete a initialization */ + zisofs->initialized = 1; + } + } + + if (!zisofs->initialized) + goto next_data; /* We need more data. */ + } + + /* + * Get block offsets from block pointers. + */ + if (zisofs->block_avail == 0) { + uint32_t bst, bed; + + if (zisofs->block_off + 4 >= zisofs->block_pointers_size) { + /* There isn't a pair of offsets. */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Illegal zisofs block pointers"); + return (ARCHIVE_FATAL); + } + bst = archive_le32dec( + zisofs->block_pointers + zisofs->block_off); + if (bst != zisofs->pz_offset + (bytes_read - avail)) { + /* TODO: Should we seek offset of current file + * by bst ? */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Illegal zisofs block pointers(cannot seek)"); + return (ARCHIVE_FATAL); + } + bed = archive_le32dec( + zisofs->block_pointers + zisofs->block_off + 4); + if (bed < bst) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Illegal zisofs block pointers"); + return (ARCHIVE_FATAL); + } + zisofs->block_avail = bed - bst; + zisofs->block_off += 4; + + /* Initialize compression library for new block. */ + if (zisofs->stream_valid) + r = inflateReset(&zisofs->stream); + else + r = inflateInit(&zisofs->stream); + if (r != Z_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can't initialize zisofs decompression."); + return (ARCHIVE_FATAL); + } + zisofs->stream_valid = 1; + zisofs->stream.total_in = 0; + zisofs->stream.total_out = 0; + } + + /* + * Make uncompressed data. + */ + if (zisofs->block_avail == 0) { + memset(zisofs->uncompressed_buffer, 0, + zisofs->uncompressed_buffer_size); + uncompressed_size = zisofs->uncompressed_buffer_size; + } else { + zisofs->stream.next_in = (Bytef *)(uintptr_t)(const void *)p; + if (avail > zisofs->block_avail) + zisofs->stream.avail_in = zisofs->block_avail; + else + zisofs->stream.avail_in = (uInt)avail; + zisofs->stream.next_out = zisofs->uncompressed_buffer; + zisofs->stream.avail_out = + (uInt)zisofs->uncompressed_buffer_size; + + r = inflate(&zisofs->stream, 0); + switch (r) { + case Z_OK: /* Decompressor made some progress.*/ + case Z_STREAM_END: /* Found end of stream. */ + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "zisofs decompression failed (%d)", r); + return (ARCHIVE_FATAL); + } + uncompressed_size = + zisofs->uncompressed_buffer_size - zisofs->stream.avail_out; + avail -= zisofs->stream.next_in - p; + zisofs->block_avail -= (uint32_t)(zisofs->stream.next_in - p); + } +next_data: + bytes_read -= avail; + *buff = zisofs->uncompressed_buffer; + *size = uncompressed_size; + *offset = iso9660->entry_sparse_offset; + iso9660->entry_sparse_offset += uncompressed_size; + iso9660->entry_bytes_remaining -= bytes_read; + iso9660->current_position += bytes_read; + zisofs->pz_offset += (uint32_t)bytes_read; + iso9660->entry_bytes_unconsumed += bytes_read; + + return (ARCHIVE_OK); +} + +#else /* HAVE_ZLIB_H */ + +static int +zisofs_read_data(struct archive_read *a, + const void **buff, size_t *size, int64_t *offset) +{ + + (void)buff;/* UNUSED */ + (void)size;/* UNUSED */ + (void)offset;/* UNUSED */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "zisofs is not supported on this platform."); + return (ARCHIVE_FAILED); +} + +#endif /* HAVE_ZLIB_H */ + +static int +archive_read_format_iso9660_read_data(struct archive_read *a, + const void **buff, size_t *size, int64_t *offset) +{ + ssize_t bytes_read; + struct iso9660 *iso9660; + + iso9660 = (struct iso9660 *)(a->format->data); + + if (iso9660->entry_bytes_unconsumed) { + __archive_read_consume(a, iso9660->entry_bytes_unconsumed); + iso9660->entry_bytes_unconsumed = 0; + } + + if (iso9660->entry_bytes_remaining <= 0) { + if (iso9660->entry_content != NULL) + iso9660->entry_content = iso9660->entry_content->next; + if (iso9660->entry_content == NULL) { + *buff = NULL; + *size = 0; + *offset = iso9660->entry_sparse_offset; + return (ARCHIVE_EOF); + } + /* Seek forward to the start of the entry. */ + if (iso9660->current_position < iso9660->entry_content->offset) { + int64_t step; + + step = iso9660->entry_content->offset - + iso9660->current_position; + step = __archive_read_consume(a, step); + if (step < 0) + return ((int)step); + iso9660->current_position = + iso9660->entry_content->offset; + } + if (iso9660->entry_content->offset < iso9660->current_position) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Ignoring out-of-order file (%s) %jd < %jd", + iso9660->pathname.s, + (intmax_t)iso9660->entry_content->offset, + (intmax_t)iso9660->current_position); + *buff = NULL; + *size = 0; + *offset = iso9660->entry_sparse_offset; + return (ARCHIVE_WARN); + } + iso9660->entry_bytes_remaining = iso9660->entry_content->size; + } + if (iso9660->entry_zisofs.pz) + return (zisofs_read_data(a, buff, size, offset)); + + *buff = __archive_read_ahead(a, 1, &bytes_read); + if (bytes_read == 0) + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Truncated input file"); + if (*buff == NULL) + return (ARCHIVE_FATAL); + if (bytes_read > iso9660->entry_bytes_remaining) + bytes_read = (ssize_t)iso9660->entry_bytes_remaining; + *size = bytes_read; + *offset = iso9660->entry_sparse_offset; + iso9660->entry_sparse_offset += bytes_read; + iso9660->entry_bytes_remaining -= bytes_read; + iso9660->entry_bytes_unconsumed = bytes_read; + iso9660->current_position += bytes_read; + return (ARCHIVE_OK); +} + +static int +archive_read_format_iso9660_cleanup(struct archive_read *a) +{ + struct iso9660 *iso9660; + int r = ARCHIVE_OK; + + iso9660 = (struct iso9660 *)(a->format->data); + release_files(iso9660); + free(iso9660->read_ce_req.reqs); + archive_string_free(&iso9660->pathname); + archive_string_free(&iso9660->previous_pathname); + if (iso9660->pending_files.files) + free(iso9660->pending_files.files); +#ifdef HAVE_ZLIB_H + free(iso9660->entry_zisofs.uncompressed_buffer); + free(iso9660->entry_zisofs.block_pointers); + if (iso9660->entry_zisofs.stream_valid) { + if (inflateEnd(&iso9660->entry_zisofs.stream) != Z_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to clean up zlib decompressor"); + r = ARCHIVE_FATAL; + } + } +#endif + free(iso9660->utf16be_path); + free(iso9660->utf16be_previous_path); + free(iso9660); + (a->format->data) = NULL; + return (r); +} + +/* + * This routine parses a single ISO directory record, makes sense + * of any extensions, and stores the result in memory. + */ +static struct file_info * +parse_file_info(struct archive_read *a, struct file_info *parent, + const unsigned char *isodirrec) +{ + struct iso9660 *iso9660; + struct file_info *file, *filep; + size_t name_len; + const unsigned char *rr_start, *rr_end; + const unsigned char *p; + size_t dr_len; + uint64_t fsize, offset; + int32_t location; + int flags; + + iso9660 = (struct iso9660 *)(a->format->data); + + dr_len = (size_t)isodirrec[DR_length_offset]; + name_len = (size_t)isodirrec[DR_name_len_offset]; + location = archive_le32dec(isodirrec + DR_extent_offset); + fsize = toi(isodirrec + DR_size_offset, DR_size_size); + /* Sanity check that dr_len needs at least 34. */ + if (dr_len < 34) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid length of directory record"); + return (NULL); + } + /* Sanity check that name_len doesn't exceed dr_len. */ + if (dr_len - 33 < name_len || name_len == 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid length of file identifier"); + return (NULL); + } + /* Sanity check that location doesn't exceed volume block. + * Don't check lower limit of location; it's possibility + * the location has negative value when file type is symbolic + * link or file size is zero. As far as I know latest mkisofs + * do that. + */ + if (location > 0 && + (location + ((fsize + iso9660->logical_block_size -1) + / iso9660->logical_block_size)) + > (uint32_t)iso9660->volume_block) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid location of extent of file"); + return (NULL); + } + /* Sanity check that location doesn't have a negative value + * when the file is not empty. it's too large. */ + if (fsize != 0 && location < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid location of extent of file"); + return (NULL); + } + + /* Sanity check that this entry does not create a cycle. */ + offset = iso9660->logical_block_size * (uint64_t)location; + for (filep = parent; filep != NULL; filep = filep->parent) { + if (filep->offset == offset) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Directory structure contains loop"); + return (NULL); + } + } + + /* Create a new file entry and copy data from the ISO dir record. */ + file = (struct file_info *)calloc(1, sizeof(*file)); + if (file == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory for file entry"); + return (NULL); + } + file->parent = parent; + file->offset = offset; + file->size = fsize; + file->mtime = isodate7(isodirrec + DR_date_offset); + file->ctime = file->atime = file->mtime; + file->rede_files.first = NULL; + file->rede_files.last = &(file->rede_files.first); + + p = isodirrec + DR_name_offset; + /* Rockridge extensions (if any) follow name. Compute this + * before fidgeting the name_len below. */ + rr_start = p + name_len + (name_len & 1 ? 0 : 1); + rr_end = isodirrec + dr_len; + + if (iso9660->seenJoliet) { + /* Joliet names are max 64 chars (128 bytes) according to spec, + * but genisoimage/mkisofs allows recording longer Joliet + * names which are 103 UCS2 characters(206 bytes) by their + * option '-joliet-long'. + */ + if (name_len > 206) + name_len = 206; + name_len &= ~1; + + /* trim trailing first version and dot from filename. + * + * Remember we were in UTF-16BE land! + * SEPARATOR 1 (.) and SEPARATOR 2 (;) are both + * 16 bits big endian characters on Joliet. + * + * TODO: sanitize filename? + * Joliet allows any UCS-2 char except: + * *, /, :, ;, ? and \. + */ + /* Chop off trailing ';1' from files. */ + if (name_len > 4 && p[name_len-4] == 0 && p[name_len-3] == ';' + && p[name_len-2] == 0 && p[name_len-1] == '1') + name_len -= 4; +#if 0 /* XXX: this somehow manages to strip of single-character file extensions, like '.c'. */ + /* Chop off trailing '.' from filenames. */ + if (name_len > 2 && p[name_len-2] == 0 && p[name_len-1] == '.') + name_len -= 2; +#endif + if ((file->utf16be_name = malloc(name_len)) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory for file name"); - return (NULL); ++ goto fail; + } + memcpy(file->utf16be_name, p, name_len); + file->utf16be_bytes = name_len; + } else { + /* Chop off trailing ';1' from files. */ + if (name_len > 2 && p[name_len - 2] == ';' && + p[name_len - 1] == '1') + name_len -= 2; + /* Chop off trailing '.' from filenames. */ + if (name_len > 1 && p[name_len - 1] == '.') + --name_len; + + archive_strncpy(&file->name, (const char *)p, name_len); + } + + flags = isodirrec[DR_flags_offset]; + if (flags & 0x02) + file->mode = AE_IFDIR | 0700; + else + file->mode = AE_IFREG | 0400; + if (flags & 0x80) + file->multi_extent = 1; + else + file->multi_extent = 0; + /* + * Use a location for the file number, which is treated as an inode + * number to find out hardlink target. If Rockridge extensions is + * being used, the file number will be overwritten by FILE SERIAL + * NUMBER of RRIP "PX" extension. + * Note: Old mkisofs did not record that FILE SERIAL NUMBER + * in ISO images. + * Note2: xorriso set 0 to the location of a symlink file. + */ + if (file->size == 0 && location >= 0) { + /* If file->size is zero, its location points wrong place, + * and so we should not use it for the file number. + * When the location has negative value, it can be used + * for the file number. + */ + file->number = -1; + /* Do not appear before any directory entries. */ + file->offset = -1; + } else + file->number = (int64_t)(uint32_t)location; + + /* Rockridge extensions overwrite information from above. */ + if (iso9660->opt_support_rockridge) { + if (parent == NULL && rr_end - rr_start >= 7) { + p = rr_start; + if (memcmp(p, "SP\x07\x01\xbe\xef", 6) == 0) { + /* + * SP extension stores the suspOffset + * (Number of bytes to skip between + * filename and SUSP records.) + * It is mandatory by the SUSP standard + * (IEEE 1281). + * + * It allows SUSP to coexist with + * non-SUSP uses of the System + * Use Area by placing non-SUSP data + * before SUSP data. + * + * SP extension must be in the root + * directory entry, disable all SUSP + * processing if not found. + */ + iso9660->suspOffset = p[6]; + iso9660->seenSUSP = 1; + rr_start += 7; + } + } + if (iso9660->seenSUSP) { + int r; + + file->name_continues = 0; + file->symlink_continues = 0; + rr_start += iso9660->suspOffset; + r = parse_rockridge(a, file, rr_start, rr_end); - if (r != ARCHIVE_OK) { - free(file); - return (NULL); - } ++ if (r != ARCHIVE_OK) ++ goto fail; + /* + * A file size of symbolic link files in ISO images + * made by makefs is not zero and its location is + * the same as those of next regular file. That is + * the same as hard like file and it causes unexpected + * error. + */ + if (file->size > 0 && + (file->mode & AE_IFMT) == AE_IFLNK) { + file->size = 0; + file->number = -1; + file->offset = -1; + } + } else + /* If there isn't SUSP, disable parsing + * rock ridge extensions. */ + iso9660->opt_support_rockridge = 0; + } + + file->nlinks = 1;/* Reset nlink. we'll calculate it later. */ + /* Tell file's parent how many children that parent has. */ + if (parent != NULL && (flags & 0x02)) + parent->subdirs++; + + if (iso9660->seenRockridge) { + if (parent != NULL && parent->parent == NULL && + (flags & 0x02) && iso9660->rr_moved == NULL && + file->name.s && + (strcmp(file->name.s, "rr_moved") == 0 || + strcmp(file->name.s, ".rr_moved") == 0)) { + iso9660->rr_moved = file; + file->rr_moved = 1; + file->rr_moved_has_re_only = 1; + file->re = 0; + parent->subdirs--; + } else if (file->re) { + /* + * Sanity check: file's parent is rr_moved. + */ + if (parent == NULL || parent->rr_moved == 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Invalid Rockridge RE"); - return (NULL); ++ goto fail; + } + /* + * Sanity check: file does not have "CL" extension. + */ + if (file->cl_offset) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Invalid Rockridge RE and CL"); - return (NULL); ++ goto fail; + } + /* + * Sanity check: The file type must be a directory. + */ + if ((flags & 0x02) == 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Invalid Rockridge RE"); - return (NULL); ++ goto fail; + } + } else if (parent != NULL && parent->rr_moved) + file->rr_moved_has_re_only = 0; + else if (parent != NULL && (flags & 0x02) && + (parent->re || parent->re_descendant)) + file->re_descendant = 1; + if (file->cl_offset) { + struct file_info *r; + + if (parent == NULL || parent->parent == NULL) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Invalid Rockridge CL"); - return (NULL); ++ goto fail; + } + /* + * Sanity check: The file type must be a regular file. + */ + if ((flags & 0x02) != 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Invalid Rockridge CL"); - return (NULL); ++ goto fail; + } + parent->subdirs++; + /* Overwrite an offset and a number of this "CL" entry + * to appear before other dirs. "+1" to those is to + * make sure to appear after "RE" entry which this + * "CL" entry should be connected with. */ + file->offset = file->number = file->cl_offset + 1; + + /* + * Sanity check: cl_offset does not point at its + * the parents or itself. + */ + for (r = parent; r; r = r->parent) { + if (r->offset == file->cl_offset) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Invalid Rockridge CL"); - return (NULL); ++ goto fail; + } + } + if (file->cl_offset == file->offset || + parent->rr_moved) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Invalid Rockridge CL"); - return (NULL); ++ goto fail; + } + } + } + +#if DEBUG + /* DEBUGGING: Warn about attributes I don't yet fully support. */ + if ((flags & ~0x02) != 0) { + fprintf(stderr, "\n ** Unrecognized flag: "); + dump_isodirrec(stderr, isodirrec); + fprintf(stderr, "\n"); + } else if (toi(isodirrec + DR_volume_sequence_number_offset, 2) != 1) { + fprintf(stderr, "\n ** Unrecognized sequence number: "); + dump_isodirrec(stderr, isodirrec); + fprintf(stderr, "\n"); + } else if (*(isodirrec + DR_file_unit_size_offset) != 0) { + fprintf(stderr, "\n ** Unexpected file unit size: "); + dump_isodirrec(stderr, isodirrec); + fprintf(stderr, "\n"); + } else if (*(isodirrec + DR_interleave_offset) != 0) { + fprintf(stderr, "\n ** Unexpected interleave: "); + dump_isodirrec(stderr, isodirrec); + fprintf(stderr, "\n"); + } else if (*(isodirrec + DR_ext_attr_length_offset) != 0) { + fprintf(stderr, "\n ** Unexpected extended attribute length: "); + dump_isodirrec(stderr, isodirrec); + fprintf(stderr, "\n"); + } +#endif + register_file(iso9660, file); + return (file); ++fail: ++ archive_string_free(&file->name); ++ free(file); ++ return (NULL); +} + +static int +parse_rockridge(struct archive_read *a, struct file_info *file, + const unsigned char *p, const unsigned char *end) +{ + struct iso9660 *iso9660; + + iso9660 = (struct iso9660 *)(a->format->data); + + while (p + 4 <= end /* Enough space for another entry. */ + && p[0] >= 'A' && p[0] <= 'Z' /* Sanity-check 1st char of name. */ + && p[1] >= 'A' && p[1] <= 'Z' /* Sanity-check 2nd char of name. */ + && p[2] >= 4 /* Sanity-check length. */ + && p + p[2] <= end) { /* Sanity-check length. */ + const unsigned char *data = p + 4; + int data_length = p[2] - 4; + int version = p[3]; + + switch(p[0]) { + case 'C': + if (p[1] == 'E') { + if (version == 1 && data_length == 24) { + /* + * CE extension comprises: + * 8 byte sector containing extension + * 8 byte offset w/in above sector + * 8 byte length of continuation + */ + int32_t location = + archive_le32dec(data); + file->ce_offset = + archive_le32dec(data+8); + file->ce_size = + archive_le32dec(data+16); + if (register_CE(a, location, file) + != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + } + else if (p[1] == 'L') { + if (version == 1 && data_length == 8) { + file->cl_offset = (uint64_t) + iso9660->logical_block_size * + (uint64_t)archive_le32dec(data); + iso9660->seenRockridge = 1; + } + } + break; + case 'N': + if (p[1] == 'M') { + if (version == 1) { + parse_rockridge_NM1(file, + data, data_length); + iso9660->seenRockridge = 1; + } + } + break; + case 'P': + /* + * PD extension is padding; + * contents are always ignored. + * + * PL extension won't appear; + * contents are always ignored. + */ + if (p[1] == 'N') { + if (version == 1 && data_length == 16) { + file->rdev = toi(data,4); + file->rdev <<= 32; + file->rdev |= toi(data + 8, 4); + iso9660->seenRockridge = 1; + } + } + else if (p[1] == 'X') { + /* + * PX extension comprises: + * 8 bytes for mode, + * 8 bytes for nlinks, + * 8 bytes for uid, + * 8 bytes for gid, + * 8 bytes for inode. + */ + if (version == 1) { + if (data_length >= 8) + file->mode + = toi(data, 4); + if (data_length >= 16) + file->nlinks + = toi(data + 8, 4); + if (data_length >= 24) + file->uid + = toi(data + 16, 4); + if (data_length >= 32) + file->gid + = toi(data + 24, 4); + if (data_length >= 40) + file->number + = toi(data + 32, 4); + iso9660->seenRockridge = 1; + } + } + break; + case 'R': + if (p[1] == 'E' && version == 1) { + file->re = 1; + iso9660->seenRockridge = 1; + } + else if (p[1] == 'R' && version == 1) { + /* + * RR extension comprises: + * one byte flag value + * This extension is obsolete, + * so contents are always ignored. + */ + } + break; + case 'S': + if (p[1] == 'L') { + if (version == 1) { + parse_rockridge_SL1(file, + data, data_length); + iso9660->seenRockridge = 1; + } + } + else if (p[1] == 'T' + && data_length == 0 && version == 1) { + /* + * ST extension marks end of this + * block of SUSP entries. + * + * It allows SUSP to coexist with + * non-SUSP uses of the System + * Use Area by placing non-SUSP data + * after SUSP data. + */ + iso9660->seenSUSP = 0; + iso9660->seenRockridge = 0; + return (ARCHIVE_OK); + } + break; + case 'T': + if (p[1] == 'F') { + if (version == 1) { + parse_rockridge_TF1(file, + data, data_length); + iso9660->seenRockridge = 1; + } + } + break; + case 'Z': + if (p[1] == 'F') { + if (version == 1) + parse_rockridge_ZF1(file, + data, data_length); + } + break; + default: + break; + } + + p += p[2]; + } + return (ARCHIVE_OK); +} + +static int +register_CE(struct archive_read *a, int32_t location, + struct file_info *file) +{ + struct iso9660 *iso9660; + struct read_ce_queue *heap; + struct read_ce_req *p; + uint64_t offset, parent_offset; + int hole, parent; + + iso9660 = (struct iso9660 *)(a->format->data); + offset = ((uint64_t)location) * (uint64_t)iso9660->logical_block_size; + if (((file->mode & AE_IFMT) == AE_IFREG && + offset >= file->offset) || + offset < iso9660->current_position || + (((uint64_t)file->ce_offset) + file->ce_size) + > (uint64_t)iso9660->logical_block_size || + offset + file->ce_offset + file->ce_size + > iso9660->volume_size) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid parameter in SUSP \"CE\" extension"); + return (ARCHIVE_FATAL); + } + + /* Expand our CE list as necessary. */ + heap = &(iso9660->read_ce_req); + if (heap->cnt >= heap->allocated) { + int new_size; + + if (heap->allocated < 16) + new_size = 16; + else + new_size = heap->allocated * 2; + /* Overflow might keep us from growing the list. */ + if (new_size <= heap->allocated) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + p = calloc(new_size, sizeof(p[0])); + if (p == NULL) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + if (heap->reqs != NULL) { + memcpy(p, heap->reqs, heap->cnt * sizeof(*p)); + free(heap->reqs); + } + heap->reqs = p; + heap->allocated = new_size; + } + + /* + * Start with hole at end, walk it up tree to find insertion point. + */ + hole = heap->cnt++; + while (hole > 0) { + parent = (hole - 1)/2; + parent_offset = heap->reqs[parent].offset; + if (offset >= parent_offset) { + heap->reqs[hole].offset = offset; + heap->reqs[hole].file = file; + return (ARCHIVE_OK); + } + /* Move parent into hole <==> move hole up tree. */ + heap->reqs[hole] = heap->reqs[parent]; + hole = parent; + } + heap->reqs[0].offset = offset; + heap->reqs[0].file = file; + return (ARCHIVE_OK); +} + +static void +next_CE(struct read_ce_queue *heap) +{ + uint64_t a_offset, b_offset, c_offset; + int a, b, c; + struct read_ce_req tmp; + + if (heap->cnt < 1) + return; + + /* + * Move the last item in the heap to the root of the tree + */ + heap->reqs[0] = heap->reqs[--(heap->cnt)]; + + /* + * Rebalance the heap. + */ + a = 0; /* Starting element and its offset */ + a_offset = heap->reqs[a].offset; + for (;;) { + b = a + a + 1; /* First child */ + if (b >= heap->cnt) + return; + b_offset = heap->reqs[b].offset; + c = b + 1; /* Use second child if it is smaller. */ + if (c < heap->cnt) { + c_offset = heap->reqs[c].offset; + if (c_offset < b_offset) { + b = c; + b_offset = c_offset; + } + } + if (a_offset <= b_offset) + return; + tmp = heap->reqs[a]; + heap->reqs[a] = heap->reqs[b]; + heap->reqs[b] = tmp; + a = b; + } +} + + +static int +read_CE(struct archive_read *a, struct iso9660 *iso9660) +{ + struct read_ce_queue *heap; + const unsigned char *b, *p, *end; + struct file_info *file; + size_t step; + int r; + + /* Read data which RRIP "CE" extension points. */ + heap = &(iso9660->read_ce_req); + step = iso9660->logical_block_size; + while (heap->cnt && + heap->reqs[0].offset == iso9660->current_position) { + b = __archive_read_ahead(a, step, NULL); + if (b == NULL) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Failed to read full block when scanning " + "ISO9660 directory list"); + return (ARCHIVE_FATAL); + } + do { + file = heap->reqs[0].file; + if (file->ce_offset + file->ce_size > step) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Malformed CE information"); + return (ARCHIVE_FATAL); + } + p = b + file->ce_offset; + end = p + file->ce_size; + next_CE(heap); + r = parse_rockridge(a, file, p, end); + if (r != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } while (heap->cnt && + heap->reqs[0].offset == iso9660->current_position); - /* NOTE: Do not move this consume's code to fron of ++ /* NOTE: Do not move this consume's code to front of + * do-while loop. Registration of nested CE extension + * might cause error because of current position. */ + __archive_read_consume(a, step); + iso9660->current_position += step; + } + return (ARCHIVE_OK); +} + +static void +parse_rockridge_NM1(struct file_info *file, + const unsigned char *data, int data_length) +{ + if (!file->name_continues) + archive_string_empty(&file->name); + file->name_continues = 0; + if (data_length < 1) + return; + /* + * NM version 1 extension comprises: + * 1 byte flag, value is one of: + * = 0: remainder is name + * = 1: remainder is name, next NM entry continues name + * = 2: "." + * = 4: ".." + * = 32: Implementation specific + * All other values are reserved. + */ + switch(data[0]) { + case 0: + if (data_length < 2) + return; + archive_strncat(&file->name, + (const char *)data + 1, data_length - 1); + break; + case 1: + if (data_length < 2) + return; + archive_strncat(&file->name, + (const char *)data + 1, data_length - 1); + file->name_continues = 1; + break; + case 2: + archive_strcat(&file->name, "."); + break; + case 4: + archive_strcat(&file->name, ".."); + break; + default: + return; + } + +} + +static void +parse_rockridge_TF1(struct file_info *file, const unsigned char *data, + int data_length) +{ + char flag; + /* + * TF extension comprises: + * one byte flag + * create time (optional) + * modify time (optional) + * access time (optional) + * attribute time (optional) + * Time format and presence of fields + * is controlled by flag bits. + */ + if (data_length < 1) + return; + flag = data[0]; + ++data; + --data_length; + if (flag & 0x80) { + /* Use 17-byte time format. */ + if ((flag & 1) && data_length >= 17) { + /* Create time. */ + file->birthtime_is_set = 1; + file->birthtime = isodate17(data); + data += 17; + data_length -= 17; + } + if ((flag & 2) && data_length >= 17) { + /* Modify time. */ + file->mtime = isodate17(data); + data += 17; + data_length -= 17; + } + if ((flag & 4) && data_length >= 17) { + /* Access time. */ + file->atime = isodate17(data); + data += 17; + data_length -= 17; + } + if ((flag & 8) && data_length >= 17) { + /* Attribute change time. */ + file->ctime = isodate17(data); + } + } else { + /* Use 7-byte time format. */ + if ((flag & 1) && data_length >= 7) { + /* Create time. */ + file->birthtime_is_set = 1; + file->birthtime = isodate7(data); + data += 7; + data_length -= 7; + } + if ((flag & 2) && data_length >= 7) { + /* Modify time. */ + file->mtime = isodate7(data); + data += 7; + data_length -= 7; + } + if ((flag & 4) && data_length >= 7) { + /* Access time. */ + file->atime = isodate7(data); + data += 7; + data_length -= 7; + } + if ((flag & 8) && data_length >= 7) { + /* Attribute change time. */ + file->ctime = isodate7(data); + } + } +} + +static void +parse_rockridge_SL1(struct file_info *file, const unsigned char *data, + int data_length) +{ + const char *separator = ""; + + if (!file->symlink_continues || file->symlink.length < 1) + archive_string_empty(&file->symlink); + file->symlink_continues = 0; + + /* + * Defined flag values: + * 0: This is the last SL record for this symbolic link + * 1: this symbolic link field continues in next SL entry + * All other values are reserved. + */ + if (data_length < 1) + return; + switch(*data) { + case 0: + break; + case 1: + file->symlink_continues = 1; + break; + default: + return; + } + ++data; /* Skip flag byte. */ + --data_length; + + /* + * SL extension body stores "components". + * Basically, this is a complicated way of storing + * a POSIX path. It also interferes with using + * symlinks for storing non-path data. + * + * Each component is 2 bytes (flag and length) + * possibly followed by name data. + */ + while (data_length >= 2) { + unsigned char flag = *data++; + unsigned char nlen = *data++; + data_length -= 2; + + archive_strcat(&file->symlink, separator); + separator = "/"; + + switch(flag) { + case 0: /* Usual case, this is text. */ + if (data_length < nlen) + return; + archive_strncat(&file->symlink, + (const char *)data, nlen); + break; + case 0x01: /* Text continues in next component. */ + if (data_length < nlen) + return; + archive_strncat(&file->symlink, + (const char *)data, nlen); + separator = ""; + break; + case 0x02: /* Current dir. */ + archive_strcat(&file->symlink, "."); + break; + case 0x04: /* Parent dir. */ + archive_strcat(&file->symlink, ".."); + break; + case 0x08: /* Root of filesystem. */ + archive_strcat(&file->symlink, "/"); + separator = ""; + break; + case 0x10: /* Undefined (historically "volume root" */ + archive_string_empty(&file->symlink); + archive_strcat(&file->symlink, "ROOT"); + break; + case 0x20: /* Undefined (historically "hostname") */ + archive_strcat(&file->symlink, "hostname"); + break; + default: + /* TODO: issue a warning ? */ + return; + } + data += nlen; + data_length -= nlen; + } +} + +static void +parse_rockridge_ZF1(struct file_info *file, const unsigned char *data, + int data_length) +{ + + if (data[0] == 0x70 && data[1] == 0x7a && data_length == 12) { + /* paged zlib */ + file->pz = 1; + file->pz_log2_bs = data[3]; + file->pz_uncompressed_size = archive_le32dec(&data[4]); + } +} + +static void +register_file(struct iso9660 *iso9660, struct file_info *file) +{ + + file->use_next = iso9660->use_files; + iso9660->use_files = file; +} + +static void +release_files(struct iso9660 *iso9660) +{ + struct content *con, *connext; + struct file_info *file; + + file = iso9660->use_files; + while (file != NULL) { + struct file_info *next = file->use_next; + + archive_string_free(&file->name); + archive_string_free(&file->symlink); + free(file->utf16be_name); + con = file->contents.first; + while (con != NULL) { + connext = con->next; + free(con); + con = connext; + } + free(file); + file = next; + } +} + +static int +next_entry_seek(struct archive_read *a, struct iso9660 *iso9660, + struct file_info **pfile) +{ + struct file_info *file; + int r; + + r = next_cache_entry(a, iso9660, pfile); + if (r != ARCHIVE_OK) + return (r); + file = *pfile; + + /* Don't waste time seeking for zero-length bodies. */ + if (file->size == 0) + file->offset = iso9660->current_position; + + /* flush any remaining bytes from the last round to ensure + * we're positioned */ + if (iso9660->entry_bytes_unconsumed) { + __archive_read_consume(a, iso9660->entry_bytes_unconsumed); + iso9660->entry_bytes_unconsumed = 0; + } + + /* Seek forward to the start of the entry. */ + if (iso9660->current_position < file->offset) { + int64_t step; + + step = file->offset - iso9660->current_position; + step = __archive_read_consume(a, step); + if (step < 0) + return ((int)step); + iso9660->current_position = file->offset; + } + + /* We found body of file; handle it now. */ + return (ARCHIVE_OK); +} + +static int +next_cache_entry(struct archive_read *a, struct iso9660 *iso9660, + struct file_info **pfile) +{ + struct file_info *file; + struct { + struct file_info *first; + struct file_info **last; + } empty_files; + int64_t number; + int count; + + file = cache_get_entry(iso9660); + if (file != NULL) { + *pfile = file; + return (ARCHIVE_OK); + } + + for (;;) { + struct file_info *re, *d; + + *pfile = file = next_entry(iso9660); + if (file == NULL) { + /* + * If directory entries all which are descendant of - * rr_moved are stil remaning, expose their. ++ * rr_moved are still remaining, expose their. + */ + if (iso9660->re_files.first != NULL && + iso9660->rr_moved != NULL && + iso9660->rr_moved->rr_moved_has_re_only) + /* Expose "rr_moved" entry. */ + cache_add_entry(iso9660, iso9660->rr_moved); + while ((re = re_get_entry(iso9660)) != NULL) { + /* Expose its descendant dirs. */ + while ((d = rede_get_entry(re)) != NULL) + cache_add_entry(iso9660, d); + } + if (iso9660->cache_files.first != NULL) + return (next_cache_entry(a, iso9660, pfile)); + return (ARCHIVE_EOF); + } + + if (file->cl_offset) { + struct file_info *first_re = NULL; + int nexted_re = 0; + + /* + * Find "RE" dir for the current file, which + * has "CL" flag. + */ + while ((re = re_get_entry(iso9660)) + != first_re) { + if (first_re == NULL) + first_re = re; + if (re->offset == file->cl_offset) { + re->parent->subdirs--; + re->parent = file->parent; + re->re = 0; + if (re->parent->re_descendant) { + nexted_re = 1; + re->re_descendant = 1; + if (rede_add_entry(re) < 0) + goto fatal_rr; + /* Move a list of descendants + * to a new ancestor. */ + while ((d = rede_get_entry( + re)) != NULL) + if (rede_add_entry(d) + < 0) + goto fatal_rr; + break; + } + /* Replace the current file + * with "RE" dir */ + *pfile = file = re; + /* Expose its descendant */ + while ((d = rede_get_entry( + file)) != NULL) + cache_add_entry( + iso9660, d); + break; + } else + re_add_entry(iso9660, re); + } + if (nexted_re) { + /* + * Do not expose this at this time + * because we have not gotten its full-path + * name yet. + */ + continue; + } + } else if ((file->mode & AE_IFMT) == AE_IFDIR) { + int r; + + /* Read file entries in this dir. */ + r = read_children(a, file); + if (r != ARCHIVE_OK) + return (r); + + /* + * Handle a special dir of Rockridge extensions, + * "rr_moved". + */ + if (file->rr_moved) { + /* + * If this has only the subdirectories which + * have "RE" flags, do not expose at this time. + */ + if (file->rr_moved_has_re_only) + continue; + /* Otherwise expose "rr_moved" entry. */ + } else if (file->re) { + /* + * Do not expose this at this time + * because we have not gotten its full-path + * name yet. + */ + re_add_entry(iso9660, file); + continue; + } else if (file->re_descendant) { + /* + * If the top level "RE" entry of this entry + * is not exposed, we, accordingly, should not + * expose this entry at this time because + * we cannot make its proper full-path name. + */ + if (rede_add_entry(file) == 0) + continue; + /* Otherwise we can expose this entry because + * it seems its top level "RE" has already been + * exposed. */ + } + } + break; + } + + if ((file->mode & AE_IFMT) != AE_IFREG || file->number == -1) + return (ARCHIVE_OK); + + count = 0; + number = file->number; + iso9660->cache_files.first = NULL; + iso9660->cache_files.last = &(iso9660->cache_files.first); + empty_files.first = NULL; + empty_files.last = &empty_files.first; + /* Collect files which has the same file serial number. + * Peek pending_files so that file which number is different - * is not put bak. */ ++ * is not put back. */ + while (iso9660->pending_files.used > 0 && + (iso9660->pending_files.files[0]->number == -1 || + iso9660->pending_files.files[0]->number == number)) { + if (file->number == -1) { + /* This file has the same offset + * but it's wrong offset which empty files + * and symlink files have. - * NOTE: This wrong offse was recorded by ++ * NOTE: This wrong offset was recorded by + * old mkisofs utility. If ISO images is + * created by latest mkisofs, this does not + * happen. + */ + file->next = NULL; + *empty_files.last = file; + empty_files.last = &(file->next); + } else { + count++; + cache_add_entry(iso9660, file); + } + file = next_entry(iso9660); + } + + if (count == 0) { + *pfile = file; + return ((file == NULL)?ARCHIVE_EOF:ARCHIVE_OK); + } + if (file->number == -1) { + file->next = NULL; + *empty_files.last = file; + empty_files.last = &(file->next); + } else { + count++; + cache_add_entry(iso9660, file); + } + + if (count > 1) { + /* The count is the same as number of hardlink, + * so much so that each nlinks of files in cache_file + * is overwritten by value of the count. + */ + for (file = iso9660->cache_files.first; + file != NULL; file = file->next) + file->nlinks = count; + } + /* If there are empty files, that files are added + * to the tail of the cache_files. */ + if (empty_files.first != NULL) { + *iso9660->cache_files.last = empty_files.first; + iso9660->cache_files.last = empty_files.last; + } + *pfile = cache_get_entry(iso9660); + return ((*pfile == NULL)?ARCHIVE_EOF:ARCHIVE_OK); + +fatal_rr: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to connect 'CL' pointer to 'RE' rr_moved pointer of " + "Rockridge extensions: current position = %jd, CL offset = %jd", + (intmax_t)iso9660->current_position, (intmax_t)file->cl_offset); + return (ARCHIVE_FATAL); +} + +static inline void +re_add_entry(struct iso9660 *iso9660, struct file_info *file) +{ + file->re_next = NULL; + *iso9660->re_files.last = file; + iso9660->re_files.last = &(file->re_next); +} + +static inline struct file_info * +re_get_entry(struct iso9660 *iso9660) +{ + struct file_info *file; + + if ((file = iso9660->re_files.first) != NULL) { + iso9660->re_files.first = file->re_next; + if (iso9660->re_files.first == NULL) + iso9660->re_files.last = + &(iso9660->re_files.first); + } + return (file); +} + +static inline int +rede_add_entry(struct file_info *file) +{ + struct file_info *re; + + /* + * Find "RE" entry. + */ + re = file->parent; + while (re != NULL && !re->re) + re = re->parent; + if (re == NULL) + return (-1); + + file->re_next = NULL; + *re->rede_files.last = file; + re->rede_files.last = &(file->re_next); + return (0); +} + +static inline struct file_info * +rede_get_entry(struct file_info *re) +{ + struct file_info *file; + + if ((file = re->rede_files.first) != NULL) { + re->rede_files.first = file->re_next; + if (re->rede_files.first == NULL) + re->rede_files.last = + &(re->rede_files.first); + } + return (file); +} + +static inline void +cache_add_entry(struct iso9660 *iso9660, struct file_info *file) +{ + file->next = NULL; + *iso9660->cache_files.last = file; + iso9660->cache_files.last = &(file->next); +} + +static inline struct file_info * +cache_get_entry(struct iso9660 *iso9660) +{ + struct file_info *file; + + if ((file = iso9660->cache_files.first) != NULL) { + iso9660->cache_files.first = file->next; + if (iso9660->cache_files.first == NULL) + iso9660->cache_files.last = + &(iso9660->cache_files.first); + } + return (file); +} + +static int +heap_add_entry(struct archive_read *a, struct heap_queue *heap, + struct file_info *file, uint64_t key) +{ + uint64_t file_key, parent_key; + int hole, parent; + + /* Expand our pending files list as necessary. */ + if (heap->used >= heap->allocated) { + struct file_info **new_pending_files; + int new_size = heap->allocated * 2; + + if (heap->allocated < 1024) + new_size = 1024; + /* Overflow might keep us from growing the list. */ + if (new_size <= heap->allocated) { + archive_set_error(&a->archive, + ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + new_pending_files = (struct file_info **) + malloc(new_size * sizeof(new_pending_files[0])); + if (new_pending_files == NULL) { + archive_set_error(&a->archive, + ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + 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; + heap->allocated = new_size; + } + + file_key = file->key = key; + + /* + * Start with hole at end, walk it up tree to find insertion point. + */ + hole = heap->used++; + while (hole > 0) { + parent = (hole - 1)/2; + parent_key = heap->files[parent]->key; + if (file_key >= parent_key) { + heap->files[hole] = file; + return (ARCHIVE_OK); + } + /* Move parent into hole <==> move hole up tree. */ + heap->files[hole] = heap->files[parent]; + hole = parent; + } + heap->files[0] = file; + + return (ARCHIVE_OK); +} + +static struct file_info * +heap_get_entry(struct heap_queue *heap) +{ + uint64_t a_key, b_key, c_key; + int a, b, c; + struct file_info *r, *tmp; + + if (heap->used < 1) + return (NULL); + + /* + * The first file in the list is the earliest; we'll return this. + */ + r = heap->files[0]; + + /* + * Move the last item in the heap to the root of the tree + */ + heap->files[0] = heap->files[--(heap->used)]; + + /* + * Rebalance the heap. + */ + a = 0; /* Starting element and its heap key */ + a_key = heap->files[a]->key; + for (;;) { + b = a + a + 1; /* First child */ + if (b >= heap->used) + return (r); + b_key = heap->files[b]->key; + c = b + 1; /* Use second child if it is smaller. */ + if (c < heap->used) { + c_key = heap->files[c]->key; + if (c_key < b_key) { + b = c; + b_key = c_key; + } + } + if (a_key <= b_key) + return (r); + tmp = heap->files[a]; + heap->files[a] = heap->files[b]; + heap->files[b] = tmp; + a = b; + } +} + +static unsigned int +toi(const void *p, int n) +{ + const unsigned char *v = (const unsigned char *)p; + if (n > 1) + return v[0] + 256 * toi(v + 1, n - 1); + if (n == 1) + return v[0]; + return (0); +} + +static time_t +isodate7(const unsigned char *v) +{ + struct tm tm; + int offset; + time_t t; + + memset(&tm, 0, sizeof(tm)); + tm.tm_year = v[0]; + tm.tm_mon = v[1] - 1; + tm.tm_mday = v[2]; + tm.tm_hour = v[3]; + tm.tm_min = v[4]; + tm.tm_sec = v[5]; + /* v[6] is the signed timezone offset, in 1/4-hour increments. */ + offset = ((const signed char *)v)[6]; + if (offset > -48 && offset < 52) { + tm.tm_hour -= offset / 4; + tm.tm_min -= (offset % 4) * 15; + } + t = time_from_tm(&tm); + if (t == (time_t)-1) + return ((time_t)0); + return (t); +} + +static time_t +isodate17(const unsigned char *v) +{ + struct tm tm; + int offset; + time_t t; + + memset(&tm, 0, sizeof(tm)); + tm.tm_year = (v[0] - '0') * 1000 + (v[1] - '0') * 100 + + (v[2] - '0') * 10 + (v[3] - '0') + - 1900; + tm.tm_mon = (v[4] - '0') * 10 + (v[5] - '0'); + tm.tm_mday = (v[6] - '0') * 10 + (v[7] - '0'); + tm.tm_hour = (v[8] - '0') * 10 + (v[9] - '0'); + tm.tm_min = (v[10] - '0') * 10 + (v[11] - '0'); + tm.tm_sec = (v[12] - '0') * 10 + (v[13] - '0'); + /* v[16] is the signed timezone offset, in 1/4-hour increments. */ + offset = ((const signed char *)v)[16]; + if (offset > -48 && offset < 52) { + tm.tm_hour -= offset / 4; + tm.tm_min -= (offset % 4) * 15; + } + t = time_from_tm(&tm); + if (t == (time_t)-1) + return ((time_t)0); + return (t); +} + +static time_t +time_from_tm(struct tm *t) +{ +#if HAVE_TIMEGM + /* Use platform timegm() if available. */ + return (timegm(t)); +#elif HAVE__MKGMTIME64 + return (_mkgmtime64(t)); +#else + /* Else use direct calculation using POSIX assumptions. */ + /* First, fix up tm_yday based on the year/month/day. */ + if (mktime(t) == (time_t)-1) + return ((time_t)-1); + /* Then we can compute timegm() from first principles. */ + return (t->tm_sec + + t->tm_min * 60 + + t->tm_hour * 3600 + + t->tm_yday * 86400 + + (t->tm_year - 70) * 31536000 + + ((t->tm_year - 69) / 4) * 86400 + - ((t->tm_year - 1) / 100) * 86400 + + ((t->tm_year + 299) / 400) * 86400); +#endif +} + +static const char * +build_pathname(struct archive_string *as, struct file_info *file, int depth) +{ + // Plain ISO9660 only allows 8 dir levels; if we get + // to 1000, then something is very, very wrong. + if (depth > 1000) { + return NULL; + } + if (file->parent != NULL && archive_strlen(&file->parent->name) > 0) { + if (build_pathname(as, file->parent, depth + 1) == NULL) { + return NULL; + } + archive_strcat(as, "/"); + } + if (archive_strlen(&file->name) == 0) + archive_strcat(as, "."); + else + archive_string_concat(as, &file->name); + return (as->s); +} + +static int +build_pathname_utf16be(unsigned char *p, size_t max, size_t *len, + struct file_info *file) +{ + if (file->parent != NULL && file->parent->utf16be_bytes > 0) { + if (build_pathname_utf16be(p, max, len, file->parent) != 0) + return (-1); + p[*len] = 0; + p[*len + 1] = '/'; + *len += 2; + } + if (file->utf16be_bytes == 0) { + if (*len + 2 > max) + return (-1);/* Path is too long! */ + p[*len] = 0; + p[*len + 1] = '.'; + *len += 2; + } else { + if (*len + file->utf16be_bytes > max) + return (-1);/* Path is too long! */ + memcpy(p + *len, file->utf16be_name, file->utf16be_bytes); + *len += file->utf16be_bytes; + } + return (0); +} + +#if DEBUG +static void +dump_isodirrec(FILE *out, const unsigned char *isodirrec) +{ + fprintf(out, " l %d,", + toi(isodirrec + DR_length_offset, DR_length_size)); + fprintf(out, " a %d,", + toi(isodirrec + DR_ext_attr_length_offset, DR_ext_attr_length_size)); + fprintf(out, " ext 0x%x,", + toi(isodirrec + DR_extent_offset, DR_extent_size)); + fprintf(out, " s %d,", + toi(isodirrec + DR_size_offset, DR_extent_size)); + fprintf(out, " f 0x%x,", + toi(isodirrec + DR_flags_offset, DR_flags_size)); + fprintf(out, " u %d,", + toi(isodirrec + DR_file_unit_size_offset, DR_file_unit_size_size)); + fprintf(out, " ilv %d,", + toi(isodirrec + DR_interleave_offset, DR_interleave_size)); + fprintf(out, " seq %d,", + toi(isodirrec + DR_volume_sequence_number_offset, + DR_volume_sequence_number_size)); + fprintf(out, " nl %d:", + toi(isodirrec + DR_name_len_offset, DR_name_len_size)); + fprintf(out, " `%.*s'", + toi(isodirrec + DR_name_len_offset, DR_name_len_size), + isodirrec + DR_name_offset); +} +#endif diff --cc Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c index eff02d8,0000000..ebd7f2c mode 100644,000000..100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_lha.c @@@ -1,2810 -1,0 +1,2817 @@@ +/*- + * Copyright (c) 2008-2014 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#include "archive.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_private.h" +#include "archive_read_private.h" +#include "archive_endian.h" + + +#define MAXMATCH 256 /* Maximum match length. */ +#define MINMATCH 3 /* Minimum match length. */ +/* + * Literal table format: + * +0 +256 +510 + * +---------------+-------------------------+ + * | literal code | match length | + * | 0 ... 255 | MINMATCH ... MAXMATCH | + * +---------------+-------------------------+ + * <--- LT_BITLEN_SIZE ---> + */ +/* Literal table size. */ +#define LT_BITLEN_SIZE (UCHAR_MAX + 1 + MAXMATCH - MINMATCH + 1) +/* Position table size. + * Note: this used for both position table and pre literal table.*/ +#define PT_BITLEN_SIZE (3 + 16) + +struct lzh_dec { + /* Decoding status. */ + int state; + + /* + * Window to see last 8Ki(lh5),32Ki(lh6),64Ki(lh7) bytes of decoded + * data. + */ + int w_size; + int w_mask; + /* Window buffer, which is a loop buffer. */ + unsigned char *w_buff; + /* The insert position to the window. */ + int w_pos; + /* The position where we can copy decoded code from the window. */ + int copy_pos; + /* The length how many bytes we can copy decoded code from + * the window. */ + int copy_len; + + /* + * Bit stream reader. + */ + struct lzh_br { +#define CACHE_TYPE uint64_t +#define CACHE_BITS (8 * sizeof(CACHE_TYPE)) + /* Cache buffer. */ + CACHE_TYPE cache_buffer; + /* Indicates how many bits avail in cache_buffer. */ + int cache_avail; + } br; + + /* + * Huffman coding. + */ + struct huffman { + int len_size; + int len_avail; + int len_bits; + int freq[17]; + unsigned char *bitlen; + + /* + * Use a index table. It's faster than searching a huffman + * 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; + } lt, pt; + + int blocks_avail; + int pos_pt_len_size; + int pos_pt_len_bits; + int literal_pt_len_size; + int literal_pt_len_bits; + int reading_position; + int loop; + int error; +}; + +struct lzh_stream { + const unsigned char *next_in; + int avail_in; + int64_t total_in; + const unsigned char *ref_ptr; + int avail_out; + int64_t total_out; + struct lzh_dec *ds; +}; + +struct lha { + /* entry_bytes_remaining is the number of bytes we expect. */ + int64_t entry_offset; + int64_t entry_bytes_remaining; + int64_t entry_unconsumed; + uint16_t entry_crc_calculated; + + size_t header_size; /* header size */ + unsigned char level; /* header level */ + char method[3]; /* compress type */ + int64_t compsize; /* compressed data size */ + int64_t origsize; /* original file size */ + int setflag; +#define BIRTHTIME_IS_SET 1 +#define ATIME_IS_SET 2 +#define UNIX_MODE_IS_SET 4 +#define CRC_IS_SET 8 + time_t birthtime; + long birthtime_tv_nsec; + time_t mtime; + long mtime_tv_nsec; + time_t atime; + long atime_tv_nsec; + mode_t mode; + int64_t uid; + int64_t gid; + struct archive_string uname; + struct archive_string gname; + uint16_t header_crc; + uint16_t crc; + struct archive_string_conv *sconv; + struct archive_string_conv *opt_sconv; + + struct archive_string dirname; + struct archive_string filename; + struct archive_wstring ws; + + unsigned char dos_attr; + + /* Flag to mark progress that an archive was read their first header.*/ + char found_first_header; + /* Flag to mark that indicates an empty directory. */ + char directory; + + /* Flags to mark progress of decompression. */ + char decompress_init; + char end_of_entry; + char end_of_entry_cleanup; + char entry_is_compressed; + + char format_name[64]; + + struct lzh_stream strm; +}; + +/* + * LHA header common member offset. + */ +#define H_METHOD_OFFSET 2 /* Compress type. */ +#define H_ATTR_OFFSET 19 /* DOS attribute. */ +#define H_LEVEL_OFFSET 20 /* Header Level. */ +#define H_SIZE 22 /* Minimum header size. */ + +static int archive_read_format_lha_bid(struct archive_read *, int); +static int archive_read_format_lha_options(struct archive_read *, + const char *, const char *); +static int archive_read_format_lha_read_header(struct archive_read *, + struct archive_entry *); +static int archive_read_format_lha_read_data(struct archive_read *, + const void **, size_t *, int64_t *); +static int archive_read_format_lha_read_data_skip(struct archive_read *); +static int archive_read_format_lha_cleanup(struct archive_read *); + +static void lha_replace_path_separator(struct lha *, + struct archive_entry *); +static int lha_read_file_header_0(struct archive_read *, struct lha *); +static int lha_read_file_header_1(struct archive_read *, struct lha *); +static int lha_read_file_header_2(struct archive_read *, struct lha *); +static int lha_read_file_header_3(struct archive_read *, struct lha *); +static int lha_read_file_extended_header(struct archive_read *, + struct lha *, uint16_t *, int, size_t, size_t *); +static size_t lha_check_header_format(const void *); +static int lha_skip_sfx(struct archive_read *); +static time_t lha_dos_time(const unsigned char *); +static time_t lha_win_time(uint64_t, long *); +static unsigned char lha_calcsum(unsigned char, const void *, + int, size_t); +static int lha_parse_linkname(struct archive_string *, + struct archive_string *); +static int lha_read_data_none(struct archive_read *, const void **, + size_t *, int64_t *); +static int lha_read_data_lzh(struct archive_read *, const void **, + size_t *, int64_t *); +static void lha_crc16_init(void); +static uint16_t lha_crc16(uint16_t, const void *, size_t); +static int lzh_decode_init(struct lzh_stream *, const char *); +static void lzh_decode_free(struct lzh_stream *); +static int lzh_decode(struct lzh_stream *, int); +static int lzh_br_fillup(struct lzh_stream *, struct lzh_br *); +static int lzh_huffman_init(struct huffman *, size_t, int); +static void lzh_huffman_free(struct huffman *); +static int lzh_read_pt_bitlen(struct lzh_stream *, int start, int end); +static int lzh_make_fake_table(struct huffman *, uint16_t); +static int lzh_make_huffman_table(struct huffman *); +static inline int lzh_decode_huffman(struct huffman *, unsigned); +static int lzh_decode_huffman_tree(struct huffman *, unsigned, int); + + +int +archive_read_support_format_lha(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct lha *lha; + int r; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_format_lha"); + + lha = (struct lha *)calloc(1, sizeof(*lha)); + if (lha == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate lha data"); + return (ARCHIVE_FATAL); + } + archive_string_init(&lha->ws); + + r = __archive_read_register_format(a, + lha, + "lha", + archive_read_format_lha_bid, + archive_read_format_lha_options, + archive_read_format_lha_read_header, + archive_read_format_lha_read_data, + archive_read_format_lha_read_data_skip, + NULL, + archive_read_format_lha_cleanup, + NULL, + NULL); + + if (r != ARCHIVE_OK) + free(lha); + return (ARCHIVE_OK); +} + +static size_t +lha_check_header_format(const void *h) +{ + const unsigned char *p = h; + size_t next_skip_bytes; + + switch (p[H_METHOD_OFFSET+3]) { + /* + * "-lh0-" ... "-lh7-" "-lhd-" + * "-lzs-" "-lz5-" + */ + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + case 'd': + case 's': + next_skip_bytes = 4; + + /* b0 == 0 means the end of an LHa archive file. */ + if (p[0] == 0) + break; + if (p[H_METHOD_OFFSET] != '-' || p[H_METHOD_OFFSET+1] != 'l' + || p[H_METHOD_OFFSET+4] != '-') + break; + + if (p[H_METHOD_OFFSET+2] == 'h') { + /* "-lh?-" */ + if (p[H_METHOD_OFFSET+3] == 's') + break; + if (p[H_LEVEL_OFFSET] == 0) + return (0); + if (p[H_LEVEL_OFFSET] <= 3 && p[H_ATTR_OFFSET] == 0x20) + return (0); + } + if (p[H_METHOD_OFFSET+2] == 'z') { + /* LArc extensions: -lzs-,-lz4- and -lz5- */ + if (p[H_LEVEL_OFFSET] != 0) + break; + if (p[H_METHOD_OFFSET+3] == 's' + || p[H_METHOD_OFFSET+3] == '4' + || p[H_METHOD_OFFSET+3] == '5') + return (0); + } + break; + case 'h': next_skip_bytes = 1; break; + case 'z': next_skip_bytes = 1; break; + case 'l': next_skip_bytes = 2; break; + case '-': next_skip_bytes = 3; break; + default : next_skip_bytes = 4; break; + } + + return (next_skip_bytes); +} + +static int +archive_read_format_lha_bid(struct archive_read *a, int best_bid) +{ + const char *p; + const void *buff; + ssize_t bytes_avail, offset, window; + size_t next; + + /* If there's already a better bid than we can ever + make, don't bother testing. */ + if (best_bid > 30) + return (-1); + + if ((p = __archive_read_ahead(a, H_SIZE, NULL)) == NULL) + return (-1); + + if (lha_check_header_format(p) == 0) + return (30); + + if (p[0] == 'M' && p[1] == 'Z') { + /* PE file */ + offset = 0; + window = 4096; + while (offset < (1024 * 20)) { + buff = __archive_read_ahead(a, offset + window, + &bytes_avail); + if (buff == NULL) { + /* Remaining bytes are less than window. */ + window >>= 1; + if (window < (H_SIZE + 3)) + return (0); + continue; + } + p = (const char *)buff + offset; + while (p + H_SIZE < (const char *)buff + bytes_avail) { + if ((next = lha_check_header_format(p)) == 0) + return (30); + p += next; + } + offset = p - (const char *)buff; + } + } + return (0); +} + +static int +archive_read_format_lha_options(struct archive_read *a, + const char *key, const char *val) +{ + struct lha *lha; + int ret = ARCHIVE_FAILED; + + lha = (struct lha *)(a->format->data); + if (strcmp(key, "hdrcharset") == 0) { + if (val == NULL || val[0] == 0) + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "lha: hdrcharset option needs a character-set name"); + else { + lha->opt_sconv = + archive_string_conversion_from_charset( + &a->archive, val, 0); + if (lha->opt_sconv != NULL) + ret = ARCHIVE_OK; + else + ret = ARCHIVE_FATAL; + } + return (ret); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +static int +lha_skip_sfx(struct archive_read *a) +{ + const void *h; + const char *p, *q; + size_t next, skip; + ssize_t bytes, window; + + window = 4096; + for (;;) { + h = __archive_read_ahead(a, window, &bytes); + if (h == NULL) { + /* Remaining bytes are less than window. */ + window >>= 1; + if (window < (H_SIZE + 3)) + goto fatal; + continue; + } + if (bytes < H_SIZE) + goto fatal; + p = h; + q = p + bytes; + + /* + * Scan ahead until we find something that looks + * like the lha header. + */ + while (p + H_SIZE < q) { + if ((next = lha_check_header_format(p)) == 0) { + skip = p - (const char *)h; + __archive_read_consume(a, skip); + return (ARCHIVE_OK); + } + p += next; + } + skip = p - (const char *)h; + __archive_read_consume(a, skip); + } +fatal: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Couldn't find out LHa header"); + return (ARCHIVE_FATAL); +} + +static int +truncated_error(struct archive_read *a) +{ + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated LHa header"); + return (ARCHIVE_FATAL); +} + +static int +archive_read_format_lha_read_header(struct archive_read *a, + struct archive_entry *entry) +{ + struct archive_string linkname; + struct archive_string pathname; + struct lha *lha; + const unsigned char *p; + const char *signature; + int err; + + lha_crc16_init(); + + a->archive.archive_format = ARCHIVE_FORMAT_LHA; + if (a->archive.archive_format_name == NULL) + a->archive.archive_format_name = "lha"; + + lha = (struct lha *)(a->format->data); + lha->decompress_init = 0; + lha->end_of_entry = 0; + lha->end_of_entry_cleanup = 0; + lha->entry_unconsumed = 0; + + if ((p = __archive_read_ahead(a, H_SIZE, NULL)) == NULL) { + /* + * LHa archiver added 0 to the tail of its archive file as + * the mark of the end of the archive. + */ + signature = __archive_read_ahead(a, sizeof(signature[0]), NULL); + if (signature == NULL || signature[0] == 0) + return (ARCHIVE_EOF); + return (truncated_error(a)); + } + + signature = (const char *)p; + if (lha->found_first_header == 0 && + signature[0] == 'M' && signature[1] == 'Z') { + /* This is an executable? Must be self-extracting... */ + err = lha_skip_sfx(a); + if (err < ARCHIVE_WARN) + return (err); + + if ((p = __archive_read_ahead(a, sizeof(*p), NULL)) == NULL) + return (truncated_error(a)); + signature = (const char *)p; + } + /* signature[0] == 0 means the end of an LHa archive file. */ + if (signature[0] == 0) + return (ARCHIVE_EOF); + + /* + * Check the header format and method type. + */ + if (lha_check_header_format(p) != 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Bad LHa file"); + return (ARCHIVE_FATAL); + } + + /* We've found the first header. */ + lha->found_first_header = 1; + /* Set a default value and common data */ + lha->header_size = 0; + lha->level = p[H_LEVEL_OFFSET]; + lha->method[0] = p[H_METHOD_OFFSET+1]; + lha->method[1] = p[H_METHOD_OFFSET+2]; + lha->method[2] = p[H_METHOD_OFFSET+3]; + if (memcmp(lha->method, "lhd", 3) == 0) + lha->directory = 1; + else + lha->directory = 0; + if (memcmp(lha->method, "lh0", 3) == 0 || + memcmp(lha->method, "lz4", 3) == 0) + lha->entry_is_compressed = 0; + else + lha->entry_is_compressed = 1; + + lha->compsize = 0; + lha->origsize = 0; + lha->setflag = 0; + lha->birthtime = 0; + lha->birthtime_tv_nsec = 0; + lha->mtime = 0; + lha->mtime_tv_nsec = 0; + lha->atime = 0; + lha->atime_tv_nsec = 0; + lha->mode = (lha->directory)? 0777 : 0666; + lha->uid = 0; + lha->gid = 0; + archive_string_empty(&lha->dirname); + archive_string_empty(&lha->filename); + lha->dos_attr = 0; + if (lha->opt_sconv != NULL) + lha->sconv = lha->opt_sconv; + else + lha->sconv = NULL; + + switch (p[H_LEVEL_OFFSET]) { + case 0: + err = lha_read_file_header_0(a, lha); + break; + case 1: + err = lha_read_file_header_1(a, lha); + break; + case 2: + err = lha_read_file_header_2(a, lha); + break; + case 3: + err = lha_read_file_header_3(a, lha); + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Unsupported LHa header level %d", p[H_LEVEL_OFFSET]); + err = ARCHIVE_FATAL; + break; + } + if (err < ARCHIVE_WARN) + return (err); + + + if (!lha->directory && archive_strlen(&lha->filename) == 0) + /* The filename has not been set */ + return (truncated_error(a)); + + /* + * Make a pathname from a dirname and a filename. + */ + archive_string_concat(&lha->dirname, &lha->filename); + archive_string_init(&pathname); + archive_string_init(&linkname); + archive_string_copy(&pathname, &lha->dirname); + + if ((lha->mode & AE_IFMT) == AE_IFLNK) { + /* + * Extract the symlink-name if it's included in the pathname. + */ + if (!lha_parse_linkname(&linkname, &pathname)) { + /* We couldn't get the symlink-name. */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Unknown symlink-name"); + archive_string_free(&pathname); + archive_string_free(&linkname); + return (ARCHIVE_FAILED); + } + } else { + /* + * Make sure a file-type is set. + * The mode has been overridden if it is in the extended data. + */ + lha->mode = (lha->mode & ~AE_IFMT) | + ((lha->directory)? AE_IFDIR: AE_IFREG); + } + if ((lha->setflag & UNIX_MODE_IS_SET) == 0 && + (lha->dos_attr & 1) != 0) + lha->mode &= ~(0222);/* read only. */ + + /* + * Set basic file parameters. + */ + if (archive_entry_copy_pathname_l(entry, pathname.s, + pathname.length, lha->sconv) != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Pathname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Pathname cannot be converted " + "from %s to current locale.", + archive_string_conversion_charset_name(lha->sconv)); + err = ARCHIVE_WARN; + } + archive_string_free(&pathname); + if (archive_strlen(&linkname) > 0) { + if (archive_entry_copy_symlink_l(entry, linkname.s, + linkname.length, lha->sconv) != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Linkname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Linkname cannot be converted " + "from %s to current locale.", + archive_string_conversion_charset_name(lha->sconv)); + err = ARCHIVE_WARN; + } + } else + archive_entry_set_symlink(entry, NULL); + archive_string_free(&linkname); + /* + * When a header level is 0, there is a possibility that + * a pathname and a symlink has '\' character, a directory + * separator in DOS/Windows. So we should convert it to '/'. + */ + if (p[H_LEVEL_OFFSET] == 0) + lha_replace_path_separator(lha, entry); + + archive_entry_set_mode(entry, lha->mode); + archive_entry_set_uid(entry, lha->uid); + archive_entry_set_gid(entry, lha->gid); + if (archive_strlen(&lha->uname) > 0) + archive_entry_set_uname(entry, lha->uname.s); + if (archive_strlen(&lha->gname) > 0) + archive_entry_set_gname(entry, lha->gname.s); + if (lha->setflag & BIRTHTIME_IS_SET) { + archive_entry_set_birthtime(entry, lha->birthtime, + lha->birthtime_tv_nsec); + archive_entry_set_ctime(entry, lha->birthtime, + lha->birthtime_tv_nsec); + } else { + archive_entry_unset_birthtime(entry); + archive_entry_unset_ctime(entry); + } + archive_entry_set_mtime(entry, lha->mtime, lha->mtime_tv_nsec); + if (lha->setflag & ATIME_IS_SET) + archive_entry_set_atime(entry, lha->atime, + lha->atime_tv_nsec); + else + archive_entry_unset_atime(entry); + if (lha->directory || archive_entry_symlink(entry) != NULL) + archive_entry_unset_size(entry); + else + archive_entry_set_size(entry, lha->origsize); + + /* + * Prepare variables used to read a file content. + */ + lha->entry_bytes_remaining = lha->compsize; + lha->entry_offset = 0; + lha->entry_crc_calculated = 0; + + /* + * This file does not have a content. + */ + if (lha->directory || lha->compsize == 0) + lha->end_of_entry = 1; + + sprintf(lha->format_name, "lha -%c%c%c-", + lha->method[0], lha->method[1], lha->method[2]); + a->archive.archive_format_name = lha->format_name; + + return (err); +} + +/* + * Replace a DOS path separator '\' by a character '/'. + * Some multi-byte character set have a character '\' in its second byte. + */ +static void +lha_replace_path_separator(struct lha *lha, struct archive_entry *entry) +{ + const wchar_t *wp; + size_t i; + + if ((wp = archive_entry_pathname_w(entry)) != NULL) { + archive_wstrcpy(&(lha->ws), wp); + for (i = 0; i < archive_strlen(&(lha->ws)); i++) { + if (lha->ws.s[i] == L'\\') + lha->ws.s[i] = L'/'; + } + archive_entry_copy_pathname_w(entry, lha->ws.s); + } + + if ((wp = archive_entry_symlink_w(entry)) != NULL) { + archive_wstrcpy(&(lha->ws), wp); + for (i = 0; i < archive_strlen(&(lha->ws)); i++) { + if (lha->ws.s[i] == L'\\') + lha->ws.s[i] = L'/'; + } + archive_entry_copy_symlink_w(entry, lha->ws.s); + } +} + +/* + * Header 0 format + * + * +0 +1 +2 +7 +11 + * +---------------+----------+----------------+-------------------+ + * |header size(*1)|header sum|compression type|compressed size(*2)| + * +---------------+----------+----------------+-------------------+ + * <---------------------(*1)----------* + * + * +11 +15 +17 +19 +20 +21 + * +-----------------+---------+---------+--------------+----------------+ + * |uncompressed size|time(DOS)|date(DOS)|attribute(DOS)|header level(=0)| + * +-----------------+---------+---------+--------------+----------------+ + * *--------------------------------(*1)---------------------------------* + * + * +21 +22 +22+(*3) +22+(*3)+2 +22+(*3)+2+(*4) + * +---------------+---------+----------+----------------+------------------+ + * |name length(*3)|file name|file CRC16|extra header(*4)| compressed data | + * +---------------+---------+----------+----------------+------------------+ + * <--(*3)-> <------(*2)------> + * *----------------------(*1)--------------------------> + * + */ +#define H0_HEADER_SIZE_OFFSET 0 +#define H0_HEADER_SUM_OFFSET 1 +#define H0_COMP_SIZE_OFFSET 7 +#define H0_ORIG_SIZE_OFFSET 11 +#define H0_DOS_TIME_OFFSET 15 +#define H0_NAME_LEN_OFFSET 21 +#define H0_FILE_NAME_OFFSET 22 +#define H0_FIXED_SIZE 24 +static int +lha_read_file_header_0(struct archive_read *a, struct lha *lha) +{ + const unsigned char *p; + int extdsize, namelen; + unsigned char headersum, sum_calculated; + + if ((p = __archive_read_ahead(a, H0_FIXED_SIZE, NULL)) == NULL) + return (truncated_error(a)); + lha->header_size = p[H0_HEADER_SIZE_OFFSET] + 2; + headersum = p[H0_HEADER_SUM_OFFSET]; + lha->compsize = archive_le32dec(p + H0_COMP_SIZE_OFFSET); + lha->origsize = archive_le32dec(p + H0_ORIG_SIZE_OFFSET); + lha->mtime = lha_dos_time(p + H0_DOS_TIME_OFFSET); + namelen = p[H0_NAME_LEN_OFFSET]; + extdsize = (int)lha->header_size - H0_FIXED_SIZE - namelen; + if ((namelen > 221 || extdsize < 0) && extdsize != -2) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid LHa header"); + return (ARCHIVE_FATAL); + } + if ((p = __archive_read_ahead(a, lha->header_size, NULL)) == NULL) + return (truncated_error(a)); + + archive_strncpy(&lha->filename, p + H0_FILE_NAME_OFFSET, namelen); + /* When extdsize == -2, A CRC16 value is not present in the header. */ + if (extdsize >= 0) { + lha->crc = archive_le16dec(p + H0_FILE_NAME_OFFSET + namelen); + lha->setflag |= CRC_IS_SET; + } + sum_calculated = lha_calcsum(0, p, 2, lha->header_size - 2); + + /* Read an extended header */ + if (extdsize > 0) { + /* This extended data is set by 'LHa for UNIX' only. + * Maybe fixed size. + */ + p += H0_FILE_NAME_OFFSET + namelen + 2; + if (p[0] == 'U' && extdsize == 12) { + /* p[1] is a minor version. */ + lha->mtime = archive_le32dec(&p[2]); + lha->mode = archive_le16dec(&p[6]); + lha->uid = archive_le16dec(&p[8]); + lha->gid = archive_le16dec(&p[10]); + lha->setflag |= UNIX_MODE_IS_SET; + } + } + __archive_read_consume(a, lha->header_size); + + if (sum_calculated != headersum) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "LHa header sum error"); + return (ARCHIVE_FATAL); + } + + return (ARCHIVE_OK); +} + +/* + * Header 1 format + * + * +0 +1 +2 +7 +11 + * +---------------+----------+----------------+-------------+ + * |header size(*1)|header sum|compression type|skip size(*2)| + * +---------------+----------+----------------+-------------+ + * <---------------(*1)----------* + * + * +11 +15 +17 +19 +20 +21 + * +-----------------+---------+---------+--------------+----------------+ + * |uncompressed size|time(DOS)|date(DOS)|attribute(DOS)|header level(=1)| + * +-----------------+---------+---------+--------------+----------------+ + * *-------------------------------(*1)----------------------------------* + * + * +21 +22 +22+(*3) +22+(*3)+2 +22+(*3)+3 +22+(*3)+3+(*4) + * +---------------+---------+----------+-----------+-----------+ + * |name length(*3)|file name|file CRC16| creator |padding(*4)| + * +---------------+---------+----------+-----------+-----------+ + * <--(*3)-> + * *----------------------------(*1)----------------------------* + * + * +22+(*3)+3+(*4) +22+(*3)+3+(*4)+2 +22+(*3)+3+(*4)+2+(*5) + * +----------------+---------------------+------------------------+ + * |next header size| extended header(*5) | compressed data | + * +----------------+---------------------+------------------------+ + * *------(*1)-----> <--------------------(*2)--------------------> + */ +#define H1_HEADER_SIZE_OFFSET 0 +#define H1_HEADER_SUM_OFFSET 1 +#define H1_COMP_SIZE_OFFSET 7 +#define H1_ORIG_SIZE_OFFSET 11 +#define H1_DOS_TIME_OFFSET 15 +#define H1_NAME_LEN_OFFSET 21 +#define H1_FILE_NAME_OFFSET 22 +#define H1_FIXED_SIZE 27 +static int +lha_read_file_header_1(struct archive_read *a, struct lha *lha) +{ + const unsigned char *p; + size_t extdsize; + int i, err, err2; + int namelen, padding; + unsigned char headersum, sum_calculated; + + err = ARCHIVE_OK; + + if ((p = __archive_read_ahead(a, H1_FIXED_SIZE, NULL)) == NULL) + return (truncated_error(a)); + + lha->header_size = p[H1_HEADER_SIZE_OFFSET] + 2; + headersum = p[H1_HEADER_SUM_OFFSET]; + /* Note: An extended header size is included in a compsize. */ + lha->compsize = archive_le32dec(p + H1_COMP_SIZE_OFFSET); + lha->origsize = archive_le32dec(p + H1_ORIG_SIZE_OFFSET); + lha->mtime = lha_dos_time(p + H1_DOS_TIME_OFFSET); + namelen = p[H1_NAME_LEN_OFFSET]; + /* Calculate a padding size. The result will be normally 0 only(?) */ + padding = ((int)lha->header_size) - H1_FIXED_SIZE - namelen; + + if (namelen > 230 || padding < 0) + goto invalid; + + if ((p = __archive_read_ahead(a, lha->header_size, NULL)) == NULL) + return (truncated_error(a)); + + for (i = 0; i < namelen; i++) { + if (p[i + H1_FILE_NAME_OFFSET] == 0xff) + goto invalid;/* Invalid filename. */ + } + archive_strncpy(&lha->filename, p + H1_FILE_NAME_OFFSET, namelen); + lha->crc = archive_le16dec(p + H1_FILE_NAME_OFFSET + namelen); + lha->setflag |= CRC_IS_SET; + + sum_calculated = lha_calcsum(0, p, 2, lha->header_size - 2); + /* Consume used bytes but not include `next header size' data + * since it will be consumed in lha_read_file_extended_header(). */ + __archive_read_consume(a, lha->header_size - 2); + + /* Read extended headers */ + err2 = lha_read_file_extended_header(a, lha, NULL, 2, + (size_t)(lha->compsize + 2), &extdsize); + if (err2 < ARCHIVE_WARN) + return (err2); + if (err2 < err) + err = err2; + /* Get a real compressed file size. */ + lha->compsize -= extdsize - 2; + ++ if (lha->compsize < 0) ++ goto invalid; /* Invalid compressed file size */ ++ + if (sum_calculated != headersum) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "LHa header sum error"); + return (ARCHIVE_FATAL); + } + return (err); +invalid: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid LHa header"); + return (ARCHIVE_FATAL); +} + +/* + * Header 2 format + * + * +0 +2 +7 +11 +15 + * +---------------+----------------+-------------------+-----------------+ + * |header size(*1)|compression type|compressed size(*2)|uncompressed size| + * +---------------+----------------+-------------------+-----------------+ + * <--------------------------------(*1)---------------------------------* + * + * +15 +19 +20 +21 +23 +24 + * +-----------------+------------+----------------+----------+-----------+ + * |data/time(time_t)| 0x20 fixed |header level(=2)|file CRC16| creator | + * +-----------------+------------+----------------+----------+-----------+ + * *---------------------------------(*1)---------------------------------* + * + * +24 +26 +26+(*3) +26+(*3)+(*4) + * +----------------+-------------------+-------------+-------------------+ + * |next header size|extended header(*3)| padding(*4) | compressed data | + * +----------------+-------------------+-------------+-------------------+ + * *--------------------------(*1)-------------------> <------(*2)-------> + * + */ +#define H2_HEADER_SIZE_OFFSET 0 +#define H2_COMP_SIZE_OFFSET 7 +#define H2_ORIG_SIZE_OFFSET 11 +#define H2_TIME_OFFSET 15 +#define H2_CRC_OFFSET 21 +#define H2_FIXED_SIZE 24 +static int +lha_read_file_header_2(struct archive_read *a, struct lha *lha) +{ + const unsigned char *p; + size_t extdsize; + int err, padding; + uint16_t header_crc; + + if ((p = __archive_read_ahead(a, H2_FIXED_SIZE, NULL)) == NULL) + return (truncated_error(a)); + + lha->header_size =archive_le16dec(p + H2_HEADER_SIZE_OFFSET); + lha->compsize = archive_le32dec(p + H2_COMP_SIZE_OFFSET); + lha->origsize = archive_le32dec(p + H2_ORIG_SIZE_OFFSET); + lha->mtime = archive_le32dec(p + H2_TIME_OFFSET); + lha->crc = archive_le16dec(p + H2_CRC_OFFSET); + lha->setflag |= CRC_IS_SET; + + if (lha->header_size < H2_FIXED_SIZE) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid LHa header size"); + return (ARCHIVE_FATAL); + } + + header_crc = lha_crc16(0, p, H2_FIXED_SIZE); + __archive_read_consume(a, H2_FIXED_SIZE); + + /* Read extended headers */ + err = lha_read_file_extended_header(a, lha, &header_crc, 2, + lha->header_size - H2_FIXED_SIZE, &extdsize); + if (err < ARCHIVE_WARN) + return (err); + + /* Calculate a padding size. The result will be normally 0 or 1. */ + padding = (int)lha->header_size - (int)(H2_FIXED_SIZE + extdsize); + if (padding > 0) { + if ((p = __archive_read_ahead(a, padding, NULL)) == NULL) + return (truncated_error(a)); + header_crc = lha_crc16(header_crc, p, padding); + __archive_read_consume(a, padding); + } + + if (header_crc != lha->header_crc) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "LHa header CRC error"); + return (ARCHIVE_FATAL); + } + return (err); +} + +/* + * Header 3 format + * + * +0 +2 +7 +11 +15 + * +------------+----------------+-------------------+-----------------+ + * | 0x04 fixed |compression type|compressed size(*2)|uncompressed size| + * +------------+----------------+-------------------+-----------------+ + * <-------------------------------(*1)-------------------------------* + * + * +15 +19 +20 +21 +23 +24 + * +-----------------+------------+----------------+----------+-----------+ + * |date/time(time_t)| 0x20 fixed |header level(=3)|file CRC16| creator | + * +-----------------+------------+----------------+----------+-----------+ + * *--------------------------------(*1)----------------------------------* + * + * +24 +28 +32 +32+(*3) + * +---------------+----------------+-------------------+-----------------+ + * |header size(*1)|next header size|extended header(*3)| compressed data | + * +---------------+----------------+-------------------+-----------------+ + * *------------------------(*1)-----------------------> <------(*2)-----> + * + */ +#define H3_FIELD_LEN_OFFSET 0 +#define H3_COMP_SIZE_OFFSET 7 +#define H3_ORIG_SIZE_OFFSET 11 +#define H3_TIME_OFFSET 15 +#define H3_CRC_OFFSET 21 +#define H3_HEADER_SIZE_OFFSET 24 +#define H3_FIXED_SIZE 28 +static int +lha_read_file_header_3(struct archive_read *a, struct lha *lha) +{ + const unsigned char *p; + size_t extdsize; + int err; + uint16_t header_crc; + + if ((p = __archive_read_ahead(a, H3_FIXED_SIZE, NULL)) == NULL) + return (truncated_error(a)); + + if (archive_le16dec(p + H3_FIELD_LEN_OFFSET) != 4) + goto invalid; + lha->header_size =archive_le32dec(p + H3_HEADER_SIZE_OFFSET); + lha->compsize = archive_le32dec(p + H3_COMP_SIZE_OFFSET); + lha->origsize = archive_le32dec(p + H3_ORIG_SIZE_OFFSET); + lha->mtime = archive_le32dec(p + H3_TIME_OFFSET); + lha->crc = archive_le16dec(p + H3_CRC_OFFSET); + lha->setflag |= CRC_IS_SET; + + if (lha->header_size < H3_FIXED_SIZE + 4) + goto invalid; + header_crc = lha_crc16(0, p, H3_FIXED_SIZE); + __archive_read_consume(a, H3_FIXED_SIZE); + + /* Read extended headers */ + err = lha_read_file_extended_header(a, lha, &header_crc, 4, + lha->header_size - H3_FIXED_SIZE, &extdsize); + if (err < ARCHIVE_WARN) + return (err); + + if (header_crc != lha->header_crc) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "LHa header CRC error"); + return (ARCHIVE_FATAL); + } + return (err); +invalid: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid LHa header"); + return (ARCHIVE_FATAL); +} + +/* + * Extended header format + * + * +0 +2 +3 -- used in header 1 and 2 + * +0 +4 +5 -- used in header 3 + * +--------------+---------+-------------------+--------------+-- + * |ex-header size|header id| data |ex-header size| ....... + * +--------------+---------+-------------------+--------------+-- + * <-------------( ex-header size)------------> <-- next extended header --* + * + * If the ex-header size is zero, it is the make of the end of extended + * headers. + * + */ +static int +lha_read_file_extended_header(struct archive_read *a, struct lha *lha, + uint16_t *crc, int sizefield_length, size_t limitsize, size_t *total_size) +{ + const void *h; + const unsigned char *extdheader; + size_t extdsize; + size_t datasize; + unsigned int i; + unsigned char extdtype; + +#define EXT_HEADER_CRC 0x00 /* Header CRC and information*/ +#define EXT_FILENAME 0x01 /* Filename */ +#define EXT_DIRECTORY 0x02 /* Directory name */ +#define EXT_DOS_ATTR 0x40 /* MS-DOS attribute */ +#define EXT_TIMESTAMP 0x41 /* Windows time stamp */ +#define EXT_FILESIZE 0x42 /* Large file size */ +#define EXT_TIMEZONE 0x43 /* Time zone */ +#define EXT_UTF16_FILENAME 0x44 /* UTF-16 filename */ +#define EXT_UTF16_DIRECTORY 0x45 /* UTF-16 directory name */ +#define EXT_CODEPAGE 0x46 /* Codepage */ +#define EXT_UNIX_MODE 0x50 /* File permission */ +#define EXT_UNIX_GID_UID 0x51 /* gid,uid */ +#define EXT_UNIX_GNAME 0x52 /* Group name */ +#define EXT_UNIX_UNAME 0x53 /* User name */ +#define EXT_UNIX_MTIME 0x54 /* Modified time */ +#define EXT_OS2_NEW_ATTR 0x7f /* new attribute(OS/2 only) */ +#define EXT_NEW_ATTR 0xff /* new attribute */ + + *total_size = sizefield_length; + + for (;;) { + /* Read an extended header size. */ + if ((h = + __archive_read_ahead(a, sizefield_length, NULL)) == NULL) + return (truncated_error(a)); + /* Check if the size is the zero indicates the end of the + * extended header. */ + if (sizefield_length == sizeof(uint16_t)) + extdsize = archive_le16dec(h); + else + extdsize = archive_le32dec(h); + if (extdsize == 0) { + /* End of extended header */ + if (crc != NULL) + *crc = lha_crc16(*crc, h, sizefield_length); + __archive_read_consume(a, sizefield_length); + return (ARCHIVE_OK); + } + + /* Sanity check to the extended header size. */ + if (((uint64_t)*total_size + extdsize) > + (uint64_t)limitsize || + extdsize <= (size_t)sizefield_length) + goto invalid; + + /* Read the extended header. */ + if ((h = __archive_read_ahead(a, extdsize, NULL)) == NULL) + return (truncated_error(a)); + *total_size += extdsize; + + extdheader = (const unsigned char *)h; + /* Get the extended header type. */ + extdtype = extdheader[sizefield_length]; + /* Calculate an extended data size. */ + datasize = extdsize - (1 + sizefield_length); + /* Skip an extended header size field and type field. */ + extdheader += sizefield_length + 1; + + if (crc != NULL && extdtype != EXT_HEADER_CRC) + *crc = lha_crc16(*crc, h, extdsize); + switch (extdtype) { + case EXT_HEADER_CRC: + /* We only use a header CRC. Following data will not + * be used. */ + if (datasize >= 2) { + lha->header_crc = archive_le16dec(extdheader); + if (crc != NULL) { + static const char zeros[2] = {0, 0}; + *crc = lha_crc16(*crc, h, + extdsize - datasize); + /* CRC value itself as zero */ + *crc = lha_crc16(*crc, zeros, 2); + *crc = lha_crc16(*crc, + extdheader+2, datasize - 2); + } + } + break; + case EXT_FILENAME: + if (datasize == 0) { + /* maybe directory header */ + archive_string_empty(&lha->filename); + break; + } + if (extdheader[0] == '\0') + goto invalid; + archive_strncpy(&lha->filename, + (const char *)extdheader, datasize); + break; + case EXT_DIRECTORY: + if (datasize == 0 || extdheader[0] == '\0') + /* no directory name data. exit this case. */ + goto invalid; + + archive_strncpy(&lha->dirname, + (const char *)extdheader, datasize); + /* + * Convert directory delimiter from 0xFF + * to '/' for local system. + */ + for (i = 0; i < lha->dirname.length; i++) { + if ((unsigned char)lha->dirname.s[i] == 0xFF) + lha->dirname.s[i] = '/'; + } + /* Is last character directory separator? */ + if (lha->dirname.s[lha->dirname.length-1] != '/') + /* invalid directory data */ + goto invalid; + break; + case EXT_DOS_ATTR: + if (datasize == 2) + lha->dos_attr = (unsigned char) + (archive_le16dec(extdheader) & 0xff); + break; + case EXT_TIMESTAMP: + if (datasize == (sizeof(uint64_t) * 3)) { + lha->birthtime = lha_win_time( + archive_le64dec(extdheader), + &lha->birthtime_tv_nsec); + extdheader += sizeof(uint64_t); + lha->mtime = lha_win_time( + archive_le64dec(extdheader), + &lha->mtime_tv_nsec); + extdheader += sizeof(uint64_t); + lha->atime = lha_win_time( + archive_le64dec(extdheader), + &lha->atime_tv_nsec); + lha->setflag |= BIRTHTIME_IS_SET | + ATIME_IS_SET; + } + break; + case EXT_FILESIZE: + if (datasize == sizeof(uint64_t) * 2) { + lha->compsize = archive_le64dec(extdheader); + extdheader += sizeof(uint64_t); + lha->origsize = archive_le64dec(extdheader); + } + break; + case EXT_CODEPAGE: + /* Get an archived filename charset from codepage. + * This overwrites the charset specified by + * hdrcharset option. */ + if (datasize == sizeof(uint32_t)) { + struct archive_string cp; + const char *charset; + + archive_string_init(&cp); + switch (archive_le32dec(extdheader)) { + case 65001: /* UTF-8 */ + charset = "UTF-8"; + break; + default: + archive_string_sprintf(&cp, "CP%d", + (int)archive_le32dec(extdheader)); + charset = cp.s; + break; + } + lha->sconv = + archive_string_conversion_from_charset( + &(a->archive), charset, 1); + archive_string_free(&cp); + if (lha->sconv == NULL) + return (ARCHIVE_FATAL); + } + break; + case EXT_UNIX_MODE: + if (datasize == sizeof(uint16_t)) { + lha->mode = archive_le16dec(extdheader); + lha->setflag |= UNIX_MODE_IS_SET; + } + break; + case EXT_UNIX_GID_UID: + if (datasize == (sizeof(uint16_t) * 2)) { + lha->gid = archive_le16dec(extdheader); + lha->uid = archive_le16dec(extdheader+2); + } + break; + case EXT_UNIX_GNAME: + if (datasize > 0) + archive_strncpy(&lha->gname, + (const char *)extdheader, datasize); + break; + case EXT_UNIX_UNAME: + if (datasize > 0) + archive_strncpy(&lha->uname, + (const char *)extdheader, datasize); + break; + case EXT_UNIX_MTIME: + if (datasize == sizeof(uint32_t)) + lha->mtime = archive_le32dec(extdheader); + break; + case EXT_OS2_NEW_ATTR: + /* This extended header is OS/2 depend. */ + if (datasize == 16) { + lha->dos_attr = (unsigned char) + (archive_le16dec(extdheader) & 0xff); + lha->mode = archive_le16dec(extdheader+2); + lha->gid = archive_le16dec(extdheader+4); + lha->uid = archive_le16dec(extdheader+6); + lha->birthtime = archive_le32dec(extdheader+8); + lha->atime = archive_le32dec(extdheader+12); + lha->setflag |= UNIX_MODE_IS_SET + | BIRTHTIME_IS_SET | ATIME_IS_SET; + } + break; + case EXT_NEW_ATTR: + if (datasize == 20) { + lha->mode = (mode_t)archive_le32dec(extdheader); + lha->gid = archive_le32dec(extdheader+4); + lha->uid = archive_le32dec(extdheader+8); + lha->birthtime = archive_le32dec(extdheader+12); + lha->atime = archive_le32dec(extdheader+16); + lha->setflag |= UNIX_MODE_IS_SET + | BIRTHTIME_IS_SET | ATIME_IS_SET; + } + break; + case EXT_TIMEZONE: /* Not supported */ + case EXT_UTF16_FILENAME: /* Not supported */ + case EXT_UTF16_DIRECTORY: /* Not supported */ + default: + break; + } + + __archive_read_consume(a, extdsize); + } +invalid: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid extended LHa header"); + return (ARCHIVE_FATAL); +} + +static int +lha_end_of_entry(struct archive_read *a) +{ + struct lha *lha = (struct lha *)(a->format->data); + int r = ARCHIVE_EOF; + + if (!lha->end_of_entry_cleanup) { + if ((lha->setflag & CRC_IS_SET) && + lha->crc != lha->entry_crc_calculated) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "LHa data CRC error"); + r = ARCHIVE_WARN; + } + + /* End-of-entry cleanup done. */ + lha->end_of_entry_cleanup = 1; + } + return (r); +} + +static int +archive_read_format_lha_read_data(struct archive_read *a, + const void **buff, size_t *size, int64_t *offset) +{ + struct lha *lha = (struct lha *)(a->format->data); + int r; + + if (lha->entry_unconsumed) { + /* Consume as much as the decompressor actually used. */ + __archive_read_consume(a, lha->entry_unconsumed); + lha->entry_unconsumed = 0; + } + if (lha->end_of_entry) { + *offset = lha->entry_offset; + *size = 0; + *buff = NULL; + return (lha_end_of_entry(a)); + } + + if (lha->entry_is_compressed) + r = lha_read_data_lzh(a, buff, size, offset); + else + /* No compression. */ + r = lha_read_data_none(a, buff, size, offset); + return (r); +} + +/* + * Read a file content in no compression. + * + * Returns ARCHIVE_OK if successful, ARCHIVE_FATAL otherwise, sets + * lha->end_of_entry if it consumes all of the data. + */ +static int +lha_read_data_none(struct archive_read *a, const void **buff, + size_t *size, int64_t *offset) +{ + struct lha *lha = (struct lha *)(a->format->data); + ssize_t bytes_avail; + + if (lha->entry_bytes_remaining == 0) { + *buff = NULL; + *size = 0; + *offset = lha->entry_offset; + lha->end_of_entry = 1; + return (ARCHIVE_OK); + } + /* + * Note: '1' here is a performance optimization. + * Recall that the decompression layer returns a count of + * available bytes; asking for more than that forces the + * decompressor to combine reads by copying data. + */ + *buff = __archive_read_ahead(a, 1, &bytes_avail); + if (bytes_avail <= 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated LHa file data"); + return (ARCHIVE_FATAL); + } + if (bytes_avail > lha->entry_bytes_remaining) + bytes_avail = (ssize_t)lha->entry_bytes_remaining; + lha->entry_crc_calculated = + lha_crc16(lha->entry_crc_calculated, *buff, bytes_avail); + *size = bytes_avail; + *offset = lha->entry_offset; + lha->entry_offset += bytes_avail; + lha->entry_bytes_remaining -= bytes_avail; + if (lha->entry_bytes_remaining == 0) + lha->end_of_entry = 1; + lha->entry_unconsumed = bytes_avail; + return (ARCHIVE_OK); +} + +/* + * Read a file content in LZHUFF encoding. + * + * Returns ARCHIVE_OK if successful, returns ARCHIVE_WARN if compression is + * unsupported, ARCHIVE_FATAL otherwise, sets lha->end_of_entry if it consumes + * all of the data. + */ +static int +lha_read_data_lzh(struct archive_read *a, const void **buff, + size_t *size, int64_t *offset) +{ + struct lha *lha = (struct lha *)(a->format->data); + ssize_t bytes_avail; + int r; + + /* If we haven't yet read any data, initialize the decompressor. */ + if (!lha->decompress_init) { + r = lzh_decode_init(&(lha->strm), lha->method); + switch (r) { + case ARCHIVE_OK: + break; + case ARCHIVE_FAILED: + /* Unsupported compression. */ + *buff = NULL; + *size = 0; + *offset = 0; + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Unsupported lzh compression method -%c%c%c-", + lha->method[0], lha->method[1], lha->method[2]); + /* We know compressed size; just skip it. */ + archive_read_format_lha_read_data_skip(a); + return (ARCHIVE_WARN); + default: + archive_set_error(&a->archive, ENOMEM, + "Couldn't allocate memory " + "for lzh decompression"); + return (ARCHIVE_FATAL); + } + /* We've initialized decompression for this stream. */ + lha->decompress_init = 1; + lha->strm.avail_out = 0; + lha->strm.total_out = 0; + } + + /* + * Note: '1' here is a performance optimization. + * Recall that the decompression layer returns a count of + * available bytes; asking for more than that forces the + * decompressor to combine reads by copying data. + */ + lha->strm.next_in = __archive_read_ahead(a, 1, &bytes_avail); + if (bytes_avail <= 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated LHa file body"); + return (ARCHIVE_FATAL); + } + if (bytes_avail > lha->entry_bytes_remaining) + bytes_avail = (ssize_t)lha->entry_bytes_remaining; + + lha->strm.avail_in = (int)bytes_avail; + lha->strm.total_in = 0; + lha->strm.avail_out = 0; + + r = lzh_decode(&(lha->strm), bytes_avail == lha->entry_bytes_remaining); + switch (r) { + case ARCHIVE_OK: + break; + case ARCHIVE_EOF: + lha->end_of_entry = 1; + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Bad lzh data"); + return (ARCHIVE_FAILED); + } + lha->entry_unconsumed = lha->strm.total_in; + lha->entry_bytes_remaining -= lha->strm.total_in; + + if (lha->strm.avail_out) { + *offset = lha->entry_offset; + *size = lha->strm.avail_out; + *buff = lha->strm.ref_ptr; + lha->entry_crc_calculated = + lha_crc16(lha->entry_crc_calculated, *buff, *size); + lha->entry_offset += *size; + } else { + *offset = lha->entry_offset; + *size = 0; + *buff = NULL; + if (lha->end_of_entry) + return (lha_end_of_entry(a)); + } + return (ARCHIVE_OK); +} + +/* + * Skip a file content. + */ +static int +archive_read_format_lha_read_data_skip(struct archive_read *a) +{ + struct lha *lha; + int64_t bytes_skipped; + + lha = (struct lha *)(a->format->data); + + if (lha->entry_unconsumed) { + /* Consume as much as the decompressor actually used. */ + __archive_read_consume(a, lha->entry_unconsumed); + lha->entry_unconsumed = 0; + } + + /* if we've already read to end of data, we're done. */ + if (lha->end_of_entry_cleanup) + return (ARCHIVE_OK); + + /* + * If the length is at the beginning, we can skip the + * compressed data much more quickly. + */ + bytes_skipped = __archive_read_consume(a, lha->entry_bytes_remaining); + if (bytes_skipped < 0) + return (ARCHIVE_FATAL); + + /* This entry is finished and done. */ + lha->end_of_entry_cleanup = lha->end_of_entry = 1; + return (ARCHIVE_OK); +} + +static int +archive_read_format_lha_cleanup(struct archive_read *a) +{ + struct lha *lha = (struct lha *)(a->format->data); + + lzh_decode_free(&(lha->strm)); + archive_string_free(&(lha->dirname)); + archive_string_free(&(lha->filename)); + archive_string_free(&(lha->uname)); + archive_string_free(&(lha->gname)); + archive_wstring_free(&(lha->ws)); + free(lha); + (a->format->data) = NULL; + return (ARCHIVE_OK); +} + +/* + * 'LHa for UNIX' utility has archived a symbolic-link name after + * a pathname with '|' character. + * This function extracts the symbolic-link name from the pathname. + * + * example. + * 1. a symbolic-name is 'aaa/bb/cc' + * 2. a filename is 'xxx/bbb' + * then a archived pathname is 'xxx/bbb|aaa/bb/cc' + */ +static int +lha_parse_linkname(struct archive_string *linkname, + struct archive_string *pathname) +{ + char * linkptr; + size_t symlen; + + linkptr = strchr(pathname->s, '|'); + if (linkptr != NULL) { + symlen = strlen(linkptr + 1); + archive_strncpy(linkname, linkptr+1, symlen); + + *linkptr = 0; + pathname->length = strlen(pathname->s); + + return (1); + } + return (0); +} + +/* Convert an MSDOS-style date/time into Unix-style time. */ +static time_t +lha_dos_time(const unsigned char *p) +{ + int msTime, msDate; + struct tm ts; + + msTime = archive_le16dec(p); + msDate = archive_le16dec(p+2); + + memset(&ts, 0, sizeof(ts)); + ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */ + ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */ + ts.tm_mday = msDate & 0x1f; /* Day of month. */ + ts.tm_hour = (msTime >> 11) & 0x1f; + ts.tm_min = (msTime >> 5) & 0x3f; + ts.tm_sec = (msTime << 1) & 0x3e; + ts.tm_isdst = -1; + return (mktime(&ts)); +} + +/* Convert an MS-Windows-style date/time into Unix-style time. */ +static time_t +lha_win_time(uint64_t wintime, long *ns) +{ +#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) + + if (wintime >= EPOC_TIME) { + wintime -= EPOC_TIME; /* 1970-01-01 00:00:00 (UTC) */ + if (ns != NULL) + *ns = (long)(wintime % 10000000) * 100; + return (wintime / 10000000); + } else { + if (ns != NULL) + *ns = 0; + return (0); + } +} + +static unsigned char +lha_calcsum(unsigned char sum, const void *pp, int offset, size_t size) +{ + unsigned char const *p = (unsigned char const *)pp; + + p += offset; + for (;size > 0; --size) + sum += *p++; + return (sum); +} + +static uint16_t crc16tbl[2][256]; +static void +lha_crc16_init(void) +{ + unsigned int i; + static int crc16init = 0; + + if (crc16init) + return; + crc16init = 1; + + for (i = 0; i < 256; i++) { + unsigned int j; + uint16_t crc = (uint16_t)i; + for (j = 8; j; j--) + crc = (crc >> 1) ^ ((crc & 1) * 0xA001); + crc16tbl[0][i] = crc; + } + + for (i = 0; i < 256; i++) { + crc16tbl[1][i] = (crc16tbl[0][i] >> 8) + ^ crc16tbl[0][crc16tbl[0][i] & 0xff]; + } +} + +static uint16_t +lha_crc16(uint16_t crc, const void *pp, size_t len) +{ + const unsigned char *p = (const unsigned char *)pp; + const uint16_t *buff; + const union { + uint32_t i; + char c[4]; + } u = { 0x01020304 }; + + if (len == 0) + return crc; + + /* Process unaligned address. */ + if (((uintptr_t)p) & (uintptr_t)0x1) { + crc = (crc >> 8) ^ crc16tbl[0][(crc ^ *p++) & 0xff]; + len--; + } + buff = (const uint16_t *)p; + /* + * Modern C compiler such as GCC does not unroll automatically yet + * without unrolling pragma, and Clang is so. So we should + * unroll this loop for its performance. + */ + for (;len >= 8; len -= 8) { + /* This if statement expects compiler optimization will - * remove the stament which will not be executed. */ ++ * remove the statement which will not be executed. */ ++#undef bswap16 +#ifndef __has_builtin +# define __has_builtin(x) 0 +#endif +#if defined(_MSC_VER) && _MSC_VER >= 1400 /* Visual Studio */ +# define bswap16(x) _byteswap_ushort(x) - #elif (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8) \ - || (defined(__clang__) && __has_builtin(__builtin_bswap16)) ++#elif defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || __GNUC__ > 4) ++/* GCC 4.8 and later has __builtin_bswap16() */ ++# define bswap16(x) __builtin_bswap16(x) ++#elif defined(__clang__) && __has_builtin(__builtin_bswap16) ++/* All clang versions have __builtin_bswap16() */ +# define bswap16(x) __builtin_bswap16(x) +#else +# define bswap16(x) ((((x) >> 8) & 0xff) | ((x) << 8)) +#endif +#define CRC16W do { \ + if(u.c[0] == 1) { /* Big endian */ \ + crc ^= bswap16(*buff); buff++; \ + } else \ + crc ^= *buff++; \ + crc = crc16tbl[1][crc & 0xff] ^ crc16tbl[0][crc >> 8];\ +} while (0) + CRC16W; + CRC16W; + CRC16W; + CRC16W; +#undef CRC16W +#undef bswap16 + } + + p = (const unsigned char *)buff; + for (;len; len--) { + crc = (crc >> 8) ^ crc16tbl[0][(crc ^ *p++) & 0xff]; + } + return crc; +} + +/* + * Initialize LZHUF decoder. + * + * Returns ARCHIVE_OK if initialization was successful. + * Returns ARCHIVE_FAILED if method is unsupported. + * Returns ARCHIVE_FATAL if initialization failed; memory allocation + * error occurred. + */ +static int +lzh_decode_init(struct lzh_stream *strm, const char *method) +{ + struct lzh_dec *ds; + int w_bits, w_size; + + if (strm->ds == NULL) { + strm->ds = calloc(1, sizeof(*strm->ds)); + if (strm->ds == NULL) + return (ARCHIVE_FATAL); + } + ds = strm->ds; + ds->error = ARCHIVE_FAILED; + if (method == NULL || method[0] != 'l' || method[1] != 'h') + return (ARCHIVE_FAILED); + switch (method[2]) { + case '5': + w_bits = 13;/* 8KiB for window */ + break; + case '6': + w_bits = 15;/* 32KiB for window */ + break; + case '7': + w_bits = 16;/* 64KiB for window */ + break; + default: + return (ARCHIVE_FAILED);/* Not supported. */ + } + ds->error = ARCHIVE_FATAL; + /* Expand a window size up to 128 KiB for decompressing process + * performance whatever its original window size is. */ + ds->w_size = 1U << 17; + ds->w_mask = ds->w_size -1; + if (ds->w_buff == NULL) { + ds->w_buff = malloc(ds->w_size); + if (ds->w_buff == NULL) + return (ARCHIVE_FATAL); + } + w_size = 1U << w_bits; + memset(ds->w_buff + ds->w_size - w_size, 0x20, w_size); + ds->w_pos = 0; + ds->state = 0; + ds->pos_pt_len_size = w_bits + 1; + ds->pos_pt_len_bits = (w_bits == 15 || w_bits == 16)? 5: 4; + ds->literal_pt_len_size = PT_BITLEN_SIZE; + ds->literal_pt_len_bits = 5; + ds->br.cache_buffer = 0; + ds->br.cache_avail = 0; + + if (lzh_huffman_init(&(ds->lt), LT_BITLEN_SIZE, 16) + != ARCHIVE_OK) + return (ARCHIVE_FATAL); + ds->lt.len_bits = 9; + if (lzh_huffman_init(&(ds->pt), PT_BITLEN_SIZE, 16) + != ARCHIVE_OK) + return (ARCHIVE_FATAL); + ds->error = 0; + + return (ARCHIVE_OK); +} + +/* + * Release LZHUF decoder. + */ +static void +lzh_decode_free(struct lzh_stream *strm) +{ + + if (strm->ds == NULL) + return; + free(strm->ds->w_buff); + lzh_huffman_free(&(strm->ds->lt)); + lzh_huffman_free(&(strm->ds->pt)); + free(strm->ds); + strm->ds = NULL; +} + +/* + * Bit stream reader. + */ +/* Check that the cache buffer has enough bits. */ +#define lzh_br_has(br, n) ((br)->cache_avail >= n) +/* Get compressed data by bit. */ +#define lzh_br_bits(br, n) \ + (((uint16_t)((br)->cache_buffer >> \ + ((br)->cache_avail - (n)))) & cache_masks[n]) +#define lzh_br_bits_forced(br, n) \ + (((uint16_t)((br)->cache_buffer << \ + ((n) - (br)->cache_avail))) & cache_masks[n]) +/* Read ahead to make sure the cache buffer has enough compressed data we + * will use. + * True : completed, there is enough data in the cache buffer. + * False : we met that strm->next_in is empty, we have to get following + * bytes. */ +#define lzh_br_read_ahead_0(strm, br, n) \ + (lzh_br_has(br, (n)) || lzh_br_fillup(strm, br)) +/* True : the cache buffer has some bits as much as we need. + * False : there are no enough bits in the cache buffer to be used, + * we have to get following bytes if we could. */ +#define lzh_br_read_ahead(strm, br, n) \ + (lzh_br_read_ahead_0((strm), (br), (n)) || lzh_br_has((br), (n))) + +/* Notify how many bits we consumed. */ +#define lzh_br_consume(br, n) ((br)->cache_avail -= (n)) +#define lzh_br_unconsume(br, n) ((br)->cache_avail += (n)) + +static const uint16_t cache_masks[] = { + 0x0000, 0x0001, 0x0003, 0x0007, + 0x000F, 0x001F, 0x003F, 0x007F, + 0x00FF, 0x01FF, 0x03FF, 0x07FF, + 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF +}; + +/* + * Shift away used bits in the cache data and fill it up with following bits. + * Call this when cache buffer does not have enough bits you need. + * + * Returns 1 if the cache buffer is full. + * Returns 0 if the cache buffer is not full; input buffer is empty. + */ +static int +lzh_br_fillup(struct lzh_stream *strm, struct lzh_br *br) +{ + int n = CACHE_BITS - br->cache_avail; + + for (;;) { + const int x = n >> 3; + if (strm->avail_in >= x) { + switch (x) { + case 8: + br->cache_buffer = + ((uint64_t)strm->next_in[0]) << 56 | + ((uint64_t)strm->next_in[1]) << 48 | + ((uint64_t)strm->next_in[2]) << 40 | + ((uint64_t)strm->next_in[3]) << 32 | + ((uint32_t)strm->next_in[4]) << 24 | + ((uint32_t)strm->next_in[5]) << 16 | + ((uint32_t)strm->next_in[6]) << 8 | + (uint32_t)strm->next_in[7]; + strm->next_in += 8; + strm->avail_in -= 8; + br->cache_avail += 8 * 8; + return (1); + case 7: + br->cache_buffer = + (br->cache_buffer << 56) | + ((uint64_t)strm->next_in[0]) << 48 | + ((uint64_t)strm->next_in[1]) << 40 | + ((uint64_t)strm->next_in[2]) << 32 | + ((uint32_t)strm->next_in[3]) << 24 | + ((uint32_t)strm->next_in[4]) << 16 | + ((uint32_t)strm->next_in[5]) << 8 | + (uint32_t)strm->next_in[6]; + strm->next_in += 7; + strm->avail_in -= 7; + br->cache_avail += 7 * 8; + return (1); + case 6: + br->cache_buffer = + (br->cache_buffer << 48) | + ((uint64_t)strm->next_in[0]) << 40 | + ((uint64_t)strm->next_in[1]) << 32 | + ((uint32_t)strm->next_in[2]) << 24 | + ((uint32_t)strm->next_in[3]) << 16 | + ((uint32_t)strm->next_in[4]) << 8 | + (uint32_t)strm->next_in[5]; + strm->next_in += 6; + strm->avail_in -= 6; + br->cache_avail += 6 * 8; + return (1); + case 0: + /* We have enough compressed data in + * the cache buffer.*/ + return (1); + default: + break; + } + } + if (strm->avail_in == 0) { + /* There is not enough compressed data to fill up the + * cache buffer. */ + return (0); + } + br->cache_buffer = + (br->cache_buffer << 8) | *strm->next_in++; + strm->avail_in--; + br->cache_avail += 8; + n -= 8; + } +} + +/* + * Decode LZHUF. + * + * 1. Returns ARCHIVE_OK if output buffer or input buffer are empty. + * Please set available buffer and call this function again. + * 2. Returns ARCHIVE_EOF if decompression has been completed. + * 3. Returns ARCHIVE_FAILED if an error occurred; compressed data + * is broken or you do not set 'last' flag properly. + * 4. 'last' flag is very important, you must set 1 to the flag if there + * is no input data. The lha compressed data format does not provide how + * to know the compressed data is really finished. + * Note: lha command utility check if the total size of output bytes is + * reached the uncompressed size recorded in its header. it does not mind + * that the decoding process is properly finished. + * GNU ZIP can decompress another compressed file made by SCO LZH compress. + * it handles EOF as null to fill read buffer with zero until the decoding + * process meet 2 bytes of zeros at reading a size of a next chunk, so the + * zeros are treated as the mark of the end of the data although the zeros + * is dummy, not the file data. + */ +static int lzh_read_blocks(struct lzh_stream *, int); +static int lzh_decode_blocks(struct lzh_stream *, int); +#define ST_RD_BLOCK 0 +#define ST_RD_PT_1 1 +#define ST_RD_PT_2 2 +#define ST_RD_PT_3 3 +#define ST_RD_PT_4 4 +#define ST_RD_LITERAL_1 5 +#define ST_RD_LITERAL_2 6 +#define ST_RD_LITERAL_3 7 +#define ST_RD_POS_DATA_1 8 +#define ST_GET_LITERAL 9 +#define ST_GET_POS_1 10 +#define ST_GET_POS_2 11 +#define ST_COPY_DATA 12 + +static int +lzh_decode(struct lzh_stream *strm, int last) +{ + struct lzh_dec *ds = strm->ds; + int avail_in; + int r; + + if (ds->error) + return (ds->error); + + avail_in = strm->avail_in; + do { + if (ds->state < ST_GET_LITERAL) + r = lzh_read_blocks(strm, last); + else + r = lzh_decode_blocks(strm, last); + } while (r == 100); + strm->total_in += avail_in - strm->avail_in; + return (r); +} + +static void +lzh_emit_window(struct lzh_stream *strm, size_t s) +{ + strm->ref_ptr = strm->ds->w_buff; + strm->avail_out = (int)s; + strm->total_out += s; +} + +static int +lzh_read_blocks(struct lzh_stream *strm, int last) +{ + struct lzh_dec *ds = strm->ds; + struct lzh_br *br = &(ds->br); + int c = 0, i; + unsigned rbits; + + for (;;) { + switch (ds->state) { + case ST_RD_BLOCK: + /* + * Read a block number indicates how many blocks + * we will handle. The block is composed of a + * literal and a match, sometimes a literal only + * in particular, there are no reference data at + * the beginning of the decompression. + */ + if (!lzh_br_read_ahead_0(strm, br, 16)) { + if (!last) + /* We need following data. */ + return (ARCHIVE_OK); + if (lzh_br_has(br, 8)) { + /* + * It seems there are extra bits. + * 1. Compressed data is broken. + * 2. `last' flag does not properly + * set. + */ + goto failed; + } + if (ds->w_pos > 0) { + lzh_emit_window(strm, ds->w_pos); + ds->w_pos = 0; + return (ARCHIVE_OK); + } + /* End of compressed data; we have completely + * handled all compressed data. */ + return (ARCHIVE_EOF); + } + ds->blocks_avail = lzh_br_bits(br, 16); + if (ds->blocks_avail == 0) + goto failed; + lzh_br_consume(br, 16); + /* + * Read a literal table compressed in huffman + * coding. + */ + ds->pt.len_size = ds->literal_pt_len_size; + ds->pt.len_bits = ds->literal_pt_len_bits; + ds->reading_position = 0; + /* FALL THROUGH */ + case ST_RD_PT_1: + /* Note: ST_RD_PT_1, ST_RD_PT_2 and ST_RD_PT_4 are + * used in reading both a literal table and a + * position table. */ + if (!lzh_br_read_ahead(strm, br, ds->pt.len_bits)) { + if (last) + goto failed;/* Truncated data. */ + ds->state = ST_RD_PT_1; + return (ARCHIVE_OK); + } + ds->pt.len_avail = lzh_br_bits(br, ds->pt.len_bits); + lzh_br_consume(br, ds->pt.len_bits); + /* FALL THROUGH */ + case ST_RD_PT_2: + if (ds->pt.len_avail == 0) { + /* There is no bitlen. */ + if (!lzh_br_read_ahead(strm, br, + ds->pt.len_bits)) { + if (last) + goto failed;/* Truncated data.*/ + ds->state = ST_RD_PT_2; + return (ARCHIVE_OK); + } + if (!lzh_make_fake_table(&(ds->pt), + lzh_br_bits(br, ds->pt.len_bits))) + goto failed;/* Invalid data. */ + lzh_br_consume(br, ds->pt.len_bits); + if (ds->reading_position) + ds->state = ST_GET_LITERAL; + else + ds->state = ST_RD_LITERAL_1; + break; + } else if (ds->pt.len_avail > ds->pt.len_size) + goto failed;/* Invalid data. */ + ds->loop = 0; + memset(ds->pt.freq, 0, sizeof(ds->pt.freq)); + if (ds->pt.len_avail < 3 || + ds->pt.len_size == ds->pos_pt_len_size) { + ds->state = ST_RD_PT_4; + break; + } + /* FALL THROUGH */ + case ST_RD_PT_3: + ds->loop = lzh_read_pt_bitlen(strm, ds->loop, 3); + if (ds->loop < 3) { + if (ds->loop < 0 || last) + goto failed;/* Invalid data. */ + /* Not completed, get following data. */ + ds->state = ST_RD_PT_3; + return (ARCHIVE_OK); + } + /* There are some null in bitlen of the literal. */ + if (!lzh_br_read_ahead(strm, br, 2)) { + if (last) + goto failed;/* Truncated data. */ + ds->state = ST_RD_PT_3; + return (ARCHIVE_OK); + } + c = lzh_br_bits(br, 2); + lzh_br_consume(br, 2); + if (c > ds->pt.len_avail - 3) + goto failed;/* Invalid data. */ + for (i = 3; c-- > 0 ;) + ds->pt.bitlen[i++] = 0; + ds->loop = i; + /* FALL THROUGH */ + case ST_RD_PT_4: + ds->loop = lzh_read_pt_bitlen(strm, ds->loop, + ds->pt.len_avail); + if (ds->loop < ds->pt.len_avail) { + if (ds->loop < 0 || last) + goto failed;/* Invalid data. */ + /* Not completed, get following data. */ + ds->state = ST_RD_PT_4; + return (ARCHIVE_OK); + } + if (!lzh_make_huffman_table(&(ds->pt))) + goto failed;/* Invalid data */ + if (ds->reading_position) { + ds->state = ST_GET_LITERAL; + break; + } + /* FALL THROUGH */ + case ST_RD_LITERAL_1: + if (!lzh_br_read_ahead(strm, br, ds->lt.len_bits)) { + if (last) + goto failed;/* Truncated data. */ + ds->state = ST_RD_LITERAL_1; + return (ARCHIVE_OK); + } + ds->lt.len_avail = lzh_br_bits(br, ds->lt.len_bits); + lzh_br_consume(br, ds->lt.len_bits); + /* FALL THROUGH */ + case ST_RD_LITERAL_2: + if (ds->lt.len_avail == 0) { + /* There is no bitlen. */ + if (!lzh_br_read_ahead(strm, br, + ds->lt.len_bits)) { + if (last) + goto failed;/* Truncated data.*/ + ds->state = ST_RD_LITERAL_2; + return (ARCHIVE_OK); + } + if (!lzh_make_fake_table(&(ds->lt), + lzh_br_bits(br, ds->lt.len_bits))) + goto failed;/* Invalid data */ + lzh_br_consume(br, ds->lt.len_bits); + ds->state = ST_RD_POS_DATA_1; + break; + } else if (ds->lt.len_avail > ds->lt.len_size) + goto failed;/* Invalid data */ + ds->loop = 0; + memset(ds->lt.freq, 0, sizeof(ds->lt.freq)); + /* FALL THROUGH */ + case ST_RD_LITERAL_3: + i = ds->loop; + while (i < ds->lt.len_avail) { + if (!lzh_br_read_ahead(strm, br, + ds->pt.max_bits)) { + if (last) + goto failed;/* Truncated data.*/ + ds->loop = i; + ds->state = ST_RD_LITERAL_3; + return (ARCHIVE_OK); + } + rbits = lzh_br_bits(br, ds->pt.max_bits); + c = lzh_decode_huffman(&(ds->pt), rbits); + if (c > 2) { + /* Note: 'c' will never be more than + * eighteen since it's limited by + * PT_BITLEN_SIZE, which is being set + * to ds->pt.len_size through + * ds->literal_pt_len_size. */ + lzh_br_consume(br, ds->pt.bitlen[c]); + c -= 2; + ds->lt.freq[c]++; + ds->lt.bitlen[i++] = c; + } else if (c == 0) { + lzh_br_consume(br, ds->pt.bitlen[c]); + ds->lt.bitlen[i++] = 0; + } else { + /* c == 1 or c == 2 */ + int n = (c == 1)?4:9; + if (!lzh_br_read_ahead(strm, br, + ds->pt.bitlen[c] + n)) { + if (last) /* Truncated data. */ + goto failed; + ds->loop = i; + ds->state = ST_RD_LITERAL_3; + return (ARCHIVE_OK); + } + lzh_br_consume(br, ds->pt.bitlen[c]); + c = lzh_br_bits(br, n); + lzh_br_consume(br, n); + c += (n == 4)?3:20; + if (i + c > ds->lt.len_avail) + goto failed;/* Invalid data */ + memset(&(ds->lt.bitlen[i]), 0, c); + i += c; + } + } + if (i > ds->lt.len_avail || + !lzh_make_huffman_table(&(ds->lt))) + goto failed;/* Invalid data */ + /* FALL THROUGH */ + case ST_RD_POS_DATA_1: + /* + * Read a position table compressed in huffman + * coding. + */ + ds->pt.len_size = ds->pos_pt_len_size; + ds->pt.len_bits = ds->pos_pt_len_bits; + ds->reading_position = 1; + ds->state = ST_RD_PT_1; + break; + case ST_GET_LITERAL: + return (100); + } + } +failed: + return (ds->error = ARCHIVE_FAILED); +} + +static int +lzh_decode_blocks(struct lzh_stream *strm, int last) +{ + struct lzh_dec *ds = strm->ds; + struct lzh_br bre = ds->br; + struct huffman *lt = &(ds->lt); + struct huffman *pt = &(ds->pt); + unsigned char *w_buff = ds->w_buff; + unsigned char *lt_bitlen = lt->bitlen; + unsigned char *pt_bitlen = pt->bitlen; + int blocks_avail = ds->blocks_avail, c = 0; + int copy_len = ds->copy_len, copy_pos = ds->copy_pos; + int w_pos = ds->w_pos, w_mask = ds->w_mask, w_size = ds->w_size; + int lt_max_bits = lt->max_bits, pt_max_bits = pt->max_bits; + int state = ds->state; + + for (;;) { + switch (state) { + case ST_GET_LITERAL: + for (;;) { + if (blocks_avail == 0) { + /* We have decoded all blocks. + * Let's handle next blocks. */ + ds->state = ST_RD_BLOCK; + ds->br = bre; + ds->blocks_avail = 0; + ds->w_pos = w_pos; + ds->copy_pos = 0; + return (100); + } + + /* lzh_br_read_ahead() always try to fill the + * cache buffer up. In specific situation we + * are close to the end of the data, the cache + * buffer will not be full and thus we have to + * determine if the cache buffer has some bits + * as much as we need after lzh_br_read_ahead() + * failed. */ + if (!lzh_br_read_ahead(strm, &bre, + lt_max_bits)) { + if (!last) + goto next_data; + /* Remaining bits are less than + * maximum bits(lt.max_bits) but maybe + * it still remains as much as we need, + * so we should try to use it with + * dummy bits. */ + c = lzh_decode_huffman(lt, + lzh_br_bits_forced(&bre, + lt_max_bits)); + lzh_br_consume(&bre, lt_bitlen[c]); + if (!lzh_br_has(&bre, 0)) + goto failed;/* Over read. */ + } else { + c = lzh_decode_huffman(lt, + lzh_br_bits(&bre, lt_max_bits)); + lzh_br_consume(&bre, lt_bitlen[c]); + } + blocks_avail--; + if (c > UCHAR_MAX) + /* Current block is a match data. */ + break; + /* + * 'c' is exactly a literal code. + */ + /* Save a decoded code to reference it + * afterward. */ + w_buff[w_pos] = c; + if (++w_pos >= w_size) { + w_pos = 0; + lzh_emit_window(strm, w_size); + goto next_data; + } + } + /* 'c' is the length of a match pattern we have + * already extracted, which has be stored in + * window(ds->w_buff). */ + copy_len = c - (UCHAR_MAX + 1) + MINMATCH; + /* FALL THROUGH */ + case ST_GET_POS_1: + /* + * Get a reference position. + */ + if (!lzh_br_read_ahead(strm, &bre, pt_max_bits)) { + if (!last) { + state = ST_GET_POS_1; + ds->copy_len = copy_len; + goto next_data; + } + copy_pos = lzh_decode_huffman(pt, + lzh_br_bits_forced(&bre, pt_max_bits)); + lzh_br_consume(&bre, pt_bitlen[copy_pos]); + if (!lzh_br_has(&bre, 0)) + goto failed;/* Over read. */ + } else { + copy_pos = lzh_decode_huffman(pt, + lzh_br_bits(&bre, pt_max_bits)); + lzh_br_consume(&bre, pt_bitlen[copy_pos]); + } + /* FALL THROUGH */ + case ST_GET_POS_2: + if (copy_pos > 1) { + /* We need an additional adjustment number to + * the position. */ + int p = copy_pos - 1; + if (!lzh_br_read_ahead(strm, &bre, p)) { + if (last) + goto failed;/* Truncated data.*/ + state = ST_GET_POS_2; + ds->copy_len = copy_len; + ds->copy_pos = copy_pos; + goto next_data; + } + copy_pos = (1 << p) + lzh_br_bits(&bre, p); + lzh_br_consume(&bre, p); + } + /* The position is actually a distance from the last + * code we had extracted and thus we have to convert + * it to a position of the window. */ + copy_pos = (w_pos - copy_pos - 1) & w_mask; + /* FALL THROUGH */ + case ST_COPY_DATA: + /* + * Copy `copy_len' bytes as extracted data from + * the window into the output buffer. + */ + for (;;) { + int l; + + l = copy_len; + if (copy_pos > w_pos) { + if (l > w_size - copy_pos) + l = w_size - copy_pos; + } else { + if (l > w_size - w_pos) + l = w_size - w_pos; + } + if ((copy_pos + l < w_pos) + || (w_pos + l < copy_pos)) { + /* No overlap. */ + memcpy(w_buff + w_pos, + w_buff + copy_pos, l); + } else { + const unsigned char *s; + unsigned char *d; + int li; + + d = w_buff + w_pos; + s = w_buff + copy_pos; + for (li = 0; li < l-1;) { + d[li] = s[li];li++; + d[li] = s[li];li++; + } + if (li < l) + d[li] = s[li]; + } + w_pos += l; + if (w_pos == w_size) { + w_pos = 0; + lzh_emit_window(strm, w_size); + if (copy_len <= l) + state = ST_GET_LITERAL; + else { + state = ST_COPY_DATA; + ds->copy_len = copy_len - l; + ds->copy_pos = + (copy_pos + l) & w_mask; + } + goto next_data; + } + if (copy_len <= l) + /* A copy of current pattern ended. */ + break; + copy_len -= l; + copy_pos = (copy_pos + l) & w_mask; + } + state = ST_GET_LITERAL; + break; + } + } +failed: + return (ds->error = ARCHIVE_FAILED); +next_data: + ds->br = bre; + ds->blocks_avail = blocks_avail; + ds->state = state; + ds->w_pos = w_pos; + return (ARCHIVE_OK); +} + +static int +lzh_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits) +{ + int bits; + + if (hf->bitlen == NULL) { + hf->bitlen = malloc(len_size * sizeof(hf->bitlen[0])); + if (hf->bitlen == NULL) + return (ARCHIVE_FATAL); + } + 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])); + if (hf->tbl == NULL) + return (ARCHIVE_FATAL); + } + 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); + } + hf->len_size = (int)len_size; + hf->tbl_bits = tbl_bits; + return (ARCHIVE_OK); +} + +static void +lzh_huffman_free(struct huffman *hf) +{ + free(hf->bitlen); + free(hf->tbl); + free(hf->tree); +} + +static 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 16, 0 +}; +static int +lzh_read_pt_bitlen(struct lzh_stream *strm, int start, int end) +{ + struct lzh_dec *ds = strm->ds; + struct lzh_br *br = &(ds->br); + int c, i; + + for (i = start; i < end; ) { + /* + * bit pattern the number we need + * 000 -> 0 + * 001 -> 1 + * 010 -> 2 + * ... + * 110 -> 6 + * 1110 -> 7 + * 11110 -> 8 + * ... + * 1111111111110 -> 16 + */ + if (!lzh_br_read_ahead(strm, br, 3)) + return (i); + if ((c = lzh_br_bits(br, 3)) == 7) { + if (!lzh_br_read_ahead(strm, br, 13)) + return (i); + c = bitlen_tbl[lzh_br_bits(br, 13) & 0x3FF]; + if (c) + lzh_br_consume(br, c - 3); + else + return (-1);/* Invalid data. */ + } else + lzh_br_consume(br, 3); + ds->pt.bitlen[i++] = c; + ds->pt.freq[c]++; + } + return (i); +} + +static int +lzh_make_fake_table(struct huffman *hf, uint16_t c) +{ + if (c >= hf->len_size) + return (0); + hf->tbl[0] = c; + hf->max_bits = 0; + hf->shift_bits = 0; + hf->bitlen[hf->tbl[0]] = 0; + return (1); +} + +/* + * Make a huffman coding table. + */ +static int +lzh_make_huffman_table(struct huffman *hf) +{ + uint16_t *tbl; + const unsigned char *bitlen; + int bitptn[17], weight[17]; + int i, maxbits = 0, ptn, tbl_size, w; + int diffbits, len_avail; + + /* + * Initialize bit patterns. + */ + ptn = 0; + for (i = 1, w = 1 << 15; i <= 16; i++, w >>= 1) { + bitptn[i] = ptn; + weight[i] = w; + if (hf->freq[i]) { + ptn += hf->freq[i] * w; + maxbits = i; + } + } + if (ptn != 0x10000 || maxbits > hf->tbl_bits) + return (0);/* Invalid */ + + hf->max_bits = maxbits; + + /* + * Cut out extra bits which we won't house in the table. + * This preparation reduces the same calculation in the for-loop + * making the table. + */ + if (maxbits < 16) { + int ebits = 16 - maxbits; + for (i = 1; i <= maxbits; i++) { + bitptn[i] >>= ebits; + weight[i] >>= ebits; + } + } + if (maxbits > HTBL_BITS) { + unsigned 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<shift_bits = diffbits; + + /* + * Make the table. + */ + tbl_size = 1 << HTBL_BITS; + tbl = hf->tbl; + bitlen = hf->bitlen; + len_avail = hf->len_avail; + hf->tree_used = 0; + 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]; + 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]); + if (cnt > 7) { + uint16_t *pc; + + cnt -= 8; + pc = &p[cnt]; + pc[0] = (uint16_t)i; + pc[1] = (uint16_t)i; + pc[2] = (uint16_t)i; + pc[3] = (uint16_t)i; + pc[4] = (uint16_t)i; + pc[5] = (uint16_t)i; + pc[6] = (uint16_t)i; + pc[7] = (uint16_t)i; + if (cnt > 7) { + cnt -= 8; + memcpy(&p[cnt], pc, + 8 * sizeof(uint16_t)); + pc = &p[cnt]; + while (cnt > 15) { + cnt -= 16; + memcpy(&p[cnt], pc, + 16 * sizeof(uint16_t)); + } + } + if (cnt) + memcpy(p, pc, cnt * sizeof(uint16_t)); + } else { + while (cnt > 1) { + p[--cnt] = (uint16_t)i; + p[--cnt] = (uint16_t)i; + } + if (cnt) + 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; + } + } + return (1); +} + +static int +lzh_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_avail) { + c -= hf->len_avail; + 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 +lzh_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]; + if (c < hf->len_avail || hf->len_avail == 0) + return (c); + /* This bit pattern needs to be found out at a huffman tree. */ + return (lzh_decode_huffman_tree(hf, rbits, c)); +} + diff --cc Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c index fc8153f,0000000..658d49d mode 100644,000000..100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_rar.c @@@ -1,2954 -1,0 +1,2953 @@@ +/*- +* Copyright (c) 2003-2007 Tim Kientzle +* Copyright (c) 2011 Andres Mejia +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "archive_platform.h" + +#ifdef HAVE_ERRNO_H +#include +#endif +#include +#include +#ifdef HAVE_ZLIB_H +#include /* crc32 */ +#endif + +#include "archive.h" +#ifndef HAVE_ZLIB_H +#include "archive_crc32.h" +#endif +#include "archive_endian.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_ppmd7_private.h" +#include "archive_private.h" +#include "archive_read_private.h" + +/* RAR signature, also known as the mark header */ +#define RAR_SIGNATURE "\x52\x61\x72\x21\x1A\x07\x00" + +/* Header types */ +#define MARK_HEAD 0x72 +#define MAIN_HEAD 0x73 +#define FILE_HEAD 0x74 +#define COMM_HEAD 0x75 +#define AV_HEAD 0x76 +#define SUB_HEAD 0x77 +#define PROTECT_HEAD 0x78 +#define SIGN_HEAD 0x79 +#define NEWSUB_HEAD 0x7a +#define ENDARC_HEAD 0x7b + +/* Main Header Flags */ +#define MHD_VOLUME 0x0001 +#define MHD_COMMENT 0x0002 +#define MHD_LOCK 0x0004 +#define MHD_SOLID 0x0008 +#define MHD_NEWNUMBERING 0x0010 +#define MHD_AV 0x0020 +#define MHD_PROTECT 0x0040 +#define MHD_PASSWORD 0x0080 +#define MHD_FIRSTVOLUME 0x0100 +#define MHD_ENCRYPTVER 0x0200 + +/* Flags common to all headers */ +#define HD_MARKDELETION 0x4000 +#define HD_ADD_SIZE_PRESENT 0x8000 + +/* File Header Flags */ +#define FHD_SPLIT_BEFORE 0x0001 +#define FHD_SPLIT_AFTER 0x0002 +#define FHD_PASSWORD 0x0004 +#define FHD_COMMENT 0x0008 +#define FHD_SOLID 0x0010 +#define FHD_LARGE 0x0100 +#define FHD_UNICODE 0x0200 +#define FHD_SALT 0x0400 +#define FHD_VERSION 0x0800 +#define FHD_EXTTIME 0x1000 +#define FHD_EXTFLAGS 0x2000 + +/* File dictionary sizes */ +#define DICTIONARY_SIZE_64 0x00 +#define DICTIONARY_SIZE_128 0x20 +#define DICTIONARY_SIZE_256 0x40 +#define DICTIONARY_SIZE_512 0x60 +#define DICTIONARY_SIZE_1024 0x80 +#define DICTIONARY_SIZE_2048 0xA0 +#define DICTIONARY_SIZE_4096 0xC0 +#define FILE_IS_DIRECTORY 0xE0 +#define DICTIONARY_MASK FILE_IS_DIRECTORY + +/* OS Flags */ +#define OS_MSDOS 0 +#define OS_OS2 1 +#define OS_WIN32 2 +#define OS_UNIX 3 +#define OS_MAC_OS 4 +#define OS_BEOS 5 + +/* Compression Methods */ +#define COMPRESS_METHOD_STORE 0x30 +/* LZSS */ +#define COMPRESS_METHOD_FASTEST 0x31 +#define COMPRESS_METHOD_FAST 0x32 +#define COMPRESS_METHOD_NORMAL 0x33 +/* PPMd Variant H */ +#define COMPRESS_METHOD_GOOD 0x34 +#define COMPRESS_METHOD_BEST 0x35 + +#define CRC_POLYNOMIAL 0xEDB88320 + +#define NS_UNIT 10000000 + +#define DICTIONARY_MAX_SIZE 0x400000 + +#define MAINCODE_SIZE 299 +#define OFFSETCODE_SIZE 60 +#define LOWOFFSETCODE_SIZE 17 +#define LENGTHCODE_SIZE 28 +#define HUFFMAN_TABLE_SIZE \ + MAINCODE_SIZE + OFFSETCODE_SIZE + LOWOFFSETCODE_SIZE + LENGTHCODE_SIZE + +#define MAX_SYMBOL_LENGTH 0xF +#define MAX_SYMBOLS 20 + +/* + * Considering L1,L2 cache miss and a calling of write system-call, + * the best size of the output buffer(uncompressed buffer) is 128K. + * If the structure of extracting process is changed, this value + * might be researched again. + */ +#define UNP_BUFFER_SIZE (128 * 1024) + +/* Define this here for non-Windows platforms */ +#if !((defined(__WIN32__) || defined(_WIN32) || defined(__WIN32)) && !defined(__CYGWIN__)) +#define FILE_ATTRIBUTE_DIRECTORY 0x10 +#endif + +/* Fields common to all headers */ +struct rar_header +{ + char crc[2]; + char type; + char flags[2]; + char size[2]; +}; + +/* Fields common to all file headers */ +struct rar_file_header +{ + char pack_size[4]; + char unp_size[4]; + char host_os; + char file_crc[4]; + char file_time[4]; + char unp_ver; + char method; + char name_size[2]; + char file_attr[4]; +}; + +struct huffman_tree_node +{ + int branches[2]; +}; + +struct huffman_table_entry +{ + unsigned int length; + int value; +}; + +struct huffman_code +{ + struct huffman_tree_node *tree; + int numentries; + int numallocatedentries; + int minlength; + int maxlength; + int tablesize; + struct huffman_table_entry *table; +}; + +struct lzss +{ + unsigned char *window; + int mask; + int64_t position; +}; + +struct data_block_offsets +{ + int64_t header_size; + int64_t start_offset; + int64_t end_offset; +}; + +struct rar +{ + /* Entries from main RAR header */ + unsigned main_flags; + unsigned long file_crc; + char reserved1[2]; + char reserved2[4]; + char encryptver; + + /* File header entries */ + char compression_method; + unsigned file_flags; + int64_t packed_size; + int64_t unp_size; + time_t mtime; + long mnsec; + mode_t mode; + char *filename; + char *filename_save; + size_t filename_save_size; + size_t filename_allocated; + + /* File header optional entries */ + char salt[8]; + time_t atime; + long ansec; + time_t ctime; + long cnsec; + time_t arctime; + long arcnsec; + + /* Fields to help with tracking decompression of files. */ + int64_t bytes_unconsumed; + int64_t bytes_remaining; + int64_t bytes_uncopied; + int64_t offset; + int64_t offset_outgoing; + int64_t offset_seek; + char valid; + unsigned int unp_offset; + unsigned int unp_buffer_size; + unsigned char *unp_buffer; + unsigned int dictionary_size; + char start_new_block; + char entry_eof; + unsigned long crc_calculated; + int found_first_header; + char has_endarc_header; + struct data_block_offsets *dbo; + unsigned int cursor; + unsigned int nodes; + + /* LZSS members */ + struct huffman_code maincode; + struct huffman_code offsetcode; + struct huffman_code lowoffsetcode; + struct huffman_code lengthcode; + unsigned char lengthtable[HUFFMAN_TABLE_SIZE]; + struct lzss lzss; + char output_last_match; + unsigned int lastlength; + unsigned int lastoffset; + unsigned int oldoffset[4]; + unsigned int lastlowoffset; + unsigned int numlowoffsetrepeats; + int64_t filterstart; + char start_new_table; + + /* PPMd Variant H members */ + char ppmd_valid; + char ppmd_eod; + char is_ppmd_block; + int ppmd_escape; + CPpmd7 ppmd7_context; + CPpmd7z_RangeDec range_dec; + IByteIn bytein; + + /* + * String conversion object. + */ + int init_default_conversion; + struct archive_string_conv *sconv_default; + struct archive_string_conv *opt_sconv; + struct archive_string_conv *sconv_utf8; + struct archive_string_conv *sconv_utf16be; + + /* + * Bit stream reader. + */ + struct rar_br { +#define CACHE_TYPE uint64_t +#define CACHE_BITS (8 * sizeof(CACHE_TYPE)) + /* Cache buffer. */ + CACHE_TYPE cache_buffer; + /* Indicates how many bits avail in cache_buffer. */ + int cache_avail; + ssize_t avail_in; + const unsigned char *next_in; + } br; + + /* + * Custom field to denote that this archive contains encrypted entries + */ + int has_encrypted_entries; +}; + +static int archive_read_support_format_rar_capabilities(struct archive_read *); +static int archive_read_format_rar_has_encrypted_entries(struct archive_read *); +static int archive_read_format_rar_bid(struct archive_read *, int); +static int archive_read_format_rar_options(struct archive_read *, + const char *, const char *); +static int archive_read_format_rar_read_header(struct archive_read *, + struct archive_entry *); +static int archive_read_format_rar_read_data(struct archive_read *, + const void **, size_t *, int64_t *); +static int archive_read_format_rar_read_data_skip(struct archive_read *a); +static int64_t archive_read_format_rar_seek_data(struct archive_read *, int64_t, + int); +static int archive_read_format_rar_cleanup(struct archive_read *); + +/* Support functions */ +static int read_header(struct archive_read *, struct archive_entry *, char); +static time_t get_time(int); +static int read_exttime(const char *, struct rar *, const char *); +static int read_symlink_stored(struct archive_read *, struct archive_entry *, + struct archive_string_conv *); +static int read_data_stored(struct archive_read *, const void **, size_t *, + int64_t *); +static int read_data_compressed(struct archive_read *, const void **, size_t *, + int64_t *); +static int rar_br_preparation(struct archive_read *, struct rar_br *); +static int parse_codes(struct archive_read *); +static void free_codes(struct archive_read *); +static int read_next_symbol(struct archive_read *, struct huffman_code *); +static int create_code(struct archive_read *, struct huffman_code *, + unsigned char *, int, char); +static int add_value(struct archive_read *, struct huffman_code *, int, int, + int); +static int new_node(struct huffman_code *); +static int make_table(struct archive_read *, struct huffman_code *); +static int make_table_recurse(struct archive_read *, struct huffman_code *, int, + struct huffman_table_entry *, int, int); +static int64_t expand(struct archive_read *, int64_t); +static int copy_from_lzss_window(struct archive_read *, const void **, + int64_t, int); +static const void *rar_read_ahead(struct archive_read *, size_t, ssize_t *); + +/* + * Bit stream reader. + */ +/* Check that the cache buffer has enough bits. */ +#define rar_br_has(br, n) ((br)->cache_avail >= n) +/* Get compressed data by bit. */ +#define rar_br_bits(br, n) \ + (((uint32_t)((br)->cache_buffer >> \ + ((br)->cache_avail - (n)))) & cache_masks[n]) +#define rar_br_bits_forced(br, n) \ + (((uint32_t)((br)->cache_buffer << \ + ((n) - (br)->cache_avail))) & cache_masks[n]) +/* Read ahead to make sure the cache buffer has enough compressed data we + * will use. + * True : completed, there is enough data in the cache buffer. + * False : there is no data in the stream. */ +#define rar_br_read_ahead(a, br, n) \ + ((rar_br_has(br, (n)) || rar_br_fillup(a, br)) || rar_br_has(br, (n))) +/* Notify how many bits we consumed. */ +#define rar_br_consume(br, n) ((br)->cache_avail -= (n)) +#define rar_br_consume_unalined_bits(br) ((br)->cache_avail &= ~7) + +static const uint32_t cache_masks[] = { + 0x00000000, 0x00000001, 0x00000003, 0x00000007, + 0x0000000F, 0x0000001F, 0x0000003F, 0x0000007F, + 0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF, + 0x00000FFF, 0x00001FFF, 0x00003FFF, 0x00007FFF, + 0x0000FFFF, 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, + 0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, + 0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, + 0x0FFFFFFF, 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF +}; + +/* + * Shift away used bits in the cache data and fill it up with following bits. + * Call this when cache buffer does not have enough bits you need. + * + * Returns 1 if the cache buffer is full. + * Returns 0 if the cache buffer is not full; input buffer is empty. + */ +static int +rar_br_fillup(struct archive_read *a, struct rar_br *br) +{ + struct rar *rar = (struct rar *)(a->format->data); + int n = CACHE_BITS - br->cache_avail; + + for (;;) { + switch (n >> 3) { + case 8: + if (br->avail_in >= 8) { + br->cache_buffer = + ((uint64_t)br->next_in[0]) << 56 | + ((uint64_t)br->next_in[1]) << 48 | + ((uint64_t)br->next_in[2]) << 40 | + ((uint64_t)br->next_in[3]) << 32 | + ((uint32_t)br->next_in[4]) << 24 | + ((uint32_t)br->next_in[5]) << 16 | + ((uint32_t)br->next_in[6]) << 8 | + (uint32_t)br->next_in[7]; + br->next_in += 8; + br->avail_in -= 8; + br->cache_avail += 8 * 8; + rar->bytes_unconsumed += 8; + rar->bytes_remaining -= 8; + return (1); + } + break; + case 7: + if (br->avail_in >= 7) { + br->cache_buffer = + (br->cache_buffer << 56) | + ((uint64_t)br->next_in[0]) << 48 | + ((uint64_t)br->next_in[1]) << 40 | + ((uint64_t)br->next_in[2]) << 32 | + ((uint32_t)br->next_in[3]) << 24 | + ((uint32_t)br->next_in[4]) << 16 | + ((uint32_t)br->next_in[5]) << 8 | + (uint32_t)br->next_in[6]; + br->next_in += 7; + br->avail_in -= 7; + br->cache_avail += 7 * 8; + rar->bytes_unconsumed += 7; + rar->bytes_remaining -= 7; + return (1); + } + break; + case 6: + if (br->avail_in >= 6) { + br->cache_buffer = + (br->cache_buffer << 48) | + ((uint64_t)br->next_in[0]) << 40 | + ((uint64_t)br->next_in[1]) << 32 | + ((uint32_t)br->next_in[2]) << 24 | + ((uint32_t)br->next_in[3]) << 16 | + ((uint32_t)br->next_in[4]) << 8 | + (uint32_t)br->next_in[5]; + br->next_in += 6; + br->avail_in -= 6; + br->cache_avail += 6 * 8; + rar->bytes_unconsumed += 6; + rar->bytes_remaining -= 6; + return (1); + } + break; + case 0: + /* We have enough compressed data in + * the cache buffer.*/ + return (1); + default: + break; + } + if (br->avail_in <= 0) { + + if (rar->bytes_unconsumed > 0) { + /* Consume as much as the decompressor + * actually used. */ + __archive_read_consume(a, rar->bytes_unconsumed); + rar->bytes_unconsumed = 0; + } + br->next_in = rar_read_ahead(a, 1, &(br->avail_in)); + if (br->next_in == NULL) + return (0); + if (br->avail_in == 0) + return (0); + } + br->cache_buffer = + (br->cache_buffer << 8) | *br->next_in++; + br->avail_in--; + br->cache_avail += 8; + n -= 8; + rar->bytes_unconsumed++; + rar->bytes_remaining--; + } +} + +static int +rar_br_preparation(struct archive_read *a, struct rar_br *br) +{ + struct rar *rar = (struct rar *)(a->format->data); + + if (rar->bytes_remaining > 0) { + br->next_in = rar_read_ahead(a, 1, &(br->avail_in)); + if (br->next_in == NULL) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated RAR file data"); + return (ARCHIVE_FATAL); + } + if (br->cache_avail == 0) + (void)rar_br_fillup(a, br); + } + return (ARCHIVE_OK); +} + +/* Find last bit set */ +static inline int +rar_fls(unsigned int word) +{ + word |= (word >> 1); + word |= (word >> 2); + word |= (word >> 4); + word |= (word >> 8); + word |= (word >> 16); + return word - (word >> 1); +} + +/* LZSS functions */ +static inline int64_t +lzss_position(struct lzss *lzss) +{ + return lzss->position; +} + +static inline int +lzss_mask(struct lzss *lzss) +{ + return lzss->mask; +} + +static inline int +lzss_size(struct lzss *lzss) +{ + return lzss->mask + 1; +} + +static inline int +lzss_offset_for_position(struct lzss *lzss, int64_t pos) +{ + return (int)(pos & lzss->mask); +} + +static inline unsigned char * +lzss_pointer_for_position(struct lzss *lzss, int64_t pos) +{ + return &lzss->window[lzss_offset_for_position(lzss, pos)]; +} + +static inline int +lzss_current_offset(struct lzss *lzss) +{ + return lzss_offset_for_position(lzss, lzss->position); +} + +static inline uint8_t * +lzss_current_pointer(struct lzss *lzss) +{ + return lzss_pointer_for_position(lzss, lzss->position); +} + +static inline void +lzss_emit_literal(struct rar *rar, uint8_t literal) +{ + *lzss_current_pointer(&rar->lzss) = literal; + rar->lzss.position++; +} + +static inline void +lzss_emit_match(struct rar *rar, int offset, int length) +{ + int dstoffs = lzss_current_offset(&rar->lzss); + int srcoffs = (dstoffs - offset) & lzss_mask(&rar->lzss); + int l, li, remaining; + unsigned char *d, *s; + + remaining = length; + while (remaining > 0) { + l = remaining; + if (dstoffs > srcoffs) { + if (l > lzss_size(&rar->lzss) - dstoffs) + l = lzss_size(&rar->lzss) - dstoffs; + } else { + if (l > lzss_size(&rar->lzss) - srcoffs) + l = lzss_size(&rar->lzss) - srcoffs; + } + d = &(rar->lzss.window[dstoffs]); + s = &(rar->lzss.window[srcoffs]); + if ((dstoffs + l < srcoffs) || (srcoffs + l < dstoffs)) + memcpy(d, s, l); + else { + for (li = 0; li < l; li++) + d[li] = s[li]; + } + remaining -= l; + dstoffs = (dstoffs + l) & lzss_mask(&(rar->lzss)); + srcoffs = (srcoffs + l) & lzss_mask(&(rar->lzss)); + } + rar->lzss.position += length; +} + +static void * +ppmd_alloc(void *p, size_t size) +{ + (void)p; + return malloc(size); +} +static void +ppmd_free(void *p, void *address) +{ + (void)p; + free(address); +} +static ISzAlloc g_szalloc = { ppmd_alloc, ppmd_free }; + +static Byte +ppmd_read(void *p) +{ + struct archive_read *a = ((IByteIn*)p)->a; + struct rar *rar = (struct rar *)(a->format->data); + struct rar_br *br = &(rar->br); + Byte b; + if (!rar_br_read_ahead(a, br, 8)) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated RAR file data"); + rar->valid = 0; + return 0; + } + b = rar_br_bits(br, 8); + rar_br_consume(br, 8); + return b; +} + +int +archive_read_support_format_rar(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct rar *rar; + int r; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, + "archive_read_support_format_rar"); + - rar = (struct rar *)malloc(sizeof(*rar)); ++ rar = (struct rar *)calloc(sizeof(*rar), 1); + if (rar == NULL) + { + archive_set_error(&a->archive, ENOMEM, "Can't allocate rar data"); + return (ARCHIVE_FATAL); + } - memset(rar, 0, sizeof(*rar)); + + /* + * Until enough data has been read, we cannot tell about + * any encrypted entries yet. + */ + rar->has_encrypted_entries = ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW; + + r = __archive_read_register_format(a, + rar, + "rar", + archive_read_format_rar_bid, + archive_read_format_rar_options, + archive_read_format_rar_read_header, + archive_read_format_rar_read_data, + archive_read_format_rar_read_data_skip, + archive_read_format_rar_seek_data, + archive_read_format_rar_cleanup, + archive_read_support_format_rar_capabilities, + archive_read_format_rar_has_encrypted_entries); + + if (r != ARCHIVE_OK) + free(rar); + return (r); +} + +static int +archive_read_support_format_rar_capabilities(struct archive_read * a) +{ + (void)a; /* UNUSED */ + return (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA + | ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA); +} + +static int +archive_read_format_rar_has_encrypted_entries(struct archive_read *_a) +{ + if (_a && _a->format) { + struct rar * rar = (struct rar *)_a->format->data; + if (rar) { + return rar->has_encrypted_entries; + } + } + return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW; +} + + +static int +archive_read_format_rar_bid(struct archive_read *a, int best_bid) +{ + const char *p; + + /* If there's already a bid > 30, we'll never win. */ + if (best_bid > 30) + return (-1); + + if ((p = __archive_read_ahead(a, 7, NULL)) == NULL) + return (-1); + + if (memcmp(p, RAR_SIGNATURE, 7) == 0) + return (30); + + if ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0) { + /* This is a PE file */ + ssize_t offset = 0x10000; + ssize_t window = 4096; + ssize_t bytes_avail; + while (offset + window <= (1024 * 128)) { + const char *buff = __archive_read_ahead(a, offset + window, &bytes_avail); + if (buff == NULL) { + /* Remaining bytes are less than window. */ + window >>= 1; + if (window < 0x40) + return (0); + continue; + } + p = buff + offset; + while (p + 7 < buff + bytes_avail) { + if (memcmp(p, RAR_SIGNATURE, 7) == 0) + return (30); + p += 0x10; + } + offset = p - buff; + } + } + return (0); +} + +static int +skip_sfx(struct archive_read *a) +{ + const void *h; + const char *p, *q; + size_t skip, total; + ssize_t bytes, window; + + total = 0; + window = 4096; + while (total + window <= (1024 * 128)) { + h = __archive_read_ahead(a, window, &bytes); + if (h == NULL) { + /* Remaining bytes are less than window. */ + window >>= 1; + if (window < 0x40) + goto fatal; + continue; + } + if (bytes < 0x40) + goto fatal; + p = h; + q = p + bytes; + + /* + * Scan ahead until we find something that looks + * like the RAR header. + */ + while (p + 7 < q) { + if (memcmp(p, RAR_SIGNATURE, 7) == 0) { + skip = p - (const char *)h; + __archive_read_consume(a, skip); + return (ARCHIVE_OK); + } + p += 0x10; + } + skip = p - (const char *)h; + __archive_read_consume(a, skip); + total += skip; + } +fatal: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Couldn't find out RAR header"); + return (ARCHIVE_FATAL); +} + +static int +archive_read_format_rar_options(struct archive_read *a, + const char *key, const char *val) +{ + struct rar *rar; + int ret = ARCHIVE_FAILED; + + rar = (struct rar *)(a->format->data); + if (strcmp(key, "hdrcharset") == 0) { + if (val == NULL || val[0] == 0) + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "rar: hdrcharset option needs a character-set name"); + else { + rar->opt_sconv = + archive_string_conversion_from_charset( + &a->archive, val, 0); + if (rar->opt_sconv != NULL) + ret = ARCHIVE_OK; + else + ret = ARCHIVE_FATAL; + } + return (ret); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +static int +archive_read_format_rar_read_header(struct archive_read *a, + struct archive_entry *entry) +{ + const void *h; + const char *p; + struct rar *rar; + size_t skip; + char head_type; + int ret; + unsigned flags; + unsigned long crc32_expected; + + a->archive.archive_format = ARCHIVE_FORMAT_RAR; + if (a->archive.archive_format_name == NULL) + a->archive.archive_format_name = "RAR"; + + rar = (struct rar *)(a->format->data); + + /* + * It should be sufficient to call archive_read_next_header() for + * a reader to determine if an entry is encrypted or not. If the + * encryption of an entry is only detectable when calling + * archive_read_data(), so be it. We'll do the same check there + * as well. + */ + if (rar->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) { + rar->has_encrypted_entries = 0; + } + + /* RAR files can be generated without EOF headers, so return ARCHIVE_EOF if + * this fails. + */ + if ((h = __archive_read_ahead(a, 7, NULL)) == NULL) + return (ARCHIVE_EOF); + + p = h; + if (rar->found_first_header == 0 && + ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0)) { + /* This is an executable ? Must be self-extracting... */ + ret = skip_sfx(a); + if (ret < ARCHIVE_WARN) + return (ret); + } + rar->found_first_header = 1; + + while (1) + { + unsigned long crc32_val; + + if ((h = __archive_read_ahead(a, 7, NULL)) == NULL) + return (ARCHIVE_FATAL); + p = h; + + head_type = p[2]; + switch(head_type) + { + case MARK_HEAD: + if (memcmp(p, RAR_SIGNATURE, 7) != 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid marker header"); + return (ARCHIVE_FATAL); + } + __archive_read_consume(a, 7); + break; + + case MAIN_HEAD: + rar->main_flags = archive_le16dec(p + 3); + skip = archive_le16dec(p + 5); + if (skip < 7 + sizeof(rar->reserved1) + sizeof(rar->reserved2)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid header size"); + return (ARCHIVE_FATAL); + } + if ((h = __archive_read_ahead(a, skip, NULL)) == NULL) + return (ARCHIVE_FATAL); + p = h; + memcpy(rar->reserved1, p + 7, sizeof(rar->reserved1)); + memcpy(rar->reserved2, p + 7 + sizeof(rar->reserved1), + sizeof(rar->reserved2)); + if (rar->main_flags & MHD_ENCRYPTVER) { + if (skip < 7 + sizeof(rar->reserved1) + sizeof(rar->reserved2)+1) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid header size"); + return (ARCHIVE_FATAL); + } + rar->encryptver = *(p + 7 + sizeof(rar->reserved1) + + sizeof(rar->reserved2)); + } + - /* Main header is password encrytped, so we cannot read any ++ /* Main header is password encrypted, so we cannot read any + file names or any other info about files from the header. */ + if (rar->main_flags & MHD_PASSWORD) + { + archive_entry_set_is_metadata_encrypted(entry, 1); + archive_entry_set_is_data_encrypted(entry, 1); + rar->has_encrypted_entries = 1; + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "RAR encryption support unavailable."); + return (ARCHIVE_FATAL); + } + + crc32_val = crc32(0, (const unsigned char *)p + 2, (unsigned)skip - 2); + if ((crc32_val & 0xffff) != archive_le16dec(p)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Header CRC error"); + return (ARCHIVE_FATAL); + } + __archive_read_consume(a, skip); + break; + + case FILE_HEAD: + return read_header(a, entry, head_type); + + case COMM_HEAD: + case AV_HEAD: + case SUB_HEAD: + case PROTECT_HEAD: + case SIGN_HEAD: + case ENDARC_HEAD: + flags = archive_le16dec(p + 3); + skip = archive_le16dec(p + 5); + if (skip < 7) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid header size too small"); + return (ARCHIVE_FATAL); + } + if (flags & HD_ADD_SIZE_PRESENT) + { + if (skip < 7 + 4) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid header size too small"); + return (ARCHIVE_FATAL); + } + if ((h = __archive_read_ahead(a, skip, NULL)) == NULL) + return (ARCHIVE_FATAL); + p = h; + skip += archive_le32dec(p + 7); + } + + /* Skip over the 2-byte CRC at the beginning of the header. */ + crc32_expected = archive_le16dec(p); + __archive_read_consume(a, 2); + skip -= 2; + + /* Skim the entire header and compute the CRC. */ + crc32_val = 0; + while (skip > 0) { + size_t to_read = skip; + ssize_t did_read; + if (to_read > 32 * 1024) { + to_read = 32 * 1024; + } + if ((h = __archive_read_ahead(a, to_read, &did_read)) == NULL) { + return (ARCHIVE_FATAL); + } + p = h; + crc32_val = crc32(crc32_val, (const unsigned char *)p, (unsigned)did_read); + __archive_read_consume(a, did_read); + skip -= did_read; + } + if ((crc32_val & 0xffff) != crc32_expected) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Header CRC error"); + return (ARCHIVE_FATAL); + } + if (head_type == ENDARC_HEAD) + return (ARCHIVE_EOF); + break; + + case NEWSUB_HEAD: + if ((ret = read_header(a, entry, head_type)) < ARCHIVE_WARN) + return ret; + break; + + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Bad RAR file"); + return (ARCHIVE_FATAL); + } + } +} + +static int +archive_read_format_rar_read_data(struct archive_read *a, const void **buff, + size_t *size, int64_t *offset) +{ + struct rar *rar = (struct rar *)(a->format->data); + int ret; + + if (rar->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) { + rar->has_encrypted_entries = 0; + } + + if (rar->bytes_unconsumed > 0) { + /* Consume as much as the decompressor actually used. */ + __archive_read_consume(a, rar->bytes_unconsumed); + rar->bytes_unconsumed = 0; + } + + *buff = NULL; + if (rar->entry_eof || rar->offset_seek >= rar->unp_size) { + *size = 0; + *offset = rar->offset; + if (*offset < rar->unp_size) + *offset = rar->unp_size; + return (ARCHIVE_EOF); + } + + switch (rar->compression_method) + { + case COMPRESS_METHOD_STORE: + ret = read_data_stored(a, buff, size, offset); + break; + + case COMPRESS_METHOD_FASTEST: + case COMPRESS_METHOD_FAST: + case COMPRESS_METHOD_NORMAL: + case COMPRESS_METHOD_GOOD: + case COMPRESS_METHOD_BEST: + ret = read_data_compressed(a, buff, size, offset); + if (ret != ARCHIVE_OK && ret != ARCHIVE_WARN) + __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context, &g_szalloc); + break; + + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Unsupported compression method for RAR file."); + ret = ARCHIVE_FATAL; + break; + } + return (ret); +} + +static int +archive_read_format_rar_read_data_skip(struct archive_read *a) +{ + struct rar *rar; + int64_t bytes_skipped; + int ret; + + rar = (struct rar *)(a->format->data); + + if (rar->bytes_unconsumed > 0) { + /* Consume as much as the decompressor actually used. */ + __archive_read_consume(a, rar->bytes_unconsumed); + rar->bytes_unconsumed = 0; + } + + if (rar->bytes_remaining > 0) { + bytes_skipped = __archive_read_consume(a, rar->bytes_remaining); + if (bytes_skipped < 0) + return (ARCHIVE_FATAL); + } + + /* Compressed data to skip must be read from each header in a multivolume + * archive. + */ + if (rar->main_flags & MHD_VOLUME && rar->file_flags & FHD_SPLIT_AFTER) + { + ret = archive_read_format_rar_read_header(a, a->entry); + if (ret == (ARCHIVE_EOF)) + ret = archive_read_format_rar_read_header(a, a->entry); + if (ret != (ARCHIVE_OK)) + return ret; + return archive_read_format_rar_read_data_skip(a); + } + + return (ARCHIVE_OK); +} + +static int64_t +archive_read_format_rar_seek_data(struct archive_read *a, int64_t offset, + int whence) +{ + int64_t client_offset, ret; + unsigned int i; + struct rar *rar = (struct rar *)(a->format->data); + + if (rar->compression_method == COMPRESS_METHOD_STORE) + { + /* Modify the offset for use with SEEK_SET */ + switch (whence) + { + case SEEK_CUR: + client_offset = rar->offset_seek; + break; + case SEEK_END: + client_offset = rar->unp_size; + break; + case SEEK_SET: + default: + client_offset = 0; + } + client_offset += offset; + if (client_offset < 0) + { + /* Can't seek past beginning of data block */ + return -1; + } + else if (client_offset > rar->unp_size) + { + /* + * Set the returned offset but only seek to the end of + * the data block. + */ + rar->offset_seek = client_offset; + client_offset = rar->unp_size; + } + + client_offset += rar->dbo[0].start_offset; + i = 0; + while (i < rar->cursor) + { + i++; + client_offset += rar->dbo[i].start_offset - rar->dbo[i-1].end_offset; + } + if (rar->main_flags & MHD_VOLUME) + { + /* Find the appropriate offset among the multivolume archive */ + while (1) + { + if (client_offset < rar->dbo[rar->cursor].start_offset && + rar->file_flags & FHD_SPLIT_BEFORE) + { + /* Search backwards for the correct data block */ + if (rar->cursor == 0) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Attempt to seek past beginning of RAR data block"); + return (ARCHIVE_FAILED); + } + rar->cursor--; + client_offset -= rar->dbo[rar->cursor+1].start_offset - + rar->dbo[rar->cursor].end_offset; + if (client_offset < rar->dbo[rar->cursor].start_offset) + continue; + ret = __archive_read_seek(a, rar->dbo[rar->cursor].start_offset - + rar->dbo[rar->cursor].header_size, SEEK_SET); + if (ret < (ARCHIVE_OK)) + return ret; + ret = archive_read_format_rar_read_header(a, a->entry); + if (ret != (ARCHIVE_OK)) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Error during seek of RAR file"); + return (ARCHIVE_FAILED); + } + rar->cursor--; + break; + } + else if (client_offset > rar->dbo[rar->cursor].end_offset && + rar->file_flags & FHD_SPLIT_AFTER) + { + /* Search forward for the correct data block */ + rar->cursor++; + if (rar->cursor < rar->nodes && + client_offset > rar->dbo[rar->cursor].end_offset) + { + client_offset += rar->dbo[rar->cursor].start_offset - + rar->dbo[rar->cursor-1].end_offset; + continue; + } + rar->cursor--; + ret = __archive_read_seek(a, rar->dbo[rar->cursor].end_offset, + SEEK_SET); + if (ret < (ARCHIVE_OK)) + return ret; + ret = archive_read_format_rar_read_header(a, a->entry); + if (ret == (ARCHIVE_EOF)) + { + rar->has_endarc_header = 1; + ret = archive_read_format_rar_read_header(a, a->entry); + } + if (ret != (ARCHIVE_OK)) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Error during seek of RAR file"); + return (ARCHIVE_FAILED); + } + client_offset += rar->dbo[rar->cursor].start_offset - + rar->dbo[rar->cursor-1].end_offset; + continue; + } + break; + } + } + + ret = __archive_read_seek(a, client_offset, SEEK_SET); + if (ret < (ARCHIVE_OK)) + return ret; + rar->bytes_remaining = rar->dbo[rar->cursor].end_offset - ret; + i = rar->cursor; + while (i > 0) + { + i--; + ret -= rar->dbo[i+1].start_offset - rar->dbo[i].end_offset; + } + ret -= rar->dbo[0].start_offset; + + /* Always restart reading the file after a seek */ + __archive_reset_read_data(&a->archive); + + rar->bytes_unconsumed = 0; + rar->offset = 0; + + /* + * If a seek past the end of file was requested, return the requested + * offset. + */ + if (ret == rar->unp_size && rar->offset_seek > rar->unp_size) + return rar->offset_seek; + + /* Return the new offset */ + rar->offset_seek = ret; + return rar->offset_seek; + } + else + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Seeking of compressed RAR files is unsupported"); + } + return (ARCHIVE_FAILED); +} + +static int +archive_read_format_rar_cleanup(struct archive_read *a) +{ + struct rar *rar; + + rar = (struct rar *)(a->format->data); + free_codes(a); + free(rar->filename); + free(rar->filename_save); + free(rar->dbo); + free(rar->unp_buffer); + free(rar->lzss.window); + __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context, &g_szalloc); + free(rar); + (a->format->data) = NULL; + return (ARCHIVE_OK); +} + +static int +read_header(struct archive_read *a, struct archive_entry *entry, + char head_type) +{ + const void *h; + const char *p, *endp; + struct rar *rar; + struct rar_header rar_header; + struct rar_file_header file_header; + int64_t header_size; + unsigned filename_size, end; + char *filename; + char *strp; + char packed_size[8]; + char unp_size[8]; + int ttime; + struct archive_string_conv *sconv, *fn_sconv; + unsigned long crc32_val; + int ret = (ARCHIVE_OK), ret2; + + rar = (struct rar *)(a->format->data); + + /* Setup a string conversion object for non-rar-unicode filenames. */ + sconv = rar->opt_sconv; + if (sconv == NULL) { + if (!rar->init_default_conversion) { + rar->sconv_default = + archive_string_default_conversion_for_read( + &(a->archive)); + rar->init_default_conversion = 1; + } + sconv = rar->sconv_default; + } + + + if ((h = __archive_read_ahead(a, 7, NULL)) == NULL) + return (ARCHIVE_FATAL); + p = h; + memcpy(&rar_header, p, sizeof(rar_header)); + rar->file_flags = archive_le16dec(rar_header.flags); + header_size = archive_le16dec(rar_header.size); + if (header_size < (int64_t)sizeof(file_header) + 7) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid header size"); + return (ARCHIVE_FATAL); + } + crc32_val = crc32(0, (const unsigned char *)p + 2, 7 - 2); + __archive_read_consume(a, 7); + + if (!(rar->file_flags & FHD_SOLID)) + { + rar->compression_method = 0; + rar->packed_size = 0; + rar->unp_size = 0; + rar->mtime = 0; + rar->ctime = 0; + rar->atime = 0; + rar->arctime = 0; + rar->mode = 0; + memset(&rar->salt, 0, sizeof(rar->salt)); + rar->atime = 0; + rar->ansec = 0; + rar->ctime = 0; + rar->cnsec = 0; + rar->mtime = 0; + rar->mnsec = 0; + rar->arctime = 0; + rar->arcnsec = 0; + } + else + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "RAR solid archive support unavailable."); + return (ARCHIVE_FATAL); + } + + if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL) + return (ARCHIVE_FATAL); + + /* File Header CRC check. */ + crc32_val = crc32(crc32_val, h, (unsigned)(header_size - 7)); + if ((crc32_val & 0xffff) != archive_le16dec(rar_header.crc)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Header CRC error"); + return (ARCHIVE_FATAL); + } + /* If no CRC error, Go on parsing File Header. */ + p = h; + endp = p + header_size - 7; + memcpy(&file_header, p, sizeof(file_header)); + p += sizeof(file_header); + + rar->compression_method = file_header.method; + + ttime = archive_le32dec(file_header.file_time); + rar->mtime = get_time(ttime); + + rar->file_crc = archive_le32dec(file_header.file_crc); + + if (rar->file_flags & FHD_PASSWORD) + { + archive_entry_set_is_data_encrypted(entry, 1); + rar->has_encrypted_entries = 1; + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "RAR encryption support unavailable."); + /* Since it is only the data part itself that is encrypted we can at least + extract information about the currently processed entry and don't need + to return ARCHIVE_FATAL here. */ + /*return (ARCHIVE_FATAL);*/ + } + + if (rar->file_flags & FHD_LARGE) + { + memcpy(packed_size, file_header.pack_size, 4); + memcpy(packed_size + 4, p, 4); /* High pack size */ + p += 4; + memcpy(unp_size, file_header.unp_size, 4); + memcpy(unp_size + 4, p, 4); /* High unpack size */ + p += 4; + rar->packed_size = archive_le64dec(&packed_size); + rar->unp_size = archive_le64dec(&unp_size); + } + else + { + rar->packed_size = archive_le32dec(file_header.pack_size); + rar->unp_size = archive_le32dec(file_header.unp_size); + } + + if (rar->packed_size < 0 || rar->unp_size < 0) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid sizes specified."); + return (ARCHIVE_FATAL); + } + + rar->bytes_remaining = rar->packed_size; + + /* TODO: RARv3 subblocks contain comments. For now the complete block is + * consumed at the end. + */ + if (head_type == NEWSUB_HEAD) { + size_t distance = p - (const char *)h; + header_size += rar->packed_size; + /* Make sure we have the extended data. */ + if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL) + return (ARCHIVE_FATAL); + p = h; + endp = p + header_size - 7; + p += distance; + } + + filename_size = archive_le16dec(file_header.name_size); + if (p + filename_size > endp) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid filename size"); + return (ARCHIVE_FATAL); + } + if (rar->filename_allocated < filename_size * 2 + 2) { + char *newptr; + size_t newsize = filename_size * 2 + 2; + newptr = realloc(rar->filename, newsize); + if (newptr == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Couldn't allocate memory."); + return (ARCHIVE_FATAL); + } + rar->filename = newptr; + rar->filename_allocated = newsize; + } + filename = rar->filename; + memcpy(filename, p, filename_size); + filename[filename_size] = '\0'; + if (rar->file_flags & FHD_UNICODE) + { + if (filename_size != strlen(filename)) + { + unsigned char highbyte, flagbits, flagbyte; + unsigned fn_end, offset; + + end = filename_size; + fn_end = filename_size * 2; + filename_size = 0; + offset = (unsigned)strlen(filename) + 1; + highbyte = *(p + offset++); + flagbits = 0; + flagbyte = 0; + while (offset < end && filename_size < fn_end) + { + if (!flagbits) + { + flagbyte = *(p + offset++); + flagbits = 8; + } + + flagbits -= 2; + switch((flagbyte >> flagbits) & 3) + { + case 0: + filename[filename_size++] = '\0'; + filename[filename_size++] = *(p + offset++); + break; + case 1: + filename[filename_size++] = highbyte; + filename[filename_size++] = *(p + offset++); + break; + case 2: + filename[filename_size++] = *(p + offset + 1); + filename[filename_size++] = *(p + offset); + offset += 2; + break; + case 3: + { + char extra, high; + uint8_t length = *(p + offset++); + + if (length & 0x80) { + extra = *(p + offset++); + high = (char)highbyte; + } else + extra = high = 0; + length = (length & 0x7f) + 2; + while (length && filename_size < fn_end) { + unsigned cp = filename_size >> 1; + filename[filename_size++] = high; + filename[filename_size++] = p[cp] + extra; + length--; + } + } + break; + } + } + if (filename_size > fn_end) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid filename"); + return (ARCHIVE_FATAL); + } + filename[filename_size++] = '\0'; + filename[filename_size++] = '\0'; + + /* Decoded unicode form is UTF-16BE, so we have to update a string + * conversion object for it. */ + if (rar->sconv_utf16be == NULL) { + rar->sconv_utf16be = archive_string_conversion_from_charset( + &a->archive, "UTF-16BE", 1); + if (rar->sconv_utf16be == NULL) + return (ARCHIVE_FATAL); + } + fn_sconv = rar->sconv_utf16be; + + strp = filename; + while (memcmp(strp, "\x00\x00", 2)) + { + if (!memcmp(strp, "\x00\\", 2)) + *(strp + 1) = '/'; + strp += 2; + } + p += offset; + } else { + /* + * If FHD_UNICODE is set but no unicode data, this file name form + * is UTF-8, so we have to update a string conversion object for + * it accordingly. + */ + if (rar->sconv_utf8 == NULL) { + rar->sconv_utf8 = archive_string_conversion_from_charset( + &a->archive, "UTF-8", 1); + if (rar->sconv_utf8 == NULL) + return (ARCHIVE_FATAL); + } + fn_sconv = rar->sconv_utf8; + while ((strp = strchr(filename, '\\')) != NULL) + *strp = '/'; + p += filename_size; + } + } + else + { + fn_sconv = sconv; + while ((strp = strchr(filename, '\\')) != NULL) + *strp = '/'; + p += filename_size; + } + + /* Split file in multivolume RAR. No more need to process header. */ + if (rar->filename_save && + filename_size == rar->filename_save_size && + !memcmp(rar->filename, rar->filename_save, filename_size + 1)) + { + __archive_read_consume(a, header_size - 7); + rar->cursor++; + if (rar->cursor >= rar->nodes) + { + rar->nodes++; + if ((rar->dbo = + realloc(rar->dbo, sizeof(*rar->dbo) * rar->nodes)) == NULL) + { + archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory."); + return (ARCHIVE_FATAL); + } + rar->dbo[rar->cursor].header_size = header_size; + rar->dbo[rar->cursor].start_offset = -1; + rar->dbo[rar->cursor].end_offset = -1; + } + if (rar->dbo[rar->cursor].start_offset < 0) + { + rar->dbo[rar->cursor].start_offset = a->filter->position; + rar->dbo[rar->cursor].end_offset = rar->dbo[rar->cursor].start_offset + + rar->packed_size; + } + return ret; + } + + rar->filename_save = (char*)realloc(rar->filename_save, + filename_size + 1); + memcpy(rar->filename_save, rar->filename, filename_size + 1); + rar->filename_save_size = filename_size; + + /* Set info for seeking */ + free(rar->dbo); + if ((rar->dbo = calloc(1, sizeof(*rar->dbo))) == NULL) + { + archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory."); + return (ARCHIVE_FATAL); + } + rar->dbo[0].header_size = header_size; + rar->dbo[0].start_offset = -1; + rar->dbo[0].end_offset = -1; + rar->cursor = 0; + rar->nodes = 1; + + if (rar->file_flags & FHD_SALT) + { + if (p + 8 > endp) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid header size"); + return (ARCHIVE_FATAL); + } + memcpy(rar->salt, p, 8); + p += 8; + } + + if (rar->file_flags & FHD_EXTTIME) { + if (read_exttime(p, rar, endp) < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid header size"); + return (ARCHIVE_FATAL); + } + } + + __archive_read_consume(a, header_size - 7); + rar->dbo[0].start_offset = a->filter->position; + rar->dbo[0].end_offset = rar->dbo[0].start_offset + rar->packed_size; + + switch(file_header.host_os) + { + case OS_MSDOS: + case OS_OS2: + case OS_WIN32: + rar->mode = archive_le32dec(file_header.file_attr); + if (rar->mode & FILE_ATTRIBUTE_DIRECTORY) + rar->mode = AE_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH; + else + rar->mode = AE_IFREG; + rar->mode |= S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; + break; + + case OS_UNIX: + case OS_MAC_OS: + case OS_BEOS: + rar->mode = archive_le32dec(file_header.file_attr); + break; + + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Unknown file attributes from RAR file's host OS"); + return (ARCHIVE_FATAL); + } + + rar->bytes_uncopied = rar->bytes_unconsumed = 0; + rar->lzss.position = rar->offset = 0; + rar->offset_seek = 0; + rar->dictionary_size = 0; + rar->offset_outgoing = 0; + rar->br.cache_avail = 0; + rar->br.avail_in = 0; + rar->crc_calculated = 0; + rar->entry_eof = 0; + rar->valid = 1; + rar->is_ppmd_block = 0; + rar->start_new_table = 1; + free(rar->unp_buffer); + rar->unp_buffer = NULL; + rar->unp_offset = 0; + rar->unp_buffer_size = UNP_BUFFER_SIZE; + memset(rar->lengthtable, 0, sizeof(rar->lengthtable)); + __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context, &g_szalloc); + rar->ppmd_valid = rar->ppmd_eod = 0; + + /* Don't set any archive entries for non-file header types */ + if (head_type == NEWSUB_HEAD) + return ret; + + archive_entry_set_mtime(entry, rar->mtime, rar->mnsec); + archive_entry_set_ctime(entry, rar->ctime, rar->cnsec); + archive_entry_set_atime(entry, rar->atime, rar->ansec); + archive_entry_set_size(entry, rar->unp_size); + archive_entry_set_mode(entry, rar->mode); + + if (archive_entry_copy_pathname_l(entry, filename, filename_size, fn_sconv)) + { + if (errno == ENOMEM) + { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Pathname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Pathname cannot be converted from %s to current locale.", + archive_string_conversion_charset_name(fn_sconv)); + ret = (ARCHIVE_WARN); + } + + if (((rar->mode) & AE_IFMT) == AE_IFLNK) + { + /* Make sure a symbolic-link file does not have its body. */ + rar->bytes_remaining = 0; + archive_entry_set_size(entry, 0); + + /* Read a symbolic-link name. */ + if ((ret2 = read_symlink_stored(a, entry, sconv)) < (ARCHIVE_WARN)) + return ret2; + if (ret > ret2) + ret = ret2; + } + + if (rar->bytes_remaining == 0) + rar->entry_eof = 1; + + return ret; +} + +static time_t +get_time(int ttime) +{ + struct tm tm; + tm.tm_sec = 2 * (ttime & 0x1f); + tm.tm_min = (ttime >> 5) & 0x3f; + tm.tm_hour = (ttime >> 11) & 0x1f; + tm.tm_mday = (ttime >> 16) & 0x1f; + tm.tm_mon = ((ttime >> 21) & 0x0f) - 1; + tm.tm_year = ((ttime >> 25) & 0x7f) + 80; + tm.tm_isdst = -1; + return mktime(&tm); +} + +static int +read_exttime(const char *p, struct rar *rar, const char *endp) +{ + unsigned rmode, flags, rem, j, count; + int ttime, i; + struct tm *tm; + time_t t; + long nsec; + + if (p + 2 > endp) + return (-1); + flags = archive_le16dec(p); + p += 2; + + for (i = 3; i >= 0; i--) + { + t = 0; + if (i == 3) + t = rar->mtime; + rmode = flags >> i * 4; + if (rmode & 8) + { + if (!t) + { + if (p + 4 > endp) + return (-1); + ttime = archive_le32dec(p); + t = get_time(ttime); + p += 4; + } + rem = 0; + count = rmode & 3; + if (p + count > endp) + return (-1); + for (j = 0; j < count; j++) + { + rem = ((*p) << 16) | (rem >> 8); + p++; + } + tm = localtime(&t); + nsec = tm->tm_sec + rem / NS_UNIT; + if (rmode & 4) + { + tm->tm_sec++; + t = mktime(tm); + } + if (i == 3) + { + rar->mtime = t; + rar->mnsec = nsec; + } + else if (i == 2) + { + rar->ctime = t; + rar->cnsec = nsec; + } + else if (i == 1) + { + rar->atime = t; + rar->ansec = nsec; + } + else + { + rar->arctime = t; + rar->arcnsec = nsec; + } + } + } + return (0); +} + +static int +read_symlink_stored(struct archive_read *a, struct archive_entry *entry, + struct archive_string_conv *sconv) +{ + const void *h; + const char *p; + struct rar *rar; + int ret = (ARCHIVE_OK); + + rar = (struct rar *)(a->format->data); + if ((h = rar_read_ahead(a, (size_t)rar->packed_size, NULL)) == NULL) + return (ARCHIVE_FATAL); + p = h; + + if (archive_entry_copy_symlink_l(entry, + p, (size_t)rar->packed_size, sconv)) + { + if (errno == ENOMEM) + { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for link"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "link cannot be converted from %s to current locale.", + archive_string_conversion_charset_name(sconv)); + ret = (ARCHIVE_WARN); + } + __archive_read_consume(a, rar->packed_size); + return ret; +} + +static int +read_data_stored(struct archive_read *a, const void **buff, size_t *size, + int64_t *offset) +{ + struct rar *rar; + ssize_t bytes_avail; + + rar = (struct rar *)(a->format->data); + if (rar->bytes_remaining == 0 && + !(rar->main_flags & MHD_VOLUME && rar->file_flags & FHD_SPLIT_AFTER)) + { + *buff = NULL; + *size = 0; + *offset = rar->offset; + if (rar->file_crc != rar->crc_calculated) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "File CRC error"); + return (ARCHIVE_FATAL); + } + rar->entry_eof = 1; + return (ARCHIVE_EOF); + } + + *buff = rar_read_ahead(a, 1, &bytes_avail); + if (bytes_avail <= 0) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated RAR file data"); + return (ARCHIVE_FATAL); + } + + *size = bytes_avail; + *offset = rar->offset; + rar->offset += bytes_avail; + rar->offset_seek += bytes_avail; + rar->bytes_remaining -= bytes_avail; + rar->bytes_unconsumed = bytes_avail; + /* Calculate File CRC. */ + rar->crc_calculated = crc32(rar->crc_calculated, *buff, + (unsigned)bytes_avail); + return (ARCHIVE_OK); +} + +static int +read_data_compressed(struct archive_read *a, const void **buff, size_t *size, + int64_t *offset) +{ + struct rar *rar; + int64_t start, end, actualend; + size_t bs; + int ret = (ARCHIVE_OK), sym, code, lzss_offset, length, i; + + rar = (struct rar *)(a->format->data); + + do { + if (!rar->valid) + return (ARCHIVE_FATAL); + if (rar->ppmd_eod || + (rar->dictionary_size && rar->offset >= rar->unp_size)) + { + if (rar->unp_offset > 0) { + /* + * We have unprocessed extracted data. write it out. + */ + *buff = rar->unp_buffer; + *size = rar->unp_offset; + *offset = rar->offset_outgoing; + rar->offset_outgoing += *size; + /* Calculate File CRC. */ + rar->crc_calculated = crc32(rar->crc_calculated, *buff, + (unsigned)*size); + rar->unp_offset = 0; + return (ARCHIVE_OK); + } + *buff = NULL; + *size = 0; + *offset = rar->offset; + if (rar->file_crc != rar->crc_calculated) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "File CRC error"); + return (ARCHIVE_FATAL); + } + rar->entry_eof = 1; + return (ARCHIVE_EOF); + } + + if (!rar->is_ppmd_block && rar->dictionary_size && rar->bytes_uncopied > 0) + { + if (rar->bytes_uncopied > (rar->unp_buffer_size - rar->unp_offset)) + bs = rar->unp_buffer_size - rar->unp_offset; + else + bs = (size_t)rar->bytes_uncopied; + ret = copy_from_lzss_window(a, buff, rar->offset, (int)bs); + if (ret != ARCHIVE_OK) + return (ret); + rar->offset += bs; + rar->bytes_uncopied -= bs; + if (*buff != NULL) { + rar->unp_offset = 0; + *size = rar->unp_buffer_size; + *offset = rar->offset_outgoing; + rar->offset_outgoing += *size; + /* Calculate File CRC. */ + rar->crc_calculated = crc32(rar->crc_calculated, *buff, + (unsigned)*size); + return (ret); + } + continue; + } + + if (!rar->br.next_in && + (ret = rar_br_preparation(a, &(rar->br))) < ARCHIVE_WARN) + return (ret); + if (rar->start_new_table && ((ret = parse_codes(a)) < (ARCHIVE_WARN))) + return (ret); + + if (rar->is_ppmd_block) + { + if ((sym = __archive_ppmd7_functions.Ppmd7_DecodeSymbol( + &rar->ppmd7_context, &rar->range_dec.p)) < 0) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid symbol"); + return (ARCHIVE_FATAL); + } + if(sym != rar->ppmd_escape) + { + lzss_emit_literal(rar, sym); + rar->bytes_uncopied++; + } + else + { + if ((code = __archive_ppmd7_functions.Ppmd7_DecodeSymbol( + &rar->ppmd7_context, &rar->range_dec.p)) < 0) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid symbol"); + return (ARCHIVE_FATAL); + } + + switch(code) + { + case 0: + rar->start_new_table = 1; + return read_data_compressed(a, buff, size, offset); + + case 2: + rar->ppmd_eod = 1;/* End Of ppmd Data. */ + continue; + + case 3: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Parsing filters is unsupported."); + return (ARCHIVE_FAILED); + + case 4: + lzss_offset = 0; + for (i = 2; i >= 0; i--) + { + if ((code = __archive_ppmd7_functions.Ppmd7_DecodeSymbol( + &rar->ppmd7_context, &rar->range_dec.p)) < 0) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid symbol"); + return (ARCHIVE_FATAL); + } + lzss_offset |= code << (i * 8); + } + if ((length = __archive_ppmd7_functions.Ppmd7_DecodeSymbol( + &rar->ppmd7_context, &rar->range_dec.p)) < 0) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid symbol"); + return (ARCHIVE_FATAL); + } + lzss_emit_match(rar, lzss_offset + 2, length + 32); + rar->bytes_uncopied += length + 32; + break; + + case 5: + if ((length = __archive_ppmd7_functions.Ppmd7_DecodeSymbol( + &rar->ppmd7_context, &rar->range_dec.p)) < 0) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid symbol"); + return (ARCHIVE_FATAL); + } + lzss_emit_match(rar, 1, length + 4); + rar->bytes_uncopied += length + 4; + break; + + default: + lzss_emit_literal(rar, sym); + rar->bytes_uncopied++; + } + } + } + else + { + start = rar->offset; + end = start + rar->dictionary_size; + rar->filterstart = INT64_MAX; + + if ((actualend = expand(a, end)) < 0) + return ((int)actualend); + + rar->bytes_uncopied = actualend - start; + if (rar->bytes_uncopied == 0) { + /* Broken RAR files cause this case. + * NOTE: If this case were possible on a normal RAR file + * we would find out where it was actually bad and + * what we would do to solve it. */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Internal error extracting RAR file"); + return (ARCHIVE_FATAL); + } + } + if (rar->bytes_uncopied > (rar->unp_buffer_size - rar->unp_offset)) + bs = rar->unp_buffer_size - rar->unp_offset; + else + bs = (size_t)rar->bytes_uncopied; + ret = copy_from_lzss_window(a, buff, rar->offset, (int)bs); + if (ret != ARCHIVE_OK) + return (ret); + rar->offset += bs; + rar->bytes_uncopied -= bs; + /* + * If *buff is NULL, it means unp_buffer is not full. + * So we have to continue extracting a RAR file. + */ + } while (*buff == NULL); + + rar->unp_offset = 0; + *size = rar->unp_buffer_size; + *offset = rar->offset_outgoing; + rar->offset_outgoing += *size; + /* Calculate File CRC. */ + rar->crc_calculated = crc32(rar->crc_calculated, *buff, (unsigned)*size); + return ret; +} + +static int +parse_codes(struct archive_read *a) +{ + int i, j, val, n, r; + unsigned char bitlengths[MAX_SYMBOLS], zerocount, ppmd_flags; + unsigned int maxorder; + struct huffman_code precode; + struct rar *rar = (struct rar *)(a->format->data); + struct rar_br *br = &(rar->br); + + free_codes(a); + + /* Skip to the next byte */ + rar_br_consume_unalined_bits(br); + + /* PPMd block flag */ + if (!rar_br_read_ahead(a, br, 1)) + goto truncated_data; + if ((rar->is_ppmd_block = rar_br_bits(br, 1)) != 0) + { + rar_br_consume(br, 1); + if (!rar_br_read_ahead(a, br, 7)) + goto truncated_data; + ppmd_flags = rar_br_bits(br, 7); + rar_br_consume(br, 7); + + /* Memory is allocated in MB */ + if (ppmd_flags & 0x20) + { + if (!rar_br_read_ahead(a, br, 8)) + goto truncated_data; + rar->dictionary_size = (rar_br_bits(br, 8) + 1) << 20; + rar_br_consume(br, 8); + } + + if (ppmd_flags & 0x40) + { + if (!rar_br_read_ahead(a, br, 8)) + goto truncated_data; + rar->ppmd_escape = rar->ppmd7_context.InitEsc = rar_br_bits(br, 8); + rar_br_consume(br, 8); + } + else + rar->ppmd_escape = 2; + + if (ppmd_flags & 0x20) + { + maxorder = (ppmd_flags & 0x1F) + 1; + if(maxorder > 16) + maxorder = 16 + (maxorder - 16) * 3; + + if (maxorder == 1) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated RAR file data"); + return (ARCHIVE_FATAL); + } + + /* Make sure ppmd7_contest is freed before Ppmd7_Construct + * because reading a broken file cause this abnormal sequence. */ + __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context, &g_szalloc); + + rar->bytein.a = a; + rar->bytein.Read = &ppmd_read; + __archive_ppmd7_functions.PpmdRAR_RangeDec_CreateVTable(&rar->range_dec); + rar->range_dec.Stream = &rar->bytein; + __archive_ppmd7_functions.Ppmd7_Construct(&rar->ppmd7_context); + + if (rar->dictionary_size == 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid zero dictionary size"); + return (ARCHIVE_FATAL); + } + + if (!__archive_ppmd7_functions.Ppmd7_Alloc(&rar->ppmd7_context, + rar->dictionary_size, &g_szalloc)) + { + archive_set_error(&a->archive, ENOMEM, + "Out of memory"); + return (ARCHIVE_FATAL); + } + if (!__archive_ppmd7_functions.PpmdRAR_RangeDec_Init(&rar->range_dec)) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Unable to initialize PPMd range decoder"); + return (ARCHIVE_FATAL); + } + __archive_ppmd7_functions.Ppmd7_Init(&rar->ppmd7_context, maxorder); + rar->ppmd_valid = 1; + } + else + { + if (!rar->ppmd_valid) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid PPMd sequence"); + return (ARCHIVE_FATAL); + } + if (!__archive_ppmd7_functions.PpmdRAR_RangeDec_Init(&rar->range_dec)) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Unable to initialize PPMd range decoder"); + return (ARCHIVE_FATAL); + } + } + } + else + { + rar_br_consume(br, 1); + + /* Keep existing table flag */ + if (!rar_br_read_ahead(a, br, 1)) + goto truncated_data; + if (!rar_br_bits(br, 1)) + memset(rar->lengthtable, 0, sizeof(rar->lengthtable)); + rar_br_consume(br, 1); + + memset(&bitlengths, 0, sizeof(bitlengths)); + for (i = 0; i < MAX_SYMBOLS;) + { + if (!rar_br_read_ahead(a, br, 4)) + goto truncated_data; + bitlengths[i++] = rar_br_bits(br, 4); + rar_br_consume(br, 4); + if (bitlengths[i-1] == 0xF) + { + if (!rar_br_read_ahead(a, br, 4)) + goto truncated_data; + zerocount = rar_br_bits(br, 4); + rar_br_consume(br, 4); + if (zerocount) + { + i--; + for (j = 0; j < zerocount + 2 && i < MAX_SYMBOLS; j++) + bitlengths[i++] = 0; + } + } + } + + memset(&precode, 0, sizeof(precode)); + r = create_code(a, &precode, bitlengths, MAX_SYMBOLS, MAX_SYMBOL_LENGTH); + if (r != ARCHIVE_OK) { + free(precode.tree); + free(precode.table); + return (r); + } + + for (i = 0; i < HUFFMAN_TABLE_SIZE;) + { + if ((val = read_next_symbol(a, &precode)) < 0) { + free(precode.tree); + free(precode.table); + return (ARCHIVE_FATAL); + } + if (val < 16) + { + rar->lengthtable[i] = (rar->lengthtable[i] + val) & 0xF; + i++; + } + else if (val < 18) + { + if (i == 0) + { + free(precode.tree); + free(precode.table); + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Internal error extracting RAR file."); + return (ARCHIVE_FATAL); + } + + if(val == 16) { + if (!rar_br_read_ahead(a, br, 3)) { + free(precode.tree); + free(precode.table); + goto truncated_data; + } + n = rar_br_bits(br, 3) + 3; + rar_br_consume(br, 3); + } else { + if (!rar_br_read_ahead(a, br, 7)) { + free(precode.tree); + free(precode.table); + goto truncated_data; + } + n = rar_br_bits(br, 7) + 11; + rar_br_consume(br, 7); + } + + for (j = 0; j < n && i < HUFFMAN_TABLE_SIZE; j++) + { + rar->lengthtable[i] = rar->lengthtable[i-1]; + i++; + } + } + else + { + if(val == 18) { + if (!rar_br_read_ahead(a, br, 3)) { + free(precode.tree); + free(precode.table); + goto truncated_data; + } + n = rar_br_bits(br, 3) + 3; + rar_br_consume(br, 3); + } else { + if (!rar_br_read_ahead(a, br, 7)) { + free(precode.tree); + free(precode.table); + goto truncated_data; + } + n = rar_br_bits(br, 7) + 11; + rar_br_consume(br, 7); + } + + for(j = 0; j < n && i < HUFFMAN_TABLE_SIZE; j++) + rar->lengthtable[i++] = 0; + } + } + free(precode.tree); + free(precode.table); + + r = create_code(a, &rar->maincode, &rar->lengthtable[0], MAINCODE_SIZE, + MAX_SYMBOL_LENGTH); + if (r != ARCHIVE_OK) + return (r); + r = create_code(a, &rar->offsetcode, &rar->lengthtable[MAINCODE_SIZE], + OFFSETCODE_SIZE, MAX_SYMBOL_LENGTH); + if (r != ARCHIVE_OK) + return (r); + r = create_code(a, &rar->lowoffsetcode, + &rar->lengthtable[MAINCODE_SIZE + OFFSETCODE_SIZE], + LOWOFFSETCODE_SIZE, MAX_SYMBOL_LENGTH); + if (r != ARCHIVE_OK) + return (r); + r = create_code(a, &rar->lengthcode, + &rar->lengthtable[MAINCODE_SIZE + OFFSETCODE_SIZE + + LOWOFFSETCODE_SIZE], LENGTHCODE_SIZE, MAX_SYMBOL_LENGTH); + if (r != ARCHIVE_OK) + return (r); + } + + if (!rar->dictionary_size || !rar->lzss.window) + { + /* Seems as though dictionary sizes are not used. Even so, minimize + * memory usage as much as possible. + */ + void *new_window; + unsigned int new_size; + + if (rar->unp_size >= DICTIONARY_MAX_SIZE) + new_size = DICTIONARY_MAX_SIZE; + else + new_size = rar_fls((unsigned int)rar->unp_size) << 1; + new_window = realloc(rar->lzss.window, new_size); + if (new_window == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Unable to allocate memory for uncompressed data."); + return (ARCHIVE_FATAL); + } + rar->lzss.window = (unsigned char *)new_window; + rar->dictionary_size = new_size; + memset(rar->lzss.window, 0, rar->dictionary_size); + rar->lzss.mask = rar->dictionary_size - 1; + } + + rar->start_new_table = 0; + return (ARCHIVE_OK); +truncated_data: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated RAR file data"); + rar->valid = 0; + return (ARCHIVE_FATAL); +} + +static void +free_codes(struct archive_read *a) +{ + struct rar *rar = (struct rar *)(a->format->data); + free(rar->maincode.tree); + free(rar->offsetcode.tree); + free(rar->lowoffsetcode.tree); + free(rar->lengthcode.tree); + free(rar->maincode.table); + free(rar->offsetcode.table); + free(rar->lowoffsetcode.table); + free(rar->lengthcode.table); + memset(&rar->maincode, 0, sizeof(rar->maincode)); + memset(&rar->offsetcode, 0, sizeof(rar->offsetcode)); + memset(&rar->lowoffsetcode, 0, sizeof(rar->lowoffsetcode)); + memset(&rar->lengthcode, 0, sizeof(rar->lengthcode)); +} + + +static int +read_next_symbol(struct archive_read *a, struct huffman_code *code) +{ + unsigned char bit; + unsigned int bits; + int length, value, node; + struct rar *rar; + struct rar_br *br; + + if (!code->table) + { + if (make_table(a, code) != (ARCHIVE_OK)) + return -1; + } + + rar = (struct rar *)(a->format->data); + br = &(rar->br); + + /* Look ahead (peek) at bits */ + if (!rar_br_read_ahead(a, br, code->tablesize)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated RAR file data"); + rar->valid = 0; + return -1; + } + bits = rar_br_bits(br, code->tablesize); + + length = code->table[bits].length; + value = code->table[bits].value; + + if (length < 0) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid prefix code in bitstream"); + return -1; + } + + if (length <= code->tablesize) + { + /* Skip length bits */ + rar_br_consume(br, length); + return value; + } + + /* Skip tablesize bits */ + rar_br_consume(br, code->tablesize); + + node = value; + while (!(code->tree[node].branches[0] == + code->tree[node].branches[1])) + { + if (!rar_br_read_ahead(a, br, 1)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated RAR file data"); + rar->valid = 0; + return -1; + } + bit = rar_br_bits(br, 1); + rar_br_consume(br, 1); + + if (code->tree[node].branches[bit] < 0) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid prefix code in bitstream"); + return -1; + } + node = code->tree[node].branches[bit]; + } + + return code->tree[node].branches[0]; +} + +static int +create_code(struct archive_read *a, struct huffman_code *code, + unsigned char *lengths, int numsymbols, char maxlength) +{ + int i, j, codebits = 0, symbolsleft = numsymbols; + + code->numentries = 0; + code->numallocatedentries = 0; + if (new_node(code) < 0) { + archive_set_error(&a->archive, ENOMEM, + "Unable to allocate memory for node data."); + return (ARCHIVE_FATAL); + } + code->numentries = 1; + code->minlength = INT_MAX; + code->maxlength = INT_MIN; + codebits = 0; + for(i = 1; i <= maxlength; i++) + { + for(j = 0; j < numsymbols; j++) + { + if (lengths[j] != i) continue; + if (add_value(a, code, j, codebits, i) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + codebits++; + if (--symbolsleft <= 0) { break; break; } + } + codebits <<= 1; + } + return (ARCHIVE_OK); +} + +static int +add_value(struct archive_read *a, struct huffman_code *code, int value, + int codebits, int length) +{ + int repeatpos, lastnode, bitpos, bit, repeatnode, nextnode; + + free(code->table); + code->table = NULL; + + if(length > code->maxlength) + code->maxlength = length; + if(length < code->minlength) + code->minlength = length; + + repeatpos = -1; + if (repeatpos == 0 || (repeatpos >= 0 + && (((codebits >> (repeatpos - 1)) & 3) == 0 + || ((codebits >> (repeatpos - 1)) & 3) == 3))) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid repeat position"); + return (ARCHIVE_FATAL); + } + + lastnode = 0; + for (bitpos = length - 1; bitpos >= 0; bitpos--) + { + bit = (codebits >> bitpos) & 1; + + /* Leaf node check */ + if (code->tree[lastnode].branches[0] == + code->tree[lastnode].branches[1]) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Prefix found"); + return (ARCHIVE_FATAL); + } + + if (bitpos == repeatpos) + { + /* Open branch check */ + if (!(code->tree[lastnode].branches[bit] < 0)) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid repeating code"); + return (ARCHIVE_FATAL); + } + + if ((repeatnode = new_node(code)) < 0) { + archive_set_error(&a->archive, ENOMEM, + "Unable to allocate memory for node data."); + return (ARCHIVE_FATAL); + } + if ((nextnode = new_node(code)) < 0) { + archive_set_error(&a->archive, ENOMEM, + "Unable to allocate memory for node data."); + return (ARCHIVE_FATAL); + } + + /* Set branches */ + code->tree[lastnode].branches[bit] = repeatnode; + code->tree[repeatnode].branches[bit] = repeatnode; + code->tree[repeatnode].branches[bit^1] = nextnode; + lastnode = nextnode; + + bitpos++; /* terminating bit already handled, skip it */ + } + else + { + /* Open branch check */ + if (code->tree[lastnode].branches[bit] < 0) + { + if (new_node(code) < 0) { + archive_set_error(&a->archive, ENOMEM, + "Unable to allocate memory for node data."); + return (ARCHIVE_FATAL); + } + code->tree[lastnode].branches[bit] = code->numentries++; + } + + /* set to branch */ + lastnode = code->tree[lastnode].branches[bit]; + } + } + + if (!(code->tree[lastnode].branches[0] == -1 + && code->tree[lastnode].branches[1] == -2)) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Prefix found"); + return (ARCHIVE_FATAL); + } + + /* Set leaf value */ + code->tree[lastnode].branches[0] = value; + code->tree[lastnode].branches[1] = value; + + return (ARCHIVE_OK); +} + +static int +new_node(struct huffman_code *code) +{ + void *new_tree; + if (code->numallocatedentries == code->numentries) { + int new_num_entries = 256; + if (code->numentries > 0) { + new_num_entries = code->numentries * 2; + } + new_tree = realloc(code->tree, new_num_entries * sizeof(*code->tree)); + if (new_tree == NULL) + return (-1); + code->tree = (struct huffman_tree_node *)new_tree; + code->numallocatedentries = new_num_entries; + } + code->tree[code->numentries].branches[0] = -1; + code->tree[code->numentries].branches[1] = -2; + return 1; +} + +static int +make_table(struct archive_read *a, struct huffman_code *code) +{ + if (code->maxlength < code->minlength || code->maxlength > 10) + code->tablesize = 10; + else + code->tablesize = code->maxlength; + + code->table = + (struct huffman_table_entry *)calloc(1, sizeof(*code->table) + * ((size_t)1 << code->tablesize)); + + return make_table_recurse(a, code, 0, code->table, 0, code->tablesize); +} + +static int +make_table_recurse(struct archive_read *a, struct huffman_code *code, int node, + struct huffman_table_entry *table, int depth, + int maxdepth) +{ + int currtablesize, i, ret = (ARCHIVE_OK); + + if (!code->tree) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Huffman tree was not created."); + return (ARCHIVE_FATAL); + } + if (node < 0 || node >= code->numentries) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid location to Huffman tree specified."); + return (ARCHIVE_FATAL); + } + + currtablesize = 1 << (maxdepth - depth); + + if (code->tree[node].branches[0] == + code->tree[node].branches[1]) + { + for(i = 0; i < currtablesize; i++) + { + table[i].length = depth; + table[i].value = code->tree[node].branches[0]; + } + } + else if (node < 0) + { + for(i = 0; i < currtablesize; i++) + table[i].length = -1; + } + else + { + if(depth == maxdepth) + { + table[0].length = maxdepth + 1; + table[0].value = node; + } + else + { + ret |= make_table_recurse(a, code, code->tree[node].branches[0], table, + depth + 1, maxdepth); + ret |= make_table_recurse(a, code, code->tree[node].branches[1], + table + currtablesize / 2, depth + 1, maxdepth); + } + } + return ret; +} + +static int64_t +expand(struct archive_read *a, int64_t end) +{ + static const unsigned char lengthbases[] = + { 0, 1, 2, 3, 4, 5, 6, + 7, 8, 10, 12, 14, 16, 20, + 24, 28, 32, 40, 48, 56, 64, + 80, 96, 112, 128, 160, 192, 224 }; + static const unsigned char lengthbits[] = + { 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 2, 2, + 2, 2, 3, 3, 3, 3, 4, + 4, 4, 4, 5, 5, 5, 5 }; + static const unsigned int offsetbases[] = + { 0, 1, 2, 3, 4, 6, + 8, 12, 16, 24, 32, 48, + 64, 96, 128, 192, 256, 384, + 512, 768, 1024, 1536, 2048, 3072, + 4096, 6144, 8192, 12288, 16384, 24576, + 32768, 49152, 65536, 98304, 131072, 196608, + 262144, 327680, 393216, 458752, 524288, 589824, + 655360, 720896, 786432, 851968, 917504, 983040, + 1048576, 1310720, 1572864, 1835008, 2097152, 2359296, + 2621440, 2883584, 3145728, 3407872, 3670016, 3932160 }; + static const unsigned char offsetbits[] = + { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, + 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, + 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18 }; + static const unsigned char shortbases[] = + { 0, 4, 8, 16, 32, 64, 128, 192 }; + static const unsigned char shortbits[] = + { 2, 2, 3, 4, 5, 6, 6, 6 }; + + int symbol, offs, len, offsindex, lensymbol, i, offssymbol, lowoffsetsymbol; + unsigned char newfile; + struct rar *rar = (struct rar *)(a->format->data); + struct rar_br *br = &(rar->br); + + if (rar->filterstart < end) + end = rar->filterstart; + + while (1) + { + if (rar->output_last_match && + lzss_position(&rar->lzss) + rar->lastlength <= end) + { + lzss_emit_match(rar, rar->lastoffset, rar->lastlength); + rar->output_last_match = 0; + } + + if(rar->is_ppmd_block || rar->output_last_match || + lzss_position(&rar->lzss) >= end) + return lzss_position(&rar->lzss); + + if ((symbol = read_next_symbol(a, &rar->maincode)) < 0) + return (ARCHIVE_FATAL); + rar->output_last_match = 0; + + if (symbol < 256) + { + lzss_emit_literal(rar, symbol); + continue; + } + else if (symbol == 256) + { + if (!rar_br_read_ahead(a, br, 1)) + goto truncated_data; + newfile = !rar_br_bits(br, 1); + rar_br_consume(br, 1); + + if(newfile) + { + rar->start_new_block = 1; + if (!rar_br_read_ahead(a, br, 1)) + goto truncated_data; + rar->start_new_table = rar_br_bits(br, 1); + rar_br_consume(br, 1); + return lzss_position(&rar->lzss); + } + else + { + if (parse_codes(a) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + continue; + } + } + else if(symbol==257) + { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Parsing filters is unsupported."); + return (ARCHIVE_FAILED); + } + else if(symbol==258) + { + if(rar->lastlength == 0) + continue; + + offs = rar->lastoffset; + len = rar->lastlength; + } + else if (symbol <= 262) + { + offsindex = symbol - 259; + offs = rar->oldoffset[offsindex]; + + if ((lensymbol = read_next_symbol(a, &rar->lengthcode)) < 0) + goto bad_data; + if (lensymbol > (int)(sizeof(lengthbases)/sizeof(lengthbases[0]))) + goto bad_data; + if (lensymbol > (int)(sizeof(lengthbits)/sizeof(lengthbits[0]))) + goto bad_data; + len = lengthbases[lensymbol] + 2; + if (lengthbits[lensymbol] > 0) { + if (!rar_br_read_ahead(a, br, lengthbits[lensymbol])) + goto truncated_data; + len += rar_br_bits(br, lengthbits[lensymbol]); + rar_br_consume(br, lengthbits[lensymbol]); + } + + for (i = offsindex; i > 0; i--) + rar->oldoffset[i] = rar->oldoffset[i-1]; + rar->oldoffset[0] = offs; + } + else if(symbol<=270) + { + offs = shortbases[symbol-263] + 1; + if(shortbits[symbol-263] > 0) { + if (!rar_br_read_ahead(a, br, shortbits[symbol-263])) + goto truncated_data; + offs += rar_br_bits(br, shortbits[symbol-263]); + rar_br_consume(br, shortbits[symbol-263]); + } + + len = 2; + + for(i = 3; i > 0; i--) + rar->oldoffset[i] = rar->oldoffset[i-1]; + rar->oldoffset[0] = offs; + } + else + { + if (symbol-271 > (int)(sizeof(lengthbases)/sizeof(lengthbases[0]))) + goto bad_data; + if (symbol-271 > (int)(sizeof(lengthbits)/sizeof(lengthbits[0]))) + goto bad_data; + len = lengthbases[symbol-271]+3; + if(lengthbits[symbol-271] > 0) { + if (!rar_br_read_ahead(a, br, lengthbits[symbol-271])) + goto truncated_data; + len += rar_br_bits(br, lengthbits[symbol-271]); + rar_br_consume(br, lengthbits[symbol-271]); + } + + if ((offssymbol = read_next_symbol(a, &rar->offsetcode)) < 0) + goto bad_data; + if (offssymbol > (int)(sizeof(offsetbases)/sizeof(offsetbases[0]))) + goto bad_data; + if (offssymbol > (int)(sizeof(offsetbits)/sizeof(offsetbits[0]))) + goto bad_data; + offs = offsetbases[offssymbol]+1; + if(offsetbits[offssymbol] > 0) + { + if(offssymbol > 9) + { + if(offsetbits[offssymbol] > 4) { + if (!rar_br_read_ahead(a, br, offsetbits[offssymbol] - 4)) + goto truncated_data; + offs += rar_br_bits(br, offsetbits[offssymbol] - 4) << 4; + rar_br_consume(br, offsetbits[offssymbol] - 4); + } + + if(rar->numlowoffsetrepeats > 0) + { + rar->numlowoffsetrepeats--; + offs += rar->lastlowoffset; + } + else + { + if ((lowoffsetsymbol = + read_next_symbol(a, &rar->lowoffsetcode)) < 0) + return (ARCHIVE_FATAL); + if(lowoffsetsymbol == 16) + { + rar->numlowoffsetrepeats = 15; + offs += rar->lastlowoffset; + } + else + { + offs += lowoffsetsymbol; + rar->lastlowoffset = lowoffsetsymbol; + } + } + } + else { + if (!rar_br_read_ahead(a, br, offsetbits[offssymbol])) + goto truncated_data; + offs += rar_br_bits(br, offsetbits[offssymbol]); + rar_br_consume(br, offsetbits[offssymbol]); + } + } + + if (offs >= 0x40000) + len++; + if (offs >= 0x2000) + len++; + + for(i = 3; i > 0; i--) + rar->oldoffset[i] = rar->oldoffset[i-1]; + rar->oldoffset[0] = offs; + } + + rar->lastoffset = offs; + rar->lastlength = len; + rar->output_last_match = 1; + } +truncated_data: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated RAR file data"); + rar->valid = 0; + return (ARCHIVE_FATAL); +bad_data: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Bad RAR file data"); + return (ARCHIVE_FATAL); +} + +static int +copy_from_lzss_window(struct archive_read *a, const void **buffer, + int64_t startpos, int length) +{ + int windowoffs, firstpart; + struct rar *rar = (struct rar *)(a->format->data); + + if (!rar->unp_buffer) + { + if ((rar->unp_buffer = malloc(rar->unp_buffer_size)) == NULL) + { + archive_set_error(&a->archive, ENOMEM, + "Unable to allocate memory for uncompressed data."); + return (ARCHIVE_FATAL); + } + } + + windowoffs = lzss_offset_for_position(&rar->lzss, startpos); + if(windowoffs + length <= lzss_size(&rar->lzss)) { + memcpy(&rar->unp_buffer[rar->unp_offset], &rar->lzss.window[windowoffs], + length); + } else if (length <= lzss_size(&rar->lzss)) { + firstpart = lzss_size(&rar->lzss) - windowoffs; + if (firstpart < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Bad RAR file data"); + return (ARCHIVE_FATAL); + } + if (firstpart < length) { + memcpy(&rar->unp_buffer[rar->unp_offset], + &rar->lzss.window[windowoffs], firstpart); + memcpy(&rar->unp_buffer[rar->unp_offset + firstpart], + &rar->lzss.window[0], length - firstpart); + } else { + memcpy(&rar->unp_buffer[rar->unp_offset], + &rar->lzss.window[windowoffs], length); + } + } else { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Bad RAR file data"); + return (ARCHIVE_FATAL); + } + rar->unp_offset += length; + if (rar->unp_offset >= rar->unp_buffer_size) + *buffer = rar->unp_buffer; + else + *buffer = NULL; + return (ARCHIVE_OK); +} + +static const void * +rar_read_ahead(struct archive_read *a, size_t min, ssize_t *avail) +{ + struct rar *rar = (struct rar *)(a->format->data); + const void *h = __archive_read_ahead(a, min, avail); + int ret; + if (avail) + { + if (a->archive.read_data_is_posix_read && *avail > (ssize_t)a->archive.read_data_requested) + *avail = a->archive.read_data_requested; + if (*avail > rar->bytes_remaining) + *avail = (ssize_t)rar->bytes_remaining; + if (*avail < 0) + return NULL; + else if (*avail == 0 && rar->main_flags & MHD_VOLUME && + rar->file_flags & FHD_SPLIT_AFTER) + { + ret = archive_read_format_rar_read_header(a, a->entry); + if (ret == (ARCHIVE_EOF)) + { + rar->has_endarc_header = 1; + ret = archive_read_format_rar_read_header(a, a->entry); + } + if (ret != (ARCHIVE_OK)) + return NULL; + return rar_read_ahead(a, min, avail); + } + } + return h; +} diff --cc Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c index ec623c6,0000000..eeac1c8 mode 100644,000000..100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_xar.c @@@ -1,3340 -1,0 +1,3287 @@@ +/*- + * Copyright (c) 2009 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#if HAVE_LIBXML_XMLREADER_H +#include +#elif HAVE_BSDXML_H +#include +#elif HAVE_EXPAT_H +#include +#endif +#ifdef HAVE_BZLIB_H +#include +#endif +#if HAVE_LZMA_H +#include - #elif HAVE_LZMADEC_H - #include +#endif +#ifdef HAVE_ZLIB_H +#include +#endif + +#include "archive.h" +#include "archive_digest_private.h" +#include "archive_endian.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_private.h" +#include "archive_read_private.h" + +#if (!defined(HAVE_LIBXML_XMLREADER_H) && \ + !defined(HAVE_BSDXML_H) && !defined(HAVE_EXPAT_H)) ||\ + !defined(HAVE_ZLIB_H) || \ + !defined(ARCHIVE_HAS_MD5) || !defined(ARCHIVE_HAS_SHA1) +/* + * xar needs several external libraries. + * o libxml2 or expat --- XML parser + * o openssl or MD5/SHA1 hash function + * o zlib + * o bzlib2 (option) + * o liblzma (option) + */ +int +archive_read_support_format_xar(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_format_xar"); + + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Xar not supported on this platform"); + return (ARCHIVE_WARN); +} + +#else /* Support xar format */ + +/* #define DEBUG 1 */ +/* #define DEBUG_PRINT_TOC 1 */ +#if DEBUG_PRINT_TOC +#define PRINT_TOC(d, outbytes) do { \ + unsigned char *x = (unsigned char *)(uintptr_t)d; \ + unsigned char c = x[outbytes-1]; \ + x[outbytes - 1] = 0; \ + fprintf(stderr, "%s", x); \ + fprintf(stderr, "%c", c); \ + x[outbytes - 1] = c; \ +} while (0) +#else +#define PRINT_TOC(d, outbytes) +#endif + +#define HEADER_MAGIC 0x78617221 +#define HEADER_SIZE 28 +#define HEADER_VERSION 1 +#define CKSUM_NONE 0 +#define CKSUM_SHA1 1 +#define CKSUM_MD5 2 + +#define MD5_SIZE 16 +#define SHA1_SIZE 20 +#define MAX_SUM_SIZE 20 + +enum enctype { + NONE, + GZIP, + BZIP2, + LZMA, + XZ, +}; + +struct chksumval { + int alg; + size_t len; + unsigned char val[MAX_SUM_SIZE]; +}; + +struct chksumwork { + int alg; +#ifdef ARCHIVE_HAS_MD5 + archive_md5_ctx md5ctx; +#endif +#ifdef ARCHIVE_HAS_SHA1 + archive_sha1_ctx sha1ctx; +#endif +}; + +struct xattr { + struct xattr *next; + struct archive_string name; + uint64_t id; + uint64_t length; + uint64_t offset; + uint64_t size; + enum enctype encoding; + struct chksumval a_sum; + struct chksumval e_sum; + struct archive_string fstype; +}; + +struct xar_file { + struct xar_file *next; + struct xar_file *hdnext; + struct xar_file *parent; + int subdirs; + + unsigned int has; +#define HAS_DATA 0x00001 +#define HAS_PATHNAME 0x00002 +#define HAS_SYMLINK 0x00004 +#define HAS_TIME 0x00008 +#define HAS_UID 0x00010 +#define HAS_GID 0x00020 +#define HAS_MODE 0x00040 +#define HAS_TYPE 0x00080 +#define HAS_DEV 0x00100 +#define HAS_DEVMAJOR 0x00200 +#define HAS_DEVMINOR 0x00400 +#define HAS_INO 0x00800 +#define HAS_FFLAGS 0x01000 +#define HAS_XATTR 0x02000 +#define HAS_ACL 0x04000 + + uint64_t id; + uint64_t length; + uint64_t offset; + uint64_t size; + enum enctype encoding; + struct chksumval a_sum; + struct chksumval e_sum; + struct archive_string pathname; + struct archive_string symlink; + time_t ctime; + time_t mtime; + time_t atime; + struct archive_string uname; + int64_t uid; + struct archive_string gname; + int64_t gid; + mode_t mode; + dev_t dev; + dev_t devmajor; + dev_t devminor; + int64_t ino64; + struct archive_string fflags_text; + unsigned int link; + unsigned int nlink; + struct archive_string hardlink; + struct xattr *xattr_list; +}; + +struct hdlink { + struct hdlink *next; + + unsigned int id; + int cnt; + struct xar_file *files; +}; + +struct heap_queue { + struct xar_file **files; + int allocated; + int used; +}; + +enum xmlstatus { + INIT, + XAR, + TOC, + TOC_CREATION_TIME, + TOC_CHECKSUM, + TOC_CHECKSUM_OFFSET, + TOC_CHECKSUM_SIZE, + TOC_FILE, + FILE_DATA, + FILE_DATA_LENGTH, + FILE_DATA_OFFSET, + FILE_DATA_SIZE, + FILE_DATA_ENCODING, + FILE_DATA_A_CHECKSUM, + FILE_DATA_E_CHECKSUM, + FILE_DATA_CONTENT, + FILE_EA, + FILE_EA_LENGTH, + FILE_EA_OFFSET, + FILE_EA_SIZE, + FILE_EA_ENCODING, + FILE_EA_A_CHECKSUM, + FILE_EA_E_CHECKSUM, + FILE_EA_NAME, + FILE_EA_FSTYPE, + FILE_CTIME, + FILE_MTIME, + FILE_ATIME, + FILE_GROUP, + FILE_GID, + FILE_USER, + FILE_UID, + FILE_MODE, + FILE_DEVICE, + FILE_DEVICE_MAJOR, + FILE_DEVICE_MINOR, + FILE_DEVICENO, + FILE_INODE, + FILE_LINK, + FILE_TYPE, + FILE_NAME, + FILE_ACL, + FILE_ACL_DEFAULT, + FILE_ACL_ACCESS, + FILE_ACL_APPLEEXTENDED, + /* BSD file flags. */ + FILE_FLAGS, + FILE_FLAGS_USER_NODUMP, + FILE_FLAGS_USER_IMMUTABLE, + FILE_FLAGS_USER_APPEND, + FILE_FLAGS_USER_OPAQUE, + FILE_FLAGS_USER_NOUNLINK, + FILE_FLAGS_SYS_ARCHIVED, + FILE_FLAGS_SYS_IMMUTABLE, + FILE_FLAGS_SYS_APPEND, + FILE_FLAGS_SYS_NOUNLINK, + FILE_FLAGS_SYS_SNAPSHOT, + /* Linux file flags. */ + FILE_EXT2, + FILE_EXT2_SecureDeletion, + FILE_EXT2_Undelete, + FILE_EXT2_Compress, + FILE_EXT2_Synchronous, + FILE_EXT2_Immutable, + FILE_EXT2_AppendOnly, + FILE_EXT2_NoDump, + FILE_EXT2_NoAtime, + FILE_EXT2_CompDirty, + FILE_EXT2_CompBlock, + FILE_EXT2_NoCompBlock, + FILE_EXT2_CompError, + FILE_EXT2_BTree, + FILE_EXT2_HashIndexed, + FILE_EXT2_iMagic, + FILE_EXT2_Journaled, + FILE_EXT2_NoTail, + FILE_EXT2_DirSync, + FILE_EXT2_TopDir, + FILE_EXT2_Reserved, + UNKNOWN, +}; + +struct unknown_tag { + struct unknown_tag *next; + struct archive_string name; +}; + +struct xar { + uint64_t offset; /* Current position in the file. */ + int64_t total; + uint64_t h_base; + int end_of_file; +#define OUTBUFF_SIZE (1024 * 64) + unsigned char *outbuff; + + enum xmlstatus xmlsts; + enum xmlstatus xmlsts_unknown; + struct unknown_tag *unknowntags; + int base64text; + + /* + * TOC + */ + uint64_t toc_remaining; + uint64_t toc_total; + uint64_t toc_chksum_offset; + uint64_t toc_chksum_size; + + /* + * For Decoding data. + */ + enum enctype rd_encoding; + z_stream stream; + int stream_valid; +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) + bz_stream bzstream; + int bzstream_valid; +#endif +#if HAVE_LZMA_H && HAVE_LIBLZMA + lzma_stream lzstream; + int lzstream_valid; - #elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC - lzmadec_stream lzstream; - int lzstream_valid; +#endif + /* + * For Checksum data. + */ + struct chksumwork a_sumwrk; + struct chksumwork e_sumwrk; + + struct xar_file *file; /* current reading file. */ + struct xattr *xattr; /* current reading extended attribute. */ + struct heap_queue file_queue; + struct xar_file *hdlink_orgs; + struct hdlink *hdlink_list; + + int entry_init; + uint64_t entry_total; + uint64_t entry_remaining; + size_t entry_unconsumed; + uint64_t entry_size; + enum enctype entry_encoding; + struct chksumval entry_a_sum; + struct chksumval entry_e_sum; + + struct archive_string_conv *sconv; +}; + +struct xmlattr { + struct xmlattr *next; + char *name; + char *value; +}; + +struct xmlattr_list { + struct xmlattr *first; + struct xmlattr **last; +}; + +static int xar_bid(struct archive_read *, int); +static int xar_read_header(struct archive_read *, + struct archive_entry *); +static int xar_read_data(struct archive_read *, + const void **, size_t *, int64_t *); +static int xar_read_data_skip(struct archive_read *); +static int xar_cleanup(struct archive_read *); +static int move_reading_point(struct archive_read *, uint64_t); +static int rd_contents_init(struct archive_read *, + enum enctype, int, int); +static int rd_contents(struct archive_read *, const void **, + size_t *, size_t *, uint64_t); +static uint64_t atol10(const char *, size_t); +static int64_t atol8(const char *, size_t); +static size_t atohex(unsigned char *, size_t, const char *, size_t); +static time_t parse_time(const char *p, size_t n); +static int heap_add_entry(struct archive_read *a, + struct heap_queue *, struct xar_file *); +static struct xar_file *heap_get_entry(struct heap_queue *); +static int add_link(struct archive_read *, + struct xar *, struct xar_file *); +static void checksum_init(struct archive_read *, int, int); +static void checksum_update(struct archive_read *, const void *, + size_t, const void *, size_t); +static int checksum_final(struct archive_read *, const void *, + size_t, const void *, size_t); ++static void checksum_cleanup(struct archive_read *); +static int decompression_init(struct archive_read *, enum enctype); +static int decompress(struct archive_read *, const void **, + size_t *, const void *, size_t *); +static int decompression_cleanup(struct archive_read *); +static void xmlattr_cleanup(struct xmlattr_list *); +static int file_new(struct archive_read *, + struct xar *, struct xmlattr_list *); +static void file_free(struct xar_file *); +static int xattr_new(struct archive_read *, + struct xar *, struct xmlattr_list *); +static void xattr_free(struct xattr *); +static int getencoding(struct xmlattr_list *); +static int getsumalgorithm(struct xmlattr_list *); +static int unknowntag_start(struct archive_read *, + struct xar *, const char *); +static void unknowntag_end(struct xar *, const char *); +static int xml_start(struct archive_read *, + const char *, struct xmlattr_list *); +static void xml_end(void *, const char *); +static void xml_data(void *, const char *, int); +static int xml_parse_file_flags(struct xar *, const char *); +static int xml_parse_file_ext2(struct xar *, const char *); +#if defined(HAVE_LIBXML_XMLREADER_H) +static int xml2_xmlattr_setup(struct archive_read *, + struct xmlattr_list *, xmlTextReaderPtr); +static int xml2_read_cb(void *, char *, int); +static int xml2_close_cb(void *); +static void xml2_error_hdr(void *, const char *, xmlParserSeverities, + xmlTextReaderLocatorPtr); +static int xml2_read_toc(struct archive_read *); +#elif defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H) +struct expat_userData { + int state; + struct archive_read *archive; +}; +static int expat_xmlattr_setup(struct archive_read *, + struct xmlattr_list *, const XML_Char **); +static void expat_start_cb(void *, const XML_Char *, const XML_Char **); +static void expat_end_cb(void *, const XML_Char *); +static void expat_data_cb(void *, const XML_Char *, int); +static int expat_read_toc(struct archive_read *); +#endif + +int +archive_read_support_format_xar(struct archive *_a) +{ + struct xar *xar; + struct archive_read *a = (struct archive_read *)_a; + int r; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_format_xar"); + + xar = (struct xar *)calloc(1, sizeof(*xar)); + if (xar == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate xar data"); + return (ARCHIVE_FATAL); + } + + r = __archive_read_register_format(a, + xar, + "xar", + xar_bid, + NULL, + xar_read_header, + xar_read_data, + xar_read_data_skip, + NULL, + xar_cleanup, + NULL, + NULL); + if (r != ARCHIVE_OK) + free(xar); + return (r); +} + +static int +xar_bid(struct archive_read *a, int best_bid) +{ + const unsigned char *b; + int bid; + + (void)best_bid; /* UNUSED */ + + b = __archive_read_ahead(a, HEADER_SIZE, NULL); + if (b == NULL) + return (-1); + + bid = 0; + /* + * Verify magic code + */ + if (archive_be32dec(b) != HEADER_MAGIC) + return (0); + bid += 32; + /* + * Verify header size + */ + if (archive_be16dec(b+4) != HEADER_SIZE) + return (0); + bid += 16; + /* + * Verify header version + */ + if (archive_be16dec(b+6) != HEADER_VERSION) + return (0); + bid += 16; + /* + * Verify type of checksum + */ + switch (archive_be32dec(b+24)) { + case CKSUM_NONE: + case CKSUM_SHA1: + case CKSUM_MD5: + bid += 32; + break; + default: + return (0); + } + + return (bid); +} + +static int +read_toc(struct archive_read *a) +{ + struct xar *xar; + struct xar_file *file; + const unsigned char *b; + uint64_t toc_compressed_size; + uint64_t toc_uncompressed_size; + uint32_t toc_chksum_alg; + ssize_t bytes; + int r; + + xar = (struct xar *)(a->format->data); + + /* + * Read xar header. + */ + b = __archive_read_ahead(a, HEADER_SIZE, &bytes); + if (bytes < 0) + return ((int)bytes); + if (bytes < HEADER_SIZE) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated archive header"); + return (ARCHIVE_FATAL); + } + + if (archive_be32dec(b) != HEADER_MAGIC) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid header magic"); + return (ARCHIVE_FATAL); + } + if (archive_be16dec(b+6) != HEADER_VERSION) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Unsupported header version(%d)", + archive_be16dec(b+6)); + return (ARCHIVE_FATAL); + } + toc_compressed_size = archive_be64dec(b+8); + xar->toc_remaining = toc_compressed_size; + toc_uncompressed_size = archive_be64dec(b+16); + toc_chksum_alg = archive_be32dec(b+24); + __archive_read_consume(a, HEADER_SIZE); + xar->offset += HEADER_SIZE; + xar->toc_total = 0; + + /* + * Read TOC(Table of Contents). + */ + /* Initialize reading contents. */ + r = move_reading_point(a, HEADER_SIZE); + if (r != ARCHIVE_OK) + return (r); + r = rd_contents_init(a, GZIP, toc_chksum_alg, CKSUM_NONE); + if (r != ARCHIVE_OK) + return (r); + +#ifdef HAVE_LIBXML_XMLREADER_H + r = xml2_read_toc(a); +#elif defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H) + r = expat_read_toc(a); +#endif + if (r != ARCHIVE_OK) + return (r); + + /* Set 'The HEAP' base. */ + xar->h_base = xar->offset; + if (xar->toc_total != toc_uncompressed_size) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "TOC uncompressed size error"); + return (ARCHIVE_FATAL); + } + + /* + * Checksum TOC + */ + if (toc_chksum_alg != CKSUM_NONE) { + r = move_reading_point(a, xar->toc_chksum_offset); + if (r != ARCHIVE_OK) + return (r); + b = __archive_read_ahead(a, + (size_t)xar->toc_chksum_size, &bytes); + if (bytes < 0) + return ((int)bytes); + if ((uint64_t)bytes < xar->toc_chksum_size) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated archive file"); + return (ARCHIVE_FATAL); + } + r = checksum_final(a, b, + (size_t)xar->toc_chksum_size, NULL, 0); + __archive_read_consume(a, xar->toc_chksum_size); + xar->offset += xar->toc_chksum_size; + if (r != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + + /* + * Connect hardlinked files. + */ + for (file = xar->hdlink_orgs; file != NULL; file = file->hdnext) { + struct hdlink **hdlink; + + for (hdlink = &(xar->hdlink_list); *hdlink != NULL; + hdlink = &((*hdlink)->next)) { + if ((*hdlink)->id == file->id) { + struct hdlink *hltmp; + struct xar_file *f2; + int nlink = (*hdlink)->cnt + 1; + + file->nlink = nlink; + for (f2 = (*hdlink)->files; f2 != NULL; + f2 = f2->hdnext) { + f2->nlink = nlink; + archive_string_copy( + &(f2->hardlink), &(file->pathname)); + } + /* Remove resolved files from hdlist_list. */ + hltmp = *hdlink; + *hdlink = hltmp->next; + free(hltmp); + break; + } + } + } + a->archive.archive_format = ARCHIVE_FORMAT_XAR; + a->archive.archive_format_name = "xar"; + + return (ARCHIVE_OK); +} + +static int +xar_read_header(struct archive_read *a, struct archive_entry *entry) +{ + struct xar *xar; + struct xar_file *file; + struct xattr *xattr; + int r; + + xar = (struct xar *)(a->format->data); + r = ARCHIVE_OK; + + if (xar->offset == 0) { + /* Create a character conversion object. */ + if (xar->sconv == NULL) { + xar->sconv = archive_string_conversion_from_charset( + &(a->archive), "UTF-8", 1); + if (xar->sconv == NULL) + return (ARCHIVE_FATAL); + } + + /* Read TOC. */ + r = read_toc(a); + if (r != ARCHIVE_OK) + return (r); + } + + for (;;) { + file = xar->file = heap_get_entry(&(xar->file_queue)); + if (file == NULL) { + xar->end_of_file = 1; + return (ARCHIVE_EOF); + } + if ((file->mode & AE_IFMT) != AE_IFDIR) + break; + if (file->has != (HAS_PATHNAME | HAS_TYPE)) + break; + /* + * If a file type is a directory and it does not have + * any metadata, do not export. + */ + file_free(file); + } + archive_entry_set_atime(entry, file->atime, 0); + archive_entry_set_ctime(entry, file->ctime, 0); + archive_entry_set_mtime(entry, file->mtime, 0); + archive_entry_set_gid(entry, file->gid); + if (file->gname.length > 0 && + archive_entry_copy_gname_l(entry, file->gname.s, + archive_strlen(&(file->gname)), xar->sconv) != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Gname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Gname cannot be converted from %s to current locale.", + archive_string_conversion_charset_name(xar->sconv)); + r = ARCHIVE_WARN; + } + archive_entry_set_uid(entry, file->uid); + if (file->uname.length > 0 && + archive_entry_copy_uname_l(entry, file->uname.s, + archive_strlen(&(file->uname)), xar->sconv) != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Uname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Uname cannot be converted from %s to current locale.", + archive_string_conversion_charset_name(xar->sconv)); + r = ARCHIVE_WARN; + } + archive_entry_set_mode(entry, file->mode); + if (archive_entry_copy_pathname_l(entry, file->pathname.s, + archive_strlen(&(file->pathname)), xar->sconv) != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Pathname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Pathname cannot be converted from %s to current locale.", + archive_string_conversion_charset_name(xar->sconv)); + r = ARCHIVE_WARN; + } + + + if (file->symlink.length > 0 && + archive_entry_copy_symlink_l(entry, file->symlink.s, + archive_strlen(&(file->symlink)), xar->sconv) != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Linkname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Linkname cannot be converted from %s to current locale.", + archive_string_conversion_charset_name(xar->sconv)); + r = ARCHIVE_WARN; + } + /* Set proper nlink. */ + if ((file->mode & AE_IFMT) == AE_IFDIR) + archive_entry_set_nlink(entry, file->subdirs + 2); + else + archive_entry_set_nlink(entry, file->nlink); + archive_entry_set_size(entry, file->size); + if (archive_strlen(&(file->hardlink)) > 0) + archive_entry_set_hardlink(entry, file->hardlink.s); + archive_entry_set_ino64(entry, file->ino64); + if (file->has & HAS_DEV) + archive_entry_set_dev(entry, file->dev); + if (file->has & HAS_DEVMAJOR) + archive_entry_set_devmajor(entry, file->devmajor); + if (file->has & HAS_DEVMINOR) + archive_entry_set_devminor(entry, file->devminor); + if (archive_strlen(&(file->fflags_text)) > 0) + archive_entry_copy_fflags_text(entry, file->fflags_text.s); + + xar->entry_init = 1; + xar->entry_total = 0; + xar->entry_remaining = file->length; + xar->entry_size = file->size; + xar->entry_encoding = file->encoding; + xar->entry_a_sum = file->a_sum; + xar->entry_e_sum = file->e_sum; + /* + * Read extended attributes. + */ + xattr = file->xattr_list; + while (xattr != NULL) { + const void *d; + size_t outbytes, used; + + r = move_reading_point(a, xattr->offset); + if (r != ARCHIVE_OK) + break; + r = rd_contents_init(a, xattr->encoding, + xattr->a_sum.alg, xattr->e_sum.alg); + if (r != ARCHIVE_OK) + break; + d = NULL; + r = rd_contents(a, &d, &outbytes, &used, xattr->length); + if (r != ARCHIVE_OK) + break; + if (outbytes != xattr->size) { + archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, + "Decompressed size error"); + r = ARCHIVE_FATAL; + break; + } + r = checksum_final(a, + xattr->a_sum.val, xattr->a_sum.len, + xattr->e_sum.val, xattr->e_sum.len); + if (r != ARCHIVE_OK) + break; + archive_entry_xattr_add_entry(entry, + xattr->name.s, d, outbytes); + xattr = xattr->next; + } + if (r != ARCHIVE_OK) { + file_free(file); + return (r); + } + + if (xar->entry_remaining > 0) + /* Move reading point to the beginning of current + * file contents. */ + r = move_reading_point(a, file->offset); + else + r = ARCHIVE_OK; + + file_free(file); + return (r); +} + +static int +xar_read_data(struct archive_read *a, + const void **buff, size_t *size, int64_t *offset) +{ + struct xar *xar; + size_t used; + int r; + + xar = (struct xar *)(a->format->data); + + if (xar->entry_unconsumed) { + __archive_read_consume(a, xar->entry_unconsumed); + xar->entry_unconsumed = 0; + } + + if (xar->end_of_file || xar->entry_remaining <= 0) { + r = ARCHIVE_EOF; + goto abort_read_data; + } + + if (xar->entry_init) { + r = rd_contents_init(a, xar->entry_encoding, + xar->entry_a_sum.alg, xar->entry_e_sum.alg); + if (r != ARCHIVE_OK) { + xar->entry_remaining = 0; + return (r); + } + xar->entry_init = 0; + } + + *buff = NULL; + r = rd_contents(a, buff, size, &used, xar->entry_remaining); + if (r != ARCHIVE_OK) + goto abort_read_data; + + *offset = xar->entry_total; + xar->entry_total += *size; + xar->total += *size; + xar->offset += used; + xar->entry_remaining -= used; + xar->entry_unconsumed = used; + + if (xar->entry_remaining == 0) { + if (xar->entry_total != xar->entry_size) { + archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, + "Decompressed size error"); + r = ARCHIVE_FATAL; + goto abort_read_data; + } + r = checksum_final(a, + xar->entry_a_sum.val, xar->entry_a_sum.len, + xar->entry_e_sum.val, xar->entry_e_sum.len); + if (r != ARCHIVE_OK) + goto abort_read_data; + } + + return (ARCHIVE_OK); +abort_read_data: + *buff = NULL; + *size = 0; + *offset = xar->total; + return (r); +} + +static int +xar_read_data_skip(struct archive_read *a) +{ + struct xar *xar; + int64_t bytes_skipped; + + xar = (struct xar *)(a->format->data); + if (xar->end_of_file) + return (ARCHIVE_EOF); + bytes_skipped = __archive_read_consume(a, xar->entry_remaining + + xar->entry_unconsumed); + if (bytes_skipped < 0) + return (ARCHIVE_FATAL); + xar->offset += bytes_skipped; + xar->entry_unconsumed = 0; + return (ARCHIVE_OK); +} + +static int +xar_cleanup(struct archive_read *a) +{ + struct xar *xar; + struct hdlink *hdlink; + int i; + int r; + + xar = (struct xar *)(a->format->data); ++ checksum_cleanup(a); + r = decompression_cleanup(a); + hdlink = xar->hdlink_list; + while (hdlink != NULL) { + struct hdlink *next = hdlink->next; + + free(hdlink); + hdlink = next; + } + for (i = 0; i < xar->file_queue.used; i++) + file_free(xar->file_queue.files[i]); ++ free(xar->file_queue.files); + while (xar->unknowntags != NULL) { + struct unknown_tag *tag; + + tag = xar->unknowntags; + xar->unknowntags = tag->next; + archive_string_free(&(tag->name)); + free(tag); + } + free(xar->outbuff); + free(xar); + a->format->data = NULL; + return (r); +} + +static int +move_reading_point(struct archive_read *a, uint64_t offset) +{ + struct xar *xar; + + xar = (struct xar *)(a->format->data); + if (xar->offset - xar->h_base != offset) { + /* Seek forward to the start of file contents. */ + int64_t step; + + step = offset - (xar->offset - xar->h_base); + if (step > 0) { + step = __archive_read_consume(a, step); + if (step < 0) + return ((int)step); + xar->offset += step; + } else { + int64_t pos = __archive_read_seek(a, offset, SEEK_SET); + if (pos == ARCHIVE_FAILED) { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "Cannot seek."); + return (ARCHIVE_FAILED); + } + xar->offset = pos; + } + } + return (ARCHIVE_OK); +} + +static int +rd_contents_init(struct archive_read *a, enum enctype encoding, + int a_sum_alg, int e_sum_alg) +{ + int r; + + /* Init decompress library. */ + if ((r = decompression_init(a, encoding)) != ARCHIVE_OK) + return (r); + /* Init checksum library. */ + checksum_init(a, a_sum_alg, e_sum_alg); + return (ARCHIVE_OK); +} + +static int +rd_contents(struct archive_read *a, const void **buff, size_t *size, + size_t *used, uint64_t remaining) +{ + const unsigned char *b; + ssize_t bytes; + + /* Get whatever bytes are immediately available. */ + b = __archive_read_ahead(a, 1, &bytes); + if (bytes < 0) + return ((int)bytes); + if (bytes == 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Truncated archive file"); + return (ARCHIVE_FATAL); + } + if ((uint64_t)bytes > remaining) + bytes = (ssize_t)remaining; + + /* + * Decompress contents of file. + */ + *used = bytes; + if (decompress(a, buff, size, b, used) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* + * Update checksum of a compressed data and a extracted data. + */ + checksum_update(a, b, *used, *buff, *size); + + return (ARCHIVE_OK); +} + +/* + * Note that this implementation does not (and should not!) obey + * locale settings; you cannot simply substitute strtol here, since + * it does obey locale. + */ + +static uint64_t +atol10(const char *p, size_t char_cnt) +{ + uint64_t l; + int digit; + + l = 0; + digit = *p - '0'; + while (digit >= 0 && digit < 10 && char_cnt-- > 0) { + l = (l * 10) + digit; + digit = *++p - '0'; + } + return (l); +} + +static int64_t +atol8(const char *p, size_t char_cnt) +{ + int64_t l; + int digit; + + l = 0; + while (char_cnt-- > 0) { + if (*p >= '0' && *p <= '7') + digit = *p - '0'; + else + break; + p++; + l <<= 3; + l |= digit; + } + return (l); +} + +static size_t +atohex(unsigned char *b, size_t bsize, const char *p, size_t psize) +{ + size_t fbsize = bsize; + + while (bsize && psize > 1) { + unsigned char x; + + if (p[0] >= 'a' && p[0] <= 'z') + x = (p[0] - 'a' + 0x0a) << 4; + else if (p[0] >= 'A' && p[0] <= 'Z') + x = (p[0] - 'A' + 0x0a) << 4; + else if (p[0] >= '0' && p[0] <= '9') + x = (p[0] - '0') << 4; + else + return (-1); + if (p[1] >= 'a' && p[1] <= 'z') + x |= p[1] - 'a' + 0x0a; + else if (p[1] >= 'A' && p[1] <= 'Z') + x |= p[1] - 'A' + 0x0a; + else if (p[1] >= '0' && p[1] <= '9') + x |= p[1] - '0'; + else + return (-1); + + *b++ = x; + bsize--; + p += 2; + psize -= 2; + } + return (fbsize - bsize); +} + +static time_t +time_from_tm(struct tm *t) +{ +#if HAVE_TIMEGM + /* Use platform timegm() if available. */ + return (timegm(t)); +#elif HAVE__MKGMTIME64 + return (_mkgmtime64(t)); +#else + /* Else use direct calculation using POSIX assumptions. */ + /* First, fix up tm_yday based on the year/month/day. */ + mktime(t); + /* Then we can compute timegm() from first principles. */ + return (t->tm_sec + + t->tm_min * 60 + + t->tm_hour * 3600 + + t->tm_yday * 86400 + + (t->tm_year - 70) * 31536000 + + ((t->tm_year - 69) / 4) * 86400 + - ((t->tm_year - 1) / 100) * 86400 + + ((t->tm_year + 299) / 400) * 86400); +#endif +} + +static time_t +parse_time(const char *p, size_t n) +{ + struct tm tm; + time_t t = 0; + int64_t data; + + memset(&tm, 0, sizeof(tm)); + if (n != 20) + return (t); + data = atol10(p, 4); + if (data < 1900) + return (t); + tm.tm_year = (int)data - 1900; + p += 4; + if (*p++ != '-') + return (t); + data = atol10(p, 2); + if (data < 1 || data > 12) + return (t); + tm.tm_mon = (int)data -1; + p += 2; + if (*p++ != '-') + return (t); + data = atol10(p, 2); + if (data < 1 || data > 31) + return (t); + tm.tm_mday = (int)data; + p += 2; + if (*p++ != 'T') + return (t); + data = atol10(p, 2); + if (data < 0 || data > 23) + return (t); + tm.tm_hour = (int)data; + p += 2; + if (*p++ != ':') + return (t); + data = atol10(p, 2); + if (data < 0 || data > 59) + return (t); + tm.tm_min = (int)data; + p += 2; + if (*p++ != ':') + return (t); + data = atol10(p, 2); + if (data < 0 || data > 60) + return (t); + tm.tm_sec = (int)data; +#if 0 + p += 2; + if (*p != 'Z') + return (t); +#endif + + t = time_from_tm(&tm); + + return (t); +} + +static int +heap_add_entry(struct archive_read *a, + struct heap_queue *heap, struct xar_file *file) +{ + uint64_t file_id, parent_id; + int hole, parent; + + /* Expand our pending files list as necessary. */ + if (heap->used >= heap->allocated) { + struct xar_file **new_pending_files; + int new_size = heap->allocated * 2; + + if (heap->allocated < 1024) + new_size = 1024; + /* Overflow might keep us from growing the list. */ + if (new_size <= heap->allocated) { + archive_set_error(&a->archive, + ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + new_pending_files = (struct xar_file **) + malloc(new_size * sizeof(new_pending_files[0])); + if (new_pending_files == NULL) { + archive_set_error(&a->archive, + ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + 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; + heap->allocated = new_size; + } + + file_id = file->id; + + /* + * Start with hole at end, walk it up tree to find insertion point. + */ + hole = heap->used++; + while (hole > 0) { + parent = (hole - 1)/2; + parent_id = heap->files[parent]->id; + if (file_id >= parent_id) { + heap->files[hole] = file; + return (ARCHIVE_OK); + } + /* Move parent into hole <==> move hole up tree. */ + heap->files[hole] = heap->files[parent]; + hole = parent; + } + heap->files[0] = file; + + return (ARCHIVE_OK); +} + +static struct xar_file * +heap_get_entry(struct heap_queue *heap) +{ + uint64_t a_id, b_id, c_id; + int a, b, c; + struct xar_file *r, *tmp; + + if (heap->used < 1) + return (NULL); + + /* + * The first file in the list is the earliest; we'll return this. + */ + r = heap->files[0]; + + /* + * Move the last item in the heap to the root of the tree + */ + heap->files[0] = heap->files[--(heap->used)]; + + /* + * Rebalance the heap. + */ + a = 0; /* Starting element and its heap key */ + a_id = heap->files[a]->id; + for (;;) { + b = a + a + 1; /* First child */ + if (b >= heap->used) + return (r); + b_id = heap->files[b]->id; + c = b + 1; /* Use second child if it is smaller. */ + if (c < heap->used) { + c_id = heap->files[c]->id; + if (c_id < b_id) { + b = c; + b_id = c_id; + } + } + if (a_id <= b_id) + return (r); + tmp = heap->files[a]; + heap->files[a] = heap->files[b]; + heap->files[b] = tmp; + a = b; + } +} + +static int +add_link(struct archive_read *a, struct xar *xar, struct xar_file *file) +{ + struct hdlink *hdlink; + + for (hdlink = xar->hdlink_list; hdlink != NULL; hdlink = hdlink->next) { + if (hdlink->id == file->link) { + file->hdnext = hdlink->files; + hdlink->cnt++; + hdlink->files = file; + return (ARCHIVE_OK); + } + } + hdlink = malloc(sizeof(*hdlink)); + if (hdlink == NULL) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + file->hdnext = NULL; + hdlink->id = file->link; + hdlink->cnt = 1; + hdlink->files = file; + hdlink->next = xar->hdlink_list; + xar->hdlink_list = hdlink; + return (ARCHIVE_OK); +} + +static void +_checksum_init(struct chksumwork *sumwrk, int sum_alg) +{ + sumwrk->alg = sum_alg; + switch (sum_alg) { + case CKSUM_NONE: + break; + case CKSUM_SHA1: + archive_sha1_init(&(sumwrk->sha1ctx)); + break; + case CKSUM_MD5: + archive_md5_init(&(sumwrk->md5ctx)); + break; + } +} + +static void +_checksum_update(struct chksumwork *sumwrk, const void *buff, size_t size) +{ + + switch (sumwrk->alg) { + case CKSUM_NONE: + break; + case CKSUM_SHA1: + archive_sha1_update(&(sumwrk->sha1ctx), buff, size); + break; + case CKSUM_MD5: + archive_md5_update(&(sumwrk->md5ctx), buff, size); + break; + } +} + +static int +_checksum_final(struct chksumwork *sumwrk, const void *val, size_t len) +{ + unsigned char sum[MAX_SUM_SIZE]; + int r = ARCHIVE_OK; + + switch (sumwrk->alg) { + case CKSUM_NONE: + break; + case CKSUM_SHA1: + archive_sha1_final(&(sumwrk->sha1ctx), sum); + if (len != SHA1_SIZE || + memcmp(val, sum, SHA1_SIZE) != 0) + r = ARCHIVE_FAILED; + break; + case CKSUM_MD5: + archive_md5_final(&(sumwrk->md5ctx), sum); + if (len != MD5_SIZE || + memcmp(val, sum, MD5_SIZE) != 0) + r = ARCHIVE_FAILED; + break; + } + return (r); +} + +static void +checksum_init(struct archive_read *a, int a_sum_alg, int e_sum_alg) +{ + struct xar *xar; + + xar = (struct xar *)(a->format->data); + _checksum_init(&(xar->a_sumwrk), a_sum_alg); + _checksum_init(&(xar->e_sumwrk), e_sum_alg); +} + +static void +checksum_update(struct archive_read *a, const void *abuff, size_t asize, + const void *ebuff, size_t esize) +{ + struct xar *xar; + + xar = (struct xar *)(a->format->data); + _checksum_update(&(xar->a_sumwrk), abuff, asize); + _checksum_update(&(xar->e_sumwrk), ebuff, esize); +} + +static int +checksum_final(struct archive_read *a, const void *a_sum_val, + size_t a_sum_len, const void *e_sum_val, size_t e_sum_len) +{ + struct xar *xar; + int r; + + xar = (struct xar *)(a->format->data); + r = _checksum_final(&(xar->a_sumwrk), a_sum_val, a_sum_len); + if (r == ARCHIVE_OK) + r = _checksum_final(&(xar->e_sumwrk), e_sum_val, e_sum_len); + if (r != ARCHIVE_OK) + archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, + "Sumcheck error"); + return (r); +} + +static int +decompression_init(struct archive_read *a, enum enctype encoding) +{ + struct xar *xar; + const char *detail; + int r; + + xar = (struct xar *)(a->format->data); + xar->rd_encoding = encoding; + switch (encoding) { + case NONE: + break; + case GZIP: + if (xar->stream_valid) + r = inflateReset(&(xar->stream)); + else + r = inflateInit(&(xar->stream)); + if (r != Z_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Couldn't initialize zlib stream."); + return (ARCHIVE_FATAL); + } + xar->stream_valid = 1; + xar->stream.total_in = 0; + xar->stream.total_out = 0; + break; +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) + case BZIP2: + if (xar->bzstream_valid) { + BZ2_bzDecompressEnd(&(xar->bzstream)); + xar->bzstream_valid = 0; + } + r = BZ2_bzDecompressInit(&(xar->bzstream), 0, 0); + if (r == BZ_MEM_ERROR) + r = BZ2_bzDecompressInit(&(xar->bzstream), 0, 1); + if (r != BZ_OK) { + int err = ARCHIVE_ERRNO_MISC; + detail = NULL; + switch (r) { + case BZ_PARAM_ERROR: + detail = "invalid setup parameter"; + break; + case BZ_MEM_ERROR: + err = ENOMEM; + detail = "out of memory"; + break; + case BZ_CONFIG_ERROR: + detail = "mis-compiled library"; + break; + } + archive_set_error(&a->archive, err, + "Internal error initializing decompressor: %s", + detail == NULL ? "??" : detail); + xar->bzstream_valid = 0; + return (ARCHIVE_FATAL); + } + xar->bzstream_valid = 1; + xar->bzstream.total_in_lo32 = 0; + xar->bzstream.total_in_hi32 = 0; + xar->bzstream.total_out_lo32 = 0; + xar->bzstream.total_out_hi32 = 0; + break; +#endif +#if defined(HAVE_LZMA_H) && defined(HAVE_LIBLZMA) +#if LZMA_VERSION_MAJOR >= 5 +/* Effectively disable the limiter. */ +#define LZMA_MEMLIMIT UINT64_MAX +#else +/* NOTE: This needs to check memory size which running system has. */ +#define LZMA_MEMLIMIT (1U << 30) +#endif + case XZ: + case LZMA: + if (xar->lzstream_valid) { + lzma_end(&(xar->lzstream)); + xar->lzstream_valid = 0; + } + if (xar->entry_encoding == XZ) + r = lzma_stream_decoder(&(xar->lzstream), + LZMA_MEMLIMIT,/* memlimit */ + LZMA_CONCATENATED); + else + r = lzma_alone_decoder(&(xar->lzstream), + LZMA_MEMLIMIT);/* memlimit */ + if (r != LZMA_OK) { + switch (r) { + case LZMA_MEM_ERROR: + archive_set_error(&a->archive, + ENOMEM, + "Internal error initializing " + "compression library: " + "Cannot allocate memory"); + break; + case LZMA_OPTIONS_ERROR: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Internal error initializing " + "compression library: " + "Invalid or unsupported options"); + break; + default: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Internal error initializing " + "lzma library"); + break; + } + return (ARCHIVE_FATAL); + } + xar->lzstream_valid = 1; + xar->lzstream.total_in = 0; + xar->lzstream.total_out = 0; + break; - #elif defined(HAVE_LZMADEC_H) && defined(HAVE_LIBLZMADEC) - case LZMA: - if (xar->lzstream_valid) - lzmadec_end(&(xar->lzstream)); - r = lzmadec_init(&(xar->lzstream)); - if (r != LZMADEC_OK) { - switch (r) { - case LZMADEC_HEADER_ERROR: - archive_set_error(&a->archive, - ARCHIVE_ERRNO_MISC, - "Internal error initializing " - "compression library: " - "invalid header"); - break; - case LZMADEC_MEM_ERROR: - archive_set_error(&a->archive, - ENOMEM, - "Internal error initializing " - "compression library: " - "out of memory"); - break; - } - return (ARCHIVE_FATAL); - } - xar->lzstream_valid = 1; - xar->lzstream.total_in = 0; - xar->lzstream.total_out = 0; - break; +#endif + /* + * Unsupported compression. + */ + default: +#if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR) + case BZIP2: +#endif +#if !defined(HAVE_LZMA_H) || !defined(HAVE_LIBLZMA) - #if !defined(HAVE_LZMADEC_H) || !defined(HAVE_LIBLZMADEC) + case LZMA: - #endif + case XZ: +#endif + switch (xar->entry_encoding) { + case BZIP2: detail = "bzip2"; break; + case LZMA: detail = "lzma"; break; + case XZ: detail = "xz"; break; + default: detail = "??"; break; + } + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "%s compression not supported on this platform", + detail); + return (ARCHIVE_FAILED); + } + return (ARCHIVE_OK); +} + +static int +decompress(struct archive_read *a, const void **buff, size_t *outbytes, + const void *b, size_t *used) +{ + struct xar *xar; + void *outbuff; + size_t avail_in, avail_out; + int r; + + xar = (struct xar *)(a->format->data); + avail_in = *used; + outbuff = (void *)(uintptr_t)*buff; + if (outbuff == NULL) { + if (xar->outbuff == NULL) { + xar->outbuff = malloc(OUTBUFF_SIZE); + if (xar->outbuff == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Couldn't allocate memory for out buffer"); + return (ARCHIVE_FATAL); + } + } + outbuff = xar->outbuff; + *buff = outbuff; + avail_out = OUTBUFF_SIZE; + } else + avail_out = *outbytes; + switch (xar->rd_encoding) { + case GZIP: + xar->stream.next_in = (Bytef *)(uintptr_t)b; + xar->stream.avail_in = avail_in; + xar->stream.next_out = (unsigned char *)outbuff; + xar->stream.avail_out = avail_out; + r = inflate(&(xar->stream), 0); + switch (r) { + case Z_OK: /* Decompressor made some progress.*/ + case Z_STREAM_END: /* Found end of stream. */ + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "File decompression failed (%d)", r); + return (ARCHIVE_FATAL); + } + *used = avail_in - xar->stream.avail_in; + *outbytes = avail_out - xar->stream.avail_out; + break; +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) + case BZIP2: + xar->bzstream.next_in = (char *)(uintptr_t)b; + xar->bzstream.avail_in = avail_in; + xar->bzstream.next_out = (char *)outbuff; + xar->bzstream.avail_out = avail_out; + r = BZ2_bzDecompress(&(xar->bzstream)); + switch (r) { + case BZ_STREAM_END: /* Found end of stream. */ + switch (BZ2_bzDecompressEnd(&(xar->bzstream))) { + case BZ_OK: + break; + default: + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "Failed to clean up decompressor"); + return (ARCHIVE_FATAL); + } + xar->bzstream_valid = 0; + /* FALLTHROUGH */ + case BZ_OK: /* Decompressor made some progress. */ + break; + default: + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "bzip decompression failed"); + return (ARCHIVE_FATAL); + } + *used = avail_in - xar->bzstream.avail_in; + *outbytes = avail_out - xar->bzstream.avail_out; + break; +#endif +#if defined(HAVE_LZMA_H) && defined(HAVE_LIBLZMA) + case LZMA: + case XZ: + xar->lzstream.next_in = b; + xar->lzstream.avail_in = avail_in; + xar->lzstream.next_out = (unsigned char *)outbuff; + xar->lzstream.avail_out = avail_out; + r = lzma_code(&(xar->lzstream), LZMA_RUN); + switch (r) { + case LZMA_STREAM_END: /* Found end of stream. */ + lzma_end(&(xar->lzstream)); + xar->lzstream_valid = 0; + /* FALLTHROUGH */ + case LZMA_OK: /* Decompressor made some progress. */ + break; + default: + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "%s decompression failed(%d)", + (xar->entry_encoding == XZ)?"xz":"lzma", + r); + return (ARCHIVE_FATAL); + } + *used = avail_in - xar->lzstream.avail_in; + *outbytes = avail_out - xar->lzstream.avail_out; + break; - #elif defined(HAVE_LZMADEC_H) && defined(HAVE_LIBLZMADEC) - case LZMA: - xar->lzstream.next_in = (unsigned char *)(uintptr_t)b; - xar->lzstream.avail_in = avail_in; - xar->lzstream.next_out = (unsigned char *)outbuff; - xar->lzstream.avail_out = avail_out; - r = lzmadec_decode(&(xar->lzstream), 0); - switch (r) { - case LZMADEC_STREAM_END: /* Found end of stream. */ - switch (lzmadec_end(&(xar->lzstream))) { - case LZMADEC_OK: - break; - default: - archive_set_error(&(a->archive), - ARCHIVE_ERRNO_MISC, - "Failed to clean up lzmadec decompressor"); - return (ARCHIVE_FATAL); - } - xar->lzstream_valid = 0; - /* FALLTHROUGH */ - case LZMADEC_OK: /* Decompressor made some progress. */ - break; - default: - archive_set_error(&(a->archive), - ARCHIVE_ERRNO_MISC, - "lzmadec decompression failed(%d)", - r); - return (ARCHIVE_FATAL); - } - *used = avail_in - xar->lzstream.avail_in; - *outbytes = avail_out - xar->lzstream.avail_out; - break; +#endif +#if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR) + case BZIP2: +#endif +#if !defined(HAVE_LZMA_H) || !defined(HAVE_LIBLZMA) - #if !defined(HAVE_LZMADEC_H) || !defined(HAVE_LIBLZMADEC) + case LZMA: - #endif + case XZ: +#endif + case NONE: + default: + if (outbuff == xar->outbuff) { + *buff = b; + *used = avail_in; + *outbytes = avail_in; + } else { + if (avail_out > avail_in) + avail_out = avail_in; + memcpy(outbuff, b, avail_out); + *used = avail_out; + *outbytes = avail_out; + } + break; + } + return (ARCHIVE_OK); +} + +static int +decompression_cleanup(struct archive_read *a) +{ + struct xar *xar; + int r; + + xar = (struct xar *)(a->format->data); + r = ARCHIVE_OK; + if (xar->stream_valid) { + if (inflateEnd(&(xar->stream)) != Z_OK) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Failed to clean up zlib decompressor"); + r = ARCHIVE_FATAL; + } + } +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) + if (xar->bzstream_valid) { + if (BZ2_bzDecompressEnd(&(xar->bzstream)) != BZ_OK) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Failed to clean up bzip2 decompressor"); + r = ARCHIVE_FATAL; + } + } +#endif +#if defined(HAVE_LZMA_H) && defined(HAVE_LIBLZMA) + if (xar->lzstream_valid) + lzma_end(&(xar->lzstream)); +#elif defined(HAVE_LZMA_H) && defined(HAVE_LIBLZMA) + if (xar->lzstream_valid) { + if (lzmadec_end(&(xar->lzstream)) != LZMADEC_OK) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Failed to clean up lzmadec decompressor"); + r = ARCHIVE_FATAL; + } + } +#endif + return (r); +} + +static void ++checksum_cleanup(struct archive_read *a) { ++ struct xar *xar; ++ ++ xar = (struct xar *)(a->format->data); ++ ++ _checksum_final(&(xar->a_sumwrk), NULL, 0); ++ _checksum_final(&(xar->e_sumwrk), NULL, 0); ++} ++ ++static void +xmlattr_cleanup(struct xmlattr_list *list) +{ + struct xmlattr *attr, *next; + + attr = list->first; + while (attr != NULL) { + next = attr->next; + free(attr->name); + free(attr->value); + free(attr); + attr = next; + } + list->first = NULL; + list->last = &(list->first); +} + +static int +file_new(struct archive_read *a, struct xar *xar, struct xmlattr_list *list) +{ + struct xar_file *file; + struct xmlattr *attr; + + file = calloc(1, sizeof(*file)); + if (file == NULL) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + file->parent = xar->file; + file->mode = 0777 | AE_IFREG; + file->atime = time(NULL); + file->mtime = time(NULL); + xar->file = file; + xar->xattr = NULL; + for (attr = list->first; attr != NULL; attr = attr->next) { + if (strcmp(attr->name, "id") == 0) + file->id = atol10(attr->value, strlen(attr->value)); + } + file->nlink = 1; + if (heap_add_entry(a, &(xar->file_queue), file) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + return (ARCHIVE_OK); +} + +static void +file_free(struct xar_file *file) +{ + struct xattr *xattr; + + archive_string_free(&(file->pathname)); + archive_string_free(&(file->symlink)); + archive_string_free(&(file->uname)); + archive_string_free(&(file->gname)); + archive_string_free(&(file->hardlink)); + xattr = file->xattr_list; + while (xattr != NULL) { + struct xattr *next; + + next = xattr->next; + xattr_free(xattr); + xattr = next; + } + + free(file); +} + +static int +xattr_new(struct archive_read *a, struct xar *xar, struct xmlattr_list *list) +{ + struct xattr *xattr, **nx; + struct xmlattr *attr; + + xattr = calloc(1, sizeof(*xattr)); + if (xattr == NULL) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + xar->xattr = xattr; + for (attr = list->first; attr != NULL; attr = attr->next) { + if (strcmp(attr->name, "id") == 0) + xattr->id = atol10(attr->value, strlen(attr->value)); + } + /* Chain to xattr list. */ + for (nx = &(xar->file->xattr_list); + *nx != NULL; nx = &((*nx)->next)) { + if (xattr->id < (*nx)->id) + break; + } + xattr->next = *nx; + *nx = xattr; + + return (ARCHIVE_OK); +} + +static void +xattr_free(struct xattr *xattr) +{ + archive_string_free(&(xattr->name)); + free(xattr); +} + +static int +getencoding(struct xmlattr_list *list) +{ + struct xmlattr *attr; + enum enctype encoding = NONE; + + for (attr = list->first; attr != NULL; attr = attr->next) { + if (strcmp(attr->name, "style") == 0) { + if (strcmp(attr->value, "application/octet-stream") == 0) + encoding = NONE; + else if (strcmp(attr->value, "application/x-gzip") == 0) + encoding = GZIP; + else if (strcmp(attr->value, "application/x-bzip2") == 0) + encoding = BZIP2; + else if (strcmp(attr->value, "application/x-lzma") == 0) + encoding = LZMA; + else if (strcmp(attr->value, "application/x-xz") == 0) + encoding = XZ; + } + } + return (encoding); +} + +static int +getsumalgorithm(struct xmlattr_list *list) +{ + struct xmlattr *attr; + int alg = CKSUM_NONE; + + for (attr = list->first; attr != NULL; attr = attr->next) { + if (strcmp(attr->name, "style") == 0) { + const char *v = attr->value; + if ((v[0] == 'S' || v[0] == 's') && + (v[1] == 'H' || v[1] == 'h') && + (v[2] == 'A' || v[2] == 'a') && + v[3] == '1' && v[4] == '\0') + alg = CKSUM_SHA1; + if ((v[0] == 'M' || v[0] == 'm') && + (v[1] == 'D' || v[1] == 'd') && + v[2] == '5' && v[3] == '\0') + alg = CKSUM_MD5; + } + } + return (alg); +} + +static int +unknowntag_start(struct archive_read *a, struct xar *xar, const char *name) +{ + struct unknown_tag *tag; + + tag = malloc(sizeof(*tag)); + if (tag == NULL) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + tag->next = xar->unknowntags; + archive_string_init(&(tag->name)); + archive_strcpy(&(tag->name), name); + if (xar->unknowntags == NULL) { +#if DEBUG + fprintf(stderr, "UNKNOWNTAG_START:%s\n", name); +#endif + xar->xmlsts_unknown = xar->xmlsts; + xar->xmlsts = UNKNOWN; + } + xar->unknowntags = tag; + return (ARCHIVE_OK); +} + +static void +unknowntag_end(struct xar *xar, const char *name) +{ + struct unknown_tag *tag; + + tag = xar->unknowntags; + if (tag == NULL || name == NULL) + return; + if (strcmp(tag->name.s, name) == 0) { + xar->unknowntags = tag->next; + archive_string_free(&(tag->name)); + free(tag); + if (xar->unknowntags == NULL) { +#if DEBUG + fprintf(stderr, "UNKNOWNTAG_END:%s\n", name); +#endif + xar->xmlsts = xar->xmlsts_unknown; + } + } +} + +static int +xml_start(struct archive_read *a, const char *name, struct xmlattr_list *list) +{ + struct xar *xar; + struct xmlattr *attr; + + xar = (struct xar *)(a->format->data); + +#if DEBUG + fprintf(stderr, "xml_sta:[%s]\n", name); + for (attr = list->first; attr != NULL; attr = attr->next) + fprintf(stderr, " attr:\"%s\"=\"%s\"\n", + attr->name, attr->value); +#endif + xar->base64text = 0; + switch (xar->xmlsts) { + case INIT: + if (strcmp(name, "xar") == 0) + xar->xmlsts = XAR; + else + if (unknowntag_start(a, xar, name) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + break; + case XAR: + if (strcmp(name, "toc") == 0) + xar->xmlsts = TOC; + else + if (unknowntag_start(a, xar, name) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + break; + case TOC: + if (strcmp(name, "creation-time") == 0) + xar->xmlsts = TOC_CREATION_TIME; + else if (strcmp(name, "checksum") == 0) + xar->xmlsts = TOC_CHECKSUM; + else if (strcmp(name, "file") == 0) { + if (file_new(a, xar, list) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + xar->xmlsts = TOC_FILE; + } + else + if (unknowntag_start(a, xar, name) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + break; + case TOC_CHECKSUM: + if (strcmp(name, "offset") == 0) + xar->xmlsts = TOC_CHECKSUM_OFFSET; + else if (strcmp(name, "size") == 0) + xar->xmlsts = TOC_CHECKSUM_SIZE; + else + if (unknowntag_start(a, xar, name) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + break; + case TOC_FILE: + if (strcmp(name, "file") == 0) { + if (file_new(a, xar, list) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + else if (strcmp(name, "data") == 0) + xar->xmlsts = FILE_DATA; + else if (strcmp(name, "ea") == 0) { + if (xattr_new(a, xar, list) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + xar->xmlsts = FILE_EA; + } + else if (strcmp(name, "ctime") == 0) + xar->xmlsts = FILE_CTIME; + else if (strcmp(name, "mtime") == 0) + xar->xmlsts = FILE_MTIME; + else if (strcmp(name, "atime") == 0) + xar->xmlsts = FILE_ATIME; + else if (strcmp(name, "group") == 0) + xar->xmlsts = FILE_GROUP; + else if (strcmp(name, "gid") == 0) + xar->xmlsts = FILE_GID; + else if (strcmp(name, "user") == 0) + xar->xmlsts = FILE_USER; + else if (strcmp(name, "uid") == 0) + xar->xmlsts = FILE_UID; + else if (strcmp(name, "mode") == 0) + xar->xmlsts = FILE_MODE; + else if (strcmp(name, "device") == 0) + xar->xmlsts = FILE_DEVICE; + else if (strcmp(name, "deviceno") == 0) + xar->xmlsts = FILE_DEVICENO; + else if (strcmp(name, "inode") == 0) + xar->xmlsts = FILE_INODE; + else if (strcmp(name, "link") == 0) + xar->xmlsts = FILE_LINK; + else if (strcmp(name, "type") == 0) { + xar->xmlsts = FILE_TYPE; + for (attr = list->first; attr != NULL; + attr = attr->next) { + if (strcmp(attr->name, "link") != 0) + continue; + if (strcmp(attr->value, "original") == 0) { + xar->file->hdnext = xar->hdlink_orgs; + xar->hdlink_orgs = xar->file; + } else { + xar->file->link = (unsigned)atol10(attr->value, + strlen(attr->value)); + if (xar->file->link > 0) + if (add_link(a, xar, xar->file) != ARCHIVE_OK) { + return (ARCHIVE_FATAL); + }; + } + } + } + else if (strcmp(name, "name") == 0) { + xar->xmlsts = FILE_NAME; + for (attr = list->first; attr != NULL; + attr = attr->next) { + if (strcmp(attr->name, "enctype") == 0 && + strcmp(attr->value, "base64") == 0) + xar->base64text = 1; + } + } + else if (strcmp(name, "acl") == 0) + xar->xmlsts = FILE_ACL; + else if (strcmp(name, "flags") == 0) + xar->xmlsts = FILE_FLAGS; + else if (strcmp(name, "ext2") == 0) + xar->xmlsts = FILE_EXT2; + else + if (unknowntag_start(a, xar, name) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + break; + case FILE_DATA: + if (strcmp(name, "length") == 0) + xar->xmlsts = FILE_DATA_LENGTH; + else if (strcmp(name, "offset") == 0) + xar->xmlsts = FILE_DATA_OFFSET; + else if (strcmp(name, "size") == 0) + xar->xmlsts = FILE_DATA_SIZE; + else if (strcmp(name, "encoding") == 0) { + xar->xmlsts = FILE_DATA_ENCODING; + xar->file->encoding = getencoding(list); + } + else if (strcmp(name, "archived-checksum") == 0) { + xar->xmlsts = FILE_DATA_A_CHECKSUM; + xar->file->a_sum.alg = getsumalgorithm(list); + } + else if (strcmp(name, "extracted-checksum") == 0) { + xar->xmlsts = FILE_DATA_E_CHECKSUM; + xar->file->e_sum.alg = getsumalgorithm(list); + } + else if (strcmp(name, "content") == 0) + xar->xmlsts = FILE_DATA_CONTENT; + else + if (unknowntag_start(a, xar, name) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + break; + case FILE_DEVICE: + if (strcmp(name, "major") == 0) + xar->xmlsts = FILE_DEVICE_MAJOR; + else if (strcmp(name, "minor") == 0) + xar->xmlsts = FILE_DEVICE_MINOR; + else + if (unknowntag_start(a, xar, name) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + break; + case FILE_DATA_CONTENT: + if (unknowntag_start(a, xar, name) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + break; + case FILE_EA: + if (strcmp(name, "length") == 0) + xar->xmlsts = FILE_EA_LENGTH; + else if (strcmp(name, "offset") == 0) + xar->xmlsts = FILE_EA_OFFSET; + else if (strcmp(name, "size") == 0) + xar->xmlsts = FILE_EA_SIZE; + else if (strcmp(name, "encoding") == 0) { + xar->xmlsts = FILE_EA_ENCODING; + xar->xattr->encoding = getencoding(list); + } else if (strcmp(name, "archived-checksum") == 0) + xar->xmlsts = FILE_EA_A_CHECKSUM; + else if (strcmp(name, "extracted-checksum") == 0) + xar->xmlsts = FILE_EA_E_CHECKSUM; + else if (strcmp(name, "name") == 0) + xar->xmlsts = FILE_EA_NAME; + else if (strcmp(name, "fstype") == 0) + xar->xmlsts = FILE_EA_FSTYPE; + else + if (unknowntag_start(a, xar, name) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + break; + case FILE_ACL: + if (strcmp(name, "appleextended") == 0) + xar->xmlsts = FILE_ACL_APPLEEXTENDED; + else if (strcmp(name, "default") == 0) + xar->xmlsts = FILE_ACL_DEFAULT; + else if (strcmp(name, "access") == 0) + xar->xmlsts = FILE_ACL_ACCESS; + else + if (unknowntag_start(a, xar, name) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + break; + case FILE_FLAGS: + if (!xml_parse_file_flags(xar, name)) + if (unknowntag_start(a, xar, name) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + break; + case FILE_EXT2: + if (!xml_parse_file_ext2(xar, name)) + if (unknowntag_start(a, xar, name) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + break; + case TOC_CREATION_TIME: + case TOC_CHECKSUM_OFFSET: + case TOC_CHECKSUM_SIZE: + case FILE_DATA_LENGTH: + case FILE_DATA_OFFSET: + case FILE_DATA_SIZE: + case FILE_DATA_ENCODING: + case FILE_DATA_A_CHECKSUM: + case FILE_DATA_E_CHECKSUM: + case FILE_EA_LENGTH: + case FILE_EA_OFFSET: + case FILE_EA_SIZE: + case FILE_EA_ENCODING: + case FILE_EA_A_CHECKSUM: + case FILE_EA_E_CHECKSUM: + case FILE_EA_NAME: + case FILE_EA_FSTYPE: + case FILE_CTIME: + case FILE_MTIME: + case FILE_ATIME: + case FILE_GROUP: + case FILE_GID: + case FILE_USER: + case FILE_UID: + case FILE_INODE: + case FILE_DEVICE_MAJOR: + case FILE_DEVICE_MINOR: + case FILE_DEVICENO: + case FILE_MODE: + case FILE_TYPE: + case FILE_LINK: + case FILE_NAME: + case FILE_ACL_DEFAULT: + case FILE_ACL_ACCESS: + case FILE_ACL_APPLEEXTENDED: + case FILE_FLAGS_USER_NODUMP: + case FILE_FLAGS_USER_IMMUTABLE: + case FILE_FLAGS_USER_APPEND: + case FILE_FLAGS_USER_OPAQUE: + case FILE_FLAGS_USER_NOUNLINK: + case FILE_FLAGS_SYS_ARCHIVED: + case FILE_FLAGS_SYS_IMMUTABLE: + case FILE_FLAGS_SYS_APPEND: + case FILE_FLAGS_SYS_NOUNLINK: + case FILE_FLAGS_SYS_SNAPSHOT: + case FILE_EXT2_SecureDeletion: + case FILE_EXT2_Undelete: + case FILE_EXT2_Compress: + case FILE_EXT2_Synchronous: + case FILE_EXT2_Immutable: + case FILE_EXT2_AppendOnly: + case FILE_EXT2_NoDump: + case FILE_EXT2_NoAtime: + case FILE_EXT2_CompDirty: + case FILE_EXT2_CompBlock: + case FILE_EXT2_NoCompBlock: + case FILE_EXT2_CompError: + case FILE_EXT2_BTree: + case FILE_EXT2_HashIndexed: + case FILE_EXT2_iMagic: + case FILE_EXT2_Journaled: + case FILE_EXT2_NoTail: + case FILE_EXT2_DirSync: + case FILE_EXT2_TopDir: + case FILE_EXT2_Reserved: + case UNKNOWN: + if (unknowntag_start(a, xar, name) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + break; + } + return (ARCHIVE_OK); +} + +static void +xml_end(void *userData, const char *name) +{ + struct archive_read *a; + struct xar *xar; + + a = (struct archive_read *)userData; + xar = (struct xar *)(a->format->data); + +#if DEBUG + fprintf(stderr, "xml_end:[%s]\n", name); +#endif + switch (xar->xmlsts) { + case INIT: + break; + case XAR: + if (strcmp(name, "xar") == 0) + xar->xmlsts = INIT; + break; + case TOC: + if (strcmp(name, "toc") == 0) + xar->xmlsts = XAR; + break; + case TOC_CREATION_TIME: + if (strcmp(name, "creation-time") == 0) + xar->xmlsts = TOC; + break; + case TOC_CHECKSUM: + if (strcmp(name, "checksum") == 0) + xar->xmlsts = TOC; + break; + case TOC_CHECKSUM_OFFSET: + if (strcmp(name, "offset") == 0) + xar->xmlsts = TOC_CHECKSUM; + break; + case TOC_CHECKSUM_SIZE: + if (strcmp(name, "size") == 0) + xar->xmlsts = TOC_CHECKSUM; + break; + case TOC_FILE: + if (strcmp(name, "file") == 0) { + if (xar->file->parent != NULL && + ((xar->file->mode & AE_IFMT) == AE_IFDIR)) + xar->file->parent->subdirs++; + xar->file = xar->file->parent; + if (xar->file == NULL) + xar->xmlsts = TOC; + } + break; + case FILE_DATA: + if (strcmp(name, "data") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_DATA_LENGTH: + if (strcmp(name, "length") == 0) + xar->xmlsts = FILE_DATA; + break; + case FILE_DATA_OFFSET: + if (strcmp(name, "offset") == 0) + xar->xmlsts = FILE_DATA; + break; + case FILE_DATA_SIZE: + if (strcmp(name, "size") == 0) + xar->xmlsts = FILE_DATA; + break; + case FILE_DATA_ENCODING: + if (strcmp(name, "encoding") == 0) + xar->xmlsts = FILE_DATA; + break; + case FILE_DATA_A_CHECKSUM: + if (strcmp(name, "archived-checksum") == 0) + xar->xmlsts = FILE_DATA; + break; + case FILE_DATA_E_CHECKSUM: + if (strcmp(name, "extracted-checksum") == 0) + xar->xmlsts = FILE_DATA; + break; + case FILE_DATA_CONTENT: + if (strcmp(name, "content") == 0) + xar->xmlsts = FILE_DATA; + break; + case FILE_EA: + if (strcmp(name, "ea") == 0) { + xar->xmlsts = TOC_FILE; + xar->xattr = NULL; + } + break; + case FILE_EA_LENGTH: + if (strcmp(name, "length") == 0) + xar->xmlsts = FILE_EA; + break; + case FILE_EA_OFFSET: + if (strcmp(name, "offset") == 0) + xar->xmlsts = FILE_EA; + break; + case FILE_EA_SIZE: + if (strcmp(name, "size") == 0) + xar->xmlsts = FILE_EA; + break; + case FILE_EA_ENCODING: + if (strcmp(name, "encoding") == 0) + xar->xmlsts = FILE_EA; + break; + case FILE_EA_A_CHECKSUM: + if (strcmp(name, "archived-checksum") == 0) + xar->xmlsts = FILE_EA; + break; + case FILE_EA_E_CHECKSUM: + if (strcmp(name, "extracted-checksum") == 0) + xar->xmlsts = FILE_EA; + break; + case FILE_EA_NAME: + if (strcmp(name, "name") == 0) + xar->xmlsts = FILE_EA; + break; + case FILE_EA_FSTYPE: + if (strcmp(name, "fstype") == 0) + xar->xmlsts = FILE_EA; + break; + case FILE_CTIME: + if (strcmp(name, "ctime") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_MTIME: + if (strcmp(name, "mtime") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_ATIME: + if (strcmp(name, "atime") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_GROUP: + if (strcmp(name, "group") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_GID: + if (strcmp(name, "gid") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_USER: + if (strcmp(name, "user") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_UID: + if (strcmp(name, "uid") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_MODE: + if (strcmp(name, "mode") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_DEVICE: + if (strcmp(name, "device") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_DEVICE_MAJOR: + if (strcmp(name, "major") == 0) + xar->xmlsts = FILE_DEVICE; + break; + case FILE_DEVICE_MINOR: + if (strcmp(name, "minor") == 0) + xar->xmlsts = FILE_DEVICE; + break; + case FILE_DEVICENO: + if (strcmp(name, "deviceno") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_INODE: + if (strcmp(name, "inode") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_LINK: + if (strcmp(name, "link") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_TYPE: + if (strcmp(name, "type") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_NAME: + if (strcmp(name, "name") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_ACL: + if (strcmp(name, "acl") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_ACL_DEFAULT: + if (strcmp(name, "default") == 0) + xar->xmlsts = FILE_ACL; + break; + case FILE_ACL_ACCESS: + if (strcmp(name, "access") == 0) + xar->xmlsts = FILE_ACL; + break; + case FILE_ACL_APPLEEXTENDED: + if (strcmp(name, "appleextended") == 0) + xar->xmlsts = FILE_ACL; + break; + case FILE_FLAGS: + if (strcmp(name, "flags") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_FLAGS_USER_NODUMP: + if (strcmp(name, "UserNoDump") == 0) + xar->xmlsts = FILE_FLAGS; + break; + case FILE_FLAGS_USER_IMMUTABLE: + if (strcmp(name, "UserImmutable") == 0) + xar->xmlsts = FILE_FLAGS; + break; + case FILE_FLAGS_USER_APPEND: + if (strcmp(name, "UserAppend") == 0) + xar->xmlsts = FILE_FLAGS; + break; + case FILE_FLAGS_USER_OPAQUE: + if (strcmp(name, "UserOpaque") == 0) + xar->xmlsts = FILE_FLAGS; + break; + case FILE_FLAGS_USER_NOUNLINK: + if (strcmp(name, "UserNoUnlink") == 0) + xar->xmlsts = FILE_FLAGS; + break; + case FILE_FLAGS_SYS_ARCHIVED: + if (strcmp(name, "SystemArchived") == 0) + xar->xmlsts = FILE_FLAGS; + break; + case FILE_FLAGS_SYS_IMMUTABLE: + if (strcmp(name, "SystemImmutable") == 0) + xar->xmlsts = FILE_FLAGS; + break; + case FILE_FLAGS_SYS_APPEND: + if (strcmp(name, "SystemAppend") == 0) + xar->xmlsts = FILE_FLAGS; + break; + case FILE_FLAGS_SYS_NOUNLINK: + if (strcmp(name, "SystemNoUnlink") == 0) + xar->xmlsts = FILE_FLAGS; + break; + case FILE_FLAGS_SYS_SNAPSHOT: + if (strcmp(name, "SystemSnapshot") == 0) + xar->xmlsts = FILE_FLAGS; + break; + case FILE_EXT2: + if (strcmp(name, "ext2") == 0) + xar->xmlsts = TOC_FILE; + break; + case FILE_EXT2_SecureDeletion: + if (strcmp(name, "SecureDeletion") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_Undelete: + if (strcmp(name, "Undelete") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_Compress: + if (strcmp(name, "Compress") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_Synchronous: + if (strcmp(name, "Synchronous") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_Immutable: + if (strcmp(name, "Immutable") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_AppendOnly: + if (strcmp(name, "AppendOnly") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_NoDump: + if (strcmp(name, "NoDump") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_NoAtime: + if (strcmp(name, "NoAtime") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_CompDirty: + if (strcmp(name, "CompDirty") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_CompBlock: + if (strcmp(name, "CompBlock") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_NoCompBlock: + if (strcmp(name, "NoCompBlock") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_CompError: + if (strcmp(name, "CompError") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_BTree: + if (strcmp(name, "BTree") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_HashIndexed: + if (strcmp(name, "HashIndexed") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_iMagic: + if (strcmp(name, "iMagic") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_Journaled: + if (strcmp(name, "Journaled") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_NoTail: + if (strcmp(name, "NoTail") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_DirSync: + if (strcmp(name, "DirSync") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_TopDir: + if (strcmp(name, "TopDir") == 0) + xar->xmlsts = FILE_EXT2; + break; + case FILE_EXT2_Reserved: + if (strcmp(name, "Reserved") == 0) + xar->xmlsts = FILE_EXT2; + break; + case UNKNOWN: + unknowntag_end(xar, name); + break; + } +} + +static const int base64[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* 00 - 0F */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* 10 - 1F */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 62, -1, -1, -1, 63, /* 20 - 2F */ + 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, -1, -1, -1, -1, -1, -1, /* 30 - 3F */ + -1, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, /* 40 - 4F */ + 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, -1, -1, -1, -1, -1, /* 50 - 5F */ + -1, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, /* 60 - 6F */ + 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, -1, -1, -1, -1, -1, /* 70 - 7F */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* 80 - 8F */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* 90 - 9F */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* A0 - AF */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* B0 - BF */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* C0 - CF */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* D0 - DF */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* E0 - EF */ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, /* F0 - FF */ +}; + +static void +strappend_base64(struct xar *xar, + struct archive_string *as, const char *s, size_t l) +{ + unsigned char buff[256]; + unsigned char *out; + const unsigned char *b; + size_t len; + + (void)xar; /* UNUSED */ + len = 0; + out = buff; + b = (const unsigned char *)s; + while (l > 0) { + int n = 0; + + if (l > 0) { + if (base64[b[0]] < 0 || base64[b[1]] < 0) + break; + n = base64[*b++] << 18; + n |= base64[*b++] << 12; + *out++ = n >> 16; + len++; + l -= 2; + } + if (l > 0) { + if (base64[*b] < 0) + break; + n |= base64[*b++] << 6; + *out++ = (n >> 8) & 0xFF; + len++; + --l; + } + if (l > 0) { + if (base64[*b] < 0) + break; + n |= base64[*b++]; + *out++ = n & 0xFF; + len++; + --l; + } + if (len+3 >= sizeof(buff)) { + archive_strncat(as, (const char *)buff, len); + len = 0; + out = buff; + } + } + if (len > 0) + archive_strncat(as, (const char *)buff, len); +} + +static void +xml_data(void *userData, const char *s, int len) +{ + struct archive_read *a; + struct xar *xar; + + a = (struct archive_read *)userData; + xar = (struct xar *)(a->format->data); + +#if DEBUG + { + char buff[1024]; + if (len > (int)(sizeof(buff)-1)) + len = (int)(sizeof(buff)-1); + strncpy(buff, s, len); + buff[len] = 0; + fprintf(stderr, "\tlen=%d:\"%s\"\n", len, buff); + } +#endif + switch (xar->xmlsts) { + case TOC_CHECKSUM_OFFSET: + xar->toc_chksum_offset = atol10(s, len); + break; + case TOC_CHECKSUM_SIZE: + xar->toc_chksum_size = atol10(s, len); + break; + default: + break; + } + if (xar->file == NULL) + return; + + switch (xar->xmlsts) { + case FILE_NAME: + if (xar->file->parent != NULL) { + archive_string_concat(&(xar->file->pathname), + &(xar->file->parent->pathname)); + archive_strappend_char(&(xar->file->pathname), '/'); + } + xar->file->has |= HAS_PATHNAME; + if (xar->base64text) { + strappend_base64(xar, + &(xar->file->pathname), s, len); + } else + archive_strncat(&(xar->file->pathname), s, len); + break; + case FILE_LINK: + xar->file->has |= HAS_SYMLINK; + archive_strncpy(&(xar->file->symlink), s, len); + break; + case FILE_TYPE: + if (strncmp("file", s, len) == 0 || + strncmp("hardlink", s, len) == 0) + xar->file->mode = + (xar->file->mode & ~AE_IFMT) | AE_IFREG; + if (strncmp("directory", s, len) == 0) + xar->file->mode = + (xar->file->mode & ~AE_IFMT) | AE_IFDIR; + if (strncmp("symlink", s, len) == 0) + xar->file->mode = + (xar->file->mode & ~AE_IFMT) | AE_IFLNK; + if (strncmp("character special", s, len) == 0) + xar->file->mode = + (xar->file->mode & ~AE_IFMT) | AE_IFCHR; + if (strncmp("block special", s, len) == 0) + xar->file->mode = + (xar->file->mode & ~AE_IFMT) | AE_IFBLK; + if (strncmp("socket", s, len) == 0) + xar->file->mode = + (xar->file->mode & ~AE_IFMT) | AE_IFSOCK; + if (strncmp("fifo", s, len) == 0) + xar->file->mode = + (xar->file->mode & ~AE_IFMT) | AE_IFIFO; + xar->file->has |= HAS_TYPE; + break; + case FILE_INODE: + xar->file->has |= HAS_INO; + xar->file->ino64 = atol10(s, len); + break; + case FILE_DEVICE_MAJOR: + xar->file->has |= HAS_DEVMAJOR; + xar->file->devmajor = (dev_t)atol10(s, len); + break; + case FILE_DEVICE_MINOR: + xar->file->has |= HAS_DEVMINOR; + xar->file->devminor = (dev_t)atol10(s, len); + break; + case FILE_DEVICENO: + xar->file->has |= HAS_DEV; + xar->file->dev = (dev_t)atol10(s, len); + break; + case FILE_MODE: + xar->file->has |= HAS_MODE; + xar->file->mode = + (xar->file->mode & AE_IFMT) | + ((mode_t)(atol8(s, len)) & ~AE_IFMT); + break; + case FILE_GROUP: + xar->file->has |= HAS_GID; + archive_strncpy(&(xar->file->gname), s, len); + break; + case FILE_GID: + xar->file->has |= HAS_GID; + xar->file->gid = atol10(s, len); + break; + case FILE_USER: + xar->file->has |= HAS_UID; + archive_strncpy(&(xar->file->uname), s, len); + break; + case FILE_UID: + xar->file->has |= HAS_UID; + xar->file->uid = atol10(s, len); + break; + case FILE_CTIME: + xar->file->has |= HAS_TIME; + xar->file->ctime = parse_time(s, len); + break; + case FILE_MTIME: + xar->file->has |= HAS_TIME; + xar->file->mtime = parse_time(s, len); + break; + case FILE_ATIME: + xar->file->has |= HAS_TIME; + xar->file->atime = parse_time(s, len); + break; + case FILE_DATA_LENGTH: + xar->file->has |= HAS_DATA; + xar->file->length = atol10(s, len); + break; + case FILE_DATA_OFFSET: + xar->file->has |= HAS_DATA; + xar->file->offset = atol10(s, len); + break; + case FILE_DATA_SIZE: + xar->file->has |= HAS_DATA; + xar->file->size = atol10(s, len); + break; + case FILE_DATA_A_CHECKSUM: + xar->file->a_sum.len = atohex(xar->file->a_sum.val, + sizeof(xar->file->a_sum.val), s, len); + break; + case FILE_DATA_E_CHECKSUM: + xar->file->e_sum.len = atohex(xar->file->e_sum.val, + sizeof(xar->file->e_sum.val), s, len); + break; + case FILE_EA_LENGTH: + xar->file->has |= HAS_XATTR; + xar->xattr->length = atol10(s, len); + break; + case FILE_EA_OFFSET: + xar->file->has |= HAS_XATTR; + xar->xattr->offset = atol10(s, len); + break; + case FILE_EA_SIZE: + xar->file->has |= HAS_XATTR; + xar->xattr->size = atol10(s, len); + break; + case FILE_EA_A_CHECKSUM: + xar->file->has |= HAS_XATTR; + xar->xattr->a_sum.len = atohex(xar->xattr->a_sum.val, + sizeof(xar->xattr->a_sum.val), s, len); + break; + case FILE_EA_E_CHECKSUM: + xar->file->has |= HAS_XATTR; + xar->xattr->e_sum.len = atohex(xar->xattr->e_sum.val, + sizeof(xar->xattr->e_sum.val), s, len); + break; + case FILE_EA_NAME: + xar->file->has |= HAS_XATTR; + archive_strncpy(&(xar->xattr->name), s, len); + break; + case FILE_EA_FSTYPE: + xar->file->has |= HAS_XATTR; + archive_strncpy(&(xar->xattr->fstype), s, len); + break; + break; + case FILE_ACL_DEFAULT: + case FILE_ACL_ACCESS: + case FILE_ACL_APPLEEXTENDED: + xar->file->has |= HAS_ACL; + /* TODO */ + break; + case INIT: + case XAR: + case TOC: + case TOC_CREATION_TIME: + case TOC_CHECKSUM: + case TOC_CHECKSUM_OFFSET: + case TOC_CHECKSUM_SIZE: + case TOC_FILE: + case FILE_DATA: + case FILE_DATA_ENCODING: + case FILE_DATA_CONTENT: + case FILE_DEVICE: + case FILE_EA: + case FILE_EA_ENCODING: + case FILE_ACL: + case FILE_FLAGS: + case FILE_FLAGS_USER_NODUMP: + case FILE_FLAGS_USER_IMMUTABLE: + case FILE_FLAGS_USER_APPEND: + case FILE_FLAGS_USER_OPAQUE: + case FILE_FLAGS_USER_NOUNLINK: + case FILE_FLAGS_SYS_ARCHIVED: + case FILE_FLAGS_SYS_IMMUTABLE: + case FILE_FLAGS_SYS_APPEND: + case FILE_FLAGS_SYS_NOUNLINK: + case FILE_FLAGS_SYS_SNAPSHOT: + case FILE_EXT2: + case FILE_EXT2_SecureDeletion: + case FILE_EXT2_Undelete: + case FILE_EXT2_Compress: + case FILE_EXT2_Synchronous: + case FILE_EXT2_Immutable: + case FILE_EXT2_AppendOnly: + case FILE_EXT2_NoDump: + case FILE_EXT2_NoAtime: + case FILE_EXT2_CompDirty: + case FILE_EXT2_CompBlock: + case FILE_EXT2_NoCompBlock: + case FILE_EXT2_CompError: + case FILE_EXT2_BTree: + case FILE_EXT2_HashIndexed: + case FILE_EXT2_iMagic: + case FILE_EXT2_Journaled: + case FILE_EXT2_NoTail: + case FILE_EXT2_DirSync: + case FILE_EXT2_TopDir: + case FILE_EXT2_Reserved: + case UNKNOWN: + break; + } +} + +/* + * BSD file flags. + */ +static int +xml_parse_file_flags(struct xar *xar, const char *name) +{ + const char *flag = NULL; + + if (strcmp(name, "UserNoDump") == 0) { + xar->xmlsts = FILE_FLAGS_USER_NODUMP; + flag = "nodump"; + } + else if (strcmp(name, "UserImmutable") == 0) { + xar->xmlsts = FILE_FLAGS_USER_IMMUTABLE; + flag = "uimmutable"; + } + else if (strcmp(name, "UserAppend") == 0) { + xar->xmlsts = FILE_FLAGS_USER_APPEND; + flag = "uappend"; + } + else if (strcmp(name, "UserOpaque") == 0) { + xar->xmlsts = FILE_FLAGS_USER_OPAQUE; + flag = "opaque"; + } + else if (strcmp(name, "UserNoUnlink") == 0) { + xar->xmlsts = FILE_FLAGS_USER_NOUNLINK; + flag = "nouunlink"; + } + else if (strcmp(name, "SystemArchived") == 0) { + xar->xmlsts = FILE_FLAGS_SYS_ARCHIVED; + flag = "archived"; + } + else if (strcmp(name, "SystemImmutable") == 0) { + xar->xmlsts = FILE_FLAGS_SYS_IMMUTABLE; + flag = "simmutable"; + } + else if (strcmp(name, "SystemAppend") == 0) { + xar->xmlsts = FILE_FLAGS_SYS_APPEND; + flag = "sappend"; + } + else if (strcmp(name, "SystemNoUnlink") == 0) { + xar->xmlsts = FILE_FLAGS_SYS_NOUNLINK; + flag = "nosunlink"; + } + else if (strcmp(name, "SystemSnapshot") == 0) { + xar->xmlsts = FILE_FLAGS_SYS_SNAPSHOT; + flag = "snapshot"; + } + + if (flag == NULL) + return (0); + xar->file->has |= HAS_FFLAGS; + if (archive_strlen(&(xar->file->fflags_text)) > 0) + archive_strappend_char(&(xar->file->fflags_text), ','); + archive_strcat(&(xar->file->fflags_text), flag); + return (1); +} + +/* + * Linux file flags. + */ +static int +xml_parse_file_ext2(struct xar *xar, const char *name) +{ + const char *flag = NULL; + + if (strcmp(name, "SecureDeletion") == 0) { + xar->xmlsts = FILE_EXT2_SecureDeletion; + flag = "securedeletion"; + } + else if (strcmp(name, "Undelete") == 0) { + xar->xmlsts = FILE_EXT2_Undelete; + flag = "nouunlink"; + } + else if (strcmp(name, "Compress") == 0) { + xar->xmlsts = FILE_EXT2_Compress; + flag = "compress"; + } + else if (strcmp(name, "Synchronous") == 0) { + xar->xmlsts = FILE_EXT2_Synchronous; + flag = "sync"; + } + else if (strcmp(name, "Immutable") == 0) { + xar->xmlsts = FILE_EXT2_Immutable; + flag = "simmutable"; + } + else if (strcmp(name, "AppendOnly") == 0) { + xar->xmlsts = FILE_EXT2_AppendOnly; + flag = "sappend"; + } + else if (strcmp(name, "NoDump") == 0) { + xar->xmlsts = FILE_EXT2_NoDump; + flag = "nodump"; + } + else if (strcmp(name, "NoAtime") == 0) { + xar->xmlsts = FILE_EXT2_NoAtime; + flag = "noatime"; + } + else if (strcmp(name, "CompDirty") == 0) { + xar->xmlsts = FILE_EXT2_CompDirty; + flag = "compdirty"; + } + else if (strcmp(name, "CompBlock") == 0) { + xar->xmlsts = FILE_EXT2_CompBlock; + flag = "comprblk"; + } + else if (strcmp(name, "NoCompBlock") == 0) { + xar->xmlsts = FILE_EXT2_NoCompBlock; + flag = "nocomprblk"; + } + else if (strcmp(name, "CompError") == 0) { + xar->xmlsts = FILE_EXT2_CompError; + flag = "comperr"; + } + else if (strcmp(name, "BTree") == 0) { + xar->xmlsts = FILE_EXT2_BTree; + flag = "btree"; + } + else if (strcmp(name, "HashIndexed") == 0) { + xar->xmlsts = FILE_EXT2_HashIndexed; + flag = "hashidx"; + } + else if (strcmp(name, "iMagic") == 0) { + xar->xmlsts = FILE_EXT2_iMagic; + flag = "imagic"; + } + else if (strcmp(name, "Journaled") == 0) { + xar->xmlsts = FILE_EXT2_Journaled; + flag = "journal"; + } + else if (strcmp(name, "NoTail") == 0) { + xar->xmlsts = FILE_EXT2_NoTail; + flag = "notail"; + } + else if (strcmp(name, "DirSync") == 0) { + xar->xmlsts = FILE_EXT2_DirSync; + flag = "dirsync"; + } + else if (strcmp(name, "TopDir") == 0) { + xar->xmlsts = FILE_EXT2_TopDir; + flag = "topdir"; + } + else if (strcmp(name, "Reserved") == 0) { + xar->xmlsts = FILE_EXT2_Reserved; + flag = "reserved"; + } + + if (flag == NULL) + return (0); + if (archive_strlen(&(xar->file->fflags_text)) > 0) + archive_strappend_char(&(xar->file->fflags_text), ','); + archive_strcat(&(xar->file->fflags_text), flag); + return (1); +} + +#ifdef HAVE_LIBXML_XMLREADER_H + +static int +xml2_xmlattr_setup(struct archive_read *a, + struct xmlattr_list *list, xmlTextReaderPtr reader) +{ + struct xmlattr *attr; + int r; + + list->first = NULL; + list->last = &(list->first); + r = xmlTextReaderMoveToFirstAttribute(reader); + while (r == 1) { + attr = malloc(sizeof*(attr)); + if (attr == NULL) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + attr->name = strdup( + (const char *)xmlTextReaderConstLocalName(reader)); + if (attr->name == NULL) { + free(attr); + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + attr->value = strdup( + (const char *)xmlTextReaderConstValue(reader)); + if (attr->value == NULL) { + free(attr->name); + free(attr); + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + attr->next = NULL; + *list->last = attr; + list->last = &(attr->next); + r = xmlTextReaderMoveToNextAttribute(reader); + } + return (r); +} + +static int +xml2_read_cb(void *context, char *buffer, int len) +{ + struct archive_read *a; + struct xar *xar; + const void *d; + size_t outbytes; - size_t used; ++ size_t used = 0; + int r; + + a = (struct archive_read *)context; + xar = (struct xar *)(a->format->data); + + if (xar->toc_remaining <= 0) + return (0); + d = buffer; + outbytes = len; + r = rd_contents(a, &d, &outbytes, &used, xar->toc_remaining); + if (r != ARCHIVE_OK) + return (r); + __archive_read_consume(a, used); + xar->toc_remaining -= used; + xar->offset += used; + xar->toc_total += outbytes; + PRINT_TOC(buffer, len); + + return ((int)outbytes); +} + +static int +xml2_close_cb(void *context) +{ + + (void)context; /* UNUSED */ + return (0); +} + +static void +xml2_error_hdr(void *arg, const char *msg, xmlParserSeverities severity, + xmlTextReaderLocatorPtr locator) +{ + struct archive_read *a; + + (void)locator; /* UNUSED */ + a = (struct archive_read *)arg; + switch (severity) { + case XML_PARSER_SEVERITY_VALIDITY_WARNING: + case XML_PARSER_SEVERITY_WARNING: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "XML Parsing error: %s", msg); + break; + case XML_PARSER_SEVERITY_VALIDITY_ERROR: + case XML_PARSER_SEVERITY_ERROR: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "XML Parsing error: %s", msg); + break; + } +} + +static int +xml2_read_toc(struct archive_read *a) +{ + xmlTextReaderPtr reader; + struct xmlattr_list list; + int r; + + reader = xmlReaderForIO(xml2_read_cb, xml2_close_cb, a, NULL, NULL, 0); + if (reader == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Couldn't allocate memory for xml parser"); + return (ARCHIVE_FATAL); + } + xmlTextReaderSetErrorHandler(reader, xml2_error_hdr, a); + + while ((r = xmlTextReaderRead(reader)) == 1) { + const char *name, *value; + int type, empty; + + type = xmlTextReaderNodeType(reader); + name = (const char *)xmlTextReaderConstLocalName(reader); + switch (type) { + case XML_READER_TYPE_ELEMENT: + empty = xmlTextReaderIsEmptyElement(reader); + r = xml2_xmlattr_setup(a, &list, reader); + if (r == ARCHIVE_OK) + r = xml_start(a, name, &list); + xmlattr_cleanup(&list); + if (r != ARCHIVE_OK) + return (r); + if (empty) + xml_end(a, name); + break; + case XML_READER_TYPE_END_ELEMENT: + xml_end(a, name); + break; + case XML_READER_TYPE_TEXT: + value = (const char *)xmlTextReaderConstValue(reader); + xml_data(a, value, strlen(value)); + break; + case XML_READER_TYPE_SIGNIFICANT_WHITESPACE: + default: + break; + } + if (r < 0) + break; + } + xmlFreeTextReader(reader); + xmlCleanupParser(); + + return ((r == 0)?ARCHIVE_OK:ARCHIVE_FATAL); +} + +#elif defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H) + +static int +expat_xmlattr_setup(struct archive_read *a, + struct xmlattr_list *list, const XML_Char **atts) +{ + struct xmlattr *attr; + char *name, *value; + + list->first = NULL; + list->last = &(list->first); + if (atts == NULL) + return (ARCHIVE_OK); + while (atts[0] != NULL && atts[1] != NULL) { + attr = malloc(sizeof*(attr)); + name = strdup(atts[0]); + value = strdup(atts[1]); + if (attr == NULL || name == NULL || value == NULL) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); ++ free(attr); ++ free(name); ++ free(value); + return (ARCHIVE_FATAL); + } + attr->name = name; + attr->value = value; + attr->next = NULL; + *list->last = attr; + list->last = &(attr->next); + atts += 2; + } + return (ARCHIVE_OK); +} + +static void +expat_start_cb(void *userData, const XML_Char *name, const XML_Char **atts) +{ + struct expat_userData *ud = (struct expat_userData *)userData; + struct archive_read *a = ud->archive; + struct xmlattr_list list; + int r; + + r = expat_xmlattr_setup(a, &list, atts); + if (r == ARCHIVE_OK) + r = xml_start(a, (const char *)name, &list); + xmlattr_cleanup(&list); + ud->state = r; +} + +static void +expat_end_cb(void *userData, const XML_Char *name) +{ + struct expat_userData *ud = (struct expat_userData *)userData; + + xml_end(ud->archive, (const char *)name); +} + +static void +expat_data_cb(void *userData, const XML_Char *s, int len) +{ + struct expat_userData *ud = (struct expat_userData *)userData; + + xml_data(ud->archive, s, len); +} + +static int +expat_read_toc(struct archive_read *a) +{ + struct xar *xar; + XML_Parser parser; + struct expat_userData ud; + + ud.state = ARCHIVE_OK; + ud.archive = a; + + xar = (struct xar *)(a->format->data); + + /* Initialize XML Parser library. */ + parser = XML_ParserCreate(NULL); + if (parser == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Couldn't allocate memory for xml parser"); + return (ARCHIVE_FATAL); + } + XML_SetUserData(parser, &ud); + XML_SetElementHandler(parser, expat_start_cb, expat_end_cb); + XML_SetCharacterDataHandler(parser, expat_data_cb); + xar->xmlsts = INIT; + + while (xar->toc_remaining && ud.state == ARCHIVE_OK) { + enum XML_Status xr; + const void *d; + size_t outbytes; + size_t used; + int r; + + d = NULL; + r = rd_contents(a, &d, &outbytes, &used, xar->toc_remaining); + if (r != ARCHIVE_OK) + return (r); + xar->toc_remaining -= used; + xar->offset += used; + xar->toc_total += outbytes; + PRINT_TOC(d, outbytes); + + xr = XML_Parse(parser, d, outbytes, xar->toc_remaining == 0); + __archive_read_consume(a, used); + if (xr == XML_STATUS_ERROR) { + XML_ParserFree(parser); + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "XML Parsing failed"); + return (ARCHIVE_FATAL); + } + } + XML_ParserFree(parser); + return (ud.state); +} +#endif /* defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H) */ + +#endif /* Support xar format */ diff --cc Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c index c50ba84,0000000..e56bd63 mode 100644,000000..100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_zip.c @@@ -1,3062 -1,0 +1,3112 @@@ +/*- + * Copyright (c) 2004-2013 Tim Kientzle + * Copyright (c) 2011-2012,2014 Michihiro NAKAJIMA + * Copyright (c) 2013 Konrad Kleine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_zip.c 201102 2009-12-28 03:11:36Z kientzle $"); + +/* + * The definitive documentation of the Zip file format is: + * http://www.pkware.com/documents/casestudies/APPNOTE.TXT + * + * The Info-Zip project has pioneered various extensions to better + * support Zip on Unix, including the 0x5455 "UT", 0x5855 "UX", 0x7855 + * "Ux", and 0x7875 "ux" extensions for time and ownership + * information. + * + * History of this code: The streaming Zip reader was first added to + * libarchive in January 2005. Support for seekable input sources was + * added in Nov 2011. Zip64 support (including a significant code + * refactoring) was added in 2014. + */ + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_ZLIB_H +#include +#endif + +#include "archive.h" +#include "archive_digest_private.h" +#include "archive_cryptor_private.h" +#include "archive_endian.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_hmac_private.h" +#include "archive_private.h" +#include "archive_rb.h" +#include "archive_read_private.h" + +#ifndef HAVE_ZLIB_H +#include "archive_crc32.h" +#endif + +struct zip_entry { + struct archive_rb_node node; + struct zip_entry *next; + int64_t local_header_offset; + int64_t compressed_size; + int64_t uncompressed_size; + int64_t gid; + int64_t uid; + struct archive_string rsrcname; + time_t mtime; + time_t atime; + time_t ctime; + uint32_t crc32; + uint16_t mode; + uint16_t zip_flags; /* From GP Flags Field */ + unsigned char compression; + unsigned char system; /* From "version written by" */ + unsigned char flags; /* Our extra markers. */ + unsigned char decdat;/* Used for Decryption check */ + + /* WinZip AES encryption extra field should be available + * when compression is 99. */ + struct { + /* Vendor version: AE-1 - 0x0001, AE-2 - 0x0002 */ + unsigned vendor; +#define AES_VENDOR_AE_1 0x0001 +#define AES_VENDOR_AE_2 0x0002 + /* AES encryption strength: + * 1 - 128 bits, 2 - 192 bits, 2 - 256 bits. */ + unsigned strength; + /* Actual compression method. */ + unsigned char compression; + } aes_extra; +}; + +struct trad_enc_ctx { + uint32_t keys[3]; +}; + +/* Bits used in zip_flags. */ +#define ZIP_ENCRYPTED (1 << 0) +#define ZIP_LENGTH_AT_END (1 << 3) +#define ZIP_STRONG_ENCRYPTED (1 << 6) +#define ZIP_UTF8_NAME (1 << 11) +/* See "7.2 Single Password Symmetric Encryption Method" + in http://www.pkware.com/documents/casestudies/APPNOTE.TXT */ +#define ZIP_CENTRAL_DIRECTORY_ENCRYPTED (1 << 13) + +/* Bits used in flags. */ +#define LA_USED_ZIP64 (1 << 0) +#define LA_FROM_CENTRAL_DIRECTORY (1 << 1) + +/* + * See "WinZip - AES Encryption Information" + * http://www.winzip.com/aes_info.htm + */ +/* Value used in compression method. */ +#define WINZIP_AES_ENCRYPTION 99 +/* Authentication code size. */ +#define AUTH_CODE_SIZE 10 +/**/ +#define MAX_DERIVED_KEY_BUF_SIZE (AES_MAX_KEY_SIZE * 2 + 2) + +struct zip { + /* Structural information about the archive. */ + struct archive_string format_name; + int64_t central_directory_offset; + size_t central_directory_entries_total; + size_t central_directory_entries_on_this_disk; + int has_encrypted_entries; + + /* List of entries (seekable Zip only) */ + struct zip_entry *zip_entries; + struct archive_rb_tree tree; + struct archive_rb_tree tree_rsrc; + + /* Bytes read but not yet consumed via __archive_read_consume() */ + size_t unconsumed; + + /* Information about entry we're currently reading. */ + struct zip_entry *entry; + int64_t entry_bytes_remaining; + + /* These count the number of bytes actually read for the entry. */ + int64_t entry_compressed_bytes_read; + int64_t entry_uncompressed_bytes_read; + + /* Running CRC32 of the decompressed data */ + unsigned long entry_crc32; + unsigned long (*crc32func)(unsigned long, const void *, + size_t); + char ignore_crc32; + + /* Flags to mark progress of decompression. */ + char decompress_init; + char end_of_entry; + +#ifdef HAVE_ZLIB_H + unsigned char *uncompressed_buffer; + size_t uncompressed_buffer_size; + z_stream stream; + char stream_valid; +#endif + + struct archive_string_conv *sconv; + struct archive_string_conv *sconv_default; + struct archive_string_conv *sconv_utf8; + int init_default_conversion; + int process_mac_extensions; + + char init_decryption; + + /* Decryption buffer. */ + /* + * The decrypted data starts at decrypted_ptr and + * extends for decrypted_bytes_remaining. Decryption + * adds new data to the end of this block, data is returned + * to clients from the beginning. When the block hits the + * end of decrypted_buffer, it has to be shuffled back to + * the beginning of the buffer. + */ + unsigned char *decrypted_buffer; + unsigned char *decrypted_ptr; + size_t decrypted_buffer_size; + size_t decrypted_bytes_remaining; + size_t decrypted_unconsumed_bytes; + + /* Traditional PKWARE decryption. */ + struct trad_enc_ctx tctx; + char tctx_valid; + - /* WinZip AES decyption. */ ++ /* WinZip AES decryption. */ + /* Contexts used for AES decryption. */ + archive_crypto_ctx cctx; + char cctx_valid; + archive_hmac_sha1_ctx hctx; + char hctx_valid; + + /* Strong encryption's decryption header information. */ + unsigned iv_size; + unsigned alg_id; + unsigned bit_len; + unsigned flags; + unsigned erd_size; + unsigned v_size; + unsigned v_crc32; + uint8_t *iv; + uint8_t *erd; + uint8_t *v_data; +}; + +/* Many systems define min or MIN, but not all. */ +#define zipmin(a,b) ((a) < (b) ? (a) : (b)) + +/* ------------------------------------------------------------------------ */ + +/* + Traditional PKWARE Decryption functions. + */ + +static void +trad_enc_update_keys(struct trad_enc_ctx *ctx, uint8_t c) +{ + uint8_t t; +#define CRC32(c, b) (crc32(c ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL) + + ctx->keys[0] = CRC32(ctx->keys[0], c); + ctx->keys[1] = (ctx->keys[1] + (ctx->keys[0] & 0xff)) * 134775813L + 1; + t = (ctx->keys[1] >> 24) & 0xff; + ctx->keys[2] = CRC32(ctx->keys[2], t); +#undef CRC32 +} + +static uint8_t - trad_enc_decypt_byte(struct trad_enc_ctx *ctx) ++trad_enc_decrypt_byte(struct trad_enc_ctx *ctx) +{ + unsigned temp = ctx->keys[2] | 2; + return (uint8_t)((temp * (temp ^ 1)) >> 8) & 0xff; +} + +static void +trad_enc_decrypt_update(struct trad_enc_ctx *ctx, const uint8_t *in, + size_t in_len, uint8_t *out, size_t out_len) +{ + unsigned i, max; + + max = (unsigned)((in_len < out_len)? in_len: out_len); + + for (i = 0; i < max; i++) { - uint8_t t = in[i] ^ trad_enc_decypt_byte(ctx); ++ uint8_t t = in[i] ^ trad_enc_decrypt_byte(ctx); + out[i] = t; + trad_enc_update_keys(ctx, t); + } +} + +static int +trad_enc_init(struct trad_enc_ctx *ctx, const char *pw, size_t pw_len, + const uint8_t *key, size_t key_len, uint8_t *crcchk) +{ + uint8_t header[12]; + + if (key_len < 12) { + *crcchk = 0xff; + return -1; + } + + ctx->keys[0] = 305419896L; + ctx->keys[1] = 591751049L; + ctx->keys[2] = 878082192L; + + for (;pw_len; --pw_len) + trad_enc_update_keys(ctx, *pw++); + + trad_enc_decrypt_update(ctx, key, 12, header, 12); + /* Return the last byte for CRC check. */ + *crcchk = header[11]; + return 0; +} + +#if 0 +static void +crypt_derive_key_sha1(const void *p, int size, unsigned char *key, + int key_size) +{ +#define MD_SIZE 20 + archive_sha1_ctx ctx; + unsigned char md1[MD_SIZE]; + unsigned char md2[MD_SIZE * 2]; + unsigned char mkb[64]; + int i; + + archive_sha1_init(&ctx); + archive_sha1_update(&ctx, p, size); + archive_sha1_final(&ctx, md1); + + memset(mkb, 0x36, sizeof(mkb)); + for (i = 0; i < MD_SIZE; i++) + mkb[i] ^= md1[i]; + archive_sha1_init(&ctx); + archive_sha1_update(&ctx, mkb, sizeof(mkb)); + archive_sha1_final(&ctx, md2); + + memset(mkb, 0x5C, sizeof(mkb)); + for (i = 0; i < MD_SIZE; i++) + mkb[i] ^= md1[i]; + archive_sha1_init(&ctx); + archive_sha1_update(&ctx, mkb, sizeof(mkb)); + archive_sha1_final(&ctx, md2 + MD_SIZE); + + if (key_size > 32) + key_size = 32; + memcpy(key, md2, key_size); +#undef MD_SIZE +} +#endif + +/* + * Common code for streaming or seeking modes. + * + * Includes code to read local file headers, decompress data + * from entry bodies, and common API. + */ + +static unsigned long +real_crc32(unsigned long crc, const void *buff, size_t len) +{ + return crc32(crc, buff, (unsigned int)len); +} + +/* Used by "ignorecrc32" option to speed up tests. */ +static unsigned long +fake_crc32(unsigned long crc, const void *buff, size_t len) +{ + (void)crc; /* UNUSED */ + (void)buff; /* UNUSED */ + (void)len; /* UNUSED */ + return 0; +} + +static struct { + int id; + const char * name; +} compression_methods[] = { + {0, "uncompressed"}, /* The file is stored (no compression) */ + {1, "shrinking"}, /* The file is Shrunk */ + {2, "reduced-1"}, /* The file is Reduced with compression factor 1 */ + {3, "reduced-2"}, /* The file is Reduced with compression factor 2 */ + {4, "reduced-3"}, /* The file is Reduced with compression factor 3 */ + {5, "reduced-4"}, /* The file is Reduced with compression factor 4 */ + {6, "imploded"}, /* The file is Imploded */ + {7, "reserved"}, /* Reserved for Tokenizing compression algorithm */ + {8, "deflation"}, /* The file is Deflated */ + {9, "deflation-64-bit"}, /* Enhanced Deflating using Deflate64(tm) */ + {10, "ibm-terse"},/* PKWARE Data Compression Library Imploding + * (old IBM TERSE) */ + {11, "reserved"}, /* Reserved by PKWARE */ + {12, "bzip"}, /* File is compressed using BZIP2 algorithm */ + {13, "reserved"}, /* Reserved by PKWARE */ + {14, "lzma"}, /* LZMA (EFS) */ + {15, "reserved"}, /* Reserved by PKWARE */ + {16, "reserved"}, /* Reserved by PKWARE */ + {17, "reserved"}, /* Reserved by PKWARE */ + {18, "ibm-terse-new"}, /* File is compressed using IBM TERSE (new) */ + {19, "ibm-lz777"},/* IBM LZ77 z Architecture (PFS) */ + {97, "wav-pack"}, /* WavPack compressed data */ + {98, "ppmd-1"}, /* PPMd version I, Rev 1 */ + {99, "aes"} /* WinZip AES encryption */ +}; + +static const char * +compression_name(const int compression) +{ + static const int num_compression_methods = + sizeof(compression_methods)/sizeof(compression_methods[0]); + int i=0; + + while(compression >= 0 && i < num_compression_methods) { + if (compression_methods[i].id == compression) + return compression_methods[i].name; + i++; + } + return "??"; +} + +/* Convert an MSDOS-style date/time into Unix-style time. */ +static time_t +zip_time(const char *p) +{ + int msTime, msDate; + struct tm ts; + + msTime = (0xff & (unsigned)p[0]) + 256 * (0xff & (unsigned)p[1]); + msDate = (0xff & (unsigned)p[2]) + 256 * (0xff & (unsigned)p[3]); + + memset(&ts, 0, sizeof(ts)); + ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */ + ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */ + ts.tm_mday = msDate & 0x1f; /* Day of month. */ + ts.tm_hour = (msTime >> 11) & 0x1f; + ts.tm_min = (msTime >> 5) & 0x3f; + ts.tm_sec = (msTime << 1) & 0x3e; + ts.tm_isdst = -1; + return mktime(&ts); +} + +/* + * The extra data is stored as a list of + * id1+size1+data1 + id2+size2+data2 ... + * triplets. id and size are 2 bytes each. + */ - static void - process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry) ++static int ++process_extra(struct archive_read *a, const char *p, size_t extra_length, struct zip_entry* zip_entry) +{ + unsigned offset = 0; + - while (offset < extra_length - 4) { ++ if (extra_length == 0) { ++ return ARCHIVE_OK; ++ } ++ ++ if (extra_length < 4) { ++ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, ++ "Too-small extra data: Need at least 4 bytes, but only found %d bytes", (int)extra_length); ++ return ARCHIVE_FAILED; ++ } ++ while (offset <= extra_length - 4) { + unsigned short headerid = archive_le16dec(p + offset); + unsigned short datasize = archive_le16dec(p + offset + 2); + + offset += 4; + if (offset + datasize > extra_length) { - break; ++ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, ++ "Extra data overflow: Need %d bytes but only found %d bytes", ++ (int)datasize, (int)(extra_length - offset)); ++ return ARCHIVE_FAILED; + } +#ifdef DEBUG + fprintf(stderr, "Header id 0x%04x, length %d\n", + headerid, datasize); +#endif + switch (headerid) { + case 0x0001: + /* Zip64 extended information extra field. */ + zip_entry->flags |= LA_USED_ZIP64; + if (zip_entry->uncompressed_size == 0xffffffff) { - if (datasize < 8) - break; - zip_entry->uncompressed_size = - archive_le64dec(p + offset); ++ uint64_t t = 0; ++ if (datasize < 8 ++ || (t = archive_le64dec(p + offset)) > INT64_MAX) { ++ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, ++ "Malformed 64-bit uncompressed size"); ++ return ARCHIVE_FAILED; ++ } ++ zip_entry->uncompressed_size = t; + offset += 8; + datasize -= 8; + } + if (zip_entry->compressed_size == 0xffffffff) { - if (datasize < 8) - break; - zip_entry->compressed_size = - archive_le64dec(p + offset); ++ uint64_t t = 0; ++ if (datasize < 8 ++ || (t = archive_le64dec(p + offset)) > INT64_MAX) { ++ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, ++ "Malformed 64-bit compressed size"); ++ return ARCHIVE_FAILED; ++ } ++ zip_entry->compressed_size = t; + offset += 8; + datasize -= 8; + } + if (zip_entry->local_header_offset == 0xffffffff) { - if (datasize < 8) - break; - zip_entry->local_header_offset = - archive_le64dec(p + offset); ++ uint64_t t = 0; ++ if (datasize < 8 ++ || (t = archive_le64dec(p + offset)) > INT64_MAX) { ++ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, ++ "Malformed 64-bit local header offset"); ++ return ARCHIVE_FAILED; ++ } ++ zip_entry->local_header_offset = t; + offset += 8; + datasize -= 8; + } + /* archive_le32dec(p + offset) gives disk + * on which file starts, but we don't handle + * multi-volume Zip files. */ + break; +#ifdef DEBUG + case 0x0017: + { + /* Strong encryption field. */ + if (archive_le16dec(p + offset) == 2) { + unsigned algId = + archive_le16dec(p + offset + 2); + unsigned bitLen = + archive_le16dec(p + offset + 4); + int flags = + archive_le16dec(p + offset + 6); + fprintf(stderr, "algId=0x%04x, bitLen=%u, " + "flgas=%d\n", algId, bitLen,flags); + } + break; + } +#endif + case 0x5455: + { + /* Extended time field "UT". */ + int flags = p[offset]; + offset++; + datasize--; + /* Flag bits indicate which dates are present. */ + if (flags & 0x01) + { +#ifdef DEBUG + fprintf(stderr, "mtime: %lld -> %d\n", + (long long)zip_entry->mtime, + archive_le32dec(p + offset)); +#endif + if (datasize < 4) + break; + zip_entry->mtime = archive_le32dec(p + offset); + offset += 4; + datasize -= 4; + } + if (flags & 0x02) + { + if (datasize < 4) + break; + zip_entry->atime = archive_le32dec(p + offset); + offset += 4; + datasize -= 4; + } + if (flags & 0x04) + { + if (datasize < 4) + break; + zip_entry->ctime = archive_le32dec(p + offset); + offset += 4; + datasize -= 4; + } + break; + } + case 0x5855: + { + /* Info-ZIP Unix Extra Field (old version) "UX". */ + if (datasize >= 8) { + zip_entry->atime = archive_le32dec(p + offset); + zip_entry->mtime = + archive_le32dec(p + offset + 4); + } + if (datasize >= 12) { + zip_entry->uid = + archive_le16dec(p + offset + 8); + zip_entry->gid = + archive_le16dec(p + offset + 10); + } + break; + } + case 0x6c78: + { + /* Experimental 'xl' field */ + /* + * Introduced Dec 2013 to provide a way to + * include external file attributes (and other + * fields that ordinarily appear only in + * central directory) in local file header. + * This provides file type and permission + * information necessary to support full + * streaming extraction. Currently being + * discussed with other Zip developers + * ... subject to change. + * + * Format: + * The field starts with a bitmap that specifies + * which additional fields are included. The + * bitmap is variable length and can be extended in + * the future. + * + * n bytes - feature bitmap: first byte has low-order + * 7 bits. If high-order bit is set, a subsequent + * byte holds the next 7 bits, etc. + * + * if bitmap & 1, 2 byte "version made by" + * if bitmap & 2, 2 byte "internal file attributes" + * if bitmap & 4, 4 byte "external file attributes" + * if bitmap & 8, 2 byte comment length + n byte comment + */ + int bitmap, bitmap_last; + + if (datasize < 1) + break; + bitmap_last = bitmap = 0xff & p[offset]; + offset += 1; + datasize -= 1; + + /* We only support first 7 bits of bitmap; skip rest. */ + while ((bitmap_last & 0x80) != 0 + && datasize >= 1) { + bitmap_last = p[offset]; + offset += 1; + datasize -= 1; + } + + if (bitmap & 1) { + /* 2 byte "version made by" */ + if (datasize < 2) + break; + zip_entry->system + = archive_le16dec(p + offset) >> 8; + offset += 2; + datasize -= 2; + } + if (bitmap & 2) { + /* 2 byte "internal file attributes" */ + uint32_t internal_attributes; + if (datasize < 2) + break; + internal_attributes + = archive_le16dec(p + offset); + /* Not used by libarchive at present. */ + (void)internal_attributes; /* UNUSED */ + offset += 2; + datasize -= 2; + } + if (bitmap & 4) { + /* 4 byte "external file attributes" */ + uint32_t external_attributes; + if (datasize < 4) + break; + external_attributes + = archive_le32dec(p + offset); + if (zip_entry->system == 3) { + zip_entry->mode + = external_attributes >> 16; + } else if (zip_entry->system == 0) { + // Interpret MSDOS directory bit + if (0x10 == (external_attributes & 0x10)) { + zip_entry->mode = AE_IFDIR | 0775; + } else { + zip_entry->mode = AE_IFREG | 0664; + } + if (0x01 == (external_attributes & 0x01)) { + // Read-only bit; strip write permissions + zip_entry->mode &= 0555; + } + } else { + zip_entry->mode = 0; + } + offset += 4; + datasize -= 4; + } + if (bitmap & 8) { + /* 2 byte comment length + comment */ + uint32_t comment_length; + if (datasize < 2) + break; + comment_length + = archive_le16dec(p + offset); + offset += 2; + datasize -= 2; + + if (datasize < comment_length) + break; + /* Comment is not supported by libarchive */ + offset += comment_length; + datasize -= comment_length; + } + break; + } + case 0x7855: + /* Info-ZIP Unix Extra Field (type 2) "Ux". */ +#ifdef DEBUG + fprintf(stderr, "uid %d gid %d\n", + archive_le16dec(p + offset), + archive_le16dec(p + offset + 2)); +#endif + if (datasize >= 2) + zip_entry->uid = archive_le16dec(p + offset); + if (datasize >= 4) + zip_entry->gid = + archive_le16dec(p + offset + 2); + break; + case 0x7875: + { + /* Info-Zip Unix Extra Field (type 3) "ux". */ + int uidsize = 0, gidsize = 0; + + /* TODO: support arbitrary uidsize/gidsize. */ + if (datasize >= 1 && p[offset] == 1) {/* version=1 */ + if (datasize >= 4) { + /* get a uid size. */ + uidsize = 0xff & (int)p[offset+1]; + if (uidsize == 2) + zip_entry->uid = + archive_le16dec( + p + offset + 2); + else if (uidsize == 4 && datasize >= 6) + zip_entry->uid = + archive_le32dec( + p + offset + 2); + } + if (datasize >= (2 + uidsize + 3)) { + /* get a gid size. */ + gidsize = 0xff & (int)p[offset+2+uidsize]; + if (gidsize == 2) + zip_entry->gid = + archive_le16dec( + p+offset+2+uidsize+1); + else if (gidsize == 4 && + datasize >= (2 + uidsize + 5)) + zip_entry->gid = + archive_le32dec( + p+offset+2+uidsize+1); + } + } + break; + } + case 0x9901: - /* WinZIp AES extra data field. */ ++ /* WinZip AES extra data field. */ + if (p[offset + 2] == 'A' && p[offset + 3] == 'E') { + /* Vendor version. */ + zip_entry->aes_extra.vendor = + archive_le16dec(p + offset); + /* AES encryption strength. */ + zip_entry->aes_extra.strength = p[offset + 4]; + /* Actual compression method. */ + zip_entry->aes_extra.compression = + p[offset + 5]; + } + break; + default: + break; + } + offset += datasize; + } - #ifdef DEBUG - if (offset != extra_length) - { - fprintf(stderr, - "Extra data field contents do not match reported size!\n"); ++ if (offset != extra_length) { ++ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, ++ "Malformed extra data: Consumed %d bytes of %d bytes", ++ (int)offset, (int)extra_length); ++ return ARCHIVE_FAILED; + } - #endif ++ return ARCHIVE_OK; +} + +/* + * Assumes file pointer is at beginning of local file header. + */ +static int +zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry, + struct zip *zip) +{ + const char *p; + const void *h; + const wchar_t *wp; + const char *cp; + size_t len, filename_length, extra_length; + struct archive_string_conv *sconv; + struct zip_entry *zip_entry = zip->entry; + struct zip_entry zip_entry_central_dir; + int ret = ARCHIVE_OK; + char version; + + /* Save a copy of the original for consistency checks. */ + zip_entry_central_dir = *zip_entry; + + zip->decompress_init = 0; + zip->end_of_entry = 0; + zip->entry_uncompressed_bytes_read = 0; + zip->entry_compressed_bytes_read = 0; + zip->entry_crc32 = zip->crc32func(0, NULL, 0); + + /* Setup default conversion. */ + if (zip->sconv == NULL && !zip->init_default_conversion) { + zip->sconv_default = + archive_string_default_conversion_for_read(&(a->archive)); + zip->init_default_conversion = 1; + } + + if ((p = __archive_read_ahead(a, 30, NULL)) == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file header"); + return (ARCHIVE_FATAL); + } + + if (memcmp(p, "PK\003\004", 4) != 0) { + archive_set_error(&a->archive, -1, "Damaged Zip archive"); + return ARCHIVE_FATAL; + } + version = p[4]; + zip_entry->system = p[5]; + zip_entry->zip_flags = archive_le16dec(p + 6); + if (zip_entry->zip_flags & (ZIP_ENCRYPTED | ZIP_STRONG_ENCRYPTED)) { + zip->has_encrypted_entries = 1; + archive_entry_set_is_data_encrypted(entry, 1); + if (zip_entry->zip_flags & ZIP_CENTRAL_DIRECTORY_ENCRYPTED && + zip_entry->zip_flags & ZIP_ENCRYPTED && + zip_entry->zip_flags & ZIP_STRONG_ENCRYPTED) { + archive_entry_set_is_metadata_encrypted(entry, 1); + return ARCHIVE_FATAL; + } + } + zip->init_decryption = (zip_entry->zip_flags & ZIP_ENCRYPTED); + zip_entry->compression = (char)archive_le16dec(p + 8); + zip_entry->mtime = zip_time(p + 10); + zip_entry->crc32 = archive_le32dec(p + 14); + if (zip_entry->zip_flags & ZIP_LENGTH_AT_END) + zip_entry->decdat = p[11]; + else + zip_entry->decdat = p[17]; + zip_entry->compressed_size = archive_le32dec(p + 18); + zip_entry->uncompressed_size = archive_le32dec(p + 22); + filename_length = archive_le16dec(p + 26); + extra_length = archive_le16dec(p + 28); + + __archive_read_consume(a, 30); + + /* Read the filename. */ + if ((h = __archive_read_ahead(a, filename_length, NULL)) == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file header"); + return (ARCHIVE_FATAL); + } + if (zip_entry->zip_flags & ZIP_UTF8_NAME) { + /* The filename is stored to be UTF-8. */ + if (zip->sconv_utf8 == NULL) { + zip->sconv_utf8 = + archive_string_conversion_from_charset( + &a->archive, "UTF-8", 1); + if (zip->sconv_utf8 == NULL) + return (ARCHIVE_FATAL); + } + sconv = zip->sconv_utf8; + } else if (zip->sconv != NULL) + sconv = zip->sconv; + else + sconv = zip->sconv_default; + + if (archive_entry_copy_pathname_l(entry, + h, filename_length, sconv) != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Pathname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Pathname cannot be converted " + "from %s to current locale.", + archive_string_conversion_charset_name(sconv)); + ret = ARCHIVE_WARN; + } + __archive_read_consume(a, filename_length); + + /* Read the extra data. */ + if ((h = __archive_read_ahead(a, extra_length, NULL)) == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file header"); + return (ARCHIVE_FATAL); + } + - process_extra(h, extra_length, zip_entry); ++ if (ARCHIVE_OK != process_extra(a, h, extra_length, zip_entry)) { ++ return ARCHIVE_FATAL; ++ } + __archive_read_consume(a, extra_length); + + /* Work around a bug in Info-Zip: When reading from a pipe, it + * stats the pipe instead of synthesizing a file entry. */ + if ((zip_entry->mode & AE_IFMT) == AE_IFIFO) { + zip_entry->mode &= ~ AE_IFMT; + zip_entry->mode |= AE_IFREG; + } + - if ((zip_entry->mode & AE_IFMT) == 0) { - /* Especially in streaming mode, we can end up - here without having seen proper mode information. - Guess from the filename. */ ++ /* If the mode is totally empty, set some sane default. */ ++ if (zip_entry->mode == 0) { ++ zip_entry->mode |= 0664; ++ } ++ ++ /* Make sure that entries with a trailing '/' are marked as directories ++ * even if the External File Attributes contains bogus values. If this ++ * is not a directory and there is no type, assume regularfile. */ ++ if ((zip_entry->mode & AE_IFMT) != AE_IFDIR) { ++ int has_slash; ++ + wp = archive_entry_pathname_w(entry); + if (wp != NULL) { + len = wcslen(wp); - if (len > 0 && wp[len - 1] == L'/') - zip_entry->mode |= AE_IFDIR; - else - zip_entry->mode |= AE_IFREG; ++ has_slash = len > 0 && wp[len - 1] == L'/'; + } else { + cp = archive_entry_pathname(entry); + len = (cp != NULL)?strlen(cp):0; - if (len > 0 && cp[len - 1] == '/') - zip_entry->mode |= AE_IFDIR; - else - zip_entry->mode |= AE_IFREG; ++ has_slash = len > 0 && cp[len - 1] == '/'; + } - if (zip_entry->mode == AE_IFDIR) { - zip_entry->mode |= 0775; - } else if (zip_entry->mode == AE_IFREG) { - zip_entry->mode |= 0664; ++ /* Correct file type as needed. */ ++ if (has_slash) { ++ zip_entry->mode &= ~AE_IFMT; ++ zip_entry->mode |= AE_IFDIR; ++ zip_entry->mode |= 0111; ++ } else if ((zip_entry->mode & AE_IFMT) == 0) { ++ zip_entry->mode |= AE_IFREG; + } + } + + /* Make sure directories end in '/' */ + if ((zip_entry->mode & AE_IFMT) == AE_IFDIR) { + wp = archive_entry_pathname_w(entry); + if (wp != NULL) { + len = wcslen(wp); + if (len > 0 && wp[len - 1] != L'/') { + struct archive_wstring s; + archive_string_init(&s); + archive_wstrcat(&s, wp); + archive_wstrappend_wchar(&s, L'/'); + archive_entry_copy_pathname_w(entry, s.s); ++ archive_wstring_free(&s); + } + } else { + cp = archive_entry_pathname(entry); + len = (cp != NULL)?strlen(cp):0; + if (len > 0 && cp[len - 1] != '/') { + struct archive_string s; + archive_string_init(&s); + archive_strcat(&s, cp); + archive_strappend_char(&s, '/'); + archive_entry_set_pathname(entry, s.s); ++ archive_string_free(&s); + } + } + } + + if (zip_entry->flags & LA_FROM_CENTRAL_DIRECTORY) { + /* If this came from the central dir, it's size info + * is definitive, so ignore the length-at-end flag. */ + zip_entry->zip_flags &= ~ZIP_LENGTH_AT_END; + /* If local header is missing a value, use the one from + the central directory. If both have it, warn about + mismatches. */ + if (zip_entry->crc32 == 0) { + zip_entry->crc32 = zip_entry_central_dir.crc32; + } else if (!zip->ignore_crc32 + && zip_entry->crc32 != zip_entry_central_dir.crc32) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Inconsistent CRC32 values"); + ret = ARCHIVE_WARN; + } + if (zip_entry->compressed_size == 0) { + zip_entry->compressed_size + = zip_entry_central_dir.compressed_size; + } else if (zip_entry->compressed_size + != zip_entry_central_dir.compressed_size) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Inconsistent compressed size: " + "%jd in central directory, %jd in local header", + (intmax_t)zip_entry_central_dir.compressed_size, + (intmax_t)zip_entry->compressed_size); + ret = ARCHIVE_WARN; + } + if (zip_entry->uncompressed_size == 0) { + zip_entry->uncompressed_size + = zip_entry_central_dir.uncompressed_size; + } else if (zip_entry->uncompressed_size + != zip_entry_central_dir.uncompressed_size) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Inconsistent uncompressed size: " + "%jd in central directory, %jd in local header", + (intmax_t)zip_entry_central_dir.uncompressed_size, + (intmax_t)zip_entry->uncompressed_size); + ret = ARCHIVE_WARN; + } + } + + /* Populate some additional entry fields: */ + archive_entry_set_mode(entry, zip_entry->mode); + archive_entry_set_uid(entry, zip_entry->uid); + archive_entry_set_gid(entry, zip_entry->gid); + archive_entry_set_mtime(entry, zip_entry->mtime, 0); + archive_entry_set_ctime(entry, zip_entry->ctime, 0); + archive_entry_set_atime(entry, zip_entry->atime, 0); + + if ((zip->entry->mode & AE_IFMT) == AE_IFLNK) { + size_t linkname_length; + + if (zip_entry->compressed_size > 64 * 1024) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Zip file with oversized link entry"); + return ARCHIVE_FATAL; + } + + linkname_length = (size_t)zip_entry->compressed_size; + + archive_entry_set_size(entry, 0); + p = __archive_read_ahead(a, linkname_length, NULL); + if (p == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Truncated Zip file"); + return ARCHIVE_FATAL; + } + + sconv = zip->sconv; + if (sconv == NULL && (zip->entry->zip_flags & ZIP_UTF8_NAME)) + sconv = zip->sconv_utf8; + if (sconv == NULL) + sconv = zip->sconv_default; + if (archive_entry_copy_symlink_l(entry, p, linkname_length, + sconv) != 0) { + if (errno != ENOMEM && sconv == zip->sconv_utf8 && + (zip->entry->zip_flags & ZIP_UTF8_NAME)) + archive_entry_copy_symlink_l(entry, p, + linkname_length, NULL); + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Symlink"); + return (ARCHIVE_FATAL); + } + /* + * Since there is no character-set regulation for + * symlink name, do not report the conversion error + * in an automatic conversion. + */ + if (sconv != zip->sconv_utf8 || + (zip->entry->zip_flags & ZIP_UTF8_NAME) == 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Symlink cannot be converted " + "from %s to current locale.", + archive_string_conversion_charset_name( + sconv)); + ret = ARCHIVE_WARN; + } + } + zip_entry->uncompressed_size = zip_entry->compressed_size = 0; + + if (__archive_read_consume(a, linkname_length) < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Read error skipping symlink target name"); + return ARCHIVE_FATAL; + } + } else if (0 == (zip_entry->zip_flags & ZIP_LENGTH_AT_END) + || zip_entry->uncompressed_size > 0) { + /* Set the size only if it's meaningful. */ + archive_entry_set_size(entry, zip_entry->uncompressed_size); + } + zip->entry_bytes_remaining = zip_entry->compressed_size; + + /* If there's no body, force read_data() to return EOF immediately. */ + if (0 == (zip_entry->zip_flags & ZIP_LENGTH_AT_END) + && zip->entry_bytes_remaining < 1) + zip->end_of_entry = 1; + + /* Set up a more descriptive format name. */ + archive_string_sprintf(&zip->format_name, "ZIP %d.%d (%s)", + version / 10, version % 10, + compression_name(zip->entry->compression)); + a->archive.archive_format_name = zip->format_name.s; + + return (ret); +} + +static int +check_authentication_code(struct archive_read *a, const void *_p) +{ + struct zip *zip = (struct zip *)(a->format->data); + + /* Check authentication code. */ + if (zip->hctx_valid) { + const void *p; + uint8_t hmac[20]; + size_t hmac_len = 20; + int cmp; + + archive_hmac_sha1_final(&zip->hctx, hmac, &hmac_len); + if (_p == NULL) { + /* Read authentication code. */ + p = __archive_read_ahead(a, AUTH_CODE_SIZE, NULL); + if (p == NULL) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file data"); + return (ARCHIVE_FATAL); + } + } else { + p = _p; + } + cmp = memcmp(hmac, p, AUTH_CODE_SIZE); + __archive_read_consume(a, AUTH_CODE_SIZE); + if (cmp != 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "ZIP bad Authentication code"); + return (ARCHIVE_WARN); + } + } + return (ARCHIVE_OK); +} + +/* + * Read "uncompressed" data. There are three cases: + * 1) We know the size of the data. This is always true for the + * seeking reader (we've examined the Central Directory already). + * 2) ZIP_LENGTH_AT_END was set, but only the CRC was deferred. + * Info-ZIP seems to do this; we know the size but have to grab + * the CRC from the data descriptor afterwards. + * 3) We're streaming and ZIP_LENGTH_AT_END was specified and + * we have no size information. In this case, we can do pretty + * well by watching for the data descriptor record. The data + * descriptor is 16 bytes and includes a computed CRC that should + * provide a strong check. + * + * TODO: Technically, the PK\007\010 signature is optional. + * In the original spec, the data descriptor contained CRC + * and size fields but had no leading signature. In practice, + * newer writers seem to provide the signature pretty consistently. + * + * For uncompressed data, the PK\007\010 marker seems essential + * to be sure we've actually seen the end of the entry. + * + * Returns ARCHIVE_OK if successful, ARCHIVE_FATAL otherwise, sets + * zip->end_of_entry if it consumes all of the data. + */ +static int +zip_read_data_none(struct archive_read *a, const void **_buff, + size_t *size, int64_t *offset) +{ + struct zip *zip; + const char *buff; + ssize_t bytes_avail; + int r; + + (void)offset; /* UNUSED */ + + zip = (struct zip *)(a->format->data); + + if (zip->entry->zip_flags & ZIP_LENGTH_AT_END) { + const char *p; + ssize_t grabbing_bytes = 24; + + if (zip->hctx_valid) + grabbing_bytes += AUTH_CODE_SIZE; + /* Grab at least 24 bytes. */ + buff = __archive_read_ahead(a, grabbing_bytes, &bytes_avail); + if (bytes_avail < grabbing_bytes) { + /* Zip archives have end-of-archive markers + that are longer than this, so a failure to get at + least 24 bytes really does indicate a truncated + file. */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file data"); + return (ARCHIVE_FATAL); + } + /* Check for a complete PK\007\010 signature, followed + * by the correct 4-byte CRC. */ + p = buff; + if (zip->hctx_valid) + p += AUTH_CODE_SIZE; + if (p[0] == 'P' && p[1] == 'K' + && p[2] == '\007' && p[3] == '\010' + && (archive_le32dec(p + 4) == zip->entry_crc32 + || zip->ignore_crc32 + || (zip->hctx_valid + && zip->entry->aes_extra.vendor == AES_VENDOR_AE_2))) { + if (zip->entry->flags & LA_USED_ZIP64) { ++ uint64_t compressed, uncompressed; + zip->entry->crc32 = archive_le32dec(p + 4); - zip->entry->compressed_size = - archive_le64dec(p + 8); - zip->entry->uncompressed_size = - archive_le64dec(p + 16); ++ compressed = archive_le64dec(p + 8); ++ uncompressed = archive_le64dec(p + 16); ++ if (compressed > INT64_MAX || uncompressed > INT64_MAX) { ++ archive_set_error(&a->archive, ++ ARCHIVE_ERRNO_FILE_FORMAT, ++ "Overflow of 64-bit file sizes"); ++ return ARCHIVE_FAILED; ++ } ++ zip->entry->compressed_size = compressed; ++ zip->entry->uncompressed_size = uncompressed; + zip->unconsumed = 24; + } else { + zip->entry->crc32 = archive_le32dec(p + 4); + zip->entry->compressed_size = + archive_le32dec(p + 8); + zip->entry->uncompressed_size = + archive_le32dec(p + 12); + zip->unconsumed = 16; + } + if (zip->hctx_valid) { + r = check_authentication_code(a, buff); + if (r != ARCHIVE_OK) + return (r); + } + zip->end_of_entry = 1; + return (ARCHIVE_OK); + } + /* If not at EOF, ensure we consume at least one byte. */ + ++p; + + /* Scan forward until we see where a PK\007\010 signature + * might be. */ + /* Return bytes up until that point. On the next call, + * the code above will verify the data descriptor. */ + while (p < buff + bytes_avail - 4) { + if (p[3] == 'P') { p += 3; } + else if (p[3] == 'K') { p += 2; } + else if (p[3] == '\007') { p += 1; } + else if (p[3] == '\010' && p[2] == '\007' + && p[1] == 'K' && p[0] == 'P') { + if (zip->hctx_valid) + p -= AUTH_CODE_SIZE; + break; + } else { p += 4; } + } + bytes_avail = p - buff; + } else { + if (zip->entry_bytes_remaining == 0) { + zip->end_of_entry = 1; + if (zip->hctx_valid) { + r = check_authentication_code(a, NULL); + if (r != ARCHIVE_OK) + return (r); + } + return (ARCHIVE_OK); + } + /* Grab a bunch of bytes. */ + buff = __archive_read_ahead(a, 1, &bytes_avail); + if (bytes_avail <= 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file data"); + return (ARCHIVE_FATAL); + } + if (bytes_avail > zip->entry_bytes_remaining) + bytes_avail = (ssize_t)zip->entry_bytes_remaining; + } + if (zip->tctx_valid || zip->cctx_valid) { + size_t dec_size = bytes_avail; + + if (dec_size > zip->decrypted_buffer_size) + dec_size = zip->decrypted_buffer_size; + if (zip->tctx_valid) { + trad_enc_decrypt_update(&zip->tctx, + (const uint8_t *)buff, dec_size, + zip->decrypted_buffer, dec_size); + } else { + size_t dsize = dec_size; + archive_hmac_sha1_update(&zip->hctx, + (const uint8_t *)buff, dec_size); + archive_decrypto_aes_ctr_update(&zip->cctx, + (const uint8_t *)buff, dec_size, + zip->decrypted_buffer, &dsize); + } + bytes_avail = dec_size; + buff = (const char *)zip->decrypted_buffer; + } + *size = bytes_avail; + zip->entry_bytes_remaining -= bytes_avail; + zip->entry_uncompressed_bytes_read += bytes_avail; + zip->entry_compressed_bytes_read += bytes_avail; + zip->unconsumed += bytes_avail; + *_buff = buff; + return (ARCHIVE_OK); +} + +#ifdef HAVE_ZLIB_H +static int +zip_deflate_init(struct archive_read *a, struct zip *zip) +{ + int r; + + /* If we haven't yet read any data, initialize the decompressor. */ + if (!zip->decompress_init) { + if (zip->stream_valid) + r = inflateReset(&zip->stream); + else + r = inflateInit2(&zip->stream, + -15 /* Don't check for zlib header */); + if (r != Z_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can't initialize ZIP decompression."); + return (ARCHIVE_FATAL); + } + /* Stream structure has been set up. */ + zip->stream_valid = 1; + /* We've initialized decompression for this stream. */ + zip->decompress_init = 1; + } + return (ARCHIVE_OK); +} + +static int +zip_read_data_deflate(struct archive_read *a, const void **buff, + size_t *size, int64_t *offset) +{ + struct zip *zip; + ssize_t bytes_avail; + const void *compressed_buff, *sp; + int r; + + (void)offset; /* UNUSED */ + + zip = (struct zip *)(a->format->data); + + /* If the buffer hasn't been allocated, allocate it now. */ + if (zip->uncompressed_buffer == NULL) { + zip->uncompressed_buffer_size = 256 * 1024; + zip->uncompressed_buffer + = (unsigned char *)malloc(zip->uncompressed_buffer_size); + if (zip->uncompressed_buffer == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory for ZIP decompression"); + return (ARCHIVE_FATAL); + } + } + + r = zip_deflate_init(a, zip); + if (r != ARCHIVE_OK) + return (r); + + /* + * Note: '1' here is a performance optimization. + * Recall that the decompression layer returns a count of + * available bytes; asking for more than that forces the + * decompressor to combine reads by copying data. + */ + compressed_buff = sp = __archive_read_ahead(a, 1, &bytes_avail); + if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END) + && bytes_avail > zip->entry_bytes_remaining) { + bytes_avail = (ssize_t)zip->entry_bytes_remaining; + } - if (bytes_avail <= 0) { ++ if (bytes_avail < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file body"); + return (ARCHIVE_FATAL); + } + + if (zip->tctx_valid || zip->cctx_valid) { + if (zip->decrypted_bytes_remaining < (size_t)bytes_avail) { + size_t buff_remaining = + (zip->decrypted_buffer + zip->decrypted_buffer_size) + - (zip->decrypted_ptr + zip->decrypted_bytes_remaining); + + if (buff_remaining > (size_t)bytes_avail) + buff_remaining = (size_t)bytes_avail; + + if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END) && + zip->entry_bytes_remaining > 0) { + if ((int64_t)(zip->decrypted_bytes_remaining + + buff_remaining) + > zip->entry_bytes_remaining) { + if (zip->entry_bytes_remaining < + (int64_t)zip->decrypted_bytes_remaining) + buff_remaining = 0; + else + buff_remaining = + (size_t)zip->entry_bytes_remaining + - zip->decrypted_bytes_remaining; + } + } + if (buff_remaining > 0) { + if (zip->tctx_valid) { + trad_enc_decrypt_update(&zip->tctx, + compressed_buff, buff_remaining, + zip->decrypted_ptr + + zip->decrypted_bytes_remaining, + buff_remaining); + } else { + size_t dsize = buff_remaining; + archive_decrypto_aes_ctr_update( + &zip->cctx, + compressed_buff, buff_remaining, + zip->decrypted_ptr + + zip->decrypted_bytes_remaining, + &dsize); + } + zip->decrypted_bytes_remaining += buff_remaining; + } + } + bytes_avail = zip->decrypted_bytes_remaining; + compressed_buff = (const char *)zip->decrypted_ptr; + } + + /* + * A bug in zlib.h: stream.next_in should be marked 'const' + * but isn't (the library never alters data through the + * next_in pointer, only reads it). The result: this ugly + * cast to remove 'const'. + */ + zip->stream.next_in = (Bytef *)(uintptr_t)(const void *)compressed_buff; + zip->stream.avail_in = (uInt)bytes_avail; + zip->stream.total_in = 0; + zip->stream.next_out = zip->uncompressed_buffer; + zip->stream.avail_out = (uInt)zip->uncompressed_buffer_size; + zip->stream.total_out = 0; + + r = inflate(&zip->stream, 0); + switch (r) { + case Z_OK: + break; + case Z_STREAM_END: + zip->end_of_entry = 1; + break; + case Z_MEM_ERROR: + archive_set_error(&a->archive, ENOMEM, + "Out of memory for ZIP decompression"); + return (ARCHIVE_FATAL); + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "ZIP decompression failed (%d)", r); + return (ARCHIVE_FATAL); + } + + /* Consume as much as the compressor actually used. */ + bytes_avail = zip->stream.total_in; + if (zip->tctx_valid || zip->cctx_valid) { + zip->decrypted_bytes_remaining -= bytes_avail; + if (zip->decrypted_bytes_remaining == 0) + zip->decrypted_ptr = zip->decrypted_buffer; + else + zip->decrypted_ptr += bytes_avail; + } + /* Calculate compressed data as much as we used.*/ + if (zip->hctx_valid) + archive_hmac_sha1_update(&zip->hctx, sp, bytes_avail); + __archive_read_consume(a, bytes_avail); + zip->entry_bytes_remaining -= bytes_avail; + zip->entry_compressed_bytes_read += bytes_avail; + + *size = zip->stream.total_out; + zip->entry_uncompressed_bytes_read += zip->stream.total_out; + *buff = zip->uncompressed_buffer; + + if (zip->end_of_entry && zip->hctx_valid) { + r = check_authentication_code(a, NULL); + if (r != ARCHIVE_OK) + return (r); + } + + if (zip->end_of_entry && (zip->entry->zip_flags & ZIP_LENGTH_AT_END)) { + const char *p; + + if (NULL == (p = __archive_read_ahead(a, 24, NULL))) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP end-of-file record"); + return (ARCHIVE_FATAL); + } + /* Consume the optional PK\007\010 marker. */ + if (p[0] == 'P' && p[1] == 'K' && + p[2] == '\007' && p[3] == '\010') { + p += 4; + zip->unconsumed = 4; + } + if (zip->entry->flags & LA_USED_ZIP64) { ++ uint64_t compressed, uncompressed; + zip->entry->crc32 = archive_le32dec(p); - zip->entry->compressed_size = archive_le64dec(p + 4); - zip->entry->uncompressed_size = archive_le64dec(p + 12); ++ compressed = archive_le64dec(p + 4); ++ uncompressed = archive_le64dec(p + 12); ++ if (compressed > INT64_MAX || uncompressed > INT64_MAX) { ++ archive_set_error(&a->archive, ++ ARCHIVE_ERRNO_FILE_FORMAT, ++ "Overflow of 64-bit file sizes"); ++ return ARCHIVE_FAILED; ++ } ++ zip->entry->compressed_size = compressed; ++ zip->entry->uncompressed_size = uncompressed; + zip->unconsumed += 20; + } else { + zip->entry->crc32 = archive_le32dec(p); + zip->entry->compressed_size = archive_le32dec(p + 4); + zip->entry->uncompressed_size = archive_le32dec(p + 8); + zip->unconsumed += 12; + } + } + + return (ARCHIVE_OK); +} +#endif + +static int +read_decryption_header(struct archive_read *a) +{ + struct zip *zip = (struct zip *)(a->format->data); + const char *p; + unsigned int remaining_size; + unsigned int ts; + + /* + * Read an initialization vector data field. + */ + p = __archive_read_ahead(a, 2, NULL); + if (p == NULL) + goto truncated; + ts = zip->iv_size; + zip->iv_size = archive_le16dec(p); + __archive_read_consume(a, 2); + if (ts < zip->iv_size) { + free(zip->iv); + zip->iv = NULL; + } + p = __archive_read_ahead(a, zip->iv_size, NULL); + if (p == NULL) + goto truncated; + if (zip->iv == NULL) { + zip->iv = malloc(zip->iv_size); + if (zip->iv == NULL) + goto nomem; + } + memcpy(zip->iv, p, zip->iv_size); + __archive_read_consume(a, zip->iv_size); + + /* + * Read a size of remaining decryption header field. + */ + p = __archive_read_ahead(a, 14, NULL); + if (p == NULL) + goto truncated; + remaining_size = archive_le32dec(p); + if (remaining_size < 16 || remaining_size > (1 << 18)) + goto corrupted; + + /* Check if format version is supported. */ + if (archive_le16dec(p+4) != 3) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Unsupported encryption format version: %u", + archive_le16dec(p+4)); + return (ARCHIVE_FAILED); + } + + /* + * Read an encryption algorithm field. + */ + zip->alg_id = archive_le16dec(p+6); + switch (zip->alg_id) { + case 0x6601:/* DES */ + case 0x6602:/* RC2 */ + case 0x6603:/* 3DES 168 */ + case 0x6609:/* 3DES 112 */ + case 0x660E:/* AES 128 */ + case 0x660F:/* AES 192 */ + case 0x6610:/* AES 256 */ + case 0x6702:/* RC2 (version >= 5.2) */ + case 0x6720:/* Blowfish */ + case 0x6721:/* Twofish */ + case 0x6801:/* RC4 */ - /* Suuported encryption algorithm. */ ++ /* Supported encryption algorithm. */ + break; + default: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Unknown encryption algorithm: %u", zip->alg_id); + return (ARCHIVE_FAILED); + } + + /* + * Read a bit length field. + */ + zip->bit_len = archive_le16dec(p+8); + + /* + * Read a flags field. + */ + zip->flags = archive_le16dec(p+10); + switch (zip->flags & 0xf000) { + case 0x0001: /* Password is required to decrypt. */ + case 0x0002: /* Certificates only. */ + case 0x0003: /* Password or certificate required to decrypt. */ + break; + default: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Unknown encryption flag: %u", zip->flags); + return (ARCHIVE_FAILED); + } + if ((zip->flags & 0xf000) == 0 || + (zip->flags & 0xf000) == 0x4000) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Unknown encryption flag: %u", zip->flags); + return (ARCHIVE_FAILED); + } + + /* + * Read an encrypted random data field. + */ + ts = zip->erd_size; + zip->erd_size = archive_le16dec(p+12); + __archive_read_consume(a, 14); + if ((zip->erd_size & 0xf) != 0 || + (zip->erd_size + 16) > remaining_size || + (zip->erd_size + 16) < zip->erd_size) + goto corrupted; + + if (ts < zip->erd_size) { + free(zip->erd); + zip->erd = NULL; + } + p = __archive_read_ahead(a, zip->erd_size, NULL); + if (p == NULL) + goto truncated; + if (zip->erd == NULL) { + zip->erd = malloc(zip->erd_size); + if (zip->erd == NULL) + goto nomem; + } + memcpy(zip->erd, p, zip->erd_size); + __archive_read_consume(a, zip->erd_size); + + /* + * Read a reserved data field. + */ + p = __archive_read_ahead(a, 4, NULL); + if (p == NULL) + goto truncated; + /* Reserved data size should be zero. */ + if (archive_le32dec(p) != 0) + goto corrupted; + __archive_read_consume(a, 4); + + /* + * Read a password validation data field. + */ + p = __archive_read_ahead(a, 2, NULL); + if (p == NULL) + goto truncated; + ts = zip->v_size; + zip->v_size = archive_le16dec(p); + __archive_read_consume(a, 2); + if ((zip->v_size & 0x0f) != 0 || + (zip->erd_size + zip->v_size + 16) > remaining_size || + (zip->erd_size + zip->v_size + 16) < (zip->erd_size + zip->v_size)) + goto corrupted; + if (ts < zip->v_size) { + free(zip->v_data); + zip->v_data = NULL; + } + p = __archive_read_ahead(a, zip->v_size, NULL); + if (p == NULL) + goto truncated; + if (zip->v_data == NULL) { + zip->v_data = malloc(zip->v_size); + if (zip->v_data == NULL) + goto nomem; + } + memcpy(zip->v_data, p, zip->v_size); + __archive_read_consume(a, zip->v_size); + + p = __archive_read_ahead(a, 4, NULL); + if (p == NULL) + goto truncated; + zip->v_crc32 = archive_le32dec(p); + __archive_read_consume(a, 4); + + /*return (ARCHIVE_OK); - * This is not fully implemnted yet.*/ ++ * This is not fully implemented yet.*/ + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Encrypted file is unsupported"); + return (ARCHIVE_FAILED); +truncated: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file data"); + return (ARCHIVE_FATAL); +corrupted: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Corrupted ZIP file data"); + return (ARCHIVE_FATAL); +nomem: + archive_set_error(&a->archive, ENOMEM, + "No memory for ZIP decryption"); + return (ARCHIVE_FATAL); +} + +static int +zip_alloc_decryption_buffer(struct archive_read *a) +{ + struct zip *zip = (struct zip *)(a->format->data); + size_t bs = 256 * 1024; + + if (zip->decrypted_buffer == NULL) { + zip->decrypted_buffer_size = bs; + zip->decrypted_buffer = malloc(bs); + if (zip->decrypted_buffer == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory for ZIP decryption"); + return (ARCHIVE_FATAL); + } + } + zip->decrypted_ptr = zip->decrypted_buffer; + return (ARCHIVE_OK); +} + +static int +init_traditional_PKWARE_decryption(struct archive_read *a) +{ + struct zip *zip = (struct zip *)(a->format->data); + const void *p; + int retry; + int r; + + if (zip->tctx_valid) + return (ARCHIVE_OK); + + /* + Read the 12 bytes encryption header stored at + the start of the data area. + */ +#define ENC_HEADER_SIZE 12 + if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END) + && zip->entry_bytes_remaining < ENC_HEADER_SIZE) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated Zip encrypted body: only %jd bytes available", + (intmax_t)zip->entry_bytes_remaining); + return (ARCHIVE_FATAL); + } + + p = __archive_read_ahead(a, ENC_HEADER_SIZE, NULL); + if (p == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file data"); + return (ARCHIVE_FATAL); + } + + for (retry = 0;; retry++) { + const char *passphrase; + uint8_t crcchk; + + passphrase = __archive_read_next_passphrase(a); + if (passphrase == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + (retry > 0)? + "Incorrect passphrase": + "Passphrase required for this entry"); + return (ARCHIVE_FAILED); + } + + /* - * Initialize ctx for Traditional PKWARE Decyption. ++ * Initialize ctx for Traditional PKWARE Decryption. + */ + r = trad_enc_init(&zip->tctx, passphrase, strlen(passphrase), + p, ENC_HEADER_SIZE, &crcchk); + if (r == 0 && crcchk == zip->entry->decdat) + break;/* The passphrase is OK. */ + if (retry > 10000) { + /* Avoid infinity loop. */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Too many incorrect passphrases"); + return (ARCHIVE_FAILED); + } + } + + __archive_read_consume(a, ENC_HEADER_SIZE); + zip->tctx_valid = 1; + if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END)) { + zip->entry_bytes_remaining -= ENC_HEADER_SIZE; + } + /*zip->entry_uncompressed_bytes_read += ENC_HEADER_SIZE;*/ + zip->entry_compressed_bytes_read += ENC_HEADER_SIZE; + zip->decrypted_bytes_remaining = 0; + + return (zip_alloc_decryption_buffer(a)); +#undef ENC_HEADER_SIZE +} + +static int +init_WinZip_AES_decryption(struct archive_read *a) +{ + struct zip *zip = (struct zip *)(a->format->data); + const void *p; + const uint8_t *pv; + size_t key_len, salt_len; + uint8_t derived_key[MAX_DERIVED_KEY_BUF_SIZE]; + int retry; + int r; + + if (zip->cctx_valid || zip->hctx_valid) + return (ARCHIVE_OK); + + switch (zip->entry->aes_extra.strength) { + case 1: salt_len = 8; key_len = 16; break; + case 2: salt_len = 12; key_len = 24; break; + case 3: salt_len = 16; key_len = 32; break; + default: goto corrupted; + } + p = __archive_read_ahead(a, salt_len + 2, NULL); + if (p == NULL) + goto truncated; + + for (retry = 0;; retry++) { + const char *passphrase; + + passphrase = __archive_read_next_passphrase(a); + if (passphrase == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + (retry > 0)? + "Incorrect passphrase": + "Passphrase required for this entry"); + return (ARCHIVE_FAILED); + } + memset(derived_key, 0, sizeof(derived_key)); + r = archive_pbkdf2_sha1(passphrase, strlen(passphrase), + p, salt_len, 1000, derived_key, key_len * 2 + 2); + if (r != 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Decryption is unsupported due to lack of " + "crypto library"); + return (ARCHIVE_FAILED); + } + + /* Check password verification value. */ + pv = ((const uint8_t *)p) + salt_len; + if (derived_key[key_len * 2] == pv[0] && + derived_key[key_len * 2 + 1] == pv[1]) + break;/* The passphrase is OK. */ + if (retry > 10000) { + /* Avoid infinity loop. */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Too many incorrect passphrases"); + return (ARCHIVE_FAILED); + } + } + + r = archive_decrypto_aes_ctr_init(&zip->cctx, derived_key, key_len); + if (r != 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Decryption is unsupported due to lack of crypto library"); + return (ARCHIVE_FAILED); + } + r = archive_hmac_sha1_init(&zip->hctx, derived_key + key_len, key_len); + if (r != 0) { + archive_decrypto_aes_ctr_release(&zip->cctx); + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to initialize HMAC-SHA1"); + return (ARCHIVE_FAILED); + } + zip->cctx_valid = zip->hctx_valid = 1; + __archive_read_consume(a, salt_len + 2); + zip->entry_bytes_remaining -= salt_len + 2 + AUTH_CODE_SIZE; + if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END) + && zip->entry_bytes_remaining < 0) + goto corrupted; + zip->entry_compressed_bytes_read += salt_len + 2 + AUTH_CODE_SIZE; + zip->decrypted_bytes_remaining = 0; + + zip->entry->compression = zip->entry->aes_extra.compression; + return (zip_alloc_decryption_buffer(a)); + +truncated: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file data"); + return (ARCHIVE_FATAL); +corrupted: + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Corrupted ZIP file data"); + return (ARCHIVE_FATAL); +} + +static int +archive_read_format_zip_read_data(struct archive_read *a, + const void **buff, size_t *size, int64_t *offset) +{ + int r; + struct zip *zip = (struct zip *)(a->format->data); + + if (zip->has_encrypted_entries == + ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) { + zip->has_encrypted_entries = 0; + } + + *offset = zip->entry_uncompressed_bytes_read; + *size = 0; + *buff = NULL; + + /* If we hit end-of-entry last time, return ARCHIVE_EOF. */ + if (zip->end_of_entry) + return (ARCHIVE_EOF); + + /* Return EOF immediately if this is a non-regular file. */ + if (AE_IFREG != (zip->entry->mode & AE_IFMT)) + return (ARCHIVE_EOF); + + __archive_read_consume(a, zip->unconsumed); + zip->unconsumed = 0; + + if (zip->init_decryption) { + zip->has_encrypted_entries = 1; + if (zip->entry->zip_flags & ZIP_STRONG_ENCRYPTED) + r = read_decryption_header(a); + else if (zip->entry->compression == WINZIP_AES_ENCRYPTION) + r = init_WinZip_AES_decryption(a); + else + r = init_traditional_PKWARE_decryption(a); + if (r != ARCHIVE_OK) + return (r); + zip->init_decryption = 0; + } + + switch(zip->entry->compression) { + case 0: /* No compression. */ + r = zip_read_data_none(a, buff, size, offset); + break; +#ifdef HAVE_ZLIB_H + case 8: /* Deflate compression. */ + r = zip_read_data_deflate(a, buff, size, offset); + break; +#endif + default: /* Unsupported compression. */ + /* Return a warning. */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Unsupported ZIP compression method (%s)", + compression_name(zip->entry->compression)); + /* We can't decompress this entry, but we will + * be able to skip() it and try the next entry. */ + return (ARCHIVE_FAILED); + break; + } + if (r != ARCHIVE_OK) + return (r); + /* Update checksum */ + if (*size) + zip->entry_crc32 = zip->crc32func(zip->entry_crc32, *buff, + (unsigned)*size); + /* If we hit the end, swallow any end-of-data marker. */ + if (zip->end_of_entry) { + /* Check file size, CRC against these values. */ + if (zip->entry->compressed_size != + zip->entry_compressed_bytes_read) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "ZIP compressed data is wrong size " + "(read %jd, expected %jd)", + (intmax_t)zip->entry_compressed_bytes_read, + (intmax_t)zip->entry->compressed_size); + return (ARCHIVE_WARN); + } + /* Size field only stores the lower 32 bits of the actual + * size. */ + if ((zip->entry->uncompressed_size & UINT32_MAX) + != (zip->entry_uncompressed_bytes_read & UINT32_MAX)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "ZIP uncompressed data is wrong size " + "(read %jd, expected %jd)\n", + (intmax_t)zip->entry_uncompressed_bytes_read, + (intmax_t)zip->entry->uncompressed_size); + return (ARCHIVE_WARN); + } + /* Check computed CRC against header */ + if ((!zip->hctx_valid || + zip->entry->aes_extra.vendor != AES_VENDOR_AE_2) && + zip->entry->crc32 != zip->entry_crc32 + && !zip->ignore_crc32) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "ZIP bad CRC: 0x%lx should be 0x%lx", + (unsigned long)zip->entry_crc32, + (unsigned long)zip->entry->crc32); + return (ARCHIVE_WARN); + } + } + + return (ARCHIVE_OK); +} + +static int +archive_read_format_zip_cleanup(struct archive_read *a) +{ + struct zip *zip; + struct zip_entry *zip_entry, *next_zip_entry; + + zip = (struct zip *)(a->format->data); +#ifdef HAVE_ZLIB_H + if (zip->stream_valid) + inflateEnd(&zip->stream); + free(zip->uncompressed_buffer); +#endif + if (zip->zip_entries) { + zip_entry = zip->zip_entries; + while (zip_entry != NULL) { + next_zip_entry = zip_entry->next; + archive_string_free(&zip_entry->rsrcname); + free(zip_entry); + zip_entry = next_zip_entry; + } + } + free(zip->decrypted_buffer); + if (zip->cctx_valid) + archive_decrypto_aes_ctr_release(&zip->cctx); + if (zip->hctx_valid) + archive_hmac_sha1_cleanup(&zip->hctx); + free(zip->iv); + free(zip->erd); + free(zip->v_data); + archive_string_free(&zip->format_name); + free(zip); + (a->format->data) = NULL; + return (ARCHIVE_OK); +} + +static int +archive_read_format_zip_has_encrypted_entries(struct archive_read *_a) +{ + if (_a && _a->format) { + struct zip * zip = (struct zip *)_a->format->data; + if (zip) { + return zip->has_encrypted_entries; + } + } + return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW; +} + +static int +archive_read_format_zip_options(struct archive_read *a, + const char *key, const char *val) +{ + struct zip *zip; + int ret = ARCHIVE_FAILED; + + zip = (struct zip *)(a->format->data); + if (strcmp(key, "compat-2x") == 0) { + /* Handle filenames as libarchive 2.x */ + zip->init_default_conversion = (val != NULL) ? 1 : 0; + return (ARCHIVE_OK); + } else if (strcmp(key, "hdrcharset") == 0) { + if (val == NULL || val[0] == 0) + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "zip: hdrcharset option needs a character-set name" + ); + else { + zip->sconv = archive_string_conversion_from_charset( + &a->archive, val, 0); + if (zip->sconv != NULL) { + if (strcmp(val, "UTF-8") == 0) + zip->sconv_utf8 = zip->sconv; + ret = ARCHIVE_OK; + } else + ret = ARCHIVE_FATAL; + } + return (ret); + } else if (strcmp(key, "ignorecrc32") == 0) { + /* Mostly useful for testing. */ + if (val == NULL || val[0] == 0) { + zip->crc32func = real_crc32; + zip->ignore_crc32 = 0; + } else { + zip->crc32func = fake_crc32; + zip->ignore_crc32 = 1; + } + return (ARCHIVE_OK); + } else if (strcmp(key, "mac-ext") == 0) { + zip->process_mac_extensions = (val != NULL && val[0] != 0); + return (ARCHIVE_OK); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +int +archive_read_support_format_zip(struct archive *a) +{ + int r; + r = archive_read_support_format_zip_streamable(a); + if (r != ARCHIVE_OK) + return r; + return (archive_read_support_format_zip_seekable(a)); +} + +/* ------------------------------------------------------------------------ */ + +/* + * Streaming-mode support + */ + + +static int +archive_read_support_format_zip_capabilities_streamable(struct archive_read * a) +{ + (void)a; /* UNUSED */ + return (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA | + ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA); +} + +static int +archive_read_format_zip_streamable_bid(struct archive_read *a, int best_bid) +{ + const char *p; + + (void)best_bid; /* UNUSED */ + + if ((p = __archive_read_ahead(a, 4, NULL)) == NULL) + return (-1); + + /* + * Bid of 29 here comes from: + * + 16 bits for "PK", + * + next 16-bit field has 6 options so contributes + * about 16 - log_2(6) ~= 16 - 2.6 ~= 13 bits + * + * So we've effectively verified ~29 total bits of check data. + */ + if (p[0] == 'P' && p[1] == 'K') { + if ((p[2] == '\001' && p[3] == '\002') + || (p[2] == '\003' && p[3] == '\004') + || (p[2] == '\005' && p[3] == '\006') + || (p[2] == '\006' && p[3] == '\006') + || (p[2] == '\007' && p[3] == '\010') + || (p[2] == '0' && p[3] == '0')) + return (29); + } + + /* TODO: It's worth looking ahead a little bit for a valid + * PK signature. In particular, that would make it possible + * to read some UUEncoded SFX files or SFX files coming from + * a network socket. */ + + return (0); +} + +static int +archive_read_format_zip_streamable_read_header(struct archive_read *a, + struct archive_entry *entry) +{ + struct zip *zip; + + a->archive.archive_format = ARCHIVE_FORMAT_ZIP; + if (a->archive.archive_format_name == NULL) + a->archive.archive_format_name = "ZIP"; + + zip = (struct zip *)(a->format->data); + + /* + * It should be sufficient to call archive_read_next_header() for + * a reader to determine if an entry is encrypted or not. If the + * encryption of an entry is only detectable when calling + * archive_read_data(), so be it. We'll do the same check there + * as well. + */ + if (zip->has_encrypted_entries == + ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) + zip->has_encrypted_entries = 0; + + /* Make sure we have a zip_entry structure to use. */ + if (zip->zip_entries == NULL) { + zip->zip_entries = malloc(sizeof(struct zip_entry)); + if (zip->zip_entries == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Out of memory"); + return ARCHIVE_FATAL; + } + } + zip->entry = zip->zip_entries; + memset(zip->entry, 0, sizeof(struct zip_entry)); + + if (zip->cctx_valid) + archive_decrypto_aes_ctr_release(&zip->cctx); + if (zip->hctx_valid) + archive_hmac_sha1_cleanup(&zip->hctx); + zip->tctx_valid = zip->cctx_valid = zip->hctx_valid = 0; + __archive_read_reset_passphrase(a); + + /* Search ahead for the next local file header. */ + __archive_read_consume(a, zip->unconsumed); + zip->unconsumed = 0; + for (;;) { + int64_t skipped = 0; + const char *p, *end; + ssize_t bytes; + + p = __archive_read_ahead(a, 4, &bytes); + if (p == NULL) + return (ARCHIVE_FATAL); + end = p + bytes; + + while (p + 4 <= end) { + if (p[0] == 'P' && p[1] == 'K') { + if (p[2] == '\003' && p[3] == '\004') { + /* Regular file entry. */ + __archive_read_consume(a, skipped); + return zip_read_local_file_header(a, + entry, zip); + } + + /* + * TODO: We cannot restore permissions + * based only on the local file headers. + * Consider scanning the central + * directory and returning additional + * entries for at least directories. + * This would allow us to properly set + * directory permissions. + * + * This won't help us fix symlinks + * and may not help with regular file + * permissions, either. + */ + if (p[2] == '\001' && p[3] == '\002') { + return (ARCHIVE_EOF); + } + + /* End of central directory? Must be an + * empty archive. */ + if ((p[2] == '\005' && p[3] == '\006') + || (p[2] == '\006' && p[3] == '\006')) + return (ARCHIVE_EOF); + } + ++p; + ++skipped; + } + __archive_read_consume(a, skipped); + } +} + +static int +archive_read_format_zip_read_data_skip_streamable(struct archive_read *a) +{ + struct zip *zip; + int64_t bytes_skipped; + + zip = (struct zip *)(a->format->data); + bytes_skipped = __archive_read_consume(a, zip->unconsumed); + zip->unconsumed = 0; + if (bytes_skipped < 0) + return (ARCHIVE_FATAL); + + /* If we've already read to end of data, we're done. */ + if (zip->end_of_entry) + return (ARCHIVE_OK); + + /* So we know we're streaming... */ + if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END) + || zip->entry->compressed_size > 0) { + /* We know the compressed length, so we can just skip. */ + bytes_skipped = __archive_read_consume(a, + zip->entry_bytes_remaining); + if (bytes_skipped < 0) + return (ARCHIVE_FATAL); + return (ARCHIVE_OK); + } + + if (zip->init_decryption) { + int r; + + zip->has_encrypted_entries = 1; + if (zip->entry->zip_flags & ZIP_STRONG_ENCRYPTED) + r = read_decryption_header(a); + else if (zip->entry->compression == WINZIP_AES_ENCRYPTION) + r = init_WinZip_AES_decryption(a); + else + r = init_traditional_PKWARE_decryption(a); + if (r != ARCHIVE_OK) + return (r); + zip->init_decryption = 0; + } + + /* We're streaming and we don't know the length. */ + /* If the body is compressed and we know the format, we can + * find an exact end-of-entry by decompressing it. */ + switch (zip->entry->compression) { +#ifdef HAVE_ZLIB_H + case 8: /* Deflate compression. */ + while (!zip->end_of_entry) { + int64_t offset = 0; + const void *buff = NULL; + size_t size = 0; + int r; + r = zip_read_data_deflate(a, &buff, &size, &offset); + if (r != ARCHIVE_OK) + return (r); + } + return ARCHIVE_OK; +#endif + default: /* Uncompressed or unknown. */ + /* Scan for a PK\007\010 signature. */ + for (;;) { + const char *p, *buff; + ssize_t bytes_avail; + buff = __archive_read_ahead(a, 16, &bytes_avail); + if (bytes_avail < 16) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file data"); + return (ARCHIVE_FATAL); + } + p = buff; + while (p <= buff + bytes_avail - 16) { + if (p[3] == 'P') { p += 3; } + else if (p[3] == 'K') { p += 2; } + else if (p[3] == '\007') { p += 1; } + else if (p[3] == '\010' && p[2] == '\007' + && p[1] == 'K' && p[0] == 'P') { + if (zip->entry->flags & LA_USED_ZIP64) + __archive_read_consume(a, + p - buff + 24); + else + __archive_read_consume(a, + p - buff + 16); + return ARCHIVE_OK; + } else { p += 4; } + } + __archive_read_consume(a, p - buff); + } + } +} + +int +archive_read_support_format_zip_streamable(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct zip *zip; + int r; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_format_zip"); + + zip = (struct zip *)calloc(1, sizeof(*zip)); + if (zip == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate zip data"); + return (ARCHIVE_FATAL); + } + + /* Streamable reader doesn't support mac extensions. */ + zip->process_mac_extensions = 0; + + /* + * Until enough data has been read, we cannot tell about + * any encrypted entries yet. + */ + zip->has_encrypted_entries = ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW; + zip->crc32func = real_crc32; + + r = __archive_read_register_format(a, + zip, + "zip", + archive_read_format_zip_streamable_bid, + archive_read_format_zip_options, + archive_read_format_zip_streamable_read_header, + archive_read_format_zip_read_data, + archive_read_format_zip_read_data_skip_streamable, + NULL, + archive_read_format_zip_cleanup, + archive_read_support_format_zip_capabilities_streamable, + archive_read_format_zip_has_encrypted_entries); + + if (r != ARCHIVE_OK) + free(zip); + return (ARCHIVE_OK); +} + +/* ------------------------------------------------------------------------ */ + +/* + * Seeking-mode support + */ + +static int +archive_read_support_format_zip_capabilities_seekable(struct archive_read * a) +{ + (void)a; /* UNUSED */ + return (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA | + ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA); +} + +/* + * TODO: This is a performance sink because it forces the read core to + * drop buffered data from the start of file, which will then have to + * be re-read again if this bidder loses. + * + * We workaround this a little by passing in the best bid so far so + * that later bidders can do nothing if they know they'll never + * outbid. But we can certainly do better... + */ +static int +read_eocd(struct zip *zip, const char *p, int64_t current_offset) +{ + /* Sanity-check the EOCD we've found. */ + + /* This must be the first volume. */ + if (archive_le16dec(p + 4) != 0) + return 0; + /* Central directory must be on this volume. */ + if (archive_le16dec(p + 4) != archive_le16dec(p + 6)) + return 0; + /* All central directory entries must be on this volume. */ + if (archive_le16dec(p + 10) != archive_le16dec(p + 8)) + return 0; + /* Central directory can't extend beyond start of EOCD record. */ + if (archive_le32dec(p + 16) + archive_le32dec(p + 12) + > current_offset) + return 0; + + /* Save the central directory location for later use. */ + zip->central_directory_offset = archive_le32dec(p + 16); + + /* This is just a tiny bit higher than the maximum + returned by the streaming Zip bidder. This ensures + that the more accurate seeking Zip parser wins + whenever seek is available. */ + return 32; +} + +/* + * Examine Zip64 EOCD locator: If it's valid, store the information + * from it. + */ +static void +read_zip64_eocd(struct archive_read *a, struct zip *zip, const char *p) +{ + int64_t eocd64_offset; + int64_t eocd64_size; + + /* Sanity-check the locator record. */ + + /* Central dir must be on first volume. */ + if (archive_le32dec(p + 4) != 0) + return; + /* Must be only a single volume. */ + if (archive_le32dec(p + 16) != 1) + return; + + /* Find the Zip64 EOCD record. */ + eocd64_offset = archive_le64dec(p + 8); + if (__archive_read_seek(a, eocd64_offset, SEEK_SET) < 0) + return; + if ((p = __archive_read_ahead(a, 56, NULL)) == NULL) + return; + /* Make sure we can read all of it. */ + eocd64_size = archive_le64dec(p + 4) + 12; + if (eocd64_size < 56 || eocd64_size > 16384) + return; + if ((p = __archive_read_ahead(a, (size_t)eocd64_size, NULL)) == NULL) + return; + + /* Sanity-check the EOCD64 */ + if (archive_le32dec(p + 16) != 0) /* Must be disk #0 */ + return; + if (archive_le32dec(p + 20) != 0) /* CD must be on disk #0 */ + return; + /* CD can't be split. */ + if (archive_le64dec(p + 24) != archive_le64dec(p + 32)) + return; + + /* Save the central directory offset for later use. */ + zip->central_directory_offset = archive_le64dec(p + 48); +} + +static int +archive_read_format_zip_seekable_bid(struct archive_read *a, int best_bid) +{ + struct zip *zip = (struct zip *)a->format->data; + int64_t file_size, current_offset; + const char *p; + int i, tail; + + /* If someone has already bid more than 32, then avoid + trashing the look-ahead buffers with a seek. */ + if (best_bid > 32) + return (-1); + + file_size = __archive_read_seek(a, 0, SEEK_END); + if (file_size <= 0) + return 0; + + /* Search last 16k of file for end-of-central-directory + * record (which starts with PK\005\006) */ + tail = (int)zipmin(1024 * 16, file_size); + current_offset = __archive_read_seek(a, -tail, SEEK_END); + if (current_offset < 0) + return 0; + if ((p = __archive_read_ahead(a, (size_t)tail, NULL)) == NULL) + return 0; + /* Boyer-Moore search backwards from the end, since we want + * to match the last EOCD in the file (there can be more than + * one if there is an uncompressed Zip archive as a member + * within this Zip archive). */ + for (i = tail - 22; i > 0;) { + switch (p[i]) { + case 'P': + 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); + } + } + i -= 4; + break; + case 'K': i -= 1; break; + case 005: i -= 2; break; + case 006: i -= 3; break; + default: i -= 4; break; + } + } + return 0; +} + +/* The red-black trees are only used in seeking mode to manage + * the in-memory copy of the central directory. */ + +static int +cmp_node(const struct archive_rb_node *n1, const struct archive_rb_node *n2) +{ + const struct zip_entry *e1 = (const struct zip_entry *)n1; + const struct zip_entry *e2 = (const struct zip_entry *)n2; + + if (e1->local_header_offset > e2->local_header_offset) + return -1; + if (e1->local_header_offset < e2->local_header_offset) + return 1; + return 0; +} + +static int +cmp_key(const struct archive_rb_node *n, const void *key) +{ + /* This function won't be called */ + (void)n; /* UNUSED */ + (void)key; /* UNUSED */ + return 1; +} + +static const struct archive_rb_tree_ops rb_ops = { + &cmp_node, &cmp_key +}; + +static int +rsrc_cmp_node(const struct archive_rb_node *n1, + const struct archive_rb_node *n2) +{ + const struct zip_entry *e1 = (const struct zip_entry *)n1; + const struct zip_entry *e2 = (const struct zip_entry *)n2; + + return (strcmp(e2->rsrcname.s, e1->rsrcname.s)); +} + +static int +rsrc_cmp_key(const struct archive_rb_node *n, const void *key) +{ + const struct zip_entry *e = (const struct zip_entry *)n; + return (strcmp((const char *)key, e->rsrcname.s)); +} + +static const struct archive_rb_tree_ops rb_rsrc_ops = { + &rsrc_cmp_node, &rsrc_cmp_key +}; + +static const char * +rsrc_basename(const char *name, size_t name_length) +{ + const char *s, *r; + + r = s = name; + for (;;) { + s = memchr(s, '/', name_length - (s - name)); + if (s == NULL) + break; + r = ++s; + } + return (r); +} + +static void +expose_parent_dirs(struct zip *zip, const char *name, size_t name_length) +{ + struct archive_string str; + struct zip_entry *dir; + char *s; + + archive_string_init(&str); + archive_strncpy(&str, name, name_length); + for (;;) { + s = strrchr(str.s, '/'); + if (s == NULL) + break; + *s = '\0'; + /* Transfer the parent directory from zip->tree_rsrc RB + * tree to zip->tree RB tree to expose. */ + dir = (struct zip_entry *) + __archive_rb_tree_find_node(&zip->tree_rsrc, str.s); + if (dir == NULL) + break; + __archive_rb_tree_remove_node(&zip->tree_rsrc, &dir->node); + archive_string_free(&dir->rsrcname); + __archive_rb_tree_insert_node(&zip->tree, &dir->node); + } + archive_string_free(&str); +} + +static int +slurp_central_directory(struct archive_read *a, struct zip *zip) +{ + ssize_t i; + unsigned found; + int64_t correction; + ssize_t bytes_avail; + const char *p; + + /* + * Find the start of the central directory. The end-of-CD + * record has our starting point, but there are lots of + * Zip archives which have had other data prepended to the + * file, which makes the recorded offsets all too small. + * So we search forward from the specified offset until we + * find the real start of the central directory. Then we + * know the correction we need to apply to account for leading + * padding. + */ + if (__archive_read_seek(a, zip->central_directory_offset, SEEK_SET) < 0) + return ARCHIVE_FATAL; + + found = 0; + while (!found) { + if ((p = __archive_read_ahead(a, 20, &bytes_avail)) == NULL) + return ARCHIVE_FATAL; + for (found = 0, i = 0; !found && i < bytes_avail - 4;) { + switch (p[i + 3]) { + case 'P': i += 3; break; + case 'K': i += 2; break; + case 001: i += 1; break; + case 002: + if (memcmp(p + i, "PK\001\002", 4) == 0) { + p += i; + found = 1; + } else + i += 4; + break; + case 005: i += 1; break; + case 006: + if (memcmp(p + i, "PK\005\006", 4) == 0) { + p += i; + found = 1; + } else if (memcmp(p + i, "PK\006\006", 4) == 0) { + p += i; + found = 1; + } else + i += 1; + break; + default: i += 4; break; + } + } + __archive_read_consume(a, i); + } + correction = archive_filter_bytes(&a->archive, 0) + - zip->central_directory_offset; + + __archive_rb_tree_init(&zip->tree, &rb_ops); + __archive_rb_tree_init(&zip->tree_rsrc, &rb_rsrc_ops); + + zip->central_directory_entries_total = 0; + while (1) { + struct zip_entry *zip_entry; + size_t filename_length, extra_length, comment_length; + uint32_t external_attributes; + const char *name, *r; + + if ((p = __archive_read_ahead(a, 4, NULL)) == NULL) + return ARCHIVE_FATAL; + if (memcmp(p, "PK\006\006", 4) == 0 + || memcmp(p, "PK\005\006", 4) == 0) { + break; + } else if (memcmp(p, "PK\001\002", 4) != 0) { + archive_set_error(&a->archive, + -1, "Invalid central directory signature"); + return ARCHIVE_FATAL; + } + if ((p = __archive_read_ahead(a, 46, NULL)) == NULL) + return ARCHIVE_FATAL; + + zip_entry = calloc(1, sizeof(struct zip_entry)); + zip_entry->next = zip->zip_entries; + zip_entry->flags |= LA_FROM_CENTRAL_DIRECTORY; + zip->zip_entries = zip_entry; + zip->central_directory_entries_total++; + + /* version = p[4]; */ + zip_entry->system = p[5]; + /* version_required = archive_le16dec(p + 6); */ + zip_entry->zip_flags = archive_le16dec(p + 8); + if (zip_entry->zip_flags + & (ZIP_ENCRYPTED | ZIP_STRONG_ENCRYPTED)){ + zip->has_encrypted_entries = 1; + } + zip_entry->compression = (char)archive_le16dec(p + 10); + zip_entry->mtime = zip_time(p + 12); + zip_entry->crc32 = archive_le32dec(p + 16); + if (zip_entry->zip_flags & ZIP_LENGTH_AT_END) + zip_entry->decdat = p[13]; + else + zip_entry->decdat = p[19]; + zip_entry->compressed_size = archive_le32dec(p + 20); + zip_entry->uncompressed_size = archive_le32dec(p + 24); + filename_length = archive_le16dec(p + 28); + extra_length = archive_le16dec(p + 30); + comment_length = archive_le16dec(p + 32); + /* disk_start = archive_le16dec(p + 34); */ /* Better be zero. */ + /* internal_attributes = archive_le16dec(p + 36); */ /* text bit */ + external_attributes = archive_le32dec(p + 38); + zip_entry->local_header_offset = + archive_le32dec(p + 42) + correction; + + /* If we can't guess the mode, leave it zero here; + when we read the local file header we might get + more information. */ + if (zip_entry->system == 3) { + zip_entry->mode = external_attributes >> 16; + } else if (zip_entry->system == 0) { + // Interpret MSDOS directory bit + if (0x10 == (external_attributes & 0x10)) { + zip_entry->mode = AE_IFDIR | 0775; + } else { + zip_entry->mode = AE_IFREG | 0664; + } + if (0x01 == (external_attributes & 0x01)) { + // Read-only bit; strip write permissions + zip_entry->mode &= 0555; + } + } else { + zip_entry->mode = 0; + } + + /* We're done with the regular data; get the filename and + * extra data. */ + __archive_read_consume(a, 46); + p = __archive_read_ahead(a, filename_length + extra_length, + NULL); + if (p == NULL) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file header"); + return ARCHIVE_FATAL; + } - process_extra(p + filename_length, extra_length, zip_entry); ++ if (ARCHIVE_OK != process_extra(a, p + filename_length, extra_length, zip_entry)) { ++ return ARCHIVE_FATAL; ++ } + + /* + * Mac resource fork files are stored under the + * "__MACOSX/" directory, so we should check if + * it is. + */ + if (!zip->process_mac_extensions) { + /* Treat every entry as a regular entry. */ + __archive_rb_tree_insert_node(&zip->tree, + &zip_entry->node); + } else { + name = p; + r = rsrc_basename(name, filename_length); + if (filename_length >= 9 && + strncmp("__MACOSX/", name, 9) == 0) { + /* If this file is not a resource fork nor + * a directory. We should treat it as a non + * resource fork file to expose it. */ + if (name[filename_length-1] != '/' && + (r - name < 3 || r[0] != '.' || r[1] != '_')) { + __archive_rb_tree_insert_node( + &zip->tree, &zip_entry->node); + /* Expose its parent directories. */ + expose_parent_dirs(zip, name, + filename_length); + } else { + /* This file is a resource fork file or + * a directory. */ + archive_strncpy(&(zip_entry->rsrcname), + name, filename_length); + __archive_rb_tree_insert_node( + &zip->tree_rsrc, &zip_entry->node); + } + } else { + /* Generate resource fork name to find its + * resource file at zip->tree_rsrc. */ + archive_strcpy(&(zip_entry->rsrcname), + "__MACOSX/"); + archive_strncat(&(zip_entry->rsrcname), + name, r - name); + archive_strcat(&(zip_entry->rsrcname), "._"); + archive_strncat(&(zip_entry->rsrcname), + name + (r - name), + filename_length - (r - name)); + /* Register an entry to RB tree to sort it by + * file offset. */ + __archive_rb_tree_insert_node(&zip->tree, + &zip_entry->node); + } + } + + /* Skip the comment too ... */ + __archive_read_consume(a, + filename_length + extra_length + comment_length); + } + + return ARCHIVE_OK; +} + +static ssize_t +zip_get_local_file_header_size(struct archive_read *a, size_t extra) +{ + const char *p; + ssize_t filename_length, extra_length; + + if ((p = __archive_read_ahead(a, extra + 30, NULL)) == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file header"); + return (ARCHIVE_WARN); + } + p += extra; + + if (memcmp(p, "PK\003\004", 4) != 0) { + archive_set_error(&a->archive, -1, "Damaged Zip archive"); + return ARCHIVE_WARN; + } + filename_length = archive_le16dec(p + 26); + extra_length = archive_le16dec(p + 28); + + return (30 + filename_length + extra_length); +} + +static int +zip_read_mac_metadata(struct archive_read *a, struct archive_entry *entry, + struct zip_entry *rsrc) +{ + struct zip *zip = (struct zip *)a->format->data; + unsigned char *metadata, *mp; + int64_t offset = archive_filter_bytes(&a->archive, 0); + size_t remaining_bytes, metadata_bytes; + ssize_t hsize; + int ret = ARCHIVE_OK, eof; + + switch(rsrc->compression) { + case 0: /* No compression. */ + if (rsrc->uncompressed_size != rsrc->compressed_size) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Malformed OS X metadata entry: inconsistent size"); + return (ARCHIVE_FATAL); + } +#ifdef HAVE_ZLIB_H + case 8: /* Deflate compression. */ +#endif + break; + default: /* Unsupported compression. */ + /* Return a warning. */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Unsupported ZIP compression method (%s)", + compression_name(rsrc->compression)); + /* We can't decompress this entry, but we will + * be able to skip() it and try the next entry. */ + return (ARCHIVE_WARN); + } + + if (rsrc->uncompressed_size > (4 * 1024 * 1024)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Mac metadata is too large: %jd > 4M bytes", + (intmax_t)rsrc->uncompressed_size); + return (ARCHIVE_WARN); + } + if (rsrc->compressed_size > (4 * 1024 * 1024)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Mac metadata is too large: %jd > 4M bytes", + (intmax_t)rsrc->compressed_size); + return (ARCHIVE_WARN); + } + + metadata = malloc((size_t)rsrc->uncompressed_size); + if (metadata == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Mac metadata"); + return (ARCHIVE_FATAL); + } + + if (offset < rsrc->local_header_offset) + __archive_read_consume(a, rsrc->local_header_offset - offset); + else if (offset != rsrc->local_header_offset) { + __archive_read_seek(a, rsrc->local_header_offset, SEEK_SET); + } + + hsize = zip_get_local_file_header_size(a, 0); + __archive_read_consume(a, hsize); + + remaining_bytes = (size_t)rsrc->compressed_size; + metadata_bytes = (size_t)rsrc->uncompressed_size; + mp = metadata; + eof = 0; + while (!eof && remaining_bytes) { + const unsigned char *p; + ssize_t bytes_avail; + size_t bytes_used; + + p = __archive_read_ahead(a, 1, &bytes_avail); + if (p == NULL) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Truncated ZIP file header"); + ret = ARCHIVE_WARN; + goto exit_mac_metadata; + } + if ((size_t)bytes_avail > remaining_bytes) + bytes_avail = remaining_bytes; + switch(rsrc->compression) { + case 0: /* No compression. */ + if ((size_t)bytes_avail > metadata_bytes) + bytes_avail = metadata_bytes; + memcpy(mp, p, bytes_avail); + bytes_used = (size_t)bytes_avail; + metadata_bytes -= bytes_used; + mp += bytes_used; + if (metadata_bytes == 0) + eof = 1; + break; +#ifdef HAVE_ZLIB_H + case 8: /* Deflate compression. */ + { + int r; + + ret = zip_deflate_init(a, zip); + if (ret != ARCHIVE_OK) + goto exit_mac_metadata; + zip->stream.next_in = + (Bytef *)(uintptr_t)(const void *)p; + zip->stream.avail_in = (uInt)bytes_avail; + zip->stream.total_in = 0; + zip->stream.next_out = mp; + zip->stream.avail_out = (uInt)metadata_bytes; + zip->stream.total_out = 0; + + r = inflate(&zip->stream, 0); + switch (r) { + case Z_OK: + break; + case Z_STREAM_END: + eof = 1; + break; + case Z_MEM_ERROR: + archive_set_error(&a->archive, ENOMEM, + "Out of memory for ZIP decompression"); + ret = ARCHIVE_FATAL; + goto exit_mac_metadata; + default: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "ZIP decompression failed (%d)", r); + ret = ARCHIVE_FATAL; + goto exit_mac_metadata; + } + bytes_used = zip->stream.total_in; + metadata_bytes -= zip->stream.total_out; + mp += zip->stream.total_out; + break; + } +#endif + default: + bytes_used = 0; + break; + } + __archive_read_consume(a, bytes_used); + remaining_bytes -= bytes_used; + } + archive_entry_copy_mac_metadata(entry, metadata, + (size_t)rsrc->uncompressed_size - metadata_bytes); + +exit_mac_metadata: + __archive_read_seek(a, offset, SEEK_SET); + zip->decompress_init = 0; + free(metadata); + return (ret); +} + +static int +archive_read_format_zip_seekable_read_header(struct archive_read *a, + struct archive_entry *entry) +{ + struct zip *zip = (struct zip *)a->format->data; + struct zip_entry *rsrc; + int64_t offset; + int r, ret = ARCHIVE_OK; + + /* + * It should be sufficient to call archive_read_next_header() for + * a reader to determine if an entry is encrypted or not. If the + * encryption of an entry is only detectable when calling + * archive_read_data(), so be it. We'll do the same check there + * as well. + */ + if (zip->has_encrypted_entries == + ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) + zip->has_encrypted_entries = 0; + + a->archive.archive_format = ARCHIVE_FORMAT_ZIP; + if (a->archive.archive_format_name == NULL) + a->archive.archive_format_name = "ZIP"; + + if (zip->zip_entries == NULL) { + r = slurp_central_directory(a, zip); + if (r != ARCHIVE_OK) + return r; + /* Get first entry whose local header offset is lower than + * other entries in the archive file. */ + zip->entry = + (struct zip_entry *)ARCHIVE_RB_TREE_MIN(&zip->tree); + } else if (zip->entry != NULL) { + /* Get next entry in local header offset order. */ + zip->entry = (struct zip_entry *)__archive_rb_tree_iterate( + &zip->tree, &zip->entry->node, ARCHIVE_RB_DIR_RIGHT); + } + + if (zip->entry == NULL) + return ARCHIVE_EOF; + + if (zip->entry->rsrcname.s) + rsrc = (struct zip_entry *)__archive_rb_tree_find_node( + &zip->tree_rsrc, zip->entry->rsrcname.s); + else + rsrc = NULL; + + if (zip->cctx_valid) + archive_decrypto_aes_ctr_release(&zip->cctx); + if (zip->hctx_valid) + archive_hmac_sha1_cleanup(&zip->hctx); + zip->tctx_valid = zip->cctx_valid = zip->hctx_valid = 0; + __archive_read_reset_passphrase(a); + + /* File entries are sorted by the header offset, we should mostly + * use __archive_read_consume to advance a read point to avoid redundant + * data reading. */ + offset = archive_filter_bytes(&a->archive, 0); + if (offset < zip->entry->local_header_offset) + __archive_read_consume(a, + zip->entry->local_header_offset - offset); + else if (offset != zip->entry->local_header_offset) { + __archive_read_seek(a, zip->entry->local_header_offset, + SEEK_SET); + } + zip->unconsumed = 0; + r = zip_read_local_file_header(a, entry, zip); + if (r != ARCHIVE_OK) + return r; + if (rsrc) { + int ret2 = zip_read_mac_metadata(a, entry, rsrc); + if (ret2 < ret) + ret = ret2; + } + return (ret); +} + +/* + * We're going to seek for the next header anyway, so we don't + * need to bother doing anything here. + */ +static int +archive_read_format_zip_read_data_skip_seekable(struct archive_read *a) +{ + struct zip *zip; + zip = (struct zip *)(a->format->data); + + zip->unconsumed = 0; + return (ARCHIVE_OK); +} + +int +archive_read_support_format_zip_seekable(struct archive *_a) +{ + struct archive_read *a = (struct archive_read *)_a; + struct zip *zip; + int r; + + archive_check_magic(_a, ARCHIVE_READ_MAGIC, + ARCHIVE_STATE_NEW, "archive_read_support_format_zip_seekable"); + + zip = (struct zip *)calloc(1, sizeof(*zip)); + if (zip == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate zip data"); + return (ARCHIVE_FATAL); + } + +#ifdef HAVE_COPYFILE_H + /* Set this by default on Mac OS. */ + zip->process_mac_extensions = 1; +#endif + + /* + * Until enough data has been read, we cannot tell about + * any encrypted entries yet. + */ + zip->has_encrypted_entries = ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW; + zip->crc32func = real_crc32; + + r = __archive_read_register_format(a, + zip, + "zip", + archive_read_format_zip_seekable_bid, + archive_read_format_zip_options, + archive_read_format_zip_seekable_read_header, + archive_read_format_zip_read_data, + archive_read_format_zip_read_data_skip_seekable, + NULL, + archive_read_format_zip_cleanup, + archive_read_support_format_zip_capabilities_seekable, + archive_read_format_zip_has_encrypted_entries); + + if (r != ARCHIVE_OK) + free(zip); + return (ARCHIVE_OK); +} diff --cc Utilities/cmlibarchive/libarchive/archive_util.c index f89df1d,0000000..f56ca33 mode 100644,000000..100644 --- a/Utilities/cmlibarchive/libarchive/archive_util.c +++ b/Utilities/cmlibarchive/libarchive/archive_util.c @@@ -1,667 -1,0 +1,667 @@@ +/*- + * 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_SYS_TYPES_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#if defined(HAVE_WINCRYPT_H) && !defined(__CYGWIN__) +#include +#endif +#ifdef HAVE_ZLIB_H +#include +#endif +#ifdef HAVE_LZMA_H +#include +#endif +#ifdef HAVE_BZLIB_H +#include +#endif +#ifdef HAVE_LZ4_H +#include +#endif + +#include "archive.h" +#include "archive_private.h" +#include "archive_random_private.h" +#include "archive_string.h" + +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + +static int archive_utility_string_sort_helper(char **, unsigned int); + +/* Generic initialization of 'struct archive' objects. */ +int +__archive_clean(struct archive *a) +{ + archive_string_conversion_free(a); + return (ARCHIVE_OK); +} + +int +archive_version_number(void) +{ + return (ARCHIVE_VERSION_NUMBER); +} + +const char * +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) +{ + return (a->archive_error_number); +} + +const char * +archive_error_string(struct archive *a) +{ + + if (a->error != NULL && *a->error != '\0') + return (a->error); + else + return (NULL); +} + +int +archive_file_count(struct archive *a) +{ + return (a->file_count); +} + +int +archive_format(struct archive *a) +{ + return (a->archive_format); +} + +const char * +archive_format_name(struct archive *a) +{ + return (a->archive_format_name); +} + + +int +archive_compression(struct archive *a) +{ + return archive_filter_code(a, 0); +} + +const char * +archive_compression_name(struct archive *a) +{ + return archive_filter_name(a, 0); +} + + +/* + * Return a count of the number of compressed bytes processed. + */ +int64_t +archive_position_compressed(struct archive *a) +{ + return archive_filter_bytes(a, -1); +} + +/* + * Return a count of the number of uncompressed bytes processed. + */ +int64_t +archive_position_uncompressed(struct archive *a) +{ + return archive_filter_bytes(a, 0); +} + +void +archive_clear_error(struct archive *a) +{ + archive_string_empty(&a->error_string); + a->error = NULL; + a->archive_error_number = 0; +} + +void +archive_set_error(struct archive *a, int error_number, const char *fmt, ...) +{ + va_list ap; + + a->archive_error_number = error_number; + if (fmt == NULL) { + a->error = NULL; + return; + } + + archive_string_empty(&(a->error_string)); + va_start(ap, fmt); + archive_string_vsprintf(&(a->error_string), fmt, ap); + va_end(ap); + a->error = a->error_string.s; +} + +void +archive_copy_error(struct archive *dest, struct archive *src) +{ + dest->archive_error_number = src->archive_error_number; + + archive_string_copy(&dest->error_string, &src->error_string); + dest->error = dest->error_string.s; +} + +void +__archive_errx(int retvalue, const char *msg) +{ + static const char *msg1 = "Fatal Internal Error in libarchive: "; + size_t s; + + s = write(2, msg1, strlen(msg1)); + (void)s; /* UNUSED */ + s = write(2, msg, strlen(msg)); + (void)s; /* UNUSED */ + s = write(2, "\n", 1); + (void)s; /* UNUSED */ + exit(retvalue); +} + +/* + * Create a temporary file + */ +#if defined(_WIN32) && !defined(__CYGWIN__) + +/* + * Do not use Windows tmpfile() function. + * It will make a temporary file under the root directory + * and it'll cause permission error if a user who is + * non-Administrator creates temporary files. + * Also Windows version of mktemp family including _mktemp_s + * are not secure. + */ +int +__archive_mktemp(const char *tmpdir) +{ + 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', + L'G', L'H', L'I', L'J', L'K', L'L', L'M', L'N', + L'O', L'P', L'Q', L'R', L'S', L'T', L'U', L'V', + L'W', L'X', L'Y', L'Z', L'a', L'b', L'c', L'd', + L'e', L'f', L'g', L'h', L'i', L'j', L'k', L'l', + L'm', L'n', L'o', L'p', L'q', L'r', L's', L't', + L'u', L'v', L'w', L'x', L'y', L'z' + }; + HCRYPTPROV hProv; + struct archive_wstring temp_name; + wchar_t *ws; + DWORD attr; + wchar_t *xp, *ep; + int fd; + + hProv = (HCRYPTPROV)NULL; + fd = -1; + ws = NULL; + archive_string_init(&temp_name); + + /* Get a temporary directory. */ + if (tmpdir == NULL) { + size_t l; + wchar_t *tmp; + + l = GetTempPathW(0, NULL); + if (l == 0) { + la_dosmaperr(GetLastError()); + goto exit_tmpfile; + } + tmp = malloc(l*sizeof(wchar_t)); + if (tmp == NULL) { + errno = ENOMEM; + goto exit_tmpfile; + } + GetTempPathW((DWORD)l, tmp); + archive_wstrcpy(&temp_name, tmp); + free(tmp); + } else { + if (archive_wstring_append_from_mbs(&temp_name, tmpdir, + strlen(tmpdir)) < 0) + goto exit_tmpfile; + if (temp_name.s[temp_name.length-1] != L'/') + archive_wstrappend_wchar(&temp_name, L'/'); + } + + /* Check if temp_name is a directory. */ + attr = GetFileAttributesW(temp_name.s); + if (attr == (DWORD)-1) { + if (GetLastError() != ERROR_FILE_NOT_FOUND) { + la_dosmaperr(GetLastError()); + goto exit_tmpfile; + } + ws = __la_win_permissive_name_w(temp_name.s); + if (ws == NULL) { + errno = EINVAL; + goto exit_tmpfile; + } + attr = GetFileAttributesW(ws); + if (attr == (DWORD)-1) { + la_dosmaperr(GetLastError()); + goto exit_tmpfile; + } + } + if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) { + errno = ENOTDIR; + goto exit_tmpfile; + } + + /* + * Create a temporary file. + */ + archive_wstrcat(&temp_name, prefix); + archive_wstrcat(&temp_name, suffix); + ep = temp_name.s + archive_strlen(&temp_name); + xp = ep - wcslen(suffix); + + if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT)) { + la_dosmaperr(GetLastError()); + goto exit_tmpfile; + } + + for (;;) { + wchar_t *p; + HANDLE h; + + /* Generate a random file name through CryptGenRandom(). */ + p = xp; + if (!CryptGenRandom(hProv, (DWORD)(ep - p)*sizeof(wchar_t), + (BYTE*)p)) { + la_dosmaperr(GetLastError()); + goto exit_tmpfile; + } + for (; p < ep; p++) + *p = num[((DWORD)*p) % (sizeof(num)/sizeof(num[0]))]; + + free(ws); + ws = __la_win_permissive_name_w(temp_name.s); + if (ws == NULL) { + errno = EINVAL; + goto exit_tmpfile; + } + /* Specifies FILE_FLAG_DELETE_ON_CLOSE flag is to + * delete this temporary file immediately when this + * file closed. */ + h = CreateFileW(ws, + GENERIC_READ | GENERIC_WRITE | DELETE, + 0,/* Not share */ + NULL, + CREATE_NEW,/* Create a new file only */ + FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, + NULL); + if (h == INVALID_HANDLE_VALUE) { + /* The same file already exists. retry with + * a new filename. */ + if (GetLastError() == ERROR_FILE_EXISTS) + continue; + /* Otherwise, fail creation temporary file. */ + la_dosmaperr(GetLastError()); + goto exit_tmpfile; + } + fd = _open_osfhandle((intptr_t)h, _O_BINARY | _O_RDWR); + if (fd == -1) { + CloseHandle(h); + goto exit_tmpfile; + } else + break;/* success! */ + } +exit_tmpfile: + if (hProv != (HCRYPTPROV)NULL) + CryptReleaseContext(hProv, 0); + free(ws); + archive_wstring_free(&temp_name); + return (fd); +} + +#else + +static int +get_tempdir(struct archive_string *temppath) +{ + const char *tmp; + + tmp = getenv("TMPDIR"); + if (tmp == NULL) +#ifdef _PATH_TMP + tmp = _PATH_TMP; +#else + tmp = "/tmp"; +#endif + archive_strcpy(temppath, tmp); + if (temppath->s[temppath->length-1] != '/') + archive_strappend_char(temppath, '/'); + return (ARCHIVE_OK); +} + +#if defined(HAVE_MKSTEMP) + +/* + * We can use mkstemp(). + */ + +int +__archive_mktemp(const char *tmpdir) +{ + struct archive_string temp_name; + int fd = -1; + + archive_string_init(&temp_name); + if (tmpdir == NULL) { + if (get_tempdir(&temp_name) != ARCHIVE_OK) + goto exit_tmpfile; + } else { + archive_strcpy(&temp_name, tmpdir); + if (temp_name.s[temp_name.length-1] != '/') + archive_strappend_char(&temp_name, '/'); + } + archive_strcat(&temp_name, "libarchive_XXXXXX"); + fd = mkstemp(temp_name.s); + if (fd < 0) + goto exit_tmpfile; + __archive_ensure_cloexec_flag(fd); + unlink(temp_name.s); +exit_tmpfile: + archive_string_free(&temp_name); + return (fd); +} + +#else + +/* + * We use a private routine. + */ + +int +__archive_mktemp(const char *tmpdir) +{ + static const char num[] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', + 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', + 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', + 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', + 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', + 'u', 'v', 'w', 'x', 'y', 'z' + }; + struct archive_string temp_name; + struct stat st; + int fd; + char *tp, *ep; + + fd = -1; + archive_string_init(&temp_name); + if (tmpdir == NULL) { + if (get_tempdir(&temp_name) != ARCHIVE_OK) + goto exit_tmpfile; + } else + archive_strcpy(&temp_name, tmpdir); + if (temp_name.s[temp_name.length-1] == '/') { + temp_name.s[temp_name.length-1] = '\0'; + temp_name.length --; + } + if (stat(temp_name.s, &st) < 0) + goto exit_tmpfile; + if (!S_ISDIR(st.st_mode)) { + errno = ENOTDIR; + goto exit_tmpfile; + } + archive_strcat(&temp_name, "/libarchive_"); + tp = temp_name.s + archive_strlen(&temp_name); + archive_strcat(&temp_name, "XXXXXXXXXX"); + ep = temp_name.s + archive_strlen(&temp_name); + + do { + char *p; + + p = tp; + archive_random(p, ep - p); + while (p < ep) { + int d = *((unsigned char *)p) % sizeof(num); + *p++ = num[d]; + } + fd = open(temp_name.s, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, + 0600); + } while (fd < 0 && errno == EEXIST); + if (fd < 0) + goto exit_tmpfile; + __archive_ensure_cloexec_flag(fd); + unlink(temp_name.s); +exit_tmpfile: + archive_string_free(&temp_name); + return (fd); +} + +#endif /* HAVE_MKSTEMP */ +#endif /* !_WIN32 || __CYGWIN__ */ + +/* + * Set FD_CLOEXEC flag to a file descriptor if it is not set. + * We have to set the flag if the platform does not provide O_CLOEXEC + * or F_DUPFD_CLOEXEC flags. + * + * Note: This function is absolutely called after creating a new file + * descriptor even if the platform seemingly provides O_CLOEXEC or + * F_DUPFD_CLOEXEC macros because it is possible that the platform + * merely declares those macros, especially Linux 2.6.18 - 2.6.24 do it. + */ +void +__archive_ensure_cloexec_flag(int fd) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) - (void)fd; /* UNSED */ ++ (void)fd; /* UNUSED */ +#else + int flags; + + if (fd >= 0) { + flags = fcntl(fd, F_GETFD); + if (flags != -1 && (flags & FD_CLOEXEC) == 0) + fcntl(fd, F_SETFD, flags | FD_CLOEXEC); + } +#endif +} + +/* + * Utility function to sort a group of strings using quicksort. + */ +static int +archive_utility_string_sort_helper(char **strings, unsigned int n) +{ + unsigned int i, lesser_count, greater_count; + char **lesser, **greater, **tmp, *pivot; + int retval1, retval2; + + /* A list of 0 or 1 elements is already sorted */ + if (n <= 1) + return (ARCHIVE_OK); + + lesser_count = greater_count = 0; + lesser = greater = NULL; + pivot = strings[0]; + for (i = 1; i < n; i++) + { + if (strcmp(strings[i], pivot) < 0) + { + lesser_count++; + tmp = (char **)realloc(lesser, + lesser_count * sizeof(char *)); + if (!tmp) { + free(greater); + free(lesser); + return (ARCHIVE_FATAL); + } + lesser = tmp; + lesser[lesser_count - 1] = strings[i]; + } + else + { + greater_count++; + tmp = (char **)realloc(greater, + greater_count * sizeof(char *)); + if (!tmp) { + free(greater); + free(lesser); + return (ARCHIVE_FATAL); + } + greater = tmp; + greater[greater_count - 1] = strings[i]; + } + } + + /* quicksort(lesser) */ + retval1 = archive_utility_string_sort_helper(lesser, lesser_count); + for (i = 0; i < lesser_count; i++) + strings[i] = lesser[i]; + free(lesser); + + /* pivot */ + strings[lesser_count] = pivot; + + /* quicksort(greater) */ + retval2 = archive_utility_string_sort_helper(greater, greater_count); + for (i = 0; i < greater_count; i++) + strings[lesser_count + 1 + i] = greater[i]; + free(greater); + + return (retval1 < retval2) ? retval1 : retval2; +} + +int +archive_utility_string_sort(char **strings) +{ + unsigned int size = 0; + while (strings[size] != NULL) + size++; + return archive_utility_string_sort_helper(strings, size); +} diff --cc Utilities/cmlibarchive/libarchive/archive_windows.h index 7c31a16,0000000..c3aed0c mode 100644,000000..100644 --- a/Utilities/cmlibarchive/libarchive/archive_windows.h +++ b/Utilities/cmlibarchive/libarchive/archive_windows.h @@@ -1,320 -1,0 +1,324 @@@ +/*- + * Copyright (c) 2009-2011 Michihiro NAKAJIMA + * Copyright (c) 2003-2006 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef __LIBARCHIVE_BUILD +#error This header is only to be used internally to libarchive. +#endif + +/* + * TODO: A lot of stuff in here isn't actually used by libarchive and + * can be trimmed out. Note that this file is used by libarchive and + * libarchive_test but nowhere else. (But note that it gets compiled + * with many different Windows environments, including MinGW, Visual + * Studio, and Cygwin. Significant changes should be tested in all three.) + */ + +/* + * TODO: Don't use off_t in here. Use __int64 instead. Note that + * Visual Studio and the Windows SDK define off_t as 32 bits; Win32's + * more modern file handling APIs all use __int64 instead of off_t. + */ + +#ifndef LIBARCHIVE_ARCHIVE_WINDOWS_H_INCLUDED +#define LIBARCHIVE_ARCHIVE_WINDOWS_H_INCLUDED + +/* Start of configuration for native Win32 */ +#ifndef MINGW_HAS_SECURE_API +#define MINGW_HAS_SECURE_API 1 +#endif + +#include +#define set_errno(val) ((errno)=val) +#include +#include //brings in NULL +#if defined(HAVE_STDINT_H) +#include +#endif +#include +#include +#include +#include +#include +#if defined(__MINGW32__) && defined(HAVE_UNISTD_H) +/* Prevent build error from a type mismatch of ftruncate(). + * This unistd.h defines it as ftruncate(int, off_t). */ +#include +#endif +#define NOCRYPT +#include +//#define EFTYPE 7 + +#if defined(_MSC_VER) +#pragma warning(push,1) +#pragma warning(disable:4142) /* benign redefinition of type */ +#pragma warning(disable:4761) /* integral size mismatch in argument; conversion supplied */ +#endif +#if defined(__BORLANDC__) +#pragma warn -8068 /* Constant out of range in comparison. */ +#pragma warn -8072 /* Suspicious pointer arithmetic. */ +#endif + +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif + +/* Alias the Windows _function to the POSIX equivalent. */ +#define close _close +#define fcntl(fd, cmd, flg) /* No operation. */ +#ifndef fileno +#define fileno _fileno +#endif +#ifdef fstat +#undef fstat +#endif +#define fstat __la_fstat +#if !defined(__BORLANDC__) +#ifdef lseek +#undef lseek +#endif +#define lseek _lseeki64 +#else +#define lseek __la_lseek +#define __LA_LSEEK_NEEDED +#endif +#define lstat __la_stat +#define open __la_open +#define read __la_read +#if !defined(__BORLANDC__) && !defined(__WATCOMC__) +#define setmode _setmode +#endif +#ifdef stat +#undef stat +#endif +#define stat(path,stref) __la_stat(path,stref) +#if !defined(__WATCOMC__) +#if !defined(__BORLANDC__) +#define strdup _strdup +#endif +#define tzset _tzset +#if !defined(__BORLANDC__) +#define umask _umask +#endif +#endif +#define waitpid __la_waitpid +#define write __la_write + +#if !defined(__WATCOMC__) + +#ifndef O_RDONLY +#define O_RDONLY _O_RDONLY +#define O_WRONLY _O_WRONLY +#define O_TRUNC _O_TRUNC +#define O_CREAT _O_CREAT +#define O_EXCL _O_EXCL +#define O_BINARY _O_BINARY +#endif + +#ifndef _S_IFIFO + #define _S_IFIFO 0010000 /* pipe */ +#endif +#ifndef _S_IFCHR + #define _S_IFCHR 0020000 /* character special */ +#endif +#ifndef _S_IFDIR + #define _S_IFDIR 0040000 /* directory */ +#endif +#ifndef _S_IFBLK + #define _S_IFBLK 0060000 /* block special */ +#endif +#ifndef _S_IFLNK + #define _S_IFLNK 0120000 /* symbolic link */ +#endif +#ifndef _S_IFSOCK + #define _S_IFSOCK 0140000 /* socket */ +#endif +#ifndef _S_IFREG + #define _S_IFREG 0100000 /* regular */ +#endif +#ifndef _S_IFMT + #define _S_IFMT 0170000 /* file type mask */ +#endif + +#ifndef S_IFIFO +#define S_IFIFO _S_IFIFO +#endif +//#define S_IFCHR _S_IFCHR +//#define S_IFDIR _S_IFDIR +#ifndef S_IFBLK +#define S_IFBLK _S_IFBLK +#endif +#ifndef S_IFLNK +#define S_IFLNK _S_IFLNK +#endif +#ifndef S_IFSOCK +#define S_IFSOCK _S_IFSOCK +#endif +//#define S_IFREG _S_IFREG +//#define S_IFMT _S_IFMT + +#ifndef S_ISBLK +#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) /* block special */ +#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) /* fifo or socket */ +#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) /* char special */ +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) /* directory */ +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) /* regular file */ +#endif + +#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) /* Symbolic link */ +#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) /* Socket */ + +#define _S_ISUID 0004000 /* set user id on execution */ +#define _S_ISGID 0002000 /* set group id on execution */ +#define _S_ISVTX 0001000 /* save swapped text even after use */ + +#define S_ISUID _S_ISUID +#define S_ISGID _S_ISGID +#define S_ISVTX _S_ISVTX + +#define _S_IRWXU (_S_IREAD | _S_IWRITE | _S_IEXEC) +#define _S_IXUSR _S_IEXEC /* read permission, user */ +#define _S_IWUSR _S_IWRITE /* write permission, user */ +#define _S_IRUSR _S_IREAD /* execute/search permission, user */ +#define _S_IRWXG (_S_IRWXU >> 3) +#define _S_IXGRP (_S_IXUSR >> 3) /* read permission, group */ +#define _S_IWGRP (_S_IWUSR >> 3) /* write permission, group */ +#define _S_IRGRP (_S_IRUSR >> 3) /* execute/search permission, group */ +#define _S_IRWXO (_S_IRWXG >> 3) +#define _S_IXOTH (_S_IXGRP >> 3) /* read permission, other */ +#define _S_IWOTH (_S_IWGRP >> 3) /* write permission, other */ +#define _S_IROTH (_S_IRGRP >> 3) /* execute/search permission, other */ + +#ifndef S_IRWXU +#define S_IRWXU _S_IRWXU +#define S_IXUSR _S_IXUSR +#define S_IWUSR _S_IWUSR +#define S_IRUSR _S_IRUSR +#endif ++#ifndef S_IRWXG +#define S_IRWXG _S_IRWXG +#define S_IXGRP _S_IXGRP +#define S_IWGRP _S_IWGRP ++#endif +#ifndef S_IRGRP +#define S_IRGRP _S_IRGRP +#endif ++#ifndef S_IRWXO +#define S_IRWXO _S_IRWXO +#define S_IXOTH _S_IXOTH +#define S_IWOTH _S_IWOTH +#define S_IROTH _S_IROTH ++#endif + +#endif + +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#define F_GETOWN 5 /* Get owner (receiver of SIGIO). */ +#define F_SETOWN 6 /* Set owner (receiver of SIGIO). */ +#define F_GETLK 7 /* Get record locking info. */ +#define F_SETLK 8 /* Set record locking info (non-blocking). */ +#define F_SETLKW 9 /* Set record locking info (blocking). */ + +/* XXX missing */ +#define F_GETLK64 7 /* Get record locking info. */ +#define F_SETLK64 8 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 9 /* Set record locking info (blocking). */ + +/* File descriptor flags used with F_GETFD and F_SETFD. */ +#define FD_CLOEXEC 1 /* Close on exec. */ + +//NOT SURE IF O_NONBLOCK is OK here but at least the 0x0004 flag is not used by anything else... +#define O_NONBLOCK 0x0004 /* Non-blocking I/O. */ +//#define O_NDELAY O_NONBLOCK + +/* Symbolic constants for the access() function */ +#if !defined(F_OK) + #define R_OK 4 /* Test for read permission */ + #define W_OK 2 /* Test for write permission */ + #define X_OK 1 /* Test for execute permission */ + #define F_OK 0 /* Test for existence of file */ +#endif + + +/* Replacement POSIX function */ +extern int __la_fstat(int fd, struct stat *st); +extern int __la_lstat(const char *path, struct stat *st); +#if defined(__LA_LSEEK_NEEDED) +extern __int64 __la_lseek(int fd, __int64 offset, int whence); +#endif +extern int __la_open(const char *path, int flags, ...); +extern ssize_t __la_read(int fd, void *buf, size_t nbytes); +extern int __la_stat(const char *path, struct stat *st); +extern pid_t __la_waitpid(HANDLE child, int *status, int option); +extern ssize_t __la_write(int fd, const void *buf, size_t nbytes); + +#define _stat64i32(path, st) __la_stat(path, st) +#define _stat64(path, st) __la_stat(path, st) +/* for status returned by la_waitpid */ +#define WIFEXITED(sts) ((sts & 0x100) == 0) +#define WEXITSTATUS(sts) (sts & 0x0FF) + +extern wchar_t *__la_win_permissive_name(const char *name); +extern wchar_t *__la_win_permissive_name_w(const wchar_t *wname); +extern void __la_dosmaperr(unsigned long e); +#define la_dosmaperr(e) __la_dosmaperr(e) +extern struct archive_entry *__la_win_entry_in_posix_pathseparator( + struct archive_entry *); + +#if defined(HAVE_WCRTOMB) && defined(__BORLANDC__) +typedef int mbstate_t; +size_t wcrtomb(char *, wchar_t, mbstate_t *); +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1300 +WINBASEAPI BOOL WINAPI GetVolumePathNameW( + LPCWSTR lpszFileName, + LPWSTR lpszVolumePathName, + DWORD cchBufferLength + ); +# if _WIN32_WINNT < 0x0500 /* windows.h not providing 0x500 API */ +typedef struct _FILE_ALLOCATED_RANGE_BUFFER { + LARGE_INTEGER FileOffset; + LARGE_INTEGER Length; +} FILE_ALLOCATED_RANGE_BUFFER, *PFILE_ALLOCATED_RANGE_BUFFER; +# define FSCTL_SET_SPARSE \ + CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 49, METHOD_BUFFERED, FILE_WRITE_DATA) +# define FSCTL_QUERY_ALLOCATED_RANGES \ + CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 51, METHOD_NEITHER, FILE_READ_DATA) +# endif +#endif + +#endif /* LIBARCHIVE_ARCHIVE_WINDOWS_H_INCLUDED */ diff --cc Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c index 4f849ce,0000000..e4a3535 mode 100644,000000..100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_add_filter_xz.c @@@ -1,547 -1,0 +1,547 @@@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * Copyright (c) 2009-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_compression_xz.c 201108 2009-12-28 03:28:21Z kientzle $"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#include +#ifdef HAVE_LZMA_H +#include +#endif + +#include "archive.h" +#include "archive_endian.h" +#include "archive_private.h" +#include "archive_write_private.h" + +#if ARCHIVE_VERSION_NUMBER < 4000000 +int +archive_write_set_compression_lzip(struct archive *a) +{ + __archive_write_filters_free(a); + return (archive_write_add_filter_lzip(a)); +} + +int +archive_write_set_compression_lzma(struct archive *a) +{ + __archive_write_filters_free(a); + return (archive_write_add_filter_lzma(a)); +} + +int +archive_write_set_compression_xz(struct archive *a) +{ + __archive_write_filters_free(a); + return (archive_write_add_filter_xz(a)); +} + +#endif + +#ifndef HAVE_LZMA_H +int +archive_write_add_filter_xz(struct archive *a) +{ + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "xz compression not supported on this platform"); + return (ARCHIVE_FATAL); +} + +int +archive_write_add_filter_lzma(struct archive *a) +{ + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "lzma compression not supported on this platform"); + return (ARCHIVE_FATAL); +} + +int +archive_write_add_filter_lzip(struct archive *a) +{ + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "lzma compression not supported on this platform"); + return (ARCHIVE_FATAL); +} +#else +/* Don't compile this if we don't have liblzma. */ + +struct private_data { + int compression_level; + uint32_t threads; + lzma_stream stream; + lzma_filter lzmafilters[2]; + lzma_options_lzma lzma_opt; + int64_t total_in; + unsigned char *compressed; + size_t compressed_buffer_size; + int64_t total_out; + /* the CRC32 value of uncompressed data for lzip */ + uint32_t crc32; +}; + +static int archive_compressor_xz_options(struct archive_write_filter *, + const char *, const char *); +static int archive_compressor_xz_open(struct archive_write_filter *); +static int archive_compressor_xz_write(struct archive_write_filter *, + const void *, size_t); +static int archive_compressor_xz_close(struct archive_write_filter *); +static int archive_compressor_xz_free(struct archive_write_filter *); +static int drive_compressor(struct archive_write_filter *, + struct private_data *, int finishing); + +struct option_value { + uint32_t dict_size; + uint32_t nice_len; + lzma_match_finder mf; +}; +static const struct option_value option_values[] = { + { 1 << 16, 32, LZMA_MF_HC3}, + { 1 << 20, 32, LZMA_MF_HC3}, + { 3 << 19, 32, LZMA_MF_HC4}, + { 1 << 21, 32, LZMA_MF_BT4}, + { 3 << 20, 32, LZMA_MF_BT4}, + { 1 << 22, 32, LZMA_MF_BT4}, + { 1 << 23, 64, LZMA_MF_BT4}, + { 1 << 24, 64, LZMA_MF_BT4}, + { 3 << 23, 64, LZMA_MF_BT4}, + { 1 << 25, 64, LZMA_MF_BT4} +}; + +static int +common_setup(struct archive_write_filter *f) +{ + struct private_data *data; + struct archive_write *a = (struct archive_write *)f->archive; + data = calloc(1, sizeof(*data)); + if (data == NULL) { + archive_set_error(&a->archive, ENOMEM, "Out of memory"); + return (ARCHIVE_FATAL); + } + f->data = data; + data->compression_level = LZMA_PRESET_DEFAULT; + data->threads = 1; + f->open = &archive_compressor_xz_open; + f->close = archive_compressor_xz_close; + f->free = archive_compressor_xz_free; + f->options = &archive_compressor_xz_options; + return (ARCHIVE_OK); +} + +/* + * Add an xz compression filter to this write handle. + */ +int +archive_write_add_filter_xz(struct archive *_a) +{ + struct archive_write_filter *f; + int r; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_add_filter_xz"); + f = __archive_write_allocate_filter(_a); + r = common_setup(f); + if (r == ARCHIVE_OK) { + f->code = ARCHIVE_FILTER_XZ; + f->name = "xz"; + } + return (r); +} + +/* LZMA is handled identically, we just need a different compression + * code set. (The liblzma setup looks at the code to determine + * the one place that XZ and LZMA require different handling.) */ +int +archive_write_add_filter_lzma(struct archive *_a) +{ + struct archive_write_filter *f; + int r; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_add_filter_lzma"); + f = __archive_write_allocate_filter(_a); + r = common_setup(f); + if (r == ARCHIVE_OK) { + f->code = ARCHIVE_FILTER_LZMA; + f->name = "lzma"; + } + return (r); +} + +int +archive_write_add_filter_lzip(struct archive *_a) +{ + struct archive_write_filter *f; + int r; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_add_filter_lzip"); + f = __archive_write_allocate_filter(_a); + r = common_setup(f); + if (r == ARCHIVE_OK) { + f->code = ARCHIVE_FILTER_LZIP; + f->name = "lzip"; + } + return (r); +} + +static int +archive_compressor_xz_init_stream(struct archive_write_filter *f, + struct private_data *data) +{ + static const lzma_stream lzma_stream_init_data = LZMA_STREAM_INIT; + int ret; +#ifdef HAVE_LZMA_STREAM_ENCODER_MT + lzma_mt mt_options; +#endif + + data->stream = lzma_stream_init_data; + data->stream.next_out = data->compressed; + data->stream.avail_out = data->compressed_buffer_size; + if (f->code == ARCHIVE_FILTER_XZ) { +#ifdef HAVE_LZMA_STREAM_ENCODER_MT + if (data->threads != 1) { - bzero(&mt_options, sizeof(mt_options)); ++ memset(&mt_options, 0, sizeof(mt_options)); + mt_options.threads = data->threads; + mt_options.timeout = 300; + mt_options.filters = data->lzmafilters; + mt_options.check = LZMA_CHECK_CRC64; + ret = lzma_stream_encoder_mt(&(data->stream), + &mt_options); + } else +#endif + ret = lzma_stream_encoder(&(data->stream), + data->lzmafilters, LZMA_CHECK_CRC64); + } else if (f->code == ARCHIVE_FILTER_LZMA) { + ret = lzma_alone_encoder(&(data->stream), &data->lzma_opt); + } else { /* ARCHIVE_FILTER_LZIP */ + int dict_size = data->lzma_opt.dict_size; + int ds, log2dic, wedges; + + /* Calculate a coded dictionary size */ + if (dict_size < (1 << 12) || dict_size > (1 << 27)) { + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "Unacceptable dictionary size for lzip: %d", + dict_size); + return (ARCHIVE_FATAL); + } + for (log2dic = 27; log2dic >= 12; log2dic--) { + if (dict_size & (1 << log2dic)) + break; + } + if (dict_size > (1 << log2dic)) { + log2dic++; + wedges = + ((1 << log2dic) - dict_size) / (1 << (log2dic - 4)); + } else + wedges = 0; + ds = ((wedges << 5) & 0xe0) | (log2dic & 0x1f); + + data->crc32 = 0; + /* Make a header */ + data->compressed[0] = 0x4C; + data->compressed[1] = 0x5A; + data->compressed[2] = 0x49; + data->compressed[3] = 0x50; + data->compressed[4] = 1;/* Version */ + data->compressed[5] = (unsigned char)ds; + data->stream.next_out += 6; + data->stream.avail_out -= 6; + + ret = lzma_raw_encoder(&(data->stream), data->lzmafilters); + } + if (ret == LZMA_OK) + return (ARCHIVE_OK); + + switch (ret) { + case LZMA_MEM_ERROR: + archive_set_error(f->archive, ENOMEM, + "Internal error initializing compression library: " + "Cannot allocate memory"); + break; + default: + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "Internal error initializing compression library: " + "It's a bug in liblzma"); + break; + } + return (ARCHIVE_FATAL); +} + +/* + * Setup callback. + */ +static int +archive_compressor_xz_open(struct archive_write_filter *f) +{ + struct private_data *data = f->data; + int ret; + + ret = __archive_write_open_filter(f->next_filter); + if (ret != ARCHIVE_OK) + return (ret); + + if (data->compressed == NULL) { + size_t bs = 65536, bpb; + if (f->archive->magic == ARCHIVE_WRITE_MAGIC) { + /* Buffer size should be a multiple number of the of bytes + * per block for performance. */ + bpb = archive_write_get_bytes_per_block(f->archive); + if (bpb > bs) + bs = bpb; + else if (bpb != 0) + bs -= bs % bpb; + } + data->compressed_buffer_size = bs; + data->compressed + = (unsigned char *)malloc(data->compressed_buffer_size); + if (data->compressed == NULL) { + archive_set_error(f->archive, ENOMEM, + "Can't allocate data for compression buffer"); + return (ARCHIVE_FATAL); + } + } + + f->write = archive_compressor_xz_write; + + /* Initialize compression library. */ + if (f->code == ARCHIVE_FILTER_LZIP) { + const struct option_value *val = + &option_values[data->compression_level]; + + data->lzma_opt.dict_size = val->dict_size; + data->lzma_opt.preset_dict = NULL; + data->lzma_opt.preset_dict_size = 0; + data->lzma_opt.lc = LZMA_LC_DEFAULT; + data->lzma_opt.lp = LZMA_LP_DEFAULT; + data->lzma_opt.pb = LZMA_PB_DEFAULT; + data->lzma_opt.mode = + data->compression_level<= 2? LZMA_MODE_FAST:LZMA_MODE_NORMAL; + data->lzma_opt.nice_len = val->nice_len; + data->lzma_opt.mf = val->mf; + data->lzma_opt.depth = 0; + data->lzmafilters[0].id = LZMA_FILTER_LZMA1; + data->lzmafilters[0].options = &data->lzma_opt; + data->lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */ + } else { + if (lzma_lzma_preset(&data->lzma_opt, data->compression_level)) { + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "Internal error initializing compression library"); + } + data->lzmafilters[0].id = LZMA_FILTER_LZMA2; + data->lzmafilters[0].options = &data->lzma_opt; + data->lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */ + } + ret = archive_compressor_xz_init_stream(f, data); + if (ret == LZMA_OK) { + f->data = data; + return (0); + } + return (ARCHIVE_FATAL); +} + +/* + * Set write options. + */ +static int +archive_compressor_xz_options(struct archive_write_filter *f, + const char *key, const char *value) +{ + struct private_data *data = (struct private_data *)f->data; + + if (strcmp(key, "compression-level") == 0) { + if (value == NULL || !(value[0] >= '0' && value[0] <= '9') || + value[1] != '\0') + return (ARCHIVE_WARN); + data->compression_level = value[0] - '0'; + if (data->compression_level > 6) + data->compression_level = 6; + return (ARCHIVE_OK); + } else if (strcmp(key, "threads") == 0) { + if (value == NULL) + return (ARCHIVE_WARN); + data->threads = (int)strtoul(value, NULL, 10); + if (data->threads == 0 && errno != 0) { + data->threads = 1; + return (ARCHIVE_WARN); + } + if (data->threads == 0) { +#ifdef HAVE_LZMA_STREAM_ENCODER_MT + data->threads = lzma_cputhreads(); +#else + data->threads = 1; +#endif + } + return (ARCHIVE_OK); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +/* + * Write data to the compressed stream. + */ +static int +archive_compressor_xz_write(struct archive_write_filter *f, + const void *buff, size_t length) +{ + struct private_data *data = (struct private_data *)f->data; + int ret; + + /* Update statistics */ + data->total_in += length; + if (f->code == ARCHIVE_FILTER_LZIP) + data->crc32 = lzma_crc32(buff, length, data->crc32); + + /* Compress input data to output buffer */ + data->stream.next_in = buff; + data->stream.avail_in = length; + if ((ret = drive_compressor(f, data, 0)) != ARCHIVE_OK) + return (ret); + + return (ARCHIVE_OK); +} + + +/* + * Finish the compression... + */ +static int +archive_compressor_xz_close(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + int ret, r1; + + ret = drive_compressor(f, data, 1); + if (ret == ARCHIVE_OK) { + data->total_out += + data->compressed_buffer_size - data->stream.avail_out; + ret = __archive_write_filter(f->next_filter, + data->compressed, + data->compressed_buffer_size - data->stream.avail_out); + if (f->code == ARCHIVE_FILTER_LZIP && ret == ARCHIVE_OK) { + archive_le32enc(data->compressed, data->crc32); + archive_le64enc(data->compressed+4, data->total_in); + archive_le64enc(data->compressed+12, data->total_out + 20); + ret = __archive_write_filter(f->next_filter, + data->compressed, 20); + } + } + lzma_end(&(data->stream)); + r1 = __archive_write_close_filter(f->next_filter); + return (r1 < ret ? r1 : ret); +} + +static int +archive_compressor_xz_free(struct archive_write_filter *f) +{ + struct private_data *data = (struct private_data *)f->data; + free(data->compressed); + free(data); + f->data = NULL; + return (ARCHIVE_OK); +} + +/* + * Utility function to push input data through compressor, + * writing full output blocks as necessary. + * + * Note that this handles both the regular write case (finishing == + * false) and the end-of-archive case (finishing == true). + */ +static int +drive_compressor(struct archive_write_filter *f, + struct private_data *data, int finishing) +{ + int ret; + + for (;;) { + if (data->stream.avail_out == 0) { + data->total_out += data->compressed_buffer_size; + ret = __archive_write_filter(f->next_filter, + data->compressed, + data->compressed_buffer_size); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + data->stream.next_out = data->compressed; + data->stream.avail_out = data->compressed_buffer_size; + } + + /* If there's nothing to do, we're done. */ + if (!finishing && data->stream.avail_in == 0) + return (ARCHIVE_OK); + + ret = lzma_code(&(data->stream), + finishing ? LZMA_FINISH : LZMA_RUN ); + + switch (ret) { + case LZMA_OK: + /* In non-finishing case, check if compressor + * consumed everything */ + if (!finishing && data->stream.avail_in == 0) + return (ARCHIVE_OK); + /* In finishing case, this return always means + * there's more work */ + break; + case LZMA_STREAM_END: + /* This return can only occur in finishing case. */ + if (finishing) + return (ARCHIVE_OK); + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "lzma compression data error"); + return (ARCHIVE_FATAL); + case LZMA_MEMLIMIT_ERROR: + archive_set_error(f->archive, ENOMEM, + "lzma compression error: " + "%ju MiB would have been needed", + (uintmax_t)((lzma_memusage(&(data->stream)) + + 1024 * 1024 -1) + / (1024 * 1024))); + return (ARCHIVE_FATAL); + default: + /* Any other return value indicates an error. */ + archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, + "lzma compression failed:" + " lzma_code() call returned status %d", + ret); + return (ARCHIVE_FATAL); + } + } +} + +#endif /* HAVE_LZMA_H */ diff --cc Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c index 5946683,0000000..53629ac mode 100644,000000..100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c @@@ -1,3903 -1,0 +1,4206 @@@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * 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$"); + +#if !defined(_WIN32) || defined(__CYGWIN__) + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_ACL_H +#include +#endif +#ifdef HAVE_SYS_EXTATTR_H +#include +#endif +#if defined(HAVE_SYS_XATTR_H) +#include +#elif defined(HAVE_ATTR_XATTR_H) +#include +#endif +#ifdef HAVE_SYS_EA_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_SYS_UTIME_H +#include +#endif +#ifdef HAVE_COPYFILE_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_GRP_H +#include +#endif +#ifdef HAVE_LANGINFO_H +#include +#endif +#ifdef HAVE_LINUX_FS_H +#include /* for Linux file flags */ +#endif +/* + * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h. + * As the include guards don't agree, the order of include is important. + */ +#ifdef HAVE_LINUX_EXT2_FS_H +#include /* for Linux file flags */ +#endif +#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__) +#include /* Linux file flags, broken on Cygwin */ +#endif +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_PWD_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_UTIME_H +#include +#endif +#ifdef F_GETTIMES /* Tru64 specific */ +#include +#endif + ++/* ++ * Macro to cast st_mtime and time_t to an int64 so that 2 numbers can reliably be compared. ++ * ++ * It assumes that the input is an integer type of no more than 64 bits. ++ * If the number is less than zero, t must be a signed type, so it fits in ++ * int64_t. Otherwise, it's a nonnegative value so we can cast it to uint64_t ++ * without loss. But it could be a large unsigned value, so we have to clip it ++ * to INT64_MAX.* ++ */ ++#define to_int64_time(t) \ ++ ((t) < 0 ? (int64_t)(t) : (uint64_t)(t) > (uint64_t)INT64_MAX ? INT64_MAX : (int64_t)(t)) ++ +#if __APPLE__ +#include +#if TARGET_OS_MAC && !TARGET_OS_EMBEDDED && HAVE_QUARANTINE_H +#include +#define HAVE_QUARANTINE 1 +#endif +#endif + +#ifdef HAVE_ZLIB_H +#include +#endif + +/* TODO: Support Mac OS 'quarantine' feature. This is really just a + * standard tag to mark files that have been downloaded as "tainted". + * On Mac OS, we should mark the extracted files as tainted if the + * archive being read was tainted. Windows has a similar feature; we + * should investigate ways to support this generically. */ + +#include "archive.h" +#include "archive_acl_private.h" +#include "archive_string.h" +#include "archive_endian.h" +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_write_disk_private.h" + +#ifndef O_BINARY +#define O_BINARY 0 +#endif +#ifndef O_CLOEXEC - #define O_CLOEXEC 0 ++#define O_CLOEXEC 0 ++#endif ++ ++/* Ignore non-int O_NOFOLLOW constant. */ ++/* gnulib's fcntl.h does this on AIX, but it seems practical everywhere */ ++#if defined O_NOFOLLOW && !(INT_MIN <= O_NOFOLLOW && O_NOFOLLOW <= INT_MAX) ++#undef O_NOFOLLOW ++#endif ++ ++#ifndef O_NOFOLLOW ++#define O_NOFOLLOW 0 +#endif + +struct fixup_entry { + struct fixup_entry *next; + struct archive_acl acl; + mode_t mode; + int64_t atime; + int64_t birthtime; + int64_t mtime; + int64_t ctime; + unsigned long atime_nanos; + unsigned long birthtime_nanos; + unsigned long mtime_nanos; + unsigned long ctime_nanos; + unsigned long fflags_set; + size_t mac_metadata_size; + void *mac_metadata; + int fixup; /* bitmask of what needs fixing */ + char *name; +}; + +/* + * We use a bitmask to track which operations remain to be done for + * this file. In particular, this helps us avoid unnecessary + * operations when it's possible to take care of one step as a + * side-effect of another. For example, mkdir() can specify the mode + * for the newly-created object but symlink() cannot. This means we + * can skip chmod() if mkdir() succeeded, but we must explicitly + * chmod() if we're trying to create a directory that already exists + * (mkdir() failed) or if we're restoring a symlink. Similarly, we + * need to verify UID/GID before trying to restore SUID/SGID bits; + * that verification can occur explicitly through a stat() call or + * implicitly because of a successful chown() call. + */ +#define TODO_MODE_FORCE 0x40000000 +#define TODO_MODE_BASE 0x20000000 +#define TODO_SUID 0x10000000 +#define TODO_SUID_CHECK 0x08000000 +#define TODO_SGID 0x04000000 +#define TODO_SGID_CHECK 0x02000000 +#define TODO_APPLEDOUBLE 0x01000000 +#define TODO_MODE (TODO_MODE_BASE|TODO_SUID|TODO_SGID) +#define TODO_TIMES ARCHIVE_EXTRACT_TIME +#define TODO_OWNER ARCHIVE_EXTRACT_OWNER +#define TODO_FFLAGS ARCHIVE_EXTRACT_FFLAGS +#define TODO_ACLS ARCHIVE_EXTRACT_ACL +#define TODO_XATTR ARCHIVE_EXTRACT_XATTR +#define TODO_MAC_METADATA ARCHIVE_EXTRACT_MAC_METADATA +#define TODO_HFS_COMPRESSION ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED + +struct archive_write_disk { + struct archive archive; + + mode_t user_umask; + struct fixup_entry *fixup_list; + struct fixup_entry *current_fixup; + int64_t user_uid; + int skip_file_set; + int64_t skip_file_dev; + int64_t skip_file_ino; + time_t start_time; + + int64_t (*lookup_gid)(void *private, const char *gname, int64_t gid); + void (*cleanup_gid)(void *private); + void *lookup_gid_data; + int64_t (*lookup_uid)(void *private, const char *uname, int64_t uid); + void (*cleanup_uid)(void *private); + void *lookup_uid_data; + + /* + * Full path of last file to satisfy symlink checks. + */ + struct archive_string path_safe; + + /* + * Cached stat data from disk for the current entry. + * If this is valid, pst points to st. Otherwise, + * pst is null. + */ + struct stat st; + struct stat *pst; + + /* Information about the object being restored right now. */ + struct archive_entry *entry; /* Entry being extracted. */ + char *name; /* Name of entry, possibly edited. */ + struct archive_string _name_data; /* backing store for 'name' */ + /* Tasks remaining for this object. */ + int todo; + /* Tasks deferred until end-of-archive. */ + int deferred; + /* Options requested by the client. */ + int flags; + /* Handle for the file we're restoring. */ + int fd; + /* Current offset for writing data to the file. */ + int64_t offset; + /* Last offset actually written to disk. */ + int64_t fd_offset; + /* Total bytes actually written to files. */ + int64_t total_bytes_written; + /* Maximum size of file, -1 if unknown. */ + int64_t filesize; + /* Dir we were in before this restore; only for deep paths. */ + int restore_pwd; + /* Mode we should use for this entry; affected by _PERM and umask. */ + mode_t mode; + /* UID/GID to use in restoring this entry. */ + int64_t uid; + int64_t gid; + /* + * HFS+ Compression. + */ + /* Xattr "com.apple.decmpfs". */ + uint32_t decmpfs_attr_size; + unsigned char *decmpfs_header_p; + /* ResourceFork set options used for fsetxattr. */ + int rsrc_xattr_options; + /* Xattr "com.apple.ResourceFork". */ + unsigned char *resource_fork; + size_t resource_fork_allocated_size; + unsigned int decmpfs_block_count; + uint32_t *decmpfs_block_info; + /* Buffer for compressed data. */ + unsigned char *compressed_buffer; + size_t compressed_buffer_size; + size_t compressed_buffer_remaining; + /* The offset of the ResourceFork where compressed data will + * be placed. */ + uint32_t compressed_rsrc_position; + uint32_t compressed_rsrc_position_v; + /* Buffer for uncompressed data. */ + char *uncompressed_buffer; + size_t block_remaining_bytes; + size_t file_remaining_bytes; +#ifdef HAVE_ZLIB_H + z_stream stream; + int stream_valid; + int decmpfs_compression_level; +#endif +}; + +/* + * Default mode for dirs created automatically (will be modified by umask). + * Note that POSIX specifies 0777 for implicitly-created dirs, "modified + * by the process' file creation mask." + */ +#define DEFAULT_DIR_MODE 0777 +/* + * Dir modes are restored in two steps: During the extraction, the permissions + * in the archive are modified to match the following limits. During + * the post-extract fixup pass, the permissions from the archive are + * applied. + */ +#define MINIMUM_DIR_MODE 0700 +#define MAXIMUM_DIR_MODE 0775 + +/* - * Maxinum uncompressed size of a decmpfs block. ++ * Maximum uncompressed size of a decmpfs block. + */ +#define MAX_DECMPFS_BLOCK_SIZE (64 * 1024) +/* + * HFS+ compression type. + */ +#define CMP_XATTR 3/* Compressed data in xattr. */ +#define CMP_RESOURCE_FORK 4/* Compressed data in resource fork. */ +/* + * HFS+ compression resource fork. + */ +#define RSRC_H_SIZE 260 /* Base size of Resource fork header. */ +#define RSRC_F_SIZE 50 /* Size of Resource fork footer. */ +/* Size to write compressed data to resource fork. */ +#define COMPRESSED_W_SIZE (64 * 1024) - /* decmpfs difinitions. */ ++/* decmpfs definitions. */ +#define MAX_DECMPFS_XATTR_SIZE 3802 +#ifndef DECMPFS_XATTR_NAME +#define DECMPFS_XATTR_NAME "com.apple.decmpfs" +#endif +#define DECMPFS_MAGIC 0x636d7066 +#define DECMPFS_COMPRESSION_MAGIC 0 +#define DECMPFS_COMPRESSION_TYPE 4 +#define DECMPFS_UNCOMPRESSED_SIZE 8 +#define DECMPFS_HEADER_SIZE 16 + +#define HFS_BLOCKS(s) ((s) >> 12) + ++static void fsobj_error(int *, struct archive_string *, int, const char *, ++ const char *); ++static int check_symlinks_fsobj(char *, int *, struct archive_string *, ++ int); +static int check_symlinks(struct archive_write_disk *); +static int create_filesystem_object(struct archive_write_disk *); - static struct fixup_entry *current_fixup(struct archive_write_disk *, const char *pathname); ++static struct fixup_entry *current_fixup(struct archive_write_disk *, ++ const char *pathname); +#if defined(HAVE_FCHDIR) && defined(PATH_MAX) +static void edit_deep_directories(struct archive_write_disk *ad); +#endif ++static int cleanup_pathname_fsobj(char *, int *, struct archive_string *, ++ int); +static int cleanup_pathname(struct archive_write_disk *); +static int create_dir(struct archive_write_disk *, char *); +static int create_parent_dir(struct archive_write_disk *, char *); +static ssize_t hfs_write_data_block(struct archive_write_disk *, + const char *, size_t); +static int fixup_appledouble(struct archive_write_disk *, const char *); +static int older(struct stat *, struct archive_entry *); +static int restore_entry(struct archive_write_disk *); +static int set_mac_metadata(struct archive_write_disk *, const char *, + const void *, size_t); +static int set_xattrs(struct archive_write_disk *); +static int clear_nochange_fflags(struct archive_write_disk *); +static int set_fflags(struct archive_write_disk *); +static int set_fflags_platform(struct archive_write_disk *, int fd, + const char *name, mode_t mode, + unsigned long fflags_set, unsigned long fflags_clear); +static int set_ownership(struct archive_write_disk *); +static int set_mode(struct archive_write_disk *, int mode); +static int set_time(int, int, const char *, time_t, long, time_t, long); +static int set_times(struct archive_write_disk *, int, int, const char *, + time_t, long, time_t, long, time_t, long, time_t, long); +static int set_times_from_entry(struct archive_write_disk *); +static struct fixup_entry *sort_dir_list(struct fixup_entry *p); +static ssize_t write_data_block(struct archive_write_disk *, + const char *, size_t); + +static struct archive_vtable *archive_write_disk_vtable(void); + +static int _archive_write_disk_close(struct archive *); +static int _archive_write_disk_free(struct archive *); - static int _archive_write_disk_header(struct archive *, struct archive_entry *); ++static int _archive_write_disk_header(struct archive *, ++ struct archive_entry *); +static int64_t _archive_write_disk_filter_bytes(struct archive *, int); +static int _archive_write_disk_finish_entry(struct archive *); - static ssize_t _archive_write_disk_data(struct archive *, const void *, size_t); - static ssize_t _archive_write_disk_data_block(struct archive *, const void *, size_t, int64_t); ++static ssize_t _archive_write_disk_data(struct archive *, const void *, ++ size_t); ++static ssize_t _archive_write_disk_data_block(struct archive *, const void *, ++ size_t, int64_t); + +static int +lazy_stat(struct archive_write_disk *a) +{ + if (a->pst != NULL) { + /* Already have stat() data available. */ + return (ARCHIVE_OK); + } +#ifdef HAVE_FSTAT + if (a->fd >= 0 && fstat(a->fd, &a->st) == 0) { + a->pst = &a->st; + return (ARCHIVE_OK); + } +#endif + /* + * XXX At this point, symlinks should not be hit, otherwise + * XXX a race occurred. Do we want to check explicitly for that? + */ + if (lstat(a->name, &a->st) == 0) { + a->pst = &a->st; + return (ARCHIVE_OK); + } + archive_set_error(&a->archive, errno, "Couldn't stat file"); + return (ARCHIVE_WARN); +} + +static struct archive_vtable * +archive_write_disk_vtable(void) +{ + static struct archive_vtable av; + static int inited = 0; + + if (!inited) { + av.archive_close = _archive_write_disk_close; + av.archive_filter_bytes = _archive_write_disk_filter_bytes; + av.archive_free = _archive_write_disk_free; + av.archive_write_header = _archive_write_disk_header; + av.archive_write_finish_entry + = _archive_write_disk_finish_entry; + av.archive_write_data = _archive_write_disk_data; + av.archive_write_data_block = _archive_write_disk_data_block; + inited = 1; + } + return (&av); +} + +static int64_t +_archive_write_disk_filter_bytes(struct archive *_a, int n) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + (void)n; /* UNUSED */ + if (n == -1 || n == 0) + return (a->total_bytes_written); + return (-1); +} + + +int +archive_write_disk_set_options(struct archive *_a, int flags) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + + a->flags = flags; + return (ARCHIVE_OK); +} + + +/* + * Extract this entry to disk. + * + * TODO: Validate hardlinks. According to the standards, we're + * supposed to check each extracted hardlink and squawk if it refers + * to a file that we didn't restore. I'm not entirely convinced this + * is a good idea, but more importantly: Is there any way to validate + * hardlinks without keeping a complete list of filenames from the + * entire archive?? Ugh. + * + */ +static int +_archive_write_disk_header(struct archive *_a, struct archive_entry *entry) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + struct fixup_entry *fe; + int ret, r; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, + "archive_write_disk_header"); + archive_clear_error(&a->archive); + if (a->archive.state & ARCHIVE_STATE_DATA) { + r = _archive_write_disk_finish_entry(&a->archive); + if (r == ARCHIVE_FATAL) + return (r); + } + + /* Set up for this particular entry. */ + a->pst = NULL; + a->current_fixup = NULL; + a->deferred = 0; + if (a->entry) { + archive_entry_free(a->entry); + a->entry = NULL; + } + a->entry = archive_entry_clone(entry); + a->fd = -1; + a->fd_offset = 0; + a->offset = 0; + a->restore_pwd = -1; + a->uid = a->user_uid; + a->mode = archive_entry_mode(a->entry); + if (archive_entry_size_is_set(a->entry)) + a->filesize = archive_entry_size(a->entry); + else + a->filesize = -1; + archive_strcpy(&(a->_name_data), archive_entry_pathname(a->entry)); + a->name = a->_name_data.s; + archive_clear_error(&a->archive); + + /* + * Clean up the requested path. This is necessary for correct + * dir restores; the dir restore logic otherwise gets messed + * up by nonsense like "dir/.". + */ + ret = cleanup_pathname(a); + if (ret != ARCHIVE_OK) + return (ret); + + /* + * Query the umask so we get predictable mode settings. + * This gets done on every call to _write_header in case the + * user edits their umask during the extraction for some + * reason. + */ + umask(a->user_umask = umask(0)); + + /* Figure out what we need to do for this entry. */ + a->todo = TODO_MODE_BASE; + if (a->flags & ARCHIVE_EXTRACT_PERM) { + a->todo |= TODO_MODE_FORCE; /* Be pushy about permissions. */ + /* + * SGID requires an extra "check" step because we + * cannot easily predict the GID that the system will + * assign. (Different systems assign GIDs to files + * based on a variety of criteria, including process + * credentials and the gid of the enclosing + * directory.) We can only restore the SGID bit if + * the file has the right GID, and we only know the + * GID if we either set it (see set_ownership) or if + * we've actually called stat() on the file after it + * was restored. Since there are several places at + * which we might verify the GID, we need a TODO bit + * to keep track. + */ + if (a->mode & S_ISGID) + a->todo |= TODO_SGID | TODO_SGID_CHECK; + /* + * Verifying the SUID is simpler, but can still be + * done in multiple ways, hence the separate "check" bit. + */ + if (a->mode & S_ISUID) + a->todo |= TODO_SUID | TODO_SUID_CHECK; + } else { + /* + * User didn't request full permissions, so don't + * restore SUID, SGID bits and obey umask. + */ + a->mode &= ~S_ISUID; + a->mode &= ~S_ISGID; + a->mode &= ~S_ISVTX; + a->mode &= ~a->user_umask; + } + if (a->flags & ARCHIVE_EXTRACT_OWNER) + a->todo |= TODO_OWNER; + if (a->flags & ARCHIVE_EXTRACT_TIME) + a->todo |= TODO_TIMES; + if (a->flags & ARCHIVE_EXTRACT_ACL) { + if (archive_entry_filetype(a->entry) == AE_IFDIR) + a->deferred |= TODO_ACLS; + else + a->todo |= TODO_ACLS; + } + if (a->flags & ARCHIVE_EXTRACT_MAC_METADATA) { + if (archive_entry_filetype(a->entry) == AE_IFDIR) + a->deferred |= TODO_MAC_METADATA; + else + a->todo |= TODO_MAC_METADATA; + } +#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_ZLIB_H) + if ((a->flags & ARCHIVE_EXTRACT_NO_HFS_COMPRESSION) == 0) { + unsigned long set, clear; + archive_entry_fflags(a->entry, &set, &clear); + if ((set & ~clear) & UF_COMPRESSED) { + a->todo |= TODO_HFS_COMPRESSION; + a->decmpfs_block_count = (unsigned)-1; + } + } + if ((a->flags & ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED) != 0 && + (a->mode & AE_IFMT) == AE_IFREG && a->filesize > 0) { + a->todo |= TODO_HFS_COMPRESSION; + a->decmpfs_block_count = (unsigned)-1; + } + { + const char *p; + + /* Check if the current file name is a type of the + * resource fork file. */ + p = strrchr(a->name, '/'); + if (p == NULL) + p = a->name; + else + p++; + if (p[0] == '.' && p[1] == '_') { + /* Do not compress "._XXX" files. */ + a->todo &= ~TODO_HFS_COMPRESSION; + if (a->filesize > 0) + a->todo |= TODO_APPLEDOUBLE; + } + } +#endif + + if (a->flags & ARCHIVE_EXTRACT_XATTR) + a->todo |= TODO_XATTR; + if (a->flags & ARCHIVE_EXTRACT_FFLAGS) + a->todo |= TODO_FFLAGS; + if (a->flags & ARCHIVE_EXTRACT_SECURE_SYMLINKS) { + ret = check_symlinks(a); + if (ret != ARCHIVE_OK) + return (ret); + } +#if defined(HAVE_FCHDIR) && defined(PATH_MAX) + /* If path exceeds PATH_MAX, shorten the path. */ + edit_deep_directories(a); +#endif + + ret = restore_entry(a); + +#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_ZLIB_H) + /* + * Check if the filesystem the file is restoring on supports + * HFS+ Compression. If not, cancel HFS+ Compression. + */ + if (a->todo | TODO_HFS_COMPRESSION) { + /* + * NOTE: UF_COMPRESSED is ignored even if the filesystem + * supports HFS+ Compression because the file should - * have at least an extended attriute "com.apple.decmpfs" ++ * have at least an extended attribute "com.apple.decmpfs" + * before the flag is set to indicate that the file have - * been compressed. If hte filesystem does not support ++ * been compressed. If the filesystem does not support + * HFS+ Compression the system call will fail. + */ + if (a->fd < 0 || fchflags(a->fd, UF_COMPRESSED) != 0) + a->todo &= ~TODO_HFS_COMPRESSION; + } +#endif + + /* + * TODO: There are rumours that some extended attributes must + * be restored before file data is written. If this is true, + * then we either need to write all extended attributes both + * before and after restoring the data, or find some rule for + * determining which must go first and which last. Due to the + * many ways people are using xattrs, this may prove to be an + * intractable problem. + */ + +#ifdef HAVE_FCHDIR + /* If we changed directory above, restore it here. */ + if (a->restore_pwd >= 0) { + r = fchdir(a->restore_pwd); + if (r != 0) { - archive_set_error(&a->archive, errno, "chdir() failure"); ++ archive_set_error(&a->archive, errno, ++ "chdir() failure"); + ret = ARCHIVE_FATAL; + } + close(a->restore_pwd); + a->restore_pwd = -1; + } +#endif + + /* + * Fixup uses the unedited pathname from archive_entry_pathname(), + * because it is relative to the base dir and the edited path + * might be relative to some intermediate dir as a result of the + * deep restore logic. + */ + if (a->deferred & TODO_MODE) { + fe = current_fixup(a, archive_entry_pathname(entry)); + if (fe == NULL) + return (ARCHIVE_FATAL); + fe->fixup |= TODO_MODE_BASE; + fe->mode = a->mode; + } + + if ((a->deferred & TODO_TIMES) + && (archive_entry_mtime_is_set(entry) + || archive_entry_atime_is_set(entry))) { + fe = current_fixup(a, archive_entry_pathname(entry)); + if (fe == NULL) + return (ARCHIVE_FATAL); + fe->mode = a->mode; + fe->fixup |= TODO_TIMES; + if (archive_entry_atime_is_set(entry)) { + fe->atime = archive_entry_atime(entry); + fe->atime_nanos = archive_entry_atime_nsec(entry); + } else { + /* If atime is unset, use start time. */ + fe->atime = a->start_time; + fe->atime_nanos = 0; + } + if (archive_entry_mtime_is_set(entry)) { + fe->mtime = archive_entry_mtime(entry); + fe->mtime_nanos = archive_entry_mtime_nsec(entry); + } else { + /* If mtime is unset, use start time. */ + fe->mtime = a->start_time; + fe->mtime_nanos = 0; + } + if (archive_entry_birthtime_is_set(entry)) { + fe->birthtime = archive_entry_birthtime(entry); - fe->birthtime_nanos = archive_entry_birthtime_nsec(entry); ++ fe->birthtime_nanos = archive_entry_birthtime_nsec( ++ entry); + } else { + /* If birthtime is unset, use mtime. */ + fe->birthtime = fe->mtime; + fe->birthtime_nanos = fe->mtime_nanos; + } + } + + if (a->deferred & TODO_ACLS) { + fe = current_fixup(a, archive_entry_pathname(entry)); + if (fe == NULL) + return (ARCHIVE_FATAL); + fe->fixup |= TODO_ACLS; + archive_acl_copy(&fe->acl, archive_entry_acl(entry)); + } + + if (a->deferred & TODO_MAC_METADATA) { + const void *metadata; + size_t metadata_size; + metadata = archive_entry_mac_metadata(a->entry, &metadata_size); + if (metadata != NULL && metadata_size > 0) { + fe = current_fixup(a, archive_entry_pathname(entry)); + if (fe == NULL) + return (ARCHIVE_FATAL); + fe->mac_metadata = malloc(metadata_size); + if (fe->mac_metadata != NULL) { - memcpy(fe->mac_metadata, metadata, metadata_size); ++ memcpy(fe->mac_metadata, metadata, ++ metadata_size); + fe->mac_metadata_size = metadata_size; + fe->fixup |= TODO_MAC_METADATA; + } + } + } + + if (a->deferred & TODO_FFLAGS) { + fe = current_fixup(a, archive_entry_pathname(entry)); + if (fe == NULL) + return (ARCHIVE_FATAL); + fe->fixup |= TODO_FFLAGS; + /* TODO: Complete this.. defer fflags from below. */ + } + + /* We've created the object and are ready to pour data into it. */ + if (ret >= ARCHIVE_WARN) + a->archive.state = ARCHIVE_STATE_DATA; + /* + * If it's not open, tell our client not to try writing. + * In particular, dirs, links, etc, don't get written to. + */ + if (a->fd < 0) { + archive_entry_set_size(entry, 0); + a->filesize = 0; + } + + return (ret); +} + +int +archive_write_disk_set_skip_file(struct archive *_a, int64_t d, int64_t i) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_write_disk_set_skip_file"); + a->skip_file_set = 1; + a->skip_file_dev = d; + a->skip_file_ino = i; + return (ARCHIVE_OK); +} + +static ssize_t +write_data_block(struct archive_write_disk *a, const char *buff, size_t size) +{ + uint64_t start_size = size; + ssize_t bytes_written = 0; + ssize_t block_size = 0, bytes_to_write; + + if (size == 0) + return (ARCHIVE_OK); + + if (a->filesize == 0 || a->fd < 0) { + archive_set_error(&a->archive, 0, + "Attempt to write to an empty file"); + return (ARCHIVE_WARN); + } + + if (a->flags & ARCHIVE_EXTRACT_SPARSE) { +#if HAVE_STRUCT_STAT_ST_BLKSIZE + int r; + if ((r = lazy_stat(a)) != ARCHIVE_OK) + return (r); + block_size = a->pst->st_blksize; +#else + /* XXX TODO XXX Is there a more appropriate choice here ? */ + /* This needn't match the filesystem allocation size. */ + block_size = 16*1024; +#endif + } + + /* If this write would run beyond the file size, truncate it. */ + if (a->filesize >= 0 && (int64_t)(a->offset + size) > a->filesize) + start_size = size = (size_t)(a->filesize - a->offset); + + /* Write the data. */ + while (size > 0) { + if (block_size == 0) { + bytes_to_write = size; + } else { + /* We're sparsifying the file. */ + const char *p, *end; + int64_t block_end; + + /* Skip leading zero bytes. */ + for (p = buff, end = buff + size; p < end; ++p) { + if (*p != '\0') + break; + } + a->offset += p - buff; + size -= p - buff; + buff = p; + if (size == 0) + break; + + /* Calculate next block boundary after offset. */ + block_end + = (a->offset / block_size + 1) * block_size; + + /* If the adjusted write would cross block boundary, + * truncate it to the block boundary. */ + bytes_to_write = size; + if (a->offset + bytes_to_write > block_end) + bytes_to_write = block_end - a->offset; + } + /* Seek if necessary to the specified offset. */ + if (a->offset != a->fd_offset) { + if (lseek(a->fd, a->offset, SEEK_SET) < 0) { + archive_set_error(&a->archive, errno, + "Seek failed"); + return (ARCHIVE_FATAL); + } + a->fd_offset = a->offset; + } + bytes_written = write(a->fd, buff, bytes_to_write); + if (bytes_written < 0) { + archive_set_error(&a->archive, errno, "Write failed"); + return (ARCHIVE_WARN); + } + buff += bytes_written; + size -= bytes_written; + a->total_bytes_written += bytes_written; + a->offset += bytes_written; + a->fd_offset = a->offset; + } + return (start_size - size); +} + +#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_SYS_XATTR_H)\ + && defined(HAVE_ZLIB_H) + +/* + * Set UF_COMPRESSED file flag. + * This have to be called after hfs_write_decmpfs() because if the + * file does not have "com.apple.decmpfs" xattr the flag is ignored. + */ +static int +hfs_set_compressed_fflag(struct archive_write_disk *a) +{ + int r; + + if ((r = lazy_stat(a)) != ARCHIVE_OK) + return (r); + + a->st.st_flags |= UF_COMPRESSED; + if (fchflags(a->fd, a->st.st_flags) != 0) { + archive_set_error(&a->archive, errno, + "Failed to set UF_COMPRESSED file flag"); + return (ARCHIVE_WARN); + } + return (ARCHIVE_OK); +} + +/* + * HFS+ Compression decmpfs + * + * +------------------------------+ +0 + * | Magic(LE 4 bytes) | + * +------------------------------+ + * | Type(LE 4 bytes) | + * +------------------------------+ + * | Uncompressed size(LE 8 bytes)| + * +------------------------------+ +16 + * | | + * | Compressed data | + * | (Placed only if Type == 3) | + * | | + * +------------------------------+ +3802 = MAX_DECMPFS_XATTR_SIZE + * + * Type is 3: decmpfs has compressed data. + * Type is 4: Resource Fork has compressed data. + */ +/* + * Write "com.apple.decmpfs" + */ +static int +hfs_write_decmpfs(struct archive_write_disk *a) +{ + int r; + uint32_t compression_type; + + r = fsetxattr(a->fd, DECMPFS_XATTR_NAME, a->decmpfs_header_p, + a->decmpfs_attr_size, 0, 0); + if (r < 0) { + archive_set_error(&a->archive, errno, + "Cannot restore xattr:%s", DECMPFS_XATTR_NAME); + compression_type = archive_le32dec( + &a->decmpfs_header_p[DECMPFS_COMPRESSION_TYPE]); + if (compression_type == CMP_RESOURCE_FORK) + fremovexattr(a->fd, XATTR_RESOURCEFORK_NAME, + XATTR_SHOWCOMPRESSION); + return (ARCHIVE_WARN); + } + return (ARCHIVE_OK); +} + +/* + * HFS+ Compression Resource Fork + * + * +-----------------------------+ + * | Header(260 bytes) | + * +-----------------------------+ + * | Block count(LE 4 bytes) | + * +-----------------------------+ --+ + * +-- | Offset (LE 4 bytes) | | + * | | [distance from Block count] | | Block 0 + * | +-----------------------------+ | + * | | Compressed size(LE 4 bytes) | | + * | +-----------------------------+ --+ + * | | | + * | | .................. | + * | | | + * | +-----------------------------+ --+ + * | | Offset (LE 4 bytes) | | + * | +-----------------------------+ | Block (Block count -1) + * | | Compressed size(LE 4 bytes) | | + * +-> +-----------------------------+ --+ + * | Compressed data(n bytes) | Block 0 + * +-----------------------------+ + * | | + * | .................. | + * | | + * +-----------------------------+ + * | Compressed data(n bytes) | Block (Block count -1) + * +-----------------------------+ + * | Footer(50 bytes) | + * +-----------------------------+ + * + */ +/* + * Write the header of "com.apple.ResourceFork" + */ +static int +hfs_write_resource_fork(struct archive_write_disk *a, unsigned char *buff, + size_t bytes, uint32_t position) +{ + int ret; + + ret = fsetxattr(a->fd, XATTR_RESOURCEFORK_NAME, buff, bytes, + position, a->rsrc_xattr_options); + if (ret < 0) { + archive_set_error(&a->archive, errno, + "Cannot restore xattr: %s at %u pos %u bytes", + XATTR_RESOURCEFORK_NAME, + (unsigned)position, + (unsigned)bytes); + return (ARCHIVE_WARN); + } + a->rsrc_xattr_options &= ~XATTR_CREATE; + return (ARCHIVE_OK); +} + +static int +hfs_write_compressed_data(struct archive_write_disk *a, size_t bytes_compressed) +{ + int ret; + + ret = hfs_write_resource_fork(a, a->compressed_buffer, + bytes_compressed, a->compressed_rsrc_position); + if (ret == ARCHIVE_OK) + a->compressed_rsrc_position += bytes_compressed; + return (ret); +} + +static int +hfs_write_resource_fork_header(struct archive_write_disk *a) +{ + unsigned char *buff; + uint32_t rsrc_bytes; + uint32_t rsrc_header_bytes; + + /* + * Write resource fork header + block info. + */ + buff = a->resource_fork; + rsrc_bytes = a->compressed_rsrc_position - RSRC_F_SIZE; + rsrc_header_bytes = + RSRC_H_SIZE + /* Header base size. */ + 4 + /* Block count. */ + (a->decmpfs_block_count * 8);/* Block info */ + archive_be32enc(buff, 0x100); + archive_be32enc(buff + 4, rsrc_bytes); + archive_be32enc(buff + 8, rsrc_bytes - 256); + archive_be32enc(buff + 12, 0x32); + memset(buff + 16, 0, 240); + archive_be32enc(buff + 256, rsrc_bytes - 260); + return hfs_write_resource_fork(a, buff, rsrc_header_bytes, 0); +} + +static size_t +hfs_set_resource_fork_footer(unsigned char *buff, size_t buff_size) +{ + static const char rsrc_footer[RSRC_F_SIZE] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1c, 0x00, 0x32, 0x00, 0x00, 'c', 'm', + 'p', 'f', 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 + }; + if (buff_size < sizeof(rsrc_footer)) + return (0); + memcpy(buff, rsrc_footer, sizeof(rsrc_footer)); + return (sizeof(rsrc_footer)); +} + +static int +hfs_reset_compressor(struct archive_write_disk *a) +{ + int ret; + + if (a->stream_valid) + ret = deflateReset(&a->stream); + else + ret = deflateInit(&a->stream, a->decmpfs_compression_level); + + if (ret != Z_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to initialize compressor"); + return (ARCHIVE_FATAL); + } else + a->stream_valid = 1; + + return (ARCHIVE_OK); +} + +static int +hfs_decompress(struct archive_write_disk *a) +{ + uint32_t *block_info; + unsigned int block_count; + uint32_t data_pos, data_size; + ssize_t r; + ssize_t bytes_written, bytes_to_write; + unsigned char *b; + + block_info = (uint32_t *)(a->resource_fork + RSRC_H_SIZE); + block_count = archive_le32dec(block_info++); + while (block_count--) { + data_pos = RSRC_H_SIZE + archive_le32dec(block_info++); + data_size = archive_le32dec(block_info++); + r = fgetxattr(a->fd, XATTR_RESOURCEFORK_NAME, + a->compressed_buffer, data_size, data_pos, 0); + if (r != data_size) { + archive_set_error(&a->archive, + (r < 0)?errno:ARCHIVE_ERRNO_MISC, + "Failed to read resource fork"); + return (ARCHIVE_WARN); + } + if (a->compressed_buffer[0] == 0xff) { + bytes_to_write = data_size -1; + b = a->compressed_buffer + 1; + } else { + uLong dest_len = MAX_DECMPFS_BLOCK_SIZE; + int zr; + + zr = uncompress((Bytef *)a->uncompressed_buffer, + &dest_len, a->compressed_buffer, data_size); + if (zr != Z_OK) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Failed to decompress resource fork"); + return (ARCHIVE_WARN); + } + bytes_to_write = dest_len; + b = (unsigned char *)a->uncompressed_buffer; + } + do { + bytes_written = write(a->fd, b, bytes_to_write); + if (bytes_written < 0) { + archive_set_error(&a->archive, errno, + "Write failed"); + return (ARCHIVE_WARN); + } + bytes_to_write -= bytes_written; + b += bytes_written; + } while (bytes_to_write > 0); + } + r = fremovexattr(a->fd, XATTR_RESOURCEFORK_NAME, 0); + if (r == -1) { + archive_set_error(&a->archive, errno, + "Failed to remove resource fork"); + return (ARCHIVE_WARN); + } + return (ARCHIVE_OK); +} + +static int +hfs_drive_compressor(struct archive_write_disk *a, const char *buff, + size_t size) +{ + unsigned char *buffer_compressed; + size_t bytes_compressed; + size_t bytes_used; + int ret; + + ret = hfs_reset_compressor(a); + if (ret != ARCHIVE_OK) + return (ret); + + if (a->compressed_buffer == NULL) { + size_t block_size; + + block_size = COMPRESSED_W_SIZE + RSRC_F_SIZE + + + compressBound(MAX_DECMPFS_BLOCK_SIZE); + a->compressed_buffer = malloc(block_size); + if (a->compressed_buffer == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Resource Fork"); + return (ARCHIVE_FATAL); + } + a->compressed_buffer_size = block_size; + a->compressed_buffer_remaining = block_size; + } + + buffer_compressed = a->compressed_buffer + + a->compressed_buffer_size - a->compressed_buffer_remaining; + a->stream.next_in = (Bytef *)(uintptr_t)(const void *)buff; + a->stream.avail_in = size; + a->stream.next_out = buffer_compressed; + a->stream.avail_out = a->compressed_buffer_remaining; + do { + ret = deflate(&a->stream, Z_FINISH); + switch (ret) { + case Z_OK: + case Z_STREAM_END: + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to compress data"); + return (ARCHIVE_FAILED); + } + } while (ret == Z_OK); + bytes_compressed = a->compressed_buffer_remaining - a->stream.avail_out; + + /* + * If the compressed size is larger than the original size, + * throw away compressed data, use uncompressed data instead. + */ + if (bytes_compressed > size) { + buffer_compressed[0] = 0xFF;/* uncompressed marker. */ + memcpy(buffer_compressed + 1, buff, size); + bytes_compressed = size + 1; + } + a->compressed_buffer_remaining -= bytes_compressed; + + /* + * If the compressed size is smaller than MAX_DECMPFS_XATTR_SIZE + * and the block count in the file is only one, store compressed + * data to decmpfs xattr instead of the resource fork. + */ + if (a->decmpfs_block_count == 1 && + (a->decmpfs_attr_size + bytes_compressed) + <= MAX_DECMPFS_XATTR_SIZE) { + archive_le32enc(&a->decmpfs_header_p[DECMPFS_COMPRESSION_TYPE], + CMP_XATTR); + memcpy(a->decmpfs_header_p + DECMPFS_HEADER_SIZE, + buffer_compressed, bytes_compressed); + a->decmpfs_attr_size += bytes_compressed; + a->compressed_buffer_remaining = a->compressed_buffer_size; + /* + * Finish HFS+ Compression. + * - Write the decmpfs xattr. + * - Set the UF_COMPRESSED file flag. + */ + ret = hfs_write_decmpfs(a); + if (ret == ARCHIVE_OK) + ret = hfs_set_compressed_fflag(a); + return (ret); + } + + /* Update block info. */ + archive_le32enc(a->decmpfs_block_info++, + a->compressed_rsrc_position_v - RSRC_H_SIZE); + archive_le32enc(a->decmpfs_block_info++, bytes_compressed); + a->compressed_rsrc_position_v += bytes_compressed; + + /* + * Write the compressed data to the resource fork. + */ + bytes_used = a->compressed_buffer_size - a->compressed_buffer_remaining; + while (bytes_used >= COMPRESSED_W_SIZE) { + ret = hfs_write_compressed_data(a, COMPRESSED_W_SIZE); + if (ret != ARCHIVE_OK) + return (ret); + bytes_used -= COMPRESSED_W_SIZE; + if (bytes_used > COMPRESSED_W_SIZE) + memmove(a->compressed_buffer, + a->compressed_buffer + COMPRESSED_W_SIZE, + bytes_used); + else + memcpy(a->compressed_buffer, + a->compressed_buffer + COMPRESSED_W_SIZE, + bytes_used); + } + a->compressed_buffer_remaining = a->compressed_buffer_size - bytes_used; + + /* + * If the current block is the last block, write the remaining + * compressed data and the resource fork footer. + */ + if (a->file_remaining_bytes == 0) { + size_t rsrc_size; + int64_t bk; + + /* Append the resource footer. */ + rsrc_size = hfs_set_resource_fork_footer( + a->compressed_buffer + bytes_used, + a->compressed_buffer_remaining); + ret = hfs_write_compressed_data(a, bytes_used + rsrc_size); + a->compressed_buffer_remaining = a->compressed_buffer_size; + - /* If the compressed size is not enouph smaller than ++ /* If the compressed size is not enough smaller than + * the uncompressed size. cancel HFS+ compression. + * TODO: study a behavior of ditto utility and improve + * the condition to fall back into no HFS+ compression. */ + bk = HFS_BLOCKS(a->compressed_rsrc_position); + bk += bk >> 7; + if (bk > HFS_BLOCKS(a->filesize)) + return hfs_decompress(a); + /* + * Write the resourcefork header. + */ + if (ret == ARCHIVE_OK) + ret = hfs_write_resource_fork_header(a); + /* + * Finish HFS+ Compression. + * - Write the decmpfs xattr. + * - Set the UF_COMPRESSED file flag. + */ + if (ret == ARCHIVE_OK) + ret = hfs_write_decmpfs(a); + if (ret == ARCHIVE_OK) + ret = hfs_set_compressed_fflag(a); + } + return (ret); +} + +static ssize_t +hfs_write_decmpfs_block(struct archive_write_disk *a, const char *buff, + size_t size) +{ + const char *buffer_to_write; + size_t bytes_to_write; + int ret; + + if (a->decmpfs_block_count == (unsigned)-1) { + void *new_block; + size_t new_size; + unsigned int block_count; + + if (a->decmpfs_header_p == NULL) { + new_block = malloc(MAX_DECMPFS_XATTR_SIZE + + sizeof(uint32_t)); + if (new_block == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for decmpfs"); + return (ARCHIVE_FATAL); + } + a->decmpfs_header_p = new_block; + } + a->decmpfs_attr_size = DECMPFS_HEADER_SIZE; + archive_le32enc(&a->decmpfs_header_p[DECMPFS_COMPRESSION_MAGIC], + DECMPFS_MAGIC); + archive_le32enc(&a->decmpfs_header_p[DECMPFS_COMPRESSION_TYPE], + CMP_RESOURCE_FORK); + archive_le64enc(&a->decmpfs_header_p[DECMPFS_UNCOMPRESSED_SIZE], + a->filesize); + + /* Calculate a block count of the file. */ + block_count = + (a->filesize + MAX_DECMPFS_BLOCK_SIZE -1) / + MAX_DECMPFS_BLOCK_SIZE; + /* + * Allocate buffer for resource fork. + * Set up related pointers; + */ + new_size = + RSRC_H_SIZE + /* header */ + 4 + /* Block count */ + (block_count * sizeof(uint32_t) * 2) + + RSRC_F_SIZE; /* footer */ + if (new_size > a->resource_fork_allocated_size) { + new_block = realloc(a->resource_fork, new_size); + if (new_block == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for ResourceFork"); + return (ARCHIVE_FATAL); + } + a->resource_fork_allocated_size = new_size; + a->resource_fork = new_block; + } + + /* Allocate uncompressed buffer */ + if (a->uncompressed_buffer == NULL) { + new_block = malloc(MAX_DECMPFS_BLOCK_SIZE); + if (new_block == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for decmpfs"); + return (ARCHIVE_FATAL); + } + a->uncompressed_buffer = new_block; + } + a->block_remaining_bytes = MAX_DECMPFS_BLOCK_SIZE; + a->file_remaining_bytes = a->filesize; + a->compressed_buffer_remaining = a->compressed_buffer_size; + + /* + * Set up a resource fork. + */ + a->rsrc_xattr_options = XATTR_CREATE; + /* Get the position where we are going to set a bunch + * of block info. */ + a->decmpfs_block_info = + (uint32_t *)(a->resource_fork + RSRC_H_SIZE); + /* Set the block count to the resource fork. */ + archive_le32enc(a->decmpfs_block_info++, block_count); - /* Get the position where we are goint to set compressed ++ /* Get the position where we are going to set compressed + * data. */ + a->compressed_rsrc_position = + RSRC_H_SIZE + 4 + (block_count * 8); + a->compressed_rsrc_position_v = a->compressed_rsrc_position; + a->decmpfs_block_count = block_count; + } + + /* Ignore redundant bytes. */ + if (a->file_remaining_bytes == 0) + return ((ssize_t)size); + + /* Do not overrun a block size. */ + if (size > a->block_remaining_bytes) + bytes_to_write = a->block_remaining_bytes; + else + bytes_to_write = size; + /* Do not overrun the file size. */ + if (bytes_to_write > a->file_remaining_bytes) + bytes_to_write = a->file_remaining_bytes; + + /* For efficiency, if a copy length is full of the uncompressed + * buffer size, do not copy writing data to it. */ + if (bytes_to_write == MAX_DECMPFS_BLOCK_SIZE) + buffer_to_write = buff; + else { + memcpy(a->uncompressed_buffer + + MAX_DECMPFS_BLOCK_SIZE - a->block_remaining_bytes, + buff, bytes_to_write); + buffer_to_write = a->uncompressed_buffer; + } + a->block_remaining_bytes -= bytes_to_write; + a->file_remaining_bytes -= bytes_to_write; + + if (a->block_remaining_bytes == 0 || a->file_remaining_bytes == 0) { + ret = hfs_drive_compressor(a, buffer_to_write, + MAX_DECMPFS_BLOCK_SIZE - a->block_remaining_bytes); + if (ret < 0) + return (ret); + a->block_remaining_bytes = MAX_DECMPFS_BLOCK_SIZE; + } + /* Ignore redundant bytes. */ + if (a->file_remaining_bytes == 0) + return ((ssize_t)size); + return (bytes_to_write); +} + +static ssize_t +hfs_write_data_block(struct archive_write_disk *a, const char *buff, + size_t size) +{ + uint64_t start_size = size; + ssize_t bytes_written = 0; + ssize_t bytes_to_write; + + if (size == 0) + return (ARCHIVE_OK); + + if (a->filesize == 0 || a->fd < 0) { + archive_set_error(&a->archive, 0, + "Attempt to write to an empty file"); + return (ARCHIVE_WARN); + } + + /* If this write would run beyond the file size, truncate it. */ + if (a->filesize >= 0 && (int64_t)(a->offset + size) > a->filesize) + start_size = size = (size_t)(a->filesize - a->offset); + + /* Write the data. */ + while (size > 0) { + bytes_to_write = size; + /* Seek if necessary to the specified offset. */ + if (a->offset < a->fd_offset) { - /* Can't support backword move. */ ++ /* Can't support backward move. */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Seek failed"); + return (ARCHIVE_FATAL); + } else if (a->offset > a->fd_offset) { + int64_t skip = a->offset - a->fd_offset; + char nullblock[1024]; + + memset(nullblock, 0, sizeof(nullblock)); + while (skip > 0) { + if (skip > (int64_t)sizeof(nullblock)) + bytes_written = hfs_write_decmpfs_block( + a, nullblock, sizeof(nullblock)); + else + bytes_written = hfs_write_decmpfs_block( + a, nullblock, skip); + if (bytes_written < 0) { + archive_set_error(&a->archive, errno, + "Write failed"); + return (ARCHIVE_WARN); + } + skip -= bytes_written; + } + + a->fd_offset = a->offset; + } + bytes_written = + hfs_write_decmpfs_block(a, buff, bytes_to_write); + if (bytes_written < 0) + return (bytes_written); + buff += bytes_written; + size -= bytes_written; + a->total_bytes_written += bytes_written; + a->offset += bytes_written; + a->fd_offset = a->offset; + } + return (start_size - size); +} +#else +static ssize_t +hfs_write_data_block(struct archive_write_disk *a, const char *buff, + size_t size) +{ + return (write_data_block(a, buff, size)); +} +#endif + +static ssize_t +_archive_write_disk_data_block(struct archive *_a, + const void *buff, size_t size, int64_t offset) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + ssize_t r; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_DATA, "archive_write_data_block"); + + a->offset = offset; + if (a->todo & TODO_HFS_COMPRESSION) + r = hfs_write_data_block(a, buff, size); + else + r = write_data_block(a, buff, size); + if (r < ARCHIVE_OK) + return (r); + if ((size_t)r < size) { + archive_set_error(&a->archive, 0, - "Too much data: Truncating file at %ju bytes", (uintmax_t)a->filesize); ++ "Too much data: Truncating file at %ju bytes", ++ (uintmax_t)a->filesize); + return (ARCHIVE_WARN); + } +#if ARCHIVE_VERSION_NUMBER < 3999000 + return (ARCHIVE_OK); +#else + return (size); +#endif +} + +static ssize_t +_archive_write_disk_data(struct archive *_a, const void *buff, size_t size) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_DATA, "archive_write_data"); + + if (a->todo & TODO_HFS_COMPRESSION) + return (hfs_write_data_block(a, buff, size)); + return (write_data_block(a, buff, size)); +} + +static int +_archive_write_disk_finish_entry(struct archive *_a) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + int ret = ARCHIVE_OK; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, + "archive_write_finish_entry"); + if (a->archive.state & ARCHIVE_STATE_HEADER) + return (ARCHIVE_OK); + archive_clear_error(&a->archive); + + /* Pad or truncate file to the right size. */ + if (a->fd < 0) { + /* There's no file. */ + } else if (a->filesize < 0) { + /* File size is unknown, so we can't set the size. */ + } else if (a->fd_offset == a->filesize) { + /* Last write ended at exactly the filesize; we're done. */ + /* Hopefully, this is the common case. */ +#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_ZLIB_H) + } else if (a->todo & TODO_HFS_COMPRESSION) { + char null_d[1024]; + ssize_t r; + + if (a->file_remaining_bytes) + memset(null_d, 0, sizeof(null_d)); + while (a->file_remaining_bytes) { + if (a->file_remaining_bytes > sizeof(null_d)) + r = hfs_write_data_block( + a, null_d, sizeof(null_d)); + else + r = hfs_write_data_block( + a, null_d, a->file_remaining_bytes); + if (r < 0) + return ((int)r); + } +#endif + } else { +#if HAVE_FTRUNCATE + if (ftruncate(a->fd, a->filesize) == -1 && + a->filesize == 0) { + archive_set_error(&a->archive, errno, + "File size could not be restored"); + return (ARCHIVE_FAILED); + } +#endif + /* + * Not all platforms implement the XSI option to + * extend files via ftruncate. Stat() the file again + * to see what happened. + */ + a->pst = NULL; + if ((ret = lazy_stat(a)) != ARCHIVE_OK) + return (ret); + /* We can use lseek()/write() to extend the file if + * ftruncate didn't work or isn't available. */ + if (a->st.st_size < a->filesize) { + const char nul = '\0'; + if (lseek(a->fd, a->filesize - 1, SEEK_SET) < 0) { + archive_set_error(&a->archive, errno, + "Seek failed"); + return (ARCHIVE_FATAL); + } + if (write(a->fd, &nul, 1) < 0) { + archive_set_error(&a->archive, errno, + "Write to restore size failed"); + return (ARCHIVE_FATAL); + } + a->pst = NULL; + } + } + + /* Restore metadata. */ + + /* + * This is specific to Mac OS X. + * If the current file is an AppleDouble file, it should be + * linked with the data fork file and remove it. + */ + if (a->todo & TODO_APPLEDOUBLE) { + int r2 = fixup_appledouble(a, a->name); + if (r2 == ARCHIVE_EOF) { + /* The current file has been successfully linked + * with the data fork file and removed. So there + * is nothing to do on the current file. */ + goto finish_metadata; + } + if (r2 < ret) ret = r2; + } + + /* + * Look up the "real" UID only if we're going to need it. + * TODO: the TODO_SGID condition can be dropped here, can't it? + */ + if (a->todo & (TODO_OWNER | TODO_SUID | TODO_SGID)) { + a->uid = archive_write_disk_uid(&a->archive, + archive_entry_uname(a->entry), + archive_entry_uid(a->entry)); + } + /* Look up the "real" GID only if we're going to need it. */ + /* TODO: the TODO_SUID condition can be dropped here, can't it? */ + if (a->todo & (TODO_OWNER | TODO_SGID | TODO_SUID)) { + a->gid = archive_write_disk_gid(&a->archive, + archive_entry_gname(a->entry), + archive_entry_gid(a->entry)); + } + + /* + * Restore ownership before set_mode tries to restore suid/sgid + * bits. If we set the owner, we know what it is and can skip + * a stat() call to examine the ownership of the file on disk. + */ + if (a->todo & TODO_OWNER) { + int r2 = set_ownership(a); + if (r2 < ret) ret = r2; + } + + /* + * set_mode must precede ACLs on systems such as Solaris and + * FreeBSD where setting the mode implicitly clears extended ACLs + */ + if (a->todo & TODO_MODE) { + int r2 = set_mode(a, a->mode); + if (r2 < ret) ret = r2; + } + + /* + * Security-related extended attributes (such as + * security.capability on Linux) have to be restored last, + * since they're implicitly removed by other file changes. + */ + if (a->todo & TODO_XATTR) { + int r2 = set_xattrs(a); + if (r2 < ret) ret = r2; + } + + /* + * Some flags prevent file modification; they must be restored after + * file contents are written. + */ + if (a->todo & TODO_FFLAGS) { + int r2 = set_fflags(a); + if (r2 < ret) ret = r2; + } + + /* + * Time must follow most other metadata; + * otherwise atime will get changed. + */ + if (a->todo & TODO_TIMES) { + int r2 = set_times_from_entry(a); + if (r2 < ret) ret = r2; + } + + /* + * Mac extended metadata includes ACLs. + */ + if (a->todo & TODO_MAC_METADATA) { + const void *metadata; + size_t metadata_size; + metadata = archive_entry_mac_metadata(a->entry, &metadata_size); + if (metadata != NULL && metadata_size > 0) { + int r2 = set_mac_metadata(a, archive_entry_pathname( + a->entry), metadata, metadata_size); + if (r2 < ret) ret = r2; + } + } + + /* + * ACLs must be restored after timestamps because there are + * ACLs that prevent attribute changes (including time). + */ + if (a->todo & TODO_ACLS) { - int r2 = archive_write_disk_set_acls(&a->archive, a->fd, - archive_entry_pathname(a->entry), - archive_entry_acl(a->entry)); ++ 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 (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)); + if (r2 < ret) ret = r2; ++#ifdef HAVE_DARWIN_ACL ++ } ++#endif + } + +finish_metadata: + /* If there's an fd, we can close it now. */ + if (a->fd >= 0) { + close(a->fd); + a->fd = -1; + } + /* If there's an entry, we can release it now. */ + if (a->entry) { + archive_entry_free(a->entry); + a->entry = NULL; + } + a->archive.state = ARCHIVE_STATE_HEADER; + return (ret); +} + +int +archive_write_disk_set_group_lookup(struct archive *_a, + void *private_data, + int64_t (*lookup_gid)(void *private, const char *gname, int64_t gid), + void (*cleanup_gid)(void *private)) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_write_disk_set_group_lookup"); + + if (a->cleanup_gid != NULL && a->lookup_gid_data != NULL) + (a->cleanup_gid)(a->lookup_gid_data); + + a->lookup_gid = lookup_gid; + a->cleanup_gid = cleanup_gid; + a->lookup_gid_data = private_data; + return (ARCHIVE_OK); +} + +int +archive_write_disk_set_user_lookup(struct archive *_a, + void *private_data, + int64_t (*lookup_uid)(void *private, const char *uname, int64_t uid), + void (*cleanup_uid)(void *private)) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_write_disk_set_user_lookup"); + + if (a->cleanup_uid != NULL && a->lookup_uid_data != NULL) + (a->cleanup_uid)(a->lookup_uid_data); + + a->lookup_uid = lookup_uid; + a->cleanup_uid = cleanup_uid; + a->lookup_uid_data = private_data; + return (ARCHIVE_OK); +} + +int64_t +archive_write_disk_gid(struct archive *_a, const char *name, int64_t id) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_write_disk_gid"); + if (a->lookup_gid) + return (a->lookup_gid)(a->lookup_gid_data, name, id); + return (id); +} + +int64_t +archive_write_disk_uid(struct archive *_a, const char *name, int64_t id) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_write_disk_uid"); + if (a->lookup_uid) + return (a->lookup_uid)(a->lookup_uid_data, name, id); + return (id); +} + +/* + * Create a new archive_write_disk object and initialize it with global state. + */ +struct archive * +archive_write_disk_new(void) +{ + struct archive_write_disk *a; + - a = (struct archive_write_disk *)malloc(sizeof(*a)); ++ a = (struct archive_write_disk *)calloc(1, sizeof(*a)); + if (a == NULL) + return (NULL); - memset(a, 0, sizeof(*a)); + a->archive.magic = ARCHIVE_WRITE_DISK_MAGIC; + /* We're ready to write a header immediately. */ + a->archive.state = ARCHIVE_STATE_HEADER; + a->archive.vtable = archive_write_disk_vtable(); + a->start_time = time(NULL); + /* Query and restore the umask. */ + umask(a->user_umask = umask(0)); +#ifdef HAVE_GETEUID + a->user_uid = geteuid(); +#endif /* HAVE_GETEUID */ + if (archive_string_ensure(&a->path_safe, 512) == NULL) { + free(a); + return (NULL); + } +#ifdef HAVE_ZLIB_H + a->decmpfs_compression_level = 5; +#endif + return (&a->archive); +} + + +/* + * If pathname is longer than PATH_MAX, chdir to a suitable + * intermediate dir and edit the path down to a shorter suffix. Note + * that this routine never returns an error; if the chdir() attempt + * fails for any reason, we just go ahead with the long pathname. The + * object creation is likely to fail, but any error will get handled + * at that time. + */ +#if defined(HAVE_FCHDIR) && defined(PATH_MAX) +static void +edit_deep_directories(struct archive_write_disk *a) +{ + int ret; + char *tail = a->name; + + /* If path is short, avoid the open() below. */ - if (strlen(tail) <= PATH_MAX) ++ if (strlen(tail) < PATH_MAX) + return; + + /* Try to record our starting dir. */ + a->restore_pwd = open(".", O_RDONLY | O_BINARY | O_CLOEXEC); + __archive_ensure_cloexec_flag(a->restore_pwd); + if (a->restore_pwd < 0) + return; + + /* As long as the path is too long... */ - while (strlen(tail) > PATH_MAX) { ++ while (strlen(tail) >= PATH_MAX) { + /* Locate a dir prefix shorter than PATH_MAX. */ + tail += PATH_MAX - 8; + while (tail > a->name && *tail != '/') + tail--; + /* Exit if we find a too-long path component. */ + if (tail <= a->name) + return; + /* Create the intermediate dir and chdir to it. */ + *tail = '\0'; /* Terminate dir portion */ + ret = create_dir(a, a->name); + if (ret == ARCHIVE_OK && chdir(a->name) != 0) + ret = ARCHIVE_FAILED; + *tail = '/'; /* Restore the / we removed. */ + if (ret != ARCHIVE_OK) + return; + tail++; + /* The chdir() succeeded; we've now shortened the path. */ + a->name = tail; + } + return; +} +#endif + +/* + * The main restore function. + */ +static int +restore_entry(struct archive_write_disk *a) +{ + int ret = ARCHIVE_OK, en; + + if (a->flags & ARCHIVE_EXTRACT_UNLINK && !S_ISDIR(a->mode)) { + /* + * TODO: Fix this. Apparently, there are platforms + * that still allow root to hose the entire filesystem + * by unlinking a dir. The S_ISDIR() test above + * prevents us from using unlink() here if the new + * object is a dir, but that doesn't mean the old + * object isn't a dir. + */ + if (a->flags & ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS) + (void)clear_nochange_fflags(a); + if (unlink(a->name) == 0) { + /* We removed it, reset cached stat. */ + a->pst = NULL; + } else if (errno == ENOENT) { + /* File didn't exist, that's just as good. */ + } else if (rmdir(a->name) == 0) { + /* It was a dir, but now it's gone. */ + a->pst = NULL; + } else { + /* We tried, but couldn't get rid of it. */ + archive_set_error(&a->archive, errno, + "Could not unlink"); + return(ARCHIVE_FAILED); + } + } + + /* Try creating it first; if this fails, we'll try to recover. */ + en = create_filesystem_object(a); + + if ((en == ENOTDIR || en == ENOENT) + && !(a->flags & ARCHIVE_EXTRACT_NO_AUTODIR)) { + /* If the parent dir doesn't exist, try creating it. */ + create_parent_dir(a, a->name); + /* Now try to create the object again. */ + en = create_filesystem_object(a); + } + + if ((en == ENOENT) && (archive_entry_hardlink(a->entry) != NULL)) { + archive_set_error(&a->archive, en, + "Hard-link target '%s' does not exist.", + archive_entry_hardlink(a->entry)); + return (ARCHIVE_FAILED); + } + + if ((en == EISDIR || en == EEXIST) + && (a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) { + /* If we're not overwriting, we're done. */ + archive_entry_unset_size(a->entry); + return (ARCHIVE_OK); + } + + /* + * Some platforms return EISDIR if you call + * open(O_WRONLY | O_EXCL | O_CREAT) on a directory, some + * return EEXIST. POSIX is ambiguous, requiring EISDIR + * for open(O_WRONLY) on a dir and EEXIST for open(O_EXCL | O_CREAT) + * on an existing item. + */ + if (en == EISDIR) { + /* A dir is in the way of a non-dir, rmdir it. */ + if (rmdir(a->name) != 0) { + archive_set_error(&a->archive, errno, + "Can't remove already-existing dir"); + return (ARCHIVE_FAILED); + } + a->pst = NULL; + /* Try again. */ + en = create_filesystem_object(a); + } else if (en == EEXIST) { + /* + * We know something is in the way, but we don't know what; + * we need to find out before we go any further. + */ + int r = 0; + /* + * The SECURE_SYMLINKS logic has already removed a + * symlink to a dir if the client wants that. So + * follow the symlink if we're creating a dir. + */ + if (S_ISDIR(a->mode)) + r = stat(a->name, &a->st); + /* + * If it's not a dir (or it's a broken symlink), + * then don't follow it. + */ + if (r != 0 || !S_ISDIR(a->mode)) + r = lstat(a->name, &a->st); + if (r != 0) { + archive_set_error(&a->archive, errno, + "Can't stat existing object"); + return (ARCHIVE_FAILED); + } + + /* + * NO_OVERWRITE_NEWER doesn't apply to directories. + */ + if ((a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER) + && !S_ISDIR(a->st.st_mode)) { + if (!older(&(a->st), a->entry)) { + archive_entry_unset_size(a->entry); + return (ARCHIVE_OK); + } + } + + /* If it's our archive, we're done. */ + if (a->skip_file_set && + a->st.st_dev == (dev_t)a->skip_file_dev && + a->st.st_ino == (ino_t)a->skip_file_ino) { + archive_set_error(&a->archive, 0, + "Refusing to overwrite archive"); + return (ARCHIVE_FAILED); + } + + if (!S_ISDIR(a->st.st_mode)) { + /* A non-dir is in the way, unlink it. */ + if (a->flags & ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS) + (void)clear_nochange_fflags(a); + if (unlink(a->name) != 0) { + archive_set_error(&a->archive, errno, + "Can't unlink already-existing object"); + return (ARCHIVE_FAILED); + } + a->pst = NULL; + /* Try again. */ + en = create_filesystem_object(a); + } else if (!S_ISDIR(a->mode)) { + /* A dir is in the way of a non-dir, rmdir it. */ + if (a->flags & ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS) + (void)clear_nochange_fflags(a); + if (rmdir(a->name) != 0) { + archive_set_error(&a->archive, errno, + "Can't replace existing directory with non-directory"); + return (ARCHIVE_FAILED); + } + /* Try again. */ + en = create_filesystem_object(a); + } else { + /* + * There's a dir in the way of a dir. Don't + * waste time with rmdir()/mkdir(), just fix + * up the permissions on the existing dir. + * Note that we don't change perms on existing + * dirs unless _EXTRACT_PERM is specified. + */ + if ((a->mode != a->st.st_mode) + && (a->todo & TODO_MODE_FORCE)) + a->deferred |= (a->todo & TODO_MODE); + /* Ownership doesn't need deferred fixup. */ + en = 0; /* Forget the EEXIST. */ + } + } + + if (en) { + /* Everything failed; give up here. */ - archive_set_error(&a->archive, en, "Can't create '%s'", - a->name); ++ if ((&a->archive)->error == NULL) ++ archive_set_error(&a->archive, en, "Can't create '%s'", ++ a->name); + return (ARCHIVE_FAILED); + } + + a->pst = NULL; /* Cached stat data no longer valid. */ + return (ret); +} + +/* + * Returns 0 if creation succeeds, or else returns errno value from + * the failed system call. Note: This function should only ever perform + * a single system call. + */ +static int +create_filesystem_object(struct archive_write_disk *a) +{ + /* Create the entry. */ + const char *linkname; + mode_t final_mode, mode; + int r; ++ /* these for check_symlinks_fsobj */ ++ char *linkname_copy; /* non-const copy of linkname */ ++ struct stat st; ++ struct archive_string error_string; ++ int error_number; + + /* We identify hard/symlinks according to the link names. */ + /* Since link(2) and symlink(2) don't handle modes, we're done here. */ + linkname = archive_entry_hardlink(a->entry); + if (linkname != NULL) { +#if !HAVE_LINK + return (EPERM); +#else ++ archive_string_init(&error_string); ++ linkname_copy = strdup(linkname); ++ if (linkname_copy == NULL) { ++ return (EPERM); ++ } ++ /* ++ * TODO: consider using the cleaned-up path as the link ++ * target? ++ */ ++ r = cleanup_pathname_fsobj(linkname_copy, &error_number, ++ &error_string, a->flags); ++ if (r != ARCHIVE_OK) { ++ archive_set_error(&a->archive, error_number, "%s", ++ error_string.s); ++ free(linkname_copy); ++ archive_string_free(&error_string); ++ /* ++ * EPERM is more appropriate than error_number for our ++ * callers ++ */ ++ return (EPERM); ++ } ++ r = check_symlinks_fsobj(linkname_copy, &error_number, ++ &error_string, a->flags); ++ if (r != ARCHIVE_OK) { ++ archive_set_error(&a->archive, error_number, "%s", ++ error_string.s); ++ free(linkname_copy); ++ archive_string_free(&error_string); ++ /* ++ * EPERM is more appropriate than error_number for our ++ * callers ++ */ ++ return (EPERM); ++ } ++ free(linkname_copy); ++ archive_string_free(&error_string); + r = link(linkname, a->name) ? errno : 0; + /* + * New cpio and pax formats allow hardlink entries + * to carry data, so we may have to open the file + * for hardlink entries. + * + * If the hardlink was successfully created and + * the archive doesn't have carry data for it, + * consider it to be non-authoritative for meta data. + * This is consistent with GNU tar and BSD pax. + * If the hardlink does carry data, let the last + * archive entry decide ownership. + */ + if (r == 0 && a->filesize <= 0) { + a->todo = 0; + a->deferred = 0; + } else if (r == 0 && a->filesize > 0) { - a->fd = open(a->name, - O_WRONLY | O_TRUNC | O_BINARY | O_CLOEXEC); - __archive_ensure_cloexec_flag(a->fd); - if (a->fd < 0) ++#ifdef HAVE_LSTAT ++ r = lstat(a->name, &st); ++#else ++ r = stat(a->name, &st); ++#endif ++ if (r != 0) + r = errno; ++ else if ((st.st_mode & AE_IFMT) == AE_IFREG) { ++ a->fd = open(a->name, O_WRONLY | O_TRUNC | ++ O_BINARY | O_CLOEXEC | O_NOFOLLOW); ++ __archive_ensure_cloexec_flag(a->fd); ++ if (a->fd < 0) ++ r = errno; ++ } + } + return (r); +#endif + } + linkname = archive_entry_symlink(a->entry); + if (linkname != NULL) { +#if HAVE_SYMLINK + return symlink(linkname, a->name) ? errno : 0; +#else + return (EPERM); +#endif + } + + /* + * The remaining system calls all set permissions, so let's + * try to take advantage of that to avoid an extra chmod() + * call. (Recall that umask is set to zero right now!) + */ + + /* Mode we want for the final restored object (w/o file type bits). */ + final_mode = a->mode & 07777; + /* + * The mode that will actually be restored in this step. Note + * that SUID, SGID, etc, require additional work to ensure + * security, so we never restore them at this point. + */ + mode = final_mode & 0777 & ~a->user_umask; + + switch (a->mode & AE_IFMT) { + default: + /* POSIX requires that we fall through here. */ + /* FALLTHROUGH */ + case AE_IFREG: + a->fd = open(a->name, + O_WRONLY | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC, mode); + __archive_ensure_cloexec_flag(a->fd); + r = (a->fd < 0); + break; + case AE_IFCHR: +#ifdef HAVE_MKNOD + /* Note: we use AE_IFCHR for the case label, and + * S_IFCHR for the mknod() call. This is correct. */ + r = mknod(a->name, mode | S_IFCHR, + archive_entry_rdev(a->entry)); + break; +#else + /* TODO: Find a better way to warn about our inability + * to restore a char device node. */ + return (EINVAL); +#endif /* HAVE_MKNOD */ + case AE_IFBLK: +#ifdef HAVE_MKNOD + r = mknod(a->name, mode | S_IFBLK, + archive_entry_rdev(a->entry)); + break; +#else + /* TODO: Find a better way to warn about our inability + * to restore a block device node. */ + return (EINVAL); +#endif /* HAVE_MKNOD */ + case AE_IFDIR: + mode = (mode | MINIMUM_DIR_MODE) & MAXIMUM_DIR_MODE; + r = mkdir(a->name, mode); + if (r == 0) { + /* Defer setting dir times. */ + a->deferred |= (a->todo & TODO_TIMES); + a->todo &= ~TODO_TIMES; + /* Never use an immediate chmod(). */ + /* We can't avoid the chmod() entirely if EXTRACT_PERM + * because of SysV SGID inheritance. */ + if ((mode != final_mode) + || (a->flags & ARCHIVE_EXTRACT_PERM)) + a->deferred |= (a->todo & TODO_MODE); + a->todo &= ~TODO_MODE; + } + break; + case AE_IFIFO: +#ifdef HAVE_MKFIFO + r = mkfifo(a->name, mode); + break; +#else + /* TODO: Find a better way to warn about our inability + * to restore a fifo. */ + return (EINVAL); +#endif /* HAVE_MKFIFO */ + } + + /* All the system calls above set errno on failure. */ + if (r) + return (errno); + + /* If we managed to set the final mode, we've avoided a chmod(). */ + if (mode == final_mode) + a->todo &= ~TODO_MODE; + return (0); +} + +/* + * Cleanup function for archive_extract. Mostly, this involves processing + * the fixup list, which is used to address a number of problems: + * * Dir permissions might prevent us from restoring a file in that + * dir, so we restore the dir with minimum 0700 permissions first, + * then correct the mode at the end. + * * Similarly, the act of restoring a file touches the directory + * and changes the timestamp on the dir, so we have to touch-up dir + * timestamps at the end as well. + * * Some file flags can interfere with the restore by, for example, + * preventing the creation of hardlinks to those files. + * * Mac OS extended metadata includes ACLs, so must be deferred on dirs. + * + * Note that tar/cpio do not require that archives be in a particular + * order; there is no way to know when the last file has been restored + * within a directory, so there's no way to optimize the memory usage + * here by fixing up the directory any earlier than the + * end-of-archive. + * + * XXX TODO: Directory ACLs should be restored here, for the same + * reason we set directory perms here. XXX + */ +static int +_archive_write_disk_close(struct archive *_a) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + struct fixup_entry *next, *p; + int ret; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, + "archive_write_disk_close"); + ret = _archive_write_disk_finish_entry(&a->archive); + + /* Sort dir list so directories are fixed up in depth-first order. */ + p = sort_dir_list(a->fixup_list); + + while (p != NULL) { + a->pst = NULL; /* Mark stat cache as out-of-date. */ + if (p->fixup & TODO_TIMES) { + set_times(a, -1, p->mode, p->name, + p->atime, p->atime_nanos, + p->birthtime, p->birthtime_nanos, + p->mtime, p->mtime_nanos, + p->ctime, p->ctime_nanos); + } + if (p->fixup & TODO_MODE_BASE) + chmod(p->name, p->mode); + if (p->fixup & TODO_ACLS) - archive_write_disk_set_acls(&a->archive, - -1, p->name, &p->acl); ++#ifdef HAVE_DARWIN_ACL ++ if (p->mac_metadata == NULL || ++ p->mac_metadata_size == 0) ++#endif ++ archive_write_disk_set_acls(&a->archive, ++ -1, p->name, &p->acl); + if (p->fixup & TODO_FFLAGS) + set_fflags_platform(a, -1, p->name, + p->mode, p->fflags_set, 0); + if (p->fixup & TODO_MAC_METADATA) + set_mac_metadata(a, p->name, p->mac_metadata, + p->mac_metadata_size); + next = p->next; + archive_acl_clear(&p->acl); + free(p->mac_metadata); + free(p->name); + free(p); + p = next; + } + a->fixup_list = NULL; + return (ret); +} + +static int +_archive_write_disk_free(struct archive *_a) +{ + struct archive_write_disk *a; + int ret; + if (_a == NULL) + return (ARCHIVE_OK); + archive_check_magic(_a, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_write_disk_free"); + a = (struct archive_write_disk *)_a; + ret = _archive_write_disk_close(&a->archive); + archive_write_disk_set_group_lookup(&a->archive, NULL, NULL, NULL); + archive_write_disk_set_user_lookup(&a->archive, NULL, NULL, NULL); + if (a->entry) + archive_entry_free(a->entry); + archive_string_free(&a->_name_data); + archive_string_free(&a->archive.error_string); + archive_string_free(&a->path_safe); + a->archive.magic = 0; + __archive_clean(&a->archive); + free(a->decmpfs_header_p); + free(a->resource_fork); + free(a->compressed_buffer); + free(a->uncompressed_buffer); +#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_SYS_XATTR_H)\ + && defined(HAVE_ZLIB_H) + if (a->stream_valid) { + switch (deflateEnd(&a->stream)) { + case Z_OK: + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to clean up compressor"); + ret = ARCHIVE_FATAL; + break; + } + } +#endif + free(a); + return (ret); +} + +/* + * Simple O(n log n) merge sort to order the fixup list. In + * particular, we want to restore dir timestamps depth-first. + */ +static struct fixup_entry * +sort_dir_list(struct fixup_entry *p) +{ + struct fixup_entry *a, *b, *t; + + if (p == NULL) + return (NULL); + /* A one-item list is already sorted. */ + if (p->next == NULL) + return (p); + + /* Step 1: split the list. */ + t = p; + a = p->next->next; + while (a != NULL) { + /* Step a twice, t once. */ + a = a->next; + if (a != NULL) + a = a->next; + t = t->next; + } + /* Now, t is at the mid-point, so break the list here. */ + b = t->next; + t->next = NULL; + a = p; + + /* Step 2: Recursively sort the two sub-lists. */ + a = sort_dir_list(a); + b = sort_dir_list(b); + + /* Step 3: Merge the returned lists. */ + /* Pick the first element for the merged list. */ + if (strcmp(a->name, b->name) > 0) { + t = p = a; + a = a->next; + } else { + t = p = b; + b = b->next; + } + + /* Always put the later element on the list first. */ + while (a != NULL && b != NULL) { + if (strcmp(a->name, b->name) > 0) { + t->next = a; + a = a->next; + } else { + t->next = b; + b = b->next; + } + t = t->next; + } + + /* Only one list is non-empty, so just splice it on. */ + if (a != NULL) + t->next = a; + if (b != NULL) + t->next = b; + + return (p); +} + +/* + * Returns a new, initialized fixup entry. + * + * TODO: Reduce the memory requirements for this list by using a tree + * structure rather than a simple list of names. + */ +static struct fixup_entry * +new_fixup(struct archive_write_disk *a, const char *pathname) +{ + struct fixup_entry *fe; + + fe = (struct fixup_entry *)calloc(1, sizeof(struct fixup_entry)); + if (fe == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for a fixup"); + return (NULL); + } + fe->next = a->fixup_list; + a->fixup_list = fe; + fe->fixup = 0; + fe->name = strdup(pathname); + return (fe); +} + +/* + * Returns a fixup structure for the current entry. + */ +static struct fixup_entry * +current_fixup(struct archive_write_disk *a, const char *pathname) +{ + if (a->current_fixup == NULL) + a->current_fixup = new_fixup(a, pathname); + return (a->current_fixup); +} + - /* TODO: Make this work. */ - /* - * TODO: The deep-directory support bypasses this; disable deep directory - * support if we're doing symlink checks. - */ ++/* Error helper for new *_fsobj functions */ ++static void ++fsobj_error(int *a_eno, struct archive_string *a_estr, ++ int err, const char *errstr, const char *path) ++{ ++ if (a_eno) ++ *a_eno = err; ++ if (a_estr) ++ archive_string_sprintf(a_estr, errstr, path); ++} ++ +/* + * TODO: Someday, integrate this with the deep dir support; they both + * scan the path and both can be optimized by comparing against other + * recent paths. + */ +/* TODO: Extend this to support symlinks on Windows Vista and later. */ ++ ++/* ++ * Checks the given path to see if any elements along it are symlinks. Returns ++ * ARCHIVE_OK if there are none, otherwise puts an error in errmsg. ++ */ +static int - check_symlinks(struct archive_write_disk *a) ++check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, ++ int flags) +{ +#if !defined(HAVE_LSTAT) + /* Platform doesn't have lstat, so we can't look for symlinks. */ - (void)a; /* UNUSED */ ++ (void)path; /* UNUSED */ ++ (void)error_number; /* UNUSED */ ++ (void)error_string; /* UNUSED */ ++ (void)flags; /* UNUSED */ + return (ARCHIVE_OK); +#else - char *pn; ++ int res = ARCHIVE_OK; ++ char *tail; ++ char *head; ++ int last; + char c; + int r; + struct stat st; ++ int restore_pwd; ++ ++ /* Nothing to do here if name is empty */ ++ if(path[0] == '\0') ++ return (ARCHIVE_OK); + + /* + * Guard against symlink tricks. Reject any archive entry whose + * destination would be altered by a symlink. ++ * ++ * Walk the filename in chunks separated by '/'. For each segment: ++ * - if it doesn't exist, continue ++ * - if it's symlink, abort or remove it ++ * - if it's a directory and it's not the last chunk, cd into it ++ * As we go: ++ * head points to the current (relative) path ++ * tail points to the temporary \0 terminating the segment we're ++ * currently examining ++ * c holds what used to be in *tail ++ * last is 1 if this is the last tail + */ - /* Whatever we checked last time doesn't need to be re-checked. */ - pn = a->name; - if (archive_strlen(&(a->path_safe)) > 0) { - char *p = a->path_safe.s; - while ((*pn != '\0') && (*p == *pn)) - ++p, ++pn; - } ++ restore_pwd = open(".", O_RDONLY | O_BINARY | O_CLOEXEC); ++ __archive_ensure_cloexec_flag(restore_pwd); ++ if (restore_pwd < 0) ++ return (ARCHIVE_FATAL); ++ head = path; ++ tail = path; ++ last = 0; ++ /* TODO: reintroduce a safe cache here? */ + /* Skip the root directory if the path is absolute. */ - if(pn == a->name && pn[0] == '/') - ++pn; - c = pn[0]; - /* Keep going until we've checked the entire name. */ - while (pn[0] != '\0' && (pn[0] != '/' || pn[1] != '\0')) { ++ if(tail == path && tail[0] == '/') ++ ++tail; ++ /* Keep going until we've checked the entire name. ++ * head, tail, path all alias the same string, which is ++ * temporarily zeroed at tail, so be careful restoring the ++ * stashed (c=tail[0]) for error messages. ++ * Exiting the loop with break is okay; continue is not. ++ */ ++ while (!last) { ++ /* ++ * Skip the separator we just consumed, plus any adjacent ones ++ */ ++ while (*tail == '/') ++ ++tail; + /* Skip the next path element. */ - while (*pn != '\0' && *pn != '/') - ++pn; - c = pn[0]; - pn[0] = '\0'; ++ while (*tail != '\0' && *tail != '/') ++ ++tail; ++ /* is this the last path component? */ ++ last = (tail[0] == '\0') || (tail[0] == '/' && tail[1] == '\0'); ++ /* temporarily truncate the string here */ ++ c = tail[0]; ++ tail[0] = '\0'; + /* Check that we haven't hit a symlink. */ - r = lstat(a->name, &st); ++ r = lstat(head, &st); + if (r != 0) { ++ tail[0] = c; + /* We've hit a dir that doesn't exist; stop now. */ - if (errno == ENOENT) ++ if (errno == ENOENT) { ++ break; ++ } else { ++ /* ++ * Treat any other error as fatal - best to be ++ * paranoid here. ++ * Note: This effectively disables deep ++ * directory support when security checks are ++ * enabled. Otherwise, very long pathnames that ++ * trigger an error here could evade the ++ * sandbox. ++ * TODO: We could do better, but it would ++ * probably require merging the symlink checks ++ * with the deep-directory editing. ++ */ ++ fsobj_error(a_eno, a_estr, errno, ++ "Could not stat %s", path); ++ res = ARCHIVE_FAILED; + break; ++ } ++ } else if (S_ISDIR(st.st_mode)) { ++ if (!last) { ++ if (chdir(head) != 0) { ++ tail[0] = c; ++ fsobj_error(a_eno, a_estr, errno, ++ "Could not chdir %s", path); ++ res = (ARCHIVE_FATAL); ++ break; ++ } ++ /* Our view is now from inside this dir: */ ++ head = tail + 1; ++ } + } else if (S_ISLNK(st.st_mode)) { - if (c == '\0') { ++ if (last) { + /* + * Last element is symlink; remove it + * so we can overwrite it with the + * item being extracted. + */ - if (unlink(a->name)) { - archive_set_error(&a->archive, errno, ++ if (unlink(head)) { ++ tail[0] = c; ++ fsobj_error(a_eno, a_estr, errno, + "Could not remove symlink %s", - a->name); - pn[0] = c; - return (ARCHIVE_FAILED); ++ path); ++ res = ARCHIVE_FAILED; ++ break; + } - a->pst = NULL; + /* + * Even if we did remove it, a warning + * is in order. The warning is silly, + * though, if we're just replacing one + * symlink with another symlink. + */ - if (!S_ISLNK(a->mode)) { - archive_set_error(&a->archive, 0, - "Removing symlink %s", - a->name); ++ tail[0] = c; ++ /* ++ * FIXME: not sure how important this is to ++ * restore ++ */ ++ /* ++ if (!S_ISLNK(path)) { ++ fsobj_error(a_eno, a_estr, 0, ++ "Removing symlink %s", path); + } ++ */ + /* Symlink gone. No more problem! */ - pn[0] = c; - return (0); - } else if (a->flags & ARCHIVE_EXTRACT_UNLINK) { ++ res = ARCHIVE_OK; ++ break; ++ } else if (flags & ARCHIVE_EXTRACT_UNLINK) { + /* User asked us to remove problems. */ - if (unlink(a->name) != 0) { - archive_set_error(&a->archive, 0, - "Cannot remove intervening symlink %s", - a->name); - pn[0] = c; - return (ARCHIVE_FAILED); ++ if (unlink(head) != 0) { ++ tail[0] = c; ++ fsobj_error(a_eno, a_estr, 0, ++ "Cannot remove intervening " ++ "symlink %s", path); ++ res = ARCHIVE_FAILED; ++ break; ++ } ++ tail[0] = c; ++ } else if ((flags & ++ ARCHIVE_EXTRACT_SECURE_SYMLINKS) == 0) { ++ /* ++ * We are not the last element and we want to ++ * follow symlinks if they are a directory. ++ * ++ * This is needed to extract hardlinks over ++ * symlinks. ++ */ ++ r = stat(head, &st); ++ if (r != 0) { ++ tail[0] = c; ++ if (errno == ENOENT) { ++ break; ++ } else { ++ fsobj_error(a_eno, a_estr, ++ errno, ++ "Could not stat %s", path); ++ res = (ARCHIVE_FAILED); ++ break; ++ } ++ } else if (S_ISDIR(st.st_mode)) { ++ if (chdir(head) != 0) { ++ tail[0] = c; ++ fsobj_error(a_eno, a_estr, ++ errno, ++ "Could not chdir %s", path); ++ res = (ARCHIVE_FATAL); ++ break; ++ } ++ /* ++ * Our view is now from inside ++ * this dir: ++ */ ++ head = tail + 1; ++ } else { ++ tail[0] = c; ++ fsobj_error(a_eno, a_estr, 0, ++ "Cannot extract through " ++ "symlink %s", path); ++ res = ARCHIVE_FAILED; ++ break; + } - a->pst = NULL; + } else { - archive_set_error(&a->archive, 0, - "Cannot extract through symlink %s", - a->name); - pn[0] = c; - return (ARCHIVE_FAILED); ++ tail[0] = c; ++ fsobj_error(a_eno, a_estr, 0, ++ "Cannot extract through symlink %s", path); ++ res = ARCHIVE_FAILED; ++ break; + } + } - pn[0] = c; - if (pn[0] != '\0') - pn++; /* Advance to the next segment. */ ++ /* be sure to always maintain this */ ++ tail[0] = c; ++ if (tail[0] != '\0') ++ tail++; /* Advance to the next segment. */ ++ } ++ /* Catches loop exits via break */ ++ tail[0] = c; ++#ifdef HAVE_FCHDIR ++ /* If we changed directory above, restore it here. */ ++ if (restore_pwd >= 0) { ++ r = fchdir(restore_pwd); ++ if (r != 0) { ++ fsobj_error(a_eno, a_estr, errno, ++ "chdir() failure", ""); ++ } ++ close(restore_pwd); ++ restore_pwd = -1; ++ if (r != 0) { ++ res = (ARCHIVE_FATAL); ++ } + } - pn[0] = c; - /* We've checked and/or cleaned the whole path, so remember it. */ - archive_strcpy(&a->path_safe, a->name); - return (ARCHIVE_OK); ++#endif ++ /* TODO: reintroduce a safe cache here? */ ++ return res; +#endif +} + ++/* ++ * Check a->name for symlinks, returning ARCHIVE_OK if its clean, otherwise ++ * calls archive_set_error and returns ARCHIVE_{FATAL,FAILED} ++ */ ++static int ++check_symlinks(struct archive_write_disk *a) ++{ ++ struct archive_string error_string; ++ int error_number; ++ int rc; ++ archive_string_init(&error_string); ++ rc = check_symlinks_fsobj(a->name, &error_number, &error_string, ++ a->flags); ++ if (rc != ARCHIVE_OK) { ++ archive_set_error(&a->archive, error_number, "%s", ++ error_string.s); ++ } ++ archive_string_free(&error_string); ++ a->pst = NULL; /* to be safe */ ++ return rc; ++} ++ ++ +#if defined(__CYGWIN__) +/* + * 1. Convert a path separator from '\' to '/' . + * We shouldn't check multibyte character directly because some + * character-set have been using the '\' character for a part of + * its multibyte character code. + * 2. Replace unusable characters in Windows with underscore('_'). + * See also : http://msdn.microsoft.com/en-us/library/aa365247.aspx + */ +static void - cleanup_pathname_win(struct archive_write_disk *a) ++cleanup_pathname_win(char *path) +{ + wchar_t wc; + char *p; + size_t alen, l; + int mb, complete, utf8; + + alen = 0; + mb = 0; + complete = 1; + utf8 = (strcmp(nl_langinfo(CODESET), "UTF-8") == 0)? 1: 0; - for (p = a->name; *p != '\0'; p++) { ++ for (p = path; *p != '\0'; p++) { + ++alen; + if (*p == '\\') { + /* If previous byte is smaller than 128, + * this is not second byte of multibyte characters, + * so we can replace '\' with '/'. */ + if (utf8 || !mb) + *p = '/'; + else + complete = 0;/* uncompleted. */ + } else if (*(unsigned char *)p > 127) + mb = 1; + else + mb = 0; + /* Rewrite the path name if its next character is unusable. */ + if (*p == ':' || *p == '*' || *p == '?' || *p == '"' || + *p == '<' || *p == '>' || *p == '|') + *p = '_'; + } + if (complete) + return; + + /* + * Convert path separator in wide-character. + */ - p = a->name; ++ p = path; + while (*p != '\0' && alen) { + l = mbtowc(&wc, p, alen); + if (l == (size_t)-1) { + while (*p != '\0') { + if (*p == '\\') + *p = '/'; + ++p; + } + break; + } + if (l == 1 && wc == L'\\') + *p = '/'; + p += l; + alen -= l; + } +} +#endif + +/* + * Canonicalize the pathname. In particular, this strips duplicate + * '/' characters, '.' elements, and trailing '/'. It also raises an + * error for an empty path, a trailing '..', (if _SECURE_NODOTDOT is + * set) any '..' in the path or (if ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS + * is set) if the path is absolute. + */ +static int - cleanup_pathname(struct archive_write_disk *a) ++cleanup_pathname_fsobj(char *path, int *a_eno, struct archive_string *a_estr, ++ int flags) +{ + char *dest, *src; + char separator = '\0'; + - dest = src = a->name; ++ dest = src = path; + if (*src == '\0') { - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Invalid empty pathname"); ++ fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC, ++ "Invalid empty ", "pathname"); + return (ARCHIVE_FAILED); + } + +#if defined(__CYGWIN__) - cleanup_pathname_win(a); ++ cleanup_pathname_win(path); +#endif + /* Skip leading '/'. */ + if (*src == '/') { - if (a->flags & ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Path is absolute"); ++ if (flags & ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS) { ++ fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC, ++ "Path is ", "absolute"); + return (ARCHIVE_FAILED); + } + + separator = *src++; + } + + /* Scan the pathname one element at a time. */ + for (;;) { + /* src points to first char after '/' */ + if (src[0] == '\0') { + break; + } else if (src[0] == '/') { + /* Found '//', ignore second one. */ + src++; + continue; + } else if (src[0] == '.') { + if (src[1] == '\0') { + /* Ignore trailing '.' */ + break; + } else if (src[1] == '/') { + /* Skip './'. */ + src += 2; + continue; + } else if (src[1] == '.') { + if (src[2] == '/' || src[2] == '\0') { + /* Conditionally warn about '..' */ - if (a->flags & ARCHIVE_EXTRACT_SECURE_NODOTDOT) { - archive_set_error(&a->archive, ++ if (flags ++ & ARCHIVE_EXTRACT_SECURE_NODOTDOT) { ++ fsobj_error(a_eno, a_estr, + ARCHIVE_ERRNO_MISC, - "Path contains '..'"); ++ "Path contains ", "'..'"); + return (ARCHIVE_FAILED); + } + } + /* + * Note: Under no circumstances do we + * remove '..' elements. In + * particular, restoring + * '/foo/../bar/' should create the + * 'foo' dir as a side-effect. + */ + } + } + + /* Copy current element, including leading '/'. */ + if (separator) + *dest++ = '/'; + while (*src != '\0' && *src != '/') { + *dest++ = *src++; + } + + if (*src == '\0') + break; + + /* Skip '/' separator. */ + separator = *src++; + } + /* + * We've just copied zero or more path elements, not including the + * final '/'. + */ - if (dest == a->name) { ++ if (dest == path) { + /* + * Nothing got copied. The path must have been something + * like '.' or '/' or './' or '/././././/./'. + */ + if (separator) + *dest++ = '/'; + else + *dest++ = '.'; + } + /* Terminate the result. */ + *dest = '\0'; + return (ARCHIVE_OK); +} + ++static int ++cleanup_pathname(struct archive_write_disk *a) ++{ ++ struct archive_string error_string; ++ int error_number; ++ int rc; ++ archive_string_init(&error_string); ++ rc = cleanup_pathname_fsobj(a->name, &error_number, &error_string, ++ a->flags); ++ if (rc != ARCHIVE_OK) { ++ archive_set_error(&a->archive, error_number, "%s", ++ error_string.s); ++ } ++ archive_string_free(&error_string); ++ return rc; ++} ++ +/* + * Create the parent directory of the specified path, assuming path + * is already in mutable storage. + */ +static int +create_parent_dir(struct archive_write_disk *a, char *path) +{ + char *slash; + int r; + + /* Remove tail element to obtain parent name. */ + slash = strrchr(path, '/'); + if (slash == NULL) + return (ARCHIVE_OK); + *slash = '\0'; + r = create_dir(a, path); + *slash = '/'; + return (r); +} + +/* + * Create the specified dir, recursing to create parents as necessary. + * + * Returns ARCHIVE_OK if the path exists when we're done here. + * Otherwise, returns ARCHIVE_FAILED. + * Assumes path is in mutable storage; path is unchanged on exit. + */ +static int +create_dir(struct archive_write_disk *a, char *path) +{ + struct stat st; + struct fixup_entry *le; + char *slash, *base; + mode_t mode_final, mode; + int r; + + /* Check for special names and just skip them. */ + slash = strrchr(path, '/'); + if (slash == NULL) + base = path; + else + base = slash + 1; + + if (base[0] == '\0' || + (base[0] == '.' && base[1] == '\0') || + (base[0] == '.' && base[1] == '.' && base[2] == '\0')) { + /* Don't bother trying to create null path, '.', or '..'. */ + if (slash != NULL) { + *slash = '\0'; + r = create_dir(a, path); + *slash = '/'; + return (r); + } + return (ARCHIVE_OK); + } + + /* + * Yes, this should be stat() and not lstat(). Using lstat() + * here loses the ability to extract through symlinks. Also note + * that this should not use the a->st cache. + */ + if (stat(path, &st) == 0) { + if (S_ISDIR(st.st_mode)) + return (ARCHIVE_OK); + if ((a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) { + archive_set_error(&a->archive, EEXIST, + "Can't create directory '%s'", path); + return (ARCHIVE_FAILED); + } + if (unlink(path) != 0) { + archive_set_error(&a->archive, errno, + "Can't create directory '%s': " + "Conflicting file cannot be removed", + path); + return (ARCHIVE_FAILED); + } + } else if (errno != ENOENT && errno != ENOTDIR) { + /* Stat failed? */ - archive_set_error(&a->archive, errno, "Can't test directory '%s'", path); ++ archive_set_error(&a->archive, errno, ++ "Can't test directory '%s'", path); + return (ARCHIVE_FAILED); + } else if (slash != NULL) { + *slash = '\0'; + r = create_dir(a, path); + *slash = '/'; + if (r != ARCHIVE_OK) + return (r); + } + + /* + * Mode we want for the final restored directory. Per POSIX, + * implicitly-created dirs must be created obeying the umask. + * There's no mention whether this is different for privileged + * restores (which the rest of this code handles by pretending + * umask=0). I've chosen here to always obey the user's umask for + * implicit dirs, even if _EXTRACT_PERM was specified. + */ + mode_final = DEFAULT_DIR_MODE & ~a->user_umask; + /* Mode we want on disk during the restore process. */ + mode = mode_final; + mode |= MINIMUM_DIR_MODE; + mode &= MAXIMUM_DIR_MODE; + if (mkdir(path, mode) == 0) { + if (mode != mode_final) { + le = new_fixup(a, path); + if (le == NULL) + return (ARCHIVE_FATAL); + le->fixup |=TODO_MODE_BASE; + le->mode = mode_final; + } + return (ARCHIVE_OK); + } + + /* + * Without the following check, a/b/../b/c/d fails at the + * second visit to 'b', so 'd' can't be created. Note that we + * don't add it to the fixup list here, as it's already been + * added. + */ + if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) + return (ARCHIVE_OK); + + archive_set_error(&a->archive, errno, "Failed to create dir '%s'", + path); + return (ARCHIVE_FAILED); +} + +/* + * Note: Although we can skip setting the user id if the desired user + * id matches the current user, we cannot skip setting the group, as + * many systems set the gid based on the containing directory. So + * we have to perform a chown syscall if we want to set the SGID + * bit. (The alternative is to stat() and then possibly chown(); it's + * more efficient to skip the stat() and just always chown().) Note + * that a successful chown() here clears the TODO_SGID_CHECK bit, which + * allows set_mode to skip the stat() check for the GID. + */ +static int +set_ownership(struct archive_write_disk *a) +{ +#ifndef __CYGWIN__ +/* unfortunately, on win32 there is no 'root' user with uid 0, + so we just have to try the chown and see if it works */ + + /* If we know we can't change it, don't bother trying. */ + if (a->user_uid != 0 && a->user_uid != a->uid) { + archive_set_error(&a->archive, errno, + "Can't set UID=%jd", (intmax_t)a->uid); + return (ARCHIVE_WARN); + } +#endif + +#ifdef HAVE_FCHOWN + /* If we have an fd, we can avoid a race. */ + if (a->fd >= 0 && fchown(a->fd, a->uid, a->gid) == 0) { + /* We've set owner and know uid/gid are correct. */ + a->todo &= ~(TODO_OWNER | TODO_SGID_CHECK | TODO_SUID_CHECK); + return (ARCHIVE_OK); + } +#endif + + /* We prefer lchown() but will use chown() if that's all we have. */ + /* Of course, if we have neither, this will always fail. */ +#ifdef HAVE_LCHOWN + if (lchown(a->name, a->uid, a->gid) == 0) { + /* We've set owner and know uid/gid are correct. */ + a->todo &= ~(TODO_OWNER | TODO_SGID_CHECK | TODO_SUID_CHECK); + return (ARCHIVE_OK); + } +#elif HAVE_CHOWN + if (!S_ISLNK(a->mode) && chown(a->name, a->uid, a->gid) == 0) { + /* We've set owner and know uid/gid are correct. */ + a->todo &= ~(TODO_OWNER | TODO_SGID_CHECK | TODO_SUID_CHECK); + return (ARCHIVE_OK); + } +#endif + + archive_set_error(&a->archive, errno, + "Can't set user=%jd/group=%jd for %s", + (intmax_t)a->uid, (intmax_t)a->gid, a->name); + return (ARCHIVE_WARN); +} + +/* + * Note: Returns 0 on success, non-zero on failure. + */ +static int +set_time(int fd, int mode, const char *name, + time_t atime, long atime_nsec, + time_t mtime, long mtime_nsec) +{ + /* Select the best implementation for this platform. */ +#if defined(HAVE_UTIMENSAT) && defined(HAVE_FUTIMENS) + /* + * utimensat() and futimens() are defined in + * POSIX.1-2008. They support ns resolution and setting times + * on fds and symlinks. + */ + struct timespec ts[2]; + (void)mode; /* UNUSED */ + ts[0].tv_sec = atime; + ts[0].tv_nsec = atime_nsec; + ts[1].tv_sec = mtime; + ts[1].tv_nsec = mtime_nsec; + if (fd >= 0) + return futimens(fd, ts); + return utimensat(AT_FDCWD, name, ts, AT_SYMLINK_NOFOLLOW); + +#elif HAVE_UTIMES + /* + * The utimes()-family functions support ?s-resolution and + * setting times fds and symlinks. utimes() is documented as + * LEGACY by POSIX, futimes() and lutimes() are not described + * in POSIX. + */ + struct timeval times[2]; + + times[0].tv_sec = atime; + times[0].tv_usec = atime_nsec / 1000; + times[1].tv_sec = mtime; + times[1].tv_usec = mtime_nsec / 1000; + +#ifdef HAVE_FUTIMES + if (fd >= 0) + return (futimes(fd, times)); +#else + (void)fd; /* UNUSED */ +#endif +#ifdef HAVE_LUTIMES + (void)mode; /* UNUSED */ + return (lutimes(name, times)); +#else + if (S_ISLNK(mode)) + return (0); + return (utimes(name, times)); +#endif + +#elif defined(HAVE_UTIME) + /* + * utime() is POSIX-standard but only supports 1s resolution and + * does not support fds or symlinks. + */ + struct utimbuf times; + (void)fd; /* UNUSED */ + (void)name; /* UNUSED */ + (void)atime_nsec; /* UNUSED */ + (void)mtime_nsec; /* UNUSED */ + times.actime = atime; + times.modtime = mtime; + if (S_ISLNK(mode)) + return (ARCHIVE_OK); + return (utime(name, ×)); + +#else + /* + * We don't know how to set the time on this platform. + */ + (void)fd; /* UNUSED */ + (void)mode; /* UNUSED */ + (void)name; /* UNUSED */ + (void)atime_nsec; /* UNUSED */ + (void)mtime_nsec; /* UNUSED */ + return (ARCHIVE_WARN); +#endif +} + +#ifdef F_SETTIMES +static int +set_time_tru64(int fd, int mode, const char *name, + time_t atime, long atime_nsec, + time_t mtime, long mtime_nsec, + time_t ctime, long ctime_nsec) +{ + struct attr_timbuf tstamp; + tstamp.atime.tv_sec = atime; + tstamp.mtime.tv_sec = mtime; + tstamp.ctime.tv_sec = ctime; +#if defined (__hpux) && defined (__ia64) + tstamp.atime.tv_nsec = atime_nsec; + tstamp.mtime.tv_nsec = mtime_nsec; + tstamp.ctime.tv_nsec = ctime_nsec; +#else + tstamp.atime.tv_usec = atime_nsec / 1000; + tstamp.mtime.tv_usec = mtime_nsec / 1000; + tstamp.ctime.tv_usec = ctime_nsec / 1000; +#endif + return (fcntl(fd,F_SETTIMES,&tstamp)); +} +#endif /* F_SETTIMES */ + +static int +set_times(struct archive_write_disk *a, + int fd, int mode, const char *name, + time_t atime, long atime_nanos, + time_t birthtime, long birthtime_nanos, + time_t mtime, long mtime_nanos, + time_t cctime, long ctime_nanos) +{ + /* Note: set_time doesn't use libarchive return conventions! + * It uses syscall conventions. So 0 here instead of ARCHIVE_OK. */ + int r1 = 0, r2 = 0; + +#ifdef F_SETTIMES + /* + * on Tru64 try own fcntl first which can restore even the + * ctime, fall back to default code path below if it fails + * or if we are not running as root + */ + if (a->user_uid == 0 && + set_time_tru64(fd, mode, name, + atime, atime_nanos, mtime, + mtime_nanos, cctime, ctime_nanos) == 0) { + return (ARCHIVE_OK); + } +#else /* Tru64 */ + (void)cctime; /* UNUSED */ + (void)ctime_nanos; /* UNUSED */ +#endif /* Tru64 */ + +#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME + /* + * If you have struct stat.st_birthtime, we assume BSD + * birthtime semantics, in which {f,l,}utimes() updates + * birthtime to earliest mtime. So we set the time twice, + * first using the birthtime, then using the mtime. If + * birthtime == mtime, this isn't necessary, so we skip it. + * If birthtime > mtime, then this won't work, so we skip it. + */ + if (birthtime < mtime + || (birthtime == mtime && birthtime_nanos < mtime_nanos)) + r1 = set_time(fd, mode, name, + atime, atime_nanos, + birthtime, birthtime_nanos); +#else + (void)birthtime; /* UNUSED */ + (void)birthtime_nanos; /* UNUSED */ +#endif + r2 = set_time(fd, mode, name, + atime, atime_nanos, + mtime, mtime_nanos); + if (r1 != 0 || r2 != 0) { + archive_set_error(&a->archive, errno, + "Can't restore time"); + return (ARCHIVE_WARN); + } + return (ARCHIVE_OK); +} + +static int +set_times_from_entry(struct archive_write_disk *a) +{ + time_t atime, birthtime, mtime, cctime; + long atime_nsec, birthtime_nsec, mtime_nsec, ctime_nsec; + + /* Suitable defaults. */ + atime = birthtime = mtime = cctime = a->start_time; + atime_nsec = birthtime_nsec = mtime_nsec = ctime_nsec = 0; + + /* If no time was provided, we're done. */ + if (!archive_entry_atime_is_set(a->entry) +#if HAVE_STRUCT_STAT_ST_BIRTHTIME + && !archive_entry_birthtime_is_set(a->entry) +#endif + && !archive_entry_mtime_is_set(a->entry)) + return (ARCHIVE_OK); + + if (archive_entry_atime_is_set(a->entry)) { + atime = archive_entry_atime(a->entry); + atime_nsec = archive_entry_atime_nsec(a->entry); + } + if (archive_entry_birthtime_is_set(a->entry)) { + birthtime = archive_entry_birthtime(a->entry); + birthtime_nsec = archive_entry_birthtime_nsec(a->entry); + } + if (archive_entry_mtime_is_set(a->entry)) { + mtime = archive_entry_mtime(a->entry); + mtime_nsec = archive_entry_mtime_nsec(a->entry); + } + if (archive_entry_ctime_is_set(a->entry)) { + cctime = archive_entry_ctime(a->entry); + ctime_nsec = archive_entry_ctime_nsec(a->entry); + } + + return set_times(a, a->fd, a->mode, a->name, + atime, atime_nsec, + birthtime, birthtime_nsec, + mtime, mtime_nsec, + cctime, ctime_nsec); +} + +static int +set_mode(struct archive_write_disk *a, int mode) +{ + int r = ARCHIVE_OK; + mode &= 07777; /* Strip off file type bits. */ + + if (a->todo & TODO_SGID_CHECK) { + /* + * If we don't know the GID is right, we must stat() + * to verify it. We can't just check the GID of this + * process, since systems sometimes set GID from + * the enclosing dir or based on ACLs. + */ + if ((r = lazy_stat(a)) != ARCHIVE_OK) + return (r); + if (a->pst->st_gid != a->gid) { + mode &= ~ S_ISGID; + if (a->flags & ARCHIVE_EXTRACT_OWNER) { + /* + * This is only an error if you + * requested owner restore. If you + * didn't, we'll try to restore + * sgid/suid, but won't consider it a + * problem if we can't. + */ + archive_set_error(&a->archive, -1, + "Can't restore SGID bit"); + r = ARCHIVE_WARN; + } + } + /* While we're here, double-check the UID. */ + if (a->pst->st_uid != a->uid + && (a->todo & TODO_SUID)) { + mode &= ~ S_ISUID; + if (a->flags & ARCHIVE_EXTRACT_OWNER) { + archive_set_error(&a->archive, -1, + "Can't restore SUID bit"); + r = ARCHIVE_WARN; + } + } + a->todo &= ~TODO_SGID_CHECK; + a->todo &= ~TODO_SUID_CHECK; + } else if (a->todo & TODO_SUID_CHECK) { + /* + * If we don't know the UID is right, we can just check + * the user, since all systems set the file UID from + * the process UID. + */ + if (a->user_uid != a->uid) { + mode &= ~ S_ISUID; + if (a->flags & ARCHIVE_EXTRACT_OWNER) { + archive_set_error(&a->archive, -1, + "Can't make file SUID"); + r = ARCHIVE_WARN; + } + } + a->todo &= ~TODO_SUID_CHECK; + } + + if (S_ISLNK(a->mode)) { +#ifdef HAVE_LCHMOD + /* + * If this is a symlink, use lchmod(). If the + * platform doesn't support lchmod(), just skip it. A + * platform that doesn't provide a way to set + * permissions on symlinks probably ignores + * permissions on symlinks, so a failure here has no + * impact. + */ + if (lchmod(a->name, mode) != 0) { + switch (errno) { + case ENOTSUP: + case ENOSYS: +#if ENOTSUP != EOPNOTSUPP + case EOPNOTSUPP: +#endif + /* + * if lchmod is defined but the platform + * doesn't support it, silently ignore + * error + */ + break; + default: + archive_set_error(&a->archive, errno, + "Can't set permissions to 0%o", (int)mode); + r = ARCHIVE_WARN; + } + } +#endif + } else if (!S_ISDIR(a->mode)) { + /* + * If it's not a symlink and not a dir, then use + * fchmod() or chmod(), depending on whether we have + * an fd. Dirs get their perms set during the + * post-extract fixup, which is handled elsewhere. + */ +#ifdef HAVE_FCHMOD + if (a->fd >= 0) { + if (fchmod(a->fd, mode) != 0) { + archive_set_error(&a->archive, errno, + "Can't set permissions to 0%o", (int)mode); + r = ARCHIVE_WARN; + } + } else +#endif + /* If this platform lacks fchmod(), then + * we'll just use chmod(). */ + if (chmod(a->name, mode) != 0) { + archive_set_error(&a->archive, errno, + "Can't set permissions to 0%o", (int)mode); + r = ARCHIVE_WARN; + } + } + return (r); +} + +static int +set_fflags(struct archive_write_disk *a) +{ + struct fixup_entry *le; + unsigned long set, clear; + int r; + int critical_flags; + mode_t mode = archive_entry_mode(a->entry); + + /* + * Make 'critical_flags' hold all file flags that can't be + * immediately restored. For example, on BSD systems, + * SF_IMMUTABLE prevents hardlinks from being created, so + * should not be set until after any hardlinks are created. To + * preserve some semblance of portability, this uses #ifdef + * extensively. Ugly, but it works. + * + * Yes, Virginia, this does create a security race. It's mitigated + * somewhat by the practice of creating dirs 0700 until the extract + * is done, but it would be nice if we could do more than that. + * People restoring critical file systems should be wary of + * other programs that might try to muck with files as they're + * being restored. + */ + /* Hopefully, the compiler will optimize this mess into a constant. */ + critical_flags = 0; +#ifdef SF_IMMUTABLE + critical_flags |= SF_IMMUTABLE; +#endif +#ifdef UF_IMMUTABLE + critical_flags |= UF_IMMUTABLE; +#endif +#ifdef SF_APPEND + critical_flags |= SF_APPEND; +#endif +#ifdef UF_APPEND + critical_flags |= UF_APPEND; +#endif +#ifdef EXT2_APPEND_FL + critical_flags |= EXT2_APPEND_FL; +#endif +#ifdef EXT2_IMMUTABLE_FL + critical_flags |= EXT2_IMMUTABLE_FL; +#endif + + if (a->todo & TODO_FFLAGS) { + archive_entry_fflags(a->entry, &set, &clear); + + /* + * The first test encourages the compiler to eliminate + * all of this if it's not necessary. + */ + if ((critical_flags != 0) && (set & critical_flags)) { + le = current_fixup(a, a->name); + if (le == NULL) + return (ARCHIVE_FATAL); + le->fixup |= TODO_FFLAGS; + le->fflags_set = set; + /* Store the mode if it's not already there. */ + if ((le->fixup & TODO_MODE) == 0) + le->mode = mode; + } else { + r = set_fflags_platform(a, a->fd, + a->name, mode, set, clear); + if (r != ARCHIVE_OK) + return (r); + } + } + return (ARCHIVE_OK); +} + +static int +clear_nochange_fflags(struct archive_write_disk *a) +{ + int nochange_flags; + mode_t mode = archive_entry_mode(a->entry); + + /* Hopefully, the compiler will optimize this mess into a constant. */ + nochange_flags = 0; +#ifdef SF_IMMUTABLE + nochange_flags |= SF_IMMUTABLE; +#endif +#ifdef UF_IMMUTABLE + nochange_flags |= UF_IMMUTABLE; +#endif +#ifdef SF_APPEND + nochange_flags |= SF_APPEND; +#endif +#ifdef UF_APPEND + nochange_flags |= UF_APPEND; +#endif +#ifdef EXT2_APPEND_FL + nochange_flags |= EXT2_APPEND_FL; +#endif +#ifdef EXT2_IMMUTABLE_FL + nochange_flags |= EXT2_IMMUTABLE_FL; +#endif + - return (set_fflags_platform(a, a->fd, a->name, mode, 0, nochange_flags)); ++ return (set_fflags_platform(a, a->fd, a->name, mode, 0, ++ nochange_flags)); +} + + +#if ( defined(HAVE_LCHFLAGS) || defined(HAVE_CHFLAGS) || defined(HAVE_FCHFLAGS) ) && defined(HAVE_STRUCT_STAT_ST_FLAGS) +/* + * BSD reads flags using stat() and sets them with one of {f,l,}chflags() + */ +static int +set_fflags_platform(struct archive_write_disk *a, int fd, const char *name, + mode_t mode, unsigned long set, unsigned long clear) +{ + int r; + + (void)mode; /* UNUSED */ + if (set == 0 && clear == 0) + return (ARCHIVE_OK); + + /* + * XXX Is the stat here really necessary? Or can I just use + * the 'set' flags directly? In particular, I'm not sure + * about the correct approach if we're overwriting an existing + * file that already has flags on it. XXX + */ + if ((r = lazy_stat(a)) != ARCHIVE_OK) + return (r); + + a->st.st_flags &= ~clear; + a->st.st_flags |= set; +#ifdef HAVE_FCHFLAGS + /* If platform has fchflags() and we were given an fd, use it. */ + if (fd >= 0 && fchflags(fd, a->st.st_flags) == 0) + return (ARCHIVE_OK); +#endif + /* + * If we can't use the fd to set the flags, we'll use the + * pathname to set flags. We prefer lchflags() but will use + * chflags() if we must. + */ +#ifdef HAVE_LCHFLAGS + if (lchflags(name, a->st.st_flags) == 0) + return (ARCHIVE_OK); +#elif defined(HAVE_CHFLAGS) + if (S_ISLNK(a->st.st_mode)) { + archive_set_error(&a->archive, errno, + "Can't set file flags on symlink."); + return (ARCHIVE_WARN); + } + if (chflags(name, a->st.st_flags) == 0) + return (ARCHIVE_OK); +#endif + archive_set_error(&a->archive, errno, + "Failed to set file flags"); + return (ARCHIVE_WARN); +} + +#elif defined(EXT2_IOC_GETFLAGS) && defined(EXT2_IOC_SETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS) +/* + * Linux uses ioctl() to read and write file flags. + */ +static int +set_fflags_platform(struct archive_write_disk *a, int fd, const char *name, + mode_t mode, unsigned long set, unsigned long clear) +{ + int ret; + int myfd = fd; + int newflags, oldflags; + int sf_mask = 0; + + if (set == 0 && clear == 0) + return (ARCHIVE_OK); + /* Only regular files and dirs can have flags. */ + if (!S_ISREG(mode) && !S_ISDIR(mode)) + return (ARCHIVE_OK); + + /* If we weren't given an fd, open it ourselves. */ + if (myfd < 0) { + myfd = open(name, O_RDONLY | O_NONBLOCK | O_BINARY | O_CLOEXEC); + __archive_ensure_cloexec_flag(myfd); + } + if (myfd < 0) + return (ARCHIVE_OK); + + /* + * Linux has no define for the flags that are only settable by + * the root user. This code may seem a little complex, but + * there seem to be some Linux systems that lack these + * defines. (?) The code below degrades reasonably gracefully + * if sf_mask is incomplete. + */ +#ifdef EXT2_IMMUTABLE_FL + sf_mask |= EXT2_IMMUTABLE_FL; +#endif +#ifdef EXT2_APPEND_FL + sf_mask |= EXT2_APPEND_FL; +#endif + /* + * XXX As above, this would be way simpler if we didn't have + * to read the current flags from disk. XXX + */ + ret = ARCHIVE_OK; + + /* Read the current file flags. */ + if (ioctl(myfd, EXT2_IOC_GETFLAGS, &oldflags) < 0) + goto fail; + + /* Try setting the flags as given. */ + newflags = (oldflags & ~clear) | set; + if (ioctl(myfd, EXT2_IOC_SETFLAGS, &newflags) >= 0) + goto cleanup; + if (errno != EPERM) + goto fail; + + /* If we couldn't set all the flags, try again with a subset. */ + newflags &= ~sf_mask; + oldflags &= sf_mask; + newflags |= oldflags; + if (ioctl(myfd, EXT2_IOC_SETFLAGS, &newflags) >= 0) + goto cleanup; + + /* We couldn't set the flags, so report the failure. */ +fail: + archive_set_error(&a->archive, errno, + "Failed to set file flags"); + ret = ARCHIVE_WARN; +cleanup: + if (fd < 0) + close(myfd); + return (ret); +} + +#else + +/* + * Of course, some systems have neither BSD chflags() nor Linux' flags + * support through ioctl(). + */ +static int +set_fflags_platform(struct archive_write_disk *a, int fd, const char *name, + mode_t mode, unsigned long set, unsigned long clear) +{ + (void)a; /* UNUSED */ + (void)fd; /* UNUSED */ + (void)name; /* UNUSED */ + (void)mode; /* UNUSED */ + (void)set; /* UNUSED */ + (void)clear; /* UNUSED */ + return (ARCHIVE_OK); +} + +#endif /* __linux */ + +#ifndef HAVE_COPYFILE_H +/* Default is to simply drop Mac extended metadata. */ +static int +set_mac_metadata(struct archive_write_disk *a, const char *pathname, + const void *metadata, size_t metadata_size) +{ + (void)a; /* UNUSED */ + (void)pathname; /* UNUSED */ + (void)metadata; /* UNUSED */ + (void)metadata_size; /* UNUSED */ + return (ARCHIVE_OK); +} + +static int +fixup_appledouble(struct archive_write_disk *a, const char *pathname) +{ + (void)a; /* UNUSED */ + (void)pathname; /* UNUSED */ + return (ARCHIVE_OK); +} +#else + +/* + * On Mac OS, we use copyfile() to unpack the metadata and + * apply it to the target file. + */ + +#if defined(HAVE_SYS_XATTR_H) +static int +copy_xattrs(struct archive_write_disk *a, int tmpfd, int dffd) +{ + ssize_t xattr_size; + char *xattr_names = NULL, *xattr_val = NULL; + int ret = ARCHIVE_OK, xattr_i; + + xattr_size = flistxattr(tmpfd, NULL, 0, 0); + if (xattr_size == -1) { + archive_set_error(&a->archive, errno, + "Failed to read metadata(xattr)"); + ret = ARCHIVE_WARN; + goto exit_xattr; + } + xattr_names = malloc(xattr_size); + if (xattr_names == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for metadata(xattr)"); + ret = ARCHIVE_FATAL; + goto exit_xattr; + } + xattr_size = flistxattr(tmpfd, xattr_names, xattr_size, 0); + if (xattr_size == -1) { + archive_set_error(&a->archive, errno, + "Failed to read metadata(xattr)"); + ret = ARCHIVE_WARN; + goto exit_xattr; + } + for (xattr_i = 0; xattr_i < xattr_size; + xattr_i += strlen(xattr_names + xattr_i) + 1) { + char *xattr_val_saved; + ssize_t s; + int f; + + s = fgetxattr(tmpfd, xattr_names + xattr_i, NULL, 0, 0, 0); + if (s == -1) { + archive_set_error(&a->archive, errno, + "Failed to get metadata(xattr)"); + ret = ARCHIVE_WARN; + goto exit_xattr; + } + xattr_val_saved = xattr_val; + xattr_val = realloc(xattr_val, s); + if (xattr_val == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Failed to get metadata(xattr)"); + ret = ARCHIVE_WARN; + free(xattr_val_saved); + goto exit_xattr; + } + s = fgetxattr(tmpfd, xattr_names + xattr_i, xattr_val, s, 0, 0); + if (s == -1) { + archive_set_error(&a->archive, errno, + "Failed to get metadata(xattr)"); + ret = ARCHIVE_WARN; + goto exit_xattr; + } + f = fsetxattr(dffd, xattr_names + xattr_i, xattr_val, s, 0, 0); + if (f == -1) { + archive_set_error(&a->archive, errno, + "Failed to get metadata(xattr)"); + ret = ARCHIVE_WARN; + goto exit_xattr; + } + } +exit_xattr: + free(xattr_names); + free(xattr_val); + return (ret); +} +#endif + +static int +copy_acls(struct archive_write_disk *a, int tmpfd, int dffd) +{ ++#ifndef HAVE_SYS_ACL_H ++ return 0; ++#else + acl_t acl, dfacl = NULL; + int acl_r, ret = ARCHIVE_OK; + + acl = acl_get_fd(tmpfd); + if (acl == NULL) { + if (errno == ENOENT) + /* There are not any ACLs. */ + return (ret); + archive_set_error(&a->archive, errno, + "Failed to get metadata(acl)"); + ret = ARCHIVE_WARN; + goto exit_acl; + } + dfacl = acl_dup(acl); + acl_r = acl_set_fd(dffd, dfacl); + if (acl_r == -1) { + archive_set_error(&a->archive, errno, + "Failed to get metadata(acl)"); + ret = ARCHIVE_WARN; + goto exit_acl; + } +exit_acl: + if (acl) + acl_free(acl); + if (dfacl) + acl_free(dfacl); + return (ret); ++#endif +} + +static int +create_tempdatafork(struct archive_write_disk *a, const char *pathname) +{ + struct archive_string tmpdatafork; + int tmpfd; + + archive_string_init(&tmpdatafork); + archive_strcpy(&tmpdatafork, "tar.md.XXXXXX"); + tmpfd = mkstemp(tmpdatafork.s); + if (tmpfd < 0) { + archive_set_error(&a->archive, errno, + "Failed to mkstemp"); + archive_string_free(&tmpdatafork); + return (-1); + } + if (copyfile(pathname, tmpdatafork.s, 0, + COPYFILE_UNPACK | COPYFILE_NOFOLLOW + | COPYFILE_ACL | COPYFILE_XATTR) < 0) { + archive_set_error(&a->archive, errno, + "Failed to restore metadata"); + close(tmpfd); + tmpfd = -1; + } + unlink(tmpdatafork.s); + archive_string_free(&tmpdatafork); + return (tmpfd); +} + +static int +copy_metadata(struct archive_write_disk *a, const char *metadata, + const char *datafork, int datafork_compressed) +{ + int ret = ARCHIVE_OK; + + if (datafork_compressed) { + int dffd, tmpfd; + + tmpfd = create_tempdatafork(a, metadata); + if (tmpfd == -1) + return (ARCHIVE_WARN); + + /* + * Do not open the data fork compressed by HFS+ compression + * with at least a writing mode(O_RDWR or O_WRONLY). it + * makes the data fork uncompressed. + */ + dffd = open(datafork, 0); + if (dffd == -1) { + archive_set_error(&a->archive, errno, + "Failed to open the data fork for metadata"); + close(tmpfd); + return (ARCHIVE_WARN); + } + +#if defined(HAVE_SYS_XATTR_H) + ret = copy_xattrs(a, tmpfd, dffd); + if (ret == ARCHIVE_OK) +#endif + ret = copy_acls(a, tmpfd, dffd); + close(tmpfd); + close(dffd); + } else { + if (copyfile(metadata, datafork, 0, + COPYFILE_UNPACK | COPYFILE_NOFOLLOW + | COPYFILE_ACL | COPYFILE_XATTR) < 0) { + archive_set_error(&a->archive, errno, + "Failed to restore metadata"); + ret = ARCHIVE_WARN; + } + } + return (ret); +} + +static int +set_mac_metadata(struct archive_write_disk *a, const char *pathname, + const void *metadata, size_t metadata_size) +{ + struct archive_string tmp; + ssize_t written; + int fd; + int ret = ARCHIVE_OK; + + /* This would be simpler if copyfile() could just accept the + * metadata as a block of memory; then we could sidestep this + * silly dance of writing the data to disk just so that + * copyfile() can read it back in again. */ + archive_string_init(&tmp); + archive_strcpy(&tmp, pathname); + archive_strcat(&tmp, ".XXXXXX"); + fd = mkstemp(tmp.s); + + if (fd < 0) { + archive_set_error(&a->archive, errno, + "Failed to restore metadata"); + archive_string_free(&tmp); + return (ARCHIVE_WARN); + } + written = write(fd, metadata, metadata_size); + close(fd); + if ((size_t)written != metadata_size) { + archive_set_error(&a->archive, errno, + "Failed to restore metadata"); + ret = ARCHIVE_WARN; + } else { + int compressed; + +#if defined(UF_COMPRESSED) + if ((a->todo & TODO_HFS_COMPRESSION) != 0 && + (ret = lazy_stat(a)) == ARCHIVE_OK) + compressed = a->st.st_flags & UF_COMPRESSED; + else +#endif + compressed = 0; + ret = copy_metadata(a, tmp.s, pathname, compressed); + } + unlink(tmp.s); + archive_string_free(&tmp); + return (ret); +} + +static int +fixup_appledouble(struct archive_write_disk *a, const char *pathname) +{ + char buff[8]; + struct stat st; + const char *p; + struct archive_string datafork; + int fd = -1, ret = ARCHIVE_OK; + + archive_string_init(&datafork); + /* Check if the current file name is a type of the resource + * fork file. */ + p = strrchr(pathname, '/'); + if (p == NULL) + p = pathname; + else + p++; + if (p[0] != '.' || p[1] != '_') + goto skip_appledouble; + + /* + * Check if the data fork file exists. + * + * TODO: Check if this write disk object has handled it. + */ + archive_strncpy(&datafork, pathname, p - pathname); + archive_strcat(&datafork, p + 2); + if (lstat(datafork.s, &st) == -1 || + (st.st_mode & AE_IFMT) != AE_IFREG) + goto skip_appledouble; + + /* + * Check if the file is in the AppleDouble form. + */ + fd = open(pathname, O_RDONLY | O_BINARY | O_CLOEXEC); + __archive_ensure_cloexec_flag(fd); + if (fd == -1) { + archive_set_error(&a->archive, errno, + "Failed to open a restoring file"); + ret = ARCHIVE_WARN; + goto skip_appledouble; + } + if (read(fd, buff, 8) == -1) { + archive_set_error(&a->archive, errno, + "Failed to read a restoring file"); + close(fd); + ret = ARCHIVE_WARN; + goto skip_appledouble; + } + close(fd); + /* Check AppleDouble Magic Code. */ + if (archive_be32dec(buff) != 0x00051607) + goto skip_appledouble; + /* Check AppleDouble Version. */ + if (archive_be32dec(buff+4) != 0x00020000) + goto skip_appledouble; + + ret = copy_metadata(a, pathname, datafork.s, +#if defined(UF_COMPRESSED) + st.st_flags & UF_COMPRESSED); +#else + 0); +#endif + if (ret == ARCHIVE_OK) { + unlink(pathname); + ret = ARCHIVE_EOF; + } +skip_appledouble: + archive_string_free(&datafork); + return (ret); +} +#endif + +#if HAVE_LSETXATTR || HAVE_LSETEA +/* + * Restore extended attributes - Linux 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; + int ret = ARCHIVE_OK; + int i = archive_entry_xattr_reset(entry); + + while (i--) { + const char *name; + const void *value; + size_t size; + 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 +#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); +#endif + } + if (e == -1) { + if (errno == ENOTSUP || errno == ENOSYS) { + if (!warning_done) { + warning_done = 1; - archive_set_error(&a->archive, errno, ++ 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, ++ archive_set_error(&a->archive, ++ ARCHIVE_ERRNO_FILE_FORMAT, + "Invalid extended attribute encountered"); + ret = ARCHIVE_WARN; + } + } + return (ret); +} +#elif HAVE_EXTATTR_SET_FILE && HAVE_DECL_EXTATTR_NAMESPACE_USER +/* + * Restore extended attributes - FreeBSD implementation + */ +static int +set_xattrs(struct archive_write_disk *a) +{ + struct archive_entry *entry = a->entry; + static int warning_done = 0; + int ret = ARCHIVE_OK; + int i = archive_entry_xattr_reset(entry); + + while (i--) { + const char *name; + const void *value; + size_t size; + archive_entry_xattr_next(entry, &name, &value, &size); + if (name != NULL) { + int e; + int namespace; + + if (strncmp(name, "user.", 5) == 0) { + /* "user." attributes go to user namespace */ + 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); + ret = ARCHIVE_WARN; + continue; + } + errno = 0; +#if HAVE_EXTATTR_SET_FD + if (a->fd >= 0) - e = extattr_set_fd(a->fd, namespace, name, value, size); ++ e = extattr_set_fd(a->fd, namespace, name, ++ value, size); + else +#endif + /* TODO: should we use extattr_set_link() instead? */ + { - e = extattr_set_file(archive_entry_pathname(entry), - namespace, name, value, size); ++ e = extattr_set_file( ++ 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, ++ 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; + } + } + } + return (ret); +} +#else +/* + * Restore extended attributes - stub implementation for unsupported systems + */ +static int +set_xattrs(struct archive_write_disk *a) +{ + static int warning_done = 0; + + /* If there aren't any extended attributes, then it's okay not + * to extract them, otherwise, issue a single warning. */ + if (archive_entry_xattr_count(a->entry) != 0 && !warning_done) { + warning_done = 1; + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Cannot restore extended attributes on this system"); + return (ARCHIVE_WARN); + } + /* Warning was already emitted; suppress further warnings. */ + return (ARCHIVE_OK); +} +#endif + +/* + * Test if file on disk is older than entry. + */ +static int +older(struct stat *st, struct archive_entry *entry) +{ + /* First, test the seconds and return if we have a definite answer. */ + /* Definitely older. */ - if (st->st_mtime < archive_entry_mtime(entry)) ++ if (to_int64_time(st->st_mtime) < to_int64_time(archive_entry_mtime(entry))) + return (1); + /* Definitely younger. */ - if (st->st_mtime > archive_entry_mtime(entry)) ++ if (to_int64_time(st->st_mtime) > to_int64_time(archive_entry_mtime(entry))) + return (0); + /* If this platform supports fractional seconds, try those. */ +#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC + /* Definitely older. */ + if (st->st_mtimespec.tv_nsec < archive_entry_mtime_nsec(entry)) + return (1); +#elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC + /* Definitely older. */ + if (st->st_mtim.tv_nsec < archive_entry_mtime_nsec(entry)) + return (1); +#elif HAVE_STRUCT_STAT_ST_MTIME_N + /* older. */ + if (st->st_mtime_n < archive_entry_mtime_nsec(entry)) + return (1); +#elif HAVE_STRUCT_STAT_ST_UMTIME + /* older. */ + if (st->st_umtime * 1000 < archive_entry_mtime_nsec(entry)) + return (1); +#elif HAVE_STRUCT_STAT_ST_MTIME_USEC + /* older. */ + if (st->st_mtime_usec * 1000 < archive_entry_mtime_nsec(entry)) + return (1); +#else + /* This system doesn't have high-res timestamps. */ +#endif + /* Same age or newer, so not older. */ + return (0); +} + +#endif /* !_WIN32 || __CYGWIN__ */ + diff --cc Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c index 8718d25,0000000..3fc5a07 mode 100644,000000..100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_7zip.c @@@ -1,2328 -1,0 +1,2328 @@@ +/*- + * Copyright (c) 2011-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_BZLIB_H +#include +#endif +#if HAVE_LZMA_H +#include +#endif +#ifdef HAVE_ZLIB_H +#include +#endif + +#include "archive.h" +#ifndef HAVE_ZLIB_H +#include "archive_crc32.h" +#endif +#include "archive_endian.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_ppmd7_private.h" +#include "archive_private.h" +#include "archive_rb.h" +#include "archive_string.h" +#include "archive_write_private.h" + +/* + * Codec ID + */ +#define _7Z_COPY 0 +#define _7Z_LZMA1 0x030101 +#define _7Z_LZMA2 0x21 +#define _7Z_DEFLATE 0x040108 +#define _7Z_BZIP2 0x040202 +#define _7Z_PPMD 0x030401 + +/* + * 7-Zip header property IDs. + */ +#define kEnd 0x00 +#define kHeader 0x01 +#define kArchiveProperties 0x02 +#define kAdditionalStreamsInfo 0x03 +#define kMainStreamsInfo 0x04 +#define kFilesInfo 0x05 +#define kPackInfo 0x06 +#define kUnPackInfo 0x07 +#define kSubStreamsInfo 0x08 +#define kSize 0x09 +#define kCRC 0x0A +#define kFolder 0x0B +#define kCodersUnPackSize 0x0C +#define kNumUnPackStream 0x0D +#define kEmptyStream 0x0E +#define kEmptyFile 0x0F +#define kAnti 0x10 +#define kName 0x11 +#define kCTime 0x12 +#define kATime 0x13 +#define kMTime 0x14 +#define kAttributes 0x15 +#define kEncodedHeader 0x17 + +enum la_zaction { + ARCHIVE_Z_FINISH, + ARCHIVE_Z_RUN +}; + +/* + * A stream object of universal compressor. + */ +struct la_zstream { + const uint8_t *next_in; + size_t avail_in; + uint64_t total_in; + + uint8_t *next_out; + size_t avail_out; + uint64_t total_out; + + uint32_t prop_size; + uint8_t *props; + + int valid; + void *real_stream; + int (*code) (struct archive *a, + struct la_zstream *lastrm, + enum la_zaction action); + int (*end)(struct archive *a, + struct la_zstream *lastrm); +}; + +#define PPMD7_DEFAULT_ORDER 6 +#define PPMD7_DEFAULT_MEM_SIZE (1 << 24) + +struct ppmd_stream { + int stat; + CPpmd7 ppmd7_context; + CPpmd7z_RangeEnc range_enc; + IByteOut byteout; + uint8_t *buff; + uint8_t *buff_ptr; + uint8_t *buff_end; + size_t buff_bytes; +}; + +struct coder { + unsigned codec; + size_t prop_size; + uint8_t *props; +}; + +struct file { + struct archive_rb_node rbnode; + + struct file *next; + unsigned name_len; + uint8_t *utf16name;/* UTF16-LE name. */ + uint64_t size; + unsigned flg; +#define MTIME_IS_SET (1<<0) +#define ATIME_IS_SET (1<<1) +#define CTIME_IS_SET (1<<2) +#define CRC32_IS_SET (1<<3) +#define HAS_STREAM (1<<4) + + struct { + time_t time; + long time_ns; + } times[3]; +#define MTIME 0 +#define ATIME 1 +#define CTIME 2 + + mode_t mode; + uint32_t crc32; + + int dir:1; +}; + +struct _7zip { + int temp_fd; + uint64_t temp_offset; + + struct file *cur_file; + size_t total_number_entry; + size_t total_number_nonempty_entry; + size_t total_number_empty_entry; + size_t total_number_dir_entry; + size_t total_bytes_entry_name; + size_t total_number_time_defined[3]; + uint64_t total_bytes_compressed; + uint64_t total_bytes_uncompressed; + uint64_t entry_bytes_remaining; + uint32_t entry_crc32; + uint32_t precode_crc32; + uint32_t encoded_crc32; + int crc32flg; +#define PRECODE_CRC32 1 +#define ENCODED_CRC32 2 + + unsigned opt_compression; + int opt_compression_level; + + struct la_zstream stream; + struct coder coder; + + struct archive_string_conv *sconv; + + /* + * Compressed data buffer. + */ + unsigned char wbuff[512 * 20 * 6]; + size_t wbuff_remaining; + + /* + * The list of the file entries which has its contents is used to + * manage struct file objects. - * We use 'next' a menber of struct file to chain. ++ * We use 'next' (a member of struct file) to chain. + */ + struct { + struct file *first; + struct file **last; + } file_list, empty_list; + struct archive_rb_tree rbtree;/* for empty files */ +}; + +static int _7z_options(struct archive_write *, + const char *, const char *); +static int _7z_write_header(struct archive_write *, + struct archive_entry *); +static ssize_t _7z_write_data(struct archive_write *, + const void *, size_t); +static int _7z_finish_entry(struct archive_write *); +static int _7z_close(struct archive_write *); +static int _7z_free(struct archive_write *); +static int file_cmp_node(const struct archive_rb_node *, + const struct archive_rb_node *); +static int file_cmp_key(const struct archive_rb_node *, const void *); +static int file_new(struct archive_write *a, struct archive_entry *, + struct file **); +static void file_free(struct file *); +static void file_register(struct _7zip *, struct file *); +static void file_register_empty(struct _7zip *, struct file *); +static void file_init_register(struct _7zip *); +static void file_init_register_empty(struct _7zip *); +static void file_free_register(struct _7zip *); +static ssize_t compress_out(struct archive_write *, const void *, size_t , + enum la_zaction); +static int compression_init_encoder_copy(struct archive *, + struct la_zstream *); +static int compression_code_copy(struct archive *, + struct la_zstream *, enum la_zaction); +static int compression_end_copy(struct archive *, struct la_zstream *); +static int compression_init_encoder_deflate(struct archive *, + struct la_zstream *, int, int); +#ifdef HAVE_ZLIB_H +static int compression_code_deflate(struct archive *, + struct la_zstream *, enum la_zaction); +static int compression_end_deflate(struct archive *, struct la_zstream *); +#endif +static int compression_init_encoder_bzip2(struct archive *, + struct la_zstream *, int); +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) +static int compression_code_bzip2(struct archive *, + struct la_zstream *, enum la_zaction); +static int compression_end_bzip2(struct archive *, struct la_zstream *); +#endif +static int compression_init_encoder_lzma1(struct archive *, + struct la_zstream *, int); +static int compression_init_encoder_lzma2(struct archive *, + struct la_zstream *, int); +#if defined(HAVE_LZMA_H) +static int compression_code_lzma(struct archive *, + struct la_zstream *, enum la_zaction); +static int compression_end_lzma(struct archive *, struct la_zstream *); +#endif +static int compression_init_encoder_ppmd(struct archive *, + struct la_zstream *, unsigned, uint32_t); +static int compression_code_ppmd(struct archive *, + struct la_zstream *, enum la_zaction); +static int compression_end_ppmd(struct archive *, struct la_zstream *); +static int _7z_compression_init_encoder(struct archive_write *, unsigned, + int); +static int compression_code(struct archive *, + struct la_zstream *, enum la_zaction); +static int compression_end(struct archive *, + struct la_zstream *); +static int enc_uint64(struct archive_write *, uint64_t); +static int make_header(struct archive_write *, uint64_t, uint64_t, + uint64_t, int, struct coder *); +static int make_streamsInfo(struct archive_write *, uint64_t, uint64_t, + uint64_t, int, struct coder *, int, uint32_t); + +int +archive_write_set_format_7zip(struct archive *_a) +{ + static const struct archive_rb_tree_ops rb_ops = { + file_cmp_node, file_cmp_key + }; + struct archive_write *a = (struct archive_write *)_a; + struct _7zip *zip; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_set_format_7zip"); + + /* If another format was already registered, unregister it. */ + if (a->format_free != NULL) + (a->format_free)(a); + + zip = calloc(1, sizeof(*zip)); + if (zip == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate 7-Zip data"); + return (ARCHIVE_FATAL); + } + zip->temp_fd = -1; + __archive_rb_tree_init(&(zip->rbtree), &rb_ops); + file_init_register(zip); + file_init_register_empty(zip); + + /* Set default compression type and its level. */ +#if HAVE_LZMA_H + zip->opt_compression = _7Z_LZMA1; +#elif defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) + zip->opt_compression = _7Z_BZIP2; +#elif defined(HAVE_ZLIB_H) + zip->opt_compression = _7Z_DEFLATE; +#else + zip->opt_compression = _7Z_COPY; +#endif + zip->opt_compression_level = 6; + + a->format_data = zip; + + a->format_name = "7zip"; + a->format_options = _7z_options; + a->format_write_header = _7z_write_header; + a->format_write_data = _7z_write_data; + a->format_finish_entry = _7z_finish_entry; + a->format_close = _7z_close; + a->format_free = _7z_free; + a->archive.archive_format = ARCHIVE_FORMAT_7ZIP; + a->archive.archive_format_name = "7zip"; + + return (ARCHIVE_OK); +} + +static int +_7z_options(struct archive_write *a, const char *key, const char *value) +{ + struct _7zip *zip; + + zip = (struct _7zip *)a->format_data; + + if (strcmp(key, "compression") == 0) { + const char *name = NULL; + + if (value == NULL || strcmp(value, "copy") == 0 || + strcmp(value, "COPY") == 0 || + strcmp(value, "store") == 0 || + strcmp(value, "STORE") == 0) + zip->opt_compression = _7Z_COPY; + else if (strcmp(value, "deflate") == 0 || + strcmp(value, "DEFLATE") == 0) +#if HAVE_ZLIB_H + zip->opt_compression = _7Z_DEFLATE; +#else + name = "deflate"; +#endif + else if (strcmp(value, "bzip2") == 0 || + strcmp(value, "BZIP2") == 0) +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) + zip->opt_compression = _7Z_BZIP2; +#else + name = "bzip2"; +#endif + else if (strcmp(value, "lzma1") == 0 || + strcmp(value, "LZMA1") == 0) +#if HAVE_LZMA_H + zip->opt_compression = _7Z_LZMA1; +#else + name = "lzma1"; +#endif + else if (strcmp(value, "lzma2") == 0 || + strcmp(value, "LZMA2") == 0) +#if HAVE_LZMA_H + zip->opt_compression = _7Z_LZMA2; +#else + name = "lzma2"; +#endif + else if (strcmp(value, "ppmd") == 0 || + strcmp(value, "PPMD") == 0 || + strcmp(value, "PPMd") == 0) + zip->opt_compression = _7Z_PPMD; + else { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "Unknown compression name: `%s'", + value); + return (ARCHIVE_FAILED); + } + if (name != NULL) { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "`%s' compression not supported " + "on this platform", + name); + return (ARCHIVE_FAILED); + } + return (ARCHIVE_OK); + } + if (strcmp(key, "compression-level") == 0) { + if (value == NULL || + !(value[0] >= '0' && value[0] <= '9') || + value[1] != '\0') { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "Illegal value `%s'", + value); + return (ARCHIVE_FAILED); + } + zip->opt_compression_level = value[0] - '0'; + return (ARCHIVE_OK); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +static int +_7z_write_header(struct archive_write *a, struct archive_entry *entry) +{ + struct _7zip *zip; + struct file *file; + int r; + + zip = (struct _7zip *)a->format_data; + zip->cur_file = NULL; + zip->entry_bytes_remaining = 0; + + if (zip->sconv == NULL) { + zip->sconv = archive_string_conversion_to_charset( + &a->archive, "UTF-16LE", 1); + if (zip->sconv == NULL) + return (ARCHIVE_FATAL); + } + + r = file_new(a, entry, &file); + if (r < ARCHIVE_WARN) { + file_free(file); + return (r); + } + if (file->size == 0 && file->dir) { + if (!__archive_rb_tree_insert_node(&(zip->rbtree), + (struct archive_rb_node *)file)) { + /* We have already had the same file. */ + file_free(file); + return (ARCHIVE_OK); + } + } + + if (file->flg & MTIME_IS_SET) + zip->total_number_time_defined[MTIME]++; + if (file->flg & CTIME_IS_SET) + zip->total_number_time_defined[CTIME]++; + if (file->flg & ATIME_IS_SET) + zip->total_number_time_defined[ATIME]++; + + zip->total_number_entry++; + zip->total_bytes_entry_name += file->name_len + 2; + if (file->size == 0) { + /* Count up the number of empty files. */ + zip->total_number_empty_entry++; + if (file->dir) + zip->total_number_dir_entry++; + else + file_register_empty(zip, file); + return (r); + } + + /* + * Init compression. + */ + if ((zip->total_number_entry - zip->total_number_empty_entry) == 1) { + r = _7z_compression_init_encoder(a, zip->opt_compression, + zip->opt_compression_level); + if (r < 0) { + file_free(file); + return (ARCHIVE_FATAL); + } + } + + /* Register a non-empty file. */ + file_register(zip, file); + + /* + * Set the current file to cur_file to read its contents. + */ + zip->cur_file = file; + + + /* Save a offset of current file in temporary file. */ + zip->entry_bytes_remaining = file->size; + zip->entry_crc32 = 0; + + /* + * Store a symbolic link name as file contents. + */ + if (archive_entry_filetype(entry) == AE_IFLNK) { + ssize_t bytes; + const void *p = (const void *)archive_entry_symlink(entry); + bytes = compress_out(a, p, (size_t)file->size, ARCHIVE_Z_RUN); + if (bytes < 0) + return ((int)bytes); + zip->entry_crc32 = crc32(zip->entry_crc32, p, (unsigned)bytes); + zip->entry_bytes_remaining -= bytes; + } + + return (r); +} + +/* + * Write data to a temporary file. + */ +static int +write_to_temp(struct archive_write *a, const void *buff, size_t s) +{ + struct _7zip *zip; + const unsigned char *p; + ssize_t ws; + + zip = (struct _7zip *)a->format_data; + + /* + * Open a temporary file. + */ + if (zip->temp_fd == -1) { + zip->temp_offset = 0; + zip->temp_fd = __archive_mktemp(NULL); + if (zip->temp_fd < 0) { + archive_set_error(&a->archive, errno, + "Couldn't create temporary file"); + return (ARCHIVE_FATAL); + } + } + + p = (const unsigned char *)buff; + while (s) { + ws = write(zip->temp_fd, p, s); + if (ws < 0) { + archive_set_error(&(a->archive), errno, + "fwrite function failed"); + return (ARCHIVE_FATAL); + } + s -= ws; + p += ws; + zip->temp_offset += ws; + } + return (ARCHIVE_OK); +} + +static ssize_t +compress_out(struct archive_write *a, const void *buff, size_t s, + enum la_zaction run) +{ + struct _7zip *zip = (struct _7zip *)a->format_data; + int r; + + if (run == ARCHIVE_Z_FINISH && zip->stream.total_in == 0 && s == 0) + return (0); + + if ((zip->crc32flg & PRECODE_CRC32) && s) + zip->precode_crc32 = crc32(zip->precode_crc32, buff, + (unsigned)s); + zip->stream.next_in = (const unsigned char *)buff; + zip->stream.avail_in = s; + for (;;) { + /* Compress file data. */ + r = compression_code(&(a->archive), &(zip->stream), run); + if (r != ARCHIVE_OK && r != ARCHIVE_EOF) + return (ARCHIVE_FATAL); + if (zip->stream.avail_out == 0) { + if (write_to_temp(a, zip->wbuff, sizeof(zip->wbuff)) + != ARCHIVE_OK) + return (ARCHIVE_FATAL); + zip->stream.next_out = zip->wbuff; + zip->stream.avail_out = sizeof(zip->wbuff); + if (zip->crc32flg & ENCODED_CRC32) + zip->encoded_crc32 = crc32(zip->encoded_crc32, + zip->wbuff, sizeof(zip->wbuff)); + if (run == ARCHIVE_Z_FINISH && r != ARCHIVE_EOF) + continue; + } + if (zip->stream.avail_in == 0) + break; + } + if (run == ARCHIVE_Z_FINISH) { + uint64_t bytes = sizeof(zip->wbuff) - zip->stream.avail_out; + if (write_to_temp(a, zip->wbuff, (size_t)bytes) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + if ((zip->crc32flg & ENCODED_CRC32) && bytes) + zip->encoded_crc32 = crc32(zip->encoded_crc32, + zip->wbuff, (unsigned)bytes); + } + + return (s); +} + +static ssize_t +_7z_write_data(struct archive_write *a, const void *buff, size_t s) +{ + struct _7zip *zip; + ssize_t bytes; + + zip = (struct _7zip *)a->format_data; + + if (s > zip->entry_bytes_remaining) + s = (size_t)zip->entry_bytes_remaining; + if (s == 0 || zip->cur_file == NULL) + return (0); + bytes = compress_out(a, buff, s, ARCHIVE_Z_RUN); + if (bytes < 0) + return (bytes); + zip->entry_crc32 = crc32(zip->entry_crc32, buff, (unsigned)bytes); + zip->entry_bytes_remaining -= bytes; + return (bytes); +} + +static int +_7z_finish_entry(struct archive_write *a) +{ + struct _7zip *zip; + size_t s; + ssize_t r; + + zip = (struct _7zip *)a->format_data; + if (zip->cur_file == NULL) + return (ARCHIVE_OK); + + while (zip->entry_bytes_remaining > 0) { + s = (size_t)zip->entry_bytes_remaining; + if (s > a->null_length) + s = a->null_length; + r = _7z_write_data(a, a->nulls, s); + if (r < 0) + return ((int)r); + } + zip->total_bytes_compressed += zip->stream.total_in; + zip->total_bytes_uncompressed += zip->stream.total_out; + zip->cur_file->crc32 = zip->entry_crc32; + zip->cur_file = NULL; + + return (ARCHIVE_OK); +} + +static int +flush_wbuff(struct archive_write *a) +{ + struct _7zip *zip; + int r; + size_t s; + + zip = (struct _7zip *)a->format_data; + s = sizeof(zip->wbuff) - zip->wbuff_remaining; + r = __archive_write_output(a, zip->wbuff, s); + if (r != ARCHIVE_OK) + return (r); + zip->wbuff_remaining = sizeof(zip->wbuff); + return (r); +} + +static int +copy_out(struct archive_write *a, uint64_t offset, uint64_t length) +{ + struct _7zip *zip; + int r; + + zip = (struct _7zip *)a->format_data; + if (zip->temp_offset > 0 && + lseek(zip->temp_fd, offset, SEEK_SET) < 0) { + archive_set_error(&(a->archive), errno, "lseek failed"); + return (ARCHIVE_FATAL); + } + while (length) { + size_t rsize; + ssize_t rs; + unsigned char *wb; + + if (length > zip->wbuff_remaining) + rsize = zip->wbuff_remaining; + else + rsize = (size_t)length; + wb = zip->wbuff + (sizeof(zip->wbuff) - zip->wbuff_remaining); + rs = read(zip->temp_fd, wb, rsize); + if (rs < 0) { + archive_set_error(&(a->archive), errno, + "Can't read temporary file(%jd)", + (intmax_t)rs); + return (ARCHIVE_FATAL); + } + if (rs == 0) { + archive_set_error(&(a->archive), 0, + "Truncated 7-Zip archive"); + return (ARCHIVE_FATAL); + } + zip->wbuff_remaining -= rs; + length -= rs; + if (zip->wbuff_remaining == 0) { + r = flush_wbuff(a); + if (r != ARCHIVE_OK) + return (r); + } + } + return (ARCHIVE_OK); +} + +static int +_7z_close(struct archive_write *a) +{ + struct _7zip *zip; + unsigned char *wb; + uint64_t header_offset, header_size, header_unpacksize; + uint64_t length; + uint32_t header_crc32; + int r; + + zip = (struct _7zip *)a->format_data; + + if (zip->total_number_entry > 0) { + struct archive_rb_node *n; + uint64_t data_offset, data_size, data_unpacksize; + unsigned header_compression; + + r = (int)compress_out(a, NULL, 0, ARCHIVE_Z_FINISH); + if (r < 0) + return (r); + data_offset = 0; + data_size = zip->stream.total_out; + data_unpacksize = zip->stream.total_in; + zip->coder.codec = zip->opt_compression; + zip->coder.prop_size = zip->stream.prop_size; + zip->coder.props = zip->stream.props; + zip->stream.prop_size = 0; + zip->stream.props = NULL; + zip->total_number_nonempty_entry = + zip->total_number_entry - zip->total_number_empty_entry; + + /* Connect an empty file list. */ + if (zip->empty_list.first != NULL) { + *zip->file_list.last = zip->empty_list.first; + zip->file_list.last = zip->empty_list.last; + } + /* Connect a directory file list. */ + ARCHIVE_RB_TREE_FOREACH(n, &(zip->rbtree)) { + file_register(zip, (struct file *)n); + } + + /* + * NOTE: 7z command supports just LZMA1, LZMA2 and COPY for + * the compression type for encoding the header. + */ +#if HAVE_LZMA_H + header_compression = _7Z_LZMA1; + /* If the stored file is only one, do not encode the header. + * This is the same way 7z command does. */ + if (zip->total_number_entry == 1) + header_compression = _7Z_COPY; +#else + header_compression = _7Z_COPY; +#endif + r = _7z_compression_init_encoder(a, header_compression, 6); + if (r < 0) + return (r); + zip->crc32flg = PRECODE_CRC32; + zip->precode_crc32 = 0; + r = make_header(a, data_offset, data_size, data_unpacksize, + 1, &(zip->coder)); + if (r < 0) + return (r); + r = (int)compress_out(a, NULL, 0, ARCHIVE_Z_FINISH); + if (r < 0) + return (r); + header_offset = data_offset + data_size; + header_size = zip->stream.total_out; + header_crc32 = zip->precode_crc32; + header_unpacksize = zip->stream.total_in; + + if (header_compression != _7Z_COPY) { + /* + * Encode the header in order to reduce the size + * of the archive. + */ + free(zip->coder.props); + zip->coder.codec = header_compression; + zip->coder.prop_size = zip->stream.prop_size; + zip->coder.props = zip->stream.props; + zip->stream.prop_size = 0; + zip->stream.props = NULL; + + r = _7z_compression_init_encoder(a, _7Z_COPY, 0); + if (r < 0) + return (r); + zip->crc32flg = ENCODED_CRC32; + zip->encoded_crc32 = 0; + + /* + * Make EncodedHeader. + */ + r = enc_uint64(a, kEncodedHeader); + if (r < 0) + return (r); + r = make_streamsInfo(a, header_offset, header_size, + header_unpacksize, 1, &(zip->coder), 0, + header_crc32); + if (r < 0) + return (r); + r = (int)compress_out(a, NULL, 0, ARCHIVE_Z_FINISH); + if (r < 0) + return (r); + header_offset = header_offset + header_size; + header_size = zip->stream.total_out; + header_crc32 = zip->encoded_crc32; + } + zip->crc32flg = 0; + } else { + header_offset = header_size = 0; + header_crc32 = 0; + } + + length = zip->temp_offset; + + /* + * Make the zip header on wbuff(write buffer). + */ + wb = zip->wbuff; + zip->wbuff_remaining = sizeof(zip->wbuff); + memcpy(&wb[0], "7z\xBC\xAF\x27\x1C", 6); + wb[6] = 0;/* Major version. */ + wb[7] = 3;/* Minor version. */ + archive_le64enc(&wb[12], header_offset);/* Next Header Offset */ + archive_le64enc(&wb[20], header_size);/* Next Header Size */ + archive_le32enc(&wb[28], header_crc32);/* Next Header CRC */ + archive_le32enc(&wb[8], crc32(0, &wb[12], 20));/* Start Header CRC */ + zip->wbuff_remaining -= 32; + + /* + * Read all file contents and an encoded header from the temporary + * file and write out it. + */ + r = copy_out(a, 0, length); + if (r != ARCHIVE_OK) + return (r); + r = flush_wbuff(a); + return (r); +} + +/* + * Encode 64 bits value into 7-Zip's encoded UINT64 value. + */ +static int +enc_uint64(struct archive_write *a, uint64_t val) +{ + unsigned mask = 0x80; + uint8_t numdata[9]; + int i; + + numdata[0] = 0; + for (i = 1; i < (int)sizeof(numdata); i++) { + if (val < mask) { + numdata[0] |= (uint8_t)val; + break; + } + numdata[i] = (uint8_t)val; + val >>= 8; + numdata[0] |= mask; + mask >>= 1; + } + return ((int)compress_out(a, numdata, i, ARCHIVE_Z_RUN)); +} + +static int +make_substreamsInfo(struct archive_write *a, struct coder *coders) +{ + struct _7zip *zip = (struct _7zip *)a->format_data; + struct file *file; + int r; + + /* + * Make SubStreamsInfo. + */ + r = enc_uint64(a, kSubStreamsInfo); + if (r < 0) + return (r); + + if (zip->total_number_nonempty_entry > 1 && coders->codec != _7Z_COPY) { + /* + * Make NumUnPackStream. + */ + r = enc_uint64(a, kNumUnPackStream); + if (r < 0) + return (r); + + /* Write numUnpackStreams */ + r = enc_uint64(a, zip->total_number_nonempty_entry); + if (r < 0) + return (r); + + /* + * Make kSize. + */ + r = enc_uint64(a, kSize); + if (r < 0) + return (r); + file = zip->file_list.first; + for (;file != NULL; file = file->next) { + if (file->next == NULL || + file->next->size == 0) + break; + r = enc_uint64(a, file->size); + if (r < 0) + return (r); + } + } + + /* + * Make CRC. + */ + r = enc_uint64(a, kCRC); + if (r < 0) + return (r); + + + /* All are defined */ + r = enc_uint64(a, 1); + if (r < 0) + return (r); + file = zip->file_list.first; + for (;file != NULL; file = file->next) { + uint8_t crc[4]; + if (file->size == 0) + break; + archive_le32enc(crc, file->crc32); + r = (int)compress_out(a, crc, 4, ARCHIVE_Z_RUN); + if (r < 0) + return (r); + } + + /* Write End. */ + r = enc_uint64(a, kEnd); + if (r < 0) + return (r); + return (ARCHIVE_OK); +} + +static int +make_streamsInfo(struct archive_write *a, uint64_t offset, uint64_t pack_size, + uint64_t unpack_size, int num_coder, struct coder *coders, int substrm, + uint32_t header_crc) +{ + struct _7zip *zip = (struct _7zip *)a->format_data; + uint8_t codec_buff[8]; + int numFolders, fi; + int codec_size; + int i, r; + + if (coders->codec == _7Z_COPY) + numFolders = (int)zip->total_number_nonempty_entry; + else + numFolders = 1; + + /* + * Make PackInfo. + */ + r = enc_uint64(a, kPackInfo); + if (r < 0) + return (r); + + /* Write PackPos. */ + r = enc_uint64(a, offset); + if (r < 0) + return (r); + + /* Write NumPackStreams. */ + r = enc_uint64(a, numFolders); + if (r < 0) + return (r); + + /* Make Size. */ + r = enc_uint64(a, kSize); + if (r < 0) + return (r); + + if (numFolders > 1) { + struct file *file = zip->file_list.first; + for (;file != NULL; file = file->next) { + if (file->size == 0) + break; + r = enc_uint64(a, file->size); + if (r < 0) + return (r); + } + } else { + /* Write size. */ + r = enc_uint64(a, pack_size); + if (r < 0) + return (r); + } + + r = enc_uint64(a, kEnd); + if (r < 0) + return (r); + + /* + * Make UnPackInfo. + */ + r = enc_uint64(a, kUnPackInfo); + if (r < 0) + return (r); + + /* + * Make Folder. + */ + r = enc_uint64(a, kFolder); + if (r < 0) + return (r); + + /* Write NumFolders. */ + r = enc_uint64(a, numFolders); + if (r < 0) + return (r); + + /* Write External. */ + r = enc_uint64(a, 0); + if (r < 0) + return (r); + + for (fi = 0; fi < numFolders; fi++) { + /* Write NumCoders. */ + r = enc_uint64(a, num_coder); + if (r < 0) + return (r); + + for (i = 0; i < num_coder; i++) { + unsigned codec_id = coders[i].codec; + + /* Write Codec flag. */ + archive_be64enc(codec_buff, codec_id); + for (codec_size = 8; codec_size > 0; codec_size--) { + if (codec_buff[8 - codec_size]) + break; + } + if (codec_size == 0) + codec_size = 1; + if (coders[i].prop_size) + r = enc_uint64(a, codec_size | 0x20); + else + r = enc_uint64(a, codec_size); + if (r < 0) + return (r); + + /* Write Codec ID. */ + codec_size &= 0x0f; + r = (int)compress_out(a, &codec_buff[8-codec_size], + codec_size, ARCHIVE_Z_RUN); + if (r < 0) + return (r); + + if (coders[i].prop_size) { + /* Write Codec property size. */ + r = enc_uint64(a, coders[i].prop_size); + if (r < 0) + return (r); + + /* Write Codec properties. */ + r = (int)compress_out(a, coders[i].props, + coders[i].prop_size, ARCHIVE_Z_RUN); + if (r < 0) + return (r); + } + } + } + + /* + * Make CodersUnPackSize. + */ + r = enc_uint64(a, kCodersUnPackSize); + if (r < 0) + return (r); + + if (numFolders > 1) { + struct file *file = zip->file_list.first; + for (;file != NULL; file = file->next) { + if (file->size == 0) + break; + r = enc_uint64(a, file->size); + if (r < 0) + return (r); + } + + } else { + /* Write UnPackSize. */ + r = enc_uint64(a, unpack_size); + if (r < 0) + return (r); + } + + if (!substrm) { + uint8_t crc[4]; + /* + * Make CRC. + */ + r = enc_uint64(a, kCRC); + if (r < 0) + return (r); + + /* All are defined */ + r = enc_uint64(a, 1); + if (r < 0) + return (r); + archive_le32enc(crc, header_crc); + r = (int)compress_out(a, crc, 4, ARCHIVE_Z_RUN); + if (r < 0) + return (r); + } + + /* Write End. */ + r = enc_uint64(a, kEnd); + if (r < 0) + return (r); + + if (substrm) { + /* + * Make SubStreamsInfo. + */ + r = make_substreamsInfo(a, coders); + if (r < 0) + return (r); + } + + + /* Write End. */ + r = enc_uint64(a, kEnd); + if (r < 0) + return (r); + + return (ARCHIVE_OK); +} + + +#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) +static uint64_t +utcToFiletime(time_t t, long ns) +{ + uint64_t fileTime; + + fileTime = t; + fileTime *= 10000000; + fileTime += ns / 100; + fileTime += EPOC_TIME; + return (fileTime); +} + +static int +make_time(struct archive_write *a, uint8_t type, unsigned flg, int ti) +{ + uint8_t filetime[8]; + struct _7zip *zip = (struct _7zip *)a->format_data; + struct file *file; + int r; + uint8_t b, mask; + + /* + * Make Time Bools. + */ + if (zip->total_number_time_defined[ti] == zip->total_number_entry) { + /* Write Time Type. */ + r = enc_uint64(a, type); + if (r < 0) + return (r); + /* Write EmptyStream Size. */ + r = enc_uint64(a, 2 + zip->total_number_entry * 8); + if (r < 0) + return (r); + /* All are defined. */ + r = enc_uint64(a, 1); + if (r < 0) + return (r); + } else { + if (zip->total_number_time_defined[ti] == 0) + return (ARCHIVE_OK); + + /* Write Time Type. */ + r = enc_uint64(a, type); + if (r < 0) + return (r); + /* Write EmptyStream Size. */ + r = enc_uint64(a, 2 + ((zip->total_number_entry + 7) >> 3) + + zip->total_number_time_defined[ti] * 8); + if (r < 0) + return (r); + + /* All are not defined. */ + r = enc_uint64(a, 0); + if (r < 0) + return (r); + + b = 0; + mask = 0x80; + file = zip->file_list.first; + for (;file != NULL; file = file->next) { + if (file->flg & flg) + b |= mask; + mask >>= 1; + if (mask == 0) { + r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN); + if (r < 0) + return (r); + mask = 0x80; + b = 0; + } + } + if (mask != 0x80) { + r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN); + if (r < 0) + return (r); + } + } + + /* External. */ + r = enc_uint64(a, 0); + if (r < 0) + return (r); + + + /* + * Make Times. + */ + file = zip->file_list.first; + for (;file != NULL; file = file->next) { + if ((file->flg & flg) == 0) + continue; + archive_le64enc(filetime, utcToFiletime(file->times[ti].time, + file->times[ti].time_ns)); + r = (int)compress_out(a, filetime, 8, ARCHIVE_Z_RUN); + if (r < 0) + return (r); + } + + return (ARCHIVE_OK); +} + +static int +make_header(struct archive_write *a, uint64_t offset, uint64_t pack_size, + uint64_t unpack_size, int codernum, struct coder *coders) +{ + struct _7zip *zip = (struct _7zip *)a->format_data; + struct file *file; + int r; + uint8_t b, mask; + + /* + * Make FilesInfo. + */ + r = enc_uint64(a, kHeader); + if (r < 0) + return (r); + + /* + * If there are empty files only, do not write MainStreamInfo. + */ + if (zip->total_number_nonempty_entry) { + /* + * Make MainStreamInfo. + */ + r = enc_uint64(a, kMainStreamsInfo); + if (r < 0) + return (r); + r = make_streamsInfo(a, offset, pack_size, unpack_size, + codernum, coders, 1, 0); + if (r < 0) + return (r); + } + + /* + * Make FilesInfo. + */ + r = enc_uint64(a, kFilesInfo); + if (r < 0) + return (r); + + /* Write numFiles. */ + r = enc_uint64(a, zip->total_number_entry); + if (r < 0) + return (r); + + if (zip->total_number_empty_entry > 0) { + /* Make EmptyStream. */ + r = enc_uint64(a, kEmptyStream); + if (r < 0) + return (r); + + /* Write EmptyStream Size. */ + r = enc_uint64(a, (zip->total_number_entry+7)>>3); + if (r < 0) + return (r); + + b = 0; + mask = 0x80; + file = zip->file_list.first; + for (;file != NULL; file = file->next) { + if (file->size == 0) + b |= mask; + mask >>= 1; + if (mask == 0) { + r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN); + if (r < 0) + return (r); + mask = 0x80; + b = 0; + } + } + if (mask != 0x80) { + r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN); + if (r < 0) + return (r); + } + } + + if (zip->total_number_empty_entry > zip->total_number_dir_entry) { + /* Make EmptyFile. */ + r = enc_uint64(a, kEmptyFile); + if (r < 0) + return (r); + + /* Write EmptyFile Size. */ + r = enc_uint64(a, (zip->total_number_empty_entry + 7) >> 3); + if (r < 0) + return (r); + + b = 0; + mask = 0x80; + file = zip->file_list.first; + for (;file != NULL; file = file->next) { + if (file->size) + continue; + if (!file->dir) + b |= mask; + mask >>= 1; + if (mask == 0) { + r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN); + if (r < 0) + return (r); + mask = 0x80; + b = 0; + } + } + if (mask != 0x80) { + r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN); + if (r < 0) + return (r); + } + } + + /* Make Name. */ + r = enc_uint64(a, kName); + if (r < 0) + return (r); + - /* Write Nume size. */ ++ /* Write Name size. */ + r = enc_uint64(a, zip->total_bytes_entry_name+1); + if (r < 0) + return (r); + + /* Write dmy byte. */ + r = enc_uint64(a, 0); + if (r < 0) + return (r); + + file = zip->file_list.first; + for (;file != NULL; file = file->next) { + r = (int)compress_out(a, file->utf16name, file->name_len+2, + ARCHIVE_Z_RUN); + if (r < 0) + return (r); + } + + /* Make MTime. */ + r = make_time(a, kMTime, MTIME_IS_SET, MTIME); + if (r < 0) + return (r); + + /* Make CTime. */ + r = make_time(a, kCTime, CTIME_IS_SET, CTIME); + if (r < 0) + return (r); + + /* Make ATime. */ + r = make_time(a, kATime, ATIME_IS_SET, ATIME); + if (r < 0) + return (r); + + /* Make Attributes. */ + r = enc_uint64(a, kAttributes); + if (r < 0) + return (r); + + /* Write Attributes size. */ + r = enc_uint64(a, 2 + zip->total_number_entry * 4); + if (r < 0) + return (r); + + /* Write "All Are Defined". */ + r = enc_uint64(a, 1); + if (r < 0) + return (r); + + /* Write dmy byte. */ + r = enc_uint64(a, 0); + if (r < 0) + return (r); + + file = zip->file_list.first; + for (;file != NULL; file = file->next) { + /* + * High 16bits is unix mode. + * Low 16bits is Windows attributes. + */ + uint32_t encattr, attr; + if (file->dir) + attr = 0x8010; + else + attr = 0x8020; + if ((file->mode & 0222) == 0) + attr |= 1;/* Read Only. */ + attr |= ((uint32_t)file->mode) << 16; + archive_le32enc(&encattr, attr); + r = (int)compress_out(a, &encattr, 4, ARCHIVE_Z_RUN); + if (r < 0) + return (r); + } + + /* Write End. */ + r = enc_uint64(a, kEnd); + if (r < 0) + return (r); + + /* Write End. */ + r = enc_uint64(a, kEnd); + if (r < 0) + return (r); + + return (ARCHIVE_OK); +} + + +static int +_7z_free(struct archive_write *a) +{ + struct _7zip *zip = (struct _7zip *)a->format_data; + + /* Close the temporary file. */ + if (zip->temp_fd >= 0) + close(zip->temp_fd); + + file_free_register(zip); + compression_end(&(a->archive), &(zip->stream)); + free(zip->coder.props); + free(zip); + + return (ARCHIVE_OK); +} + +static int +file_cmp_node(const struct archive_rb_node *n1, + const struct archive_rb_node *n2) +{ + const struct file *f1 = (const struct file *)n1; + const struct file *f2 = (const struct file *)n2; + + if (f1->name_len == f2->name_len) + return (memcmp(f1->utf16name, f2->utf16name, f1->name_len)); + return (f1->name_len > f2->name_len)?1:-1; +} + +static int +file_cmp_key(const struct archive_rb_node *n, const void *key) +{ + const struct file *f = (const struct file *)n; + + return (f->name_len - *(const char *)key); +} + +static int +file_new(struct archive_write *a, struct archive_entry *entry, + struct file **newfile) +{ + struct _7zip *zip; + struct file *file; + const char *u16; + size_t u16len; + int ret = ARCHIVE_OK; + + zip = (struct _7zip *)a->format_data; + *newfile = NULL; + + file = calloc(1, sizeof(*file)); + if (file == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + + if (0 > archive_entry_pathname_l(entry, &u16, &u16len, zip->sconv)) { + if (errno == ENOMEM) { + free(file); + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for UTF-16LE"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "A filename cannot be converted to UTF-16LE;" + "You should disable making Joliet extension"); + ret = ARCHIVE_WARN; + } + file->utf16name = malloc(u16len + 2); + if (file->utf16name == NULL) { + free(file); + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Name"); + return (ARCHIVE_FATAL); + } + memcpy(file->utf16name, u16, u16len); + file->utf16name[u16len+0] = 0; + file->utf16name[u16len+1] = 0; + file->name_len = (unsigned)u16len; + file->mode = archive_entry_mode(entry); + if (archive_entry_filetype(entry) == AE_IFREG) + file->size = archive_entry_size(entry); + else + archive_entry_set_size(entry, 0); + if (archive_entry_filetype(entry) == AE_IFDIR) + file->dir = 1; + else if (archive_entry_filetype(entry) == AE_IFLNK) + file->size = strlen(archive_entry_symlink(entry)); + if (archive_entry_mtime_is_set(entry)) { + file->flg |= MTIME_IS_SET; + file->times[MTIME].time = archive_entry_mtime(entry); + file->times[MTIME].time_ns = archive_entry_mtime_nsec(entry); + } + if (archive_entry_atime_is_set(entry)) { + file->flg |= ATIME_IS_SET; + file->times[ATIME].time = archive_entry_atime(entry); + file->times[ATIME].time_ns = archive_entry_atime_nsec(entry); + } + if (archive_entry_ctime_is_set(entry)) { + file->flg |= CTIME_IS_SET; + file->times[CTIME].time = archive_entry_ctime(entry); + file->times[CTIME].time_ns = archive_entry_ctime_nsec(entry); + } + + *newfile = file; + return (ret); +} + +static void +file_free(struct file *file) +{ + free(file->utf16name); + free(file); +} + +static void +file_register(struct _7zip *zip, struct file *file) +{ + file->next = NULL; + *zip->file_list.last = file; + zip->file_list.last = &(file->next); +} + +static void +file_init_register(struct _7zip *zip) +{ + zip->file_list.first = NULL; + zip->file_list.last = &(zip->file_list.first); +} + +static void +file_free_register(struct _7zip *zip) +{ + struct file *file, *file_next; + + file = zip->file_list.first; + while (file != NULL) { + file_next = file->next; + file_free(file); + file = file_next; + } +} + +static void +file_register_empty(struct _7zip *zip, struct file *file) +{ + file->next = NULL; + *zip->empty_list.last = file; + zip->empty_list.last = &(file->next); +} + +static void +file_init_register_empty(struct _7zip *zip) +{ + zip->empty_list.first = NULL; + zip->empty_list.last = &(zip->empty_list.first); +} + +#if !defined(HAVE_ZLIB_H) || !defined(HAVE_BZLIB_H) ||\ + !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H) +static int +compression_unsupported_encoder(struct archive *a, + struct la_zstream *lastrm, const char *name) +{ + + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "%s compression not supported on this platform", name); + lastrm->valid = 0; + lastrm->real_stream = NULL; + return (ARCHIVE_FAILED); +} +#endif + +/* + * _7_COPY compressor. + */ +static int +compression_init_encoder_copy(struct archive *a, struct la_zstream *lastrm) +{ + + if (lastrm->valid) + compression_end(a, lastrm); + lastrm->valid = 1; + lastrm->code = compression_code_copy; + lastrm->end = compression_end_copy; + return (ARCHIVE_OK); +} + +static int +compression_code_copy(struct archive *a, + struct la_zstream *lastrm, enum la_zaction action) +{ + size_t bytes; + + (void)a; /* UNUSED */ + if (lastrm->avail_out > lastrm->avail_in) + bytes = lastrm->avail_in; + else + bytes = lastrm->avail_out; + if (bytes) { + memcpy(lastrm->next_out, lastrm->next_in, bytes); + lastrm->next_in += bytes; + lastrm->avail_in -= bytes; + lastrm->total_in += bytes; + lastrm->next_out += bytes; + lastrm->avail_out -= bytes; + lastrm->total_out += bytes; + } + if (action == ARCHIVE_Z_FINISH && lastrm->avail_in == 0) + return (ARCHIVE_EOF); + return (ARCHIVE_OK); +} + +static int +compression_end_copy(struct archive *a, struct la_zstream *lastrm) +{ + (void)a; /* UNUSED */ + lastrm->valid = 0; + return (ARCHIVE_OK); +} + +/* + * _7_DEFLATE compressor. + */ +#ifdef HAVE_ZLIB_H +static int +compression_init_encoder_deflate(struct archive *a, + struct la_zstream *lastrm, int level, int withheader) +{ + z_stream *strm; + + if (lastrm->valid) + compression_end(a, lastrm); + strm = calloc(1, sizeof(*strm)); + if (strm == NULL) { + archive_set_error(a, ENOMEM, + "Can't allocate memory for gzip stream"); + return (ARCHIVE_FATAL); + } + /* zlib.h is not const-correct, so we need this one bit + * of ugly hackery to convert a const * pointer to + * a non-const pointer. */ + strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in; + strm->avail_in = (uInt)lastrm->avail_in; + strm->total_in = (uLong)lastrm->total_in; + strm->next_out = lastrm->next_out; + strm->avail_out = (uInt)lastrm->avail_out; + strm->total_out = (uLong)lastrm->total_out; + if (deflateInit2(strm, level, Z_DEFLATED, + (withheader)?15:-15, + 8, Z_DEFAULT_STRATEGY) != Z_OK) { + free(strm); + lastrm->real_stream = NULL; + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Internal error initializing compression library"); + return (ARCHIVE_FATAL); + } + lastrm->real_stream = strm; + lastrm->valid = 1; + lastrm->code = compression_code_deflate; + lastrm->end = compression_end_deflate; + return (ARCHIVE_OK); +} + +static int +compression_code_deflate(struct archive *a, + struct la_zstream *lastrm, enum la_zaction action) +{ + z_stream *strm; + int r; + + strm = (z_stream *)lastrm->real_stream; + /* zlib.h is not const-correct, so we need this one bit + * of ugly hackery to convert a const * pointer to + * a non-const pointer. */ + strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in; + strm->avail_in = (uInt)lastrm->avail_in; + strm->total_in = (uLong)lastrm->total_in; + strm->next_out = lastrm->next_out; + strm->avail_out = (uInt)lastrm->avail_out; + strm->total_out = (uLong)lastrm->total_out; + r = deflate(strm, + (action == ARCHIVE_Z_FINISH)? Z_FINISH: Z_NO_FLUSH); + lastrm->next_in = strm->next_in; + lastrm->avail_in = strm->avail_in; + lastrm->total_in = strm->total_in; + lastrm->next_out = strm->next_out; + lastrm->avail_out = strm->avail_out; + lastrm->total_out = strm->total_out; + switch (r) { + case Z_OK: + return (ARCHIVE_OK); + case Z_STREAM_END: + return (ARCHIVE_EOF); + default: + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "GZip compression failed:" + " deflate() call returned status %d", r); + return (ARCHIVE_FATAL); + } +} + +static int +compression_end_deflate(struct archive *a, struct la_zstream *lastrm) +{ + z_stream *strm; + int r; + + strm = (z_stream *)lastrm->real_stream; + r = deflateEnd(strm); + free(strm); + lastrm->real_stream = NULL; + lastrm->valid = 0; + if (r != Z_OK) { + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Failed to clean up compressor"); + return (ARCHIVE_FATAL); + } + return (ARCHIVE_OK); +} +#else +static int +compression_init_encoder_deflate(struct archive *a, + struct la_zstream *lastrm, int level, int withheader) +{ + + (void) level; /* UNUSED */ + (void) withheader; /* UNUSED */ + if (lastrm->valid) + compression_end(a, lastrm); + return (compression_unsupported_encoder(a, lastrm, "deflate")); +} +#endif + +/* + * _7_BZIP2 compressor. + */ +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) +static int +compression_init_encoder_bzip2(struct archive *a, + struct la_zstream *lastrm, int level) +{ + bz_stream *strm; + + if (lastrm->valid) + compression_end(a, lastrm); + strm = calloc(1, sizeof(*strm)); + if (strm == NULL) { + archive_set_error(a, ENOMEM, + "Can't allocate memory for bzip2 stream"); + return (ARCHIVE_FATAL); + } + /* bzlib.h is not const-correct, so we need this one bit + * of ugly hackery to convert a const * pointer to + * a non-const pointer. */ + strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in; + strm->avail_in = lastrm->avail_in; + strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff); + strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32); + strm->next_out = (char *)lastrm->next_out; + strm->avail_out = lastrm->avail_out; + strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff); + strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32); + if (BZ2_bzCompressInit(strm, level, 0, 30) != BZ_OK) { + free(strm); + lastrm->real_stream = NULL; + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Internal error initializing compression library"); + return (ARCHIVE_FATAL); + } + lastrm->real_stream = strm; + lastrm->valid = 1; + lastrm->code = compression_code_bzip2; + lastrm->end = compression_end_bzip2; + return (ARCHIVE_OK); +} + +static int +compression_code_bzip2(struct archive *a, + struct la_zstream *lastrm, enum la_zaction action) +{ + bz_stream *strm; + int r; + + strm = (bz_stream *)lastrm->real_stream; + /* bzlib.h is not const-correct, so we need this one bit + * of ugly hackery to convert a const * pointer to + * a non-const pointer. */ + strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in; + strm->avail_in = lastrm->avail_in; + strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff); + strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32); + strm->next_out = (char *)lastrm->next_out; + strm->avail_out = lastrm->avail_out; + strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff); + strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32); + r = BZ2_bzCompress(strm, + (action == ARCHIVE_Z_FINISH)? BZ_FINISH: BZ_RUN); + lastrm->next_in = (const unsigned char *)strm->next_in; + lastrm->avail_in = strm->avail_in; + lastrm->total_in = + (((uint64_t)(uint32_t)strm->total_in_hi32) << 32) + + (uint64_t)(uint32_t)strm->total_in_lo32; + lastrm->next_out = (unsigned char *)strm->next_out; + lastrm->avail_out = strm->avail_out; + lastrm->total_out = + (((uint64_t)(uint32_t)strm->total_out_hi32) << 32) + + (uint64_t)(uint32_t)strm->total_out_lo32; + switch (r) { + case BZ_RUN_OK: /* Non-finishing */ + case BZ_FINISH_OK: /* Finishing: There's more work to do */ + return (ARCHIVE_OK); + case BZ_STREAM_END: /* Finishing: all done */ + /* Only occurs in finishing case */ + return (ARCHIVE_EOF); + default: + /* Any other return value indicates an error */ + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Bzip2 compression failed:" + " BZ2_bzCompress() call returned status %d", r); + return (ARCHIVE_FATAL); + } +} + +static int +compression_end_bzip2(struct archive *a, struct la_zstream *lastrm) +{ + bz_stream *strm; + int r; + + strm = (bz_stream *)lastrm->real_stream; + r = BZ2_bzCompressEnd(strm); + free(strm); + lastrm->real_stream = NULL; + lastrm->valid = 0; + if (r != BZ_OK) { + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Failed to clean up compressor"); + return (ARCHIVE_FATAL); + } + return (ARCHIVE_OK); +} + +#else +static int +compression_init_encoder_bzip2(struct archive *a, + struct la_zstream *lastrm, int level) +{ + + (void) level; /* UNUSED */ + if (lastrm->valid) + compression_end(a, lastrm); + return (compression_unsupported_encoder(a, lastrm, "bzip2")); +} +#endif + +/* + * _7_LZMA1, _7_LZMA2 compressor. + */ +#if defined(HAVE_LZMA_H) +static int +compression_init_encoder_lzma(struct archive *a, + struct la_zstream *lastrm, int level, uint64_t filter_id) +{ + static const lzma_stream lzma_init_data = LZMA_STREAM_INIT; + lzma_stream *strm; + lzma_filter *lzmafilters; + lzma_options_lzma lzma_opt; + int r; + + if (lastrm->valid) + compression_end(a, lastrm); + strm = calloc(1, sizeof(*strm) + sizeof(*lzmafilters) * 2); + if (strm == NULL) { + archive_set_error(a, ENOMEM, + "Can't allocate memory for lzma stream"); + return (ARCHIVE_FATAL); + } + lzmafilters = (lzma_filter *)(strm+1); + if (level > 6) + level = 6; + if (lzma_lzma_preset(&lzma_opt, level)) { + free(strm); + lastrm->real_stream = NULL; + archive_set_error(a, ENOMEM, + "Internal error initializing compression library"); + return (ARCHIVE_FATAL); + } + lzmafilters[0].id = filter_id; + lzmafilters[0].options = &lzma_opt; + lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */ + + r = lzma_properties_size(&(lastrm->prop_size), lzmafilters); + if (r != LZMA_OK) { + free(strm); + lastrm->real_stream = NULL; + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "lzma_properties_size failed"); + return (ARCHIVE_FATAL); + } + if (lastrm->prop_size) { + lastrm->props = malloc(lastrm->prop_size); + if (lastrm->props == NULL) { + free(strm); + lastrm->real_stream = NULL; + archive_set_error(a, ENOMEM, + "Cannot allocate memory"); + return (ARCHIVE_FATAL); + } + r = lzma_properties_encode(lzmafilters, lastrm->props); + if (r != LZMA_OK) { + free(strm); + lastrm->real_stream = NULL; + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "lzma_properties_encode failed"); + return (ARCHIVE_FATAL); + } + } + + *strm = lzma_init_data; + r = lzma_raw_encoder(strm, lzmafilters); + switch (r) { + case LZMA_OK: + lastrm->real_stream = strm; + lastrm->valid = 1; + lastrm->code = compression_code_lzma; + lastrm->end = compression_end_lzma; + r = ARCHIVE_OK; + break; + case LZMA_MEM_ERROR: + free(strm); + lastrm->real_stream = NULL; + archive_set_error(a, ENOMEM, + "Internal error initializing compression library: " + "Cannot allocate memory"); + r = ARCHIVE_FATAL; + break; + default: + free(strm); + lastrm->real_stream = NULL; + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Internal error initializing compression library: " + "It's a bug in liblzma"); + r = ARCHIVE_FATAL; + break; + } + return (r); +} + +static int +compression_init_encoder_lzma1(struct archive *a, + struct la_zstream *lastrm, int level) +{ + return compression_init_encoder_lzma(a, lastrm, level, + LZMA_FILTER_LZMA1); +} + +static int +compression_init_encoder_lzma2(struct archive *a, + struct la_zstream *lastrm, int level) +{ + return compression_init_encoder_lzma(a, lastrm, level, + LZMA_FILTER_LZMA2); +} + +static int +compression_code_lzma(struct archive *a, + struct la_zstream *lastrm, enum la_zaction action) +{ + lzma_stream *strm; + int r; + + strm = (lzma_stream *)lastrm->real_stream; + strm->next_in = lastrm->next_in; + strm->avail_in = lastrm->avail_in; + strm->total_in = lastrm->total_in; + strm->next_out = lastrm->next_out; + strm->avail_out = lastrm->avail_out; + strm->total_out = lastrm->total_out; + r = lzma_code(strm, + (action == ARCHIVE_Z_FINISH)? LZMA_FINISH: LZMA_RUN); + lastrm->next_in = strm->next_in; + lastrm->avail_in = strm->avail_in; + lastrm->total_in = strm->total_in; + lastrm->next_out = strm->next_out; + lastrm->avail_out = strm->avail_out; + lastrm->total_out = strm->total_out; + switch (r) { + case LZMA_OK: + /* Non-finishing case */ + return (ARCHIVE_OK); + case LZMA_STREAM_END: + /* This return can only occur in finishing case. */ + return (ARCHIVE_EOF); + case LZMA_MEMLIMIT_ERROR: + archive_set_error(a, ENOMEM, + "lzma compression error:" + " %ju MiB would have been needed", + (uintmax_t)((lzma_memusage(strm) + 1024 * 1024 -1) + / (1024 * 1024))); + return (ARCHIVE_FATAL); + default: + /* Any other return value indicates an error */ + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "lzma compression failed:" + " lzma_code() call returned status %d", r); + return (ARCHIVE_FATAL); + } +} + +static int +compression_end_lzma(struct archive *a, struct la_zstream *lastrm) +{ + lzma_stream *strm; + + (void)a; /* UNUSED */ + strm = (lzma_stream *)lastrm->real_stream; + lzma_end(strm); + free(strm); + lastrm->valid = 0; + lastrm->real_stream = NULL; + return (ARCHIVE_OK); +} +#else +static int +compression_init_encoder_lzma1(struct archive *a, + struct la_zstream *lastrm, int level) +{ + + (void) level; /* UNUSED */ + if (lastrm->valid) + compression_end(a, lastrm); + return (compression_unsupported_encoder(a, lastrm, "lzma")); +} +static int +compression_init_encoder_lzma2(struct archive *a, + struct la_zstream *lastrm, int level) +{ + + (void) level; /* UNUSED */ + if (lastrm->valid) + compression_end(a, lastrm); + return (compression_unsupported_encoder(a, lastrm, "lzma")); +} +#endif + +/* + * _7_PPMD compressor. + */ +static void * +ppmd_alloc(void *p, size_t size) +{ + (void)p; + return malloc(size); +} +static void +ppmd_free(void *p, void *address) +{ + (void)p; + free(address); +} +static ISzAlloc g_szalloc = { ppmd_alloc, ppmd_free }; +static void +ppmd_write(void *p, Byte b) +{ + struct archive_write *a = ((IByteOut *)p)->a; + struct _7zip *zip = (struct _7zip *)(a->format_data); + struct la_zstream *lastrm = &(zip->stream); + struct ppmd_stream *strm; + + if (lastrm->avail_out) { + *lastrm->next_out++ = b; + lastrm->avail_out--; + lastrm->total_out++; + return; + } + strm = (struct ppmd_stream *)lastrm->real_stream; + if (strm->buff_ptr < strm->buff_end) { + *strm->buff_ptr++ = b; + strm->buff_bytes++; + } +} + +static int +compression_init_encoder_ppmd(struct archive *a, + struct la_zstream *lastrm, unsigned maxOrder, uint32_t msize) +{ + struct ppmd_stream *strm; + uint8_t *props; + int r; + + if (lastrm->valid) + compression_end(a, lastrm); + strm = calloc(1, sizeof(*strm)); + if (strm == NULL) { + archive_set_error(a, ENOMEM, + "Can't allocate memory for PPMd"); + return (ARCHIVE_FATAL); + } + strm->buff = malloc(32); + if (strm->buff == NULL) { + free(strm); + archive_set_error(a, ENOMEM, + "Can't allocate memory for PPMd"); + return (ARCHIVE_FATAL); + } + strm->buff_ptr = strm->buff; + strm->buff_end = strm->buff + 32; + + props = malloc(1+4); + if (props == NULL) { + free(strm->buff); + free(strm); + archive_set_error(a, ENOMEM, + "Coludn't allocate memory for PPMd"); + return (ARCHIVE_FATAL); + } + props[0] = maxOrder; + archive_le32enc(props+1, msize); + __archive_ppmd7_functions.Ppmd7_Construct(&strm->ppmd7_context); + r = __archive_ppmd7_functions.Ppmd7_Alloc( + &strm->ppmd7_context, msize, &g_szalloc); + if (r == 0) { + free(strm->buff); + free(strm); + free(props); + archive_set_error(a, ENOMEM, + "Coludn't allocate memory for PPMd"); + return (ARCHIVE_FATAL); + } + __archive_ppmd7_functions.Ppmd7_Init(&(strm->ppmd7_context), maxOrder); + strm->byteout.a = (struct archive_write *)a; + strm->byteout.Write = ppmd_write; + strm->range_enc.Stream = &(strm->byteout); + __archive_ppmd7_functions.Ppmd7z_RangeEnc_Init(&(strm->range_enc)); + strm->stat = 0; + + lastrm->real_stream = strm; + lastrm->valid = 1; + lastrm->code = compression_code_ppmd; + lastrm->end = compression_end_ppmd; + lastrm->prop_size = 5; + lastrm->props = props; + return (ARCHIVE_OK); +} + +static int +compression_code_ppmd(struct archive *a, + struct la_zstream *lastrm, enum la_zaction action) +{ + struct ppmd_stream *strm; + + (void)a; /* UNUSED */ + + strm = (struct ppmd_stream *)lastrm->real_stream; + + /* Copy encoded data if there are remaining bytes from previous call. */ + if (strm->buff_bytes) { + uint8_t *p = strm->buff_ptr - strm->buff_bytes; + while (lastrm->avail_out && strm->buff_bytes) { + *lastrm->next_out++ = *p++; + lastrm->avail_out--; + lastrm->total_out++; + strm->buff_bytes--; + } + if (strm->buff_bytes) + return (ARCHIVE_OK); + if (strm->stat == 1) + return (ARCHIVE_EOF); + strm->buff_ptr = strm->buff; + } + while (lastrm->avail_in && lastrm->avail_out) { + __archive_ppmd7_functions.Ppmd7_EncodeSymbol( + &(strm->ppmd7_context), &(strm->range_enc), + *lastrm->next_in++); + lastrm->avail_in--; + lastrm->total_in++; + } + if (lastrm->avail_in == 0 && action == ARCHIVE_Z_FINISH) { + __archive_ppmd7_functions.Ppmd7z_RangeEnc_FlushData( + &(strm->range_enc)); + strm->stat = 1; + /* Return EOF if there are no remaining bytes. */ + if (strm->buff_bytes == 0) + return (ARCHIVE_EOF); + } + return (ARCHIVE_OK); +} + +static int +compression_end_ppmd(struct archive *a, struct la_zstream *lastrm) +{ + struct ppmd_stream *strm; + + (void)a; /* UNUSED */ + + strm = (struct ppmd_stream *)lastrm->real_stream; + __archive_ppmd7_functions.Ppmd7_Free(&strm->ppmd7_context, &g_szalloc); + free(strm->buff); + free(strm); + lastrm->real_stream = NULL; + lastrm->valid = 0; + return (ARCHIVE_OK); +} + +/* + * Universal compressor initializer. + */ +static int +_7z_compression_init_encoder(struct archive_write *a, unsigned compression, + int compression_level) +{ + struct _7zip *zip; + int r; + + zip = (struct _7zip *)a->format_data; + switch (compression) { + case _7Z_DEFLATE: + r = compression_init_encoder_deflate( + &(a->archive), &(zip->stream), + compression_level, 0); + break; + case _7Z_BZIP2: + r = compression_init_encoder_bzip2( + &(a->archive), &(zip->stream), + compression_level); + break; + case _7Z_LZMA1: + r = compression_init_encoder_lzma1( + &(a->archive), &(zip->stream), + compression_level); + break; + case _7Z_LZMA2: + r = compression_init_encoder_lzma2( + &(a->archive), &(zip->stream), + compression_level); + break; + case _7Z_PPMD: + r = compression_init_encoder_ppmd( + &(a->archive), &(zip->stream), + PPMD7_DEFAULT_ORDER, PPMD7_DEFAULT_MEM_SIZE); + break; + case _7Z_COPY: + default: + r = compression_init_encoder_copy( + &(a->archive), &(zip->stream)); + break; + } + if (r == ARCHIVE_OK) { + zip->stream.total_in = 0; + zip->stream.next_out = zip->wbuff; + zip->stream.avail_out = sizeof(zip->wbuff); + zip->stream.total_out = 0; + } + + return (r); +} + +static int +compression_code(struct archive *a, struct la_zstream *lastrm, + enum la_zaction action) +{ + if (lastrm->valid) + return (lastrm->code(a, lastrm, action)); + return (ARCHIVE_OK); +} + +static int +compression_end(struct archive *a, struct la_zstream *lastrm) +{ + if (lastrm->valid) { + lastrm->prop_size = 0; + free(lastrm->props); + lastrm->props = NULL; + return (lastrm->end(a, lastrm)); + } + return (ARCHIVE_OK); +} + + diff --cc Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c index 879a776,0000000..eb98491 mode 100644,000000..100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c @@@ -1,8160 -1,0 +1,8162 @@@ +/*- + * Copyright (c) 2009-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_UTSNAME_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_LIMITS_H +#include +#endif +#include +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_ZLIB_H +#include +#endif + +#include "archive.h" +#include "archive_endian.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_private.h" +#include "archive_rb.h" +#include "archive_write_private.h" + +#if defined(_WIN32) && !defined(__CYGWIN__) +#define getuid() 0 +#define getgid() 0 +#endif + +/*#define DEBUG 1*/ +#ifdef DEBUG +/* To compare to the ISO image file made by mkisofs. */ +#define COMPAT_MKISOFS 1 +#endif + +#define LOGICAL_BLOCK_BITS 11 +#define LOGICAL_BLOCK_SIZE 2048 +#define PATH_TABLE_BLOCK_SIZE 4096 + +#define SYSTEM_AREA_BLOCK 16 +#define PRIMARY_VOLUME_DESCRIPTOR_BLOCK 1 +#define SUPPLEMENTARY_VOLUME_DESCRIPTOR_BLOCK 1 +#define BOOT_RECORD_DESCRIPTOR_BLOCK 1 +#define VOLUME_DESCRIPTOR_SET_TERMINATOR_BLOCK 1 +#define NON_ISO_FILE_SYSTEM_INFORMATION_BLOCK 1 +#define RRIP_ER_BLOCK 1 +#define PADDING_BLOCK 150 + +#define FD_1_2M_SIZE (1024 * 1200) +#define FD_1_44M_SIZE (1024 * 1440) +#define FD_2_88M_SIZE (1024 * 2880) +#define MULTI_EXTENT_SIZE (ARCHIVE_LITERAL_LL(1) << 32) /* 4Gi bytes. */ +#define MAX_DEPTH 8 +#define RR_CE_SIZE 28 /* SUSP "CE" extension size */ + +#define FILE_FLAG_EXISTENCE 0x01 +#define FILE_FLAG_DIRECTORY 0x02 +#define FILE_FLAG_ASSOCIATED 0x04 +#define FILE_FLAG_RECORD 0x08 +#define FILE_FLAG_PROTECTION 0x10 +#define FILE_FLAG_MULTI_EXTENT 0x80 + +static const char rrip_identifier[] = + "RRIP_1991A"; +static const char rrip_descriptor[] = + "THE ROCK RIDGE INTERCHANGE PROTOCOL PROVIDES SUPPORT FOR " + "POSIX FILE SYSTEM SEMANTICS"; +static const char rrip_source[] = + "PLEASE CONTACT DISC PUBLISHER FOR SPECIFICATION SOURCE. " + "SEE PUBLISHER IDENTIFIER IN PRIMARY VOLUME DESCRIPTOR FOR " + "CONTACT INFORMATION."; +#define RRIP_ER_ID_SIZE (sizeof(rrip_identifier)-1) +#define RRIP_ER_DSC_SIZE (sizeof(rrip_descriptor)-1) +#define RRIP_ER_SRC_SIZE (sizeof(rrip_source)-1) +#define RRIP_ER_SIZE (8 + RRIP_ER_ID_SIZE + \ + RRIP_ER_DSC_SIZE + RRIP_ER_SRC_SIZE) + +static const unsigned char zisofs_magic[8] = { + 0x37, 0xE4, 0x53, 0x96, 0xC9, 0xDB, 0xD6, 0x07 +}; + +#define ZF_HEADER_SIZE 16 /* zisofs header size. */ +#define ZF_LOG2_BS 15 /* log2 block size; 32K bytes. */ +#define ZF_BLOCK_SIZE (1UL << ZF_LOG2_BS) + +/* + * Manage extra records. + */ +struct extr_rec { + int location; + int offset; + unsigned char buf[LOGICAL_BLOCK_SIZE]; + struct extr_rec *next; +}; + +struct ctl_extr_rec { + int use_extr; + unsigned char *bp; + struct isoent *isoent; + unsigned char *ce_ptr; + int cur_len; + int dr_len; + int limit; + int extr_off; + int extr_loc; +}; +#define DR_SAFETY RR_CE_SIZE +#define DR_LIMIT (254 - DR_SAFETY) + +/* + * The relation of struct isofile and isoent and archive_entry. + * + * Primary volume tree --> struct isoent + * | + * v + * struct isofile --> archive_entry + * ^ + * | + * Joliet volume tree --> struct isoent + * + * struct isoent has specific information for volume. + */ + +struct isofile { + /* Used for managing struct isofile list. */ + struct isofile *allnext; + struct isofile *datanext; - /* Used for managing a hardlined struct isofile list. */ ++ /* Used for managing a hardlinked struct isofile list. */ + struct isofile *hlnext; + struct isofile *hardlink_target; + + struct archive_entry *entry; + + /* + * Used for making a directory tree. + */ + struct archive_string parentdir; + struct archive_string basename; + struct archive_string basename_utf16; + struct archive_string symlink; + int dircnt; /* The number of elements of + * its parent directory */ + + /* + * Used for a Directory Record. + */ + struct content { + int64_t offset_of_temp; + int64_t size; + int blocks; + uint32_t location; + /* + * One extent equals one content. + * If this entry has multi extent, `next' variable points + * next content data. + */ + struct content *next; /* next content */ + } content, *cur_content; + int write_content; + + enum { + NO = 0, + BOOT_CATALOG, + BOOT_IMAGE + } boot; + + /* + * Used for a zisofs. + */ + struct { + unsigned char header_size; + unsigned char log2_bs; + uint32_t uncompressed_size; + } zisofs; +}; + +struct isoent { + /* Keep `rbnode' at the first member of struct isoent. */ + struct archive_rb_node rbnode; + + struct isofile *file; + + struct isoent *parent; + /* A list of children.(use chnext) */ + struct { + struct isoent *first; + struct isoent **last; + int cnt; + } children; + struct archive_rb_tree rbtree; + + /* A list of sub directories.(use drnext) */ + struct { + struct isoent *first; + struct isoent **last; + int cnt; + } subdirs; + /* A sorted list of sub directories. */ + struct isoent **children_sorted; + /* Used for managing struct isoent list. */ + struct isoent *chnext; + struct isoent *drnext; + struct isoent *ptnext; + + /* + * Used for making a Directory Record. + */ + int dir_number; + struct { + int vd; + int self; + int parent; + int normal; + } dr_len; + uint32_t dir_location; + int dir_block; + + /* + * Identifier: + * on primary, ISO9660 file/directory name. + * on joliet, UCS2 file/directory name. + * ext_off : offset of identifier extension. + * ext_len : length of identifier extension. + * id_len : byte size of identifier. + * on primary, this is ext_off + ext_len + version length. + * on joliet, this is ext_off + ext_len. + * mb_len : length of multibyte-character of identifier. + * on primary, mb_len and id_len are always the same. + * on joliet, mb_len and id_len are different. + */ + char *identifier; + int ext_off; + int ext_len; + int id_len; + int mb_len; + + /* + * Used for making a Rockridge extension. + * This is a part of Directory Records. + */ + struct isoent *rr_parent; + struct isoent *rr_child; + + /* Extra Record.(which we call in this source file) + * A maximum size of the Directory Record is 254. + * so, if generated RRIP data of a file cannot into a Directory + * Record because of its size, that surplus data relocate this + * Extra Record. + */ + struct { + struct extr_rec *first; + struct extr_rec **last; + struct extr_rec *current; + } extr_rec_list; + + int virtual:1; + /* If set to one, this file type is a directory. + * A convenience flag to be used as + * "archive_entry_filetype(isoent->file->entry) == AE_IFDIR". + */ + int dir:1; +}; + +struct hardlink { + struct archive_rb_node rbnode; + int nlink; + struct { + struct isofile *first; + struct isofile **last; + } file_list; +}; + +/* + * ISO writer options + */ +struct iso_option { + /* + * Usage : abstract-file= + * Type : string, max 37 bytes + * Default: Not specified + * COMPAT : mkisofs -abstract + * + * Specifies Abstract Filename. + * This file shall be described in the Root Directory + * and containing a abstract statement. + */ + unsigned int abstract_file:1; +#define OPT_ABSTRACT_FILE_DEFAULT 0 /* Not specified */ +#define ABSTRACT_FILE_SIZE 37 + + /* + * Usage : application-id= + * Type : string, max 128 bytes + * Default: Not specified + * COMPAT : mkisofs -A/-appid . + * + * Specifies Application Identifier. + * If the first byte is set to '_'(5F), the remaining + * bytes of this option shall specify an identifier + * for a file containing the identification of the + * application. + * This file shall be described in the Root Directory. + */ + unsigned int application_id:1; +#define OPT_APPLICATION_ID_DEFAULT 0 /* Use default identifier */ +#define APPLICATION_IDENTIFIER_SIZE 128 + + /* + * Usage : !allow-vernum + * Type : boolean + * Default: Enabled + * : Violates the ISO9660 standard if disable. + * COMPAT: mkisofs -N + * + * Allow filenames to use version numbers. + */ + unsigned int allow_vernum:1; +#define OPT_ALLOW_VERNUM_DEFAULT 1 /* Enabled */ + + /* + * Usage : biblio-file= + * Type : string, max 37 bytes + * Default: Not specified + * COMPAT : mkisofs -biblio + * + * Specifies Bibliographic Filename. + * This file shall be described in the Root Directory + * and containing bibliographic records. + */ + unsigned int biblio_file:1; +#define OPT_BIBLIO_FILE_DEFAULT 0 /* Not specified */ +#define BIBLIO_FILE_SIZE 37 + + /* + * Usage : boot= + * Type : string + * Default: Not specified + * COMPAT : mkisofs -b/-eltorito-boot + * + * Specifies "El Torito" boot image file to make + * a bootable CD. + */ + unsigned int boot:1; +#define OPT_BOOT_DEFAULT 0 /* Not specified */ + + /* + * Usage : boot-catalog= + * Type : string + * Default: "boot.catalog" + * COMPAT : mkisofs -c/-eltorito-catalog + * + * Specifies a fullpath of El Torito boot catalog. + */ + unsigned int boot_catalog:1; +#define OPT_BOOT_CATALOG_DEFAULT 0 /* Not specified */ + + /* + * Usage : boot-info-table + * Type : boolean + * Default: Disabled + * COMPAT : mkisofs -boot-info-table + * + * Modify the boot image file specified by `boot' + * option; ISO writer stores boot file information + * into the boot file in ISO image at offset 8 + * through offset 64. + */ + unsigned int boot_info_table:1; +#define OPT_BOOT_INFO_TABLE_DEFAULT 0 /* Disabled */ + + /* + * Usage : boot-load-seg= + * Type : hexadecimal + * Default: Not specified + * COMPAT : mkisofs -boot-load-seg + * + * Specifies a load segment for boot image. + * This is used with no-emulation mode. + */ + unsigned int boot_load_seg:1; +#define OPT_BOOT_LOAD_SEG_DEFAULT 0 /* Not specified */ + + /* + * Usage : boot-load-size= + * Type : decimal + * Default: Not specified + * COMPAT : mkisofs -boot-load-size + * + * Specifies a sector count for boot image. + * This is used with no-emulation mode. + */ + unsigned int boot_load_size:1; +#define OPT_BOOT_LOAD_SIZE_DEFAULT 0 /* Not specified */ + + /* + * Usage : boot-type= + * : 'no-emulation' : 'no emulation' image + * : 'fd' : floppy disk image + * : 'hard-disk' : hard disk image + * Type : string + * Default: Auto detect + * : We check a size of boot image; - * : If ths size is just 1.22M/1.44M/2.88M, ++ * : If the size is just 1.22M/1.44M/2.88M, + * : we assume boot_type is 'fd'; + * : otherwise boot_type is 'no-emulation'. + * COMPAT : + * boot=no-emulation + * mkisofs -no-emul-boot + * boot=fd + * This is a default on the mkisofs. + * boot=hard-disk + * mkisofs -hard-disk-boot + * + * Specifies a type of "El Torito" boot image. + */ + unsigned int boot_type:2; +#define OPT_BOOT_TYPE_AUTO 0 /* auto detect */ +#define OPT_BOOT_TYPE_NO_EMU 1 /* ``no emulation'' image */ +#define OPT_BOOT_TYPE_FD 2 /* floppy disk image */ +#define OPT_BOOT_TYPE_HARD_DISK 3 /* hard disk image */ +#define OPT_BOOT_TYPE_DEFAULT OPT_BOOT_TYPE_AUTO + + /* + * Usage : compression-level= + * Type : decimal + * Default: Not specified + * COMPAT : NONE + * + * Specifies compression level for option zisofs=direct. + */ + unsigned int compression_level:1; +#define OPT_COMPRESSION_LEVEL_DEFAULT 0 /* Not specified */ + + /* + * Usage : copyright-file= + * Type : string, max 37 bytes + * Default: Not specified + * COMPAT : mkisofs -copyright + * + * Specifies Copyright Filename. + * This file shall be described in the Root Directory + * and containing a copyright statement. + */ + unsigned int copyright_file:1; +#define OPT_COPYRIGHT_FILE_DEFAULT 0 /* Not specified */ +#define COPYRIGHT_FILE_SIZE 37 + + /* + * Usage : gid= + * Type : decimal + * Default: Not specified + * COMPAT : mkisofs -gid + * + * Specifies a group id to rewrite the group id of all files. + */ + unsigned int gid:1; +#define OPT_GID_DEFAULT 0 /* Not specified */ + + /* + * Usage : iso-level=[1234] + * Type : decimal + * Default: 1 + * COMPAT : mkisofs -iso-level + * + * Specifies ISO9600 Level. + * Level 1: [DEFAULT] + * - limits each file size less than 4Gi bytes; + * - a File Name shall not contain more than eight + * d-characters or eight d1-characters; + * - a File Name Extension shall not contain more than + * three d-characters or three d1-characters; + * - a Directory Identifier shall not contain more + * than eight d-characters or eight d1-characters. + * Level 2: + * - limits each file size less than 4Giga bytes; + * - a File Name shall not contain more than thirty + * d-characters or thirty d1-characters; + * - a File Name Extension shall not contain more than + * thirty d-characters or thirty d1-characters; + * - a Directory Identifier shall not contain more + * than thirty-one d-characters or thirty-one + * d1-characters. + * Level 3: + * - no limit of file size; use multi extent. + * Level 4: + * - this level 4 simulates mkisofs option + * '-iso-level 4'; + * - crate a enhanced volume as mkisofs doing; + * - allow a File Name to have leading dot; + * - allow a File Name to have all ASCII letters; + * - allow a File Name to have multiple dots; + * - allow more then 8 depths of directory trees; + * - disable a version number to a File Name; + * - disable a forced period to the tail of a File Name; - * - the maxinum length of files and directories is raised to 193. ++ * - the maximum length of files and directories is raised to 193. + * if rockridge option is disabled, raised to 207. + */ + unsigned int iso_level:3; +#define OPT_ISO_LEVEL_DEFAULT 1 /* ISO Level 1 */ + + /* + * Usage : joliet[=long] + * : !joliet + * : Do not generate Joliet Volume and Records. + * : joliet [DEFAULT] + * : Generates Joliet Volume and Directory Records. + * : [COMPAT: mkisofs -J/-joliet] + * : joliet=long + * : The joliet filenames are up to 103 Unicode + * : characters. + * : This option breaks the Joliet specification. + * : [COMPAT: mkisofs -J -joliet-long] + * Type : boolean/string + * Default: Enabled + * COMPAT : mkisofs -J / -joliet-long + * + * Generates Joliet Volume and Directory Records. + */ + unsigned int joliet:2; +#define OPT_JOLIET_DISABLE 0 /* Not generate Joliet Records. */ +#define OPT_JOLIET_ENABLE 1 /* Generate Joliet Records. */ +#define OPT_JOLIET_LONGNAME 2 /* Use long joliet filenames.*/ +#define OPT_JOLIET_DEFAULT OPT_JOLIET_ENABLE + + /* + * Usage : !limit-depth + * Type : boolean + * Default: Enabled + * : Violates the ISO9660 standard if disable. + * COMPAT : mkisofs -D/-disable-deep-relocation + * + * The number of levels in hierarchy cannot exceed eight. + */ + unsigned int limit_depth:1; +#define OPT_LIMIT_DEPTH_DEFAULT 1 /* Enabled */ + + /* + * Usage : !limit-dirs + * Type : boolean + * Default: Enabled + * : Violates the ISO9660 standard if disable. + * COMPAT : mkisofs -no-limit-pathtables + * + * Limits the number of directories less than 65536 due + * to the size of the Parent Directory Number of Path + * Table. + */ + unsigned int limit_dirs:1; +#define OPT_LIMIT_DIRS_DEFAULT 1 /* Enabled */ + + /* + * Usage : !pad + * Type : boolean + * Default: Enabled + * COMPAT : -pad/-no-pad + * + * Pads the end of the ISO image by null of 300Ki bytes. + */ + unsigned int pad:1; +#define OPT_PAD_DEFAULT 1 /* Enabled */ + + /* + * Usage : publisher= + * Type : string, max 128 bytes + * Default: Not specified + * COMPAT : mkisofs -publisher + * + * Specifies Publisher Identifier. + * If the first byte is set to '_'(5F), the remaining + * bytes of this option shall specify an identifier + * for a file containing the identification of the user. + * This file shall be described in the Root Directory. + */ + unsigned int publisher:1; +#define OPT_PUBLISHER_DEFAULT 0 /* Not specified */ +#define PUBLISHER_IDENTIFIER_SIZE 128 + + /* + * Usage : rockridge + * : !rockridge + * : disable to generate SUSP and RR records. + * : rockridge + * : the same as 'rockridge=useful'. + * : rockridge=strict + * : generate SUSP and RR records. + * : [COMPAT: mkisofs -R] + * : rockridge=useful [DEFAULT] + * : generate SUSP and RR records. + * : [COMPAT: mkisofs -r] + * : NOTE Our rockridge=useful option does not set a zero + * : to uid and gid, you should use application + * : option such as --gid,--gname,--uid and --uname - * : badtar options instead. ++ * : bsdtar options instead. + * Type : boolean/string + * Default: Enabled as rockridge=useful + * COMPAT : mkisofs -r / -R + * + * Generates SUSP and RR records. + */ + unsigned int rr:2; +#define OPT_RR_DISABLED 0 +#define OPT_RR_STRICT 1 +#define OPT_RR_USEFUL 2 +#define OPT_RR_DEFAULT OPT_RR_USEFUL + + /* + * Usage : volume-id= + * Type : string, max 32 bytes + * Default: Not specified + * COMPAT : mkisofs -V + * + * Specifies Volume Identifier. + */ + unsigned int volume_id:1; +#define OPT_VOLUME_ID_DEFAULT 0 /* Use default identifier */ +#define VOLUME_IDENTIFIER_SIZE 32 + + /* + * Usage : !zisofs [DEFAULT] + * : Disable to generate RRIP 'ZF' extension. + * : zisofs + * : Make files zisofs file and generate RRIP 'ZF' + * : extension. So you do not need mkzftree utility + * : for making zisofs. + * : When the file size is less than one Logical Block + * : size, that file will not zisofs'ed since it does - * : reduece an ISO-image size. ++ * : reduce an ISO-image size. + * : + * : When you specify option 'boot=', that + * : 'boot-image' file won't be converted to zisofs file. + * Type : boolean + * Default: Disabled + * + * Generates RRIP 'ZF' System Use Entry. + */ + unsigned int zisofs:1; +#define OPT_ZISOFS_DISABLED 0 +#define OPT_ZISOFS_DIRECT 1 +#define OPT_ZISOFS_DEFAULT OPT_ZISOFS_DISABLED + +}; + +struct iso9660 { + /* The creation time of ISO image. */ + time_t birth_time; + /* A file stream of a temporary file, which file contents - * save to until ISO iamge can be created. */ ++ * save to until ISO image can be created. */ + int temp_fd; + + struct isofile *cur_file; + struct isoent *cur_dirent; + struct archive_string cur_dirstr; + uint64_t bytes_remaining; + int need_multi_extent; + + /* Temporary string buffer for Joliet extension. */ + struct archive_string utf16be; + struct archive_string mbs; + + struct archive_string_conv *sconv_to_utf16be; + struct archive_string_conv *sconv_from_utf16be; + + /* A list of all of struct isofile entries. */ + struct { + struct isofile *first; + struct isofile **last; + } all_file_list; + + /* A list of struct isofile entries which have its - * contents and are not a directory, a hardlined file ++ * contents and are not a directory, a hardlinked file + * and a symlink file. */ + struct { + struct isofile *first; + struct isofile **last; + } data_file_list; + + /* Used for managing to find hardlinking files. */ + struct archive_rb_tree hardlink_rbtree; + + /* Used for making the Path Table Record. */ + struct vdd { + /* the root of entry tree. */ + struct isoent *rootent; + enum vdd_type { + VDD_PRIMARY, + VDD_JOLIET, + VDD_ENHANCED + } vdd_type; + + struct path_table { + struct isoent *first; + struct isoent **last; + struct isoent **sorted; + int cnt; + } *pathtbl; + int max_depth; + + int path_table_block; + int path_table_size; + int location_type_L_path_table; + int location_type_M_path_table; + int total_dir_block; + } primary, joliet; + + /* Used for making a Volume Descriptor. */ + int volume_space_size; + int volume_sequence_number; + int total_file_block; + struct archive_string volume_identifier; + struct archive_string publisher_identifier; + struct archive_string data_preparer_identifier; + struct archive_string application_identifier; + struct archive_string copyright_file_identifier; + struct archive_string abstract_file_identifier; + struct archive_string bibliographic_file_identifier; + + /* Used for making rockridge extensions. */ + int location_rrip_er; + + /* Used for making zisofs. */ + struct { + int detect_magic:1; + int making:1; + int allzero:1; + unsigned char magic_buffer[64]; + int magic_cnt; + +#ifdef HAVE_ZLIB_H + /* + * Copy a compressed file to iso9660.zisofs.temp_fd + * and also copy a uncompressed file(original file) to + * iso9660.temp_fd . If the number of logical block + * of the compressed file is less than the number of + * logical block of the uncompressed file, use it and + * remove the copy of the uncompressed file. + * but if not, we use uncompressed file and remove + * the copy of the compressed file. + */ + uint32_t *block_pointers; + size_t block_pointers_allocated; + int block_pointers_cnt; + int block_pointers_idx; + int64_t total_size; + int64_t block_offset; + + z_stream stream; + int stream_valid; + int64_t remaining; + int compression_level; +#endif + } zisofs; + + struct isoent *directories_too_deep; + int dircnt_max; + + /* Write buffer. */ +#define wb_buffmax() (LOGICAL_BLOCK_SIZE * 32) +#define wb_remaining(a) (((struct iso9660 *)(a)->format_data)->wbuff_remaining) +#define wb_offset(a) (((struct iso9660 *)(a)->format_data)->wbuff_offset \ + + wb_buffmax() - wb_remaining(a)) + unsigned char wbuff[LOGICAL_BLOCK_SIZE * 32]; + size_t wbuff_remaining; + enum { + WB_TO_STREAM, + WB_TO_TEMP + } wbuff_type; + int64_t wbuff_offset; + int64_t wbuff_written; + int64_t wbuff_tail; + + /* 'El Torito' boot data. */ + struct { + /* boot catalog file */ + struct archive_string catalog_filename; + struct isoent *catalog; + /* boot image file */ + struct archive_string boot_filename; + struct isoent *boot; + + unsigned char platform_id; +#define BOOT_PLATFORM_X86 0 +#define BOOT_PLATFORM_PPC 1 +#define BOOT_PLATFORM_MAC 2 + struct archive_string id; + unsigned char media_type; +#define BOOT_MEDIA_NO_EMULATION 0 +#define BOOT_MEDIA_1_2M_DISKETTE 1 +#define BOOT_MEDIA_1_44M_DISKETTE 2 +#define BOOT_MEDIA_2_88M_DISKETTE 3 +#define BOOT_MEDIA_HARD_DISK 4 + unsigned char system_type; + uint16_t boot_load_seg; + uint16_t boot_load_size; +#define BOOT_LOAD_SIZE 4 + } el_torito; + + struct iso_option opt; +}; + +/* + * Types of Volume Descriptor + */ +enum VD_type { + VDT_BOOT_RECORD=0, /* Boot Record Volume Descriptor */ + VDT_PRIMARY=1, /* Primary Volume Descriptor */ + VDT_SUPPLEMENTARY=2, /* Supplementary Volume Descriptor */ + VDT_TERMINATOR=255 /* Volume Descriptor Set Terminator */ +}; + +/* + * Types of Directory Record + */ +enum dir_rec_type { + DIR_REC_VD, /* Stored in Volume Descriptor. */ + DIR_REC_SELF, /* Stored as Current Directory. */ + DIR_REC_PARENT, /* Stored as Parent Directory. */ + DIR_REC_NORMAL /* Stored as Child. */ +}; + +/* + * Kinds of Volume Descriptor Character + */ +enum vdc { + VDC_STD, + VDC_LOWERCASE, + VDC_UCS2, + VDC_UCS2_DIRECT +}; + +/* + * IDentifier Resolver. + * Used for resolving duplicated filenames. + */ +struct idr { + struct idrent { + struct archive_rb_node rbnode; + /* Used in wait_list. */ + struct idrent *wnext; + struct idrent *avail; + + struct isoent *isoent; + int weight; + int noff; + int rename_num; + } *idrent_pool; + + struct archive_rb_tree rbtree; + + struct { + struct idrent *first; + struct idrent **last; + } wait_list; + + int pool_size; + int pool_idx; + int num_size; + int null_size; + + char char_map[0x80]; +}; + +enum char_type { + A_CHAR, + D_CHAR +}; + + +static int iso9660_options(struct archive_write *, + const char *, const char *); +static int iso9660_write_header(struct archive_write *, + struct archive_entry *); +static ssize_t iso9660_write_data(struct archive_write *, + const void *, size_t); +static int iso9660_finish_entry(struct archive_write *); +static int iso9660_close(struct archive_write *); +static int iso9660_free(struct archive_write *); + +static void get_system_identitier(char *, size_t); +static void set_str(unsigned char *, const char *, size_t, char, + const char *); +static inline int joliet_allowed_char(unsigned char, unsigned char); +static int set_str_utf16be(struct archive_write *, unsigned char *, + const char *, size_t, uint16_t, enum vdc); +static int set_str_a_characters_bp(struct archive_write *, + unsigned char *, int, int, const char *, enum vdc); +static int set_str_d_characters_bp(struct archive_write *, + unsigned char *, int, int, const char *, enum vdc); +static void set_VD_bp(unsigned char *, enum VD_type, unsigned char); +static inline void set_unused_field_bp(unsigned char *, int, int); + +static unsigned char *extra_open_record(unsigned char *, int, + struct isoent *, struct ctl_extr_rec *); +static void extra_close_record(struct ctl_extr_rec *, int); +static unsigned char * extra_next_record(struct ctl_extr_rec *, int); +static unsigned char *extra_get_record(struct isoent *, int *, int *, int *); +static void extra_tell_used_size(struct ctl_extr_rec *, int); +static int extra_setup_location(struct isoent *, int); +static int set_directory_record_rr(unsigned char *, int, + struct isoent *, struct iso9660 *, enum dir_rec_type); +static int set_directory_record(unsigned char *, size_t, + struct isoent *, struct iso9660 *, enum dir_rec_type, + enum vdd_type); +static inline int get_dir_rec_size(struct iso9660 *, struct isoent *, + enum dir_rec_type, enum vdd_type); +static inline unsigned char *wb_buffptr(struct archive_write *); +static int wb_write_out(struct archive_write *); +static int wb_consume(struct archive_write *, size_t); +#ifdef HAVE_ZLIB_H +static int wb_set_offset(struct archive_write *, int64_t); +#endif +static int write_null(struct archive_write *, size_t); +static int write_VD_terminator(struct archive_write *); +static int set_file_identifier(unsigned char *, int, int, enum vdc, + struct archive_write *, struct vdd *, + struct archive_string *, const char *, int, + enum char_type); +static int write_VD(struct archive_write *, struct vdd *); +static int write_VD_boot_record(struct archive_write *); +static int write_information_block(struct archive_write *); +static int write_path_table(struct archive_write *, int, + struct vdd *); +static int write_directory_descriptors(struct archive_write *, + struct vdd *); +static int write_file_descriptors(struct archive_write *); +static int write_rr_ER(struct archive_write *); +static void calculate_path_table_size(struct vdd *); + +static void isofile_init_entry_list(struct iso9660 *); +static void isofile_add_entry(struct iso9660 *, struct isofile *); +static void isofile_free_all_entries(struct iso9660 *); +static void isofile_init_entry_data_file_list(struct iso9660 *); +static void isofile_add_data_file(struct iso9660 *, struct isofile *); +static struct isofile * isofile_new(struct archive_write *, + struct archive_entry *); +static void isofile_free(struct isofile *); +static int isofile_gen_utility_names(struct archive_write *, + struct isofile *); +static int isofile_register_hardlink(struct archive_write *, + struct isofile *); +static void isofile_connect_hardlink_files(struct iso9660 *); +static void isofile_init_hardlinks(struct iso9660 *); +static void isofile_free_hardlinks(struct iso9660 *); + +static struct isoent *isoent_new(struct isofile *); +static int isoent_clone_tree(struct archive_write *, + struct isoent **, struct isoent *); +static void _isoent_free(struct isoent *isoent); +static void isoent_free_all(struct isoent *); +static struct isoent * isoent_create_virtual_dir(struct archive_write *, + struct iso9660 *, const char *); +static int isoent_cmp_node(const struct archive_rb_node *, + const struct archive_rb_node *); +static int isoent_cmp_key(const struct archive_rb_node *, + const void *); +static int isoent_add_child_head(struct isoent *, struct isoent *); +static int isoent_add_child_tail(struct isoent *, struct isoent *); +static void isoent_remove_child(struct isoent *, struct isoent *); +static void isoent_setup_directory_location(struct iso9660 *, + int, struct vdd *); +static void isoent_setup_file_location(struct iso9660 *, int); +static int get_path_component(char *, size_t, const char *); +static int isoent_tree(struct archive_write *, struct isoent **); +static struct isoent *isoent_find_child(struct isoent *, const char *); +static struct isoent *isoent_find_entry(struct isoent *, const char *); +static void idr_relaxed_filenames(char *); +static void idr_init(struct iso9660 *, struct vdd *, struct idr *); +static void idr_cleanup(struct idr *); +static int idr_ensure_poolsize(struct archive_write *, struct idr *, + int); +static int idr_start(struct archive_write *, struct idr *, + int, int, int, int, const struct archive_rb_tree_ops *); +static void idr_register(struct idr *, struct isoent *, int, + int); +static void idr_extend_identifier(struct idrent *, int, int); +static void idr_resolve(struct idr *, void (*)(unsigned char *, int)); +static void idr_set_num(unsigned char *, int); +static void idr_set_num_beutf16(unsigned char *, int); +static int isoent_gen_iso9660_identifier(struct archive_write *, + struct isoent *, struct idr *); +static int isoent_gen_joliet_identifier(struct archive_write *, + struct isoent *, struct idr *); +static int isoent_cmp_iso9660_identifier(const struct isoent *, + const struct isoent *); +static int isoent_cmp_node_iso9660(const struct archive_rb_node *, + const struct archive_rb_node *); +static int isoent_cmp_key_iso9660(const struct archive_rb_node *, + const void *); +static int isoent_cmp_joliet_identifier(const struct isoent *, + const struct isoent *); +static int isoent_cmp_node_joliet(const struct archive_rb_node *, + const struct archive_rb_node *); +static int isoent_cmp_key_joliet(const struct archive_rb_node *, + const void *); +static inline void path_table_add_entry(struct path_table *, struct isoent *); +static inline struct isoent * path_table_last_entry(struct path_table *); +static int isoent_make_path_table(struct archive_write *); +static int isoent_find_out_boot_file(struct archive_write *, + struct isoent *); +static int isoent_create_boot_catalog(struct archive_write *, + struct isoent *); +static size_t fd_boot_image_size(int); +static int make_boot_catalog(struct archive_write *); +static int setup_boot_information(struct archive_write *); + +static int zisofs_init(struct archive_write *, struct isofile *); +static void zisofs_detect_magic(struct archive_write *, + const void *, size_t); +static int zisofs_write_to_temp(struct archive_write *, + const void *, size_t); +static int zisofs_finish_entry(struct archive_write *); +static int zisofs_rewind_boot_file(struct archive_write *); +static int zisofs_free(struct archive_write *); + +int +archive_write_set_format_iso9660(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct iso9660 *iso9660; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_set_format_iso9660"); + + /* If another format was already registered, unregister it. */ + if (a->format_free != NULL) + (a->format_free)(a); + + iso9660 = calloc(1, sizeof(*iso9660)); + if (iso9660 == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate iso9660 data"); + return (ARCHIVE_FATAL); + } + iso9660->birth_time = 0; + iso9660->temp_fd = -1; + iso9660->cur_file = NULL; + iso9660->primary.max_depth = 0; + iso9660->primary.vdd_type = VDD_PRIMARY; + iso9660->primary.pathtbl = NULL; + iso9660->joliet.rootent = NULL; + iso9660->joliet.max_depth = 0; + iso9660->joliet.vdd_type = VDD_JOLIET; + iso9660->joliet.pathtbl = NULL; + isofile_init_entry_list(iso9660); + isofile_init_entry_data_file_list(iso9660); + isofile_init_hardlinks(iso9660); + iso9660->directories_too_deep = NULL; + iso9660->dircnt_max = 1; + iso9660->wbuff_remaining = wb_buffmax(); + iso9660->wbuff_type = WB_TO_TEMP; + iso9660->wbuff_offset = 0; + iso9660->wbuff_written = 0; + iso9660->wbuff_tail = 0; + archive_string_init(&(iso9660->utf16be)); + archive_string_init(&(iso9660->mbs)); + + /* + * Init Identifiers used for PVD and SVD. + */ + archive_string_init(&(iso9660->volume_identifier)); + archive_strcpy(&(iso9660->volume_identifier), "CDROM"); + archive_string_init(&(iso9660->publisher_identifier)); + archive_string_init(&(iso9660->data_preparer_identifier)); + archive_string_init(&(iso9660->application_identifier)); + archive_strcpy(&(iso9660->application_identifier), + archive_version_string()); + archive_string_init(&(iso9660->copyright_file_identifier)); + archive_string_init(&(iso9660->abstract_file_identifier)); + archive_string_init(&(iso9660->bibliographic_file_identifier)); + + /* + * Init El Torito bootable CD variables. + */ + archive_string_init(&(iso9660->el_torito.catalog_filename)); + iso9660->el_torito.catalog = NULL; + /* Set default file name of boot catalog */ + archive_strcpy(&(iso9660->el_torito.catalog_filename), + "boot.catalog"); + archive_string_init(&(iso9660->el_torito.boot_filename)); + iso9660->el_torito.boot = NULL; + iso9660->el_torito.platform_id = BOOT_PLATFORM_X86; + archive_string_init(&(iso9660->el_torito.id)); + iso9660->el_torito.boot_load_seg = 0; + iso9660->el_torito.boot_load_size = BOOT_LOAD_SIZE; + + /* + * Init zisofs variables. + */ +#ifdef HAVE_ZLIB_H + iso9660->zisofs.block_pointers = NULL; + iso9660->zisofs.block_pointers_allocated = 0; + iso9660->zisofs.stream_valid = 0; + iso9660->zisofs.compression_level = 9; + memset(&(iso9660->zisofs.stream), 0, + sizeof(iso9660->zisofs.stream)); +#endif + + /* + * Set default value of iso9660 options. + */ + iso9660->opt.abstract_file = OPT_ABSTRACT_FILE_DEFAULT; + iso9660->opt.application_id = OPT_APPLICATION_ID_DEFAULT; + iso9660->opt.allow_vernum = OPT_ALLOW_VERNUM_DEFAULT; + iso9660->opt.biblio_file = OPT_BIBLIO_FILE_DEFAULT; + iso9660->opt.boot = OPT_BOOT_DEFAULT; + iso9660->opt.boot_catalog = OPT_BOOT_CATALOG_DEFAULT; + iso9660->opt.boot_info_table = OPT_BOOT_INFO_TABLE_DEFAULT; + iso9660->opt.boot_load_seg = OPT_BOOT_LOAD_SEG_DEFAULT; + iso9660->opt.boot_load_size = OPT_BOOT_LOAD_SIZE_DEFAULT; + iso9660->opt.boot_type = OPT_BOOT_TYPE_DEFAULT; + iso9660->opt.compression_level = OPT_COMPRESSION_LEVEL_DEFAULT; + iso9660->opt.copyright_file = OPT_COPYRIGHT_FILE_DEFAULT; + iso9660->opt.iso_level = OPT_ISO_LEVEL_DEFAULT; + iso9660->opt.joliet = OPT_JOLIET_DEFAULT; + iso9660->opt.limit_depth = OPT_LIMIT_DEPTH_DEFAULT; + iso9660->opt.limit_dirs = OPT_LIMIT_DIRS_DEFAULT; + iso9660->opt.pad = OPT_PAD_DEFAULT; + iso9660->opt.publisher = OPT_PUBLISHER_DEFAULT; + iso9660->opt.rr = OPT_RR_DEFAULT; + iso9660->opt.volume_id = OPT_VOLUME_ID_DEFAULT; + iso9660->opt.zisofs = OPT_ZISOFS_DEFAULT; + + /* Create the root directory. */ + iso9660->primary.rootent = + isoent_create_virtual_dir(a, iso9660, ""); + if (iso9660->primary.rootent == NULL) { + free(iso9660); + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + iso9660->primary.rootent->parent = iso9660->primary.rootent; + iso9660->cur_dirent = iso9660->primary.rootent; + archive_string_init(&(iso9660->cur_dirstr)); + archive_string_ensure(&(iso9660->cur_dirstr), 1); + iso9660->cur_dirstr.s[0] = 0; + iso9660->sconv_to_utf16be = NULL; + iso9660->sconv_from_utf16be = NULL; + + a->format_data = iso9660; + a->format_name = "iso9660"; + a->format_options = iso9660_options; + a->format_write_header = iso9660_write_header; + a->format_write_data = iso9660_write_data; + a->format_finish_entry = iso9660_finish_entry; + a->format_close = iso9660_close; + a->format_free = iso9660_free; + a->archive.archive_format = ARCHIVE_FORMAT_ISO9660; + a->archive.archive_format_name = "ISO9660"; + + return (ARCHIVE_OK); +} + +static int +get_str_opt(struct archive_write *a, struct archive_string *s, + size_t maxsize, const char *key, const char *value) +{ + + if (strlen(value) > maxsize) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Value is longer than %zu characters " + "for option ``%s''", maxsize, key); + return (ARCHIVE_FATAL); + } + archive_strcpy(s, value); + return (ARCHIVE_OK); +} + +static int +get_num_opt(struct archive_write *a, int *num, int high, int low, + const char *key, const char *value) +{ + const char *p = value; + int data = 0; + int neg = 0; + + if (p == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid value(empty) for option ``%s''", key); + return (ARCHIVE_FATAL); + } + if (*p == '-') { + neg = 1; + p++; + } + while (*p) { + if (*p >= '0' && *p <= '9') + data = data * 10 + *p - '0'; + else { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid value for option ``%s''", key); + return (ARCHIVE_FATAL); + } + if (data > high) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid value(over %d) for " + "option ``%s''", high, key); + return (ARCHIVE_FATAL); + } + if (data < low) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid value(under %d) for " + "option ``%s''", low, key); + return (ARCHIVE_FATAL); + } + p++; + } + if (neg) + data *= -1; + *num = data; + + return (ARCHIVE_OK); +} + +static int +iso9660_options(struct archive_write *a, const char *key, const char *value) +{ + struct iso9660 *iso9660 = a->format_data; + const char *p; + int r; + + switch (key[0]) { + case 'a': + if (strcmp(key, "abstract-file") == 0) { + r = get_str_opt(a, + &(iso9660->abstract_file_identifier), + ABSTRACT_FILE_SIZE, key, value); + iso9660->opt.abstract_file = r == ARCHIVE_OK; + return (r); + } + if (strcmp(key, "application-id") == 0) { + r = get_str_opt(a, + &(iso9660->application_identifier), + APPLICATION_IDENTIFIER_SIZE, key, value); + iso9660->opt.application_id = r == ARCHIVE_OK; + return (r); + } + if (strcmp(key, "allow-vernum") == 0) { + iso9660->opt.allow_vernum = value != NULL; + return (ARCHIVE_OK); + } + break; + case 'b': + if (strcmp(key, "biblio-file") == 0) { + r = get_str_opt(a, + &(iso9660->bibliographic_file_identifier), + BIBLIO_FILE_SIZE, key, value); + iso9660->opt.biblio_file = r == ARCHIVE_OK; + return (r); + } + if (strcmp(key, "boot") == 0) { + if (value == NULL) + iso9660->opt.boot = 0; + else { + iso9660->opt.boot = 1; + archive_strcpy( + &(iso9660->el_torito.boot_filename), + value); + } + return (ARCHIVE_OK); + } + if (strcmp(key, "boot-catalog") == 0) { + r = get_str_opt(a, + &(iso9660->el_torito.catalog_filename), + 1024, key, value); + iso9660->opt.boot_catalog = r == ARCHIVE_OK; + return (r); + } + if (strcmp(key, "boot-info-table") == 0) { + iso9660->opt.boot_info_table = value != NULL; + return (ARCHIVE_OK); + } + if (strcmp(key, "boot-load-seg") == 0) { + uint32_t seg; + + iso9660->opt.boot_load_seg = 0; + if (value == NULL) + goto invalid_value; + seg = 0; + p = value; + if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) + p += 2; + while (*p) { + if (seg) + seg <<= 4; + if (*p >= 'A' && *p <= 'F') + seg += *p - 'A' + 0x0a; + else if (*p >= 'a' && *p <= 'f') + seg += *p - 'a' + 0x0a; + else if (*p >= '0' && *p <= '9') + seg += *p - '0'; + else + goto invalid_value; + if (seg > 0xffff) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Invalid value(over 0xffff) for " + "option ``%s''", key); + return (ARCHIVE_FATAL); + } + p++; + } + iso9660->el_torito.boot_load_seg = (uint16_t)seg; + iso9660->opt.boot_load_seg = 1; + return (ARCHIVE_OK); + } + if (strcmp(key, "boot-load-size") == 0) { + int num = 0; + r = get_num_opt(a, &num, 0xffff, 1, key, value); + iso9660->opt.boot_load_size = r == ARCHIVE_OK; + if (r != ARCHIVE_OK) + return (ARCHIVE_FATAL); + iso9660->el_torito.boot_load_size = (uint16_t)num; + return (ARCHIVE_OK); + } + if (strcmp(key, "boot-type") == 0) { + if (value == NULL) + goto invalid_value; + if (strcmp(value, "no-emulation") == 0) + iso9660->opt.boot_type = OPT_BOOT_TYPE_NO_EMU; + else if (strcmp(value, "fd") == 0) + iso9660->opt.boot_type = OPT_BOOT_TYPE_FD; + else if (strcmp(value, "hard-disk") == 0) + iso9660->opt.boot_type = OPT_BOOT_TYPE_HARD_DISK; + else + goto invalid_value; + return (ARCHIVE_OK); + } + break; + case 'c': + if (strcmp(key, "compression-level") == 0) { +#ifdef HAVE_ZLIB_H + if (value == NULL || + !(value[0] >= '0' && value[0] <= '9') || + value[1] != '\0') + goto invalid_value; + iso9660->zisofs.compression_level = value[0] - '0'; + iso9660->opt.compression_level = 1; + return (ARCHIVE_OK); +#else + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Option ``%s'' " + "is not supported on this platform.", key); + return (ARCHIVE_FATAL); +#endif + } + if (strcmp(key, "copyright-file") == 0) { + r = get_str_opt(a, + &(iso9660->copyright_file_identifier), + COPYRIGHT_FILE_SIZE, key, value); + iso9660->opt.copyright_file = r == ARCHIVE_OK; + return (r); + } +#ifdef DEBUG + /* Specifies Volume creation date and time; + * year(4),month(2),day(2),hour(2),minute(2),second(2). + * e.g. "20090929033757" + */ + if (strcmp(key, "creation") == 0) { + struct tm tm; + char buf[5]; + + p = value; + if (p == NULL || strlen(p) < 14) + goto invalid_value; + memset(&tm, 0, sizeof(tm)); + memcpy(buf, p, 4); buf[4] = '\0'; p += 4; + tm.tm_year = strtol(buf, NULL, 10) - 1900; + memcpy(buf, p, 2); buf[2] = '\0'; p += 2; + tm.tm_mon = strtol(buf, NULL, 10) - 1; + memcpy(buf, p, 2); buf[2] = '\0'; p += 2; + tm.tm_mday = strtol(buf, NULL, 10); + memcpy(buf, p, 2); buf[2] = '\0'; p += 2; + tm.tm_hour = strtol(buf, NULL, 10); + memcpy(buf, p, 2); buf[2] = '\0'; p += 2; + tm.tm_min = strtol(buf, NULL, 10); + memcpy(buf, p, 2); buf[2] = '\0'; + tm.tm_sec = strtol(buf, NULL, 10); + iso9660->birth_time = mktime(&tm); + return (ARCHIVE_OK); + } +#endif + break; + case 'i': + if (strcmp(key, "iso-level") == 0) { + if (value != NULL && value[1] == '\0' && + (value[0] >= '1' && value[0] <= '4')) { + iso9660->opt.iso_level = value[0]-'0'; + return (ARCHIVE_OK); + } + goto invalid_value; + } + break; + case 'j': + if (strcmp(key, "joliet") == 0) { + if (value == NULL) + iso9660->opt.joliet = OPT_JOLIET_DISABLE; + else if (strcmp(value, "1") == 0) + iso9660->opt.joliet = OPT_JOLIET_ENABLE; + else if (strcmp(value, "long") == 0) + iso9660->opt.joliet = OPT_JOLIET_LONGNAME; + else + goto invalid_value; + return (ARCHIVE_OK); + } + break; + case 'l': + if (strcmp(key, "limit-depth") == 0) { + iso9660->opt.limit_depth = value != NULL; + return (ARCHIVE_OK); + } + if (strcmp(key, "limit-dirs") == 0) { + iso9660->opt.limit_dirs = value != NULL; + return (ARCHIVE_OK); + } + break; + case 'p': + if (strcmp(key, "pad") == 0) { + iso9660->opt.pad = value != NULL; + return (ARCHIVE_OK); + } + if (strcmp(key, "publisher") == 0) { + r = get_str_opt(a, + &(iso9660->publisher_identifier), + PUBLISHER_IDENTIFIER_SIZE, key, value); + iso9660->opt.publisher = r == ARCHIVE_OK; + return (r); + } + break; + case 'r': + if (strcmp(key, "rockridge") == 0 || + strcmp(key, "Rockridge") == 0) { + if (value == NULL) + iso9660->opt.rr = OPT_RR_DISABLED; + else if (strcmp(value, "1") == 0) + iso9660->opt.rr = OPT_RR_USEFUL; + else if (strcmp(value, "strict") == 0) + iso9660->opt.rr = OPT_RR_STRICT; + else if (strcmp(value, "useful") == 0) + iso9660->opt.rr = OPT_RR_USEFUL; + else + goto invalid_value; + return (ARCHIVE_OK); + } + break; + case 'v': + if (strcmp(key, "volume-id") == 0) { + r = get_str_opt(a, &(iso9660->volume_identifier), + VOLUME_IDENTIFIER_SIZE, key, value); + iso9660->opt.volume_id = r == ARCHIVE_OK; + return (r); + } + break; + case 'z': + if (strcmp(key, "zisofs") == 0) { + if (value == NULL) + iso9660->opt.zisofs = OPT_ZISOFS_DISABLED; + else { +#ifdef HAVE_ZLIB_H + iso9660->opt.zisofs = OPT_ZISOFS_DIRECT; +#else + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "``zisofs'' " + "is not supported on this platform."); + return (ARCHIVE_FATAL); +#endif + } + return (ARCHIVE_OK); + } + break; + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); + +invalid_value: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid value for option ``%s''", key); + return (ARCHIVE_FAILED); +} + +static int +iso9660_write_header(struct archive_write *a, struct archive_entry *entry) +{ + struct iso9660 *iso9660; + struct isofile *file; + struct isoent *isoent; + int r, ret = ARCHIVE_OK; + + iso9660 = a->format_data; + + iso9660->cur_file = NULL; + iso9660->bytes_remaining = 0; + iso9660->need_multi_extent = 0; + if (archive_entry_filetype(entry) == AE_IFLNK + && iso9660->opt.rr == OPT_RR_DISABLED) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Ignore symlink file."); + iso9660->cur_file = NULL; + return (ARCHIVE_WARN); + } + if (archive_entry_filetype(entry) == AE_IFREG && + archive_entry_size(entry) >= MULTI_EXTENT_SIZE) { + if (iso9660->opt.iso_level < 3) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Ignore over %lld bytes file. " + "This file too large.", + MULTI_EXTENT_SIZE); + iso9660->cur_file = NULL; + return (ARCHIVE_WARN); + } + iso9660->need_multi_extent = 1; + } + + file = isofile_new(a, entry); + if (file == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate data"); + return (ARCHIVE_FATAL); + } + r = isofile_gen_utility_names(a, file); + if (r < ARCHIVE_WARN) { + isofile_free(file); + return (r); + } + else if (r < ret) + ret = r; + + /* + * Ignore a path which looks like the top of directory name + * since we have already made the root directory of an ISO image. + */ + if (archive_strlen(&(file->parentdir)) == 0 && + archive_strlen(&(file->basename)) == 0) { + isofile_free(file); + return (r); + } + + isofile_add_entry(iso9660, file); + isoent = isoent_new(file); + if (isoent == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate data"); + return (ARCHIVE_FATAL); + } + if (isoent->file->dircnt > iso9660->dircnt_max) + iso9660->dircnt_max = isoent->file->dircnt; + + /* Add the current file into tree */ + r = isoent_tree(a, &isoent); + if (r != ARCHIVE_OK) + return (r); + + /* If there is the same file in tree and + * the current file is older than the file in tree. + * So we don't need the current file data anymore. */ + if (isoent->file != file) + return (ARCHIVE_OK); + + /* Non regular files contents are unneeded to be saved to + * temporary files. */ + if (archive_entry_filetype(file->entry) != AE_IFREG) + return (ret); + + /* + * Set the current file to cur_file to read its contents. + */ + iso9660->cur_file = file; + + if (archive_entry_nlink(file->entry) > 1) { + r = isofile_register_hardlink(a, file); + if (r != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + + /* + * Prepare to save the contents of the file. + */ + if (iso9660->temp_fd < 0) { + iso9660->temp_fd = __archive_mktemp(NULL); + if (iso9660->temp_fd < 0) { + archive_set_error(&a->archive, errno, + "Couldn't create temporary file"); + return (ARCHIVE_FATAL); + } + } + + /* Save an offset of current file in temporary file. */ + file->content.offset_of_temp = wb_offset(a); + file->cur_content = &(file->content); + r = zisofs_init(a, file); + if (r < ret) + ret = r; + iso9660->bytes_remaining = archive_entry_size(file->entry); + + return (ret); +} + +static int +write_to_temp(struct archive_write *a, const void *buff, size_t s) +{ + struct iso9660 *iso9660 = a->format_data; + ssize_t written; + const unsigned char *b; + + b = (const unsigned char *)buff; + while (s) { + written = write(iso9660->temp_fd, b, s); + if (written < 0) { + archive_set_error(&a->archive, errno, + "Can't write to temporary file"); + return (ARCHIVE_FATAL); + } + s -= written; + b += written; + } + return (ARCHIVE_OK); +} + +static int +wb_write_to_temp(struct archive_write *a, const void *buff, size_t s) +{ + const char *xp = buff; + size_t xs = s; + + /* + * If a written data size is big enough to use system-call + * and there is no waiting data, this calls write_to_temp() in + * order to reduce a extra memory copy. + */ + if (wb_remaining(a) == wb_buffmax() && s > (1024 * 16)) { + struct iso9660 *iso9660 = (struct iso9660 *)a->format_data; + xs = s % LOGICAL_BLOCK_SIZE; + iso9660->wbuff_offset += s - xs; + if (write_to_temp(a, buff, s - xs) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + if (xs == 0) + return (ARCHIVE_OK); + xp += s - xs; + } + + while (xs) { + size_t size = xs; + if (size > wb_remaining(a)) + size = wb_remaining(a); + memcpy(wb_buffptr(a), xp, size); + if (wb_consume(a, size) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + xs -= size; + xp += size; + } + return (ARCHIVE_OK); +} + +static int +wb_write_padding_to_temp(struct archive_write *a, int64_t csize) +{ + size_t ns; + int ret; + + ns = (size_t)(csize % LOGICAL_BLOCK_SIZE); + if (ns != 0) + ret = write_null(a, LOGICAL_BLOCK_SIZE - ns); + else + ret = ARCHIVE_OK; + return (ret); +} + +static ssize_t +write_iso9660_data(struct archive_write *a, const void *buff, size_t s) +{ + struct iso9660 *iso9660 = a->format_data; + size_t ws; + + if (iso9660->temp_fd < 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Couldn't create temporary file"); + return (ARCHIVE_FATAL); + } + + ws = s; + if (iso9660->need_multi_extent && + (iso9660->cur_file->cur_content->size + ws) >= + (MULTI_EXTENT_SIZE - LOGICAL_BLOCK_SIZE)) { + struct content *con; + size_t ts; + + ts = (size_t)(MULTI_EXTENT_SIZE - LOGICAL_BLOCK_SIZE - + iso9660->cur_file->cur_content->size); + + if (iso9660->zisofs.detect_magic) + zisofs_detect_magic(a, buff, ts); + + if (iso9660->zisofs.making) { + if (zisofs_write_to_temp(a, buff, ts) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } else { + if (wb_write_to_temp(a, buff, ts) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + iso9660->cur_file->cur_content->size += ts; + } + + /* Write padding. */ + if (wb_write_padding_to_temp(a, + iso9660->cur_file->cur_content->size) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* Compute the logical block number. */ + iso9660->cur_file->cur_content->blocks = (int) + ((iso9660->cur_file->cur_content->size + + LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS); + + /* + * Make next extent. + */ + ws -= ts; + buff = (const void *)(((const unsigned char *)buff) + ts); + /* Make a content for next extent. */ + con = calloc(1, sizeof(*con)); + if (con == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate content data"); + return (ARCHIVE_FATAL); + } + con->offset_of_temp = wb_offset(a); + iso9660->cur_file->cur_content->next = con; + iso9660->cur_file->cur_content = con; +#ifdef HAVE_ZLIB_H + iso9660->zisofs.block_offset = 0; +#endif + } + + if (iso9660->zisofs.detect_magic) + zisofs_detect_magic(a, buff, ws); + + if (iso9660->zisofs.making) { + if (zisofs_write_to_temp(a, buff, ws) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } else { + if (wb_write_to_temp(a, buff, ws) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + iso9660->cur_file->cur_content->size += ws; + } + + return (s); +} + +static ssize_t +iso9660_write_data(struct archive_write *a, const void *buff, size_t s) +{ + struct iso9660 *iso9660 = a->format_data; + ssize_t r; + + if (iso9660->cur_file == NULL) + return (0); + if (archive_entry_filetype(iso9660->cur_file->entry) != AE_IFREG) + return (0); + if (s > iso9660->bytes_remaining) + s = (size_t)iso9660->bytes_remaining; + if (s == 0) + return (0); + + r = write_iso9660_data(a, buff, s); + if (r > 0) + iso9660->bytes_remaining -= r; + return (r); +} + +static int +iso9660_finish_entry(struct archive_write *a) +{ + struct iso9660 *iso9660 = a->format_data; + + if (iso9660->cur_file == NULL) + return (ARCHIVE_OK); + if (archive_entry_filetype(iso9660->cur_file->entry) != AE_IFREG) + return (ARCHIVE_OK); + if (iso9660->cur_file->content.size == 0) + return (ARCHIVE_OK); + + /* If there are unwritten data, write null data instead. */ + while (iso9660->bytes_remaining > 0) { + size_t s; + + s = (iso9660->bytes_remaining > a->null_length)? + a->null_length: (size_t)iso9660->bytes_remaining; + if (write_iso9660_data(a, a->nulls, s) < 0) + return (ARCHIVE_FATAL); + iso9660->bytes_remaining -= s; + } + + if (iso9660->zisofs.making && zisofs_finish_entry(a) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* Write padding. */ + if (wb_write_padding_to_temp(a, iso9660->cur_file->cur_content->size) + != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* Compute the logical block number. */ + iso9660->cur_file->cur_content->blocks = (int) + ((iso9660->cur_file->cur_content->size + + LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS); + + /* Add the current file to data file list. */ + isofile_add_data_file(iso9660, iso9660->cur_file); + + return (ARCHIVE_OK); +} + +static int +iso9660_close(struct archive_write *a) +{ + struct iso9660 *iso9660; + int ret, blocks; + + iso9660 = a->format_data; + + /* + * Write remaining data out to the temporary file. + */ + if (wb_remaining(a) > 0) { + ret = wb_write_out(a); + if (ret < 0) + return (ret); + } + + /* + * Preparations... + */ +#ifdef DEBUG + if (iso9660->birth_time == 0) +#endif + time(&(iso9660->birth_time)); + + /* + * Prepare a bootable ISO image. + */ + if (iso9660->opt.boot) { + /* Find out the boot file entry. */ + ret = isoent_find_out_boot_file(a, iso9660->primary.rootent); + if (ret < 0) + return (ret); + /* Reconvert the boot file from zisofs'ed form to + * plain form. */ + ret = zisofs_rewind_boot_file(a); + if (ret < 0) + return (ret); + /* Write remaining data out to the temporary file. */ + if (wb_remaining(a) > 0) { + ret = wb_write_out(a); + if (ret < 0) + return (ret); + } + /* Create the boot catalog. */ + ret = isoent_create_boot_catalog(a, iso9660->primary.rootent); + if (ret < 0) + return (ret); + } + + /* + * Prepare joliet extensions. + */ + if (iso9660->opt.joliet) { + /* Make a new tree for joliet. */ + ret = isoent_clone_tree(a, &(iso9660->joliet.rootent), + iso9660->primary.rootent); + if (ret < 0) + return (ret); - /* Make sure we have UTF-16BE convertors. - * if there is no file entry, convertors are still - * uninitilized. */ ++ /* Make sure we have UTF-16BE converters. ++ * if there is no file entry, converters are still ++ * uninitialized. */ + if (iso9660->sconv_to_utf16be == NULL) { + iso9660->sconv_to_utf16be = + archive_string_conversion_to_charset( + &(a->archive), "UTF-16BE", 1); + if (iso9660->sconv_to_utf16be == NULL) + /* Couldn't allocate memory */ + return (ARCHIVE_FATAL); + iso9660->sconv_from_utf16be = + archive_string_conversion_from_charset( + &(a->archive), "UTF-16BE", 1); + if (iso9660->sconv_from_utf16be == NULL) + /* Couldn't allocate memory */ + return (ARCHIVE_FATAL); + } + } + + /* + * Make Path Tables. + */ + ret = isoent_make_path_table(a); + if (ret < 0) + return (ret); + + /* + * Calculate a total volume size and setup all locations of + * contents of an iso9660 image. + */ + blocks = SYSTEM_AREA_BLOCK + + PRIMARY_VOLUME_DESCRIPTOR_BLOCK + + VOLUME_DESCRIPTOR_SET_TERMINATOR_BLOCK + + NON_ISO_FILE_SYSTEM_INFORMATION_BLOCK; + if (iso9660->opt.boot) + blocks += BOOT_RECORD_DESCRIPTOR_BLOCK; + if (iso9660->opt.joliet) + blocks += SUPPLEMENTARY_VOLUME_DESCRIPTOR_BLOCK; + if (iso9660->opt.iso_level == 4) + blocks += SUPPLEMENTARY_VOLUME_DESCRIPTOR_BLOCK; + + /* Setup the locations of Path Table. */ + iso9660->primary.location_type_L_path_table = blocks; + blocks += iso9660->primary.path_table_block; + iso9660->primary.location_type_M_path_table = blocks; + blocks += iso9660->primary.path_table_block; + if (iso9660->opt.joliet) { + iso9660->joliet.location_type_L_path_table = blocks; + blocks += iso9660->joliet.path_table_block; + iso9660->joliet.location_type_M_path_table = blocks; + blocks += iso9660->joliet.path_table_block; + } + + /* Setup the locations of directories. */ + isoent_setup_directory_location(iso9660, blocks, + &(iso9660->primary)); + blocks += iso9660->primary.total_dir_block; + if (iso9660->opt.joliet) { + isoent_setup_directory_location(iso9660, blocks, + &(iso9660->joliet)); + blocks += iso9660->joliet.total_dir_block; + } + + if (iso9660->opt.rr) { + iso9660->location_rrip_er = blocks; + blocks += RRIP_ER_BLOCK; + } + + /* Setup the locations of all file contents. */ + isoent_setup_file_location(iso9660, blocks); + blocks += iso9660->total_file_block; + if (iso9660->opt.boot && iso9660->opt.boot_info_table) { + ret = setup_boot_information(a); + if (ret < 0) + return (ret); + } + + /* Now we have a total volume size. */ + iso9660->volume_space_size = blocks; + if (iso9660->opt.pad) + iso9660->volume_space_size += PADDING_BLOCK; + iso9660->volume_sequence_number = 1; + + + /* + * Write an ISO 9660 image. + */ + - /* Switc to start using wbuff as file buffer. */ ++ /* Switch to start using wbuff as file buffer. */ + iso9660->wbuff_remaining = wb_buffmax(); + iso9660->wbuff_type = WB_TO_STREAM; + iso9660->wbuff_offset = 0; + iso9660->wbuff_written = 0; + iso9660->wbuff_tail = 0; + + /* Write The System Area */ + ret = write_null(a, SYSTEM_AREA_BLOCK * LOGICAL_BLOCK_SIZE); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* Write Primary Volume Descriptor */ + ret = write_VD(a, &(iso9660->primary)); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + if (iso9660->opt.boot) { + /* Write Boot Record Volume Descriptor */ + ret = write_VD_boot_record(a); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + + if (iso9660->opt.iso_level == 4) { + /* Write Enhanced Volume Descriptor */ + iso9660->primary.vdd_type = VDD_ENHANCED; + ret = write_VD(a, &(iso9660->primary)); + iso9660->primary.vdd_type = VDD_PRIMARY; + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + + if (iso9660->opt.joliet) { + ret = write_VD(a, &(iso9660->joliet)); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + + /* Write Volume Descriptor Set Terminator */ + ret = write_VD_terminator(a); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* Write Non-ISO File System Information */ + ret = write_information_block(a); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* Write Type L Path Table */ + ret = write_path_table(a, 0, &(iso9660->primary)); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* Write Type M Path Table */ + ret = write_path_table(a, 1, &(iso9660->primary)); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + if (iso9660->opt.joliet) { + /* Write Type L Path Table */ + ret = write_path_table(a, 0, &(iso9660->joliet)); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* Write Type M Path Table */ + ret = write_path_table(a, 1, &(iso9660->joliet)); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + + /* Write Directory Descriptors */ + ret = write_directory_descriptors(a, &(iso9660->primary)); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + if (iso9660->opt.joliet) { + ret = write_directory_descriptors(a, &(iso9660->joliet)); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + + if (iso9660->opt.rr) { + /* Write Rockridge ER(Extensions Reference) */ + ret = write_rr_ER(a); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + + /* Write File Descriptors */ + ret = write_file_descriptors(a); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* Write Padding */ + if (iso9660->opt.pad) { + ret = write_null(a, PADDING_BLOCK * LOGICAL_BLOCK_SIZE); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + + if (iso9660->directories_too_deep != NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "%s: Directories too deep.", + archive_entry_pathname( + iso9660->directories_too_deep->file->entry)); + return (ARCHIVE_WARN); + } + + /* Write remaining data out. */ + ret = wb_write_out(a); + + return (ret); +} + +static int +iso9660_free(struct archive_write *a) +{ + struct iso9660 *iso9660; + int i, ret; + + iso9660 = a->format_data; + + /* Close the temporary file. */ + if (iso9660->temp_fd >= 0) + close(iso9660->temp_fd); + + /* Free some stuff for zisofs operations. */ + ret = zisofs_free(a); + + /* Remove directory entries in tree which includes file entries. */ + isoent_free_all(iso9660->primary.rootent); + for (i = 0; i < iso9660->primary.max_depth; i++) + free(iso9660->primary.pathtbl[i].sorted); + free(iso9660->primary.pathtbl); + + if (iso9660->opt.joliet) { + isoent_free_all(iso9660->joliet.rootent); + for (i = 0; i < iso9660->joliet.max_depth; i++) + free(iso9660->joliet.pathtbl[i].sorted); + free(iso9660->joliet.pathtbl); + } + + /* Remove isofile entries. */ + isofile_free_all_entries(iso9660); + isofile_free_hardlinks(iso9660); + + archive_string_free(&(iso9660->cur_dirstr)); + archive_string_free(&(iso9660->volume_identifier)); + archive_string_free(&(iso9660->publisher_identifier)); + archive_string_free(&(iso9660->data_preparer_identifier)); + archive_string_free(&(iso9660->application_identifier)); + archive_string_free(&(iso9660->copyright_file_identifier)); + archive_string_free(&(iso9660->abstract_file_identifier)); + archive_string_free(&(iso9660->bibliographic_file_identifier)); + archive_string_free(&(iso9660->el_torito.catalog_filename)); + archive_string_free(&(iso9660->el_torito.boot_filename)); + archive_string_free(&(iso9660->el_torito.id)); + archive_string_free(&(iso9660->utf16be)); + archive_string_free(&(iso9660->mbs)); + + free(iso9660); + a->format_data = NULL; + + return (ret); +} + +/* + * Get the System Identifier + */ +static void +get_system_identitier(char *system_id, size_t size) +{ +#if defined(HAVE_SYS_UTSNAME_H) + struct utsname u; + + uname(&u); + strncpy(system_id, u.sysname, size-1); + system_id[size-1] = '\0'; +#elif defined(_WIN32) && !defined(__CYGWIN__) + strncpy(system_id, "Windows", size-1); + system_id[size-1] = '\0'; +#else +#error no way to get the system identifier on your platform. +#endif +} + +static void +set_str(unsigned char *p, const char *s, size_t l, char f, const char *map) +{ + unsigned char c; + + if (s == NULL) + s = ""; + while ((c = *s++) != 0 && l > 0) { + if (c >= 0x80 || map[c] == 0) + { + /* illegal character */ + if (c >= 'a' && c <= 'z') { + /* convert c from a-z to A-Z */ + c -= 0x20; + } else + c = 0x5f; + } + *p++ = c; + l--; + } + /* If l isn't zero, fill p buffer by the character + * which indicated by f. */ + if (l > 0) + memset(p , f, l); +} + +static inline int +joliet_allowed_char(unsigned char high, unsigned char low) +{ + int utf16 = (high << 8) | low; + + if (utf16 <= 0x001F) + return (0); + + switch (utf16) { + case 0x002A: /* '*' */ + case 0x002F: /* '/' */ + case 0x003A: /* ':' */ + case 0x003B: /* ';' */ + case 0x003F: /* '?' */ + case 0x005C: /* '\' */ + return (0);/* Not allowed. */ + } + return (1); +} + +static int +set_str_utf16be(struct archive_write *a, unsigned char *p, const char *s, + size_t l, uint16_t uf, enum vdc vdc) +{ + size_t size, i; + int onepad; + + if (s == NULL) + s = ""; + if (l & 0x01) { + onepad = 1; + l &= ~1; + } else + onepad = 0; + if (vdc == VDC_UCS2) { + struct iso9660 *iso9660 = a->format_data; + if (archive_strncpy_l(&iso9660->utf16be, s, strlen(s), + iso9660->sconv_to_utf16be) != 0 && errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for UTF-16BE"); + return (ARCHIVE_FATAL); + } + size = iso9660->utf16be.length; + if (size > l) + size = l; + memcpy(p, iso9660->utf16be.s, size); + } else { + const uint16_t *u16 = (const uint16_t *)s; + + size = 0; + while (*u16++) + size += 2; + if (size > l) + size = l; + memcpy(p, s, size); + } + for (i = 0; i < size; i += 2, p += 2) { + if (!joliet_allowed_char(p[0], p[1])) + archive_be16enc(p, 0x005F);/* '_' */ + } + l -= size; + while (l > 0) { + archive_be16enc(p, uf); + p += 2; + l -= 2; + } + if (onepad) + *p = 0; + return (ARCHIVE_OK); +} + +static const char a_characters_map[0x80] = { +/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */ + 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 20-2F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 30-3F */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 60-6F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 70-7F */ +}; + +static const char a1_characters_map[0x80] = { +/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */ + 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 20-2F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 30-3F */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 60-6F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,/* 70-7F */ +}; + +static const char d_characters_map[0x80] = { +/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 20-2F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,/* 30-3F */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 60-6F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 70-7F */ +}; + +static const char d1_characters_map[0x80] = { +/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 00-0F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 10-1F */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,/* 20-2F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,/* 30-3F */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 40-4F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,/* 50-5F */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,/* 60-6F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,/* 70-7F */ +}; + +static int +set_str_a_characters_bp(struct archive_write *a, unsigned char *bp, + int from, int to, const char *s, enum vdc vdc) +{ + int r; + + switch (vdc) { + case VDC_STD: + set_str(bp+from, s, to - from + 1, 0x20, + a_characters_map); + r = ARCHIVE_OK; + break; + case VDC_LOWERCASE: + set_str(bp+from, s, to - from + 1, 0x20, + a1_characters_map); + r = ARCHIVE_OK; + break; + case VDC_UCS2: + case VDC_UCS2_DIRECT: + r = set_str_utf16be(a, bp+from, s, to - from + 1, + 0x0020, vdc); + break; + default: + r = ARCHIVE_FATAL; + } + return (r); +} + +static int +set_str_d_characters_bp(struct archive_write *a, unsigned char *bp, + int from, int to, const char *s, enum vdc vdc) +{ + int r; + + switch (vdc) { + case VDC_STD: + set_str(bp+from, s, to - from + 1, 0x20, + d_characters_map); + r = ARCHIVE_OK; + break; + case VDC_LOWERCASE: + set_str(bp+from, s, to - from + 1, 0x20, + d1_characters_map); + r = ARCHIVE_OK; + break; + case VDC_UCS2: + case VDC_UCS2_DIRECT: + r = set_str_utf16be(a, bp+from, s, to - from + 1, + 0x0020, vdc); + break; + default: + r = ARCHIVE_FATAL; + } + return (r); +} + +static void +set_VD_bp(unsigned char *bp, enum VD_type type, unsigned char ver) +{ + + /* Volume Descriptor Type */ + bp[1] = (unsigned char)type; + /* Standard Identifier */ + memcpy(bp + 2, "CD001", 5); + /* Volume Descriptor Version */ + bp[7] = ver; +} + +static inline void +set_unused_field_bp(unsigned char *bp, int from, int to) +{ + memset(bp + from, 0, to - from + 1); +} + +/* + * 8-bit unsigned numerical values. + * ISO9660 Standard 7.1.1 + */ +static inline void +set_num_711(unsigned char *p, unsigned char value) +{ + *p = value; +} + +/* + * 8-bit signed numerical values. + * ISO9660 Standard 7.1.2 + */ +static inline void +set_num_712(unsigned char *p, char value) +{ + *((char *)p) = value; +} + +/* + * Least significant byte first. + * ISO9660 Standard 7.2.1 + */ +static inline void +set_num_721(unsigned char *p, uint16_t value) +{ + archive_le16enc(p, value); +} + +/* + * Most significant byte first. + * ISO9660 Standard 7.2.2 + */ +static inline void +set_num_722(unsigned char *p, uint16_t value) +{ + archive_be16enc(p, value); +} + +/* + * Both-byte orders. + * ISO9660 Standard 7.2.3 + */ +static void +set_num_723(unsigned char *p, uint16_t value) +{ + archive_le16enc(p, value); + archive_be16enc(p+2, value); +} + +/* + * Least significant byte first. + * ISO9660 Standard 7.3.1 + */ +static inline void +set_num_731(unsigned char *p, uint32_t value) +{ + archive_le32enc(p, value); +} + +/* + * Most significant byte first. + * ISO9660 Standard 7.3.2 + */ +static inline void +set_num_732(unsigned char *p, uint32_t value) +{ + archive_be32enc(p, value); +} + +/* + * Both-byte orders. + * ISO9660 Standard 7.3.3 + */ +static inline void +set_num_733(unsigned char *p, uint32_t value) +{ + archive_le32enc(p, value); + archive_be32enc(p+4, value); +} + +static void +set_digit(unsigned char *p, size_t s, int value) +{ + + while (s--) { + p[s] = '0' + (value % 10); + value /= 10; + } +} + +#if defined(HAVE_STRUCT_TM_TM_GMTOFF) +#define get_gmoffset(tm) ((tm)->tm_gmtoff) +#elif defined(HAVE_STRUCT_TM___TM_GMTOFF) +#define get_gmoffset(tm) ((tm)->__tm_gmtoff) +#else +static long +get_gmoffset(struct tm *tm) +{ + long offset; + +#if defined(HAVE__GET_TIMEZONE) + _get_timezone(&offset); +#elif defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__) + offset = _timezone; +#else + offset = timezone; +#endif + offset *= -1; + if (tm->tm_isdst) + offset += 3600; + return (offset); +} +#endif + +static void +get_tmfromtime(struct tm *tm, time_t *t) +{ +#if HAVE_LOCALTIME_R + tzset(); + localtime_r(t, tm); +#elif HAVE__LOCALTIME64_S - _localtime64_s(tm, t); ++ __time64_t tmp_t = (__time64_t) *t; //time_t may be shorter than 64 bits ++ _localtime64_s(tm, &tmp_t); +#else + memcpy(tm, localtime(t), sizeof(*tm)); +#endif +} + +/* + * Date and Time Format. + * ISO9660 Standard 8.4.26.1 + */ +static void +set_date_time(unsigned char *p, time_t t) +{ + struct tm tm; + + get_tmfromtime(&tm, &t); + set_digit(p, 4, tm.tm_year + 1900); + set_digit(p+4, 2, tm.tm_mon + 1); + set_digit(p+6, 2, tm.tm_mday); + set_digit(p+8, 2, tm.tm_hour); + set_digit(p+10, 2, tm.tm_min); + set_digit(p+12, 2, tm.tm_sec); + set_digit(p+14, 2, 0); + set_num_712(p+16, (char)(get_gmoffset(&tm)/(60*15))); +} + +static void +set_date_time_null(unsigned char *p) +{ - memset(p, '0', 16); ++ memset(p, (int)'0', 16); + p[16] = 0; +} + +static void +set_time_915(unsigned char *p, time_t t) +{ + struct tm tm; + + get_tmfromtime(&tm, &t); + set_num_711(p+0, tm.tm_year); + set_num_711(p+1, tm.tm_mon+1); + set_num_711(p+2, tm.tm_mday); + set_num_711(p+3, tm.tm_hour); + set_num_711(p+4, tm.tm_min); + set_num_711(p+5, tm.tm_sec); + set_num_712(p+6, (char)(get_gmoffset(&tm)/(60*15))); +} + + +/* + * Write SUSP "CE" System Use Entry. + */ +static int +set_SUSP_CE(unsigned char *p, int location, int offset, int size) +{ + unsigned char *bp = p -1; + /* Extend the System Use Area + * "CE" Format: + * len ver + * +----+----+----+----+-----------+-----------+ + * | 'C'| 'E'| 1C | 01 | LOCATION1 | LOCATION2 | + * +----+----+----+----+-----------+-----------+ + * 0 1 2 3 4 12 20 + * +-----------+ + * | LOCATION3 | + * +-----------+ + * 20 28 + * LOCATION1 : Location of Continuation of System Use Area. + * LOCATION2 : Offset to Start of Continuation. + * LOCATION3 : Length of the Continuation. + */ + + bp[1] = 'C'; + bp[2] = 'E'; + bp[3] = RR_CE_SIZE; /* length */ + bp[4] = 1; /* version */ + set_num_733(bp+5, location); + set_num_733(bp+13, offset); + set_num_733(bp+21, size); + return (RR_CE_SIZE); +} + +/* + * The functions, which names are beginning with extra_, are used to + * control extra records. + * The maximum size of a Directory Record is 254. When a filename is + * very long, all of RRIP data of a file won't stored to the Directory + * Record and so remaining RRIP data store to an extra record instead. + */ +static unsigned char * +extra_open_record(unsigned char *bp, int dr_len, struct isoent *isoent, + struct ctl_extr_rec *ctl) +{ + ctl->bp = bp; + if (bp != NULL) + bp += dr_len; + ctl->use_extr = 0; + ctl->isoent = isoent; + ctl->ce_ptr = NULL; + ctl->cur_len = ctl->dr_len = dr_len; + ctl->limit = DR_LIMIT; + + return (bp); +} + +static void +extra_close_record(struct ctl_extr_rec *ctl, int ce_size) +{ + int padding = 0; + + if (ce_size > 0) + extra_tell_used_size(ctl, ce_size); + /* Padding. */ + if (ctl->cur_len & 0x01) { + ctl->cur_len++; + if (ctl->bp != NULL) + ctl->bp[ctl->cur_len] = 0; + padding = 1; + } + if (ctl->use_extr) { + if (ctl->ce_ptr != NULL) + set_SUSP_CE(ctl->ce_ptr, ctl->extr_loc, + ctl->extr_off, ctl->cur_len - padding); + } else + ctl->dr_len = ctl->cur_len; +} + +#define extra_space(ctl) ((ctl)->limit - (ctl)->cur_len) + +static unsigned char * +extra_next_record(struct ctl_extr_rec *ctl, int length) +{ + int cur_len = ctl->cur_len;/* save cur_len */ + + /* Close the current extra record or Directory Record. */ + extra_close_record(ctl, RR_CE_SIZE); + + /* Get a next extra record. */ + ctl->use_extr = 1; + if (ctl->bp != NULL) { + /* Storing data into an extra record. */ + unsigned char *p; + + /* Save the pointer where a CE extension will be + * stored to. */ + ctl->ce_ptr = &ctl->bp[cur_len+1]; + p = extra_get_record(ctl->isoent, + &ctl->limit, &ctl->extr_off, &ctl->extr_loc); + ctl->bp = p - 1;/* the base of bp offset is 1. */ + } else + /* Calculating the size of an extra record. */ + (void)extra_get_record(ctl->isoent, + &ctl->limit, NULL, NULL); + ctl->cur_len = 0; + /* Check if an extra record is almost full. + * If so, get a next one. */ + if (extra_space(ctl) < length) + (void)extra_next_record(ctl, length); + + return (ctl->bp); +} + +static inline struct extr_rec * +extra_last_record(struct isoent *isoent) +{ + if (isoent->extr_rec_list.first == NULL) + return (NULL); + return ((struct extr_rec *)(void *) + ((char *)(isoent->extr_rec_list.last) + - offsetof(struct extr_rec, next))); +} + +static unsigned char * +extra_get_record(struct isoent *isoent, int *space, int *off, int *loc) +{ + struct extr_rec *rec; + + isoent = isoent->parent; + if (off != NULL) { + /* Storing data into an extra record. */ + rec = isoent->extr_rec_list.current; + if (DR_SAFETY > LOGICAL_BLOCK_SIZE - rec->offset) + rec = rec->next; + } else { + /* Calculating the size of an extra record. */ + rec = extra_last_record(isoent); + if (rec == NULL || + DR_SAFETY > LOGICAL_BLOCK_SIZE - rec->offset) { + rec = malloc(sizeof(*rec)); + if (rec == NULL) + return (NULL); + rec->location = 0; + rec->offset = 0; + /* Insert `rec` into the tail of isoent->extr_rec_list */ + rec->next = NULL; + /* + * Note: testing isoent->extr_rec_list.last == NULL + * here is really unneeded since it has been already + * initialized at isoent_new function but Clang Static + * Analyzer claims that it is dereference of null + * pointer. + */ + if (isoent->extr_rec_list.last == NULL) + isoent->extr_rec_list.last = + &(isoent->extr_rec_list.first); + *isoent->extr_rec_list.last = rec; + isoent->extr_rec_list.last = &(rec->next); + } + } + *space = LOGICAL_BLOCK_SIZE - rec->offset - DR_SAFETY; + if (*space & 0x01) + *space -= 1;/* Keep padding space. */ + if (off != NULL) + *off = rec->offset; + if (loc != NULL) + *loc = rec->location; + isoent->extr_rec_list.current = rec; + + return (&rec->buf[rec->offset]); +} + +static void +extra_tell_used_size(struct ctl_extr_rec *ctl, int size) +{ + struct isoent *isoent; + struct extr_rec *rec; + + if (ctl->use_extr) { + isoent = ctl->isoent->parent; + rec = isoent->extr_rec_list.current; + if (rec != NULL) + rec->offset += size; + } + ctl->cur_len += size; +} + +static int +extra_setup_location(struct isoent *isoent, int location) +{ + struct extr_rec *rec; + int cnt; + + cnt = 0; + rec = isoent->extr_rec_list.first; + isoent->extr_rec_list.current = rec; + while (rec) { + cnt++; + rec->location = location++; + rec->offset = 0; + rec = rec->next; + } + return (cnt); +} + +/* + * Create the RRIP entries. + */ +static int +set_directory_record_rr(unsigned char *bp, int dr_len, + struct isoent *isoent, struct iso9660 *iso9660, enum dir_rec_type t) +{ + /* Flags(BP 5) of the Rockridge "RR" System Use Field */ + unsigned char rr_flag; +#define RR_USE_PX 0x01 +#define RR_USE_PN 0x02 +#define RR_USE_SL 0x04 +#define RR_USE_NM 0x08 +#define RR_USE_CL 0x10 +#define RR_USE_PL 0x20 +#define RR_USE_RE 0x40 +#define RR_USE_TF 0x80 + int length; + struct ctl_extr_rec ctl; + struct isoent *rr_parent, *pxent; + struct isofile *file; + + bp = extra_open_record(bp, dr_len, isoent, &ctl); + + if (t == DIR_REC_PARENT) { + rr_parent = isoent->rr_parent; + pxent = isoent->parent; + if (rr_parent != NULL) + isoent = rr_parent; + else + isoent = isoent->parent; + } else { + rr_parent = NULL; + pxent = isoent; + } + file = isoent->file; + + if (t != DIR_REC_NORMAL) { + rr_flag = RR_USE_PX | RR_USE_TF; + if (rr_parent != NULL) + rr_flag |= RR_USE_PL; + } else { + rr_flag = RR_USE_PX | RR_USE_NM | RR_USE_TF; + if (archive_entry_filetype(file->entry) == AE_IFLNK) + rr_flag |= RR_USE_SL; + if (isoent->rr_parent != NULL) + rr_flag |= RR_USE_RE; + if (isoent->rr_child != NULL) + rr_flag |= RR_USE_CL; + if (archive_entry_filetype(file->entry) == AE_IFCHR || + archive_entry_filetype(file->entry) == AE_IFBLK) + rr_flag |= RR_USE_PN; +#ifdef COMPAT_MKISOFS + /* + * mkisofs 2.01.01a63 records "RE" extension to + * the entry of "rr_moved" directory. + * I don't understand this behavior. + */ + if (isoent->virtual && + isoent->parent == iso9660->primary.rootent && + strcmp(isoent->file->basename.s, "rr_moved") == 0) + rr_flag |= RR_USE_RE; +#endif + } + + /* Write "SP" System Use Entry. */ + if (t == DIR_REC_SELF && isoent == isoent->parent) { + length = 7; + if (bp != NULL) { + bp[1] = 'S'; + bp[2] = 'P'; + bp[3] = length; + bp[4] = 1; /* version */ + bp[5] = 0xBE; /* Check Byte */ + bp[6] = 0xEF; /* Check Byte */ + bp[7] = 0; + bp += length; + } + extra_tell_used_size(&ctl, length); + } + + /* Write "RR" System Use Entry. */ + length = 5; + if (extra_space(&ctl) < length) + bp = extra_next_record(&ctl, length); + if (bp != NULL) { + bp[1] = 'R'; + bp[2] = 'R'; + bp[3] = length; + bp[4] = 1; /* version */ + bp[5] = rr_flag; + bp += length; + } + extra_tell_used_size(&ctl, length); + + /* Write "NM" System Use Entry. */ + if (rr_flag & RR_USE_NM) { + /* + * "NM" Format: + * e.g. a basename is 'foo' + * len ver flg + * +----+----+----+----+----+----+----+----+ + * | 'N'| 'M'| 08 | 01 | 00 | 'f'| 'o'| 'o'| + * +----+----+----+----+----+----+----+----+ + * <----------------- len -----------------> + */ + size_t nmlen = file->basename.length; + const char *nm = file->basename.s; + size_t nmmax; + + if (extra_space(&ctl) < 6) + bp = extra_next_record(&ctl, 6); + if (bp != NULL) { + bp[1] = 'N'; + bp[2] = 'M'; + bp[4] = 1; /* version */ + } + nmmax = extra_space(&ctl); + if (nmmax > 0xff) + nmmax = 0xff; + while (nmlen + 5 > nmmax) { + length = (int)nmmax; + if (bp != NULL) { + bp[3] = length; + bp[5] = 0x01;/* Alternate Name continues + * in next "NM" field */ + memcpy(bp+6, nm, length - 5); + bp += length; + } + nmlen -= length - 5; + nm += length - 5; + extra_tell_used_size(&ctl, length); + if (extra_space(&ctl) < 6) { + bp = extra_next_record(&ctl, 6); + nmmax = extra_space(&ctl); + if (nmmax > 0xff) + nmmax = 0xff; + } + if (bp != NULL) { + bp[1] = 'N'; + bp[2] = 'M'; + bp[4] = 1; /* version */ + } + } + length = 5 + (int)nmlen; + if (bp != NULL) { + bp[3] = length; + bp[5] = 0; + memcpy(bp+6, nm, nmlen); + bp += length; + } + extra_tell_used_size(&ctl, length); + } + + /* Write "PX" System Use Entry. */ + if (rr_flag & RR_USE_PX) { + /* + * "PX" Format: + * len ver + * +----+----+----+----+-----------+-----------+ + * | 'P'| 'X'| 2C | 01 | FILE MODE | LINKS | + * +----+----+----+----+-----------+-----------+ + * 0 1 2 3 4 12 20 + * +-----------+-----------+------------------+ + * | USER ID | GROUP ID |FILE SERIAL NUMBER| + * +-----------+-----------+------------------+ + * 20 28 36 44 + */ + length = 44; + if (extra_space(&ctl) < length) + bp = extra_next_record(&ctl, length); + if (bp != NULL) { + mode_t mode; + int64_t uid; + int64_t gid; + + mode = archive_entry_mode(file->entry); + uid = archive_entry_uid(file->entry); + gid = archive_entry_gid(file->entry); + if (iso9660->opt.rr == OPT_RR_USEFUL) { + /* - * This action is simular mkisofs -r option ++ * This action is similar to mkisofs -r option + * but our rockridge=useful option does not + * set a zero to uid and gid. + */ + /* set all read bit ON */ + mode |= 0444; +#if !defined(_WIN32) && !defined(__CYGWIN__) + if (mode & 0111) +#endif + /* set all exec bit ON */ + mode |= 0111; + /* clear all write bits. */ + mode &= ~0222; + /* clear setuid,setgid,sticky bits. */ + mode &= ~07000; + } + + bp[1] = 'P'; + bp[2] = 'X'; + bp[3] = length; + bp[4] = 1; /* version */ + /* file mode */ + set_num_733(bp+5, mode); + /* file links (stat.st_nlink) */ + set_num_733(bp+13, + archive_entry_nlink(file->entry)); + set_num_733(bp+21, (uint32_t)uid); + set_num_733(bp+29, (uint32_t)gid); + /* File Serial Number */ + if (pxent->dir) + set_num_733(bp+37, pxent->dir_location); + else if (file->hardlink_target != NULL) + set_num_733(bp+37, + file->hardlink_target->cur_content->location); + else + set_num_733(bp+37, + file->cur_content->location); + bp += length; + } + extra_tell_used_size(&ctl, length); + } + + /* Write "SL" System Use Entry. */ + if (rr_flag & RR_USE_SL) { + /* + * "SL" Format: + * e.g. a symbolic name is 'foo/bar' + * len ver flg + * +----+----+----+----+----+------------+ + * | 'S'| 'L'| 0F | 01 | 00 | components | + * +----+----+----+----+----+-----+------+ + * 0 1 2 3 4 5 ...|... 15 + * <----------------- len --------+------> + * components : | + * cflg clen | + * +----+----+----+----+----+ | + * | 00 | 03 | 'f'| 'o'| 'o'| <---+ + * +----+----+----+----+----+ | + * 5 6 7 8 9 10 | + * cflg clen | + * +----+----+----+----+----+ | + * | 00 | 03 | 'b'| 'a'| 'r'| <---+ + * +----+----+----+----+----+ + * 10 11 12 13 14 15 + * - * - cflg : flag of componet - * - clen : length of componet ++ * - cflg : flag of component ++ * - clen : length of component + */ + const char *sl; + char sl_last; + + if (extra_space(&ctl) < 7) + bp = extra_next_record(&ctl, 7); + sl = file->symlink.s; + sl_last = '\0'; + if (bp != NULL) { + bp[1] = 'S'; + bp[2] = 'L'; + bp[4] = 1; /* version */ + } + for (;;) { + unsigned char *nc, *cf, *cl, cldmy = 0; + int sllen, slmax; + + slmax = extra_space(&ctl); + if (slmax > 0xff) + slmax = 0xff; + if (bp != NULL) + nc = &bp[6]; + else + nc = NULL; + cf = cl = NULL; + sllen = 0; + while (*sl && sllen + 11 < slmax) { + if (sl_last == '\0' && sl[0] == '/') { + /* + * flg len + * +----+----+ + * | 08 | 00 | ROOT component. + * +----+----+ ("/") + * + * Root component has to appear + * at the first component only. + */ + if (nc != NULL) { + cf = nc++; + *cf = 0x08; /* ROOT */ + *nc++ = 0; + } + sllen += 2; + sl++; + sl_last = '/'; + cl = NULL; + continue; + } + if (((sl_last == '\0' || sl_last == '/') && + sl[0] == '.' && sl[1] == '.' && + (sl[2] == '/' || sl[2] == '\0')) || + (sl[0] == '/' && + sl[1] == '.' && sl[2] == '.' && + (sl[3] == '/' || sl[3] == '\0'))) { + /* + * flg len + * +----+----+ + * | 04 | 00 | PARENT component. + * +----+----+ ("..") + */ + if (nc != NULL) { + cf = nc++; + *cf = 0x04; /* PARENT */ + *nc++ = 0; + } + sllen += 2; + if (sl[0] == '/') + sl += 3;/* skip "/.." */ + else + sl += 2;/* skip ".." */ + sl_last = '.'; + cl = NULL; + continue; + } + if (((sl_last == '\0' || sl_last == '/') && + sl[0] == '.' && + (sl[1] == '/' || sl[1] == '\0')) || + (sl[0] == '/' && sl[1] == '.' && + (sl[2] == '/' || sl[2] == '\0'))) { + /* + * flg len + * +----+----+ - * | 02 | 00 | CURREENT component. ++ * | 02 | 00 | CURRENT component. + * +----+----+ (".") + */ + if (nc != NULL) { + cf = nc++; + *cf = 0x02; /* CURRENT */ + *nc++ = 0; + } + sllen += 2; + if (sl[0] == '/') + sl += 2;/* skip "/." */ + else + sl ++; /* skip "." */ + sl_last = '.'; + cl = NULL; + continue; + } + if (sl[0] == '/' || cl == NULL) { + if (nc != NULL) { + cf = nc++; + *cf = 0; + cl = nc++; + *cl = 0; + } else + cl = &cldmy; + sllen += 2; + if (sl[0] == '/') { + sl_last = *sl++; + continue; + } + } + sl_last = *sl++; + if (nc != NULL) { + *nc++ = sl_last; + (*cl) ++; + } + sllen++; + } + if (*sl) { + length = 5 + sllen; + if (bp != NULL) { + /* + * Mark flg as CONTINUE component. + */ + *cf |= 0x01; + /* + * len ver flg + * +----+----+----+----+----+- + * | 'S'| 'L'| XX | 01 | 01 | + * +----+----+----+----+----+- + * ^ + * continues in next "SL" + */ + bp[3] = length; + bp[5] = 0x01;/* This Symbolic Link + * continues in next + * "SL" field */ + bp += length; + } + extra_tell_used_size(&ctl, length); + if (extra_space(&ctl) < 11) + bp = extra_next_record(&ctl, 11); + if (bp != NULL) { + /* Next 'SL' */ + bp[1] = 'S'; + bp[2] = 'L'; + bp[4] = 1; /* version */ + } + } else { + length = 5 + sllen; + if (bp != NULL) { + bp[3] = length; + bp[5] = 0; + bp += length; + } + extra_tell_used_size(&ctl, length); + break; + } + } + } + + /* Write "TF" System Use Entry. */ + if (rr_flag & RR_USE_TF) { + /* + * "TF" Format: + * len ver + * +----+----+----+----+-----+-------------+ + * | 'T'| 'F'| XX | 01 |FLAGS| TIME STAMPS | + * +----+----+----+----+-----+-------------+ + * 0 1 2 3 4 5 XX + * TIME STAMPS : ISO 9660 Standard 9.1.5. + * If TF_LONG_FORM FLAGS is set, + * use ISO9660 Standard 8.4.26.1. + */ +#define TF_CREATION 0x01 /* Creation time recorded */ +#define TF_MODIFY 0x02 /* Modification time recorded */ +#define TF_ACCESS 0x04 /* Last Access time recorded */ +#define TF_ATTRIBUTES 0x08 /* Last Attribute Change time recorded */ +#define TF_BACKUP 0x10 /* Last Backup time recorded */ +#define TF_EXPIRATION 0x20 /* Expiration time recorded */ +#define TF_EFFECTIVE 0x40 /* Effective time recorded */ +#define TF_LONG_FORM 0x80 /* ISO 9660 17-byte time format used */ + unsigned char tf_flags; + + length = 5; + tf_flags = 0; +#ifndef COMPAT_MKISOFS + if (archive_entry_birthtime_is_set(file->entry) && + archive_entry_birthtime(file->entry) <= + archive_entry_mtime(file->entry)) { + length += 7; + tf_flags |= TF_CREATION; + } +#endif + if (archive_entry_mtime_is_set(file->entry)) { + length += 7; + tf_flags |= TF_MODIFY; + } + if (archive_entry_atime_is_set(file->entry)) { + length += 7; + tf_flags |= TF_ACCESS; + } + if (archive_entry_ctime_is_set(file->entry)) { + length += 7; + tf_flags |= TF_ATTRIBUTES; + } + if (extra_space(&ctl) < length) + bp = extra_next_record(&ctl, length); + if (bp != NULL) { + bp[1] = 'T'; + bp[2] = 'F'; + bp[3] = length; + bp[4] = 1; /* version */ + bp[5] = tf_flags; + bp += 5; + /* Creation time */ + if (tf_flags & TF_CREATION) { + set_time_915(bp+1, + archive_entry_birthtime(file->entry)); + bp += 7; + } + /* Modification time */ + if (tf_flags & TF_MODIFY) { + set_time_915(bp+1, + archive_entry_mtime(file->entry)); + bp += 7; + } + /* Last Access time */ + if (tf_flags & TF_ACCESS) { + set_time_915(bp+1, + archive_entry_atime(file->entry)); + bp += 7; + } + /* Last Attribute Change time */ + if (tf_flags & TF_ATTRIBUTES) { + set_time_915(bp+1, + archive_entry_ctime(file->entry)); + bp += 7; + } + } + extra_tell_used_size(&ctl, length); + } + + /* Write "RE" System Use Entry. */ + if (rr_flag & RR_USE_RE) { + /* + * "RE" Format: + * len ver + * +----+----+----+----+ + * | 'R'| 'E'| 04 | 01 | + * +----+----+----+----+ + * 0 1 2 3 4 + */ + length = 4; + if (extra_space(&ctl) < length) + bp = extra_next_record(&ctl, length); + if (bp != NULL) { + bp[1] = 'R'; + bp[2] = 'E'; + bp[3] = length; + bp[4] = 1; /* version */ + bp += length; + } + extra_tell_used_size(&ctl, length); + } + + /* Write "PL" System Use Entry. */ + if (rr_flag & RR_USE_PL) { + /* + * "PL" Format: + * len ver + * +----+----+----+----+------------+ + * | 'P'| 'L'| 0C | 01 | *LOCATION | + * +----+----+----+----+------------+ + * 0 1 2 3 4 12 + * *LOCATION: location of parent directory + */ + length = 12; + if (extra_space(&ctl) < length) + bp = extra_next_record(&ctl, length); + if (bp != NULL) { + bp[1] = 'P'; + bp[2] = 'L'; + bp[3] = length; + bp[4] = 1; /* version */ + set_num_733(bp + 5, + rr_parent->dir_location); + bp += length; + } + extra_tell_used_size(&ctl, length); + } + + /* Write "CL" System Use Entry. */ + if (rr_flag & RR_USE_CL) { + /* + * "CL" Format: + * len ver + * +----+----+----+----+------------+ + * | 'C'| 'L'| 0C | 01 | *LOCATION | + * +----+----+----+----+------------+ + * 0 1 2 3 4 12 + * *LOCATION: location of child directory + */ + length = 12; + if (extra_space(&ctl) < length) + bp = extra_next_record(&ctl, length); + if (bp != NULL) { + bp[1] = 'C'; + bp[2] = 'L'; + bp[3] = length; + bp[4] = 1; /* version */ + set_num_733(bp + 5, + isoent->rr_child->dir_location); + bp += length; + } + extra_tell_used_size(&ctl, length); + } + + /* Write "PN" System Use Entry. */ + if (rr_flag & RR_USE_PN) { + /* + * "PN" Format: + * len ver + * +----+----+----+----+------------+------------+ + * | 'P'| 'N'| 14 | 01 | dev_t high | dev_t low | + * +----+----+----+----+------------+------------+ + * 0 1 2 3 4 12 20 + */ + length = 20; + if (extra_space(&ctl) < length) + bp = extra_next_record(&ctl, length); + if (bp != NULL) { + uint64_t dev; + + bp[1] = 'P'; + bp[2] = 'N'; + bp[3] = length; + bp[4] = 1; /* version */ + dev = (uint64_t)archive_entry_rdev(file->entry); + set_num_733(bp + 5, (uint32_t)(dev >> 32)); + set_num_733(bp + 13, (uint32_t)(dev & 0xFFFFFFFF)); + bp += length; + } + extra_tell_used_size(&ctl, length); + } + + /* Write "ZF" System Use Entry. */ + if (file->zisofs.header_size) { + /* + * "ZF" Format: + * len ver + * +----+----+----+----+----+----+-------------+ + * | 'Z'| 'F'| 10 | 01 | 'p'| 'z'| Header Size | + * +----+----+----+----+----+----+-------------+ + * 0 1 2 3 4 5 6 7 + * +--------------------+-------------------+ + * | Log2 of block Size | Uncompressed Size | + * +--------------------+-------------------+ + * 7 8 16 + */ + length = 16; + if (extra_space(&ctl) < length) + bp = extra_next_record(&ctl, length); + if (bp != NULL) { + bp[1] = 'Z'; + bp[2] = 'F'; + bp[3] = length; + bp[4] = 1; /* version */ + bp[5] = 'p'; + bp[6] = 'z'; + bp[7] = file->zisofs.header_size; + bp[8] = file->zisofs.log2_bs; + set_num_733(bp + 9, file->zisofs.uncompressed_size); + bp += length; + } + extra_tell_used_size(&ctl, length); + } + + /* Write "CE" System Use Entry. */ + if (t == DIR_REC_SELF && isoent == isoent->parent) { + length = RR_CE_SIZE; + if (bp != NULL) + set_SUSP_CE(bp+1, iso9660->location_rrip_er, + 0, RRIP_ER_SIZE); + extra_tell_used_size(&ctl, length); + } + + extra_close_record(&ctl, 0); + + return (ctl.dr_len); +} + +/* + * Write data of a Directory Record or calculate writing bytes itself. + * If parameter `p' is NULL, calculates the size of writing data, which + * a Directory Record needs to write, then it saved and return + * the calculated size. + * Parameter `n' is a remaining size of buffer. when parameter `p' is + * not NULL, check whether that `n' is not less than the saved size. + * if that `n' is small, return zero. + * + * This format of the Directory Record is according to + * ISO9660 Standard 9.1 + */ +static int +set_directory_record(unsigned char *p, size_t n, struct isoent *isoent, + struct iso9660 *iso9660, enum dir_rec_type t, + enum vdd_type vdd_type) +{ + unsigned char *bp; + size_t dr_len; + size_t fi_len; + + if (p != NULL) { + /* + * Check whether a write buffer size is less than the + * saved size which is needed to write this Directory + * Record. + */ + switch (t) { + case DIR_REC_VD: + dr_len = isoent->dr_len.vd; break; + case DIR_REC_SELF: + dr_len = isoent->dr_len.self; break; + case DIR_REC_PARENT: + dr_len = isoent->dr_len.parent; break; + case DIR_REC_NORMAL: + default: + dr_len = isoent->dr_len.normal; break; + } + if (dr_len > n) + return (0);/* Needs more buffer size. */ + } + + if (t == DIR_REC_NORMAL && isoent->identifier != NULL) + fi_len = isoent->id_len; + else + fi_len = 1; + + if (p != NULL) { + struct isoent *xisoent; + struct isofile *file; + unsigned char flag; + + if (t == DIR_REC_PARENT) + xisoent = isoent->parent; + else + xisoent = isoent; + file = isoent->file; + if (file->hardlink_target != NULL) + file = file->hardlink_target; + /* Make a file flag. */ + if (xisoent->dir) + flag = FILE_FLAG_DIRECTORY; + else { + if (file->cur_content->next != NULL) + flag = FILE_FLAG_MULTI_EXTENT; + else + flag = 0; + } + + bp = p -1; + /* Extended Attribute Record Length */ + set_num_711(bp+2, 0); + /* Location of Extent */ + if (xisoent->dir) + set_num_733(bp+3, xisoent->dir_location); + else + set_num_733(bp+3, file->cur_content->location); + /* Data Length */ + if (xisoent->dir) + set_num_733(bp+11, + xisoent->dir_block * LOGICAL_BLOCK_SIZE); + else + set_num_733(bp+11, (uint32_t)file->cur_content->size); + /* Recording Date and Time */ + /* NOTE: + * If a file type is symbolic link, you are seeing this + * field value is different from a value mkisofs makes. + * libarchive uses lstat to get this one, but it + * seems mkisofs uses stat to get. + */ + set_time_915(bp+19, + archive_entry_mtime(xisoent->file->entry)); + /* File Flags */ + bp[26] = flag; + /* File Unit Size */ + set_num_711(bp+27, 0); + /* Interleave Gap Size */ + set_num_711(bp+28, 0); + /* Volume Sequence Number */ + set_num_723(bp+29, iso9660->volume_sequence_number); + /* Length of File Identifier */ + set_num_711(bp+33, (unsigned char)fi_len); + /* File Identifier */ + switch (t) { + case DIR_REC_VD: + case DIR_REC_SELF: + set_num_711(bp+34, 0); + break; + case DIR_REC_PARENT: + set_num_711(bp+34, 1); + break; + case DIR_REC_NORMAL: + if (isoent->identifier != NULL) + memcpy(bp+34, isoent->identifier, fi_len); + else + set_num_711(bp+34, 0); + break; + } + } else + bp = NULL; + dr_len = 33 + fi_len; + /* Padding Field */ + if (dr_len & 0x01) { + dr_len ++; + if (p != NULL) + bp[dr_len] = 0; + } + + /* Volume Descriptor does not record extension. */ + if (t == DIR_REC_VD) { + if (p != NULL) + /* Length of Directory Record */ + set_num_711(p, (unsigned char)dr_len); + else + isoent->dr_len.vd = (int)dr_len; + return ((int)dr_len); + } + + /* Rockridge */ + if (iso9660->opt.rr && vdd_type != VDD_JOLIET) + dr_len = set_directory_record_rr(bp, (int)dr_len, + isoent, iso9660, t); + + if (p != NULL) + /* Length of Directory Record */ + set_num_711(p, (unsigned char)dr_len); + else { + /* + * Save the size which is needed to write this + * Directory Record. + */ + switch (t) { + case DIR_REC_VD: + /* This case does not come, but compiler + * complains that DIR_REC_VD not handled + * in switch .... */ + break; + case DIR_REC_SELF: + isoent->dr_len.self = (int)dr_len; break; + case DIR_REC_PARENT: + isoent->dr_len.parent = (int)dr_len; break; + case DIR_REC_NORMAL: + isoent->dr_len.normal = (int)dr_len; break; + } + } + + return ((int)dr_len); +} + +/* + * Calculate the size of a directory record. + */ +static inline int +get_dir_rec_size(struct iso9660 *iso9660, struct isoent *isoent, + enum dir_rec_type t, enum vdd_type vdd_type) +{ + + return (set_directory_record(NULL, SIZE_MAX, + isoent, iso9660, t, vdd_type)); +} + +/* + * Manage to write ISO-image data with wbuff to reduce calling + * __archive_write_output() for performance. + */ + + +static inline unsigned char * +wb_buffptr(struct archive_write *a) +{ + struct iso9660 *iso9660 = (struct iso9660 *)a->format_data; + + return (&(iso9660->wbuff[sizeof(iso9660->wbuff) + - iso9660->wbuff_remaining])); +} + +static int +wb_write_out(struct archive_write *a) +{ + struct iso9660 *iso9660 = (struct iso9660 *)a->format_data; + size_t wsize, nw; + int r; + + wsize = sizeof(iso9660->wbuff) - iso9660->wbuff_remaining; + nw = wsize % LOGICAL_BLOCK_SIZE; + if (iso9660->wbuff_type == WB_TO_STREAM) + r = __archive_write_output(a, iso9660->wbuff, wsize - nw); + else + r = write_to_temp(a, iso9660->wbuff, wsize - nw); + /* Increase the offset. */ + iso9660->wbuff_offset += wsize - nw; + if (iso9660->wbuff_offset > iso9660->wbuff_written) + iso9660->wbuff_written = iso9660->wbuff_offset; + iso9660->wbuff_remaining = sizeof(iso9660->wbuff); + if (nw) { + iso9660->wbuff_remaining -= nw; + memmove(iso9660->wbuff, iso9660->wbuff + wsize - nw, nw); + } + return (r); +} + +static int +wb_consume(struct archive_write *a, size_t size) +{ + struct iso9660 *iso9660 = (struct iso9660 *)a->format_data; + + if (size > iso9660->wbuff_remaining || + iso9660->wbuff_remaining == 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Internal Programing error: iso9660:wb_consume()" + " size=%jd, wbuff_remaining=%jd", + (intmax_t)size, (intmax_t)iso9660->wbuff_remaining); + return (ARCHIVE_FATAL); + } + iso9660->wbuff_remaining -= size; + if (iso9660->wbuff_remaining < LOGICAL_BLOCK_SIZE) + return (wb_write_out(a)); + return (ARCHIVE_OK); +} + +#ifdef HAVE_ZLIB_H + +static int +wb_set_offset(struct archive_write *a, int64_t off) +{ + struct iso9660 *iso9660 = (struct iso9660 *)a->format_data; + int64_t used, ext_bytes; + + if (iso9660->wbuff_type != WB_TO_TEMP) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Internal Programing error: iso9660:wb_set_offset()"); + return (ARCHIVE_FATAL); + } + + used = sizeof(iso9660->wbuff) - iso9660->wbuff_remaining; + if (iso9660->wbuff_offset + used > iso9660->wbuff_tail) + iso9660->wbuff_tail = iso9660->wbuff_offset + used; + if (iso9660->wbuff_offset < iso9660->wbuff_written) { + if (used > 0 && + write_to_temp(a, iso9660->wbuff, (size_t)used) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + iso9660->wbuff_offset = iso9660->wbuff_written; + lseek(iso9660->temp_fd, iso9660->wbuff_offset, SEEK_SET); + iso9660->wbuff_remaining = sizeof(iso9660->wbuff); + used = 0; + } + if (off < iso9660->wbuff_offset) { + /* + * Write out waiting data. + */ + if (used > 0) { + if (wb_write_out(a) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + lseek(iso9660->temp_fd, off, SEEK_SET); + iso9660->wbuff_offset = off; + iso9660->wbuff_remaining = sizeof(iso9660->wbuff); + } else if (off <= iso9660->wbuff_tail) { + iso9660->wbuff_remaining = (size_t) + (sizeof(iso9660->wbuff) - (off - iso9660->wbuff_offset)); + } else { + ext_bytes = off - iso9660->wbuff_tail; + iso9660->wbuff_remaining = (size_t)(sizeof(iso9660->wbuff) + - (iso9660->wbuff_tail - iso9660->wbuff_offset)); + while (ext_bytes >= (int64_t)iso9660->wbuff_remaining) { + if (write_null(a, (size_t)iso9660->wbuff_remaining) + != ARCHIVE_OK) + return (ARCHIVE_FATAL); + ext_bytes -= iso9660->wbuff_remaining; + } + if (ext_bytes > 0) { + if (write_null(a, (size_t)ext_bytes) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + } + return (ARCHIVE_OK); +} + +#endif /* HAVE_ZLIB_H */ + +static int +write_null(struct archive_write *a, size_t size) +{ + size_t remaining; + unsigned char *p, *old; + int r; + + remaining = wb_remaining(a); + p = wb_buffptr(a); + if (size <= remaining) { + memset(p, 0, size); + return (wb_consume(a, size)); + } + memset(p, 0, remaining); + r = wb_consume(a, remaining); + if (r != ARCHIVE_OK) + return (r); + size -= remaining; + old = p; + p = wb_buffptr(a); + memset(p, 0, old - p); + remaining = wb_remaining(a); + while (size) { + size_t wsize = size; + + if (wsize > remaining) + wsize = remaining; + r = wb_consume(a, wsize); + if (r != ARCHIVE_OK) + return (r); + size -= wsize; + } + return (ARCHIVE_OK); +} + +/* + * Write Volume Descriptor Set Terminator + */ +static int +write_VD_terminator(struct archive_write *a) +{ + unsigned char *bp; + + bp = wb_buffptr(a) -1; + set_VD_bp(bp, VDT_TERMINATOR, 1); + set_unused_field_bp(bp, 8, LOGICAL_BLOCK_SIZE); + + return (wb_consume(a, LOGICAL_BLOCK_SIZE)); +} + +static int +set_file_identifier(unsigned char *bp, int from, int to, enum vdc vdc, + struct archive_write *a, struct vdd *vdd, struct archive_string *id, + const char *label, int leading_under, enum char_type char_type) +{ + char identifier[256]; + struct isoent *isoent; + const char *ids; + size_t len; + int r; + + if (id->length > 0 && leading_under && id->s[0] != '_') { + if (char_type == A_CHAR) + r = set_str_a_characters_bp(a, bp, from, to, id->s, vdc); + else + r = set_str_d_characters_bp(a, bp, from, to, id->s, vdc); + } else if (id->length > 0) { + ids = id->s; + if (leading_under) + ids++; + isoent = isoent_find_entry(vdd->rootent, ids); + if (isoent == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Not Found %s `%s'.", + label, ids); + return (ARCHIVE_FATAL); + } + len = isoent->ext_off + isoent->ext_len; + if (vdd->vdd_type == VDD_JOLIET) { + if (len > sizeof(identifier)-2) + len = sizeof(identifier)-2; + } else { + if (len > sizeof(identifier)-1) + len = sizeof(identifier)-1; + } + memcpy(identifier, isoent->identifier, len); + identifier[len] = '\0'; + if (vdd->vdd_type == VDD_JOLIET) { + identifier[len+1] = 0; + vdc = VDC_UCS2_DIRECT; + } + if (char_type == A_CHAR) + r = set_str_a_characters_bp(a, bp, from, to, + identifier, vdc); + else + r = set_str_d_characters_bp(a, bp, from, to, + identifier, vdc); + } else { + if (char_type == A_CHAR) + r = set_str_a_characters_bp(a, bp, from, to, NULL, vdc); + else + r = set_str_d_characters_bp(a, bp, from, to, NULL, vdc); + } + return (r); +} + +/* + * Write Primary/Supplementary Volume Descriptor + */ +static int +write_VD(struct archive_write *a, struct vdd *vdd) +{ + struct iso9660 *iso9660; + unsigned char *bp; + uint16_t volume_set_size = 1; + char identifier[256]; + enum VD_type vdt; + enum vdc vdc; + unsigned char vd_ver, fst_ver; + int r; + + iso9660 = a->format_data; + switch (vdd->vdd_type) { + case VDD_JOLIET: + vdt = VDT_SUPPLEMENTARY; + vd_ver = fst_ver = 1; + vdc = VDC_UCS2; + break; + case VDD_ENHANCED: + vdt = VDT_SUPPLEMENTARY; + vd_ver = fst_ver = 2; + vdc = VDC_LOWERCASE; + break; + case VDD_PRIMARY: + default: + vdt = VDT_PRIMARY; + vd_ver = fst_ver = 1; +#ifdef COMPAT_MKISOFS + vdc = VDC_LOWERCASE; +#else + vdc = VDC_STD; +#endif + break; + } + + bp = wb_buffptr(a) -1; + /* Volume Descriptor Type */ + set_VD_bp(bp, vdt, vd_ver); + /* Unused Field */ + set_unused_field_bp(bp, 8, 8); + /* System Identifier */ + get_system_identitier(identifier, sizeof(identifier)); + r = set_str_a_characters_bp(a, bp, 9, 40, identifier, vdc); + if (r != ARCHIVE_OK) + return (r); + /* Volume Identifier */ + r = set_str_d_characters_bp(a, bp, 41, 72, + iso9660->volume_identifier.s, vdc); + if (r != ARCHIVE_OK) + return (r); + /* Unused Field */ + set_unused_field_bp(bp, 73, 80); + /* Volume Space Size */ + set_num_733(bp+81, iso9660->volume_space_size); + if (vdd->vdd_type == VDD_JOLIET) { + /* Escape Sequences */ + bp[89] = 0x25;/* UCS-2 Level 3 */ + bp[90] = 0x2F; + bp[91] = 0x45; + memset(bp + 92, 0, 120 - 92 + 1); + } else { + /* Unused Field */ + set_unused_field_bp(bp, 89, 120); + } + /* Volume Set Size */ + set_num_723(bp+121, volume_set_size); + /* Volume Sequence Number */ + set_num_723(bp+125, iso9660->volume_sequence_number); + /* Logical Block Size */ + set_num_723(bp+129, LOGICAL_BLOCK_SIZE); + /* Path Table Size */ + set_num_733(bp+133, vdd->path_table_size); + /* Location of Occurrence of Type L Path Table */ + set_num_731(bp+141, vdd->location_type_L_path_table); + /* Location of Optional Occurrence of Type L Path Table */ + set_num_731(bp+145, 0); + /* Location of Occurrence of Type M Path Table */ + set_num_732(bp+149, vdd->location_type_M_path_table); + /* Location of Optional Occurrence of Type M Path Table */ + set_num_732(bp+153, 0); + /* Directory Record for Root Directory(BP 157 to 190) */ + set_directory_record(bp+157, 190-157+1, vdd->rootent, + iso9660, DIR_REC_VD, vdd->vdd_type); + /* Volume Set Identifier */ + r = set_str_d_characters_bp(a, bp, 191, 318, "", vdc); + if (r != ARCHIVE_OK) + return (r); + /* Publisher Identifier */ + r = set_file_identifier(bp, 319, 446, vdc, a, vdd, + &(iso9660->publisher_identifier), + "Publisher File", 1, A_CHAR); + if (r != ARCHIVE_OK) + return (r); + /* Data Preparer Identifier */ + r = set_file_identifier(bp, 447, 574, vdc, a, vdd, + &(iso9660->data_preparer_identifier), + "Data Preparer File", 1, A_CHAR); + if (r != ARCHIVE_OK) + return (r); + /* Application Identifier */ + r = set_file_identifier(bp, 575, 702, vdc, a, vdd, + &(iso9660->application_identifier), + "Application File", 1, A_CHAR); + if (r != ARCHIVE_OK) + return (r); + /* Copyright File Identifier */ + r = set_file_identifier(bp, 703, 739, vdc, a, vdd, + &(iso9660->copyright_file_identifier), + "Copyright File", 0, D_CHAR); + if (r != ARCHIVE_OK) + return (r); + /* Abstract File Identifier */ + r = set_file_identifier(bp, 740, 776, vdc, a, vdd, + &(iso9660->abstract_file_identifier), + "Abstract File", 0, D_CHAR); + if (r != ARCHIVE_OK) + return (r); - /* Bibliongraphic File Identifier */ ++ /* Bibliographic File Identifier */ + r = set_file_identifier(bp, 777, 813, vdc, a, vdd, + &(iso9660->bibliographic_file_identifier), + "Bibliongraphic File", 0, D_CHAR); + if (r != ARCHIVE_OK) + return (r); + /* Volume Creation Date and Time */ + set_date_time(bp+814, iso9660->birth_time); + /* Volume Modification Date and Time */ + set_date_time(bp+831, iso9660->birth_time); + /* Volume Expiration Date and Time(obsolete) */ + set_date_time_null(bp+848); + /* Volume Effective Date and Time */ + set_date_time(bp+865, iso9660->birth_time); + /* File Structure Version */ + bp[882] = fst_ver; + /* Reserved */ + bp[883] = 0; + /* Application Use */ + memset(bp + 884, 0x20, 1395 - 884 + 1); + /* Reserved */ + set_unused_field_bp(bp, 1396, LOGICAL_BLOCK_SIZE); + + return (wb_consume(a, LOGICAL_BLOCK_SIZE)); +} + +/* + * Write Boot Record Volume Descriptor + */ +static int +write_VD_boot_record(struct archive_write *a) +{ + struct iso9660 *iso9660; + unsigned char *bp; + + iso9660 = a->format_data; + bp = wb_buffptr(a) -1; + /* Volume Descriptor Type */ + set_VD_bp(bp, VDT_BOOT_RECORD, 1); + /* Boot System Identifier */ + memcpy(bp+8, "EL TORITO SPECIFICATION", 23); + set_unused_field_bp(bp, 8+23, 39); + /* Unused */ + set_unused_field_bp(bp, 40, 71); + /* Absolute pointer to first sector of Boot Catalog */ + set_num_731(bp+72, + iso9660->el_torito.catalog->file->content.location); + /* Unused */ + set_unused_field_bp(bp, 76, LOGICAL_BLOCK_SIZE); + + return (wb_consume(a, LOGICAL_BLOCK_SIZE)); +} + +enum keytype { + KEY_FLG, + KEY_STR, + KEY_INT, + KEY_HEX +}; +static void +set_option_info(struct archive_string *info, int *opt, const char *key, + enum keytype type, ...) +{ + va_list ap; + char prefix; + const char *s; + int d; + + prefix = (*opt==0)? ' ':','; + va_start(ap, type); + switch (type) { + case KEY_FLG: + d = va_arg(ap, int); + archive_string_sprintf(info, "%c%s%s", + prefix, (d == 0)?"!":"", key); + break; + case KEY_STR: + s = va_arg(ap, const char *); + archive_string_sprintf(info, "%c%s=%s", + prefix, key, s); + break; + case KEY_INT: + d = va_arg(ap, int); + archive_string_sprintf(info, "%c%s=%d", + prefix, key, d); + break; + case KEY_HEX: + d = va_arg(ap, int); + archive_string_sprintf(info, "%c%s=%x", + prefix, key, d); + break; + } + va_end(ap); + + *opt = 1; +} + +/* + * Make Non-ISO File System Information + */ +static int +write_information_block(struct archive_write *a) +{ + struct iso9660 *iso9660; + char buf[128]; + const char *v; + int opt, r; + struct archive_string info; + size_t info_size = LOGICAL_BLOCK_SIZE * + NON_ISO_FILE_SYSTEM_INFORMATION_BLOCK; + + iso9660 = (struct iso9660 *)a->format_data; + if (info_size > wb_remaining(a)) { + r = wb_write_out(a); + if (r != ARCHIVE_OK) + return (r); + } + archive_string_init(&info); + if (archive_string_ensure(&info, info_size) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + memset(info.s, 0, info_size); + opt = 0; +#if defined(HAVE__CTIME64_S) - _ctime64_s(buf, sizeof(buf), &(iso9660->birth_time)); ++ __time64_t iso9660_birth_time_tmp = (__time64_t) iso9660->birth_time; //time_t may be shorter than 64 bits ++ _ctime64_s(buf, sizeof(buf), &(iso9660_birth_time_tmp)); +#elif defined(HAVE_CTIME_R) + ctime_r(&(iso9660->birth_time), buf); +#else + strncpy(buf, ctime(&(iso9660->birth_time)), sizeof(buf)-1); + buf[sizeof(buf)-1] = '\0'; +#endif + archive_string_sprintf(&info, + "INFO %s%s", buf, archive_version_string()); + if (iso9660->opt.abstract_file != OPT_ABSTRACT_FILE_DEFAULT) + set_option_info(&info, &opt, "abstract-file", + KEY_STR, iso9660->abstract_file_identifier.s); + if (iso9660->opt.application_id != OPT_APPLICATION_ID_DEFAULT) + set_option_info(&info, &opt, "application-id", + KEY_STR, iso9660->application_identifier.s); + if (iso9660->opt.allow_vernum != OPT_ALLOW_VERNUM_DEFAULT) + set_option_info(&info, &opt, "allow-vernum", + KEY_FLG, iso9660->opt.allow_vernum); + if (iso9660->opt.biblio_file != OPT_BIBLIO_FILE_DEFAULT) + set_option_info(&info, &opt, "biblio-file", + KEY_STR, iso9660->bibliographic_file_identifier.s); + if (iso9660->opt.boot != OPT_BOOT_DEFAULT) + set_option_info(&info, &opt, "boot", + KEY_STR, iso9660->el_torito.boot_filename.s); + if (iso9660->opt.boot_catalog != OPT_BOOT_CATALOG_DEFAULT) + set_option_info(&info, &opt, "boot-catalog", + KEY_STR, iso9660->el_torito.catalog_filename.s); + if (iso9660->opt.boot_info_table != OPT_BOOT_INFO_TABLE_DEFAULT) + set_option_info(&info, &opt, "boot-info-table", + KEY_FLG, iso9660->opt.boot_info_table); + if (iso9660->opt.boot_load_seg != OPT_BOOT_LOAD_SEG_DEFAULT) + set_option_info(&info, &opt, "boot-load-seg", + KEY_HEX, iso9660->el_torito.boot_load_seg); + if (iso9660->opt.boot_load_size != OPT_BOOT_LOAD_SIZE_DEFAULT) + set_option_info(&info, &opt, "boot-load-size", + KEY_INT, iso9660->el_torito.boot_load_size); + if (iso9660->opt.boot_type != OPT_BOOT_TYPE_DEFAULT) { + v = "no-emulation"; + if (iso9660->opt.boot_type == OPT_BOOT_TYPE_FD) + v = "fd"; + if (iso9660->opt.boot_type == OPT_BOOT_TYPE_HARD_DISK) + v = "hard-disk"; + set_option_info(&info, &opt, "boot-type", + KEY_STR, v); + } +#ifdef HAVE_ZLIB_H + if (iso9660->opt.compression_level != OPT_COMPRESSION_LEVEL_DEFAULT) + set_option_info(&info, &opt, "compression-level", + KEY_INT, iso9660->zisofs.compression_level); +#endif + if (iso9660->opt.copyright_file != OPT_COPYRIGHT_FILE_DEFAULT) + set_option_info(&info, &opt, "copyright-file", + KEY_STR, iso9660->copyright_file_identifier.s); + if (iso9660->opt.iso_level != OPT_ISO_LEVEL_DEFAULT) + set_option_info(&info, &opt, "iso-level", + KEY_INT, iso9660->opt.iso_level); + if (iso9660->opt.joliet != OPT_JOLIET_DEFAULT) { + if (iso9660->opt.joliet == OPT_JOLIET_LONGNAME) + set_option_info(&info, &opt, "joliet", + KEY_STR, "long"); + else + set_option_info(&info, &opt, "joliet", + KEY_FLG, iso9660->opt.joliet); + } + if (iso9660->opt.limit_depth != OPT_LIMIT_DEPTH_DEFAULT) + set_option_info(&info, &opt, "limit-depth", + KEY_FLG, iso9660->opt.limit_depth); + if (iso9660->opt.limit_dirs != OPT_LIMIT_DIRS_DEFAULT) + set_option_info(&info, &opt, "limit-dirs", + KEY_FLG, iso9660->opt.limit_dirs); + if (iso9660->opt.pad != OPT_PAD_DEFAULT) + set_option_info(&info, &opt, "pad", + KEY_FLG, iso9660->opt.pad); + if (iso9660->opt.publisher != OPT_PUBLISHER_DEFAULT) + set_option_info(&info, &opt, "publisher", + KEY_STR, iso9660->publisher_identifier.s); + if (iso9660->opt.rr != OPT_RR_DEFAULT) { + if (iso9660->opt.rr == OPT_RR_DISABLED) + set_option_info(&info, &opt, "rockridge", + KEY_FLG, iso9660->opt.rr); + else if (iso9660->opt.rr == OPT_RR_STRICT) + set_option_info(&info, &opt, "rockridge", + KEY_STR, "strict"); + else if (iso9660->opt.rr == OPT_RR_USEFUL) + set_option_info(&info, &opt, "rockridge", + KEY_STR, "useful"); + } + if (iso9660->opt.volume_id != OPT_VOLUME_ID_DEFAULT) + set_option_info(&info, &opt, "volume-id", + KEY_STR, iso9660->volume_identifier.s); + if (iso9660->opt.zisofs != OPT_ZISOFS_DEFAULT) + set_option_info(&info, &opt, "zisofs", + KEY_FLG, iso9660->opt.zisofs); + + memcpy(wb_buffptr(a), info.s, info_size); + archive_string_free(&info); + return (wb_consume(a, info_size)); +} + +static int +write_rr_ER(struct archive_write *a) +{ + unsigned char *p; + + p = wb_buffptr(a); + + memset(p, 0, LOGICAL_BLOCK_SIZE); + p[0] = 'E'; + p[1] = 'R'; + p[3] = 0x01; + p[2] = RRIP_ER_SIZE; + p[4] = RRIP_ER_ID_SIZE; + p[5] = RRIP_ER_DSC_SIZE; + p[6] = RRIP_ER_SRC_SIZE; + p[7] = 0x01; + memcpy(&p[8], rrip_identifier, p[4]); + memcpy(&p[8+p[4]], rrip_descriptor, p[5]); + memcpy(&p[8+p[4]+p[5]], rrip_source, p[6]); + + return (wb_consume(a, LOGICAL_BLOCK_SIZE)); +} + +static void +calculate_path_table_size(struct vdd *vdd) +{ + int depth, size; + struct path_table *pt; + + pt = vdd->pathtbl; + size = 0; + for (depth = 0; depth < vdd->max_depth; depth++) { + struct isoent **ptbl; + int i, cnt; + + if ((cnt = pt[depth].cnt) == 0) + break; + + ptbl = pt[depth].sorted; + for (i = 0; i < cnt; i++) { + int len; + + if (ptbl[i]->identifier == NULL) + len = 1; /* root directory */ + else + len = ptbl[i]->id_len; + if (len & 0x01) + len++; /* Padding Field */ + size += 8 + len; + } + } + vdd->path_table_size = size; + vdd->path_table_block = + ((size + PATH_TABLE_BLOCK_SIZE -1) / + PATH_TABLE_BLOCK_SIZE) * + (PATH_TABLE_BLOCK_SIZE / LOGICAL_BLOCK_SIZE); +} + +static int +_write_path_table(struct archive_write *a, int type_m, int depth, + struct vdd *vdd) +{ + unsigned char *bp, *wb; + struct isoent **ptbl; + size_t wbremaining; + int i, r, wsize; + + if (vdd->pathtbl[depth].cnt == 0) + return (0); + + wsize = 0; + wb = wb_buffptr(a); + wbremaining = wb_remaining(a); + bp = wb - 1; + ptbl = vdd->pathtbl[depth].sorted; + for (i = 0; i < vdd->pathtbl[depth].cnt; i++) { + struct isoent *np; + size_t len; + + np = ptbl[i]; + if (np->identifier == NULL) + len = 1; /* root directory */ + else + len = np->id_len; + if (wbremaining - ((bp+1) - wb) < (len + 1 + 8)) { + r = wb_consume(a, (bp+1) - wb); + if (r < 0) + return (r); + wb = wb_buffptr(a); + wbremaining = wb_remaining(a); + bp = wb -1; + } + /* Length of Directory Identifier */ + set_num_711(bp+1, (unsigned char)len); + /* Extended Attribute Record Length */ + set_num_711(bp+2, 0); + /* Location of Extent */ + if (type_m) + set_num_732(bp+3, np->dir_location); + else + set_num_731(bp+3, np->dir_location); + /* Parent Directory Number */ + if (type_m) + set_num_722(bp+7, np->parent->dir_number); + else + set_num_721(bp+7, np->parent->dir_number); + /* Directory Identifier */ + if (np->identifier == NULL) + bp[9] = 0; + else + memcpy(&bp[9], np->identifier, len); + if (len & 0x01) { + /* Padding Field */ + bp[9+len] = 0; + len++; + } + wsize += 8 + (int)len; + bp += 8 + len; + } + if ((bp + 1) > wb) { + r = wb_consume(a, (bp+1)-wb); + if (r < 0) + return (r); + } + return (wsize); +} + +static int +write_path_table(struct archive_write *a, int type_m, struct vdd *vdd) +{ + int depth, r; + size_t path_table_size; + + r = ARCHIVE_OK; + path_table_size = 0; + for (depth = 0; depth < vdd->max_depth; depth++) { + r = _write_path_table(a, type_m, depth, vdd); + if (r < 0) + return (r); + path_table_size += r; + } + + /* Write padding data. */ + path_table_size = path_table_size % PATH_TABLE_BLOCK_SIZE; + if (path_table_size > 0) + r = write_null(a, PATH_TABLE_BLOCK_SIZE - path_table_size); + return (r); +} + +static int +calculate_directory_descriptors(struct iso9660 *iso9660, struct vdd *vdd, + struct isoent *isoent, int depth) +{ + struct isoent **enttbl; + int bs, block, i; + + block = 1; + bs = get_dir_rec_size(iso9660, isoent, DIR_REC_SELF, vdd->vdd_type); + bs += get_dir_rec_size(iso9660, isoent, DIR_REC_PARENT, vdd->vdd_type); + + if (isoent->children.cnt <= 0 || (vdd->vdd_type != VDD_JOLIET && + !iso9660->opt.rr && depth + 1 >= vdd->max_depth)) + return (block); + + enttbl = isoent->children_sorted; + for (i = 0; i < isoent->children.cnt; i++) { + struct isoent *np = enttbl[i]; + struct isofile *file; + + file = np->file; + if (file->hardlink_target != NULL) + file = file->hardlink_target; + file->cur_content = &(file->content); + do { + int dr_l; + + dr_l = get_dir_rec_size(iso9660, np, DIR_REC_NORMAL, + vdd->vdd_type); + if ((bs + dr_l) > LOGICAL_BLOCK_SIZE) { + block ++; + bs = dr_l; + } else + bs += dr_l; + file->cur_content = file->cur_content->next; + } while (file->cur_content != NULL); + } + return (block); +} + +static int +_write_directory_descriptors(struct archive_write *a, struct vdd *vdd, + struct isoent *isoent, int depth) +{ + struct iso9660 *iso9660 = a->format_data; + struct isoent **enttbl; + unsigned char *p, *wb; + int i, r; + int dr_l; + + p = wb = wb_buffptr(a); +#define WD_REMAINING (LOGICAL_BLOCK_SIZE - (p - wb)) + p += set_directory_record(p, WD_REMAINING, isoent, + iso9660, DIR_REC_SELF, vdd->vdd_type); + p += set_directory_record(p, WD_REMAINING, isoent, + iso9660, DIR_REC_PARENT, vdd->vdd_type); + + if (isoent->children.cnt <= 0 || (vdd->vdd_type != VDD_JOLIET && + !iso9660->opt.rr && depth + 1 >= vdd->max_depth)) { + memset(p, 0, WD_REMAINING); + return (wb_consume(a, LOGICAL_BLOCK_SIZE)); + } + + enttbl = isoent->children_sorted; + for (i = 0; i < isoent->children.cnt; i++) { + struct isoent *np = enttbl[i]; + struct isofile *file = np->file; + + if (file->hardlink_target != NULL) + file = file->hardlink_target; + file->cur_content = &(file->content); + do { + dr_l = set_directory_record(p, WD_REMAINING, + np, iso9660, DIR_REC_NORMAL, + vdd->vdd_type); + if (dr_l == 0) { + memset(p, 0, WD_REMAINING); + r = wb_consume(a, LOGICAL_BLOCK_SIZE); + if (r < 0) + return (r); + p = wb = wb_buffptr(a); + dr_l = set_directory_record(p, + WD_REMAINING, np, iso9660, + DIR_REC_NORMAL, vdd->vdd_type); + } + p += dr_l; + file->cur_content = file->cur_content->next; + } while (file->cur_content != NULL); + } + memset(p, 0, WD_REMAINING); + return (wb_consume(a, LOGICAL_BLOCK_SIZE)); +} + +static int +write_directory_descriptors(struct archive_write *a, struct vdd *vdd) +{ + struct isoent *np; + int depth, r; + + depth = 0; + np = vdd->rootent; + do { + struct extr_rec *extr; + + r = _write_directory_descriptors(a, vdd, np, depth); + if (r < 0) + return (r); + if (vdd->vdd_type != VDD_JOLIET) { + /* + * This extract record is used by SUSP,RRIP. + * Not for joliet. + */ + for (extr = np->extr_rec_list.first; + extr != NULL; + extr = extr->next) { + unsigned char *wb; + + wb = wb_buffptr(a); + memcpy(wb, extr->buf, extr->offset); + memset(wb + extr->offset, 0, + LOGICAL_BLOCK_SIZE - extr->offset); + r = wb_consume(a, LOGICAL_BLOCK_SIZE); + if (r < 0) + return (r); + } + } + + if (np->subdirs.first != NULL && depth + 1 < vdd->max_depth) { + /* Enter to sub directories. */ + np = np->subdirs.first; + depth++; + continue; + } + while (np != np->parent) { + if (np->drnext == NULL) { + /* Return to the parent directory. */ + np = np->parent; + depth--; + } else { + np = np->drnext; + break; + } + } + } while (np != np->parent); + + return (ARCHIVE_OK); +} + +/* + * Read file contents from the temporary file, and write it. + */ +static int +write_file_contents(struct archive_write *a, int64_t offset, int64_t size) +{ + struct iso9660 *iso9660 = a->format_data; + int r; + + lseek(iso9660->temp_fd, offset, SEEK_SET); + + while (size) { + size_t rsize; + ssize_t rs; + unsigned char *wb; + + wb = wb_buffptr(a); + rsize = wb_remaining(a); + if (rsize > (size_t)size) + rsize = (size_t)size; + rs = read(iso9660->temp_fd, wb, rsize); + if (rs <= 0) { + archive_set_error(&a->archive, errno, + "Can't read temporary file(%jd)", (intmax_t)rs); + return (ARCHIVE_FATAL); + } + size -= rs; + r = wb_consume(a, rs); + if (r < 0) + return (r); + } + return (ARCHIVE_OK); +} + +static int +write_file_descriptors(struct archive_write *a) +{ + struct iso9660 *iso9660 = a->format_data; + struct isofile *file; + int64_t blocks, offset; + int r; + + blocks = 0; + offset = 0; + + /* Make the boot catalog contents, and write it. */ + if (iso9660->el_torito.catalog != NULL) { + r = make_boot_catalog(a); + if (r < 0) + return (r); + } + + /* Write the boot file contents. */ + if (iso9660->el_torito.boot != NULL) { + file = iso9660->el_torito.boot->file; + blocks = file->content.blocks; + offset = file->content.offset_of_temp; + if (offset != 0) { + r = write_file_contents(a, offset, + blocks << LOGICAL_BLOCK_BITS); + if (r < 0) + return (r); + blocks = 0; + offset = 0; + } + } + + /* Write out all file contents. */ + for (file = iso9660->data_file_list.first; + file != NULL; file = file->datanext) { + + if (!file->write_content) + continue; + + if ((offset + (blocks << LOGICAL_BLOCK_BITS)) < + file->content.offset_of_temp) { + if (blocks > 0) { + r = write_file_contents(a, offset, + blocks << LOGICAL_BLOCK_BITS); + if (r < 0) + return (r); + } + blocks = 0; + offset = file->content.offset_of_temp; + } + + file->cur_content = &(file->content); + do { + blocks += file->cur_content->blocks; - /* Next fragument */ ++ /* Next fragment */ + file->cur_content = file->cur_content->next; + } while (file->cur_content != NULL); + } + + /* Flush out remaining blocks. */ + if (blocks > 0) { + r = write_file_contents(a, offset, + blocks << LOGICAL_BLOCK_BITS); + if (r < 0) + return (r); + } + + return (ARCHIVE_OK); +} + +static void +isofile_init_entry_list(struct iso9660 *iso9660) +{ + iso9660->all_file_list.first = NULL; + iso9660->all_file_list.last = &(iso9660->all_file_list.first); +} + +static void +isofile_add_entry(struct iso9660 *iso9660, struct isofile *file) +{ + file->allnext = NULL; + *iso9660->all_file_list.last = file; + iso9660->all_file_list.last = &(file->allnext); +} + +static void +isofile_free_all_entries(struct iso9660 *iso9660) +{ + struct isofile *file, *file_next; + + file = iso9660->all_file_list.first; + while (file != NULL) { + file_next = file->allnext; + isofile_free(file); + file = file_next; + } +} + +static void +isofile_init_entry_data_file_list(struct iso9660 *iso9660) +{ + iso9660->data_file_list.first = NULL; + iso9660->data_file_list.last = &(iso9660->data_file_list.first); +} + +static void +isofile_add_data_file(struct iso9660 *iso9660, struct isofile *file) +{ + file->datanext = NULL; + *iso9660->data_file_list.last = file; + iso9660->data_file_list.last = &(file->datanext); +} + + +static struct isofile * +isofile_new(struct archive_write *a, struct archive_entry *entry) +{ + struct isofile *file; + + file = calloc(1, sizeof(*file)); + if (file == NULL) + return (NULL); + + if (entry != NULL) + file->entry = archive_entry_clone(entry); + else + file->entry = archive_entry_new2(&a->archive); + if (file->entry == NULL) { + free(file); + return (NULL); + } + archive_string_init(&(file->parentdir)); + archive_string_init(&(file->basename)); + archive_string_init(&(file->basename_utf16)); + archive_string_init(&(file->symlink)); + file->cur_content = &(file->content); + + return (file); +} + +static void +isofile_free(struct isofile *file) +{ + struct content *con, *tmp; + + con = file->content.next; + while (con != NULL) { + tmp = con; + con = con->next; + free(tmp); + } + archive_entry_free(file->entry); + archive_string_free(&(file->parentdir)); + archive_string_free(&(file->basename)); + archive_string_free(&(file->basename_utf16)); + archive_string_free(&(file->symlink)); + free(file); +} + +#if defined(_WIN32) || defined(__CYGWIN__) +static int +cleanup_backslash_1(char *p) +{ + int mb, dos; + + mb = dos = 0; + while (*p) { + if (*(unsigned char *)p > 127) + mb = 1; + if (*p == '\\') { + /* If we have not met any multi-byte characters, + * we can replace '\' with '/'. */ + if (!mb) + *p = '/'; + dos = 1; + } + p++; + } + if (!mb || !dos) + return (0); + return (-1); +} + +static void +cleanup_backslash_2(wchar_t *p) +{ + + /* Convert a path-separator from '\' to '/' */ + while (*p != L'\0') { + if (*p == L'\\') + *p = L'/'; + p++; + } +} +#endif + +/* + * Generate a parent directory name and a base name from a pathname. + */ +static int +isofile_gen_utility_names(struct archive_write *a, struct isofile *file) +{ + struct iso9660 *iso9660; + const char *pathname; + char *p, *dirname, *slash; + size_t len; + int ret = ARCHIVE_OK; + + iso9660 = a->format_data; + + archive_string_empty(&(file->parentdir)); + archive_string_empty(&(file->basename)); + archive_string_empty(&(file->basename_utf16)); + archive_string_empty(&(file->symlink)); + + pathname = archive_entry_pathname(file->entry); + if (pathname == NULL || pathname[0] == '\0') {/* virtual root */ + file->dircnt = 0; + return (ret); + } + + /* + * Make a UTF-16BE basename if Joliet extension enabled. + */ + if (iso9660->opt.joliet) { + const char *u16, *ulast; + size_t u16len, ulen_last; + + if (iso9660->sconv_to_utf16be == NULL) { + iso9660->sconv_to_utf16be = + archive_string_conversion_to_charset( + &(a->archive), "UTF-16BE", 1); + if (iso9660->sconv_to_utf16be == NULL) + /* Couldn't allocate memory */ + return (ARCHIVE_FATAL); + iso9660->sconv_from_utf16be = + archive_string_conversion_from_charset( + &(a->archive), "UTF-16BE", 1); + if (iso9660->sconv_from_utf16be == NULL) + /* Couldn't allocate memory */ + return (ARCHIVE_FATAL); + } + + /* - * Converte a filename to UTF-16BE. ++ * Convert a filename to UTF-16BE. + */ + if (0 > archive_entry_pathname_l(file->entry, &u16, &u16len, + iso9660->sconv_to_utf16be)) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for UTF-16BE"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "A filename cannot be converted to UTF-16BE;" + "You should disable making Joliet extension"); + ret = ARCHIVE_WARN; + } + + /* + * Make sure a path separator is not in the last; + * Remove trailing '/'. + */ + while (u16len >= 2) { +#if defined(_WIN32) || defined(__CYGWIN__) + if (u16[u16len-2] == 0 && + (u16[u16len-1] == '/' || u16[u16len-1] == '\\')) +#else + if (u16[u16len-2] == 0 && u16[u16len-1] == '/') +#endif + { + u16len -= 2; + } else + break; + } + + /* + * Find a basename in UTF-16BE. + */ + ulast = u16; + u16len >>= 1; + ulen_last = u16len; + while (u16len > 0) { +#if defined(_WIN32) || defined(__CYGWIN__) + if (u16[0] == 0 && (u16[1] == '/' || u16[1] == '\\')) +#else + if (u16[0] == 0 && u16[1] == '/') +#endif + { + ulast = u16 + 2; + ulen_last = u16len -1; + } + u16 += 2; + u16len --; + } + ulen_last <<= 1; + if (archive_string_ensure(&(file->basename_utf16), + ulen_last) == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for UTF-16BE"); + return (ARCHIVE_FATAL); + } + + /* + * Set UTF-16BE basename. + */ + memcpy(file->basename_utf16.s, ulast, ulen_last); + file->basename_utf16.length = ulen_last; + } + + archive_strcpy(&(file->parentdir), pathname); +#if defined(_WIN32) || defined(__CYGWIN__) + /* + * Convert a path-separator from '\' to '/' + */ + if (cleanup_backslash_1(file->parentdir.s) != 0) { + const wchar_t *wp = archive_entry_pathname_w(file->entry); + struct archive_wstring ws; + + if (wp != NULL) { + int r; + archive_string_init(&ws); + archive_wstrcpy(&ws, wp); + cleanup_backslash_2(ws.s); + archive_string_empty(&(file->parentdir)); + r = archive_string_append_from_wcs(&(file->parentdir), + ws.s, ws.length); + archive_wstring_free(&ws); + if (r < 0 && errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + } + } +#endif + + len = file->parentdir.length; + p = dirname = file->parentdir.s; + + /* + * Remove leading '/', '../' and './' elements + */ + while (*p) { + if (p[0] == '/') { + p++; + len--; + } else if (p[0] != '.') + break; + else if (p[1] == '.' && p[2] == '/') { + p += 3; + len -= 3; + } else if (p[1] == '/' || (p[1] == '.' && p[2] == '\0')) { + p += 2; + len -= 2; + } else if (p[1] == '\0') { + p++; + len--; + } else + break; + } + if (p != dirname) { + memmove(dirname, p, len+1); + p = dirname; + } + /* + * Remove "/","/." and "/.." elements from tail. + */ + while (len > 0) { + size_t ll = len; + + if (len > 0 && p[len-1] == '/') { + p[len-1] = '\0'; + len--; + } + if (len > 1 && p[len-2] == '/' && p[len-1] == '.') { + p[len-2] = '\0'; + len -= 2; + } + if (len > 2 && p[len-3] == '/' && p[len-2] == '.' && + p[len-1] == '.') { + p[len-3] = '\0'; + len -= 3; + } + if (ll == len) + break; + } + while (*p) { + if (p[0] == '/') { + if (p[1] == '/') + /* Convert '//' --> '/' */ + strcpy(p, p+1); + else if (p[1] == '.' && p[2] == '/') + /* Convert '/./' --> '/' */ + strcpy(p, p+2); + else if (p[1] == '.' && p[2] == '.' && p[3] == '/') { + /* Convert 'dir/dir1/../dir2/' + * --> 'dir/dir2/' + */ + char *rp = p -1; + while (rp >= dirname) { + if (*rp == '/') + break; + --rp; + } + if (rp > dirname) { + strcpy(rp, p+3); + p = rp; + } else { + strcpy(dirname, p+4); + p = dirname; + } + } else + p++; + } else + p++; + } + p = dirname; + len = strlen(p); + + if (archive_entry_filetype(file->entry) == AE_IFLNK) { + /* Convert symlink name too. */ + pathname = archive_entry_symlink(file->entry); + archive_strcpy(&(file->symlink), pathname); +#if defined(_WIN32) || defined(__CYGWIN__) + /* + * Convert a path-separator from '\' to '/' + */ + if (archive_strlen(&(file->symlink)) > 0 && + cleanup_backslash_1(file->symlink.s) != 0) { + const wchar_t *wp = + archive_entry_symlink_w(file->entry); + struct archive_wstring ws; + + if (wp != NULL) { + int r; + archive_string_init(&ws); + archive_wstrcpy(&ws, wp); + cleanup_backslash_2(ws.s); + archive_string_empty(&(file->symlink)); + r = archive_string_append_from_wcs( + &(file->symlink), + ws.s, ws.length); + archive_wstring_free(&ws); + if (r < 0 && errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + } + } +#endif + } + /* + * - Count up directory elements. + * - Find out the position which points the last position of + * path separator('/'). + */ + slash = NULL; + file->dircnt = 0; + for (; *p != '\0'; p++) + if (*p == '/') { + slash = p; + file->dircnt++; + } + if (slash == NULL) { + /* The pathname doesn't have a parent directory. */ + file->parentdir.length = len; + archive_string_copy(&(file->basename), &(file->parentdir)); + archive_string_empty(&(file->parentdir)); + *file->parentdir.s = '\0'; + return (ret); + } + + /* Make a basename from dirname and slash */ + *slash = '\0'; + file->parentdir.length = slash - dirname; + archive_strcpy(&(file->basename), slash + 1); + if (archive_entry_filetype(file->entry) == AE_IFDIR) + file->dircnt ++; + return (ret); +} + +/* + * Register a entry to get a hardlink target. + */ +static int +isofile_register_hardlink(struct archive_write *a, struct isofile *file) +{ + struct iso9660 *iso9660 = a->format_data; + struct hardlink *hl; + const char *pathname; + + archive_entry_set_nlink(file->entry, 1); + pathname = archive_entry_hardlink(file->entry); + if (pathname == NULL) { + /* This `file` is a hardlink target. */ + hl = malloc(sizeof(*hl)); + if (hl == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + hl->nlink = 1; + /* A hardlink target must be the first position. */ + file->hlnext = NULL; + hl->file_list.first = file; + hl->file_list.last = &(file->hlnext); + __archive_rb_tree_insert_node(&(iso9660->hardlink_rbtree), + (struct archive_rb_node *)hl); + } else { + hl = (struct hardlink *)__archive_rb_tree_find_node( + &(iso9660->hardlink_rbtree), pathname); + if (hl != NULL) { + /* Insert `file` entry into the tail. */ + file->hlnext = NULL; + *hl->file_list.last = file; + hl->file_list.last = &(file->hlnext); + hl->nlink++; + } + archive_entry_unset_size(file->entry); + } + + return (ARCHIVE_OK); +} + +/* + * Hardlinked files have to have the same location of extent. + * We have to find out hardlink target entries for the entries + * which have a hardlink target name. + */ +static void +isofile_connect_hardlink_files(struct iso9660 *iso9660) +{ + struct archive_rb_node *n; + struct hardlink *hl; + struct isofile *target, *nf; + + ARCHIVE_RB_TREE_FOREACH(n, &(iso9660->hardlink_rbtree)) { + hl = (struct hardlink *)n; + + /* The first entry must be a hardlink target. */ + target = hl->file_list.first; + archive_entry_set_nlink(target->entry, hl->nlink); + /* Set a hardlink target to reference entries. */ + for (nf = target->hlnext; + nf != NULL; nf = nf->hlnext) { + nf->hardlink_target = target; + archive_entry_set_nlink(nf->entry, hl->nlink); + } + } +} + +static int +isofile_hd_cmp_node(const struct archive_rb_node *n1, + const struct archive_rb_node *n2) +{ + const struct hardlink *h1 = (const struct hardlink *)n1; + const struct hardlink *h2 = (const struct hardlink *)n2; + + return (strcmp(archive_entry_pathname(h1->file_list.first->entry), + archive_entry_pathname(h2->file_list.first->entry))); +} + +static int +isofile_hd_cmp_key(const struct archive_rb_node *n, const void *key) +{ + const struct hardlink *h = (const struct hardlink *)n; + + return (strcmp(archive_entry_pathname(h->file_list.first->entry), + (const char *)key)); +} + +static void +isofile_init_hardlinks(struct iso9660 *iso9660) +{ + static const struct archive_rb_tree_ops rb_ops = { + isofile_hd_cmp_node, isofile_hd_cmp_key, + }; + + __archive_rb_tree_init(&(iso9660->hardlink_rbtree), &rb_ops); +} + +static void +isofile_free_hardlinks(struct iso9660 *iso9660) +{ + struct archive_rb_node *n, *next; + + for (n = ARCHIVE_RB_TREE_MIN(&(iso9660->hardlink_rbtree)); n;) { + next = __archive_rb_tree_iterate(&(iso9660->hardlink_rbtree), + n, ARCHIVE_RB_DIR_RIGHT); + free(n); + n = next; + } +} + +static struct isoent * +isoent_new(struct isofile *file) +{ + struct isoent *isoent; + static const struct archive_rb_tree_ops rb_ops = { + isoent_cmp_node, isoent_cmp_key, + }; + + isoent = calloc(1, sizeof(*isoent)); + if (isoent == NULL) + return (NULL); + isoent->file = file; + isoent->children.first = NULL; + isoent->children.last = &(isoent->children.first); + __archive_rb_tree_init(&(isoent->rbtree), &rb_ops); + isoent->subdirs.first = NULL; + isoent->subdirs.last = &(isoent->subdirs.first); + isoent->extr_rec_list.first = NULL; + isoent->extr_rec_list.last = &(isoent->extr_rec_list.first); + isoent->extr_rec_list.current = NULL; + if (archive_entry_filetype(file->entry) == AE_IFDIR) + isoent->dir = 1; + + return (isoent); +} + +static inline struct isoent * +isoent_clone(struct isoent *src) +{ + return (isoent_new(src->file)); +} + +static void +_isoent_free(struct isoent *isoent) +{ + struct extr_rec *er, *er_next; + + free(isoent->children_sorted); + free(isoent->identifier); + er = isoent->extr_rec_list.first; + while (er != NULL) { + er_next = er->next; + free(er); + er = er_next; + } + free(isoent); +} + +static void +isoent_free_all(struct isoent *isoent) +{ + struct isoent *np, *np_temp; + + if (isoent == NULL) + return; + np = isoent; + for (;;) { + if (np->dir) { + if (np->children.first != NULL) { + /* Enter to sub directories. */ + np = np->children.first; + continue; + } + } + for (;;) { + np_temp = np; + if (np->chnext == NULL) { + /* Return to the parent directory. */ + np = np->parent; + _isoent_free(np_temp); + if (np == np_temp) + return; + } else { + np = np->chnext; + _isoent_free(np_temp); + break; + } + } + } +} + +static struct isoent * +isoent_create_virtual_dir(struct archive_write *a, struct iso9660 *iso9660, const char *pathname) +{ + struct isofile *file; + struct isoent *isoent; + + file = isofile_new(a, NULL); + if (file == NULL) + return (NULL); + archive_entry_set_pathname(file->entry, pathname); + archive_entry_unset_mtime(file->entry); + archive_entry_unset_atime(file->entry); + archive_entry_unset_ctime(file->entry); + archive_entry_set_uid(file->entry, getuid()); + archive_entry_set_gid(file->entry, getgid()); + archive_entry_set_mode(file->entry, 0555 | AE_IFDIR); + archive_entry_set_nlink(file->entry, 2); + if (isofile_gen_utility_names(a, file) < ARCHIVE_WARN) { + isofile_free(file); + return (NULL); + } + isofile_add_entry(iso9660, file); + + isoent = isoent_new(file); + if (isoent == NULL) + return (NULL); + isoent->dir = 1; + isoent->virtual = 1; + + return (isoent); +} + +static int +isoent_cmp_node(const struct archive_rb_node *n1, + const struct archive_rb_node *n2) +{ + const struct isoent *e1 = (const struct isoent *)n1; + const struct isoent *e2 = (const struct isoent *)n2; + + return (strcmp(e1->file->basename.s, e2->file->basename.s)); +} + +static int +isoent_cmp_key(const struct archive_rb_node *n, const void *key) +{ + const struct isoent *e = (const struct isoent *)n; + + return (strcmp(e->file->basename.s, (const char *)key)); +} + +static int +isoent_add_child_head(struct isoent *parent, struct isoent *child) +{ + + if (!__archive_rb_tree_insert_node( + &(parent->rbtree), (struct archive_rb_node *)child)) + return (0); + if ((child->chnext = parent->children.first) == NULL) + parent->children.last = &(child->chnext); + parent->children.first = child; + parent->children.cnt++; + child->parent = parent; + + /* Add a child to a sub-directory chain */ + if (child->dir) { + if ((child->drnext = parent->subdirs.first) == NULL) + parent->subdirs.last = &(child->drnext); + parent->subdirs.first = child; + parent->subdirs.cnt++; + child->parent = parent; + } else + child->drnext = NULL; + return (1); +} + +static int +isoent_add_child_tail(struct isoent *parent, struct isoent *child) +{ + + if (!__archive_rb_tree_insert_node( + &(parent->rbtree), (struct archive_rb_node *)child)) + return (0); + child->chnext = NULL; + *parent->children.last = child; + parent->children.last = &(child->chnext); + parent->children.cnt++; + child->parent = parent; + + /* Add a child to a sub-directory chain */ + child->drnext = NULL; + if (child->dir) { + *parent->subdirs.last = child; + parent->subdirs.last = &(child->drnext); + parent->subdirs.cnt++; + child->parent = parent; + } + return (1); +} + +static void +isoent_remove_child(struct isoent *parent, struct isoent *child) +{ + struct isoent *ent; + + /* Remove a child entry from children chain. */ + ent = parent->children.first; + while (ent->chnext != child) + ent = ent->chnext; + if ((ent->chnext = ent->chnext->chnext) == NULL) + parent->children.last = &(ent->chnext); + parent->children.cnt--; + + if (child->dir) { + /* Remove a child entry from sub-directory chain. */ + ent = parent->subdirs.first; + while (ent->drnext != child) + ent = ent->drnext; + if ((ent->drnext = ent->drnext->drnext) == NULL) + parent->subdirs.last = &(ent->drnext); + parent->subdirs.cnt--; + } + + __archive_rb_tree_remove_node(&(parent->rbtree), + (struct archive_rb_node *)child); +} + +static int +isoent_clone_tree(struct archive_write *a, struct isoent **nroot, + struct isoent *root) +{ + struct isoent *np, *xroot, *newent; + + np = root; + xroot = NULL; + do { + newent = isoent_clone(np); + if (newent == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + if (xroot == NULL) { + *nroot = xroot = newent; + newent->parent = xroot; + } else + isoent_add_child_tail(xroot, newent); + if (np->dir && np->children.first != NULL) { + /* Enter to sub directories. */ + np = np->children.first; + xroot = newent; + continue; + } + while (np != np->parent) { + if (np->chnext == NULL) { + /* Return to the parent directory. */ + np = np->parent; + xroot = xroot->parent; + } else { + np = np->chnext; + break; + } + } + } while (np != np->parent); + + return (ARCHIVE_OK); +} + +/* + * Setup directory locations. + */ +static void +isoent_setup_directory_location(struct iso9660 *iso9660, int location, + struct vdd *vdd) +{ + struct isoent *np; + int depth; + + vdd->total_dir_block = 0; + depth = 0; + np = vdd->rootent; + do { + int block; + + np->dir_block = calculate_directory_descriptors( + iso9660, vdd, np, depth); + vdd->total_dir_block += np->dir_block; + np->dir_location = location; + location += np->dir_block; + block = extra_setup_location(np, location); + vdd->total_dir_block += block; + location += block; + + if (np->subdirs.first != NULL && depth + 1 < vdd->max_depth) { + /* Enter to sub directories. */ + np = np->subdirs.first; + depth++; + continue; + } + while (np != np->parent) { + if (np->drnext == NULL) { + /* Return to the parent directory. */ + np = np->parent; + depth--; + } else { + np = np->drnext; + break; + } + } + } while (np != np->parent); +} + +static void +_isoent_file_location(struct iso9660 *iso9660, struct isoent *isoent, + int *symlocation) +{ + struct isoent **children; + int n; + + if (isoent->children.cnt == 0) + return; + + children = isoent->children_sorted; + for (n = 0; n < isoent->children.cnt; n++) { + struct isoent *np; + struct isofile *file; + + np = children[n]; + if (np->dir) + continue; + if (np == iso9660->el_torito.boot) + continue; + file = np->file; + if (file->boot || file->hardlink_target != NULL) + continue; + if (archive_entry_filetype(file->entry) == AE_IFLNK || + file->content.size == 0) { + /* + * Do not point a valid location. + * Make sure entry is not hardlink file. + */ + file->content.location = (*symlocation)--; + continue; + } + + file->write_content = 1; + } +} + +/* + * Setup file locations. + */ +static void +isoent_setup_file_location(struct iso9660 *iso9660, int location) +{ + struct isoent *isoent; + struct isoent *np; + struct isofile *file; + size_t size; + int block; + int depth; + int joliet; + int symlocation; + int total_block; + + iso9660->total_file_block = 0; + if ((isoent = iso9660->el_torito.catalog) != NULL) { + isoent->file->content.location = location; + block = (int)((archive_entry_size(isoent->file->entry) + + LOGICAL_BLOCK_SIZE -1) >> LOGICAL_BLOCK_BITS); + location += block; + iso9660->total_file_block += block; + } + if ((isoent = iso9660->el_torito.boot) != NULL) { + isoent->file->content.location = location; + size = fd_boot_image_size(iso9660->el_torito.media_type); + if (size == 0) + size = (size_t)archive_entry_size(isoent->file->entry); + block = ((int)size + LOGICAL_BLOCK_SIZE -1) + >> LOGICAL_BLOCK_BITS; + location += block; + iso9660->total_file_block += block; + isoent->file->content.blocks = block; + } + + depth = 0; + symlocation = -16; + if (!iso9660->opt.rr && iso9660->opt.joliet) { + joliet = 1; + np = iso9660->joliet.rootent; + } else { + joliet = 0; + np = iso9660->primary.rootent; + } + do { + _isoent_file_location(iso9660, np, &symlocation); + + if (np->subdirs.first != NULL && + (joliet || + ((iso9660->opt.rr == OPT_RR_DISABLED && + depth + 2 < iso9660->primary.max_depth) || + (iso9660->opt.rr && + depth + 1 < iso9660->primary.max_depth)))) { + /* Enter to sub directories. */ + np = np->subdirs.first; + depth++; + continue; + } + while (np != np->parent) { + if (np->drnext == NULL) { + /* Return to the parent directory. */ + np = np->parent; + depth--; + } else { + np = np->drnext; + break; + } + } + } while (np != np->parent); + + total_block = 0; + for (file = iso9660->data_file_list.first; + file != NULL; file = file->datanext) { + + if (!file->write_content) + continue; + + file->cur_content = &(file->content); + do { + file->cur_content->location = location; + location += file->cur_content->blocks; + total_block += file->cur_content->blocks; - /* Next fragument */ ++ /* Next fragment */ + file->cur_content = file->cur_content->next; + } while (file->cur_content != NULL); + } + iso9660->total_file_block += total_block; +} + +static int +get_path_component(char *name, size_t n, const char *fn) +{ + char *p; + size_t l; + + p = strchr(fn, '/'); + if (p == NULL) { + if ((l = strlen(fn)) == 0) + return (0); + } else + l = p - fn; + if (l > n -1) + return (-1); + memcpy(name, fn, l); + name[l] = '\0'; + + return ((int)l); +} + +/* + * Add a new entry into the tree. + */ +static int +isoent_tree(struct archive_write *a, struct isoent **isoentpp) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + char name[_MAX_FNAME];/* Included null terminator size. */ +#elif defined(NAME_MAX) && NAME_MAX >= 255 + char name[NAME_MAX+1]; +#else + char name[256]; +#endif + struct iso9660 *iso9660 = a->format_data; + struct isoent *dent, *isoent, *np; + struct isofile *f1, *f2; + const char *fn, *p; + int l; + + isoent = *isoentpp; + dent = iso9660->primary.rootent; + if (isoent->file->parentdir.length > 0) + fn = p = isoent->file->parentdir.s; + else + fn = p = ""; + + /* + * If the path of the parent directory of `isoent' entry is + * the same as the path of `cur_dirent', add isoent to + * `cur_dirent'. + */ + if (archive_strlen(&(iso9660->cur_dirstr)) + == archive_strlen(&(isoent->file->parentdir)) && + strcmp(iso9660->cur_dirstr.s, fn) == 0) { + if (!isoent_add_child_tail(iso9660->cur_dirent, isoent)) { + np = (struct isoent *)__archive_rb_tree_find_node( + &(iso9660->cur_dirent->rbtree), + isoent->file->basename.s); + goto same_entry; + } + return (ARCHIVE_OK); + } + + for (;;) { + l = get_path_component(name, sizeof(name), fn); + if (l == 0) { + np = NULL; + break; + } + if (l < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "A name buffer is too small"); + _isoent_free(isoent); + return (ARCHIVE_FATAL); + } + + np = isoent_find_child(dent, name); + if (np == NULL || fn[0] == '\0') + break; + + /* Find next subdirectory. */ + if (!np->dir) { + /* NOT Directory! */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "`%s' is not directory, we cannot insert `%s' ", + archive_entry_pathname(np->file->entry), + archive_entry_pathname(isoent->file->entry)); + _isoent_free(isoent); + *isoentpp = NULL; + return (ARCHIVE_FAILED); + } + fn += l; + if (fn[0] == '/') + fn++; + dent = np; + } + if (np == NULL) { + /* + * Create virtual parent directories. + */ + while (fn[0] != '\0') { + struct isoent *vp; + struct archive_string as; + + archive_string_init(&as); + archive_strncat(&as, p, fn - p + l); + if (as.s[as.length-1] == '/') { + as.s[as.length-1] = '\0'; + as.length--; + } + vp = isoent_create_virtual_dir(a, iso9660, as.s); + if (vp == NULL) { + archive_string_free(&as); + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + _isoent_free(isoent); + *isoentpp = NULL; + return (ARCHIVE_FATAL); + } + archive_string_free(&as); + + if (vp->file->dircnt > iso9660->dircnt_max) + iso9660->dircnt_max = vp->file->dircnt; + isoent_add_child_tail(dent, vp); + np = vp; + + fn += l; + if (fn[0] == '/') + fn++; + l = get_path_component(name, sizeof(name), fn); + if (l < 0) { + archive_string_free(&as); + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "A name buffer is too small"); + _isoent_free(isoent); + *isoentpp = NULL; + return (ARCHIVE_FATAL); + } + dent = np; + } + + /* Found out the parent directory where isoent can be + * inserted. */ + iso9660->cur_dirent = dent; + archive_string_empty(&(iso9660->cur_dirstr)); + archive_string_ensure(&(iso9660->cur_dirstr), + archive_strlen(&(dent->file->parentdir)) + + archive_strlen(&(dent->file->basename)) + 2); + if (archive_strlen(&(dent->file->parentdir)) + + archive_strlen(&(dent->file->basename)) == 0) + iso9660->cur_dirstr.s[0] = 0; + else { + if (archive_strlen(&(dent->file->parentdir)) > 0) { + archive_string_copy(&(iso9660->cur_dirstr), + &(dent->file->parentdir)); + archive_strappend_char(&(iso9660->cur_dirstr), '/'); + } + archive_string_concat(&(iso9660->cur_dirstr), + &(dent->file->basename)); + } + + if (!isoent_add_child_tail(dent, isoent)) { + np = (struct isoent *)__archive_rb_tree_find_node( + &(dent->rbtree), isoent->file->basename.s); + goto same_entry; + } + return (ARCHIVE_OK); + } + +same_entry: + /* + * We have already has the entry the filename of which is + * the same. + */ + f1 = np->file; + f2 = isoent->file; + + /* If the file type of entries is different, + * we cannot handle it. */ + if (archive_entry_filetype(f1->entry) != + archive_entry_filetype(f2->entry)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Found duplicate entries `%s' and its file type is " + "different", + archive_entry_pathname(f1->entry)); + _isoent_free(isoent); + *isoentpp = NULL; + return (ARCHIVE_FAILED); + } + + /* Swap file entries. */ + np->file = f2; + isoent->file = f1; + np->virtual = 0; + + _isoent_free(isoent); + *isoentpp = np; + return (ARCHIVE_OK); +} + +/* + * Find a entry from `isoent' + */ +static struct isoent * +isoent_find_child(struct isoent *isoent, const char *child_name) +{ + struct isoent *np; + + np = (struct isoent *)__archive_rb_tree_find_node( + &(isoent->rbtree), child_name); + return (np); +} + +/* + * Find a entry full-path of which is specified by `fn' parameter, + * in the tree. + */ +static struct isoent * +isoent_find_entry(struct isoent *rootent, const char *fn) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + char name[_MAX_FNAME];/* Included null terminator size. */ +#elif defined(NAME_MAX) && NAME_MAX >= 255 + char name[NAME_MAX+1]; +#else + char name[256]; +#endif + struct isoent *isoent, *np; + int l; + + isoent = rootent; + np = NULL; + for (;;) { + l = get_path_component(name, sizeof(name), fn); + if (l == 0) + break; + fn += l; + if (fn[0] == '/') + fn++; + + np = isoent_find_child(isoent, name); + if (np == NULL) + break; + if (fn[0] == '\0') + break;/* We found out the entry */ + + /* Try sub directory. */ + isoent = np; + np = NULL; + if (!isoent->dir) + break;/* Not directory */ + } + + return (np); +} + +/* + * Following idr_* functions are used for resolving duplicated filenames + * and unreceivable filenames to generate ISO9660/Joliet Identifiers. + */ + +static void +idr_relaxed_filenames(char *map) +{ + int i; + + for (i = 0x21; i <= 0x2F; i++) + map[i] = 1; + for (i = 0x3A; i <= 0x41; i++) + map[i] = 1; + for (i = 0x5B; i <= 0x5E; i++) + map[i] = 1; + map[0x60] = 1; + for (i = 0x7B; i <= 0x7E; i++) + map[i] = 1; +} + +static void +idr_init(struct iso9660 *iso9660, struct vdd *vdd, struct idr *idr) +{ + + idr->idrent_pool = NULL; + idr->pool_size = 0; + if (vdd->vdd_type != VDD_JOLIET) { + if (iso9660->opt.iso_level <= 3) { + memcpy(idr->char_map, d_characters_map, + sizeof(idr->char_map)); + } else { + memcpy(idr->char_map, d1_characters_map, + sizeof(idr->char_map)); + idr_relaxed_filenames(idr->char_map); + } + } +} + +static void +idr_cleanup(struct idr *idr) +{ + free(idr->idrent_pool); +} + +static int +idr_ensure_poolsize(struct archive_write *a, struct idr *idr, + int cnt) +{ + + if (idr->pool_size < cnt) { + void *p; + const int bk = (1 << 7) - 1; + int psize; + + psize = (cnt + bk) & ~bk; + p = realloc(idr->idrent_pool, sizeof(struct idrent) * psize); + if (p == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + idr->idrent_pool = (struct idrent *)p; + idr->pool_size = psize; + } + return (ARCHIVE_OK); +} + +static int +idr_start(struct archive_write *a, struct idr *idr, int cnt, int ffmax, + int num_size, int null_size, const struct archive_rb_tree_ops *rbt_ops) +{ + int r; + + (void)ffmax; /* UNUSED */ + + r = idr_ensure_poolsize(a, idr, cnt); + if (r != ARCHIVE_OK) + return (r); + __archive_rb_tree_init(&(idr->rbtree), rbt_ops); + idr->wait_list.first = NULL; + idr->wait_list.last = &(idr->wait_list.first); + idr->pool_idx = 0; + idr->num_size = num_size; + idr->null_size = null_size; + return (ARCHIVE_OK); +} + +static void +idr_register(struct idr *idr, struct isoent *isoent, int weight, int noff) +{ + struct idrent *idrent, *n; + + idrent = &(idr->idrent_pool[idr->pool_idx++]); + idrent->wnext = idrent->avail = NULL; + idrent->isoent = isoent; + idrent->weight = weight; + idrent->noff = noff; + idrent->rename_num = 0; + + if (!__archive_rb_tree_insert_node(&(idr->rbtree), &(idrent->rbnode))) { + n = (struct idrent *)__archive_rb_tree_find_node( + &(idr->rbtree), idrent->isoent); + if (n != NULL) { + /* this `idrent' needs to rename. */ + idrent->avail = n; + *idr->wait_list.last = idrent; + idr->wait_list.last = &(idrent->wnext); + } + } +} + +static void +idr_extend_identifier(struct idrent *wnp, int numsize, int nullsize) +{ + unsigned char *p; + int wnp_ext_off; + + wnp_ext_off = wnp->isoent->ext_off; + if (wnp->noff + numsize != wnp_ext_off) { + p = (unsigned char *)wnp->isoent->identifier; + /* Extend the filename; foo.c --> foo___.c */ + memmove(p + wnp->noff + numsize, p + wnp_ext_off, + wnp->isoent->ext_len + nullsize); + wnp->isoent->ext_off = wnp_ext_off = wnp->noff + numsize; + wnp->isoent->id_len = wnp_ext_off + wnp->isoent->ext_len; + } +} + +static void +idr_resolve(struct idr *idr, void (*fsetnum)(unsigned char *p, int num)) +{ + struct idrent *n; + unsigned char *p; + + for (n = idr->wait_list.first; n != NULL; n = n->wnext) { + idr_extend_identifier(n, idr->num_size, idr->null_size); + p = (unsigned char *)n->isoent->identifier + n->noff; + do { + fsetnum(p, n->avail->rename_num++); + } while (!__archive_rb_tree_insert_node( + &(idr->rbtree), &(n->rbnode))); + } +} + +static void +idr_set_num(unsigned char *p, int num) +{ + static const char xdig[] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z' + }; + + num %= sizeof(xdig) * sizeof(xdig) * sizeof(xdig); + p[0] = xdig[(num / (sizeof(xdig) * sizeof(xdig)))]; + num %= sizeof(xdig) * sizeof(xdig); + p[1] = xdig[ (num / sizeof(xdig))]; + num %= sizeof(xdig); + p[2] = xdig[num]; +} + +static void +idr_set_num_beutf16(unsigned char *p, int num) +{ + static const uint16_t xdig[] = { + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, + 0x0036, 0x0037, 0x0038, 0x0039, + 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, + 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, + 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, + 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, + 0x0059, 0x005A + }; +#define XDIG_CNT (sizeof(xdig)/sizeof(xdig[0])) + + num %= XDIG_CNT * XDIG_CNT * XDIG_CNT; + archive_be16enc(p, xdig[(num / (XDIG_CNT * XDIG_CNT))]); + num %= XDIG_CNT * XDIG_CNT; + archive_be16enc(p+2, xdig[ (num / XDIG_CNT)]); + num %= XDIG_CNT; + archive_be16enc(p+4, xdig[num]); +} + +/* + * Generate ISO9660 Identifier. + */ +static int +isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent, + struct idr *idr) +{ + struct iso9660 *iso9660; + struct isoent *np; + char *p; + int l, r; + const char *char_map; + char allow_ldots, allow_multidot, allow_period, allow_vernum; + int fnmax, ffmax, dnmax; + static const struct archive_rb_tree_ops rb_ops = { + isoent_cmp_node_iso9660, isoent_cmp_key_iso9660 + }; + + if (isoent->children.cnt == 0) + return (0); + + iso9660 = a->format_data; + char_map = idr->char_map; + if (iso9660->opt.iso_level <= 3) { + allow_ldots = 0; + allow_multidot = 0; + allow_period = 1; + allow_vernum = iso9660->opt.allow_vernum; + if (iso9660->opt.iso_level == 1) { + fnmax = 8; + ffmax = 12;/* fnmax + '.' + 3 */ + dnmax = 8; + } else { + fnmax = 30; + ffmax = 31; + dnmax = 31; + } + } else { + allow_ldots = allow_multidot = 1; + allow_period = allow_vernum = 0; + if (iso9660->opt.rr) + /* + * MDR : The maximum size of Directory Record(254). + * DRL : A Directory Record Length(33). + * CE : A size of SUSP CE System Use Entry(28). + * MDR - DRL - CE = 254 - 33 - 28 = 193. + */ + fnmax = ffmax = dnmax = 193; + else + /* + * XA : CD-ROM XA System Use Extension + * Information(14). + * MDR - DRL - XA = 254 - 33 -14 = 207. + */ + fnmax = ffmax = dnmax = 207; + } + + r = idr_start(a, idr, isoent->children.cnt, ffmax, 3, 1, &rb_ops); + if (r < 0) + return (r); + + for (np = isoent->children.first; np != NULL; np = np->chnext) { + char *dot, *xdot; + int ext_off, noff, weight; + + l = (int)np->file->basename.length; + p = malloc(l+31+2+1); + if (p == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + memcpy(p, np->file->basename.s, l); + p[l] = '\0'; + np->identifier = p; + + dot = xdot = NULL; + if (!allow_ldots) { + /* + * If there is a '.' character at the first byte, + * it has to be replaced by '_' character. + */ + if (*p == '.') + *p++ = '_'; + } + for (;*p; p++) { + if (*p & 0x80) { + *p = '_'; + continue; + } + if (char_map[(unsigned char)*p]) { + /* if iso-level is '4', a character '.' is + * allowed by char_map. */ + if (*p == '.') { + xdot = dot; + dot = p; + } + continue; + } + if (*p >= 'a' && *p <= 'z') { + *p -= 'a' - 'A'; + continue; + } + if (*p == '.') { + xdot = dot; + dot = p; + if (allow_multidot) + continue; + } + *p = '_'; + } + p = np->identifier; + weight = -1; + if (dot == NULL) { + int nammax; + + if (np->dir) + nammax = dnmax; + else + nammax = fnmax; + + if (l > nammax) { + p[nammax] = '\0'; + weight = nammax; + ext_off = nammax; + } else + ext_off = l; + } else { + *dot = '.'; + ext_off = (int)(dot - p); + + if (iso9660->opt.iso_level == 1) { + if (dot - p <= 8) { + if (strlen(dot) > 4) { + /* A length of a file extension + * must be less than 4 */ + dot[4] = '\0'; + weight = 0; + } + } else { + p[8] = dot[0]; + p[9] = dot[1]; + p[10] = dot[2]; + p[11] = dot[3]; + p[12] = '\0'; + weight = 8; + ext_off = 8; + } + } else if (np->dir) { + if (l > dnmax) { + p[dnmax] = '\0'; + weight = dnmax; + if (ext_off > dnmax) + ext_off = dnmax; + } + } else if (l > ffmax) { + int extlen = (int)strlen(dot); + int xdoff; + + if (xdot != NULL) + xdoff = (int)(xdot - p); + else + xdoff = 0; + + if (extlen > 1 && xdoff < fnmax-1) { + int off; + + if (extlen > ffmax) + extlen = ffmax; + off = ffmax - extlen; + if (off == 0) { + /* A dot('.') character - * does't place to the first ++ * doesn't place to the first + * byte of identifier. */ + off ++; + extlen --; + } + memmove(p+off, dot, extlen); + p[ffmax] = '\0'; + ext_off = off; + weight = off; +#ifdef COMPAT_MKISOFS + } else if (xdoff >= fnmax-1) { + /* Simulate a bug(?) of mkisofs. */ + p[fnmax-1] = '\0'; + ext_off = fnmax-1; + weight = fnmax-1; +#endif + } else { + p[fnmax] = '\0'; + ext_off = fnmax; + weight = fnmax; + } + } + } + /* Save an offset of a file name extension to sort files. */ + np->ext_off = ext_off; + np->ext_len = (int)strlen(&p[ext_off]); + np->id_len = l = ext_off + np->ext_len; + + /* Make an offset of the number which is used to be set - * hexadecimal number to avoid duplicate identififier. */ ++ * hexadecimal number to avoid duplicate identifier. */ + if (iso9660->opt.iso_level == 1) { + if (ext_off >= 5) + noff = 5; + else + noff = ext_off; + } else { + if (l == ffmax) + noff = ext_off - 3; + else if (l == ffmax-1) + noff = ext_off - 2; + else if (l == ffmax-2) + noff = ext_off - 1; + else + noff = ext_off; + } + /* Register entry to the identifier resolver. */ + idr_register(idr, np, weight, noff); + } + + /* Resolve duplicate identifier. */ + idr_resolve(idr, idr_set_num); + + /* Add a period and a version number to identifiers. */ + for (np = isoent->children.first; np != NULL; np = np->chnext) { + if (!np->dir && np->rr_child == NULL) { + p = np->identifier + np->ext_off + np->ext_len; + if (np->ext_len == 0 && allow_period) { + *p++ = '.'; + np->ext_len = 1; + } + if (np->ext_len == 1 && !allow_period) { + *--p = '\0'; + np->ext_len = 0; + } + np->id_len = np->ext_off + np->ext_len; + if (allow_vernum) { + *p++ = ';'; + *p++ = '1'; + np->id_len += 2; + } + *p = '\0'; + } else + np->id_len = np->ext_off + np->ext_len; + np->mb_len = np->id_len; + } + return (ARCHIVE_OK); +} + +/* + * Generate Joliet Identifier. + */ +static int +isoent_gen_joliet_identifier(struct archive_write *a, struct isoent *isoent, + struct idr *idr) +{ + struct iso9660 *iso9660; + struct isoent *np; + unsigned char *p; + size_t l; + int r; + size_t ffmax, parent_len; + static const struct archive_rb_tree_ops rb_ops = { + isoent_cmp_node_joliet, isoent_cmp_key_joliet + }; + + if (isoent->children.cnt == 0) + return (0); + + iso9660 = a->format_data; + if (iso9660->opt.joliet == OPT_JOLIET_LONGNAME) + ffmax = 206; + else + ffmax = 128; + + r = idr_start(a, idr, isoent->children.cnt, (int)ffmax, 6, 2, &rb_ops); + if (r < 0) + return (r); + + parent_len = 1; + for (np = isoent; np->parent != np; np = np->parent) + parent_len += np->mb_len + 1; + + for (np = isoent->children.first; np != NULL; np = np->chnext) { + unsigned char *dot; + int ext_off, noff, weight; + size_t lt; + + if ((l = np->file->basename_utf16.length) > ffmax) + l = ffmax; + + p = malloc((l+1)*2); + if (p == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + memcpy(p, np->file->basename_utf16.s, l); + p[l] = 0; + p[l+1] = 0; + + np->identifier = (char *)p; + lt = l; + dot = p + l; + weight = 0; + while (lt > 0) { + if (!joliet_allowed_char(p[0], p[1])) + archive_be16enc(p, 0x005F); /* '_' */ + else if (p[0] == 0 && p[1] == 0x2E) /* '.' */ + dot = p; + p += 2; + lt -= 2; + } + ext_off = (int)(dot - (unsigned char *)np->identifier); + np->ext_off = ext_off; + np->ext_len = (int)l - ext_off; + np->id_len = (int)l; + + /* + * Get a length of MBS of a full-pathname. + */ + if (np->file->basename_utf16.length > ffmax) { + if (archive_strncpy_l(&iso9660->mbs, + (const char *)np->identifier, l, + iso9660->sconv_from_utf16be) != 0 && + errno == ENOMEM) { + archive_set_error(&a->archive, errno, + "No memory"); + return (ARCHIVE_FATAL); + } + np->mb_len = (int)iso9660->mbs.length; + if (np->mb_len != (int)np->file->basename.length) + weight = np->mb_len; + } else + np->mb_len = (int)np->file->basename.length; + + /* If a length of full-pathname is longer than 240 bytes, + * it violates Joliet extensions regulation. */ + if (parent_len > 240 + || np->mb_len > 240 + || parent_len + np->mb_len > 240) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "The regulation of Joliet extensions;" + " A length of a full-pathname of `%s' is " + "longer than 240 bytes, (p=%d, b=%d)", + archive_entry_pathname(np->file->entry), + (int)parent_len, (int)np->mb_len); + return (ARCHIVE_FATAL); + } + + /* Make an offset of the number which is used to be set + * hexadecimal number to avoid duplicate identifier. */ + if (l == ffmax) + noff = ext_off - 6; + else if (l == ffmax-2) + noff = ext_off - 4; + else if (l == ffmax-4) + noff = ext_off - 2; + else + noff = ext_off; + /* Register entry to the identifier resolver. */ + idr_register(idr, np, weight, noff); + } + + /* Resolve duplicate identifier with Joliet Volume. */ + idr_resolve(idr, idr_set_num_beutf16); + + return (ARCHIVE_OK); +} + +/* + * This comparing rule is according to ISO9660 Standard 9.3 + */ +static int +isoent_cmp_iso9660_identifier(const struct isoent *p1, const struct isoent *p2) +{ + const char *s1, *s2; + int cmp; + int l; + + s1 = p1->identifier; + s2 = p2->identifier; + + /* Compare File Name */ + l = p1->ext_off; + if (l > p2->ext_off) + l = p2->ext_off; + cmp = memcmp(s1, s2, l); + if (cmp != 0) + return (cmp); + if (p1->ext_off < p2->ext_off) { + s2 += l; + l = p2->ext_off - p1->ext_off; + while (l--) + if (0x20 != *s2++) + return (0x20 + - *(const unsigned char *)(s2 - 1)); + } else if (p1->ext_off > p2->ext_off) { + s1 += l; + l = p1->ext_off - p2->ext_off; + while (l--) + if (0x20 != *s1++) + return (*(const unsigned char *)(s1 - 1) + - 0x20); + } + /* Compare File Name Extension */ + if (p1->ext_len == 0 && p2->ext_len == 0) + return (0); + if (p1->ext_len == 1 && p2->ext_len == 1) + return (0); + if (p1->ext_len <= 1) + return (-1); + if (p2->ext_len <= 1) + return (1); + l = p1->ext_len; + if (l > p2->ext_len) + l = p2->ext_len; + s1 = p1->identifier + p1->ext_off; + s2 = p2->identifier + p2->ext_off; + if (l > 1) { + cmp = memcmp(s1, s2, l); + if (cmp != 0) + return (cmp); + } + if (p1->ext_len < p2->ext_len) { + s2 += l; + l = p2->ext_len - p1->ext_len; + while (l--) + if (0x20 != *s2++) + return (0x20 + - *(const unsigned char *)(s2 - 1)); + } else if (p1->ext_len > p2->ext_len) { + s1 += l; + l = p1->ext_len - p2->ext_len; + while (l--) + if (0x20 != *s1++) + return (*(const unsigned char *)(s1 - 1) + - 0x20); + } + /* Compare File Version Number */ + /* No operation. The File Version Number is always one. */ + + return (cmp); +} + +static int +isoent_cmp_node_iso9660(const struct archive_rb_node *n1, + const struct archive_rb_node *n2) +{ + const struct idrent *e1 = (const struct idrent *)n1; + const struct idrent *e2 = (const struct idrent *)n2; + + return (isoent_cmp_iso9660_identifier(e2->isoent, e1->isoent)); +} + +static int +isoent_cmp_key_iso9660(const struct archive_rb_node *node, const void *key) +{ + const struct isoent *isoent = (const struct isoent *)key; + const struct idrent *idrent = (const struct idrent *)node; + + return (isoent_cmp_iso9660_identifier(isoent, idrent->isoent)); +} + +static int +isoent_cmp_joliet_identifier(const struct isoent *p1, const struct isoent *p2) +{ + const unsigned char *s1, *s2; + int cmp; + int l; + + s1 = (const unsigned char *)p1->identifier; + s2 = (const unsigned char *)p2->identifier; + + /* Compare File Name */ + l = p1->ext_off; + if (l > p2->ext_off) + l = p2->ext_off; + cmp = memcmp(s1, s2, l); + if (cmp != 0) + return (cmp); + if (p1->ext_off < p2->ext_off) { + s2 += l; + l = p2->ext_off - p1->ext_off; + while (l--) + if (0 != *s2++) + return (- *(const unsigned char *)(s2 - 1)); + } else if (p1->ext_off > p2->ext_off) { + s1 += l; + l = p1->ext_off - p2->ext_off; + while (l--) + if (0 != *s1++) + return (*(const unsigned char *)(s1 - 1)); + } + /* Compare File Name Extension */ + if (p1->ext_len == 0 && p2->ext_len == 0) + return (0); + if (p1->ext_len == 2 && p2->ext_len == 2) + return (0); + if (p1->ext_len <= 2) + return (-1); + if (p2->ext_len <= 2) + return (1); + l = p1->ext_len; + if (l > p2->ext_len) + l = p2->ext_len; + s1 = (unsigned char *)(p1->identifier + p1->ext_off); + s2 = (unsigned char *)(p2->identifier + p2->ext_off); + if (l > 1) { + cmp = memcmp(s1, s2, l); + if (cmp != 0) + return (cmp); + } + if (p1->ext_len < p2->ext_len) { + s2 += l; + l = p2->ext_len - p1->ext_len; + while (l--) + if (0 != *s2++) + return (- *(const unsigned char *)(s2 - 1)); + } else if (p1->ext_len > p2->ext_len) { + s1 += l; + l = p1->ext_len - p2->ext_len; + while (l--) + if (0 != *s1++) + return (*(const unsigned char *)(s1 - 1)); + } + /* Compare File Version Number */ + /* No operation. The File Version Number is always one. */ + + return (cmp); +} + +static int +isoent_cmp_node_joliet(const struct archive_rb_node *n1, + const struct archive_rb_node *n2) +{ + const struct idrent *e1 = (const struct idrent *)n1; + const struct idrent *e2 = (const struct idrent *)n2; + + return (isoent_cmp_joliet_identifier(e2->isoent, e1->isoent)); +} + +static int +isoent_cmp_key_joliet(const struct archive_rb_node *node, const void *key) +{ + const struct isoent *isoent = (const struct isoent *)key; + const struct idrent *idrent = (const struct idrent *)node; + + return (isoent_cmp_joliet_identifier(isoent, idrent->isoent)); +} + +static int +isoent_make_sorted_files(struct archive_write *a, struct isoent *isoent, + struct idr *idr) +{ + struct archive_rb_node *rn; + struct isoent **children; + + children = malloc(isoent->children.cnt * sizeof(struct isoent *)); + if (children == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + isoent->children_sorted = children; + + ARCHIVE_RB_TREE_FOREACH(rn, &(idr->rbtree)) { + struct idrent *idrent = (struct idrent *)rn; + *children ++ = idrent->isoent; + } + return (ARCHIVE_OK); +} + +/* + * - Generate ISO9660 and Joliet identifiers from basenames. + * - Sort files by each directory. + */ +static int +isoent_traverse_tree(struct archive_write *a, struct vdd* vdd) +{ + struct iso9660 *iso9660 = a->format_data; + struct isoent *np; + struct idr idr; + int depth; + int r; + int (*genid)(struct archive_write *, struct isoent *, struct idr *); + + idr_init(iso9660, vdd, &idr); + np = vdd->rootent; + depth = 0; + if (vdd->vdd_type == VDD_JOLIET) + genid = isoent_gen_joliet_identifier; + else + genid = isoent_gen_iso9660_identifier; + do { + if (np->virtual && + !archive_entry_mtime_is_set(np->file->entry)) { + /* Set properly times to virtual directory */ + archive_entry_set_mtime(np->file->entry, + iso9660->birth_time, 0); + archive_entry_set_atime(np->file->entry, + iso9660->birth_time, 0); + archive_entry_set_ctime(np->file->entry, + iso9660->birth_time, 0); + } + if (np->children.first != NULL) { + if (vdd->vdd_type != VDD_JOLIET && + !iso9660->opt.rr && depth + 1 >= vdd->max_depth) { + if (np->children.cnt > 0) + iso9660->directories_too_deep = np; + } else { + /* Generate Identifier */ + r = genid(a, np, &idr); + if (r < 0) + goto exit_traverse_tree; + r = isoent_make_sorted_files(a, np, &idr); + if (r < 0) + goto exit_traverse_tree; + + if (np->subdirs.first != NULL && + depth + 1 < vdd->max_depth) { + /* Enter to sub directories. */ + np = np->subdirs.first; + depth++; + continue; + } + } + } + while (np != np->parent) { + if (np->drnext == NULL) { + /* Return to the parent directory. */ + np = np->parent; + depth--; + } else { + np = np->drnext; + break; + } + } + } while (np != np->parent); + + r = ARCHIVE_OK; +exit_traverse_tree: + idr_cleanup(&idr); + + return (r); +} + +/* + * Collect directory entries into path_table by a directory depth. + */ +static int +isoent_collect_dirs(struct vdd *vdd, struct isoent *rootent, int depth) +{ + struct isoent *np; + + if (rootent == NULL) + rootent = vdd->rootent; + np = rootent; + do { + /* Register current directory to pathtable. */ + path_table_add_entry(&(vdd->pathtbl[depth]), np); + + if (np->subdirs.first != NULL && depth + 1 < vdd->max_depth) { + /* Enter to sub directories. */ + np = np->subdirs.first; + depth++; + continue; + } + while (np != rootent) { + if (np->drnext == NULL) { + /* Return to the parent directory. */ + np = np->parent; + depth--; + } else { + np = np->drnext; + break; + } + } + } while (np != rootent); + + return (ARCHIVE_OK); +} + +/* + * The entry whose number of levels in a directory hierarchy is + * large than eight relocate to rr_move directory. + */ +static int +isoent_rr_move_dir(struct archive_write *a, struct isoent **rr_moved, + struct isoent *curent, struct isoent **newent) +{ + struct iso9660 *iso9660 = a->format_data; + struct isoent *rrmoved, *mvent, *np; + + if ((rrmoved = *rr_moved) == NULL) { + struct isoent *rootent = iso9660->primary.rootent; + /* There isn't rr_move entry. + * Create rr_move entry and insert it into the root entry. + */ + rrmoved = isoent_create_virtual_dir(a, iso9660, "rr_moved"); + if (rrmoved == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + /* Add "rr_moved" entry to the root entry. */ + isoent_add_child_head(rootent, rrmoved); + archive_entry_set_nlink(rootent->file->entry, + archive_entry_nlink(rootent->file->entry) + 1); + /* Register "rr_moved" entry to second level pathtable. */ + path_table_add_entry(&(iso9660->primary.pathtbl[1]), rrmoved); + /* Save rr_moved. */ + *rr_moved = rrmoved; + } + /* + * Make a clone of curent which is going to be relocated + * to rr_moved. + */ + mvent = isoent_clone(curent); + if (mvent == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + /* linking.. and use for creating "CL", "PL" and "RE" */ + mvent->rr_parent = curent->parent; + curent->rr_child = mvent; + /* + * Move subdirectories from the curent to mvent + */ + if (curent->children.first != NULL) { + *mvent->children.last = curent->children.first; + mvent->children.last = curent->children.last; + } + for (np = mvent->children.first; np != NULL; np = np->chnext) + np->parent = mvent; + mvent->children.cnt = curent->children.cnt; + curent->children.cnt = 0; + curent->children.first = NULL; + curent->children.last = &curent->children.first; + + if (curent->subdirs.first != NULL) { + *mvent->subdirs.last = curent->subdirs.first; + mvent->subdirs.last = curent->subdirs.last; + } + mvent->subdirs.cnt = curent->subdirs.cnt; + curent->subdirs.cnt = 0; + curent->subdirs.first = NULL; + curent->subdirs.last = &curent->subdirs.first; + + /* + * The mvent becomes a child of the rr_moved entry. + */ + isoent_add_child_tail(rrmoved, mvent); + archive_entry_set_nlink(rrmoved->file->entry, + archive_entry_nlink(rrmoved->file->entry) + 1); + /* + * This entry which relocated to the rr_moved directory + * has to set the flag as a file. + * See also RRIP 4.1.5.1 Description of the "CL" System Use Entry. + */ + curent->dir = 0; + + *newent = mvent; + + return (ARCHIVE_OK); +} + +static int +isoent_rr_move(struct archive_write *a) +{ + struct iso9660 *iso9660 = a->format_data; + struct path_table *pt; + struct isoent *rootent, *rr_moved; + struct isoent *np, *last; + int r; + + pt = &(iso9660->primary.pathtbl[MAX_DEPTH-1]); - /* Theare aren't level 8 directories reaching a deepr level. */ ++ /* There aren't level 8 directories reaching a deeper level. */ + if (pt->cnt == 0) + return (ARCHIVE_OK); + + rootent = iso9660->primary.rootent; + /* If "rr_moved" directory is already existing, + * we have to use it. */ + rr_moved = isoent_find_child(rootent, "rr_moved"); + if (rr_moved != NULL && + rr_moved != rootent->children.first) { + /* + * It's necessary that rr_move is the first entry + * of the root. + */ + /* Remove "rr_moved" entry from children chain. */ + isoent_remove_child(rootent, rr_moved); + + /* Add "rr_moved" entry into the head of children chain. */ + isoent_add_child_head(rootent, rr_moved); + } + + /* + * Check level 8 path_table. + * If find out sub directory entries, that entries move to rr_move. + */ + np = pt->first; + while (np != NULL) { + last = path_table_last_entry(pt); + for (; np != NULL; np = np->ptnext) { + struct isoent *mvent; + struct isoent *newent; + + if (!np->dir) + continue; + for (mvent = np->subdirs.first; + mvent != NULL; mvent = mvent->drnext) { + r = isoent_rr_move_dir(a, &rr_moved, + mvent, &newent); + if (r < 0) + return (r); + isoent_collect_dirs(&(iso9660->primary), + newent, 2); + } + } + /* If new entries are added to level 8 path_talbe, + * its sub directory entries move to rr_move too. + */ + np = last->ptnext; + } + + return (ARCHIVE_OK); +} + +/* + * This comparing rule is according to ISO9660 Standard 6.9.1 + */ +static int +_compare_path_table(const void *v1, const void *v2) +{ + const struct isoent *p1, *p2; + const char *s1, *s2; + int cmp, l; + + p1 = *((const struct isoent **)(uintptr_t)v1); + p2 = *((const struct isoent **)(uintptr_t)v2); + + /* Compare parent directory number */ + cmp = p1->parent->dir_number - p2->parent->dir_number; + if (cmp != 0) + return (cmp); + - /* Compare indetifier */ ++ /* Compare identifier */ + s1 = p1->identifier; + s2 = p2->identifier; + l = p1->ext_off; + if (l > p2->ext_off) + l = p2->ext_off; + cmp = strncmp(s1, s2, l); + if (cmp != 0) + return (cmp); + if (p1->ext_off < p2->ext_off) { + s2 += l; + l = p2->ext_off - p1->ext_off; + while (l--) + if (0x20 != *s2++) + return (0x20 + - *(const unsigned char *)(s2 - 1)); + } else if (p1->ext_off > p2->ext_off) { + s1 += l; + l = p1->ext_off - p2->ext_off; + while (l--) + if (0x20 != *s1++) + return (*(const unsigned char *)(s1 - 1) + - 0x20); + } + return (0); +} + +static int +_compare_path_table_joliet(const void *v1, const void *v2) +{ + const struct isoent *p1, *p2; + const unsigned char *s1, *s2; + int cmp, l; + + p1 = *((const struct isoent **)(uintptr_t)v1); + p2 = *((const struct isoent **)(uintptr_t)v2); + + /* Compare parent directory number */ + cmp = p1->parent->dir_number - p2->parent->dir_number; + if (cmp != 0) + return (cmp); + - /* Compare indetifier */ ++ /* Compare identifier */ + s1 = (const unsigned char *)p1->identifier; + s2 = (const unsigned char *)p2->identifier; + l = p1->ext_off; + if (l > p2->ext_off) + l = p2->ext_off; + cmp = memcmp(s1, s2, l); + if (cmp != 0) + return (cmp); + if (p1->ext_off < p2->ext_off) { + s2 += l; + l = p2->ext_off - p1->ext_off; + while (l--) + if (0 != *s2++) + return (- *(const unsigned char *)(s2 - 1)); + } else if (p1->ext_off > p2->ext_off) { + s1 += l; + l = p1->ext_off - p2->ext_off; + while (l--) + if (0 != *s1++) + return (*(const unsigned char *)(s1 - 1)); + } + return (0); +} + +static inline void +path_table_add_entry(struct path_table *pathtbl, struct isoent *ent) +{ + ent->ptnext = NULL; + *pathtbl->last = ent; + pathtbl->last = &(ent->ptnext); + pathtbl->cnt ++; +} + +static inline struct isoent * +path_table_last_entry(struct path_table *pathtbl) +{ + if (pathtbl->first == NULL) + return (NULL); + return (((struct isoent *)(void *) + ((char *)(pathtbl->last) - offsetof(struct isoent, ptnext)))); +} + +/* + * Sort directory entries in path_table + * and assign directory number to each entries. + */ +static int +isoent_make_path_table_2(struct archive_write *a, struct vdd *vdd, + int depth, int *dir_number) +{ + struct isoent *np; + struct isoent **enttbl; + struct path_table *pt; + int i; + + pt = &vdd->pathtbl[depth]; + if (pt->cnt == 0) { + pt->sorted = NULL; + return (ARCHIVE_OK); + } + enttbl = malloc(pt->cnt * sizeof(struct isoent *)); + if (enttbl == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + pt->sorted = enttbl; + for (np = pt->first; np != NULL; np = np->ptnext) + *enttbl ++ = np; + enttbl = pt->sorted; + + switch (vdd->vdd_type) { + case VDD_PRIMARY: + case VDD_ENHANCED: +#ifdef __COMPAR_FN_T + qsort(enttbl, pt->cnt, sizeof(struct isoent *), + (__compar_fn_t)_compare_path_table); +#else + qsort(enttbl, pt->cnt, sizeof(struct isoent *), + _compare_path_table); +#endif + break; + case VDD_JOLIET: +#ifdef __COMPAR_FN_T + qsort(enttbl, pt->cnt, sizeof(struct isoent *), + (__compar_fn_t)_compare_path_table_joliet); +#else + qsort(enttbl, pt->cnt, sizeof(struct isoent *), + _compare_path_table_joliet); +#endif + break; + } + for (i = 0; i < pt->cnt; i++) + enttbl[i]->dir_number = (*dir_number)++; + + return (ARCHIVE_OK); +} + +static int +isoent_alloc_path_table(struct archive_write *a, struct vdd *vdd, + int max_depth) +{ + int i; + + vdd->max_depth = max_depth; + vdd->pathtbl = malloc(sizeof(*vdd->pathtbl) * vdd->max_depth); + if (vdd->pathtbl == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + for (i = 0; i < vdd->max_depth; i++) { + vdd->pathtbl[i].first = NULL; + vdd->pathtbl[i].last = &(vdd->pathtbl[i].first); + vdd->pathtbl[i].sorted = NULL; + vdd->pathtbl[i].cnt = 0; + } + return (ARCHIVE_OK); +} + +/* + * Make Path Tables + */ +static int +isoent_make_path_table(struct archive_write *a) +{ + struct iso9660 *iso9660 = a->format_data; + int depth, r; + int dir_number; + + /* + * Init Path Table. + */ + if (iso9660->dircnt_max >= MAX_DEPTH && + (!iso9660->opt.limit_depth || iso9660->opt.iso_level == 4)) + r = isoent_alloc_path_table(a, &(iso9660->primary), + iso9660->dircnt_max + 1); + else + /* The number of levels in the hierarchy cannot exceed + * eight. */ + r = isoent_alloc_path_table(a, &(iso9660->primary), + MAX_DEPTH); + if (r < 0) + return (r); + if (iso9660->opt.joliet) { + r = isoent_alloc_path_table(a, &(iso9660->joliet), + iso9660->dircnt_max + 1); + if (r < 0) + return (r); + } + + /* Step 0. + * - Collect directories for primary and joliet. + */ + isoent_collect_dirs(&(iso9660->primary), NULL, 0); + if (iso9660->opt.joliet) + isoent_collect_dirs(&(iso9660->joliet), NULL, 0); + /* + * Rockridge; move deeper depth directories to rr_moved. + */ + if (iso9660->opt.rr) { + r = isoent_rr_move(a); + if (r < 0) + return (r); + } + + /* Update nlink. */ + isofile_connect_hardlink_files(iso9660); + + /* Step 1. + * - Renew a value of the depth of that directories. + * - Resolve hardlinks. + * - Convert pathnames to ISO9660 name or UCS2(joliet). + * - Sort files by each directory. + */ + r = isoent_traverse_tree(a, &(iso9660->primary)); + if (r < 0) + return (r); + if (iso9660->opt.joliet) { + r = isoent_traverse_tree(a, &(iso9660->joliet)); + if (r < 0) + return (r); + } + + /* Step 2. + * - Sort directories. + * - Assign all directory number. + */ + dir_number = 1; + for (depth = 0; depth < iso9660->primary.max_depth; depth++) { + r = isoent_make_path_table_2(a, &(iso9660->primary), + depth, &dir_number); + if (r < 0) + return (r); + } + if (iso9660->opt.joliet) { + dir_number = 1; + for (depth = 0; depth < iso9660->joliet.max_depth; depth++) { + r = isoent_make_path_table_2(a, &(iso9660->joliet), + depth, &dir_number); + if (r < 0) + return (r); + } + } + if (iso9660->opt.limit_dirs && dir_number > 0xffff) { + /* + * Maximum number of directories is 65535(0xffff) + * doe to size(16bit) of Parent Directory Number of + * the Path Table. + * See also ISO9660 Standard 9.4. + */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Too many directories(%d) over 65535.", dir_number); + return (ARCHIVE_FATAL); + } + + /* Get the size of the Path Table. */ + calculate_path_table_size(&(iso9660->primary)); + if (iso9660->opt.joliet) + calculate_path_table_size(&(iso9660->joliet)); + + return (ARCHIVE_OK); +} + +static int +isoent_find_out_boot_file(struct archive_write *a, struct isoent *rootent) +{ + struct iso9660 *iso9660 = a->format_data; + + /* Find a isoent of the boot file. */ + iso9660->el_torito.boot = isoent_find_entry(rootent, + iso9660->el_torito.boot_filename.s); + if (iso9660->el_torito.boot == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can't find the boot image file ``%s''", + iso9660->el_torito.boot_filename.s); + return (ARCHIVE_FATAL); + } + iso9660->el_torito.boot->file->boot = BOOT_IMAGE; + return (ARCHIVE_OK); +} + +static int +isoent_create_boot_catalog(struct archive_write *a, struct isoent *rootent) +{ + struct iso9660 *iso9660 = a->format_data; + struct isofile *file; + struct isoent *isoent; + struct archive_entry *entry; + + (void)rootent; /* UNUSED */ + /* + * Create the entry which is the "boot.catalog" file. + */ + file = isofile_new(a, NULL); + if (file == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + archive_entry_set_pathname(file->entry, + iso9660->el_torito.catalog_filename.s); + archive_entry_set_size(file->entry, LOGICAL_BLOCK_SIZE); + archive_entry_set_mtime(file->entry, iso9660->birth_time, 0); + archive_entry_set_atime(file->entry, iso9660->birth_time, 0); + archive_entry_set_ctime(file->entry, iso9660->birth_time, 0); + archive_entry_set_uid(file->entry, getuid()); + archive_entry_set_gid(file->entry, getgid()); + archive_entry_set_mode(file->entry, AE_IFREG | 0444); + archive_entry_set_nlink(file->entry, 1); + + if (isofile_gen_utility_names(a, file) < ARCHIVE_WARN) { + isofile_free(file); + return (ARCHIVE_FATAL); + } + file->boot = BOOT_CATALOG; + file->content.size = LOGICAL_BLOCK_SIZE; + isofile_add_entry(iso9660, file); + + isoent = isoent_new(file); + if (isoent == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + isoent->virtual = 1; + + /* Add the "boot.catalog" entry into tree */ + if (isoent_tree(a, &isoent) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + iso9660->el_torito.catalog = isoent; + /* - * Get a boot medai type. ++ * Get a boot media type. + */ + switch (iso9660->opt.boot_type) { + default: + case OPT_BOOT_TYPE_AUTO: + /* Try detecting a media type of the boot image. */ + entry = iso9660->el_torito.boot->file->entry; + if (archive_entry_size(entry) == FD_1_2M_SIZE) + iso9660->el_torito.media_type = + BOOT_MEDIA_1_2M_DISKETTE; + else if (archive_entry_size(entry) == FD_1_44M_SIZE) + iso9660->el_torito.media_type = + BOOT_MEDIA_1_44M_DISKETTE; + else if (archive_entry_size(entry) == FD_2_88M_SIZE) + iso9660->el_torito.media_type = + BOOT_MEDIA_2_88M_DISKETTE; + else + /* We cannot decide whether the boot image is + * hard-disk. */ + iso9660->el_torito.media_type = + BOOT_MEDIA_NO_EMULATION; + break; + case OPT_BOOT_TYPE_NO_EMU: + iso9660->el_torito.media_type = BOOT_MEDIA_NO_EMULATION; + break; + case OPT_BOOT_TYPE_HARD_DISK: + iso9660->el_torito.media_type = BOOT_MEDIA_HARD_DISK; + break; + case OPT_BOOT_TYPE_FD: + entry = iso9660->el_torito.boot->file->entry; + if (archive_entry_size(entry) <= FD_1_2M_SIZE) + iso9660->el_torito.media_type = + BOOT_MEDIA_1_2M_DISKETTE; + else if (archive_entry_size(entry) <= FD_1_44M_SIZE) + iso9660->el_torito.media_type = + BOOT_MEDIA_1_44M_DISKETTE; + else if (archive_entry_size(entry) <= FD_2_88M_SIZE) + iso9660->el_torito.media_type = + BOOT_MEDIA_2_88M_DISKETTE; + else { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Boot image file(``%s'') size is too big " + "for fd type.", + iso9660->el_torito.boot_filename.s); + return (ARCHIVE_FATAL); + } + break; + } + + /* + * Get a system type. + * TODO: `El Torito' specification says "A copy of byte 5 from the + * Partition Table found in the boot image". + */ + iso9660->el_torito.system_type = 0; + + /* + * Get an ID. + */ + if (iso9660->opt.publisher) + archive_string_copy(&(iso9660->el_torito.id), + &(iso9660->publisher_identifier)); + + + return (ARCHIVE_OK); +} + +/* + * If a media type is floppy, return its image size. + * otherwise return 0. + */ +static size_t +fd_boot_image_size(int media_type) +{ + switch (media_type) { + case BOOT_MEDIA_1_2M_DISKETTE: + return (FD_1_2M_SIZE); + case BOOT_MEDIA_1_44M_DISKETTE: + return (FD_1_44M_SIZE); + case BOOT_MEDIA_2_88M_DISKETTE: + return (FD_2_88M_SIZE); + default: + return (0); + } +} + +/* + * Make a boot catalog image data. + */ +static int +make_boot_catalog(struct archive_write *a) +{ + struct iso9660 *iso9660 = a->format_data; + unsigned char *block; + unsigned char *p; + uint16_t sum, *wp; + + block = wb_buffptr(a); + memset(block, 0, LOGICAL_BLOCK_SIZE); + p = block; + /* + * Validation Entry + */ + /* Header ID */ + p[0] = 1; + /* Platform ID */ + p[1] = iso9660->el_torito.platform_id; + /* Reserved */ + p[2] = p[3] = 0; + /* ID */ + if (archive_strlen(&(iso9660->el_torito.id)) > 0) + strncpy((char *)p+4, iso9660->el_torito.id.s, 23); + p[27] = 0; + /* Checksum */ + p[28] = p[29] = 0; + /* Key */ + p[30] = 0x55; + p[31] = 0xAA; + + sum = 0; + wp = (uint16_t *)block; + while (wp < (uint16_t *)&block[32]) + sum += archive_le16dec(wp++); + set_num_721(&block[28], (~sum) + 1); + + /* + * Initial/Default Entry + */ + p = &block[32]; + /* Boot Indicator */ + p[0] = 0x88; + /* Boot media type */ + p[1] = iso9660->el_torito.media_type; + /* Load Segment */ + if (iso9660->el_torito.media_type == BOOT_MEDIA_NO_EMULATION) + set_num_721(&p[2], iso9660->el_torito.boot_load_seg); + else + set_num_721(&p[2], 0); + /* System Type */ + p[4] = iso9660->el_torito.system_type; + /* Unused */ + p[5] = 0; + /* Sector Count */ + if (iso9660->el_torito.media_type == BOOT_MEDIA_NO_EMULATION) + set_num_721(&p[6], iso9660->el_torito.boot_load_size); + else + set_num_721(&p[6], 1); + /* Load RBA */ + set_num_731(&p[8], + iso9660->el_torito.boot->file->content.location); + /* Unused */ + memset(&p[12], 0, 20); + + return (wb_consume(a, LOGICAL_BLOCK_SIZE)); +} + +static int +setup_boot_information(struct archive_write *a) +{ + struct iso9660 *iso9660 = a->format_data; + struct isoent *np; + int64_t size; + uint32_t sum; + unsigned char buff[4096]; + + np = iso9660->el_torito.boot; + lseek(iso9660->temp_fd, + np->file->content.offset_of_temp + 64, SEEK_SET); + size = archive_entry_size(np->file->entry) - 64; + if (size <= 0) { + archive_set_error(&a->archive, errno, + "Boot file(%jd) is too small", (intmax_t)size + 64); + return (ARCHIVE_FATAL); + } + sum = 0; + while (size > 0) { + size_t rsize; + ssize_t i, rs; + + if (size > (int64_t)sizeof(buff)) + rsize = sizeof(buff); + else + rsize = (size_t)size; + + rs = read(iso9660->temp_fd, buff, rsize); + if (rs <= 0) { + archive_set_error(&a->archive, errno, + "Can't read temporary file(%jd)", + (intmax_t)rs); + return (ARCHIVE_FATAL); + } + for (i = 0; i < rs; i += 4) + sum += archive_le32dec(buff + i); + size -= rs; + } + /* Set the location of Primary Volume Descriptor. */ + set_num_731(buff, SYSTEM_AREA_BLOCK); + /* Set the location of the boot file. */ + set_num_731(buff+4, np->file->content.location); + /* Set the size of the boot file. */ + size = fd_boot_image_size(iso9660->el_torito.media_type); + if (size == 0) + size = archive_entry_size(np->file->entry); + set_num_731(buff+8, (uint32_t)size); + /* Set the sum of the boot file. */ + set_num_731(buff+12, sum); + /* Clear reserved bytes. */ + memset(buff+16, 0, 40); + + /* Overwrite the boot file. */ + lseek(iso9660->temp_fd, + np->file->content.offset_of_temp + 8, SEEK_SET); + return (write_to_temp(a, buff, 56)); +} + +#ifdef HAVE_ZLIB_H + +static int +zisofs_init_zstream(struct archive_write *a) +{ + struct iso9660 *iso9660 = a->format_data; + int r; + + iso9660->zisofs.stream.next_in = NULL; + iso9660->zisofs.stream.avail_in = 0; + iso9660->zisofs.stream.total_in = 0; + iso9660->zisofs.stream.total_out = 0; + if (iso9660->zisofs.stream_valid) + r = deflateReset(&(iso9660->zisofs.stream)); + else { + r = deflateInit(&(iso9660->zisofs.stream), + iso9660->zisofs.compression_level); + iso9660->zisofs.stream_valid = 1; + } + switch (r) { + case Z_OK: + break; + default: + case Z_STREAM_ERROR: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Internal error initializing " + "compression library: invalid setup parameter"); + return (ARCHIVE_FATAL); + case Z_MEM_ERROR: + archive_set_error(&a->archive, ENOMEM, + "Internal error initializing " + "compression library"); + return (ARCHIVE_FATAL); + case Z_VERSION_ERROR: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Internal error initializing " + "compression library: invalid library version"); + return (ARCHIVE_FATAL); + } + return (ARCHIVE_OK); +} + +#endif /* HAVE_ZLIB_H */ + +static int +zisofs_init(struct archive_write *a, struct isofile *file) +{ + struct iso9660 *iso9660 = a->format_data; +#ifdef HAVE_ZLIB_H + uint64_t tsize; + size_t _ceil, bpsize; + int r; +#endif + + iso9660->zisofs.detect_magic = 0; + iso9660->zisofs.making = 0; + + if (!iso9660->opt.rr || !iso9660->opt.zisofs) + return (ARCHIVE_OK); + + if (archive_entry_size(file->entry) >= 24 && + archive_entry_size(file->entry) < MULTI_EXTENT_SIZE) { + /* Acceptable file size for zisofs. */ + iso9660->zisofs.detect_magic = 1; + iso9660->zisofs.magic_cnt = 0; + } + if (!iso9660->zisofs.detect_magic) + return (ARCHIVE_OK); + +#ifdef HAVE_ZLIB_H + /* The number of Logical Blocks which uncompressed data + * will use in iso-image file is the same as the number of + * Logical Blocks which zisofs(compressed) data will use + * in ISO-image file. It won't reduce iso-image file size. */ + if (archive_entry_size(file->entry) <= LOGICAL_BLOCK_SIZE) + return (ARCHIVE_OK); + + /* Initialize compression library */ + r = zisofs_init_zstream(a); + if (r != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* Mark file->zisofs to create RRIP 'ZF' Use Entry. */ + file->zisofs.header_size = ZF_HEADER_SIZE >> 2; + file->zisofs.log2_bs = ZF_LOG2_BS; + file->zisofs.uncompressed_size = + (uint32_t)archive_entry_size(file->entry); + + /* Calculate a size of Block Pointers of zisofs. */ + _ceil = (file->zisofs.uncompressed_size + ZF_BLOCK_SIZE -1) + >> file->zisofs.log2_bs; + iso9660->zisofs.block_pointers_cnt = (int)_ceil + 1; + iso9660->zisofs.block_pointers_idx = 0; + + /* Ensure a buffer size used for Block Pointers */ + bpsize = iso9660->zisofs.block_pointers_cnt * + sizeof(iso9660->zisofs.block_pointers[0]); + if (iso9660->zisofs.block_pointers_allocated < bpsize) { + free(iso9660->zisofs.block_pointers); + iso9660->zisofs.block_pointers = malloc(bpsize); + if (iso9660->zisofs.block_pointers == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate data"); + return (ARCHIVE_FATAL); + } + iso9660->zisofs.block_pointers_allocated = bpsize; + } + + /* + * Skip zisofs header and Block Pointers, which we will write + * after all compressed data of a file written to the temporary + * file. + */ + tsize = ZF_HEADER_SIZE + bpsize; + if (write_null(a, (size_t)tsize) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* + * Initialize some variables to make zisofs. + */ + archive_le32enc(&(iso9660->zisofs.block_pointers[0]), + (uint32_t)tsize); + iso9660->zisofs.remaining = file->zisofs.uncompressed_size; + iso9660->zisofs.making = 1; + iso9660->zisofs.allzero = 1; + iso9660->zisofs.block_offset = tsize; + iso9660->zisofs.total_size = tsize; + iso9660->cur_file->cur_content->size = tsize; +#endif + + return (ARCHIVE_OK); +} + +static void +zisofs_detect_magic(struct archive_write *a, const void *buff, size_t s) +{ + struct iso9660 *iso9660 = a->format_data; + struct isofile *file = iso9660->cur_file; + const unsigned char *p, *endp; + const unsigned char *magic_buff; + uint32_t uncompressed_size; + unsigned char header_size; + unsigned char log2_bs; + size_t _ceil, doff; + uint32_t bst, bed; + int magic_max; + int64_t entry_size; + + entry_size = archive_entry_size(file->entry); + if ((int64_t)sizeof(iso9660->zisofs.magic_buffer) > entry_size) + magic_max = (int)entry_size; + else + magic_max = sizeof(iso9660->zisofs.magic_buffer); + + if (iso9660->zisofs.magic_cnt == 0 && s >= (size_t)magic_max) + /* It's unnecessary we copy buffer. */ + magic_buff = buff; + else { + if (iso9660->zisofs.magic_cnt < magic_max) { + size_t l; + + l = sizeof(iso9660->zisofs.magic_buffer) + - iso9660->zisofs.magic_cnt; + if (l > s) + l = s; + memcpy(iso9660->zisofs.magic_buffer + + iso9660->zisofs.magic_cnt, buff, l); + iso9660->zisofs.magic_cnt += (int)l; + if (iso9660->zisofs.magic_cnt < magic_max) + return; + } + magic_buff = iso9660->zisofs.magic_buffer; + } + iso9660->zisofs.detect_magic = 0; + p = magic_buff; + + /* Check the magic code of zisofs. */ + if (memcmp(p, zisofs_magic, sizeof(zisofs_magic)) != 0) + /* This is not zisofs file which made by mkzftree. */ + return; + p += sizeof(zisofs_magic); + + /* Read a zisofs header. */ + uncompressed_size = archive_le32dec(p); + header_size = p[4]; + log2_bs = p[5]; + if (uncompressed_size < 24 || header_size != 4 || + log2_bs > 30 || log2_bs < 7) + return;/* Invalid or not supported header. */ + + /* Calculate a size of Block Pointers of zisofs. */ + _ceil = (uncompressed_size + + (ARCHIVE_LITERAL_LL(1) << log2_bs) -1) >> log2_bs; + doff = (_ceil + 1) * 4 + 16; + if (entry_size < (int64_t)doff) + return;/* Invalid data. */ + + /* Check every Block Pointer has valid value. */ + p = magic_buff + 16; + endp = magic_buff + magic_max; + while (_ceil && p + 8 <= endp) { + bst = archive_le32dec(p); + if (bst != doff) + return;/* Invalid data. */ + p += 4; + bed = archive_le32dec(p); + if (bed < bst || bed > entry_size) + return;/* Invalid data. */ + doff += bed - bst; + _ceil--; + } + + file->zisofs.uncompressed_size = uncompressed_size; + file->zisofs.header_size = header_size; + file->zisofs.log2_bs = log2_bs; + + /* Disable making a zisofs image. */ + iso9660->zisofs.making = 0; +} + +#ifdef HAVE_ZLIB_H + +/* + * Compress data and write it to a temporary file. + */ +static int +zisofs_write_to_temp(struct archive_write *a, const void *buff, size_t s) +{ + struct iso9660 *iso9660 = a->format_data; + struct isofile *file = iso9660->cur_file; + const unsigned char *b; + z_stream *zstrm; + size_t avail, csize; + int flush, r; + + zstrm = &(iso9660->zisofs.stream); + zstrm->next_out = wb_buffptr(a); + zstrm->avail_out = (uInt)wb_remaining(a); + b = (const unsigned char *)buff; + do { + avail = ZF_BLOCK_SIZE - zstrm->total_in; + if (s < avail) { + avail = s; + flush = Z_NO_FLUSH; + } else + flush = Z_FINISH; + iso9660->zisofs.remaining -= avail; + if (iso9660->zisofs.remaining <= 0) + flush = Z_FINISH; + + zstrm->next_in = (Bytef *)(uintptr_t)(const void *)b; + zstrm->avail_in = (uInt)avail; + + /* + * Check if current data block are all zero. + */ + if (iso9660->zisofs.allzero) { + const unsigned char *nonzero = b; + const unsigned char *nonzeroend = b + avail; + + while (nonzero < nonzeroend) + if (*nonzero++) { + iso9660->zisofs.allzero = 0; + break; + } + } + b += avail; + s -= avail; + + /* + * If current data block are all zero, we do not use + * compressed data. + */ + if (flush == Z_FINISH && iso9660->zisofs.allzero && + avail + zstrm->total_in == ZF_BLOCK_SIZE) { + if (iso9660->zisofs.block_offset != + file->cur_content->size) { + int64_t diff; + + r = wb_set_offset(a, + file->cur_content->offset_of_temp + + iso9660->zisofs.block_offset); + if (r != ARCHIVE_OK) + return (r); + diff = file->cur_content->size - + iso9660->zisofs.block_offset; + file->cur_content->size -= diff; + iso9660->zisofs.total_size -= diff; + } + zstrm->avail_in = 0; + } + + /* + * Compress file data. + */ + while (zstrm->avail_in > 0) { + csize = zstrm->total_out; + r = deflate(zstrm, flush); + switch (r) { + case Z_OK: + case Z_STREAM_END: + csize = zstrm->total_out - csize; + if (wb_consume(a, csize) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + iso9660->zisofs.total_size += csize; + iso9660->cur_file->cur_content->size += csize; + zstrm->next_out = wb_buffptr(a); + zstrm->avail_out = (uInt)wb_remaining(a); + break; + default: + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Compression failed:" + " deflate() call returned status %d", + r); + return (ARCHIVE_FATAL); + } + } + + if (flush == Z_FINISH) { + /* + * Save the information of one zisofs block. + */ + iso9660->zisofs.block_pointers_idx ++; + archive_le32enc(&(iso9660->zisofs.block_pointers[ + iso9660->zisofs.block_pointers_idx]), + (uint32_t)iso9660->zisofs.total_size); + r = zisofs_init_zstream(a); + if (r != ARCHIVE_OK) + return (ARCHIVE_FATAL); + iso9660->zisofs.allzero = 1; + iso9660->zisofs.block_offset = file->cur_content->size; + } + } while (s); + + return (ARCHIVE_OK); +} + +static int +zisofs_finish_entry(struct archive_write *a) +{ + struct iso9660 *iso9660 = a->format_data; + struct isofile *file = iso9660->cur_file; + unsigned char buff[16]; + size_t s; + int64_t tail; + + /* Direct temp file stream to zisofs temp file stream. */ + archive_entry_set_size(file->entry, iso9660->zisofs.total_size); + + /* + * Save a file pointer which points the end of current zisofs data. + */ + tail = wb_offset(a); + + /* + * Make a header. + * + * +-----------------+----------------+-----------------+ + * | Header 16 bytes | Block Pointers | Compressed data | + * +-----------------+----------------+-----------------+ + * 0 16 +X + * Block Pointers : + * 4 * (((Uncompressed file size + block_size -1) / block_size) + 1) + * + * Write zisofs header. + * Magic number + * +----+----+----+----+----+----+----+----+ + * | 37 | E4 | 53 | 96 | C9 | DB | D6 | 07 | + * +----+----+----+----+----+----+----+----+ + * 0 1 2 3 4 5 6 7 8 + * + * +------------------------+------------------+ + * | Uncompressed file size | header_size >> 2 | + * +------------------------+------------------+ + * 8 12 13 + * + * +-----------------+----------------+ + * | log2 block_size | Reserved(0000) | + * +-----------------+----------------+ + * 13 14 16 + */ + memcpy(buff, zisofs_magic, 8); + set_num_731(buff+8, file->zisofs.uncompressed_size); + buff[12] = file->zisofs.header_size; + buff[13] = file->zisofs.log2_bs; + buff[14] = buff[15] = 0;/* Reserved */ + + /* Move to the right position to write the header. */ + wb_set_offset(a, file->content.offset_of_temp); + + /* Write the header. */ + if (wb_write_to_temp(a, buff, 16) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* + * Write zisofs Block Pointers. + */ + s = iso9660->zisofs.block_pointers_cnt * + sizeof(iso9660->zisofs.block_pointers[0]); + if (wb_write_to_temp(a, iso9660->zisofs.block_pointers, s) + != ARCHIVE_OK) + return (ARCHIVE_FATAL); + + /* Set a file pointer back to the end of the temporary file. */ + wb_set_offset(a, tail); + + return (ARCHIVE_OK); +} + +static int +zisofs_free(struct archive_write *a) +{ + struct iso9660 *iso9660 = a->format_data; + int ret = ARCHIVE_OK; + + free(iso9660->zisofs.block_pointers); + if (iso9660->zisofs.stream_valid && + deflateEnd(&(iso9660->zisofs.stream)) != Z_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to clean up compressor"); + ret = ARCHIVE_FATAL; + } + iso9660->zisofs.block_pointers = NULL; + iso9660->zisofs.stream_valid = 0; + return (ret); +} + +struct zisofs_extract { + int pz_log2_bs; /* Log2 of block size */ + uint64_t pz_uncompressed_size; + size_t uncompressed_buffer_size; + + int initialized:1; + int header_passed:1; + + uint32_t pz_offset; + unsigned char *block_pointers; + size_t block_pointers_size; + size_t block_pointers_avail; + size_t block_off; + uint32_t block_avail; + + z_stream stream; + int stream_valid; +}; + +static ssize_t +zisofs_extract_init(struct archive_write *a, struct zisofs_extract *zisofs, + const unsigned char *p, size_t bytes) +{ + size_t avail = bytes; + size_t _ceil, xsize; + + /* Allocate block pointers buffer. */ + _ceil = (size_t)((zisofs->pz_uncompressed_size + + (((int64_t)1) << zisofs->pz_log2_bs) - 1) + >> zisofs->pz_log2_bs); + xsize = (_ceil + 1) * 4; + if (zisofs->block_pointers == NULL) { + size_t alloc = ((xsize >> 10) + 1) << 10; + zisofs->block_pointers = malloc(alloc); + if (zisofs->block_pointers == NULL) { + archive_set_error(&a->archive, ENOMEM, + "No memory for zisofs decompression"); + return (ARCHIVE_FATAL); + } + } + zisofs->block_pointers_size = xsize; + + /* Allocate uncompressed data buffer. */ + zisofs->uncompressed_buffer_size = (size_t)1UL << zisofs->pz_log2_bs; + + /* + * Read the file header, and check the magic code of zisofs. + */ + if (!zisofs->header_passed) { + int err = 0; + if (avail < 16) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Illegal zisofs file body"); + return (ARCHIVE_FATAL); + } + + if (memcmp(p, zisofs_magic, sizeof(zisofs_magic)) != 0) + err = 1; + else if (archive_le32dec(p + 8) != zisofs->pz_uncompressed_size) + err = 1; + else if (p[12] != 4 || p[13] != zisofs->pz_log2_bs) + err = 1; + if (err) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Illegal zisofs file body"); + return (ARCHIVE_FATAL); + } + avail -= 16; + p += 16; + zisofs->header_passed = 1; + } + + /* + * Read block pointers. + */ + if (zisofs->header_passed && + zisofs->block_pointers_avail < zisofs->block_pointers_size) { + xsize = zisofs->block_pointers_size + - zisofs->block_pointers_avail; + if (avail < xsize) + xsize = avail; + memcpy(zisofs->block_pointers + + zisofs->block_pointers_avail, p, xsize); + zisofs->block_pointers_avail += xsize; + avail -= xsize; + if (zisofs->block_pointers_avail + == zisofs->block_pointers_size) { + /* We've got all block pointers and initialize + * related variables. */ + zisofs->block_off = 0; + zisofs->block_avail = 0; + /* Complete a initialization */ + zisofs->initialized = 1; + } + } + return ((ssize_t)avail); +} + +static ssize_t +zisofs_extract(struct archive_write *a, struct zisofs_extract *zisofs, + const unsigned char *p, size_t bytes) +{ + size_t avail; + int r; + + if (!zisofs->initialized) { + ssize_t rs = zisofs_extract_init(a, zisofs, p, bytes); + if (rs < 0) + return (rs); + if (!zisofs->initialized) { + /* We need more data. */ + zisofs->pz_offset += (uint32_t)bytes; + return (bytes); + } + avail = rs; + p += bytes - avail; + } else + avail = bytes; + + /* + * Get block offsets from block pointers. + */ + if (zisofs->block_avail == 0) { + uint32_t bst, bed; + + if (zisofs->block_off + 4 >= zisofs->block_pointers_size) { + /* There isn't a pair of offsets. */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Illegal zisofs block pointers"); + return (ARCHIVE_FATAL); + } + bst = archive_le32dec( + zisofs->block_pointers + zisofs->block_off); + if (bst != zisofs->pz_offset + (bytes - avail)) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Illegal zisofs block pointers(cannot seek)"); + return (ARCHIVE_FATAL); + } + bed = archive_le32dec( + zisofs->block_pointers + zisofs->block_off + 4); + if (bed < bst) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Illegal zisofs block pointers"); + return (ARCHIVE_FATAL); + } + zisofs->block_avail = bed - bst; + zisofs->block_off += 4; + + /* Initialize compression library for new block. */ + if (zisofs->stream_valid) + r = inflateReset(&zisofs->stream); + else + r = inflateInit(&zisofs->stream); + if (r != Z_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can't initialize zisofs decompression."); + return (ARCHIVE_FATAL); + } + zisofs->stream_valid = 1; + zisofs->stream.total_in = 0; + zisofs->stream.total_out = 0; + } + + /* + * Make uncompressed data. + */ + if (zisofs->block_avail == 0) { + /* + * It's basically 32K bytes NUL data. + */ + unsigned char *wb; + size_t size, wsize; + + size = zisofs->uncompressed_buffer_size; + while (size) { + wb = wb_buffptr(a); + if (size > wb_remaining(a)) + wsize = wb_remaining(a); + else + wsize = size; + memset(wb, 0, wsize); + r = wb_consume(a, wsize); + if (r < 0) + return (r); + size -= wsize; + } + } else { + zisofs->stream.next_in = (Bytef *)(uintptr_t)(const void *)p; + if (avail > zisofs->block_avail) + zisofs->stream.avail_in = zisofs->block_avail; + else + zisofs->stream.avail_in = (uInt)avail; + zisofs->stream.next_out = wb_buffptr(a); + zisofs->stream.avail_out = (uInt)wb_remaining(a); + + r = inflate(&zisofs->stream, 0); + switch (r) { + case Z_OK: /* Decompressor made some progress.*/ + case Z_STREAM_END: /* Found end of stream. */ + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "zisofs decompression failed (%d)", r); + return (ARCHIVE_FATAL); + } + avail -= zisofs->stream.next_in - p; + zisofs->block_avail -= (uint32_t)(zisofs->stream.next_in - p); + r = wb_consume(a, wb_remaining(a) - zisofs->stream.avail_out); + if (r < 0) + return (r); + } + zisofs->pz_offset += (uint32_t)bytes; + return (bytes - avail); +} + +static int +zisofs_rewind_boot_file(struct archive_write *a) +{ + struct iso9660 *iso9660 = a->format_data; + struct isofile *file; + unsigned char *rbuff; + ssize_t r; + size_t remaining, rbuff_size; + struct zisofs_extract zext; + int64_t read_offset, write_offset, new_offset; + int fd, ret = ARCHIVE_OK; + + file = iso9660->el_torito.boot->file; + /* + * There is nothing to do if this boot file does not have + * zisofs header. + */ + if (file->zisofs.header_size == 0) + return (ARCHIVE_OK); + + /* + * Uncompress the zisofs'ed file contents. + */ + memset(&zext, 0, sizeof(zext)); + zext.pz_uncompressed_size = file->zisofs.uncompressed_size; + zext.pz_log2_bs = file->zisofs.log2_bs; + + fd = iso9660->temp_fd; + new_offset = wb_offset(a); + read_offset = file->content.offset_of_temp; + remaining = (size_t)file->content.size; + if (remaining > 1024 * 32) + rbuff_size = 1024 * 32; + else + rbuff_size = remaining; + + rbuff = malloc(rbuff_size); + if (rbuff == NULL) { + archive_set_error(&a->archive, ENOMEM, "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + while (remaining) { + size_t rsize; + ssize_t rs; + + /* Get the current file pointer. */ + write_offset = lseek(fd, 0, SEEK_CUR); + + /* Change the file pointer to read. */ + lseek(fd, read_offset, SEEK_SET); + + rsize = rbuff_size; + if (rsize > remaining) + rsize = remaining; + rs = read(iso9660->temp_fd, rbuff, rsize); + if (rs <= 0) { + archive_set_error(&a->archive, errno, + "Can't read temporary file(%jd)", (intmax_t)rs); + ret = ARCHIVE_FATAL; + break; + } + remaining -= rs; + read_offset += rs; + + /* Put the file pointer back to write. */ + lseek(fd, write_offset, SEEK_SET); + + r = zisofs_extract(a, &zext, rbuff, rs); + if (r < 0) { + ret = (int)r; + break; + } + } + + if (ret == ARCHIVE_OK) { + /* + * Change the boot file content from zisofs'ed data + * to plain data. + */ + file->content.offset_of_temp = new_offset; + file->content.size = file->zisofs.uncompressed_size; + archive_entry_set_size(file->entry, file->content.size); + /* Set to be no zisofs. */ + file->zisofs.header_size = 0; + file->zisofs.log2_bs = 0; + file->zisofs.uncompressed_size = 0; + r = wb_write_padding_to_temp(a, file->content.size); + if (r < 0) + ret = ARCHIVE_FATAL; + } + + /* + * Free the resource we used in this function only. + */ + free(rbuff); + free(zext.block_pointers); + if (zext.stream_valid && inflateEnd(&(zext.stream)) != Z_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to clean up compressor"); + ret = ARCHIVE_FATAL; + } + + return (ret); +} + +#else + +static int +zisofs_write_to_temp(struct archive_write *a, const void *buff, size_t s) +{ + (void)buff; /* UNUSED */ + (void)s; /* UNUSED */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Programing error"); + return (ARCHIVE_FATAL); +} + +static int +zisofs_rewind_boot_file(struct archive_write *a) +{ + struct iso9660 *iso9660 = a->format_data; + + if (iso9660->el_torito.boot->file->zisofs.header_size != 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "We cannot extract the zisofs imaged boot file;" + " this may not boot in being zisofs imaged"); + return (ARCHIVE_FAILED); + } + return (ARCHIVE_OK); +} + +static int +zisofs_finish_entry(struct archive_write *a) +{ + (void)a; /* UNUSED */ + return (ARCHIVE_OK); +} + +static int +zisofs_free(struct archive_write *a) +{ + (void)a; /* UNUSED */ + return (ARCHIVE_OK); +} + +#endif /* HAVE_ZLIB_H */ + diff --cc Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c index 58ad9e0,0000000..3c617ec mode 100644,000000..100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_xar.c @@@ -1,3223 -1,0 +1,3224 @@@ +/*- + * Copyright (c) 2010-2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_LIMITS_H +#include +#endif +#include +#if HAVE_LIBXML_XMLWRITER_H +#include +#endif +#ifdef HAVE_BZLIB_H +#include +#endif +#if HAVE_LZMA_H +#include +#endif +#ifdef HAVE_ZLIB_H +#include +#endif + +#include "archive.h" +#include "archive_digest_private.h" +#include "archive_endian.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_private.h" +#include "archive_rb.h" +#include "archive_string.h" +#include "archive_write_private.h" + +/* + * Differences to xar utility. + * - Subdocument is not supported yet. + * - ACL is not supported yet. + * - When writing an XML element , + * which is a file type a symbolic link is referencing is always marked + * as "broken". Xar utility uses stat(2) to get the file type, but, in - * libarcive format writer, we should not use it; if it is needed, we ++ * libarchive format writer, we should not use it; if it is needed, we + * should get about it at archive_read_disk.c. + * - It is possible to appear both and elements. + * Xar utility generates on BSD platform and on Linux + * platform. + * + */ + +#if !(defined(HAVE_LIBXML_XMLWRITER_H) && defined(LIBXML_VERSION) &&\ + LIBXML_VERSION >= 20703) ||\ + !defined(HAVE_ZLIB_H) || \ + !defined(ARCHIVE_HAS_MD5) || !defined(ARCHIVE_HAS_SHA1) +/* + * xar needs several external libraries. + * o libxml2 + * o openssl or MD5/SHA1 hash function + * o zlib + * o bzlib2 (option) + * o liblzma (option) + */ +int +archive_write_set_format_xar(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Xar not supported on this platform"); + return (ARCHIVE_WARN); +} + +#else /* Support xar format */ + +/*#define DEBUG_PRINT_TOC 1 */ + +#define BAD_CAST_CONST (const xmlChar *) + +#define HEADER_MAGIC 0x78617221 +#define HEADER_SIZE 28 +#define HEADER_VERSION 1 + +enum sumalg { + CKSUM_NONE = 0, + CKSUM_SHA1 = 1, + CKSUM_MD5 = 2 +}; + +#define MD5_SIZE 16 +#define SHA1_SIZE 20 +#define MAX_SUM_SIZE 20 +#define MD5_NAME "md5" +#define SHA1_NAME "sha1" + +enum enctype { + NONE, + GZIP, + BZIP2, + LZMA, + XZ, +}; + +struct chksumwork { + enum sumalg alg; +#ifdef ARCHIVE_HAS_MD5 + archive_md5_ctx md5ctx; +#endif +#ifdef ARCHIVE_HAS_SHA1 + archive_sha1_ctx sha1ctx; +#endif +}; + +enum la_zaction { + ARCHIVE_Z_FINISH, + ARCHIVE_Z_RUN +}; + +/* + * Universal zstream. + */ +struct la_zstream { + const unsigned char *next_in; + size_t avail_in; + uint64_t total_in; + + unsigned char *next_out; + size_t avail_out; + uint64_t total_out; + + int valid; + void *real_stream; + int (*code) (struct archive *a, + struct la_zstream *lastrm, + enum la_zaction action); + int (*end)(struct archive *a, + struct la_zstream *lastrm); +}; + +struct chksumval { + enum sumalg alg; + size_t len; + unsigned char val[MAX_SUM_SIZE]; +}; + +struct heap_data { + int id; + struct heap_data *next; + uint64_t temp_offset; + uint64_t length; /* archived size. */ + uint64_t size; /* extracted size. */ + enum enctype compression; + struct chksumval a_sum; /* archived checksum. */ + struct chksumval e_sum; /* extracted checksum. */ +}; + +struct file { + struct archive_rb_node rbnode; + + int id; + struct archive_entry *entry; + + struct archive_rb_tree rbtree; + struct file *next; + struct file *chnext; + struct file *hlnext; + /* For hardlinked files. + * Use only when archive_entry_nlink() > 1 */ + struct file *hardlink_target; + struct file *parent; /* parent directory entry */ + /* + * To manage sub directory files. - * We use 'chnext' a menber of struct file to chain. ++ * We use 'chnext' (a member of struct file) to chain. + */ + struct { + struct file *first; + struct file **last; + } children; + + /* For making a directory tree. */ + struct archive_string parentdir; + struct archive_string basename; + struct archive_string symlink; + + int ea_idx; + struct { + struct heap_data *first; + struct heap_data **last; + } xattr; + struct heap_data data; + struct archive_string script; + + int virtual:1; + int dir:1; +}; + +struct hardlink { + struct archive_rb_node rbnode; + int nlink; + struct { + struct file *first; + struct file **last; + } file_list; +}; + +struct xar { + int temp_fd; + uint64_t temp_offset; + + int file_idx; + struct file *root; + struct file *cur_dirent; + struct archive_string cur_dirstr; + struct file *cur_file; + uint64_t bytes_remaining; + struct archive_string tstr; + struct archive_string vstr; + + enum sumalg opt_toc_sumalg; + enum sumalg opt_sumalg; + enum enctype opt_compression; + int opt_compression_level; + uint32_t opt_threads; + + struct chksumwork a_sumwrk; /* archived checksum. */ + struct chksumwork e_sumwrk; /* extracted checksum. */ + struct la_zstream stream; + struct archive_string_conv *sconv; + /* + * Compressed data buffer. + */ + unsigned char wbuff[1024 * 64]; + size_t wbuff_remaining; + + struct heap_data toc; + /* + * The list of all file entries is used to manage struct file + * objects. - * We use 'next' a menber of struct file to chain. ++ * We use 'next' (a member of struct file) to chain. + */ + struct { + struct file *first; + struct file **last; + } file_list; + /* + * The list of hard-linked file entries. - * We use 'hlnext' a menber of struct file to chain. ++ * We use 'hlnext' (a member of struct file) to chain. + */ + struct archive_rb_tree hardlink_rbtree; +}; + +static int xar_options(struct archive_write *, + const char *, const char *); +static int xar_write_header(struct archive_write *, + struct archive_entry *); +static ssize_t xar_write_data(struct archive_write *, + const void *, size_t); +static int xar_finish_entry(struct archive_write *); +static int xar_close(struct archive_write *); +static int xar_free(struct archive_write *); + +static struct file *file_new(struct archive_write *a, struct archive_entry *); +static void file_free(struct file *); +static struct file *file_create_virtual_dir(struct archive_write *a, struct xar *, + const char *); +static int file_add_child_tail(struct file *, struct file *); +static struct file *file_find_child(struct file *, const char *); +static int file_gen_utility_names(struct archive_write *, + struct file *); +static int get_path_component(char *, int, const char *); +static int file_tree(struct archive_write *, struct file **); +static void file_register(struct xar *, struct file *); +static void file_init_register(struct xar *); +static void file_free_register(struct xar *); +static int file_register_hardlink(struct archive_write *, + struct file *); +static void file_connect_hardlink_files(struct xar *); +static void file_init_hardlinks(struct xar *); +static void file_free_hardlinks(struct xar *); + +static void checksum_init(struct chksumwork *, enum sumalg); +static void checksum_update(struct chksumwork *, const void *, size_t); +static void checksum_final(struct chksumwork *, struct chksumval *); +static int compression_init_encoder_gzip(struct archive *, + struct la_zstream *, int, int); +static int compression_code_gzip(struct archive *, + struct la_zstream *, enum la_zaction); +static int compression_end_gzip(struct archive *, struct la_zstream *); +static int compression_init_encoder_bzip2(struct archive *, + struct la_zstream *, int); +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) +static int compression_code_bzip2(struct archive *, + struct la_zstream *, enum la_zaction); +static int compression_end_bzip2(struct archive *, struct la_zstream *); +#endif +static int compression_init_encoder_lzma(struct archive *, + struct la_zstream *, int); +static int compression_init_encoder_xz(struct archive *, + struct la_zstream *, int, int); +#if defined(HAVE_LZMA_H) +static int compression_code_lzma(struct archive *, + struct la_zstream *, enum la_zaction); +static int compression_end_lzma(struct archive *, struct la_zstream *); +#endif +static int xar_compression_init_encoder(struct archive_write *); +static int compression_code(struct archive *, + struct la_zstream *, enum la_zaction); +static int compression_end(struct archive *, + struct la_zstream *); +static int save_xattrs(struct archive_write *, struct file *); +static int getalgsize(enum sumalg); +static const char *getalgname(enum sumalg); + +int +archive_write_set_format_xar(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct xar *xar; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_set_format_xar"); + + /* If another format was already registered, unregister it. */ + if (a->format_free != NULL) + (a->format_free)(a); + + xar = calloc(1, sizeof(*xar)); + if (xar == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate xar data"); + return (ARCHIVE_FATAL); + } + xar->temp_fd = -1; + file_init_register(xar); + file_init_hardlinks(xar); + archive_string_init(&(xar->tstr)); + archive_string_init(&(xar->vstr)); + + /* + * Create the root directory. + */ + xar->root = file_create_virtual_dir(a, xar, ""); + if (xar->root == NULL) { + free(xar); + archive_set_error(&a->archive, ENOMEM, + "Can't allocate xar data"); + return (ARCHIVE_FATAL); + } + xar->root->parent = xar->root; + file_register(xar, xar->root); + xar->cur_dirent = xar->root; + archive_string_init(&(xar->cur_dirstr)); + archive_string_ensure(&(xar->cur_dirstr), 1); + xar->cur_dirstr.s[0] = 0; + + /* + * Initialize option. + */ + /* Set default checksum type. */ + xar->opt_toc_sumalg = CKSUM_SHA1; + xar->opt_sumalg = CKSUM_SHA1; + /* Set default compression type, level, and number of threads. */ + xar->opt_compression = GZIP; + xar->opt_compression_level = 6; + xar->opt_threads = 1; + + a->format_data = xar; + + a->format_name = "xar"; + a->format_options = xar_options; + a->format_write_header = xar_write_header; + a->format_write_data = xar_write_data; + a->format_finish_entry = xar_finish_entry; + a->format_close = xar_close; + a->format_free = xar_free; + a->archive.archive_format = ARCHIVE_FORMAT_XAR; + a->archive.archive_format_name = "xar"; + + return (ARCHIVE_OK); +} + +static int +xar_options(struct archive_write *a, const char *key, const char *value) +{ + struct xar *xar; + + xar = (struct xar *)a->format_data; + + if (strcmp(key, "checksum") == 0) { + if (value == NULL) + xar->opt_sumalg = CKSUM_NONE; + else if (strcmp(value, "sha1") == 0) + xar->opt_sumalg = CKSUM_SHA1; + else if (strcmp(value, "md5") == 0) + xar->opt_sumalg = CKSUM_MD5; + else { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "Unknown checksum name: `%s'", + value); + return (ARCHIVE_FAILED); + } + return (ARCHIVE_OK); + } + if (strcmp(key, "compression") == 0) { + const char *name = NULL; + + if (value == NULL) + xar->opt_compression = NONE; + else if (strcmp(value, "gzip") == 0) + xar->opt_compression = GZIP; + else if (strcmp(value, "bzip2") == 0) +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) + xar->opt_compression = BZIP2; +#else + name = "bzip2"; +#endif + else if (strcmp(value, "lzma") == 0) +#if HAVE_LZMA_H + xar->opt_compression = LZMA; +#else + name = "lzma"; +#endif + else if (strcmp(value, "xz") == 0) +#if HAVE_LZMA_H + xar->opt_compression = XZ; +#else + name = "xz"; +#endif + else { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "Unknown compression name: `%s'", + value); + return (ARCHIVE_FAILED); + } + if (name != NULL) { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "`%s' compression not supported " + "on this platform", + name); + return (ARCHIVE_FAILED); + } + return (ARCHIVE_OK); + } + if (strcmp(key, "compression-level") == 0) { + if (value == NULL || + !(value[0] >= '0' && value[0] <= '9') || + value[1] != '\0') { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "Illegal value `%s'", + value); + return (ARCHIVE_FAILED); + } + xar->opt_compression_level = value[0] - '0'; + return (ARCHIVE_OK); + } + if (strcmp(key, "toc-checksum") == 0) { + if (value == NULL) + xar->opt_toc_sumalg = CKSUM_NONE; + else if (strcmp(value, "sha1") == 0) + xar->opt_toc_sumalg = CKSUM_SHA1; + else if (strcmp(value, "md5") == 0) + xar->opt_toc_sumalg = CKSUM_MD5; + else { + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "Unknown checksum name: `%s'", + value); + return (ARCHIVE_FAILED); + } + return (ARCHIVE_OK); + } + if (strcmp(key, "threads") == 0) { + if (value == NULL) + return (ARCHIVE_FAILED); + xar->opt_threads = (int)strtoul(value, NULL, 10); + if (xar->opt_threads == 0 && errno != 0) { + xar->opt_threads = 1; + archive_set_error(&(a->archive), + ARCHIVE_ERRNO_MISC, + "Illegal value `%s'", + value); + return (ARCHIVE_FAILED); + } + if (xar->opt_threads == 0) { +#ifdef HAVE_LZMA_STREAM_ENCODER_MT + xar->opt_threads = lzma_cputhreads(); +#else + xar->opt_threads = 1; +#endif + } + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +static int +xar_write_header(struct archive_write *a, struct archive_entry *entry) +{ + struct xar *xar; + struct file *file; + struct archive_entry *file_entry; + int r, r2; + + xar = (struct xar *)a->format_data; + xar->cur_file = NULL; + xar->bytes_remaining = 0; + + if (xar->sconv == NULL) { + xar->sconv = archive_string_conversion_to_charset( + &a->archive, "UTF-8", 1); + if (xar->sconv == NULL) + return (ARCHIVE_FATAL); + } + + file = file_new(a, entry); + if (file == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate data"); + return (ARCHIVE_FATAL); + } + r2 = file_gen_utility_names(a, file); + if (r2 < ARCHIVE_WARN) + return (r2); + + /* + * Ignore a path which looks like the top of directory name + * since we have already made the root directory of an Xar archive. + */ + if (archive_strlen(&(file->parentdir)) == 0 && + archive_strlen(&(file->basename)) == 0) { + file_free(file); + return (r2); + } + + /* Add entry into tree */ + file_entry = file->entry; + r = file_tree(a, &file); + if (r != ARCHIVE_OK) + return (r); + /* There is the same file in tree and + * the current file is older than the file in tree. + * So we don't need the current file data anymore. */ + if (file->entry != file_entry) + return (r2); + if (file->id == 0) + file_register(xar, file); + + /* A virtual file, which is a directory, does not have + * any contents and we won't store it into a archive + * file other than its name. */ + if (file->virtual) + return (r2); + + /* + * Prepare to save the contents of the file. + */ + if (xar->temp_fd == -1) { + int algsize; + xar->temp_offset = 0; + xar->temp_fd = __archive_mktemp(NULL); + if (xar->temp_fd < 0) { + archive_set_error(&a->archive, errno, + "Couldn't create temporary file"); + return (ARCHIVE_FATAL); + } + algsize = getalgsize(xar->opt_toc_sumalg); + if (algsize > 0) { + if (lseek(xar->temp_fd, algsize, SEEK_SET) < 0) { + archive_set_error(&(a->archive), errno, + "lseek failed"); + return (ARCHIVE_FATAL); + } + xar->temp_offset = algsize; + } + } + + if (archive_entry_hardlink(file->entry) == NULL) { + r = save_xattrs(a, file); + if (r != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + + /* Non regular files contents are unneeded to be saved to + * a temporary file. */ + if (archive_entry_filetype(file->entry) != AE_IFREG) + return (r2); + + /* + * Set the current file to cur_file to read its contents. + */ + xar->cur_file = file; + + if (archive_entry_nlink(file->entry) > 1) { + r = file_register_hardlink(a, file); + if (r != ARCHIVE_OK) + return (r); + if (archive_entry_hardlink(file->entry) != NULL) { + archive_entry_unset_size(file->entry); + return (r2); + } + } + + /* Save a offset of current file in temporary file. */ + file->data.temp_offset = xar->temp_offset; + file->data.size = archive_entry_size(file->entry); + file->data.compression = xar->opt_compression; + xar->bytes_remaining = archive_entry_size(file->entry); + checksum_init(&(xar->a_sumwrk), xar->opt_sumalg); + checksum_init(&(xar->e_sumwrk), xar->opt_sumalg); + r = xar_compression_init_encoder(a); + + if (r != ARCHIVE_OK) + return (r); + else + return (r2); +} + +static int +write_to_temp(struct archive_write *a, const void *buff, size_t s) +{ + struct xar *xar; + const unsigned char *p; + ssize_t ws; + + xar = (struct xar *)a->format_data; + p = (const unsigned char *)buff; + while (s) { + ws = write(xar->temp_fd, p, s); + if (ws < 0) { + archive_set_error(&(a->archive), errno, + "fwrite function failed"); + return (ARCHIVE_FATAL); + } + s -= ws; + p += ws; + xar->temp_offset += ws; + } + return (ARCHIVE_OK); +} + +static ssize_t +xar_write_data(struct archive_write *a, const void *buff, size_t s) +{ + struct xar *xar; + enum la_zaction run; + size_t size, rsize; + int r; + + xar = (struct xar *)a->format_data; + + if (s > xar->bytes_remaining) + s = (size_t)xar->bytes_remaining; + if (s == 0 || xar->cur_file == NULL) + return (0); + if (xar->cur_file->data.compression == NONE) { + checksum_update(&(xar->e_sumwrk), buff, s); + checksum_update(&(xar->a_sumwrk), buff, s); + size = rsize = s; + } else { + xar->stream.next_in = (const unsigned char *)buff; + xar->stream.avail_in = s; + if (xar->bytes_remaining > s) + run = ARCHIVE_Z_RUN; + else + run = ARCHIVE_Z_FINISH; + /* Compress file data. */ + r = compression_code(&(a->archive), &(xar->stream), run); + if (r != ARCHIVE_OK && r != ARCHIVE_EOF) + return (ARCHIVE_FATAL); + rsize = s - xar->stream.avail_in; + checksum_update(&(xar->e_sumwrk), buff, rsize); + size = sizeof(xar->wbuff) - xar->stream.avail_out; + checksum_update(&(xar->a_sumwrk), xar->wbuff, size); + } +#if !defined(_WIN32) || defined(__CYGWIN__) + if (xar->bytes_remaining == + (uint64_t)archive_entry_size(xar->cur_file->entry)) { + /* + * Get the path of a shell script if so. + */ + const unsigned char *b = (const unsigned char *)buff; + + archive_string_empty(&(xar->cur_file->script)); + if (rsize > 2 && b[0] == '#' && b[1] == '!') { + size_t i, end, off; + + off = 2; + if (b[off] == ' ') + off++; +#ifdef PATH_MAX + if ((rsize - off) > PATH_MAX) + end = off + PATH_MAX; + else +#endif + end = rsize; + /* Find the end of a script path. */ + for (i = off; i < end && b[i] != '\0' && + b[i] != '\n' && b[i] != '\r' && + b[i] != ' ' && b[i] != '\t'; i++) + ; + archive_strncpy(&(xar->cur_file->script), b + off, + i - off); + } + } +#endif + + if (xar->cur_file->data.compression == NONE) { + if (write_to_temp(a, buff, size) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } else { + if (write_to_temp(a, xar->wbuff, size) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + xar->bytes_remaining -= rsize; + xar->cur_file->data.length += size; + + return (rsize); +} + +static int +xar_finish_entry(struct archive_write *a) +{ + struct xar *xar; + struct file *file; + size_t s; + ssize_t w; + + xar = (struct xar *)a->format_data; + if (xar->cur_file == NULL) + return (ARCHIVE_OK); + + while (xar->bytes_remaining > 0) { + s = (size_t)xar->bytes_remaining; + if (s > a->null_length) + s = a->null_length; + w = xar_write_data(a, a->nulls, s); + if (w > 0) + xar->bytes_remaining -= w; + else + return (w); + } + file = xar->cur_file; + checksum_final(&(xar->e_sumwrk), &(file->data.e_sum)); + checksum_final(&(xar->a_sumwrk), &(file->data.a_sum)); + xar->cur_file = NULL; + + return (ARCHIVE_OK); +} + +static int +xmlwrite_string_attr(struct archive_write *a, xmlTextWriterPtr writer, + const char *key, const char *value, + const char *attrkey, const char *attrvalue) +{ + int r; + + r = xmlTextWriterStartElement(writer, BAD_CAST_CONST(key)); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterStartElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + if (attrkey != NULL && attrvalue != NULL) { + r = xmlTextWriterWriteAttribute(writer, + BAD_CAST_CONST(attrkey), BAD_CAST_CONST(attrvalue)); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterWriteAttribute() failed: %d", r); + return (ARCHIVE_FATAL); + } + } + if (value != NULL) { + r = xmlTextWriterWriteString(writer, BAD_CAST_CONST(value)); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterWriteString() failed: %d", r); + return (ARCHIVE_FATAL); + } + } + r = xmlTextWriterEndElement(writer); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterEndElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + return (ARCHIVE_OK); +} + +static int +xmlwrite_string(struct archive_write *a, xmlTextWriterPtr writer, + const char *key, const char *value) +{ + int r; + + if (value == NULL) + return (ARCHIVE_OK); + + r = xmlTextWriterStartElement(writer, BAD_CAST_CONST(key)); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterStartElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + if (value != NULL) { + r = xmlTextWriterWriteString(writer, BAD_CAST_CONST(value)); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterWriteString() failed: %d", r); + return (ARCHIVE_FATAL); + } + } + r = xmlTextWriterEndElement(writer); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterEndElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + return (ARCHIVE_OK); +} + +static int +xmlwrite_fstring(struct archive_write *a, xmlTextWriterPtr writer, + const char *key, const char *fmt, ...) +{ + struct xar *xar; + va_list ap; + + xar = (struct xar *)a->format_data; + va_start(ap, fmt); + archive_string_empty(&xar->vstr); + archive_string_vsprintf(&xar->vstr, fmt, ap); + va_end(ap); + return (xmlwrite_string(a, writer, key, xar->vstr.s)); +} + +static int +xmlwrite_time(struct archive_write *a, xmlTextWriterPtr writer, + const char *key, time_t t, int z) +{ + char timestr[100]; + struct tm tm; + +#if defined(HAVE_GMTIME_R) + gmtime_r(&t, &tm); +#elif defined(HAVE__GMTIME64_S) + _gmtime64_s(&tm, &t); +#else + memcpy(&tm, gmtime(&t), sizeof(tm)); +#endif + memset(×tr, 0, sizeof(timestr)); + /* Do not use %F and %T for portability. */ + strftime(timestr, sizeof(timestr), "%Y-%m-%dT%H:%M:%S", &tm); + if (z) + strcat(timestr, "Z"); + return (xmlwrite_string(a, writer, key, timestr)); +} + +static int +xmlwrite_mode(struct archive_write *a, xmlTextWriterPtr writer, + const char *key, mode_t mode) +{ + char ms[5]; + + ms[0] = '0'; + ms[1] = '0' + ((mode >> 6) & 07); + ms[2] = '0' + ((mode >> 3) & 07); + ms[3] = '0' + (mode & 07); + ms[4] = '\0'; + + return (xmlwrite_string(a, writer, key, ms)); +} + +static int +xmlwrite_sum(struct archive_write *a, xmlTextWriterPtr writer, + const char *key, struct chksumval *sum) +{ + const char *algname; + int algsize; + char buff[MAX_SUM_SIZE*2 + 1]; + char *p; + unsigned char *s; + int i, r; + + if (sum->len > 0) { + algname = getalgname(sum->alg); + algsize = getalgsize(sum->alg); + if (algname != NULL) { + const char *hex = "0123456789abcdef"; + p = buff; + s = sum->val; + for (i = 0; i < algsize; i++) { + *p++ = hex[(*s >> 4)]; + *p++ = hex[(*s & 0x0f)]; + s++; + } + *p = '\0'; + r = xmlwrite_string_attr(a, writer, + key, buff, + "style", algname); + if (r < 0) + return (ARCHIVE_FATAL); + } + } + return (ARCHIVE_OK); +} + +static int +xmlwrite_heap(struct archive_write *a, xmlTextWriterPtr writer, + struct heap_data *heap) +{ + const char *encname; + int r; + + r = xmlwrite_fstring(a, writer, "length", "%ju", heap->length); + if (r < 0) + return (ARCHIVE_FATAL); + r = xmlwrite_fstring(a, writer, "offset", "%ju", heap->temp_offset); + if (r < 0) + return (ARCHIVE_FATAL); + r = xmlwrite_fstring(a, writer, "size", "%ju", heap->size); + if (r < 0) + return (ARCHIVE_FATAL); + switch (heap->compression) { + case GZIP: + encname = "application/x-gzip"; break; + case BZIP2: + encname = "application/x-bzip2"; break; + case LZMA: + encname = "application/x-lzma"; break; + case XZ: + encname = "application/x-xz"; break; + default: + encname = "application/octet-stream"; break; + } + r = xmlwrite_string_attr(a, writer, "encoding", NULL, + "style", encname); + if (r < 0) + return (ARCHIVE_FATAL); + r = xmlwrite_sum(a, writer, "archived-checksum", &(heap->a_sum)); + if (r < 0) + return (ARCHIVE_FATAL); + r = xmlwrite_sum(a, writer, "extracted-checksum", &(heap->e_sum)); + if (r < 0) + return (ARCHIVE_FATAL); + return (ARCHIVE_OK); +} + +/* + * xar utility records fflags as following xml elements: + * + * + * ..... + * + * or + * + * + * ..... + * + * If xar is running on BSD platform, records ..; + * if xar is running on linux platform, records ..; + * otherwise does not record. + * + * Our implements records both and if it's necessary. + */ +static int +make_fflags_entry(struct archive_write *a, xmlTextWriterPtr writer, + const char *element, const char *fflags_text) +{ + static const struct flagentry { + const char *name; + const char *xarname; + } + flagbsd[] = { + { "sappnd", "SystemAppend"}, + { "sappend", "SystemAppend"}, + { "arch", "SystemArchived"}, + { "archived", "SystemArchived"}, + { "schg", "SystemImmutable"}, + { "schange", "SystemImmutable"}, + { "simmutable", "SystemImmutable"}, + { "nosunlnk", "SystemNoUnlink"}, + { "nosunlink", "SystemNoUnlink"}, + { "snapshot", "SystemSnapshot"}, + { "uappnd", "UserAppend"}, + { "uappend", "UserAppend"}, + { "uchg", "UserImmutable"}, + { "uchange", "UserImmutable"}, + { "uimmutable", "UserImmutable"}, + { "nodump", "UserNoDump"}, + { "noopaque", "UserOpaque"}, + { "nouunlnk", "UserNoUnlink"}, + { "nouunlink", "UserNoUnlink"}, + { NULL, NULL} + }, + flagext2[] = { + { "sappnd", "AppendOnly"}, + { "sappend", "AppendOnly"}, + { "schg", "Immutable"}, + { "schange", "Immutable"}, + { "simmutable", "Immutable"}, + { "nodump", "NoDump"}, + { "nouunlnk", "Undelete"}, + { "nouunlink", "Undelete"}, + { "btree", "BTree"}, + { "comperr", "CompError"}, + { "compress", "Compress"}, + { "noatime", "NoAtime"}, + { "compdirty", "CompDirty"}, + { "comprblk", "CompBlock"}, + { "dirsync", "DirSync"}, + { "hashidx", "HashIndexed"}, + { "imagic", "iMagic"}, + { "journal", "Journaled"}, + { "securedeletion", "SecureDeletion"}, + { "sync", "Synchronous"}, + { "notail", "NoTail"}, + { "topdir", "TopDir"}, + { "reserved", "Reserved"}, + { NULL, NULL} + }; + const struct flagentry *fe, *flagentry; +#define FLAGENTRY_MAXSIZE ((sizeof(flagbsd)+sizeof(flagext2))/sizeof(flagbsd)) + const struct flagentry *avail[FLAGENTRY_MAXSIZE]; + const char *p; + int i, n, r; + + if (strcmp(element, "ext2") == 0) + flagentry = flagext2; + else + flagentry = flagbsd; + n = 0; + p = fflags_text; + do { + const char *cp; + + cp = strchr(p, ','); + if (cp == NULL) + cp = p + strlen(p); + + for (fe = flagentry; fe->name != NULL; fe++) { + if (fe->name[cp - p] != '\0' + || p[0] != fe->name[0]) + continue; + if (strncmp(p, fe->name, cp - p) == 0) { + avail[n++] = fe; + break; + } + } + if (*cp == ',') + p = cp + 1; + else + p = NULL; + } while (p != NULL); + + if (n > 0) { + r = xmlTextWriterStartElement(writer, BAD_CAST_CONST(element)); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterStartElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + for (i = 0; i < n; i++) { + r = xmlwrite_string(a, writer, + avail[i]->xarname, NULL); + if (r != ARCHIVE_OK) + return (r); + } + + r = xmlTextWriterEndElement(writer); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterEndElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + } + return (ARCHIVE_OK); +} + +static int +make_file_entry(struct archive_write *a, xmlTextWriterPtr writer, + struct file *file) +{ + struct xar *xar; + const char *filetype, *filelink, *fflags; + struct archive_string linkto; + struct heap_data *heap; + unsigned char *tmp; + const char *p; + size_t len; + int r, r2, l, ll; + + xar = (struct xar *)a->format_data; + r2 = ARCHIVE_OK; + + /* + * Make a file name entry, "". + */ + l = ll = archive_strlen(&(file->basename)); + tmp = malloc(l); + if (tmp == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + r = UTF8Toisolat1(tmp, &l, BAD_CAST(file->basename.s), &ll); + free(tmp); + if (r < 0) { + r = xmlTextWriterStartElement(writer, BAD_CAST("name")); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterStartElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + r = xmlTextWriterWriteAttribute(writer, + BAD_CAST("enctype"), BAD_CAST("base64")); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterWriteAttribute() failed: %d", r); + return (ARCHIVE_FATAL); + } + r = xmlTextWriterWriteBase64(writer, file->basename.s, + 0, archive_strlen(&(file->basename))); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterWriteBase64() failed: %d", r); + return (ARCHIVE_FATAL); + } + r = xmlTextWriterEndElement(writer); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterEndElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + } else { + r = xmlwrite_string(a, writer, "name", file->basename.s); + if (r < 0) + return (ARCHIVE_FATAL); + } + + /* + * Make a file type entry, "". + */ + filelink = NULL; + archive_string_init(&linkto); + switch (archive_entry_filetype(file->entry)) { + case AE_IFDIR: + filetype = "directory"; break; + case AE_IFLNK: + filetype = "symlink"; break; + case AE_IFCHR: + filetype = "character special"; break; + case AE_IFBLK: + filetype = "block special"; break; + case AE_IFSOCK: + filetype = "socket"; break; + case AE_IFIFO: + filetype = "fifo"; break; + case AE_IFREG: + default: + if (file->hardlink_target != NULL) { + filetype = "hardlink"; + filelink = "link"; + if (file->hardlink_target == file) + archive_strcpy(&linkto, "original"); + else + archive_string_sprintf(&linkto, "%d", + file->hardlink_target->id); + } else + filetype = "file"; + break; + } + r = xmlwrite_string_attr(a, writer, "type", filetype, + filelink, linkto.s); + archive_string_free(&linkto); + if (r < 0) + return (ARCHIVE_FATAL); + + /* + * On a virtual directory, we record "name" and "type" only. + */ + if (file->virtual) + return (ARCHIVE_OK); + + switch (archive_entry_filetype(file->entry)) { + case AE_IFLNK: + /* + * xar utility has checked a file type, which - * a symblic-link file has referenced. ++ * a symbolic-link file has referenced. + * For example: + * ../ref/ + * The symlink target file is "../ref/" and its + * file type is a directory. + * + * ../f + * The symlink target file is "../f" and its + * file type is a regular file. + * - * But our implemention cannot do it, and then we - * always record that a attribute "type" is "borken", ++ * But our implementation cannot do it, and then we ++ * always record that a attribute "type" is "broken", + * for example: + * foo/bar + * It means "foo/bar" is not reachable. + */ + r = xmlwrite_string_attr(a, writer, "link", + file->symlink.s, + "type", "broken"); + if (r < 0) + return (ARCHIVE_FATAL); + break; + case AE_IFCHR: + case AE_IFBLK: + r = xmlTextWriterStartElement(writer, BAD_CAST("device")); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterStartElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + r = xmlwrite_fstring(a, writer, "major", + "%d", archive_entry_rdevmajor(file->entry)); + if (r < 0) + return (ARCHIVE_FATAL); + r = xmlwrite_fstring(a, writer, "minor", + "%d", archive_entry_rdevminor(file->entry)); + if (r < 0) + return (ARCHIVE_FATAL); + r = xmlTextWriterEndElement(writer); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterEndElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + break; + default: + break; + } + + /* + * Make a inode entry, "". + */ + r = xmlwrite_fstring(a, writer, "inode", + "%jd", archive_entry_ino64(file->entry)); + if (r < 0) + return (ARCHIVE_FATAL); + if (archive_entry_dev(file->entry) != 0) { + r = xmlwrite_fstring(a, writer, "deviceno", + "%d", archive_entry_dev(file->entry)); + if (r < 0) + return (ARCHIVE_FATAL); + } + + /* + * Make a file mode entry, "". + */ + r = xmlwrite_mode(a, writer, "mode", + archive_entry_mode(file->entry)); + if (r < 0) + return (ARCHIVE_FATAL); + + /* + * Make a user entry, "" and ". + */ + r = xmlwrite_fstring(a, writer, "uid", + "%d", archive_entry_uid(file->entry)); + if (r < 0) + return (ARCHIVE_FATAL); + r = archive_entry_uname_l(file->entry, &p, &len, xar->sconv); + if (r != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Uname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate uname '%s' to UTF-8", + archive_entry_uname(file->entry)); + r2 = ARCHIVE_WARN; + } + if (len > 0) { + r = xmlwrite_string(a, writer, "user", p); + if (r < 0) + return (ARCHIVE_FATAL); + } + + /* + * Make a group entry, "" and ". + */ + r = xmlwrite_fstring(a, writer, "gid", + "%d", archive_entry_gid(file->entry)); + if (r < 0) + return (ARCHIVE_FATAL); + r = archive_entry_gname_l(file->entry, &p, &len, xar->sconv); + if (r != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Gname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate gname '%s' to UTF-8", + archive_entry_gname(file->entry)); + r2 = ARCHIVE_WARN; + } + if (len > 0) { + r = xmlwrite_string(a, writer, "group", p); + if (r < 0) + return (ARCHIVE_FATAL); + } + + /* + * Make a ctime entry, "". + */ + if (archive_entry_ctime_is_set(file->entry)) { + r = xmlwrite_time(a, writer, "ctime", + archive_entry_ctime(file->entry), 1); + if (r < 0) + return (ARCHIVE_FATAL); + } + + /* + * Make a mtime entry, "". + */ + if (archive_entry_mtime_is_set(file->entry)) { + r = xmlwrite_time(a, writer, "mtime", + archive_entry_mtime(file->entry), 1); + if (r < 0) + return (ARCHIVE_FATAL); + } + + /* + * Make a atime entry, "". + */ + if (archive_entry_atime_is_set(file->entry)) { + r = xmlwrite_time(a, writer, "atime", + archive_entry_atime(file->entry), 1); + if (r < 0) + return (ARCHIVE_FATAL); + } + + /* + * Make fflags entries, "" and "". + */ + fflags = archive_entry_fflags_text(file->entry); + if (fflags != NULL) { + r = make_fflags_entry(a, writer, "flags", fflags); + if (r < 0) + return (r); + r = make_fflags_entry(a, writer, "ext2", fflags); + if (r < 0) + return (r); + } + + /* + * Make extended attribute entries, "". + */ + archive_entry_xattr_reset(file->entry); + for (heap = file->xattr.first; heap != NULL; heap = heap->next) { + const char *name; + const void *value; + size_t size; + + archive_entry_xattr_next(file->entry, + &name, &value, &size); + r = xmlTextWriterStartElement(writer, BAD_CAST("ea")); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterStartElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + r = xmlTextWriterWriteFormatAttribute(writer, + BAD_CAST("id"), "%d", heap->id); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterWriteAttribute() failed: %d", r); + return (ARCHIVE_FATAL); + } + r = xmlwrite_heap(a, writer, heap); + if (r < 0) + return (ARCHIVE_FATAL); + r = xmlwrite_string(a, writer, "name", name); + if (r < 0) + return (ARCHIVE_FATAL); + + r = xmlTextWriterEndElement(writer); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterEndElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + } + + /* + * Make a file data entry, "". + */ + if (file->data.length > 0) { + r = xmlTextWriterStartElement(writer, BAD_CAST("data")); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterStartElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + + r = xmlwrite_heap(a, writer, &(file->data)); + if (r < 0) + return (ARCHIVE_FATAL); + + r = xmlTextWriterEndElement(writer); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterEndElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + } + + if (archive_strlen(&file->script) > 0) { + r = xmlTextWriterStartElement(writer, BAD_CAST("content")); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterStartElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + + r = xmlwrite_string(a, writer, + "interpreter", file->script.s); + if (r < 0) + return (ARCHIVE_FATAL); + + r = xmlwrite_string(a, writer, "type", "script"); + if (r < 0) + return (ARCHIVE_FATAL); + + r = xmlTextWriterEndElement(writer); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterEndElement() failed: %d", r); + return (ARCHIVE_FATAL); + } + } + + return (r2); +} + +/* + * Make the TOC + */ +static int +make_toc(struct archive_write *a) +{ + struct xar *xar; + struct file *np; + xmlBufferPtr bp; + xmlTextWriterPtr writer; + int algsize; + int r, ret; + + xar = (struct xar *)a->format_data; + + ret = ARCHIVE_FATAL; + + /* + * Initialize xml writer. + */ + writer = NULL; + bp = xmlBufferCreate(); + if (bp == NULL) { + archive_set_error(&a->archive, ENOMEM, + "xmlBufferCreate() " + "couldn't create xml buffer"); + goto exit_toc; + } + writer = xmlNewTextWriterMemory(bp, 0); + if (writer == NULL) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlNewTextWriterMemory() " + "couldn't create xml writer"); + goto exit_toc; + } + r = xmlTextWriterStartDocument(writer, "1.0", "UTF-8", NULL); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterStartDocument() failed: %d", r); + goto exit_toc; + } + r = xmlTextWriterSetIndent(writer, 4); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterSetIndent() failed: %d", r); + goto exit_toc; + } + + /* - * Start recoding TOC ++ * Start recording TOC + */ + r = xmlTextWriterStartElement(writer, BAD_CAST("xar")); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterStartElement() failed: %d", r); + goto exit_toc; + } + r = xmlTextWriterStartElement(writer, BAD_CAST("toc")); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterStartDocument() failed: %d", r); + goto exit_toc; + } + + /* + * Record the creation time of the archive file. + */ + r = xmlwrite_time(a, writer, "creation-time", time(NULL), 0); + if (r < 0) + goto exit_toc; + + /* + * Record the checksum value of TOC + */ + algsize = getalgsize(xar->opt_toc_sumalg); + if (algsize) { + /* + * Record TOC checksum + */ + r = xmlTextWriterStartElement(writer, BAD_CAST("checksum")); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterStartElement() failed: %d", r); + goto exit_toc; + } + r = xmlTextWriterWriteAttribute(writer, BAD_CAST("style"), + BAD_CAST_CONST(getalgname(xar->opt_toc_sumalg))); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterWriteAttribute() failed: %d", r); + goto exit_toc; + } + + /* + * Record the offset of the value of checksum of TOC + */ + r = xmlwrite_string(a, writer, "offset", "0"); + if (r < 0) + goto exit_toc; + + /* + * Record the size of the value of checksum of TOC + */ + r = xmlwrite_fstring(a, writer, "size", "%d", algsize); + if (r < 0) + goto exit_toc; + + r = xmlTextWriterEndElement(writer); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterEndElement() failed: %d", r); + goto exit_toc; + } + } + + np = xar->root; + do { + if (np != np->parent) { + r = make_file_entry(a, writer, np); + if (r != ARCHIVE_OK) + goto exit_toc; + } + + if (np->dir && np->children.first != NULL) { + /* Enter to sub directories. */ + np = np->children.first; + r = xmlTextWriterStartElement(writer, + BAD_CAST("file")); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterStartElement() " + "failed: %d", r); + goto exit_toc; + } + r = xmlTextWriterWriteFormatAttribute( + writer, BAD_CAST("id"), "%d", np->id); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterWriteAttribute() " + "failed: %d", r); + goto exit_toc; + } + continue; + } + while (np != np->parent) { + r = xmlTextWriterEndElement(writer); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterEndElement() " + "failed: %d", r); + goto exit_toc; + } + if (np->chnext == NULL) { + /* Return to the parent directory. */ + np = np->parent; + } else { + np = np->chnext; + r = xmlTextWriterStartElement(writer, + BAD_CAST("file")); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterStartElement() " + "failed: %d", r); + goto exit_toc; + } + r = xmlTextWriterWriteFormatAttribute( + writer, BAD_CAST("id"), "%d", np->id); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterWriteAttribute() " + "failed: %d", r); + goto exit_toc; + } + break; + } + } + } while (np != np->parent); + + r = xmlTextWriterEndDocument(writer); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xmlTextWriterEndDocument() failed: %d", r); + goto exit_toc; + } +#if DEBUG_PRINT_TOC + fprintf(stderr, "\n---TOC-- %d bytes --\n%s\n", + strlen((const char *)bp->content), bp->content); +#endif + + /* + * Compress the TOC and calculate the sum of the TOC. + */ + xar->toc.temp_offset = xar->temp_offset; + xar->toc.size = bp->use; + checksum_init(&(xar->a_sumwrk), xar->opt_toc_sumalg); + + r = compression_init_encoder_gzip(&(a->archive), + &(xar->stream), 6, 1); + if (r != ARCHIVE_OK) + goto exit_toc; + xar->stream.next_in = bp->content; + xar->stream.avail_in = bp->use; + xar->stream.total_in = 0; + xar->stream.next_out = xar->wbuff; + xar->stream.avail_out = sizeof(xar->wbuff); + xar->stream.total_out = 0; + for (;;) { + size_t size; + + r = compression_code(&(a->archive), + &(xar->stream), ARCHIVE_Z_FINISH); + if (r != ARCHIVE_OK && r != ARCHIVE_EOF) + goto exit_toc; + size = sizeof(xar->wbuff) - xar->stream.avail_out; + checksum_update(&(xar->a_sumwrk), xar->wbuff, size); + if (write_to_temp(a, xar->wbuff, size) != ARCHIVE_OK) + goto exit_toc; + if (r == ARCHIVE_EOF) + break; + xar->stream.next_out = xar->wbuff; + xar->stream.avail_out = sizeof(xar->wbuff); + } + r = compression_end(&(a->archive), &(xar->stream)); + if (r != ARCHIVE_OK) + goto exit_toc; + xar->toc.length = xar->stream.total_out; + xar->toc.compression = GZIP; + checksum_final(&(xar->a_sumwrk), &(xar->toc.a_sum)); + + ret = ARCHIVE_OK; +exit_toc: + if (writer) + xmlFreeTextWriter(writer); + if (bp) + xmlBufferFree(bp); + + return (ret); +} + +static int +flush_wbuff(struct archive_write *a) +{ + struct xar *xar; + int r; + size_t s; + + xar = (struct xar *)a->format_data; + s = sizeof(xar->wbuff) - xar->wbuff_remaining; + r = __archive_write_output(a, xar->wbuff, s); + if (r != ARCHIVE_OK) + return (r); + xar->wbuff_remaining = sizeof(xar->wbuff); + return (r); +} + +static int +copy_out(struct archive_write *a, uint64_t offset, uint64_t length) +{ + struct xar *xar; + int r; + + xar = (struct xar *)a->format_data; + if (lseek(xar->temp_fd, offset, SEEK_SET) < 0) { + archive_set_error(&(a->archive), errno, "lseek failed"); + return (ARCHIVE_FATAL); + } + while (length) { + size_t rsize; + ssize_t rs; + unsigned char *wb; + + if (length > xar->wbuff_remaining) + rsize = xar->wbuff_remaining; + else + rsize = (size_t)length; + wb = xar->wbuff + (sizeof(xar->wbuff) - xar->wbuff_remaining); + rs = read(xar->temp_fd, wb, rsize); + if (rs < 0) { + archive_set_error(&(a->archive), errno, + "Can't read temporary file(%jd)", + (intmax_t)rs); + return (ARCHIVE_FATAL); + } + if (rs == 0) { + archive_set_error(&(a->archive), 0, + "Truncated xar archive"); + return (ARCHIVE_FATAL); + } + xar->wbuff_remaining -= rs; + length -= rs; + if (xar->wbuff_remaining == 0) { + r = flush_wbuff(a); + if (r != ARCHIVE_OK) + return (r); + } + } + return (ARCHIVE_OK); +} + +static int +xar_close(struct archive_write *a) +{ + struct xar *xar; + unsigned char *wb; + uint64_t length; + int r; + + xar = (struct xar *)a->format_data; + + /* Empty! */ + if (xar->root->children.first == NULL) + return (ARCHIVE_OK); + + /* Save the length of all file extended attributes and contents. */ + length = xar->temp_offset; + + /* Connect hardlinked files */ + file_connect_hardlink_files(xar); + + /* Make the TOC */ + r = make_toc(a); + if (r != ARCHIVE_OK) + return (r); + /* + * Make the xar header on wbuff(write buffer). + */ + wb = xar->wbuff; + xar->wbuff_remaining = sizeof(xar->wbuff); + archive_be32enc(&wb[0], HEADER_MAGIC); + archive_be16enc(&wb[4], HEADER_SIZE); + archive_be16enc(&wb[6], HEADER_VERSION); + archive_be64enc(&wb[8], xar->toc.length); + archive_be64enc(&wb[16], xar->toc.size); + archive_be32enc(&wb[24], xar->toc.a_sum.alg); + xar->wbuff_remaining -= HEADER_SIZE; + + /* + * Write the TOC + */ + r = copy_out(a, xar->toc.temp_offset, xar->toc.length); + if (r != ARCHIVE_OK) + return (r); + + /* Write the checksum value of the TOC. */ + if (xar->toc.a_sum.len) { + if (xar->wbuff_remaining < xar->toc.a_sum.len) { + r = flush_wbuff(a); + if (r != ARCHIVE_OK) + return (r); + } + wb = xar->wbuff + (sizeof(xar->wbuff) - xar->wbuff_remaining); + memcpy(wb, xar->toc.a_sum.val, xar->toc.a_sum.len); + xar->wbuff_remaining -= xar->toc.a_sum.len; + } + + /* + * Write all file extended attributes and contents. + */ + r = copy_out(a, xar->toc.a_sum.len, length); + if (r != ARCHIVE_OK) + return (r); + r = flush_wbuff(a); + return (r); +} + +static int +xar_free(struct archive_write *a) +{ + struct xar *xar; + + xar = (struct xar *)a->format_data; + + /* Close the temporary file. */ + if (xar->temp_fd >= 0) + close(xar->temp_fd); + + archive_string_free(&(xar->cur_dirstr)); + archive_string_free(&(xar->tstr)); + archive_string_free(&(xar->vstr)); + file_free_hardlinks(xar); + file_free_register(xar); + compression_end(&(a->archive), &(xar->stream)); + free(xar); + + return (ARCHIVE_OK); +} + +static int +file_cmp_node(const struct archive_rb_node *n1, + const struct archive_rb_node *n2) +{ + const struct file *f1 = (const struct file *)n1; + const struct file *f2 = (const struct file *)n2; + + return (strcmp(f1->basename.s, f2->basename.s)); +} + +static int +file_cmp_key(const struct archive_rb_node *n, const void *key) +{ + const struct file *f = (const struct file *)n; + + return (strcmp(f->basename.s, (const char *)key)); +} + +static struct file * +file_new(struct archive_write *a, struct archive_entry *entry) +{ + struct file *file; + static const struct archive_rb_tree_ops rb_ops = { + file_cmp_node, file_cmp_key + }; + + file = calloc(1, sizeof(*file)); + if (file == NULL) + return (NULL); + + if (entry != NULL) + file->entry = archive_entry_clone(entry); + else + file->entry = archive_entry_new2(&a->archive); + if (file->entry == NULL) { + free(file); + return (NULL); + } + __archive_rb_tree_init(&(file->rbtree), &rb_ops); + file->children.first = NULL; + file->children.last = &(file->children.first); + file->xattr.first = NULL; + file->xattr.last = &(file->xattr.first); + archive_string_init(&(file->parentdir)); + archive_string_init(&(file->basename)); + archive_string_init(&(file->symlink)); + archive_string_init(&(file->script)); + if (entry != NULL && archive_entry_filetype(entry) == AE_IFDIR) + file->dir = 1; + + return (file); +} + +static void +file_free(struct file *file) +{ + struct heap_data *heap, *next_heap; + + heap = file->xattr.first; + while (heap != NULL) { + next_heap = heap->next; + free(heap); + heap = next_heap; + } + archive_string_free(&(file->parentdir)); + archive_string_free(&(file->basename)); + archive_string_free(&(file->symlink)); + archive_string_free(&(file->script)); ++ archive_entry_free(file->entry); + free(file); +} + +static struct file * +file_create_virtual_dir(struct archive_write *a, struct xar *xar, + const char *pathname) +{ + struct file *file; + + (void)xar; /* UNUSED */ + + file = file_new(a, NULL); + if (file == NULL) + return (NULL); + archive_entry_set_pathname(file->entry, pathname); + archive_entry_set_mode(file->entry, 0555 | AE_IFDIR); + + file->dir = 1; + file->virtual = 1; + + return (file); +} + +static int +file_add_child_tail(struct file *parent, struct file *child) +{ + if (!__archive_rb_tree_insert_node( + &(parent->rbtree), (struct archive_rb_node *)child)) + return (0); + child->chnext = NULL; + *parent->children.last = child; + parent->children.last = &(child->chnext); + child->parent = parent; + return (1); +} + +/* + * Find a entry from `parent' + */ +static struct file * +file_find_child(struct file *parent, const char *child_name) +{ + struct file *np; + + np = (struct file *)__archive_rb_tree_find_node( + &(parent->rbtree), child_name); + return (np); +} + +#if defined(_WIN32) || defined(__CYGWIN__) +static void +cleanup_backslash(char *utf8, size_t len) +{ + + /* Convert a path-separator from '\' to '/' */ + while (*utf8 != '\0' && len) { + if (*utf8 == '\\') + *utf8 = '/'; + ++utf8; + --len; + } +} +#else +#define cleanup_backslash(p, len) /* nop */ +#endif + +/* + * Generate a parent directory name and a base name from a pathname. + */ +static int +file_gen_utility_names(struct archive_write *a, struct file *file) +{ + struct xar *xar; + const char *pp; + char *p, *dirname, *slash; + size_t len; + int r = ARCHIVE_OK; + + xar = (struct xar *)a->format_data; + archive_string_empty(&(file->parentdir)); + archive_string_empty(&(file->basename)); + archive_string_empty(&(file->symlink)); + + if (file->parent == file)/* virtual root */ + return (ARCHIVE_OK); + + if (archive_entry_pathname_l(file->entry, &pp, &len, xar->sconv) + != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Pathname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate pathname '%s' to UTF-8", + archive_entry_pathname(file->entry)); + r = ARCHIVE_WARN; + } + archive_strncpy(&(file->parentdir), pp, len); + len = file->parentdir.length; + p = dirname = file->parentdir.s; + /* + * Convert a path-separator from '\' to '/' + */ + cleanup_backslash(p, len); + + /* + * Remove leading '/', '../' and './' elements + */ + while (*p) { + if (p[0] == '/') { + p++; + len--; + } else if (p[0] != '.') + break; + else if (p[1] == '.' && p[2] == '/') { + p += 3; + len -= 3; + } else if (p[1] == '/' || (p[1] == '.' && p[2] == '\0')) { + p += 2; + len -= 2; + } else if (p[1] == '\0') { + p++; + len--; + } else + break; + } + if (p != dirname) { + memmove(dirname, p, len+1); + p = dirname; + } + /* + * Remove "/","/." and "/.." elements from tail. + */ + while (len > 0) { + size_t ll = len; + + if (len > 0 && p[len-1] == '/') { + p[len-1] = '\0'; + len--; + } + if (len > 1 && p[len-2] == '/' && p[len-1] == '.') { + p[len-2] = '\0'; + len -= 2; + } + if (len > 2 && p[len-3] == '/' && p[len-2] == '.' && + p[len-1] == '.') { + p[len-3] = '\0'; + len -= 3; + } + if (ll == len) + break; + } + while (*p) { + if (p[0] == '/') { + if (p[1] == '/') + /* Convert '//' --> '/' */ + strcpy(p, p+1); + else if (p[1] == '.' && p[2] == '/') + /* Convert '/./' --> '/' */ + strcpy(p, p+2); + else if (p[1] == '.' && p[2] == '.' && p[3] == '/') { + /* Convert 'dir/dir1/../dir2/' + * --> 'dir/dir2/' + */ + char *rp = p -1; + while (rp >= dirname) { + if (*rp == '/') + break; + --rp; + } + if (rp > dirname) { + strcpy(rp, p+3); + p = rp; + } else { + strcpy(dirname, p+4); + p = dirname; + } + } else + p++; + } else + p++; + } + p = dirname; + len = strlen(p); + + if (archive_entry_filetype(file->entry) == AE_IFLNK) { + size_t len2; + /* Convert symlink name too. */ + if (archive_entry_symlink_l(file->entry, &pp, &len2, + xar->sconv) != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Linkname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate symlink '%s' to UTF-8", + archive_entry_symlink(file->entry)); + r = ARCHIVE_WARN; + } + archive_strncpy(&(file->symlink), pp, len2); + cleanup_backslash(file->symlink.s, file->symlink.length); + } + /* + * - Count up directory elements. + * - Find out the position which points the last position of + * path separator('/'). + */ + slash = NULL; + for (; *p != '\0'; p++) + if (*p == '/') + slash = p; + if (slash == NULL) { + /* The pathname doesn't have a parent directory. */ + file->parentdir.length = len; + archive_string_copy(&(file->basename), &(file->parentdir)); + archive_string_empty(&(file->parentdir)); + *file->parentdir.s = '\0'; + return (r); + } + + /* Make a basename from dirname and slash */ + *slash = '\0'; + file->parentdir.length = slash - dirname; + archive_strcpy(&(file->basename), slash + 1); + return (r); +} + +static int +get_path_component(char *name, int n, const char *fn) +{ + char *p; + int l; + + p = strchr(fn, '/'); + if (p == NULL) { + if ((l = strlen(fn)) == 0) + return (0); + } else + l = p - fn; + if (l > n -1) + return (-1); + memcpy(name, fn, l); + name[l] = '\0'; + + return (l); +} + +/* + * Add a new entry into the tree. + */ +static int +file_tree(struct archive_write *a, struct file **filepp) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + char name[_MAX_FNAME];/* Included null terminator size. */ +#elif defined(NAME_MAX) && NAME_MAX >= 255 + char name[NAME_MAX+1]; +#else + char name[256]; +#endif + struct xar *xar = (struct xar *)a->format_data; + struct file *dent, *file, *np; + struct archive_entry *ent; + const char *fn, *p; + int l; + + file = *filepp; + dent = xar->root; + if (file->parentdir.length > 0) + fn = p = file->parentdir.s; + else + fn = p = ""; + + /* + * If the path of the parent directory of `file' entry is + * the same as the path of `cur_dirent', add isoent to + * `cur_dirent'. + */ + if (archive_strlen(&(xar->cur_dirstr)) + == archive_strlen(&(file->parentdir)) && + strcmp(xar->cur_dirstr.s, fn) == 0) { + if (!file_add_child_tail(xar->cur_dirent, file)) { + np = (struct file *)__archive_rb_tree_find_node( + &(xar->cur_dirent->rbtree), + file->basename.s); + goto same_entry; + } + return (ARCHIVE_OK); + } + + for (;;) { + l = get_path_component(name, sizeof(name), fn); + if (l == 0) { + np = NULL; + break; + } + if (l < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "A name buffer is too small"); + file_free(file); + *filepp = NULL; + return (ARCHIVE_FATAL); + } + + np = file_find_child(dent, name); + if (np == NULL || fn[0] == '\0') + break; + + /* Find next subdirectory. */ + if (!np->dir) { + /* NOT Directory! */ + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "`%s' is not directory, we cannot insert `%s' ", + archive_entry_pathname(np->entry), + archive_entry_pathname(file->entry)); + file_free(file); + *filepp = NULL; + return (ARCHIVE_FAILED); + } + fn += l; + if (fn[0] == '/') + fn++; + dent = np; + } + if (np == NULL) { + /* + * Create virtual parent directories. + */ + while (fn[0] != '\0') { + struct file *vp; + struct archive_string as; + + archive_string_init(&as); + archive_strncat(&as, p, fn - p + l); + if (as.s[as.length-1] == '/') { + as.s[as.length-1] = '\0'; + as.length--; + } + vp = file_create_virtual_dir(a, xar, as.s); + if (vp == NULL) { + archive_string_free(&as); + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + file_free(file); + *filepp = NULL; + return (ARCHIVE_FATAL); + } + archive_string_free(&as); + if (file_gen_utility_names(a, vp) <= ARCHIVE_FAILED) + return (ARCHIVE_FATAL); + file_add_child_tail(dent, vp); + file_register(xar, vp); + np = vp; + + fn += l; + if (fn[0] == '/') + fn++; + l = get_path_component(name, sizeof(name), fn); + if (l < 0) { + archive_string_free(&as); + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "A name buffer is too small"); + file_free(file); + *filepp = NULL; + return (ARCHIVE_FATAL); + } + dent = np; + } + + /* Found out the parent directory where isoent can be + * inserted. */ + xar->cur_dirent = dent; + archive_string_empty(&(xar->cur_dirstr)); + archive_string_ensure(&(xar->cur_dirstr), + archive_strlen(&(dent->parentdir)) + + archive_strlen(&(dent->basename)) + 2); + if (archive_strlen(&(dent->parentdir)) + + archive_strlen(&(dent->basename)) == 0) + xar->cur_dirstr.s[0] = 0; + else { + if (archive_strlen(&(dent->parentdir)) > 0) { + archive_string_copy(&(xar->cur_dirstr), + &(dent->parentdir)); + archive_strappend_char(&(xar->cur_dirstr), '/'); + } + archive_string_concat(&(xar->cur_dirstr), + &(dent->basename)); + } + + if (!file_add_child_tail(dent, file)) { + np = (struct file *)__archive_rb_tree_find_node( + &(dent->rbtree), file->basename.s); + goto same_entry; + } + return (ARCHIVE_OK); + } + +same_entry: + /* + * We have already has the entry the filename of which is + * the same. + */ + if (archive_entry_filetype(np->entry) != + archive_entry_filetype(file->entry)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Found duplicate entries `%s' and its file type is " + "different", + archive_entry_pathname(np->entry)); + file_free(file); + *filepp = NULL; + return (ARCHIVE_FAILED); + } + + /* Swap files. */ + ent = np->entry; + np->entry = file->entry; + file->entry = ent; + np->virtual = 0; + + file_free(file); + *filepp = np; + return (ARCHIVE_OK); +} + +static void +file_register(struct xar *xar, struct file *file) +{ + file->id = xar->file_idx++; + file->next = NULL; + *xar->file_list.last = file; + xar->file_list.last = &(file->next); +} + +static void +file_init_register(struct xar *xar) +{ + xar->file_list.first = NULL; + xar->file_list.last = &(xar->file_list.first); +} + +static void +file_free_register(struct xar *xar) +{ + struct file *file, *file_next; + + file = xar->file_list.first; + while (file != NULL) { + file_next = file->next; + file_free(file); + file = file_next; + } +} + +/* + * Register entry to get a hardlink target. + */ +static int +file_register_hardlink(struct archive_write *a, struct file *file) +{ + struct xar *xar = (struct xar *)a->format_data; + struct hardlink *hl; + const char *pathname; + + archive_entry_set_nlink(file->entry, 1); + pathname = archive_entry_hardlink(file->entry); + if (pathname == NULL) { + /* This `file` is a hardlink target. */ + hl = malloc(sizeof(*hl)); + if (hl == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory"); + return (ARCHIVE_FATAL); + } + hl->nlink = 1; + /* A hardlink target must be the first position. */ + file->hlnext = NULL; + hl->file_list.first = file; + hl->file_list.last = &(file->hlnext); + __archive_rb_tree_insert_node(&(xar->hardlink_rbtree), + (struct archive_rb_node *)hl); + } else { + hl = (struct hardlink *)__archive_rb_tree_find_node( + &(xar->hardlink_rbtree), pathname); + if (hl != NULL) { + /* Insert `file` entry into the tail. */ + file->hlnext = NULL; + *hl->file_list.last = file; + hl->file_list.last = &(file->hlnext); + hl->nlink++; + } + archive_entry_unset_size(file->entry); + } + + return (ARCHIVE_OK); +} + +/* + * Hardlinked files have to have the same location of extent. + * We have to find out hardlink target entries for entries which + * have a hardlink target name. + */ +static void +file_connect_hardlink_files(struct xar *xar) +{ + struct archive_rb_node *n; + struct hardlink *hl; + struct file *target, *nf; + + ARCHIVE_RB_TREE_FOREACH(n, &(xar->hardlink_rbtree)) { + hl = (struct hardlink *)n; + + /* The first entry must be a hardlink target. */ + target = hl->file_list.first; + archive_entry_set_nlink(target->entry, hl->nlink); + if (hl->nlink > 1) + /* It means this file is a hardlink - * targe itself. */ ++ * target itself. */ + target->hardlink_target = target; + for (nf = target->hlnext; + nf != NULL; nf = nf->hlnext) { + nf->hardlink_target = target; + archive_entry_set_nlink(nf->entry, hl->nlink); + } + } +} + +static int +file_hd_cmp_node(const struct archive_rb_node *n1, + const struct archive_rb_node *n2) +{ + const struct hardlink *h1 = (const struct hardlink *)n1; + const struct hardlink *h2 = (const struct hardlink *)n2; + + return (strcmp(archive_entry_pathname(h1->file_list.first->entry), + archive_entry_pathname(h2->file_list.first->entry))); +} + +static int +file_hd_cmp_key(const struct archive_rb_node *n, const void *key) +{ + const struct hardlink *h = (const struct hardlink *)n; + + return (strcmp(archive_entry_pathname(h->file_list.first->entry), + (const char *)key)); +} + + +static void +file_init_hardlinks(struct xar *xar) +{ + static const struct archive_rb_tree_ops rb_ops = { + file_hd_cmp_node, file_hd_cmp_key, + }; + + __archive_rb_tree_init(&(xar->hardlink_rbtree), &rb_ops); +} + +static void +file_free_hardlinks(struct xar *xar) +{ + struct archive_rb_node *n, *next; + + for (n = ARCHIVE_RB_TREE_MIN(&(xar->hardlink_rbtree)); n;) { + next = __archive_rb_tree_iterate(&(xar->hardlink_rbtree), + n, ARCHIVE_RB_DIR_RIGHT); + free(n); + n = next; + } +} + +static void +checksum_init(struct chksumwork *sumwrk, enum sumalg sum_alg) +{ + sumwrk->alg = sum_alg; + switch (sum_alg) { + case CKSUM_NONE: + break; + case CKSUM_SHA1: + archive_sha1_init(&(sumwrk->sha1ctx)); + break; + case CKSUM_MD5: + archive_md5_init(&(sumwrk->md5ctx)); + break; + } +} + +static void +checksum_update(struct chksumwork *sumwrk, const void *buff, size_t size) +{ + + switch (sumwrk->alg) { + case CKSUM_NONE: + break; + case CKSUM_SHA1: + archive_sha1_update(&(sumwrk->sha1ctx), buff, size); + break; + case CKSUM_MD5: + archive_md5_update(&(sumwrk->md5ctx), buff, size); + break; + } +} + +static void +checksum_final(struct chksumwork *sumwrk, struct chksumval *sumval) +{ + + switch (sumwrk->alg) { + case CKSUM_NONE: + sumval->len = 0; + break; + case CKSUM_SHA1: + archive_sha1_final(&(sumwrk->sha1ctx), sumval->val); + sumval->len = SHA1_SIZE; + break; + case CKSUM_MD5: + archive_md5_final(&(sumwrk->md5ctx), sumval->val); + sumval->len = MD5_SIZE; + break; + } + sumval->alg = sumwrk->alg; +} + +#if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H) +static int +compression_unsupported_encoder(struct archive *a, + struct la_zstream *lastrm, const char *name) +{ + + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "%s compression not supported on this platform", name); + lastrm->valid = 0; + lastrm->real_stream = NULL; + return (ARCHIVE_FAILED); +} +#endif + +static int +compression_init_encoder_gzip(struct archive *a, + struct la_zstream *lastrm, int level, int withheader) +{ + z_stream *strm; + + if (lastrm->valid) + compression_end(a, lastrm); + strm = calloc(1, sizeof(*strm)); + if (strm == NULL) { + archive_set_error(a, ENOMEM, + "Can't allocate memory for gzip stream"); + return (ARCHIVE_FATAL); + } + /* zlib.h is not const-correct, so we need this one bit + * of ugly hackery to convert a const * pointer to + * a non-const pointer. */ + strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in; + strm->avail_in = lastrm->avail_in; + strm->total_in = (uLong)lastrm->total_in; + strm->next_out = lastrm->next_out; + strm->avail_out = lastrm->avail_out; + strm->total_out = (uLong)lastrm->total_out; + if (deflateInit2(strm, level, Z_DEFLATED, + (withheader)?15:-15, + 8, Z_DEFAULT_STRATEGY) != Z_OK) { + free(strm); + lastrm->real_stream = NULL; + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Internal error initializing compression library"); + return (ARCHIVE_FATAL); + } + lastrm->real_stream = strm; + lastrm->valid = 1; + lastrm->code = compression_code_gzip; + lastrm->end = compression_end_gzip; + return (ARCHIVE_OK); +} + +static int +compression_code_gzip(struct archive *a, + struct la_zstream *lastrm, enum la_zaction action) +{ + z_stream *strm; + int r; + + strm = (z_stream *)lastrm->real_stream; + /* zlib.h is not const-correct, so we need this one bit + * of ugly hackery to convert a const * pointer to + * a non-const pointer. */ + strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in; + strm->avail_in = lastrm->avail_in; + strm->total_in = (uLong)lastrm->total_in; + strm->next_out = lastrm->next_out; + strm->avail_out = lastrm->avail_out; + strm->total_out = (uLong)lastrm->total_out; + r = deflate(strm, + (action == ARCHIVE_Z_FINISH)? Z_FINISH: Z_NO_FLUSH); + lastrm->next_in = strm->next_in; + lastrm->avail_in = strm->avail_in; + lastrm->total_in = strm->total_in; + lastrm->next_out = strm->next_out; + lastrm->avail_out = strm->avail_out; + lastrm->total_out = strm->total_out; + switch (r) { + case Z_OK: + return (ARCHIVE_OK); + case Z_STREAM_END: + return (ARCHIVE_EOF); + default: + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "GZip compression failed:" + " deflate() call returned status %d", r); + return (ARCHIVE_FATAL); + } +} + +static int +compression_end_gzip(struct archive *a, struct la_zstream *lastrm) +{ + z_stream *strm; + int r; + + strm = (z_stream *)lastrm->real_stream; + r = deflateEnd(strm); + free(strm); + lastrm->real_stream = NULL; + lastrm->valid = 0; + if (r != Z_OK) { + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Failed to clean up compressor"); + return (ARCHIVE_FATAL); + } + return (ARCHIVE_OK); +} + +#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) +static int +compression_init_encoder_bzip2(struct archive *a, + struct la_zstream *lastrm, int level) +{ + bz_stream *strm; + + if (lastrm->valid) + compression_end(a, lastrm); + strm = calloc(1, sizeof(*strm)); + if (strm == NULL) { + archive_set_error(a, ENOMEM, + "Can't allocate memory for bzip2 stream"); + return (ARCHIVE_FATAL); + } + /* bzlib.h is not const-correct, so we need this one bit + * of ugly hackery to convert a const * pointer to + * a non-const pointer. */ + strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in; + strm->avail_in = lastrm->avail_in; + strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff); + strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32); + strm->next_out = (char *)lastrm->next_out; + strm->avail_out = lastrm->avail_out; + strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff); + strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32); + if (BZ2_bzCompressInit(strm, level, 0, 30) != BZ_OK) { + free(strm); + lastrm->real_stream = NULL; + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Internal error initializing compression library"); + return (ARCHIVE_FATAL); + } + lastrm->real_stream = strm; + lastrm->valid = 1; + lastrm->code = compression_code_bzip2; + lastrm->end = compression_end_bzip2; + return (ARCHIVE_OK); +} + +static int +compression_code_bzip2(struct archive *a, + struct la_zstream *lastrm, enum la_zaction action) +{ + bz_stream *strm; + int r; + + strm = (bz_stream *)lastrm->real_stream; + /* bzlib.h is not const-correct, so we need this one bit + * of ugly hackery to convert a const * pointer to + * a non-const pointer. */ + strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in; + strm->avail_in = lastrm->avail_in; + strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff); + strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32); + strm->next_out = (char *)lastrm->next_out; + strm->avail_out = lastrm->avail_out; + strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff); + strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32); + r = BZ2_bzCompress(strm, + (action == ARCHIVE_Z_FINISH)? BZ_FINISH: BZ_RUN); + lastrm->next_in = (const unsigned char *)strm->next_in; + lastrm->avail_in = strm->avail_in; + lastrm->total_in = + (((uint64_t)(uint32_t)strm->total_in_hi32) << 32) + + (uint64_t)(uint32_t)strm->total_in_lo32; + lastrm->next_out = (unsigned char *)strm->next_out; + lastrm->avail_out = strm->avail_out; + lastrm->total_out = + (((uint64_t)(uint32_t)strm->total_out_hi32) << 32) + + (uint64_t)(uint32_t)strm->total_out_lo32; + switch (r) { + case BZ_RUN_OK: /* Non-finishing */ + case BZ_FINISH_OK: /* Finishing: There's more work to do */ + return (ARCHIVE_OK); + case BZ_STREAM_END: /* Finishing: all done */ + /* Only occurs in finishing case */ + return (ARCHIVE_EOF); + default: + /* Any other return value indicates an error */ + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Bzip2 compression failed:" + " BZ2_bzCompress() call returned status %d", r); + return (ARCHIVE_FATAL); + } +} + +static int +compression_end_bzip2(struct archive *a, struct la_zstream *lastrm) +{ + bz_stream *strm; + int r; + + strm = (bz_stream *)lastrm->real_stream; + r = BZ2_bzCompressEnd(strm); + free(strm); + lastrm->real_stream = NULL; + lastrm->valid = 0; + if (r != BZ_OK) { + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Failed to clean up compressor"); + return (ARCHIVE_FATAL); + } + return (ARCHIVE_OK); +} + +#else +static int +compression_init_encoder_bzip2(struct archive *a, + struct la_zstream *lastrm, int level) +{ + + (void) level; /* UNUSED */ + if (lastrm->valid) + compression_end(a, lastrm); + return (compression_unsupported_encoder(a, lastrm, "bzip2")); +} +#endif + +#if defined(HAVE_LZMA_H) +static int +compression_init_encoder_lzma(struct archive *a, + struct la_zstream *lastrm, int level) +{ + static const lzma_stream lzma_init_data = LZMA_STREAM_INIT; + lzma_stream *strm; + lzma_options_lzma lzma_opt; + int r; + + if (lastrm->valid) + compression_end(a, lastrm); + if (lzma_lzma_preset(&lzma_opt, level)) { + lastrm->real_stream = NULL; + archive_set_error(a, ENOMEM, + "Internal error initializing compression library"); + return (ARCHIVE_FATAL); + } + strm = calloc(1, sizeof(*strm)); + if (strm == NULL) { + archive_set_error(a, ENOMEM, + "Can't allocate memory for lzma stream"); + return (ARCHIVE_FATAL); + } + *strm = lzma_init_data; + r = lzma_alone_encoder(strm, &lzma_opt); + switch (r) { + case LZMA_OK: + lastrm->real_stream = strm; + lastrm->valid = 1; + lastrm->code = compression_code_lzma; + lastrm->end = compression_end_lzma; + r = ARCHIVE_OK; + break; + case LZMA_MEM_ERROR: + free(strm); + lastrm->real_stream = NULL; + archive_set_error(a, ENOMEM, + "Internal error initializing compression library: " + "Cannot allocate memory"); + r = ARCHIVE_FATAL; + break; + default: + free(strm); + lastrm->real_stream = NULL; + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Internal error initializing compression library: " + "It's a bug in liblzma"); + r = ARCHIVE_FATAL; + break; + } + return (r); +} + +static int +compression_init_encoder_xz(struct archive *a, + struct la_zstream *lastrm, int level, int threads) +{ + static const lzma_stream lzma_init_data = LZMA_STREAM_INIT; + lzma_stream *strm; + lzma_filter *lzmafilters; + lzma_options_lzma lzma_opt; + int r; +#ifdef HAVE_LZMA_STREAM_ENCODER_MT + lzma_mt mt_options; +#endif + + (void)threads; /* UNUSED (if multi-threaded LZMA library not avail) */ + + if (lastrm->valid) + compression_end(a, lastrm); + strm = calloc(1, sizeof(*strm) + sizeof(*lzmafilters) * 2); + if (strm == NULL) { + archive_set_error(a, ENOMEM, + "Can't allocate memory for xz stream"); + return (ARCHIVE_FATAL); + } + lzmafilters = (lzma_filter *)(strm+1); + if (level > 6) + level = 6; + if (lzma_lzma_preset(&lzma_opt, level)) { + free(strm); + lastrm->real_stream = NULL; + archive_set_error(a, ENOMEM, + "Internal error initializing compression library"); + return (ARCHIVE_FATAL); + } + lzmafilters[0].id = LZMA_FILTER_LZMA2; + lzmafilters[0].options = &lzma_opt; + lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */ + + *strm = lzma_init_data; +#ifdef HAVE_LZMA_STREAM_ENCODER_MT + if (threads > 1) { - bzero(&mt_options, sizeof(mt_options)); ++ memset(&mt_options, 0, sizeof(mt_options)); + mt_options.threads = threads; + mt_options.timeout = 300; + mt_options.filters = lzmafilters; + mt_options.check = LZMA_CHECK_CRC64; + r = lzma_stream_encoder_mt(strm, &mt_options); + } else +#endif + r = lzma_stream_encoder(strm, lzmafilters, LZMA_CHECK_CRC64); + switch (r) { + case LZMA_OK: + lastrm->real_stream = strm; + lastrm->valid = 1; + lastrm->code = compression_code_lzma; + lastrm->end = compression_end_lzma; + r = ARCHIVE_OK; + break; + case LZMA_MEM_ERROR: + free(strm); + lastrm->real_stream = NULL; + archive_set_error(a, ENOMEM, + "Internal error initializing compression library: " + "Cannot allocate memory"); + r = ARCHIVE_FATAL; + break; + default: + free(strm); + lastrm->real_stream = NULL; + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Internal error initializing compression library: " + "It's a bug in liblzma"); + r = ARCHIVE_FATAL; + break; + } + return (r); +} + +static int +compression_code_lzma(struct archive *a, + struct la_zstream *lastrm, enum la_zaction action) +{ + lzma_stream *strm; + int r; + + strm = (lzma_stream *)lastrm->real_stream; + strm->next_in = lastrm->next_in; + strm->avail_in = lastrm->avail_in; + strm->total_in = lastrm->total_in; + strm->next_out = lastrm->next_out; + strm->avail_out = lastrm->avail_out; + strm->total_out = lastrm->total_out; + r = lzma_code(strm, + (action == ARCHIVE_Z_FINISH)? LZMA_FINISH: LZMA_RUN); + lastrm->next_in = strm->next_in; + lastrm->avail_in = strm->avail_in; + lastrm->total_in = strm->total_in; + lastrm->next_out = strm->next_out; + lastrm->avail_out = strm->avail_out; + lastrm->total_out = strm->total_out; + switch (r) { + case LZMA_OK: + /* Non-finishing case */ + return (ARCHIVE_OK); + case LZMA_STREAM_END: + /* This return can only occur in finishing case. */ + return (ARCHIVE_EOF); + case LZMA_MEMLIMIT_ERROR: + archive_set_error(a, ENOMEM, + "lzma compression error:" + " %ju MiB would have been needed", + (uintmax_t)((lzma_memusage(strm) + 1024 * 1024 -1) + / (1024 * 1024))); + return (ARCHIVE_FATAL); + default: + /* Any other return value indicates an error */ + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "lzma compression failed:" + " lzma_code() call returned status %d", r); + return (ARCHIVE_FATAL); + } +} + +static int +compression_end_lzma(struct archive *a, struct la_zstream *lastrm) +{ + lzma_stream *strm; + + (void)a; /* UNUSED */ + strm = (lzma_stream *)lastrm->real_stream; + lzma_end(strm); + free(strm); + lastrm->valid = 0; + lastrm->real_stream = NULL; + return (ARCHIVE_OK); +} +#else +static int +compression_init_encoder_lzma(struct archive *a, + struct la_zstream *lastrm, int level) +{ + + (void) level; /* UNUSED */ + if (lastrm->valid) + compression_end(a, lastrm); + return (compression_unsupported_encoder(a, lastrm, "lzma")); +} +static int +compression_init_encoder_xz(struct archive *a, + struct la_zstream *lastrm, int level, int threads) +{ + + (void) level; /* UNUSED */ + (void) threads; /* UNUSED */ + if (lastrm->valid) + compression_end(a, lastrm); + return (compression_unsupported_encoder(a, lastrm, "xz")); +} +#endif + +static int +xar_compression_init_encoder(struct archive_write *a) +{ + struct xar *xar; + int r; + + xar = (struct xar *)a->format_data; + switch (xar->opt_compression) { + case GZIP: + r = compression_init_encoder_gzip( + &(a->archive), &(xar->stream), + xar->opt_compression_level, 1); + break; + case BZIP2: + r = compression_init_encoder_bzip2( + &(a->archive), &(xar->stream), + xar->opt_compression_level); + break; + case LZMA: + r = compression_init_encoder_lzma( + &(a->archive), &(xar->stream), + xar->opt_compression_level); + break; + case XZ: + r = compression_init_encoder_xz( + &(a->archive), &(xar->stream), + xar->opt_compression_level, xar->opt_threads); + break; + default: + r = ARCHIVE_OK; + break; + } + if (r == ARCHIVE_OK) { + xar->stream.total_in = 0; + xar->stream.next_out = xar->wbuff; + xar->stream.avail_out = sizeof(xar->wbuff); + xar->stream.total_out = 0; + } + + return (r); +} + +static int +compression_code(struct archive *a, struct la_zstream *lastrm, + enum la_zaction action) +{ + if (lastrm->valid) + return (lastrm->code(a, lastrm, action)); + return (ARCHIVE_OK); +} + +static int +compression_end(struct archive *a, struct la_zstream *lastrm) +{ + if (lastrm->valid) + return (lastrm->end(a, lastrm)); + return (ARCHIVE_OK); +} + + +static int +save_xattrs(struct archive_write *a, struct file *file) +{ + struct xar *xar; + const char *name; + const void *value; + struct heap_data *heap; + size_t size; + int count, r; + + xar = (struct xar *)a->format_data; + count = archive_entry_xattr_reset(file->entry); + if (count == 0) + return (ARCHIVE_OK); + while (count--) { + archive_entry_xattr_next(file->entry, + &name, &value, &size); + checksum_init(&(xar->a_sumwrk), xar->opt_sumalg); + checksum_init(&(xar->e_sumwrk), xar->opt_sumalg); + + heap = calloc(1, sizeof(*heap)); + if (heap == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for xattr"); + return (ARCHIVE_FATAL); + } + heap->id = file->ea_idx++; + heap->temp_offset = xar->temp_offset; + heap->size = size;/* save a extracted size */ + heap->compression = xar->opt_compression; + /* Get a extracted sumcheck value. */ + checksum_update(&(xar->e_sumwrk), value, size); + checksum_final(&(xar->e_sumwrk), &(heap->e_sum)); + + /* + * Not compression to xattr is simple way. + */ + if (heap->compression == NONE) { + checksum_update(&(xar->a_sumwrk), value, size); + checksum_final(&(xar->a_sumwrk), &(heap->a_sum)); + if (write_to_temp(a, value, size) + != ARCHIVE_OK) { + free(heap); + return (ARCHIVE_FATAL); + } + heap->length = size; + /* Add heap to the tail of file->xattr. */ + heap->next = NULL; + *file->xattr.last = heap; + file->xattr.last = &(heap->next); + /* Next xattr */ + continue; + } + + /* + * Init compression library. + */ + r = xar_compression_init_encoder(a); + if (r != ARCHIVE_OK) { + free(heap); + return (ARCHIVE_FATAL); + } + + xar->stream.next_in = (const unsigned char *)value; + xar->stream.avail_in = size; + for (;;) { + r = compression_code(&(a->archive), + &(xar->stream), ARCHIVE_Z_FINISH); + if (r != ARCHIVE_OK && r != ARCHIVE_EOF) { + free(heap); + return (ARCHIVE_FATAL); + } + size = sizeof(xar->wbuff) - xar->stream.avail_out; + checksum_update(&(xar->a_sumwrk), + xar->wbuff, size); + if (write_to_temp(a, xar->wbuff, size) + != ARCHIVE_OK) + return (ARCHIVE_FATAL); + if (r == ARCHIVE_OK) { + xar->stream.next_out = xar->wbuff; + xar->stream.avail_out = sizeof(xar->wbuff); + } else { + checksum_final(&(xar->a_sumwrk), + &(heap->a_sum)); + heap->length = xar->stream.total_out; + /* Add heap to the tail of file->xattr. */ + heap->next = NULL; + *file->xattr.last = heap; + file->xattr.last = &(heap->next); + break; + } + } + /* Clean up compression library. */ + r = compression_end(&(a->archive), &(xar->stream)); + if (r != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + return (ARCHIVE_OK); +} + +static int +getalgsize(enum sumalg sumalg) +{ + switch (sumalg) { + default: + case CKSUM_NONE: + return (0); + case CKSUM_SHA1: + return (SHA1_SIZE); + case CKSUM_MD5: + return (MD5_SIZE); + } +} + +static const char * +getalgname(enum sumalg sumalg) +{ + switch (sumalg) { + default: + case CKSUM_NONE: + return (NULL); + case CKSUM_SHA1: + return (SHA1_NAME); + case CKSUM_MD5: + return (MD5_NAME); + } +} + +#endif /* Support xar format */ diff --cc Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c index 0b2c69b,0000000..a4ae229 mode 100644,000000..100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_zip.c @@@ -1,1678 -1,0 +1,1678 @@@ +/*- + * Copyright (c) 2008 Anselm Strauss + * Copyright (c) 2009 Joerg Sonnenberger + * Copyright (c) 2011-2012,2014 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Development supported by Google Summer of Code 2008. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_zip.c 201168 2009-12-29 06:15:32Z kientzle $"); + +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_LANGINFO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_ZLIB_H +#include +#endif + +#include "archive.h" +#include "archive_cryptor_private.h" +#include "archive_endian.h" +#include "archive_entry.h" +#include "archive_entry_locale.h" +#include "archive_hmac_private.h" +#include "archive_private.h" +#include "archive_random_private.h" +#include "archive_write_private.h" + +#ifndef HAVE_ZLIB_H +#include "archive_crc32.h" +#endif + +#define ZIP_ENTRY_FLAG_ENCRYPTED (1<<0) +#define ZIP_ENTRY_FLAG_LENGTH_AT_END (1<<3) +#define ZIP_ENTRY_FLAG_UTF8_NAME (1 << 11) + +#define ZIP_4GB_MAX ARCHIVE_LITERAL_LL(0xffffffff) +#define ZIP_4GB_MAX_UNCOMPRESSED ARCHIVE_LITERAL_LL(0xff000000) + +enum compression { + COMPRESSION_UNSPECIFIED = -1, + COMPRESSION_STORE = 0, + COMPRESSION_DEFLATE = 8 +}; + +#ifdef HAVE_ZLIB_H +#define COMPRESSION_DEFAULT COMPRESSION_DEFLATE +#else +#define COMPRESSION_DEFAULT COMPRESSION_STORE +#endif + +enum encryption { + ENCRYPTION_NONE = 0, + ENCRYPTION_TRADITIONAL, /* Traditional PKWARE encryption. */ + ENCRYPTION_WINZIP_AES128, /* WinZIP AES-128 encryption. */ + ENCRYPTION_WINZIP_AES256, /* WinZIP AES-256 encryption. */ +}; + +#define TRAD_HEADER_SIZE 12 +/* + * See "WinZip - AES Encryption Information" + * http://www.winzip.com/aes_info.htm + */ +/* Value used in compression method. */ +#define WINZIP_AES_ENCRYPTION 99 +/* A WinZip AES header size which is stored at the beginning of + * file contents. */ +#define WINZIP_AES128_HEADER_SIZE (8 + 2) +#define WINZIP_AES256_HEADER_SIZE (16 + 2) +/* AES vendor version. */ +#define AES_VENDOR_AE_1 0x0001 +#define AES_VENDOR_AE_2 0x0002 +/* Authentication code size. */ +#define AUTH_CODE_SIZE 10 +/**/ +#define MAX_DERIVED_KEY_BUF_SIZE (AES_MAX_KEY_SIZE * 2 + 2) + +struct cd_segment { + struct cd_segment *next; + size_t buff_size; + unsigned char *buff; + unsigned char *p; +}; + +struct trad_enc_ctx { + uint32_t keys[3]; +}; + +struct zip { + + int64_t entry_offset; + int64_t entry_compressed_size; + int64_t entry_uncompressed_size; + int64_t entry_compressed_written; + int64_t entry_uncompressed_written; + int64_t entry_uncompressed_limit; + struct archive_entry *entry; + uint32_t entry_crc32; + enum compression entry_compression; + enum encryption entry_encryption; + int entry_flags; + int entry_uses_zip64; + int experiments; + struct trad_enc_ctx tctx; + char tctx_valid; + unsigned char trad_chkdat; + unsigned aes_vendor; + archive_crypto_ctx cctx; + char cctx_valid; + archive_hmac_sha1_ctx hctx; + char hctx_valid; + + unsigned char *file_header; + size_t file_header_extra_offset; + unsigned long (*crc32func)(unsigned long crc, const void *buff, size_t len); + + struct cd_segment *central_directory; + struct cd_segment *central_directory_last; + size_t central_directory_bytes; + size_t central_directory_entries; + + int64_t written_bytes; /* Overall position in file. */ + + struct archive_string_conv *opt_sconv; + struct archive_string_conv *sconv_default; + enum compression requested_compression; + int deflate_compression_level; + int init_default_conversion; + enum encryption encryption_type; + +#define ZIP_FLAG_AVOID_ZIP64 1 +#define ZIP_FLAG_FORCE_ZIP64 2 +#define ZIP_FLAG_EXPERIMENT_xl 4 + int flags; + +#ifdef HAVE_ZLIB_H + z_stream stream; +#endif + size_t len_buf; + unsigned char *buf; +}; + +/* Don't call this min or MIN, since those are already defined + on lots of platforms (but not all). */ +#define zipmin(a, b) ((a) > (b) ? (b) : (a)) + +static ssize_t archive_write_zip_data(struct archive_write *, + const void *buff, size_t s); +static int archive_write_zip_close(struct archive_write *); +static int archive_write_zip_free(struct archive_write *); +static int archive_write_zip_finish_entry(struct archive_write *); +static int archive_write_zip_header(struct archive_write *, + struct archive_entry *); +static int archive_write_zip_options(struct archive_write *, + const char *, const char *); +static unsigned int dos_time(const time_t); +static size_t path_length(struct archive_entry *); +static int write_path(struct archive_entry *, struct archive_write *); +static void copy_path(struct archive_entry *, unsigned char *); +static struct archive_string_conv *get_sconv(struct archive_write *, struct zip *); +static int trad_enc_init(struct trad_enc_ctx *, const char *, size_t); +static unsigned trad_enc_encrypt_update(struct trad_enc_ctx *, const uint8_t *, + size_t, uint8_t *, size_t); +static int init_traditional_pkware_encryption(struct archive_write *); +static int is_traditional_pkware_encryption_supported(void); +static int init_winzip_aes_encryption(struct archive_write *); +static int is_winzip_aes_encryption_supported(int encryption); + +static unsigned char * +cd_alloc(struct zip *zip, size_t length) +{ + unsigned char *p; + + if (zip->central_directory == NULL + || (zip->central_directory_last->p + length + > zip->central_directory_last->buff + zip->central_directory_last->buff_size)) { + struct cd_segment *segment = calloc(1, sizeof(*segment)); + if (segment == NULL) + return NULL; + segment->buff_size = 64 * 1024; + segment->buff = malloc(segment->buff_size); + if (segment->buff == NULL) { + free(segment); + return NULL; + } + segment->p = segment->buff; + + if (zip->central_directory == NULL) { + zip->central_directory + = zip->central_directory_last + = segment; + } else { + zip->central_directory_last->next = segment; + zip->central_directory_last = segment; + } + } + + p = zip->central_directory_last->p; + zip->central_directory_last->p += length; + zip->central_directory_bytes += length; + return (p); +} + +static unsigned long +real_crc32(unsigned long crc, const void *buff, size_t len) +{ + return crc32(crc, buff, (unsigned int)len); +} + +static unsigned long +fake_crc32(unsigned long crc, const void *buff, size_t len) +{ + (void)crc; /* UNUSED */ + (void)buff; /* UNUSED */ + (void)len; /* UNUSED */ + return 0; +} + +static int +archive_write_zip_options(struct archive_write *a, const char *key, + const char *val) +{ + struct zip *zip = a->format_data; + int ret = ARCHIVE_FAILED; + + if (strcmp(key, "compression") == 0) { + /* + * Set compression to use on all future entries. + * This only affects regular files. + */ + if (val == NULL || val[0] == 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "%s: compression option needs a compression name", + a->format_name); + } else if (strcmp(val, "deflate") == 0) { +#ifdef HAVE_ZLIB_H + zip->requested_compression = COMPRESSION_DEFLATE; + ret = ARCHIVE_OK; +#else + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "deflate compression not supported"); +#endif + } else if (strcmp(val, "store") == 0) { + zip->requested_compression = COMPRESSION_STORE; + ret = ARCHIVE_OK; + } + return (ret); + } else if (strcmp(key, "compression-level") == 0) { + if (val == NULL || !(val[0] >= '0' && val[0] <= '9') || val[1] != '\0') { + return ARCHIVE_WARN; + } + + if (val[0] == '0') { + zip->requested_compression = COMPRESSION_STORE; + return ARCHIVE_OK; + } else { +#ifdef HAVE_ZLIB_H + zip->requested_compression = COMPRESSION_DEFLATE; + zip->deflate_compression_level = val[0] - '0'; + return ARCHIVE_OK; +#else + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "deflate compression not supported"); +#endif + } + } else if (strcmp(key, "encryption") == 0) { + if (val == NULL) { + zip->encryption_type = ENCRYPTION_NONE; + ret = ARCHIVE_OK; + } else if (val[0] == '1' || strcmp(val, "traditional") == 0 + || strcmp(val, "zipcrypt") == 0 + || strcmp(val, "ZipCrypt") == 0) { + if (is_traditional_pkware_encryption_supported()) { + zip->encryption_type = ENCRYPTION_TRADITIONAL; + ret = ARCHIVE_OK; + } else { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "encryption not supported"); + } + } else if (strcmp(val, "aes128") == 0) { + if (is_winzip_aes_encryption_supported( + ENCRYPTION_WINZIP_AES128)) { + zip->encryption_type = ENCRYPTION_WINZIP_AES128; + ret = ARCHIVE_OK; + } else { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "encryption not supported"); + } + } else if (strcmp(val, "aes256") == 0) { + if (is_winzip_aes_encryption_supported( + ENCRYPTION_WINZIP_AES256)) { + zip->encryption_type = ENCRYPTION_WINZIP_AES256; + ret = ARCHIVE_OK; + } else { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "encryption not supported"); + } + } else { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "%s: unknown encryption '%s'", + a->format_name, val); + } + return (ret); + } else if (strcmp(key, "experimental") == 0) { + if (val == NULL || val[0] == 0) { + zip->flags &= ~ ZIP_FLAG_EXPERIMENT_xl; + } else { + zip->flags |= ZIP_FLAG_EXPERIMENT_xl; + } + return (ARCHIVE_OK); + } else if (strcmp(key, "fakecrc32") == 0) { + /* + * FOR TESTING ONLY: disable CRC calculation to speed up + * certain complex tests. + */ + if (val == NULL || val[0] == 0) { + zip->crc32func = real_crc32; + } else { + zip->crc32func = fake_crc32; + } + return (ARCHIVE_OK); + } else if (strcmp(key, "hdrcharset") == 0) { + /* + * Set the character set used in translating filenames. + */ + if (val == NULL || val[0] == 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "%s: hdrcharset option needs a character-set name", + a->format_name); + } else { + zip->opt_sconv = archive_string_conversion_to_charset( + &a->archive, val, 0); + if (zip->opt_sconv != NULL) + ret = ARCHIVE_OK; + else + ret = ARCHIVE_FATAL; + } + return (ret); + } else if (strcmp(key, "zip64") == 0) { + /* + * Bias decisions about Zip64: force them to be + * generated in certain cases where they are not + * forbidden or avoid them in certain cases where they + * are not strictly required. + */ + if (val != NULL && *val != '\0') { + zip->flags |= ZIP_FLAG_FORCE_ZIP64; + zip->flags &= ~ZIP_FLAG_AVOID_ZIP64; + } else { + zip->flags &= ~ZIP_FLAG_FORCE_ZIP64; + zip->flags |= ZIP_FLAG_AVOID_ZIP64; + } + return (ARCHIVE_OK); + } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ + return (ARCHIVE_WARN); +} + +int +archive_write_zip_set_compression_deflate(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + int ret = ARCHIVE_FAILED; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW | ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, + "archive_write_zip_set_compression_deflate"); + if (a->archive.archive_format != ARCHIVE_FORMAT_ZIP) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can only use archive_write_zip_set_compression_deflate" + " with zip format"); + ret = ARCHIVE_FATAL; + } else { +#ifdef HAVE_ZLIB_H + struct zip *zip = a->format_data; + zip->requested_compression = COMPRESSION_DEFLATE; + ret = ARCHIVE_OK; +#else + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "deflate compression not supported"); + ret = ARCHIVE_FAILED; +#endif + } + return (ret); +} + +int +archive_write_zip_set_compression_store(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct zip *zip = a->format_data; + int ret = ARCHIVE_FAILED; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW | ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, + "archive_write_zip_set_compression_deflate"); + if (a->archive.archive_format != ARCHIVE_FORMAT_ZIP) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can only use archive_write_zip_set_compression_store" + " with zip format"); + ret = ARCHIVE_FATAL; + } else { + zip->requested_compression = COMPRESSION_STORE; + ret = ARCHIVE_OK; + } + return (ret); +} + +int +archive_write_set_format_zip(struct archive *_a) +{ + struct archive_write *a = (struct archive_write *)_a; + struct zip *zip; + + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_set_format_zip"); + + /* If another format was already registered, unregister it. */ + if (a->format_free != NULL) + (a->format_free)(a); + + zip = (struct zip *) calloc(1, sizeof(*zip)); + if (zip == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate zip data"); + return (ARCHIVE_FATAL); + } + + /* "Unspecified" lets us choose the appropriate compression. */ + zip->requested_compression = COMPRESSION_UNSPECIFIED; +#ifdef HAVE_ZLIB_H + zip->deflate_compression_level = Z_DEFAULT_COMPRESSION; +#endif + zip->crc32func = real_crc32; + + /* A buffer used for both compression and encryption. */ + zip->len_buf = 65536; + zip->buf = malloc(zip->len_buf); + if (zip->buf == NULL) { + free(zip); + archive_set_error(&a->archive, ENOMEM, + "Can't allocate compression buffer"); + return (ARCHIVE_FATAL); + } + + a->format_data = zip; + a->format_name = "zip"; + a->format_options = archive_write_zip_options; + a->format_write_header = archive_write_zip_header; + a->format_write_data = archive_write_zip_data; + a->format_finish_entry = archive_write_zip_finish_entry; + a->format_close = archive_write_zip_close; + a->format_free = archive_write_zip_free; + a->archive.archive_format = ARCHIVE_FORMAT_ZIP; + a->archive.archive_format_name = "ZIP"; + + return (ARCHIVE_OK); +} + +static int +is_all_ascii(const char *p) +{ + const unsigned char *pp = (const unsigned char *)p; + + while (*pp) { + if (*pp++ > 127) + return (0); + } + return (1); +} + +static int +archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) +{ + unsigned char local_header[32]; + unsigned char local_extra[144]; + struct zip *zip = a->format_data; + unsigned char *e; + unsigned char *cd_extra; + size_t filename_length; + const char *slink = NULL; + size_t slink_size = 0; + struct archive_string_conv *sconv = get_sconv(a, zip); + int ret, ret2 = ARCHIVE_OK; + mode_t type; + int version_needed = 10; + + /* Ignore types of entries that we don't support. */ + type = archive_entry_filetype(entry); + if (type != AE_IFREG && type != AE_IFDIR && type != AE_IFLNK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Filetype not supported"); + return ARCHIVE_FAILED; + }; + + /* If we're not using Zip64, reject large files. */ + if (zip->flags & ZIP_FLAG_AVOID_ZIP64) { + /* Reject entries over 4GB. */ + if (archive_entry_size_is_set(entry) + && (archive_entry_size(entry) > ZIP_4GB_MAX)) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Files > 4GB require Zip64 extensions"); + return ARCHIVE_FAILED; + } + /* Reject entries if archive is > 4GB. */ + if (zip->written_bytes > ZIP_4GB_MAX) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Archives > 4GB require Zip64 extensions"); + return ARCHIVE_FAILED; + } + } + + /* Only regular files can have size > 0. */ + if (type != AE_IFREG) + archive_entry_set_size(entry, 0); + + + /* Reset information from last entry. */ + zip->entry_offset = zip->written_bytes; + zip->entry_uncompressed_limit = INT64_MAX; + zip->entry_compressed_size = 0; + zip->entry_uncompressed_size = 0; + zip->entry_compressed_written = 0; + zip->entry_uncompressed_written = 0; + zip->entry_flags = 0; + zip->entry_uses_zip64 = 0; + zip->entry_crc32 = zip->crc32func(0, NULL, 0); + zip->entry_encryption = 0; + if (zip->entry != NULL) { + archive_entry_free(zip->entry); + zip->entry = NULL; + } + + if (zip->cctx_valid) + archive_encrypto_aes_ctr_release(&zip->cctx); + if (zip->hctx_valid) + archive_hmac_sha1_cleanup(&zip->hctx); + zip->tctx_valid = zip->cctx_valid = zip->hctx_valid = 0; + + if (type == AE_IFREG + &&(!archive_entry_size_is_set(entry) + || archive_entry_size(entry) > 0)) { + switch (zip->encryption_type) { + case ENCRYPTION_TRADITIONAL: + case ENCRYPTION_WINZIP_AES128: + case ENCRYPTION_WINZIP_AES256: + zip->entry_flags |= ZIP_ENTRY_FLAG_ENCRYPTED; + zip->entry_encryption = zip->encryption_type; + break; + default: + break; + } + } + + +#if defined(_WIN32) && !defined(__CYGWIN__) - /* Make sure the path separators in pahtname, hardlink and symlink ++ /* Make sure the path separators in pathname, hardlink and symlink + * are all slash '/', not the Windows path separator '\'. */ + zip->entry = __la_win_entry_in_posix_pathseparator(entry); + if (zip->entry == entry) + zip->entry = archive_entry_clone(entry); +#else + zip->entry = archive_entry_clone(entry); +#endif + if (zip->entry == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate zip header data"); + return (ARCHIVE_FATAL); + } + + if (sconv != NULL) { + const char *p; + size_t len; + + if (archive_entry_pathname_l(entry, &p, &len, sconv) != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Pathname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate Pathname '%s' to %s", + archive_entry_pathname(entry), + archive_string_conversion_charset_name(sconv)); + ret2 = ARCHIVE_WARN; + } + if (len > 0) + archive_entry_set_pathname(zip->entry, p); + + /* + * There is no standard for symlink handling; we convert + * it using the same character-set translation that we use + * for filename. + */ + if (type == AE_IFLNK) { + if (archive_entry_symlink_l(entry, &p, &len, sconv)) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory " + " for Symlink"); + return (ARCHIVE_FATAL); + } + /* No error if we can't convert. */ + } else if (len > 0) + archive_entry_set_symlink(zip->entry, p); + } + } + + /* If filename isn't ASCII and we can use UTF-8, set the UTF-8 flag. */ + if (!is_all_ascii(archive_entry_pathname(zip->entry))) { + if (zip->opt_sconv != NULL) { + if (strcmp(archive_string_conversion_charset_name( + zip->opt_sconv), "UTF-8") == 0) + zip->entry_flags |= ZIP_ENTRY_FLAG_UTF8_NAME; +#if HAVE_NL_LANGINFO + } else if (strcmp(nl_langinfo(CODESET), "UTF-8") == 0) { + zip->entry_flags |= ZIP_ENTRY_FLAG_UTF8_NAME; +#endif + } + } + filename_length = path_length(zip->entry); + + /* Determine appropriate compression and size for this entry. */ + if (type == AE_IFLNK) { + slink = archive_entry_symlink(zip->entry); + if (slink != NULL) + slink_size = strlen(slink); + else + slink_size = 0; + zip->entry_uncompressed_limit = slink_size; + zip->entry_compressed_size = slink_size; + zip->entry_uncompressed_size = slink_size; + zip->entry_crc32 = zip->crc32func(zip->entry_crc32, + (const unsigned char *)slink, slink_size); + zip->entry_compression = COMPRESSION_STORE; + version_needed = 20; + } else if (type != AE_IFREG) { + zip->entry_compression = COMPRESSION_STORE; + zip->entry_uncompressed_limit = 0; + version_needed = 20; + } else if (archive_entry_size_is_set(zip->entry)) { + int64_t size = archive_entry_size(zip->entry); + int64_t additional_size = 0; + + zip->entry_uncompressed_limit = size; + zip->entry_compression = zip->requested_compression; + if (zip->entry_compression == COMPRESSION_UNSPECIFIED) { + zip->entry_compression = COMPRESSION_DEFAULT; + } + if (zip->entry_compression == COMPRESSION_STORE) { + zip->entry_compressed_size = size; + zip->entry_uncompressed_size = size; + version_needed = 10; + } else { + zip->entry_uncompressed_size = size; + version_needed = 20; + } + + if (zip->entry_flags & ZIP_ENTRY_FLAG_ENCRYPTED) { + switch (zip->entry_encryption) { + case ENCRYPTION_TRADITIONAL: + additional_size = TRAD_HEADER_SIZE; + version_needed = 20; + break; + case ENCRYPTION_WINZIP_AES128: + additional_size = WINZIP_AES128_HEADER_SIZE + + AUTH_CODE_SIZE; + version_needed = 20; + break; + case ENCRYPTION_WINZIP_AES256: + additional_size = WINZIP_AES256_HEADER_SIZE + + AUTH_CODE_SIZE; + version_needed = 20; + break; + default: + break; + } + if (zip->entry_compression == COMPRESSION_STORE) + zip->entry_compressed_size += additional_size; + } + + /* + * Set Zip64 extension in any of the following cases + * (this was suggested by discussion on info-zip-dev + * mailing list): + * = Zip64 is being forced by user + * = File is over 4GiB uncompressed + * (including encryption header, if any) + * = File is close to 4GiB and is being compressed + * (compression might make file larger) + */ + if ((zip->flags & ZIP_FLAG_FORCE_ZIP64) + || (zip->entry_uncompressed_size + additional_size > ZIP_4GB_MAX) + || (zip->entry_uncompressed_size > ZIP_4GB_MAX_UNCOMPRESSED + && zip->entry_compression != COMPRESSION_STORE)) { + zip->entry_uses_zip64 = 1; + version_needed = 45; + } + + /* We may know the size, but never the CRC. */ + zip->entry_flags |= ZIP_ENTRY_FLAG_LENGTH_AT_END; + } else { + /* We don't know the size. In this case, we prefer + * deflate (it has a clear end-of-data marker which + * makes length-at-end more reliable) and will + * enable Zip64 extensions unless we're told not to. + */ + zip->entry_compression = COMPRESSION_DEFAULT; + zip->entry_flags |= ZIP_ENTRY_FLAG_LENGTH_AT_END; + if ((zip->flags & ZIP_FLAG_AVOID_ZIP64) == 0) { + zip->entry_uses_zip64 = 1; + version_needed = 45; + } else if (zip->entry_compression == COMPRESSION_STORE) { + version_needed = 10; + } else { + version_needed = 20; + } + + if (zip->entry_flags & ZIP_ENTRY_FLAG_ENCRYPTED) { + switch (zip->entry_encryption) { + case ENCRYPTION_TRADITIONAL: + case ENCRYPTION_WINZIP_AES128: + case ENCRYPTION_WINZIP_AES256: + if (version_needed < 20) + version_needed = 20; + break; + default: + break; + } + } + } + + /* Format the local header. */ + memset(local_header, 0, sizeof(local_header)); + memcpy(local_header, "PK\003\004", 4); + archive_le16enc(local_header + 4, version_needed); + archive_le16enc(local_header + 6, zip->entry_flags); + if (zip->entry_encryption == ENCRYPTION_WINZIP_AES128 + || zip->entry_encryption == ENCRYPTION_WINZIP_AES256) + archive_le16enc(local_header + 8, WINZIP_AES_ENCRYPTION); + else + archive_le16enc(local_header + 8, zip->entry_compression); + archive_le32enc(local_header + 10, + dos_time(archive_entry_mtime(zip->entry))); + archive_le32enc(local_header + 14, zip->entry_crc32); + if (zip->entry_uses_zip64) { + /* Zip64 data in the local header "must" include both + * compressed and uncompressed sizes AND those fields + * are included only if these are 0xffffffff; + * THEREFORE these must be set this way, even if we + * know one of them is smaller. */ + archive_le32enc(local_header + 18, ZIP_4GB_MAX); + archive_le32enc(local_header + 22, ZIP_4GB_MAX); + } else { + archive_le32enc(local_header + 18, (uint32_t)zip->entry_compressed_size); + archive_le32enc(local_header + 22, (uint32_t)zip->entry_uncompressed_size); + } + archive_le16enc(local_header + 26, (uint16_t)filename_length); + + if (zip->entry_encryption == ENCRYPTION_TRADITIONAL) { + if (zip->entry_flags & ZIP_ENTRY_FLAG_LENGTH_AT_END) + zip->trad_chkdat = local_header[11]; + else + zip->trad_chkdat = local_header[17]; + } + + /* Format as much of central directory file header as we can: */ + zip->file_header = cd_alloc(zip, 46); + /* If (zip->file_header == NULL) XXXX */ + ++zip->central_directory_entries; + memset(zip->file_header, 0, 46); + memcpy(zip->file_header, "PK\001\002", 4); + /* "Made by PKZip 2.0 on Unix." */ + archive_le16enc(zip->file_header + 4, 3 * 256 + version_needed); + archive_le16enc(zip->file_header + 6, version_needed); + archive_le16enc(zip->file_header + 8, zip->entry_flags); + if (zip->entry_encryption == ENCRYPTION_WINZIP_AES128 + || zip->entry_encryption == ENCRYPTION_WINZIP_AES256) + archive_le16enc(zip->file_header + 10, WINZIP_AES_ENCRYPTION); + else + archive_le16enc(zip->file_header + 10, zip->entry_compression); + archive_le32enc(zip->file_header + 12, + dos_time(archive_entry_mtime(zip->entry))); + archive_le16enc(zip->file_header + 28, (uint16_t)filename_length); + /* Following Info-Zip, store mode in the "external attributes" field. */ + archive_le32enc(zip->file_header + 38, + ((uint32_t)archive_entry_mode(zip->entry)) << 16); + e = cd_alloc(zip, filename_length); + /* If (e == NULL) XXXX */ + copy_path(zip->entry, e); + + /* Format extra data. */ + memset(local_extra, 0, sizeof(local_extra)); + e = local_extra; + + /* First, extra blocks that are the same between + * the local file header and the central directory. + * We format them once and then duplicate them. */ + + /* UT timestamp, length depends on what timestamps are set. */ + memcpy(e, "UT", 2); + archive_le16enc(e + 2, + 1 + + (archive_entry_mtime_is_set(entry) ? 4 : 0) + + (archive_entry_atime_is_set(entry) ? 4 : 0) + + (archive_entry_ctime_is_set(entry) ? 4 : 0)); + e += 4; + *e++ = + (archive_entry_mtime_is_set(entry) ? 1 : 0) + | (archive_entry_atime_is_set(entry) ? 2 : 0) + | (archive_entry_ctime_is_set(entry) ? 4 : 0); + if (archive_entry_mtime_is_set(entry)) { + archive_le32enc(e, (uint32_t)archive_entry_mtime(entry)); + e += 4; + } + if (archive_entry_atime_is_set(entry)) { + archive_le32enc(e, (uint32_t)archive_entry_atime(entry)); + e += 4; + } + if (archive_entry_ctime_is_set(entry)) { + archive_le32enc(e, (uint32_t)archive_entry_ctime(entry)); + e += 4; + } + + /* ux Unix extra data, length 11, version 1 */ + /* TODO: If uid < 64k, use 2 bytes, ditto for gid. */ + memcpy(e, "ux\013\000\001", 5); + e += 5; + *e++ = 4; /* Length of following UID */ + archive_le32enc(e, (uint32_t)archive_entry_uid(entry)); + e += 4; + *e++ = 4; /* Length of following GID */ + archive_le32enc(e, (uint32_t)archive_entry_gid(entry)); + e += 4; + + /* AES extra data field: WinZIP AES information, ID=0x9901 */ + if ((zip->entry_flags & ZIP_ENTRY_FLAG_ENCRYPTED) + && (zip->entry_encryption == ENCRYPTION_WINZIP_AES128 + || zip->entry_encryption == ENCRYPTION_WINZIP_AES256)) { + + memcpy(e, "\001\231\007\000\001\000AE", 8); - /* AES vendoer version AE-2 does not store a CRC. ++ /* AES vendor version AE-2 does not store a CRC. + * WinZip 11 uses AE-1, which does store the CRC, + * but it does not store the CRC when the file size + * is less than 20 bytes. So we simulate what + * WinZip 11 does. + * NOTE: WinZip 9.0 and 10.0 uses AE-2 by default. */ + if (archive_entry_size_is_set(zip->entry) + && archive_entry_size(zip->entry) < 20) { + archive_le16enc(e+4, AES_VENDOR_AE_2); + zip->aes_vendor = AES_VENDOR_AE_2;/* no CRC. */ + } else + zip->aes_vendor = AES_VENDOR_AE_1; + e += 8; + /* AES encryption strength. */ + *e++ = (zip->entry_encryption == ENCRYPTION_WINZIP_AES128)?1:3; + /* Actual compression method. */ + archive_le16enc(e, zip->entry_compression); + e += 2; + } + + /* Copy UT ,ux, and AES-extra into central directory as well. */ + zip->file_header_extra_offset = zip->central_directory_bytes; + cd_extra = cd_alloc(zip, e - local_extra); + memcpy(cd_extra, local_extra, e - local_extra); + + /* + * Following extra blocks vary between local header and + * central directory. These are the local header versions. + * Central directory versions get formatted in + * archive_write_zip_finish_entry() below. + */ + + /* "[Zip64 entry] in the local header MUST include BOTH + * original [uncompressed] and compressed size fields." */ + if (zip->entry_uses_zip64) { + unsigned char *zip64_start = e; + memcpy(e, "\001\000\020\000", 4); + e += 4; + archive_le64enc(e, zip->entry_uncompressed_size); + e += 8; + archive_le64enc(e, zip->entry_compressed_size); + e += 8; + archive_le16enc(zip64_start + 2, (uint16_t)(e - (zip64_start + 4))); + } + + if (zip->flags & ZIP_FLAG_EXPERIMENT_xl) { + /* Experimental 'xl' extension to improve streaming. */ + unsigned char *external_info = e; + int included = 7; + memcpy(e, "xl\000\000", 4); // 0x6c65 + 2-byte length + e += 4; + e[0] = included; /* bitmap of included fields */ + e += 1; + if (included & 1) { + archive_le16enc(e, /* "Version created by" */ + 3 * 256 + version_needed); + e += 2; + } + if (included & 2) { + archive_le16enc(e, 0); /* internal file attributes */ + e += 2; + } + if (included & 4) { + archive_le32enc(e, /* external file attributes */ + ((uint32_t)archive_entry_mode(zip->entry)) << 16); + e += 4; + } + if (included & 8) { + // Libarchive does not currently support file comments. + } + archive_le16enc(external_info + 2, (uint16_t)(e - (external_info + 4))); + } + + /* Update local header with size of extra data and write it all out: */ + archive_le16enc(local_header + 28, (uint16_t)(e - local_extra)); + + ret = __archive_write_output(a, local_header, 30); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + zip->written_bytes += 30; + + ret = write_path(zip->entry, a); + if (ret <= ARCHIVE_OK) + return (ARCHIVE_FATAL); + zip->written_bytes += ret; + + ret = __archive_write_output(a, local_extra, e - local_extra); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + zip->written_bytes += e - local_extra; + + /* For symlinks, write the body now. */ + if (slink != NULL) { + ret = __archive_write_output(a, slink, slink_size); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + zip->entry_compressed_written += slink_size; + zip->entry_uncompressed_written += slink_size; + zip->written_bytes += slink_size; + } + +#ifdef HAVE_ZLIB_H + if (zip->entry_compression == COMPRESSION_DEFLATE) { + zip->stream.zalloc = Z_NULL; + zip->stream.zfree = Z_NULL; + zip->stream.opaque = Z_NULL; + zip->stream.next_out = zip->buf; + zip->stream.avail_out = (uInt)zip->len_buf; + if (deflateInit2(&zip->stream, zip->deflate_compression_level, + Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY) != Z_OK) { + archive_set_error(&a->archive, ENOMEM, + "Can't init deflate compressor"); + return (ARCHIVE_FATAL); + } + } +#endif + + return (ret2); +} + +static ssize_t +archive_write_zip_data(struct archive_write *a, const void *buff, size_t s) +{ + int ret; + struct zip *zip = a->format_data; + + if ((int64_t)s > zip->entry_uncompressed_limit) + s = (size_t)zip->entry_uncompressed_limit; + zip->entry_uncompressed_written += s; + + if (s == 0) return 0; + + if (zip->entry_flags & ZIP_ENTRY_FLAG_ENCRYPTED) { + switch (zip->entry_encryption) { + case ENCRYPTION_TRADITIONAL: - /* Initialize traditoinal PKWARE encryption context. */ ++ /* Initialize traditional PKWARE encryption context. */ + if (!zip->tctx_valid) { + ret = init_traditional_pkware_encryption(a); + if (ret != ARCHIVE_OK) + return (ret); + zip->tctx_valid = 1; + } + break; + case ENCRYPTION_WINZIP_AES128: + case ENCRYPTION_WINZIP_AES256: + if (!zip->cctx_valid) { + ret = init_winzip_aes_encryption(a); + if (ret != ARCHIVE_OK) + return (ret); + zip->cctx_valid = zip->hctx_valid = 1; + } + break; + default: + break; + } + } + + switch (zip->entry_compression) { + case COMPRESSION_STORE: + if (zip->tctx_valid || zip->cctx_valid) { + const uint8_t *rb = (const uint8_t *)buff; + const uint8_t * const re = rb + s; + + while (rb < re) { + size_t l; + + if (zip->tctx_valid) { + l = trad_enc_encrypt_update(&zip->tctx, + rb, re - rb, + zip->buf, zip->len_buf); + } else { + l = zip->len_buf; + ret = archive_encrypto_aes_ctr_update( + &zip->cctx, + rb, re - rb, zip->buf, &l); + if (ret < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Failed to encrypt file"); + return (ARCHIVE_FAILED); + } + archive_hmac_sha1_update(&zip->hctx, + zip->buf, l); + } + ret = __archive_write_output(a, zip->buf, l); + if (ret != ARCHIVE_OK) + return (ret); + zip->entry_compressed_written += l; + zip->written_bytes += l; + rb += l; + } + } else { + ret = __archive_write_output(a, buff, s); + if (ret != ARCHIVE_OK) + return (ret); + zip->written_bytes += s; + zip->entry_compressed_written += s; + } + break; +#if HAVE_ZLIB_H + case COMPRESSION_DEFLATE: + zip->stream.next_in = (unsigned char*)(uintptr_t)buff; + zip->stream.avail_in = (uInt)s; + do { + ret = deflate(&zip->stream, Z_NO_FLUSH); + if (ret == Z_STREAM_ERROR) + return (ARCHIVE_FATAL); + if (zip->stream.avail_out == 0) { + if (zip->tctx_valid) { + trad_enc_encrypt_update(&zip->tctx, + zip->buf, zip->len_buf, + zip->buf, zip->len_buf); + } else if (zip->cctx_valid) { + size_t outl = zip->len_buf; + ret = archive_encrypto_aes_ctr_update( + &zip->cctx, + zip->buf, zip->len_buf, + zip->buf, &outl); + if (ret < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Failed to encrypt file"); + return (ARCHIVE_FAILED); + } + archive_hmac_sha1_update(&zip->hctx, + zip->buf, zip->len_buf); + } + ret = __archive_write_output(a, zip->buf, + zip->len_buf); + if (ret != ARCHIVE_OK) + return (ret); + zip->entry_compressed_written += zip->len_buf; + zip->written_bytes += zip->len_buf; + zip->stream.next_out = zip->buf; + zip->stream.avail_out = (uInt)zip->len_buf; + } + } while (zip->stream.avail_in != 0); + break; +#endif + + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid ZIP compression type"); + return ARCHIVE_FATAL; + } + + zip->entry_uncompressed_limit -= s; + if (!zip->cctx_valid || zip->aes_vendor != AES_VENDOR_AE_2) + zip->entry_crc32 = + zip->crc32func(zip->entry_crc32, buff, (unsigned)s); + return (s); + +} + +static int +archive_write_zip_finish_entry(struct archive_write *a) +{ + struct zip *zip = a->format_data; + int ret; + +#if HAVE_ZLIB_H + if (zip->entry_compression == COMPRESSION_DEFLATE) { + for (;;) { + size_t remainder; + + ret = deflate(&zip->stream, Z_FINISH); + if (ret == Z_STREAM_ERROR) + return (ARCHIVE_FATAL); + remainder = zip->len_buf - zip->stream.avail_out; + if (zip->tctx_valid) { + trad_enc_encrypt_update(&zip->tctx, + zip->buf, remainder, zip->buf, remainder); + } else if (zip->cctx_valid) { + size_t outl = remainder; + ret = archive_encrypto_aes_ctr_update( + &zip->cctx, zip->buf, remainder, + zip->buf, &outl); + if (ret < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Failed to encrypt file"); + return (ARCHIVE_FAILED); + } + archive_hmac_sha1_update(&zip->hctx, + zip->buf, remainder); + } + ret = __archive_write_output(a, zip->buf, remainder); + if (ret != ARCHIVE_OK) + return (ret); + zip->entry_compressed_written += remainder; + zip->written_bytes += remainder; + zip->stream.next_out = zip->buf; + if (zip->stream.avail_out != 0) + break; + zip->stream.avail_out = (uInt)zip->len_buf; + } + deflateEnd(&zip->stream); + } +#endif + if (zip->hctx_valid) { + uint8_t hmac[20]; + size_t hmac_len = 20; + + archive_hmac_sha1_final(&zip->hctx, hmac, &hmac_len); + ret = __archive_write_output(a, hmac, AUTH_CODE_SIZE); + if (ret != ARCHIVE_OK) + return (ret); + zip->entry_compressed_written += AUTH_CODE_SIZE; + zip->written_bytes += AUTH_CODE_SIZE; + } + + /* Write trailing data descriptor. */ + if ((zip->entry_flags & ZIP_ENTRY_FLAG_LENGTH_AT_END) != 0) { + char d[24]; + memcpy(d, "PK\007\010", 4); + if (zip->cctx_valid && zip->aes_vendor == AES_VENDOR_AE_2) + archive_le32enc(d + 4, 0);/* no CRC.*/ + else + archive_le32enc(d + 4, zip->entry_crc32); + if (zip->entry_uses_zip64) { + archive_le64enc(d + 8, + (uint64_t)zip->entry_compressed_written); + archive_le64enc(d + 16, + (uint64_t)zip->entry_uncompressed_written); + ret = __archive_write_output(a, d, 24); + zip->written_bytes += 24; + } else { + archive_le32enc(d + 8, + (uint32_t)zip->entry_compressed_written); + archive_le32enc(d + 12, + (uint32_t)zip->entry_uncompressed_written); + ret = __archive_write_output(a, d, 16); + zip->written_bytes += 16; + } + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } + + /* Append Zip64 extra data to central directory information. */ + if (zip->entry_compressed_written > ZIP_4GB_MAX + || zip->entry_uncompressed_written > ZIP_4GB_MAX + || zip->entry_offset > ZIP_4GB_MAX) { + unsigned char zip64[32]; + unsigned char *z = zip64, *zd; + memcpy(z, "\001\000\000\000", 4); + z += 4; + if (zip->entry_uncompressed_written >= ZIP_4GB_MAX) { + archive_le64enc(z, zip->entry_uncompressed_written); + z += 8; + } + if (zip->entry_compressed_written >= ZIP_4GB_MAX) { + archive_le64enc(z, zip->entry_compressed_written); + z += 8; + } + if (zip->entry_offset >= ZIP_4GB_MAX) { + archive_le64enc(z, zip->entry_offset); + z += 8; + } + archive_le16enc(zip64 + 2, (uint16_t)(z - (zip64 + 4))); + zd = cd_alloc(zip, z - zip64); + if (zd == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate zip data"); + return (ARCHIVE_FATAL); + } + memcpy(zd, zip64, z - zip64); + /* Zip64 means version needs to be set to at least 4.5 */ + if (archive_le16dec(zip->file_header + 6) < 45) + archive_le16enc(zip->file_header + 6, 45); + } + + /* Fix up central directory file header. */ + if (zip->cctx_valid && zip->aes_vendor == AES_VENDOR_AE_2) + archive_le32enc(zip->file_header + 16, 0);/* no CRC.*/ + else + archive_le32enc(zip->file_header + 16, zip->entry_crc32); + archive_le32enc(zip->file_header + 20, + (uint32_t)zipmin(zip->entry_compressed_written, + ZIP_4GB_MAX)); + archive_le32enc(zip->file_header + 24, + (uint32_t)zipmin(zip->entry_uncompressed_written, + ZIP_4GB_MAX)); + archive_le16enc(zip->file_header + 30, + (uint16_t)(zip->central_directory_bytes - zip->file_header_extra_offset)); + archive_le32enc(zip->file_header + 42, + (uint32_t)zipmin(zip->entry_offset, + ZIP_4GB_MAX)); + + return (ARCHIVE_OK); +} + +static int +archive_write_zip_close(struct archive_write *a) +{ + uint8_t buff[64]; + int64_t offset_start, offset_end; + struct zip *zip = a->format_data; + struct cd_segment *segment; + int ret; + + offset_start = zip->written_bytes; + segment = zip->central_directory; + while (segment != NULL) { + ret = __archive_write_output(a, + segment->buff, segment->p - segment->buff); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + zip->written_bytes += segment->p - segment->buff; + segment = segment->next; + } + offset_end = zip->written_bytes; + + /* If central dir info is too large, write Zip64 end-of-cd */ + if (offset_end - offset_start > ZIP_4GB_MAX + || offset_start > ZIP_4GB_MAX + || zip->central_directory_entries > 0xffffUL + || (zip->flags & ZIP_FLAG_FORCE_ZIP64)) { + /* Zip64 end-of-cd record */ + memset(buff, 0, 56); + memcpy(buff, "PK\006\006", 4); + archive_le64enc(buff + 4, 44); + archive_le16enc(buff + 12, 45); + archive_le16enc(buff + 14, 45); + /* This is disk 0 of 0. */ + archive_le64enc(buff + 24, zip->central_directory_entries); + archive_le64enc(buff + 32, zip->central_directory_entries); + archive_le64enc(buff + 40, offset_end - offset_start); + archive_le64enc(buff + 48, offset_start); + ret = __archive_write_output(a, buff, 56); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + zip->written_bytes += 56; + + /* Zip64 end-of-cd locator record. */ + memset(buff, 0, 20); + memcpy(buff, "PK\006\007", 4); + archive_le32enc(buff + 4, 0); + archive_le64enc(buff + 8, offset_end); + archive_le32enc(buff + 16, 1); + ret = __archive_write_output(a, buff, 20); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + zip->written_bytes += 20; + + } + + /* Format and write end of central directory. */ + memset(buff, 0, sizeof(buff)); + memcpy(buff, "PK\005\006", 4); + archive_le16enc(buff + 8, (uint16_t)zipmin(0xffffU, + zip->central_directory_entries)); + archive_le16enc(buff + 10, (uint16_t)zipmin(0xffffU, + zip->central_directory_entries)); + archive_le32enc(buff + 12, + (uint32_t)zipmin(ZIP_4GB_MAX, (offset_end - offset_start))); + archive_le32enc(buff + 16, + (uint32_t)zipmin(ZIP_4GB_MAX, offset_start)); + ret = __archive_write_output(a, buff, 22); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + zip->written_bytes += 22; + return (ARCHIVE_OK); +} + +static int +archive_write_zip_free(struct archive_write *a) +{ + struct zip *zip; + struct cd_segment *segment; + + zip = a->format_data; + while (zip->central_directory != NULL) { + segment = zip->central_directory; + zip->central_directory = segment->next; + free(segment->buff); + free(segment); + } + free(zip->buf); + archive_entry_free(zip->entry); + if (zip->cctx_valid) + archive_encrypto_aes_ctr_release(&zip->cctx); + if (zip->hctx_valid) + archive_hmac_sha1_cleanup(&zip->hctx); + /* TODO: Free opt_sconv, sconv_default */ + + free(zip); + a->format_data = NULL; + return (ARCHIVE_OK); +} + +/* Convert into MSDOS-style date/time. */ +static unsigned int +dos_time(const time_t unix_time) +{ + struct tm *t; + unsigned int dt; + + /* This will not preserve time when creating/extracting the archive + * on two systems with different time zones. */ + t = localtime(&unix_time); + + /* MSDOS-style date/time is only between 1980-01-01 and 2107-12-31 */ + if (t->tm_year < 1980 - 1900) + /* Set minimum date/time '1980-01-01 00:00:00'. */ + dt = 0x00210000U; + else if (t->tm_year > 2107 - 1900) + /* Set maximum date/time '2107-12-31 23:59:58'. */ + dt = 0xff9fbf7dU; + else { + dt = 0; + dt += ((t->tm_year - 80) & 0x7f) << 9; + dt += ((t->tm_mon + 1) & 0x0f) << 5; + dt += (t->tm_mday & 0x1f); + dt <<= 16; + dt += (t->tm_hour & 0x1f) << 11; + dt += (t->tm_min & 0x3f) << 5; + dt += (t->tm_sec & 0x3e) >> 1; /* Only counting every 2 seconds. */ + } + return dt; +} + +static size_t +path_length(struct archive_entry *entry) +{ + mode_t type; + const char *path; + + type = archive_entry_filetype(entry); + path = archive_entry_pathname(entry); + + if (path == NULL) + return (0); + if (type == AE_IFDIR && + (path[0] == '\0' || path[strlen(path) - 1] != '/')) { + return strlen(path) + 1; + } else { + return strlen(path); + } +} + +static int +write_path(struct archive_entry *entry, struct archive_write *archive) +{ + int ret; + const char *path; + mode_t type; + size_t written_bytes; + + path = archive_entry_pathname(entry); + type = archive_entry_filetype(entry); + written_bytes = 0; + + ret = __archive_write_output(archive, path, strlen(path)); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + written_bytes += strlen(path); + + /* Folders are recognized by a trailing slash. */ + if ((type == AE_IFDIR) & (path[strlen(path) - 1] != '/')) { + ret = __archive_write_output(archive, "/", 1); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + written_bytes += 1; + } + + return ((int)written_bytes); +} + +static void +copy_path(struct archive_entry *entry, unsigned char *p) +{ + const char *path; + size_t pathlen; + mode_t type; + + path = archive_entry_pathname(entry); + pathlen = strlen(path); + type = archive_entry_filetype(entry); + + memcpy(p, path, pathlen); + + /* Folders are recognized by a trailing slash. */ + if ((type == AE_IFDIR) & (path[pathlen - 1] != '/')) { + p[pathlen] = '/'; + p[pathlen + 1] = '\0'; + } +} + + +static struct archive_string_conv * +get_sconv(struct archive_write *a, struct zip *zip) +{ + if (zip->opt_sconv != NULL) + return (zip->opt_sconv); + + if (!zip->init_default_conversion) { + zip->sconv_default = + archive_string_default_conversion_for_write(&(a->archive)); + zip->init_default_conversion = 1; + } + return (zip->sconv_default); +} + +/* + Traditional PKWARE Decryption functions. + */ + +static void +trad_enc_update_keys(struct trad_enc_ctx *ctx, uint8_t c) +{ + uint8_t t; +#define CRC32(c, b) (crc32(c ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL) + + ctx->keys[0] = CRC32(ctx->keys[0], c); + ctx->keys[1] = (ctx->keys[1] + (ctx->keys[0] & 0xff)) * 134775813L + 1; + t = (ctx->keys[1] >> 24) & 0xff; + ctx->keys[2] = CRC32(ctx->keys[2], t); +#undef CRC32 +} + +static uint8_t - trad_enc_decypt_byte(struct trad_enc_ctx *ctx) ++trad_enc_decrypt_byte(struct trad_enc_ctx *ctx) +{ + unsigned temp = ctx->keys[2] | 2; + return (uint8_t)((temp * (temp ^ 1)) >> 8) & 0xff; +} + +static unsigned +trad_enc_encrypt_update(struct trad_enc_ctx *ctx, const uint8_t *in, + size_t in_len, uint8_t *out, size_t out_len) +{ + unsigned i, max; + + max = (unsigned)((in_len < out_len)? in_len: out_len); + + for (i = 0; i < max; i++) { + uint8_t t = in[i]; - out[i] = t ^ trad_enc_decypt_byte(ctx); ++ out[i] = t ^ trad_enc_decrypt_byte(ctx); + trad_enc_update_keys(ctx, t); + } + return i; +} + +static int +trad_enc_init(struct trad_enc_ctx *ctx, const char *pw, size_t pw_len) +{ + + ctx->keys[0] = 305419896L; + ctx->keys[1] = 591751049L; + ctx->keys[2] = 878082192L; + + for (;pw_len; --pw_len) + trad_enc_update_keys(ctx, *pw++); + return 0; +} + +static int +is_traditional_pkware_encryption_supported(void) +{ + uint8_t key[TRAD_HEADER_SIZE]; + + if (archive_random(key, sizeof(key)-1) != ARCHIVE_OK) + return (0); + return (1); +} + +static int +init_traditional_pkware_encryption(struct archive_write *a) +{ + struct zip *zip = a->format_data; + const char *passphrase; + uint8_t key[TRAD_HEADER_SIZE]; + uint8_t key_encrypted[TRAD_HEADER_SIZE]; + int ret; + + passphrase = __archive_write_get_passphrase(a); + if (passphrase == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Encryption needs passphrase"); + return ARCHIVE_FAILED; + } + if (archive_random(key, sizeof(key)-1) != ARCHIVE_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can't generate random number for encryption"); + return ARCHIVE_FATAL; + } + trad_enc_init(&zip->tctx, passphrase, strlen(passphrase)); + /* Set the last key code which will be used as a check code + * for verifying passphrase in decryption. */ + key[TRAD_HEADER_SIZE-1] = zip->trad_chkdat; + trad_enc_encrypt_update(&zip->tctx, key, TRAD_HEADER_SIZE, + key_encrypted, TRAD_HEADER_SIZE); + /* Write encrypted keys in the top of the file content. */ + ret = __archive_write_output(a, key_encrypted, TRAD_HEADER_SIZE); + if (ret != ARCHIVE_OK) + return (ret); + zip->written_bytes += TRAD_HEADER_SIZE; + zip->entry_compressed_written += TRAD_HEADER_SIZE; + return (ret); +} + +static int +init_winzip_aes_encryption(struct archive_write *a) +{ + struct zip *zip = a->format_data; + const char *passphrase; + size_t key_len, salt_len; + uint8_t salt[16 + 2]; + uint8_t derived_key[MAX_DERIVED_KEY_BUF_SIZE]; + int ret; + + passphrase = __archive_write_get_passphrase(a); + if (passphrase == NULL) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Encryption needs passphrase"); + return (ARCHIVE_FAILED); + } + if (zip->entry_encryption == ENCRYPTION_WINZIP_AES128) { + salt_len = 8; + key_len = 16; + } else { + /* AES 256 */ + salt_len = 16; + key_len = 32; + } + if (archive_random(salt, salt_len) != ARCHIVE_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Can't generate random number for encryption"); + return (ARCHIVE_FATAL); + } + archive_pbkdf2_sha1(passphrase, strlen(passphrase), + salt, salt_len, 1000, derived_key, key_len * 2 + 2); + + ret = archive_encrypto_aes_ctr_init(&zip->cctx, derived_key, key_len); + if (ret != 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Decryption is unsupported due to lack of crypto library"); + return (ARCHIVE_FAILED); + } + ret = archive_hmac_sha1_init(&zip->hctx, derived_key + key_len, + key_len); + if (ret != 0) { + archive_encrypto_aes_ctr_release(&zip->cctx); + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to initialize HMAC-SHA1"); + return (ARCHIVE_FAILED); + } + - /* Set a passowrd verification value after the 'salt'. */ ++ /* Set a password verification value after the 'salt'. */ + salt[salt_len] = derived_key[key_len * 2]; + salt[salt_len + 1] = derived_key[key_len * 2 + 1]; + + /* Write encrypted keys in the top of the file content. */ + ret = __archive_write_output(a, salt, salt_len + 2); + if (ret != ARCHIVE_OK) + return (ret); + zip->written_bytes += salt_len + 2; + zip->entry_compressed_written += salt_len + 2; + + return (ARCHIVE_OK); +} + +static int +is_winzip_aes_encryption_supported(int encryption) +{ + size_t key_len, salt_len; + uint8_t salt[16 + 2]; + uint8_t derived_key[MAX_DERIVED_KEY_BUF_SIZE]; + archive_crypto_ctx cctx; + archive_hmac_sha1_ctx hctx; + int ret; + + if (encryption == ENCRYPTION_WINZIP_AES128) { + salt_len = 8; + key_len = 16; + } else { + /* AES 256 */ + salt_len = 16; + key_len = 32; + } + if (archive_random(salt, salt_len) != ARCHIVE_OK) + return (0); + ret = archive_pbkdf2_sha1("p", 1, salt, salt_len, 1000, + derived_key, key_len * 2 + 2); + if (ret != 0) + return (0); + + ret = archive_encrypto_aes_ctr_init(&cctx, derived_key, key_len); + if (ret != 0) + return (0); + ret = archive_hmac_sha1_init(&hctx, derived_key + key_len, + key_len); + archive_encrypto_aes_ctr_release(&cctx); + if (ret != 0) + return (0); + archive_hmac_sha1_cleanup(&hctx); + return (1); +} https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c206211af647dd1f7039da91c34c9c72e50aefdf commit c206211af647dd1f7039da91c34c9c72e50aefdf Author: LibArchive Upstream AuthorDate: Sun Feb 19 20:35:52 2017 -0800 Commit: Brad King CommitDate: Mon Feb 20 07:50:48 2017 -0500 LibArchive 2017-02-19 (100ee75a) Code extracted from: https://github.com/libarchive/libarchive.git at commit 100ee75a01f1f785fc681f616db49a33405f8bf3 (v3.3.0). diff --git a/CMakeLists.txt b/CMakeLists.txt index 68e94a6..eb36b5b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -179,13 +179,15 @@ include(CTest) OPTION(ENABLE_NETTLE "Enable use of Nettle" ON) OPTION(ENABLE_OPENSSL "Enable use of OpenSSL" ON) -OPTION(ENABLE_LZMA "Enable the use of the system found LZMA library if found" ON) -OPTION(ENABLE_ZLIB "Enable the use of the system found ZLIB library if found" ON) -OPTION(ENABLE_BZip2 "Enable the use of the system found BZip2 library if found" ON) -OPTION(ENABLE_LIBXML2 "Enable the use of the system found libxml2 library if found" ON) -OPTION(ENABLE_EXPAT "Enable the use of the system found EXPAT library if found" ON) -OPTION(ENABLE_PCREPOSIX "Enable the use of the system found PCREPOSIX library if found" ON) -OPTION(ENABLE_LibGCC "Enable the use of the system found LibGCC library if found" ON) +OPTION(ENABLE_LZO "Enable the use of the system LZO library if found" OFF) +OPTION(ENABLE_LZMA "Enable the use of the system LZMA library if found" ON) + +OPTION(ENABLE_ZLIB "Enable the use of the system ZLIB library if found" ON) +OPTION(ENABLE_BZip2 "Enable the use of the system BZip2 library if found" ON) +OPTION(ENABLE_LIBXML2 "Enable the use of the system libxml2 library if found" ON) +OPTION(ENABLE_EXPAT "Enable the use of the system EXPAT library if found" ON) +OPTION(ENABLE_PCREPOSIX "Enable the use of the system PCREPOSIX library if found" ON) +OPTION(ENABLE_LibGCC "Enable the use of the system LibGCC library if found" ON) # CNG is used for encrypt/decrypt Zip archives on Windows. OPTION(ENABLE_CNG "Enable the use of CNG(Crypto Next Generation)" ON) @@ -274,7 +276,7 @@ INCLUDE(CheckHeaderDirent) INCLUDE(CheckIncludeFile) INCLUDE(CheckIncludeFiles) INCLUDE(CheckLibraryExists) -INCLUDE(CheckStructMember) +INCLUDE(CheckStructHasMember) INCLUDE(CheckSymbolExists) INCLUDE(CheckTypeExists) INCLUDE(CheckTypeSize) @@ -452,46 +454,44 @@ MARK_AS_ADVANCED(CLEAR BZIP2_LIBRARIES) # Find LZMA # IF(ENABLE_LZMA) - FIND_PACKAGE(LZMA) + FIND_PACKAGE(LibLZMA) ELSE() - SET(LZMA_FOUND FALSE) # Override cached value - SET(LZMADEC_FOUND FALSE) # Override cached value + SET(LIBZMA_FOUND FALSE) # Override cached value ENDIF() -IF(LZMA_FOUND) +IF(LIBLZMA_FOUND) SET(HAVE_LIBLZMA 1) SET(HAVE_LZMA_H 1) - INCLUDE_DIRECTORIES(${LZMA_INCLUDE_DIR}) - LIST(APPEND ADDITIONAL_LIBS ${LZMA_LIBRARIES}) + INCLUDE_DIRECTORIES(${LIBLZMA_INCLUDE_DIRS}) + LIST(APPEND ADDITIONAL_LIBS ${LIBLZMA_LIBRARIES}) # Test if a macro is needed for the library. TRY_MACRO_FOR_LIBRARY( - "${LZMA_INCLUDE_DIR}" "${LZMA_LIBRARIES}" + "${LIBLZMA_INCLUDE_DIRS}" "${LIBLZMA_LIBRARIES}" COMPILES "#include \nint main() {return (int)lzma_version_number(); }" "WITHOUT_LZMA_API_STATIC;LZMA_API_STATIC") IF(NOT WITHOUT_LZMA_API_STATIC AND LZMA_API_STATIC) ADD_DEFINITIONS(-DLZMA_API_STATIC) ENDIF(NOT WITHOUT_LZMA_API_STATIC AND LZMA_API_STATIC) -ELSEIF(LZMADEC_FOUND) - SET(HAVE_LIBLZMADEC 1) - SET(HAVE_LZMADEC_H 1) - INCLUDE_DIRECTORIES(${LZMADEC_INCLUDE_DIR}) - LIST(APPEND ADDITIONAL_LIBS ${LZMADEC_LIBRARIES}) -ELSE(LZMA_FOUND) +ELSE(LIBLZMA_FOUND) # LZMA not found and will not be used. -ENDIF(LZMA_FOUND) +ENDIF(LIBLZMA_FOUND) # # Find LZO2 # -IF (LZO2_INCLUDE_DIR) - # Already in cache, be silent - SET(LZO2_FIND_QUIETLY TRUE) -ENDIF (LZO2_INCLUDE_DIR) - -FIND_PATH(LZO2_INCLUDE_DIR lzo/lzoconf.h) -FIND_LIBRARY(LZO2_LIBRARY NAMES lzo2 liblzo2) -INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZO2 DEFAULT_MSG LZO2_LIBRARY LZO2_INCLUDE_DIR) +IF(ENABLE_LZO) + IF (LZO2_INCLUDE_DIR) + # Already in cache, be silent + SET(LZO2_FIND_QUIETLY TRUE) + ENDIF (LZO2_INCLUDE_DIR) + + FIND_PATH(LZO2_INCLUDE_DIR lzo/lzoconf.h) + FIND_LIBRARY(LZO2_LIBRARY NAMES lzo2 liblzo2) + INCLUDE(FindPackageHandleStandardArgs) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZO2 DEFAULT_MSG LZO2_LIBRARY LZO2_INCLUDE_DIR) +ELSE(ENABLE_LZO) + SET(LIBZMA_FOUND FALSE) # Override cached value +ENDIF(ENABLE_LZO) IF(LZO2_FOUND) SET(HAVE_LIBLZO2 1) SET(HAVE_LZO_LZOCONF_H 1) @@ -614,7 +614,7 @@ IF(ENABLE_CNG) ELSE(ENABLE_CNG) UNSET(HAVE_BCRYPT_H CACHE) ENDIF(ENABLE_CNG) -# Following files need windwos.h, so we should test it after windows.h test. +# Following files need windows.h, so we should test it after windows.h test. LA_CHECK_INCLUDE_FILE("wincrypt.h" HAVE_WINCRYPT_H) LA_CHECK_INCLUDE_FILE("winioctl.h" HAVE_WINIOCTL_H) @@ -1274,6 +1274,14 @@ CHECK_FUNCTION_EXISTS(wmemmove HAVE_WMEMMOVE) CMAKE_POP_CHECK_STATE() # Restore the state of the variables +CHECK_C_SOURCE_COMPILES( + "#include \n#include \nint main(void) { struct vfsconf v; return sizeof(v);}" + HAVE_STRUCT_VFSCONF) + +CHECK_C_SOURCE_COMPILES( + "#include \n#include \nint main(void) { struct xvfsconf v; return sizeof(v);}" + HAVE_STRUCT_XVFSCONF) + # Make sure we have the POSIX version of readdir_r, not the # older 2-argument version. CHECK_C_SOURCE_COMPILES( @@ -1299,6 +1307,10 @@ CHECK_C_SOURCE_COMPILES( "#include \nint main() { return major(256); }" MAJOR_IN_SYSMACROS) +CHECK_C_SOURCE_COMPILES( + "#include \n#if LZMA_VERSION < 50020000\n#error unsupported\n#endif\nint main(void){lzma_stream_encoder_mt(0, 0); return 0;}" + HAVE_LZMA_STREAM_ENCODER_MT) + IF(HAVE_STRERROR_R) SET(HAVE_DECL_STRERROR_R 1) ENDIF(HAVE_STRERROR_R) @@ -1332,47 +1344,47 @@ CHECK_SYMBOL_EXISTS(SSIZE_MAX "limits.h" HAVE_DECL_SSIZE_MAX) # Check struct members # # Check for tm_gmtoff in struct tm -CHECK_STRUCT_MEMBER("struct tm" tm_gmtoff +CHECK_STRUCT_HAS_MEMBER("struct tm" tm_gmtoff "time.h" HAVE_STRUCT_TM_TM_GMTOFF) -CHECK_STRUCT_MEMBER("struct tm" __tm_gmtoff +CHECK_STRUCT_HAS_MEMBER("struct tm" __tm_gmtoff "time.h" HAVE_STRUCT_TM___TM_GMTOFF) # Check for f_namemax in struct statfs -CHECK_STRUCT_MEMBER("struct statfs" f_namemax +CHECK_STRUCT_HAS_MEMBER("struct statfs" f_namemax "sys/param.h;sys/mount.h" HAVE_STRUCT_STATFS_F_NAMEMAX) # Check for birthtime in struct stat -CHECK_STRUCT_MEMBER("struct stat" st_birthtime +CHECK_STRUCT_HAS_MEMBER("struct stat" st_birthtime "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_BIRTHTIME) # Check for high-resolution timestamps in struct stat -CHECK_STRUCT_MEMBER("struct stat" st_birthtimespec.tv_nsec +CHECK_STRUCT_HAS_MEMBER("struct stat" st_birthtimespec.tv_nsec "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC) -CHECK_STRUCT_MEMBER("struct stat" st_mtimespec.tv_nsec +CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtimespec.tv_nsec "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC) -CHECK_STRUCT_MEMBER("struct stat" st_mtim.tv_nsec +CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtim.tv_nsec "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC) -CHECK_STRUCT_MEMBER("struct stat" st_mtime_n +CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtime_n "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIME_N) -CHECK_STRUCT_MEMBER("struct stat" st_umtime +CHECK_STRUCT_HAS_MEMBER("struct stat" st_umtime "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_UMTIME) -CHECK_STRUCT_MEMBER("struct stat" st_mtime_usec +CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtime_usec "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIME_USEC) # Check for block size support in struct stat -CHECK_STRUCT_MEMBER("struct stat" st_blksize +CHECK_STRUCT_HAS_MEMBER("struct stat" st_blksize "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_BLKSIZE) # Check for st_flags in struct stat (BSD fflags) -CHECK_STRUCT_MEMBER("struct stat" st_flags +CHECK_STRUCT_HAS_MEMBER("struct stat" st_flags "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_FLAGS) IF(HAVE_SYS_STATVFS_H) - CHECK_STRUCT_MEMBER("struct statvfs" f_iosize + CHECK_STRUCT_HAS_MEMBER("struct statvfs" f_iosize "sys/types.h;sys/statvfs.h" HAVE_STRUCT_STATVFS_F_IOSIZE) ENDIF() # # -CHECK_STRUCT_MEMBER("struct tm" tm_sec +CHECK_STRUCT_HAS_MEMBER("struct tm" tm_sec "sys/types.h;sys/time.h;time.h" TIME_WITH_SYS_TIME) # @@ -1592,16 +1604,36 @@ IF(ENABLE_ACL) # 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 +#include +int main(void) { return ACL_TYPE_EXTENDED; }" HAVE_ACL_TYPE_EXTENDED) + + # 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. @@ -1616,7 +1648,15 @@ ELSE(ENABLE_ACL) 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) ENDIF(ENABLE_ACL) # diff --git a/build/cmake/CheckStructMember.cmake b/build/cmake/CheckStructMember.cmake deleted file mode 100644 index 05ddb3a..0000000 --- a/build/cmake/CheckStructMember.cmake +++ /dev/null @@ -1,43 +0,0 @@ -# - Check if the given struct or class has the specified member variable -# CHECK_STRUCT_MEMBER (STRUCT MEMBER HEADER VARIABLE) -# -# STRUCT - the name of the struct or class you are interested in -# MEMBER - the member which existence you want to check -# HEADER - the header(s) where the prototype should be declared -# VARIABLE - variable to store the result -# -# The following variables may be set before calling this macro to -# modify the way the check is run: -# -# CMAKE_REQUIRED_FLAGS = string of compile command line flags -# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar) -# CMAKE_REQUIRED_INCLUDES = list of include directories - -# Copyright (c) 2006, Alexander Neundorf, -# -# Redistribution and use is allowed according to the terms of the BSD license. -# For details see the accompanying COPYING-CMAKE-SCRIPTS file. - - -INCLUDE(CheckCSourceCompiles) - -MACRO (CHECK_STRUCT_MEMBER _STRUCT _MEMBER _HEADER _RESULT) - SET(_INCLUDE_FILES) - FOREACH (it ${_HEADER}) - SET(_INCLUDE_FILES "${_INCLUDE_FILES}#include <${it}>\n") - ENDFOREACH (it) - - SET(_CHECK_STRUCT_MEMBER_SOURCE_CODE " -${_INCLUDE_FILES} -int main() -{ - static ${_STRUCT} tmp; - if (sizeof(tmp.${_MEMBER})) - return 0; - return 0; -} -") - CHECK_C_SOURCE_COMPILES("${_CHECK_STRUCT_MEMBER_SOURCE_CODE}" ${_RESULT}) - -ENDMACRO (CHECK_STRUCT_MEMBER) - diff --git a/build/cmake/FindLZMA.cmake b/build/cmake/FindLZMA.cmake deleted file mode 100644 index 0b46b2c..0000000 --- a/build/cmake/FindLZMA.cmake +++ /dev/null @@ -1,48 +0,0 @@ -# - Find lzma and lzmadec -# Find the native LZMA includes and library -# -# LZMA_INCLUDE_DIR - where to find lzma.h, etc. -# LZMA_LIBRARIES - List of libraries when using liblzma. -# LZMA_FOUND - True if liblzma found. -# LZMADEC_INCLUDE_DIR - where to find lzmadec.h, etc. -# LZMADEC_LIBRARIES - List of libraries when using liblzmadec. -# LZMADEC_FOUND - True if liblzmadec found. - -IF (LZMA_INCLUDE_DIR) - # Already in cache, be silent - SET(LZMA_FIND_QUIETLY TRUE) -ENDIF (LZMA_INCLUDE_DIR) - -FIND_PATH(LZMA_INCLUDE_DIR lzma.h) -FIND_LIBRARY(LZMA_LIBRARY NAMES lzma liblzma) - -# handle the QUIETLY and REQUIRED arguments and set LZMA_FOUND to TRUE if -# all listed variables are TRUE -INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZMA DEFAULT_MSG LZMA_LIBRARY LZMA_INCLUDE_DIR) - -IF(LZMA_FOUND) - SET( LZMA_LIBRARIES ${LZMA_LIBRARY} ) -ELSE(LZMA_FOUND) - SET( LZMA_LIBRARIES ) - - IF (LZMADEC_INCLUDE_DIR) - # Already in cache, be silent - SET(LZMADEC_FIND_QUIETLY TRUE) - ENDIF (LZMADEC_INCLUDE_DIR) - - FIND_PATH(LZMADEC_INCLUDE_DIR lzmadec.h) - FIND_LIBRARY(LZMADEC_LIBRARY NAMES lzmadec ) - - # handle the QUIETLY and REQUIRED arguments and set LZMADEC_FOUND to TRUE if - # all listed variables are TRUE - INCLUDE(FindPackageHandleStandardArgs) - FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZMADEC DEFAULT_MSG LZMADEC_LIBRARY - LZMADEC_INCLUDE_DIR) - - IF(LZMADEC_FOUND) - SET( LZMADEC_LIBRARIES ${LZMADEC_LIBRARY} ) - ELSE(LZMADEC_FOUND) - SET( LZMADEC_LIBRARIES ) - ENDIF(LZMADEC_FOUND) -ENDIF(LZMA_FOUND) diff --git a/build/cmake/config.h.in b/build/cmake/config.h.in index 64f4d4d..ec64d99 100644 --- a/build/cmake/config.h.in +++ b/build/cmake/config.h.in @@ -293,6 +293,9 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the `acl_create_entry' function. */ #cmakedefine HAVE_ACL_CREATE_ENTRY 1 +/* Define to 1 if you have the `acl_get_fd_np' function. */ +#cmakedefine HAVE_ACL_GET_FD_NP 1 + /* Define to 1 if you have the `acl_get_link' function. */ #cmakedefine HAVE_ACL_GET_LINK 1 @@ -323,6 +326,12 @@ 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 @@ -721,6 +730,9 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have the header file. */ #cmakedefine HAVE_LZMA_H 1 +/* Define to 1 if you have a working `lzma_stream_encoder_mt' function. */ +#cmakedefine HAVE_LZMA_STREAM_ENCODER_MT 1 + /* Define to 1 if you have the header file. */ #cmakedefine HAVE_LZO_LZO1X_H 1 @@ -923,6 +935,12 @@ typedef uint64_t uintmax_t; /* Define to 1 if `__tm_gmtoff' is a member of `struct tm'. */ #cmakedefine HAVE_STRUCT_TM___TM_GMTOFF 1 +/* Define to 1 if you have `struct vfsconf'. */ +#cmakedefine HAVE_STRUCT_VFSCONF 1 + +/* Define to 1 if you have `struct xvfsconf'. */ +#cmakedefine HAVE_STRUCT_XVFSCONF 1 + /* Define to 1 if you have the `symlink' function. */ #cmakedefine HAVE_SYMLINK 1 diff --git a/build/version b/build/version index f293156..a000b30 100644 --- a/build/version +++ b/build/version @@ -1 +1 @@ -3002001 +3003000 diff --git a/libarchive/CMakeLists.txt b/libarchive/CMakeLists.txt index 4cc9a2c..1f85c01 100644 --- a/libarchive/CMakeLists.txt +++ b/libarchive/CMakeLists.txt @@ -38,6 +38,8 @@ SET(libarchive_SOURCES archive_hmac.c archive_hmac_private.h archive_match.c + archive_openssl_evp_private.h + archive_openssl_hmac_private.h archive_options.c archive_options_private.h archive_pack_dev.h @@ -166,15 +168,33 @@ SET(libarchive_MANS archive_entry_time.3 archive_read.3 archive_read_add_passphrase.3 + archive_read_data.3 archive_read_disk.3 + archive_read_extract.3 + archive_read_filter.3 + archive_read_format.3 + archive_read_free.3 + archive_read_header.3 + archive_read_new.3 + archive_read_open.3 archive_read_set_options.3 archive_util.3 archive_write.3 + archive_write_blocksize.3 + archive_write_data.3 archive_write_disk.3 + archive_write_filter.3 + archive_write_finish_entry.3 + archive_write_format.3 + archive_write_free.3 + archive_write_header.3 + archive_write_new.3 + archive_write_open.3 archive_write_set_options.3 archive_write_set_passphrase.3 cpio.5 libarchive.3 + libarchive_changes.3 libarchive_internals.3 libarchive-formats.5 mtree.5 diff --git a/libarchive/archive.h b/libarchive/archive.h index 1794dd3..cd27c90 100644 --- a/libarchive/archive.h +++ b/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 3002001 +#define ARCHIVE_VERSION_NUMBER 3003000 #include #include /* for wchar_t */ @@ -155,7 +155,7 @@ __LA_DECL int archive_version_number(void); /* * Textual name/version of the library, useful for version displays. */ -#define ARCHIVE_VERSION_ONLY_STRING "3.2.1" +#define ARCHIVE_VERSION_ONLY_STRING "3.3.0" #define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING __LA_DECL const char * archive_version_string(void); @@ -373,7 +373,7 @@ typedef const char *archive_passphrase_callback(struct archive *, * 4) Repeatedly call archive_read_next_header to get information about * successive archive entries. Call archive_read_data to extract * data for entries of interest. - * 5) Call archive_read_finish to end processing. + * 5) Call archive_read_free to end processing. */ __LA_DECL struct archive *archive_read_new(void); @@ -562,7 +562,7 @@ __LA_DECL la_int64_t archive_read_header_position(struct archive *); * we cannot say whether there are encrypted entries, then * ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned. * In general, this function will return values below zero when the - * reader is uncertain or totally uncapable of encryption support. + * reader is uncertain or totally incapable of encryption support. * When this function returns 0 you can be sure that the reader * supports encryption detection but no encrypted entries have * been found yet. @@ -984,12 +984,12 @@ __LA_DECL int archive_read_disk_can_descend(struct archive *); __LA_DECL int archive_read_disk_current_filesystem(struct archive *); __LA_DECL int archive_read_disk_current_filesystem_is_synthetic(struct archive *); __LA_DECL int archive_read_disk_current_filesystem_is_remote(struct archive *); -/* Request that the access time of the entry visited by travesal be restored. */ +/* Request that the access time of the entry visited by traversal be restored. */ __LA_DECL int archive_read_disk_set_atime_restored(struct archive *); /* * Set behavior. The "flags" argument selects optional behavior. */ -/* Request that the access time of the entry visited by travesal be restored. +/* Request that the access time of the entry visited by traversal be restored. * This is the same as archive_read_disk_set_atime_restored. */ #define ARCHIVE_READDISK_RESTORE_ATIME (0x0001) /* Default: Do not skip an entry which has nodump flags. */ @@ -1124,7 +1124,7 @@ __LA_DECL int archive_match_time_excluded(struct archive *, /* * Flags to tell a matching type of time stamps. These are used for - * following functinos. + * following functions. */ /* Time flag: mtime to be tested. */ #define ARCHIVE_MATCH_MTIME (0x0100) @@ -1144,7 +1144,7 @@ __LA_DECL int archive_match_include_date(struct archive *, int _flag, const char *_datestr); __LA_DECL int archive_match_include_date_w(struct archive *, int _flag, const wchar_t *_datestr); -/* Set inclusion time by a particluar file. */ +/* Set inclusion time by a particular file. */ __LA_DECL int archive_match_include_file_time(struct archive *, int _flag, const char *_pathname); __LA_DECL int archive_match_include_file_time_w(struct archive *, diff --git a/libarchive/archive_acl.c b/libarchive/archive_acl.c index bf4b610..b8b6b63 100644 --- a/libarchive/archive_acl.c +++ b/libarchive/archive_acl.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 2003-2010 Tim Kientzle + * Copyright (c) 2016 Martin Matuska * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -55,25 +56,77 @@ static struct archive_acl_entry *acl_new_entry(struct archive_acl *acl, static int archive_acl_add_entry_len_l(struct archive_acl *acl, int type, int permset, int tag, int id, const char *name, size_t len, struct archive_string_conv *sc); +static int archive_acl_text_want_type(struct archive_acl *acl, int flags); +static ssize_t archive_acl_text_len(struct archive_acl *acl, int want_type, + int flags, int wide, struct archive *a, + struct archive_string_conv *sc); static int isint_w(const wchar_t *start, const wchar_t *end, int *result); static int ismode_w(const wchar_t *start, const wchar_t *end, int *result); +static int is_nfs4_flags_w(const wchar_t *start, const wchar_t *end, + int *result); +static int is_nfs4_perms_w(const wchar_t *start, const wchar_t *end, + int *result); static void next_field_w(const wchar_t **wp, const wchar_t **start, const wchar_t **end, wchar_t *sep); -static int prefix_w(const wchar_t *start, const wchar_t *end, - const wchar_t *test); -static void append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag, - const wchar_t *wname, int perm, int id); +static void append_entry_w(wchar_t **wp, const wchar_t *prefix, int type, + int tag, int flags, const wchar_t *wname, int perm, int id); static void append_id_w(wchar_t **wp, int id); static int isint(const char *start, const char *end, int *result); static int ismode(const char *start, const char *end, int *result); +static int is_nfs4_flags(const char *start, const char *end, + int *result); +static int is_nfs4_perms(const char *start, const char *end, + int *result); static void next_field(const char **p, const char **start, const char **end, char *sep); -static int prefix_c(const char *start, const char *end, - const char *test); -static void append_entry(char **p, const char *prefix, int tag, - const char *name, int perm, int id); +static void append_entry(char **p, const char *prefix, int type, + int tag, int flags, const char *name, int perm, int id); static void append_id(char **p, int id); +static const struct { + const int perm; + const char c; + const wchar_t wc; +} nfsv4_acl_perm_map[] = { + { ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, 'r', + L'r' }, + { ARCHIVE_ENTRY_ACL_WRITE_DATA | ARCHIVE_ENTRY_ACL_ADD_FILE, 'w', + L'w' }, + { ARCHIVE_ENTRY_ACL_EXECUTE, 'x', L'x' }, + { ARCHIVE_ENTRY_ACL_APPEND_DATA | ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, + 'p', L'p' }, + { ARCHIVE_ENTRY_ACL_DELETE, 'd', L'd' }, + { ARCHIVE_ENTRY_ACL_DELETE_CHILD, 'D', L'D' }, + { ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, 'a', L'a' }, + { ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, 'A', L'A' }, + { ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, 'R', L'R' }, + { ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, 'W', L'W' }, + { ARCHIVE_ENTRY_ACL_READ_ACL, 'c', L'c' }, + { ARCHIVE_ENTRY_ACL_WRITE_ACL, 'C', L'C' }, + { ARCHIVE_ENTRY_ACL_WRITE_OWNER, 'o', L'o' }, + { ARCHIVE_ENTRY_ACL_SYNCHRONIZE, 's', L's' } +}; + +static const int nfsv4_acl_perm_map_size = (int)(sizeof(nfsv4_acl_perm_map) / + sizeof(nfsv4_acl_perm_map[0])); + +static const struct { + const int perm; + const char c; + const wchar_t wc; +} nfsv4_acl_flag_map[] = { + { ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, 'f', L'f' }, + { ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, 'd', L'd' }, + { ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, 'i', L'i' }, + { ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, 'n', L'n' }, + { ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, 'S', L'S' }, + { ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, 'F', L'F' }, + { ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, 'I', L'I' } +}; + +static const int nfsv4_acl_flag_map_size = (int)(sizeof(nfsv4_acl_flag_map) / + sizeof(nfsv4_acl_flag_map[0])); + void archive_acl_clear(struct archive_acl *acl) { @@ -94,6 +147,7 @@ archive_acl_clear(struct archive_acl *acl) acl->acl_text = NULL; } acl->acl_p = NULL; + acl->acl_types = 0; acl->acl_state = 0; /* Not counting. */ } @@ -279,23 +333,31 @@ acl_new_entry(struct archive_acl *acl, acl->acl_text = NULL; } - /* If there's a matching entry already in the list, overwrite it. */ + /* + * If there's a matching entry already in the list, overwrite it. + * NFSv4 entries may be repeated and are not overwritten. + * + * TODO: compare names of no id is provided (needs more rework) + */ ap = acl->acl_head; aq = NULL; while (ap != NULL) { - if (ap->type == type && ap->tag == tag && ap->id == id) { - ap->permset = permset; - return (ap); + if (((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0) && + ap->type == type && ap->tag == tag && ap->id == id) { + if (id != -1 || (tag != ARCHIVE_ENTRY_ACL_USER && + tag != ARCHIVE_ENTRY_ACL_GROUP)) { + ap->permset = permset; + return (ap); + } } aq = ap; ap = ap->next; } /* Add a new entry to the end of the list. */ - ap = (struct archive_acl_entry *)malloc(sizeof(*ap)); + ap = (struct archive_acl_entry *)calloc(1, sizeof(*ap)); if (ap == NULL) return (NULL); - memset(ap, 0, sizeof(*ap)); if (aq == NULL) acl->acl_head = ap; else @@ -331,6 +393,15 @@ archive_acl_count(struct archive_acl *acl, int want_type) } /* + * Return a bitmask of stored ACL types in an ACL list + */ +int +archive_acl_types(struct archive_acl *acl) +{ + return (acl->acl_types); +} + +/* * Prepare for reading entries from the ACL data. Returns a count * of entries matching "want_type", or zero if there are no * non-extended ACL entries of that type. @@ -366,8 +437,8 @@ archive_acl_reset(struct archive_acl *acl, int want_type) * standard permissions and include them in the returned list. */ int -archive_acl_next(struct archive *a, struct archive_acl *acl, int want_type, int *type, - int *permset, int *tag, int *id, const char **name) +archive_acl_next(struct archive *a, struct archive_acl *acl, int want_type, + int *type, int *permset, int *tag, int *id, const char **name) { *name = NULL; *id = -1; @@ -432,130 +503,273 @@ archive_acl_next(struct archive *a, struct archive_acl *acl, int want_type, int } /* - * Generate a text version of the ACL. The flags parameter controls - * the style of the generated ACL. + * Determine what type of ACL do we want */ -const wchar_t * -archive_acl_text_w(struct archive *a, struct archive_acl *acl, int flags) +static int +archive_acl_text_want_type(struct archive_acl *acl, int flags) { - int count; - size_t length; - const wchar_t *wname; - const wchar_t *prefix; - wchar_t separator; - struct archive_acl_entry *ap; - int id, r; - wchar_t *wp; + int want_type; - if (acl->acl_text_w != NULL) { - free (acl->acl_text_w); - acl->acl_text_w = NULL; + /* Check if ACL is NFSv4 */ + if ((acl->acl_types & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { + /* NFSv4 should never mix with POSIX.1e */ + if ((acl->acl_types & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) + return (0); + else + return (ARCHIVE_ENTRY_ACL_TYPE_NFS4); } - separator = L','; + /* Now deal with POSIX.1e ACLs */ + + want_type = 0; + if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) + want_type |= ARCHIVE_ENTRY_ACL_TYPE_ACCESS; + if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) + want_type |= ARCHIVE_ENTRY_ACL_TYPE_DEFAULT; + + /* By default we want both access and default ACLs */ + if (want_type == 0) + return (ARCHIVE_ENTRY_ACL_TYPE_POSIX1E); + + return (want_type); +} + +/* + * Calculate ACL text string length + */ +static ssize_t +archive_acl_text_len(struct archive_acl *acl, int want_type, int flags, + int wide, struct archive *a, struct archive_string_conv *sc) { + struct archive_acl_entry *ap; + const char *name; + const wchar_t *wname; + int count, idlen, tmp, r; + ssize_t length; + size_t len; + count = 0; length = 0; - ap = acl->acl_head; - while (ap != NULL) { - if ((ap->type & flags) != 0) { - count++; - if ((flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) && - (ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)) - length += 8; /* "default:" */ - length += 5; /* tag name */ - length += 1; /* colon */ - r = archive_mstring_get_wcs(a, &ap->name, &wname); - if (r == 0 && wname != NULL) - length += wcslen(wname); - else if (r < 0 && errno == ENOMEM) - return (NULL); - else - length += sizeof(uid_t) * 3 + 1; - length ++; /* colon */ + for (ap = acl->acl_head; ap != NULL; ap = ap->next) { + if ((ap->type & want_type) == 0) + continue; + /* + * Filemode-mapping ACL entries are stored exclusively in + * ap->mode so they should not be in the list + */ + if ((ap->type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) + && (ap->tag == ARCHIVE_ENTRY_ACL_USER_OBJ + || ap->tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ + || ap->tag == ARCHIVE_ENTRY_ACL_OTHER)) + continue; + count++; + if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0 + && (ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) + length += 8; /* "default:" */ + switch (ap->tag) { + case ARCHIVE_ENTRY_ACL_USER_OBJ: + if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + length += 6; /* "owner@" */ + break; + } + /* FALLTHROUGH */ + case ARCHIVE_ENTRY_ACL_USER: + case ARCHIVE_ENTRY_ACL_MASK: + length += 4; /* "user", "mask" */ + break; + case ARCHIVE_ENTRY_ACL_GROUP_OBJ: + if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + length += 6; /* "group@" */ + break; + } + /* FALLTHROUGH */ + case ARCHIVE_ENTRY_ACL_GROUP: + case ARCHIVE_ENTRY_ACL_OTHER: + length += 5; /* "group", "other" */ + break; + case ARCHIVE_ENTRY_ACL_EVERYONE: + length += 9; /* "everyone@" */ + break; + } + length += 1; /* colon after tag */ + if (ap->tag == ARCHIVE_ENTRY_ACL_USER || + ap->tag == ARCHIVE_ENTRY_ACL_GROUP) { + if (wide) { + r = archive_mstring_get_wcs(a, &ap->name, + &wname); + if (r == 0 && wname != NULL) + length += wcslen(wname); + else if (r < 0 && errno == ENOMEM) + return (0); + else + length += sizeof(uid_t) * 3 + 1; + } else { + r = archive_mstring_get_mbs_l(&ap->name, &name, + &len, sc); + if (r != 0) + return (0); + if (len > 0 && name != NULL) + length += len; + else + length += sizeof(uid_t) * 3 + 1; + } + length += 1; /* colon after user or group name */ + } else if (want_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) + length += 1; /* 2nd colon empty user,group or other */ + + if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) != 0) + && ((want_type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) + && (ap->tag == ARCHIVE_ENTRY_ACL_OTHER + || ap->tag == ARCHIVE_ENTRY_ACL_MASK)) { + /* Solaris has no colon after other: and mask: */ + length = length - 1; + } + + if (want_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + /* rwxpdDaARWcCos:fdinSFI:deny */ + length += 27; + if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DENY) == 0) + length += 1; /* allow, alarm, audit */ + } else length += 3; /* rwx */ + + if ((ap->tag == ARCHIVE_ENTRY_ACL_USER || + ap->tag == ARCHIVE_ENTRY_ACL_GROUP) && + (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) != 0) { length += 1; /* colon */ - length += max(sizeof(uid_t), sizeof(gid_t)) * 3 + 1; - length ++; /* newline */ + /* ID digit count */ + idlen = 1; + tmp = ap->id; + while (tmp > 9) { + tmp = tmp / 10; + idlen++; + } + length += idlen; } - ap = ap->next; + length ++; /* entry separator */ } - if (count > 0 && ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)) { - length += 10; /* "user::rwx\n" */ - length += 11; /* "group::rwx\n" */ - length += 11; /* "other::rwx\n" */ - } + /* Add filemode-mapping access entries to the length */ + if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { + if ((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) != 0) { + /* "user::rwx\ngroup::rwx\nother:rwx\n" */ + length += 31; + } else { + /* "user::rwx\ngroup::rwx\nother::rwx\n" */ + length += 32; + } + } else if (count == 0) + return (0); + + /* The terminating character is included in count */ + return (length); +} + +/* + * Generate a wide text version of the ACL. The flags parameter controls + * the type and style of the generated ACL. + */ +wchar_t * +archive_acl_to_text_w(struct archive_acl *acl, ssize_t *text_len, int flags, + struct archive *a) +{ + int count; + ssize_t length; + size_t len; + const wchar_t *wname; + const wchar_t *prefix; + wchar_t separator; + struct archive_acl_entry *ap; + int id, r, want_type; + wchar_t *wp, *ws; + + want_type = archive_acl_text_want_type(acl, flags); + + /* Both NFSv4 and POSIX.1 types found */ + if (want_type == 0) + return (NULL); + + if (want_type == ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) + flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT; + + length = archive_acl_text_len(acl, want_type, flags, 1, a, NULL); - if (count == 0) + if (length == 0) return (NULL); + if (flags & ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA) + separator = L','; + else + separator = L'\n'; + /* Now, allocate the string and actually populate it. */ - wp = acl->acl_text_w = (wchar_t *)malloc(length * sizeof(wchar_t)); - if (wp == NULL) + wp = ws = (wchar_t *)malloc(length * sizeof(wchar_t)); + if (wp == NULL) { + if (errno == ENOMEM) + __archive_errx(1, "No memory"); return (NULL); + } count = 0; - if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { - append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_USER_OBJ, NULL, + + if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { + append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_USER_OBJ, flags, NULL, acl->mode & 0700, -1); - *wp++ = ','; - append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_GROUP_OBJ, NULL, + *wp++ = separator; + append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, flags, NULL, acl->mode & 0070, -1); - *wp++ = ','; - append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_OTHER, NULL, + *wp++ = separator; + append_entry_w(&wp, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_OTHER, flags, NULL, acl->mode & 0007, -1); count += 3; - - ap = acl->acl_head; - while (ap != NULL) { - if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { - r = archive_mstring_get_wcs(a, &ap->name, &wname); - if (r == 0) { - *wp++ = separator; - if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) - id = ap->id; - else - id = -1; - append_entry_w(&wp, NULL, ap->tag, wname, - ap->permset, id); - count++; - } else if (r < 0 && errno == ENOMEM) - return (NULL); - } - ap = ap->next; - } } - - if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) { - if (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) + for (ap = acl->acl_head; ap != NULL; ap = ap->next) { + if ((ap->type & want_type) == 0) + continue; + /* + * Filemode-mapping ACL entries are stored exclusively in + * ap->mode so they should not be in the list + */ + if ((ap->type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) + && (ap->tag == ARCHIVE_ENTRY_ACL_USER_OBJ + || ap->tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ + || ap->tag == ARCHIVE_ENTRY_ACL_OTHER)) + continue; + if (ap->type == ARCHIVE_ENTRY_ACL_TYPE_DEFAULT && + (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0) prefix = L"default:"; else prefix = NULL; - ap = acl->acl_head; - count = 0; - while (ap != NULL) { - if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) { - r = archive_mstring_get_wcs(a, &ap->name, &wname); - if (r == 0) { - if (count > 0) - *wp++ = separator; - if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) - id = ap->id; - else - id = -1; - append_entry_w(&wp, prefix, ap->tag, - wname, ap->permset, id); - count ++; - } else if (r < 0 && errno == ENOMEM) - return (NULL); - } - ap = ap->next; - } + r = archive_mstring_get_wcs(a, &ap->name, &wname); + if (r == 0) { + if (count > 0) + *wp++ = separator; + if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) + id = ap->id; + else + id = -1; + append_entry_w(&wp, prefix, ap->type, ap->tag, flags, + wname, ap->permset, id); + count++; + } else if (r < 0 && errno == ENOMEM) + return (NULL); } - return (acl->acl_text_w); -} + /* Add terminating character */ + *wp++ = L'\0'; + + len = wcslen(ws); + if ((ssize_t)len > (length - 1)) + __archive_errx(1, "Buffer overrun"); + + if (text_len != NULL) + *text_len = len; + + return (ws); +} static void append_id_w(wchar_t **wp, int id) @@ -568,9 +782,11 @@ append_id_w(wchar_t **wp, int id) } static void -append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag, - const wchar_t *wname, int perm, int id) +append_entry_w(wchar_t **wp, const wchar_t *prefix, int type, + int tag, int flags, const wchar_t *wname, int perm, int id) { + int i; + if (prefix != NULL) { wcscpy(*wp, prefix); *wp += wcslen(*wp); @@ -579,6 +795,10 @@ append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag, case ARCHIVE_ENTRY_ACL_USER_OBJ: wname = NULL; id = -1; + if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { + wcscpy(*wp, L"owner@"); + break; + } /* FALLTHROUGH */ case ARCHIVE_ENTRY_ACL_USER: wcscpy(*wp, L"user"); @@ -586,6 +806,10 @@ append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag, case ARCHIVE_ENTRY_ACL_GROUP_OBJ: wname = NULL; id = -1; + if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { + wcscpy(*wp, L"group@"); + break; + } /* FALLTHROUGH */ case ARCHIVE_ENTRY_ACL_GROUP: wcscpy(*wp, L"group"); @@ -600,153 +824,184 @@ append_entry_w(wchar_t **wp, const wchar_t *prefix, int tag, wname = NULL; id = -1; break; + case ARCHIVE_ENTRY_ACL_EVERYONE: + wcscpy(*wp, L"everyone@"); + wname = NULL; + id = -1; + break; } *wp += wcslen(*wp); *(*wp)++ = L':'; - if (wname != NULL) { - wcscpy(*wp, wname); + if (((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) || + tag == ARCHIVE_ENTRY_ACL_USER || + tag == ARCHIVE_ENTRY_ACL_GROUP) { + if (wname != NULL) { + wcscpy(*wp, wname); + *wp += wcslen(*wp); + } else if (tag == ARCHIVE_ENTRY_ACL_USER + || tag == ARCHIVE_ENTRY_ACL_GROUP) { + append_id_w(wp, id); + if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0) + id = -1; + } + /* Solaris style has no second colon after other and mask */ + if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) == 0) + || (tag != ARCHIVE_ENTRY_ACL_OTHER + && tag != ARCHIVE_ENTRY_ACL_MASK)) + *(*wp)++ = L':'; + } + if ((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) { + /* POSIX.1e ACL perms */ + *(*wp)++ = (perm & 0444) ? L'r' : L'-'; + *(*wp)++ = (perm & 0222) ? L'w' : L'-'; + *(*wp)++ = (perm & 0111) ? L'x' : L'-'; + } else { + /* NFSv4 ACL perms */ + for (i = 0; i < nfsv4_acl_perm_map_size; i++) { + if (perm & nfsv4_acl_perm_map[i].perm) + *(*wp)++ = nfsv4_acl_perm_map[i].wc; + else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0) + *(*wp)++ = L'-'; + } + *(*wp)++ = L':'; + for (i = 0; i < nfsv4_acl_flag_map_size; i++) { + if (perm & nfsv4_acl_flag_map[i].perm) + *(*wp)++ = nfsv4_acl_flag_map[i].wc; + else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0) + *(*wp)++ = L'-'; + } + *(*wp)++ = L':'; + switch (type) { + case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: + wcscpy(*wp, L"allow"); + break; + case ARCHIVE_ENTRY_ACL_TYPE_DENY: + wcscpy(*wp, L"deny"); + break; + case ARCHIVE_ENTRY_ACL_TYPE_AUDIT: + wcscpy(*wp, L"audit"); + break; + case ARCHIVE_ENTRY_ACL_TYPE_ALARM: + wcscpy(*wp, L"alarm"); + break; + default: + break; + } *wp += wcslen(*wp); - } else if (tag == ARCHIVE_ENTRY_ACL_USER - || tag == ARCHIVE_ENTRY_ACL_GROUP) { - append_id_w(wp, id); - id = -1; } - *(*wp)++ = L':'; - *(*wp)++ = (perm & 0444) ? L'r' : L'-'; - *(*wp)++ = (perm & 0222) ? L'w' : L'-'; - *(*wp)++ = (perm & 0111) ? L'x' : L'-'; if (id != -1) { *(*wp)++ = L':'; append_id_w(wp, id); } - **wp = L'\0'; } -int -archive_acl_text_l(struct archive_acl *acl, int flags, - const char **acl_text, size_t *acl_text_len, +/* + * Generate a text version of the ACL. The flags parameter controls + * the type and style of the generated ACL. + */ +char * +archive_acl_to_text_l(struct archive_acl *acl, ssize_t *text_len, int flags, struct archive_string_conv *sc) { int count; - size_t length; + ssize_t length; + size_t len; const char *name; const char *prefix; char separator; struct archive_acl_entry *ap; - size_t len; - int id, r; - char *p; + int id, r, want_type; + char *p, *s; - if (acl->acl_text != NULL) { - free (acl->acl_text); - acl->acl_text = NULL; - } + want_type = archive_acl_text_want_type(acl, flags); - *acl_text = NULL; - if (acl_text_len != NULL) - *acl_text_len = 0; - separator = ','; - count = 0; - length = 0; - ap = acl->acl_head; - while (ap != NULL) { - if ((ap->type & flags) != 0) { - count++; - if ((flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) && - (ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)) - length += 8; /* "default:" */ - length += 5; /* tag name */ - length += 1; /* colon */ - r = archive_mstring_get_mbs_l( - &ap->name, &name, &len, sc); - if (r != 0) - return (-1); - if (len > 0 && name != NULL) - length += len; - else - length += sizeof(uid_t) * 3 + 1; - length ++; /* colon */ - length += 3; /* rwx */ - length += 1; /* colon */ - length += max(sizeof(uid_t), sizeof(gid_t)) * 3 + 1; - length ++; /* newline */ - } - ap = ap->next; - } + /* Both NFSv4 and POSIX.1 types found */ + if (want_type == 0) + return (NULL); - if (count > 0 && ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0)) { - length += 10; /* "user::rwx\n" */ - length += 11; /* "group::rwx\n" */ - length += 11; /* "other::rwx\n" */ - } + if (want_type == ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) + flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT; - if (count == 0) - return (0); + length = archive_acl_text_len(acl, want_type, flags, 0, NULL, sc); + + if (length == 0) + return (NULL); + + if (flags & ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA) + separator = ','; + else + separator = '\n'; /* Now, allocate the string and actually populate it. */ - p = acl->acl_text = (char *)malloc(length); - if (p == NULL) - return (-1); + p = s = (char *)malloc(length * sizeof(char)); + if (p == NULL) { + if (errno == ENOMEM) + __archive_errx(1, "No memory"); + return (NULL); + } count = 0; - if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { - append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_USER_OBJ, NULL, + + if ((want_type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) { + append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_USER_OBJ, flags, NULL, acl->mode & 0700, -1); - *p++ = ','; - append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_GROUP_OBJ, NULL, + *p++ = separator; + append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_GROUP_OBJ, flags, NULL, acl->mode & 0070, -1); - *p++ = ','; - append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_OTHER, NULL, + *p++ = separator; + append_entry(&p, NULL, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, + ARCHIVE_ENTRY_ACL_OTHER, flags, NULL, acl->mode & 0007, -1); count += 3; - - for (ap = acl->acl_head; ap != NULL; ap = ap->next) { - if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) == 0) - continue; - r = archive_mstring_get_mbs_l( - &ap->name, &name, &len, sc); - if (r != 0) - return (-1); - *p++ = separator; - if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) - id = ap->id; - else - id = -1; - append_entry(&p, NULL, ap->tag, name, - ap->permset, id); - count++; - } } - - if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) { - if (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) + for (ap = acl->acl_head; ap != NULL; ap = ap->next) { + if ((ap->type & want_type) == 0) + continue; + /* + * Filemode-mapping ACL entries are stored exclusively in + * ap->mode so they should not be in the list + */ + if ((ap->type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) + && (ap->tag == ARCHIVE_ENTRY_ACL_USER_OBJ + || ap->tag == ARCHIVE_ENTRY_ACL_GROUP_OBJ + || ap->tag == ARCHIVE_ENTRY_ACL_OTHER)) + continue; + if (ap->type == ARCHIVE_ENTRY_ACL_TYPE_DEFAULT && + (flags & ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0) prefix = "default:"; else prefix = NULL; - count = 0; - for (ap = acl->acl_head; ap != NULL; ap = ap->next) { - if ((ap->type & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) == 0) - continue; - r = archive_mstring_get_mbs_l( - &ap->name, &name, &len, sc); - if (r != 0) - return (-1); - if (count > 0) - *p++ = separator; - if (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) - id = ap->id; - else - id = -1; - append_entry(&p, prefix, ap->tag, - name, ap->permset, id); - count ++; + r = archive_mstring_get_mbs_l( + &ap->name, &name, &len, sc); + if (r != 0) + return (NULL); + if (count > 0) + *p++ = separator; + if (name == NULL || + (flags & ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID)) { + id = ap->id; + } else { + id = -1; } + append_entry(&p, prefix, ap->type, ap->tag, flags, name, + ap->permset, id); + count++; } - *acl_text = acl->acl_text; - if (acl_text_len != NULL) - *acl_text_len = strlen(acl->acl_text); - return (0); + /* Add terminating character */ + *p++ = '\0'; + + len = strlen(s); + + if ((ssize_t)len > (length - 1)) + __archive_errx(1, "Buffer overrun"); + + if (text_len != NULL) + *text_len = len; + + return (s); } static void @@ -760,9 +1015,11 @@ append_id(char **p, int id) } static void -append_entry(char **p, const char *prefix, int tag, - const char *name, int perm, int id) +append_entry(char **p, const char *prefix, int type, + int tag, int flags, const char *name, int perm, int id) { + int i; + if (prefix != NULL) { strcpy(*p, prefix); *p += strlen(*p); @@ -771,6 +1028,10 @@ append_entry(char **p, const char *prefix, int tag, case ARCHIVE_ENTRY_ACL_USER_OBJ: name = NULL; id = -1; + if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { + strcpy(*p, "owner@"); + break; + } /* FALLTHROUGH */ case ARCHIVE_ENTRY_ACL_USER: strcpy(*p, "user"); @@ -778,6 +1039,10 @@ append_entry(char **p, const char *prefix, int tag, case ARCHIVE_ENTRY_ACL_GROUP_OBJ: name = NULL; id = -1; + if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { + strcpy(*p, "group@"); + break; + } /* FALLTHROUGH */ case ARCHIVE_ENTRY_ACL_GROUP: strcpy(*p, "group"); @@ -792,48 +1057,120 @@ append_entry(char **p, const char *prefix, int tag, name = NULL; id = -1; break; + case ARCHIVE_ENTRY_ACL_EVERYONE: + strcpy(*p, "everyone@"); + name = NULL; + id = -1; + break; } *p += strlen(*p); *(*p)++ = ':'; - if (name != NULL) { - strcpy(*p, name); + if (((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) || + tag == ARCHIVE_ENTRY_ACL_USER || + tag == ARCHIVE_ENTRY_ACL_GROUP) { + if (name != NULL) { + strcpy(*p, name); + *p += strlen(*p); + } else if (tag == ARCHIVE_ENTRY_ACL_USER + || tag == ARCHIVE_ENTRY_ACL_GROUP) { + append_id(p, id); + if ((type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) == 0) + id = -1; + } + /* Solaris style has no second colon after other and mask */ + if (((flags & ARCHIVE_ENTRY_ACL_STYLE_SOLARIS) == 0) + || (tag != ARCHIVE_ENTRY_ACL_OTHER + && tag != ARCHIVE_ENTRY_ACL_MASK)) + *(*p)++ = ':'; + } + if ((type & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) { + /* POSIX.1e ACL perms */ + *(*p)++ = (perm & 0444) ? 'r' : '-'; + *(*p)++ = (perm & 0222) ? 'w' : '-'; + *(*p)++ = (perm & 0111) ? 'x' : '-'; + } else { + /* NFSv4 ACL perms */ + for (i = 0; i < nfsv4_acl_perm_map_size; i++) { + if (perm & nfsv4_acl_perm_map[i].perm) + *(*p)++ = nfsv4_acl_perm_map[i].c; + else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0) + *(*p)++ = '-'; + } + *(*p)++ = ':'; + for (i = 0; i < nfsv4_acl_flag_map_size; i++) { + if (perm & nfsv4_acl_flag_map[i].perm) + *(*p)++ = nfsv4_acl_flag_map[i].c; + else if ((flags & ARCHIVE_ENTRY_ACL_STYLE_COMPACT) == 0) + *(*p)++ = '-'; + } + *(*p)++ = ':'; + switch (type) { + case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: + strcpy(*p, "allow"); + break; + case ARCHIVE_ENTRY_ACL_TYPE_DENY: + strcpy(*p, "deny"); + break; + case ARCHIVE_ENTRY_ACL_TYPE_AUDIT: + strcpy(*p, "audit"); + break; + case ARCHIVE_ENTRY_ACL_TYPE_ALARM: + strcpy(*p, "alarm"); + break; + } *p += strlen(*p); - } else if (tag == ARCHIVE_ENTRY_ACL_USER - || tag == ARCHIVE_ENTRY_ACL_GROUP) { - append_id(p, id); - id = -1; } - *(*p)++ = ':'; - *(*p)++ = (perm & 0444) ? 'r' : '-'; - *(*p)++ = (perm & 0222) ? 'w' : '-'; - *(*p)++ = (perm & 0111) ? 'x' : '-'; if (id != -1) { *(*p)++ = ':'; append_id(p, id); } - **p = '\0'; } /* - * Parse a textual ACL. This automatically recognizes and supports - * extensions described above. The 'type' argument is used to - * indicate the type that should be used for any entries not - * explicitly marked as "default:". + * Parse a wide ACL text string. + * + * The want_type argument may be one of the following: + * ARCHIVE_ENTRY_ACL_TYPE_ACCESS - text is a POSIX.1e ACL of type ACCESS + * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - text is a POSIX.1e ACL of type DEFAULT + * ARCHIVE_ENTRY_ACL_TYPE_NFS4 - text is as a NFSv4 ACL + * + * POSIX.1e ACL entries prefixed with "default:" are treated as + * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT unless type is ARCHIVE_ENTRY_ACL_TYPE_NFS4 */ int -archive_acl_parse_w(struct archive_acl *acl, - const wchar_t *text, int default_type) +archive_acl_from_text_w(struct archive_acl *acl, const wchar_t *text, + int want_type) { struct { const wchar_t *start; const wchar_t *end; - } field[4], name; + } field[6], name; + + const wchar_t *s, *st; - int fields, n; - int type, tag, permset, id; + int numfields, fields, n, r, sol, ret; + int type, types, tag, permset, id; + size_t len; wchar_t sep; - while (text != NULL && *text != L'\0') { + ret = ARCHIVE_OK; + types = 0; + + switch (want_type) { + case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E: + want_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS; + case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: + case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: + numfields = 5; + break; + case ARCHIVE_ENTRY_ACL_TYPE_NFS4: + numfields = 6; + break; + default: + return (ARCHIVE_FATAL); + } + + while (text != NULL && *text != L'\0') { /* * Parse the fields out of the next entry, * advance 'text' to start of next entry. @@ -842,7 +1179,7 @@ archive_acl_parse_w(struct archive_acl *acl, do { const wchar_t *start, *end; next_field_w(&text, &start, &end, &sep); - if (fields < 4) { + if (fields < numfields) { field[fields].start = start; field[fields].end = end; } @@ -850,78 +1187,210 @@ archive_acl_parse_w(struct archive_acl *acl, } while (sep == L':'); /* Set remaining fields to blank. */ - for (n = fields; n < 4; ++n) + for (n = fields; n < numfields; ++n) field[n].start = field[n].end = NULL; - /* Check for a numeric ID in field 1 or 3. */ - id = -1; - isint_w(field[1].start, field[1].end, &id); - /* Field 3 is optional. */ - if (id == -1 && fields > 3) - isint_w(field[3].start, field[3].end, &id); - - /* - * Solaris extension: "defaultuser::rwx" is the - * default ACL corresponding to "user::rwx", etc. - */ - if (field[0].end - field[0].start > 7 - && wmemcmp(field[0].start, L"default", 7) == 0) { - type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT; - field[0].start += 7; - } else - type = default_type; + if (field[0].start != NULL && *(field[0].start) == L'#') { + /* Comment, skip entry */ + continue; + } + n = 0; + sol = 0; + id = -1; + permset = 0; name.start = name.end = NULL; - if (prefix_w(field[0].start, field[0].end, L"user")) { - if (!ismode_w(field[2].start, field[2].end, &permset)) - return (ARCHIVE_WARN); - if (id != -1 || field[1].start < field[1].end) { - tag = ARCHIVE_ENTRY_ACL_USER; - name = field[1]; + + if (want_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + /* POSIX.1e ACLs */ + /* + * Default keyword "default:user::rwx" + * if found, we have one more field + * + * We also support old Solaris extension: + * "defaultuser::rwx" is the default ACL corresponding + * to "user::rwx", etc. valid only for first field + */ + s = field[0].start; + len = field[0].end - field[0].start; + if (*s == L'd' && (len == 1 || (len >= 7 + && wmemcmp((s + 1), L"efault", 6) == 0))) { + type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT; + if (len > 7) + field[0].start += 7; + else + n = 1; } else - tag = ARCHIVE_ENTRY_ACL_USER_OBJ; - } else if (prefix_w(field[0].start, field[0].end, L"group")) { - if (!ismode_w(field[2].start, field[2].end, &permset)) - return (ARCHIVE_WARN); - if (id != -1 || field[1].start < field[1].end) { - tag = ARCHIVE_ENTRY_ACL_GROUP; + type = want_type; + + /* Check for a numeric ID in field n+1 or n+3. */ + isint_w(field[n + 1].start, field[n + 1].end, &id); + /* Field n+3 is optional. */ + if (id == -1 && fields > n+3) + isint_w(field[n + 3].start, field[n + 3].end, + &id); + + tag = 0; + s = field[n].start; + st = field[n].start + 1; + len = field[n].end - field[n].start; + + switch (*s) { + case L'u': + if (len == 1 || (len == 4 + && wmemcmp(st, L"ser", 3) == 0)) + tag = ARCHIVE_ENTRY_ACL_USER_OBJ; + break; + case L'g': + if (len == 1 || (len == 5 + && wmemcmp(st, L"roup", 4) == 0)) + tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; + break; + case L'o': + if (len == 1 || (len == 5 + && wmemcmp(st, L"ther", 4) == 0)) + tag = ARCHIVE_ENTRY_ACL_OTHER; + break; + case L'm': + if (len == 1 || (len == 4 + && wmemcmp(st, L"ask", 3) == 0)) + tag = ARCHIVE_ENTRY_ACL_MASK; + break; + default: + break; + } + + switch (tag) { + case ARCHIVE_ENTRY_ACL_OTHER: + case ARCHIVE_ENTRY_ACL_MASK: + if (fields == (n + 2) + && field[n + 1].start < field[n + 1].end + && ismode_w(field[n + 1].start, + field[n + 1].end, &permset)) { + /* This is Solaris-style "other:rwx" */ + sol = 1; + } else if (fields == (n + 3) && + field[n + 1].start < field[n + 1].end) { + /* Invalid mask or other field */ + ret = ARCHIVE_WARN; + continue; + } + break; + case ARCHIVE_ENTRY_ACL_USER_OBJ: + case ARCHIVE_ENTRY_ACL_GROUP_OBJ: + if (id != -1 || + field[n + 1].start < field[n + 1].end) { + name = field[n + 1]; + if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ) + tag = ARCHIVE_ENTRY_ACL_USER; + else + tag = ARCHIVE_ENTRY_ACL_GROUP; + } + break; + default: + /* Invalid tag, skip entry */ + ret = ARCHIVE_WARN; + continue; + } + + /* + * Without "default:" we expect mode in field 2 + * Exception: Solaris other and mask fields + */ + if (permset == 0 && !ismode_w(field[n + 2 - sol].start, + field[n + 2 - sol].end, &permset)) { + /* Invalid mode, skip entry */ + ret = ARCHIVE_WARN; + continue; + } + } else { + /* NFS4 ACLs */ + s = field[0].start; + len = field[0].end - field[0].start; + tag = 0; + + switch (len) { + case 4: + if (wmemcmp(s, L"user", 4) == 0) + tag = ARCHIVE_ENTRY_ACL_USER; + break; + case 5: + if (wmemcmp(s, L"group", 5) == 0) + tag = ARCHIVE_ENTRY_ACL_GROUP; + break; + case 6: + if (wmemcmp(s, L"owner@", 6) == 0) + tag = ARCHIVE_ENTRY_ACL_USER_OBJ; + else if (wmemcmp(s, L"group@", len) == 0) + tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; + break; + case 9: + if (wmemcmp(s, L"everyone@", 9) == 0) + tag = ARCHIVE_ENTRY_ACL_EVERYONE; + default: + break; + } + + if (tag == 0) { + /* Invalid tag, skip entry */ + ret = ARCHIVE_WARN; + continue; + } else if (tag == ARCHIVE_ENTRY_ACL_USER || + tag == ARCHIVE_ENTRY_ACL_GROUP) { + n = 1; name = field[1]; + isint_w(name.start, name.end, &id); } else - tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; - } else if (prefix_w(field[0].start, field[0].end, L"other")) { - if (fields == 2 - && field[1].start < field[1].end - && ismode_w(field[1].start, field[1].end, &permset)) { - /* This is Solaris-style "other:rwx" */ - } else if (fields == 3 - && field[1].start == field[1].end - && field[2].start < field[2].end - && ismode_w(field[2].start, field[2].end, &permset)) { - /* This is FreeBSD-style "other::rwx" */ - } else - return (ARCHIVE_WARN); - tag = ARCHIVE_ENTRY_ACL_OTHER; - } else if (prefix_w(field[0].start, field[0].end, L"mask")) { - if (fields == 2 - && field[1].start < field[1].end - && ismode_w(field[1].start, field[1].end, &permset)) { - /* This is Solaris-style "mask:rwx" */ - } else if (fields == 3 - && field[1].start == field[1].end - && field[2].start < field[2].end - && ismode_w(field[2].start, field[2].end, &permset)) { - /* This is FreeBSD-style "mask::rwx" */ - } else - return (ARCHIVE_WARN); - tag = ARCHIVE_ENTRY_ACL_MASK; - } else - return (ARCHIVE_WARN); + n = 0; + + if (!is_nfs4_perms_w(field[1 + n].start, + field[1 + n].end, &permset)) { + /* Invalid NFSv4 perms, skip entry */ + ret = ARCHIVE_WARN; + continue; + } + if (!is_nfs4_flags_w(field[2 + n].start, + field[2 + n].end, &permset)) { + /* Invalid NFSv4 flags, skip entry */ + ret = ARCHIVE_WARN; + continue; + } + s = field[3 + n].start; + len = field[3 + n].end - field[3 + n].start; + type = 0; + if (len == 4) { + if (wmemcmp(s, L"deny", 4) == 0) + type = ARCHIVE_ENTRY_ACL_TYPE_DENY; + } else if (len == 5) { + if (wmemcmp(s, L"allow", 5) == 0) + type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; + else if (wmemcmp(s, L"audit", 5) == 0) + type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT; + else if (wmemcmp(s, L"alarm", 5) == 0) + type = ARCHIVE_ENTRY_ACL_TYPE_ALARM; + } + if (type == 0) { + /* Invalid entry type, skip entry */ + ret = ARCHIVE_WARN; + continue; + } + isint_w(field[4 + n].start, field[4 + n].end, &id); + } /* Add entry to the internal list. */ - archive_acl_add_entry_w_len(acl, type, permset, + r = archive_acl_add_entry_w_len(acl, type, permset, tag, id, name.start, name.end - name.start); + if (r < ARCHIVE_WARN) + return (r); + if (r != ARCHIVE_OK) + ret = ARCHIVE_WARN; + types |= type; } - return (ARCHIVE_OK); + + /* Reset ACL */ + archive_acl_reset(acl, types); + + return (ret); } /* @@ -967,16 +1436,122 @@ ismode_w(const wchar_t *start, const wchar_t *end, int *permset) *permset = 0; while (p < end) { switch (*p++) { - case 'r': case 'R': + case L'r': case L'R': *permset |= ARCHIVE_ENTRY_ACL_READ; break; - case 'w': case 'W': + case L'w': case L'W': *permset |= ARCHIVE_ENTRY_ACL_WRITE; break; - case 'x': case 'X': + case L'x': case L'X': *permset |= ARCHIVE_ENTRY_ACL_EXECUTE; break; - case '-': + case L'-': + break; + default: + return (0); + } + } + return (1); +} + +/* + * Parse a string as a NFS4 ACL permission field. + * Returns true if the string is non-empty and consists only of NFS4 ACL + * permission characters, false otherwise + */ +static int +is_nfs4_perms_w(const wchar_t *start, const wchar_t *end, int *permset) +{ + const wchar_t *p = start; + + while (p < end) { + switch (*p++) { + case L'r': + *permset |= ARCHIVE_ENTRY_ACL_READ_DATA; + break; + case L'w': + *permset |= ARCHIVE_ENTRY_ACL_WRITE_DATA; + break; + case L'x': + *permset |= ARCHIVE_ENTRY_ACL_EXECUTE; + break; + case L'p': + *permset |= ARCHIVE_ENTRY_ACL_APPEND_DATA; + break; + case L'D': + *permset |= ARCHIVE_ENTRY_ACL_DELETE_CHILD; + break; + case L'd': + *permset |= ARCHIVE_ENTRY_ACL_DELETE; + break; + case L'a': + *permset |= ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES; + break; + case L'A': + *permset |= ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES; + break; + case L'R': + *permset |= ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS; + break; + case L'W': + *permset |= ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS; + break; + case L'c': + *permset |= ARCHIVE_ENTRY_ACL_READ_ACL; + break; + case L'C': + *permset |= ARCHIVE_ENTRY_ACL_WRITE_ACL; + break; + case L'o': + *permset |= ARCHIVE_ENTRY_ACL_WRITE_OWNER; + break; + case L's': + *permset |= ARCHIVE_ENTRY_ACL_SYNCHRONIZE; + break; + case L'-': + break; + default: + return(0); + } + } + return (1); +} + +/* + * Parse a string as a NFS4 ACL flags field. + * Returns true if the string is non-empty and consists only of NFS4 ACL + * flag characters, false otherwise + */ +static int +is_nfs4_flags_w(const wchar_t *start, const wchar_t *end, int *permset) +{ + const wchar_t *p = start; + + while (p < end) { + switch(*p++) { + case L'f': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT; + break; + case L'd': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT; + break; + case L'i': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY; + break; + case L'n': + *permset |= + ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT; + break; + case L'S': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS; + break; + case L'F': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS; + break; + case L'I': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERITED; + break; + case L'-': break; default: return (0); @@ -1023,46 +1598,48 @@ next_field_w(const wchar_t **wp, const wchar_t **start, } /* - * Return true if the characters [start...end) are a prefix of 'test'. - * This makes it easy to handle the obvious abbreviations: 'u' for 'user', etc. - */ -static int -prefix_w(const wchar_t *start, const wchar_t *end, const wchar_t *test) -{ - if (start == end) - return (0); - - if (*start++ != *test++) - return (0); - - while (start < end && *start++ == *test++) - ; - - if (start < end) - return (0); - - return (1); -} - -/* - * Parse a textual ACL. This automatically recognizes and supports - * extensions described above. The 'type' argument is used to - * indicate the type that should be used for any entries not - * explicitly marked as "default:". + * Parse an ACL text string. + * + * The want_type argument may be one of the following: + * ARCHIVE_ENTRY_ACL_TYPE_ACCESS - text is a POSIX.1e ACL of type ACCESS + * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - text is a POSIX.1e ACL of type DEFAULT + * ARCHIVE_ENTRY_ACL_TYPE_NFS4 - text is as a NFSv4 ACL + * + * POSIX.1e ACL entries prefixed with "default:" are treated as + * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT unless type is ARCHIVE_ENTRY_ACL_TYPE_NFS4 */ int -archive_acl_parse_l(struct archive_acl *acl, - const char *text, int default_type, struct archive_string_conv *sc) +archive_acl_from_text_l(struct archive_acl *acl, const char *text, + int want_type, struct archive_string_conv *sc) { struct { const char *start; const char *end; - } field[4], name; + } field[6], name; - int fields, n, r, ret = ARCHIVE_OK; - int type, tag, permset, id; + const char *s, *st; + int numfields, fields, n, r, sol, ret; + int type, types, tag, permset, id; + size_t len; char sep; + switch (want_type) { + case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E: + want_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS; + case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: + case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: + numfields = 5; + break; + case ARCHIVE_ENTRY_ACL_TYPE_NFS4: + numfields = 6; + break; + default: + return (ARCHIVE_FATAL); + } + + ret = ARCHIVE_OK; + types = 0; + while (text != NULL && *text != '\0') { /* * Parse the fields out of the next entry, @@ -1072,7 +1649,7 @@ archive_acl_parse_l(struct archive_acl *acl, do { const char *start, *end; next_field(&text, &start, &end, &sep); - if (fields < 4) { + if (fields < numfields) { field[fields].start = start; field[fields].end = end; } @@ -1080,72 +1657,197 @@ archive_acl_parse_l(struct archive_acl *acl, } while (sep == ':'); /* Set remaining fields to blank. */ - for (n = fields; n < 4; ++n) + for (n = fields; n < numfields; ++n) field[n].start = field[n].end = NULL; - /* Check for a numeric ID in field 1 or 3. */ - id = -1; - isint(field[1].start, field[1].end, &id); - /* Field 3 is optional. */ - if (id == -1 && fields > 3) - isint(field[3].start, field[3].end, &id); - - /* - * Solaris extension: "defaultuser::rwx" is the - * default ACL corresponding to "user::rwx", etc. - */ - if (field[0].end - field[0].start > 7 - && memcmp(field[0].start, "default", 7) == 0) { - type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT; - field[0].start += 7; - } else - type = default_type; + if (field[0].start != NULL && *(field[0].start) == '#') { + /* Comment, skip entry */ + continue; + } + n = 0; + sol = 0; + id = -1; + permset = 0; name.start = name.end = NULL; - if (prefix_c(field[0].start, field[0].end, "user")) { - if (!ismode(field[2].start, field[2].end, &permset)) - return (ARCHIVE_WARN); - if (id != -1 || field[1].start < field[1].end) { - tag = ARCHIVE_ENTRY_ACL_USER; - name = field[1]; + + if (want_type != ARCHIVE_ENTRY_ACL_TYPE_NFS4) { + /* POSIX.1e ACLs */ + /* + * Default keyword "default:user::rwx" + * if found, we have one more field + * + * We also support old Solaris extension: + * "defaultuser::rwx" is the default ACL corresponding + * to "user::rwx", etc. valid only for first field + */ + s = field[0].start; + len = field[0].end - field[0].start; + if (*s == 'd' && (len == 1 || (len >= 7 + && memcmp((s + 1), "efault", 6) == 0))) { + type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT; + if (len > 7) + field[0].start += 7; + else + n = 1; } else - tag = ARCHIVE_ENTRY_ACL_USER_OBJ; - } else if (prefix_c(field[0].start, field[0].end, "group")) { - if (!ismode(field[2].start, field[2].end, &permset)) - return (ARCHIVE_WARN); - if (id != -1 || field[1].start < field[1].end) { - tag = ARCHIVE_ENTRY_ACL_GROUP; + type = want_type; + + /* Check for a numeric ID in field n+1 or n+3. */ + isint(field[n + 1].start, field[n + 1].end, &id); + /* Field n+3 is optional. */ + if (id == -1 && fields > (n + 3)) + isint(field[n + 3].start, field[n + 3].end, + &id); + + tag = 0; + s = field[n].start; + st = field[n].start + 1; + len = field[n].end - field[n].start; + + switch (*s) { + case 'u': + if (len == 1 || (len == 4 + && memcmp(st, "ser", 3) == 0)) + tag = ARCHIVE_ENTRY_ACL_USER_OBJ; + break; + case 'g': + if (len == 1 || (len == 5 + && memcmp(st, "roup", 4) == 0)) + tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; + break; + case 'o': + if (len == 1 || (len == 5 + && memcmp(st, "ther", 4) == 0)) + tag = ARCHIVE_ENTRY_ACL_OTHER; + break; + case 'm': + if (len == 1 || (len == 4 + && memcmp(st, "ask", 3) == 0)) + tag = ARCHIVE_ENTRY_ACL_MASK; + break; + default: + break; + } + + switch (tag) { + case ARCHIVE_ENTRY_ACL_OTHER: + case ARCHIVE_ENTRY_ACL_MASK: + if (fields == (n + 2) + && field[n + 1].start < field[n + 1].end + && ismode(field[n + 1].start, + field[n + 1].end, &permset)) { + /* This is Solaris-style "other:rwx" */ + sol = 1; + } else if (fields == (n + 3) && + field[n + 1].start < field[n + 1].end) { + /* Invalid mask or other field */ + ret = ARCHIVE_WARN; + continue; + } + break; + case ARCHIVE_ENTRY_ACL_USER_OBJ: + case ARCHIVE_ENTRY_ACL_GROUP_OBJ: + if (id != -1 || + field[n + 1].start < field[n + 1].end) { + name = field[n + 1]; + if (tag == ARCHIVE_ENTRY_ACL_USER_OBJ) + tag = ARCHIVE_ENTRY_ACL_USER; + else + tag = ARCHIVE_ENTRY_ACL_GROUP; + } + break; + default: + /* Invalid tag, skip entry */ + ret = ARCHIVE_WARN; + continue; + } + + /* + * Without "default:" we expect mode in field 3 + * Exception: Solaris other and mask fields + */ + if (permset == 0 && !ismode(field[n + 2 - sol].start, + field[n + 2 - sol].end, &permset)) { + /* Invalid mode, skip entry */ + ret = ARCHIVE_WARN; + continue; + } + } else { + /* NFS4 ACLs */ + s = field[0].start; + len = field[0].end - field[0].start; + tag = 0; + + switch (len) { + case 4: + if (memcmp(s, "user", 4) == 0) + tag = ARCHIVE_ENTRY_ACL_USER; + break; + case 5: + if (memcmp(s, "group", 5) == 0) + tag = ARCHIVE_ENTRY_ACL_GROUP; + break; + case 6: + if (memcmp(s, "owner@", 6) == 0) + tag = ARCHIVE_ENTRY_ACL_USER_OBJ; + else if (memcmp(s, "group@", 6) == 0) + tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; + break; + case 9: + if (memcmp(s, "everyone@", 9) == 0) + tag = ARCHIVE_ENTRY_ACL_EVERYONE; + break; + default: + break; + } + + if (tag == 0) { + /* Invalid tag, skip entry */ + ret = ARCHIVE_WARN; + continue; + } else if (tag == ARCHIVE_ENTRY_ACL_USER || + tag == ARCHIVE_ENTRY_ACL_GROUP) { + n = 1; name = field[1]; + isint(name.start, name.end, &id); } else - tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; - } else if (prefix_c(field[0].start, field[0].end, "other")) { - if (fields == 2 - && field[1].start < field[1].end - && ismode(field[1].start, field[1].end, &permset)) { - /* This is Solaris-style "other:rwx" */ - } else if (fields == 3 - && field[1].start == field[1].end - && field[2].start < field[2].end - && ismode(field[2].start, field[2].end, &permset)) { - /* This is FreeBSD-style "other::rwx" */ - } else - return (ARCHIVE_WARN); - tag = ARCHIVE_ENTRY_ACL_OTHER; - } else if (prefix_c(field[0].start, field[0].end, "mask")) { - if (fields == 2 - && field[1].start < field[1].end - && ismode(field[1].start, field[1].end, &permset)) { - /* This is Solaris-style "mask:rwx" */ - } else if (fields == 3 - && field[1].start == field[1].end - && field[2].start < field[2].end - && ismode(field[2].start, field[2].end, &permset)) { - /* This is FreeBSD-style "mask::rwx" */ - } else - return (ARCHIVE_WARN); - tag = ARCHIVE_ENTRY_ACL_MASK; - } else - return (ARCHIVE_WARN); + n = 0; + + if (!is_nfs4_perms(field[1 + n].start, + field[1 + n].end, &permset)) { + /* Invalid NFSv4 perms, skip entry */ + ret = ARCHIVE_WARN; + continue; + } + if (!is_nfs4_flags(field[2 + n].start, + field[2 + n].end, &permset)) { + /* Invalid NFSv4 flags, skip entry */ + ret = ARCHIVE_WARN; + continue; + } + s = field[3 + n].start; + len = field[3 + n].end - field[3 + n].start; + type = 0; + if (len == 4) { + if (memcmp(s, "deny", 4) == 0) + type = ARCHIVE_ENTRY_ACL_TYPE_DENY; + } else if (len == 5) { + if (memcmp(s, "allow", 5) == 0) + type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; + else if (memcmp(s, "audit", 5) == 0) + type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT; + else if (memcmp(s, "alarm", 5) == 0) + type = ARCHIVE_ENTRY_ACL_TYPE_ALARM; + } + if (type == 0) { + /* Invalid entry type, skip entry */ + ret = ARCHIVE_WARN; + continue; + } + isint(field[4 + n].start, field[4 + n].end, + &id); + } /* Add entry to the internal list. */ r = archive_acl_add_entry_len_l(acl, type, permset, @@ -1154,7 +1856,12 @@ archive_acl_parse_l(struct archive_acl *acl, return (r); if (r != ARCHIVE_OK) ret = ARCHIVE_WARN; + types |= type; } + + /* Reset ACL */ + archive_acl_reset(acl, types); + return (ret); } @@ -1220,6 +1927,112 @@ ismode(const char *start, const char *end, int *permset) } /* + * Parse a string as a NFS4 ACL permission field. + * Returns true if the string is non-empty and consists only of NFS4 ACL + * permission characters, false otherwise + */ +static int +is_nfs4_perms(const char *start, const char *end, int *permset) +{ + const char *p = start; + + while (p < end) { + switch (*p++) { + case 'r': + *permset |= ARCHIVE_ENTRY_ACL_READ_DATA; + break; + case 'w': + *permset |= ARCHIVE_ENTRY_ACL_WRITE_DATA; + break; + case 'x': + *permset |= ARCHIVE_ENTRY_ACL_EXECUTE; + break; + case 'p': + *permset |= ARCHIVE_ENTRY_ACL_APPEND_DATA; + break; + case 'D': + *permset |= ARCHIVE_ENTRY_ACL_DELETE_CHILD; + break; + case 'd': + *permset |= ARCHIVE_ENTRY_ACL_DELETE; + break; + case 'a': + *permset |= ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES; + break; + case 'A': + *permset |= ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES; + break; + case 'R': + *permset |= ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS; + break; + case 'W': + *permset |= ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS; + break; + case 'c': + *permset |= ARCHIVE_ENTRY_ACL_READ_ACL; + break; + case 'C': + *permset |= ARCHIVE_ENTRY_ACL_WRITE_ACL; + break; + case 'o': + *permset |= ARCHIVE_ENTRY_ACL_WRITE_OWNER; + break; + case 's': + *permset |= ARCHIVE_ENTRY_ACL_SYNCHRONIZE; + break; + case '-': + break; + default: + return(0); + } + } + return (1); +} + +/* + * Parse a string as a NFS4 ACL flags field. + * Returns true if the string is non-empty and consists only of NFS4 ACL + * flag characters, false otherwise + */ +static int +is_nfs4_flags(const char *start, const char *end, int *permset) +{ + const char *p = start; + + while (p < end) { + switch(*p++) { + case 'f': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT; + break; + case 'd': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT; + break; + case 'i': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY; + break; + case 'n': + *permset |= + ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT; + break; + case 'S': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS; + break; + case 'F': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS; + break; + case 'I': + *permset |= ARCHIVE_ENTRY_ACL_ENTRY_INHERITED; + break; + case '-': + break; + default: + return (0); + } + } + return (1); +} + +/* * Match "[:whitespace:]*(.*)[:whitespace:]*[:,\n]". *wp is updated * to point to just after the separator. *start points to the first * character of the matched text and *end just after the last @@ -1254,25 +2067,3 @@ next_field(const char **p, const char **start, if (**p != '\0') (*p)++; } - -/* - * Return true if the characters [start...end) are a prefix of 'test'. - * This makes it easy to handle the obvious abbreviations: 'u' for 'user', etc. - */ -static int -prefix_c(const char *start, const char *end, const char *test) -{ - if (start == end) - return (0); - - if (*start++ != *test++) - return (0); - - while (start < end && *start++ == *test++) - ; - - if (start < end) - return (0); - - return (1); -} diff --git a/libarchive/archive_acl_private.h b/libarchive/archive_acl_private.h index 1421adb..ef0b023 100644 --- a/libarchive/archive_acl_private.h +++ b/libarchive/archive_acl_private.h @@ -56,6 +56,7 @@ struct archive_acl { void archive_acl_clear(struct archive_acl *); void archive_acl_copy(struct archive_acl *, struct archive_acl *); int archive_acl_count(struct archive_acl *, int); +int archive_acl_types(struct archive_acl *); int archive_acl_reset(struct archive_acl *, int); int archive_acl_next(struct archive *, struct archive_acl *, int, int *, int *, int *, int *, const char **); @@ -66,22 +67,17 @@ int archive_acl_add_entry_w_len(struct archive_acl *, int archive_acl_add_entry_len(struct archive_acl *, int, int, int, int, const char *, size_t); -const wchar_t *archive_acl_text_w(struct archive *, struct archive_acl *, int); -int archive_acl_text_l(struct archive_acl *, int, const char **, size_t *, +wchar_t *archive_acl_to_text_w(struct archive_acl *, ssize_t *, int, + struct archive *); +char *archive_acl_to_text_l(struct archive_acl *, ssize_t *, int, struct archive_string_conv *); /* - * Private ACL parser. This is private because it handles some - * very weird formats that clients should not be messing with. - * Clients should only deal with their platform-native formats. - * Because of the need to support many formats cleanly, new arguments - * are likely to get added on a regular basis. Clients who try to use - * this interface are likely to be surprised when it changes. + * ACL text parser. */ -int archive_acl_parse_w(struct archive_acl *, - const wchar_t *, int /* type */); -int archive_acl_parse_l(struct archive_acl *, - const char *, int /* type */, - struct archive_string_conv *); +int archive_acl_from_text_w(struct archive_acl *, const wchar_t * /* wtext */, + int /* type */); +int archive_acl_from_text_l(struct archive_acl *, const char * /* text */, + int /* type */, struct archive_string_conv *); #endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */ diff --git a/libarchive/archive_cryptor.c b/libarchive/archive_cryptor.c index 0be30c6..ced52fd 100644 --- a/libarchive/archive_cryptor.c +++ b/libarchive/archive_cryptor.c @@ -302,6 +302,8 @@ aes_ctr_release(archive_crypto_ctx *ctx) static int aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len) { + if ((ctx->ctx = EVP_CIPHER_CTX_new()) == NULL) + return -1; switch (key_len) { case 16: ctx->type = EVP_aes_128_ecb(); break; @@ -314,7 +316,7 @@ aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len) memcpy(ctx->key, key, key_len); memset(ctx->nonce, 0, sizeof(ctx->nonce)); ctx->encr_pos = AES_BLOCK_SIZE; - EVP_CIPHER_CTX_init(&ctx->ctx); + EVP_CIPHER_CTX_init(ctx->ctx); return 0; } @@ -324,10 +326,10 @@ aes_ctr_encrypt_counter(archive_crypto_ctx *ctx) int outl = 0; int r; - r = EVP_EncryptInit_ex(&ctx->ctx, ctx->type, NULL, ctx->key, NULL); + r = EVP_EncryptInit_ex(ctx->ctx, ctx->type, NULL, ctx->key, NULL); if (r == 0) return -1; - r = EVP_EncryptUpdate(&ctx->ctx, ctx->encr_buf, &outl, ctx->nonce, + r = EVP_EncryptUpdate(ctx->ctx, ctx->encr_buf, &outl, ctx->nonce, AES_BLOCK_SIZE); if (r == 0 || outl != AES_BLOCK_SIZE) return -1; @@ -337,7 +339,7 @@ aes_ctr_encrypt_counter(archive_crypto_ctx *ctx) static int aes_ctr_release(archive_crypto_ctx *ctx) { - EVP_CIPHER_CTX_cleanup(&ctx->ctx); + EVP_CIPHER_CTX_free(ctx->ctx); memset(ctx->key, 0, ctx->key_len); memset(ctx->nonce, 0, sizeof(ctx->nonce)); return 0; diff --git a/libarchive/archive_cryptor_private.h b/libarchive/archive_cryptor_private.h index 37eaad3..0ca544b 100644 --- a/libarchive/archive_cryptor_private.h +++ b/libarchive/archive_cryptor_private.h @@ -99,12 +99,12 @@ typedef struct { } archive_crypto_ctx; #elif defined(HAVE_LIBCRYPTO) -#include +#include "archive_openssl_evp_private.h" #define AES_BLOCK_SIZE 16 #define AES_MAX_KEY_SIZE 32 typedef struct { - EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX *ctx; const EVP_CIPHER *type; uint8_t key[AES_MAX_KEY_SIZE]; unsigned key_len; diff --git a/libarchive/archive_digest.c b/libarchive/archive_digest.c index f009d31..4153923 100644 --- a/libarchive/archive_digest.c +++ b/libarchive/archive_digest.c @@ -207,7 +207,9 @@ __archive_nettle_md5final(archive_md5_ctx *ctx, void *md) static int __archive_openssl_md5init(archive_md5_ctx *ctx) { - EVP_DigestInit(ctx, EVP_md5()); + if ((*ctx = EVP_MD_CTX_new()) == NULL) + return (ARCHIVE_FAILED); + EVP_DigestInit(*ctx, EVP_md5()); return (ARCHIVE_OK); } @@ -215,7 +217,7 @@ static int __archive_openssl_md5update(archive_md5_ctx *ctx, const void *indata, size_t insize) { - EVP_DigestUpdate(ctx, indata, insize); + EVP_DigestUpdate(*ctx, indata, insize); return (ARCHIVE_OK); } @@ -226,8 +228,11 @@ __archive_openssl_md5final(archive_md5_ctx *ctx, void *md) * this is meant to cope with that. Real fix is probably to fix * archive_write_set_format_xar.c */ - if (ctx->digest) - EVP_DigestFinal(ctx, md, NULL); + if (*ctx) { + EVP_DigestFinal(*ctx, md, NULL); + EVP_MD_CTX_free(*ctx); + *ctx = NULL; + } return (ARCHIVE_OK); } @@ -359,7 +364,9 @@ __archive_nettle_ripemd160final(archive_rmd160_ctx *ctx, void *md) static int __archive_openssl_ripemd160init(archive_rmd160_ctx *ctx) { - EVP_DigestInit(ctx, EVP_ripemd160()); + if ((*ctx = EVP_MD_CTX_new()) == NULL) + return (ARCHIVE_FAILED); + EVP_DigestInit(*ctx, EVP_ripemd160()); return (ARCHIVE_OK); } @@ -367,14 +374,18 @@ static int __archive_openssl_ripemd160update(archive_rmd160_ctx *ctx, const void *indata, size_t insize) { - EVP_DigestUpdate(ctx, indata, insize); + EVP_DigestUpdate(*ctx, indata, insize); return (ARCHIVE_OK); } static int __archive_openssl_ripemd160final(archive_rmd160_ctx *ctx, void *md) { - EVP_DigestFinal(ctx, md, NULL); + if (*ctx) { + EVP_DigestFinal(*ctx, md, NULL); + EVP_MD_CTX_free(*ctx); + *ctx = NULL; + } return (ARCHIVE_OK); } @@ -509,7 +520,9 @@ __archive_nettle_sha1final(archive_sha1_ctx *ctx, void *md) static int __archive_openssl_sha1init(archive_sha1_ctx *ctx) { - EVP_DigestInit(ctx, EVP_sha1()); + if ((*ctx = EVP_MD_CTX_new()) == NULL) + return (ARCHIVE_FAILED); + EVP_DigestInit(*ctx, EVP_sha1()); return (ARCHIVE_OK); } @@ -517,7 +530,7 @@ static int __archive_openssl_sha1update(archive_sha1_ctx *ctx, const void *indata, size_t insize) { - EVP_DigestUpdate(ctx, indata, insize); + EVP_DigestUpdate(*ctx, indata, insize); return (ARCHIVE_OK); } @@ -528,8 +541,11 @@ __archive_openssl_sha1final(archive_sha1_ctx *ctx, void *md) * this is meant to cope with that. Real fix is probably to fix * archive_write_set_format_xar.c */ - if (ctx->digest) - EVP_DigestFinal(ctx, md, NULL); + if (*ctx) { + EVP_DigestFinal(*ctx, md, NULL); + EVP_MD_CTX_free(*ctx); + *ctx = NULL; + } return (ARCHIVE_OK); } @@ -733,7 +749,9 @@ __archive_nettle_sha256final(archive_sha256_ctx *ctx, void *md) static int __archive_openssl_sha256init(archive_sha256_ctx *ctx) { - EVP_DigestInit(ctx, EVP_sha256()); + if ((*ctx = EVP_MD_CTX_new()) == NULL) + return (ARCHIVE_FAILED); + EVP_DigestInit(*ctx, EVP_sha256()); return (ARCHIVE_OK); } @@ -741,14 +759,18 @@ static int __archive_openssl_sha256update(archive_sha256_ctx *ctx, const void *indata, size_t insize) { - EVP_DigestUpdate(ctx, indata, insize); + EVP_DigestUpdate(*ctx, indata, insize); return (ARCHIVE_OK); } static int __archive_openssl_sha256final(archive_sha256_ctx *ctx, void *md) { - EVP_DigestFinal(ctx, md, NULL); + if (*ctx) { + EVP_DigestFinal(*ctx, md, NULL); + EVP_MD_CTX_free(*ctx); + *ctx = NULL; + } return (ARCHIVE_OK); } @@ -928,7 +950,9 @@ __archive_nettle_sha384final(archive_sha384_ctx *ctx, void *md) static int __archive_openssl_sha384init(archive_sha384_ctx *ctx) { - EVP_DigestInit(ctx, EVP_sha384()); + if ((*ctx = EVP_MD_CTX_new()) == NULL) + return (ARCHIVE_FAILED); + EVP_DigestInit(*ctx, EVP_sha384()); return (ARCHIVE_OK); } @@ -936,14 +960,18 @@ static int __archive_openssl_sha384update(archive_sha384_ctx *ctx, const void *indata, size_t insize) { - EVP_DigestUpdate(ctx, indata, insize); + EVP_DigestUpdate(*ctx, indata, insize); return (ARCHIVE_OK); } static int __archive_openssl_sha384final(archive_sha384_ctx *ctx, void *md) { - EVP_DigestFinal(ctx, md, NULL); + if (*ctx) { + EVP_DigestFinal(*ctx, md, NULL); + EVP_MD_CTX_free(*ctx); + *ctx = NULL; + } return (ARCHIVE_OK); } @@ -1147,7 +1175,9 @@ __archive_nettle_sha512final(archive_sha512_ctx *ctx, void *md) static int __archive_openssl_sha512init(archive_sha512_ctx *ctx) { - EVP_DigestInit(ctx, EVP_sha512()); + if ((*ctx = EVP_MD_CTX_new()) == NULL) + return (ARCHIVE_FAILED); + EVP_DigestInit(*ctx, EVP_sha512()); return (ARCHIVE_OK); } @@ -1155,14 +1185,18 @@ static int __archive_openssl_sha512update(archive_sha512_ctx *ctx, const void *indata, size_t insize) { - EVP_DigestUpdate(ctx, indata, insize); + EVP_DigestUpdate(*ctx, indata, insize); return (ARCHIVE_OK); } static int __archive_openssl_sha512final(archive_sha512_ctx *ctx, void *md) { - EVP_DigestFinal(ctx, md, NULL); + if (*ctx) { + EVP_DigestFinal(*ctx, md, NULL); + EVP_MD_CTX_free(*ctx); + *ctx = NULL; + } return (ARCHIVE_OK); } diff --git a/libarchive/archive_digest_private.h b/libarchive/archive_digest_private.h index 77fad58..b58ffb3 100644 --- a/libarchive/archive_digest_private.h +++ b/libarchive/archive_digest_private.h @@ -134,7 +134,7 @@ defined(ARCHIVE_CRYPTO_SHA384_OPENSSL) ||\ defined(ARCHIVE_CRYPTO_SHA512_OPENSSL) #define ARCHIVE_CRYPTO_OPENSSL 1 -#include +#include "archive_openssl_evp_private.h" #endif /* Windows crypto headers */ @@ -161,7 +161,7 @@ typedef CC_MD5_CTX archive_md5_ctx; #elif defined(ARCHIVE_CRYPTO_MD5_NETTLE) typedef struct md5_ctx archive_md5_ctx; #elif defined(ARCHIVE_CRYPTO_MD5_OPENSSL) -typedef EVP_MD_CTX archive_md5_ctx; +typedef EVP_MD_CTX *archive_md5_ctx; #elif defined(ARCHIVE_CRYPTO_MD5_WIN) typedef Digest_CTX archive_md5_ctx; #else @@ -175,7 +175,7 @@ typedef RIPEMD160_CTX archive_rmd160_ctx; #elif defined(ARCHIVE_CRYPTO_RMD160_NETTLE) typedef struct ripemd160_ctx archive_rmd160_ctx; #elif defined(ARCHIVE_CRYPTO_RMD160_OPENSSL) -typedef EVP_MD_CTX archive_rmd160_ctx; +typedef EVP_MD_CTX *archive_rmd160_ctx; #else typedef unsigned char archive_rmd160_ctx; #endif @@ -189,7 +189,7 @@ typedef CC_SHA1_CTX archive_sha1_ctx; #elif defined(ARCHIVE_CRYPTO_SHA1_NETTLE) typedef struct sha1_ctx archive_sha1_ctx; #elif defined(ARCHIVE_CRYPTO_SHA1_OPENSSL) -typedef EVP_MD_CTX archive_sha1_ctx; +typedef EVP_MD_CTX *archive_sha1_ctx; #elif defined(ARCHIVE_CRYPTO_SHA1_WIN) typedef Digest_CTX archive_sha1_ctx; #else @@ -209,7 +209,7 @@ typedef CC_SHA256_CTX archive_sha256_ctx; #elif defined(ARCHIVE_CRYPTO_SHA256_NETTLE) typedef struct sha256_ctx archive_sha256_ctx; #elif defined(ARCHIVE_CRYPTO_SHA256_OPENSSL) -typedef EVP_MD_CTX archive_sha256_ctx; +typedef EVP_MD_CTX *archive_sha256_ctx; #elif defined(ARCHIVE_CRYPTO_SHA256_WIN) typedef Digest_CTX archive_sha256_ctx; #else @@ -227,7 +227,7 @@ typedef CC_SHA512_CTX archive_sha384_ctx; #elif defined(ARCHIVE_CRYPTO_SHA384_NETTLE) typedef struct sha384_ctx archive_sha384_ctx; #elif defined(ARCHIVE_CRYPTO_SHA384_OPENSSL) -typedef EVP_MD_CTX archive_sha384_ctx; +typedef EVP_MD_CTX *archive_sha384_ctx; #elif defined(ARCHIVE_CRYPTO_SHA384_WIN) typedef Digest_CTX archive_sha384_ctx; #else @@ -247,7 +247,7 @@ typedef CC_SHA512_CTX archive_sha512_ctx; #elif defined(ARCHIVE_CRYPTO_SHA512_NETTLE) typedef struct sha512_ctx archive_sha512_ctx; #elif defined(ARCHIVE_CRYPTO_SHA512_OPENSSL) -typedef EVP_MD_CTX archive_sha512_ctx; +typedef EVP_MD_CTX *archive_sha512_ctx; #elif defined(ARCHIVE_CRYPTO_SHA512_WIN) typedef Digest_CTX archive_sha512_ctx; #else diff --git a/libarchive/archive_entry.c b/libarchive/archive_entry.c index 4ac1966..d4f061b 100644 --- a/libarchive/archive_entry.c +++ b/libarchive/archive_entry.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 2003-2007 Tim Kientzle + * Copyright (c) 2016 Martin Matuska * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -248,10 +249,9 @@ archive_entry_new2(struct archive *a) { struct archive_entry *entry; - entry = (struct archive_entry *)malloc(sizeof(*entry)); + entry = (struct archive_entry *)calloc(1, sizeof(*entry)); if (entry == NULL) return (NULL); - memset(entry, 0, sizeof(*entry)); entry->archive = a; return (entry); } @@ -1442,6 +1442,15 @@ archive_entry_acl_add_entry_w(struct archive_entry *entry, } /* + * Return a bitmask of ACL types in an archive entry ACL list + */ +int +archive_entry_acl_types(struct archive_entry *entry) +{ + return (archive_acl_types(&entry->acl)); +} + +/* * Return a count of entries matching "want_type". */ int @@ -1478,34 +1487,121 @@ archive_entry_acl_next(struct archive_entry *entry, int want_type, int *type, } /* - * Generate a text version of the ACL. The flags parameter controls + * Generate a text version of the ACL. The flags parameter controls * the style of the generated ACL. */ +wchar_t * +archive_entry_acl_to_text_w(struct archive_entry *entry, ssize_t *len, + int flags) +{ + return (archive_acl_to_text_w(&entry->acl, len, flags, + entry->archive)); +} + +char * +archive_entry_acl_to_text(struct archive_entry *entry, ssize_t *len, + int flags) +{ + return (archive_acl_to_text_l(&entry->acl, len, flags, NULL)); +} + +char * +_archive_entry_acl_to_text_l(struct archive_entry *entry, ssize_t *len, + int flags, struct archive_string_conv *sc) +{ + return (archive_acl_to_text_l(&entry->acl, len, flags, sc)); +} + +/* + * ACL text parser. + */ +int +archive_entry_acl_from_text_w(struct archive_entry *entry, + const wchar_t *wtext, int type) +{ + return (archive_acl_from_text_w(&entry->acl, wtext, type)); +} + +int +archive_entry_acl_from_text(struct archive_entry *entry, + const char *text, int type) +{ + return (archive_acl_from_text_l(&entry->acl, text, type, NULL)); +} + +int +_archive_entry_acl_from_text_l(struct archive_entry *entry, const char *text, + int type, struct archive_string_conv *sc) +{ + return (archive_acl_from_text_l(&entry->acl, text, type, sc)); +} + +/* Deprecated */ +static int +archive_entry_acl_text_compat(int *flags) +{ + if ((*flags & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) == 0) + return (1); + + /* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID */ + if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) != 0) + *flags |= ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID; + + /* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT */ + if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0) + *flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT; + + *flags |= ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA; + + return (0); +} + +/* Deprecated */ const wchar_t * archive_entry_acl_text_w(struct archive_entry *entry, int flags) { - const wchar_t *r; - r = archive_acl_text_w(entry->archive, &entry->acl, flags); - if (r == NULL && errno == ENOMEM) - __archive_errx(1, "No memory"); - return (r); + if (entry->acl.acl_text_w != NULL) { + free(entry->acl.acl_text_w); + entry->acl.acl_text_w = NULL; + } + if (archive_entry_acl_text_compat(&flags) == 0) + entry->acl.acl_text_w = archive_acl_to_text_w(&entry->acl, + NULL, flags, entry->archive); + return (entry->acl.acl_text_w); } +/* Deprecated */ const char * archive_entry_acl_text(struct archive_entry *entry, int flags) { - const char *p; - if (archive_acl_text_l(&entry->acl, flags, &p, NULL, NULL) != 0 - && errno == ENOMEM) - __archive_errx(1, "No memory"); - return (p); + if (entry->acl.acl_text != NULL) { + free(entry->acl.acl_text); + entry->acl.acl_text = NULL; + } + if (archive_entry_acl_text_compat(&flags) == 0) + entry->acl.acl_text = archive_acl_to_text_l(&entry->acl, NULL, + flags, NULL); + + return (entry->acl.acl_text); } +/* Deprecated */ int _archive_entry_acl_text_l(struct archive_entry *entry, int flags, const char **acl_text, size_t *len, struct archive_string_conv *sc) { - return (archive_acl_text_l(&entry->acl, flags, acl_text, len, sc)); + if (entry->acl.acl_text != NULL) { + free(entry->acl.acl_text); + entry->acl.acl_text = NULL; + } + + if (archive_entry_acl_text_compat(&flags) == 0) + entry->acl.acl_text = archive_acl_to_text_l(&entry->acl, + (ssize_t *)len, flags, sc); + + *acl_text = entry->acl.acl_text; + + return (0); } /* diff --git a/libarchive/archive_entry.h b/libarchive/archive_entry.h index dab2c9d..2dd557a 100644 --- a/libarchive/archive_entry.h +++ b/libarchive/archive_entry.h @@ -1,5 +1,6 @@ /*- * Copyright (c) 2003-2008 Tim Kientzle + * Copyright (c) 2016 Martin Matuska * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,7 +30,7 @@ #define ARCHIVE_ENTRY_H_INCLUDED /* Note: Compiler will complain if this does not match archive.h! */ -#define ARCHIVE_VERSION_NUMBER 3002001 +#define ARCHIVE_VERSION_NUMBER 3003000 /* * Note: archive_entry.h is for use outside of libarchive; the @@ -104,6 +105,12 @@ typedef int64_t la_int64_t; # define __LA_DECL #endif +#if defined(__GNUC__) && __GNUC__ >= 3 && __GNUC_MINOR__ >= 1 +# define __LA_DEPRECATED __attribute__((deprecated)) +#else +# define __LA_DEPRECATED +#endif + #ifdef __cplusplus extern "C" { #endif @@ -420,6 +427,7 @@ __LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const voi /* * Inheritance values (NFS4 ACLs only); included in permset. */ +#define ARCHIVE_ENTRY_ACL_ENTRY_INHERITED 0x01000000 #define ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT 0x02000000 #define ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT 0x04000000 #define ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT 0x08000000 @@ -433,15 +441,16 @@ __LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const voi | ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT \ | ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY \ | ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS \ - | ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS) + | ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS \ + | ARCHIVE_ENTRY_ACL_ENTRY_INHERITED) /* We need to be able to specify combinations of these. */ -#define ARCHIVE_ENTRY_ACL_TYPE_ACCESS 256 /* POSIX.1e only */ -#define ARCHIVE_ENTRY_ACL_TYPE_DEFAULT 512 /* POSIX.1e only */ -#define ARCHIVE_ENTRY_ACL_TYPE_ALLOW 1024 /* NFS4 only */ -#define ARCHIVE_ENTRY_ACL_TYPE_DENY 2048 /* NFS4 only */ -#define ARCHIVE_ENTRY_ACL_TYPE_AUDIT 4096 /* NFS4 only */ -#define ARCHIVE_ENTRY_ACL_TYPE_ALARM 8192 /* NFS4 only */ +#define ARCHIVE_ENTRY_ACL_TYPE_ACCESS 0x00000100 /* POSIX.1e only */ +#define ARCHIVE_ENTRY_ACL_TYPE_DEFAULT 0x00000200 /* POSIX.1e only */ +#define ARCHIVE_ENTRY_ACL_TYPE_ALLOW 0x00000400 /* NFS4 only */ +#define ARCHIVE_ENTRY_ACL_TYPE_DENY 0x00000800 /* NFS4 only */ +#define ARCHIVE_ENTRY_ACL_TYPE_AUDIT 0x00001000 /* NFS4 only */ +#define ARCHIVE_ENTRY_ACL_TYPE_ALARM 0x00002000 /* NFS4 only */ #define ARCHIVE_ENTRY_ACL_TYPE_POSIX1E (ARCHIVE_ENTRY_ACL_TYPE_ACCESS \ | ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) #define ARCHIVE_ENTRY_ACL_TYPE_NFS4 (ARCHIVE_ENTRY_ACL_TYPE_ALLOW \ @@ -492,21 +501,51 @@ __LA_DECL int archive_entry_acl_next_w(struct archive_entry *, int /* want_type * Construct a text-format ACL. The flags argument is a bitmask that * can include any of the following: * + * Flags only for archive entries with POSIX.1e ACL: * ARCHIVE_ENTRY_ACL_TYPE_ACCESS - Include POSIX.1e "access" entries. * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - Include POSIX.1e "default" entries. - * ARCHIVE_ENTRY_ACL_TYPE_NFS4 - Include NFS4 entries. - * ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID - Include extra numeric ID field in - * each ACL entry. ('star' introduced this for POSIX.1e, this flag - * also applies to NFS4.) * ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT - Include "default:" before each - * default ACL entry, as used in old Solaris ACLs. + * default ACL entry. + * ARCHIVE_ENTRY_ACL_STYLE_SOLARIS - Output only one colon after "other" and + * "mask" entries. + * + * Flags only for archive entries with NFSv4 ACL: + * ARCHIVE_ENTRY_ACL_STYLE_COMPACT - Do not output the minus character for + * unset permissions and flags in NFSv4 ACL permission and flag fields + * + * Flags for for archive entries with POSIX.1e ACL or NFSv4 ACL: + * ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID - Include extra numeric ID field in + * each ACL entry. + * ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA - Separate entries with comma + * instead of newline. */ -#define ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 1024 -#define ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 2048 +#define ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 0x00000001 +#define ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 0x00000002 +#define ARCHIVE_ENTRY_ACL_STYLE_SOLARIS 0x00000004 +#define ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA 0x00000008 +#define ARCHIVE_ENTRY_ACL_STYLE_COMPACT 0x00000010 + +__LA_DECL wchar_t *archive_entry_acl_to_text_w(struct archive_entry *, + ssize_t * /* len */, int /* flags */); +__LA_DECL char *archive_entry_acl_to_text(struct archive_entry *, + ssize_t * /* len */, int /* flags */); +__LA_DECL int archive_entry_acl_from_text_w(struct archive_entry *, + const wchar_t * /* wtext */, int /* type */); +__LA_DECL int archive_entry_acl_from_text(struct archive_entry *, + const char * /* text */, int /* type */); + +/* Deprecated constants */ +#define OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 1024 +#define OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 2048 + +/* Deprecated functions */ __LA_DECL const wchar_t *archive_entry_acl_text_w(struct archive_entry *, - int /* flags */); + int /* flags */) __LA_DEPRECATED; __LA_DECL const char *archive_entry_acl_text(struct archive_entry *, - int /* flags */); + int /* flags */) __LA_DEPRECATED; + +/* Return bitmask of ACL types in an archive entry */ +__LA_DECL int archive_entry_acl_types(struct archive_entry *); /* Return a count of entries matching 'want_type' */ __LA_DECL int archive_entry_acl_count(struct archive_entry *, int /* want_type */); diff --git a/libarchive/archive_entry_acl.3 b/libarchive/archive_entry_acl.3 index 5aff996..c5115f7 100644 --- a/libarchive/archive_entry_acl.3 +++ b/libarchive/archive_entry_acl.3 @@ -1,4 +1,5 @@ .\" Copyright (c) 2010 Joerg Sonnenberger +.\" Copyright (c) 2016 Martin Matuska .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -22,7 +23,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd February 2, 2012 +.Dd February 15, 2017 .Dt ARCHIVE_ENTRY_ACL 3 .Os .Sh NAME @@ -30,10 +31,14 @@ .Nm archive_entry_acl_add_entry_w , .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_next , .Nm archive_entry_acl_next_w , .Nm archive_entry_acl_reset , -.Nm archive_entry_acl_text_w +.Nm archive_entry_acl_to_text , +.Nm archive_entry_acl_to_text_w , +.Nm archive_entry_acl_types .Nd functions for manipulating Access Control Lists in archive entry descriptions .Sh LIBRARY Streaming Archive Library (libarchive, -larchive) @@ -62,6 +67,18 @@ Streaming Archive Library (libarchive, -larchive) .Ft int .Fn archive_entry_acl_count "struct archive_entry *a" "int type" .Ft int +.Fo archive_entry_acl_from_text +.Fa "struct archive_entry *a" +.Fa "const char *text" +.Fa "int type" +.Fc +.Ft int +.Fo archive_entry_acl_from_text_w +.Fa "struct archive_entry *a" +.Fa "const wchar_t *text" +.Fa "int type" +.Fc +.Ft int .Fo archive_entry_acl_next .Fa "struct archive_entry *a" .Fa "int type" @@ -83,31 +100,48 @@ Streaming Archive Library (libarchive, -larchive) .Fc .Ft int .Fn archive_entry_acl_reset "struct archive_entry *a" "int type" -.Ft const wchar_t * -.Fn archive_entry_acl_text_w "struct archive_entry *a" "int flags" +.Ft char * +.Fo archive_entry_acl_to_text +.Fa "struct archive_entry *a" +.Fa "ssize_t *len_p" +.Fa "int flags" +.Fc +.Ft wchar_t * +.Fo archive_entry_acl_to_text_w +.Fa "struct archive_entry *a" +.Fa "ssize_t *len_p" +.Fa "int flags" +.Fc +.Ft int +.Fn archive_entry_acl_types "struct archive_entry *a" .\" enum? .Sh DESCRIPTION -An -.Dq Access Control List -is a generalisation of the classic Unix permission system. +The +.Dq Access Control Lists (ACLs) +extend the standard Unix perssion model. The ACL interface of .Nm libarchive -is derived from the POSIX.1e draft, but restricted to simplify dealing -with practical implementations in various Operating Systems and archive formats. -.Pp -An ACL consists of a number of independent entries. +supports both POSIX.1e and NFSv4 style ACLs. Use of ACLs is restricted by +various levels of ACL support in operating systems, file systems and archive +formats. +.Ss POSIX.1e Access Control Lists +A POSIX.1e ACL consists of a number of independent entries. Each entry specifies the permission set as bitmask of basic permissions. -Valid permissions are: +Valid permissions in the +.Fa permset +are: .Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_EXECUTE" -.It Dv ARCHIVE_ENTRY_ACL_EXECUTE -.It Dv ARCHIVE_ENTRY_ACL_WRITE -.It Dv ARCHIVE_ENTRY_ACL_READ +.It Dv ARCHIVE_ENTRY_ACL_READ ( Sy r ) +.It Dv ARCHIVE_ENTRY_ACL_WRITE ( Sy w ) +.It Dv ARCHIVE_ENTRY_ACL_EXECUTE ( Sy x ) .El The permissions correspond to the normal Unix permissions. .Pp -The tag specifies the principal to which the permission applies. +The +.Fa tag +specifies the principal to which the permission applies. Valid values are: -.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_GROUP_OBJ" +.Bl -hang -offset indent -compact -width "ARCHIVE_ENTRY_ACL_GROUP_OBJ" .It Dv ARCHIVE_ENTRY_ACL_USER The user specified by the name field. .It Dv ARCHIVE_ENTRY_ACL_USER_OBJ @@ -119,8 +153,9 @@ The group who owns the file. .It Dv ARCHIVE_ENTRY_ACL_MASK The maximum permissions to be obtained via group permissions. .It Dv ARCHIVE_ENTRY_ACL_OTHER -Any principal who doesn't have a user or group entry. +Any principal who is not file owner or a member of the owning group. .El +.Pp The principals .Dv ARCHIVE_ENTRY_ACL_USER_OBJ , .Dv ARCHIVE_ENTRY_ACL_GROUP_OBJ @@ -129,19 +164,123 @@ and are equivalent to user, group and other in the classic Unix permission model and specify non-extended ACL entries. .Pp -All files have an access ACL +All files with have an access ACL .Pq Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS . This specifies the permissions required for access to the file itself. Directories have an additional ACL .Pq Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT , which controls the initial access ACL for newly created directory entries. +.Ss NFSv4 Access Control Lists +A NFSv4 ACL consists of multiple individual entries called Access Control +Entries (ACEs). +.Pp +There are four possible types of a NFSv4 ACE: +.Bl -hang -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYE_ALLOW" +.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALLOW +Allow principal to perform actions requiring given permissions. +.It Dv ARCHIVE_ENTRY_ACL_TYPE_DENY +Prevent principal from performing actions requiring given permissions. +.It Dv ARCHIVE_ENTRY_ACL_TYPE_AUDIT +Log access attempts by principal which require given permissions. +.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALARM +Trigger a system alarm on access attempts by principal which require given +permissions. +.El +.Pp +The +.Fa tag +specifies the principal to which the permission applies. +Valid values are: +.Bl -hang -offset indent -compact -width "ARCHIVE_ENTRY_ACL_GROUP_OBJ" +.It Dv ARCHIVE_ENTRY_ACL_USER +The user specified by the name field. +.It Dv ARCHIVE_ENTRY_ACL_USER_OBJ +The owner of the file. +.It Dv ARCHIVE_ENTRY_ACL_GROUP +The group specied by the name field. +.It Dv ARCHIVE_ENTRY_ACL_GROUP_OBJ +The group who owns the file. +.It Dv ARCHIVE_ENTRY_ACL_EVERYONE +Any principal who is not file owner or a member of the owning group. +.El +.Pp +Entries with the +.Dv ARCHIVE_ENTRY_ACL_USER +or +.Dv ARCHIVE_ENTRY_ACL_GROUP +tag store the user and group name in the +.Fa name +string and optionally the user or group ID in the +.Fa qualifier +integer. +.Pp +NFSv4 ACE permissions and flags are stored in the same +.Fa permset +bitfield. Some permissions share the same constant and permission character but +have different effect on directories than on files. The following ACE +permissions are supported: +.Bl -tag -offset indent -compact -width ARCHIV +.It Dv ARCHIVE_ENTRY_ACL_READ_DATA ( Sy r ) +Read data (file). +.It Dv ARCHIVE_ENTRY_ACL_LIST_DIRECTORY ( Sy r ) +List entries (directory). +.It ARCHIVE_ENTRY_ACL_WRITE_DATA ( Sy w ) +Write data (file). +.It ARCHIVE_ENTRY_ACL_ADD_FILE ( Sy w ) +Create files (directory). +.It Dv ARCHIVE_ENTRY_ACL_EXECUTE ( Sy x ) +Execute file or change into a directory. +.It Dv ARCHIVE_ENTRY_ACL_APPEND_DATA ( Sy p ) +Append data (file). +.It Dv ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY ( Sy p ) +Create subdirectories (directory). +.It Dv ARCHIVE_ENTRY_ACL_DELETE_CHILD ( Sy D ) +Remove files and subdirectories inside a directory. +.It Dv ARCHIVE_ENTRY_ACL_DELETE ( Sy d ) +Remove file or directory. +.It Dv ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES ( Sy a ) +Read file or directory attributes. +.It Dv ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES ( Sy A ) +Write file or directory attributes. +.It Dv ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS ( Sy R ) +Read named file or directory attributes. +.It Dv ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS ( Sy W ) +Write named file or directory attributes. +.It Dv ARCHIVE_ENTRY_ACL_READ_ACL ( Sy c ) +Read file or directory ACL. +.It Dv ARCHIVE_ENTRY_ACL_WRITE_ACL ( Sy C ) +Write file or directory ACL. +.It Dv ARCHIVE_ENTRY_ACL_WRITE_OWNER ( Sy o ) +Change owner of a file or directory. +.It Dv ARCHIVE_ENTRY_ACL_SYNCHRONIZE ( Sy s ) +Use synchronous I/O. +.El .Pp +The following NFSv4 ACL inheritance flags are supported: +.Bl -tag -offset indent -compact -width ARCHIV +.It Dv ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT ( Sy f ) +Inherit parent directory ACE to files. +.It Dv ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT ( Sy d ) +Inherit parent directory ACE to subdirectories. +.It Dv ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY ( Sy i ) +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. +.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 ) +Mark that ACE was inherited. +.El +.Ss Functions .Fn archive_entry_acl_add_entry and .Fn archive_entry_acl_add_entry_w add a single ACL entry. For the access ACL and non-extended principals, the classic Unix permissions -are updated. +are updated. An archive enry cannot contain both POSIX.1e and NFSv4 ACL +entries. .Pp .Fn archive_entry_acl_clear removes all ACL entries and resets the enumeration pointer. @@ -150,14 +289,58 @@ removes all ACL entries and resets the enumeration pointer. counts the ACL entries that have the given type mask. .Fa type can be the bitwise-or of -.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS -and -.Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT . -If +.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYPE_DEFAULT" +.It Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS +.It Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT +.El +for POSIX.1e ACLs and +.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYPE_ALLOW" +.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALLOW +.It Dv ARCHIVE_ENTRY_ACL_TYPE_DENY +.It Dv ARCHIVE_ENTRY_ACL_TYPE_AUDIT +.It Dv ARCHIVE_ENTRY_ACL_TYPE_ALARM +.El +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. .Pp +.Fn archive_entry_acl_from_text +and +.Fn archive_entry_acl_from_text_w +add new +.Pq or merge with existing +ACL entries from +.Pq wide +text. The argument +.Fa type +may take one of the following values: +.Bl -tag -offset indent -compact -width "ARCHIVE_ENTRY_ACL_TYPE_DEFAULT" +.It Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS +.It Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT +.It Dv ARCHIVE_ENTRY_ACL_TYPE_NFS4 +.El +Supports all formats that can be created with +.Fn archive_entry_acl_to_text +or respective +.Fn archive_entry_acl_to_text_w . +Existing ACL entries are preserved. To get a clean new ACL from text +.Fn archive_entry_acl_clear +must be called first. Entries prefixed with +.Dq default: +are treated as +.Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT +unless +.Fa type +is +.Dv ARCHIVE_ENTRY_ACL_TYPE_NFS4 . +Invalid entries, non-parseable ACL entries and entries beginning with +the +.Sq # +character +.Pq comments +are skipped. +.Pp .Fn archive_entry_acl_next and .Fn archive_entry_acl_next_w @@ -179,29 +362,81 @@ or set using Otherwise, the function returns the same value as .Fn archive_entry_acl_count . .Pp -.Fn archive_entry_acl_text_w -converts the ACL entries for the given type mask into a wide string. -In addition to the normal type flags, -.Dv ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID +.Fn archive_entry_acl_to_text and -.Dv ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT -can be specified to further customize the result. -The returned long string is valid until the next call to -.Fn archive_entry_acl_clear , -.Fn archive_entry_acl_add_entry , -.Fn archive_entry_acl_add_entry_w +.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 +.Fa len_p +is not NULL, then the function shall return the length of the string +.Pq not including the NULL terminator +in the location pointed to by +.Fa len_p . +The +.Fa flag +argument is a bitwise-or. +.Pp +The following flags are effective only on POSIX.1e ACL: +.Bl -tag -offset indent -compact -width ARCHIV +.It Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS +Output access ACLs. +.It Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT +Output POSIX.1e default ACLs. +.It Dv ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT +Prefix each default ACL entry with the word +.Dq default: . +.It Dv ARCHIVE_ENTRY_ACL_STYLE_SOLARIS +The mask and other ACLs don not contain a double colon. +.El +.Pp +The following flags are effecive only on NFSv4 ACL: +.Bl -tag -offset indent -compact -width ARCHIV +.It Dv ARCHIVE_ENTRY_ACL_STYLE_COMPACT +Do not output minus characters for unset permissions and flags in NFSv4 ACL +permission and flag fields. +.El +.Pp +The following flags are effective on both POSIX.1e and NFSv4 ACL: +.Bl -tag -offset indent -compact -width ARCHIV +.It Dv ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID +Add an additional colon-separated field containing the user or group id. +.It Dv ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA +Separate ACL entries with comma instead of newline. +.El +.Pp +If the archive entry contains NFSv4 ACLs, all types of NFSv4 ACLs are returned. +It the entry contains POSIX.1e ACLs and none of the flags +.Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS or -.Fn archive_entry_acl_text_w . +.Dv ARCHIVE_ENTRY_ACL_TYPE_DEFAULT +are specified, both access and default entries are returned and default entries +are prefixed with +.Dq default: . +.Pp +.Fn archive_entry_acl_types +get ACL entry types contained in an archive entry's ACL. As POSIX.1e and NFSv4 +ACL entries cannot be mixed, this function is a very efficient way to detect if +an ACL already contains POSIX.1e or NFSv4 ACL entries. .Sh RETURN VALUES .Fn archive_entry_acl_count and .Fn archive_entry_acl_reset returns the number of ACL entries that match the given type mask. -If the type mask includes +For POSIX.1e ACLS if the type mask includes .Dv ARCHIVE_ENTRY_ACL_TYPE_ACCESS and at least one extended ACL entry exists, the three classic Unix permissions are counted. .Pp +.Fn archive_entry_acl_from_text +and +.Fn archive_entry_acl_from_text_w +return +.Dv ARCHIVE_OK +if all entries were successfully parsed and +.Dv ARCHIVE_WARN +if one or more entries were invalid or non-parseable. +.Pp .Fn archive_entry_acl_next and .Fn archive_entry_acl_next_w @@ -216,20 +451,16 @@ if .Fn archive_entry_acl_reset has not been called first. .Pp -.Fn archive_entry_text_w -returns a wide string representation of the ACL entrise matching the -given type mask. -The returned long string is valid until the next call to -.Fn archive_entry_acl_clear , -.Fn archive_entry_acl_add_entry , -.Fn archive_entry_acl_add_entry_w -or -.Fn archive_entry_acl_text_w . +.Fn archive_entry_acl_to_text +returns a string representing the ACL entries matching the given type and +flags on success or NULL on error. +.Pp +.Fn archive_entry_acl_to_text_w +returns a wide string representing the ACL entries matching the given type +and flags on success or NULL on error. +.Pp +.Fn archive_entry_acl_types +returns a bitmask of ACL entry types or 0 if archive entry has no ACL entries. .Sh SEE ALSO -.Xr archive_entry 3 -.Xr libarchive 3 , -.Sh BUGS -.Dv ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID -and -.Dv ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT -are not documented. +.Xr archive_entry 3 , +.Xr libarchive 3 diff --git a/libarchive/archive_entry_locale.h b/libarchive/archive_entry_locale.h index 02e024a..44550c5 100644 --- a/libarchive/archive_entry_locale.h +++ b/libarchive/archive_entry_locale.h @@ -63,9 +63,13 @@ int _archive_entry_uname_l(struct archive_entry *, const char **, size_t *, struct archive_string_conv *); #define archive_entry_acl_text_l _archive_entry_acl_text_l int _archive_entry_acl_text_l(struct archive_entry *, int, - const char **, size_t *, struct archive_string_conv *); - - +const char **, size_t *, struct archive_string_conv *) __LA_DEPRECATED; +#define archive_entry_acl_to_text_l _archive_entry_acl_to_text_l +char *_archive_entry_acl_to_text_l(struct archive_entry *, ssize_t *, int, + struct archive_string_conv *); +#define archive_entry_acl_from_text_l _archive_entry_acl_from_text_l +int _archive_entry_acl_from_text_l(struct archive_entry *, const char* text, + int type, struct archive_string_conv *); #define archive_entry_copy_gname_l _archive_entry_copy_gname_l int _archive_entry_copy_gname_l(struct archive_entry *, const char *, size_t, struct archive_string_conv *); diff --git a/libarchive/archive_entry_strmode.c b/libarchive/archive_entry_strmode.c index 16cb3f7..af2517a 100644 --- a/libarchive/archive_entry_strmode.c +++ b/libarchive/archive_entry_strmode.c @@ -80,7 +80,7 @@ archive_entry_strmode(struct archive_entry *entry) if (mode & 0001) bp[9] = 't'; else bp[9] = 'T'; } - if (archive_entry_acl_count(entry, ARCHIVE_ENTRY_ACL_TYPE_ACCESS)) + if (archive_entry_acl_types(entry) != 0) bp[10] = '+'; return (bp); diff --git a/libarchive/archive_hmac.c b/libarchive/archive_hmac.c index 7857c0f..1e0ae28 100644 --- a/libarchive/archive_hmac.c +++ b/libarchive/archive_hmac.c @@ -176,8 +176,10 @@ __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) static int __hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) { - HMAC_CTX_init(ctx); - HMAC_Init(ctx, key, key_len, EVP_sha1()); + *ctx = HMAC_CTX_new(); + if (*ctx == NULL) + return -1; + HMAC_Init_ex(*ctx, key, key_len, EVP_sha1(), NULL); return 0; } @@ -185,22 +187,22 @@ static void __hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, size_t data_len) { - HMAC_Update(ctx, data, data_len); + HMAC_Update(*ctx, data, data_len); } static void __hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) { unsigned int len = (unsigned int)*out_len; - HMAC_Final(ctx, out, &len); + HMAC_Final(*ctx, out, &len); *out_len = len; } static void __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) { - HMAC_CTX_cleanup(ctx); - memset(ctx, 0, sizeof(*ctx)); + HMAC_CTX_free(*ctx); + *ctx = NULL; } #else diff --git a/libarchive/archive_hmac_private.h b/libarchive/archive_hmac_private.h index 64de743..eb45c4e 100644 --- a/libarchive/archive_hmac_private.h +++ b/libarchive/archive_hmac_private.h @@ -70,9 +70,9 @@ typedef struct { typedef struct hmac_sha1_ctx archive_hmac_sha1_ctx; #elif defined(HAVE_LIBCRYPTO) -#include +#include "archive_openssl_hmac_private.h" -typedef HMAC_CTX archive_hmac_sha1_ctx; +typedef HMAC_CTX* archive_hmac_sha1_ctx; #else diff --git a/libarchive/archive_match.c b/libarchive/archive_match.c index 4c41bad..be72066 100644 --- a/libarchive/archive_match.c +++ b/libarchive/archive_match.c @@ -471,7 +471,7 @@ archive_match_path_excluded(struct archive *_a, } /* - * Utilty functions to get statistic information for inclusion patterns. + * Utility functions to get statistic information for inclusion patterns. */ int archive_match_path_unmatched_inclusions(struct archive *_a) @@ -655,7 +655,7 @@ add_pattern_from_file(struct archive_match *a, struct match_list *mlist, } } - /* If something error happend, report it immediately. */ + /* If an error occurred, report it immediately. */ if (r < ARCHIVE_OK) { archive_copy_error(&(a->archive), ar); archive_read_free(ar); @@ -1270,7 +1270,7 @@ set_timefilter_pathname_wcs(struct archive_match *a, int timetype, #endif /* _WIN32 && !__CYGWIN__ */ /* - * Call back funtions for archive_rb. + * Call back functions for archive_rb. */ static int cmp_node_mbs(const struct archive_rb_node *n1, @@ -1405,7 +1405,7 @@ add_entry(struct archive_match *a, int flag, &(a->exclusion_tree), pathname); /* - * We always overwrite comparison condision. + * We always overwrite comparison condition. * If you do not want to overwrite it, you should not * call archive_match_exclude_entry(). We cannot know * what behavior you really expect since overwriting @@ -1481,7 +1481,7 @@ time_excluded(struct archive_match *a, struct archive_entry *entry) if (nsec == a->older_ctime_nsec && (a->older_ctime_filter & ARCHIVE_MATCH_EQUAL) == 0) - return (1); /* Eeual, skip it. */ + return (1); /* Equal, skip it. */ } } if (a->newer_mtime_filter) { @@ -1513,7 +1513,7 @@ time_excluded(struct archive_match *a, struct archive_entry *entry) } } - /* If there is no excluson list, include the file. */ + /* If there is no exclusion list, include the file. */ if (a->exclusion_entry_list.count == 0) return (0); @@ -1700,7 +1700,7 @@ add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id) break; } - /* Add oowner id. */ + /* Add owner id. */ if (i == ids->count) ids->ids[ids->count++] = id; else if (ids->ids[i] != id) { diff --git a/libarchive/archive_openssl_evp_private.h b/libarchive/archive_openssl_evp_private.h new file mode 100644 index 0000000..43a3ccc --- /dev/null +++ b/libarchive/archive_openssl_evp_private.h @@ -0,0 +1,48 @@ +/*- + * 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. + */ +#ifndef ARCHIVE_OPENSSL_EVP_PRIVATE_H_INCLUDED +#define ARCHIVE_OPENSSL_EVP_PRIVATE_H_INCLUDED + +#include +#include + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#include /* malloc, free */ +#include /* memset */ +static inline EVP_MD_CTX *EVP_MD_CTX_new(void) +{ + EVP_MD_CTX *ctx = (EVP_MD_CTX *)calloc(1, sizeof(EVP_MD_CTX)); + return ctx; +} + +static inline void EVP_MD_CTX_free(EVP_MD_CTX *ctx) +{ + EVP_MD_CTX_cleanup(ctx); + memset(ctx, 0, sizeof(*ctx)); + free(ctx); +} +#endif + +#endif diff --git a/libarchive/archive_openssl_hmac_private.h b/libarchive/archive_openssl_hmac_private.h new file mode 100644 index 0000000..2deeb5f --- /dev/null +++ b/libarchive/archive_openssl_hmac_private.h @@ -0,0 +1,48 @@ +/*- + * 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. + */ +#ifndef ARCHIVE_OPENSSL_HMAC_PRIVATE_H_INCLUDED +#define ARCHIVE_OPENSSL_HMAC_PRIVATE_H_INCLUDED + +#include +#include + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#include /* malloc, free */ +#include /* memset */ +static inline HMAC_CTX *HMAC_CTX_new(void) +{ + HMAC_CTX *ctx = (HMAC_CTX *)calloc(1, sizeof(HMAC_CTX)); + return ctx; +} + +static inline void HMAC_CTX_free(HMAC_CTX *ctx) +{ + HMAC_CTX_cleanup(ctx); + memset(ctx, 0, sizeof(*ctx)); + free(ctx); +} +#endif + +#endif diff --git a/libarchive/archive_options.c b/libarchive/archive_options.c index dbf3e80..6496025 100644 --- a/libarchive/archive_options.c +++ b/libarchive/archive_options.c @@ -26,6 +26,10 @@ #include "archive_platform.h" __FBSDID("$FreeBSD$"); +#ifdef HAVE_ERRNO_H +#include +#endif + #include "archive_options_private.h" static const char * @@ -105,8 +109,11 @@ _archive_set_options(struct archive *a, const char *options, if (options == NULL || options[0] == '\0') return ARCHIVE_OK; - data = (char *)malloc(strlen(options) + 1); - strcpy(data, options); + if ((data = strdup(options)) == NULL) { + archive_set_error(a, + ENOMEM, "Out of memory adding file to list"); + return (ARCHIVE_FATAL); + } s = (const char *)data; do { diff --git a/libarchive/archive_platform.h b/libarchive/archive_platform.h index b06c3cd..c9a9602 100644 --- a/libarchive/archive_platform.h +++ b/libarchive/archive_platform.h @@ -147,8 +147,25 @@ * acl_set_file(), and ACL_USER, we assume it has the rest of the * POSIX.1e draft functions used in archive_read_extract.c. */ -#if HAVE_SYS_ACL_H && HAVE_ACL_CREATE_ENTRY && HAVE_ACL_INIT && HAVE_ACL_SET_FILE && HAVE_ACL_USER +#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 , 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 /* @@ -159,6 +176,15 @@ #define CAN_RESTORE_METADATA_FD #endif +/* + * glibc 2.24 deprecates readdir_r + */ +#if defined(HAVE_READDIR_R) && (!defined(__GLIBC__) || !defined(__GLIBC_MINOR__) || __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 24)) +#define USE_READDIR_R 1 +#else +#undef USE_READDIR_R +#endif + /* Set up defaults for internal error codes. */ #ifndef ARCHIVE_ERRNO_FILE_FORMAT #if HAVE_EFTYPE diff --git a/libarchive/archive_ppmd7_private.h b/libarchive/archive_ppmd7_private.h index 3a6b9eb..06c99e8 100644 --- a/libarchive/archive_ppmd7_private.h +++ b/libarchive/archive_ppmd7_private.h @@ -19,7 +19,7 @@ If you need the compatibility with original PPMd var.H, you can use external Ran #define PPMD7_MAX_ORDER 64 #define PPMD7_MIN_MEM_SIZE (1 << 11) -#define PPMD7_MAX_MEM_SIZE (0xFFFFFFFF - 12 * 3) +#define PPMD7_MAX_MEM_SIZE (0xFFFFFFFFu - 12 * 3) struct CPpmd7_Context_; diff --git a/libarchive/archive_random.c b/libarchive/archive_random.c index a20b9b1..357f973 100644 --- a/libarchive/archive_random.c +++ b/libarchive/archive_random.c @@ -80,7 +80,7 @@ archive_random(void *buf, size_t nbytes) success = CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); - if (!success && GetLastError() == NTE_BAD_KEYSET) { + if (!success && GetLastError() == (DWORD)NTE_BAD_KEYSET) { success = CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET); } diff --git a/libarchive/archive_rb.c b/libarchive/archive_rb.c index 5b5da20..cf58ac3 100644 --- a/libarchive/archive_rb.c +++ b/libarchive/archive_rb.c @@ -312,7 +312,7 @@ __archive_rb_tree_insert_rebalance(struct archive_rb_tree *rbt, father = RB_FATHER(self); if (RB_BLACK_P(father)) { /* - * If our greatgrandpa is black, we're done. + * If our great-grandpa is black, we're done. */ return; } diff --git a/libarchive/archive_read.c b/libarchive/archive_read.c index 0bbacc8..d1feceb 100644 --- a/libarchive/archive_read.c +++ b/libarchive/archive_read.c @@ -57,6 +57,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read.c 201157 2009-12-29 05:30:2 static int choose_filters(struct archive_read *); static int choose_format(struct archive_read *); +static int close_filters(struct archive_read *); static struct archive_vtable *archive_read_vtable(void); static int64_t _archive_filter_bytes(struct archive *, int); static int _archive_filter_code(struct archive *, int); @@ -528,7 +529,7 @@ archive_read_open1(struct archive *_a) { slot = choose_format(a); if (slot < 0) { - __archive_read_close_filters(a); + close_filters(a); a->archive.state = ARCHIVE_STATE_FATAL; return (ARCHIVE_FATAL); } @@ -582,7 +583,6 @@ choose_filters(struct archive_read *a) /* Verify the filter by asking it for some data. */ __archive_read_filter_ahead(a->filter, 1, &avail); if (avail < 0) { - __archive_read_close_filters(a); __archive_read_free_filters(a); return (ARCHIVE_FATAL); } @@ -601,7 +601,6 @@ choose_filters(struct archive_read *a) a->filter = filter; r = (best_bidder->init)(a->filter); if (r != ARCHIVE_OK) { - __archive_read_close_filters(a); __archive_read_free_filters(a); return (ARCHIVE_FATAL); } @@ -765,7 +764,7 @@ archive_read_header_position(struct archive *_a) * we cannot say whether there are encrypted entries, then * ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned. * In general, this function will return values below zero when the - * reader is uncertain or totally uncapable of encryption support. + * reader is uncertain or totally incapable of encryption support. * When this function returns 0 you can be sure that the reader * supports encryption detection but no encrypted entries have * been found yet. @@ -986,8 +985,8 @@ _archive_read_data_block(struct archive *_a, return (a->format->read_data)(a, buff, size, offset); } -int -__archive_read_close_filters(struct archive_read *a) +static int +close_filters(struct archive_read *a) { struct archive_read_filter *f = a->filter; int r = ARCHIVE_OK; @@ -1010,6 +1009,9 @@ __archive_read_close_filters(struct archive_read *a) void __archive_read_free_filters(struct archive_read *a) { + /* Make sure filters are closed and their buffers are freed */ + close_filters(a); + while (a->filter != NULL) { struct archive_read_filter *t = a->filter->upstream; free(a->filter); @@ -1052,7 +1054,7 @@ _archive_read_close(struct archive *_a) /* TODO: Clean up the formatters. */ /* Release the filter objects. */ - r1 = __archive_read_close_filters(a); + r1 = close_filters(a); if (r1 < r) r = r1; diff --git a/libarchive/archive_read_add_passphrase.c b/libarchive/archive_read_add_passphrase.c index f67f1eb..cf821b5 100644 --- a/libarchive/archive_read_add_passphrase.c +++ b/libarchive/archive_read_add_passphrase.c @@ -125,7 +125,7 @@ void __archive_read_reset_passphrase(struct archive_read *a) { - a->passphrases.candiate = -1; + a->passphrases.candidate = -1; } /* @@ -137,31 +137,31 @@ __archive_read_next_passphrase(struct archive_read *a) struct archive_read_passphrase *p; const char *passphrase; - if (a->passphrases.candiate < 0) { + if (a->passphrases.candidate < 0) { /* Count out how many passphrases we have. */ int cnt = 0; for (p = a->passphrases.first; p != NULL; p = p->next) cnt++; - a->passphrases.candiate = cnt; + a->passphrases.candidate = cnt; p = a->passphrases.first; - } else if (a->passphrases.candiate > 1) { + } else if (a->passphrases.candidate > 1) { /* Rotate a passphrase list. */ - a->passphrases.candiate--; + a->passphrases.candidate--; p = remove_passphrases_from_head(a); add_passphrase_to_tail(a, p); - /* Pick a new passphrase candiate up. */ + /* Pick a new passphrase candidate up. */ p = a->passphrases.first; - } else if (a->passphrases.candiate == 1) { - /* This case is that all cadiates failed to decryption. */ - a->passphrases.candiate = 0; + } else if (a->passphrases.candidate == 1) { + /* This case is that all candidates failed to decrypt. */ + a->passphrases.candidate = 0; if (a->passphrases.first->next != NULL) { /* Rotate a passphrase list. */ p = remove_passphrases_from_head(a); add_passphrase_to_tail(a, p); } p = NULL; - } else /* There is no passphrase candaite. */ + } else /* There is no passphrase candidate. */ p = NULL; if (p != NULL) @@ -177,7 +177,7 @@ __archive_read_next_passphrase(struct archive_read *a) if (p == NULL) return (NULL); insert_passphrase_to_head(a, p); - a->passphrases.candiate = 1; + a->passphrases.candidate = 1; } } else passphrase = NULL; diff --git a/libarchive/archive_read_append_filter.c b/libarchive/archive_read_append_filter.c index 3a0d4d6..5e4d163 100644 --- a/libarchive/archive_read_append_filter.c +++ b/libarchive/archive_read_append_filter.c @@ -133,7 +133,6 @@ archive_read_append_filter(struct archive *_a, int code) a->filter = filter; r2 = (bidder->init)(a->filter); if (r2 != ARCHIVE_OK) { - __archive_read_close_filters(a); __archive_read_free_filters(a); return (ARCHIVE_FATAL); } @@ -191,7 +190,6 @@ archive_read_append_filter_program_signature(struct archive *_a, a->filter = filter; r = (bidder->init)(a->filter); if (r != ARCHIVE_OK) { - __archive_read_close_filters(a); __archive_read_free_filters(a); return (ARCHIVE_FATAL); } diff --git a/libarchive/archive_read_disk.3 b/libarchive/archive_read_disk.3 index 525dc59..2a5c130 100644 --- a/libarchive/archive_read_disk.3 +++ b/libarchive/archive_read_disk.3 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 2, 2012 +.Dd December 30, 2016 .Dt ARCHIVE_READ_DISK 3 .Os .Sh NAME @@ -54,9 +54,9 @@ Streaming Archive Library (libarchive, -larchive) .Fn archive_read_disk_set_symlink_physical "struct archive *" .Ft int .Fn archive_read_disk_set_symlink_hybrid "struct archive *" -.Ft int +.Ft const char * .Fn archive_read_disk_gname "struct archive *" "gid_t" -.Ft int +.Ft const char * .Fn archive_read_disk_uname "struct archive *" "uid_t" .Ft int .Fo archive_read_disk_set_gname_lookup diff --git a/libarchive/archive_read_disk_entry_from_file.c b/libarchive/archive_read_disk_entry_from_file.c index 74fe353..591a212 100644 --- a/libarchive/archive_read_disk_entry_from_file.c +++ b/libarchive/archive_read_disk_entry_from_file.c @@ -1,6 +1,7 @@ /*- * Copyright (c) 2003-2009 Tim Kientzle * Copyright (c) 2010-2012 Michihiro NAKAJIMA + * Copyright (c) 2016 Martin Matuska * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,6 +38,11 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010 #ifdef HAVE_SYS_ACL_H #include #endif +#ifdef HAVE_DARWIN_ACL +#include +#include +#include +#endif #ifdef HAVE_SYS_EXTATTR_H #include #endif @@ -117,6 +123,15 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 2010 #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 *, @@ -125,6 +140,10 @@ static int setup_xattrs(struct archive_read_disk *, struct archive_entry *, int *fd); static int setup_sparse(struct archive_read_disk *, struct archive_entry *, int *fd); +#if defined(HAVE_LINUX_FIEMAP_H) +static int setup_sparse_fiemap(struct archive_read_disk *, + struct archive_entry *, int *fd); +#endif int archive_read_disk_entry_from_file(struct archive *_a, @@ -302,20 +321,17 @@ setup_mac_metadata(struct archive_read_disk *a, name = archive_entry_sourcepath(entry); 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); } - if (a->tree != NULL) { - if (a->tree_enter_working_dir(a->tree) != 0) { - archive_set_error(&a->archive, errno, - "Couldn't change dir"); - return (ARCHIVE_FAILED); - } - } - /* Short-circuit if there's nothing to do. */ have_attrs = copyfile(name, NULL, 0, copyfile_flags | COPYFILE_CHECK); if (have_attrs == -1) { @@ -400,34 +416,87 @@ 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 -#ifdef HAVE_POSIX_ACL +#if HAVE_POSIX_ACL || HAVE_NFS4_ACL static int translate_acl(struct archive_read_disk *a, - struct archive_entry *entry, acl_t acl, int archive_entry_acl_type); + 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; - acl_t acl; -#if HAVE_ACL_IS_TRIVIAL_NP - int r; +#if HAVE_SUN_ACL + acl_t *acl; +#else + acl_t acl; #endif + int r; - accpath = archive_entry_sourcepath(entry); - if (accpath == NULL) - accpath = archive_entry_pathname(entry); + 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); -#ifdef ACL_TYPE_NFS4 - /* Try NFS4 ACL first. */ + 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, ACL_TYPE_NFS4); + acl = acl_get_link_np(accpath, ARCHIVE_PLATFORM_ACL_TYPE_NFS4); #else else if ((!a->follow_symlinks) && (archive_entry_filetype(entry) == AE_IFLNK)) @@ -436,21 +505,62 @@ setup_acls(struct archive_read_disk *a, acl = NULL; #endif else - acl = acl_get_file(accpath, ACL_TYPE_NFS4); -#if HAVE_ACL_IS_TRIVIAL_NP +#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. */ - acl_is_trivial_np(acl, &r); - if (r) { - acl_free(acl); - acl = NULL; - } + 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) { - translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4); + r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4); acl_free(acl); - return (ARCHIVE_OK); - } + 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 */ /* Retrieve access ACL from file. */ if (*fd >= 0) @@ -467,88 +577,609 @@ setup_acls(struct archive_read_disk *a, #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) { - translate_acl(a, entry, acl, - ARCHIVE_ENTRY_ACL_TYPE_ACCESS); + 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) { - translate_acl(a, entry, acl, + 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 into libarchive internal structure. + * Translate system ACL permissions into libarchive internal structure */ - -static struct { - int archive_perm; - int platform_perm; +static const struct { + const int archive_perm; + const int platform_perm; } acl_perm_map[] = { - {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, - {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE}, - {ARCHIVE_ENTRY_ACL_READ, ACL_READ}, -#ifdef ACL_TYPE_NFS4 - {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA}, - {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY}, - {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA}, - {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} +#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 */ }; -#ifdef ACL_TYPE_NFS4 -static struct { - int archive_inherit; - int platform_inherit; +#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[] = { - {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT}, +#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_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 +#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; -#ifdef ACL_TYPE_NFS4 +#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; - int brand, r; #endif acl_entry_t acl_entry; acl_permset_t acl_permset; int i, entry_acl_type; - int s, ae_id, ae_tag, ae_perm; + int r, s, ae_id, ae_tag, ae_perm; +#if !HAVE_DARWIN_ACL + void *q; +#endif const char *ae_name; - -#ifdef ACL_TYPE_NFS4 +#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. - acl_get_brand_np(acl, &brand); + 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) { @@ -556,40 +1187,67 @@ translate_acl(struct archive_read_disk *a, case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: break; default: - // XXX set warning message? - return ARCHIVE_FAILED; + 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) { - // XXX set warning message? - return ARCHIVE_FAILED; + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Invalid ACL entry type for NFSv4 ACL"); + return (ARCHIVE_WARN); } break; default: - // XXX set warning message? - return ARCHIVE_FAILED; - break; + 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); - while (s == 1) { + 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; - acl_get_tag_type(acl_entry, &acl_tag); + 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: - ae_id = (int)*(uid_t *)acl_get_qualifier(acl_entry); - ae_name = archive_read_disk_uname(&a->archive, ae_id); + 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: - ae_id = (int)*(gid_t *)acl_get_qualifier(acl_entry); - ae_name = archive_read_disk_gname(&a->archive, ae_id); + 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: @@ -604,24 +1262,52 @@ translate_acl(struct archive_read_disk *a, case ACL_OTHER: ae_tag = ARCHIVE_ENTRY_ACL_OTHER; break; -#ifdef ACL_TYPE_NFS4 +#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; } - // XXX acl type maps to allow/deny/audit/YYYY bits - // XXX acl_get_entry_type_np on FreeBSD returns EINVAL for - // non-NFSv4 ACLs +#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; -#ifdef ACL_TYPE_NFS4 - r = acl_get_entry_type_np(acl_entry, &acl_type); - if (r == 0) { +#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; @@ -635,29 +1321,54 @@ translate_acl(struct archive_read_disk *a, 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(acl_entry, &acl_flagset); - for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) { - if (acl_get_flag_np(acl_flagset, - acl_inherit_map[i].platform_inherit)) - ae_perm |= acl_inherit_map[i].archive_inherit; +#endif /* HAVE_ACL_TYPE_NFS4 */ - } -#endif + /* + * 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 */ - acl_get_permset(acl_entry, &acl_permset); + 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. */ - if (ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_perm)) + 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; } @@ -666,10 +1377,18 @@ translate_acl(struct archive_read_disk *a, 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); } -#else +#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) @@ -679,7 +1398,7 @@ setup_acls(struct archive_read_disk *a, (void)fd; /* UNUSED */ return (ARCHIVE_OK); } -#endif +#endif /* !HAVE_POSIX_ACL && !HAVE_NFS4_ACL */ #if (HAVE_FGETXATTR && HAVE_FLISTXATTR && HAVE_LISTXATTR && \ HAVE_LLISTXATTR && HAVE_GETXATTR && HAVE_LGETXATTR) || \ @@ -699,15 +1418,10 @@ setup_acls(struct archive_read_disk *a, static int setup_xattr(struct archive_read_disk *a, - struct archive_entry *entry, const char *name, int fd) + struct archive_entry *entry, const char *name, int fd, const char *accpath) { ssize_t size; void *value = NULL; - const char *accpath; - - accpath = archive_entry_sourcepath(entry); - if (accpath == NULL) - accpath = archive_entry_pathname(entry); #if HAVE_FGETXATTR if (fd >= 0) @@ -772,21 +1486,23 @@ setup_xattrs(struct archive_read_disk *a, const char *path; ssize_t list_size; - path = archive_entry_sourcepath(entry); - if (path == NULL) - path = archive_entry_pathname(entry); + path = NULL; - if (*fd < 0 && a->tree != NULL) { - if (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) { - if (a->tree_enter_working_dir(a->tree) != 0) { - archive_set_error(&a->archive, errno, - "Couldn't access %s", path); - return (ARCHIVE_FAILED); - } + 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"); + 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); } } @@ -849,7 +1565,7 @@ setup_xattrs(struct archive_read_disk *a, if (strncmp(p, "system.", 7) == 0 || strncmp(p, "xfsroot.", 8) == 0) continue; - setup_xattr(a, entry, p, *fd); + setup_xattr(a, entry, p, *fd, path); } free(list); @@ -870,19 +1586,16 @@ setup_xattrs(struct archive_read_disk *a, */ static int setup_xattr(struct archive_read_disk *a, struct archive_entry *entry, - int namespace, const char *name, const char *fullname, int fd); + int namespace, const char *name, const char *fullname, int fd, + const char *path); static int setup_xattr(struct archive_read_disk *a, struct archive_entry *entry, - int namespace, const char *name, const char *fullname, int fd) + int namespace, const char *name, const char *fullname, int fd, + const char *accpath) { ssize_t size; void *value = NULL; - const char *accpath; - - accpath = archive_entry_sourcepath(entry); - if (accpath == NULL) - accpath = archive_entry_pathname(entry); if (fd >= 0) size = extattr_get_fd(fd, namespace, name, NULL, 0); @@ -932,21 +1645,23 @@ setup_xattrs(struct archive_read_disk *a, const char *path; int namespace = EXTATTR_NAMESPACE_USER; - path = archive_entry_sourcepath(entry); - if (path == NULL) - path = archive_entry_pathname(entry); + path = NULL; - if (*fd < 0 && a->tree != NULL) { - if (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) { - if (a->tree_enter_working_dir(a->tree) != 0) { - archive_set_error(&a->archive, errno, - "Couldn't access %s", path); - return (ARCHIVE_FAILED); - } + 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"); + 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); } } @@ -996,7 +1711,7 @@ setup_xattrs(struct archive_read_disk *a, name = buff + strlen(buff); memcpy(name, p + 1, len); name[len] = '\0'; - setup_xattr(a, entry, namespace, name, buff, *fd); + setup_xattr(a, entry, namespace, name, buff, *fd, path); p += 1 + len; } @@ -1024,7 +1739,7 @@ setup_xattrs(struct archive_read_disk *a, #if defined(HAVE_LINUX_FIEMAP_H) /* - * Linux sparse interface. + * Linux FIEMAP sparse interface. * * The FIEMAP ioctl returns an "extent" for each physical allocation * on disk. We need to process those to generate a more compact list @@ -1039,7 +1754,7 @@ setup_xattrs(struct archive_read_disk *a, */ static int -setup_sparse(struct archive_read_disk *a, +setup_sparse_fiemap(struct archive_read_disk *a, struct archive_entry *entry, int *fd) { char buff[4096]; @@ -1090,8 +1805,8 @@ setup_sparse(struct archive_read_disk *a, if (r < 0) { /* When something error happens, it is better we * should return ARCHIVE_OK because an earlier - * version(<2.6.28) cannot perfom FS_IOC_FIEMAP. */ - goto exit_setup_sparse; + * version(<2.6.28) cannot perform FS_IOC_FIEMAP. */ + goto exit_setup_sparse_fiemap; } if (fm->fm_mapped_extents == 0) { if (iters == 0) { @@ -1126,14 +1841,24 @@ setup_sparse(struct archive_read_disk *a, } else break; } -exit_setup_sparse: +exit_setup_sparse_fiemap: return (exit_sts); } -#elif defined(SEEK_HOLE) && defined(SEEK_DATA) && defined(_PC_MIN_HOLE_SIZE) +#if !defined(SEEK_HOLE) || !defined(SEEK_DATA) +static int +setup_sparse(struct archive_read_disk *a, + struct archive_entry *entry, int *fd) +{ + return setup_sparse_fiemap(a, entry, fd); +} +#endif +#endif /* defined(HAVE_LINUX_FIEMAP_H) */ + +#if defined(SEEK_HOLE) && defined(SEEK_DATA) /* - * FreeBSD and Solaris sparse interface. + * SEEK_HOLE sparse interface (FreeBSD, Linux, Solaris) */ static int @@ -1141,8 +1866,8 @@ setup_sparse(struct archive_read_disk *a, struct archive_entry *entry, int *fd) { int64_t size; - off_t initial_off; /* FreeBSD/Solaris only, so off_t okay here */ - off_t off_s, off_e; /* FreeBSD/Solaris only, so off_t okay here */ + off_t initial_off; + off_t off_s, off_e; int exit_sts = ARCHIVE_OK; int check_fully_sparse = 0; @@ -1168,8 +1893,10 @@ setup_sparse(struct archive_read_disk *a, } if (*fd >= 0) { +#ifdef _PC_MIN_HOLE_SIZE if (fpathconf(*fd, _PC_MIN_HOLE_SIZE) <= 0) return (ARCHIVE_OK); +#endif initial_off = lseek(*fd, 0, SEEK_CUR); if (initial_off != 0) lseek(*fd, 0, SEEK_SET); @@ -1180,8 +1907,10 @@ setup_sparse(struct archive_read_disk *a, if (path == NULL) path = archive_entry_pathname(entry); +#ifdef _PC_MIN_HOLE_SIZE if (pathconf(path, _PC_MIN_HOLE_SIZE) <= 0) return (ARCHIVE_OK); +#endif *fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC); if (*fd < 0) { archive_set_error(&a->archive, errno, @@ -1192,6 +1921,19 @@ setup_sparse(struct archive_read_disk *a, initial_off = 0; } +#ifndef _PC_MIN_HOLE_SIZE + /* Check if the underlying filesystem supports seek hole */ + off_s = lseek(*fd, 0, SEEK_HOLE); + if (off_s < 0) +#if defined(HAVE_LINUX_FIEMAP_H) + return setup_sparse_fiemap(a, entry, fd); +#else + goto exit_setup_sparse; +#endif + else if (off_s > 0) + lseek(*fd, 0, SEEK_SET); +#endif + off_s = 0; size = archive_entry_size(entry); while (off_s < size) { @@ -1223,7 +1965,7 @@ setup_sparse(struct archive_read_disk *a, goto exit_setup_sparse; } if (off_s == 0 && off_e == size) - break;/* This is not spase. */ + break;/* This is not sparse. */ archive_entry_sparse_add_entry(entry, off_s, off_e - off_s); off_s = off_e; @@ -1241,7 +1983,7 @@ exit_setup_sparse: return (exit_sts); } -#else +#elif !defined(HAVE_LINUX_FIEMAP_H) /* * Generic (stub) sparse support. diff --git a/libarchive/archive_read_disk_posix.c b/libarchive/archive_read_disk_posix.c index 22a1f14..b893704 100644 --- a/libarchive/archive_read_disk_posix.c +++ b/libarchive/archive_read_disk_posix.c @@ -165,7 +165,7 @@ struct filesystem { int synthetic; int remote; int noatime; -#if defined(HAVE_READDIR_R) +#if defined(USE_READDIR_R) size_t name_max; #endif long incr_xfer_size; @@ -200,7 +200,7 @@ struct tree { DIR *d; #define INVALID_DIR_HANDLE NULL struct dirent *de; -#if defined(HAVE_READDIR_R) +#if defined(USE_READDIR_R) struct dirent *dirent; size_t dirent_allocated; #endif @@ -244,7 +244,7 @@ struct tree { int initial_filesystem_id; int current_filesystem_id; int max_filesystem_id; - int allocated_filesytem; + int allocated_filesystem; int entry_fd; int entry_eof; @@ -675,7 +675,7 @@ setup_suitable_read_buffer(struct archive_read_disk *a) asize = cf->min_xfer_size; /* Increase a buffer size up to 64K bytes in - * a proper incremant size. */ + * a proper increment size. */ while (asize < 1024*64) asize += incr; /* Take a margin to adjust to the filesystem @@ -938,7 +938,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, r = archive_match_path_excluded(a->matching, entry); if (r < 0) { archive_set_error(&(a->archive), errno, - "Faild : %s", archive_error_string(a->matching)); + "Failed : %s", archive_error_string(a->matching)); return (r); } if (r) { @@ -1026,7 +1026,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, /* Save the times to be restored. This must be in before * calling archive_read_disk_descend() or any chance of it, - * especially, invokng a callback. */ + * especially, invoking a callback. */ t->restore_time.mtime = archive_entry_mtime(entry); t->restore_time.mtime_nsec = archive_entry_mtime_nsec(entry); t->restore_time.atime = archive_entry_atime(entry); @@ -1041,7 +1041,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, r = archive_match_time_excluded(a->matching, entry); if (r < 0) { archive_set_error(&(a->archive), errno, - "Faild : %s", archive_error_string(a->matching)); + "Failed : %s", archive_error_string(a->matching)); return (r); } if (r) { @@ -1067,7 +1067,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, r = archive_match_owner_excluded(a->matching, entry); if (r < 0) { archive_set_error(&(a->archive), errno, - "Faild : %s", archive_error_string(a->matching)); + "Failed : %s", archive_error_string(a->matching)); return (r); } if (r) { @@ -1382,7 +1382,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev) for (i = 0; i < t->max_filesystem_id; i++) { if (t->filesystem_table[i].dev == dev) { - /* There is the filesytem ID we've already generated. */ + /* There is the filesystem ID we've already generated. */ t->current_filesystem_id = i; t->current_filesystem = &(t->filesystem_table[i]); return (ARCHIVE_OK); @@ -1390,10 +1390,10 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev) } /* - * This is the new filesytem which we have to generate a new ID for. + * This is the new filesystem which we have to generate a new ID for. */ fid = t->max_filesystem_id++; - if (t->max_filesystem_id > t->allocated_filesytem) { + if (t->max_filesystem_id > t->allocated_filesystem) { size_t s; void *p; @@ -1406,7 +1406,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev) return (ARCHIVE_FATAL); } t->filesystem_table = (struct filesystem *)p; - t->allocated_filesytem = s; + t->allocated_filesystem = s; } t->current_filesystem_id = fid; t->current_filesystem = &(t->filesystem_table[fid]); @@ -1504,7 +1504,20 @@ setup_current_filesystem(struct archive_read_disk *a) struct tree *t = a->tree; struct statfs sfs; #if defined(HAVE_GETVFSBYNAME) && defined(VFCF_SYNTHETIC) +/* TODO: configure should set GETVFSBYNAME_ARG_TYPE to make + * this accurate; some platforms have both and we need the one that's + * used by getvfsbyname() + * + * Then the following would become: + * #if defined(GETVFSBYNAME_ARG_TYPE) + * GETVFSBYNAME_ARG_TYPE vfc; + * #endif + */ +# if defined(HAVE_STRUCT_XVFSCONF) struct xvfsconf vfc; +# else + struct vfsconf vfc; +# endif #endif int r, xr = 0; #if !defined(HAVE_STRUCT_STATFS_F_NAMEMAX) @@ -1579,7 +1592,7 @@ setup_current_filesystem(struct archive_read_disk *a) #endif t->current_filesystem->noatime = 0; -#if defined(HAVE_READDIR_R) +#if defined(USE_READDIR_R) /* Set maximum filename length. */ #if defined(HAVE_STRUCT_STATFS_F_NAMEMAX) t->current_filesystem->name_max = sfs.f_namemax; @@ -1602,7 +1615,7 @@ setup_current_filesystem(struct archive_read_disk *a) else t->current_filesystem->name_max = nm; #endif -#endif /* HAVE_READDIR_R */ +#endif /* USE_READDIR_R */ return (ARCHIVE_OK); } @@ -1643,7 +1656,7 @@ setup_current_filesystem(struct archive_read_disk *a) archive_set_error(&a->archive, errno, "statvfs failed"); return (ARCHIVE_FAILED); } else if (xr == 1) { - /* Usuall come here unless NetBSD supports _PC_REC_XFER_ALIGN + /* Usually come here unless NetBSD supports _PC_REC_XFER_ALIGN * for pathconf() function. */ t->current_filesystem->xfer_align = sfs.f_frsize; t->current_filesystem->max_xfer_size = -1; @@ -1804,7 +1817,7 @@ setup_current_filesystem(struct archive_read_disk *a) #endif t->current_filesystem->noatime = 0; -#if defined(HAVE_READDIR_R) +#if defined(USE_READDIR_R) /* Set maximum filename length. */ t->current_filesystem->name_max = sfs.f_namelen; #endif @@ -1888,7 +1901,7 @@ setup_current_filesystem(struct archive_read_disk *a) #endif t->current_filesystem->noatime = 0; -#if defined(HAVE_READDIR_R) +#if defined(USE_READDIR_R) /* Set maximum filename length. */ t->current_filesystem->name_max = sfs.f_namemax; #endif @@ -1905,7 +1918,7 @@ static int setup_current_filesystem(struct archive_read_disk *a) { struct tree *t = a->tree; -#if defined(_PC_NAME_MAX) && defined(HAVE_READDIR_R) +#if defined(_PC_NAME_MAX) && defined(USE_READDIR_R) long nm; #endif t->current_filesystem->synthetic = -1;/* Not supported */ @@ -1917,7 +1930,7 @@ setup_current_filesystem(struct archive_read_disk *a) t->current_filesystem->min_xfer_size = -1; t->current_filesystem->incr_xfer_size = -1; -#if defined(HAVE_READDIR_R) +#if defined(USE_READDIR_R) /* Set maximum filename length. */ # if defined(_PC_NAME_MAX) if (tree_current_is_symblic_link_target(t)) { @@ -1931,7 +1944,7 @@ setup_current_filesystem(struct archive_read_disk *a) if (nm == -1) # endif /* _PC_NAME_MAX */ /* - * Some sysmtes (HP-UX or others?) incorrectly defined + * Some systems (HP-UX or others?) incorrectly defined * NAME_MAX macro to be a smaller value. */ # if defined(NAME_MAX) && NAME_MAX >= 255 @@ -1945,7 +1958,7 @@ setup_current_filesystem(struct archive_read_disk *a) else t->current_filesystem->name_max = nm; # endif /* _PC_NAME_MAX */ -#endif /* HAVE_READDIR_R */ +#endif /* USE_READDIR_R */ return (ARCHIVE_OK); } @@ -2050,8 +2063,7 @@ tree_push(struct tree *t, const char *path, int filesystem_id, { struct tree_entry *te; - te = malloc(sizeof(*te)); - memset(te, 0, sizeof(*te)); + te = calloc(1, sizeof(*te)); te->next = t->stack; te->parent = t->current; if (te->parent) @@ -2109,9 +2121,8 @@ tree_open(const char *path, int symlink_mode, int restore_time) { struct tree *t; - if ((t = malloc(sizeof(*t))) == NULL) + if ((t = calloc(1, sizeof(*t))) == NULL) return (NULL); - memset(t, 0, sizeof(*t)); archive_string_init(&t->path); archive_string_ensure(&t->path, 31); t->initial_symlink_mode = symlink_mode; @@ -2353,7 +2364,7 @@ tree_dir_next_posix(struct tree *t) size_t namelen; if (t->d == NULL) { -#if defined(HAVE_READDIR_R) +#if defined(USE_READDIR_R) size_t dirent_size; #endif @@ -2374,7 +2385,7 @@ tree_dir_next_posix(struct tree *t) t->visit_type = r != 0 ? r : TREE_ERROR_DIR; return (t->visit_type); } -#if defined(HAVE_READDIR_R) +#if defined(USE_READDIR_R) dirent_size = offsetof(struct dirent, d_name) + t->filesystem_table[t->current->filesystem_id].name_max + 1; if (t->dirent == NULL || t->dirent_allocated < dirent_size) { @@ -2391,11 +2402,11 @@ tree_dir_next_posix(struct tree *t) } t->dirent_allocated = dirent_size; } -#endif /* HAVE_READDIR_R */ +#endif /* USE_READDIR_R */ } for (;;) { errno = 0; -#if defined(HAVE_READDIR_R) +#if defined(USE_READDIR_R) r = readdir_r(t->d, t->dirent, &t->de); #ifdef _AIX /* Note: According to the man page, return value 9 indicates @@ -2647,7 +2658,7 @@ tree_free(struct tree *t) if (t == NULL) return; archive_string_free(&t->path); -#if defined(HAVE_READDIR_R) +#if defined(USE_READDIR_R) free(t->dirent); #endif free(t->sparse_list); diff --git a/libarchive/archive_read_disk_set_standard_lookup.c b/libarchive/archive_read_disk_set_standard_lookup.c index d6b2d55..c7fd247 100644 --- a/libarchive/archive_read_disk_set_standard_lookup.c +++ b/libarchive/archive_read_disk_set_standard_lookup.c @@ -232,6 +232,7 @@ static const char * lookup_uname_helper(struct name_cache *cache, id_t id) { struct passwd *result; + (void)cache; /* UNUSED */ result = getpwuid((uid_t)id); @@ -298,6 +299,7 @@ static const char * lookup_gname_helper(struct name_cache *cache, id_t id) { struct group *result; + (void)cache; /* UNUSED */ result = getgrgid((gid_t)id); diff --git a/libarchive/archive_read_disk_windows.c b/libarchive/archive_read_disk_windows.c index 566d264..27b75e3 100644 --- a/libarchive/archive_read_disk_windows.c +++ b/libarchive/archive_read_disk_windows.c @@ -168,7 +168,7 @@ struct tree { int initial_filesystem_id; int current_filesystem_id; int max_filesystem_id; - int allocated_filesytem; + int allocated_filesystem; HANDLE entry_fh; int entry_eof; @@ -389,10 +389,9 @@ archive_read_disk_new(void) { struct archive_read_disk *a; - a = (struct archive_read_disk *)malloc(sizeof(*a)); + a = (struct archive_read_disk *)calloc(1, sizeof(*a)); if (a == NULL) return (NULL); - memset(a, 0, sizeof(*a)); a->archive.magic = ARCHIVE_READ_DISK_MAGIC; a->archive.state = ARCHIVE_STATE_NEW; a->archive.vtable = archive_read_disk_vtable(); @@ -803,7 +802,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, r = archive_match_path_excluded(a->matching, entry); if (r < 0) { archive_set_error(&(a->archive), errno, - "Faild : %s", archive_error_string(a->matching)); + "Failed : %s", archive_error_string(a->matching)); return (r); } if (r) { @@ -863,7 +862,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, /* Save the times to be restored. This must be in before * calling archive_read_disk_descend() or any chance of it, - * especially, invokng a callback. */ + * especially, invoking a callback. */ t->restore_time.lastWriteTime = st->ftLastWriteTime; t->restore_time.lastAccessTime = st->ftLastAccessTime; t->restore_time.filetype = archive_entry_filetype(entry); @@ -875,7 +874,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, r = archive_match_time_excluded(a->matching, entry); if (r < 0) { archive_set_error(&(a->archive), errno, - "Faild : %s", archive_error_string(a->matching)); + "Failed : %s", archive_error_string(a->matching)); return (r); } if (r) { @@ -901,7 +900,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, r = archive_match_owner_excluded(a->matching, entry); if (r < 0) { archive_set_error(&(a->archive), errno, - "Faild : %s", archive_error_string(a->matching)); + "Failed : %s", archive_error_string(a->matching)); return (r); } if (r) { @@ -1261,7 +1260,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev) for (i = 0; i < t->max_filesystem_id; i++) { if (t->filesystem_table[i].dev == dev) { - /* There is the filesytem ID we've already generated. */ + /* There is the filesystem ID we've already generated. */ t->current_filesystem_id = i; t->current_filesystem = &(t->filesystem_table[i]); return (ARCHIVE_OK); @@ -1269,10 +1268,10 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev) } /* - * There is a new filesytem, we generate a new ID for. + * There is a new filesystem, we generate a new ID for. */ fid = t->max_filesystem_id++; - if (t->max_filesystem_id > t->allocated_filesytem) { + if (t->max_filesystem_id > t->allocated_filesystem) { size_t s; void *p; @@ -1285,7 +1284,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev) return (ARCHIVE_FATAL); } t->filesystem_table = (struct filesystem *)p; - t->allocated_filesytem = (int)s; + t->allocated_filesystem = (int)s; } t->current_filesystem_id = fid; t->current_filesystem = &(t->filesystem_table[fid]); @@ -1402,7 +1401,7 @@ close_and_restore_time(HANDLE h, struct tree *t, struct restore_time *rt) if (h == INVALID_HANDLE_VALUE && AE_IFLNK == rt->filetype) return (0); - /* Close a file descritor. + /* Close a file descriptor. * It will not be used for SetFileTime() because it has been opened * by a read only mode. */ @@ -1437,8 +1436,7 @@ tree_push(struct tree *t, const wchar_t *path, const wchar_t *full_path, { struct tree_entry *te; - te = malloc(sizeof(*te)); - memset(te, 0, sizeof(*te)); + te = calloc(1, sizeof(*te)); te->next = t->stack; te->parent = t->current; if (te->parent) @@ -1507,8 +1505,7 @@ tree_open(const wchar_t *path, int symlink_mode, int restore_time) { struct tree *t; - t = malloc(sizeof(*t)); - memset(t, 0, sizeof(*t)); + t = calloc(1, sizeof(*t)); archive_string_init(&(t->full_path)); archive_string_init(&t->path); archive_wstring_ensure(&t->path, 15); diff --git a/libarchive/archive_read_extract2.c b/libarchive/archive_read_extract2.c index 7b2c126..4febd8c 100644 --- a/libarchive/archive_read_extract2.c +++ b/libarchive/archive_read_extract2.c @@ -52,12 +52,11 @@ struct archive_read_extract * __archive_read_get_extract(struct archive_read *a) { if (a->extract == NULL) { - a->extract = (struct archive_read_extract *)malloc(sizeof(*a->extract)); + a->extract = (struct archive_read_extract *)calloc(1, sizeof(*a->extract)); if (a->extract == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't extract"); return (NULL); } - memset(a->extract, 0, sizeof(*a->extract)); a->cleanup_archive_extract = archive_read_extract_cleanup; } return (a->extract); diff --git a/libarchive/archive_read_open_filename.c b/libarchive/archive_read_open_filename.c index 5611aa8..86635e2 100644 --- a/libarchive/archive_read_open_filename.c +++ b/libarchive/archive_read_open_filename.c @@ -222,7 +222,7 @@ file_open(struct archive *a, void *client_data) void *buffer; const char *filename = NULL; const wchar_t *wfilename = NULL; - int fd; + int fd = -1; int is_disk_like = 0; #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) off_t mediasize = 0; /* FreeBSD-specific, so off_t okay here. */ @@ -277,7 +277,7 @@ file_open(struct archive *a, void *client_data) #else archive_set_error(a, ARCHIVE_ERRNO_MISC, "Unexpedted operation in archive_read_open_filename"); - return (ARCHIVE_FATAL); + goto fail; #endif } if (fstat(fd, &st) != 0) { @@ -287,7 +287,7 @@ file_open(struct archive *a, void *client_data) else archive_set_error(a, errno, "Can't stat '%s'", filename); - return (ARCHIVE_FATAL); + goto fail; } /* @@ -356,11 +356,9 @@ file_open(struct archive *a, void *client_data) mine->block_size = new_block_size; } buffer = malloc(mine->block_size); - if (mine == NULL || buffer == NULL) { + if (buffer == NULL) { archive_set_error(a, ENOMEM, "No memory"); - free(mine); - free(buffer); - return (ARCHIVE_FATAL); + goto fail; } mine->buffer = buffer; mine->fd = fd; @@ -372,6 +370,14 @@ file_open(struct archive *a, void *client_data) mine->use_lseek = 1; return (ARCHIVE_OK); +fail: + /* + * Don't close file descriptors not opened or ones pointing referring + * to `FNT_STDIN`. + */ + if (fd != -1 && fd != 0) + close(fd); + return (ARCHIVE_FATAL); } static ssize_t diff --git a/libarchive/archive_read_open_memory.c b/libarchive/archive_read_open_memory.c index ff935a7..311be47 100644 --- a/libarchive/archive_read_open_memory.c +++ b/libarchive/archive_read_open_memory.c @@ -70,12 +70,11 @@ archive_read_open_memory2(struct archive *a, const void *buff, { struct read_memory_data *mine; - mine = (struct read_memory_data *)malloc(sizeof(*mine)); + mine = (struct read_memory_data *)calloc(1, sizeof(*mine)); if (mine == NULL) { archive_set_error(a, ENOMEM, "No memory"); return (ARCHIVE_FATAL); } - memset(mine, 0, sizeof(*mine)); mine->start = mine->p = (const unsigned char *)buff; mine->end = mine->start + size; mine->read_size = read_size; diff --git a/libarchive/archive_read_private.h b/libarchive/archive_read_private.h index 9b61a53..78546dc 100644 --- a/libarchive/archive_read_private.h +++ b/libarchive/archive_read_private.h @@ -221,7 +221,7 @@ struct archive_read { struct { struct archive_read_passphrase *first; struct archive_read_passphrase **last; - int candiate; + int candidate; archive_passphrase_callback *callback; void *client_data; } passphrases; @@ -252,7 +252,6 @@ int64_t __archive_read_consume(struct archive_read *, int64_t); int64_t __archive_read_filter_consume(struct archive_read_filter *, int64_t); int __archive_read_program(struct archive_read_filter *, const char *); void __archive_read_free_filters(struct archive_read *); -int __archive_read_close_filters(struct archive_read *); struct archive_read_extract *__archive_read_get_extract(struct archive_read *); diff --git a/libarchive/archive_read_support_filter_lz4.c b/libarchive/archive_read_support_filter_lz4.c index e877917..663e2d3 100644 --- a/libarchive/archive_read_support_filter_lz4.c +++ b/libarchive/archive_read_support_filter_lz4.c @@ -180,7 +180,7 @@ lz4_reader_bid(struct archive_read_filter_bidder *self, return (0); bits_checked += 8; BD = buffer[5]; - /* A block maximum size shuld be more than 3. */ + /* A block maximum size should be more than 3. */ if (((BD & 0x70) >> 4) < 4) return (0); /* Reserved bits must be "0". */ @@ -417,7 +417,7 @@ lz4_filter_read_descriptor(struct archive_read_filter *self) /* Reserved bits must be zero. */ if (bd & 0x8f) goto malformed_error; - /* Get a maxinum block size. */ + /* Get a maximum block size. */ switch (read_buf[1] >> 4) { case 4: /* 64 KB */ state->flags.block_maximum_size = 64 * 1024; @@ -595,7 +595,7 @@ lz4_filter_read_data_block(struct archive_read_filter *self, const void **p) #endif } - /* Check if an error happend in decompression process. */ + /* Check if an error occurred in the decompression process. */ if (uncompressed_size < 0) { archive_set_error(&(self->archive->archive), ARCHIVE_ERRNO_MISC, "lz4 decompression failed"); @@ -627,7 +627,7 @@ lz4_filter_read_default_stream(struct archive_read_filter *self, const void **p) if (state->stage == SELECT_STREAM) { state->stage = READ_DEFAULT_STREAM; - /* First, read a desciprtor. */ + /* First, read a descriptor. */ if((ret = lz4_filter_read_descriptor(self)) != ARCHIVE_OK) return (ret); state->stage = READ_DEFAULT_BLOCK; @@ -706,6 +706,11 @@ lz4_filter_read_legacy_stream(struct archive_read_filter *self, const void **p) /* Make sure we have a whole block. */ read_buf = __archive_read_filter_ahead(self->upstream, 4 + compressed, NULL); + if (read_buf == NULL) { + archive_set_error(&(self->archive->archive), + ARCHIVE_ERRNO_MISC, "truncated lz4 input"); + return (ARCHIVE_FATAL); + } ret = LZ4_decompress_safe(read_buf + 4, state->out_block, compressed, (int)state->out_block_size); if (ret < 0) { diff --git a/libarchive/archive_read_support_filter_lzop.c b/libarchive/archive_read_support_filter_lzop.c index 44ac996..a1c392f 100644 --- a/libarchive/archive_read_support_filter_lzop.c +++ b/libarchive/archive_read_support_filter_lzop.c @@ -436,7 +436,7 @@ lzop_filter_read(struct archive_read_filter *self, const void **p) } /* - * Drive lzo uncompresison. + * Drive lzo uncompression. */ out_size = (lzo_uint)state->uncompressed_size; r = lzo1x_decompress_safe(b, (lzo_uint)state->compressed_size, diff --git a/libarchive/archive_read_support_filter_program.c b/libarchive/archive_read_support_filter_program.c index 66dc2f4..b8bf128 100644 --- a/libarchive/archive_read_support_filter_program.c +++ b/libarchive/archive_read_support_filter_program.c @@ -430,6 +430,7 @@ __archive_read_program(struct archive_read_filter *self, const char *cmd) &state->child_stdout); if (child == -1) { free(state->out_buf); + archive_string_free(&state->description); free(state); archive_set_error(&self->archive->archive, EINVAL, "Can't initialize filter; unable to run program \"%s\"", @@ -441,6 +442,7 @@ __archive_read_program(struct archive_read_filter *self, const char *cmd) if (state->child == NULL) { child_stop(self, state); free(state->out_buf); + archive_string_free(&state->description); free(state); archive_set_error(&self->archive->archive, EINVAL, "Can't initialize filter; unable to run program \"%s\"", diff --git a/libarchive/archive_read_support_filter_uu.c b/libarchive/archive_read_support_filter_uu.c index 787a619..6412979 100644 --- a/libarchive/archive_read_support_filter_uu.c +++ b/libarchive/archive_read_support_filter_uu.c @@ -312,6 +312,7 @@ uudecode_bidder_bid(struct archive_read_filter_bidder *self, avail -= len; if (l == 6) { + /* "begin " */ if (!uuchar[*b]) return (0); /* Get a length of decoded bytes. */ @@ -319,30 +320,14 @@ uudecode_bidder_bid(struct archive_read_filter_bidder *self, if (l > 45) /* Normally, maximum length is 45(character 'M'). */ return (0); - while (l && len-nl > 0) { - if (l > 0) { - if (!uuchar[*b++]) - return (0); - if (!uuchar[*b++]) - return (0); - len -= 2; - --l; - } - if (l > 0) { - if (!uuchar[*b++]) - return (0); - --len; - --l; - } - if (l > 0) { - if (!uuchar[*b++]) - return (0); - --len; - --l; - } + if (l > len - nl) + return (0); /* Line too short. */ + while (l) { + if (!uuchar[*b++]) + return (0); + --len; + --l; } - if (len-nl < 0) - return (0); if (len-nl == 1 && (uuchar[*b] || /* Check sum. */ (*b >= 'a' && *b <= 'z'))) {/* Padding data(MINIX). */ @@ -352,8 +337,8 @@ uudecode_bidder_bid(struct archive_read_filter_bidder *self, b += nl; if (avail && uuchar[*b]) return (firstline+30); - } - if (l == 13) { + } else if (l == 13) { + /* "begin-base64 " */ while (len-nl > 0) { if (!base64[*b++]) return (0); @@ -510,6 +495,13 @@ read_more: } llen = len; if ((nl == 0) && (uudecode->state != ST_UUEND)) { + if (total == 0 && ravail <= 0) { + /* There is nothing more to read, fail */ + archive_set_error(&self->archive->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Missing format data"); + return (ARCHIVE_FATAL); + } /* * Save remaining data which does not contain * NL('\n','\r'). @@ -566,7 +558,7 @@ read_more: "Insufficient compressed data"); return (ARCHIVE_FATAL); } - /* Get length of undecoded bytes of curent line. */ + /* Get length of undecoded bytes of current line. */ l = UUDECODE(*b++); body--; if (l > body) { diff --git a/libarchive/archive_read_support_filter_xz.c b/libarchive/archive_read_support_filter_xz.c index 4e0a95f..11807cf 100644 --- a/libarchive/archive_read_support_filter_xz.c +++ b/libarchive/archive_read_support_filter_xz.c @@ -43,8 +43,6 @@ __FBSDID("$FreeBSD$"); #endif #if HAVE_LZMA_H #include -#elif HAVE_LZMADEC_H -#include #endif #include "archive.h" @@ -82,19 +80,6 @@ static ssize_t xz_filter_read(struct archive_read_filter *, const void **); static int xz_filter_close(struct archive_read_filter *); static int xz_lzma_bidder_init(struct archive_read_filter *); -#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC - -struct private_data { - lzmadec_stream stream; - unsigned char *out_block; - size_t out_block_size; - int64_t total_out; - char eof; /* True = found end of compressed data. */ -}; - -/* Lzma-only filter */ -static ssize_t lzma_filter_read(struct archive_read_filter *, const void **); -static int lzma_filter_close(struct archive_read_filter *); #endif /* @@ -178,8 +163,6 @@ archive_read_support_filter_lzma(struct archive *_a) bidder->free = NULL; #if HAVE_LZMA_H && HAVE_LIBLZMA return (ARCHIVE_OK); -#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC - return (ARCHIVE_OK); #else archive_set_error(_a, ARCHIVE_ERRNO_MISC, "Using external lzma program for lzma decompression"); @@ -310,7 +293,7 @@ lzma_bidder_bid(struct archive_read_filter_bidder *self, /* Second through fifth bytes are dictionary size, stored in * little-endian order. The minimum dictionary size is * 1 << 12(4KiB) which the lzma of LZMA SDK uses with option - * -d12 and the maxinam dictionary size is 1 << 27(128MiB) + * -d12 and the maximum dictionary size is 1 << 27(128MiB) * which the one uses with option -d27. * NOTE: A comment of LZMA SDK source code says this dictionary * range is from 1 << 12 to 1 << 30. */ @@ -601,9 +584,7 @@ lzip_init(struct archive_read_filter *self) return (ARCHIVE_FATAL); } ret = lzma_raw_decoder(&(state->stream), filters); -#if LZMA_VERSION < 50010000 free(filters[0].options); -#endif if (ret != LZMA_OK) { set_error(self, ret); return (ARCHIVE_FATAL); @@ -763,175 +744,6 @@ xz_filter_close(struct archive_read_filter *self) #else -#if HAVE_LZMADEC_H && HAVE_LIBLZMADEC - -/* - * If we have the older liblzmadec library, then we can handle - * LZMA streams but not XZ streams. - */ - -/* - * Setup the callbacks. - */ -static int -lzma_bidder_init(struct archive_read_filter *self) -{ - static const size_t out_block_size = 64 * 1024; - void *out_block; - struct private_data *state; - ssize_t ret, avail_in; - - self->code = ARCHIVE_FILTER_LZMA; - self->name = "lzma"; - - state = (struct private_data *)calloc(sizeof(*state), 1); - out_block = (unsigned char *)malloc(out_block_size); - if (state == NULL || out_block == NULL) { - archive_set_error(&self->archive->archive, ENOMEM, - "Can't allocate data for lzma decompression"); - free(out_block); - free(state); - return (ARCHIVE_FATAL); - } - - self->data = state; - state->out_block_size = out_block_size; - state->out_block = out_block; - self->read = lzma_filter_read; - self->skip = NULL; /* not supported */ - self->close = lzma_filter_close; - - /* Prime the lzma library with 18 bytes of input. */ - state->stream.next_in = (unsigned char *)(uintptr_t) - __archive_read_filter_ahead(self->upstream, 18, &avail_in); - if (state->stream.next_in == NULL) - return (ARCHIVE_FATAL); - state->stream.avail_in = avail_in; - state->stream.next_out = state->out_block; - state->stream.avail_out = state->out_block_size; - - /* Initialize compression library. */ - ret = lzmadec_init(&(state->stream)); - __archive_read_filter_consume(self->upstream, - avail_in - state->stream.avail_in); - if (ret == LZMADEC_OK) - return (ARCHIVE_OK); - - /* Library setup failed: Clean up. */ - archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, - "Internal error initializing lzma library"); - - /* Override the error message if we know what really went wrong. */ - switch (ret) { - case LZMADEC_HEADER_ERROR: - archive_set_error(&self->archive->archive, - ARCHIVE_ERRNO_MISC, - "Internal error initializing compression library: " - "invalid header"); - break; - case LZMADEC_MEM_ERROR: - archive_set_error(&self->archive->archive, ENOMEM, - "Internal error initializing compression library: " - "out of memory"); - break; - } - - free(state->out_block); - free(state); - self->data = NULL; - return (ARCHIVE_FATAL); -} - -/* - * Return the next block of decompressed data. - */ -static ssize_t -lzma_filter_read(struct archive_read_filter *self, const void **p) -{ - struct private_data *state; - size_t decompressed; - ssize_t avail_in, ret; - - state = (struct private_data *)self->data; - - /* Empty our output buffer. */ - state->stream.next_out = state->out_block; - state->stream.avail_out = state->out_block_size; - - /* Try to fill the output buffer. */ - while (state->stream.avail_out > 0 && !state->eof) { - state->stream.next_in = (unsigned char *)(uintptr_t) - __archive_read_filter_ahead(self->upstream, 1, &avail_in); - if (state->stream.next_in == NULL && avail_in < 0) { - archive_set_error(&self->archive->archive, - ARCHIVE_ERRNO_MISC, - "truncated lzma input"); - return (ARCHIVE_FATAL); - } - state->stream.avail_in = avail_in; - - /* Decompress as much as we can in one pass. */ - ret = lzmadec_decode(&(state->stream), avail_in == 0); - switch (ret) { - case LZMADEC_STREAM_END: /* Found end of stream. */ - state->eof = 1; - /* FALL THROUGH */ - case LZMADEC_OK: /* Decompressor made some progress. */ - __archive_read_filter_consume(self->upstream, - avail_in - state->stream.avail_in); - break; - case LZMADEC_BUF_ERROR: /* Insufficient input data? */ - archive_set_error(&self->archive->archive, - ARCHIVE_ERRNO_MISC, - "Insufficient compressed data"); - return (ARCHIVE_FATAL); - default: - /* Return an error. */ - archive_set_error(&self->archive->archive, - ARCHIVE_ERRNO_MISC, - "Lzma decompression failed"); - return (ARCHIVE_FATAL); - } - } - - decompressed = state->stream.next_out - state->out_block; - state->total_out += decompressed; - if (decompressed == 0) - *p = NULL; - else - *p = state->out_block; - return (decompressed); -} - -/* - * Clean up the decompressor. - */ -static int -lzma_filter_close(struct archive_read_filter *self) -{ - struct private_data *state; - int ret; - - state = (struct private_data *)self->data; - ret = ARCHIVE_OK; - switch (lzmadec_end(&(state->stream))) { - case LZMADEC_OK: - break; - default: - archive_set_error(&(self->archive->archive), - ARCHIVE_ERRNO_MISC, - "Failed to clean up %s compressor", - self->archive->archive.compression_name); - ret = ARCHIVE_FATAL; - } - - free(state->out_block); - free(state); - return (ret); -} - -#else - /* * * If we have no suitable library on this system, we can't actually do @@ -953,9 +765,6 @@ lzma_bidder_init(struct archive_read_filter *self) return (r); } -#endif /* HAVE_LZMADEC_H */ - - static int xz_bidder_init(struct archive_read_filter *self) { @@ -984,5 +793,4 @@ lzip_bidder_init(struct archive_read_filter *self) return (r); } - #endif /* HAVE_LZMA_H */ diff --git a/libarchive/archive_read_support_format_7zip.c b/libarchive/archive_read_support_format_7zip.c index 1dfe52b..3387eaf 100644 --- a/libarchive/archive_read_support_format_7zip.c +++ b/libarchive/archive_read_support_format_7zip.c @@ -213,7 +213,7 @@ struct _7zip { int header_is_encoded; uint64_t header_bytes_remaining; unsigned long header_crc32; - /* Header offset to check that reading pointes of the file contens + /* Header offset to check that reading points of the file contents * will not exceed the header. */ uint64_t header_offset; /* Base offset of the archive file for a seek in case reading SFX. */ @@ -263,22 +263,22 @@ struct _7zip { /* * Decompressor controllers. */ - /* Decording LZMA1 and LZMA2 data. */ + /* Decoding LZMA1 and LZMA2 data. */ #ifdef HAVE_LZMA_H lzma_stream lzstream; int lzstream_valid; #endif - /* Decording bzip2 data. */ + /* Decoding bzip2 data. */ #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) bz_stream bzstream; int bzstream_valid; #endif - /* Decording deflate data. */ + /* Decoding deflate data. */ #ifdef HAVE_ZLIB_H z_stream stream; int stream_valid; #endif - /* Decording PPMd data. */ + /* Decoding PPMd data. */ int ppmd7_stat; CPpmd7 ppmd7_context; CPpmd7z_RangeDec range_dec; @@ -552,7 +552,7 @@ skip_sfx(struct archive_read *a, ssize_t bytes_avail) /* * If bytes_avail > SFX_MIN_ADDR we do not have to call * __archive_read_seek() at this time since we have - * alredy had enough data. + * already had enough data. */ if (bytes_avail > SFX_MIN_ADDR) __archive_read_consume(a, SFX_MIN_ADDR); @@ -760,7 +760,7 @@ archive_read_format_7zip_read_header(struct archive_read *a, symsize += size; } if (symsize == 0) { - /* If there is no synname, handle it as a regular + /* If there is no symname, handle it as a regular * file. */ zip_entry->mode &= ~AE_IFMT; zip_entry->mode |= AE_IFREG; @@ -1056,10 +1056,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip, #endif { lzma_options_delta delta_opt; - lzma_filter filters[LZMA_FILTERS_MAX]; -#if LZMA_VERSION < 50010000 - lzma_filter *ff; -#endif + lzma_filter filters[LZMA_FILTERS_MAX], *ff; int fi = 0; if (zip->lzstream_valid) { @@ -1144,9 +1141,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip, else filters[fi].id = LZMA_FILTER_LZMA1; filters[fi].options = NULL; -#if LZMA_VERSION < 50010000 ff = &filters[fi]; -#endif r = lzma_properties_decode(&filters[fi], NULL, coder1->properties, (size_t)coder1->propertiesSize); if (r != LZMA_OK) { @@ -1158,9 +1153,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip, filters[fi].id = LZMA_VLI_UNKNOWN; filters[fi].options = NULL; r = lzma_raw_decoder(&(zip->lzstream), filters); -#if LZMA_VERSION < 50010000 free(ff->options); -#endif if (r != LZMA_OK) { set_error(a, r); return (ARCHIVE_FAILED); @@ -2431,6 +2424,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h, switch (type) { case kEmptyStream: + if (h->emptyStreamBools != NULL) + return (-1); h->emptyStreamBools = calloc((size_t)zip->numFiles, sizeof(*h->emptyStreamBools)); if (h->emptyStreamBools == NULL) @@ -2451,6 +2446,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h, return (-1); break; } + if (h->emptyFileBools != NULL) + return (-1); h->emptyFileBools = calloc(empty_streams, sizeof(*h->emptyFileBools)); if (h->emptyFileBools == NULL) @@ -2465,6 +2462,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h, return (-1); break; } + if (h->antiBools != NULL) + return (-1); h->antiBools = calloc(empty_streams, sizeof(*h->antiBools)); if (h->antiBools == NULL) @@ -2491,6 +2490,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h, if ((ll & 1) || ll < zip->numFiles * 4) return (-1); + if (zip->entry_names != NULL) + return (-1); zip->entry_names = malloc(ll); if (zip->entry_names == NULL) return (-1); @@ -2543,6 +2544,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h, if ((p = header_bytes(a, 2)) == NULL) return (-1); allAreDefined = *p; + if (h->attrBools != NULL) + return (-1); h->attrBools = calloc((size_t)zip->numFiles, sizeof(*h->attrBools)); if (h->attrBools == NULL) @@ -3285,7 +3288,7 @@ read_stream(struct archive_read *a, const void **buff, size_t size, return (r); /* - * Skip the bytes we alrady has skipped in skip_stream(). + * Skip the bytes we already has skipped in skip_stream(). */ while (skip_bytes) { ssize_t skipped; @@ -3503,7 +3506,7 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder, return (ARCHIVE_FATAL); } - /* Allocate memory for the decorded data of a sub + /* Allocate memory for the decoded data of a sub * stream. */ b[i] = malloc((size_t)zip->folder_outbytes_remaining); if (b[i] == NULL) { @@ -3588,7 +3591,7 @@ skip_stream(struct archive_read *a, size_t skip_bytes) if (zip->folder_index == 0) { /* * Optimization for a list mode. - * Avoid unncecessary decoding operations. + * Avoid unnecessary decoding operations. */ zip->si.ci.folders[zip->entry->folderIndex].skipped_bytes += skip_bytes; diff --git a/libarchive/archive_read_support_format_ar.c b/libarchive/archive_read_support_format_ar.c index 4b5b66b..b6b9fc3 100644 --- a/libarchive/archive_read_support_format_ar.c +++ b/libarchive/archive_read_support_format_ar.c @@ -104,13 +104,12 @@ archive_read_support_format_ar(struct archive *_a) archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, "archive_read_support_format_ar"); - ar = (struct ar *)malloc(sizeof(*ar)); + ar = (struct ar *)calloc(1, sizeof(*ar)); if (ar == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate ar data"); return (ARCHIVE_FATAL); } - memset(ar, 0, sizeof(*ar)); ar->strtab = NULL; r = __archive_read_register_format(a, @@ -260,7 +259,7 @@ _ar_read_header(struct archive_read *a, struct archive_entry *entry, archive_entry_set_filetype(entry, AE_IFREG); /* Get the size of the filename table. */ number = ar_atol10(h + AR_size_offset, AR_size_size); - if (number > SIZE_MAX) { + if (number > SIZE_MAX || number > 1024 * 1024 * 1024) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Filename table too large"); return (ARCHIVE_FATAL); @@ -316,7 +315,7 @@ _ar_read_header(struct archive_read *a, struct archive_entry *entry, * If we can't look up the real name, warn and return * the entry with the wrong name. */ - if (ar->strtab == NULL || number > ar->strtab_size) { + if (ar->strtab == NULL || number >= ar->strtab_size) { archive_set_error(&a->archive, EINVAL, "Can't find long filename for GNU/SVR4 archive entry"); archive_entry_copy_pathname(entry, filename); @@ -342,16 +341,19 @@ _ar_read_header(struct archive_read *a, struct archive_entry *entry, /* Parse the size of the name, adjust the file size. */ number = ar_atol10(h + AR_name_offset + 3, AR_name_size - 3); - bsd_name_length = (size_t)number; - /* Guard against the filename + trailing NUL - * overflowing a size_t and against the filename size - * being larger than the entire entry. */ - if (number > (uint64_t)(bsd_name_length + 1) - || (int64_t)bsd_name_length > ar->entry_bytes_remaining) { + /* Sanity check the filename length: + * = Must be <= SIZE_MAX - 1 + * = Must be <= 1MB + * = Cannot be bigger than the entire entry + */ + if (number > SIZE_MAX - 1 + || number > 1024 * 1024 + || (int64_t)number > ar->entry_bytes_remaining) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Bad input file size"); return (ARCHIVE_FATAL); } + bsd_name_length = (size_t)number; ar->entry_bytes_remaining -= bsd_name_length; /* Adjust file size reported to client. */ archive_entry_set_size(entry, ar->entry_bytes_remaining); diff --git a/libarchive/archive_read_support_format_cab.c b/libarchive/archive_read_support_format_cab.c index fc70684..e2f8c6b 100644 --- a/libarchive/archive_read_support_format_cab.c +++ b/libarchive/archive_read_support_format_cab.c @@ -67,7 +67,7 @@ struct lzx_dec { /* The length how many bytes we can copy decoded code from * the window. */ int copy_len; - /* Translation reversal for x86 proccessor CALL byte sequence(E8). + /* Translation reversal for x86 processor CALL byte sequence(E8). * This is used for LZX only. */ uint32_t translation_size; char translation; @@ -645,12 +645,13 @@ cab_read_header(struct archive_read *a) cab = (struct cab *)(a->format->data); if (cab->found_header == 0 && p[0] == 'M' && p[1] == 'Z') { - /* This is an executable? Must be self-extracting... */ + /* This is an executable? Must be self-extracting... */ err = cab_skip_sfx(a); if (err < ARCHIVE_WARN) return (err); - if ((p = __archive_read_ahead(a, sizeof(*p), NULL)) == NULL) + /* Re-read header after processing the SFX. */ + if ((p = __archive_read_ahead(a, 42, NULL)) == NULL) return (truncated_error(a)); } @@ -1494,6 +1495,8 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail) /* Cut out a tow-byte MSZIP signature(0x43, 0x4b). */ if (mszip > 0) { + if (bytes_avail <= 0) + goto nomszip; if (bytes_avail <= mszip) { if (mszip == 2) { if (cab->stream.next_in[0] != 0x43) @@ -1554,7 +1557,7 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail) /* * Note: I suspect there is a bug in makecab.exe because, in rare * case, compressed bytes are still remaining regardless we have - * gotten all uncompressed bytes, which size is recoded in CFDATA, + * gotten all uncompressed bytes, which size is recorded in CFDATA, * as much as we need, and we have to use the garbage so as to * correctly compute the sum of CFDATA accordingly. */ @@ -1741,7 +1744,7 @@ cab_read_ahead_cfdata_lzx(struct archive_read *a, ssize_t *avail) } /* - * Translation reversal of x86 proccessor CALL byte sequence(E8). + * Translation reversal of x86 processor CALL byte sequence(E8). */ lzx_translation(&cab->xstrm, cab->uncompressed_buffer, cfdata->uncompressed_size, @@ -2270,7 +2273,7 @@ static int lzx_br_fillup(struct lzx_stream *strm, struct lzx_br *br) { /* - * x86 proccessor family can read misaligned data without an access error. + * x86 processor family can read misaligned data without an access error. */ int n = CACHE_BITS - br->cache_avail; diff --git a/libarchive/archive_read_support_format_cpio.c b/libarchive/archive_read_support_format_cpio.c index b09db0e..ffd4a85 100644 --- a/libarchive/archive_read_support_format_cpio.c +++ b/libarchive/archive_read_support_format_cpio.c @@ -326,7 +326,7 @@ archive_read_format_cpio_options(struct archive_read *a, cpio = (struct cpio *)(a->format->data); if (strcmp(key, "compat-2x") == 0) { - /* Handle filnames as libarchive 2.x */ + /* Handle filenames as libarchive 2.x */ cpio->init_default_conversion = (val != NULL)?1:0; return (ARCHIVE_OK); } else if (strcmp(key, "hdrcharset") == 0) { @@ -356,7 +356,7 @@ archive_read_format_cpio_read_header(struct archive_read *a, struct archive_entry *entry) { struct cpio *cpio; - const void *h; + const void *h, *hl; struct archive_string_conv *sconv; size_t namelength; size_t name_pad; @@ -406,11 +406,11 @@ archive_read_format_cpio_read_header(struct archive_read *a, "Rejecting malformed cpio archive: symlink contents exceed 1 megabyte"); return (ARCHIVE_FATAL); } - h = __archive_read_ahead(a, + hl = __archive_read_ahead(a, (size_t)cpio->entry_bytes_remaining, NULL); - if (h == NULL) + if (hl == NULL) return (ARCHIVE_FATAL); - if (archive_entry_copy_symlink_l(entry, (const char *)h, + if (archive_entry_copy_symlink_l(entry, (const char *)hl, (size_t)cpio->entry_bytes_remaining, sconv) != 0) { if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, @@ -434,7 +434,8 @@ archive_read_format_cpio_read_header(struct archive_read *a, * header. XXX */ /* Compare name to "TRAILER!!!" to test for end-of-archive. */ - if (namelength == 11 && strcmp((const char *)h, "TRAILER!!!") == 0) { + if (namelength == 11 && strncmp((const char *)h, "TRAILER!!!", + 11) == 0) { /* TODO: Store file location of start of block. */ archive_clear_error(&a->archive); return (ARCHIVE_EOF); @@ -814,8 +815,8 @@ header_odc(struct archive_read *a, struct cpio *cpio, * NOTE: if a filename suffix is ".z", it is the file gziped by afio. * it would be nice that we can show uncompressed file size and we can * uncompressed file contents automatically, unfortunately we have nothing - * to get a uncompressed file size while reading each header. it means - * we also cannot uncompressed file contens under the our framework. + * to get a uncompressed file size while reading each header. It means + * we also cannot uncompress file contents under our framework. */ static int header_afiol(struct archive_read *a, struct cpio *cpio, diff --git a/libarchive/archive_read_support_format_iso9660.c b/libarchive/archive_read_support_format_iso9660.c index f41ba38..76da406 100644 --- a/libarchive/archive_read_support_format_iso9660.c +++ b/libarchive/archive_read_support_format_iso9660.c @@ -322,7 +322,7 @@ struct iso9660 { struct archive_string pathname; char seenRockridge; /* Set true if RR extensions are used. */ - char seenSUSP; /* Set true if SUSP is beging used. */ + char seenSUSP; /* Set true if SUSP is being used. */ char seenJoliet; unsigned char suspOffset; @@ -374,7 +374,7 @@ struct iso9660 { size_t utf16be_path_len; unsigned char *utf16be_previous_path; size_t utf16be_previous_path_len; - /* Null buufer used in bidder to improve its performance. */ + /* Null buffer used in bidder to improve its performance. */ unsigned char null[2048]; }; @@ -1199,7 +1199,7 @@ archive_read_format_iso9660_read_header(struct archive_read *a, archive_string_conversion_from_charset( &(a->archive), "UTF-16BE", 1); if (iso9660->sconv_utf16be == NULL) - /* Coundn't allocate memory */ + /* Couldn't allocate memory */ return (ARCHIVE_FATAL); } if (iso9660->utf16be_path == NULL) { @@ -1864,7 +1864,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent, if ((file->utf16be_name = malloc(name_len)) == NULL) { archive_set_error(&a->archive, ENOMEM, "No memory for file name"); - return (NULL); + goto fail; } memcpy(file->utf16be_name, p, name_len); file->utf16be_bytes = name_len; @@ -1943,10 +1943,8 @@ parse_file_info(struct archive_read *a, struct file_info *parent, file->symlink_continues = 0; rr_start += iso9660->suspOffset; r = parse_rockridge(a, file, rr_start, rr_end); - if (r != ARCHIVE_OK) { - free(file); - return (NULL); - } + if (r != ARCHIVE_OK) + goto fail; /* * A file size of symbolic link files in ISO images * made by makefs is not zero and its location is @@ -1990,7 +1988,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Invalid Rockridge RE"); - return (NULL); + goto fail; } /* * Sanity check: file does not have "CL" extension. @@ -1999,7 +1997,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Invalid Rockridge RE and CL"); - return (NULL); + goto fail; } /* * Sanity check: The file type must be a directory. @@ -2008,7 +2006,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Invalid Rockridge RE"); - return (NULL); + goto fail; } } else if (parent != NULL && parent->rr_moved) file->rr_moved_has_re_only = 0; @@ -2022,7 +2020,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Invalid Rockridge CL"); - return (NULL); + goto fail; } /* * Sanity check: The file type must be a regular file. @@ -2031,7 +2029,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Invalid Rockridge CL"); - return (NULL); + goto fail; } parent->subdirs++; /* Overwrite an offset and a number of this "CL" entry @@ -2049,7 +2047,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Invalid Rockridge CL"); - return (NULL); + goto fail; } } if (file->cl_offset == file->offset || @@ -2057,7 +2055,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent, archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Invalid Rockridge CL"); - return (NULL); + goto fail; } } } @@ -2088,6 +2086,10 @@ parse_file_info(struct archive_read *a, struct file_info *parent, #endif register_file(iso9660, file); return (file); +fail: + archive_string_free(&file->name); + free(file); + return (NULL); } static int @@ -2407,7 +2409,7 @@ read_CE(struct archive_read *a, struct iso9660 *iso9660) return (ARCHIVE_FATAL); } while (heap->cnt && heap->reqs[0].offset == iso9660->current_position); - /* NOTE: Do not move this consume's code to fron of + /* NOTE: Do not move this consume's code to front of * do-while loop. Registration of nested CE extension * might cause error because of current position. */ __archive_read_consume(a, step); @@ -2729,7 +2731,7 @@ next_cache_entry(struct archive_read *a, struct iso9660 *iso9660, if (file == NULL) { /* * If directory entries all which are descendant of - * rr_moved are stil remaning, expose their. + * rr_moved are still remaining, expose their. */ if (iso9660->re_files.first != NULL && iso9660->rr_moved != NULL && @@ -2852,7 +2854,7 @@ next_cache_entry(struct archive_read *a, struct iso9660 *iso9660, empty_files.last = &empty_files.first; /* Collect files which has the same file serial number. * Peek pending_files so that file which number is different - * is not put bak. */ + * is not put back. */ while (iso9660->pending_files.used > 0 && (iso9660->pending_files.files[0]->number == -1 || iso9660->pending_files.files[0]->number == number)) { @@ -2860,7 +2862,7 @@ next_cache_entry(struct archive_read *a, struct iso9660 *iso9660, /* This file has the same offset * but it's wrong offset which empty files * and symlink files have. - * NOTE: This wrong offse was recorded by + * NOTE: This wrong offset was recorded by * old mkisofs utility. If ISO images is * created by latest mkisofs, this does not * happen. diff --git a/libarchive/archive_read_support_format_lha.c b/libarchive/archive_read_support_format_lha.c index c359d83..d77a7c2 100644 --- a/libarchive/archive_read_support_format_lha.c +++ b/libarchive/archive_read_support_format_lha.c @@ -924,6 +924,9 @@ lha_read_file_header_1(struct archive_read *a, struct lha *lha) /* Get a real compressed file size. */ lha->compsize -= extdsize - 2; + if (lha->compsize < 0) + goto invalid; /* Invalid compressed file size */ + if (sum_calculated != headersum) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "LHa header sum error"); @@ -1711,11 +1714,15 @@ lha_crc16(uint16_t crc, const void *pp, size_t len) */ for (;len >= 8; len -= 8) { /* This if statement expects compiler optimization will - * remove the stament which will not be executed. */ + * remove the statement which will not be executed. */ +#undef bswap16 #if defined(_MSC_VER) && _MSC_VER >= 1400 /* Visual Studio */ # define bswap16(x) _byteswap_ushort(x) -#elif (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8) \ - || defined(__clang__) +#elif defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || __GNUC__ > 4) +/* GCC 4.8 and later has __builtin_bswap16() */ +# define bswap16(x) __builtin_bswap16(x) +#elif defined(__clang__) +/* All clang versions have __builtin_bswap16() */ # define bswap16(x) __builtin_bswap16(x) #else # define bswap16(x) ((((x) >> 8) & 0xff) | ((x) << 8)) diff --git a/libarchive/archive_read_support_format_mtree.c b/libarchive/archive_read_support_format_mtree.c index 8c3be9a..4231ff5 100644 --- a/libarchive/archive_read_support_format_mtree.c +++ b/libarchive/archive_read_support_format_mtree.c @@ -75,6 +75,8 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_mtree.c 2011 #define MTREE_HAS_OPTIONAL 0x0800 #define MTREE_HAS_NOCHANGE 0x1000 /* FreeBSD specific */ +#define MTREE_HASHTABLE_SIZE 1024 + struct mtree_option { struct mtree_option *next; char *value; @@ -86,6 +88,8 @@ struct mtree_entry { char *name; char full; char used; + unsigned int name_hash; + struct mtree_entry *hashtable_next; }; struct mtree { @@ -98,6 +102,7 @@ struct mtree { const char *archive_format_name; struct mtree_entry *entries; struct mtree_entry *this_entry; + struct mtree_entry *entry_hashtable[MTREE_HASHTABLE_SIZE]; struct archive_string current_dir; struct archive_string contents_name; @@ -110,6 +115,7 @@ struct mtree { static int bid_keycmp(const char *, const char *, ssize_t); static int cleanup(struct archive_read *); static int detect_form(struct archive_read *, int *); +static unsigned int hash(const char *); static int mtree_bid(struct archive_read *, int); static int parse_file(struct archive_read *, struct archive_entry *, struct mtree *, struct mtree_entry *, int *); @@ -223,13 +229,12 @@ archive_read_support_format_mtree(struct archive *_a) archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, "archive_read_support_format_mtree"); - mtree = (struct mtree *)malloc(sizeof(*mtree)); + mtree = (struct mtree *)calloc(1, sizeof(*mtree)); if (mtree == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate mtree data"); return (ARCHIVE_FATAL); } - memset(mtree, 0, sizeof(*mtree)); mtree->fd = -1; r = __archive_read_register_format(a, mtree, "mtree", @@ -301,6 +306,15 @@ get_line_size(const char *b, ssize_t avail, ssize_t *nlsize) return (avail); } +/* + * <---------------- ravail ---------------------> + * <-- diff ------> <--- avail -----------------> + * <---- len -----------> + * | Previous lines | line being parsed nl extra | + * ^ + * b + * + */ static ssize_t next_line(struct archive_read *a, const char **b, ssize_t *avail, ssize_t *ravail, ssize_t *nl) @@ -339,7 +353,7 @@ next_line(struct archive_read *a, *b += diff; *avail -= diff; tested = len;/* Skip some bytes we already determinated. */ - len = get_line_size(*b, *avail, nl); + len = get_line_size(*b + len, *avail - len, nl); if (len >= 0) len += tested; } @@ -701,13 +715,13 @@ detect_form(struct archive_read *a, int *is_form_d) } } else break; - } else if (strncmp(p, "/set", 4) == 0) { + } else if (len > 4 && strncmp(p, "/set", 4) == 0) { if (bid_keyword_list(p+4, len-4, 0, 0) <= 0) break; /* This line continues. */ if (p[len-nl-1] == '\\') multiline = 2; - } else if (strncmp(p, "/unset", 6) == 0) { + } else if (len > 6 && strncmp(p, "/unset", 6) == 0) { if (bid_keyword_list(p+6, len-6, 1, 0) <= 0) break; /* This line continues. */ @@ -853,11 +867,12 @@ process_add_entry(struct archive_read *a, struct mtree *mtree, struct mtree_option **global, const char *line, ssize_t line_len, struct mtree_entry **last_entry, int is_form_d) { - struct mtree_entry *entry; + struct mtree_entry *entry, *ht_iter; struct mtree_option *iter; const char *next, *eq, *name, *end; size_t name_len, len; int r, i; + unsigned int ht_idx; if ((entry = malloc(sizeof(*entry))) == NULL) { archive_set_error(&a->archive, errno, "Can't allocate memory"); @@ -868,6 +883,8 @@ process_add_entry(struct archive_read *a, struct mtree *mtree, entry->name = NULL; entry->used = 0; entry->full = 0; + entry->name_hash = 0; + entry->hashtable_next = NULL; /* Add this entry to list. */ if (*last_entry == NULL) @@ -920,6 +937,16 @@ process_add_entry(struct archive_read *a, struct mtree *mtree, memcpy(entry->name, name, name_len); entry->name[name_len] = '\0'; parse_escapes(entry->name, entry); + entry->name_hash = hash(entry->name); + + ht_idx = entry->name_hash % MTREE_HASHTABLE_SIZE; + if ((ht_iter = mtree->entry_hashtable[ht_idx]) != NULL) { + while (ht_iter->hashtable_next) + ht_iter = ht_iter->hashtable_next; + ht_iter->hashtable_next = entry; + } else { + mtree->entry_hashtable[ht_idx] = entry; + } for (iter = *global; iter != NULL; iter = iter->next) { r = add_option(a, &entry->options, iter->value, @@ -992,11 +1019,11 @@ read_mtree(struct archive_read *a, struct mtree *mtree) if (*p != '/') { r = process_add_entry(a, mtree, &global, p, len, &last_entry, is_form_d); - } else if (strncmp(p, "/set", 4) == 0) { + } else if (len > 4 && strncmp(p, "/set", 4) == 0) { if (p[4] != ' ' && p[4] != '\t') break; r = process_global_set(a, &global, p); - } else if (strncmp(p, "/unset", 6) == 0) { + } else if (len > 6 && strncmp(p, "/unset", 6) == 0) { if (p[6] != ' ' && p[6] != '\t') break; r = process_global_unset(a, &global, p); @@ -1113,9 +1140,10 @@ parse_file(struct archive_read *a, struct archive_entry *entry, * with pathname canonicalization, which is a very * tricky subject.) */ - for (mp = mentry->next; mp != NULL; mp = mp->next) { + for (mp = mentry->hashtable_next; mp != NULL; mp = mp->hashtable_next) { if (mp->full && !mp->used - && strcmp(mentry->name, mp->name) == 0) { + && mentry->name_hash == mp->name_hash + && strcmp(mentry->name, mp->name) == 0) { /* Later lines override earlier ones. */ mp->used = 1; r1 = parse_line(a, entry, mtree, mp, @@ -1580,8 +1608,11 @@ parse_keyword(struct archive_read *a, struct mtree *mtree, if (*val == '.') { ++val; ns = (long)mtree_atol10(&val); - } else - ns = 0; + if (ns < 0) + ns = 0; + else if (ns > 999999999) + ns = 999999999; + } if (m > my_time_t_max) m = my_time_t_max; else if (m < my_time_t_min) @@ -1991,3 +2022,19 @@ readline(struct archive_read *a, struct mtree *mtree, char **start, find_off = u - mtree->line.s; } } + +static unsigned int +hash(const char *p) +{ + /* A 32-bit version of Peter Weinberger's (PJW) hash algorithm, + as used by ELF for hashing function names. */ + unsigned g, h = 0; + while (*p != '\0') { + h = (h << 4) + *p++; + if ((g = h & 0xF0000000) != 0) { + h ^= g >> 24; + h &= 0x0FFFFFFF; + } + } + return h; +} diff --git a/libarchive/archive_read_support_format_rar.c b/libarchive/archive_read_support_format_rar.c index f729f17..1e9849f 100644 --- a/libarchive/archive_read_support_format_rar.c +++ b/libarchive/archive_read_support_format_rar.c @@ -647,13 +647,12 @@ archive_read_support_format_rar(struct archive *_a) archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, "archive_read_support_format_rar"); - rar = (struct rar *)malloc(sizeof(*rar)); + rar = (struct rar *)calloc(sizeof(*rar), 1); if (rar == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate rar data"); return (ARCHIVE_FATAL); } - memset(rar, 0, sizeof(*rar)); /* * Until enough data has been read, we cannot tell about @@ -907,7 +906,7 @@ archive_read_format_rar_read_header(struct archive_read *a, sizeof(rar->reserved2)); } - /* Main header is password encrytped, so we cannot read any + /* Main header is password encrypted, so we cannot read any file names or any other info about files from the header. */ if (rar->main_flags & MHD_PASSWORD) { diff --git a/libarchive/archive_read_support_format_tar.c b/libarchive/archive_read_support_format_tar.c index b0521a6..bd7f13d 100644 --- a/libarchive/archive_read_support_format_tar.c +++ b/libarchive/archive_read_support_format_tar.c @@ -1,6 +1,7 @@ /*- * Copyright (c) 2003-2007 Tim Kientzle * Copyright (c) 2011-2012 Michihiro NAKAJIMA + * Copyright (c) 2016 Martin Matuska * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -136,6 +137,7 @@ struct tar { int64_t entry_padding; int64_t entry_bytes_unconsumed; int64_t realsize; + int sparse_allowed; struct sparse_block *sparse_list; struct sparse_block *sparse_last; int64_t sparse_offset; @@ -202,9 +204,14 @@ static int archive_read_format_tar_read_header(struct archive_read *, struct archive_entry *); static int checksum(struct archive_read *, const void *); static int pax_attribute(struct archive_read *, struct tar *, - struct archive_entry *, const char *key, const char *value); + struct archive_entry *, const char *key, const char *value, + size_t value_length); +static int pax_attribute_acl(struct archive_read *, struct tar *, + struct archive_entry *, const char *, int); +static int pax_attribute_xattr(struct archive_entry *, const char *, + const char *); static int pax_header(struct archive_read *, struct tar *, - struct archive_entry *, char *attr); + struct archive_entry *, struct archive_string *); static void pax_time(const char *, int64_t *sec, long *nanos); static ssize_t readline(struct archive_read *, struct tar *, const char **, ssize_t limit, size_t *); @@ -293,6 +300,57 @@ archive_read_format_tar_cleanup(struct archive_read *a) return (ARCHIVE_OK); } +/* + * Validate number field + * + * This has to be pretty lenient in order to accommodate the enormous + * variety of tar writers in the world: + * = POSIX (IEEE Std 1003.1-1988) ustar requires octal values with leading + * zeros and allows fields to be terminated with space or null characters + * = Many writers use different termination (in particular, libarchive + * omits terminator bytes to squeeze one or two more digits) + * = Many writers pad with space and omit leading zeros + * = GNU tar and star write base-256 values if numbers are too + * big to be represented in octal + * + * Examples of specific tar headers that we should support: + * = Perl Archive::Tar terminates uid, gid, devminor and devmajor with two + * null bytes, pads size with spaces and other numeric fields with zeroes + * = plexus-archiver prior to 2.6.3 (before switching to commons-compress) + * may have uid and gid fields filled with spaces without any octal digits + * at all and pads all numeric fields with spaces + * + * This should tolerate all variants in use. It will reject a field + * where the writer just left garbage after a trailing NUL. + */ +static int +validate_number_field(const char* p_field, size_t i_size) +{ + unsigned char marker = (unsigned char)p_field[0]; + if (marker == 128 || marker == 255 || marker == 0) { + /* Base-256 marker, there's nothing we can check. */ + return 1; + } else { + /* Must be octal */ + size_t i = 0; + /* Skip any leading spaces */ + while (i < i_size && p_field[i] == ' ') { + ++i; + } + /* Skip octal digits. */ + while (i < i_size && p_field[i] >= '0' && p_field[i] <= '7') { + ++i; + } + /* Any remaining characters must be space or NUL padding. */ + while (i < i_size) { + if (p_field[i] != ' ' && p_field[i] != 0) { + return 0; + } + ++i; + } + return 1; + } +} static int archive_read_format_tar_bid(struct archive_read *a, int best_bid) @@ -345,23 +403,19 @@ archive_read_format_tar_bid(struct archive_read *a, int best_bid) return (0); bid += 2; /* 6 bits of variation in an 8-bit field leaves 2 bits. */ - /* Sanity check: Look at first byte of mode field. */ - switch (255 & (unsigned)header->mode[0]) { - case 0: case 255: - /* Base-256 value: No further verification possible! */ - break; - case ' ': /* Not recommended, but not illegal, either. */ - break; - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - /* Octal Value. */ - /* TODO: Check format of remainder of this field. */ - break; - default: - /* Not a valid mode; bail out here. */ - return (0); + /* + * Check format of mode/uid/gid/mtime/size/rdevmajor/rdevminor fields. + */ + if (bid > 0 && ( + validate_number_field(header->mode, sizeof(header->mode)) == 0 + || validate_number_field(header->uid, sizeof(header->uid)) == 0 + || validate_number_field(header->gid, sizeof(header->gid)) == 0 + || validate_number_field(header->mtime, sizeof(header->mtime)) == 0 + || validate_number_field(header->size, sizeof(header->size)) == 0 + || validate_number_field(header->rdevmajor, sizeof(header->rdevmajor)) == 0 + || validate_number_field(header->rdevminor, sizeof(header->rdevminor)) == 0)) { + bid = 0; } - /* TODO: Sanity test uid/gid/size/mtime/rdevmajor/rdevminor fields. */ return (bid); } @@ -375,7 +429,7 @@ archive_read_format_tar_options(struct archive_read *a, tar = (struct tar *)(a->format->data); if (strcmp(key, "compat-2x") == 0) { - /* Handle UTF-8 filnames as libarchive 2.x */ + /* Handle UTF-8 filenames as libarchive 2.x */ tar->compat_2x = (val != NULL && val[0] != 0); tar->init_default_conversion = tar->compat_2x; return (ARCHIVE_OK); @@ -793,9 +847,9 @@ tar_read_header(struct archive_read *a, struct tar *tar, tar->sparse_gnu_pending = 0; /* Read initial sparse map. */ bytes_read = gnu_sparse_10_read(a, tar, unconsumed); - tar->entry_bytes_remaining -= bytes_read; if (bytes_read < 0) return ((int)bytes_read); + tar->entry_bytes_remaining -= bytes_read; } else { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, @@ -890,7 +944,7 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar, { const struct archive_entry_header_ustar *header; size_t size; - int err; + int err, acl_type; int64_t type; char *acl, *p; @@ -935,11 +989,12 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar, switch ((int)type & ~0777777) { case 01000000: /* POSIX.1e ACL */ + acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS; break; case 03000000: - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Solaris NFSv4 ACLs not supported"); - return (ARCHIVE_WARN); + /* NFSv4 ACL */ + acl_type = ARCHIVE_ENTRY_ACL_TYPE_NFS4; + break; default: archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Malformed Solaris ACL attribute (unsupported type %o)", @@ -968,8 +1023,8 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar, return (ARCHIVE_FATAL); } archive_strncpy(&(tar->localname), acl, p - acl); - err = archive_acl_parse_l(archive_entry_acl(entry), - tar->localname.s, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, tar->sconv_acl); + err = archive_acl_from_text_l(archive_entry_acl(entry), + tar->localname.s, acl_type, tar->sconv_acl); if (err != ARCHIVE_OK) { if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, @@ -1128,8 +1183,15 @@ header_common(struct archive_read *a, struct tar *tar, if (tar->entry_bytes_remaining < 0) { tar->entry_bytes_remaining = 0; archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Tar entry has negative size?"); - err = ARCHIVE_WARN; + "Tar entry has negative size"); + return (ARCHIVE_FATAL); + } + if (tar->entry_bytes_remaining == INT64_MAX) { + /* Note: tar_atol returns INT64_MAX on overflow */ + tar->entry_bytes_remaining = 0; + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Tar entry size overflow"); + return (ARCHIVE_FATAL); } tar->realsize = tar->entry_bytes_remaining; archive_entry_set_size(entry, tar->entry_bytes_remaining); @@ -1264,6 +1326,14 @@ header_common(struct archive_read *a, struct tar *tar, * sparse information in the extended area. */ /* FALLTHROUGH */ + case '0': + /* + * Enable sparse file "read" support only for regular + * files and explicit GNU sparse files. However, we + * don't allow non-standard file types to be sparse. + */ + tar->sparse_allowed = 1; + /* FALLTHROUGH */ default: /* Regular file and non-standard types */ /* * Per POSIX: non-recognized types should always be @@ -1415,7 +1485,7 @@ header_pax_extensions(struct archive_read *a, struct tar *tar, * and then skip any fields in the standard header that were * defined in the pax header. */ - err2 = pax_header(a, tar, entry, tar->pax_header.s); + err2 = pax_header(a, tar, entry, &tar->pax_header); err = err_combine(err, err2); tar->entry_padding = 0x1ff & (-tar->entry_bytes_remaining); return (err); @@ -1496,16 +1566,17 @@ header_ustar(struct archive_read *a, struct tar *tar, */ static int pax_header(struct archive_read *a, struct tar *tar, - struct archive_entry *entry, char *attr) + struct archive_entry *entry, struct archive_string *in_as) { - size_t attr_length, l, line_length; + size_t attr_length, l, line_length, value_length; char *p; char *key, *value; struct archive_string *as; struct archive_string_conv *sconv; int err, err2; + char *attr = in_as->s; - attr_length = strlen(attr); + attr_length = in_as->length; tar->pax_hdrcharset_binary = 0; archive_string_empty(&(tar->entry_gname)); archive_string_empty(&(tar->entry_linkpath)); @@ -1570,11 +1641,13 @@ pax_header(struct archive_read *a, struct tar *tar, } *p = '\0'; - /* Identify null-terminated 'value' portion. */ value = p + 1; + /* Some values may be binary data */ + value_length = attr + line_length - 1 - value; + /* Identify this attribute and set it in the entry. */ - err2 = pax_attribute(a, tar, entry, key, value); + err2 = pax_attribute(a, tar, entry, key, value, value_length); if (err2 == ARCHIVE_FATAL) return (err2); err = err_combine(err, err2); @@ -1695,6 +1768,66 @@ pax_attribute_xattr(struct archive_entry *entry, return 0; } +static int +pax_attribute_schily_xattr(struct archive_entry *entry, + const char *name, const char *value, size_t value_length) +{ + if (strlen(name) < 14 || (memcmp(name, "SCHILY.xattr.", 13)) != 0) + return 1; + + name += 13; + + archive_entry_xattr_add_entry(entry, name, value, value_length); + + return 0; +} + +static int +pax_attribute_acl(struct archive_read *a, struct tar *tar, + struct archive_entry *entry, const char *value, int type) +{ + int r; + const char* errstr; + + switch (type) { + case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: + errstr = "SCHILY.acl.access"; + break; + case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: + errstr = "SCHILY.acl.default"; + break; + case ARCHIVE_ENTRY_ACL_TYPE_NFS4: + errstr = "SCHILY.acl.ace"; + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Unknown ACL type: %d", type); + return(ARCHIVE_FATAL); + } + + if (tar->sconv_acl == NULL) { + tar->sconv_acl = + archive_string_conversion_from_charset( + &(a->archive), "UTF-8", 1); + if (tar->sconv_acl == NULL) + return (ARCHIVE_FATAL); + } + + r = archive_acl_from_text_l(archive_entry_acl(entry), value, type, + tar->sconv_acl); + if (r != ARCHIVE_OK) { + if (r == ARCHIVE_FATAL) { + archive_set_error(&a->archive, ENOMEM, + "%s %s", "Can't allocate memory for ", + errstr); + return (r); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, "%s %s", "Parse error: ", errstr); + } + return (r); +} + /* * Parse a single key=value attribute. key/value pointers are * assumed to point into reasonably long-lived storage. @@ -1710,7 +1843,7 @@ pax_attribute_xattr(struct archive_entry *entry, */ static int pax_attribute(struct archive_read *a, struct tar *tar, - struct archive_entry *entry, const char *key, const char *value) + struct archive_entry *entry, const char *key, const char *value, size_t value_length) { int64_t s; long n; @@ -1721,6 +1854,14 @@ pax_attribute(struct archive_read *a, struct tar *tar, * NULL pointer to strlen(). */ switch (key[0]) { case 'G': + /* Reject GNU.sparse.* headers on non-regular files. */ + if (strncmp(key, "GNU.sparse", 10) == 0 && + !tar->sparse_allowed) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Non-regular file cannot be sparse"); + return (ARCHIVE_FATAL); + } + /* GNU "0.0" sparse pax format. */ if (strcmp(key, "GNU.sparse.numblocks") == 0) { tar->sparse_offset = -1; @@ -1803,53 +1944,20 @@ pax_attribute(struct archive_read *a, struct tar *tar, case 'S': /* We support some keys used by the "star" archiver */ if (strcmp(key, "SCHILY.acl.access") == 0) { - if (tar->sconv_acl == NULL) { - tar->sconv_acl = - archive_string_conversion_from_charset( - &(a->archive), "UTF-8", 1); - if (tar->sconv_acl == NULL) - return (ARCHIVE_FATAL); - } - - r = archive_acl_parse_l(archive_entry_acl(entry), - value, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, - tar->sconv_acl); - if (r != ARCHIVE_OK) { - err = r; - if (err == ARCHIVE_FATAL) { - archive_set_error(&a->archive, ENOMEM, - "Can't allocate memory for " - "SCHILY.acl.access"); - return (err); - } - archive_set_error(&a->archive, - ARCHIVE_ERRNO_MISC, - "Parse error: SCHILY.acl.access"); - } + r = pax_attribute_acl(a, tar, entry, value, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS); + if (r == ARCHIVE_FATAL) + return (r); } else if (strcmp(key, "SCHILY.acl.default") == 0) { - if (tar->sconv_acl == NULL) { - tar->sconv_acl = - archive_string_conversion_from_charset( - &(a->archive), "UTF-8", 1); - if (tar->sconv_acl == NULL) - return (ARCHIVE_FATAL); - } - - r = archive_acl_parse_l(archive_entry_acl(entry), - value, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, - tar->sconv_acl); - if (r != ARCHIVE_OK) { - err = r; - if (err == ARCHIVE_FATAL) { - archive_set_error(&a->archive, ENOMEM, - "Can't allocate memory for " - "SCHILY.acl.default"); - return (err); - } - archive_set_error(&a->archive, - ARCHIVE_ERRNO_MISC, - "Parse error: SCHILY.acl.default"); - } + r = pax_attribute_acl(a, tar, entry, value, + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT); + if (r == ARCHIVE_FATAL) + return (r); + } else if (strcmp(key, "SCHILY.acl.ace") == 0) { + r = pax_attribute_acl(a, tar, entry, value, + ARCHIVE_ENTRY_ACL_TYPE_NFS4); + if (r == ARCHIVE_FATAL) + return (r); } else if (strcmp(key, "SCHILY.devmajor") == 0) { archive_entry_set_rdevmajor(entry, (dev_t)tar_atol10(value, strlen(value))); @@ -1870,6 +1978,9 @@ pax_attribute(struct archive_read *a, struct tar *tar, } else if (strcmp(key, "SCHILY.realsize") == 0) { tar->realsize = tar_atol10(value, strlen(value)); archive_entry_set_size(entry, tar->realsize); + } else if (strncmp(key, "SCHILY.xattr.", 13) == 0) { + pax_attribute_schily_xattr(entry, key, value, + value_length); } else if (strcmp(key, "SUN.holesdata") == 0) { /* A Solaris extension for sparse. */ r = solaris_sparse_parse(a, tar, entry, value); @@ -2116,12 +2227,11 @@ gnu_add_sparse_entry(struct archive_read *a, struct tar *tar, { struct sparse_block *p; - p = (struct sparse_block *)malloc(sizeof(*p)); + p = (struct sparse_block *)calloc(1, sizeof(*p)); if (p == NULL) { archive_set_error(&a->archive, ENOMEM, "Out of memory"); return (ARCHIVE_FATAL); } - memset(p, 0, sizeof(*p)); if (tar->sparse_last != NULL) tar->sparse_last->next = p; else @@ -2377,6 +2487,9 @@ gnu_sparse_10_read(struct archive_read *a, struct tar *tar, size_t *unconsumed) tar_flush_unconsumed(a, unconsumed); bytes_read = (ssize_t)(tar->entry_bytes_remaining - remaining); to_skip = 0x1ff & -bytes_read; + /* Fail if tar->entry_bytes_remaing would get negative */ + if (to_skip > remaining) + return (ARCHIVE_FATAL); if (to_skip != __archive_read_consume(a, to_skip)) return (ARCHIVE_FATAL); return ((ssize_t)(bytes_read + to_skip)); @@ -2472,7 +2585,7 @@ tar_atol_base_n(const char *p, size_t char_cnt, int base) last_digit_limit = INT64_MAX % base; /* the pointer will not be dereferenced if char_cnt is zero - * due to the way the && operator is evaulated. + * due to the way the && operator is evaluated. */ while (char_cnt != 0 && (*p == ' ' || *p == '\t')) { p++; diff --git a/libarchive/archive_read_support_format_warc.c b/libarchive/archive_read_support_format_warc.c index 46a59ea..5e22438 100644 --- a/libarchive/archive_read_support_format_warc.c +++ b/libarchive/archive_read_support_format_warc.c @@ -88,7 +88,7 @@ typedef enum { WT_RVIS, /* conversion, unsupported */ WT_CONV, - /* continutation, unsupported at the moment */ + /* continuation, unsupported at the moment */ WT_CONT, /* invalid type */ LAST_WT @@ -134,8 +134,8 @@ static ssize_t _warc_rdlen(const char *buf, size_t bsz); static time_t _warc_rdrtm(const char *buf, size_t bsz); static time_t _warc_rdmtm(const char *buf, size_t bsz); static const char *_warc_find_eoh(const char *buf, size_t bsz); +static const char *_warc_find_eol(const char *buf, size_t bsz); - int archive_read_support_format_warc(struct archive *_a) { @@ -146,12 +146,11 @@ archive_read_support_format_warc(struct archive *_a) archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, "archive_read_support_format_warc"); - if ((w = malloc(sizeof(*w))) == NULL) { + if ((w = calloc(1, sizeof(*w))) == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate warc data"); return (ARCHIVE_FATAL); } - memset(w, 0, sizeof(*w)); r = __archive_read_register_format( a, w, "warc", @@ -199,8 +198,8 @@ _warc_bid(struct archive_read *a, int best_bid) /* otherwise snarf the record's version number */ ver = _warc_rdver(hdr, nrd); - if (ver == 0U || ver > 10000U) { - /* oh oh oh, best not to wager ... */ + if (ver < 1200U || ver > 10000U) { + /* we only support WARC 0.12 to 1.0 */ return -1; } @@ -255,23 +254,32 @@ start_over: &a->archive, ARCHIVE_ERRNO_MISC, "Bad record header"); return (ARCHIVE_FATAL); - } else if ((ver = _warc_rdver(buf, eoh - buf)) > 10000U) { - /* nawww, I wish they promised backward compatibility - * anyhoo, in their infinite wisdom the 28500 guys might - * come up with something we can't possibly handle so - * best end things here */ + } + ver = _warc_rdver(buf, eoh - buf); + /* we currently support WARC 0.12 to 1.0 */ + if (ver == 0U) { archive_set_error( &a->archive, ARCHIVE_ERRNO_MISC, - "Unsupported record version"); + "Invalid record version"); return (ARCHIVE_FATAL); - } else if ((cntlen = _warc_rdlen(buf, eoh - buf)) < 0) { + } else if (ver < 1200U || ver > 10000U) { + archive_set_error( + &a->archive, ARCHIVE_ERRNO_MISC, + "Unsupported record version: %u.%u", + ver / 10000, (ver % 10000) / 100); + return (ARCHIVE_FATAL); + } + cntlen = _warc_rdlen(buf, eoh - buf); + if (cntlen < 0) { /* nightmare! the specs say content-length is mandatory * so I don't feel overly bad stopping the reader here */ archive_set_error( &a->archive, EINVAL, "Bad content length"); return (ARCHIVE_FATAL); - } else if ((rtime = _warc_rdrtm(buf, eoh - buf)) == (time_t)-1) { + } + rtime = _warc_rdrtm(buf, eoh - buf); + if (rtime == (time_t)-1) { /* record time is mandatory as per WARC/1.0, * so just barf here, fast and loud */ archive_set_error( @@ -285,7 +293,7 @@ start_over: if (ver != w->pver) { /* stringify this entry's version */ archive_string_sprintf(&w->sver, - "WARC/%u.%u", ver / 10000, ver % 10000); + "WARC/%u.%u", ver / 10000, (ver % 10000) / 100); /* remember the version */ w->pver = ver; } @@ -318,7 +326,7 @@ start_over: } memcpy(w->pool.str, fnam.str, fnam.len); w->pool.str[fnam.len] = '\0'; - /* let noone else know about the pool, it's a secret, shhh */ + /* let no one else know about the pool, it's a secret, shhh */ fnam.str = w->pool.str; /* snarf mtime or deduce from rtime @@ -535,7 +543,8 @@ xstrpisotime(const char *s, char **endptr) /* as a courtesy to our callers, and since this is a non-standard * routine, we skip leading whitespace */ - for (; isspace(*s); s++); + while (isblank((unsigned char)*s)) + ++s; /* read year */ if ((tm.tm_year = strtoi_lim(s, &s, 1583, 4095)) < 0 || *s++ != '-') { @@ -562,7 +571,7 @@ xstrpisotime(const char *s, char **endptr) goto out; } - /* massage TM to fulfill some of POSIX' contraints */ + /* massage TM to fulfill some of POSIX' constraints */ tm.tm_year -= 1900; tm.tm_mon--; @@ -577,51 +586,41 @@ out: } static unsigned int -_warc_rdver(const char buf[10], size_t bsz) +_warc_rdver(const char *buf, size_t bsz) { static const char magic[] = "WARC/"; - unsigned int ver; - - (void)bsz; /* UNUSED */ + unsigned int ver = 0U; + unsigned int end = 0U; - if (memcmp(buf, magic, sizeof(magic) - 1U) != 0) { - /* nope */ - return 99999U; + if (bsz < 12 || memcmp(buf, magic, sizeof(magic) - 1U) != 0) { + /* buffer too small or invalid magic */ + return ver; } /* looks good so far, read the version number for a laugh */ buf += sizeof(magic) - 1U; - /* most common case gets a quick-check here */ - if (memcmp(buf, "1.0\r\n", 5U) == 0) { - ver = 10000U; - } else { - switch (*buf) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - if (buf[1U] == '.') { - char *on; - - /* set up major version */ - ver = (buf[0U] - '0') * 10000U; - /* minor version, anyone? */ - ver += (strtol(buf + 2U, &on, 10)) * 100U; - /* don't parse anything else */ - if (on > buf + 2U) { - break; - } - } - /* FALLTHROUGH */ - case '9': - default: - /* just make the version ridiculously high */ - ver = 999999U; - break; + + if (isdigit(buf[0U]) && (buf[1U] == '.') && isdigit(buf[2U])) { + /* we support a maximum of 2 digits in the minor version */ + if (isdigit(buf[3U])) + end = 1U; + /* set up major version */ + ver = (buf[0U] - '0') * 10000U; + /* set up minor version */ + if (end == 1U) { + ver += (buf[2U] - '0') * 1000U; + ver += (buf[3U] - '0') * 100U; + } else + ver += (buf[2U] - '0') * 100U; + /* + * WARC below version 0.12 has a space-separated header + * WARC 0.12 and above terminates the version with a CRLF + */ + if (ver >= 1200U) { + if (memcmp(buf + 3U + end, "\r\n", 2U) != 0) + ver = 0U; + } else if (ver < 1200U) { + if (!isblank(*(buf + 3U + end))) + ver = 0U; } } return ver; @@ -631,32 +630,27 @@ static unsigned int _warc_rdtyp(const char *buf, size_t bsz) { static const char _key[] = "\r\nWARC-Type:"; - const char *const eob = buf + bsz; - const char *val; + const char *val, *eol; if ((val = xmemmem(buf, bsz, _key, sizeof(_key) - 1U)) == NULL) { /* no bother */ return WT_NONE; } + val += sizeof(_key) - 1U; + if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL) { + /* no end of line */ + return WT_NONE; + } + /* overread whitespace */ - for (val += sizeof(_key) - 1U; val < eob && isspace(*val); val++); - - if (val + 8U > eob) { - ; - } else if (memcmp(val, "resource", 8U) == 0) { - return WT_RSRC; - } else if (memcmp(val, "warcinfo", 8U) == 0) { - return WT_INFO; - } else if (memcmp(val, "metadata", 8U) == 0) { - return WT_META; - } else if (memcmp(val, "request", 7U) == 0) { - return WT_REQ; - } else if (memcmp(val, "response", 8U) == 0) { - return WT_RSP; - } else if (memcmp(val, "conversi", 8U) == 0) { - return WT_CONV; - } else if (memcmp(val, "continua", 8U) == 0) { - return WT_CONT; + while (val < eol && isblank((unsigned char)*val)) + ++val; + + if (val + 8U == eol) { + if (memcmp(val, "resource", 8U) == 0) + return WT_RSRC; + else if (memcmp(val, "response", 8U) == 0) + return WT_RSP; } return WT_NONE; } @@ -665,10 +659,7 @@ static warc_string_t _warc_rduri(const char *buf, size_t bsz) { static const char _key[] = "\r\nWARC-Target-URI:"; - const char *const eob = buf + bsz; - const char *val; - const char *uri; - const char *eol; + const char *val, *uri, *eol, *p; warc_string_t res = {0U, NULL}; if ((val = xmemmem(buf, bsz, _key, sizeof(_key) - 1U)) == NULL) { @@ -676,23 +667,33 @@ _warc_rduri(const char *buf, size_t bsz) return res; } /* overread whitespace */ - for (val += sizeof(_key) - 1U; val < eob && isspace(*val); val++); + val += sizeof(_key) - 1U; + if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL) { + /* no end of line */ + return res; + } + + while (val < eol && isblank((unsigned char)*val)) + ++val; /* overread URL designators */ - if ((uri = xmemmem(val, eob - val, "://", 3U)) == NULL) { + if ((uri = xmemmem(val, eol - val, "://", 3U)) == NULL) { /* not touching that! */ return res; - } else if ((eol = memchr(uri, '\n', eob - uri)) == NULL) { - /* no end of line? :O */ - return res; } - /* massage uri to point to after :// */ + /* spaces inside uri are not allowed, CRLF should follow */ + for (p = val; p < eol; p++) { + if (isspace(*p)) + return res; + } + + /* there must be at least space for ftp */ + if (uri < (val + 3U)) + return res; + + /* move uri to point to after :// */ uri += 3U; - /* also massage eol to point to the first whitespace - * after the last non-whitespace character before - * the end of the line */ - for (; eol > uri && isspace(eol[-1]); eol--); /* now then, inspect the URI */ if (memcmp(val, "file", 4U) == 0) { @@ -715,7 +716,7 @@ static ssize_t _warc_rdlen(const char *buf, size_t bsz) { static const char _key[] = "\r\nContent-Length:"; - const char *val; + const char *val, *eol; char *on = NULL; long int len; @@ -723,14 +724,24 @@ _warc_rdlen(const char *buf, size_t bsz) /* no bother */ return -1; } - - /* strtol kindly overreads whitespace for us, so use that */ val += sizeof(_key) - 1U; + if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL) { + /* no end of line */ + return -1; + } + + /* skip leading whitespace */ + while (val < eol && isblank(*val)) + val++; + /* there must be at least one digit */ + if (!isdigit(*val)) + return -1; len = strtol(val, &on, 10); - if (on == NULL || !isspace(*on)) { - /* hm, can we trust that number? Best not. */ + if (on != eol) { + /* line must end here */ return -1; } + return (size_t)len; } @@ -738,7 +749,7 @@ static time_t _warc_rdrtm(const char *buf, size_t bsz) { static const char _key[] = "\r\nWARC-Date:"; - const char *val; + const char *val, *eol; char *on = NULL; time_t res; @@ -746,13 +757,17 @@ _warc_rdrtm(const char *buf, size_t bsz) /* no bother */ return (time_t)-1; } + val += sizeof(_key) - 1U; + if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL ) { + /* no end of line */ + return -1; + } /* xstrpisotime() kindly overreads whitespace for us, so use that */ - val += sizeof(_key) - 1U; res = xstrpisotime(val, &on); - if (on == NULL || !isspace(*on)) { - /* hm, can we trust that number? Best not. */ - return (time_t)-1; + if (on != eol) { + /* line must end here */ + return -1; } return res; } @@ -761,7 +776,7 @@ static time_t _warc_rdmtm(const char *buf, size_t bsz) { static const char _key[] = "\r\nLast-Modified:"; - const char *val; + const char *val, *eol; char *on = NULL; time_t res; @@ -769,13 +784,17 @@ _warc_rdmtm(const char *buf, size_t bsz) /* no bother */ return (time_t)-1; } + val += sizeof(_key) - 1U; + if ((eol = _warc_find_eol(val, buf + bsz - val)) == NULL ) { + /* no end of line */ + return -1; + } /* xstrpisotime() kindly overreads whitespace for us, so use that */ - val += sizeof(_key) - 1U; res = xstrpisotime(val, &on); - if (on == NULL || !isspace(*on)) { - /* hm, can we trust that number? Best not. */ - return (time_t)-1; + if (on != eol) { + /* line must end here */ + return -1; } return res; } @@ -792,4 +811,12 @@ _warc_find_eoh(const char *buf, size_t bsz) return hit; } +static const char* +_warc_find_eol(const char *buf, size_t bsz) +{ + static const char _marker[] = "\r\n"; + const char *hit = xmemmem(buf, bsz, _marker, sizeof(_marker) - 1U); + + return hit; +} /* archive_read_support_format_warc.c ends here */ diff --git a/libarchive/archive_read_support_format_xar.c b/libarchive/archive_read_support_format_xar.c index ab88750..7a22beb 100644 --- a/libarchive/archive_read_support_format_xar.c +++ b/libarchive/archive_read_support_format_xar.c @@ -43,8 +43,6 @@ __FBSDID("$FreeBSD$"); #endif #if HAVE_LZMA_H #include -#elif HAVE_LZMADEC_H -#include #endif #ifdef HAVE_ZLIB_H #include @@ -334,9 +332,6 @@ struct xar { #if HAVE_LZMA_H && HAVE_LIBLZMA lzma_stream lzstream; int lzstream_valid; -#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC - lzmadec_stream lzstream; - int lzstream_valid; #endif /* * For Checksum data. @@ -399,6 +394,7 @@ static void checksum_update(struct archive_read *, const void *, size_t, const void *, size_t); static int checksum_final(struct archive_read *, const void *, size_t, const void *, size_t); +static void checksum_cleanup(struct archive_read *); static int decompression_init(struct archive_read *, enum enctype); static int decompress(struct archive_read *, const void **, size_t *, const void *, size_t *); @@ -928,6 +924,7 @@ xar_cleanup(struct archive_read *a) int r; xar = (struct xar *)(a->format->data); + checksum_cleanup(a); r = decompression_cleanup(a); hdlink = xar->hdlink_list; while (hdlink != NULL) { @@ -938,6 +935,7 @@ xar_cleanup(struct archive_read *a) } for (i = 0; i < xar->file_queue.used; i++) file_free(xar->file_queue.files[i]); + free(xar->file_queue.files); while (xar->unknowntags != NULL) { struct unknown_tag *tag; @@ -1526,34 +1524,6 @@ decompression_init(struct archive_read *a, enum enctype encoding) xar->lzstream.total_in = 0; xar->lzstream.total_out = 0; break; -#elif defined(HAVE_LZMADEC_H) && defined(HAVE_LIBLZMADEC) - case LZMA: - if (xar->lzstream_valid) - lzmadec_end(&(xar->lzstream)); - r = lzmadec_init(&(xar->lzstream)); - if (r != LZMADEC_OK) { - switch (r) { - case LZMADEC_HEADER_ERROR: - archive_set_error(&a->archive, - ARCHIVE_ERRNO_MISC, - "Internal error initializing " - "compression library: " - "invalid header"); - break; - case LZMADEC_MEM_ERROR: - archive_set_error(&a->archive, - ENOMEM, - "Internal error initializing " - "compression library: " - "out of memory"); - break; - } - return (ARCHIVE_FATAL); - } - xar->lzstream_valid = 1; - xar->lzstream.total_in = 0; - xar->lzstream.total_out = 0; - break; #endif /* * Unsupported compression. @@ -1563,9 +1533,7 @@ decompression_init(struct archive_read *a, enum enctype encoding) case BZIP2: #endif #if !defined(HAVE_LZMA_H) || !defined(HAVE_LIBLZMA) -#if !defined(HAVE_LZMADEC_H) || !defined(HAVE_LIBLZMADEC) case LZMA: -#endif case XZ: #endif switch (xar->entry_encoding) { @@ -1685,46 +1653,12 @@ decompress(struct archive_read *a, const void **buff, size_t *outbytes, *used = avail_in - xar->lzstream.avail_in; *outbytes = avail_out - xar->lzstream.avail_out; break; -#elif defined(HAVE_LZMADEC_H) && defined(HAVE_LIBLZMADEC) - case LZMA: - xar->lzstream.next_in = (unsigned char *)(uintptr_t)b; - xar->lzstream.avail_in = avail_in; - xar->lzstream.next_out = (unsigned char *)outbuff; - xar->lzstream.avail_out = avail_out; - r = lzmadec_decode(&(xar->lzstream), 0); - switch (r) { - case LZMADEC_STREAM_END: /* Found end of stream. */ - switch (lzmadec_end(&(xar->lzstream))) { - case LZMADEC_OK: - break; - default: - archive_set_error(&(a->archive), - ARCHIVE_ERRNO_MISC, - "Failed to clean up lzmadec decompressor"); - return (ARCHIVE_FATAL); - } - xar->lzstream_valid = 0; - /* FALLTHROUGH */ - case LZMADEC_OK: /* Decompressor made some progress. */ - break; - default: - archive_set_error(&(a->archive), - ARCHIVE_ERRNO_MISC, - "lzmadec decompression failed(%d)", - r); - return (ARCHIVE_FATAL); - } - *used = avail_in - xar->lzstream.avail_in; - *outbytes = avail_out - xar->lzstream.avail_out; - break; #endif #if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR) case BZIP2: #endif #if !defined(HAVE_LZMA_H) || !defined(HAVE_LIBLZMA) -#if !defined(HAVE_LZMADEC_H) || !defined(HAVE_LIBLZMADEC) case LZMA: -#endif case XZ: #endif case NONE: @@ -1788,6 +1722,16 @@ decompression_cleanup(struct archive_read *a) } static void +checksum_cleanup(struct archive_read *a) { + struct xar *xar; + + xar = (struct xar *)(a->format->data); + + _checksum_final(&(xar->a_sumwrk), NULL, 0); + _checksum_final(&(xar->e_sumwrk), NULL, 0); +} + +static void xmlattr_cleanup(struct xmlattr_list *list) { struct xmlattr *attr, *next; @@ -3116,7 +3060,7 @@ xml2_read_cb(void *context, char *buffer, int len) struct xar *xar; const void *d; size_t outbytes; - size_t used; + size_t used = 0; int r; a = (struct archive_read *)context; @@ -3240,6 +3184,9 @@ expat_xmlattr_setup(struct archive_read *a, value = strdup(atts[1]); if (attr == NULL || name == NULL || value == NULL) { archive_set_error(&a->archive, ENOMEM, "Out of memory"); + free(attr); + free(name); + free(value); return (ARCHIVE_FATAL); } attr->name = name; diff --git a/libarchive/archive_read_support_format_zip.c b/libarchive/archive_read_support_format_zip.c index 34ab04e..08bcf1f 100644 --- a/libarchive/archive_read_support_format_zip.c +++ b/libarchive/archive_read_support_format_zip.c @@ -199,7 +199,7 @@ struct zip { struct trad_enc_ctx tctx; char tctx_valid; - /* WinZip AES decyption. */ + /* WinZip AES decryption. */ /* Contexts used for AES decryption. */ archive_crypto_ctx cctx; char cctx_valid; @@ -242,7 +242,7 @@ trad_enc_update_keys(struct trad_enc_ctx *ctx, uint8_t c) } static uint8_t -trad_enc_decypt_byte(struct trad_enc_ctx *ctx) +trad_enc_decrypt_byte(struct trad_enc_ctx *ctx) { unsigned temp = ctx->keys[2] | 2; return (uint8_t)((temp * (temp ^ 1)) >> 8) & 0xff; @@ -257,7 +257,7 @@ trad_enc_decrypt_update(struct trad_enc_ctx *ctx, const uint8_t *in, max = (unsigned)((in_len < out_len)? in_len: out_len); for (i = 0; i < max; i++) { - uint8_t t = in[i] ^ trad_enc_decypt_byte(ctx); + uint8_t t = in[i] ^ trad_enc_decrypt_byte(ctx); out[i] = t; trad_enc_update_keys(ctx, t); } @@ -418,18 +418,30 @@ zip_time(const char *p) * id1+size1+data1 + id2+size2+data2 ... * triplets. id and size are 2 bytes each. */ -static void -process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry) +static int +process_extra(struct archive_read *a, const char *p, size_t extra_length, struct zip_entry* zip_entry) { unsigned offset = 0; - while (offset < extra_length - 4) { + if (extra_length == 0) { + return ARCHIVE_OK; + } + + if (extra_length < 4) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Too-small extra data: Need at least 4 bytes, but only found %d bytes", (int)extra_length); + return ARCHIVE_FAILED; + } + while (offset <= extra_length - 4) { unsigned short headerid = archive_le16dec(p + offset); unsigned short datasize = archive_le16dec(p + offset + 2); offset += 4; if (offset + datasize > extra_length) { - break; + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Extra data overflow: Need %d bytes but only found %d bytes", + (int)datasize, (int)(extra_length - offset)); + return ARCHIVE_FAILED; } #ifdef DEBUG fprintf(stderr, "Header id 0x%04x, length %d\n", @@ -440,26 +452,38 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry) /* Zip64 extended information extra field. */ zip_entry->flags |= LA_USED_ZIP64; if (zip_entry->uncompressed_size == 0xffffffff) { - if (datasize < 8) - break; - zip_entry->uncompressed_size = - archive_le64dec(p + offset); + uint64_t t = 0; + if (datasize < 8 + || (t = archive_le64dec(p + offset)) > INT64_MAX) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Malformed 64-bit uncompressed size"); + return ARCHIVE_FAILED; + } + zip_entry->uncompressed_size = t; offset += 8; datasize -= 8; } if (zip_entry->compressed_size == 0xffffffff) { - if (datasize < 8) - break; - zip_entry->compressed_size = - archive_le64dec(p + offset); + uint64_t t = 0; + if (datasize < 8 + || (t = archive_le64dec(p + offset)) > INT64_MAX) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Malformed 64-bit compressed size"); + return ARCHIVE_FAILED; + } + zip_entry->compressed_size = t; offset += 8; datasize -= 8; } if (zip_entry->local_header_offset == 0xffffffff) { - if (datasize < 8) - break; - zip_entry->local_header_offset = - archive_le64dec(p + offset); + uint64_t t = 0; + if (datasize < 8 + || (t = archive_le64dec(p + offset)) > INT64_MAX) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Malformed 64-bit local header offset"); + return ARCHIVE_FAILED; + } + zip_entry->local_header_offset = t; offset += 8; datasize -= 8; } @@ -698,7 +722,7 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry) break; } case 0x9901: - /* WinZIp AES extra data field. */ + /* WinZip AES extra data field. */ if (p[offset + 2] == 'A' && p[offset + 3] == 'E') { /* Vendor version. */ zip_entry->aes_extra.vendor = @@ -715,13 +739,13 @@ process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry) } offset += datasize; } -#ifdef DEBUG - if (offset != extra_length) - { - fprintf(stderr, - "Extra data field contents do not match reported size!\n"); + if (offset != extra_length) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Malformed extra data: Consumed %d bytes of %d bytes", + (int)offset, (int)extra_length); + return ARCHIVE_FAILED; } -#endif + return ARCHIVE_OK; } /* @@ -840,7 +864,9 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry, return (ARCHIVE_FATAL); } - process_extra(h, extra_length, zip_entry); + if (ARCHIVE_OK != process_extra(a, h, extra_length, zip_entry)) { + return ARCHIVE_FATAL; + } __archive_read_consume(a, extra_length); /* Work around a bug in Info-Zip: When reading from a pipe, it @@ -850,29 +876,33 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry, zip_entry->mode |= AE_IFREG; } - if ((zip_entry->mode & AE_IFMT) == 0) { - /* Especially in streaming mode, we can end up - here without having seen proper mode information. - Guess from the filename. */ + /* If the mode is totally empty, set some sane default. */ + if (zip_entry->mode == 0) { + zip_entry->mode |= 0664; + } + + /* Make sure that entries with a trailing '/' are marked as directories + * even if the External File Attributes contains bogus values. If this + * is not a directory and there is no type, assume regularfile. */ + if ((zip_entry->mode & AE_IFMT) != AE_IFDIR) { + int has_slash; + wp = archive_entry_pathname_w(entry); if (wp != NULL) { len = wcslen(wp); - if (len > 0 && wp[len - 1] == L'/') - zip_entry->mode |= AE_IFDIR; - else - zip_entry->mode |= AE_IFREG; + has_slash = len > 0 && wp[len - 1] == L'/'; } else { cp = archive_entry_pathname(entry); len = (cp != NULL)?strlen(cp):0; - if (len > 0 && cp[len - 1] == '/') - zip_entry->mode |= AE_IFDIR; - else - zip_entry->mode |= AE_IFREG; + has_slash = len > 0 && cp[len - 1] == '/'; } - if (zip_entry->mode == AE_IFDIR) { - zip_entry->mode |= 0775; - } else if (zip_entry->mode == AE_IFREG) { - zip_entry->mode |= 0664; + /* Correct file type as needed. */ + if (has_slash) { + zip_entry->mode &= ~AE_IFMT; + zip_entry->mode |= AE_IFDIR; + zip_entry->mode |= 0111; + } else if ((zip_entry->mode & AE_IFMT) == 0) { + zip_entry->mode |= AE_IFREG; } } @@ -887,6 +917,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry, archive_wstrcat(&s, wp); archive_wstrappend_wchar(&s, L'/'); archive_entry_copy_pathname_w(entry, s.s); + archive_wstring_free(&s); } } else { cp = archive_entry_pathname(entry); @@ -897,6 +928,7 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry, archive_strcat(&s, cp); archive_strappend_char(&s, '/'); archive_entry_set_pathname(entry, s.s); + archive_string_free(&s); } } } @@ -1136,11 +1168,18 @@ zip_read_data_none(struct archive_read *a, const void **_buff, || (zip->hctx_valid && zip->entry->aes_extra.vendor == AES_VENDOR_AE_2))) { if (zip->entry->flags & LA_USED_ZIP64) { + uint64_t compressed, uncompressed; zip->entry->crc32 = archive_le32dec(p + 4); - zip->entry->compressed_size = - archive_le64dec(p + 8); - zip->entry->uncompressed_size = - archive_le64dec(p + 16); + compressed = archive_le64dec(p + 8); + uncompressed = archive_le64dec(p + 16); + if (compressed > INT64_MAX || uncompressed > INT64_MAX) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Overflow of 64-bit file sizes"); + return ARCHIVE_FAILED; + } + zip->entry->compressed_size = compressed; + zip->entry->uncompressed_size = uncompressed; zip->unconsumed = 24; } else { zip->entry->crc32 = archive_le32dec(p + 4); @@ -1293,7 +1332,7 @@ zip_read_data_deflate(struct archive_read *a, const void **buff, && bytes_avail > zip->entry_bytes_remaining) { bytes_avail = (ssize_t)zip->entry_bytes_remaining; } - if (bytes_avail <= 0) { + if (bytes_avail < 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated ZIP file body"); return (ARCHIVE_FATAL); @@ -1417,9 +1456,18 @@ zip_read_data_deflate(struct archive_read *a, const void **buff, zip->unconsumed = 4; } if (zip->entry->flags & LA_USED_ZIP64) { + uint64_t compressed, uncompressed; zip->entry->crc32 = archive_le32dec(p); - zip->entry->compressed_size = archive_le64dec(p + 4); - zip->entry->uncompressed_size = archive_le64dec(p + 12); + compressed = archive_le64dec(p + 4); + uncompressed = archive_le64dec(p + 12); + if (compressed > INT64_MAX || uncompressed > INT64_MAX) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Overflow of 64-bit file sizes"); + return ARCHIVE_FAILED; + } + zip->entry->compressed_size = compressed; + zip->entry->uncompressed_size = uncompressed; zip->unconsumed += 20; } else { zip->entry->crc32 = archive_le32dec(p); @@ -1500,7 +1548,7 @@ read_decryption_header(struct archive_read *a) case 0x6720:/* Blowfish */ case 0x6721:/* Twofish */ case 0x6801:/* RC4 */ - /* Suuported encryption algorithm. */ + /* Supported encryption algorithm. */ break; default: archive_set_error(&a->archive, @@ -1609,7 +1657,7 @@ read_decryption_header(struct archive_read *a) __archive_read_consume(a, 4); /*return (ARCHIVE_OK); - * This is not fully implemnted yet.*/ + * This is not fully implemented yet.*/ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Encrypted file is unsupported"); return (ARCHIVE_FAILED); @@ -1691,7 +1739,7 @@ init_traditional_PKWARE_decryption(struct archive_read *a) } /* - * Initialize ctx for Traditional PKWARE Decyption. + * Initialize ctx for Traditional PKWARE Decryption. */ r = trad_enc_init(&zip->tctx, passphrase, strlen(passphrase), p, ENC_HEADER_SIZE, &crcchk); @@ -2691,7 +2739,9 @@ slurp_central_directory(struct archive_read *a, struct zip *zip) "Truncated ZIP file header"); return ARCHIVE_FATAL; } - process_extra(p + filename_length, extra_length, zip_entry); + if (ARCHIVE_OK != process_extra(a, p + filename_length, extra_length, zip_entry)) { + return ARCHIVE_FATAL; + } /* * Mac resource fork files are stored under the diff --git a/libarchive/archive_string.c b/libarchive/archive_string.c index 282c58e..592ead2 100644 --- a/libarchive/archive_string.c +++ b/libarchive/archive_string.c @@ -219,6 +219,12 @@ archive_wstring_append(struct archive_wstring *as, const wchar_t *p, size_t s) return (as); } +struct archive_string * +archive_array_append(struct archive_string *as, const char *p, size_t s) +{ + return archive_string_append(as, p, s); +} + void archive_string_concat(struct archive_string *dest, struct archive_string *src) { @@ -559,7 +565,8 @@ archive_wstring_append_from_mbs_in_codepage(struct archive_wstring *dest, } if (count == 0 && length != 0) ret = -1; - } while (0); + break; + } while (1); } dest->length += count; dest->s[dest->length] = L'\0'; @@ -596,7 +603,7 @@ archive_wstring_append_from_mbs(struct archive_wstring *dest, wcs = dest->s + dest->length; /* * We cannot use mbsrtowcs/mbstowcs here because those may convert - * extra MBS when strlen(p) > len and one wide character consis of + * extra MBS when strlen(p) > len and one wide character consists of * multi bytes. */ while (*mbs && mbs_length > 0) { @@ -1247,7 +1254,7 @@ create_sconv_object(const char *fc, const char *tc, sc->cd = iconv_open(tc, fc); if (sc->cd == (iconv_t)-1 && (sc->flag & SCONV_BEST_EFFORT)) { /* - * Unfortunaly, all of iconv implements do support + * Unfortunately, all of iconv implements do support * "CP932" character-set, so we should use "SJIS" * instead if iconv_open failed. */ @@ -1260,7 +1267,7 @@ create_sconv_object(const char *fc, const char *tc, /* * archive_mstring on Windows directly convert multi-bytes * into archive_wstring in order not to depend on locale - * so that you can do a I18N programing. This will be + * so that you can do a I18N programming. This will be * used only in archive_mstring_copy_mbs_len_l so far. */ if (flag & SCONV_FROM_CHARSET) { @@ -1725,7 +1732,7 @@ archive_string_conversion_from_charset(struct archive *a, const char *charset, * in tar or zip files. But mbstowcs/wcstombs(CRT) usually use CP_ACP * unless you use setlocale(LC_ALL, ".OCP")(specify CP_OEMCP). * So we should make a string conversion between CP_ACP and CP_OEMCP - * for compatibillty. + * for compatibility. */ #if defined(_WIN32) && !defined(__CYGWIN__) struct archive_string_conv * @@ -1826,7 +1833,7 @@ archive_string_conversion_set_opt(struct archive_string_conv *sc, int opt) * A filename in UTF-8 was made with libarchive 2.x in a wrong * assumption that wchar_t was Unicode. * This option enables simulating the assumption in order to read - * that filname correctly. + * that filename correctly. */ case SCONV_SET_OPT_UTF8_LIBARCHIVE2X: #if (defined(_WIN32) && !defined(__CYGWIN__)) \ @@ -1938,12 +1945,19 @@ archive_strncat_l(struct archive_string *as, const void *_p, size_t n, struct archive_string_conv *sc) { const void *s; - size_t length; + size_t length = 0; int i, r = 0, r2; + if (_p != NULL && n > 0) { + if (sc != NULL && (sc->flag & SCONV_FROM_UTF16)) + length = utf16nbytes(_p, n); + else + length = mbsnbytes(_p, n); + } + /* We must allocate memory even if there is no data for conversion * or copy. This simulates archive_string_append behavior. */ - if (_p == NULL || n == 0) { + if (length == 0) { int tn = 1; if (sc != NULL && (sc->flag & SCONV_TO_UTF16)) tn = 2; @@ -1959,16 +1973,11 @@ archive_strncat_l(struct archive_string *as, const void *_p, size_t n, * If sc is NULL, we just make a copy. */ if (sc == NULL) { - length = mbsnbytes(_p, n); if (archive_string_append(as, _p, length) == NULL) return (-1);/* No memory */ return (0); } - if (sc->flag & SCONV_FROM_UTF16) - length = utf16nbytes(_p, n); - else - length = mbsnbytes(_p, n); s = _p; i = 0; if (sc->nconverter > 1) { @@ -1991,7 +2000,7 @@ archive_strncat_l(struct archive_string *as, const void *_p, size_t n, #if HAVE_ICONV /* - * Return -1 if conversion failes. + * Return -1 if conversion fails. */ static int iconv_strncat_in_locale(struct archive_string *as, const void *_p, @@ -2093,7 +2102,7 @@ iconv_strncat_in_locale(struct archive_string *as, const void *_p, /* * Translate a string from a some CodePage to an another CodePage by - * Windows APIs, and copy the result. Return -1 if conversion failes. + * Windows APIs, and copy the result. Return -1 if conversion fails. */ static int strncat_in_codepage(struct archive_string *as, @@ -2217,7 +2226,7 @@ best_effort_strncat_in_locale(struct archive_string *as, const void *_p, /* * If a character is ASCII, this just copies it. If not, this - * assigns '?' charater instead but in UTF-8 locale this assigns + * assigns '?' character instead but in UTF-8 locale this assigns * byte sequence 0xEF 0xBD 0xBD, which are code point U+FFFD, * a Replacement Character in Unicode. */ @@ -2297,7 +2306,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n) return (0); /* Standard: return 0 for end-of-string. */ cnt = utf8_count[ch]; - /* Invalide sequence or there are not plenty bytes. */ + /* Invalid sequence or there are not plenty bytes. */ if ((int)n < cnt) { cnt = (int)n; for (i = 1; i < cnt; i++) { @@ -2378,7 +2387,7 @@ _utf8_to_unicode(uint32_t *pwc, const char *s, size_t n) goto invalid_sequence; } - /* The code point larger than 0x10FFFF is not leagal + /* The code point larger than 0x10FFFF is not legal * Unicode values. */ if (wc > UNICODE_MAX) goto invalid_sequence; @@ -2396,7 +2405,7 @@ utf8_to_unicode(uint32_t *pwc, const char *s, size_t n) int cnt; cnt = _utf8_to_unicode(pwc, s, n); - /* Any of Surrogate pair is not leagal Unicode values. */ + /* Any of Surrogate pair is not legal Unicode values. */ if (cnt == 3 && IS_SURROGATE_PAIR_LA(*pwc)) return (-3); return (cnt); @@ -2457,7 +2466,7 @@ invalid_sequence: /* * Convert a Unicode code point to a single UTF-8 sequence. * - * NOTE:This function does not check if the Unicode is leagal or not. + * NOTE:This function does not check if the Unicode is legal or not. * Please you definitely check it before calling this. */ static size_t @@ -2551,9 +2560,9 @@ utf16_to_unicode(uint32_t *pwc, const char *s, size_t n, int be) /* * Surrogate pair values(0xd800 through 0xdfff) are only - * used by UTF-16, so, after above culculation, the code + * used by UTF-16, so, after above calculation, the code * must not be surrogate values, and Unicode has no codes - * larger than 0x10ffff. Thus, those are not leagal Unicode + * larger than 0x10ffff. Thus, those are not legal Unicode * values. */ if (IS_SURROGATE_PAIR_LA(uc) || uc > UNICODE_MAX) { @@ -2900,7 +2909,7 @@ get_nfc(uint32_t uc, uint32_t uc2) /* * Normalize UTF-8/UTF-16BE characters to Form C and copy the result. * - * TODO: Convert composition exclusions,which are never converted + * TODO: Convert composition exclusions, which are never converted * from NFC,NFD,NFKC and NFKD, to Form C. */ static int @@ -3434,7 +3443,7 @@ strncat_from_utf8_libarchive2(struct archive_string *as, } /* - * As libarchie 2.x, translates the UTF-8 characters into + * As libarchive 2.x, translates the UTF-8 characters into * wide-characters in the assumption that WCS is Unicode. */ if (n < 0) { @@ -3473,7 +3482,7 @@ strncat_from_utf8_libarchive2(struct archive_string *as, /* * Convert a UTF-16BE/LE string to current locale and copy the result. - * Return -1 if conversion failes. + * Return -1 if conversion fails. */ static int win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes, @@ -3552,18 +3561,19 @@ win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes, ll = WideCharToMultiByte(sc->to_cp, 0, (LPCWSTR)u16, (int)bytes>>1, mbs, (int)mbs_size, NULL, &defchar); - if (ll == 0 && - GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - /* Need more buffer for MBS. */ - ll = WideCharToMultiByte(sc->to_cp, 0, - (LPCWSTR)u16, (int)bytes, NULL, 0, NULL, NULL); - if (archive_string_ensure(as, ll +1) == NULL) - return (-1); - mbs = as->s + as->length; - mbs_size = as->buffer_length - as->length -1; - continue; + /* Exit loop if we succeeded */ + if (ll != 0 || + GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + break; } - } while (0); + /* Else expand buffer and loop to try again. */ + ll = WideCharToMultiByte(sc->to_cp, 0, + (LPCWSTR)u16, (int)bytes, NULL, 0, NULL, NULL); + if (archive_string_ensure(as, ll +1) == NULL) + return (-1); + mbs = as->s + as->length; + mbs_size = as->buffer_length - as->length -1; + } while (1); archive_string_free(&tmp); as->length += ll; as->s[as->length] = '\0'; @@ -3596,7 +3606,7 @@ is_big_endian(void) /* * Convert a current locale string to UTF-16BE/LE and copy the result. - * Return -1 if conversion failes. + * Return -1 if conversion fails. */ static int win_strncat_to_utf16(struct archive_string *as16, const void *_p, @@ -3634,19 +3644,20 @@ win_strncat_to_utf16(struct archive_string *as16, const void *_p, do { count = MultiByteToWideChar(sc->from_cp, MB_PRECOMPOSED, s, (int)length, (LPWSTR)u16, (int)avail>>1); - if (count == 0 && - GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - /* Need more buffer for UTF-16 string */ - count = MultiByteToWideChar(sc->from_cp, - MB_PRECOMPOSED, s, (int)length, NULL, 0); - if (archive_string_ensure(as16, (count +1) * 2) - == NULL) - return (-1); - u16 = as16->s + as16->length; - avail = as16->buffer_length - 2; - continue; + /* Exit loop if we succeeded */ + if (count != 0 || + GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + break; } - } while (0); + /* Expand buffer and try again */ + count = MultiByteToWideChar(sc->from_cp, + MB_PRECOMPOSED, s, (int)length, NULL, 0); + if (archive_string_ensure(as16, (count +1) * 2) + == NULL) + return (-1); + u16 = as16->s + as16->length; + avail = as16->buffer_length - 2; + } while (1); as16->length += count * 2; as16->s[as16->length] = 0; as16->s[as16->length+1] = 0; @@ -3700,7 +3711,7 @@ win_strncat_to_utf16le(struct archive_string *as16, const void *_p, /* * Convert a UTF-16BE string to current locale and copy the result. - * Return -1 if conversion failes. + * Return -1 if conversion fails. */ static int best_effort_strncat_from_utf16(struct archive_string *as, const void *_p, @@ -3758,7 +3769,7 @@ best_effort_strncat_from_utf16le(struct archive_string *as, const void *_p, /* * Convert a current locale string to UTF-16BE/LE and copy the result. - * Return -1 if conversion failes. + * Return -1 if conversion fails. */ static int best_effort_strncat_to_utf16(struct archive_string *as16, const void *_p, @@ -3942,7 +3953,7 @@ archive_mstring_get_mbs_l(struct archive_mstring *aes, #if defined(_WIN32) && !defined(__CYGWIN__) /* - * Internationalization programing on Windows must use Wide + * Internationalization programming on Windows must use Wide * characters because Windows platform cannot make locale UTF-8. */ if (sc != NULL && (aes->aes_set & AES_SET_WCS) != 0) { @@ -4074,7 +4085,7 @@ archive_mstring_copy_mbs_len_l(struct archive_mstring *aes, archive_string_empty(&(aes->aes_utf8)); #if defined(_WIN32) && !defined(__CYGWIN__) /* - * Internationalization programing on Windows must use Wide + * Internationalization programming on Windows must use Wide * characters because Windows platform cannot make locale UTF-8. */ if (sc == NULL) { diff --git a/libarchive/archive_string.h b/libarchive/archive_string.h index 23f4916..56dfbb2 100644 --- a/libarchive/archive_string.h +++ b/libarchive/archive_string.h @@ -81,6 +81,10 @@ archive_strappend_char(struct archive_string *, char); struct archive_wstring * archive_wstrappend_wchar(struct archive_wstring *, wchar_t); +/* Append a raw array to an archive_string, resizing as necessary */ +struct archive_string * +archive_array_append(struct archive_string *, const char *, size_t); + /* Convert a Unicode string to current locale and append the result. */ /* Returns -1 if conversion fails. */ int @@ -115,13 +119,13 @@ archive_string_conversion_set_opt(struct archive_string_conv *, int); /* Copy one archive_string to another in locale conversion. - * Return -1 if conversion failes. */ + * Return -1 if conversion fails. */ int archive_strncpy_l(struct archive_string *, const void *, size_t, struct archive_string_conv *); /* Copy one archive_string to another in locale conversion. - * Return -1 if conversion failes. */ + * Return -1 if conversion fails. */ int archive_strncat_l(struct archive_string *, const void *, size_t, struct archive_string_conv *); diff --git a/libarchive/archive_string_composition.h b/libarchive/archive_string_composition.h index be41e33..8902ac1 100644 --- a/libarchive/archive_string_composition.h +++ b/libarchive/archive_string_composition.h @@ -1009,7 +1009,7 @@ static const char u_decomposable_blocks[0x1D2+1] = { (((uc) > 0x1D244)?0:\ ccc_val[ccc_val_index[ccc_index[(uc)>>8]][((uc)>>4)&0x0F]][(uc)&0x0F]) -/* The table of the value of Canonical Cimbining Class */ +/* The table of the value of Canonical Combining Class */ static const unsigned char ccc_val[][16] = { /* idx=0: XXXX0 - XXXXF */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, diff --git a/libarchive/archive_util.c b/libarchive/archive_util.c index cc3d1c4..6b3bd61 100644 --- a/libarchive/archive_util.c +++ b/libarchive/archive_util.c @@ -580,7 +580,7 @@ void __archive_ensure_cloexec_flag(int fd) { #if defined(_WIN32) && !defined(__CYGWIN__) - (void)fd; /* UNSED */ + (void)fd; /* UNUSED */ #else int flags; diff --git a/libarchive/archive_windows.c b/libarchive/archive_windows.c index d4e93fe..6ff8749 100644 --- a/libarchive/archive_windows.c +++ b/libarchive/archive_windows.c @@ -766,7 +766,7 @@ __la_win_entry_in_posix_pathseparator(struct archive_entry *entry) has_backslash = 1; } /* - * If there is no backslach chars, return the original. + * If there is no backslash chars, return the original. */ if (!has_backslash) return (entry); @@ -891,7 +891,7 @@ __la_dosmaperr(unsigned long e) return; } - for (i = 0; i < (int)sizeof(doserrors); i++) + for (i = 0; i < (int)(sizeof(doserrors)/sizeof(doserrors[0])); i++) { if (doserrors[i].winerr == e) { diff --git a/libarchive/archive_windows.h b/libarchive/archive_windows.h index 8cf1c56..e77cd08 100644 --- a/libarchive/archive_windows.h +++ b/libarchive/archive_windows.h @@ -218,16 +218,20 @@ #define S_IWUSR _S_IWUSR #define S_IRUSR _S_IRUSR #endif +#ifndef S_IRWXG #define S_IRWXG _S_IRWXG #define S_IXGRP _S_IXGRP #define S_IWGRP _S_IWGRP +#endif #ifndef S_IRGRP #define S_IRGRP _S_IRGRP #endif +#ifndef S_IRWXO #define S_IRWXO _S_IRWXO #define S_IXOTH _S_IXOTH #define S_IWOTH _S_IWOTH #define S_IROTH _S_IROTH +#endif #endif diff --git a/libarchive/archive_write.c b/libarchive/archive_write.c index e3fa335..0634a22 100644 --- a/libarchive/archive_write.c +++ b/libarchive/archive_write.c @@ -109,10 +109,9 @@ archive_write_new(void) struct archive_write *a; unsigned char *nulls; - a = (struct archive_write *)malloc(sizeof(*a)); + a = (struct archive_write *)calloc(1, sizeof(*a)); if (a == NULL) return (NULL); - memset(a, 0, sizeof(*a)); a->archive.magic = ARCHIVE_WRITE_MAGIC; a->archive.state = ARCHIVE_STATE_NEW; a->archive.vtable = archive_write_vtable(); @@ -126,12 +125,11 @@ archive_write_new(void) /* Initialize a block of nulls for padding purposes. */ a->null_length = 1024; - nulls = (unsigned char *)malloc(a->null_length); + nulls = (unsigned char *)calloc(1, a->null_length); if (nulls == NULL) { free(a); return (NULL); } - memset(nulls, 0, a->null_length); a->nulls = nulls; return (&a->archive); } @@ -233,7 +231,7 @@ __archive_write_filter(struct archive_write_filter *f, if (length == 0) return(ARCHIVE_OK); if (f->write == NULL) - /* If unset, a fatal error has already ocuured, so this filter + /* If unset, a fatal error has already occurred, so this filter * didn't open. We cannot write anything. */ return(ARCHIVE_FATAL); r = (f->write)(f, buff, length); diff --git a/libarchive/archive_write_add_filter_lz4.c b/libarchive/archive_write_add_filter_lz4.c index 1d0ab8c..e655185 100644 --- a/libarchive/archive_write_add_filter_lz4.c +++ b/libarchive/archive_write_add_filter_lz4.c @@ -523,7 +523,7 @@ drive_compressor_independence(struct archive_write_filter *f, const char *p, archive_le32enc(data->out, outsize); data->out += 4; } else { - /* The buffer is not compressed. The commpressed size was + /* The buffer is not compressed. The compressed size was * bigger than its uncompressed size. */ archive_le32enc(data->out, length | 0x80000000); data->out += 4; @@ -608,7 +608,7 @@ drive_compressor_dependence(struct archive_write_filter *f, const char *p, archive_le32enc(data->out, outsize); data->out += 4; } else { - /* The buffer is not compressed. The commpressed size was + /* The buffer is not compressed. The compressed size was * bigger than its uncompressed size. */ archive_le32enc(data->out, length | 0x80000000); data->out += 4; diff --git a/libarchive/archive_write_add_filter_program.c b/libarchive/archive_write_add_filter_program.c index 31a1b6f..55b5e8e 100644 --- a/libarchive/archive_write_add_filter_program.c +++ b/libarchive/archive_write_add_filter_program.c @@ -200,6 +200,7 @@ __archive_write_program_free(struct archive_write_program_data *data) if (data->child) CloseHandle(data->child); #endif + free(data->program_name); free(data->child_buf); free(data); } diff --git a/libarchive/archive_write_add_filter_xz.c b/libarchive/archive_write_add_filter_xz.c index 46a6c38..b0f25a6 100644 --- a/libarchive/archive_write_add_filter_xz.c +++ b/libarchive/archive_write_add_filter_xz.c @@ -233,7 +233,7 @@ archive_compressor_xz_init_stream(struct archive_write_filter *f, if (f->code == ARCHIVE_FILTER_XZ) { #ifdef HAVE_LZMA_STREAM_ENCODER_MT if (data->threads != 1) { - bzero(&mt_options, sizeof(mt_options)); + memset(&mt_options, 0, sizeof(mt_options)); mt_options.threads = data->threads; mt_options.timeout = 300; mt_options.filters = data->lzmafilters; diff --git a/libarchive/archive_write_disk_acl.c b/libarchive/archive_write_disk_acl.c index 5cbba54..144ab7e 100644 --- a/libarchive/archive_write_disk_acl.c +++ b/libarchive/archive_write_disk_acl.c @@ -34,6 +34,9 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_disk.c 201159 2009-12-29 0 #define _ACL_PRIVATE /* For debugging */ #include #endif +#if HAVE_DARWIN_ACL +#include +#endif #ifdef HAVE_ERRNO_H #include #endif @@ -43,7 +46,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_disk.c 201159 2009-12-29 0 #include "archive_acl_private.h" #include "archive_write_disk_private.h" -#ifndef HAVE_POSIX_ACL +#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, @@ -56,47 +59,111 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name, return (ARCHIVE_OK); } -#else +#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); -/* - * XXX TODO: What about ACL types other than ACCESS and DEFAULT? - */ int archive_write_disk_set_acls(struct archive *a, int fd, const char *name, struct archive_acl *abstract_acl) { - int ret; + int ret = ARCHIVE_OK; - if (archive_acl_count(abstract_acl, ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) > 0) { - ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_ACCESS, - ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access"); - if (ret != ARCHIVE_OK) - return (ret); - ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_DEFAULT, - ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default"); +#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); -#ifdef ACL_TYPE_NFS4 - } else if (archive_acl_count(abstract_acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4) > 0) { - ret = set_acl(a, fd, name, abstract_acl, ACL_TYPE_NFS4, + } +#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"); - return (ret); -#endif - } else - return ARCHIVE_OK; + } +#endif /* HAVE_NFS4_ACL */ + return (ret); } -static struct { - int archive_perm; - int platform_perm; +/* + * 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}, -#ifdef ACL_TYPE_NFS4 +#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}, @@ -114,33 +181,69 @@ static struct { {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER}, {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE} #endif +#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */ }; -#ifdef ACL_TYPE_NFS4 -static struct { - int archive_inherit; - int platform_inherit; +#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_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 +#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; -#ifdef ACL_TYPE_NFS4 +#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; @@ -151,22 +254,165 @@ set_acl(struct archive *a, int fd, const char *name, 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) { - acl_create_entry(&acl, &acl_entry); - +#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 at . + * 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: - acl_set_tag_type(acl_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: - acl_set_tag_type(acl_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; @@ -179,85 +425,230 @@ set_acl(struct archive *a, int fd, const char *name, case ARCHIVE_ENTRY_ACL_OTHER: acl_set_tag_type(acl_entry, ACL_OTHER); break; -#ifdef ACL_TYPE_NFS4 +#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: - /* XXX */ - break; + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unknown ACL tag"); + ret = ARCHIVE_FAILED; + goto exit_free; } -#ifdef ACL_TYPE_NFS4 +#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: - acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW); + r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW); break; case ARCHIVE_ENTRY_ACL_TYPE_DENY: - acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_DENY); + r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_DENY); break; case ARCHIVE_ENTRY_ACL_TYPE_AUDIT: - acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_AUDIT); + r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_AUDIT); break; case ARCHIVE_ENTRY_ACL_TYPE_ALARM: - acl_set_entry_type_np(acl_entry, ACL_ENTRY_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: - // XXX error handling here. - break; + archive_set_error(a, ARCHIVE_ERRNO_MISC, + "Unknown ACL entry type"); + ret = ARCHIVE_FAILED; + goto exit_free; } -#endif - acl_get_permset(acl_entry, &acl_permset); - acl_clear_perms(acl_permset); + 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) - acl_add_perm(acl_permset, - acl_perm_map[i].platform_perm); + 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 + } } -#ifdef ACL_TYPE_NFS4 - acl_get_flagset_np(acl_entry, &acl_flagset); - acl_clear_flags_np(acl_flagset); - for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) { - if (ae_permset & acl_inherit_map[i].archive_inherit) - acl_add_flag_np(acl_flagset, - acl_inherit_map[i].platform_inherit); +#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_ACL_SET_FD - if (fd >= 0 && acl_type == ACL_TYPE_ACCESS && acl_set_fd(fd, acl) == 0) - ret = ARCHIVE_OK; - else -#else -#if HAVE_ACL_SET_FD_NP - if (fd >= 0 && acl_set_fd_np(fd, acl, acl_type) == 0) - ret = ARCHIVE_OK; - else +#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 -#if HAVE_ACL_SET_LINK_NP - if (acl_set_link_np(name, acl_type, acl) != 0) { - archive_set_error(a, errno, "Failed to set %s acl", tname); - ret = ARCHIVE_WARN; - } + 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) { - archive_set_error(a, errno, "Failed to set %s acl", tname); - ret = ARCHIVE_WARN; - } + 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 +#endif /* HAVE_POSIX_ACL || HAVE_NFS4_ACL */ diff --git a/libarchive/archive_write_disk_posix.c b/libarchive/archive_write_disk_posix.c index 6737cd7..20450ba 100644 --- a/libarchive/archive_write_disk_posix.c +++ b/libarchive/archive_write_disk_posix.c @@ -110,6 +110,18 @@ __FBSDID("$FreeBSD$"); #include #endif +/* + * Macro to cast st_mtime and time_t to an int64 so that 2 numbers can reliably be compared. + * + * It assumes that the input is an integer type of no more than 64 bits. + * If the number is less than zero, t must be a signed type, so it fits in + * int64_t. Otherwise, it's a nonnegative value so we can cast it to uint64_t + * without loss. But it could be a large unsigned value, so we have to clip it + * to INT64_MAX.* + */ +#define to_int64_time(t) \ + ((t) < 0 ? (int64_t)(t) : (uint64_t)(t) > (uint64_t)INT64_MAX ? INT64_MAX : (int64_t)(t)) + #if __APPLE__ #include #if TARGET_OS_MAC && !TARGET_OS_EMBEDDED && HAVE_QUARANTINE_H @@ -140,7 +152,17 @@ __FBSDID("$FreeBSD$"); #define O_BINARY 0 #endif #ifndef O_CLOEXEC -#define O_CLOEXEC 0 +#define O_CLOEXEC 0 +#endif + +/* Ignore non-int O_NOFOLLOW constant. */ +/* gnulib's fcntl.h does this on AIX, but it seems practical everywhere */ +#if defined O_NOFOLLOW && !(INT_MIN <= O_NOFOLLOW && O_NOFOLLOW <= INT_MAX) +#undef O_NOFOLLOW +#endif + +#ifndef O_NOFOLLOW +#define O_NOFOLLOW 0 #endif struct fixup_entry { @@ -298,7 +320,7 @@ struct archive_write_disk { #define MAXIMUM_DIR_MODE 0775 /* - * Maxinum uncompressed size of a decmpfs block. + * Maximum uncompressed size of a decmpfs block. */ #define MAX_DECMPFS_BLOCK_SIZE (64 * 1024) /* @@ -313,7 +335,7 @@ struct archive_write_disk { #define RSRC_F_SIZE 50 /* Size of Resource fork footer. */ /* Size to write compressed data to resource fork. */ #define COMPRESSED_W_SIZE (64 * 1024) -/* decmpfs difinitions. */ +/* decmpfs definitions. */ #define MAX_DECMPFS_XATTR_SIZE 3802 #ifndef DECMPFS_XATTR_NAME #define DECMPFS_XATTR_NAME "com.apple.decmpfs" @@ -326,12 +348,19 @@ struct archive_write_disk { #define HFS_BLOCKS(s) ((s) >> 12) +static void fsobj_error(int *, struct archive_string *, int, const char *, + const char *); +static int check_symlinks_fsobj(char *, int *, struct archive_string *, + int); static int check_symlinks(struct archive_write_disk *); static int create_filesystem_object(struct archive_write_disk *); -static struct fixup_entry *current_fixup(struct archive_write_disk *, const char *pathname); +static struct fixup_entry *current_fixup(struct archive_write_disk *, + const char *pathname); #if defined(HAVE_FCHDIR) && defined(PATH_MAX) static void edit_deep_directories(struct archive_write_disk *ad); #endif +static int cleanup_pathname_fsobj(char *, int *, struct archive_string *, + int); static int cleanup_pathname(struct archive_write_disk *); static int create_dir(struct archive_write_disk *, char *); static int create_parent_dir(struct archive_write_disk *, char *); @@ -362,11 +391,14 @@ static struct archive_vtable *archive_write_disk_vtable(void); static int _archive_write_disk_close(struct archive *); static int _archive_write_disk_free(struct archive *); -static int _archive_write_disk_header(struct archive *, struct archive_entry *); +static int _archive_write_disk_header(struct archive *, + struct archive_entry *); static int64_t _archive_write_disk_filter_bytes(struct archive *, int); static int _archive_write_disk_finish_entry(struct archive *); -static ssize_t _archive_write_disk_data(struct archive *, const void *, size_t); -static ssize_t _archive_write_disk_data_block(struct archive *, const void *, size_t, int64_t); +static ssize_t _archive_write_disk_data(struct archive *, const void *, + size_t); +static ssize_t _archive_write_disk_data_block(struct archive *, const void *, + size_t, int64_t); static int lazy_stat(struct archive_write_disk *a) @@ -612,9 +644,9 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry) /* * NOTE: UF_COMPRESSED is ignored even if the filesystem * supports HFS+ Compression because the file should - * have at least an extended attriute "com.apple.decmpfs" + * have at least an extended attribute "com.apple.decmpfs" * before the flag is set to indicate that the file have - * been compressed. If hte filesystem does not support + * been compressed. If the filesystem does not support * HFS+ Compression the system call will fail. */ if (a->fd < 0 || fchflags(a->fd, UF_COMPRESSED) != 0) @@ -637,7 +669,8 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry) if (a->restore_pwd >= 0) { r = fchdir(a->restore_pwd); if (r != 0) { - archive_set_error(&a->archive, errno, "chdir() failure"); + archive_set_error(&a->archive, errno, + "chdir() failure"); ret = ARCHIVE_FATAL; } close(a->restore_pwd); @@ -685,7 +718,8 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry) } if (archive_entry_birthtime_is_set(entry)) { fe->birthtime = archive_entry_birthtime(entry); - fe->birthtime_nanos = archive_entry_birthtime_nsec(entry); + fe->birthtime_nanos = archive_entry_birthtime_nsec( + entry); } else { /* If birthtime is unset, use mtime. */ fe->birthtime = fe->mtime; @@ -711,7 +745,8 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry) return (ARCHIVE_FATAL); fe->mac_metadata = malloc(metadata_size); if (fe->mac_metadata != NULL) { - memcpy(fe->mac_metadata, metadata, metadata_size); + memcpy(fe->mac_metadata, metadata, + metadata_size); fe->mac_metadata_size = metadata_size; fe->fixup |= TODO_MAC_METADATA; } @@ -1224,7 +1259,7 @@ hfs_drive_compressor(struct archive_write_disk *a, const char *buff, ret = hfs_write_compressed_data(a, bytes_used + rsrc_size); a->compressed_buffer_remaining = a->compressed_buffer_size; - /* If the compressed size is not enouph smaller than + /* If the compressed size is not enough smaller than * the uncompressed size. cancel HFS+ compression. * TODO: study a behavior of ditto utility and improve * the condition to fall back into no HFS+ compression. */ @@ -1329,7 +1364,7 @@ hfs_write_decmpfs_block(struct archive_write_disk *a, const char *buff, (uint32_t *)(a->resource_fork + RSRC_H_SIZE); /* Set the block count to the resource fork. */ archive_le32enc(a->decmpfs_block_info++, block_count); - /* Get the position where we are goint to set compressed + /* Get the position where we are going to set compressed * data. */ a->compressed_rsrc_position = RSRC_H_SIZE + 4 + (block_count * 8); @@ -1402,7 +1437,7 @@ hfs_write_data_block(struct archive_write_disk *a, const char *buff, bytes_to_write = size; /* Seek if necessary to the specified offset. */ if (a->offset < a->fd_offset) { - /* Can't support backword move. */ + /* Can't support backward move. */ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Seek failed"); return (ARCHIVE_FATAL); @@ -1468,7 +1503,8 @@ _archive_write_disk_data_block(struct archive *_a, return (r); if ((size_t)r < size) { archive_set_error(&a->archive, 0, - "Too much data: Truncating file at %ju bytes", (uintmax_t)a->filesize); + "Too much data: Truncating file at %ju bytes", + (uintmax_t)a->filesize); return (ARCHIVE_WARN); } #if ARCHIVE_VERSION_NUMBER < 3999000 @@ -1666,10 +1702,25 @@ _archive_write_disk_finish_entry(struct archive *_a) * ACLs that prevent attribute changes (including time). */ if (a->todo & TODO_ACLS) { - int r2 = archive_write_disk_set_acls(&a->archive, a->fd, - archive_entry_pathname(a->entry), - archive_entry_acl(a->entry)); + 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 (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)); if (r2 < ret) ret = r2; +#ifdef HAVE_DARWIN_ACL + } +#endif } finish_metadata: @@ -1755,10 +1806,9 @@ archive_write_disk_new(void) { struct archive_write_disk *a; - a = (struct archive_write_disk *)malloc(sizeof(*a)); + a = (struct archive_write_disk *)calloc(1, sizeof(*a)); if (a == NULL) return (NULL); - memset(a, 0, sizeof(*a)); a->archive.magic = ARCHIVE_WRITE_DISK_MAGIC; /* We're ready to write a header immediately. */ a->archive.state = ARCHIVE_STATE_HEADER; @@ -1796,7 +1846,7 @@ edit_deep_directories(struct archive_write_disk *a) char *tail = a->name; /* If path is short, avoid the open() below. */ - if (strlen(tail) <= PATH_MAX) + if (strlen(tail) < PATH_MAX) return; /* Try to record our starting dir. */ @@ -1806,7 +1856,7 @@ edit_deep_directories(struct archive_write_disk *a) return; /* As long as the path is too long... */ - while (strlen(tail) > PATH_MAX) { + while (strlen(tail) >= PATH_MAX) { /* Locate a dir prefix shorter than PATH_MAX. */ tail += PATH_MAX - 8; while (tail > a->name && *tail != '/') @@ -1993,8 +2043,9 @@ restore_entry(struct archive_write_disk *a) if (en) { /* Everything failed; give up here. */ - archive_set_error(&a->archive, en, "Can't create '%s'", - a->name); + if ((&a->archive)->error == NULL) + archive_set_error(&a->archive, en, "Can't create '%s'", + a->name); return (ARCHIVE_FAILED); } @@ -2014,6 +2065,11 @@ create_filesystem_object(struct archive_write_disk *a) const char *linkname; mode_t final_mode, mode; int r; + /* these for check_symlinks_fsobj */ + char *linkname_copy; /* non-const copy of linkname */ + struct stat st; + struct archive_string error_string; + int error_number; /* We identify hard/symlinks according to the link names. */ /* Since link(2) and symlink(2) don't handle modes, we're done here. */ @@ -2022,6 +2078,43 @@ create_filesystem_object(struct archive_write_disk *a) #if !HAVE_LINK return (EPERM); #else + archive_string_init(&error_string); + linkname_copy = strdup(linkname); + if (linkname_copy == NULL) { + return (EPERM); + } + /* + * TODO: consider using the cleaned-up path as the link + * target? + */ + r = cleanup_pathname_fsobj(linkname_copy, &error_number, + &error_string, a->flags); + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, error_number, "%s", + error_string.s); + free(linkname_copy); + archive_string_free(&error_string); + /* + * EPERM is more appropriate than error_number for our + * callers + */ + return (EPERM); + } + r = check_symlinks_fsobj(linkname_copy, &error_number, + &error_string, a->flags); + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, error_number, "%s", + error_string.s); + free(linkname_copy); + archive_string_free(&error_string); + /* + * EPERM is more appropriate than error_number for our + * callers + */ + return (EPERM); + } + free(linkname_copy); + archive_string_free(&error_string); r = link(linkname, a->name) ? errno : 0; /* * New cpio and pax formats allow hardlink entries @@ -2039,11 +2132,20 @@ create_filesystem_object(struct archive_write_disk *a) a->todo = 0; a->deferred = 0; } else if (r == 0 && a->filesize > 0) { - a->fd = open(a->name, - O_WRONLY | O_TRUNC | O_BINARY | O_CLOEXEC); - __archive_ensure_cloexec_flag(a->fd); - if (a->fd < 0) +#ifdef HAVE_LSTAT + r = lstat(a->name, &st); +#else + r = stat(a->name, &st); +#endif + if (r != 0) r = errno; + else if ((st.st_mode & AE_IFMT) == AE_IFREG) { + a->fd = open(a->name, O_WRONLY | O_TRUNC | + O_BINARY | O_CLOEXEC | O_NOFOLLOW); + __archive_ensure_cloexec_flag(a->fd); + if (a->fd < 0) + r = errno; + } } return (r); #endif @@ -2190,8 +2292,12 @@ _archive_write_disk_close(struct archive *_a) if (p->fixup & TODO_MODE_BASE) chmod(p->name, p->mode); if (p->fixup & TODO_ACLS) - archive_write_disk_set_acls(&a->archive, - -1, p->name, &p->acl); +#ifdef HAVE_DARWIN_ACL + if (p->mac_metadata == NULL || + p->mac_metadata_size == 0) +#endif + archive_write_disk_set_acls(&a->archive, + -1, p->name, &p->acl); if (p->fixup & TODO_FFLAGS) set_fflags_platform(a, -1, p->name, p->mode, p->fflags_set, 0); @@ -2351,116 +2457,283 @@ current_fixup(struct archive_write_disk *a, const char *pathname) return (a->current_fixup); } -/* TODO: Make this work. */ -/* - * TODO: The deep-directory support bypasses this; disable deep directory - * support if we're doing symlink checks. - */ +/* Error helper for new *_fsobj functions */ +static void +fsobj_error(int *a_eno, struct archive_string *a_estr, + int err, const char *errstr, const char *path) +{ + if (a_eno) + *a_eno = err; + if (a_estr) + archive_string_sprintf(a_estr, errstr, path); +} + /* * TODO: Someday, integrate this with the deep dir support; they both * scan the path and both can be optimized by comparing against other * recent paths. */ /* TODO: Extend this to support symlinks on Windows Vista and later. */ + +/* + * Checks the given path to see if any elements along it are symlinks. Returns + * ARCHIVE_OK if there are none, otherwise puts an error in errmsg. + */ static int -check_symlinks(struct archive_write_disk *a) +check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, + int flags) { #if !defined(HAVE_LSTAT) /* Platform doesn't have lstat, so we can't look for symlinks. */ - (void)a; /* UNUSED */ + (void)path; /* UNUSED */ + (void)error_number; /* UNUSED */ + (void)error_string; /* UNUSED */ + (void)flags; /* UNUSED */ return (ARCHIVE_OK); #else - char *pn; + int res = ARCHIVE_OK; + char *tail; + char *head; + int last; char c; int r; struct stat st; + int restore_pwd; + + /* Nothing to do here if name is empty */ + if(path[0] == '\0') + return (ARCHIVE_OK); /* * Guard against symlink tricks. Reject any archive entry whose * destination would be altered by a symlink. + * + * Walk the filename in chunks separated by '/'. For each segment: + * - if it doesn't exist, continue + * - if it's symlink, abort or remove it + * - if it's a directory and it's not the last chunk, cd into it + * As we go: + * head points to the current (relative) path + * tail points to the temporary \0 terminating the segment we're + * currently examining + * c holds what used to be in *tail + * last is 1 if this is the last tail */ - /* Whatever we checked last time doesn't need to be re-checked. */ - pn = a->name; - if (archive_strlen(&(a->path_safe)) > 0) { - char *p = a->path_safe.s; - while ((*pn != '\0') && (*p == *pn)) - ++p, ++pn; - } + restore_pwd = open(".", O_RDONLY | O_BINARY | O_CLOEXEC); + __archive_ensure_cloexec_flag(restore_pwd); + if (restore_pwd < 0) + return (ARCHIVE_FATAL); + head = path; + tail = path; + last = 0; + /* TODO: reintroduce a safe cache here? */ /* Skip the root directory if the path is absolute. */ - if(pn == a->name && pn[0] == '/') - ++pn; - c = pn[0]; - /* Keep going until we've checked the entire name. */ - while (pn[0] != '\0' && (pn[0] != '/' || pn[1] != '\0')) { + if(tail == path && tail[0] == '/') + ++tail; + /* Keep going until we've checked the entire name. + * head, tail, path all alias the same string, which is + * temporarily zeroed at tail, so be careful restoring the + * stashed (c=tail[0]) for error messages. + * Exiting the loop with break is okay; continue is not. + */ + while (!last) { + /* + * Skip the separator we just consumed, plus any adjacent ones + */ + while (*tail == '/') + ++tail; /* Skip the next path element. */ - while (*pn != '\0' && *pn != '/') - ++pn; - c = pn[0]; - pn[0] = '\0'; + while (*tail != '\0' && *tail != '/') + ++tail; + /* is this the last path component? */ + last = (tail[0] == '\0') || (tail[0] == '/' && tail[1] == '\0'); + /* temporarily truncate the string here */ + c = tail[0]; + tail[0] = '\0'; /* Check that we haven't hit a symlink. */ - r = lstat(a->name, &st); + r = lstat(head, &st); if (r != 0) { + tail[0] = c; /* We've hit a dir that doesn't exist; stop now. */ - if (errno == ENOENT) + if (errno == ENOENT) { + break; + } else { + /* + * Treat any other error as fatal - best to be + * paranoid here. + * Note: This effectively disables deep + * directory support when security checks are + * enabled. Otherwise, very long pathnames that + * trigger an error here could evade the + * sandbox. + * TODO: We could do better, but it would + * probably require merging the symlink checks + * with the deep-directory editing. + */ + fsobj_error(a_eno, a_estr, errno, + "Could not stat %s", path); + res = ARCHIVE_FAILED; break; + } + } else if (S_ISDIR(st.st_mode)) { + if (!last) { + if (chdir(head) != 0) { + tail[0] = c; + fsobj_error(a_eno, a_estr, errno, + "Could not chdir %s", path); + res = (ARCHIVE_FATAL); + break; + } + /* Our view is now from inside this dir: */ + head = tail + 1; + } } else if (S_ISLNK(st.st_mode)) { - if (c == '\0') { + if (last) { /* * Last element is symlink; remove it * so we can overwrite it with the * item being extracted. */ - if (unlink(a->name)) { - archive_set_error(&a->archive, errno, + if (unlink(head)) { + tail[0] = c; + fsobj_error(a_eno, a_estr, errno, "Could not remove symlink %s", - a->name); - pn[0] = c; - return (ARCHIVE_FAILED); + path); + res = ARCHIVE_FAILED; + break; } - a->pst = NULL; /* * Even if we did remove it, a warning * is in order. The warning is silly, * though, if we're just replacing one * symlink with another symlink. */ - if (!S_ISLNK(a->mode)) { - archive_set_error(&a->archive, 0, - "Removing symlink %s", - a->name); + tail[0] = c; + /* + * FIXME: not sure how important this is to + * restore + */ + /* + if (!S_ISLNK(path)) { + fsobj_error(a_eno, a_estr, 0, + "Removing symlink %s", path); } + */ /* Symlink gone. No more problem! */ - pn[0] = c; - return (0); - } else if (a->flags & ARCHIVE_EXTRACT_UNLINK) { + res = ARCHIVE_OK; + break; + } else if (flags & ARCHIVE_EXTRACT_UNLINK) { /* User asked us to remove problems. */ - if (unlink(a->name) != 0) { - archive_set_error(&a->archive, 0, - "Cannot remove intervening symlink %s", - a->name); - pn[0] = c; - return (ARCHIVE_FAILED); + if (unlink(head) != 0) { + tail[0] = c; + fsobj_error(a_eno, a_estr, 0, + "Cannot remove intervening " + "symlink %s", path); + res = ARCHIVE_FAILED; + break; + } + tail[0] = c; + } else if ((flags & + ARCHIVE_EXTRACT_SECURE_SYMLINKS) == 0) { + /* + * We are not the last element and we want to + * follow symlinks if they are a directory. + * + * This is needed to extract hardlinks over + * symlinks. + */ + r = stat(head, &st); + if (r != 0) { + tail[0] = c; + if (errno == ENOENT) { + break; + } else { + fsobj_error(a_eno, a_estr, + errno, + "Could not stat %s", path); + res = (ARCHIVE_FAILED); + break; + } + } else if (S_ISDIR(st.st_mode)) { + if (chdir(head) != 0) { + tail[0] = c; + fsobj_error(a_eno, a_estr, + errno, + "Could not chdir %s", path); + res = (ARCHIVE_FATAL); + break; + } + /* + * Our view is now from inside + * this dir: + */ + head = tail + 1; + } else { + tail[0] = c; + fsobj_error(a_eno, a_estr, 0, + "Cannot extract through " + "symlink %s", path); + res = ARCHIVE_FAILED; + break; } - a->pst = NULL; } else { - archive_set_error(&a->archive, 0, - "Cannot extract through symlink %s", - a->name); - pn[0] = c; - return (ARCHIVE_FAILED); + tail[0] = c; + fsobj_error(a_eno, a_estr, 0, + "Cannot extract through symlink %s", path); + res = ARCHIVE_FAILED; + break; } } - pn[0] = c; - if (pn[0] != '\0') - pn++; /* Advance to the next segment. */ + /* be sure to always maintain this */ + tail[0] = c; + if (tail[0] != '\0') + tail++; /* Advance to the next segment. */ + } + /* Catches loop exits via break */ + tail[0] = c; +#ifdef HAVE_FCHDIR + /* If we changed directory above, restore it here. */ + if (restore_pwd >= 0) { + r = fchdir(restore_pwd); + if (r != 0) { + fsobj_error(a_eno, a_estr, errno, + "chdir() failure", ""); + } + close(restore_pwd); + restore_pwd = -1; + if (r != 0) { + res = (ARCHIVE_FATAL); + } } - pn[0] = c; - /* We've checked and/or cleaned the whole path, so remember it. */ - archive_strcpy(&a->path_safe, a->name); - return (ARCHIVE_OK); +#endif + /* TODO: reintroduce a safe cache here? */ + return res; #endif } +/* + * Check a->name for symlinks, returning ARCHIVE_OK if its clean, otherwise + * calls archive_set_error and returns ARCHIVE_{FATAL,FAILED} + */ +static int +check_symlinks(struct archive_write_disk *a) +{ + struct archive_string error_string; + int error_number; + int rc; + archive_string_init(&error_string); + rc = check_symlinks_fsobj(a->name, &error_number, &error_string, + a->flags); + if (rc != ARCHIVE_OK) { + archive_set_error(&a->archive, error_number, "%s", + error_string.s); + } + archive_string_free(&error_string); + a->pst = NULL; /* to be safe */ + return rc; +} + + #if defined(__CYGWIN__) /* * 1. Convert a path separator from '\' to '/' . @@ -2471,7 +2744,7 @@ check_symlinks(struct archive_write_disk *a) * See also : http://msdn.microsoft.com/en-us/library/aa365247.aspx */ static void -cleanup_pathname_win(struct archive_write_disk *a) +cleanup_pathname_win(char *path) { wchar_t wc; char *p; @@ -2482,7 +2755,7 @@ cleanup_pathname_win(struct archive_write_disk *a) mb = 0; complete = 1; utf8 = (strcmp(nl_langinfo(CODESET), "UTF-8") == 0)? 1: 0; - for (p = a->name; *p != '\0'; p++) { + for (p = path; *p != '\0'; p++) { ++alen; if (*p == '\\') { /* If previous byte is smaller than 128, @@ -2507,7 +2780,7 @@ cleanup_pathname_win(struct archive_write_disk *a) /* * Convert path separator in wide-character. */ - p = a->name; + p = path; while (*p != '\0' && alen) { l = mbtowc(&wc, p, alen); if (l == (size_t)-1) { @@ -2534,26 +2807,27 @@ cleanup_pathname_win(struct archive_write_disk *a) * is set) if the path is absolute. */ static int -cleanup_pathname(struct archive_write_disk *a) +cleanup_pathname_fsobj(char *path, int *a_eno, struct archive_string *a_estr, + int flags) { char *dest, *src; char separator = '\0'; - dest = src = a->name; + dest = src = path; if (*src == '\0') { - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Invalid empty pathname"); + fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC, + "Invalid empty ", "pathname"); return (ARCHIVE_FAILED); } #if defined(__CYGWIN__) - cleanup_pathname_win(a); + cleanup_pathname_win(path); #endif /* Skip leading '/'. */ if (*src == '/') { - if (a->flags & ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Path is absolute"); + if (flags & ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS) { + fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC, + "Path is ", "absolute"); return (ARCHIVE_FAILED); } @@ -2580,10 +2854,11 @@ cleanup_pathname(struct archive_write_disk *a) } else if (src[1] == '.') { if (src[2] == '/' || src[2] == '\0') { /* Conditionally warn about '..' */ - if (a->flags & ARCHIVE_EXTRACT_SECURE_NODOTDOT) { - archive_set_error(&a->archive, + if (flags + & ARCHIVE_EXTRACT_SECURE_NODOTDOT) { + fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC, - "Path contains '..'"); + "Path contains ", "'..'"); return (ARCHIVE_FAILED); } } @@ -2614,7 +2889,7 @@ cleanup_pathname(struct archive_write_disk *a) * We've just copied zero or more path elements, not including the * final '/'. */ - if (dest == a->name) { + if (dest == path) { /* * Nothing got copied. The path must have been something * like '.' or '/' or './' or '/././././/./'. @@ -2629,6 +2904,23 @@ cleanup_pathname(struct archive_write_disk *a) return (ARCHIVE_OK); } +static int +cleanup_pathname(struct archive_write_disk *a) +{ + struct archive_string error_string; + int error_number; + int rc; + archive_string_init(&error_string); + rc = cleanup_pathname_fsobj(a->name, &error_number, &error_string, + a->flags); + if (rc != ARCHIVE_OK) { + archive_set_error(&a->archive, error_number, "%s", + error_string.s); + } + archive_string_free(&error_string); + return rc; +} + /* * Create the parent directory of the specified path, assuming path * is already in mutable storage. @@ -2707,7 +2999,8 @@ create_dir(struct archive_write_disk *a, char *path) } } else if (errno != ENOENT && errno != ENOTDIR) { /* Stat failed? */ - archive_set_error(&a->archive, errno, "Can't test directory '%s'", path); + archive_set_error(&a->archive, errno, + "Can't test directory '%s'", path); return (ARCHIVE_FAILED); } else if (slash != NULL) { *slash = '\0'; @@ -3232,7 +3525,8 @@ clear_nochange_fflags(struct archive_write_disk *a) nochange_flags |= EXT2_IMMUTABLE_FL; #endif - return (set_fflags_platform(a, a->fd, a->name, mode, 0, nochange_flags)); + return (set_fflags_platform(a, a->fd, a->name, mode, 0, + nochange_flags)); } @@ -3487,6 +3781,9 @@ exit_xattr: static int copy_acls(struct archive_write_disk *a, int tmpfd, int dffd) { +#ifndef HAVE_SYS_ACL_H + return 0; +#else acl_t acl, dfacl = NULL; int acl_r, ret = ARCHIVE_OK; @@ -3514,6 +3811,7 @@ exit_acl: if (dfacl) acl_free(dfacl); return (ret); +#endif } static int @@ -3753,7 +4051,8 @@ set_xattrs(struct archive_write_disk *a) if (errno == ENOTSUP || errno == ENOSYS) { if (!warning_done) { warning_done = 1; - archive_set_error(&a->archive, errno, + archive_set_error(&a->archive, + errno, "Cannot restore extended " "attributes on this file " "system"); @@ -3764,7 +4063,8 @@ set_xattrs(struct archive_write_disk *a) ret = ARCHIVE_WARN; } } else { - archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "Invalid extended attribute encountered"); ret = ARCHIVE_WARN; } @@ -3808,19 +4108,22 @@ set_xattrs(struct archive_write_disk *a) errno = 0; #if HAVE_EXTATTR_SET_FD if (a->fd >= 0) - e = extattr_set_fd(a->fd, namespace, name, value, size); + e = extattr_set_fd(a->fd, namespace, name, + value, size); else #endif /* TODO: should we use extattr_set_link() instead? */ { - e = extattr_set_file(archive_entry_pathname(entry), - namespace, name, value, size); + e = extattr_set_file( + 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, + archive_set_error(&a->archive, + errno, "Cannot restore extended " "attributes on this file " "system"); @@ -3866,10 +4169,10 @@ older(struct stat *st, struct archive_entry *entry) { /* First, test the seconds and return if we have a definite answer. */ /* Definitely older. */ - if (st->st_mtime < archive_entry_mtime(entry)) + if (to_int64_time(st->st_mtime) < to_int64_time(archive_entry_mtime(entry))) return (1); /* Definitely younger. */ - if (st->st_mtime > archive_entry_mtime(entry)) + if (to_int64_time(st->st_mtime) > to_int64_time(archive_entry_mtime(entry))) return (0); /* If this platform supports fractional seconds, try those. */ #if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC diff --git a/libarchive/archive_write_disk_set_standard_lookup.c b/libarchive/archive_write_disk_set_standard_lookup.c index 3b868fb..5c766d7 100644 --- a/libarchive/archive_write_disk_set_standard_lookup.c +++ b/libarchive/archive_write_disk_set_standard_lookup.c @@ -84,15 +84,13 @@ static void cleanup(void *); int archive_write_disk_set_standard_lookup(struct archive *a) { - struct bucket *ucache = malloc(cache_size * sizeof(struct bucket)); - struct bucket *gcache = malloc(cache_size * sizeof(struct bucket)); + struct bucket *ucache = calloc(cache_size, sizeof(struct bucket)); + struct bucket *gcache = calloc(cache_size, sizeof(struct bucket)); if (ucache == NULL || gcache == NULL) { free(ucache); free(gcache); return (ARCHIVE_FATAL); } - memset(ucache, 0, cache_size * sizeof(struct bucket)); - memset(gcache, 0, cache_size * sizeof(struct bucket)); archive_write_disk_set_group_lookup(a, gcache, lookup_gid, cleanup); archive_write_disk_set_user_lookup(a, ucache, lookup_uid, cleanup); return (ARCHIVE_OK); diff --git a/libarchive/archive_write_disk_windows.c b/libarchive/archive_write_disk_windows.c index da76c54..94b016e 100644 --- a/libarchive/archive_write_disk_windows.c +++ b/libarchive/archive_write_disk_windows.c @@ -192,7 +192,7 @@ struct archive_write_disk { /* * Default mode for dirs created automatically (will be modified by umask). - * Note that POSIX specifies 0777 for implicity-created dirs, "modified + * Note that POSIX specifies 0777 for implicitly-created dirs, "modified * by the process' file creation mask." */ #define DEFAULT_DIR_MODE 0777 @@ -396,7 +396,7 @@ permissive_name_w(struct archive_write_disk *a) } /* - * A full-pathname pointig a network drive + * A full-pathname pointing to a network drive * like "\\\\file". */ if (wnp[0] == L'\\' && wnp[1] == L'\\' && wnp[2] != L'\\') { @@ -1221,10 +1221,9 @@ archive_write_disk_new(void) { struct archive_write_disk *a; - a = (struct archive_write_disk *)malloc(sizeof(*a)); + a = (struct archive_write_disk *)calloc(1, sizeof(*a)); if (a == NULL) return (NULL); - memset(a, 0, sizeof(*a)); a->archive.magic = ARCHIVE_WRITE_DISK_MAGIC; /* We're ready to write a header immediately. */ a->archive.state = ARCHIVE_STATE_HEADER; diff --git a/libarchive/archive_write_open.3 b/libarchive/archive_write_open.3 index a52959b..457873e 100644 --- a/libarchive/archive_write_open.3 +++ b/libarchive/archive_write_open.3 @@ -66,6 +66,7 @@ Freeze the settings, open the archive, and prepare for writing entries. This is the most generic form of this function, which accepts pointers to three callback functions which will be invoked by the compression layer to write the constructed archive. +This does not alter the default archive padding. .It Fn archive_write_open_fd A convenience form of .Fn archive_write_open @@ -123,12 +124,21 @@ is currently in use. You should be careful to ensure that this variable remains allocated until after the archive is closed. +This function will disable padding unless you +have specifically set the block size. .El More information about the .Va struct archive object and the overall design of the library can be found in the .Xr libarchive 3 overview. +.Pp +Note that the convenience forms above vary in how +they block the output. +See +.Xr archive_write_blocksize 3 +if you need to control the block size used for writes +or the end-of-file padding behavior. .\" .Sh CLIENT CALLBACKS To use this library, you will need to define and register @@ -226,6 +236,7 @@ functions. .Xr tar 1 , .Xr libarchive 3 , .Xr archive_write 3 , +.Xr archive_write_blocksize 3 , .Xr archive_write_filter 3 , .Xr archive_write_format 3 , .Xr archive_write_new 3 , diff --git a/libarchive/archive_write_open_memory.c b/libarchive/archive_write_open_memory.c index 4f8d679..ea6ae0a 100644 --- a/libarchive/archive_write_open_memory.c +++ b/libarchive/archive_write_open_memory.c @@ -53,12 +53,11 @@ archive_write_open_memory(struct archive *a, void *buff, size_t buffSize, size_t { struct write_memory_data *mine; - mine = (struct write_memory_data *)malloc(sizeof(*mine)); + mine = (struct write_memory_data *)calloc(1, sizeof(*mine)); if (mine == NULL) { archive_set_error(a, ENOMEM, "No memory"); return (ARCHIVE_FATAL); } - memset(mine, 0, sizeof(*mine)); mine->buff = buff; mine->size = buffSize; mine->client_size = used; diff --git a/libarchive/archive_write_set_format_7zip.c b/libarchive/archive_write_set_format_7zip.c index fc6ccfe..41ed74d 100644 --- a/libarchive/archive_write_set_format_7zip.c +++ b/libarchive/archive_write_set_format_7zip.c @@ -205,7 +205,7 @@ struct _7zip { /* * The list of the file entries which has its contents is used to * manage struct file objects. - * We use 'next' a menber of struct file to chain. + * We use 'next' (a member of struct file) to chain. */ struct { struct file *first; @@ -1358,7 +1358,7 @@ make_header(struct archive_write *a, uint64_t offset, uint64_t pack_size, if (r < 0) return (r); - /* Write Nume size. */ + /* Write Name size. */ r = enc_uint64(a, zip->total_bytes_entry_name+1); if (r < 0) return (r); diff --git a/libarchive/archive_write_set_format_ar.c b/libarchive/archive_write_set_format_ar.c index 9f17564..c9771d8 100644 --- a/libarchive/archive_write_set_format_ar.c +++ b/libarchive/archive_write_set_format_ar.c @@ -126,12 +126,11 @@ archive_write_set_format_ar(struct archive_write *a) if (a->format_free != NULL) (a->format_free)(a); - ar = (struct ar_w *)malloc(sizeof(*ar)); + ar = (struct ar_w *)calloc(1, sizeof(*ar)); if (ar == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate ar data"); return (ARCHIVE_FATAL); } - memset(ar, 0, sizeof(*ar)); a->format_data = ar; a->format_name = "ar"; diff --git a/libarchive/archive_write_set_format_cpio.c b/libarchive/archive_write_set_format_cpio.c index 3526493..a4c9d1e 100644 --- a/libarchive/archive_write_set_format_cpio.c +++ b/libarchive/archive_write_set_format_cpio.c @@ -289,7 +289,7 @@ write_header(struct archive_write *a, struct archive_entry *entry) sconv = get_sconv(a); #if defined(_WIN32) && !defined(__CYGWIN__) - /* Make sure the path separators in pahtname, hardlink and symlink + /* Make sure the path separators in pathname, hardlink and symlink * are all slash '/', not the Windows path separator '\'. */ entry_main = __la_win_entry_in_posix_pathseparator(entry); if (entry_main == NULL) { diff --git a/libarchive/archive_write_set_format_cpio_newc.c b/libarchive/archive_write_set_format_cpio_newc.c index a9bfa80..957f1a3 100644 --- a/libarchive/archive_write_set_format_cpio_newc.c +++ b/libarchive/archive_write_set_format_cpio_newc.c @@ -116,12 +116,11 @@ archive_write_set_format_cpio_newc(struct archive *_a) if (a->format_free != NULL) (a->format_free)(a); - cpio = (struct cpio *)malloc(sizeof(*cpio)); + cpio = (struct cpio *)calloc(1, sizeof(*cpio)); if (cpio == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data"); return (ARCHIVE_FATAL); } - memset(cpio, 0, sizeof(*cpio)); a->format_data = cpio; a->format_name = "cpio"; a->format_options = archive_write_newc_options; @@ -232,7 +231,7 @@ write_header(struct archive_write *a, struct archive_entry *entry) sconv = get_sconv(a); #if defined(_WIN32) && !defined(__CYGWIN__) - /* Make sure the path separators in pahtname, hardlink and symlink + /* Make sure the path separators in pathname, hardlink and symlink * are all slash '/', not the Windows path separator '\'. */ entry_main = __la_win_entry_in_posix_pathseparator(entry); if (entry_main == NULL) { diff --git a/libarchive/archive_write_set_format_gnutar.c b/libarchive/archive_write_set_format_gnutar.c index 1d635d2..2d858c9 100644 --- a/libarchive/archive_write_set_format_gnutar.c +++ b/libarchive/archive_write_set_format_gnutar.c @@ -119,9 +119,9 @@ static const char template_header[] = { '0','0','0','0','0','0', '0','\0', /* gid, null termination: 8 bytes */ '0','0','0','0','0','0', '0','\0', - /* size, space termation: 12 bytes */ + /* size, space termination: 12 bytes */ '0','0','0','0','0','0','0','0','0','0','0', '\0', - /* mtime, space termation: 12 bytes */ + /* mtime, space termination: 12 bytes */ '0','0','0','0','0','0','0','0','0','0','0', '\0', /* Initial checksum value: 8 spaces */ ' ',' ',' ',' ',' ',' ',' ',' ', @@ -368,7 +368,7 @@ archive_write_gnutar_header(struct archive_write *a, } #if defined(_WIN32) && !defined(__CYGWIN__) - /* Make sure the path separators in pahtname, hardlink and symlink + /* Make sure the path separators in pathname, hardlink and symlink * are all slash '/', not the Windows path separator '\'. */ entry_main = __la_win_entry_in_posix_pathseparator(entry); if (entry_main == NULL) { @@ -478,15 +478,15 @@ archive_write_gnutar_header(struct archive_write *a, archive_entry_set_pathname(temp, "././@LongLink"); archive_entry_set_size(temp, length); ret = archive_format_gnutar_header(a, buff, temp, 'K'); + archive_entry_free(temp); if (ret < ARCHIVE_WARN) goto exit_write_header; ret = __archive_write_output(a, buff, 512); - if(ret < ARCHIVE_WARN) + if (ret < ARCHIVE_WARN) goto exit_write_header; - archive_entry_free(temp); /* Write name and trailing null byte. */ ret = __archive_write_output(a, gnutar->linkname, length); - if(ret < ARCHIVE_WARN) + if (ret < ARCHIVE_WARN) goto exit_write_header; /* Pad to 512 bytes */ ret = __archive_write_nulls(a, 0x1ff & (-(ssize_t)length)); @@ -508,12 +508,12 @@ archive_write_gnutar_header(struct archive_write *a, archive_entry_set_pathname(temp, "././@LongLink"); archive_entry_set_size(temp, length); ret = archive_format_gnutar_header(a, buff, temp, 'L'); + archive_entry_free(temp); if (ret < ARCHIVE_WARN) goto exit_write_header; ret = __archive_write_output(a, buff, 512); if(ret < ARCHIVE_WARN) goto exit_write_header; - archive_entry_free(temp); /* Write pathname + trailing null byte. */ ret = __archive_write_output(a, pathname, length); if(ret < ARCHIVE_WARN) diff --git a/libarchive/archive_write_set_format_iso9660.c b/libarchive/archive_write_set_format_iso9660.c index cb3e54e..4e91097 100644 --- a/libarchive/archive_write_set_format_iso9660.c +++ b/libarchive/archive_write_set_format_iso9660.c @@ -161,7 +161,7 @@ struct isofile { /* Used for managing struct isofile list. */ struct isofile *allnext; struct isofile *datanext; - /* Used for managing a hardlined struct isofile list. */ + /* Used for managing a hardlinked struct isofile list. */ struct isofile *hlnext; struct isofile *hardlink_target; @@ -436,7 +436,7 @@ struct iso_option { * Type : string * Default: Auto detect * : We check a size of boot image; - * : If ths size is just 1.22M/1.44M/2.88M, + * : If the size is just 1.22M/1.44M/2.88M, * : we assume boot_type is 'fd'; * : otherwise boot_type is 'no-emulation'. * COMPAT : @@ -528,7 +528,7 @@ struct iso_option { * - allow more then 8 depths of directory trees; * - disable a version number to a File Name; * - disable a forced period to the tail of a File Name; - * - the maxinum length of files and directories is raised to 193. + * - the maximum length of files and directories is raised to 193. * if rockridge option is disabled, raised to 207. */ unsigned int iso_level:3; @@ -626,7 +626,7 @@ struct iso_option { * : NOTE Our rockridge=useful option does not set a zero * : to uid and gid, you should use application * : option such as --gid,--gname,--uid and --uname - * : badtar options instead. + * : bsdtar options instead. * Type : boolean/string * Default: Enabled as rockridge=useful * COMPAT : mkisofs -r / -R @@ -660,7 +660,7 @@ struct iso_option { * : for making zisofs. * : When the file size is less than one Logical Block * : size, that file will not zisofs'ed since it does - * : reduece an ISO-image size. + * : reduce an ISO-image size. * : * : When you specify option 'boot=', that * : 'boot-image' file won't be converted to zisofs file. @@ -680,7 +680,7 @@ struct iso9660 { /* The creation time of ISO image. */ time_t birth_time; /* A file stream of a temporary file, which file contents - * save to until ISO iamge can be created. */ + * save to until ISO image can be created. */ int temp_fd; struct isofile *cur_file; @@ -703,7 +703,7 @@ struct iso9660 { } all_file_list; /* A list of struct isofile entries which have its - * contents and are not a directory, a hardlined file + * contents and are not a directory, a hardlinked file * and a symlink file. */ struct { struct isofile *first; @@ -1907,9 +1907,9 @@ iso9660_close(struct archive_write *a) iso9660->primary.rootent); if (ret < 0) return (ret); - /* Make sure we have UTF-16BE convertors. - * if there is no file entry, convertors are still - * uninitilized. */ + /* Make sure we have UTF-16BE converters. + * if there is no file entry, converters are still + * uninitialized. */ if (iso9660->sconv_to_utf16be == NULL) { iso9660->sconv_to_utf16be = archive_string_conversion_to_charset( @@ -1995,7 +1995,7 @@ iso9660_close(struct archive_write *a) * Write an ISO 9660 image. */ - /* Switc to start using wbuff as file buffer. */ + /* Switch to start using wbuff as file buffer. */ iso9660->wbuff_remaining = wb_buffmax(); iso9660->wbuff_type = WB_TO_STREAM; iso9660->wbuff_offset = 0; @@ -2524,7 +2524,8 @@ get_tmfromtime(struct tm *tm, time_t *t) tzset(); localtime_r(t, tm); #elif HAVE__LOCALTIME64_S - _localtime64_s(tm, t); + __time64_t tmp_t = (__time64_t) *t; //time_t may be shorter than 64 bits + _localtime64_s(tm, &tmp_t); #else memcpy(tm, localtime(t), sizeof(*tm)); #endif @@ -2553,7 +2554,7 @@ set_date_time(unsigned char *p, time_t t) static void set_date_time_null(unsigned char *p) { - memset(p, '0', 16); + memset(p, (int)'0', 16); p[16] = 0; } @@ -2959,7 +2960,7 @@ set_directory_record_rr(unsigned char *bp, int dr_len, gid = archive_entry_gid(file->entry); if (iso9660->opt.rr == OPT_RR_USEFUL) { /* - * This action is simular mkisofs -r option + * This action is similar to mkisofs -r option * but our rockridge=useful option does not * set a zero to uid and gid. */ @@ -3024,8 +3025,8 @@ set_directory_record_rr(unsigned char *bp, int dr_len, * +----+----+----+----+----+ * 10 11 12 13 14 15 * - * - cflg : flag of componet - * - clen : length of componet + * - cflg : flag of component + * - clen : length of component */ const char *sl; char sl_last; @@ -3108,7 +3109,7 @@ set_directory_record_rr(unsigned char *bp, int dr_len, /* * flg len * +----+----+ - * | 02 | 00 | CURREENT component. + * | 02 | 00 | CURRENT component. * +----+----+ (".") */ if (nc != NULL) { @@ -3947,7 +3948,7 @@ write_VD(struct archive_write *a, struct vdd *vdd) "Abstract File", 0, D_CHAR); if (r != ARCHIVE_OK) return (r); - /* Bibliongraphic File Identifier */ + /* Bibliographic File Identifier */ r = set_file_identifier(bp, 777, 813, vdc, a, vdd, &(iso9660->bibliographic_file_identifier), "Bibliongraphic File", 0, D_CHAR); @@ -4073,7 +4074,8 @@ write_information_block(struct archive_write *a) memset(info.s, 0, info_size); opt = 0; #if defined(HAVE__CTIME64_S) - _ctime64_s(buf, sizeof(buf), &(iso9660->birth_time)); + __time64_t iso9660_birth_time_tmp = (__time64_t) iso9660->birth_time; //time_t may be shorter than 64 bits + _ctime64_s(buf, sizeof(buf), &(iso9660_birth_time_tmp)); #elif defined(HAVE_CTIME_R) ctime_r(&(iso9660->birth_time), buf); #else @@ -4558,7 +4560,7 @@ write_file_descriptors(struct archive_write *a) file->cur_content = &(file->content); do { blocks += file->cur_content->blocks; - /* Next fragument */ + /* Next fragment */ file->cur_content = file->cur_content->next; } while (file->cur_content != NULL); } @@ -4748,7 +4750,7 @@ isofile_gen_utility_names(struct archive_write *a, struct isofile *file) } /* - * Converte a filename to UTF-16BE. + * Convert a filename to UTF-16BE. */ if (0 > archive_entry_pathname_l(file->entry, &u16, &u16len, iso9660->sconv_to_utf16be)) { @@ -5512,7 +5514,7 @@ isoent_setup_file_location(struct iso9660 *iso9660, int location) file->cur_content->location = location; location += file->cur_content->blocks; total_block += file->cur_content->blocks; - /* Next fragument */ + /* Next fragment */ file->cur_content = file->cur_content->next; } while (file->cur_content != NULL); } @@ -6135,7 +6137,7 @@ isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent, off = ffmax - extlen; if (off == 0) { /* A dot('.') character - * does't place to the first + * doesn't place to the first * byte of identifier. */ off ++; extlen --; @@ -6164,7 +6166,7 @@ isoent_gen_iso9660_identifier(struct archive_write *a, struct isoent *isoent, np->id_len = l = ext_off + np->ext_len; /* Make an offset of the number which is used to be set - * hexadecimal number to avoid duplicate identififier. */ + * hexadecimal number to avoid duplicate identifier. */ if (iso9660->opt.iso_level == 1) { if (ext_off >= 5) noff = 5; @@ -6742,7 +6744,7 @@ isoent_rr_move(struct archive_write *a) int r; pt = &(iso9660->primary.pathtbl[MAX_DEPTH-1]); - /* Theare aren't level 8 directories reaching a deepr level. */ + /* There aren't level 8 directories reaching a deeper level. */ if (pt->cnt == 0) return (ARCHIVE_OK); @@ -6813,7 +6815,7 @@ _compare_path_table(const void *v1, const void *v2) if (cmp != 0) return (cmp); - /* Compare indetifier */ + /* Compare identifier */ s1 = p1->identifier; s2 = p2->identifier; l = p1->ext_off; @@ -6855,7 +6857,7 @@ _compare_path_table_joliet(const void *v1, const void *v2) if (cmp != 0) return (cmp); - /* Compare indetifier */ + /* Compare identifier */ s1 = (const unsigned char *)p1->identifier; s2 = (const unsigned char *)p2->identifier; l = p1->ext_off; @@ -7149,7 +7151,7 @@ isoent_create_boot_catalog(struct archive_write *a, struct isoent *rootent) iso9660->el_torito.catalog = isoent; /* - * Get a boot medai type. + * Get a boot media type. */ switch (iso9660->opt.boot_type) { default: diff --git a/libarchive/archive_write_set_format_mtree.c b/libarchive/archive_write_set_format_mtree.c index b686303..493d473 100644 --- a/libarchive/archive_write_set_format_mtree.c +++ b/libarchive/archive_write_set_format_mtree.c @@ -1840,9 +1840,9 @@ mtree_entry_setup_filenames(struct archive_write *a, struct mtree_entry *file, len = strlen(p); /* - * Add "./" prefiex. + * Add "./" prefix. * NOTE: If the pathname does not have a path separator, we have - * to add "./" to the head of the pathename because mtree reader + * to add "./" to the head of the pathname because mtree reader * will suppose that it is v1(a.k.a classic) mtree format and * change the directory unexpectedly and so it will make a wrong * path. diff --git a/libarchive/archive_write_set_format_pax.c b/libarchive/archive_write_set_format_pax.c index 6f7fe78..6a301ac 100644 --- a/libarchive/archive_write_set_format_pax.c +++ b/libarchive/archive_write_set_format_pax.c @@ -1,6 +1,7 @@ /*- * Copyright (c) 2003-2007 Tim Kientzle * Copyright (c) 2010-2012 Michihiro NAKAJIMA + * Copyright (c) 2016 Martin Matuska * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -61,15 +62,24 @@ struct pax { struct sparse_block *sparse_tail; struct archive_string_conv *sconv_utf8; int opt_binary; + + unsigned flags; +#define WRITE_SCHILY_XATTR (1 << 0) +#define WRITE_LIBARCHIVE_XATTR (1 << 1) }; static void add_pax_attr(struct archive_string *, const char *key, const char *value); +static void add_pax_attr_binary(struct archive_string *, + const char *key, + const char *value, size_t value_len); static void add_pax_attr_int(struct archive_string *, const char *key, int64_t value); static void add_pax_attr_time(struct archive_string *, const char *key, int64_t sec, unsigned long nanos); +static int add_pax_acl(struct archive_write *, + struct archive_entry *, struct pax *, int); static ssize_t archive_write_pax_data(struct archive_write *, const void *, size_t); static int archive_write_pax_close(struct archive_write *); @@ -127,13 +137,14 @@ archive_write_set_format_pax(struct archive *_a) if (a->format_free != NULL) (a->format_free)(a); - pax = (struct pax *)malloc(sizeof(*pax)); + pax = (struct pax *)calloc(1, sizeof(*pax)); if (pax == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate pax data"); return (ARCHIVE_FATAL); } - memset(pax, 0, sizeof(*pax)); + pax->flags = WRITE_LIBARCHIVE_XATTR | WRITE_SCHILY_XATTR; + a->format_data = pax; a->format_name = "pax"; a->format_options = archive_write_pax_options; @@ -273,6 +284,17 @@ add_pax_attr_int(struct archive_string *as, const char *key, int64_t value) static void add_pax_attr(struct archive_string *as, const char *key, const char *value) { + add_pax_attr_binary(as, key, value, strlen(value)); +} + +/* + * Add a key/value attribute to the pax header. This function handles + * binary values. + */ +static void +add_pax_attr_binary(struct archive_string *as, const char *key, + const char *value, size_t value_len) +{ int digits, i, len, next_ten; char tmp[1 + 3 * sizeof(int)]; /* < 3 base-10 digits per byte */ @@ -280,7 +302,7 @@ add_pax_attr(struct archive_string *as, const char *key, const char *value) * PAX attributes have the following layout: * <=> */ - len = 1 + (int)strlen(key) + 1 + (int)strlen(value) + 1; + len = 1 + (int)strlen(key) + 1 + (int)value_len + 1; /* * The field includes the length of the field, so @@ -311,21 +333,47 @@ add_pax_attr(struct archive_string *as, const char *key, const char *value) archive_strappend_char(as, ' '); archive_strcat(as, key); archive_strappend_char(as, '='); - archive_strcat(as, value); + archive_array_append(as, value, value_len); archive_strappend_char(as, '\n'); } +static void +archive_write_pax_header_xattr(struct pax *pax, const char *encoded_name, + const void *value, size_t value_len) +{ + struct archive_string s; + char *encoded_value; + + if (pax->flags & WRITE_LIBARCHIVE_XATTR) { + encoded_value = base64_encode((const char *)value, value_len); + + if (encoded_name != NULL && encoded_value != NULL) { + archive_string_init(&s); + archive_strcpy(&s, "LIBARCHIVE.xattr."); + archive_strcat(&s, encoded_name); + add_pax_attr(&(pax->pax_header), s.s, encoded_value); + archive_string_free(&s); + } + free(encoded_value); + } + if (pax->flags & WRITE_SCHILY_XATTR) { + archive_string_init(&s); + archive_strcpy(&s, "SCHILY.xattr."); + archive_strcat(&s, encoded_name); + add_pax_attr_binary(&(pax->pax_header), s.s, value, value_len); + archive_string_free(&s); + } +} + static int archive_write_pax_header_xattrs(struct archive_write *a, struct pax *pax, struct archive_entry *entry) { - struct archive_string s; int i = archive_entry_xattr_reset(entry); while (i--) { const char *name; const void *value; - char *encoded_value; char *url_encoded_name = NULL, *encoded_name = NULL; size_t size; int r; @@ -346,16 +394,9 @@ archive_write_pax_header_xattrs(struct archive_write *a, } } - encoded_value = base64_encode((const char *)value, size); + archive_write_pax_header_xattr(pax, encoded_name, + value, size); - if (encoded_name != NULL && encoded_value != NULL) { - archive_string_init(&s); - archive_strcpy(&s, "LIBARCHIVE.xattr."); - archive_strcat(&s, encoded_name); - add_pax_attr(&(pax->pax_header), s.s, encoded_value); - archive_string_free(&s); - } - free(encoded_value); } return (ARCHIVE_OK); } @@ -450,6 +491,45 @@ get_entry_symlink(struct archive_write *a, struct archive_entry *entry, return (ARCHIVE_OK); } +/* Add ACL to pax header */ +static int +add_pax_acl(struct archive_write *a, + struct archive_entry *entry, struct pax *pax, int flags) +{ + char *p; + const char *attr; + int acl_types; + + acl_types = archive_entry_acl_types(entry); + + if ((acl_types & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) + attr = "SCHILY.acl.ace"; + else if ((flags & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) + attr = "SCHILY.acl.access"; + else if ((flags & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0) + attr = "SCHILY.acl.default"; + else + return (ARCHIVE_FATAL); + + p = archive_entry_acl_to_text_l(entry, NULL, flags, pax->sconv_utf8); + if (p == NULL) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, "%s %s", + "Can't allocate memory for ", attr); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, "%s %s %s", + "Can't translate ", attr, " to UTF-8"); + return(ARCHIVE_WARN); + } else if (*p != '\0') { + add_pax_attr(&(pax->pax_header), + attr, p); + free(p); + } + return(ARCHIVE_OK); +} + /* * TODO: Consider adding 'comment' and 'charset' fields to * archive_entry so that clients can specify them. Also, consider @@ -466,6 +546,7 @@ archive_write_pax_header(struct archive_write *a, const char *p; const char *suffix; int need_extension, r, ret; + int acl_types; int sparse_count; uint64_t sparse_total, real_size; struct pax *pax; @@ -709,7 +790,7 @@ archive_write_pax_header(struct archive_write *a, /* Copy entry so we can modify it as needed. */ #if defined(_WIN32) && !defined(__CYGWIN__) - /* Make sure the path separators in pahtname, hardlink and symlink + /* Make sure the path separators in pathname, hardlink and symlink * are all slash '/', not the Windows path separator '\'. */ entry_main = __la_win_entry_in_posix_pathseparator(entry_original); if (entry_main == entry_original) @@ -1017,16 +1098,6 @@ archive_write_pax_header(struct archive_write *a, if (!need_extension && p != NULL && *p != '\0') need_extension = 1; - /* If there are non-trivial ACL entries, we need an extension. */ - if (!need_extension && archive_entry_acl_count(entry_original, - ARCHIVE_ENTRY_ACL_TYPE_ACCESS) > 0) - need_extension = 1; - - /* If there are non-trivial ACL entries, we need an extension. */ - if (!need_extension && archive_entry_acl_count(entry_original, - ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) > 0) - need_extension = 1; - /* If there are extended attributes, we need an extension */ if (!need_extension && archive_entry_xattr_count(entry_original) > 0) need_extension = 1; @@ -1035,6 +1106,12 @@ archive_write_pax_header(struct archive_write *a, if (!need_extension && sparse_count > 0) need_extension = 1; + acl_types = archive_entry_acl_types(entry_original); + + /* If there are any ACL entries, we need an extension */ + if (!need_extension && acl_types != 0) + need_extension = 1; + /* * Libarchive used to include these in extended headers for * restricted pax format, but that confused people who @@ -1086,43 +1163,29 @@ archive_write_pax_header(struct archive_write *a, add_pax_attr(&(pax->pax_header), "SCHILY.fflags", p); /* I use star-compatible ACL attributes. */ - r = archive_entry_acl_text_l(entry_original, - ARCHIVE_ENTRY_ACL_TYPE_ACCESS | - ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID, - &p, NULL, pax->sconv_utf8); - if (r != 0) { - if (errno == ENOMEM) { - archive_set_error(&a->archive, ENOMEM, - "Can't allocate memory for " - "ACL.access"); + if ((acl_types & ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) { + ret = add_pax_acl(a, entry_original, pax, + ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID | + ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA | + ARCHIVE_ENTRY_ACL_STYLE_COMPACT); + if (ret == ARCHIVE_FATAL) return (ARCHIVE_FATAL); - } - archive_set_error(&a->archive, - ARCHIVE_ERRNO_FILE_FORMAT, - "Can't translate ACL.access to UTF-8"); - ret = ARCHIVE_WARN; - } else if (p != NULL && *p != '\0') { - add_pax_attr(&(pax->pax_header), - "SCHILY.acl.access", p); } - r = archive_entry_acl_text_l(entry_original, - ARCHIVE_ENTRY_ACL_TYPE_DEFAULT | - ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID, - &p, NULL, pax->sconv_utf8); - if (r != 0) { - if (errno == ENOMEM) { - archive_set_error(&a->archive, ENOMEM, - "Can't allocate memory for " - "ACL.default"); + if (acl_types & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) { + ret = add_pax_acl(a, entry_original, pax, + ARCHIVE_ENTRY_ACL_TYPE_ACCESS | + ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID | + ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA); + if (ret == ARCHIVE_FATAL) + return (ARCHIVE_FATAL); + } + if (acl_types & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) { + ret = add_pax_acl(a, entry_original, pax, + ARCHIVE_ENTRY_ACL_TYPE_DEFAULT | + ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID | + ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA); + if (ret == ARCHIVE_FATAL) return (ARCHIVE_FATAL); - } - archive_set_error(&a->archive, - ARCHIVE_ERRNO_FILE_FORMAT, - "Can't translate ACL.default to UTF-8"); - ret = ARCHIVE_WARN; - } else if (p != NULL && *p != '\0') { - add_pax_attr(&(pax->pax_header), - "SCHILY.acl.default", p); } /* We use GNU-tar-compatible sparse attributes. */ diff --git a/libarchive/archive_write_set_format_shar.c b/libarchive/archive_write_set_format_shar.c index c033fb3..5be310a 100644 --- a/libarchive/archive_write_set_format_shar.c +++ b/libarchive/archive_write_set_format_shar.c @@ -113,12 +113,11 @@ archive_write_set_format_shar(struct archive *_a) if (a->format_free != NULL) (a->format_free)(a); - shar = (struct shar *)malloc(sizeof(*shar)); + shar = (struct shar *)calloc(1, sizeof(*shar)); if (shar == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate shar data"); return (ARCHIVE_FATAL); } - memset(shar, 0, sizeof(*shar)); archive_string_init(&shar->work); archive_string_init(&shar->quoted_name); a->format_data = shar; diff --git a/libarchive/archive_write_set_format_ustar.c b/libarchive/archive_write_set_format_ustar.c index 484ab34..c54aeab 100644 --- a/libarchive/archive_write_set_format_ustar.c +++ b/libarchive/archive_write_set_format_ustar.c @@ -114,9 +114,9 @@ static const char template_header[] = { '0','0','0','0','0','0', ' ','\0', /* gid, space-null termination: 8 bytes */ '0','0','0','0','0','0', ' ','\0', - /* size, space termation: 12 bytes */ + /* size, space termination: 12 bytes */ '0','0','0','0','0','0','0','0','0','0','0', ' ', - /* mtime, space termation: 12 bytes */ + /* mtime, space termination: 12 bytes */ '0','0','0','0','0','0','0','0','0','0','0', ' ', /* Initial checksum value: 8 spaces */ ' ',' ',' ',' ',' ',' ',' ',' ', @@ -184,13 +184,12 @@ archive_write_set_format_ustar(struct archive *_a) return (ARCHIVE_FATAL); } - ustar = (struct ustar *)malloc(sizeof(*ustar)); + ustar = (struct ustar *)calloc(1, sizeof(*ustar)); if (ustar == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate ustar data"); return (ARCHIVE_FATAL); } - memset(ustar, 0, sizeof(*ustar)); a->format_data = ustar; a->format_name = "ustar"; a->format_options = archive_write_ustar_options; @@ -307,7 +306,7 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry) * case getting WCS failed. On POSIX, this is a * normal operation. */ - if (p != NULL && p[strlen(p) - 1] != '/') { + if (p != NULL && p[0] != '\0' && p[strlen(p) - 1] != '/') { struct archive_string as; archive_string_init(&as); @@ -336,7 +335,7 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry) } #if defined(_WIN32) && !defined(__CYGWIN__) - /* Make sure the path separators in pahtname, hardlink and symlink + /* Make sure the path separators in pathname, hardlink and symlink * are all slash '/', not the Windows path separator '\'. */ entry_main = __la_win_entry_in_posix_pathseparator(entry); if (entry_main == NULL) { diff --git a/libarchive/archive_write_set_format_v7tar.c b/libarchive/archive_write_set_format_v7tar.c index 17efbaf..62b1522 100644 --- a/libarchive/archive_write_set_format_v7tar.c +++ b/libarchive/archive_write_set_format_v7tar.c @@ -98,9 +98,9 @@ static const char template_header[] = { '0','0','0','0','0','0', ' ','\0', /* gid, space-null termination: 8 bytes */ '0','0','0','0','0','0', ' ','\0', - /* size, space termation: 12 bytes */ + /* size, space termination: 12 bytes */ '0','0','0','0','0','0','0','0','0','0','0', ' ', - /* mtime, space termation: 12 bytes */ + /* mtime, space termination: 12 bytes */ '0','0','0','0','0','0','0','0','0','0','0', ' ', /* Initial checksum value: 8 spaces */ ' ',' ',' ',' ',' ',' ',' ',' ', @@ -161,13 +161,12 @@ archive_write_set_format_v7tar(struct archive *_a) return (ARCHIVE_FATAL); } - v7tar = (struct v7tar *)malloc(sizeof(*v7tar)); + v7tar = (struct v7tar *)calloc(1, sizeof(*v7tar)); if (v7tar == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate v7tar data"); return (ARCHIVE_FATAL); } - memset(v7tar, 0, sizeof(*v7tar)); a->format_data = v7tar; a->format_name = "tar (non-POSIX)"; a->format_options = archive_write_v7tar_options; @@ -314,7 +313,7 @@ archive_write_v7tar_header(struct archive_write *a, struct archive_entry *entry) } #if defined(_WIN32) && !defined(__CYGWIN__) - /* Make sure the path separators in pahtname, hardlink and symlink + /* Make sure the path separators in pathname, hardlink and symlink * are all slash '/', not the Windows path separator '\'. */ entry_main = __la_win_entry_in_posix_pathseparator(entry); if (entry_main == NULL) { diff --git a/libarchive/archive_write_set_format_warc.c b/libarchive/archive_write_set_format_warc.c index ea66929..8b6daf9 100644 --- a/libarchive/archive_write_set_format_warc.c +++ b/libarchive/archive_write_set_format_warc.c @@ -79,7 +79,7 @@ typedef enum { WT_RVIS, /* conversion, unsupported */ WT_CONV, - /* continutation, unsupported at the moment */ + /* continuation, unsupported at the moment */ WT_CONT, /* invalid type */ LAST_WT diff --git a/libarchive/archive_write_set_format_xar.c b/libarchive/archive_write_set_format_xar.c index a2dbc03..495f0d4 100644 --- a/libarchive/archive_write_set_format_xar.c +++ b/libarchive/archive_write_set_format_xar.c @@ -63,7 +63,7 @@ __FBSDID("$FreeBSD$"); * - When writing an XML element , * which is a file type a symbolic link is referencing is always marked * as "broken". Xar utility uses stat(2) to get the file type, but, in - * libarcive format writer, we should not use it; if it is needed, we + * libarchive format writer, we should not use it; if it is needed, we * should get about it at archive_read_disk.c. * - It is possible to appear both and elements. * Xar utility generates on BSD platform and on Linux @@ -192,7 +192,7 @@ struct file { struct file *parent; /* parent directory entry */ /* * To manage sub directory files. - * We use 'chnext' a menber of struct file to chain. + * We use 'chnext' (a member of struct file) to chain. */ struct { struct file *first; @@ -258,7 +258,7 @@ struct xar { /* * The list of all file entries is used to manage struct file * objects. - * We use 'next' a menber of struct file to chain. + * We use 'next' (a member of struct file) to chain. */ struct { struct file *first; @@ -266,7 +266,7 @@ struct xar { } file_list; /* * The list of hard-linked file entries. - * We use 'hlnext' a menber of struct file to chain. + * We use 'hlnext' (a member of struct file) to chain. */ struct archive_rb_tree hardlink_rbtree; }; @@ -1227,7 +1227,7 @@ make_file_entry(struct archive_write *a, xmlTextWriterPtr writer, case AE_IFLNK: /* * xar utility has checked a file type, which - * a symblic-link file has referenced. + * a symbolic-link file has referenced. * For example: * ../ref/ * The symlink target file is "../ref/" and its @@ -1237,8 +1237,8 @@ make_file_entry(struct archive_write *a, xmlTextWriterPtr writer, * The symlink target file is "../f" and its * file type is a regular file. * - * But our implemention cannot do it, and then we - * always record that a attribute "type" is "borken", + * But our implementation cannot do it, and then we + * always record that a attribute "type" is "broken", * for example: * foo/bar * It means "foo/bar" is not reachable. @@ -1544,7 +1544,7 @@ make_toc(struct archive_write *a) } /* - * Start recoding TOC + * Start recording TOC */ r = xmlTextWriterStartElement(writer, BAD_CAST("xar")); if (r < 0) { @@ -1961,6 +1961,7 @@ file_free(struct file *file) archive_string_free(&(file->basename)); archive_string_free(&(file->symlink)); archive_string_free(&(file->script)); + archive_entry_free(file->entry); free(file); } @@ -2484,7 +2485,7 @@ file_connect_hardlink_files(struct xar *xar) archive_entry_set_nlink(target->entry, hl->nlink); if (hl->nlink > 1) /* It means this file is a hardlink - * targe itself. */ + * target itself. */ target->hardlink_target = target; for (nf = target->hlnext; nf != NULL; nf = nf->hlnext) { @@ -2913,7 +2914,7 @@ compression_init_encoder_xz(struct archive *a, *strm = lzma_init_data; #ifdef HAVE_LZMA_STREAM_ENCODER_MT if (threads > 1) { - bzero(&mt_options, sizeof(mt_options)); + memset(&mt_options, 0, sizeof(mt_options)); mt_options.threads = threads; mt_options.timeout = 300; mt_options.filters = lzmafilters; diff --git a/libarchive/archive_write_set_format_zip.c b/libarchive/archive_write_set_format_zip.c index e4edb81..f69b846 100644 --- a/libarchive/archive_write_set_format_zip.c +++ b/libarchive/archive_write_set_format_zip.c @@ -592,7 +592,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) #if defined(_WIN32) && !defined(__CYGWIN__) - /* Make sure the path separators in pahtname, hardlink and symlink + /* Make sure the path separators in pathname, hardlink and symlink * are all slash '/', not the Windows path separator '\'. */ zip->entry = __la_win_entry_in_posix_pathseparator(entry); if (zip->entry == entry) @@ -878,7 +878,7 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) || zip->entry_encryption == ENCRYPTION_WINZIP_AES256)) { memcpy(e, "\001\231\007\000\001\000AE", 8); - /* AES vendoer version AE-2 does not store a CRC. + /* AES vendor version AE-2 does not store a CRC. * WinZip 11 uses AE-1, which does store the CRC, * but it does not store the CRC when the file size * is less than 20 bytes. So we simulate what @@ -1013,7 +1013,7 @@ archive_write_zip_data(struct archive_write *a, const void *buff, size_t s) if (zip->entry_flags & ZIP_ENTRY_FLAG_ENCRYPTED) { switch (zip->entry_encryption) { case ENCRYPTION_TRADITIONAL: - /* Initialize traditoinal PKWARE encryption context. */ + /* Initialize traditional PKWARE encryption context. */ if (!zip->tctx_valid) { ret = init_traditional_pkware_encryption(a); if (ret != ARCHIVE_OK) @@ -1499,7 +1499,7 @@ trad_enc_update_keys(struct trad_enc_ctx *ctx, uint8_t c) } static uint8_t -trad_enc_decypt_byte(struct trad_enc_ctx *ctx) +trad_enc_decrypt_byte(struct trad_enc_ctx *ctx) { unsigned temp = ctx->keys[2] | 2; return (uint8_t)((temp * (temp ^ 1)) >> 8) & 0xff; @@ -1515,7 +1515,7 @@ trad_enc_encrypt_update(struct trad_enc_ctx *ctx, const uint8_t *in, for (i = 0; i < max; i++) { uint8_t t = in[i]; - out[i] = t ^ trad_enc_decypt_byte(ctx); + out[i] = t ^ trad_enc_decrypt_byte(ctx); trad_enc_update_keys(ctx, t); } return i; @@ -1626,7 +1626,7 @@ init_winzip_aes_encryption(struct archive_write *a) return (ARCHIVE_FAILED); } - /* Set a passowrd verification value after the 'salt'. */ + /* Set a password verification value after the 'salt'. */ salt[salt_len] = derived_key[key_len * 2]; salt[salt_len + 1] = derived_key[key_len * 2 + 1]; diff --git a/libarchive/config_freebsd.h b/libarchive/config_freebsd.h index 2073431..215e886 100644 --- a/libarchive/config_freebsd.h +++ b/libarchive/config_freebsd.h @@ -28,6 +28,7 @@ /* FreeBSD 5.0 and later have 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 @@ -39,6 +40,7 @@ #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 diff --git a/libarchive/libarchive-formats.5 b/libarchive/libarchive-formats.5 index 9cec760..62359dd 100644 --- a/libarchive/libarchive-formats.5 +++ b/libarchive/libarchive-formats.5 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd March 18, 2012 +.Dd December 27, 2016 .Dt LIBARCHIVE-FORMATS 5 .Os .Sh NAME @@ -191,8 +191,6 @@ and device numbers. .It Solaris extensions Libarchive recognizes ACL and extended attribute records written by Solaris tar. -Currently, libarchive only has support for old-style ACLs; the -newer NFSv4 ACLs are recognized but discarded. .El .Pp The first tar program appeared in Seventh Edition Unix in 1979. diff --git a/libarchive/tar.5 b/libarchive/tar.5 index 6e6f0c0..30b837d 100644 --- a/libarchive/tar.5 +++ b/libarchive/tar.5 @@ -1,4 +1,5 @@ .\" Copyright (c) 2003-2009 Tim Kientzle +.\" Copyright (c) 2016 Martin Matuska .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -24,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 23, 2011 +.Dd December 27, 2016 .Dt TAR 5 .Os .Sh NAME @@ -440,11 +441,11 @@ archives to store files much larger than the historic 8GB limit. Vendor-specific attributes used by Joerg Schilling's .Nm star implementation. -.It Cm SCHILY.acl.access , Cm SCHILY.acl.default -Stores the access and default ACLs as textual strings in a format +.It Cm SCHILY.acl.access , Cm SCHILY.acl.default, Cm SCHILY.acl.ace +Stores the access, default and NFSv4 ACLs as textual strings in a format that is an extension of the format specified by POSIX.1e draft 17. -In particular, each user or group access specification can include a fourth -colon-separated field with the numeric UID or GID. +In particular, each user or group access specification can include +an additional colon-separated field with the numeric UID or GID. This allows ACLs to be restored on systems that may not have complete user or group information available (such as when NIS/YP or LDAP services are temporarily unavailable). diff --git a/libarchive/xxhash.c b/libarchive/xxhash.c index d7f8e96..6f5ba52 100644 --- a/libarchive/xxhash.c +++ b/libarchive/xxhash.c @@ -29,10 +29,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. You can contact the author at : - xxHash source repository : http://code.google.com/p/xxhash/ */ +#include "archive_platform.h" + #include #include -#include "archive_platform.h" #include "archive_xxhash.h" #ifdef HAVE_LIBLZ4 @@ -60,7 +61,7 @@ You can contact the author at : ** By default, xxHash library provides endian-independent Hash values, based on little-endian convention. ** Results are therefore identical for little-endian and big-endian CPU. ** This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format. -** Should endian-independance be of no importance for your application, you may set the #define below to 1. +** Should endian-independence be of no importance for your application, you may set the #define below to 1. ** It will improve speed for Big-endian CPU. ** This option has no impact on Little_Endian CPU. */ https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=cdce7c619c58ec0947c036b93013445bb93e4be8 commit cdce7c619c58ec0947c036b93013445bb93e4be8 Author: Brad King AuthorDate: Mon Feb 20 07:49:59 2017 -0500 Commit: Brad King CommitDate: Mon Feb 20 07:50:23 2017 -0500 libarchive: Update script to get 3.3.0 diff --git a/Utilities/Scripts/update-libarchive.bash b/Utilities/Scripts/update-libarchive.bash index 3b42269..6c4eeb0 100755 --- a/Utilities/Scripts/update-libarchive.bash +++ b/Utilities/Scripts/update-libarchive.bash @@ -8,7 +8,7 @@ readonly name="LibArchive" readonly ownership="LibArchive Upstream " readonly subtree="Utilities/cmlibarchive" readonly repo="https://github.com/libarchive/libarchive.git" -readonly tag="master" +readonly tag="v3.3.0" readonly shortlog=false readonly paths=" CMakeLists.txt ----------------------------------------------------------------------- Summary of changes: CMakeLists.txt | 24 +- Utilities/Scripts/update-libarchive.bash | 2 +- Utilities/cmlibarchive/CMakeLists.txt | 132 +- .../build/cmake/CheckStructMember.cmake | 43 - Utilities/cmlibarchive/build/cmake/FindLZMA.cmake | 48 - Utilities/cmlibarchive/build/cmake/config.h.in | 18 + Utilities/cmlibarchive/build/version | 2 +- Utilities/cmlibarchive/libarchive/CMakeLists.txt | 18 + Utilities/cmlibarchive/libarchive/archive.h | 16 +- Utilities/cmlibarchive/libarchive/archive_acl.c | 1639 +++++++++++++++----- .../cmlibarchive/libarchive/archive_acl_private.h | 22 +- .../cmlibarchive/libarchive/archive_cryptor.c | 3 +- Utilities/cmlibarchive/libarchive/archive_entry.c | 124 +- Utilities/cmlibarchive/libarchive/archive_entry.h | 91 +- .../cmlibarchive/libarchive/archive_entry_acl.3 | 335 +++- .../cmlibarchive/libarchive/archive_entry_locale.h | 10 +- .../libarchive/archive_entry_strmode.c | 2 +- Utilities/cmlibarchive/libarchive/archive_match.c | 14 +- .../libarchive/archive_openssl_evp_private.h | 5 +- .../libarchive/archive_openssl_hmac_private.h | 6 +- .../cmlibarchive/libarchive/archive_options.c | 11 +- .../cmlibarchive/libarchive/archive_platform.h | 28 +- .../libarchive/archive_ppmd7_private.h | 2 +- Utilities/cmlibarchive/libarchive/archive_random.c | 2 +- Utilities/cmlibarchive/libarchive/archive_rb.c | 2 +- Utilities/cmlibarchive/libarchive/archive_read.c | 16 +- .../libarchive/archive_read_add_passphrase.c | 22 +- .../libarchive/archive_read_append_filter.c | 2 - .../cmlibarchive/libarchive/archive_read_disk.3 | 6 +- .../libarchive/archive_read_disk_entry_from_file.c | 1066 +++++++++++-- .../libarchive/archive_read_disk_posix.c | 71 +- .../archive_read_disk_set_standard_lookup.c | 2 + .../libarchive/archive_read_disk_windows.c | 29 +- .../libarchive/archive_read_extract2.c | 3 +- .../libarchive/archive_read_open_filename.c | 20 +- .../libarchive/archive_read_open_memory.c | 3 +- .../cmlibarchive/libarchive/archive_read_private.h | 3 +- .../libarchive/archive_read_support_filter_lz4.c | 13 +- .../libarchive/archive_read_support_filter_lzop.c | 2 +- .../archive_read_support_filter_program.c | 2 + .../libarchive/archive_read_support_filter_uu.c | 44 +- .../libarchive/archive_read_support_filter_xz.c | 194 +-- .../libarchive/archive_read_support_format_7zip.c | 39 +- .../libarchive/archive_read_support_format_ar.c | 22 +- .../libarchive/archive_read_support_format_cab.c | 15 +- .../libarchive/archive_read_support_format_cpio.c | 17 +- .../archive_read_support_format_iso9660.c | 40 +- .../libarchive/archive_read_support_format_lha.c | 13 +- .../libarchive/archive_read_support_format_mtree.c | 71 +- .../libarchive/archive_read_support_format_rar.c | 5 +- .../libarchive/archive_read_support_format_tar.c | 281 +++- .../libarchive/archive_read_support_format_warc.c | 239 +-- .../libarchive/archive_read_support_format_xar.c | 87 +- .../libarchive/archive_read_support_format_zip.c | 158 +- Utilities/cmlibarchive/libarchive/archive_string.c | 117 +- Utilities/cmlibarchive/libarchive/archive_string.h | 8 +- .../libarchive/archive_string_composition.h | 2 +- Utilities/cmlibarchive/libarchive/archive_util.c | 2 +- .../cmlibarchive/libarchive/archive_windows.c | 4 +- .../cmlibarchive/libarchive/archive_windows.h | 4 + Utilities/cmlibarchive/libarchive/archive_write.c | 8 +- .../libarchive/archive_write_add_filter_lz4.c | 4 +- .../libarchive/archive_write_add_filter_program.c | 1 + .../libarchive/archive_write_add_filter_xz.c | 2 +- .../libarchive/archive_write_disk_acl.c | 545 ++++++- .../libarchive/archive_write_disk_posix.c | 533 +++++-- .../archive_write_disk_set_standard_lookup.c | 6 +- .../libarchive/archive_write_disk_windows.c | 7 +- .../cmlibarchive/libarchive/archive_write_open.3 | 11 + .../libarchive/archive_write_open_memory.c | 3 +- .../libarchive/archive_write_set_format_7zip.c | 4 +- .../libarchive/archive_write_set_format_ar.c | 3 +- .../libarchive/archive_write_set_format_cpio.c | 2 +- .../archive_write_set_format_cpio_newc.c | 5 +- .../libarchive/archive_write_set_format_gnutar.c | 14 +- .../libarchive/archive_write_set_format_iso9660.c | 58 +- .../libarchive/archive_write_set_format_mtree.c | 4 +- .../libarchive/archive_write_set_format_pax.c | 183 ++- .../libarchive/archive_write_set_format_shar.c | 3 +- .../libarchive/archive_write_set_format_ustar.c | 11 +- .../libarchive/archive_write_set_format_v7tar.c | 9 +- .../libarchive/archive_write_set_format_warc.c | 2 +- .../libarchive/archive_write_set_format_xar.c | 21 +- .../libarchive/archive_write_set_format_zip.c | 12 +- Utilities/cmlibarchive/libarchive/config_freebsd.h | 2 + .../cmlibarchive/libarchive/libarchive-formats.5 | 4 +- Utilities/cmlibarchive/libarchive/tar.5 | 11 +- Utilities/cmlibarchive/libarchive/xxhash.c | 6 +- 88 files changed, 4714 insertions(+), 1981 deletions(-) delete mode 100644 Utilities/cmlibarchive/build/cmake/CheckStructMember.cmake delete mode 100644 Utilities/cmlibarchive/build/cmake/FindLZMA.cmake hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 22 13:23:27 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 22 Feb 2017 13:23:27 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-460-g4375971 Message-ID: <20170222182327.11C54F9FB9@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 4375971fb861de2a194f61668006fe2ce6641f0a (commit) via 0372802e4961bbcf05b6f5a4df447a7f19492b9b (commit) from c42f62b6bed8248fd99a48737c14054d09f973a7 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4375971fb861de2a194f61668006fe2ce6641f0a commit 4375971fb861de2a194f61668006fe2ce6641f0a Merge: c42f62b 0372802 Author: Brad King AuthorDate: Wed Feb 22 13:23:26 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 22 13:23:26 2017 -0500 Merge topic 'cmake_m4_find_package_var_check' into next 0372802e cmake.m4: do not set _XXXFLAGS or _LIBS var if already set https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0372802e4961bbcf05b6f5a4df447a7f19492b9b commit 0372802e4961bbcf05b6f5a4df447a7f19492b9b Author: John Donoghue AuthorDate: Sun Feb 12 13:57:19 2017 -0500 Commit: Brad King CommitDate: Wed Feb 22 13:22:42 2017 -0500 cmake.m4: do not set _XXXFLAGS or _LIBS var if already set * Auxiliary/cmake.m4 (CMAKE_FIND_PACKAGE): change var tests from -n to -z to check if var is already set before calling cmake Fixes: #16663 diff --git a/Auxiliary/cmake.m4 b/Auxiliary/cmake.m4 index 3ef4c16..7beff41 100644 --- a/Auxiliary/cmake.m4 +++ b/Auxiliary/cmake.m4 @@ -24,10 +24,10 @@ AC_ARG_VAR([$1][_LIBS], [linker flags for $1. This overrides the cmake output])d failed=false AC_MSG_CHECKING([for $1]) -if test -n "$1[]_$2[]FLAGS"; then +if test -z "${$1[]_$2[]FLAGS}"; then $1[]_$2[]FLAGS=`$CMAKE_BINARY --find-package "-DNAME=$1" "-DCOMPILER_ID=m4_default([$3], [GNU])" "-DLANGUAGE=$2" -DMODE=COMPILE $4` || failed=true fi -if test -n "$1[]_LIBS"; then +if test -z "${$1[]_LIBS}"; then $1[]_LIBS=`$CMAKE_BINARY --find-package "-DNAME=$1" "-DCOMPILER_ID=m4_default([$3], [GNU])" "-DLANGUAGE=$2" -DMODE=LINK $4` || failed=true fi ----------------------------------------------------------------------- Summary of changes: Auxiliary/cmake.m4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 22 15:16:27 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 22 Feb 2017 15:16:27 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-464-g3d81491 Message-ID: <20170222201629.358ACF484D@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 3d814916c4fca95f0e0aa638f86348f1cd65f24e (commit) via d3a3a96563e17297cfae0db5aa4a82045d3a3bd5 (commit) via 1dbf4d071424b9a34fde3fde47fe17c11448f2a8 (commit) via 499379056c188576fa2ab8cb968366353334f09d (commit) from 4375971fb861de2a194f61668006fe2ce6641f0a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3d814916c4fca95f0e0aa638f86348f1cd65f24e commit 3d814916c4fca95f0e0aa638f86348f1cd65f24e Merge: 4375971 d3a3a96 Author: Brad King AuthorDate: Wed Feb 22 15:16:23 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 22 15:16:23 2017 -0500 Merge topic 'clang-format-attrs' into next d3a3a965 clang-format.bash: Use Git attributes to mark files for formatting 1dbf4d07 Define a custom Git attribute to mark sources using our C style 49937905 Define a custom Git attribute to mark source files as generated https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d3a3a96563e17297cfae0db5aa4a82045d3a3bd5 commit d3a3a96563e17297cfae0db5aa4a82045d3a3bd5 Author: Brad King AuthorDate: Wed Feb 22 15:01:23 2017 -0500 Commit: Brad King CommitDate: Wed Feb 22 15:06:34 2017 -0500 clang-format.bash: Use Git attributes to mark files for formatting diff --git a/.gitattributes b/.gitattributes index abb698a..50fde87 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,11 +2,11 @@ .hooks* export-ignore # Custom attribute to mark sources as using our C code style. -[attr]our-c-style whitespace=tab-in-indent +[attr]our-c-style whitespace=tab-in-indent format.clang # Custom attribute to mark sources as generated. -# Do not perform whitespace checks. -[attr]generated whitespace=-tab-in-indent,-indent-with-non-tab +# Do not perform whitespace checks. Do not format. +[attr]generated whitespace=-tab-in-indent,-indent-with-non-tab -format.clang bootstrap crlf=input configure crlf=input diff --git a/Source/.gitattributes b/Source/.gitattributes index 47eedfb..81902f3 100644 --- a/Source/.gitattributes +++ b/Source/.gitattributes @@ -15,3 +15,7 @@ /cmFortranParser.cxx generated /cmFortranParserTokens.h generated /cmListFileLexer.c generated + +# Do not format third-party sources. +/bindexplib.* -format.clang +/kwsys/** -format.clang diff --git a/Source/CursesDialog/form/.gitattributes b/Source/CursesDialog/form/.gitattributes new file mode 100644 index 0000000..405ee74 --- /dev/null +++ b/Source/CursesDialog/form/.gitattributes @@ -0,0 +1 @@ +* -format.clang diff --git a/Tests/CompileFeatures/.gitattributes b/Tests/CompileFeatures/.gitattributes new file mode 100644 index 0000000..742b780 --- /dev/null +++ b/Tests/CompileFeatures/.gitattributes @@ -0,0 +1,2 @@ +# Do not format a source containing C++11 '>>' syntax as C++98. +cxx_right_angle_brackets.cpp -format.clang diff --git a/Tests/PositionIndependentTargets/.gitattributes b/Tests/PositionIndependentTargets/.gitattributes new file mode 100644 index 0000000..5ecb721 --- /dev/null +++ b/Tests/PositionIndependentTargets/.gitattributes @@ -0,0 +1,2 @@ +# Do not format a source where we want a long line preserved. +pic_test.h -format.clang diff --git a/Tests/RunCMake/CommandLine/cmake_depends/.gitattributes b/Tests/RunCMake/CommandLine/cmake_depends/.gitattributes new file mode 100644 index 0000000..de25724 --- /dev/null +++ b/Tests/RunCMake/CommandLine/cmake_depends/.gitattributes @@ -0,0 +1,2 @@ +# Do not format a source encoded in UTF-16. +test_UTF-16LE.h -format.clang diff --git a/Tests/RunCMake/GenerateExportHeader/reference/.gitattributes b/Tests/RunCMake/GenerateExportHeader/reference/.gitattributes new file mode 100644 index 0000000..dc98048 --- /dev/null +++ b/Tests/RunCMake/GenerateExportHeader/reference/.gitattributes @@ -0,0 +1,2 @@ +# Exclude reference content from formatting. +* -format.clang diff --git a/Utilities/.gitattributes b/Utilities/.gitattributes index c6345eb..1dba5d6 100644 --- a/Utilities/.gitattributes +++ b/Utilities/.gitattributes @@ -1,3 +1,7 @@ /Git export-ignore /GitSetup export-ignore SetupForDevelopment.sh export-ignore + +# Do not format third-party sources. +/KWIML/** -format.clang +/cm*/** -format.clang diff --git a/Utilities/Scripts/clang-format.bash b/Utilities/Scripts/clang-format.bash index 2b36ac5..096045c 100755 --- a/Utilities/Scripts/clang-format.bash +++ b/Utilities/Scripts/clang-format.bash @@ -1,6 +1,6 @@ #!/usr/bin/env bash #============================================================================= -# Copyright 2015-2016 Kitware, Inc. +# Copyright 2015-2017 Kitware, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -106,34 +106,12 @@ case "$mode" in *) die "invalid mode: $mode" ;; esac -# Filter sources to which our style should apply. -$git_ls -z -- '*.c' '*.cc' '*.cpp' '*.cxx' '*.h' '*.hh' '*.hpp' '*.hxx' '*.cu' '*.notcu' | +# List files as selected above. +$git_ls | - # Exclude lexer/parser generator input and output. - egrep -z -v '^Source/cmCommandArgumentLexer\.' | - egrep -z -v '^Source/cmCommandArgumentParser(\.y|\.cxx|Tokens\.h)' | - egrep -z -v '^Source/cmDependsJavaLexer\.' | - egrep -z -v '^Source/cmDependsJavaParser(\.y|\.cxx|Tokens\.h)' | - egrep -z -v '^Source/cmExprLexer\.' | - egrep -z -v '^Source/cmExprParser(\.y|\.cxx|Tokens\.h)' | - egrep -z -v '^Source/cmFortranLexer\.' | - egrep -z -v '^Source/cmFortranParser(\.y|\.cxx|Tokens\.h)' | - egrep -z -v '^Source/cmListFileLexer(\.in\.l|\.c)' | - - # Exclude third-party sources. - egrep -z -v '^Source/bindexplib' | - egrep -z -v '^Source/(kwsys|CursesDialog/form)/' | - egrep -z -v '^Utilities/(KW|cm).*/' | - - # Exclude reference content. - egrep -z -v '^Tests/RunCMake/GenerateExportHeader/reference/' | - - # Exclude manually-formatted sources (e.g. with long lines). - egrep -z -v '^Tests/PositionIndependentTargets/pic_test.h' | - egrep -z -v '^Tests/CompileFeatures/cxx_right_angle_brackets.cpp' | - - # Exclude sources with encoding not suported by clang-format. - egrep -z -v '^Tests/RunCMake/CommandLine/cmake_depends/test_UTF-16LE.h' | + # Select sources with our attribute. + git check-attr --stdin format.clang | + sed -n '/: format\.clang: set$/ {s/:[^:]*:[^:]*$//;p;}' | # Update sources in-place. - xargs -0 "$clang_format" -i + xargs -d '\n' "$clang_format" -i https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1dbf4d071424b9a34fde3fde47fe17c11448f2a8 commit 1dbf4d071424b9a34fde3fde47fe17c11448f2a8 Author: Brad King AuthorDate: Wed Feb 22 14:58:27 2017 -0500 Commit: Brad King CommitDate: Wed Feb 22 15:05:47 2017 -0500 Define a custom Git attribute to mark sources using our C style diff --git a/.gitattributes b/.gitattributes index dfc3250..abb698a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,6 +1,9 @@ .gitattributes export-ignore .hooks* export-ignore +# Custom attribute to mark sources as using our C code style. +[attr]our-c-style whitespace=tab-in-indent + # Custom attribute to mark sources as generated. # Do not perform whitespace checks. [attr]generated whitespace=-tab-in-indent,-indent-with-non-tab @@ -20,10 +23,17 @@ configure crlf=input *.sln -crlf *.vcproj -crlf -*.c whitespace=tab-in-indent -*.h whitespace=tab-in-indent -*.cxx whitespace=tab-in-indent -*.txt whitespace=tab-in-indent -*.cmake whitespace=tab-in-indent +*.c our-c-style +*.cc our-c-style +*.cpp our-c-style +*.cu our-c-style +*.cxx our-c-style +*.h our-c-style +*.hh our-c-style +*.hpp our-c-style +*.hxx our-c-style +*.notcu our-c-style +*.cmake whitespace=tab-in-indent *.rst whitespace=tab-in-indent conflict-marker-size=79 +*.txt whitespace=tab-in-indent https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=499379056c188576fa2ab8cb968366353334f09d commit 499379056c188576fa2ab8cb968366353334f09d Author: Brad King AuthorDate: Wed Feb 22 14:33:30 2017 -0500 Commit: Brad King CommitDate: Wed Feb 22 15:03:46 2017 -0500 Define a custom Git attribute to mark source files as generated diff --git a/.gitattributes b/.gitattributes index d959918..dfc3250 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,6 +1,10 @@ .gitattributes export-ignore .hooks* export-ignore +# Custom attribute to mark sources as generated. +# Do not perform whitespace checks. +[attr]generated whitespace=-tab-in-indent,-indent-with-non-tab + bootstrap crlf=input configure crlf=input *.[1-9] crlf=input diff --git a/Source/.gitattributes b/Source/.gitattributes index dbd6382..47eedfb 100644 --- a/Source/.gitattributes +++ b/Source/.gitattributes @@ -1,10 +1,17 @@ -# Preserve indentation style in generated code. -cmCommandArgumentLexer.cxx whitespace=-tab-in-indent,-indent-with-non-tab -cmCommandArgumentLexer.h whitespace=-tab-in-indent,-indent-with-non-tab -cmDependsJavaLexer.cxx whitespace=-tab-in-indent,-indent-with-non-tab -cmDependsJavaLexer.h whitespace=-tab-in-indent,-indent-with-non-tab -cmExprLexer.cxx whitespace=-tab-in-indent,-indent-with-non-tab -cmExprLexer.h whitespace=-tab-in-indent,-indent-with-non-tab -cmFortranLexer.cxx whitespace=-tab-in-indent,-indent-with-non-tab -cmFortranLexer.h whitespace=-tab-in-indent,-indent-with-non-tab -cmListFileLexer.c whitespace=-tab-in-indent,-indent-with-non-tab +/cmCommandArgumentLexer.cxx generated +/cmCommandArgumentLexer.h generated +/cmCommandArgumentParser.cxx generated +/cmCommandArgumentParserTokens.h generated +/cmDependsJavaLexer.cxx generated +/cmDependsJavaLexer.h generated +/cmDependsJavaParser.cxx generated +/cmDependsJavaParserTokens.h generated +/cmExprLexer.cxx generated +/cmExprLexer.h generated +/cmExprParser.cxx generated +/cmExprParserTokens.h generated +/cmFortranLexer.cxx generated +/cmFortranLexer.h generated +/cmFortranParser.cxx generated +/cmFortranParserTokens.h generated +/cmListFileLexer.c generated ----------------------------------------------------------------------- Summary of changes: .gitattributes | 24 ++++++++++--- Source/.gitattributes | 31 +++++++++++------ Source/CursesDialog/form/.gitattributes | 1 + Tests/CompileFeatures/.gitattributes | 2 ++ Tests/PositionIndependentTargets/.gitattributes | 2 ++ .../CommandLine/cmake_depends/.gitattributes | 2 ++ .../GenerateExportHeader/reference/.gitattributes | 2 ++ Utilities/.gitattributes | 4 +++ Utilities/Scripts/clang-format.bash | 36 ++++---------------- 9 files changed, 60 insertions(+), 44 deletions(-) create mode 100644 Source/CursesDialog/form/.gitattributes create mode 100644 Tests/CompileFeatures/.gitattributes create mode 100644 Tests/PositionIndependentTargets/.gitattributes create mode 100644 Tests/RunCMake/CommandLine/cmake_depends/.gitattributes create mode 100644 Tests/RunCMake/GenerateExportHeader/reference/.gitattributes hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 22 15:21:52 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 22 Feb 2017 15:21:52 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-470-g0ec9309 Message-ID: <20170222202153.01844F9E47@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 0ec930925c5e16f6e6ad20d565076d505a91906c (commit) via 624021a09e7850b1f6cb75af40b17a38d98c95e3 (commit) via 5da9266af50af3c2c1a827a1d162c8a9b16e7fd9 (commit) via e80ac953035703dde6e03e2c32ba9fded8c69f2a (commit) via 9293e57d9cef75a5abb6f28d5bf712106471a137 (commit) via 33a1d727d5aafeaa0d9e729119d7d43ea9fcb370 (commit) from 3d814916c4fca95f0e0aa638f86348f1cd65f24e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0ec930925c5e16f6e6ad20d565076d505a91906c commit 0ec930925c5e16f6e6ad20d565076d505a91906c Merge: 3d81491 624021a Author: Brad King AuthorDate: Wed Feb 22 15:21:49 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 22 15:21:49 2017 -0500 Merge topic '16615-xcode-object-libraries-depends' into next 624021a0 Add test for object library dependencies 5da9266a Xcode: Always track object library dependencies via hacky Makefile e80ac953 Xcode: Record dependency information also for object libraries 9293e57d Xcode: Collect dummy rules during iteration and emit afterwards 33a1d727 Makefile: Allow adding post-build rules to object libraries https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=624021a09e7850b1f6cb75af40b17a38d98c95e3 commit 624021a09e7850b1f6cb75af40b17a38d98c95e3 Author: Gregor Jasny AuthorDate: Sat Feb 18 22:27:46 2017 +0100 Commit: Brad King CommitDate: Wed Feb 22 15:21:06 2017 -0500 Add test for object library dependencies Issue: #16615 diff --git a/Tests/RunCMake/ObjectLibrary/Dependencies.cmake b/Tests/RunCMake/ObjectLibrary/Dependencies.cmake new file mode 100644 index 0000000..4e3db5f --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/Dependencies.cmake @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 3.7) + +project(Dependencies) + +add_library(myobj OBJECT ${CMAKE_BINARY_DIR}/depends_obj.cpp) +add_library(mylib STATIC $ depends_lib.cpp) +add_executable(myexe depends_main.cpp) +target_link_libraries(myexe mylib) + +enable_testing() +add_test(NAME myexe COMMAND $) diff --git a/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake index 42973f8..9291218 100644 --- a/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake +++ b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake @@ -16,3 +16,22 @@ run_cmake(ObjWithObj) run_cmake(PostBuild) run_cmake(PreBuild) run_cmake(PreLink) + +function(run_Dependencies) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Dependencies-build) + set(RunCMake_TEST_NO_CLEAN 1) + + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + + run_cmake_command(Dependencies-build ${CMAKE_COMMAND} -E copy ${RunCMake_SOURCE_DIR}/depends_obj1.cpp ${RunCMake_TEST_BINARY_DIR}/depends_obj.cpp) + run_cmake(Dependencies) + run_cmake_command(Dependencies-build ${CMAKE_COMMAND} --build .) + run_cmake_command(Dependencies-build ${CMAKE_COMMAND} -E copy ${RunCMake_SOURCE_DIR}/depends_obj0.cpp ${RunCMake_TEST_BINARY_DIR}/depends_obj.cpp) + run_cmake_command(Dependencies-build ${CMAKE_COMMAND} -E sleep 1) + run_cmake_command(Dependencies-build ${CMAKE_COMMAND} -E touch_nocreate ${RunCMake_TEST_BINARY_DIR}/depends_obj.cpp) + run_cmake_command(Dependencies-build ${CMAKE_COMMAND} --build .) + run_cmake_command(Dependencies-build ${CMAKE_CTEST_COMMAND} -C Debug) +endfunction() + +run_Dependencies() diff --git a/Tests/RunCMake/ObjectLibrary/depends_lib.cpp b/Tests/RunCMake/ObjectLibrary/depends_lib.cpp new file mode 100644 index 0000000..540b536 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/depends_lib.cpp @@ -0,0 +1,7 @@ +#include +int myobj_foo(); + +void mylib_foo() +{ + exit(myobj_foo()); +} diff --git a/Tests/RunCMake/ObjectLibrary/depends_main.cpp b/Tests/RunCMake/ObjectLibrary/depends_main.cpp new file mode 100644 index 0000000..a9d323d --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/depends_main.cpp @@ -0,0 +1,7 @@ +void mylib_foo(); + +int main() +{ + mylib_foo(); + return 0; +} diff --git a/Tests/RunCMake/ObjectLibrary/depends_obj0.cpp b/Tests/RunCMake/ObjectLibrary/depends_obj0.cpp new file mode 100644 index 0000000..73a17e7 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/depends_obj0.cpp @@ -0,0 +1,4 @@ +int myobj_foo() +{ + return 0; +} diff --git a/Tests/RunCMake/ObjectLibrary/depends_obj1.cpp b/Tests/RunCMake/ObjectLibrary/depends_obj1.cpp new file mode 100644 index 0000000..f62ef70 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/depends_obj1.cpp @@ -0,0 +1,4 @@ +int myobj_foo() +{ + return 1; +} https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=5da9266af50af3c2c1a827a1d162c8a9b16e7fd9 commit 5da9266af50af3c2c1a827a1d162c8a9b16e7fd9 Author: Gregor Jasny AuthorDate: Sat Feb 18 18:43:25 2017 +0100 Commit: Brad King CommitDate: Wed Feb 22 15:20:11 2017 -0500 Xcode: Always track object library dependencies via hacky Makefile Always use the dependency tracker Makefile to ensure targets that depend on object libraries are up-to-date. For all other target types we use the hack only for Xcode < 5. Fixes: #16615 diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 0a9c7b8..5167205 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -423,14 +423,12 @@ void cmGlobalXCodeGenerator::AddExtraTargets( // Add XCODE depend helper std::string dir = root->GetCurrentBinaryDirectory(); cmCustomCommandLine makeHelper; - if (this->XcodeVersion < 50) { - makeHelper.push_back("make"); - makeHelper.push_back("-C"); - makeHelper.push_back(dir); - makeHelper.push_back("-f"); - makeHelper.push_back(this->CurrentXCodeHackMakefile); - makeHelper.push_back(""); // placeholder, see below - } + makeHelper.push_back("make"); + makeHelper.push_back("-C"); + makeHelper.push_back(dir); + makeHelper.push_back("-f"); + makeHelper.push_back(this->CurrentXCodeHackMakefile); + makeHelper.push_back(""); // placeholder, see below // Add ZERO_CHECK bool regenerate = !mf->IsOn("CMAKE_SUPPRESS_REGENERATION"); @@ -475,12 +473,12 @@ void cmGlobalXCodeGenerator::AddExtraTargets( // run the depend check makefile as a post build rule // this will make sure that when the next target is built // things are up-to-date - if (!makeHelper.empty() && - (target->GetType() == cmStateEnums::EXECUTABLE || - target->GetType() == cmStateEnums::OBJECT_LIBRARY || - target->GetType() == cmStateEnums::STATIC_LIBRARY || - target->GetType() == cmStateEnums::SHARED_LIBRARY || - target->GetType() == cmStateEnums::MODULE_LIBRARY)) { + if (target->GetType() == cmStateEnums::OBJECT_LIBRARY || + (this->XcodeVersion < 50 && + (target->GetType() == cmStateEnums::EXECUTABLE || + target->GetType() == cmStateEnums::STATIC_LIBRARY || + target->GetType() == cmStateEnums::SHARED_LIBRARY || + target->GetType() == cmStateEnums::MODULE_LIBRARY))) { makeHelper[makeHelper.size() - 1] = // fill placeholder this->PostBuildMakeTarget(target->GetName(), "$(CONFIGURATION)"); cmCustomCommandLines commandLines; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e80ac953035703dde6e03e2c32ba9fded8c69f2a commit e80ac953035703dde6e03e2c32ba9fded8c69f2a Author: Gregor Jasny AuthorDate: Sat Feb 18 18:41:03 2017 +0100 Commit: Gregor Jasny CommitDate: Wed Feb 22 17:05:18 2017 +0100 Xcode: Record dependency information also for object libraries Xcode seems to have troubles to track target dependecies to object files. This may lead to stale targets as reported in issue #16615. As a work-around the pre-Xcode 5 dependecy tracker hack with post-build make files is extended to also take object libraries into account. diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 9d5c99e..0a9c7b8 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -477,8 +477,7 @@ void cmGlobalXCodeGenerator::AddExtraTargets( // things are up-to-date if (!makeHelper.empty() && (target->GetType() == cmStateEnums::EXECUTABLE || - // Nope - no post-build for OBJECT_LIRBRARY - // target->GetType() == cmStateEnums::OBJECT_LIBRARY || + target->GetType() == cmStateEnums::OBJECT_LIBRARY || target->GetType() == cmStateEnums::STATIC_LIBRARY || target->GetType() == cmStateEnums::SHARED_LIBRARY || target->GetType() == cmStateEnums::MODULE_LIBRARY)) { @@ -3130,10 +3129,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( cmXCodeObject* t = *i; this->AddDependAndLinkInformation(t); } - if (this->XcodeVersion < 50) { - // now create xcode depend hack makefile - this->CreateXCodeDependHackTarget(targets); - } + this->CreateXCodeDependHackTarget(targets); // now add all targets to the root object cmXCodeObject* allTargets = this->CreateObject(cmXCodeObject::OBJECT_LIST); for (std::vector::iterator i = targets.begin(); @@ -3205,8 +3201,7 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( cmGeneratorTarget* gt = target->GetTarget(); if (gt->GetType() == cmStateEnums::EXECUTABLE || - // Nope - no post-build for OBJECT_LIRBRARY - // gt->GetType() == cmStateEnums::OBJECT_LIBRARY || + gt->GetType() == cmStateEnums::OBJECT_LIBRARY || gt->GetType() == cmStateEnums::STATIC_LIBRARY || gt->GetType() == cmStateEnums::SHARED_LIBRARY || gt->GetType() == cmStateEnums::MODULE_LIBRARY) { @@ -3216,6 +3211,7 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( } if (gt->GetType() == cmStateEnums::EXECUTABLE || + gt->GetType() == cmStateEnums::STATIC_LIBRARY || gt->GetType() == cmStateEnums::SHARED_LIBRARY || gt->GetType() == cmStateEnums::MODULE_LIBRARY) { std::string tfull = gt->GetFullPath(configName); @@ -3233,6 +3229,15 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( } } + std::vector objlibs; + gt->GetObjectLibrariesCMP0026(objlibs); + for (std::vector::const_iterator it = + objlibs.begin(); + it != objlibs.end(); ++it) { + makefileStream << this->PostBuildMakeTarget((*it)->GetName(), *ct) + << ": " << trel << "\n"; + } + // Create a rule for this target. makefileStream << trel << ":"; @@ -3248,6 +3253,23 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( dummyRules.insert(file); } } + + for (std::vector::const_iterator it = + objlibs.begin(); + it != objlibs.end(); ++it) { + + const std::string objLibName = (*it)->GetName(); + std::string d = this->GetObjectsNormalDirectory(this->CurrentProject, + configName, *it); + d += "lib"; + d += objLibName; + d += ".a"; + + std::string dependency = this->ConvertToRelativeForMake(d.c_str()); + makefileStream << "\\\n\t" << dependency; + dummyRules.insert(dependency); + } + // Write the action to remove the target if it is out of date. makefileStream << "\n"; makefileStream << "\t/bin/rm -f " https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9293e57d9cef75a5abb6f28d5bf712106471a137 commit 9293e57d9cef75a5abb6f28d5bf712106471a137 Author: Gregor Jasny AuthorDate: Sat Feb 18 18:23:59 2017 +0100 Commit: Gregor Jasny CommitDate: Wed Feb 22 17:05:17 2017 +0100 Xcode: Collect dummy rules during iteration and emit afterwards diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 5029a94..9d5c99e 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -3184,29 +3184,9 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( "default:\n" "\techo \"Do not invoke directly\"\n" "\n"; - makefileStream - << "# For each target create a dummy rule " - "so the target does not have to exist\n"; /* clang-format on */ - std::set emitted; - for (std::vector::iterator i = targets.begin(); - i != targets.end(); ++i) { - cmXCodeObject* target = *i; - std::map const& deplibs = - target->GetDependLibraries(); - for (std::map::const_iterator ci = - deplibs.begin(); - ci != deplibs.end(); ++ci) { - for (cmXCodeObject::StringVec::const_iterator d = ci->second.begin(); - d != ci->second.end(); ++d) { - if (emitted.insert(*d).second) { - makefileStream << this->ConvertToRelativeForMake(d->c_str()) - << ":\n"; - } - } - } - } - makefileStream << "\n\n"; + + std::set dummyRules; // Write rules to help Xcode relink things at the right time. /* clang-format off */ @@ -3263,8 +3243,9 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( std::vector const& deplibs = x->second; for (std::vector::const_iterator d = deplibs.begin(); d != deplibs.end(); ++d) { - makefileStream << "\\\n\t" - << this->ConvertToRelativeForMake(d->c_str()); + std::string file = this->ConvertToRelativeForMake(d->c_str()); + makefileStream << "\\\n\t" << file; + dummyRules.insert(file); } } // Write the action to remove the target if it is out of date. @@ -3294,6 +3275,14 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( } } } + + makefileStream << "\n\n" + << "# For each target create a dummy rule" + << "so the target does not have to exist\n"; + for (std::set::const_iterator it = dummyRules.begin(); + it != dummyRules.end(); ++it) { + makefileStream << *it << ":\n"; + } } void cmGlobalXCodeGenerator::OutputXCodeProject( https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=33a1d727d5aafeaa0d9e729119d7d43ea9fcb370 commit 33a1d727d5aafeaa0d9e729119d7d43ea9fcb370 Author: Gregor Jasny AuthorDate: Sat Feb 18 20:12:27 2017 +0100 Commit: Gregor Jasny CommitDate: Wed Feb 22 17:05:17 2017 +0100 Makefile: Allow adding post-build rules to object libraries diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 8627cf2..5029a94 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -489,7 +489,8 @@ void cmGlobalXCodeGenerator::AddExtraTargets( std::vector no_byproducts; lg->GetMakefile()->AddCustomCommandToTarget( target->GetName(), no_byproducts, no_depends, commandLines, - cmTarget::POST_BUILD, "Depend check for xcode", dir.c_str()); + cmTarget::POST_BUILD, "Depend check for xcode", dir.c_str(), true, + false, "", false, cmMakefile::AcceptObjectLibraryCommands); } if (target->GetType() != cmStateEnums::INTERFACE_LIBRARY && diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index bdaca97..7f9e6ef 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -684,7 +684,8 @@ void cmMakefile::AddCustomCommandToTarget( const std::vector& depends, const cmCustomCommandLines& commandLines, cmTarget::CustomCommandType type, const char* comment, const char* workingDir, bool escapeOldStyle, - bool uses_terminal, const std::string& depfile, bool command_expand_lists) + bool uses_terminal, const std::string& depfile, bool command_expand_lists, + ObjectLibraryCommands objLibraryCommands) { // Find the target to which to add the custom command. cmTargets::iterator ti = this->Targets.find(target); @@ -724,7 +725,8 @@ void cmMakefile::AddCustomCommandToTarget( return; } - if (ti->second.GetType() == cmStateEnums::OBJECT_LIBRARY) { + if (objLibraryCommands == RejectObjectLibraryCommands && + ti->second.GetType() == cmStateEnums::OBJECT_LIBRARY) { std::ostringstream e; e << "Target \"" << target << "\" is an OBJECT library " diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 9d9e90a..4d5ce98 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -119,6 +119,13 @@ public: */ void FinalPass(); + /** How to handle custom commands for object libraries */ + enum ObjectLibraryCommands + { + RejectObjectLibraryCommands, + AcceptObjectLibraryCommands + }; + /** Add a custom command to the build. */ void AddCustomCommandToTarget( const std::string& target, const std::vector& byproducts, @@ -126,7 +133,8 @@ public: const cmCustomCommandLines& commandLines, cmTarget::CustomCommandType type, const char* comment, const char* workingDir, bool escapeOldStyle = true, bool uses_terminal = false, const std::string& depfile = "", - bool command_expand_lists = false); + bool command_expand_lists = false, + ObjectLibraryCommands objLibraryCommands = RejectObjectLibraryCommands); cmSourceFile* AddCustomCommandToOutput( const std::vector& outputs, const std::vector& byproducts, ----------------------------------------------------------------------- Summary of changes: Source/cmGlobalXCodeGenerator.cxx | 102 +++++++++++--------- Source/cmMakefile.cxx | 6 +- Source/cmMakefile.h | 10 +- Tests/RunCMake/ObjectLibrary/Dependencies.cmake | 11 +++ Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake | 19 ++++ Tests/RunCMake/ObjectLibrary/depends_lib.cpp | 7 ++ Tests/RunCMake/ObjectLibrary/depends_main.cpp | 7 ++ .../RunCMake/ObjectLibrary/depends_obj0.cpp | 2 +- .../ObjectLibrary/depends_obj1.cpp} | 2 +- 9 files changed, 115 insertions(+), 51 deletions(-) create mode 100644 Tests/RunCMake/ObjectLibrary/Dependencies.cmake create mode 100644 Tests/RunCMake/ObjectLibrary/depends_lib.cpp create mode 100644 Tests/RunCMake/ObjectLibrary/depends_main.cpp copy Modules/DummyCXXFile.cxx => Tests/RunCMake/ObjectLibrary/depends_obj0.cpp (50%) copy Tests/{Complex/Library/ExtraSources/file1.cxx => RunCMake/ObjectLibrary/depends_obj1.cpp} (50%) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 22 16:22:16 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 22 Feb 2017 16:22:16 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-472-g3e46192 Message-ID: <20170222212216.B14A2FA036@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 3e46192ef2c87777d136894f4dcc9bcb524164f9 (commit) via f765e21b903d36c79d83dfcfdf0a44c43540f99a (commit) from 0ec930925c5e16f6e6ad20d565076d505a91906c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3e46192ef2c87777d136894f4dcc9bcb524164f9 commit 3e46192ef2c87777d136894f4dcc9bcb524164f9 Merge: 0ec9309 f765e21 Author: Brad King AuthorDate: Wed Feb 22 16:22:15 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 22 16:22:15 2017 -0500 Merge topic 'doc-cmake-language-makefile-vars' into next f765e21b Help: Clarify 'make-style' variable references in cmake-language(7) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f765e21b903d36c79d83dfcfdf0a44c43540f99a commit f765e21b903d36c79d83dfcfdf0a44c43540f99a Author: Michael Maltese AuthorDate: Wed Feb 22 12:32:13 2017 -0800 Commit: Brad King CommitDate: Wed Feb 22 15:48:38 2017 -0500 Help: Clarify 'make-style' variable references in cmake-language(7) Fixes: #16661 diff --git a/Help/manual/cmake-language.7.rst b/Help/manual/cmake-language.7.rst index ba0b30f..f98200c 100644 --- a/Help/manual/cmake-language.7.rst +++ b/Help/manual/cmake-language.7.rst @@ -329,11 +329,17 @@ For example: To support legacy CMake code, unquoted arguments may also contain double-quoted strings (``"..."``, possibly enclosing horizontal whitespace), and make-style variable references (``$(MAKEVAR)``). + Unescaped double-quotes must balance, may not appear at the beginning of an unquoted argument, and are treated as part of the content. For example, the unquoted arguments ``-Da="b c"``, ``-Da=$(v)``, and ``a" "b"c"d`` are each interpreted literally. + Make-style references are also treated literally as part of the + content and do not undergo variable expansion. They are treated + as part of a single argument (rather than as separate ``$``, ``(``, + ``MAKEVAR``, and ``)`` arguments). + The above "unquoted_legacy" production represents such arguments. We do not recommend using legacy unquoted arguments in new code. Instead use a `Quoted Argument`_ or a `Bracket Argument`_ to ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-language.7.rst | 6 ++++++ 1 file changed, 6 insertions(+) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 22 16:46:09 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 22 Feb 2017 16:46:09 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-474-g89a9078 Message-ID: <20170222214609.522B1E513E@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 89a9078a7caa162f1793a242caf3ce1d90cb2fd4 (commit) via 08526b1ae92bfab52c750e7d5fd7b6790a4baac8 (commit) from 3e46192ef2c87777d136894f4dcc9bcb524164f9 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=89a9078a7caa162f1793a242caf3ce1d90cb2fd4 commit 89a9078a7caa162f1793a242caf3ce1d90cb2fd4 Merge: 3e46192 08526b1 Author: Brad King AuthorDate: Wed Feb 22 16:46:08 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 22 16:46:08 2017 -0500 Merge topic 'doc-cmake-language-makefile-vars' into next 08526b1a fixup! Help: Clarify 'make-style' variable references in cmake-language(7) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=08526b1ae92bfab52c750e7d5fd7b6790a4baac8 commit 08526b1ae92bfab52c750e7d5fd7b6790a4baac8 Author: Brad King AuthorDate: Wed Feb 22 16:45:55 2017 -0500 Commit: Brad King CommitDate: Wed Feb 22 16:45:55 2017 -0500 fixup! Help: Clarify 'make-style' variable references in cmake-language(7) diff --git a/Help/manual/cmake-language.7.rst b/Help/manual/cmake-language.7.rst index f98200c..27b5d30 100644 --- a/Help/manual/cmake-language.7.rst +++ b/Help/manual/cmake-language.7.rst @@ -335,9 +335,9 @@ For example: content. For example, the unquoted arguments ``-Da="b c"``, ``-Da=$(v)``, and ``a" "b"c"d`` are each interpreted literally. - Make-style references are also treated literally as part of the - content and do not undergo variable expansion. They are treated - as part of a single argument (rather than as separate ``$``, ``(``, + Make-style references are treated literally as part of the content + and do not undergo variable expansion. They are treated as part + of a single argument (rather than as separate ``$``, ``(``, ``MAKEVAR``, and ``)`` arguments). The above "unquoted_legacy" production represents such arguments. ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-language.7.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 22 16:46:29 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 22 Feb 2017 16:46:29 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-476-g2d2c94d Message-ID: <20170222214629.2AABFE5433@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 2d2c94d08fd5f241bb4a736900d6e5acfe5f686b (commit) via 1dc13019259bd62d63b9295011227029283c2ef7 (commit) from 89a9078a7caa162f1793a242caf3ce1d90cb2fd4 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=2d2c94d08fd5f241bb4a736900d6e5acfe5f686b commit 2d2c94d08fd5f241bb4a736900d6e5acfe5f686b Merge: 89a9078 1dc1301 Author: Brad King AuthorDate: Wed Feb 22 16:46:28 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 22 16:46:28 2017 -0500 Merge topic 'doc-cmake-language-makefile-vars' into next 1dc13019 Help: Clarify 'make-style' variable references in cmake-language(7) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1dc13019259bd62d63b9295011227029283c2ef7 commit 1dc13019259bd62d63b9295011227029283c2ef7 Author: Michael Maltese AuthorDate: Wed Feb 22 12:32:13 2017 -0800 Commit: Michael Maltese CommitDate: Wed Feb 22 13:39:09 2017 -0800 Help: Clarify 'make-style' variable references in cmake-language(7) Fixes: #16661 diff --git a/Help/manual/cmake-language.7.rst b/Help/manual/cmake-language.7.rst index ba0b30f..27b5d30 100644 --- a/Help/manual/cmake-language.7.rst +++ b/Help/manual/cmake-language.7.rst @@ -329,11 +329,17 @@ For example: To support legacy CMake code, unquoted arguments may also contain double-quoted strings (``"..."``, possibly enclosing horizontal whitespace), and make-style variable references (``$(MAKEVAR)``). + Unescaped double-quotes must balance, may not appear at the beginning of an unquoted argument, and are treated as part of the content. For example, the unquoted arguments ``-Da="b c"``, ``-Da=$(v)``, and ``a" "b"c"d`` are each interpreted literally. + Make-style references are treated literally as part of the content + and do not undergo variable expansion. They are treated as part + of a single argument (rather than as separate ``$``, ``(``, + ``MAKEVAR``, and ``)`` arguments). + The above "unquoted_legacy" production represents such arguments. We do not recommend using legacy unquoted arguments in new code. Instead use a `Quoted Argument`_ or a `Bracket Argument`_ to ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 22 16:51:30 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 22 Feb 2017 16:51:30 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-478-ge0fe4bc Message-ID: <20170222215130.9E991F9A4C@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via e0fe4bc5ffc8b29bb337113645eb74ace68deada (commit) via b5dc36e1264200bdbdd5a8119b426bc4e3e7ca82 (commit) from 2d2c94d08fd5f241bb4a736900d6e5acfe5f686b (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e0fe4bc5ffc8b29bb337113645eb74ace68deada commit e0fe4bc5ffc8b29bb337113645eb74ace68deada Merge: 2d2c94d b5dc36e Author: Brad King AuthorDate: Wed Feb 22 16:51:29 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 22 16:51:29 2017 -0500 Merge topic 'clang-format-attrs' into next b5dc36e1 Revert topic 'clang-format-attrs' https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b5dc36e1264200bdbdd5a8119b426bc4e3e7ca82 commit b5dc36e1264200bdbdd5a8119b426bc4e3e7ca82 Author: Brad King AuthorDate: Wed Feb 22 16:51:13 2017 -0500 Commit: Brad King CommitDate: Wed Feb 22 16:51:13 2017 -0500 Revert topic 'clang-format-attrs' It will be revised and restored. diff --git a/.gitattributes b/.gitattributes index 50fde87..d959918 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,13 +1,6 @@ .gitattributes export-ignore .hooks* export-ignore -# Custom attribute to mark sources as using our C code style. -[attr]our-c-style whitespace=tab-in-indent format.clang - -# Custom attribute to mark sources as generated. -# Do not perform whitespace checks. Do not format. -[attr]generated whitespace=-tab-in-indent,-indent-with-non-tab -format.clang - bootstrap crlf=input configure crlf=input *.[1-9] crlf=input @@ -23,17 +16,10 @@ configure crlf=input *.sln -crlf *.vcproj -crlf -*.c our-c-style -*.cc our-c-style -*.cpp our-c-style -*.cu our-c-style -*.cxx our-c-style -*.h our-c-style -*.hh our-c-style -*.hpp our-c-style -*.hxx our-c-style -*.notcu our-c-style - +*.c whitespace=tab-in-indent +*.h whitespace=tab-in-indent +*.cxx whitespace=tab-in-indent +*.txt whitespace=tab-in-indent *.cmake whitespace=tab-in-indent + *.rst whitespace=tab-in-indent conflict-marker-size=79 -*.txt whitespace=tab-in-indent diff --git a/Source/.gitattributes b/Source/.gitattributes index 81902f3..dbd6382 100644 --- a/Source/.gitattributes +++ b/Source/.gitattributes @@ -1,21 +1,10 @@ -/cmCommandArgumentLexer.cxx generated -/cmCommandArgumentLexer.h generated -/cmCommandArgumentParser.cxx generated -/cmCommandArgumentParserTokens.h generated -/cmDependsJavaLexer.cxx generated -/cmDependsJavaLexer.h generated -/cmDependsJavaParser.cxx generated -/cmDependsJavaParserTokens.h generated -/cmExprLexer.cxx generated -/cmExprLexer.h generated -/cmExprParser.cxx generated -/cmExprParserTokens.h generated -/cmFortranLexer.cxx generated -/cmFortranLexer.h generated -/cmFortranParser.cxx generated -/cmFortranParserTokens.h generated -/cmListFileLexer.c generated - -# Do not format third-party sources. -/bindexplib.* -format.clang -/kwsys/** -format.clang +# Preserve indentation style in generated code. +cmCommandArgumentLexer.cxx whitespace=-tab-in-indent,-indent-with-non-tab +cmCommandArgumentLexer.h whitespace=-tab-in-indent,-indent-with-non-tab +cmDependsJavaLexer.cxx whitespace=-tab-in-indent,-indent-with-non-tab +cmDependsJavaLexer.h whitespace=-tab-in-indent,-indent-with-non-tab +cmExprLexer.cxx whitespace=-tab-in-indent,-indent-with-non-tab +cmExprLexer.h whitespace=-tab-in-indent,-indent-with-non-tab +cmFortranLexer.cxx whitespace=-tab-in-indent,-indent-with-non-tab +cmFortranLexer.h whitespace=-tab-in-indent,-indent-with-non-tab +cmListFileLexer.c whitespace=-tab-in-indent,-indent-with-non-tab diff --git a/Source/CursesDialog/form/.gitattributes b/Source/CursesDialog/form/.gitattributes deleted file mode 100644 index 405ee74..0000000 --- a/Source/CursesDialog/form/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -* -format.clang diff --git a/Tests/CompileFeatures/.gitattributes b/Tests/CompileFeatures/.gitattributes deleted file mode 100644 index 742b780..0000000 --- a/Tests/CompileFeatures/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -# Do not format a source containing C++11 '>>' syntax as C++98. -cxx_right_angle_brackets.cpp -format.clang diff --git a/Tests/PositionIndependentTargets/.gitattributes b/Tests/PositionIndependentTargets/.gitattributes deleted file mode 100644 index 5ecb721..0000000 --- a/Tests/PositionIndependentTargets/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -# Do not format a source where we want a long line preserved. -pic_test.h -format.clang diff --git a/Tests/RunCMake/CommandLine/cmake_depends/.gitattributes b/Tests/RunCMake/CommandLine/cmake_depends/.gitattributes deleted file mode 100644 index de25724..0000000 --- a/Tests/RunCMake/CommandLine/cmake_depends/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -# Do not format a source encoded in UTF-16. -test_UTF-16LE.h -format.clang diff --git a/Tests/RunCMake/GenerateExportHeader/reference/.gitattributes b/Tests/RunCMake/GenerateExportHeader/reference/.gitattributes deleted file mode 100644 index dc98048..0000000 --- a/Tests/RunCMake/GenerateExportHeader/reference/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -# Exclude reference content from formatting. -* -format.clang diff --git a/Utilities/.gitattributes b/Utilities/.gitattributes index 1dba5d6..c6345eb 100644 --- a/Utilities/.gitattributes +++ b/Utilities/.gitattributes @@ -1,7 +1,3 @@ /Git export-ignore /GitSetup export-ignore SetupForDevelopment.sh export-ignore - -# Do not format third-party sources. -/KWIML/** -format.clang -/cm*/** -format.clang diff --git a/Utilities/Scripts/clang-format.bash b/Utilities/Scripts/clang-format.bash index 096045c..2b36ac5 100755 --- a/Utilities/Scripts/clang-format.bash +++ b/Utilities/Scripts/clang-format.bash @@ -1,6 +1,6 @@ #!/usr/bin/env bash #============================================================================= -# Copyright 2015-2017 Kitware, Inc. +# Copyright 2015-2016 Kitware, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -106,12 +106,34 @@ case "$mode" in *) die "invalid mode: $mode" ;; esac -# List files as selected above. -$git_ls | +# Filter sources to which our style should apply. +$git_ls -z -- '*.c' '*.cc' '*.cpp' '*.cxx' '*.h' '*.hh' '*.hpp' '*.hxx' '*.cu' '*.notcu' | - # Select sources with our attribute. - git check-attr --stdin format.clang | - sed -n '/: format\.clang: set$/ {s/:[^:]*:[^:]*$//;p;}' | + # Exclude lexer/parser generator input and output. + egrep -z -v '^Source/cmCommandArgumentLexer\.' | + egrep -z -v '^Source/cmCommandArgumentParser(\.y|\.cxx|Tokens\.h)' | + egrep -z -v '^Source/cmDependsJavaLexer\.' | + egrep -z -v '^Source/cmDependsJavaParser(\.y|\.cxx|Tokens\.h)' | + egrep -z -v '^Source/cmExprLexer\.' | + egrep -z -v '^Source/cmExprParser(\.y|\.cxx|Tokens\.h)' | + egrep -z -v '^Source/cmFortranLexer\.' | + egrep -z -v '^Source/cmFortranParser(\.y|\.cxx|Tokens\.h)' | + egrep -z -v '^Source/cmListFileLexer(\.in\.l|\.c)' | + + # Exclude third-party sources. + egrep -z -v '^Source/bindexplib' | + egrep -z -v '^Source/(kwsys|CursesDialog/form)/' | + egrep -z -v '^Utilities/(KW|cm).*/' | + + # Exclude reference content. + egrep -z -v '^Tests/RunCMake/GenerateExportHeader/reference/' | + + # Exclude manually-formatted sources (e.g. with long lines). + egrep -z -v '^Tests/PositionIndependentTargets/pic_test.h' | + egrep -z -v '^Tests/CompileFeatures/cxx_right_angle_brackets.cpp' | + + # Exclude sources with encoding not suported by clang-format. + egrep -z -v '^Tests/RunCMake/CommandLine/cmake_depends/test_UTF-16LE.h' | # Update sources in-place. - xargs -d '\n' "$clang_format" -i + xargs -0 "$clang_format" -i ----------------------------------------------------------------------- Summary of changes: .gitattributes | 24 +++---------- Source/.gitattributes | 31 ++++++----------- Source/CursesDialog/form/.gitattributes | 1 - Tests/CompileFeatures/.gitattributes | 2 -- Tests/PositionIndependentTargets/.gitattributes | 2 -- .../CommandLine/cmake_depends/.gitattributes | 2 -- .../GenerateExportHeader/reference/.gitattributes | 2 -- Utilities/.gitattributes | 4 --- Utilities/Scripts/clang-format.bash | 36 ++++++++++++++++---- 9 files changed, 44 insertions(+), 60 deletions(-) delete mode 100644 Source/CursesDialog/form/.gitattributes delete mode 100644 Tests/CompileFeatures/.gitattributes delete mode 100644 Tests/PositionIndependentTargets/.gitattributes delete mode 100644 Tests/RunCMake/CommandLine/cmake_depends/.gitattributes delete mode 100644 Tests/RunCMake/GenerateExportHeader/reference/.gitattributes hooks/post-receive -- CMake From brad.king at kitware.com Wed Feb 22 17:02:32 2017 From: brad.king at kitware.com (Brad King) Date: Wed, 22 Feb 2017 17:02:32 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-482-g4e78fde Message-ID: <20170222220232.42950FA2BF@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 4e78fde27cf461a80bece2e82b84a3356249b92c (commit) via d5f39a56a44fe061018c6acc15e1c3aa7337ff54 (commit) via f6986ee479f1cce6da17859eaf6a0616852b9e20 (commit) via 2256c3a7db89c58ecdd0e6cfcdff7805522187f1 (commit) from e0fe4bc5ffc8b29bb337113645eb74ace68deada (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4e78fde27cf461a80bece2e82b84a3356249b92c commit 4e78fde27cf461a80bece2e82b84a3356249b92c Merge: e0fe4bc d5f39a5 Author: Brad King AuthorDate: Wed Feb 22 17:02:31 2017 -0500 Commit: CMake Topic Stage CommitDate: Wed Feb 22 17:02:31 2017 -0500 Merge topic 'clang-format-attrs' into next d5f39a56 clang-format.bash: Use Git attributes to mark files for formatting f6986ee4 Define a custom Git attribute to mark sources using our C style 2256c3a7 Define a custom Git attribute to mark source files as generated https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d5f39a56a44fe061018c6acc15e1c3aa7337ff54 commit d5f39a56a44fe061018c6acc15e1c3aa7337ff54 Author: Brad King AuthorDate: Wed Feb 22 15:01:23 2017 -0500 Commit: Brad King CommitDate: Wed Feb 22 16:59:26 2017 -0500 clang-format.bash: Use Git attributes to mark files for formatting diff --git a/.gitattributes b/.gitattributes index abb698a..3829160 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,11 +2,11 @@ .hooks* export-ignore # Custom attribute to mark sources as using our C code style. -[attr]our-c-style whitespace=tab-in-indent +[attr]our-c-style whitespace=tab-in-indent format.clang-format # Custom attribute to mark sources as generated. -# Do not perform whitespace checks. -[attr]generated whitespace=-tab-in-indent,-indent-with-non-tab +# Do not perform whitespace checks. Do not format. +[attr]generated whitespace=-tab-in-indent,-indent-with-non-tab -format.clang-format bootstrap crlf=input configure crlf=input diff --git a/Source/.gitattributes b/Source/.gitattributes index 47eedfb..1cec8a3 100644 --- a/Source/.gitattributes +++ b/Source/.gitattributes @@ -15,3 +15,7 @@ /cmFortranParser.cxx generated /cmFortranParserTokens.h generated /cmListFileLexer.c generated + +# Do not format third-party sources. +/bindexplib.* -format.clang-format +/kwsys/** -format.clang-format diff --git a/Source/CursesDialog/form/.gitattributes b/Source/CursesDialog/form/.gitattributes new file mode 100644 index 0000000..62d728c --- /dev/null +++ b/Source/CursesDialog/form/.gitattributes @@ -0,0 +1 @@ +* -format.clang-format diff --git a/Tests/CompileFeatures/.gitattributes b/Tests/CompileFeatures/.gitattributes new file mode 100644 index 0000000..83da28d --- /dev/null +++ b/Tests/CompileFeatures/.gitattributes @@ -0,0 +1,2 @@ +# Do not format a source containing C++11 '>>' syntax as C++98. +cxx_right_angle_brackets.cpp -format.clang-format diff --git a/Tests/PositionIndependentTargets/.gitattributes b/Tests/PositionIndependentTargets/.gitattributes new file mode 100644 index 0000000..ed36631 --- /dev/null +++ b/Tests/PositionIndependentTargets/.gitattributes @@ -0,0 +1,2 @@ +# Do not format a source where we want a long line preserved. +pic_test.h -format.clang-format diff --git a/Tests/RunCMake/CommandLine/cmake_depends/.gitattributes b/Tests/RunCMake/CommandLine/cmake_depends/.gitattributes new file mode 100644 index 0000000..9c22288 --- /dev/null +++ b/Tests/RunCMake/CommandLine/cmake_depends/.gitattributes @@ -0,0 +1,2 @@ +# Do not format a source encoded in UTF-16. +test_UTF-16LE.h -format.clang-format diff --git a/Tests/RunCMake/GenerateExportHeader/reference/.gitattributes b/Tests/RunCMake/GenerateExportHeader/reference/.gitattributes new file mode 100644 index 0000000..883a7f1 --- /dev/null +++ b/Tests/RunCMake/GenerateExportHeader/reference/.gitattributes @@ -0,0 +1,2 @@ +# Exclude reference content from formatting. +* -format.clang-format diff --git a/Utilities/.gitattributes b/Utilities/.gitattributes index c6345eb..bd97802 100644 --- a/Utilities/.gitattributes +++ b/Utilities/.gitattributes @@ -1,3 +1,7 @@ /Git export-ignore /GitSetup export-ignore SetupForDevelopment.sh export-ignore + +# Do not format third-party sources. +/KWIML/** -format.clang-format +/cm*/** -format.clang-format diff --git a/Utilities/Scripts/clang-format.bash b/Utilities/Scripts/clang-format.bash index 2b36ac5..edcda77 100755 --- a/Utilities/Scripts/clang-format.bash +++ b/Utilities/Scripts/clang-format.bash @@ -1,6 +1,6 @@ #!/usr/bin/env bash #============================================================================= -# Copyright 2015-2016 Kitware, Inc. +# Copyright 2015-2017 Kitware, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -106,34 +106,12 @@ case "$mode" in *) die "invalid mode: $mode" ;; esac -# Filter sources to which our style should apply. -$git_ls -z -- '*.c' '*.cc' '*.cpp' '*.cxx' '*.h' '*.hh' '*.hpp' '*.hxx' '*.cu' '*.notcu' | +# List files as selected above. +$git_ls | - # Exclude lexer/parser generator input and output. - egrep -z -v '^Source/cmCommandArgumentLexer\.' | - egrep -z -v '^Source/cmCommandArgumentParser(\.y|\.cxx|Tokens\.h)' | - egrep -z -v '^Source/cmDependsJavaLexer\.' | - egrep -z -v '^Source/cmDependsJavaParser(\.y|\.cxx|Tokens\.h)' | - egrep -z -v '^Source/cmExprLexer\.' | - egrep -z -v '^Source/cmExprParser(\.y|\.cxx|Tokens\.h)' | - egrep -z -v '^Source/cmFortranLexer\.' | - egrep -z -v '^Source/cmFortranParser(\.y|\.cxx|Tokens\.h)' | - egrep -z -v '^Source/cmListFileLexer(\.in\.l|\.c)' | - - # Exclude third-party sources. - egrep -z -v '^Source/bindexplib' | - egrep -z -v '^Source/(kwsys|CursesDialog/form)/' | - egrep -z -v '^Utilities/(KW|cm).*/' | - - # Exclude reference content. - egrep -z -v '^Tests/RunCMake/GenerateExportHeader/reference/' | - - # Exclude manually-formatted sources (e.g. with long lines). - egrep -z -v '^Tests/PositionIndependentTargets/pic_test.h' | - egrep -z -v '^Tests/CompileFeatures/cxx_right_angle_brackets.cpp' | - - # Exclude sources with encoding not suported by clang-format. - egrep -z -v '^Tests/RunCMake/CommandLine/cmake_depends/test_UTF-16LE.h' | + # Select sources with our attribute. + git check-attr --stdin format.clang-format | + sed -n '/: format\.clang-format: set$/ {s/:[^:]*:[^:]*$//p}' | # Update sources in-place. - xargs -0 "$clang_format" -i + xargs -d '\n' "$clang_format" -i https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f6986ee479f1cce6da17859eaf6a0616852b9e20 commit f6986ee479f1cce6da17859eaf6a0616852b9e20 Author: Brad King AuthorDate: Wed Feb 22 14:58:27 2017 -0500 Commit: Brad King CommitDate: Wed Feb 22 16:53:29 2017 -0500 Define a custom Git attribute to mark sources using our C style diff --git a/.gitattributes b/.gitattributes index dfc3250..abb698a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,6 +1,9 @@ .gitattributes export-ignore .hooks* export-ignore +# Custom attribute to mark sources as using our C code style. +[attr]our-c-style whitespace=tab-in-indent + # Custom attribute to mark sources as generated. # Do not perform whitespace checks. [attr]generated whitespace=-tab-in-indent,-indent-with-non-tab @@ -20,10 +23,17 @@ configure crlf=input *.sln -crlf *.vcproj -crlf -*.c whitespace=tab-in-indent -*.h whitespace=tab-in-indent -*.cxx whitespace=tab-in-indent -*.txt whitespace=tab-in-indent -*.cmake whitespace=tab-in-indent +*.c our-c-style +*.cc our-c-style +*.cpp our-c-style +*.cu our-c-style +*.cxx our-c-style +*.h our-c-style +*.hh our-c-style +*.hpp our-c-style +*.hxx our-c-style +*.notcu our-c-style +*.cmake whitespace=tab-in-indent *.rst whitespace=tab-in-indent conflict-marker-size=79 +*.txt whitespace=tab-in-indent https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=2256c3a7db89c58ecdd0e6cfcdff7805522187f1 commit 2256c3a7db89c58ecdd0e6cfcdff7805522187f1 Author: Brad King AuthorDate: Wed Feb 22 14:33:30 2017 -0500 Commit: Brad King CommitDate: Wed Feb 22 16:53:26 2017 -0500 Define a custom Git attribute to mark source files as generated diff --git a/.gitattributes b/.gitattributes index d959918..dfc3250 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,6 +1,10 @@ .gitattributes export-ignore .hooks* export-ignore +# Custom attribute to mark sources as generated. +# Do not perform whitespace checks. +[attr]generated whitespace=-tab-in-indent,-indent-with-non-tab + bootstrap crlf=input configure crlf=input *.[1-9] crlf=input diff --git a/Source/.gitattributes b/Source/.gitattributes index dbd6382..47eedfb 100644 --- a/Source/.gitattributes +++ b/Source/.gitattributes @@ -1,10 +1,17 @@ -# Preserve indentation style in generated code. -cmCommandArgumentLexer.cxx whitespace=-tab-in-indent,-indent-with-non-tab -cmCommandArgumentLexer.h whitespace=-tab-in-indent,-indent-with-non-tab -cmDependsJavaLexer.cxx whitespace=-tab-in-indent,-indent-with-non-tab -cmDependsJavaLexer.h whitespace=-tab-in-indent,-indent-with-non-tab -cmExprLexer.cxx whitespace=-tab-in-indent,-indent-with-non-tab -cmExprLexer.h whitespace=-tab-in-indent,-indent-with-non-tab -cmFortranLexer.cxx whitespace=-tab-in-indent,-indent-with-non-tab -cmFortranLexer.h whitespace=-tab-in-indent,-indent-with-non-tab -cmListFileLexer.c whitespace=-tab-in-indent,-indent-with-non-tab +/cmCommandArgumentLexer.cxx generated +/cmCommandArgumentLexer.h generated +/cmCommandArgumentParser.cxx generated +/cmCommandArgumentParserTokens.h generated +/cmDependsJavaLexer.cxx generated +/cmDependsJavaLexer.h generated +/cmDependsJavaParser.cxx generated +/cmDependsJavaParserTokens.h generated +/cmExprLexer.cxx generated +/cmExprLexer.h generated +/cmExprParser.cxx generated +/cmExprParserTokens.h generated +/cmFortranLexer.cxx generated +/cmFortranLexer.h generated +/cmFortranParser.cxx generated +/cmFortranParserTokens.h generated +/cmListFileLexer.c generated ----------------------------------------------------------------------- Summary of changes: .gitattributes | 24 ++++++++++--- Source/.gitattributes | 31 +++++++++++------ Source/CursesDialog/form/.gitattributes | 1 + Tests/CompileFeatures/.gitattributes | 2 ++ Tests/PositionIndependentTargets/.gitattributes | 2 ++ .../CommandLine/cmake_depends/.gitattributes | 2 ++ .../GenerateExportHeader/reference/.gitattributes | 2 ++ Utilities/.gitattributes | 4 +++ Utilities/Scripts/clang-format.bash | 36 ++++---------------- 9 files changed, 60 insertions(+), 44 deletions(-) create mode 100644 Source/CursesDialog/form/.gitattributes create mode 100644 Tests/CompileFeatures/.gitattributes create mode 100644 Tests/PositionIndependentTargets/.gitattributes create mode 100644 Tests/RunCMake/CommandLine/cmake_depends/.gitattributes create mode 100644 Tests/RunCMake/GenerateExportHeader/reference/.gitattributes hooks/post-receive -- CMake From kwrobot at kitware.com Thu Feb 23 00:01:05 2017 From: kwrobot at kitware.com (Kitware Robot) Date: Thu, 23 Feb 2017 00:01:05 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-245-g77cbcb7 Message-ID: <20170223050105.D96B5FA205@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 77cbcb76bb5d75254c6ced0ed782152024f51d8c (commit) from b803d00bc1a6b5ff37867ea70cc3c0bda018ee2c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=77cbcb76bb5d75254c6ced0ed782152024f51d8c commit 77cbcb76bb5d75254c6ced0ed782152024f51d8c Author: Kitware Robot AuthorDate: Thu Feb 23 00:01:03 2017 -0500 Commit: Kitware Robot CommitDate: Thu Feb 23 00:01:03 2017 -0500 CMake Nightly Date Stamp diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index d8261b7..0dc9dad 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 8) -set(CMake_VERSION_PATCH 20170222) +set(CMake_VERSION_PATCH 20170223) #set(CMake_VERSION_RC 1) ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 23 07:12:33 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 23 Feb 2017 07:12:33 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-485-g7c3dd73 Message-ID: <20170223121233.EEBA0C02E3@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 7c3dd733d37449045a062f0ecc1c465b06163e58 (commit) via 1f37e987d0d2dcfdb55d4248d3f7ade9de68ec71 (commit) via 64c33f118272a5d1f8d380587b6a67615eadcc57 (commit) from 4e78fde27cf461a80bece2e82b84a3356249b92c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7c3dd733d37449045a062f0ecc1c465b06163e58 commit 7c3dd733d37449045a062f0ecc1c465b06163e58 Merge: 4e78fde 1f37e98 Author: Brad King AuthorDate: Thu Feb 23 07:12:32 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 23 07:12:32 2017 -0500 Merge topic 'update-libarchive' into next 1f37e987 libarchive: Avoid using isblank 64c33f11 libarchive: Avoid declaration after statement in C code https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1f37e987d0d2dcfdb55d4248d3f7ade9de68ec71 commit 1f37e987d0d2dcfdb55d4248d3f7ade9de68ec71 Author: Brad King AuthorDate: Thu Feb 23 06:57:26 2017 -0500 Commit: Brad King CommitDate: Thu Feb 23 06:57:26 2017 -0500 libarchive: Avoid using isblank It is not available on VS 2012 and below. diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c index 5e22438..1e3b518 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c @@ -531,6 +531,10 @@ time_from_tm(struct tm *t) #endif } +static int la_isblank(int c) { + return c == ' ' || c == '\t'; +} + static time_t xstrpisotime(const char *s, char **endptr) { @@ -543,7 +547,7 @@ xstrpisotime(const char *s, char **endptr) /* as a courtesy to our callers, and since this is a non-standard * routine, we skip leading whitespace */ - while (isblank((unsigned char)*s)) + while (la_isblank((unsigned char)*s)) ++s; /* read year */ @@ -619,7 +623,7 @@ _warc_rdver(const char *buf, size_t bsz) if (memcmp(buf + 3U + end, "\r\n", 2U) != 0) ver = 0U; } else if (ver < 1200U) { - if (!isblank(*(buf + 3U + end))) + if (!la_isblank(*(buf + 3U + end))) ver = 0U; } } @@ -643,7 +647,7 @@ _warc_rdtyp(const char *buf, size_t bsz) } /* overread whitespace */ - while (val < eol && isblank((unsigned char)*val)) + while (val < eol && la_isblank((unsigned char)*val)) ++val; if (val + 8U == eol) { @@ -673,7 +677,7 @@ _warc_rduri(const char *buf, size_t bsz) return res; } - while (val < eol && isblank((unsigned char)*val)) + while (val < eol && la_isblank((unsigned char)*val)) ++val; /* overread URL designators */ @@ -731,7 +735,7 @@ _warc_rdlen(const char *buf, size_t bsz) } /* skip leading whitespace */ - while (val < eol && isblank(*val)) + while (val < eol && la_isblank(*val)) val++; /* there must be at least one digit */ if (!isdigit(*val)) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=64c33f118272a5d1f8d380587b6a67615eadcc57 commit 64c33f118272a5d1f8d380587b6a67615eadcc57 Author: Brad King AuthorDate: Thu Feb 23 06:50:21 2017 -0500 Commit: Brad King CommitDate: Thu Feb 23 06:50:21 2017 -0500 libarchive: Avoid declaration after statement in C code diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c index eb98491..4adf68e 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c @@ -4074,8 +4074,10 @@ write_information_block(struct archive_write *a) memset(info.s, 0, info_size); opt = 0; #if defined(HAVE__CTIME64_S) - __time64_t iso9660_birth_time_tmp = (__time64_t) iso9660->birth_time; //time_t may be shorter than 64 bits - _ctime64_s(buf, sizeof(buf), &(iso9660_birth_time_tmp)); + { + __time64_t iso9660_birth_time_tmp = (__time64_t) iso9660->birth_time; //time_t may be shorter than 64 bits + _ctime64_s(buf, sizeof(buf), &(iso9660_birth_time_tmp)); + } #elif defined(HAVE_CTIME_R) ctime_r(&(iso9660->birth_time), buf); #else ----------------------------------------------------------------------- Summary of changes: .../libarchive/archive_read_support_format_warc.c | 14 +++++++++----- .../libarchive/archive_write_set_format_iso9660.c | 6 ++++-- 2 files changed, 13 insertions(+), 7 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 23 07:13:16 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 23 Feb 2017 07:13:16 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-487-g6790a78 Message-ID: <20170223121316.0AAB0E1102@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 6790a78a1199a40bf1de5bbe6762668d7dd266ab (commit) via dc35291b99827855ee454acc9fc441400121e16e (commit) from 7c3dd733d37449045a062f0ecc1c465b06163e58 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6790a78a1199a40bf1de5bbe6762668d7dd266ab commit 6790a78a1199a40bf1de5bbe6762668d7dd266ab Merge: 7c3dd73 dc35291 Author: Brad King AuthorDate: Thu Feb 23 07:13:15 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 23 07:13:15 2017 -0500 Merge topic 'update-libarchive' into next dc35291b fixup! libarchive: Avoid using isblank https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=dc35291b99827855ee454acc9fc441400121e16e commit dc35291b99827855ee454acc9fc441400121e16e Author: Brad King AuthorDate: Thu Feb 23 07:13:05 2017 -0500 Commit: Brad King CommitDate: Thu Feb 23 07:13:05 2017 -0500 fixup! libarchive: Avoid using isblank diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c index 1e3b518..c3e86c0 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c @@ -532,7 +532,7 @@ time_from_tm(struct tm *t) } static int la_isblank(int c) { - return c == ' ' || c == '\t'; + return c == ' ' || c == '\t'; } static time_t ----------------------------------------------------------------------- Summary of changes: Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 23 07:13:52 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 23 Feb 2017 07:13:52 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-491-g169bff4 Message-ID: <20170223121352.E18F2E1102@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 169bff43f65cb53f8b825b8f2e981c683ac08ea1 (commit) via ffa6c85bf958b3334c201168b2a6510f809b7cb1 (commit) via 8e2e2a44b1215552fbe36963a247fa73b7dec9f1 (commit) via 86b58f2606e771bde2e2a25ff9384fc34cbe891c (commit) from 6790a78a1199a40bf1de5bbe6762668d7dd266ab (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=169bff43f65cb53f8b825b8f2e981c683ac08ea1 commit 169bff43f65cb53f8b825b8f2e981c683ac08ea1 Merge: 6790a78 ffa6c85 Author: Brad King AuthorDate: Thu Feb 23 07:13:51 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 23 07:13:51 2017 -0500 Merge topic 'update-libarchive' into next ffa6c85b Update CMake pre-cached values for libarchive 3.3.0 8e2e2a44 libarchive: Avoid using isblank 86b58f26 libarchive: Avoid declaration after statement in C code https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ffa6c85bf958b3334c201168b2a6510f809b7cb1 commit ffa6c85bf958b3334c201168b2a6510f809b7cb1 Author: Brad King AuthorDate: Mon Feb 20 09:10:11 2017 -0500 Commit: Brad King CommitDate: Thu Feb 23 07:13:40 2017 -0500 Update CMake pre-cached values for libarchive 3.3.0 diff --git a/CMakeLists.txt b/CMakeLists.txt index bec81a3..e613224 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -421,14 +421,15 @@ macro (CMAKE_BUILD_UTILITIES) if(NOT LIBLZMA_FOUND) message(FATAL_ERROR "CMAKE_USE_SYSTEM_LIBLZMA is ON but LibLZMA is not found!") endif() - set(LZMA_INCLUDE_DIR ${LIBLZMA_INCLUDE_DIRS}) - set(LZMA_LIBRARY ${LIBLZMA_LIBRARIES}) else() add_subdirectory(Utilities/cmliblzma) CMAKE_SET_TARGET_FOLDER(cmliblzma "Utilities/3rdParty") - set(LZMA_INCLUDE_DIR + set(LIBLZMA_HAS_AUTO_DECODER 1) + set(LIBLZMA_HAS_EASY_ENCODER 1) + set(LIBLZMA_HAS_LZMA_PRESET 1) + set(LIBLZMA_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Utilities/cmliblzma/liblzma/api") - set(LZMA_LIBRARY cmliblzma) + set(LIBLZMA_LIBRARY cmliblzma) endif() endif() @@ -449,13 +450,14 @@ macro (CMAKE_BUILD_UTILITIES) add_definitions(-DLIBARCHIVE_STATIC) set(ENABLE_NETTLE OFF CACHE INTERNAL "Enable use of Nettle") set(ENABLE_OPENSSL ${CMAKE_USE_OPENSSL} CACHE INTERNAL "Enable use of OpenSSL") - set(ENABLE_LZMA ON CACHE INTERNAL "Enable the use of the system found LZMA library if found") - set(ENABLE_ZLIB ON CACHE INTERNAL "Enable the use of the system found ZLIB library if found") - set(ENABLE_BZip2 ON CACHE INTERNAL "Enable the use of the system found BZip2 library if found") - set(ENABLE_LIBXML2 OFF CACHE INTERNAL "Enable the use of the system found libxml2 library if found") - set(ENABLE_EXPAT ON CACHE INTERNAL "Enable the use of the system found EXPAT library if found") - set(ENABLE_PCREPOSIX OFF CACHE INTERNAL "Enable the use of the system found PCREPOSIX library if found") - set(ENABLE_LibGCC OFF CACHE INTERNAL "Enable the use of the system found LibGCC library if found") + set(ENABLE_LZMA ON CACHE INTERNAL "Enable the use of the system LZMA library if found") + set(ENABLE_LZO OFF CACHE INTERNAL "Enable the use of the system LZO library if found") + set(ENABLE_ZLIB ON CACHE INTERNAL "Enable the use of the system ZLIB library if found") + set(ENABLE_BZip2 ON CACHE INTERNAL "Enable the use of the system BZip2 library if found") + set(ENABLE_LIBXML2 OFF CACHE INTERNAL "Enable the use of the system libxml2 library if found") + set(ENABLE_EXPAT ON CACHE INTERNAL "Enable the use of the system EXPAT library if found") + set(ENABLE_PCREPOSIX OFF CACHE INTERNAL "Enable the use of the system PCREPOSIX library if found") + set(ENABLE_LibGCC OFF CACHE INTERNAL "Enable the use of the system LibGCC library if found") set(ENABLE_XATTR OFF CACHE INTERNAL "Enable extended attribute support") set(ENABLE_ACL OFF CACHE INTERNAL "Enable ACL support") set(ENABLE_ICONV OFF CACHE INTERNAL "Enable iconv support") https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8e2e2a44b1215552fbe36963a247fa73b7dec9f1 commit 8e2e2a44b1215552fbe36963a247fa73b7dec9f1 Author: Brad King AuthorDate: Thu Feb 23 06:57:26 2017 -0500 Commit: Brad King CommitDate: Thu Feb 23 07:13:40 2017 -0500 libarchive: Avoid using isblank It is not available on VS 2012 and below. Use our own impl instead. diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c index 5e22438..c3e86c0 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c @@ -531,6 +531,10 @@ time_from_tm(struct tm *t) #endif } +static int la_isblank(int c) { + return c == ' ' || c == '\t'; +} + static time_t xstrpisotime(const char *s, char **endptr) { @@ -543,7 +547,7 @@ xstrpisotime(const char *s, char **endptr) /* as a courtesy to our callers, and since this is a non-standard * routine, we skip leading whitespace */ - while (isblank((unsigned char)*s)) + while (la_isblank((unsigned char)*s)) ++s; /* read year */ @@ -619,7 +623,7 @@ _warc_rdver(const char *buf, size_t bsz) if (memcmp(buf + 3U + end, "\r\n", 2U) != 0) ver = 0U; } else if (ver < 1200U) { - if (!isblank(*(buf + 3U + end))) + if (!la_isblank(*(buf + 3U + end))) ver = 0U; } } @@ -643,7 +647,7 @@ _warc_rdtyp(const char *buf, size_t bsz) } /* overread whitespace */ - while (val < eol && isblank((unsigned char)*val)) + while (val < eol && la_isblank((unsigned char)*val)) ++val; if (val + 8U == eol) { @@ -673,7 +677,7 @@ _warc_rduri(const char *buf, size_t bsz) return res; } - while (val < eol && isblank((unsigned char)*val)) + while (val < eol && la_isblank((unsigned char)*val)) ++val; /* overread URL designators */ @@ -731,7 +735,7 @@ _warc_rdlen(const char *buf, size_t bsz) } /* skip leading whitespace */ - while (val < eol && isblank(*val)) + while (val < eol && la_isblank(*val)) val++; /* there must be at least one digit */ if (!isdigit(*val)) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=86b58f2606e771bde2e2a25ff9384fc34cbe891c commit 86b58f2606e771bde2e2a25ff9384fc34cbe891c Author: Brad King AuthorDate: Thu Feb 23 06:50:21 2017 -0500 Commit: Brad King CommitDate: Thu Feb 23 07:13:39 2017 -0500 libarchive: Avoid declaration after statement in C code diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c index eb98491..4adf68e 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c @@ -4074,8 +4074,10 @@ write_information_block(struct archive_write *a) memset(info.s, 0, info_size); opt = 0; #if defined(HAVE__CTIME64_S) - __time64_t iso9660_birth_time_tmp = (__time64_t) iso9660->birth_time; //time_t may be shorter than 64 bits - _ctime64_s(buf, sizeof(buf), &(iso9660_birth_time_tmp)); + { + __time64_t iso9660_birth_time_tmp = (__time64_t) iso9660->birth_time; //time_t may be shorter than 64 bits + _ctime64_s(buf, sizeof(buf), &(iso9660_birth_time_tmp)); + } #elif defined(HAVE_CTIME_R) ctime_r(&(iso9660->birth_time), buf); #else ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 23 07:15:30 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 23 Feb 2017 07:15:30 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-497-gf0e2f9e Message-ID: <20170223121530.89CC5F59DA@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via f0e2f9e063e08ab02a15d1ffbd3252984eec0845 (commit) via d49176e91e4fb4ae31be1011c1029ca07d2cf494 (commit) via ce8f117fe2c10f1ebd56cb8adec0dcde1fc62457 (commit) via e0f725f821f251165c17a7580c2000342ac505a2 (commit) via ae4861ec2214cb025f8bf2426376a4aca9809d73 (commit) via fecb70dd34b5ba244263e72c42f90701775e132f (commit) from 169bff43f65cb53f8b825b8f2e981c683ac08ea1 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f0e2f9e063e08ab02a15d1ffbd3252984eec0845 commit f0e2f9e063e08ab02a15d1ffbd3252984eec0845 Merge: 169bff4 d49176e Author: Brad King AuthorDate: Thu Feb 23 07:15:29 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 23 07:15:29 2017 -0500 Merge topic 'update-libarchive' into next d49176e9 libarchive: Avoid using isblank ce8f117f libarchive: Avoid declaration after statement in C code e0f725f8 libarchive: Fix use of ssize_t in archive_entry.h ae4861ec libarchive: Define __LA_DEPRECATED consistently fecb70dd Update CMake pre-cached values for libarchive 3.3.0 https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d49176e91e4fb4ae31be1011c1029ca07d2cf494 commit d49176e91e4fb4ae31be1011c1029ca07d2cf494 Author: Brad King AuthorDate: Thu Feb 23 06:57:26 2017 -0500 Commit: Brad King CommitDate: Thu Feb 23 07:15:21 2017 -0500 libarchive: Avoid using isblank It is not available on VS 2012 and below. Use our own impl instead. diff --git a/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c b/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c index 5e22438..c3e86c0 100644 --- a/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c +++ b/Utilities/cmlibarchive/libarchive/archive_read_support_format_warc.c @@ -531,6 +531,10 @@ time_from_tm(struct tm *t) #endif } +static int la_isblank(int c) { + return c == ' ' || c == '\t'; +} + static time_t xstrpisotime(const char *s, char **endptr) { @@ -543,7 +547,7 @@ xstrpisotime(const char *s, char **endptr) /* as a courtesy to our callers, and since this is a non-standard * routine, we skip leading whitespace */ - while (isblank((unsigned char)*s)) + while (la_isblank((unsigned char)*s)) ++s; /* read year */ @@ -619,7 +623,7 @@ _warc_rdver(const char *buf, size_t bsz) if (memcmp(buf + 3U + end, "\r\n", 2U) != 0) ver = 0U; } else if (ver < 1200U) { - if (!isblank(*(buf + 3U + end))) + if (!la_isblank(*(buf + 3U + end))) ver = 0U; } } @@ -643,7 +647,7 @@ _warc_rdtyp(const char *buf, size_t bsz) } /* overread whitespace */ - while (val < eol && isblank((unsigned char)*val)) + while (val < eol && la_isblank((unsigned char)*val)) ++val; if (val + 8U == eol) { @@ -673,7 +677,7 @@ _warc_rduri(const char *buf, size_t bsz) return res; } - while (val < eol && isblank((unsigned char)*val)) + while (val < eol && la_isblank((unsigned char)*val)) ++val; /* overread URL designators */ @@ -731,7 +735,7 @@ _warc_rdlen(const char *buf, size_t bsz) } /* skip leading whitespace */ - while (val < eol && isblank(*val)) + while (val < eol && la_isblank(*val)) val++; /* there must be at least one digit */ if (!isdigit(*val)) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ce8f117fe2c10f1ebd56cb8adec0dcde1fc62457 commit ce8f117fe2c10f1ebd56cb8adec0dcde1fc62457 Author: Brad King AuthorDate: Thu Feb 23 06:50:21 2017 -0500 Commit: Brad King CommitDate: Thu Feb 23 07:15:21 2017 -0500 libarchive: Avoid declaration after statement in C code diff --git a/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c b/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c index eb98491..4adf68e 100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_set_format_iso9660.c @@ -4074,8 +4074,10 @@ write_information_block(struct archive_write *a) memset(info.s, 0, info_size); opt = 0; #if defined(HAVE__CTIME64_S) - __time64_t iso9660_birth_time_tmp = (__time64_t) iso9660->birth_time; //time_t may be shorter than 64 bits - _ctime64_s(buf, sizeof(buf), &(iso9660_birth_time_tmp)); + { + __time64_t iso9660_birth_time_tmp = (__time64_t) iso9660->birth_time; //time_t may be shorter than 64 bits + _ctime64_s(buf, sizeof(buf), &(iso9660_birth_time_tmp)); + } #elif defined(HAVE_CTIME_R) ctime_r(&(iso9660->birth_time), buf); #else https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e0f725f821f251165c17a7580c2000342ac505a2 commit e0f725f821f251165c17a7580c2000342ac505a2 Author: Brad King AuthorDate: Mon Feb 20 09:08:29 2017 -0500 Commit: Brad King CommitDate: Thu Feb 23 07:15:21 2017 -0500 libarchive: Fix use of ssize_t in archive_entry.h This type is not available on Windows compilers so for clients including this header we need to use `la_ssize_t` instead as we do in `archive.h`. diff --git a/Utilities/cmlibarchive/libarchive/archive_entry.h b/Utilities/cmlibarchive/libarchive/archive_entry.h index fe86ee3..c331117 100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry.h +++ b/Utilities/cmlibarchive/libarchive/archive_entry.h @@ -66,6 +66,27 @@ typedef int64_t la_int64_t; # endif #endif +/* The la_ssize_t should match the type used in 'struct stat' */ +#if !defined(__LA_SSIZE_T_DEFINED) +/* Older code relied on the __LA_SSIZE_T macro; after 4.0 we'll switch to the typedef exclusively. */ +# if ARCHIVE_VERSION_NUMBER < 4000000 +#define __LA_SSIZE_T la_ssize_t +# endif +#define __LA_SSIZE_T_DEFINED +# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__) +# if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_) +typedef ssize_t la_ssize_t; +# elif defined(_WIN64) +typedef __int64 la_ssize_t; +# else +typedef long la_ssize_t; +# endif +# else +# include /* ssize_t */ +typedef ssize_t la_ssize_t; +# endif +#endif + /* Get a suitable definition for mode_t */ #if ARCHIVE_VERSION_NUMBER >= 3999000 /* Switch to plain 'int' for libarchive 4.0. It's less broken than 'mode_t' */ @@ -523,9 +544,9 @@ __LA_DECL int archive_entry_acl_next_w(struct archive_entry *, int /* want_type #define ARCHIVE_ENTRY_ACL_STYLE_COMPACT 0x00000010 __LA_DECL wchar_t *archive_entry_acl_to_text_w(struct archive_entry *, - ssize_t * /* len */, int /* flags */); + la_ssize_t * /* len */, int /* flags */); __LA_DECL char *archive_entry_acl_to_text(struct archive_entry *, - ssize_t * /* len */, int /* flags */); + la_ssize_t * /* len */, int /* flags */); __LA_DECL int archive_entry_acl_from_text_w(struct archive_entry *, const wchar_t * /* wtext */, int /* type */); __LA_DECL int archive_entry_acl_from_text(struct archive_entry *, https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ae4861ec2214cb025f8bf2426376a4aca9809d73 commit ae4861ec2214cb025f8bf2426376a4aca9809d73 Author: Brad King AuthorDate: Mon Feb 20 08:10:33 2017 -0500 Commit: Brad King CommitDate: Thu Feb 23 07:15:20 2017 -0500 libarchive: Define __LA_DEPRECATED consistently Upstream libarchive now defines this macro in two places with the same logic in both. However, CMake's bundled copy disables this macro, so we need to update the new location of its definition to be consistent. diff --git a/Utilities/cmlibarchive/libarchive/archive_entry.h b/Utilities/cmlibarchive/libarchive/archive_entry.h index 9427413..fe86ee3 100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry.h +++ b/Utilities/cmlibarchive/libarchive/archive_entry.h @@ -105,11 +105,8 @@ typedef int64_t la_int64_t; # define __LA_DECL #endif -#if defined(__GNUC__) && __GNUC__ >= 3 && __GNUC_MINOR__ >= 1 -# define __LA_DEPRECATED __attribute__((deprecated)) -#else -# define __LA_DEPRECATED -#endif +/* CMake uses some deprecated APIs to build with old libarchive versions. */ +#define __LA_DEPRECATED #ifdef __cplusplus extern "C" { https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=fecb70dd34b5ba244263e72c42f90701775e132f commit fecb70dd34b5ba244263e72c42f90701775e132f Author: Brad King AuthorDate: Mon Feb 20 09:10:11 2017 -0500 Commit: Brad King CommitDate: Thu Feb 23 07:15:19 2017 -0500 Update CMake pre-cached values for libarchive 3.3.0 diff --git a/CMakeLists.txt b/CMakeLists.txt index bec81a3..e613224 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -421,14 +421,15 @@ macro (CMAKE_BUILD_UTILITIES) if(NOT LIBLZMA_FOUND) message(FATAL_ERROR "CMAKE_USE_SYSTEM_LIBLZMA is ON but LibLZMA is not found!") endif() - set(LZMA_INCLUDE_DIR ${LIBLZMA_INCLUDE_DIRS}) - set(LZMA_LIBRARY ${LIBLZMA_LIBRARIES}) else() add_subdirectory(Utilities/cmliblzma) CMAKE_SET_TARGET_FOLDER(cmliblzma "Utilities/3rdParty") - set(LZMA_INCLUDE_DIR + set(LIBLZMA_HAS_AUTO_DECODER 1) + set(LIBLZMA_HAS_EASY_ENCODER 1) + set(LIBLZMA_HAS_LZMA_PRESET 1) + set(LIBLZMA_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Utilities/cmliblzma/liblzma/api") - set(LZMA_LIBRARY cmliblzma) + set(LIBLZMA_LIBRARY cmliblzma) endif() endif() @@ -449,13 +450,14 @@ macro (CMAKE_BUILD_UTILITIES) add_definitions(-DLIBARCHIVE_STATIC) set(ENABLE_NETTLE OFF CACHE INTERNAL "Enable use of Nettle") set(ENABLE_OPENSSL ${CMAKE_USE_OPENSSL} CACHE INTERNAL "Enable use of OpenSSL") - set(ENABLE_LZMA ON CACHE INTERNAL "Enable the use of the system found LZMA library if found") - set(ENABLE_ZLIB ON CACHE INTERNAL "Enable the use of the system found ZLIB library if found") - set(ENABLE_BZip2 ON CACHE INTERNAL "Enable the use of the system found BZip2 library if found") - set(ENABLE_LIBXML2 OFF CACHE INTERNAL "Enable the use of the system found libxml2 library if found") - set(ENABLE_EXPAT ON CACHE INTERNAL "Enable the use of the system found EXPAT library if found") - set(ENABLE_PCREPOSIX OFF CACHE INTERNAL "Enable the use of the system found PCREPOSIX library if found") - set(ENABLE_LibGCC OFF CACHE INTERNAL "Enable the use of the system found LibGCC library if found") + set(ENABLE_LZMA ON CACHE INTERNAL "Enable the use of the system LZMA library if found") + set(ENABLE_LZO OFF CACHE INTERNAL "Enable the use of the system LZO library if found") + set(ENABLE_ZLIB ON CACHE INTERNAL "Enable the use of the system ZLIB library if found") + set(ENABLE_BZip2 ON CACHE INTERNAL "Enable the use of the system BZip2 library if found") + set(ENABLE_LIBXML2 OFF CACHE INTERNAL "Enable the use of the system libxml2 library if found") + set(ENABLE_EXPAT ON CACHE INTERNAL "Enable the use of the system EXPAT library if found") + set(ENABLE_PCREPOSIX OFF CACHE INTERNAL "Enable the use of the system PCREPOSIX library if found") + set(ENABLE_LibGCC OFF CACHE INTERNAL "Enable the use of the system LibGCC library if found") set(ENABLE_XATTR OFF CACHE INTERNAL "Enable extended attribute support") set(ENABLE_ACL OFF CACHE INTERNAL "Enable ACL support") set(ENABLE_ICONV OFF CACHE INTERNAL "Enable iconv support") ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 23 07:17:51 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 23 Feb 2017 07:17:51 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-499-gec6c9db Message-ID: <20170223121751.8B723F6BEB@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via ec6c9db25ddf2ecc464f54c3dc666c93ed60d3dc (commit) via 7788db9c4ee673fda9181de656363884d790592a (commit) from f0e2f9e063e08ab02a15d1ffbd3252984eec0845 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ec6c9db25ddf2ecc464f54c3dc666c93ed60d3dc commit ec6c9db25ddf2ecc464f54c3dc666c93ed60d3dc Merge: f0e2f9e 7788db9 Author: Brad King AuthorDate: Thu Feb 23 07:17:51 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 23 07:17:51 2017 -0500 Merge topic 'cmake_m4_find_package_var_check' into next 7788db9c cmake.m4: do not set _XXXFLAGS or _LIBS var if already set https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7788db9c4ee673fda9181de656363884d790592a commit 7788db9c4ee673fda9181de656363884d790592a Author: John Donoghue AuthorDate: Sun Feb 12 13:57:19 2017 -0500 Commit: Brad King CommitDate: Thu Feb 23 07:16:16 2017 -0500 cmake.m4: do not set _XXXFLAGS or _LIBS var if already set * Auxiliary/cmake.m4 (CMAKE_FIND_PACKAGE): change var tests from -n to -z to check if var is already set before calling cmake Fixes: #14460, #16663 diff --git a/Auxiliary/cmake.m4 b/Auxiliary/cmake.m4 index 3ef4c16..7beff41 100644 --- a/Auxiliary/cmake.m4 +++ b/Auxiliary/cmake.m4 @@ -24,10 +24,10 @@ AC_ARG_VAR([$1][_LIBS], [linker flags for $1. This overrides the cmake output])d failed=false AC_MSG_CHECKING([for $1]) -if test -n "$1[]_$2[]FLAGS"; then +if test -z "${$1[]_$2[]FLAGS}"; then $1[]_$2[]FLAGS=`$CMAKE_BINARY --find-package "-DNAME=$1" "-DCOMPILER_ID=m4_default([$3], [GNU])" "-DLANGUAGE=$2" -DMODE=COMPILE $4` || failed=true fi -if test -n "$1[]_LIBS"; then +if test -z "${$1[]_LIBS}"; then $1[]_LIBS=`$CMAKE_BINARY --find-package "-DNAME=$1" "-DCOMPILER_ID=m4_default([$3], [GNU])" "-DLANGUAGE=$2" -DMODE=LINK $4` || failed=true fi ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 23 07:34:14 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 23 Feb 2017 07:34:14 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-502-gafdef5f Message-ID: <20170223123414.B189EFA696@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via afdef5f94742f17434b08a8c2678735a0db4f1ab (commit) via 0c14db2558a3792b59da08ebeccdc1f3acba945a (commit) via 77cbcb76bb5d75254c6ced0ed782152024f51d8c (commit) from ec6c9db25ddf2ecc464f54c3dc666c93ed60d3dc (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=afdef5f94742f17434b08a8c2678735a0db4f1ab commit afdef5f94742f17434b08a8c2678735a0db4f1ab Merge: ec6c9db 0c14db2 Author: Brad King AuthorDate: Thu Feb 23 07:34:14 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 23 07:34:14 2017 -0500 Merge topic 'cmake-server-aix' into next 0c14db25 cmServerConnection.h: Include cmConfigure.h first 77cbcb76 CMake Nightly Date Stamp https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0c14db2558a3792b59da08ebeccdc1f3acba945a commit 0c14db2558a3792b59da08ebeccdc1f3acba945a Author: Brad King AuthorDate: Thu Feb 23 07:32:24 2017 -0500 Commit: Brad King CommitDate: Thu Feb 23 07:32:24 2017 -0500 cmServerConnection.h: Include cmConfigure.h first We need this to make Large File Support definitions consistent with other translation units. diff --git a/Source/cmServerConnection.h b/Source/cmServerConnection.h index 3efe28d..9357831 100644 --- a/Source/cmServerConnection.h +++ b/Source/cmServerConnection.h @@ -2,6 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #pragma once +#include // IWYU pragma: keep + #include #include ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- Source/cmServerConnection.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 23 07:35:28 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 23 Feb 2017 07:35:28 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-247-ge2717d6 Message-ID: <20170223123528.BEDEEFA6C4@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via e2717d69df8eee036cfa5be431e019e117b94efe (commit) via 7788db9c4ee673fda9181de656363884d790592a (commit) from 77cbcb76bb5d75254c6ced0ed782152024f51d8c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e2717d69df8eee036cfa5be431e019e117b94efe commit e2717d69df8eee036cfa5be431e019e117b94efe Merge: 77cbcb7 7788db9 Author: Brad King AuthorDate: Thu Feb 23 07:35:26 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 23 07:35:26 2017 -0500 Merge topic 'cmake_m4_find_package_var_check' 7788db9c cmake.m4: do not set _XXXFLAGS or _LIBS var if already set ----------------------------------------------------------------------- Summary of changes: Auxiliary/cmake.m4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 23 07:35:31 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 23 Feb 2017 07:35:31 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-249-ge68aad3 Message-ID: <20170223123531.67BC8FA6C4@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via e68aad3eb88b910266b7af3f80f9ee8a6370401c (commit) via 934eb497f211b2e48ba070041ba775e1ac55d01d (commit) from e2717d69df8eee036cfa5be431e019e117b94efe (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e68aad3eb88b910266b7af3f80f9ee8a6370401c commit e68aad3eb88b910266b7af3f80f9ee8a6370401c Merge: e2717d6 934eb49 Author: Brad King AuthorDate: Thu Feb 23 07:35:29 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 23 07:35:29 2017 -0500 Merge topic 'FindCUDA-fix-init' 934eb497 FindCUDA: Fix PTX selection with multiple architectures ----------------------------------------------------------------------- Summary of changes: Modules/FindCUDA/select_compute_arch.cmake | 1 + 1 file changed, 1 insertion(+) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 23 07:35:35 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 23 Feb 2017 07:35:35 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-253-gd23f441 Message-ID: <20170223123535.C3DFEFA6CD@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via d23f4414c44b977abc3f9ff49aa06f709a3d9db1 (commit) via d5f39a56a44fe061018c6acc15e1c3aa7337ff54 (commit) via f6986ee479f1cce6da17859eaf6a0616852b9e20 (commit) via 2256c3a7db89c58ecdd0e6cfcdff7805522187f1 (commit) from e68aad3eb88b910266b7af3f80f9ee8a6370401c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d23f4414c44b977abc3f9ff49aa06f709a3d9db1 commit d23f4414c44b977abc3f9ff49aa06f709a3d9db1 Merge: e68aad3 d5f39a5 Author: Brad King AuthorDate: Thu Feb 23 07:35:32 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 23 07:35:32 2017 -0500 Merge topic 'clang-format-attrs' d5f39a56 clang-format.bash: Use Git attributes to mark files for formatting f6986ee4 Define a custom Git attribute to mark sources using our C style 2256c3a7 Define a custom Git attribute to mark source files as generated ----------------------------------------------------------------------- Summary of changes: .gitattributes | 24 ++++++++++--- Source/.gitattributes | 31 +++++++++++------ Source/CursesDialog/form/.gitattributes | 1 + Tests/CompileFeatures/.gitattributes | 2 ++ Tests/PositionIndependentTargets/.gitattributes | 2 ++ .../CommandLine/cmake_depends/.gitattributes | 2 ++ .../GenerateExportHeader/reference/.gitattributes | 2 ++ Utilities/.gitattributes | 4 +++ Utilities/Scripts/clang-format.bash | 36 ++++---------------- 9 files changed, 60 insertions(+), 44 deletions(-) create mode 100644 Source/CursesDialog/form/.gitattributes create mode 100644 Tests/CompileFeatures/.gitattributes create mode 100644 Tests/PositionIndependentTargets/.gitattributes create mode 100644 Tests/RunCMake/CommandLine/cmake_depends/.gitattributes create mode 100644 Tests/RunCMake/GenerateExportHeader/reference/.gitattributes hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 23 07:35:38 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 23 Feb 2017 07:35:38 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-255-g3f8e94f Message-ID: <20170223123538.6B407FA6CC@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 3f8e94f71effc552fd13d4d37a5ae367fe896644 (commit) via 1dc13019259bd62d63b9295011227029283c2ef7 (commit) from d23f4414c44b977abc3f9ff49aa06f709a3d9db1 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3f8e94f71effc552fd13d4d37a5ae367fe896644 commit 3f8e94f71effc552fd13d4d37a5ae367fe896644 Merge: d23f441 1dc1301 Author: Brad King AuthorDate: Thu Feb 23 07:35:36 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 23 07:35:36 2017 -0500 Merge topic 'doc-cmake-language-makefile-vars' 1dc13019 Help: Clarify 'make-style' variable references in cmake-language(7) ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-language.7.rst | 6 ++++++ 1 file changed, 6 insertions(+) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 23 07:36:00 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 23 Feb 2017 07:36:00 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-507-g5b4f3ea Message-ID: <20170223123600.E2266FA6C7@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 5b4f3ea3e7776c6a2c0fb2d9e1c052af8f8a1209 (commit) via 3f8e94f71effc552fd13d4d37a5ae367fe896644 (commit) via d23f4414c44b977abc3f9ff49aa06f709a3d9db1 (commit) via e68aad3eb88b910266b7af3f80f9ee8a6370401c (commit) via e2717d69df8eee036cfa5be431e019e117b94efe (commit) from afdef5f94742f17434b08a8c2678735a0db4f1ab (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=5b4f3ea3e7776c6a2c0fb2d9e1c052af8f8a1209 commit 5b4f3ea3e7776c6a2c0fb2d9e1c052af8f8a1209 Merge: afdef5f 3f8e94f Author: Brad King AuthorDate: Thu Feb 23 07:35:52 2017 -0500 Commit: Brad King CommitDate: Thu Feb 23 07:35:52 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 23 07:50:18 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 23 Feb 2017 07:50:18 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-509-gfe5a2d8 Message-ID: <20170223125018.29300F9CE2@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via fe5a2d877f809d13961d3c21a3661275257ce2e3 (commit) via eacf7decbf78a184cdad7a6fd533aa4f433ec27f (commit) from 5b4f3ea3e7776c6a2c0fb2d9e1c052af8f8a1209 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=fe5a2d877f809d13961d3c21a3661275257ce2e3 commit fe5a2d877f809d13961d3c21a3661275257ce2e3 Merge: 5b4f3ea eacf7de Author: Brad King AuthorDate: Thu Feb 23 07:50:17 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 23 07:50:17 2017 -0500 Merge topic 'GetPrerequisites-find_item_basename' into next eacf7dec GetPrerequisites: also try to resolve just the basename https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=eacf7decbf78a184cdad7a6fd533aa4f433ec27f commit eacf7decbf78a184cdad7a6fd533aa4f433ec27f Author: Michael Maltese AuthorDate: Tue Feb 21 22:21:49 2017 -0800 Commit: Michael Maltese CommitDate: Wed Feb 22 12:27:39 2017 -0800 GetPrerequisites: also try to resolve just the basename Fixes #16625. diff --git a/Modules/GetPrerequisites.cmake b/Modules/GetPrerequisites.cmake index 1b23800..417af7c 100644 --- a/Modules/GetPrerequisites.cmake +++ b/Modules/GetPrerequisites.cmake @@ -399,6 +399,11 @@ function(gp_resolve_item context item exepath dirs resolved_item_var) set(ri "ri-NOTFOUND") find_file(ri "${item}" ${exepath} ${dirs} NO_DEFAULT_PATH) find_file(ri "${item}" ${exepath} ${dirs} /usr/lib) + + get_filename_component(basename_item "${item}" NAME) + find_file(ri "${basename_item}" PATHS ${exepath} ${dirs} NO_DEFAULT_PATH) + find_file(ri "${basename_item}" PATHS /usr/lib) + if(ri) #message(STATUS "info: 'find_file' in exepath/dirs (${ri})") set(resolved 1) ----------------------------------------------------------------------- Summary of changes: Modules/GetPrerequisites.cmake | 5 +++++ 1 file changed, 5 insertions(+) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 23 10:02:17 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 23 Feb 2017 10:02:17 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-511-g22db66f Message-ID: <20170223150217.3F7D5FA5B8@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 22db66f0aa60018e26af1bdc3efc84ef77c1b154 (commit) via 9dc7a2ed2cbc36d9b6a9286822020a5da2536df2 (commit) from fe5a2d877f809d13961d3c21a3661275257ce2e3 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=22db66f0aa60018e26af1bdc3efc84ef77c1b154 commit 22db66f0aa60018e26af1bdc3efc84ef77c1b154 Merge: fe5a2d8 9dc7a2e Author: Brad King AuthorDate: Thu Feb 23 10:02:16 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 23 10:02:16 2017 -0500 Merge topic 'find_openmp_clang_patch' into next 9dc7a2ed FindOpenMP: Add iomp5 variant of Clang OpenMP flags https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9dc7a2ed2cbc36d9b6a9286822020a5da2536df2 commit 9dc7a2ed2cbc36d9b6a9286822020a5da2536df2 Author: Lucas Czech AuthorDate: Thu Feb 23 15:27:29 2017 +0100 Commit: Brad King CommitDate: Thu Feb 23 09:59:46 2017 -0500 FindOpenMP: Add iomp5 variant of Clang OpenMP flags Try `-fopenmp=libiomp5` in addition to `-fopenmp=libomp`. Leave the latter as the default that we try first when the compiler id is `Clang`. If that does not work we will still fall back to trying all the candidates and eventually get to the iomp5 variant. diff --git a/Modules/FindOpenMP.cmake b/Modules/FindOpenMP.cmake index 2ee9439..f399836 100644 --- a/Modules/FindOpenMP.cmake +++ b/Modules/FindOpenMP.cmake @@ -48,6 +48,7 @@ function(_OPENMP_FLAG_CANDIDATES LANG) #GNU "-fopenmp" #Clang + "-fopenmp=libiomp5" "-fopenmp=libomp" #Microsoft Visual Studio "/openmp" ----------------------------------------------------------------------- Summary of changes: Modules/FindOpenMP.cmake | 1 + 1 file changed, 1 insertion(+) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 23 10:08:14 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 23 Feb 2017 10:08:14 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-519-gf2d9386 Message-ID: <20170223150814.9D093FA6BA@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via f2d9386c0dcb7ed57297ba1886dab692fc304e4a (commit) via 62a1e292f29d740d0b193e45f0acd37f7ffaced6 (commit) via e98465cfed68f6511af552ac8ab0d168791f4302 (commit) via 96f6f392e3d2ba95c11d0b77fbb5da485e626ed4 (commit) via 94e3f82cf114d12b190d1999a72838018eb171c9 (commit) via 70ebf35cdaaf391138df7564a07cd205de4af971 (commit) via 2a6fd4328adfad4cae0097d6d71e571c122fc0d1 (commit) via e9a8a207ad6817cc93eab2b878de090b5ece8bfe (commit) from 22db66f0aa60018e26af1bdc3efc84ef77c1b154 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f2d9386c0dcb7ed57297ba1886dab692fc304e4a commit f2d9386c0dcb7ed57297ba1886dab692fc304e4a Merge: 22db66f 62a1e29 Author: Brad King AuthorDate: Thu Feb 23 10:08:08 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 23 10:08:08 2017 -0500 Merge topic 'autogen_depends' into next 62a1e292 Autogen: Add hint to SKIP_AUTOMOC in error message e98465cf Autogen: Add Quote function and use it for logging 96f6f392 Autogen: Add AUTOMOC_DEPEND_FILTERS documentation 94e3f82c Autogen: Add AUTOMOC_DEPEND_FILTERS test 70ebf35c Autogen: Add AUTOMOC_DEPEND_FILTERS support 2a6fd432 Autogen: Single point of return in Run() method e9a8a207 Autogen: Log simplifications https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=62a1e292f29d740d0b193e45f0acd37f7ffaced6 commit 62a1e292f29d740d0b193e45f0acd37f7ffaced6 Author: Sebastian Holtermann AuthorDate: Wed Feb 22 20:16:44 2017 +0100 Commit: Sebastian Holtermann CommitDate: Thu Feb 23 14:14:29 2017 +0100 Autogen: Add hint to SKIP_AUTOMOC in error message Closes #15751 diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 8d65129..e7e456a 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -1022,7 +1022,9 @@ bool cmQtAutoGenerators::MocParseSourceContent( ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n" << "The file contains a " << macroName << " macro, but does not include " - << Quoted(scannedFileBasename + ".moc") << "!"; + << Quoted(scannedFileBasename + ".moc") << "!\n" + << "Consider adding the include or enabling SKIP_AUTOMOC for this " + "file."; this->LogError(ost.str()); return false; } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e98465cfed68f6511af552ac8ab0d168791f4302 commit e98465cfed68f6511af552ac8ab0d168791f4302 Author: Sebastian Holtermann AuthorDate: Wed Feb 22 20:08:53 2017 +0100 Commit: Sebastian Holtermann CommitDate: Thu Feb 23 14:14:29 2017 +0100 Autogen: Add Quote function and use it for logging diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index e1b4f35..8d65129 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -36,6 +36,25 @@ static const char* SettingsKeyRcc = "AM_RCC_OLD_SETTINGS"; // -- Static functions +/** + * @brief Returns a the string escaped and enclosed in quotes + */ +static std::string Quoted(const std::string& text) +{ + static const char* rep[18] = { "\\", "\\\\", "\"", "\\\"", "\a", "\\a", + "\b", "\\b", "\f", "\\f", "\n", "\\n", + "\r", "\\r", "\t", "\\t", "\v", "\\v" }; + + std::string res = text; + for (const char* const* it = cmArrayBegin(rep); it != cmArrayEnd(rep); + it += 2) { + cmSystemTools::ReplaceString(res, *it, *(it + 1)); + } + res = '"' + res; + res += '"'; + return res; +} + static std::string GetConfigDefinition(cmMakefile* makefile, const std::string& key, const std::string& config) @@ -273,8 +292,8 @@ bool cmQtAutoGenerators::MocDependFilterPush(const std::string& key, success = true; } else { this->LogError("AutoMoc: Error in AUTOMOC_DEPEND_FILTERS: Compiling " - "regular expression failed.\nKey: \"" + - key + "\"\nReg. exp.: \"" + regExp + "\""); + "regular expression failed.\nKey: " + + Quoted(key) + "\nExp.: " + Quoted(regExp)); } } else { this->LogError("AutoMoc: Error in AUTOMOC_DEPEND_FILTERS: Regular " @@ -320,8 +339,8 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( } // Check Qt version if ((this->QtMajorVersion != "4") && (this->QtMajorVersion != "5")) { - this->LogError("AutoGen: Error: Unsupported Qt version: \"" + - this->QtMajorVersion + "\""); + this->LogError("AutoGen: Error: Unsupported Qt version: " + + Quoted(this->QtMajorVersion)); return false; } @@ -719,13 +738,13 @@ void cmQtAutoGenerators::MocFindDepends( if (!incFile.empty()) { mocDepends[absFilename].insert(incFile); if (this->Verbose) { - this->LogInfo("AutoMoc: Found dependency:\n \"" + absFilename + - "\"\n \"" + incFile + "\""); + this->LogInfo("AutoMoc: Found dependency:\n " + + Quoted(absFilename) + "\n " + Quoted(incFile)); } } else { - this->LogWarning("AutoMoc: Warning: \"" + absFilename + "\"\n" + - "Could not find dependency file \"" + match + - "\""); + this->LogWarning("AutoMoc: Warning: " + Quoted(absFilename) + + "\n" + "Could not find dependency file " + + Quoted(match)); } } contentChars += filter.regExp.end(); @@ -878,9 +897,11 @@ bool cmQtAutoGenerators::MocParseSourceContent( } else { std::ostringstream ost; ost << "AutoMoc: Error: " << absFilename << "\n" - << "The file includes the moc file \"" << incString - << "\", but could not find header \"" << incRealBasename << '{' - << JoinExts(this->HeaderExtensions) << "}\"\n"; + << "The file includes the moc file " << Quoted(incString) + << ", but could not find header " + << Quoted(incRealBasename + "{" + + JoinExts(this->HeaderExtensions) + "}"); + ; this->LogError(ost.str()); return false; } @@ -902,32 +923,33 @@ bool cmQtAutoGenerators::MocParseSourceContent( fileToMoc = headerToMoc; if (!requiresMoc && (incBasename == scannedFileBasename)) { std::ostringstream ost; - ost << "AutoMoc: Warning: " << absFilename << "\n" - << "The file includes the moc file \"" << incString << "\"" + ost << "AutoMoc: Warning: " << Quoted(absFilename) << "\n" + << "The file includes the moc file " << Quoted(incString) << ", but does not contain a Q_OBJECT or Q_GADGET macro.\n" - << "Running moc on \"" << headerToMoc << "\"!\n" - << "Include \"moc_" << incBasename - << ".cpp\" for a compatibility with " - "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; + << "Running moc on " << Quoted(headerToMoc) << "!\n" + << "Include " << Quoted("moc_" + incBasename + ".cpp") + << " for a compatibility with strict mode (see " + "CMAKE_AUTOMOC_RELAXED_MODE).\n"; this->LogWarning(ost.str()); } else { std::ostringstream ost; - ost << "AutoMoc: Warning: " << absFilename << "\n" - << "The file includes the moc file \"" << incString - << "\" instead of \"moc_" << incBasename << ".cpp\".\n" - << "Running moc on \"" << headerToMoc << "\"!\n" - << "Include \"moc_" << incBasename - << ".cpp\" for compatibility with " - "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; + ost << "AutoMoc: Warning: " << Quoted(absFilename) << "\n" + << "The file includes the moc file " << Quoted(incString) + << " instead of " << Quoted("moc_" + incBasename + ".cpp") + << ".\n" + << "Running moc on " << Quoted(headerToMoc) << "!\n" + << "Include " << Quoted("moc_" + incBasename + ".cpp") + << " for compatibility with strict mode (see " + "CMAKE_AUTOMOC_RELAXED_MODE).\n"; this->LogWarning(ost.str()); } } else { std::ostringstream ost; - ost << "AutoMoc: Error: " << absFilename << "\n" - << "The file includes the moc file \"" << incString - << "\", which seems to be the moc file from a different " + ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n" + << "The file includes the moc file " << Quoted(incString) + << ". which seems to be the moc file from a different " "source file. CMake also could not find a matching " - "header.\n"; + "header."; this->LogError(ost.str()); return false; } @@ -941,21 +963,21 @@ bool cmQtAutoGenerators::MocParseSourceContent( // Accept but issue a warning if moc isn't required if (!requiresMoc) { std::ostringstream ost; - ost << "AutoMoc: Error: " << absFilename << "\n" - << "The file includes the moc file \"" << incString << "\"" + ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n" + << "The file includes the moc file " << Quoted(incString) << ", but does not contain a Q_OBJECT or Q_GADGET " - "macro.\n"; + "macro."; this->LogWarning(ost.str()); } } else { // Don't allow FOO.moc include other than self in strict mode std::ostringstream ost; - ost << "AutoMoc: Error: " << absFilename << "\n" - << "The file includes the moc file \"" << incString - << "\", which seems to be the moc file from a different " - "source file. This is not supported. Include \"" - << scannedFileBasename - << ".moc\" to run moc on this source file.\n"; + ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n" + << "The file includes the moc file " << Quoted(incString) + << ", which seems to be the moc file from a different " + "source file. This is not supported. Include " + << Quoted(scannedFileBasename + ".moc") + << " to run moc on this source file."; this->LogError(ost.str()); return false; } @@ -978,15 +1000,15 @@ bool cmQtAutoGenerators::MocParseSourceContent( if (relaxed && !ownMocUnderscoreInclude.empty()) { // This is for KDE4 compatibility: std::ostringstream ost; - ost << "AutoMoc: Warning: " << absFilename << "\n" + ost << "AutoMoc: Warning: " << Quoted(absFilename) << "\n" << "The file contains a " << macroName << " macro, but does not include " - << "\"" << scannedFileBasename << ".moc\", but instead includes " - << "\"" << ownMocUnderscoreInclude << "\".\n" - << "Running moc on \"" << absFilename << "\"!\n" - << "Better include \"" << scannedFileBasename - << ".moc\" for compatibility with " - "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"; + << Quoted(scannedFileBasename + ".moc") << ", but instead includes " + << Quoted(ownMocUnderscoreInclude) << ".\n" + << "Running moc on " << Quoted(absFilename) << "!\n" + << "Better include " << Quoted(scannedFileBasename + ".moc") + << " for compatibility with strict mode (see " + "CMAKE_AUTOMOC_RELAXED_MODE)."; this->LogWarning(ost.str()); // Use scanned source file instead of scanned header file as moc source @@ -997,10 +1019,10 @@ bool cmQtAutoGenerators::MocParseSourceContent( } else { // Otherwise always error out since it will not compile: std::ostringstream ost; - ost << "AutoMoc: Error: " << absFilename << "\n" + ost << "AutoMoc: Error: " << Quoted(absFilename) << "\n" << "The file contains a " << macroName << " macro, but does not include " - << "\"" << scannedFileBasename << ".moc\"!\n"; + << Quoted(scannedFileBasename + ".moc") << "!"; this->LogError(ost.str()); return false; } @@ -1280,7 +1302,7 @@ bool cmQtAutoGenerators::MocGenerateFile( { std::ostringstream ost; ost << "AutoMoc: Error: moc process failed for\n"; - ost << "\"" << mocFileRel << "\"\n"; + ost << Quoted(mocFileRel) << "\n"; ost << "AutoMoc: Command:\n" << cmJoin(cmd, " ") << "\n"; ost << "AutoMoc: Command output:\n" << output << "\n"; this->LogError(ost.str()); @@ -1419,8 +1441,8 @@ bool cmQtAutoGenerators::UicGenerateFile(const std::string& realName, { std::ostringstream ost; ost << "AutoUic: Error: uic process failed for\n"; - ost << "\"" << uicFileRel << "\" needed by\n"; - ost << "\"" << realName << "\"\n"; + ost << Quoted(uicFileRel) << " needed by\n"; + ost << Quoted(realName) << "\n"; ost << "AutoUic: Command:\n" << cmJoin(cmd, " ") << "\n"; ost << "AutoUic: Command output:\n" << output << "\n"; this->LogError(ost.str()); @@ -1558,7 +1580,7 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile, { std::ostringstream ost; ost << "AutoRcc: Error: rcc process failed for\n"; - ost << "\"" << rccOutputFile << "\"\n"; + ost << Quoted(rccOutputFile) << "\n"; ost << "AutoRcc: Command:\n" << cmJoin(cmd, " ") << "\n"; ost << "AutoRcc: Command output:\n" << output << "\n"; this->LogError(ost.str()); https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=96f6f392e3d2ba95c11d0b77fbb5da485e626ed4 commit 96f6f392e3d2ba95c11d0b77fbb5da485e626ed4 Author: Sebastian Holtermann AuthorDate: Thu Feb 23 13:50:29 2017 +0100 Commit: Sebastian Holtermann CommitDate: Thu Feb 23 14:14:29 2017 +0100 Autogen: Add AUTOMOC_DEPEND_FILTERS documentation diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 5fad10c..a3b6e6b 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -115,6 +115,7 @@ Properties on Targets /prop_tgt/ARCHIVE_OUTPUT_NAME_CONFIG /prop_tgt/ARCHIVE_OUTPUT_NAME /prop_tgt/AUTOGEN_TARGET_DEPENDS + /prop_tgt/AUTOMOC_DEPEND_FILTERS /prop_tgt/AUTOMOC_MOC_OPTIONS /prop_tgt/AUTOMOC /prop_tgt/AUTOUIC diff --git a/Help/manual/cmake-qt.7.rst b/Help/manual/cmake-qt.7.rst index e9da396..3b9931e 100644 --- a/Help/manual/cmake-qt.7.rst +++ b/Help/manual/cmake-qt.7.rst @@ -87,6 +87,9 @@ following targets by setting the :variable:`CMAKE_AUTOMOC` variable. The options to pass to ``moc``. The :variable:`CMAKE_AUTOMOC_MOC_OPTIONS` variable may be populated to pre-set the options for all following targets. +Additional ``moc`` dependency file names can be extracted from source code +by using :prop_tgt:`AUTOMOC_DEPEND_FILTERS`. + Source C++ files can be excluded from :prop_tgt:`AUTOMOC` processing by enabling :prop_sf:`SKIP_AUTOMOC` or the broader :prop_sf:`SKIP_AUTOGEN`. diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 6112e65..259d87b 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -256,6 +256,7 @@ Variables that Control the Build /variable/CMAKE_ANDROID_STL_TYPE /variable/CMAKE_ARCHIVE_OUTPUT_DIRECTORY /variable/CMAKE_ARCHIVE_OUTPUT_DIRECTORY_CONFIG + /variable/CMAKE_AUTOMOC_DEPEND_FILTERS /variable/CMAKE_AUTOMOC_MOC_OPTIONS /variable/CMAKE_AUTOMOC /variable/CMAKE_AUTORCC diff --git a/Help/prop_tgt/AUTOMOC.rst b/Help/prop_tgt/AUTOMOC.rst index 4ac9b6e..b729c0b 100644 --- a/Help/prop_tgt/AUTOMOC.rst +++ b/Help/prop_tgt/AUTOMOC.rst @@ -57,6 +57,9 @@ See the documentation for this variable for more details. The global property :prop_gbl:`AUTOGEN_TARGETS_FOLDER` can be used to group the automoc targets together in an IDE, e.g. in MSVS. +Additional ``moc`` dependency file names can be extracted from source code +by using :prop_tgt:`AUTOMOC_DEPEND_FILTERS`. + Source C++ files can be excluded from :prop_tgt:`AUTOMOC` processing by enabling :prop_sf:`SKIP_AUTOMOC` or the broader :prop_sf:`SKIP_AUTOGEN`. diff --git a/Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst b/Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst new file mode 100644 index 0000000..810cbf4 --- /dev/null +++ b/Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst @@ -0,0 +1,45 @@ +AUTOMOC_DEPEND_FILTERS +---------------------- + +Filter definitions used by :prop_tgt:`AUTOMOC` to extract file names from +source code as additional dependencies for the ``moc`` file. + +This property is only used if the :prop_tgt:`AUTOMOC` property is ``ON`` +for this target. + +Filters are defined as ``KEYWORD;REGULAR_EXPRESSION`` pairs. First the file +content is searched for ``KEYWORD``. If it is found at least once, then file +names are extracted by successively searching for ``REGULAR_EXPRESSION`` and +taking the first match group. + +Consider a filter extracts the file name ``DEP`` from the content of a file +``FOO``. If ``DEP`` changes, then the ``moc`` file for ``FOO`` gets rebuilt. +The file ``DEP`` is searched for first in the vicinity +of ``FOO`` and afterwards in the target's :prop_tgt:`INCLUDE_DIRECTORIES`. + +By default :prop_tgt:`AUTOMOC_DEPEND_FILTERS` is initialized from +:variable:`CMAKE_AUTOMOC_DEPEND_FILTERS`, which is empty by default. + +See the :manual:`cmake-qt(7)` manual for more information on using CMake +with Qt. + + +Example +------- + +Consider a file ``FOO.hpp`` holds a custom macro ``OBJ_JSON_FILE`` and we +want the ``moc`` file to depend on the macro`s file name argument:: + + class My_Class : public QObject + { + Q_OBJECT + OBJ_JSON_FILE ( "DEP.json" ) + ... + }; + +Then we might use :variable:`CMAKE_AUTOMOC_DEPEND_FILTERS` to +define a filter like this:: + + set(CMAKE_AUTOMOC_DEPEND_FILTERS + "OBJ_JSON_FILE" "[\n][ \t]*OBJ_JSON_FILE[ \t]*\\([ \t]*\"([^\"]+)\"" + ) diff --git a/Help/release/dev/Autogen_depends.rst b/Help/release/dev/Autogen_depends.rst new file mode 100644 index 0000000..c774386 --- /dev/null +++ b/Help/release/dev/Autogen_depends.rst @@ -0,0 +1,10 @@ +AutoGen depends +--------------- + +* Variable :variable:`CMAKE_AUTOMOC_DEPEND_FILTERS` was introduced to + allow :variable:`CMAKE_AUTOMOC` to extract additional dependency file names + for ``moc`` from the contents of source files. + +* The new target property :prop_tgt:`AUTOMOC_DEPEND_FILTERS` was introduced to + allow :prop_tgt:`AUTOMOC` to extract additional dependency file names + for ``moc`` from the contents of source files. diff --git a/Help/variable/CMAKE_AUTOMOC_DEPEND_FILTERS.rst b/Help/variable/CMAKE_AUTOMOC_DEPEND_FILTERS.rst new file mode 100644 index 0000000..5c3662d --- /dev/null +++ b/Help/variable/CMAKE_AUTOMOC_DEPEND_FILTERS.rst @@ -0,0 +1,12 @@ +CMAKE_AUTOMOC_DEPEND_FILTERS +---------------------------- + +Filter definitions used by :variable:`CMAKE_AUTOMOC` +to extract file names from source code as additional dependencies +for the ``moc`` file. + +This variable is used to initialize the :prop_tgt:`AUTOMOC_DEPEND_FILTERS` +property on all the targets. See that target property for additional +information. + +By default it is empty. https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=94e3f82cf114d12b190d1999a72838018eb171c9 commit 94e3f82cf114d12b190d1999a72838018eb171c9 Author: Sebastian Holtermann AuthorDate: Wed Feb 22 21:08:36 2017 +0100 Commit: Sebastian Holtermann CommitDate: Wed Feb 22 21:15:03 2017 +0100 Autogen: Add AUTOMOC_DEPEND_FILTERS test diff --git a/Tests/QtAutogen/CMakeLists.txt b/Tests/QtAutogen/CMakeLists.txt index 260331b..257c187 100644 --- a/Tests/QtAutogen/CMakeLists.txt +++ b/Tests/QtAutogen/CMakeLists.txt @@ -247,10 +247,7 @@ if (NOT QT_TEST_VERSION STREQUAL 4) execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${mocPluginBinDir}/jsonFiles/StyleC.json") execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${mocPluginBinDir}/jsonFiles/sub/StyleD.json") - - execute_process(COMMAND "${CMAKE_COMMAND}" --build . - WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mocPlugin" - ) + execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${mocPluginBinDir}") file(TIMESTAMP "${style_a_file}" style_a_after "${timeformat}") file(TIMESTAMP "${style_b_file}" style_b_after "${timeformat}") @@ -269,6 +266,23 @@ if (NOT QT_TEST_VERSION STREQUAL 4) if (NOT style_d_after GREATER style_d_before) message(SEND_ERROR "file (${style_d_file}) should have changed!") endif() + + # Test custom macro + file(TIMESTAMP "${style_c_file}" style_c_before "${timeformat}") + file(TIMESTAMP "${style_d_file}" style_d_before "${timeformat}") + execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) + execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${mocPluginBinDir}/jsonFiles/StyleC_Custom.json") + execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${mocPluginBinDir}/jsonFiles/sub/StyleD_Custom.json") + execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${mocPluginBinDir}") + file(TIMESTAMP "${style_c_file}" style_c_after "${timeformat}") + file(TIMESTAMP "${style_d_file}" style_d_after "${timeformat}") + if (NOT style_c_after GREATER style_c_before) + message(SEND_ERROR "file (${style_c_file}) should have changed!") + endif() + if (NOT style_d_after GREATER style_d_before) + message(SEND_ERROR "file (${style_d_file}) should have changed!") + endif() + endif() # -- Test diff --git a/Tests/QtAutogen/mocPlugin/CMakeLists.txt b/Tests/QtAutogen/mocPlugin/CMakeLists.txt index eed7d39..b72b05d 100644 --- a/Tests/QtAutogen/mocPlugin/CMakeLists.txt +++ b/Tests/QtAutogen/mocPlugin/CMakeLists.txt @@ -1,5 +1,10 @@ cmake_minimum_required(VERSION 3.8) +set(CMAKE_AUTOMOC_DEPEND_FILTERS + "A_CUSTOM_MACRO" + "[\n][ \t]*A_CUSTOM_MACRO[ \t\r\n]*\\([^,]+,[ \t\r\n]*\"([^\"]+)\"" + ) + if (NOT QT_TEST_VERSION STREQUAL 5) message(SEND_ERROR "Invalid Qt version specified.") endif() @@ -9,8 +14,10 @@ if(Qt5_POSITION_INDEPENDENT_CODE AND CMAKE_CXX_COMPILE_OPTIONS_PIC) add_definitions(${CMAKE_CXX_COMPILE_OPTIONS_PIC}) endif() -configure_file(jsonIn/StyleC.json jsonFiles/StyleC.json @ONLY) -configure_file(jsonIn/StyleD.json jsonFiles/sub/StyleD.json @ONLY) +configure_file(jsonIn/StyleC.json jsonFiles/StyleC.json) +configure_file(jsonIn/StyleD.json jsonFiles/sub/StyleD.json) +configure_file(jsonIn/StyleC.json jsonFiles/StyleC_Custom.json) +configure_file(jsonIn/StyleD.json jsonFiles/sub/StyleD_Custom.json) # Enable automoc set(CMAKE_AUTOMOC TRUE) diff --git a/Tests/QtAutogen/mocPlugin/StyleA.hpp b/Tests/QtAutogen/mocPlugin/StyleA.hpp index b105b02..1b6154d 100644 --- a/Tests/QtAutogen/mocPlugin/StyleA.hpp +++ b/Tests/QtAutogen/mocPlugin/StyleA.hpp @@ -1,6 +1,7 @@ #ifndef STYLEA_HPP #define STYLEA_HPP +#include "StyleCommon.hpp" #include class StyleA : public QStylePlugin @@ -8,6 +9,7 @@ class StyleA : public QStylePlugin Q_OBJECT // Json file in local directory Q_PLUGIN_METADATA(IID "org.styles.A" FILE "StyleA.json") + A_CUSTOM_MACRO(SomeArg, "StyleA_Custom.json", AnotherArg) public: QStyle* create(const QString& key); }; diff --git a/Tests/QtAutogen/mocPlugin/StyleA_Custom.json b/Tests/QtAutogen/mocPlugin/StyleA_Custom.json new file mode 100644 index 0000000..cc33953 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleA_Custom.json @@ -0,0 +1 @@ +{ "Keys": [ "Rocket", "Starbuster" ] } diff --git a/Tests/QtAutogen/mocPlugin/StyleB.hpp b/Tests/QtAutogen/mocPlugin/StyleB.hpp index ba89127..163c9b2 100644 --- a/Tests/QtAutogen/mocPlugin/StyleB.hpp +++ b/Tests/QtAutogen/mocPlugin/StyleB.hpp @@ -1,6 +1,7 @@ #ifndef STYLEB_HPP #define STYLEB_HPP +#include "StyleCommon.hpp" #include class StyleB : public QStylePlugin @@ -8,6 +9,7 @@ class StyleB : public QStylePlugin Q_OBJECT // Json file in local subdirectory Q_PLUGIN_METADATA(IID "org.styles.B" FILE "jsonIn/StyleB.json") + A_CUSTOM_MACRO(SomeArg, "jsonIn/StyleB_Custom.json", AnotherArg) public: QStyle* create(const QString& key); }; diff --git a/Tests/QtAutogen/mocPlugin/StyleC.hpp b/Tests/QtAutogen/mocPlugin/StyleC.hpp index 9f71d75..52a887a 100644 --- a/Tests/QtAutogen/mocPlugin/StyleC.hpp +++ b/Tests/QtAutogen/mocPlugin/StyleC.hpp @@ -1,6 +1,7 @@ #ifndef STYLEC_HPP #define STYLEC_HPP +#include "StyleCommon.hpp" #include class StyleC : public QStylePlugin @@ -8,6 +9,7 @@ class StyleC : public QStylePlugin Q_OBJECT // Json file in global root directory Q_PLUGIN_METADATA(IID "org.styles.C" FILE "StyleC.json") + A_CUSTOM_MACRO(SomeArg, "StyleC_Custom.json", AnotherArg) public: QStyle* create(const QString& key); }; diff --git a/Tests/QtAutogen/mocPlugin/StyleCommon.hpp b/Tests/QtAutogen/mocPlugin/StyleCommon.hpp new file mode 100644 index 0000000..f1a7ec6 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/StyleCommon.hpp @@ -0,0 +1,7 @@ +#ifndef STYLECOMMON_HPP +#define STYLECOMMON_HPP + +// Empty test macro definition +#define A_CUSTOM_MACRO(name, jsonFile, pluginRegistrations) + +#endif diff --git a/Tests/QtAutogen/mocPlugin/StyleD.hpp b/Tests/QtAutogen/mocPlugin/StyleD.hpp index e58444d..df8a439 100644 --- a/Tests/QtAutogen/mocPlugin/StyleD.hpp +++ b/Tests/QtAutogen/mocPlugin/StyleD.hpp @@ -1,6 +1,7 @@ #ifndef STYLED_HPP #define STYLED_HPP +#include "StyleCommon.hpp" #include class StyleD : public QStylePlugin @@ -8,6 +9,7 @@ class StyleD : public QStylePlugin Q_OBJECT // Json file in global sub director Q_PLUGIN_METADATA(IID "org.styles.D" FILE "sub/StyleD.json") + A_CUSTOM_MACRO(SomeArg, "sub/StyleD_Custom.json", AnotherArg) public: QStyle* create(const QString& key); }; diff --git a/Tests/QtAutogen/mocPlugin/StyleE.hpp b/Tests/QtAutogen/mocPlugin/StyleE.hpp index 80e0b79..e7915a8 100644 --- a/Tests/QtAutogen/mocPlugin/StyleE.hpp +++ b/Tests/QtAutogen/mocPlugin/StyleE.hpp @@ -1,6 +1,7 @@ #ifndef STYLEE_HPP #define STYLEE_HPP +#include "StyleCommon.hpp" #include class StyleE : public QStylePlugin @@ -8,6 +9,7 @@ class StyleE : public QStylePlugin Q_OBJECT // No Json file Q_PLUGIN_METADATA(IID "org.styles.E") + A_CUSTOM_MACRO(SomeArg, InvalidFileArg, AnotherArg) public: QStyle* create(const QString& key); }; diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleB_Custom.json b/Tests/QtAutogen/mocPlugin/jsonIn/StyleB_Custom.json new file mode 100644 index 0000000..129cac4 --- /dev/null +++ b/Tests/QtAutogen/mocPlugin/jsonIn/StyleB_Custom.json @@ -0,0 +1 @@ +{ "Keys": [ "Rocket", "StarbusterB" ] } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=70ebf35cdaaf391138df7564a07cd205de4af971 commit 70ebf35cdaaf391138df7564a07cd205de4af971 Author: Sebastian Holtermann AuthorDate: Wed Feb 22 17:40:36 2017 +0100 Commit: Sebastian Holtermann CommitDate: Wed Feb 22 21:13:48 2017 +0100 Autogen: Add AUTOMOC_DEPEND_FILTERS support diff --git a/Modules/AutogenInfo.cmake.in b/Modules/AutogenInfo.cmake.in index b647ecf..fc5024f 100644 --- a/Modules/AutogenInfo.cmake.in +++ b/Modules/AutogenInfo.cmake.in @@ -20,6 +20,7 @@ set(AM_MOC_COMPILE_DEFINITIONS @_moc_compile_defs@) set(AM_MOC_INCLUDES @_moc_incs@) set(AM_MOC_OPTIONS @_moc_options@) set(AM_MOC_RELAXED_MODE @_moc_relaxed_mode@) +set(AM_MOC_DEPEND_FILTERS @_moc_depend_filters@) # UIC settings set(AM_UIC_SKIP @_uic_skip@) set(AM_UIC_TARGET_OPTIONS @_uic_target_options@) diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index 52112ff..de18265 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -218,6 +218,8 @@ static void MocSetupAutoTarget( AddDefinitionEscaped(makefile, "_moc_relaxed_mode", makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE") ? "TRUE" : "FALSE"); + AddDefinitionEscaped(makefile, "_moc_depend_filters", + GetSafeProperty(target, "AUTOMOC_DEPEND_FILTERS")); // Moc includes and compile definitions { diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 4463d62..e1b4f35 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -260,6 +260,32 @@ bool cmQtAutoGenerators::Run(const std::string& targetDirectory, return success; } +bool cmQtAutoGenerators::MocDependFilterPush(const std::string& key, + const std::string& regExp) +{ + bool success = false; + if (!key.empty()) { + if (!regExp.empty()) { + MocDependFilter filter; + filter.key = key; + if (filter.regExp.compile(regExp)) { + this->MocDependFilters.push_back(filter); + success = true; + } else { + this->LogError("AutoMoc: Error in AUTOMOC_DEPEND_FILTERS: Compiling " + "regular expression failed.\nKey: \"" + + key + "\"\nReg. exp.: \"" + regExp + "\""); + } + } else { + this->LogError("AutoMoc: Error in AUTOMOC_DEPEND_FILTERS: Regular " + "expression is empty"); + } + } else { + this->LogError("AutoMoc: Error in AUTOMOC_DEPEND_FILTERS: Key is empty"); + } + return success; +} + bool cmQtAutoGenerators::ReadAutogenInfoFile( cmMakefile* makefile, const std::string& targetDirectory, const std::string& config) @@ -320,6 +346,30 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( this->MocIncludePaths); cmSystemTools::ExpandListArgument( makefile->GetSafeDefinition("AM_MOC_OPTIONS"), this->MocOptions); + { + std::vector mocDependFilters; + cmSystemTools::ExpandListArgument( + makefile->GetSafeDefinition("AM_MOC_DEPEND_FILTERS"), mocDependFilters); + // Insert Q_PLUGIN_METADATA dependency filter + if (this->QtMajorVersion != "4") { + this->MocDependFilterPush("Q_PLUGIN_METADATA", + "[\n][ \t]*Q_PLUGIN_METADATA[ \t]*\\(" + "[^\\)]*FILE[ \t]*\"([^\"]+)\""); + } + // Insert user defined dependency filters + if ((mocDependFilters.size() % 2) == 0) { + for (std::vector::const_iterator dit = + mocDependFilters.begin(); + dit != mocDependFilters.end(); dit += 2) { + if (!this->MocDependFilterPush(*dit, *(dit + 1))) { + return false; + } + } + } else { + this->LogError("AutoMoc: Error: AUTOMOC_DEPEND_FILTERS list size is not " + "a multiple of 2"); + } + } // - Uic cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_UIC_SKIP"), @@ -559,16 +609,6 @@ void cmQtAutoGenerators::Init(cmMakefile* makefile) this->MocIncludes.push_back(*it); } } - - // Insert MocDependFilter for Q_PLUGIN_METADATA - if (QtMajorVersion != "4") { - MocDependFilter filter; - filter.key = "Q_PLUGIN_METADATA"; - filter.regExp.compile("[\n][ \t]*" - "Q_PLUGIN_METADATA[ \t]*\\(" - "[^\\)]*FILE[ \t]*\"([^\"]+)\""); - this->MocDependFilters.push_back(filter); - } } bool cmQtAutoGenerators::RunAutogen() diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index c20b83c..e4b7f60 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -33,6 +33,7 @@ private: typedef std::pair MacroFilter; // - Configuration + bool MocDependFilterPush(const std::string& key, const std::string& regExp); bool ReadAutogenInfoFile(cmMakefile* makefile, const std::string& targetDirectory, const std::string& config); diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index ad3d604..0f3d91b 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -245,6 +245,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, this->SetPropertyDefault("AUTOMOC", CM_NULLPTR); this->SetPropertyDefault("AUTOUIC", CM_NULLPTR); this->SetPropertyDefault("AUTORCC", CM_NULLPTR); + this->SetPropertyDefault("AUTOMOC_DEPEND_FILTERS", CM_NULLPTR); this->SetPropertyDefault("AUTOMOC_MOC_OPTIONS", CM_NULLPTR); this->SetPropertyDefault("AUTOUIC_OPTIONS", CM_NULLPTR); this->SetPropertyDefault("AUTORCC_OPTIONS", CM_NULLPTR); https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=2a6fd4328adfad4cae0097d6d71e571c122fc0d1 commit 2a6fd4328adfad4cae0097d6d71e571c122fc0d1 Author: Sebastian Holtermann AuthorDate: Wed Feb 22 17:52:16 2017 +0100 Commit: Sebastian Holtermann CommitDate: Wed Feb 22 17:52:16 2017 +0100 Autogen: Single point of return in Run() method diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 373a192..4463d62 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -244,23 +244,20 @@ bool cmQtAutoGenerators::Run(const std::string& targetDirectory, CM_AUTO_PTR mf(new cmMakefile(&gg, snapshot)); gg.SetCurrentMakefile(mf.get()); - if (!this->ReadAutogenInfoFile(mf.get(), targetDirectory, config)) { - return false; - } - // Read old settings - this->SettingsFileRead(mf.get(), targetDirectory); - // Init and run - this->Init(mf.get()); - if (this->QtMajorVersion == "4" || this->QtMajorVersion == "5") { - if (!this->RunAutogen()) { - return false; + bool success = false; + if (this->ReadAutogenInfoFile(mf.get(), targetDirectory, config)) { + // Read old settings + this->SettingsFileRead(mf.get(), targetDirectory); + // Init and run + this->Init(mf.get()); + if (this->RunAutogen()) { + // Write current settings + if (this->SettingsFileWrite(targetDirectory)) { + success = true; + } } } - // Write latest settings - if (!this->SettingsFileWrite(targetDirectory)) { - return false; - } - return true; + return success; } bool cmQtAutoGenerators::ReadAutogenInfoFile( @@ -295,6 +292,13 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( this->QtMajorVersion = makefile->GetSafeDefinition("AM_Qt5Core_VERSION_MAJOR"); } + // Check Qt version + if ((this->QtMajorVersion != "4") && (this->QtMajorVersion != "5")) { + this->LogError("AutoGen: Error: Unsupported Qt version: \"" + + this->QtMajorVersion + "\""); + return false; + } + this->MocExecutable = makefile->GetSafeDefinition("AM_QT_MOC_EXECUTABLE"); this->UicExecutable = makefile->GetSafeDefinition("AM_QT_UIC_EXECUTABLE"); this->RccExecutable = makefile->GetSafeDefinition("AM_QT_RCC_EXECUTABLE"); https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e9a8a207ad6817cc93eab2b878de090b5ece8bfe commit e9a8a207ad6817cc93eab2b878de090b5ece8bfe Author: Sebastian Holtermann AuthorDate: Wed Feb 22 17:44:35 2017 +0100 Commit: Sebastian Holtermann CommitDate: Wed Feb 22 17:44:35 2017 +0100 Autogen: Log simplifications diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index d51efb4..373a192 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -272,9 +272,7 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( filename += "/AutogenInfo.cmake"; if (!makefile->ReadListFile(filename.c_str())) { - std::ostringstream err; - err << "AutoGen: error processing file: " << filename << std::endl; - this->LogError(err.str()); + this->LogError("AutoGen: Error processing file: " + filename); return false; } @@ -333,10 +331,9 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( cmSystemTools::ExpandListArgument( makefile->GetSafeDefinition("AM_UIC_OPTIONS_OPTIONS"), uicOptionsVec); if (uicFilesVec.size() != uicOptionsVec.size()) { - std::ostringstream err; - err << "AutoGen: Error: Uic files/options lists size missmatch in: " - << filename << std::endl; - this->LogError(err.str()); + this->LogError( + "AutoGen: Error: Uic files/options lists size missmatch in: " + + filename); return false; } for (std::vector::iterator fileIt = uicFilesVec.begin(), @@ -358,10 +355,9 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( cmSystemTools::ExpandListArgument( makefile->GetSafeDefinition("AM_RCC_OPTIONS_OPTIONS"), rccOptionsVec); if (rccFilesVec.size() != rccOptionsVec.size()) { - std::ostringstream err; - err << "AutoGen: Error: RCC files/options lists size missmatch in: " - << filename << std::endl; - this->LogError(err.str()); + this->LogError( + "AutoGen: Error: RCC files/options lists size missmatch in: " + + filename); return false; } for (std::vector::iterator fileIt = rccFilesVec.begin(), @@ -381,10 +377,9 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( rccInputLists.resize(this->RccSources.size()); } if (this->RccSources.size() != rccInputLists.size()) { - std::ostringstream err; - err << "AutoGen: Error: RCC sources/inputs lists size missmatch in: " - << filename << std::endl; - this->LogError(err.str()); + this->LogError( + "AutoGen: Error: RCC sources/inputs lists size missmatch in: " + + filename); return false; } for (std::vector::iterator fileIt = this->RccSources.begin(), @@ -480,12 +475,8 @@ bool cmQtAutoGenerators::SettingsFileWrite(const std::string& targetDirectory) success = false; // Remove old settings file to trigger full rebuild on next run cmSystemTools::RemoveFile(filename); - { - std::ostringstream err; - err << "AutoGen: Error: Writing old settings file failed: " - << filename; - this->LogError(err.str()); - } + this->LogError("AutoGen: Error: Writing old settings file failed: " + + filename); } } return success; @@ -1150,13 +1141,13 @@ bool cmQtAutoGenerators::MocGenerateAll( outfile.open(this->MocCppFilenameAbs.c_str(), std::ios::trunc); if (!outfile) { success = false; - this->LogError("AutoMoc: error opening " + this->MocCppFilenameAbs); + this->LogError("AutoMoc: Error opening " + this->MocCppFilenameAbs); } else { outfile << automocSource; // Check for write errors if (!outfile.good()) { success = false; - this->LogError("AutoMoc: error writing " + this->MocCppFilenameAbs); + this->LogError("AutoMoc: Error writing " + this->MocCppFilenameAbs); } } } @@ -1768,7 +1759,7 @@ bool cmQtAutoGenerators::MakeParentDirectory(const std::string& filename) const if (!dirName.empty()) { success = cmsys::SystemTools::MakeDirectory(dirName); if (!success) { - this->LogError("AutoGen: Directory creation failed: " + dirName); + this->LogError("AutoGen: Error: Directory creation failed: " + dirName); } } return success; ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-properties.7.rst | 1 + Help/manual/cmake-qt.7.rst | 3 + Help/manual/cmake-variables.7.rst | 1 + Help/prop_tgt/AUTOMOC.rst | 3 + Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst | 45 ++++ Help/release/dev/Autogen_depends.rst | 10 + Help/variable/CMAKE_AUTOMOC_DEPEND_FILTERS.rst | 12 + Modules/AutogenInfo.cmake.in | 1 + Source/cmQtAutoGeneratorInitializer.cxx | 2 + Source/cmQtAutoGenerators.cxx | 249 ++++++++++++-------- Source/cmQtAutoGenerators.h | 1 + Source/cmTarget.cxx | 1 + Tests/QtAutogen/CMakeLists.txt | 22 +- Tests/QtAutogen/mocPlugin/CMakeLists.txt | 11 +- Tests/QtAutogen/mocPlugin/StyleA.hpp | 2 + .../mocPlugin/{StyleA.json => StyleA_Custom.json} | 0 Tests/QtAutogen/mocPlugin/StyleB.hpp | 2 + Tests/QtAutogen/mocPlugin/StyleC.hpp | 2 + Tests/QtAutogen/mocPlugin/StyleCommon.hpp | 7 + Tests/QtAutogen/mocPlugin/StyleD.hpp | 2 + Tests/QtAutogen/mocPlugin/StyleE.hpp | 2 + .../jsonIn/{StyleB.json => StyleB_Custom.json} | 0 22 files changed, 278 insertions(+), 101 deletions(-) create mode 100644 Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst create mode 100644 Help/release/dev/Autogen_depends.rst create mode 100644 Help/variable/CMAKE_AUTOMOC_DEPEND_FILTERS.rst copy Tests/QtAutogen/mocPlugin/{StyleA.json => StyleA_Custom.json} (100%) create mode 100644 Tests/QtAutogen/mocPlugin/StyleCommon.hpp copy Tests/QtAutogen/mocPlugin/jsonIn/{StyleB.json => StyleB_Custom.json} (100%) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 23 14:18:14 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 23 Feb 2017 14:18:14 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-521-gcf660ad Message-ID: <20170223191815.2D4C7F3E4B@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via cf660ade3f88a6364dc86a9616da9b9198216e25 (commit) via 356068cd2e3c395fa824568613c1de315fa8b05b (commit) from f2d9386c0dcb7ed57297ba1886dab692fc304e4a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=cf660ade3f88a6364dc86a9616da9b9198216e25 commit cf660ade3f88a6364dc86a9616da9b9198216e25 Merge: f2d9386 356068c Author: Brad King AuthorDate: Thu Feb 23 14:18:13 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 23 14:18:13 2017 -0500 Merge topic 'dragndrop-format' into next 356068cd cmCPackDragNDropGenerator: Improving handling of temporary dmg images https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=356068cd2e3c395fa824568613c1de315fa8b05b commit 356068cd2e3c395fa824568613c1de315fa8b05b Author: Clinton Stimpson AuthorDate: Thu Feb 23 09:53:09 2017 -0700 Commit: Brad King CommitDate: Thu Feb 23 14:12:52 2017 -0500 cmCPackDragNDropGenerator: Improving handling of temporary dmg images Adjust the image format to create the initial `dmg`, and convert only when necessary. This eliminates spurious hdiutil create -format UDRW failures I'm seeing which may be related to an anti-virus scanner. Running hdiutil create -format UDRW -verbose indicates a "resource is busy" issue when unmounting an image. diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx index fd67df9..ec5fc88 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.cxx +++ b/Source/CPack/cmCPackDragNDropGenerator.cxx @@ -390,6 +390,8 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, bool remount_image = !cpack_package_icon.empty() || !cpack_dmg_ds_store_setup_script.empty(); + std::string temp_image_format = "UDZO"; + // Create 1 MB dummy padding file in staging area when we need to remount // image, so we have enough space for storing changes ... if (remount_image) { @@ -401,6 +403,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, return 0; } + temp_image_format = "UDRW"; } // Create a temporary read-write disk image ... @@ -413,7 +416,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, temp_image_command << " -ov"; temp_image_command << " -srcfolder \"" << staging.str() << "\""; temp_image_command << " -volname \"" << cpack_dmg_volume_name << "\""; - temp_image_command << " -format UDRW"; + temp_image_command << " -format " << temp_image_format; temp_image_command << " \"" << temp_image << "\""; if (!this->RunCommand(temp_image_command)) { @@ -632,29 +635,33 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, return 0; } - // convert to UDCO - std::string temp_udco = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); - temp_udco += "/temp-udco.dmg"; + if (temp_image_format != "UDZO") { + temp_image_format = "UDZO"; + // convert to UDZO to enable unflatten/flatten + std::string temp_udzo = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); + temp_udzo += "/temp-udzo.dmg"; - std::ostringstream udco_image_command; - udco_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL"); - udco_image_command << " convert \"" << temp_image << "\""; - udco_image_command << " -format UDCO"; - udco_image_command << " -ov -o \"" << temp_udco << "\""; + std::ostringstream udco_image_command; + udco_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL"); + udco_image_command << " convert \"" << temp_image << "\""; + udco_image_command << " -format UDZO"; + udco_image_command << " -ov -o \"" << temp_udzo << "\""; - if (!this->RunCommand(udco_image_command, &error)) { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Error converting to UDCO dmg for adding SLA." - << std::endl - << error << std::endl); - return 0; + if (!this->RunCommand(udco_image_command, &error)) { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "Error converting to UDCO dmg for adding SLA." + << std::endl + << error << std::endl); + return 0; + } + temp_image = temp_udzo; } // unflatten dmg std::ostringstream unflatten_command; unflatten_command << this->GetOption("CPACK_COMMAND_HDIUTIL"); unflatten_command << " unflatten "; - unflatten_command << "\"" << temp_udco << "\""; + unflatten_command << "\"" << temp_image << "\""; if (!this->RunCommand(unflatten_command, &error)) { cmCPackLogger(cmCPackLog::LOG_ERROR, @@ -673,7 +680,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, } embed_sla_command << " \"" << sla_r << "\""; embed_sla_command << " -a -o "; - embed_sla_command << "\"" << temp_udco << "\""; + embed_sla_command << "\"" << temp_image << "\""; if (!this->RunCommand(embed_sla_command, &error)) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Error adding SLA." << std::endl @@ -686,7 +693,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, std::ostringstream flatten_command; flatten_command << this->GetOption("CPACK_COMMAND_HDIUTIL"); flatten_command << " flatten "; - flatten_command << "\"" << temp_udco << "\""; + flatten_command << "\"" << temp_image << "\""; if (!this->RunCommand(flatten_command, &error)) { cmCPackLogger(cmCPackLog::LOG_ERROR, @@ -695,8 +702,6 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, << std::endl); return 0; } - - temp_image = temp_udco; } // Create the final compressed read-only disk image ... ----------------------------------------------------------------------- Summary of changes: Source/CPack/cmCPackDragNDropGenerator.cxx | 45 +++++++++++++++------------- 1 file changed, 25 insertions(+), 20 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 23 14:27:42 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 23 Feb 2017 14:27:42 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-523-g9870ed6 Message-ID: <20170223192742.A77B0FA0BD@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 9870ed61b83cd7b822d47a955f0c0e2543d065a7 (commit) via fe5b8275e69a3ffe2ce22c80ba0ea08936967323 (commit) from cf660ade3f88a6364dc86a9616da9b9198216e25 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9870ed61b83cd7b822d47a955f0c0e2543d065a7 commit 9870ed61b83cd7b822d47a955f0c0e2543d065a7 Merge: cf660ad fe5b827 Author: Brad King AuthorDate: Thu Feb 23 14:27:41 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 23 14:27:41 2017 -0500 Merge topic 'cache-xaml-resx-headers' into next fe5b8275 VS: Cache the list of xaml and resx headers https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=fe5b8275e69a3ffe2ce22c80ba0ea08936967323 commit fe5b8275e69a3ffe2ce22c80ba0ea08936967323 Author: Dmitry Kochkin AuthorDate: Thu Feb 23 20:08:08 2017 +0100 Commit: Brad King CommitDate: Thu Feb 23 14:23:15 2017 -0500 VS: Cache the list of xaml and resx headers Speed up VS project generation with many such headers. diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 8512b99..dfb6a5e 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -711,12 +711,17 @@ void cmGeneratorTarget::GetExternalObjects( IMPLEMENT_VISIT(ExternalObjects); } -void cmGeneratorTarget::GetExpectedResxHeaders(std::set& srcs, +void cmGeneratorTarget::GetExpectedResxHeaders(std::set& headers, const std::string& config) const { - ResxData data; - IMPLEMENT_VISIT_IMPL(Resx, COMMA cmGeneratorTarget::ResxData) - srcs = data.ExpectedResxHeaders; + HeadersCacheType::const_iterator it = this->ResxHeadersCache.find(config); + if (it == ResxHeadersCache.end()) { + ResxData data; + IMPLEMENT_VISIT_IMPL(Resx, COMMA cmGeneratorTarget::ResxData) + this->ResxHeadersCache[config] = data.ExpectedResxHeaders; + } else { + headers = it->second; + } } void cmGeneratorTarget::GetResxSources(std::vector& srcs, @@ -748,9 +753,14 @@ void cmGeneratorTarget::GetCertificates(std::vector& data, void cmGeneratorTarget::GetExpectedXamlHeaders(std::set& headers, const std::string& config) const { - XamlData data; - IMPLEMENT_VISIT_IMPL(Xaml, COMMA cmGeneratorTarget::XamlData) - headers = data.ExpectedXamlHeaders; + HeadersCacheType::const_iterator it = this->XamlHeadersCache.find(config); + if (it == XamlHeadersCache.end()) { + XamlData data; + IMPLEMENT_VISIT_IMPL(Xaml, COMMA cmGeneratorTarget::XamlData) + this->XamlHeadersCache[config] = data.ExpectedXamlHeaders; + } else { + headers = it->second; + } } void cmGeneratorTarget::GetExpectedXamlSources(std::set& srcs, diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 689fbda..e72e0a6 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -739,6 +739,10 @@ private: bool ComputePDBOutputDir(const std::string& kind, const std::string& config, std::string& out) const; + typedef std::map > HeadersCacheType; + mutable HeadersCacheType ResxHeadersCache; + mutable HeadersCacheType XamlHeadersCache; + public: const std::vector& GetLinkImplementationClosure( const std::string& config) const; ----------------------------------------------------------------------- Summary of changes: Source/cmGeneratorTarget.cxx | 24 +++++++++++++++++------- Source/cmGeneratorTarget.h | 4 ++++ 2 files changed, 21 insertions(+), 7 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Thu Feb 23 14:29:57 2017 From: brad.king at kitware.com (Brad King) Date: Thu, 23 Feb 2017 14:29:57 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-525-g4e8742d Message-ID: <20170223192957.AF762FA12B@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 4e8742d78f9176a3476ec442d7353fc4b3a7a58a (commit) via 2cb165e8c0943baa8bc05e97ef89b5e0b0261297 (commit) from 9870ed61b83cd7b822d47a955f0c0e2543d065a7 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4e8742d78f9176a3476ec442d7353fc4b3a7a58a commit 4e8742d78f9176a3476ec442d7353fc4b3a7a58a Merge: 9870ed6 2cb165e Author: Brad King AuthorDate: Thu Feb 23 14:29:55 2017 -0500 Commit: CMake Topic Stage CommitDate: Thu Feb 23 14:29:55 2017 -0500 Merge topic 'vcxproj-indentation' into next 2cb165e8 VS: Fix .vcxproj indentation https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=2cb165e8c0943baa8bc05e97ef89b5e0b0261297 commit 2cb165e8c0943baa8bc05e97ef89b5e0b0261297 Author: Brad King AuthorDate: Thu Feb 23 13:38:47 2017 -0500 Commit: Brad King CommitDate: Thu Feb 23 13:38:47 2017 -0500 VS: Fix .vcxproj indentation In commit v3.8.0-rc1~87^2~1 (VS: added support for C#, 2017-01-09) we removed what looked like a no-op streaming operation but in fact it is responsible for applying indentation. Restore the line. diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 2e6c19b..21bb774 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -130,6 +130,7 @@ void cmVisualStudio10TargetGenerator::WritePlatformConfigTag( } stream->fill(' '); stream->width(indentLevel * 2); + (*stream) << ""; // applies indentation (*stream) << "<" << tag << " Condition=\""; (*stream) << "'$(Configuration)|$(Platform)'=='"; (*stream) << config << "|" << this->Platform; ----------------------------------------------------------------------- Summary of changes: Source/cmVisualStudio10TargetGenerator.cxx | 1 + 1 file changed, 1 insertion(+) hooks/post-receive -- CMake From kwrobot at kitware.com Fri Feb 24 00:01:09 2017 From: kwrobot at kitware.com (Kitware Robot) Date: Fri, 24 Feb 2017 00:01:09 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-256-g32cb417 Message-ID: <20170224050109.4EA6BFA332@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 32cb4172bd6b98810f9638076e978a6bc569f6ae (commit) from 3f8e94f71effc552fd13d4d37a5ae367fe896644 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=32cb4172bd6b98810f9638076e978a6bc569f6ae commit 32cb4172bd6b98810f9638076e978a6bc569f6ae Author: Kitware Robot AuthorDate: Fri Feb 24 00:01:05 2017 -0500 Commit: Kitware Robot CommitDate: Fri Feb 24 00:01:05 2017 -0500 CMake Nightly Date Stamp diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 0dc9dad..12dc033 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 8) -set(CMake_VERSION_PATCH 20170223) +set(CMake_VERSION_PATCH 20170224) #set(CMake_VERSION_RC 1) ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 24 09:09:52 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 24 Feb 2017 09:09:52 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-527-g1b1ec57 Message-ID: <20170224140952.B4C74A9CEF@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 1b1ec57d5aef2e96192b7bc5f16d1e5a215784a1 (commit) via 2491e369274a50ea8f27404d2a0de626c2ce93d0 (commit) from 4e8742d78f9176a3476ec442d7353fc4b3a7a58a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1b1ec57d5aef2e96192b7bc5f16d1e5a215784a1 commit 1b1ec57d5aef2e96192b7bc5f16d1e5a215784a1 Merge: 4e8742d 2491e36 Author: Brad King AuthorDate: Fri Feb 24 09:09:52 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 24 09:09:52 2017 -0500 Merge topic 'cache-xaml-resx-headers' into next 2491e369 Revert "VS: Cache the list of xaml and resx headers" https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=2491e369274a50ea8f27404d2a0de626c2ce93d0 commit 2491e369274a50ea8f27404d2a0de626c2ce93d0 Author: Brad King AuthorDate: Fri Feb 24 09:09:42 2017 -0500 Commit: Brad King CommitDate: Fri Feb 24 09:09:42 2017 -0500 Revert "VS: Cache the list of xaml and resx headers" This reverts commit fe5b8275e69a3ffe2ce22c80ba0ea08936967323. diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index dfb6a5e..8512b99 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -711,17 +711,12 @@ void cmGeneratorTarget::GetExternalObjects( IMPLEMENT_VISIT(ExternalObjects); } -void cmGeneratorTarget::GetExpectedResxHeaders(std::set& headers, +void cmGeneratorTarget::GetExpectedResxHeaders(std::set& srcs, const std::string& config) const { - HeadersCacheType::const_iterator it = this->ResxHeadersCache.find(config); - if (it == ResxHeadersCache.end()) { - ResxData data; - IMPLEMENT_VISIT_IMPL(Resx, COMMA cmGeneratorTarget::ResxData) - this->ResxHeadersCache[config] = data.ExpectedResxHeaders; - } else { - headers = it->second; - } + ResxData data; + IMPLEMENT_VISIT_IMPL(Resx, COMMA cmGeneratorTarget::ResxData) + srcs = data.ExpectedResxHeaders; } void cmGeneratorTarget::GetResxSources(std::vector& srcs, @@ -753,14 +748,9 @@ void cmGeneratorTarget::GetCertificates(std::vector& data, void cmGeneratorTarget::GetExpectedXamlHeaders(std::set& headers, const std::string& config) const { - HeadersCacheType::const_iterator it = this->XamlHeadersCache.find(config); - if (it == XamlHeadersCache.end()) { - XamlData data; - IMPLEMENT_VISIT_IMPL(Xaml, COMMA cmGeneratorTarget::XamlData) - this->XamlHeadersCache[config] = data.ExpectedXamlHeaders; - } else { - headers = it->second; - } + XamlData data; + IMPLEMENT_VISIT_IMPL(Xaml, COMMA cmGeneratorTarget::XamlData) + headers = data.ExpectedXamlHeaders; } void cmGeneratorTarget::GetExpectedXamlSources(std::set& srcs, diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index e72e0a6..689fbda 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -739,10 +739,6 @@ private: bool ComputePDBOutputDir(const std::string& kind, const std::string& config, std::string& out) const; - typedef std::map > HeadersCacheType; - mutable HeadersCacheType ResxHeadersCache; - mutable HeadersCacheType XamlHeadersCache; - public: const std::vector& GetLinkImplementationClosure( const std::string& config) const; ----------------------------------------------------------------------- Summary of changes: Source/cmGeneratorTarget.cxx | 24 +++++++----------------- Source/cmGeneratorTarget.h | 4 ---- 2 files changed, 7 insertions(+), 21 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 24 09:31:21 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 24 Feb 2017 09:31:21 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-259-g8429068 Message-ID: <20170224143121.4B440F9FE6@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 8429068d7c37d06e53b871811760419ab3e36455 (commit) via 741b7621b3c71406359d75098f9bdf8d3567662f (commit) via 1f661e87a6a8304edb77bd30b546e5d113477c59 (commit) from 32cb4172bd6b98810f9638076e978a6bc569f6ae (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8429068d7c37d06e53b871811760419ab3e36455 commit 8429068d7c37d06e53b871811760419ab3e36455 Merge: 32cb417 741b762 Author: Brad King AuthorDate: Fri Feb 24 09:31:18 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 24 09:31:18 2017 -0500 Merge topic 'update-libuv' 741b7621 Merge branch 'upstream-libuv' into update-libuv 1f661e87 libuv 2017-02-21 (52ae8264) ----------------------------------------------------------------------- Summary of changes: Utilities/cmlibuv/include/pthread-barrier.h | 2 + Utilities/cmlibuv/include/uv-os390.h | 3 + Utilities/cmlibuv/include/uv-unix.h | 4 + Utilities/cmlibuv/include/uv-version.h | 4 +- Utilities/cmlibuv/include/uv-win.h | 1 + Utilities/cmlibuv/include/uv.h | 2 + Utilities/cmlibuv/src/unix/aix.c | 86 ++- Utilities/cmlibuv/src/unix/atomic-ops.h | 27 +- Utilities/cmlibuv/src/unix/core.c | 18 +- Utilities/cmlibuv/src/unix/fs.c | 57 +- Utilities/cmlibuv/src/unix/internal.h | 12 +- Utilities/cmlibuv/src/unix/openbsd.c | 2 +- Utilities/cmlibuv/src/unix/os390-syscalls.c | 334 +++++++++++ Utilities/cmlibuv/src/unix/os390-syscalls.h | 69 +++ Utilities/cmlibuv/src/unix/os390.c | 823 ++++++++++++++++++++++++++ Utilities/cmlibuv/src/unix/poll.c | 4 +- Utilities/cmlibuv/src/unix/process.c | 4 +- Utilities/cmlibuv/src/unix/proctitle.c | 6 + Utilities/cmlibuv/src/unix/pthread-barrier.c | 3 +- Utilities/cmlibuv/src/unix/signal.c | 8 +- Utilities/cmlibuv/src/unix/stream.c | 31 +- Utilities/cmlibuv/src/unix/sunos.c | 11 +- Utilities/cmlibuv/src/unix/thread.c | 32 +- Utilities/cmlibuv/src/uv-common.c | 12 +- Utilities/cmlibuv/src/win/core.c | 4 - Utilities/cmlibuv/src/win/error.c | 1 + Utilities/cmlibuv/src/win/fs-event.c | 3 +- Utilities/cmlibuv/src/win/fs.c | 4 +- Utilities/cmlibuv/src/win/getaddrinfo.c | 3 +- Utilities/cmlibuv/src/win/process-stdio.c | 1 + Utilities/cmlibuv/src/win/process.c | 2 +- Utilities/cmlibuv/src/win/signal.c | 118 +--- Utilities/cmlibuv/src/win/tty.c | 91 +-- Utilities/cmlibuv/src/win/winapi.h | 4 + 34 files changed, 1530 insertions(+), 256 deletions(-) create mode 100644 Utilities/cmlibuv/src/unix/os390-syscalls.c create mode 100644 Utilities/cmlibuv/src/unix/os390-syscalls.h hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 24 09:31:24 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 24 Feb 2017 09:31:24 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-268-g33f6362 Message-ID: <20170224143124.45156ADB71@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 33f636264a5d830f67316dc6184f4056b3a3629f (commit) via d49176e91e4fb4ae31be1011c1029ca07d2cf494 (commit) via ce8f117fe2c10f1ebd56cb8adec0dcde1fc62457 (commit) via e0f725f821f251165c17a7580c2000342ac505a2 (commit) via ae4861ec2214cb025f8bf2426376a4aca9809d73 (commit) via fecb70dd34b5ba244263e72c42f90701775e132f (commit) via a59a7ee95601f3496ec9ba9ae1283a8d980460bf (commit) via c206211af647dd1f7039da91c34c9c72e50aefdf (commit) via cdce7c619c58ec0947c036b93013445bb93e4be8 (commit) from 8429068d7c37d06e53b871811760419ab3e36455 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=33f636264a5d830f67316dc6184f4056b3a3629f commit 33f636264a5d830f67316dc6184f4056b3a3629f Merge: 8429068 d49176e Author: Brad King AuthorDate: Fri Feb 24 09:31:22 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 24 09:31:22 2017 -0500 Merge topic 'update-libarchive' d49176e9 libarchive: Avoid using isblank ce8f117f libarchive: Avoid declaration after statement in C code e0f725f8 libarchive: Fix use of ssize_t in archive_entry.h ae4861ec libarchive: Define __LA_DEPRECATED consistently fecb70dd Update CMake pre-cached values for libarchive 3.3.0 a59a7ee9 Merge branch 'upstream-LibArchive' into update-libarchive c206211a LibArchive 2017-02-19 (100ee75a) cdce7c61 libarchive: Update script to get 3.3.0 ----------------------------------------------------------------------- Summary of changes: CMakeLists.txt | 24 +- Utilities/Scripts/update-libarchive.bash | 2 +- Utilities/cmlibarchive/CMakeLists.txt | 132 +- .../build/cmake/CheckStructMember.cmake | 43 - Utilities/cmlibarchive/build/cmake/FindLZMA.cmake | 48 - Utilities/cmlibarchive/build/cmake/config.h.in | 18 + Utilities/cmlibarchive/build/version | 2 +- Utilities/cmlibarchive/libarchive/CMakeLists.txt | 18 + Utilities/cmlibarchive/libarchive/archive.h | 16 +- Utilities/cmlibarchive/libarchive/archive_acl.c | 1639 +++++++++++++++----- .../cmlibarchive/libarchive/archive_acl_private.h | 22 +- .../cmlibarchive/libarchive/archive_cryptor.c | 3 +- Utilities/cmlibarchive/libarchive/archive_entry.c | 124 +- Utilities/cmlibarchive/libarchive/archive_entry.h | 91 +- .../cmlibarchive/libarchive/archive_entry_acl.3 | 335 +++- .../cmlibarchive/libarchive/archive_entry_locale.h | 10 +- .../libarchive/archive_entry_strmode.c | 2 +- Utilities/cmlibarchive/libarchive/archive_match.c | 14 +- .../libarchive/archive_openssl_evp_private.h | 5 +- .../libarchive/archive_openssl_hmac_private.h | 6 +- .../cmlibarchive/libarchive/archive_options.c | 11 +- .../cmlibarchive/libarchive/archive_platform.h | 28 +- .../libarchive/archive_ppmd7_private.h | 2 +- Utilities/cmlibarchive/libarchive/archive_random.c | 2 +- Utilities/cmlibarchive/libarchive/archive_rb.c | 2 +- Utilities/cmlibarchive/libarchive/archive_read.c | 16 +- .../libarchive/archive_read_add_passphrase.c | 22 +- .../libarchive/archive_read_append_filter.c | 2 - .../cmlibarchive/libarchive/archive_read_disk.3 | 6 +- .../libarchive/archive_read_disk_entry_from_file.c | 1066 +++++++++++-- .../libarchive/archive_read_disk_posix.c | 71 +- .../archive_read_disk_set_standard_lookup.c | 2 + .../libarchive/archive_read_disk_windows.c | 29 +- .../libarchive/archive_read_extract2.c | 3 +- .../libarchive/archive_read_open_filename.c | 20 +- .../libarchive/archive_read_open_memory.c | 3 +- .../cmlibarchive/libarchive/archive_read_private.h | 3 +- .../libarchive/archive_read_support_filter_lz4.c | 13 +- .../libarchive/archive_read_support_filter_lzop.c | 2 +- .../archive_read_support_filter_program.c | 2 + .../libarchive/archive_read_support_filter_uu.c | 44 +- .../libarchive/archive_read_support_filter_xz.c | 194 +-- .../libarchive/archive_read_support_format_7zip.c | 39 +- .../libarchive/archive_read_support_format_ar.c | 22 +- .../libarchive/archive_read_support_format_cab.c | 15 +- .../libarchive/archive_read_support_format_cpio.c | 17 +- .../archive_read_support_format_iso9660.c | 40 +- .../libarchive/archive_read_support_format_lha.c | 13 +- .../libarchive/archive_read_support_format_mtree.c | 71 +- .../libarchive/archive_read_support_format_rar.c | 5 +- .../libarchive/archive_read_support_format_tar.c | 281 +++- .../libarchive/archive_read_support_format_warc.c | 243 +-- .../libarchive/archive_read_support_format_xar.c | 87 +- .../libarchive/archive_read_support_format_zip.c | 158 +- Utilities/cmlibarchive/libarchive/archive_string.c | 117 +- Utilities/cmlibarchive/libarchive/archive_string.h | 8 +- .../libarchive/archive_string_composition.h | 2 +- Utilities/cmlibarchive/libarchive/archive_util.c | 2 +- .../cmlibarchive/libarchive/archive_windows.c | 4 +- .../cmlibarchive/libarchive/archive_windows.h | 4 + Utilities/cmlibarchive/libarchive/archive_write.c | 8 +- .../libarchive/archive_write_add_filter_lz4.c | 4 +- .../libarchive/archive_write_add_filter_program.c | 1 + .../libarchive/archive_write_add_filter_xz.c | 2 +- .../libarchive/archive_write_disk_acl.c | 545 ++++++- .../libarchive/archive_write_disk_posix.c | 533 +++++-- .../archive_write_disk_set_standard_lookup.c | 6 +- .../libarchive/archive_write_disk_windows.c | 7 +- .../cmlibarchive/libarchive/archive_write_open.3 | 11 + .../libarchive/archive_write_open_memory.c | 3 +- .../libarchive/archive_write_set_format_7zip.c | 4 +- .../libarchive/archive_write_set_format_ar.c | 3 +- .../libarchive/archive_write_set_format_cpio.c | 2 +- .../archive_write_set_format_cpio_newc.c | 5 +- .../libarchive/archive_write_set_format_gnutar.c | 14 +- .../libarchive/archive_write_set_format_iso9660.c | 60 +- .../libarchive/archive_write_set_format_mtree.c | 4 +- .../libarchive/archive_write_set_format_pax.c | 183 ++- .../libarchive/archive_write_set_format_shar.c | 3 +- .../libarchive/archive_write_set_format_ustar.c | 11 +- .../libarchive/archive_write_set_format_v7tar.c | 9 +- .../libarchive/archive_write_set_format_warc.c | 2 +- .../libarchive/archive_write_set_format_xar.c | 21 +- .../libarchive/archive_write_set_format_zip.c | 12 +- Utilities/cmlibarchive/libarchive/config_freebsd.h | 2 + .../cmlibarchive/libarchive/libarchive-formats.5 | 4 +- Utilities/cmlibarchive/libarchive/tar.5 | 11 +- Utilities/cmlibarchive/libarchive/xxhash.c | 6 +- 88 files changed, 4720 insertions(+), 1981 deletions(-) delete mode 100644 Utilities/cmlibarchive/build/cmake/CheckStructMember.cmake delete mode 100644 Utilities/cmlibarchive/build/cmake/FindLZMA.cmake hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 24 09:31:27 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 24 Feb 2017 09:31:27 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-270-gf104fe4 Message-ID: <20170224143127.05457FA108@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via f104fe45fc9179e96065f576b0cc3529b29cd624 (commit) via 0c14db2558a3792b59da08ebeccdc1f3acba945a (commit) from 33f636264a5d830f67316dc6184f4056b3a3629f (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f104fe45fc9179e96065f576b0cc3529b29cd624 commit f104fe45fc9179e96065f576b0cc3529b29cd624 Merge: 33f6362 0c14db2 Author: Brad King AuthorDate: Fri Feb 24 09:31:25 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 24 09:31:25 2017 -0500 Merge topic 'cmake-server-aix' 0c14db25 cmServerConnection.h: Include cmConfigure.h first ----------------------------------------------------------------------- Summary of changes: Source/cmServerConnection.h | 2 ++ 1 file changed, 2 insertions(+) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 24 09:31:30 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 24 Feb 2017 09:31:30 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-278-g31282e7 Message-ID: <20170224143130.1C113FA0BD@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 31282e7854dfa4f28ebe26839599104b4f0b7008 (commit) via 62a1e292f29d740d0b193e45f0acd37f7ffaced6 (commit) via e98465cfed68f6511af552ac8ab0d168791f4302 (commit) via 96f6f392e3d2ba95c11d0b77fbb5da485e626ed4 (commit) via 94e3f82cf114d12b190d1999a72838018eb171c9 (commit) via 70ebf35cdaaf391138df7564a07cd205de4af971 (commit) via 2a6fd4328adfad4cae0097d6d71e571c122fc0d1 (commit) via e9a8a207ad6817cc93eab2b878de090b5ece8bfe (commit) from f104fe45fc9179e96065f576b0cc3529b29cd624 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=31282e7854dfa4f28ebe26839599104b4f0b7008 commit 31282e7854dfa4f28ebe26839599104b4f0b7008 Merge: f104fe4 62a1e29 Author: Brad King AuthorDate: Fri Feb 24 09:31:27 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 24 09:31:27 2017 -0500 Merge topic 'autogen_depends' 62a1e292 Autogen: Add hint to SKIP_AUTOMOC in error message e98465cf Autogen: Add Quote function and use it for logging 96f6f392 Autogen: Add AUTOMOC_DEPEND_FILTERS documentation 94e3f82c Autogen: Add AUTOMOC_DEPEND_FILTERS test 70ebf35c Autogen: Add AUTOMOC_DEPEND_FILTERS support 2a6fd432 Autogen: Single point of return in Run() method e9a8a207 Autogen: Log simplifications ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-properties.7.rst | 1 + Help/manual/cmake-qt.7.rst | 3 + Help/manual/cmake-variables.7.rst | 1 + Help/prop_tgt/AUTOMOC.rst | 3 + Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst | 45 ++++ Help/release/dev/Autogen_depends.rst | 10 + Help/variable/CMAKE_AUTOMOC_DEPEND_FILTERS.rst | 12 + Modules/AutogenInfo.cmake.in | 1 + Source/cmQtAutoGeneratorInitializer.cxx | 2 + Source/cmQtAutoGenerators.cxx | 249 ++++++++++++-------- Source/cmQtAutoGenerators.h | 1 + Source/cmTarget.cxx | 1 + Tests/QtAutogen/CMakeLists.txt | 22 +- Tests/QtAutogen/mocPlugin/CMakeLists.txt | 11 +- Tests/QtAutogen/mocPlugin/StyleA.hpp | 2 + .../mocPlugin/{StyleA.json => StyleA_Custom.json} | 0 Tests/QtAutogen/mocPlugin/StyleB.hpp | 2 + Tests/QtAutogen/mocPlugin/StyleC.hpp | 2 + Tests/QtAutogen/mocPlugin/StyleCommon.hpp | 7 + Tests/QtAutogen/mocPlugin/StyleD.hpp | 2 + Tests/QtAutogen/mocPlugin/StyleE.hpp | 2 + .../jsonIn/{StyleB.json => StyleB_Custom.json} | 0 22 files changed, 278 insertions(+), 101 deletions(-) create mode 100644 Help/prop_tgt/AUTOMOC_DEPEND_FILTERS.rst create mode 100644 Help/release/dev/Autogen_depends.rst create mode 100644 Help/variable/CMAKE_AUTOMOC_DEPEND_FILTERS.rst copy Tests/QtAutogen/mocPlugin/{StyleA.json => StyleA_Custom.json} (100%) create mode 100644 Tests/QtAutogen/mocPlugin/StyleCommon.hpp copy Tests/QtAutogen/mocPlugin/jsonIn/{StyleB.json => StyleB_Custom.json} (100%) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 24 09:31:32 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 24 Feb 2017 09:31:32 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-280-g0b0e28d Message-ID: <20170224143132.9F6DFFA0BD@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 0b0e28d30b1b3b91150ce88a3cb94c8bf39fa7ce (commit) via 9dc7a2ed2cbc36d9b6a9286822020a5da2536df2 (commit) from 31282e7854dfa4f28ebe26839599104b4f0b7008 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0b0e28d30b1b3b91150ce88a3cb94c8bf39fa7ce commit 0b0e28d30b1b3b91150ce88a3cb94c8bf39fa7ce Merge: 31282e7 9dc7a2e Author: Brad King AuthorDate: Fri Feb 24 09:31:30 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 24 09:31:30 2017 -0500 Merge topic 'find_openmp_clang_patch' 9dc7a2ed FindOpenMP: Add iomp5 variant of Clang OpenMP flags ----------------------------------------------------------------------- Summary of changes: Modules/FindOpenMP.cmake | 1 + 1 file changed, 1 insertion(+) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 24 09:31:35 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 24 Feb 2017 09:31:35 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-282-g17c1519 Message-ID: <20170224143135.887D2FA089@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 17c151965d4c8f7d5a75e82341403fa43c7ca42f (commit) via 2cb165e8c0943baa8bc05e97ef89b5e0b0261297 (commit) from 0b0e28d30b1b3b91150ce88a3cb94c8bf39fa7ce (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=17c151965d4c8f7d5a75e82341403fa43c7ca42f commit 17c151965d4c8f7d5a75e82341403fa43c7ca42f Merge: 0b0e28d 2cb165e Author: Brad King AuthorDate: Fri Feb 24 09:31:33 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 24 09:31:33 2017 -0500 Merge topic 'vcxproj-indentation' 2cb165e8 VS: Fix .vcxproj indentation ----------------------------------------------------------------------- Summary of changes: Source/cmVisualStudio10TargetGenerator.cxx | 1 + 1 file changed, 1 insertion(+) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 24 09:31:38 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 24 Feb 2017 09:31:38 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-284-g58ec493 Message-ID: <20170224143138.200CDFA10E@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 58ec4932e348814d70d70f7e60ad0c2fcb2240f7 (commit) via 356068cd2e3c395fa824568613c1de315fa8b05b (commit) from 17c151965d4c8f7d5a75e82341403fa43c7ca42f (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=58ec4932e348814d70d70f7e60ad0c2fcb2240f7 commit 58ec4932e348814d70d70f7e60ad0c2fcb2240f7 Merge: 17c1519 356068c Author: Brad King AuthorDate: Fri Feb 24 09:31:36 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 24 09:31:36 2017 -0500 Merge topic 'dragndrop-format' 356068cd cmCPackDragNDropGenerator: Improving handling of temporary dmg images ----------------------------------------------------------------------- Summary of changes: Source/CPack/cmCPackDragNDropGenerator.cxx | 45 +++++++++++++++------------- 1 file changed, 25 insertions(+), 20 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 24 09:31:41 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 24 Feb 2017 09:31:41 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-290-g32f13fb Message-ID: <20170224143141.326FDFA10E@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 32f13fbe09fc8a5814bb3137abf2158cf1e24807 (commit) via 624021a09e7850b1f6cb75af40b17a38d98c95e3 (commit) via 5da9266af50af3c2c1a827a1d162c8a9b16e7fd9 (commit) via e80ac953035703dde6e03e2c32ba9fded8c69f2a (commit) via 9293e57d9cef75a5abb6f28d5bf712106471a137 (commit) via 33a1d727d5aafeaa0d9e729119d7d43ea9fcb370 (commit) from 58ec4932e348814d70d70f7e60ad0c2fcb2240f7 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=32f13fbe09fc8a5814bb3137abf2158cf1e24807 commit 32f13fbe09fc8a5814bb3137abf2158cf1e24807 Merge: 58ec493 624021a Author: Brad King AuthorDate: Fri Feb 24 09:31:39 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 24 09:31:39 2017 -0500 Merge topic '16615-xcode-object-libraries-depends' 624021a0 Add test for object library dependencies 5da9266a Xcode: Always track object library dependencies via hacky Makefile e80ac953 Xcode: Record dependency information also for object libraries 9293e57d Xcode: Collect dummy rules during iteration and emit afterwards 33a1d727 Makefile: Allow adding post-build rules to object libraries ----------------------------------------------------------------------- Summary of changes: Source/cmGlobalXCodeGenerator.cxx | 102 +++++++++++--------- Source/cmMakefile.cxx | 6 +- Source/cmMakefile.h | 10 +- Tests/RunCMake/ObjectLibrary/Dependencies.cmake | 11 +++ Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake | 19 ++++ Tests/RunCMake/ObjectLibrary/depends_lib.cpp | 7 ++ Tests/RunCMake/ObjectLibrary/depends_main.cpp | 7 ++ .../RunCMake/ObjectLibrary/depends_obj0.cpp | 2 +- .../ObjectLibrary/depends_obj1.cpp} | 2 +- 9 files changed, 115 insertions(+), 51 deletions(-) create mode 100644 Tests/RunCMake/ObjectLibrary/Dependencies.cmake create mode 100644 Tests/RunCMake/ObjectLibrary/depends_lib.cpp create mode 100644 Tests/RunCMake/ObjectLibrary/depends_main.cpp copy Modules/DummyCXXFile.cxx => Tests/RunCMake/ObjectLibrary/depends_obj0.cpp (50%) copy Tests/{Complex/Library/ExtraSources/file1.cxx => RunCMake/ObjectLibrary/depends_obj1.cpp} (50%) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 24 09:31:43 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 24 Feb 2017 09:31:43 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-292-gfd14f87 Message-ID: <20170224143143.BC265FA108@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via fd14f8733934469a524d3f2be595aba20c47c82c (commit) via eacf7decbf78a184cdad7a6fd533aa4f433ec27f (commit) from 32f13fbe09fc8a5814bb3137abf2158cf1e24807 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=fd14f8733934469a524d3f2be595aba20c47c82c commit fd14f8733934469a524d3f2be595aba20c47c82c Merge: 32f13fb eacf7de Author: Brad King AuthorDate: Fri Feb 24 09:31:41 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 24 09:31:41 2017 -0500 Merge topic 'GetPrerequisites-find_item_basename' eacf7dec GetPrerequisites: also try to resolve just the basename ----------------------------------------------------------------------- Summary of changes: Modules/GetPrerequisites.cmake | 5 +++++ 1 file changed, 5 insertions(+) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 24 09:32:10 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 24 Feb 2017 09:32:10 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-538-g19fec70 Message-ID: <20170224143210.69E0BF9FE6@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 19fec70c0830e7c31b2b552ed6f560762950fbf0 (commit) via fd14f8733934469a524d3f2be595aba20c47c82c (commit) via 32f13fbe09fc8a5814bb3137abf2158cf1e24807 (commit) via 58ec4932e348814d70d70f7e60ad0c2fcb2240f7 (commit) via 17c151965d4c8f7d5a75e82341403fa43c7ca42f (commit) via 0b0e28d30b1b3b91150ce88a3cb94c8bf39fa7ce (commit) via 31282e7854dfa4f28ebe26839599104b4f0b7008 (commit) via f104fe45fc9179e96065f576b0cc3529b29cd624 (commit) via 33f636264a5d830f67316dc6184f4056b3a3629f (commit) via 8429068d7c37d06e53b871811760419ab3e36455 (commit) via 32cb4172bd6b98810f9638076e978a6bc569f6ae (commit) from 1b1ec57d5aef2e96192b7bc5f16d1e5a215784a1 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=19fec70c0830e7c31b2b552ed6f560762950fbf0 commit 19fec70c0830e7c31b2b552ed6f560762950fbf0 Merge: 1b1ec57 fd14f87 Author: Brad King AuthorDate: Fri Feb 24 09:31:50 2017 -0500 Commit: Brad King CommitDate: Fri Feb 24 09:31:50 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 24 10:02:11 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 24 Feb 2017 10:02:11 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-297-gbadc2c4 Message-ID: <20170224150211.92EFBFA41A@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via badc2c44d8d1c5367c54b2ae67aff84ecef178fe (commit) via 5eb4d9d80bbdbf316a1ccb2b062dcc9f34f95c3a (commit) via 25480ffbf6aacc6a61dd68934131c839eefd036e (commit) via 970fe6ec2fa5c195f157338bb8b9b3c8766e00a3 (commit) via 4734c3e6dbf5cdabcfedb449e92a61471f7664b7 (commit) from fd14f8733934469a524d3f2be595aba20c47c82c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 24 10:02:11 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 24 Feb 2017 10:02:11 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-544-g69d7feb Message-ID: <20170224150211.AD399FA41F@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 69d7feb40cd3bc891e6ad029921a26c7e8347547 (commit) via badc2c44d8d1c5367c54b2ae67aff84ecef178fe (commit) via 5eb4d9d80bbdbf316a1ccb2b062dcc9f34f95c3a (commit) via 25480ffbf6aacc6a61dd68934131c839eefd036e (commit) via 970fe6ec2fa5c195f157338bb8b9b3c8766e00a3 (commit) via 4734c3e6dbf5cdabcfedb449e92a61471f7664b7 (commit) from 19fec70c0830e7c31b2b552ed6f560762950fbf0 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=69d7feb40cd3bc891e6ad029921a26c7e8347547 commit 69d7feb40cd3bc891e6ad029921a26c7e8347547 Merge: 19fec70 badc2c4 Author: Brad King AuthorDate: Fri Feb 24 10:02:00 2017 -0500 Commit: Brad King CommitDate: Fri Feb 24 10:02:00 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 24 10:02:11 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 24 Feb 2017 10:02:11 -0500 (EST) Subject: [Cmake-commits] CMake branch, release, updated. v3.8.0-rc1-49-g5eb4d9d Message-ID: <20170224150211.F2AA7FA440@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, release has been updated via 5eb4d9d80bbdbf316a1ccb2b062dcc9f34f95c3a (commit) via 2cb165e8c0943baa8bc05e97ef89b5e0b0261297 (commit) via 25480ffbf6aacc6a61dd68934131c839eefd036e (commit) via d5f39a56a44fe061018c6acc15e1c3aa7337ff54 (commit) via f6986ee479f1cce6da17859eaf6a0616852b9e20 (commit) via 2256c3a7db89c58ecdd0e6cfcdff7805522187f1 (commit) via 970fe6ec2fa5c195f157338bb8b9b3c8766e00a3 (commit) via 1dc13019259bd62d63b9295011227029283c2ef7 (commit) via 4734c3e6dbf5cdabcfedb449e92a61471f7664b7 (commit) via 934eb497f211b2e48ba070041ba775e1ac55d01d (commit) from e9e8a5dc084b470a50ab4a16008db30022068fb0 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- Summary of changes: .gitattributes | 24 ++++++++++--- Help/manual/cmake-language.7.rst | 6 ++++ Modules/FindCUDA/select_compute_arch.cmake | 1 + Source/.gitattributes | 31 +++++++++++------ Source/CursesDialog/form/.gitattributes | 1 + Source/cmVisualStudio10TargetGenerator.cxx | 1 + Tests/CompileFeatures/.gitattributes | 2 ++ Tests/PositionIndependentTargets/.gitattributes | 2 ++ .../CommandLine/cmake_depends/.gitattributes | 2 ++ .../GenerateExportHeader/reference/.gitattributes | 2 ++ Utilities/.gitattributes | 4 +++ Utilities/Scripts/clang-format.bash | 36 ++++---------------- 12 files changed, 68 insertions(+), 44 deletions(-) create mode 100644 Source/CursesDialog/form/.gitattributes create mode 100644 Tests/CompileFeatures/.gitattributes create mode 100644 Tests/PositionIndependentTargets/.gitattributes create mode 100644 Tests/RunCMake/CommandLine/cmake_depends/.gitattributes create mode 100644 Tests/RunCMake/GenerateExportHeader/reference/.gitattributes hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 24 10:26:50 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 24 Feb 2017 10:26:50 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-546-g813afd6 Message-ID: <20170224152650.EFAB0FA262@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 813afd66c2017ab3ef7385beb5d476ea16e0d0d0 (commit) via 666ad1df2dc5b181a40d831c125529fe7e9bf0b4 (commit) from 69d7feb40cd3bc891e6ad029921a26c7e8347547 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=813afd66c2017ab3ef7385beb5d476ea16e0d0d0 commit 813afd66c2017ab3ef7385beb5d476ea16e0d0d0 Merge: 69d7feb 666ad1d Author: Brad King AuthorDate: Fri Feb 24 10:26:50 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 24 10:26:50 2017 -0500 Merge topic 'ninja-no-full-path' into next 666ad1df Revert "Ninja: Use full path for all source files" diff --cc Source/cmNinjaTargetGenerator.cxx index f096416,5c85dfa..b1f26e4 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@@ -380,12 -373,11 +380,12 @@@ void cmNinjaTargetGenerator::WriteLangu void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) { - cmLocalGenerator::RuleVariables vars; - vars.RuleLauncher = "RULE_LAUNCH_COMPILE"; - vars.CMTarget = this->GetGeneratorTarget(); + cmRulePlaceholderExpander::RuleVariables vars; + vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str(); + vars.CMTargetType = + cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()); vars.Language = lang.c_str(); - vars.Source = "$IN_ABS"; + vars.Source = "$in"; vars.Object = "$out"; vars.Defines = "$DEFINES"; vars.Includes = "$INCLUDES"; https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=666ad1df2dc5b181a40d831c125529fe7e9bf0b4 commit 666ad1df2dc5b181a40d831c125529fe7e9bf0b4 Author: Brad King AuthorDate: Fri Feb 24 10:07:18 2017 -0500 Commit: Brad King CommitDate: Fri Feb 24 10:15:50 2017 -0500 Revert "Ninja: Use full path for all source files" This reverts commit v3.7.0-rc1~275^2 (Ninja: Use full path for all source files, 2016-08-05). Unfortunately using absolute paths can cause incorrect rebuilds due to ninja limitations. The ninja manual [1] explains: > ... using absolute paths, your depfile may result in a mixture of > relative and absolute paths. Paths used by other build rules need > to match exactly. Passing an absolute path to a source file to the compiler while using a relative path in the ninja build manifest can cause such mixture and lead to incorrect rebuilds. Simply revert the change for now. Note that there was a follow-up to the original change in commit v3.7.0-rc2~10^2 (Ninja: Fix RC language depfile generation with cmcldeps, 2016-10-13). We don't need to revert that because that change made the relevant code cleverly adapt to whatever variable we use to reference the source file. [1] https://ninja-build.org/manual.html#_deps Fixes: #16675 Issue: #13894 diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 46a6161..5c85dfa 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -377,7 +377,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) vars.RuleLauncher = "RULE_LAUNCH_COMPILE"; vars.CMTarget = this->GetGeneratorTarget(); vars.Language = lang.c_str(); - vars.Source = "$IN_ABS"; + vars.Source = "$in"; vars.Object = "$out"; vars.Defines = "$DEFINES"; vars.Includes = "$INCLUDES"; @@ -729,7 +729,8 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( cmSourceFile const* source, bool writeOrderDependsTargetForTarget) { std::string const language = source->GetLanguage(); - std::string const sourceFileName = this->GetSourceFilePath(source); + std::string const sourceFileName = + language == "RC" ? source->GetFullPath() : this->GetSourceFilePath(source); std::string const objectDir = this->ConvertToNinjaPath(this->GeneratorTarget->GetSupportDirectory()); std::string const objectFileName = @@ -738,8 +739,6 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( cmSystemTools::GetFilenamePath(objectFileName); cmNinjaVars vars; - vars["IN_ABS"] = this->GetLocalGenerator()->ConvertToOutputFormat( - source->GetFullPath(), cmOutputConverter::SHELL); vars["FLAGS"] = this->ComputeFlagsForObject(source, language); vars["DEFINES"] = this->ComputeDefines(source, language); vars["INCLUDES"] = this->GetIncludes(language); ----------------------------------------------------------------------- Summary of changes: Source/cmNinjaTargetGenerator.cxx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 24 11:04:21 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 24 Feb 2017 11:04:21 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-548-g6db5484 Message-ID: <20170224160421.DDD5DFA647@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 6db54841a2c989474985a959a46caf688a0bab4f (commit) via 3abffa5f64b06bd3ead0d6390adaf927665ae792 (commit) from 813afd66c2017ab3ef7385beb5d476ea16e0d0d0 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6db54841a2c989474985a959a46caf688a0bab4f commit 6db54841a2c989474985a959a46caf688a0bab4f Merge: 813afd6 3abffa5 Author: Brad King AuthorDate: Fri Feb 24 11:04:20 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 24 11:04:20 2017 -0500 Merge topic '16607-error-out-on-non-seekable-input-files' into next 3abffa5f cmListFileLexer: bail out on seek-errors https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3abffa5f64b06bd3ead0d6390adaf927665ae792 commit 3abffa5f64b06bd3ead0d6390adaf927665ae792 Author: Gregor Jasny AuthorDate: Sun Feb 19 18:26:44 2017 +0100 Commit: Brad King CommitDate: Fri Feb 24 11:03:07 2017 -0500 cmListFileLexer: bail out on seek-errors If we are given a FIFO, for example, we cannot seek back after trying to read a Byte-Order-Mark. Closes: #16607 diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index b1cd889..23b666e 100644 --- a/Source/cmListFileCache.cxx +++ b/Source/cmListFileCache.cxx @@ -80,6 +80,13 @@ bool cmListFileParser::ParseFile() return false; } + if (bom == cmListFileLexer_BOM_Broken) { + cmListFileLexer_SetFileName(this->Lexer, CM_NULLPTR, CM_NULLPTR); + this->IssueFileOpenError("Error while reading Byte-Order-Mark. " + "File not seekable?"); + return false; + } + // Verify the Byte-Order-Mark, if any. if (bom != cmListFileLexer_BOM_None && bom != cmListFileLexer_BOM_UTF8) { cmListFileLexer_SetFileName(this->Lexer, CM_NULLPTR, CM_NULLPTR); diff --git a/Source/cmListFileLexer.c b/Source/cmListFileLexer.c index 56559f6..44d0894 100644 --- a/Source/cmListFileLexer.c +++ b/Source/cmListFileLexer.c @@ -2559,11 +2559,15 @@ static cmListFileLexer_BOM cmListFileLexer_ReadBOM(FILE* f) if (fread(b, 1, 2, f) == 2 && b[0] == 0 && b[1] == 0) { return cmListFileLexer_BOM_UTF32LE; } - fsetpos(f, &p); + if (fsetpos(f, &p) != 0) { + return cmListFileLexer_BOM_Broken; + } return cmListFileLexer_BOM_UTF16LE; } } - rewind(f); + if (fseek(f, 0, SEEK_SET) != 0) { + return cmListFileLexer_BOM_Broken; + } return cmListFileLexer_BOM_None; } diff --git a/Source/cmListFileLexer.h b/Source/cmListFileLexer.h index c9fb6da..f243010a 100644 --- a/Source/cmListFileLexer.h +++ b/Source/cmListFileLexer.h @@ -32,6 +32,7 @@ struct cmListFileLexer_Token_s enum cmListFileLexer_BOM_e { cmListFileLexer_BOM_None, + cmListFileLexer_BOM_Broken, cmListFileLexer_BOM_UTF8, cmListFileLexer_BOM_UTF16BE, cmListFileLexer_BOM_UTF16LE, diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index 0c4f71c..bfee159 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -301,3 +301,12 @@ set(CMAKE_RELATIVE_PATH_TOP_BINARY \"${RunCMake_TEST_BINARY_DIR}\") ) endfunction() run_cmake_depends() + +function(reject_fifo) + find_program(BASH_EXECUTABLE bash) + if(CMAKE_HOST_UNIX AND BASH_EXECUTABLE) + set(BASH_COMMAND_ARGUMENT "${CMAKE_COMMAND} -P <(echo 'return()')") + run_cmake_command(reject_fifo ${BASH_EXECUTABLE} -c ${BASH_COMMAND_ARGUMENT}) + endif() +endfunction() +reject_fifo() diff --git a/Tests/RunCMake/CommandLine/reject_fifo-result.txt b/Tests/RunCMake/CommandLine/reject_fifo-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/reject_fifo-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/reject_fifo-stderr.txt b/Tests/RunCMake/CommandLine/reject_fifo-stderr.txt new file mode 100644 index 0000000..7a335c3 --- /dev/null +++ b/Tests/RunCMake/CommandLine/reject_fifo-stderr.txt @@ -0,0 +1,2 @@ +CMake Error in .* + Error while reading Byte-Order-Mark\. File not seekable\? ----------------------------------------------------------------------- Summary of changes: Source/cmListFileCache.cxx | 7 +++++++ Source/cmListFileLexer.c | 8 ++++++-- Source/cmListFileLexer.h | 1 + Tests/RunCMake/CommandLine/RunCMakeTest.cmake | 9 +++++++++ .../reject_fifo-result.txt} | 0 Tests/RunCMake/CommandLine/reject_fifo-stderr.txt | 2 ++ 6 files changed, 25 insertions(+), 2 deletions(-) copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => CommandLine/reject_fifo-result.txt} (100%) create mode 100644 Tests/RunCMake/CommandLine/reject_fifo-stderr.txt hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 24 11:13:34 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 24 Feb 2017 11:13:34 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-550-g3cc17be Message-ID: <20170224161334.449B5B218B@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 3cc17beb1eb141920e16afe1a0739765db33ec88 (commit) via cb3ab217e59108a13ef3b8da00e6fd0fd3a9c910 (commit) from 6db54841a2c989474985a959a46caf688a0bab4f (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3cc17beb1eb141920e16afe1a0739765db33ec88 commit 3cc17beb1eb141920e16afe1a0739765db33ec88 Merge: 6db5484 cb3ab21 Author: Brad King AuthorDate: Fri Feb 24 11:13:33 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 24 11:13:33 2017 -0500 Merge topic '16607-error-out-on-non-seekable-input-files' into next cb3ab217 fixup! cmListFileLexer: bail out on seek-errors https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=cb3ab217e59108a13ef3b8da00e6fd0fd3a9c910 commit cb3ab217e59108a13ef3b8da00e6fd0fd3a9c910 Author: Brad King AuthorDate: Fri Feb 24 11:13:13 2017 -0500 Commit: Brad King CommitDate: Fri Feb 24 11:13:13 2017 -0500 fixup! cmListFileLexer: bail out on seek-errors diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index bfee159..0c79856 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -305,7 +305,7 @@ run_cmake_depends() function(reject_fifo) find_program(BASH_EXECUTABLE bash) if(CMAKE_HOST_UNIX AND BASH_EXECUTABLE) - set(BASH_COMMAND_ARGUMENT "${CMAKE_COMMAND} -P <(echo 'return()')") + set(BASH_COMMAND_ARGUMENT "'${CMAKE_COMMAND}' -P <(echo 'return()')") run_cmake_command(reject_fifo ${BASH_EXECUTABLE} -c ${BASH_COMMAND_ARGUMENT}) endif() endfunction() ----------------------------------------------------------------------- Summary of changes: Tests/RunCMake/CommandLine/RunCMakeTest.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 24 11:13:46 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 24 Feb 2017 11:13:46 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-552-g0da16ec Message-ID: <20170224161346.35247B223F@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 0da16ecd007f3a444aefa6f70fe075ed09dbb795 (commit) via 988b1e9b3b974c3eddea1c4171989353a8c2f3ff (commit) from 3cc17beb1eb141920e16afe1a0739765db33ec88 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0da16ecd007f3a444aefa6f70fe075ed09dbb795 commit 0da16ecd007f3a444aefa6f70fe075ed09dbb795 Merge: 3cc17be 988b1e9 Author: Brad King AuthorDate: Fri Feb 24 11:13:45 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 24 11:13:45 2017 -0500 Merge topic '16607-error-out-on-non-seekable-input-files' into next 988b1e9b cmListFileLexer: bail out on seek-errors https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=988b1e9b3b974c3eddea1c4171989353a8c2f3ff commit 988b1e9b3b974c3eddea1c4171989353a8c2f3ff Author: Gregor Jasny AuthorDate: Sun Feb 19 18:26:44 2017 +0100 Commit: Brad King CommitDate: Fri Feb 24 11:13:37 2017 -0500 cmListFileLexer: bail out on seek-errors If we are given a FIFO, for example, we cannot seek back after trying to read a Byte-Order-Mark. Closes: #16607 diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index b1cd889..23b666e 100644 --- a/Source/cmListFileCache.cxx +++ b/Source/cmListFileCache.cxx @@ -80,6 +80,13 @@ bool cmListFileParser::ParseFile() return false; } + if (bom == cmListFileLexer_BOM_Broken) { + cmListFileLexer_SetFileName(this->Lexer, CM_NULLPTR, CM_NULLPTR); + this->IssueFileOpenError("Error while reading Byte-Order-Mark. " + "File not seekable?"); + return false; + } + // Verify the Byte-Order-Mark, if any. if (bom != cmListFileLexer_BOM_None && bom != cmListFileLexer_BOM_UTF8) { cmListFileLexer_SetFileName(this->Lexer, CM_NULLPTR, CM_NULLPTR); diff --git a/Source/cmListFileLexer.c b/Source/cmListFileLexer.c index 56559f6..44d0894 100644 --- a/Source/cmListFileLexer.c +++ b/Source/cmListFileLexer.c @@ -2559,11 +2559,15 @@ static cmListFileLexer_BOM cmListFileLexer_ReadBOM(FILE* f) if (fread(b, 1, 2, f) == 2 && b[0] == 0 && b[1] == 0) { return cmListFileLexer_BOM_UTF32LE; } - fsetpos(f, &p); + if (fsetpos(f, &p) != 0) { + return cmListFileLexer_BOM_Broken; + } return cmListFileLexer_BOM_UTF16LE; } } - rewind(f); + if (fseek(f, 0, SEEK_SET) != 0) { + return cmListFileLexer_BOM_Broken; + } return cmListFileLexer_BOM_None; } diff --git a/Source/cmListFileLexer.h b/Source/cmListFileLexer.h index c9fb6da..f243010a 100644 --- a/Source/cmListFileLexer.h +++ b/Source/cmListFileLexer.h @@ -32,6 +32,7 @@ struct cmListFileLexer_Token_s enum cmListFileLexer_BOM_e { cmListFileLexer_BOM_None, + cmListFileLexer_BOM_Broken, cmListFileLexer_BOM_UTF8, cmListFileLexer_BOM_UTF16BE, cmListFileLexer_BOM_UTF16LE, diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index 0c4f71c..0c79856 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -301,3 +301,12 @@ set(CMAKE_RELATIVE_PATH_TOP_BINARY \"${RunCMake_TEST_BINARY_DIR}\") ) endfunction() run_cmake_depends() + +function(reject_fifo) + find_program(BASH_EXECUTABLE bash) + if(CMAKE_HOST_UNIX AND BASH_EXECUTABLE) + set(BASH_COMMAND_ARGUMENT "'${CMAKE_COMMAND}' -P <(echo 'return()')") + run_cmake_command(reject_fifo ${BASH_EXECUTABLE} -c ${BASH_COMMAND_ARGUMENT}) + endif() +endfunction() +reject_fifo() diff --git a/Tests/RunCMake/CommandLine/reject_fifo-result.txt b/Tests/RunCMake/CommandLine/reject_fifo-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/reject_fifo-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/reject_fifo-stderr.txt b/Tests/RunCMake/CommandLine/reject_fifo-stderr.txt new file mode 100644 index 0000000..7a335c3 --- /dev/null +++ b/Tests/RunCMake/CommandLine/reject_fifo-stderr.txt @@ -0,0 +1,2 @@ +CMake Error in .* + Error while reading Byte-Order-Mark\. File not seekable\? ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 24 11:33:45 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 24 Feb 2017 11:33:45 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-554-g434c112 Message-ID: <20170224163345.E9138FA672@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 434c1123eb011a242e60279691df906e4a5244a7 (commit) via feff52d42ca18a52fd99e8fdfd3093c3a94eb498 (commit) from 0da16ecd007f3a444aefa6f70fe075ed09dbb795 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=434c1123eb011a242e60279691df906e4a5244a7 commit 434c1123eb011a242e60279691df906e4a5244a7 Merge: 0da16ec feff52d4 Author: Brad King AuthorDate: Fri Feb 24 11:33:44 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 24 11:33:44 2017 -0500 Merge topic 'object-library-compile-pdb' into next feff52d4 Fix COMPILE_PDB_NAME when used on an OBJECT library https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=feff52d42ca18a52fd99e8fdfd3093c3a94eb498 commit feff52d42ca18a52fd99e8fdfd3093c3a94eb498 Author: Brad King AuthorDate: Fri Feb 24 11:19:24 2017 -0500 Commit: Brad King CommitDate: Fri Feb 24 11:26:52 2017 -0500 Fix COMPILE_PDB_NAME when used on an OBJECT library When `COMPILE_PDB_NAME` is used without `COMPILE_PDB_OUTPUT_DIRECTORY` we cannot fall back on the link `PDB_OUTPUT_DIRECTORY` for an object library because it has no link step. Fixes: #16674 diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 6ce8140..3fe5c83 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -1147,7 +1147,7 @@ std::string cmGeneratorTarget::GetCompilePDBPath( { std::string dir = this->GetCompilePDBDirectory(config); std::string name = this->GetCompilePDBName(config); - if (dir.empty() && !name.empty()) { + if (dir.empty() && !name.empty() && this->HaveWellDefinedOutputFiles()) { dir = this->GetPDBDirectory(config); } if (!dir.empty()) { diff --git a/Tests/ObjectLibrary/A/CMakeLists.txt b/Tests/ObjectLibrary/A/CMakeLists.txt index 188fd64..c185d75 100644 --- a/Tests/ObjectLibrary/A/CMakeLists.txt +++ b/Tests/ObjectLibrary/A/CMakeLists.txt @@ -21,3 +21,4 @@ add_custom_command( add_library(A OBJECT a1.c a2.c a.cmake) target_include_directories(A PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +set_property(TARGET A PROPERTY COMPILE_PDB_NAME Apdb) ----------------------------------------------------------------------- Summary of changes: Source/cmGeneratorTarget.cxx | 2 +- Tests/ObjectLibrary/A/CMakeLists.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 24 13:22:59 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 24 Feb 2017 13:22:59 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-556-g617e34c Message-ID: <20170224182259.5966FF9FE5@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 617e34c8d5fed40eb5d1d99a4d1717c091c3ad2d (commit) via a9fa6a2c777bf68ac1c6d885fd07b21bf98e3f77 (commit) from 434c1123eb011a242e60279691df906e4a5244a7 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=617e34c8d5fed40eb5d1d99a4d1717c091c3ad2d commit 617e34c8d5fed40eb5d1d99a4d1717c091c3ad2d Merge: 434c112 a9fa6a2 Author: Brad King AuthorDate: Fri Feb 24 13:22:58 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 24 13:22:58 2017 -0500 Merge topic 'ExternalProject-checkout-clarify' into next a9fa6a2c ExternalProject: Run `git checkout` with `--` to clarify arguments https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a9fa6a2c777bf68ac1c6d885fd07b21bf98e3f77 commit a9fa6a2c777bf68ac1c6d885fd07b21bf98e3f77 Author: Brad King AuthorDate: Fri Feb 24 13:21:06 2017 -0500 Commit: Brad King CommitDate: Fri Feb 24 13:22:40 2017 -0500 ExternalProject: Run `git checkout` with `--` to clarify arguments Fix the case when the tag name to be checked out also happens to match a path name. Fixes: #16678 diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake index 458c114..95fbd53 100644 --- a/Modules/ExternalProject.cmake +++ b/Modules/ExternalProject.cmake @@ -594,7 +594,7 @@ if(error_code) endif() execute_process( - COMMAND \"${git_EXECUTABLE}\" \${git_options} checkout ${git_tag} + COMMAND \"${git_EXECUTABLE}\" \${git_options} checkout ${git_tag} -- WORKING_DIRECTORY \"${work_dir}/${src_name}\" RESULT_VARIABLE error_code ) ----------------------------------------------------------------------- Summary of changes: Modules/ExternalProject.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Fri Feb 24 13:33:55 2017 From: brad.king at kitware.com (Brad King) Date: Fri, 24 Feb 2017 13:33:55 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-558-gfa67829 Message-ID: <20170224183355.7F5C3FA661@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via fa678294b653cb39dda9e631e24aead5a308cb78 (commit) via 73ad60499b429f6e38de1a6b564300286c468477 (commit) from 617e34c8d5fed40eb5d1d99a4d1717c091c3ad2d (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=fa678294b653cb39dda9e631e24aead5a308cb78 commit fa678294b653cb39dda9e631e24aead5a308cb78 Merge: 617e34c 73ad604 Author: Brad King AuthorDate: Fri Feb 24 13:33:54 2017 -0500 Commit: CMake Topic Stage CommitDate: Fri Feb 24 13:33:54 2017 -0500 Merge topic 'autogen_json_fix' into next 73ad6049 Autogen: Fix for Q_PLUGIN_METADATA change detection test https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=73ad60499b429f6e38de1a6b564300286c468477 commit 73ad60499b429f6e38de1a6b564300286c468477 Author: Sebastian Holtermann AuthorDate: Fri Feb 24 18:27:41 2017 +0100 Commit: Sebastian Holtermann CommitDate: Fri Feb 24 19:24:39 2017 +0100 Autogen: Fix for Q_PLUGIN_METADATA change detection test diff --git a/Tests/QtAutogen/CMakeLists.txt b/Tests/QtAutogen/CMakeLists.txt index 257c187..dfecff7 100644 --- a/Tests/QtAutogen/CMakeLists.txt +++ b/Tests/QtAutogen/CMakeLists.txt @@ -233,10 +233,10 @@ if (NOT QT_TEST_VERSION STREQUAL 4) set(timeformat "%Y%j%H%M%S") set(mocPluginBinDir "${CMAKE_CURRENT_BINARY_DIR}/mocPlugin") - find_library(style_a_file "PluginStyleA" "${mocPluginBinDir}") - find_library(style_b_file "PluginStyleB" "${mocPluginBinDir}") - find_library(style_c_file "PluginStyleC" "${mocPluginBinDir}") - find_library(style_d_file "PluginStyleD" "${mocPluginBinDir}") + find_library(style_a_file "PluginStyleA" PATHS "${mocPluginBinDir}" NO_DEFAULT_PATH) + find_library(style_b_file "PluginStyleB" PATHS "${mocPluginBinDir}" NO_DEFAULT_PATH) + find_library(style_c_file "PluginStyleC" PATHS "${mocPluginBinDir}" NO_DEFAULT_PATH) + find_library(style_d_file "PluginStyleD" PATHS "${mocPluginBinDir}" NO_DEFAULT_PATH) file(TIMESTAMP "${style_a_file}" style_a_before "${timeformat}") file(TIMESTAMP "${style_b_file}" style_b_before "${timeformat}") ----------------------------------------------------------------------- Summary of changes: Tests/QtAutogen/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) hooks/post-receive -- CMake From kwrobot at kitware.com Sat Feb 25 00:01:06 2017 From: kwrobot at kitware.com (Kitware Robot) Date: Sat, 25 Feb 2017 00:01:06 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-298-g160ebe5 Message-ID: <20170225050106.C5462FA344@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 160ebe58b53d542f44f2aac6b69d4cf02ec40c15 (commit) from badc2c44d8d1c5367c54b2ae67aff84ecef178fe (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=160ebe58b53d542f44f2aac6b69d4cf02ec40c15 commit 160ebe58b53d542f44f2aac6b69d4cf02ec40c15 Author: Kitware Robot AuthorDate: Sat Feb 25 00:01:03 2017 -0500 Commit: Kitware Robot CommitDate: Sat Feb 25 00:01:03 2017 -0500 CMake Nightly Date Stamp diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 12dc033..87905c9 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 8) -set(CMake_VERSION_PATCH 20170224) +set(CMake_VERSION_PATCH 20170225) #set(CMake_VERSION_RC 1) ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From kwrobot at kitware.com Sun Feb 26 00:01:07 2017 From: kwrobot at kitware.com (Kitware Robot) Date: Sun, 26 Feb 2017 00:01:07 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-299-gda91515 Message-ID: <20170226050107.489BEFA27B@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via da915157b0ac1194e5290ca92695fc0afc073e1b (commit) from 160ebe58b53d542f44f2aac6b69d4cf02ec40c15 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=da915157b0ac1194e5290ca92695fc0afc073e1b commit da915157b0ac1194e5290ca92695fc0afc073e1b Author: Kitware Robot AuthorDate: Sun Feb 26 00:01:02 2017 -0500 Commit: Kitware Robot CommitDate: Sun Feb 26 00:01:02 2017 -0500 CMake Nightly Date Stamp diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 87905c9..d179a74 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 8) -set(CMake_VERSION_PATCH 20170225) +set(CMake_VERSION_PATCH 20170226) #set(CMake_VERSION_RC 1) ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Sun Feb 26 10:44:05 2017 From: brad.king at kitware.com (Brad King) Date: Sun, 26 Feb 2017 10:44:05 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-560-gada4028 Message-ID: <20170226154405.84371F9FB9@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via ada4028f25cbac073191b7e466b19281eebd9f29 (commit) via 53a2377962a50934e695abc8879e944dc27e0ff8 (commit) from fa678294b653cb39dda9e631e24aead5a308cb78 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ada4028f25cbac073191b7e466b19281eebd9f29 commit ada4028f25cbac073191b7e466b19281eebd9f29 Merge: fa67829 53a2377 Author: Brad King AuthorDate: Sun Feb 26 10:44:04 2017 -0500 Commit: CMake Topic Stage CommitDate: Sun Feb 26 10:44:04 2017 -0500 Merge topic '16607-error-out-on-non-seekable-input-files' into next 53a23779 fixup! cmListFileLexer: bail out on seek-errors https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=53a2377962a50934e695abc8879e944dc27e0ff8 commit 53a2377962a50934e695abc8879e944dc27e0ff8 Author: Brad King AuthorDate: Sun Feb 26 10:22:28 2017 -0500 Commit: Brad King CommitDate: Sun Feb 26 10:22:28 2017 -0500 fixup! cmListFileLexer: bail out on seek-errors diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index 0c79856..18d487e 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -304,9 +304,11 @@ run_cmake_depends() function(reject_fifo) find_program(BASH_EXECUTABLE bash) - if(CMAKE_HOST_UNIX AND BASH_EXECUTABLE) + if(BASH_EXECUTABLE) set(BASH_COMMAND_ARGUMENT "'${CMAKE_COMMAND}' -P <(echo 'return()')") run_cmake_command(reject_fifo ${BASH_EXECUTABLE} -c ${BASH_COMMAND_ARGUMENT}) endif() endfunction() -reject_fifo() +if(CMAKE_HOST_UNIX AND NOT CYGWIN) + reject_fifo() +endif() ----------------------------------------------------------------------- Summary of changes: Tests/RunCMake/CommandLine/RunCMakeTest.cmake | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Sun Feb 26 10:46:57 2017 From: brad.king at kitware.com (Brad King) Date: Sun, 26 Feb 2017 10:46:57 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-563-g4f36d88 Message-ID: <20170226154657.83DA4FA082@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 4f36d8840546f9722b223b72424d404a84eb95a5 (commit) via b35a949bb6ce6ae5204de2cf867dac903cb71262 (commit) via 01347954187ebccf83fc7540163f150a5f430c36 (commit) from ada4028f25cbac073191b7e466b19281eebd9f29 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4f36d8840546f9722b223b72424d404a84eb95a5 commit 4f36d8840546f9722b223b72424d404a84eb95a5 Merge: ada4028 b35a949 Author: Brad King AuthorDate: Sun Feb 26 10:46:56 2017 -0500 Commit: CMake Topic Stage CommitDate: Sun Feb 26 10:46:56 2017 -0500 Merge topic 'test-objlib-deps-cleanup' into next b35a949b Tests: Change RunCMake.ObjectLibrary dependencies case to C 01347954 Tests: Fix RunCMake.ObjectLibrary dependency delay https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b35a949bb6ce6ae5204de2cf867dac903cb71262 commit b35a949bb6ce6ae5204de2cf867dac903cb71262 Author: Brad King AuthorDate: Sun Feb 26 10:38:39 2017 -0500 Commit: Brad King CommitDate: Sun Feb 26 10:43:32 2017 -0500 Tests: Change RunCMake.ObjectLibrary dependencies case to C diff --git a/Tests/RunCMake/ObjectLibrary/Dependencies.cmake b/Tests/RunCMake/ObjectLibrary/Dependencies.cmake index 4e3db5f..6ddf545 100644 --- a/Tests/RunCMake/ObjectLibrary/Dependencies.cmake +++ b/Tests/RunCMake/ObjectLibrary/Dependencies.cmake @@ -1,10 +1,6 @@ -cmake_minimum_required(VERSION 3.7) - -project(Dependencies) - -add_library(myobj OBJECT ${CMAKE_BINARY_DIR}/depends_obj.cpp) -add_library(mylib STATIC $ depends_lib.cpp) -add_executable(myexe depends_main.cpp) +add_library(myobj OBJECT ${CMAKE_BINARY_DIR}/depends_obj.c) +add_library(mylib STATIC $ depends_lib.c) +add_executable(myexe depends_main.c) target_link_libraries(myexe mylib) enable_testing() diff --git a/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake index 0ac5b8c..e932693 100644 --- a/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake +++ b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake @@ -31,11 +31,11 @@ function(run_Dependencies) set(fs_delay 1.125) endif() - run_cmake_command(Dependencies-build ${CMAKE_COMMAND} -E copy ${RunCMake_SOURCE_DIR}/depends_obj1.cpp ${RunCMake_TEST_BINARY_DIR}/depends_obj.cpp) + run_cmake_command(Dependencies-build ${CMAKE_COMMAND} -E copy ${RunCMake_SOURCE_DIR}/depends_obj1.c ${RunCMake_TEST_BINARY_DIR}/depends_obj.c) run_cmake(Dependencies) run_cmake_command(Dependencies-build ${CMAKE_COMMAND} --build . --config Debug) run_cmake_command(Dependencies-build ${CMAKE_COMMAND} -E sleep ${fs_delay}) - run_cmake_command(Dependencies-build ${CMAKE_COMMAND} -E copy ${RunCMake_SOURCE_DIR}/depends_obj0.cpp ${RunCMake_TEST_BINARY_DIR}/depends_obj.cpp) + run_cmake_command(Dependencies-build ${CMAKE_COMMAND} -E copy ${RunCMake_SOURCE_DIR}/depends_obj0.c ${RunCMake_TEST_BINARY_DIR}/depends_obj.c) run_cmake_command(Dependencies-build ${CMAKE_COMMAND} --build . --config Debug) run_cmake_command(Dependencies-build ${CMAKE_CTEST_COMMAND} -C Debug -V) endfunction() diff --git a/Tests/RunCMake/ObjectLibrary/depends_lib.c b/Tests/RunCMake/ObjectLibrary/depends_lib.c new file mode 100644 index 0000000..a41b32c --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/depends_lib.c @@ -0,0 +1,7 @@ +#include +extern int myobj_foo(void); + +void mylib_foo(void) +{ + exit(myobj_foo()); +} diff --git a/Tests/RunCMake/ObjectLibrary/depends_lib.cpp b/Tests/RunCMake/ObjectLibrary/depends_lib.cpp deleted file mode 100644 index 540b536..0000000 --- a/Tests/RunCMake/ObjectLibrary/depends_lib.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include -int myobj_foo(); - -void mylib_foo() -{ - exit(myobj_foo()); -} diff --git a/Tests/RunCMake/ObjectLibrary/depends_main.c b/Tests/RunCMake/ObjectLibrary/depends_main.c new file mode 100644 index 0000000..acc66c7 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/depends_main.c @@ -0,0 +1,7 @@ +extern void mylib_foo(void); + +int main(void) +{ + mylib_foo(); + return 0; +} diff --git a/Tests/RunCMake/ObjectLibrary/depends_main.cpp b/Tests/RunCMake/ObjectLibrary/depends_main.cpp deleted file mode 100644 index a9d323d..0000000 --- a/Tests/RunCMake/ObjectLibrary/depends_main.cpp +++ /dev/null @@ -1,7 +0,0 @@ -void mylib_foo(); - -int main() -{ - mylib_foo(); - return 0; -} diff --git a/Tests/RunCMake/ObjectLibrary/depends_obj0.c b/Tests/RunCMake/ObjectLibrary/depends_obj0.c new file mode 100644 index 0000000..649d507 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/depends_obj0.c @@ -0,0 +1,4 @@ +int myobj_foo(void) +{ + return 0; +} diff --git a/Tests/RunCMake/ObjectLibrary/depends_obj0.cpp b/Tests/RunCMake/ObjectLibrary/depends_obj0.cpp deleted file mode 100644 index 73a17e7..0000000 --- a/Tests/RunCMake/ObjectLibrary/depends_obj0.cpp +++ /dev/null @@ -1,4 +0,0 @@ -int myobj_foo() -{ - return 0; -} diff --git a/Tests/RunCMake/ObjectLibrary/depends_obj1.c b/Tests/RunCMake/ObjectLibrary/depends_obj1.c new file mode 100644 index 0000000..e1f9f6a --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/depends_obj1.c @@ -0,0 +1,4 @@ +int myobj_foo(void) +{ + return 1; +} diff --git a/Tests/RunCMake/ObjectLibrary/depends_obj1.cpp b/Tests/RunCMake/ObjectLibrary/depends_obj1.cpp deleted file mode 100644 index f62ef70..0000000 --- a/Tests/RunCMake/ObjectLibrary/depends_obj1.cpp +++ /dev/null @@ -1,4 +0,0 @@ -int myobj_foo() -{ - return 1; -} https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=01347954187ebccf83fc7540163f150a5f430c36 commit 01347954187ebccf83fc7540163f150a5f430c36 Author: Brad King AuthorDate: Sun Feb 26 10:34:48 2017 -0500 Commit: Brad King CommitDate: Sun Feb 26 10:43:30 2017 -0500 Tests: Fix RunCMake.ObjectLibrary dependency delay Sleep before the second copy to avoid the need for a touch. Sleep for longer on generators whose build tools have low resolution timestamps. diff --git a/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake index 9291218..0ac5b8c 100644 --- a/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake +++ b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake @@ -24,14 +24,20 @@ function(run_Dependencies) file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + if(RunCMake_GENERATOR STREQUAL "Borland Makefiles" OR + RunCMake_GENERATOR STREQUAL "Watcom WMake") + set(fs_delay 3) + else() + set(fs_delay 1.125) + endif() + run_cmake_command(Dependencies-build ${CMAKE_COMMAND} -E copy ${RunCMake_SOURCE_DIR}/depends_obj1.cpp ${RunCMake_TEST_BINARY_DIR}/depends_obj.cpp) run_cmake(Dependencies) - run_cmake_command(Dependencies-build ${CMAKE_COMMAND} --build .) + run_cmake_command(Dependencies-build ${CMAKE_COMMAND} --build . --config Debug) + run_cmake_command(Dependencies-build ${CMAKE_COMMAND} -E sleep ${fs_delay}) run_cmake_command(Dependencies-build ${CMAKE_COMMAND} -E copy ${RunCMake_SOURCE_DIR}/depends_obj0.cpp ${RunCMake_TEST_BINARY_DIR}/depends_obj.cpp) - run_cmake_command(Dependencies-build ${CMAKE_COMMAND} -E sleep 1) - run_cmake_command(Dependencies-build ${CMAKE_COMMAND} -E touch_nocreate ${RunCMake_TEST_BINARY_DIR}/depends_obj.cpp) - run_cmake_command(Dependencies-build ${CMAKE_COMMAND} --build .) - run_cmake_command(Dependencies-build ${CMAKE_CTEST_COMMAND} -C Debug) + run_cmake_command(Dependencies-build ${CMAKE_COMMAND} --build . --config Debug) + run_cmake_command(Dependencies-build ${CMAKE_CTEST_COMMAND} -C Debug -V) endfunction() run_Dependencies() ----------------------------------------------------------------------- Summary of changes: Tests/RunCMake/ObjectLibrary/Dependencies.cmake | 10 +++------- Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake | 20 +++++++++++++------- Tests/RunCMake/ObjectLibrary/depends_lib.c | 7 +++++++ Tests/RunCMake/ObjectLibrary/depends_lib.cpp | 7 ------- Tests/RunCMake/ObjectLibrary/depends_main.c | 7 +++++++ Tests/RunCMake/ObjectLibrary/depends_main.cpp | 7 ------- Tests/RunCMake/ObjectLibrary/depends_obj0.c | 4 ++++ Tests/RunCMake/ObjectLibrary/depends_obj0.cpp | 4 ---- Tests/RunCMake/ObjectLibrary/depends_obj1.c | 4 ++++ Tests/RunCMake/ObjectLibrary/depends_obj1.cpp | 4 ---- 10 files changed, 38 insertions(+), 36 deletions(-) create mode 100644 Tests/RunCMake/ObjectLibrary/depends_lib.c delete mode 100644 Tests/RunCMake/ObjectLibrary/depends_lib.cpp create mode 100644 Tests/RunCMake/ObjectLibrary/depends_main.c delete mode 100644 Tests/RunCMake/ObjectLibrary/depends_main.cpp create mode 100644 Tests/RunCMake/ObjectLibrary/depends_obj0.c delete mode 100644 Tests/RunCMake/ObjectLibrary/depends_obj0.cpp create mode 100644 Tests/RunCMake/ObjectLibrary/depends_obj1.c delete mode 100644 Tests/RunCMake/ObjectLibrary/depends_obj1.cpp hooks/post-receive -- CMake From brad.king at kitware.com Sun Feb 26 10:49:02 2017 From: brad.king at kitware.com (Brad King) Date: Sun, 26 Feb 2017 10:49:02 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-568-g316aa77 Message-ID: <20170226154902.5659FFA0CD@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 316aa77eea2dff8e982257904344c46336673fce (commit) via 4f2650d5a96e0c1c6a29597bf891909681349b80 (commit) via c9b3c5625a4b35235bfe19e95db8e7d0dfbde59c (commit) via f06986926ae2ed76023956e6594711f9e65b4106 (commit) via 5651257fffc4482861c2ed6a67721fd00f0da6c0 (commit) from 4f36d8840546f9722b223b72424d404a84eb95a5 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=316aa77eea2dff8e982257904344c46336673fce commit 316aa77eea2dff8e982257904344c46336673fce Merge: 4f36d88 4f2650d Author: Brad King AuthorDate: Sun Feb 26 10:49:01 2017 -0500 Commit: CMake Topic Stage CommitDate: Sun Feb 26 10:49:01 2017 -0500 Merge topic 'libuv-solaris-10' into next 4f2650d5 Enable libuv on Solaris 10 c9b3c562 libuv: Link to 'rt' library on Solaris 10 to get semaphores f0698692 libuv: Implement mkdtemp on Solaris 10 5651257f libuv: automatically skip ifaddrs on Solaris 10 https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4f2650d5a96e0c1c6a29597bf891909681349b80 commit 4f2650d5a96e0c1c6a29597bf891909681349b80 Author: Brad King AuthorDate: Tue Feb 21 19:45:48 2017 -0500 Commit: Brad King CommitDate: Sun Feb 26 10:48:27 2017 -0500 Enable libuv on Solaris 10 We've ported our libuv to this platform so we can build it now. diff --git a/CMakeLists.txt b/CMakeLists.txt index e613224..472c6ab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -509,12 +509,6 @@ int main(void) { return 0; } elseif(CMAKE_SYSTEM_NAME STREQUAL "HP-UX") # Disable until it can be ported. set(CMAKE_USE_LIBUV 0) - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "sparc") - # Disable until it can be ported. - set(CMAKE_USE_LIBUV 0) - elseif(CMAKE_SYSTEM STREQUAL "SunOS-5.10") - # Disable until it can be ported. - set(CMAKE_USE_LIBUV 0) endif() endif() if(CMAKE_USE_LIBUV) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c9b3c5625a4b35235bfe19e95db8e7d0dfbde59c commit c9b3c5625a4b35235bfe19e95db8e7d0dfbde59c Author: Brad King AuthorDate: Tue Feb 21 19:45:14 2017 -0500 Commit: Brad King CommitDate: Sun Feb 26 10:48:26 2017 -0500 libuv: Link to 'rt' library on Solaris 10 to get semaphores diff --git a/Utilities/cmlibuv/CMakeLists.txt b/Utilities/cmlibuv/CMakeLists.txt index a8e25ba..1899f83 100644 --- a/Utilities/cmlibuv/CMakeLists.txt +++ b/Utilities/cmlibuv/CMakeLists.txt @@ -212,6 +212,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "SunOS") nsl sendfile socket + rt ) list(APPEND uv_headers include/uv-sunos.h https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f06986926ae2ed76023956e6594711f9e65b4106 commit f06986926ae2ed76023956e6594711f9e65b4106 Author: Brad King AuthorDate: Tue Feb 21 19:44:53 2017 -0500 Commit: Brad King CommitDate: Sun Feb 26 10:48:26 2017 -0500 libuv: Implement mkdtemp on Solaris 10 diff --git a/Utilities/cmlibuv/src/unix/fs.c b/Utilities/cmlibuv/src/unix/fs.c index f9513ea..8a4ba7a 100644 --- a/Utilities/cmlibuv/src/unix/fs.c +++ b/Utilities/cmlibuv/src/unix/fs.c @@ -244,9 +244,19 @@ skip: #endif } +#if defined(__sun) && _XOPEN_SOURCE < 600 +static char* uv__mkdtemp(char *template) +{ + if (!mktemp(template) || mkdir(template, 0700)) + return NULL; + return template; +} +#else +#define uv__mkdtemp mkdtemp +#endif static ssize_t uv__fs_mkdtemp(uv_fs_t* req) { - return mkdtemp((char*) req->path) ? 0 : -1; + return uv__mkdtemp((char*) req->path) ? 0 : -1; } https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=5651257fffc4482861c2ed6a67721fd00f0da6c0 commit 5651257fffc4482861c2ed6a67721fd00f0da6c0 Author: Brad King AuthorDate: Tue Feb 21 19:44:19 2017 -0500 Commit: Brad King CommitDate: Sun Feb 26 10:48:26 2017 -0500 libuv: automatically skip ifaddrs on Solaris 10 diff --git a/Utilities/cmlibuv/src/unix/sunos.c b/Utilities/cmlibuv/src/unix/sunos.c index a43f7f1..14c58af 100644 --- a/Utilities/cmlibuv/src/unix/sunos.c +++ b/Utilities/cmlibuv/src/unix/sunos.c @@ -28,6 +28,10 @@ #include #include +#if !defined(SUNOS_NO_IFADDRS) && _XOPEN_SOURCE < 600 +#define SUNOS_NO_IFADDRS +#endif + #ifndef SUNOS_NO_IFADDRS # include #endif ----------------------------------------------------------------------- Summary of changes: CMakeLists.txt | 6 ------ Utilities/cmlibuv/CMakeLists.txt | 1 + Utilities/cmlibuv/src/unix/fs.c | 12 +++++++++++- Utilities/cmlibuv/src/unix/sunos.c | 4 ++++ 4 files changed, 16 insertions(+), 7 deletions(-) hooks/post-receive -- CMake From kwrobot at kitware.com Mon Feb 27 00:01:05 2017 From: kwrobot at kitware.com (Kitware Robot) Date: Mon, 27 Feb 2017 00:01:05 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-300-gadcade6 Message-ID: <20170227050106.073F1F9D02@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via adcade6088a8bbe19002ac88f724d25ac95597c5 (commit) from da915157b0ac1194e5290ca92695fc0afc073e1b (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=adcade6088a8bbe19002ac88f724d25ac95597c5 commit adcade6088a8bbe19002ac88f724d25ac95597c5 Author: Kitware Robot AuthorDate: Mon Feb 27 00:01:03 2017 -0500 Commit: Kitware Robot CommitDate: Mon Feb 27 00:01:03 2017 -0500 CMake Nightly Date Stamp diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index d179a74..13bd07b 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 8) -set(CMake_VERSION_PATCH 20170226) +set(CMake_VERSION_PATCH 20170227) #set(CMake_VERSION_RC 1) ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 27 06:13:01 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 27 Feb 2017 06:13:01 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-570-gcb2ea66 Message-ID: <20170227111301.66424F3707@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via cb2ea6642dced14a1f0e0929ea8a9073cdf7f9b8 (commit) via 8fe228929fb69ce7d157e3f88ed9b33e145d6f3b (commit) from 316aa77eea2dff8e982257904344c46336673fce (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=cb2ea6642dced14a1f0e0929ea8a9073cdf7f9b8 commit cb2ea6642dced14a1f0e0929ea8a9073cdf7f9b8 Merge: 316aa77 8fe2289 Author: Brad King AuthorDate: Mon Feb 27 06:13:00 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 27 06:13:00 2017 -0500 Merge topic '16607-error-out-on-non-seekable-input-files' into next 8fe22892 fixup! cmListFileLexer: bail out on seek-errors https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8fe228929fb69ce7d157e3f88ed9b33e145d6f3b commit 8fe228929fb69ce7d157e3f88ed9b33e145d6f3b Author: Brad King AuthorDate: Mon Feb 27 06:09:49 2017 -0500 Commit: Brad King CommitDate: Mon Feb 27 06:09:49 2017 -0500 fixup! cmListFileLexer: bail out on seek-errors diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index bd92013..6423bfd 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -290,7 +290,7 @@ add_RunCMake_test(target_link_libraries) add_RunCMake_test(target_compile_features) add_RunCMake_test(CheckModules) -add_RunCMake_test(CommandLine) +add_RunCMake_test(CommandLine -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}) add_RunCMake_test(CommandLineTar) add_RunCMake_test(install) diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index 18d487e..b213ee2 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -1,3 +1,5 @@ +cmake_minimum_required(VERSION 3.1) + include(RunCMake) run_cmake_command(NoArgs ${CMAKE_COMMAND}) @@ -309,6 +311,6 @@ function(reject_fifo) run_cmake_command(reject_fifo ${BASH_EXECUTABLE} -c ${BASH_COMMAND_ARGUMENT}) endif() endfunction() -if(CMAKE_HOST_UNIX AND NOT CYGWIN) +if(CMAKE_HOST_UNIX AND NOT CMAKE_SYSTEM_NAME STREQUAL "CYGWIN") reject_fifo() endif() ----------------------------------------------------------------------- Summary of changes: Tests/RunCMake/CMakeLists.txt | 2 +- Tests/RunCMake/CommandLine/RunCMakeTest.cmake | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 27 09:03:51 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 27 Feb 2017 09:03:51 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-578-g013e7ec Message-ID: <20170227140351.4C399FA6E8@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 013e7ec9100fe5fd850a4c4f89d34359d12f6dd9 (commit) via 29528cc33e929b3c034b1491842ddaf91b3855cf (commit) via 62d0e22325d36e5f9d61ccfbef0d68cfe1935f1b (commit) via 059aa805c9c0cb34c92eb69abf66febc40ab62db (commit) via 5fee76606b7a1f252e75e95c3d8303777459938d (commit) via adcade6088a8bbe19002ac88f724d25ac95597c5 (commit) via da915157b0ac1194e5290ca92695fc0afc073e1b (commit) via 160ebe58b53d542f44f2aac6b69d4cf02ec40c15 (commit) from cb2ea6642dced14a1f0e0929ea8a9073cdf7f9b8 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=013e7ec9100fe5fd850a4c4f89d34359d12f6dd9 commit 013e7ec9100fe5fd850a4c4f89d34359d12f6dd9 Merge: cb2ea66 29528cc Author: Brad King AuthorDate: Mon Feb 27 09:03:49 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 27 09:03:49 2017 -0500 Merge topic 'update-libarchive' into next 29528cc3 libarchive: Remove liblzma from introspection tests 62d0e223 Merge branch 'upstream-LibArchive' into update-libarchive 059aa805 LibArchive 2017-02-25 (d6b1bb9f) 5fee7660 libarchive: Update script to get 3.3.1 adcade60 CMake Nightly Date Stamp da915157 CMake Nightly Date Stamp 160ebe58 CMake Nightly Date Stamp https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=29528cc33e929b3c034b1491842ddaf91b3855cf commit 29528cc33e929b3c034b1491842ddaf91b3855cf Author: Brad King AuthorDate: Mon Feb 27 08:53:08 2017 -0500 Commit: Brad King CommitDate: Mon Feb 27 08:53:08 2017 -0500 libarchive: Remove liblzma from introspection tests This was added upstream but does not make sense in CMake because we may replace the library with a logical target name that will not work inside a `try_compile`. diff --git a/Utilities/cmlibarchive/CMakeLists.txt b/Utilities/cmlibarchive/CMakeLists.txt index f4a34ab..bfe6b13 100644 --- a/Utilities/cmlibarchive/CMakeLists.txt +++ b/Utilities/cmlibarchive/CMakeLists.txt @@ -295,8 +295,6 @@ ENDIF() IF(LIBLZMA_FOUND) SET(HAVE_LIBLZMA 1) SET(HAVE_LZMA_H 1) - SET(CMAKE_REQUIRED_INCLUDES ${LIBLZMA_INCLUDE_DIR}) - SET(CMAKE_REQUIRED_LIBRARIES ${LIBLZMA_LIBRARIES}) INCLUDE_DIRECTORIES(${LIBLZMA_INCLUDE_DIRS}) LIST(APPEND ADDITIONAL_LIBS ${LIBLZMA_LIBRARIES}) IF(CMAKE_USE_SYSTEM_LIBLZMA) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=62d0e22325d36e5f9d61ccfbef0d68cfe1935f1b commit 62d0e22325d36e5f9d61ccfbef0d68cfe1935f1b Merge: 5fee766 059aa80 Author: Brad King AuthorDate: Mon Feb 27 08:51:36 2017 -0500 Commit: Brad King CommitDate: Mon Feb 27 08:51:36 2017 -0500 Merge branch 'upstream-LibArchive' into update-libarchive * upstream-LibArchive: LibArchive 2017-02-25 (d6b1bb9f) diff --cc Utilities/cmlibarchive/CMakeLists.txt index 56811b6,0000000..f4a34ab mode 100644,000000..100644 --- a/Utilities/cmlibarchive/CMakeLists.txt +++ b/Utilities/cmlibarchive/CMakeLists.txt @@@ -1,1447 -1,0 +1,1454 @@@ +PROJECT(libarchive C) +# +SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/build/cmake") +if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${libarchive_BINARY_DIR}/bin) +endif() + +# On MacOS, prefer MacPorts libraries to system libraries. +# I haven't come up with a compelling argument for this to be conditional. +list(APPEND CMAKE_PREFIX_PATH /opt/local) +# Enable @rpath in the install name. +# detail in "cmake --help-policy CMP0042" +SET(CMAKE_MACOSX_RPATH ON) + +# +# Version - read from 'version' file. +# +FILE(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/build/version _version) +STRING(REGEX REPLACE - "^([0-9])[0-9][0-9][0-9][0-9][0-9][0-9][a-z]?$" "\\1" _major ${_version}) ++ "^([0-9])[0-9][0-9][0-9][0-9][0-9][0-9][a-z]*$" "\\1" _major ${_version}) +STRING(REGEX REPLACE - "^[0-9]([0-9][0-9][0-9])[0-9][0-9][0-9][a-z]?$" "\\1" _minor ${_version}) ++ "^[0-9]([0-9][0-9][0-9])[0-9][0-9][0-9][a-z]*$" "\\1" _minor ${_version}) +STRING(REGEX REPLACE - "^[0-9][0-9][0-9][0-9]([0-9][0-9][0-9])[a-z]?$" "\\1" _revision ${_version}) ++ "^[0-9][0-9][0-9][0-9]([0-9][0-9][0-9])[a-z]*$" "\\1" _revision ${_version}) +STRING(REGEX REPLACE - "^[0-9][0-9][0-9][0-9][0-9][0-9][0-9]([a-z]?)$" "\\1" _quality ${_version}) ++ "^[0-9][0-9][0-9][0-9][0-9][0-9][0-9]([a-z]*)$" "\\1" _quality ${_version}) +SET(_version_number ${_major}${_minor}${_revision}) +STRING(REGEX REPLACE "[0]*([^0]*[0-9])$" "\\1" _trimmed_minor ${_minor}) +STRING(REGEX REPLACE "[0]*([^0]*[0-9])$" "\\1" _trimmed_revision ${_revision}) +# +SET(VERSION "${_major}.${_trimmed_minor}.${_trimmed_revision}${_quality}") +SET(BSDCPIO_VERSION_STRING "${VERSION}") +SET(BSDTAR_VERSION_STRING "${VERSION}") +SET(BSDCAT_VERSION_STRING "${VERSION}") +SET(LIBARCHIVE_VERSION_NUMBER "${_version_number}") +SET(LIBARCHIVE_VERSION_STRING "${VERSION}") + +# INTERFACE_VERSION increments with every release +# libarchive 2.7 == interface version 9 = 2 + 7 +# libarchive 2.8 == interface version 10 = 2 + 8 +# libarchive 2.9 == interface version 11 = 2 + 9 +# libarchive 3.0 == interface version 12 +# libarchive 3.1 == interface version 13 +math(EXPR INTERFACE_VERSION "13 + ${_minor}") + +# Set SOVERSION == Interface version +# ?? Should there be more here ?? +SET(SOVERSION "${INTERFACE_VERSION}") + +# Enalbe CMAKE_PUSH_CHECK_STATE() and CMAKE_POP_CHECK_STATE() macros +# saving and restoring the state of the variables. +INCLUDE(${CMake_SOURCE_DIR}/Modules/CMakePushCheckState.cmake) + +# Initialize the state of the variables. This initialization is not +# necessary but this shows you what value the variables initially have. +SET(CMAKE_REQUIRED_DEFINITIONS) +SET(CMAKE_REQUIRED_INCLUDES) +SET(CMAKE_REQUIRED_LIBRARIES) +SET(CMAKE_REQUIRED_FLAGS) + +# Disable warnings to avoid changing 3rd party code. +IF(CMAKE_C_COMPILER_ID MATCHES + "^(GNU|Clang|AppleClang|XL|VisualAge|SunPro|MIPSpro|HP|Intel)$") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w") +ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "PathScale") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall") +ENDIF() + +# Enable CTest/CDash support +include(CTest) + +OPTION(ENABLE_NETTLE "Enable use of Nettle" ON) +OPTION(ENABLE_OPENSSL "Enable use of OpenSSL" ON) +OPTION(ENABLE_LZO "Enable the use of the system LZO library if found" OFF) +OPTION(ENABLE_LZMA "Enable the use of the system LZMA library if found" ON) + +OPTION(ENABLE_ZLIB "Enable the use of the system ZLIB library if found" ON) +OPTION(ENABLE_BZip2 "Enable the use of the system BZip2 library if found" ON) +OPTION(ENABLE_LIBXML2 "Enable the use of the system libxml2 library if found" ON) +OPTION(ENABLE_EXPAT "Enable the use of the system EXPAT library if found" ON) +OPTION(ENABLE_PCREPOSIX "Enable the use of the system PCREPOSIX library if found" ON) +OPTION(ENABLE_LibGCC "Enable the use of the system LibGCC library if found" ON) +# CNG is used for encrypt/decrypt Zip archives on Windows. +OPTION(ENABLE_CNG "Enable the use of CNG(Crypto Next Generation)" ON) + +OPTION(ENABLE_XATTR "Enable extended attribute support" ON) +OPTION(ENABLE_ACL "Enable ACL support" ON) +OPTION(ENABLE_ICONV "Enable iconv support" ON) + +IF(WIN32) + #ELSEIF(WINDOWS_VERSION STREQUAL "WINXP") + SET(NTDDI_VERSION 0x05010000) + SET(_WIN32_WINNT 0x0501) + SET(WINVER 0x0501) +ENDIF(WIN32) + +set(HAVE_PTHREAD_H 0) # no threads in CMake + +IF("${CMAKE_C_PLATFORM_ID}" MATCHES "^(HP-UX)$") + ADD_DEFINITIONS(-D_XOPEN_SOURCE=500) # Ask wchar.h for mbstate_t +ENDIF() + +# +INCLUDE(CheckCSourceCompiles) +INCLUDE(CheckCSourceRuns) +INCLUDE(CheckFileOffsetBits) +INCLUDE(CheckFuncs) +INCLUDE(CheckHeaderDirent) +INCLUDE(CheckIncludeFile) +INCLUDE(CheckIncludeFiles) +INCLUDE(CheckLibraryExists) +INCLUDE(CheckStructHasMember) +INCLUDE(CheckSymbolExists) +INCLUDE(CheckTypeExists) +INCLUDE(CheckTypeSize) + +# +# Generate list.h +# +MACRO (GENERATE_LIST_H _listfile _cmlist __list_sources) + SET(_argv ${ARGV}) + # Remove _listfile and _cmlist from _argv + LIST(REMOVE_AT _argv 0 1) + IF (NOT EXISTS "${_listfile}" OR + ${_cmlist} IS_NEWER_THAN "${_listfile}") + + MESSAGE(STATUS "Generating ${_listfile}") + FILE(WRITE ${_listfile} "") + FOREACH (testfile ${_argv}) + IF (testfile MATCHES "^test_[^/]+[.]c$") + FILE(STRINGS ${testfile} testvar REGEX "^DEFINE_TEST") + FOREACH (deftest ${testvar}) + FILE(APPEND ${_listfile} "${deftest}\n") + ENDFOREACH (deftest) + ENDIF (testfile MATCHES "^test_[^/]+[.]c$") + ENDFOREACH (testfile) + + ENDIF (NOT EXISTS "${_listfile}" OR + ${_cmlist} IS_NEWER_THAN "${_listfile}") +ENDMACRO (GENERATE_LIST_H) +# +# Generate installation rules for man pages. +# +MACRO (INSTALL_MAN __mans) + FOREACH (_man ${ARGV}) + STRING(REGEX REPLACE "^.+[.]([1-9])" "\\1" _mansect ${_man}) + INSTALL(FILES ${_man} DESTINATION "share/man/man${_mansect}") + ENDFOREACH (_man) +ENDMACRO (INSTALL_MAN __mans) +# +# Find out what macro is needed to use libraries on Windows. +# +MACRO (TRY_MACRO_FOR_LIBRARY INCLUDES LIBRARIES + TRY_TYPE SAMPLE_SOURCE MACRO_LIST) + IF(WIN32 AND NOT CYGWIN) + CMAKE_PUSH_CHECK_STATE() # Save the state of the variables + SET(CMAKE_REQUIRED_INCLUDES ${INCLUDES}) + SET(CMAKE_REQUIRED_LIBRARIES ${LIBRARIES}) + FOREACH(VAR ${MACRO_LIST}) + # Clear ${VAR} from CACHE If the libraries which ${VAR} was + # checked with are changed. + SET(VAR_WITH_LIB "${VAR}_WITH_LIB") + GET_PROPERTY(PREV_VAR_WITH_LIB VARIABLE PROPERTY ${VAR_WITH_LIB}) + IF(NOT "${PREV_VAR_WITH_LIB}" STREQUAL "${LIBRARIES}") + UNSET(${VAR} CACHE) + ENDIF(NOT "${PREV_VAR_WITH_LIB}" STREQUAL "${LIBRARIES}") + # Check if the library can be used with the macro. + IF("${TRY_TYPE}" MATCHES "COMPILES") + CHECK_C_SOURCE_COMPILES("${SAMPLE_SOURCE}" ${VAR}) + ELSEIF("${TRY_TYPE}" MATCHES "RUNS") + CHECK_C_SOURCE_RUNS("${SAMPLE_SOURCE}" ${VAR}) + ELSE("${TRY_TYPE}" MATCHES "COMPILES") + MESSAGE(FATAL_ERROR "UNKNOWN KEYWORD \"${TRY_TYPE}\" FOR TRY_TYPE") + ENDIF("${TRY_TYPE}" MATCHES "COMPILES") + # Save the libraries which ${VAR} is checked with. + SET(${VAR_WITH_LIB} "${LIBRARIES}" CACHE INTERNAL + "Macro ${VAR} is checked with") + ENDFOREACH(VAR) + CMAKE_POP_CHECK_STATE() # Restore the state of the variables + ENDIF(WIN32 AND NOT CYGWIN) +ENDMACRO (TRY_MACRO_FOR_LIBRARY) +# +# Check compress/decompress libraries +# +IF(WIN32 AND NOT CMAKE_CL_64 AND NOT CYGWIN) + # GnuWin32 is only for Win32, not Win64. + SET(__GNUWIN32PATH "C:/Program Files/GnuWin32") +ENDIF(WIN32 AND NOT CMAKE_CL_64 AND NOT CYGWIN) +IF(DEFINED __GNUWIN32PATH AND EXISTS "${__GNUWIN32PATH}") + # You have to add a path availabel DLL file into PATH environment variable. + # Maybe DLL path is "C:/Program Files/GnuWin32/bin". + # The zlib and the bzip2 Setup program have installed programs and DLLs into + # "C:/Program Files/GnuWin32" by default. + # This is convenience setting for Windows. + SET(CMAKE_PREFIX_PATH ${__GNUWIN32PATH} $(CMAKE_PREFIX_PATH)) + # + # If you didn't use Setup program or installed into nonstandard path, + # cmake cannot find out your zlib or bzip2 libraries and include files, + # you should execute cmake with -DCMAKE_PREFIX_PATH option. + # e.g. + # cmake -DCMAKE_PREFIX_PATH= + # + # If compiling error occurred in zconf.h, You may need patch to zconf.h. + #--- zconf.h.orig 2005-07-21 00:40:26.000000000 + #+++ zconf.h 2009-01-19 11:39:10.093750000 + #@@ -286,7 +286,7 @@ + # + # #if 1 /* HAVE_UNISTD_H -- this line is updated by ./configure */ + # # include /* for off_t */ + #-# include /* for SEEK_* and off_t */ + #+# include /* for SEEK_* and off_t */ + # # ifdef VMS + # # include /* for off_t */ + # # endif +ENDIF(DEFINED __GNUWIN32PATH AND EXISTS "${__GNUWIN32PATH}") + +SET(ADDITIONAL_LIBS "") +# +# Find ZLIB +# +IF(ENABLE_ZLIB) + FIND_PACKAGE(ZLIB) +ELSE() + SET(ZLIB_FOUND FALSE) # Override cached value +ENDIF() +IF(ZLIB_FOUND) + SET(HAVE_LIBZ 1) + SET(HAVE_ZLIB_H 1) + INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR}) + LIST(APPEND ADDITIONAL_LIBS ${ZLIB_LIBRARIES}) + IF(WIN32 AND NOT CYGWIN) + # + # Test if ZLIB_WINAPI macro is needed to use. + # + TRY_MACRO_FOR_LIBRARY( + "${ZLIB_INCLUDE_DIR}" "${ZLIB_LIBRARIES}" + RUNS + "#include \nint main() {uLong f = zlibCompileFlags(); return (f&(1U<<10))?0:-1; }" + ZLIB_WINAPI) + IF(ZLIB_WINAPI) + ADD_DEFINITIONS(-DZLIB_WINAPI) + ELSE(ZLIB_WINAPI) + # Test if a macro is needed for the library. + TRY_MACRO_FOR_LIBRARY( + "${ZLIB_INCLUDE_DIR}" "${ZLIB_LIBRARIES}" + COMPILES + "#include \nint main() {return zlibVersion()?1:0; }" + "ZLIB_DLL;WITHOUT_ZLIB_DLL") + IF(ZLIB_DLL) + ADD_DEFINITIONS(-DZLIB_DLL) + ENDIF(ZLIB_DLL) + ENDIF(ZLIB_WINAPI) + ENDIF(WIN32 AND NOT CYGWIN) +ELSE(ZLIB_FOUND) + MESSAGE(FATAL_ERROR "CMake requires zlib to be available to libarchive") +ENDIF(ZLIB_FOUND) +# +# Find BZip2 +# +IF(ENABLE_BZip2) + FIND_PACKAGE(BZip2) +ELSE() + SET(BZIP2_FOUND FALSE) # Override cached value +ENDIF() +IF(BZIP2_FOUND) + SET(HAVE_LIBBZ2 1) + SET(HAVE_BZLIB_H 1) + INCLUDE_DIRECTORIES(${BZIP2_INCLUDE_DIR}) + LIST(APPEND ADDITIONAL_LIBS ${BZIP2_LIBRARIES}) + # Test if a macro is needed for the library. + TRY_MACRO_FOR_LIBRARY( + "${BZIP2_INCLUDE_DIR}" "${BZIP2_LIBRARIES}" + COMPILES + "#include \nint main() {return BZ2_bzlibVersion()?1:0; }" + "USE_BZIP2_DLL;USE_BZIP2_STATIC") + IF(USE_BZIP2_DLL) + ADD_DEFINITIONS(-DUSE_BZIP2_DLL) + ELSEIF(USE_BZIP2_STATIC) + ADD_DEFINITIONS(-DUSE_BZIP2_STATIC) + ENDIF(USE_BZIP2_DLL) +ENDIF(BZIP2_FOUND) +MARK_AS_ADVANCED(CLEAR BZIP2_INCLUDE_DIR) +MARK_AS_ADVANCED(CLEAR BZIP2_LIBRARIES) + + +# +# Find LZMA +# +IF(ENABLE_LZMA) + FIND_PACKAGE(LibLZMA) +ELSE() + SET(LIBZMA_FOUND FALSE) # Override cached value +ENDIF() + +IF(LIBLZMA_FOUND) + SET(HAVE_LIBLZMA 1) + SET(HAVE_LZMA_H 1) ++ SET(CMAKE_REQUIRED_INCLUDES ${LIBLZMA_INCLUDE_DIR}) ++ SET(CMAKE_REQUIRED_LIBRARIES ${LIBLZMA_LIBRARIES}) + INCLUDE_DIRECTORIES(${LIBLZMA_INCLUDE_DIRS}) + LIST(APPEND ADDITIONAL_LIBS ${LIBLZMA_LIBRARIES}) + IF(CMAKE_USE_SYSTEM_LIBLZMA) + # Test if a macro is needed for the library. + TRY_MACRO_FOR_LIBRARY( + "${LIBLZMA_INCLUDE_DIRS}" "${LIBLZMA_LIBRARIES}" + COMPILES + "#include \nint main() {return (int)lzma_version_number(); }" + "WITHOUT_LZMA_API_STATIC;LZMA_API_STATIC") + IF(NOT WITHOUT_LZMA_API_STATIC AND LZMA_API_STATIC) + ADD_DEFINITIONS(-DLZMA_API_STATIC) + ENDIF(NOT WITHOUT_LZMA_API_STATIC AND LZMA_API_STATIC) + ELSE() + ADD_DEFINITIONS(-DLZMA_API_STATIC) + ENDIF() +ELSE(LIBLZMA_FOUND) +# LZMA not found and will not be used. +ENDIF(LIBLZMA_FOUND) +IF(0) # CMake does not need LZO2 support in libarchive +# +# Find LZO2 +# +IF(ENABLE_LZO) + IF (LZO2_INCLUDE_DIR) + # Already in cache, be silent + SET(LZO2_FIND_QUIETLY TRUE) + ENDIF (LZO2_INCLUDE_DIR) + + FIND_PATH(LZO2_INCLUDE_DIR lzo/lzoconf.h) + FIND_LIBRARY(LZO2_LIBRARY NAMES lzo2 liblzo2) + INCLUDE(FindPackageHandleStandardArgs) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZO2 DEFAULT_MSG LZO2_LIBRARY LZO2_INCLUDE_DIR) +ELSE(ENABLE_LZO) + SET(LIBZMA_FOUND FALSE) # Override cached value +ENDIF(ENABLE_LZO) +IF(LZO2_FOUND) + SET(HAVE_LIBLZO2 1) + SET(HAVE_LZO_LZOCONF_H 1) + SET(HAVE_LZO_LZO1X_H 1) + INCLUDE_DIRECTORIES(${LZO2_INCLUDE_DIR}) + LIST(APPEND ADDITIONAL_LIBS ${LZO2_LIBRARY}) + # + # TODO: test for static library. + # +ENDIF(LZO2_FOUND) +MARK_AS_ADVANCED(CLEAR LZO2_INCLUDE_DIR) +MARK_AS_ADVANCED(CLEAR LZO2_LIBRARY) +ENDIF() +IF(0) # CMake does not need LZ4 support in libarchive +# +# Find LZ4 +# +IF (LZ4_INCLUDE_DIR) + # Already in cache, be silent + SET(LZ4_FIND_QUIETLY TRUE) +ENDIF (LZ4_INCLUDE_DIR) + +FIND_PATH(LZ4_INCLUDE_DIR lz4.h) +FIND_LIBRARY(LZ4_LIBRARY NAMES lz4 liblz4) +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LZ4 DEFAULT_MSG LZ4_LIBRARY LZ4_INCLUDE_DIR) +IF(LZ4_FOUND) + SET(HAVE_LIBLZ4 1) + SET(HAVE_LZ4_H 1) + CMAKE_PUSH_CHECK_STATE() # Save the state of the variables + SET(CMAKE_REQUIRED_INCLUDES ${LZ4_INCLUDE_DIR}) + CHECK_INCLUDE_FILES("lz4hc.h" HAVE_LZ4HC_H) + CMAKE_POP_CHECK_STATE() # Restore the state of the variables + INCLUDE_DIRECTORIES(${LZ4_INCLUDE_DIR}) + LIST(APPEND ADDITIONAL_LIBS ${LZ4_LIBRARY}) + # + # TODO: test for static library. + # +ENDIF(LZ4_FOUND) +MARK_AS_ADVANCED(CLEAR LZ4_INCLUDE_DIR) +MARK_AS_ADVANCED(CLEAR LZ4_LIBRARY) +ENDIF() + +# +# Check headers +# +CHECK_HEADER_DIRENT() + +SET(INCLUDES "") +MACRO (LA_CHECK_INCLUDE_FILE header var) + CHECK_INCLUDE_FILES("${INCLUDES};${header}" ${var}) + IF (${var}) + SET(INCLUDES ${INCLUDES} ${header}) + ENDIF (${var}) +ENDMACRO (LA_CHECK_INCLUDE_FILE) + +# Some FreeBSD headers assume sys/types.h was already included. +LA_CHECK_INCLUDE_FILE("sys/types.h" HAVE_SYS_TYPES_H) + +# Alphabetize the rest unless there's a compelling reason +IF(ENABLE_ACL) + LA_CHECK_INCLUDE_FILE("acl/libacl.h" HAVE_ACL_LIBACL_H) +ELSE(ENABLE_ACL) + SET(HAVE_ACL_LIBACL_H FALSE) +ENDIF(ENABLE_ACL) +LA_CHECK_INCLUDE_FILE("ctype.h" HAVE_CTYPE_H) +LA_CHECK_INCLUDE_FILE("copyfile.h" HAVE_COPYFILE_H) +LA_CHECK_INCLUDE_FILE("direct.h" HAVE_DIRECT_H) +LA_CHECK_INCLUDE_FILE("dlfcn.h" HAVE_DLFCN_H) +LA_CHECK_INCLUDE_FILE("errno.h" HAVE_ERRNO_H) +LA_CHECK_INCLUDE_FILE("ext2fs/ext2_fs.h" HAVE_EXT2FS_EXT2_FS_H) + +CHECK_C_SOURCE_COMPILES("#include +#include +int main(void) { return EXT2_IOC_GETFLAGS; }" HAVE_WORKING_EXT2_IOC_GETFLAGS) + +LA_CHECK_INCLUDE_FILE("fcntl.h" HAVE_FCNTL_H) +LA_CHECK_INCLUDE_FILE("grp.h" HAVE_GRP_H) +LA_CHECK_INCLUDE_FILE("inttypes.h" HAVE_INTTYPES_H) +LA_CHECK_INCLUDE_FILE("io.h" HAVE_IO_H) +LA_CHECK_INCLUDE_FILE("langinfo.h" HAVE_LANGINFO_H) +LA_CHECK_INCLUDE_FILE("limits.h" HAVE_LIMITS_H) +LA_CHECK_INCLUDE_FILE("linux/types.h" HAVE_LINUX_TYPES_H) +LA_CHECK_INCLUDE_FILE("linux/fiemap.h" HAVE_LINUX_FIEMAP_H) +LA_CHECK_INCLUDE_FILE("linux/fs.h" HAVE_LINUX_FS_H) ++ ++CHECK_C_SOURCE_COMPILES("#include ++#include ++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("memory.h" HAVE_MEMORY_H) +LA_CHECK_INCLUDE_FILE("paths.h" HAVE_PATHS_H) +LA_CHECK_INCLUDE_FILE("poll.h" HAVE_POLL_H) +LA_CHECK_INCLUDE_FILE("process.h" HAVE_PROCESS_H) +LA_CHECK_INCLUDE_FILE("pthread.h" HAVE_PTHREAD_H) +LA_CHECK_INCLUDE_FILE("pwd.h" HAVE_PWD_H) +LA_CHECK_INCLUDE_FILE("readpassphrase.h" HAVE_READPASSPHRASE_H) +LA_CHECK_INCLUDE_FILE("regex.h" HAVE_REGEX_H) +LA_CHECK_INCLUDE_FILE("signal.h" HAVE_SIGNAL_H) +LA_CHECK_INCLUDE_FILE("spawn.h" HAVE_SPAWN_H) +LA_CHECK_INCLUDE_FILE("stdarg.h" HAVE_STDARG_H) +LA_CHECK_INCLUDE_FILE("stdint.h" HAVE_STDINT_H) +LA_CHECK_INCLUDE_FILE("stdlib.h" HAVE_STDLIB_H) +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/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/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) +LA_CHECK_INCLUDE_FILE("sys/statvfs.h" HAVE_SYS_STATVFS_H) +LA_CHECK_INCLUDE_FILE("sys/time.h" HAVE_SYS_TIME_H) +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("time.h" HAVE_TIME_H) +LA_CHECK_INCLUDE_FILE("unistd.h" HAVE_UNISTD_H) +LA_CHECK_INCLUDE_FILE("utime.h" HAVE_UTIME_H) +LA_CHECK_INCLUDE_FILE("wchar.h" HAVE_WCHAR_H) +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) +ELSE(ENABLE_CNG) + UNSET(HAVE_BCRYPT_H CACHE) +ENDIF(ENABLE_CNG) +# Following files need windows.h, so we should test it after windows.h test. +LA_CHECK_INCLUDE_FILE("wincrypt.h" HAVE_WINCRYPT_H) +LA_CHECK_INCLUDE_FILE("winioctl.h" HAVE_WINIOCTL_H) + +# +# Check whether use of __EXTENSIONS__ is safe. +# We need some macro such as _GNU_SOURCE to use extension functions. +# +SET(_INCLUDE_FILES) +FOREACH (it ${_HEADER}) + SET(_INCLUDE_FILES "${_INCLUDE_FILES}#include <${it}>\n") +ENDFOREACH (it) + +CHECK_C_SOURCE_COMPILES( + "#define __EXTENSIONS__ 1 + ${_INCLUDE_FILES} + int main() { return 0;}" + SAFE_TO_DEFINE_EXTENSIONS) + +# +# Find Nettle +# +IF(ENABLE_NETTLE) + FIND_PACKAGE(Nettle) + IF(NETTLE_FOUND) + SET(HAVE_LIBNETTLE 1) + LIST(APPEND ADDITIONAL_LIBS ${NETTLE_LIBRARIES}) + INCLUDE_DIRECTORIES(${NETTLE_INCLUDE_DIR}) + + LIST(APPEND CMAKE_REQUIRED_INCLUDES ${NETTLE_INCLUDE_DIR}) + LA_CHECK_INCLUDE_FILE("nettle/aes.h" HAVE_NETTLE_AES_H) + LA_CHECK_INCLUDE_FILE("nettle/hmac.h" HAVE_NETTLE_HMAC_H) + LA_CHECK_INCLUDE_FILE("nettle/md5.h" HAVE_NETTLE_MD5_H) + LA_CHECK_INCLUDE_FILE("nettle/pbkdf2.h" HAVE_NETTLE_PBKDF2_H) + LA_CHECK_INCLUDE_FILE("nettle/ripemd160.h" HAVE_NETTLE_RIPEMD160_H) + LA_CHECK_INCLUDE_FILE("nettle/sha.h" HAVE_NETTLE_SHA_H) + + ENDIF(NETTLE_FOUND) + MARK_AS_ADVANCED(CLEAR NETTLE_INCLUDE_DIR) + MARK_AS_ADVANCED(CLEAR NETTLE_LIBRARIES) +ENDIF(ENABLE_NETTLE) + +# +# Find OpenSSL +# (Except on Mac, where OpenSSL is deprecated.) +# +IF(ENABLE_OPENSSL AND NOT CMAKE_SYSTEM_NAME MATCHES "Darwin") + FIND_PACKAGE(OpenSSL) + IF(OPENSSL_FOUND) + SET(HAVE_LIBCRYPTO 1) + INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR}) + ENDIF(OPENSSL_FOUND) +ELSE() + SET(OPENSSL_FOUND FALSE) # Override cached value +ENDIF() + +# FreeBSD libmd +IF(NOT OPENSSL_FOUND) + CHECK_LIBRARY_EXISTS(md "MD5Init" "" LIBMD_FOUND) + IF(LIBMD_FOUND) + CMAKE_PUSH_CHECK_STATE() # Save the state of the variables + SET(CMAKE_REQUIRED_LIBRARIES "md") + FIND_LIBRARY(LIBMD_LIBRARY NAMES md) + LIST(APPEND ADDITIONAL_LIBS ${LIBMD_LIBRARY}) + CMAKE_POP_CHECK_STATE() # Restore the state of the variables + ENDIF(LIBMD_FOUND) +ENDIF(NOT OPENSSL_FOUND) + +# +# How to prove that CRYPTO functions, which have several names on various +# platforms, just see if archive_digest.c can compile and link against +# required libraries. +# +MACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION) + FOREACH(ALGORITHM ${ALGORITHMS}) + IF(NOT ARCHIVE_CRYPTO_${ALGORITHM}) + STRING(TOLOWER "${ALGORITHM}" lower_algorithm) + STRING(TOUPPER "${ALGORITHM}" algorithm) + IF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND NOT OPENSSL_FOUND) + SET(ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} FALSE) + ELSEIF("${IMPLEMENTATION}" MATCHES "^NETTLE$" AND NOT NETTLE_FOUND) + SET(ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} FALSE) + ENDIF("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND NOT OPENSSL_FOUND) + + IF(NOT DEFINED ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}) + # Probe the local implementation for whether this + # crypto implementation is available on this platform. + SET(TRY_CRYPTO_REQUIRED_INCLUDES + "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}/libarchive;${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp") + SET(TRY_CRYPTO_REQUIRED_LIBS) + IF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND) + SET(TRY_CRYPTO_REQUIRED_INCLUDES + "${TRY_CRYPTO_REQUIRED_INCLUDES};${OPENSSL_INCLUDE_DIR}") + SET(TRY_CRYPTO_REQUIRED_LIBS + "-DLINK_LIBRARIES:STRING=${OPENSSL_LIBRARIES}") + ELSEIF("${IMPLEMENTATION}" MATCHES "^NETTLE$" AND NETTLE_FOUND) + SET(TRY_CRYPTO_REQUIRED_INCLUDES + "${TRY_CRYPTO_REQUIRED_INCLUDES};${NETTLE_INCLUDE_DIR}") + SET(TRY_CRYPTO_REQUIRED_LIBS + "-DLINK_LIBRARIES:STRING=${NETTLE_LIBRARY}") + ELSEIF("${IMPLEMENTATION}" MATCHES "^LIBMD$" AND LIBMD_FOUND) + SET(TRY_CRYPTO_REQUIRED_LIBS + "-DLINK_LIBRARIES:STRING=${LIBMD_LIBRARY}") + ENDIF("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND) + + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.h.in + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h) + FILE(READ "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h" + CONFDEFS_H) + FILE(READ "${CMAKE_CURRENT_SOURCE_DIR}/libarchive/archive_digest.c" + ARCHIVE_CRYPTO_C) + + SET(SOURCE "${CONFDEFS_H} + +#define ARCHIVE_${algorithm}_COMPILE_TEST +#define ARCHIVE_CRYPTO_${algorithm}_${IMPLEMENTATION} +#define PLATFORM_CONFIG_H \"check_crypto_md.h\" + +${ARCHIVE_CRYPTO_C} + +int +main(int argc, char **argv) +{ + archive_${lower_algorithm}_ctx ctx; + archive_${lower_algorithm}_init(&ctx); + archive_${lower_algorithm}_update(&ctx, *argv, argc); + archive_${lower_algorithm}_final(&ctx, NULL); + return 0; +} +") + + FILE(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_md.h" "") + FILE(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_md.c" "${SOURCE}") + MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}") + + TRY_COMPILE(ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} + ${CMAKE_BINARY_DIR} + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_md.c + CMAKE_FLAGS + "${TRY_CRYPTO_REQUIRED_LIBS}" + "${TRY_CRYPTO_REQUIRED_INCLUDES}" + OUTPUT_VARIABLE OUTPUT) + + # Inform user whether or not we found it; if not, log why we didn't. + IF (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}) + MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} -- found") + SET(ARCHIVE_CRYPTO_${ALGORITHM} 1) + ELSE (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}) + MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} -- not found") + FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Checking support for ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION} failed with the following output:\n" + "${OUTPUT}\n" + "Source file was:\n${SOURCE}\n") + ENDIF (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}) + ENDIF(NOT DEFINED ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}) + + # Add appropriate libs/includes depending on whether the implementation + # was found on this platform. + IF (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}) + IF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND) + INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR}) + LIST(APPEND ADDITIONAL_LIBS ${OPENSSL_LIBRARIES}) + LIST(REMOVE_DUPLICATES ADDITIONAL_LIBS) + ENDIF ("${IMPLEMENTATION}" MATCHES "^OPENSSL$" AND OPENSSL_FOUND) + ENDIF (ARCHIVE_CRYPTO_${ALGORITHM}_${IMPLEMENTATION}) + ENDIF(NOT ARCHIVE_CRYPTO_${ALGORITHM}) + ENDFOREACH(ALGORITHM ${ALGORITHMS}) +ENDMACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION) + +# +# CRYPTO functions on Windows is defined at archive_windows.c, thus we do not +# need the test what the functions can be mapped to archive_{crypto name}_init, +# archive_{crypto name}_update and archive_{crypto name}_final. +# The functions on Windows use CALG_{crypto name} macro to create a crypt object +# and then we need to know what CALG_{crypto name} macros is available to show +# ARCHIVE_CRYPTO_{crypto name}_WIN macros because Windows 2000 and earlier version +# of Windows XP do not support SHA256, SHA384 and SHA512. +# +MACRO(CHECK_CRYPTO_WIN CRYPTO_LIST) + IF(WIN32 AND NOT CYGWIN) + FOREACH(CRYPTO ${CRYPTO_LIST}) + IF(NOT ARCHIVE_CRYPTO_${CRYPTO}) + IF(NOT DEFINED ARCHIVE_CRYPTO_${CRYPTO}_WIN) + STRING(TOUPPER "${CRYPTO}" crypto) + SET(ALGID "") + IF ("${CRYPTO}" MATCHES "^MD5$") + SET(ALGID "CALG_MD5") + ENDIF ("${CRYPTO}" MATCHES "^MD5$") + IF ("${CRYPTO}" MATCHES "^SHA1$") + SET(ALGID "CALG_SHA1") + ENDIF ("${CRYPTO}" MATCHES "^SHA1$") + IF ("${CRYPTO}" MATCHES "^SHA256$") + SET(ALGID "CALG_SHA_256") + ENDIF ("${CRYPTO}" MATCHES "^SHA256$") + IF ("${CRYPTO}" MATCHES "^SHA384$") + SET(ALGID "CALG_SHA_384") + ENDIF ("${CRYPTO}" MATCHES "^SHA384$") + IF ("${CRYPTO}" MATCHES "^SHA512$") + SET(ALGID "CALG_SHA_512") + ENDIF ("${CRYPTO}" MATCHES "^SHA512$") + + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.h.in + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h) + FILE(READ "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h" + CONFDEFS_H) + + SET(SOURCE "${CONFDEFS_H} + +#define ${crypto}_COMPILE_TEST +#include +#include + +int +main(int argc, char **argv) +{ + return ${ALGID}; +} +") + SET(SOURCE_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_win.c") + + FILE(WRITE "${SOURCE_FILE}" "${SOURCE}") + MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN") + + TRY_COMPILE(ARCHIVE_CRYPTO_${CRYPTO}_WIN + ${CMAKE_BINARY_DIR} + ${SOURCE_FILE} + CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}/libarchive" + OUTPUT_VARIABLE OUTPUT) + + IF (ARCHIVE_CRYPTO_${CRYPTO}_WIN) + MESSAGE(STATUS + "Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN -- found") + SET(ARCHIVE_CRYPTO_${CRYPTO} 1) + ELSE (ARCHIVE_CRYPTO_${CRYPTO}_WIN) + MESSAGE(STATUS + "Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN -- not found") + FILE(APPEND + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN failed with the following output:\n" + "${OUTPUT}\n" + "Source file was:\n${SOURCE}\n") + ENDIF (ARCHIVE_CRYPTO_${CRYPTO}_WIN) + + ENDIF(NOT DEFINED ARCHIVE_CRYPTO_${CRYPTO}_WIN) + ENDIF(NOT ARCHIVE_CRYPTO_${CRYPTO}) + ENDFOREACH(CRYPTO) + ENDIF(WIN32 AND NOT CYGWIN) +ENDMACRO(CHECK_CRYPTO_WIN CRYPTO_LIST) + +# +# Find iconv +# POSIX defines the second arg as const char ** +# and requires it to be in libc. But we can accept +# a non-const argument here and can support iconv() +# being in libiconv. +# +MACRO(CHECK_ICONV LIB TRY_ICONV_CONST) + IF(NOT HAVE_ICONV) + CMAKE_PUSH_CHECK_STATE() # Save the state of the variables + IF (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR + CMAKE_C_COMPILER_ID STREQUAL "Clang") + # + # During checking iconv proto type, we should use -Werror to avoid the + # success of iconv detection with a warnig which success is a miss + # detection. So this needs for all build mode(even it's a release mode). + # + SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror") + ENDIF () + IF (CMAKE_C_COMPILER_ID STREQUAL "XL") + SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -qhalt=w -qflag=w:w") + ENDIF () + IF (MSVC) + # NOTE: /WX option is the same as gcc's -Werror option. + SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} /WX") + ENDIF (MSVC) + # + CHECK_C_SOURCE_COMPILES( + "#include + #include + int main() { + ${TRY_ICONV_CONST} char *ccp; + iconv_t cd = iconv_open(\"\", \"\"); + iconv(cd, &ccp, (size_t *)0, (char **)0, (size_t *)0); + iconv_close(cd); + return 0; + }" + HAVE_ICONV_${LIB}_${TRY_ICONV_CONST}) + IF(HAVE_ICONV_${LIB}_${TRY_ICONV_CONST}) + SET(HAVE_ICONV true) + SET(ICONV_CONST ${TRY_ICONV_CONST}) + ENDIF(HAVE_ICONV_${LIB}_${TRY_ICONV_CONST}) + CMAKE_POP_CHECK_STATE() # Restore the state of the variables + ENDIF(NOT HAVE_ICONV) +ENDMACRO(CHECK_ICONV TRY_ICONV_CONST) + +IF(ENABLE_ICONV) + CMAKE_PUSH_CHECK_STATE() # Save the state of the variables + FIND_PATH(ICONV_INCLUDE_DIR iconv.h) + MARK_AS_ADVANCED(ICONV_INCLUDE_DIR) + IF(ICONV_INCLUDE_DIR) + #SET(INCLUDES ${INCLUDES} "iconv.h") + SET(HAVE_ICONV_H 1) + INCLUDE_DIRECTORIES(${ICONV_INCLUDE_DIR}) + SET(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR}) + CHECK_ICONV("libc" "const") + CHECK_ICONV("libc" "") + + # If iconv isn't in libc and we have a libiconv, try that. + FIND_LIBRARY(LIBICONV_PATH NAMES iconv libiconv) + IF(NOT HAVE_ICONV AND LIBICONV_PATH) + LIST(APPEND CMAKE_REQUIRED_LIBRARIES ${LIBICONV_PATH}) + # Test if a macro is needed for the library. + TRY_MACRO_FOR_LIBRARY( + "${ICONV_INCLUDE_DIR}" "${LIBICONV_PATH}" + COMPILES + "#include \nint main() {return iconv_close((iconv_t)0);}" + "WITHOUT_LIBICONV_STATIC;LIBICONV_STATIC") + IF(NOT WITHOUT_LIBICONV_STATIC AND LIBICONV_STATIC) + ADD_DEFINITIONS(-DLIBICONV_STATIC) + ENDIF(NOT WITHOUT_LIBICONV_STATIC AND LIBICONV_STATIC) + # + # Set up CMAKE_REQUIRED_* for CHECK_ICONV + # + SET(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR}) + SET(CMAKE_REQUIRED_LIBRARIES ${LIBICONV_PATH}) + IF(LIBICONV_STATIC) + # LIBICONV_STATIC is necessary for the success of CHECK_ICONV + # on Windows. + SET(CMAKE_REQUIRED_DEFINITIONS "-DLIBICONV_STATIC") + ELSE(LIBICONV_STATIC) + SET(CMAKE_REQUIRED_DEFINITIONS) + ENDIF(LIBICONV_STATIC) + CHECK_ICONV("libiconv" "const") + CHECK_ICONV("libiconv" "") + IF (HAVE_ICONV) + LIST(APPEND ADDITIONAL_LIBS ${LIBICONV_PATH}) + ENDIF(HAVE_ICONV) + ENDIF(NOT HAVE_ICONV AND LIBICONV_PATH) + ENDIF(ICONV_INCLUDE_DIR) + # + # Find locale_charset() for libiconv. + # + IF(LIBICONV_PATH) + SET(CMAKE_REQUIRED_DEFINITIONS) + SET(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR}) + SET(CMAKE_REQUIRED_LIBRARIES) + CHECK_INCLUDE_FILES("localcharset.h" HAVE_LOCALCHARSET_H) + FIND_LIBRARY(LIBCHARSET_PATH NAMES charset libcharset) + IF(LIBCHARSET_PATH) + SET(CMAKE_REQUIRED_LIBRARIES ${LIBCHARSET_PATH}) + IF(WIN32 AND NOT CYGWIN) + # Test if a macro is needed for the library. + TRY_MACRO_FOR_LIBRARY( + "${ICONV_INCLUDE_DIR}" "${LIBCHARSET_PATH}" + COMPILES + "#include \nint main() {return locale_charset()?1:0;}" + "WITHOUT_LIBCHARSET_STATIC;LIBCHARSET_STATIC") + IF(NOT WITHOUT_LIBCHARSET_STATIC AND LIBCHARSET_STATIC) + ADD_DEFINITIONS(-DLIBCHARSET_STATIC) + ENDIF(NOT WITHOUT_LIBCHARSET_STATIC AND LIBCHARSET_STATIC) + IF(WITHOUT_LIBCHARSET_STATIC OR LIBCHARSET_STATIC) + SET(HAVE_LOCALE_CHARSET ON CACHE INTERNAL + "Have function locale_charset") + ENDIF(WITHOUT_LIBCHARSET_STATIC OR LIBCHARSET_STATIC) + ELSE(WIN32 AND NOT CYGWIN) + CHECK_FUNCTION_EXISTS_GLIBC(locale_charset HAVE_LOCALE_CHARSET) + ENDIF(WIN32 AND NOT CYGWIN) + IF(HAVE_LOCALE_CHARSET) + LIST(APPEND ADDITIONAL_LIBS ${LIBCHARSET_PATH}) + ENDIF(HAVE_LOCALE_CHARSET) + ENDIF(LIBCHARSET_PATH) + ENDIF(LIBICONV_PATH) + CMAKE_POP_CHECK_STATE() # Restore the state of the variables +ELSE(ENABLE_ICONV) + # Make sure ICONV variables are not in CACHE after ENABLE_ICONV disabled + # (once enabled). + UNSET(HAVE_LOCALE_CHARSET CACHE) + UNSET(HAVE_ICONV CACHE) + UNSET(HAVE_ICONV_libc_ CACHE) + UNSET(HAVE_ICONV_libc_const CACHE) + UNSET(HAVE_ICONV_libiconv_ CACHE) + UNSET(HAVE_ICONV_libiconv_const CACHE) + UNSET(ICONV_INCLUDE_DIR CACHE) + UNSET(LIBICONV_PATH CACHE) + UNSET(LIBICONV_DLL CACHE) + UNSET(LIBICONV_STATIC CACHE) + UNSET(LIBCHARSET_DLL CACHE) + UNSET(LIBCHARSET_STATIC CACHE) +ENDIF(ENABLE_ICONV) + +IF(0) # CMake does not need XML support in libarchive +# +# Find Libxml2 +# +IF(ENABLE_LIBXML2) + FIND_PACKAGE(LibXml2) +ELSE() + SET(LIBXML2_FOUND FALSE) +ENDIF() +IF(LIBXML2_FOUND) + CMAKE_PUSH_CHECK_STATE() # Save the state of the variables + INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR}) + LIST(APPEND ADDITIONAL_LIBS ${LIBXML2_LIBRARIES}) + SET(HAVE_LIBXML2 1) + # libxml2's include files use iconv.h + SET(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR}) + CHECK_INCLUDE_FILES("libxml/xmlreader.h" HAVE_LIBXML_XMLREADER_H) + CHECK_INCLUDE_FILES("libxml/xmlwriter.h" HAVE_LIBXML_XMLWRITER_H) + # Test if a macro is needed for the library. + TRY_MACRO_FOR_LIBRARY( + "${ICONV_INCLUDE_DIR};${LIBXML2_INCLUDE_DIR}" + "ws2_32.lib;${ZLIB_LIBRARIES};${LIBICONV_PATH};${LIBXML2_LIBRARIES}" + COMPILES + "#include \n#include \nint main() {return xmlTextReaderRead((xmlTextReaderPtr)(void *)0);}" + "WITHOUT_LIBXML_STATIC;LIBXML_STATIC") + IF(NOT WITHOUT_LIBXML_STATIC AND LIBXML_STATIC) + ADD_DEFINITIONS(-DLIBXML_STATIC) + ENDIF(NOT WITHOUT_LIBXML_STATIC AND LIBXML_STATIC) + CMAKE_POP_CHECK_STATE() # Restore the state of the variables +ELSE(LIBXML2_FOUND) + # + # Find Expat + # + IF(ENABLE_EXPAT) + FIND_PACKAGE(EXPAT) + ELSE() + SET(EXPAT_FOUND FALSE) + ENDIF() + IF(EXPAT_FOUND) + CMAKE_PUSH_CHECK_STATE() # Save the state of the variables + INCLUDE_DIRECTORIES(${EXPAT_INCLUDE_DIR}) + LIST(APPEND ADDITIONAL_LIBS ${EXPAT_LIBRARIES}) + SET(HAVE_LIBEXPAT 1) + LA_CHECK_INCLUDE_FILE("expat.h" HAVE_EXPAT_H) + CMAKE_POP_CHECK_STATE() # Restore the state of the variables + ENDIF(EXPAT_FOUND) +ENDIF(LIBXML2_FOUND) +MARK_AS_ADVANCED(CLEAR LIBXML2_INCLUDE_DIR) +MARK_AS_ADVANCED(CLEAR LIBXML2_LIBRARIES) +ENDIF() + +# +# Check functions +# +CMAKE_PUSH_CHECK_STATE() # Save the state of the variables +IF (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR + CMAKE_C_COMPILER_ID STREQUAL "Clang") + # + # During checking functions, we should use -fno-builtin to avoid the + # failure of function detection which failure is an error "conflicting + # types for built-in function" caused by using -Werror option. + # + SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fno-builtin") +ENDIF () +CHECK_SYMBOL_EXISTS(_CrtSetReportMode "crtdbg.h" HAVE__CrtSetReportMode) +CHECK_FUNCTION_EXISTS_GLIBC(arc4random_buf HAVE_ARC4RANDOM_BUF) +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) +CHECK_FUNCTION_EXISTS_GLIBC(fchown HAVE_FCHOWN) +CHECK_FUNCTION_EXISTS_GLIBC(fcntl HAVE_FCNTL) +CHECK_FUNCTION_EXISTS_GLIBC(fdopendir HAVE_FDOPENDIR) +CHECK_FUNCTION_EXISTS_GLIBC(fork HAVE_FORK) +CHECK_FUNCTION_EXISTS_GLIBC(fstat HAVE_FSTAT) +CHECK_FUNCTION_EXISTS_GLIBC(fstatat HAVE_FSTATAT) +CHECK_FUNCTION_EXISTS_GLIBC(fstatfs HAVE_FSTATFS) +CHECK_FUNCTION_EXISTS_GLIBC(fstatvfs HAVE_FSTATVFS) +CHECK_FUNCTION_EXISTS_GLIBC(ftruncate HAVE_FTRUNCATE) +CHECK_FUNCTION_EXISTS_GLIBC(futimens HAVE_FUTIMENS) +CHECK_FUNCTION_EXISTS_GLIBC(futimes HAVE_FUTIMES) +CHECK_FUNCTION_EXISTS_GLIBC(futimesat HAVE_FUTIMESAT) +CHECK_FUNCTION_EXISTS_GLIBC(geteuid HAVE_GETEUID) +CHECK_FUNCTION_EXISTS_GLIBC(getgrgid_r HAVE_GETGRGID_R) +CHECK_FUNCTION_EXISTS_GLIBC(getgrnam_r HAVE_GETGRNAM_R) +CHECK_FUNCTION_EXISTS_GLIBC(getpwnam_r HAVE_GETPWNAM_R) +CHECK_FUNCTION_EXISTS_GLIBC(getpwuid_r HAVE_GETPWUID_R) +CHECK_FUNCTION_EXISTS_GLIBC(getpid HAVE_GETPID) +CHECK_FUNCTION_EXISTS_GLIBC(getvfsbyname HAVE_GETVFSBYNAME) +CHECK_FUNCTION_EXISTS_GLIBC(gmtime_r HAVE_GMTIME_R) +CHECK_FUNCTION_EXISTS_GLIBC(lchflags HAVE_LCHFLAGS) +CHECK_FUNCTION_EXISTS_GLIBC(lchmod HAVE_LCHMOD) +CHECK_FUNCTION_EXISTS_GLIBC(lchown HAVE_LCHOWN) +CHECK_FUNCTION_EXISTS_GLIBC(link HAVE_LINK) +CHECK_FUNCTION_EXISTS_GLIBC(localtime_r HAVE_LOCALTIME_R) +CHECK_FUNCTION_EXISTS_GLIBC(lstat HAVE_LSTAT) +CHECK_FUNCTION_EXISTS_GLIBC(lutimes HAVE_LUTIMES) +CHECK_FUNCTION_EXISTS_GLIBC(mbrtowc HAVE_MBRTOWC) +CHECK_FUNCTION_EXISTS_GLIBC(memmove HAVE_MEMMOVE) +CHECK_FUNCTION_EXISTS_GLIBC(mkdir HAVE_MKDIR) +CHECK_FUNCTION_EXISTS_GLIBC(mkfifo HAVE_MKFIFO) +CHECK_FUNCTION_EXISTS_GLIBC(mknod HAVE_MKNOD) +CHECK_FUNCTION_EXISTS_GLIBC(mkstemp HAVE_MKSTEMP) +CHECK_FUNCTION_EXISTS_GLIBC(nl_langinfo HAVE_NL_LANGINFO) +CHECK_FUNCTION_EXISTS_GLIBC(openat HAVE_OPENAT) +CHECK_FUNCTION_EXISTS_GLIBC(pipe HAVE_PIPE) +CHECK_FUNCTION_EXISTS_GLIBC(poll HAVE_POLL) +CHECK_FUNCTION_EXISTS_GLIBC(posix_spawnp HAVE_POSIX_SPAWNP) +CHECK_FUNCTION_EXISTS_GLIBC(readlink HAVE_READLINK) +CHECK_FUNCTION_EXISTS_GLIBC(readpassphrase HAVE_READPASSPHRASE) +CHECK_FUNCTION_EXISTS_GLIBC(select HAVE_SELECT) +CHECK_FUNCTION_EXISTS_GLIBC(setenv HAVE_SETENV) +CHECK_FUNCTION_EXISTS_GLIBC(setlocale HAVE_SETLOCALE) +CHECK_FUNCTION_EXISTS_GLIBC(sigaction HAVE_SIGACTION) +CHECK_FUNCTION_EXISTS_GLIBC(statfs HAVE_STATFS) +CHECK_FUNCTION_EXISTS_GLIBC(statvfs HAVE_STATVFS) +CHECK_FUNCTION_EXISTS_GLIBC(strchr HAVE_STRCHR) +CHECK_FUNCTION_EXISTS_GLIBC(strdup HAVE_STRDUP) +CHECK_FUNCTION_EXISTS_GLIBC(strerror HAVE_STRERROR) +CHECK_FUNCTION_EXISTS_GLIBC(strncpy_s HAVE_STRNCPY_S) +CHECK_FUNCTION_EXISTS_GLIBC(strrchr HAVE_STRRCHR) +CHECK_FUNCTION_EXISTS_GLIBC(symlink HAVE_SYMLINK) +CHECK_FUNCTION_EXISTS_GLIBC(timegm HAVE_TIMEGM) +CHECK_FUNCTION_EXISTS_GLIBC(tzset HAVE_TZSET) +CHECK_FUNCTION_EXISTS_GLIBC(unsetenv HAVE_UNSETENV) +CHECK_FUNCTION_EXISTS_GLIBC(utime HAVE_UTIME) +CHECK_FUNCTION_EXISTS_GLIBC(utimes HAVE_UTIMES) +CHECK_FUNCTION_EXISTS_GLIBC(utimensat HAVE_UTIMENSAT) +CHECK_FUNCTION_EXISTS_GLIBC(vfork HAVE_VFORK) +CHECK_FUNCTION_EXISTS_GLIBC(wcrtomb HAVE_WCRTOMB) +CHECK_FUNCTION_EXISTS_GLIBC(wcscmp HAVE_WCSCMP) +CHECK_FUNCTION_EXISTS_GLIBC(wcscpy HAVE_WCSCPY) +CHECK_FUNCTION_EXISTS_GLIBC(wcslen HAVE_WCSLEN) +CHECK_FUNCTION_EXISTS_GLIBC(wctomb HAVE_WCTOMB) +CHECK_FUNCTION_EXISTS_GLIBC(_ctime64_s HAVE__CTIME64_S) +CHECK_FUNCTION_EXISTS_GLIBC(_fseeki64 HAVE__FSEEKI64) +CHECK_FUNCTION_EXISTS_GLIBC(_get_timezone HAVE__GET_TIMEZONE) +CHECK_FUNCTION_EXISTS_GLIBC(_localtime64_s HAVE__LOCALTIME64_S) +CHECK_FUNCTION_EXISTS_GLIBC(_mkgmtime64 HAVE__MKGMTIME64) + +SET(CMAKE_REQUIRED_LIBRARIES "") +CHECK_FUNCTION_EXISTS(cygwin_conv_path HAVE_CYGWIN_CONV_PATH) +CHECK_FUNCTION_EXISTS(fseeko HAVE_FSEEKO) +CHECK_FUNCTION_EXISTS(strerror_r HAVE_STRERROR_R) +CHECK_FUNCTION_EXISTS(strftime HAVE_STRFTIME) +CHECK_FUNCTION_EXISTS(vprintf HAVE_VPRINTF) +CHECK_FUNCTION_EXISTS(wmemcmp HAVE_WMEMCMP) +CHECK_FUNCTION_EXISTS(wmemcpy HAVE_WMEMCPY) +CHECK_FUNCTION_EXISTS(wmemmove HAVE_WMEMMOVE) + +CMAKE_POP_CHECK_STATE() # Restore the state of the variables + +CHECK_C_SOURCE_COMPILES( + "#include \n#include \nint main(void) { struct vfsconf v; return sizeof(v);}" + HAVE_STRUCT_VFSCONF) + +CHECK_C_SOURCE_COMPILES( + "#include \n#include \nint main(void) { struct xvfsconf v; return sizeof(v);}" + HAVE_STRUCT_XVFSCONF) + +# Make sure we have the POSIX version of readdir_r, not the +# older 2-argument version. +CHECK_C_SOURCE_COMPILES( + "#include \nint main() {DIR *d = opendir(\".\"); struct dirent e,*r; return readdir_r(d,&e,&r);}" + HAVE_READDIR_R) + + +# Only detect readlinkat() if we also have AT_FDCWD in unistd.h. +# NOTE: linux requires fcntl.h for AT_FDCWD. +CHECK_C_SOURCE_COMPILES( + "#include \n#include \nint main() {char buf[10]; return readlinkat(AT_FDCWD, \"\", buf, 0);}" + HAVE_READLINKAT) + + +# To verify major(), we need to both include the header +# of interest and verify that the result can be linked. +# CHECK_FUNCTION_EXISTS doesn't accept a header argument, +# CHECK_SYMBOL_EXISTS doesn't test linkage. +CHECK_C_SOURCE_COMPILES( + "#include \nint main() { return major(256); }" + MAJOR_IN_MKDEV) +CHECK_C_SOURCE_COMPILES( + "#include \nint main() { return major(256); }" + MAJOR_IN_SYSMACROS) + +CHECK_C_SOURCE_COMPILES( + "#include \n#if LZMA_VERSION < 50020000\n#error unsupported\n#endif\nint main(void){lzma_stream_encoder_mt(0, 0); return 0;}" + HAVE_LZMA_STREAM_ENCODER_MT) + +IF(HAVE_STRERROR_R) + SET(HAVE_DECL_STRERROR_R 1) +ENDIF(HAVE_STRERROR_R) + +# +# Check defines +# +SET(headers "limits.h") +IF(HAVE_STDINT_H) + LIST(APPEND headers "stdint.h") +ENDIF(HAVE_STDINT_H) +IF(HAVE_INTTYPES_H) + LIST(APPEND headers "inttypes.h") +ENDIF(HAVE_INTTYPES_H) +CHECK_SYMBOL_EXISTS(EFTYPE "errno.h" HAVE_EFTYPE) +CHECK_SYMBOL_EXISTS(EILSEQ "errno.h" HAVE_EILSEQ) +CHECK_SYMBOL_EXISTS(D_MD_ORDER "langinfo.h" HAVE_D_MD_ORDER) +CHECK_SYMBOL_EXISTS(INT32_MAX "${headers}" HAVE_DECL_INT32_MAX) +CHECK_SYMBOL_EXISTS(INT32_MIN "${headers}" HAVE_DECL_INT32_MIN) +CHECK_SYMBOL_EXISTS(INT64_MAX "${headers}" HAVE_DECL_INT64_MAX) +CHECK_SYMBOL_EXISTS(INT64_MIN "${headers}" HAVE_DECL_INT64_MIN) +CHECK_SYMBOL_EXISTS(INTMAX_MAX "${headers}" HAVE_DECL_INTMAX_MAX) +CHECK_SYMBOL_EXISTS(INTMAX_MIN "${headers}" HAVE_DECL_INTMAX_MIN) +CHECK_SYMBOL_EXISTS(UINT32_MAX "${headers}" HAVE_DECL_UINT32_MAX) +CHECK_SYMBOL_EXISTS(UINT64_MAX "${headers}" HAVE_DECL_UINT64_MAX) +CHECK_SYMBOL_EXISTS(UINTMAX_MAX "${headers}" HAVE_DECL_UINTMAX_MAX) +CHECK_SYMBOL_EXISTS(SIZE_MAX "${headers}" HAVE_DECL_SIZE_MAX) +CHECK_SYMBOL_EXISTS(SSIZE_MAX "limits.h" HAVE_DECL_SSIZE_MAX) + +# +# Check struct members +# +# Check for tm_gmtoff in struct tm +CHECK_STRUCT_HAS_MEMBER("struct tm" tm_gmtoff + "time.h" HAVE_STRUCT_TM_TM_GMTOFF) +CHECK_STRUCT_HAS_MEMBER("struct tm" __tm_gmtoff + "time.h" HAVE_STRUCT_TM___TM_GMTOFF) + +# Check for f_namemax in struct statfs +CHECK_STRUCT_HAS_MEMBER("struct statfs" f_namemax + "sys/param.h;sys/mount.h" HAVE_STRUCT_STATFS_F_NAMEMAX) + +# Check for birthtime in struct stat +CHECK_STRUCT_HAS_MEMBER("struct stat" st_birthtime + "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_BIRTHTIME) + +# Check for high-resolution timestamps in struct stat +CHECK_STRUCT_HAS_MEMBER("struct stat" st_birthtimespec.tv_nsec + "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC) +CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtimespec.tv_nsec + "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC) +CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtim.tv_nsec + "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC) +CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtime_n + "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIME_N) +CHECK_STRUCT_HAS_MEMBER("struct stat" st_umtime + "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_UMTIME) +CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtime_usec + "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIME_USEC) +# Check for block size support in struct stat +CHECK_STRUCT_HAS_MEMBER("struct stat" st_blksize + "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_BLKSIZE) +# Check for st_flags in struct stat (BSD fflags) +CHECK_STRUCT_HAS_MEMBER("struct stat" st_flags + "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_FLAGS) + +IF(HAVE_SYS_STATVFS_H) + CHECK_STRUCT_HAS_MEMBER("struct statvfs" f_iosize + "sys/types.h;sys/statvfs.h" HAVE_STRUCT_STATVFS_F_IOSIZE) +ENDIF() + +# +# +CHECK_STRUCT_HAS_MEMBER("struct tm" tm_sec + "sys/types.h;sys/time.h;time.h" TIME_WITH_SYS_TIME) + +# +# Check for integer types +# +# +CHECK_TYPE_SIZE("short" SIZE_OF_SHORT) +CHECK_TYPE_SIZE("int" SIZE_OF_INT) +CHECK_TYPE_SIZE("long" SIZE_OF_LONG) +CHECK_TYPE_SIZE("long long" SIZE_OF_LONG_LONG) + +CHECK_TYPE_SIZE("unsigned short" SIZE_OF_UNSIGNED_SHORT) +CHECK_TYPE_SIZE("unsigned" SIZE_OF_UNSIGNED) +CHECK_TYPE_SIZE("unsigned long" SIZE_OF_UNSIGNED_LONG) +CHECK_TYPE_SIZE("unsigned long long" SIZE_OF_UNSIGNED_LONG_LONG) + +CHECK_TYPE_SIZE("__int64" __INT64) +CHECK_TYPE_SIZE("unsigned __int64" UNSIGNED___INT64) + +CHECK_TYPE_SIZE(int16_t INT16_T) +CHECK_TYPE_SIZE(int32_t INT32_T) +CHECK_TYPE_SIZE(int64_t INT64_T) +CHECK_TYPE_SIZE(intmax_t INTMAX_T) +CHECK_TYPE_SIZE(uint8_t UINT8_T) +CHECK_TYPE_SIZE(uint16_t UINT16_T) +CHECK_TYPE_SIZE(uint32_t UINT32_T) +CHECK_TYPE_SIZE(uint64_t UINT64_T) +CHECK_TYPE_SIZE(uintmax_t UINTMAX_T) + +CHECK_TYPE_SIZE(dev_t DEV_T) +IF(NOT HAVE_DEV_T) + IF(MSVC) + SET(dev_t "unsigned int") + ENDIF(MSVC) +ENDIF(NOT HAVE_DEV_T) +# +CHECK_TYPE_SIZE(gid_t GID_T) +IF(NOT HAVE_GID_T) + IF(WIN32) + SET(gid_t "short") + ELSE(WIN32) + SET(gid_t "unsigned int") + ENDIF(WIN32) +ENDIF(NOT HAVE_GID_T) +# +CHECK_TYPE_SIZE(id_t ID_T) +IF(NOT HAVE_ID_T) + IF(WIN32) + SET(id_t "short") + ELSE(WIN32) + SET(id_t "unsigned int") + ENDIF(WIN32) +ENDIF(NOT HAVE_ID_T) +# +CHECK_TYPE_SIZE(mode_t MODE_T) +IF(NOT HAVE_MODE_T) + IF(WIN32) + SET(mode_t "unsigned short") + ELSE(WIN32) + SET(mode_t "int") + ENDIF(WIN32) +ENDIF(NOT HAVE_MODE_T) +# +CHECK_TYPE_SIZE(off_t OFF_T) +IF(NOT HAVE_OFF_T) + SET(off_t "__int64") +ENDIF(NOT HAVE_OFF_T) +# +CHECK_TYPE_SIZE(size_t SIZE_T) +IF(NOT HAVE_SIZE_T) + IF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) + SET(size_t "uint64_t") + ELSE("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) + SET(size_t "uint32_t") + ENDIF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) +ENDIF(NOT HAVE_SIZE_T) +# +CHECK_TYPE_SIZE(ssize_t SSIZE_T) +IF(NOT HAVE_SSIZE_T) + IF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) + SET(ssize_t "int64_t") + ELSE("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) + SET(ssize_t "long") + ENDIF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) +ENDIF(NOT HAVE_SSIZE_T) +# +CHECK_TYPE_SIZE(uid_t UID_T) +IF(NOT HAVE_UID_T) + IF(WIN32) + SET(uid_t "short") + ELSE(WIN32) + SET(uid_t "unsigned int") + ENDIF(WIN32) +ENDIF(NOT HAVE_UID_T) +# +CHECK_TYPE_SIZE(pid_t PID_T) +IF(NOT HAVE_PID_T) + IF(WIN32) + SET(pid_t "int") + ELSE(WIN32) + MESSAGE(FATAL_ERROR "pid_t doesn't exist on this platform?") + ENDIF(WIN32) +ENDIF(NOT HAVE_PID_T) +# +CHECK_TYPE_SIZE(intptr_t INTPTR_T) +IF(NOT HAVE_INTPTR_T) + IF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) + SET(intptr_t "int64_t") + ELSE() + SET(intptr_t "int32_t") + ENDIF() +ENDIF(NOT HAVE_INTPTR_T) +# +CHECK_TYPE_SIZE(uintptr_t UINTPTR_T) +IF(NOT HAVE_UINTPTR_T) + IF("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) + SET(uintptr_t "uint64_t") + ELSE() + SET(uintptr_t "uint32_t") + ENDIF() +ENDIF(NOT HAVE_UINTPTR_T) +# +CHECK_TYPE_SIZE(wchar_t SIZEOF_WCHAR_T) +IF(HAVE_SIZEOF_WCHAR_T) + SET(HAVE_WCHAR_T 1) +ENDIF(HAVE_SIZEOF_WCHAR_T) +# +# Check if _FILE_OFFSET_BITS macro needed for large files +# +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) +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) +ENDIF(ENABLE_XATTR) + +# +# Check for ACL libraries, headers, and functions +# +# The ACL support in libarchive is written against the POSIX1e draft, +# which was never officially approved and varies quite a bit across +# platforms. Worse, some systems have completely non-POSIX acl functions, +# which makes the following checks rather more complex than I would like. +# +IF(ENABLE_ACL) + 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 +#include +int main(void) { return ACL_TYPE_EXTENDED; }" HAVE_ACL_TYPE_EXTENDED) + + # 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) +ENDIF(ENABLE_ACL) + +# +# Check MD5/RMD160/SHA support +# NOTE: Crypto checks must be run last before generating config.h +# +CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA384;SHA512" LIBC) +CHECK_CRYPTO("SHA256;SHA384;SHA512" LIBC2) +CHECK_CRYPTO("SHA256;SHA384;SHA512" LIBC3) +CHECK_CRYPTO("MD5;SHA1;SHA256;SHA384;SHA512" LIBSYSTEM) +CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA384;SHA512" NETTLE) +CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA384;SHA512" OPENSSL) + +# Libmd has to be probed after OpenSSL. +CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA512" LIBMD) + +CHECK_CRYPTO_WIN("MD5;SHA1;SHA256;SHA384;SHA512") + +# Generate "config.h" from "build/cmake/config.h.in" +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.h.in + ${CMAKE_CURRENT_BINARY_DIR}/config.h) +INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_BINARY_DIR}) +ADD_DEFINITIONS(-DHAVE_CONFIG_H) + +# +# Register installation of PDF documents. +# +IF(WIN32 AND NOT CYGWIN) + # + # On Windows platform, It's better that we install PDF documents + # on one's computer. + # These PDF documents are available in the release package. + # + IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/doc/pdf) + INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc/pdf + DESTINATION share/man + FILES_MATCHING PATTERN "*.pdf" + ) + ENDIF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/doc/pdf) +ENDIF(WIN32 AND NOT CYGWIN) +# +# +# +INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/libarchive) +# +IF(MSVC) + ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE) +ENDIF(MSVC) + +# We need CoreServices on Mac OS. +IF(APPLE) + LIST(APPEND ADDITIONAL_LIBS "-framework CoreServices") +ENDIF(APPLE) + +add_subdirectory(libarchive) + +install(FILES COPYING DESTINATION ${CMAKE_DOC_DIR}/cmlibarchive) diff --cc Utilities/cmlibarchive/build/cmake/config.h.in index fc248b3,0000000..55e04b9 mode 100644,000000..100644 --- a/Utilities/cmlibarchive/build/cmake/config.h.in +++ b/Utilities/cmlibarchive/build/cmake/config.h.in @@@ -1,1242 -1,0 +1,1245 @@@ +/* config.h. Generated from build/cmake/config.h.in by cmake configure */ +#if defined(__osf__) +# define _OSF_SOURCE +#endif + +/* + * Ensure we have C99-style int64_t, etc, all defined. + */ + +/* First, we need to know if the system has already defined them. */ +#cmakedefine HAVE_INT16_T +#cmakedefine HAVE_INT32_T +#cmakedefine HAVE_INT64_T +#cmakedefine HAVE_INTMAX_T + +#cmakedefine HAVE_UINT8_T +#cmakedefine HAVE_UINT16_T +#cmakedefine HAVE_UINT32_T +#cmakedefine HAVE_UINT64_T +#cmakedefine HAVE_UINTMAX_T + +/* We might have the types we want under other spellings. */ +#cmakedefine HAVE___INT64 +#cmakedefine HAVE_U_INT64_T +#cmakedefine HAVE_UNSIGNED___INT64 + +/* The sizes of various standard integer types. */ + at SIZE_OF_SHORT_CODE@ + at SIZE_OF_INT_CODE@ + at SIZE_OF_LONG_CODE@ + at SIZE_OF_LONG_LONG_CODE@ + at SIZE_OF_UNSIGNED_SHORT_CODE@ + at SIZE_OF_UNSIGNED_CODE@ + at SIZE_OF_UNSIGNED_LONG_CODE@ + at SIZE_OF_UNSIGNED_LONG_LONG_CODE@ + +/* + * If we lack int64_t, define it to the first of __int64, int, long, and long long + * that exists and is the right size. + */ +#if !defined(HAVE_INT64_T) && defined(HAVE___INT64) +typedef __int64 int64_t; +#define HAVE_INT64_T +#endif + +#if !defined(HAVE_INT64_T) && SIZE_OF_INT == 8 +typedef int int64_t; +#define HAVE_INT64_T +#endif + +#if !defined(HAVE_INT64_T) && SIZE_OF_LONG == 8 +typedef long int64_t; +#define HAVE_INT64_T +#endif + +#if !defined(HAVE_INT64_T) && SIZE_OF_LONG_LONG == 8 +typedef long long int64_t; +#define HAVE_INT64_T +#endif + +#if !defined(HAVE_INT64_T) +#error No 64-bit integer type was found. +#endif + +/* + * Similarly for int32_t + */ +#if !defined(HAVE_INT32_T) && SIZE_OF_INT == 4 +typedef int int32_t; +#define HAVE_INT32_T +#endif + +#if !defined(HAVE_INT32_T) && SIZE_OF_LONG == 4 +typedef long int32_t; +#define HAVE_INT32_T +#endif + +#if !defined(HAVE_INT32_T) +#error No 32-bit integer type was found. +#endif + +/* + * Similarly for int16_t + */ +#if !defined(HAVE_INT16_T) && SIZE_OF_INT == 2 +typedef int int16_t; +#define HAVE_INT16_T +#endif + +#if !defined(HAVE_INT16_T) && SIZE_OF_SHORT == 2 +typedef short int16_t; +#define HAVE_INT16_T +#endif + +#if !defined(HAVE_INT16_T) +#error No 16-bit integer type was found. +#endif + +/* + * Similarly for uint64_t + */ +#if !defined(HAVE_UINT64_T) && defined(HAVE_UNSIGNED___INT64) +typedef unsigned __int64 uint64_t; +#define HAVE_UINT64_T +#endif + +#if !defined(HAVE_UINT64_T) && SIZE_OF_UNSIGNED == 8 +typedef unsigned uint64_t; +#define HAVE_UINT64_T +#endif + +#if !defined(HAVE_UINT64_T) && SIZE_OF_UNSIGNED_LONG == 8 +typedef unsigned long uint64_t; +#define HAVE_UINT64_T +#endif + +#if !defined(HAVE_UINT64_T) && SIZE_OF_UNSIGNED_LONG_LONG == 8 +typedef unsigned long long uint64_t; +#define HAVE_UINT64_T +#endif + +#if !defined(HAVE_UINT64_T) +#error No 64-bit unsigned integer type was found. +#endif + + +/* + * Similarly for uint32_t + */ +#if !defined(HAVE_UINT32_T) && SIZE_OF_UNSIGNED == 4 +typedef unsigned uint32_t; +#define HAVE_UINT32_T +#endif + +#if !defined(HAVE_UINT32_T) && SIZE_OF_UNSIGNED_LONG == 4 +typedef unsigned long uint32_t; +#define HAVE_UINT32_T +#endif + +#if !defined(HAVE_UINT32_T) +#error No 32-bit unsigned integer type was found. +#endif + +/* + * Similarly for uint16_t + */ +#if !defined(HAVE_UINT16_T) && SIZE_OF_UNSIGNED == 2 +typedef unsigned uint16_t; +#define HAVE_UINT16_T +#endif + +#if !defined(HAVE_UINT16_T) && SIZE_OF_UNSIGNED_SHORT == 2 +typedef unsigned short uint16_t; +#define HAVE_UINT16_T +#endif + +#if !defined(HAVE_UINT16_T) +#error No 16-bit unsigned integer type was found. +#endif + +/* + * Similarly for uint8_t + */ +#if !defined(HAVE_UINT8_T) +typedef unsigned char uint8_t; +#define HAVE_UINT8_T +#endif + +#if !defined(HAVE_UINT16_T) +#error No 8-bit unsigned integer type was found. +#endif + +/* Define intmax_t and uintmax_t if they are not already defined. */ +#if !defined(HAVE_INTMAX_T) +typedef int64_t intmax_t; +#endif + +#if !defined(HAVE_UINTMAX_T) +typedef uint64_t uintmax_t; +#endif + +/* Define ZLIB_WINAPI if zlib was built on Visual Studio. */ +#cmakedefine ZLIB_WINAPI 1 + +/* MD5 via ARCHIVE_CRYPTO_MD5_LIBC supported. */ +#cmakedefine ARCHIVE_CRYPTO_MD5_LIBC 1 + +/* MD5 via ARCHIVE_CRYPTO_MD5_LIBSYSTEM supported. */ +#cmakedefine ARCHIVE_CRYPTO_MD5_LIBSYSTEM 1 + +/* MD5 via ARCHIVE_CRYPTO_MD5_NETTLE supported. */ +#cmakedefine ARCHIVE_CRYPTO_MD5_NETTLE 1 + +/* MD5 via ARCHIVE_CRYPTO_MD5_OPENSSL supported. */ +#cmakedefine ARCHIVE_CRYPTO_MD5_OPENSSL 1 + +/* MD5 via ARCHIVE_CRYPTO_MD5_WIN supported. */ +#cmakedefine ARCHIVE_CRYPTO_MD5_WIN 1 + +/* RMD160 via ARCHIVE_CRYPTO_RMD160_LIBC supported. */ +#cmakedefine ARCHIVE_CRYPTO_RMD160_LIBC 1 + +/* RMD160 via ARCHIVE_CRYPTO_RMD160_NETTLE supported. */ +#cmakedefine ARCHIVE_CRYPTO_RMD160_NETTLE 1 + +/* RMD160 via ARCHIVE_CRYPTO_RMD160_OPENSSL supported. */ +#cmakedefine ARCHIVE_CRYPTO_RMD160_OPENSSL 1 + +/* SHA1 via ARCHIVE_CRYPTO_SHA1_LIBC supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA1_LIBC 1 + +/* SHA1 via ARCHIVE_CRYPTO_SHA1_LIBSYSTEM supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA1_LIBSYSTEM 1 + +/* SHA1 via ARCHIVE_CRYPTO_SHA1_NETTLE supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA1_NETTLE 1 + +/* SHA1 via ARCHIVE_CRYPTO_SHA1_OPENSSL supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA1_OPENSSL 1 + +/* SHA1 via ARCHIVE_CRYPTO_SHA1_WIN supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA1_WIN 1 + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBC supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA256_LIBC 1 + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBC2 supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA256_LIBC2 1 + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBC3 supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA256_LIBC3 1 + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_LIBSYSTEM supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA256_LIBSYSTEM 1 + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_NETTLE supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA256_NETTLE 1 + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_OPENSSL supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA256_OPENSSL 1 + +/* SHA256 via ARCHIVE_CRYPTO_SHA256_WIN supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA256_WIN 1 + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBC supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA384_LIBC 1 + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBC2 supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA384_LIBC2 1 + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBC3 supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA384_LIBC3 1 + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_LIBSYSTEM supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA384_LIBSYSTEM 1 + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_NETTLE supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA384_NETTLE 1 + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_OPENSSL supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA384_OPENSSL 1 + +/* SHA384 via ARCHIVE_CRYPTO_SHA384_WIN supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA384_WIN 1 + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBC supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA512_LIBC 1 + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBC2 supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA512_LIBC2 1 + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBC3 supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA512_LIBC3 1 + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_LIBSYSTEM supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA512_LIBSYSTEM 1 + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_NETTLE supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA512_NETTLE 1 + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_OPENSSL supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA512_OPENSSL 1 + +/* SHA512 via ARCHIVE_CRYPTO_SHA512_WIN supported. */ +#cmakedefine ARCHIVE_CRYPTO_SHA512_WIN 1 + +/* Version number of bsdcpio */ +#cmakedefine BSDCPIO_VERSION_STRING "${BSDCPIO_VERSION_STRING}" + +/* Version number of bsdtar */ +#cmakedefine BSDTAR_VERSION_STRING "${BSDTAR_VERSION_STRING}" + +/* Version number of bsdcat */ +#cmakedefine BSDCAT_VERSION_STRING "${BSDCAT_VERSION_STRING}" + +/* Define to 1 if you have the `acl_create_entry' function. */ +#cmakedefine HAVE_ACL_CREATE_ENTRY 1 + +/* Define to 1 if you have the `acl_get_fd_np' function. */ +#cmakedefine HAVE_ACL_GET_FD_NP 1 + +/* Define to 1 if you have the `acl_get_link' function. */ +#cmakedefine HAVE_ACL_GET_LINK 1 + +/* Define to 1 if you have the `acl_get_link_np' function. */ +#cmakedefine HAVE_ACL_GET_LINK_NP 1 + +/* Define to 1 if you have the `acl_get_perm' function. */ +#cmakedefine HAVE_ACL_GET_PERM 1 + +/* Define to 1 if you have the `acl_get_perm_np' function. */ +#cmakedefine HAVE_ACL_GET_PERM_NP 1 + +/* Define to 1 if you have the `acl_init' function. */ +#cmakedefine HAVE_ACL_INIT 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ACL_LIBACL_H 1 + +/* Define to 1 if the system has the type `acl_permset_t'. */ +#cmakedefine HAVE_ACL_PERMSET_T 1 + +/* Define to 1 if you have the `acl_set_fd' function. */ +#cmakedefine HAVE_ACL_SET_FD 1 + +/* Define to 1 if you have the `acl_set_fd_np' function. */ +#cmakedefine HAVE_ACL_SET_FD_NP 1 + +/* 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 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ATTR_XATTR_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_BCRYPT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_BSDXML_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_BZLIB_H 1 + +/* Define to 1 if you have the `chflags' function. */ +#cmakedefine HAVE_CHFLAGS 1 + +/* Define to 1 if you have the `chown' function. */ +#cmakedefine HAVE_CHOWN 1 + +/* Define to 1 if you have the `chroot' function. */ +#cmakedefine HAVE_CHROOT 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_COPYFILE_H 1 + +/* Define to 1 if you have the `ctime_r' function. */ +#cmakedefine HAVE_CTIME_R 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_CTYPE_H 1 + +/* 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 `INT32_MAX', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_INT32_MAX 1 + +/* Define to 1 if you have the declaration of `INT32_MIN', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_INT32_MIN 1 + +/* Define to 1 if you have the declaration of `INT64_MAX', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_INT64_MAX 1 + +/* Define to 1 if you have the declaration of `INT64_MIN', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_INT64_MIN 1 + +/* Define to 1 if you have the declaration of `INTMAX_MAX', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_INTMAX_MAX 1 + +/* Define to 1 if you have the declaration of `INTMAX_MIN', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_INTMAX_MIN 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 + +/* Define to 1 if you have the declaration of `SSIZE_MAX', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_SSIZE_MAX 1 + +/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_STRERROR_R 1 + +/* Define to 1 if you have the declaration of `UINT32_MAX', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_UINT32_MAX 1 + +/* Define to 1 if you have the declaration of `UINT64_MAX', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_UINT64_MAX 1 + +/* Define to 1 if you have the declaration of `UINTMAX_MAX', and to 0 if you + don't. */ +#cmakedefine HAVE_DECL_UINTMAX_MAX 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_DIRECT_H 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#cmakedefine HAVE_DIRENT_H 1 + +/* Define to 1 if you have the `dirfd' function. */ +#cmakedefine HAVE_DIRFD 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_DLFCN_H 1 + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +#cmakedefine HAVE_DOPRNT 1 + +/* Define to 1 if nl_langinfo supports D_MD_ORDER */ +#cmakedefine HAVE_D_MD_ORDER 1 + +/* A possible errno value for invalid file format errors */ +#cmakedefine HAVE_EFTYPE 1 + +/* A possible errno value for invalid file format errors */ +#cmakedefine HAVE_EILSEQ 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ERRNO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_EXPAT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_EXT2FS_EXT2_FS_H 1 + +/* Define to 1 if you have the `extattr_get_file' function. */ +#cmakedefine HAVE_EXTATTR_GET_FILE 1 + +/* Define to 1 if you have the `extattr_list_file' function. */ +#cmakedefine HAVE_EXTATTR_LIST_FILE 1 + +/* Define to 1 if you have the `extattr_set_fd' function. */ +#cmakedefine HAVE_EXTATTR_SET_FD 1 + +/* Define to 1 if you have the `extattr_set_file' function. */ +#cmakedefine HAVE_EXTATTR_SET_FILE 1 + +/* 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 `fchdir' function. */ +#cmakedefine HAVE_FCHDIR 1 + +/* Define to 1 if you have the `fchflags' function. */ +#cmakedefine HAVE_FCHFLAGS 1 + +/* Define to 1 if you have the `fchmod' function. */ +#cmakedefine HAVE_FCHMOD 1 + +/* Define to 1 if you have the `fchown' function. */ +#cmakedefine HAVE_FCHOWN 1 + +/* Define to 1 if you have the `fcntl' function. */ +#cmakedefine HAVE_FCNTL 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `fdopendir' function. */ +#cmakedefine HAVE_FDOPENDIR 1 + +/* Define to 1 if you have the `fgetea' function. */ +#cmakedefine HAVE_FGETEA 1 + +/* Define to 1 if you have the `fgetxattr' function. */ +#cmakedefine HAVE_FGETXATTR 1 + +/* Define to 1 if you have the `flistea' function. */ +#cmakedefine HAVE_FLISTEA 1 + +/* Define to 1 if you have the `flistxattr' function. */ +#cmakedefine HAVE_FLISTXATTR 1 + +/* Define to 1 if you have the `fork' function. */ +#cmakedefine HAVE_FORK 1 + +/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ +#cmakedefine HAVE_FSEEKO 1 + +/* Define to 1 if you have the `fsetea' function. */ +#cmakedefine HAVE_FSETEA 1 + +/* Define to 1 if you have the `fsetxattr' function. */ +#cmakedefine HAVE_FSETXATTR 1 + +/* Define to 1 if you have the `fstat' function. */ +#cmakedefine HAVE_FSTAT 1 + +/* Define to 1 if you have the `fstatat' function. */ +#cmakedefine HAVE_FSTATAT 1 + +/* Define to 1 if you have the `fstatfs' function. */ +#cmakedefine HAVE_FSTATFS 1 + +/* Define to 1 if you have the `fstatvfs' function. */ +#cmakedefine HAVE_FSTATVFS 1 + +/* Define to 1 if you have the `ftruncate' function. */ +#cmakedefine HAVE_FTRUNCATE 1 + +/* Define to 1 if you have the `futimens' function. */ +#cmakedefine HAVE_FUTIMENS 1 + +/* Define to 1 if you have the `futimes' function. */ +#cmakedefine HAVE_FUTIMES 1 + +/* Define to 1 if you have the `futimesat' function. */ +#cmakedefine HAVE_FUTIMESAT 1 + +/* Define to 1 if you have the `getea' function. */ +#cmakedefine HAVE_GETEA 1 + +/* Define to 1 if you have the `geteuid' function. */ +#cmakedefine HAVE_GETEUID 1 + +/* Define to 1 if you have the `getgrgid_r' function. */ +#cmakedefine HAVE_GETGRGID_R 1 + +/* Define to 1 if you have the `getgrnam_r' function. */ +#cmakedefine HAVE_GETGRNAM_R 1 + +/* Define to 1 if you have the `getpid' function. */ +#cmakedefine HAVE_GETPID 1 + +/* Define to 1 if you have the `getpwnam_r' function. */ +#cmakedefine HAVE_GETPWNAM_R 1 + +/* Define to 1 if you have the `getpwuid_r' function. */ +#cmakedefine HAVE_GETPWUID_R 1 + +/* Define to 1 if you have the `getvfsbyname' function. */ +#cmakedefine HAVE_GETVFSBYNAME 1 + +/* Define to 1 if you have the `getxattr' function. */ +#cmakedefine HAVE_GETXATTR 1 + +/* Define to 1 if you have the `gmtime_r' function. */ +#cmakedefine HAVE_GMTIME_R 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_GRP_H 1 + +/* Define to 1 if you have the `iconv' function. */ +#cmakedefine HAVE_ICONV 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ICONV_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_IO_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LANGINFO_H 1 + +/* Define to 1 if you have the `lchflags' function. */ +#cmakedefine HAVE_LCHFLAGS 1 + +/* Define to 1 if you have the `lchmod' function. */ +#cmakedefine HAVE_LCHMOD 1 + +/* Define to 1 if you have the `lchown' function. */ +#cmakedefine HAVE_LCHOWN 1 + +/* Define to 1 if you have the `lgetea' function. */ +#cmakedefine HAVE_LGETEA 1 + +/* Define to 1 if you have the `lgetxattr' function. */ +#cmakedefine HAVE_LGETXATTR 1 + +/* Define to 1 if you have the `acl' library (-lacl). */ +#cmakedefine HAVE_LIBACL 1 + +/* Define to 1 if you have the `attr' library (-lattr). */ +#cmakedefine HAVE_LIBATTR 1 + +/* Define to 1 if you have the `bsdxml' library (-lbsdxml). */ +#cmakedefine HAVE_LIBBSDXML 1 + +/* Define to 1 if you have the `bz2' library (-lbz2). */ +#cmakedefine HAVE_LIBBZ2 1 + +/* Define to 1 if you have the `charset' library (-lcharset). */ +#cmakedefine HAVE_LIBCHARSET 1 + +/* Define to 1 if you have the `crypto' library (-lcrypto). */ +#cmakedefine HAVE_LIBCRYPTO 1 + +/* Define to 1 if you have the `expat' library (-lexpat). */ +#cmakedefine HAVE_LIBEXPAT 1 + +/* Define to 1 if you have the `gcc' library (-lgcc). */ +#cmakedefine HAVE_LIBGCC 1 + +/* Define to 1 if you have the `lz4' library (-llz4). */ +#cmakedefine HAVE_LIBLZ4 1 + +/* Define to 1 if you have the `lzma' library (-llzma). */ +#cmakedefine HAVE_LIBLZMA 1 + +/* Define to 1 if you have the `lzmadec' library (-llzmadec). */ +#cmakedefine HAVE_LIBLZMADEC 1 + +/* Define to 1 if you have the `lzo2' library (-llzo2). */ +#cmakedefine HAVE_LIBLZO2 1 + +/* Define to 1 if you have the `nettle' library (-lnettle). */ +#cmakedefine HAVE_LIBNETTLE 1 + +/* Define to 1 if you have the `pcre' library (-lpcre). */ +#cmakedefine HAVE_LIBPCRE 1 + +/* Define to 1 if you have the `pcreposix' library (-lpcreposix). */ +#cmakedefine HAVE_LIBPCREPOSIX 1 + +/* Define to 1 if you have the `xml2' library (-lxml2). */ +#cmakedefine HAVE_LIBXML2 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LIBXML_XMLREADER_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LIBXML_XMLWRITER_H 1 + +/* Define to 1 if you have the `z' library (-lz). */ +#cmakedefine HAVE_LIBZ 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LIMITS_H 1 + +/* Define to 1 if you have the `link' function. */ +#cmakedefine HAVE_LINK 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LINUX_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LINUX_FIEMAP_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LINUX_FS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LINUX_MAGIC_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LINUX_TYPES_H 1 + +/* Define to 1 if you have the `listea' function. */ +#cmakedefine HAVE_LISTEA 1 + +/* Define to 1 if you have the `listxattr' function. */ +#cmakedefine HAVE_LISTXATTR 1 + +/* Define to 1 if you have the `llistea' function. */ +#cmakedefine HAVE_LLISTEA 1 + +/* Define to 1 if you have the `llistxattr' function. */ +#cmakedefine HAVE_LLISTXATTR 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LOCALCHARSET_H 1 + +/* Define to 1 if you have the `locale_charset' function. */ +#cmakedefine HAVE_LOCALE_CHARSET 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LOCALE_H 1 + +/* Define to 1 if you have the `localtime_r' function. */ +#cmakedefine HAVE_LOCALTIME_R 1 + +/* Define to 1 if the system has the type `long long int'. */ +#cmakedefine HAVE_LONG_LONG_INT 1 + +/* Define to 1 if you have the `lsetea' function. */ +#cmakedefine HAVE_LSETEA 1 + +/* Define to 1 if you have the `lsetxattr' function. */ +#cmakedefine HAVE_LSETXATTR 1 + +/* Define to 1 if you have the `lstat' function. */ +#cmakedefine HAVE_LSTAT 1 + +/* Define to 1 if `lstat' has the bug that it succeeds when given the + zero-length file name argument. */ +#cmakedefine HAVE_LSTAT_EMPTY_STRING_BUG 1 + +/* Define to 1 if you have the `lutimes' function. */ +#cmakedefine HAVE_LUTIMES 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LZ4HC_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LZ4_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LZMADEC_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LZMA_H 1 + +/* Define to 1 if you have a working `lzma_stream_encoder_mt' function. */ +#cmakedefine HAVE_LZMA_STREAM_ENCODER_MT 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LZO_LZO1X_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LZO_LZOCONF_H 1 + +/* Define to 1 if you have the `mbrtowc' function. */ +#cmakedefine HAVE_MBRTOWC 1 + +/* Define to 1 if you have the `memmove' function. */ +#cmakedefine HAVE_MEMMOVE 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mkdir' function. */ +#cmakedefine HAVE_MKDIR 1 + +/* Define to 1 if you have the `mkfifo' function. */ +#cmakedefine HAVE_MKFIFO 1 + +/* Define to 1 if you have the `mknod' function. */ +#cmakedefine HAVE_MKNOD 1 + +/* Define to 1 if you have the `mkstemp' function. */ +#cmakedefine HAVE_MKSTEMP 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +#cmakedefine HAVE_NDIR_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETTLE_AES_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETTLE_HMAC_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETTLE_MD5_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETTLE_PBKDF2_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETTLE_RIPEMD160_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_NETTLE_SHA_H 1 + +/* Define to 1 if you have the `nl_langinfo' function. */ +#cmakedefine HAVE_NL_LANGINFO 1 + +/* Define to 1 if you have the `openat' function. */ +#cmakedefine HAVE_OPENAT 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_PATHS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_PCREPOSIX_H 1 + +/* Define to 1 if you have the `pipe' function. */ +#cmakedefine HAVE_PIPE 1 + +/* Define to 1 if you have the `PKCS5_PBKDF2_HMAC_SHA1' function. */ +#cmakedefine HAVE_PKCS5_PBKDF2_HMAC_SHA1 1 + +/* Define to 1 if you have the `poll' function. */ +#cmakedefine HAVE_POLL 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_POLL_H 1 + +/* Define to 1 if you have the `posix_spawnp' function. */ +#cmakedefine HAVE_POSIX_SPAWNP 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_PROCESS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_PTHREAD_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_PWD_H 1 + +/* Define to 1 if you have the `readdir_r' function. */ +#cmakedefine HAVE_READDIR_R 1 + +/* Define to 1 if you have the `readlink' function. */ +#cmakedefine HAVE_READLINK 1 + +/* Define to 1 if you have the `readlinkat' function. */ +#cmakedefine HAVE_READLINKAT 1 + +/* Define to 1 if you have the `readpassphrase' function. */ +#cmakedefine HAVE_READPASSPHRASE 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_READPASSPHRASE_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_REGEX_H 1 + +/* Define to 1 if you have the `select' function. */ +#cmakedefine HAVE_SELECT 1 + +/* Define to 1 if you have the `setenv' function. */ +#cmakedefine HAVE_SETENV 1 + +/* Define to 1 if you have the `setlocale' function. */ +#cmakedefine HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `sigaction' function. */ +#cmakedefine HAVE_SIGACTION 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SPAWN_H 1 + +/* Define to 1 if you have the `statfs' function. */ +#cmakedefine HAVE_STATFS 1 + +/* Define to 1 if you have the `statvfs' function. */ +#cmakedefine HAVE_STATVFS 1 + +/* Define to 1 if `stat' has the bug that it succeeds when given the + zero-length file name argument. */ +#cmakedefine HAVE_STAT_EMPTY_STRING_BUG 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDARG_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strchr' function. */ +#cmakedefine HAVE_STRCHR 1 + +/* Define to 1 if you have the `strdup' function. */ +#cmakedefine HAVE_STRDUP 1 + +/* Define to 1 if you have the `strerror' function. */ +#cmakedefine HAVE_STRERROR 1 + +/* Define to 1 if you have the `strerror_r' function. */ +#cmakedefine HAVE_STRERROR_R 1 + +/* Define to 1 if you have the `strftime' function. */ +#cmakedefine HAVE_STRFTIME 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRING_H 1 + +/* Define to 1 if you have the `strrchr' function. */ +#cmakedefine HAVE_STRRCHR 1 + +/* Define to 1 if `f_namemax' is a member of `struct statfs'. */ +#cmakedefine HAVE_STRUCT_STATFS_F_NAMEMAX 1 + +/* Define to 1 if `f_iosize' is a member of `struct statvfs'. */ +#cmakedefine HAVE_STRUCT_STATVFS_F_IOSIZE 1 + +/* Define to 1 if `st_birthtime' is a member of `struct stat'. */ +#cmakedefine HAVE_STRUCT_STAT_ST_BIRTHTIME 1 + +/* Define to 1 if `st_birthtimespec.tv_nsec' is a member of `struct stat'. */ +#cmakedefine HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC 1 + +/* Define to 1 if `st_blksize' is a member of `struct stat'. */ +#cmakedefine HAVE_STRUCT_STAT_ST_BLKSIZE 1 + +/* Define to 1 if `st_flags' is a member of `struct stat'. */ +#cmakedefine HAVE_STRUCT_STAT_ST_FLAGS 1 + +/* Define to 1 if `st_mtimespec.tv_nsec' is a member of `struct stat'. */ +#cmakedefine HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1 + +/* Define to 1 if `st_mtime_n' is a member of `struct stat'. */ +#cmakedefine HAVE_STRUCT_STAT_ST_MTIME_N 1 + +/* Define to 1 if `st_mtime_usec' is a member of `struct stat'. */ +#cmakedefine HAVE_STRUCT_STAT_ST_MTIME_USEC 1 + +/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */ +#cmakedefine HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 1 + +/* Define to 1 if `st_umtime' is a member of `struct stat'. */ +#cmakedefine HAVE_STRUCT_STAT_ST_UMTIME 1 + +/* Define to 1 if `tm_gmtoff' is a member of `struct tm'. */ +#cmakedefine HAVE_STRUCT_TM_TM_GMTOFF 1 + +/* Define to 1 if `__tm_gmtoff' is a member of `struct tm'. */ +#cmakedefine HAVE_STRUCT_TM___TM_GMTOFF 1 + +/* Define to 1 if you have `struct vfsconf'. */ +#cmakedefine HAVE_STRUCT_VFSCONF 1 + +/* Define to 1 if you have `struct xvfsconf'. */ +#cmakedefine HAVE_STRUCT_XVFSCONF 1 + +/* Define to 1 if you have the `symlink' function. */ +#cmakedefine HAVE_SYMLINK 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_ACL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_CDEFS_H 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#cmakedefine HAVE_SYS_DIR_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_EA_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_EXTATTR_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_MKDEV_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_MOUNT_H 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#cmakedefine HAVE_SYS_NDIR_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_POLL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_STATFS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_STATVFS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_UTIME_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_UTSNAME_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_VFS_H 1 + +/* Define to 1 if you have that is POSIX.1 compatible. */ +#cmakedefine HAVE_SYS_WAIT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_XATTR_H 1 + +/* Define to 1 if you have the `timegm' function. */ +#cmakedefine HAVE_TIMEGM 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_TIME_H 1 + +/* Define to 1 if you have the `tzset' function. */ +#cmakedefine HAVE_TZSET 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `unsetenv' function. */ +#cmakedefine HAVE_UNSETENV 1 + +/* Define to 1 if the system has the type `unsigned long long'. */ +#cmakedefine HAVE_UNSIGNED_LONG_LONG 1 + +/* Define to 1 if the system has the type `unsigned long long int'. */ +#cmakedefine HAVE_UNSIGNED_LONG_LONG_INT 1 + +/* Define to 1 if you have the `utime' function. */ +#cmakedefine HAVE_UTIME 1 + +/* Define to 1 if you have the `utimensat' function. */ +#cmakedefine HAVE_UTIMENSAT 1 + +/* Define to 1 if you have the `utimes' function. */ +#cmakedefine HAVE_UTIMES 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UTIME_H 1 + +/* Define to 1 if you have the `vfork' function. */ +#cmakedefine HAVE_VFORK 1 + +/* Define to 1 if you have the `vprintf' function. */ +#cmakedefine HAVE_VPRINTF 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_WCHAR_H 1 + +/* Define to 1 if the system has the type `wchar_t'. */ +#cmakedefine HAVE_WCHAR_T 1 + +/* Define to 1 if you have the `wcrtomb' function. */ +#cmakedefine HAVE_WCRTOMB 1 + +/* Define to 1 if you have the `wcscmp' function. */ +#cmakedefine HAVE_WCSCMP 1 + +/* Define to 1 if you have the `wcscpy' function. */ +#cmakedefine HAVE_WCSCPY 1 + +/* Define to 1 if you have the `wcslen' function. */ +#cmakedefine HAVE_WCSLEN 1 + +/* Define to 1 if you have the `wctomb' function. */ +#cmakedefine HAVE_WCTOMB 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_WCTYPE_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_WINCRYPT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_WINDOWS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_WINIOCTL_H 1 + +/* Define to 1 if you have _CrtSetReportMode in */ +#cmakedefine HAVE__CrtSetReportMode 1 + +/* Define to 1 if you have the `wmemcmp' function. */ +#cmakedefine HAVE_WMEMCMP 1 + +/* Define to 1 if you have the `wmemcpy' function. */ +#cmakedefine HAVE_WMEMCPY 1 + +/* Define to 1 if you have the `wmemmove' function. */ +#cmakedefine HAVE_WMEMMOVE 1 + +/* Define to 1 if you have a working EXT2_IOC_GETFLAGS */ +#cmakedefine HAVE_WORKING_EXT2_IOC_GETFLAGS 1 + ++/* Define to 1 if you have a working FS_IOC_GETFLAGS */ ++#cmakedefine HAVE_WORKING_FS_IOC_GETFLAGS 1 ++ +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ZLIB_H 1 + +/* Define to 1 if you have the `_ctime64_s' function. */ +#cmakedefine HAVE__CTIME64_S 1 + +/* Define to 1 if you have the `_fseeki64' function. */ +#cmakedefine HAVE__FSEEKI64 1 + +/* Define to 1 if you have the `_get_timezone' function. */ +#cmakedefine HAVE__GET_TIMEZONE 1 + +/* Define to 1 if you have the `_localtime64_s' function. */ +#cmakedefine HAVE__LOCALTIME64_S 1 + +/* Define to 1 if you have the `_mkgmtime64' function. */ +#cmakedefine HAVE__MKGMTIME64 1 + +/* Define as const if the declaration of iconv() needs const. */ +#define ICONV_CONST ${ICONV_CONST} + +/* Version number of libarchive as a single integer */ +#cmakedefine LIBARCHIVE_VERSION_NUMBER "${LIBARCHIVE_VERSION_NUMBER}" + +/* Version number of libarchive */ +#cmakedefine LIBARCHIVE_VERSION_STRING "${LIBARCHIVE_VERSION_STRING}" + +/* Define to 1 if `lstat' dereferences a symlink specified with a trailing + slash. */ +#cmakedefine LSTAT_FOLLOWS_SLASHED_SYMLINK 1 + +/* Define to 1 if `major', `minor', and `makedev' are declared in . + */ +#cmakedefine MAJOR_IN_MKDEV 1 + +/* Define to 1 if `major', `minor', and `makedev' are declared in + . */ +#cmakedefine MAJOR_IN_SYSMACROS 1 + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +#cmakedefine NO_MINUS_C_MINUS_O 1 + +/* The size of `wchar_t', as computed by sizeof. */ +#cmakedefine SIZEOF_WCHAR_T ${SIZEOF_WCHAR_T} + +/* Define to 1 if strerror_r returns char *. */ +#cmakedefine STRERROR_R_CHAR_P 1 + +/* Define to 1 if you can safely include both and . */ +#cmakedefine TIME_WITH_SYS_TIME 1 + +/* + * Some platform requires a macro to use extension functions. + */ +#cmakedefine SAFE_TO_DEFINE_EXTENSIONS 1 +#ifdef SAFE_TO_DEFINE_EXTENSIONS +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# define _ALL_SOURCE 1 +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# define _POSIX_PTHREAD_SEMANTICS 1 +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# define _TANDEM_SOURCE 1 +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# define __EXTENSIONS__ 1 +#endif +#endif /* SAFE_TO_DEFINE_EXTENSIONS */ + +/* Version number of package */ +#cmakedefine VERSION "${VERSION}" + +/* Number of bits in a file offset, on hosts where this is settable. */ +#cmakedefine _FILE_OFFSET_BITS ${_FILE_OFFSET_BITS} + +/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ +#cmakedefine _LARGEFILE_SOURCE 1 + +/* Define for large files, on AIX-style hosts. */ +#cmakedefine _LARGE_FILES ${_LARGE_FILES} + +/* Define to control Windows SDK version */ +#ifndef NTDDI_VERSION +#cmakedefine NTDDI_VERSION ${NTDDI_VERSION} +#endif // NTDDI_VERSION + +#ifndef _WIN32_WINNT +#cmakedefine _WIN32_WINNT ${_WIN32_WINNT} +#endif // _WIN32_WINNT + +#ifndef WINVER +#cmakedefine WINVER ${WINVER} +#endif // WINVER + +/* Define to empty if `const' does not conform to ANSI C. */ +#cmakedefine const ${const} + +/* Define to `int' if doesn't define. */ +#cmakedefine gid_t ${gid_t} + +/* Define to `unsigned long' if does not define. */ +#cmakedefine id_t ${id_t} + +/* Define to `int' if does not define. */ +#cmakedefine mode_t ${mode_t} + +/* Define to `long long' if does not define. */ +#cmakedefine off_t ${off_t} + +/* Define to `int' if doesn't define. */ +#cmakedefine pid_t ${pid_t} + +/* Define to `unsigned int' if does not define. */ +#cmakedefine size_t ${size_t} + +/* Define to `int' if does not define. */ +#cmakedefine ssize_t ${ssize_t} + +/* Define to `int' if doesn't define. */ +#cmakedefine uid_t ${uid_t} + +/* Define to `int' if does not define. */ +#cmakedefine intptr_t ${intptr_t} + +/* Define to `unsigned int' if does not define. */ +#cmakedefine uintptr_t ${uintptr_t} diff --cc Utilities/cmlibarchive/libarchive/archive.h index 040f151,0000000..cfb5c48 mode 100644,000000..100644 --- a/Utilities/cmlibarchive/libarchive/archive.h +++ b/Utilities/cmlibarchive/libarchive/archive.h @@@ -1,1180 -1,0 +1,1184 @@@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: src/lib/libarchive/archive.h.in,v 1.50 2008/05/26 17:00:22 kientzle Exp $ + */ + +#ifndef ARCHIVE_H_INCLUDED +#define ARCHIVE_H_INCLUDED + +/* + * The version number is expressed as a single integer that makes it + * easy to compare versions at build time: for version a.b.c, the + * version number is printf("%d%03d%03d",a,b,c). For example, if you + * know your application requires version 2.12.108 or later, you can + * assert that ARCHIVE_VERSION_NUMBER >= 2012108. + */ +/* Note: Compiler will complain if this does not match archive_entry.h! */ - #define ARCHIVE_VERSION_NUMBER 3003000 ++#define ARCHIVE_VERSION_NUMBER 3003001 + +#include +#include /* for wchar_t */ +#include /* For FILE * */ +#include /* For time_t */ + +/* + * Note: archive.h is for use outside of libarchive; the configuration + * headers (config.h, archive_platform.h, etc.) are purely internal. + * Do NOT use HAVE_XXX configuration macros to control the behavior of + * this header! If you must conditionalize, use predefined compiler and/or + * platform macros. + */ +#if defined(__BORLANDC__) && __BORLANDC__ >= 0x560 +# include +#elif !defined(__WATCOMC__) && !defined(_MSC_VER) && !defined(__INTERIX) && !defined(__BORLANDC__) && !defined(_SCO_DS) && !defined(__osf__) +# include +#endif + +/* Get appropriate definitions of 64-bit integer */ +#if !defined(__LA_INT64_T_DEFINED) +/* Older code relied on the __LA_INT64_T macro; after 4.0 we'll switch to the typedef exclusively. */ +# if ARCHIVE_VERSION_NUMBER < 4000000 +#define __LA_INT64_T la_int64_t +# endif +#define __LA_INT64_T_DEFINED +# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__) +typedef __int64 la_int64_t; +# else +# include /* ssize_t */ +# if defined(_SCO_DS) || defined(__osf__) +typedef long long la_int64_t; +# else +typedef int64_t la_int64_t; +# endif +# endif +#endif + +/* The la_ssize_t should match the type used in 'struct stat' */ +#if !defined(__LA_SSIZE_T_DEFINED) +/* Older code relied on the __LA_SSIZE_T macro; after 4.0 we'll switch to the typedef exclusively. */ +# if ARCHIVE_VERSION_NUMBER < 4000000 +#define __LA_SSIZE_T la_ssize_t +# endif +#define __LA_SSIZE_T_DEFINED +# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__) +# if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_) +typedef ssize_t la_ssize_t; +# elif defined(_WIN64) +typedef __int64 la_ssize_t; +# else +typedef long la_ssize_t; +# endif +# else +# include /* ssize_t */ +typedef ssize_t la_ssize_t; +# endif +#endif + +/* Large file support for Android */ +#ifdef __ANDROID__ +#include "android_lf.h" +#endif + +/* + * On Windows, define LIBARCHIVE_STATIC if you're building or using a + * .lib. The default here assumes you're building a DLL. Only + * libarchive source should ever define __LIBARCHIVE_BUILD. + */ +#if ((defined __WIN32__) || (defined _WIN32) || defined(__CYGWIN__)) && (!defined LIBARCHIVE_STATIC) +# ifdef __LIBARCHIVE_BUILD +# ifdef __GNUC__ +# define __LA_DECL __attribute__((dllexport)) extern +# else +# define __LA_DECL __declspec(dllexport) +# endif +# else +# ifdef __GNUC__ +# define __LA_DECL +# else +# define __LA_DECL __declspec(dllimport) +# endif +# endif +#else +/* Static libraries or non-Windows needs no special declaration. */ +# define __LA_DECL +#endif + +#if defined(__GNUC__) && __GNUC__ >= 3 && !defined(__MINGW32__) +#define __LA_PRINTF(fmtarg, firstvararg) \ + __attribute__((__format__ (__printf__, fmtarg, firstvararg))) +#else +#define __LA_PRINTF(fmtarg, firstvararg) /* nothing */ +#endif + +/* CMake uses some deprecated APIs to build with old libarchive versions. */ +#define __LA_DEPRECATED + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The version number is provided as both a macro and a function. + * The macro identifies the installed header; the function identifies + * the library version (which may not be the same if you're using a + * dynamically-linked version of the library). Of course, if the + * header and library are very different, you should expect some + * strangeness. Don't do that. + */ +__LA_DECL int archive_version_number(void); + +/* + * Textual name/version of the library, useful for version displays. + */ - #define ARCHIVE_VERSION_ONLY_STRING "3.3.0" ++#define ARCHIVE_VERSION_ONLY_STRING "3.3.1" +#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING +__LA_DECL const char * archive_version_string(void); + +/* + * Detailed textual name/version of the library and its dependencies. + * This has the form: + * "libarchive x.y.z zlib/a.b.c liblzma/d.e.f ... etc ..." + * the list of libraries described here will vary depending on how + * libarchive was compiled. + */ +__LA_DECL const char * archive_version_details(void); + +/* + * Returns NULL if libarchive was compiled without the associated library. + * Otherwise, returns the version number that libarchive was compiled + * against. + */ +__LA_DECL const char * archive_zlib_version(void); +__LA_DECL const char * archive_liblzma_version(void); +__LA_DECL const char * archive_bzlib_version(void); +__LA_DECL const char * archive_liblz4_version(void); + +/* Declare our basic types. */ +struct archive; +struct archive_entry; + +/* + * Error codes: Use archive_errno() and archive_error_string() + * to retrieve details. Unless specified otherwise, all functions + * that return 'int' use these codes. + */ +#define ARCHIVE_EOF 1 /* Found end of archive. */ +#define ARCHIVE_OK 0 /* Operation was successful. */ +#define ARCHIVE_RETRY (-10) /* Retry might succeed. */ +#define ARCHIVE_WARN (-20) /* Partial success. */ +/* For example, if write_header "fails", then you can't push data. */ +#define ARCHIVE_FAILED (-25) /* Current operation cannot complete. */ +/* But if write_header is "fatal," then this archive is dead and useless. */ +#define ARCHIVE_FATAL (-30) /* No more operations are possible. */ + +/* + * As far as possible, archive_errno returns standard platform errno codes. + * Of course, the details vary by platform, so the actual definitions + * here are stored in "archive_platform.h". The symbols are listed here + * for reference; as a rule, clients should not need to know the exact + * platform-dependent error code. + */ +/* Unrecognized or invalid file format. */ +/* #define ARCHIVE_ERRNO_FILE_FORMAT */ +/* Illegal usage of the library. */ +/* #define ARCHIVE_ERRNO_PROGRAMMER_ERROR */ +/* Unknown or unclassified error. */ +/* #define ARCHIVE_ERRNO_MISC */ + +/* + * Callbacks are invoked to automatically read/skip/write/open/close the + * archive. You can provide your own for complex tasks (like breaking + * archives across multiple tapes) or use standard ones built into the + * library. + */ + +/* Returns pointer and size of next block of data from archive. */ +typedef la_ssize_t archive_read_callback(struct archive *, + void *_client_data, const void **_buffer); + +/* Skips at most request bytes from archive and returns the skipped amount. + * This may skip fewer bytes than requested; it may even skip zero bytes. + * If you do skip fewer bytes than requested, libarchive will invoke your + * read callback and discard data as necessary to make up the full skip. + */ +typedef la_int64_t archive_skip_callback(struct archive *, + void *_client_data, la_int64_t request); + +/* Seeks to specified location in the file and returns the position. + * Whence values are SEEK_SET, SEEK_CUR, SEEK_END from stdio.h. + * Return ARCHIVE_FATAL if the seek fails for any reason. + */ +typedef la_int64_t archive_seek_callback(struct archive *, + void *_client_data, la_int64_t offset, int whence); + +/* Returns size actually written, zero on EOF, -1 on error. */ +typedef la_ssize_t archive_write_callback(struct archive *, + void *_client_data, + const void *_buffer, size_t _length); + +typedef int archive_open_callback(struct archive *, void *_client_data); + +typedef int archive_close_callback(struct archive *, void *_client_data); + +/* Switches from one client data object to the next/prev client data object. + * This is useful for reading from different data blocks such as a set of files + * that make up one large file. + */ +typedef int archive_switch_callback(struct archive *, void *_client_data1, + void *_client_data2); + +/* + * Returns a passphrase used for encryption or decryption, NULL on nothing + * to do and give it up. + */ +typedef const char *archive_passphrase_callback(struct archive *, + void *_client_data); + +/* + * Codes to identify various stream filters. + */ +#define ARCHIVE_FILTER_NONE 0 +#define ARCHIVE_FILTER_GZIP 1 +#define ARCHIVE_FILTER_BZIP2 2 +#define ARCHIVE_FILTER_COMPRESS 3 +#define ARCHIVE_FILTER_PROGRAM 4 +#define ARCHIVE_FILTER_LZMA 5 +#define ARCHIVE_FILTER_XZ 6 +#define ARCHIVE_FILTER_UU 7 +#define ARCHIVE_FILTER_RPM 8 +#define ARCHIVE_FILTER_LZIP 9 +#define ARCHIVE_FILTER_LRZIP 10 +#define ARCHIVE_FILTER_LZOP 11 +#define ARCHIVE_FILTER_GRZIP 12 +#define ARCHIVE_FILTER_LZ4 13 + +#if ARCHIVE_VERSION_NUMBER < 4000000 +#define ARCHIVE_COMPRESSION_NONE ARCHIVE_FILTER_NONE +#define ARCHIVE_COMPRESSION_GZIP ARCHIVE_FILTER_GZIP +#define ARCHIVE_COMPRESSION_BZIP2 ARCHIVE_FILTER_BZIP2 +#define ARCHIVE_COMPRESSION_COMPRESS ARCHIVE_FILTER_COMPRESS +#define ARCHIVE_COMPRESSION_PROGRAM ARCHIVE_FILTER_PROGRAM +#define ARCHIVE_COMPRESSION_LZMA ARCHIVE_FILTER_LZMA +#define ARCHIVE_COMPRESSION_XZ ARCHIVE_FILTER_XZ +#define ARCHIVE_COMPRESSION_UU ARCHIVE_FILTER_UU +#define ARCHIVE_COMPRESSION_RPM ARCHIVE_FILTER_RPM +#define ARCHIVE_COMPRESSION_LZIP ARCHIVE_FILTER_LZIP +#define ARCHIVE_COMPRESSION_LRZIP ARCHIVE_FILTER_LRZIP +#endif + +/* + * Codes returned by archive_format. + * + * Top 16 bits identifies the format family (e.g., "tar"); lower + * 16 bits indicate the variant. This is updated by read_next_header. + * Note that the lower 16 bits will often vary from entry to entry. + * In some cases, this variation occurs as libarchive learns more about + * the archive (for example, later entries might utilize extensions that + * weren't necessary earlier in the archive; in this case, libarchive + * will change the format code to indicate the extended format that + * was used). In other cases, it's because different tools have + * modified the archive and so different parts of the archive + * actually have slightly different formats. (Both tar and cpio store + * format codes in each entry, so it is quite possible for each + * entry to be in a different format.) + */ +#define ARCHIVE_FORMAT_BASE_MASK 0xff0000 +#define ARCHIVE_FORMAT_CPIO 0x10000 +#define ARCHIVE_FORMAT_CPIO_POSIX (ARCHIVE_FORMAT_CPIO | 1) +#define ARCHIVE_FORMAT_CPIO_BIN_LE (ARCHIVE_FORMAT_CPIO | 2) +#define ARCHIVE_FORMAT_CPIO_BIN_BE (ARCHIVE_FORMAT_CPIO | 3) +#define ARCHIVE_FORMAT_CPIO_SVR4_NOCRC (ARCHIVE_FORMAT_CPIO | 4) +#define ARCHIVE_FORMAT_CPIO_SVR4_CRC (ARCHIVE_FORMAT_CPIO | 5) +#define ARCHIVE_FORMAT_CPIO_AFIO_LARGE (ARCHIVE_FORMAT_CPIO | 6) +#define ARCHIVE_FORMAT_SHAR 0x20000 +#define ARCHIVE_FORMAT_SHAR_BASE (ARCHIVE_FORMAT_SHAR | 1) +#define ARCHIVE_FORMAT_SHAR_DUMP (ARCHIVE_FORMAT_SHAR | 2) +#define ARCHIVE_FORMAT_TAR 0x30000 +#define ARCHIVE_FORMAT_TAR_USTAR (ARCHIVE_FORMAT_TAR | 1) +#define ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE (ARCHIVE_FORMAT_TAR | 2) +#define ARCHIVE_FORMAT_TAR_PAX_RESTRICTED (ARCHIVE_FORMAT_TAR | 3) +#define ARCHIVE_FORMAT_TAR_GNUTAR (ARCHIVE_FORMAT_TAR | 4) +#define ARCHIVE_FORMAT_ISO9660 0x40000 +#define ARCHIVE_FORMAT_ISO9660_ROCKRIDGE (ARCHIVE_FORMAT_ISO9660 | 1) +#define ARCHIVE_FORMAT_ZIP 0x50000 +#define ARCHIVE_FORMAT_EMPTY 0x60000 +#define ARCHIVE_FORMAT_AR 0x70000 +#define ARCHIVE_FORMAT_AR_GNU (ARCHIVE_FORMAT_AR | 1) +#define ARCHIVE_FORMAT_AR_BSD (ARCHIVE_FORMAT_AR | 2) +#define ARCHIVE_FORMAT_MTREE 0x80000 +#define ARCHIVE_FORMAT_RAW 0x90000 +#define ARCHIVE_FORMAT_XAR 0xA0000 +#define ARCHIVE_FORMAT_LHA 0xB0000 +#define ARCHIVE_FORMAT_CAB 0xC0000 +#define ARCHIVE_FORMAT_RAR 0xD0000 +#define ARCHIVE_FORMAT_7ZIP 0xE0000 +#define ARCHIVE_FORMAT_WARC 0xF0000 + +/* + * Codes returned by archive_read_format_capabilities(). + * + * This list can be extended with values between 0 and 0xffff. + * The original purpose of this list was to let different archive + * format readers expose their general capabilities in terms of + * encryption. + */ +#define ARCHIVE_READ_FORMAT_CAPS_NONE (0) /* no special capabilities */ +#define ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA (1<<0) /* reader can detect encrypted data */ +#define ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA (1<<1) /* reader can detect encryptable metadata (pathname, mtime, etc.) */ + +/* + * Codes returned by archive_read_has_encrypted_entries(). + * + * In case the archive does not support encryption detection at all + * ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED is returned. If the reader + * for some other reason (e.g. not enough bytes read) cannot say if + * there are encrypted entries, ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW + * is returned. + */ +#define ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED -2 +#define ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW -1 + +/*- + * Basic outline for reading an archive: + * 1) Ask archive_read_new for an archive reader object. + * 2) Update any global properties as appropriate. + * In particular, you'll certainly want to call appropriate + * archive_read_support_XXX functions. + * 3) Call archive_read_open_XXX to open the archive + * 4) Repeatedly call archive_read_next_header to get information about + * successive archive entries. Call archive_read_data to extract + * data for entries of interest. + * 5) Call archive_read_free to end processing. + */ +__LA_DECL struct archive *archive_read_new(void); + +/* + * The archive_read_support_XXX calls enable auto-detect for this + * archive handle. They also link in the necessary support code. + * For example, if you don't want bzlib linked in, don't invoke + * support_compression_bzip2(). The "all" functions provide the + * obvious shorthand. + */ + +#if ARCHIVE_VERSION_NUMBER < 4000000 +__LA_DECL int archive_read_support_compression_all(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_bzip2(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_compress(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_gzip(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_lzip(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_lzma(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_none(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_program(struct archive *, + const char *command) __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_program_signature + (struct archive *, const char *, + const void * /* match */, size_t) __LA_DEPRECATED; + +__LA_DECL int archive_read_support_compression_rpm(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_uu(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_read_support_compression_xz(struct archive *) + __LA_DEPRECATED; +#endif + +__LA_DECL int archive_read_support_filter_all(struct archive *); +__LA_DECL int archive_read_support_filter_bzip2(struct archive *); +__LA_DECL int archive_read_support_filter_compress(struct archive *); +__LA_DECL int archive_read_support_filter_gzip(struct archive *); +__LA_DECL int archive_read_support_filter_grzip(struct archive *); +__LA_DECL int archive_read_support_filter_lrzip(struct archive *); +__LA_DECL int archive_read_support_filter_lz4(struct archive *); +__LA_DECL int archive_read_support_filter_lzip(struct archive *); +__LA_DECL int archive_read_support_filter_lzma(struct archive *); +__LA_DECL int archive_read_support_filter_lzop(struct archive *); +__LA_DECL int archive_read_support_filter_none(struct archive *); +__LA_DECL int archive_read_support_filter_program(struct archive *, + const char *command); +__LA_DECL int archive_read_support_filter_program_signature + (struct archive *, const char * /* cmd */, + const void * /* match */, size_t); +__LA_DECL int archive_read_support_filter_rpm(struct archive *); +__LA_DECL int archive_read_support_filter_uu(struct archive *); +__LA_DECL int archive_read_support_filter_xz(struct archive *); + +__LA_DECL int archive_read_support_format_7zip(struct archive *); +__LA_DECL int archive_read_support_format_all(struct archive *); +__LA_DECL int archive_read_support_format_ar(struct archive *); +__LA_DECL int archive_read_support_format_by_code(struct archive *, int); +__LA_DECL int archive_read_support_format_cab(struct archive *); +__LA_DECL int archive_read_support_format_cpio(struct archive *); +__LA_DECL int archive_read_support_format_empty(struct archive *); +__LA_DECL int archive_read_support_format_gnutar(struct archive *); +__LA_DECL int archive_read_support_format_iso9660(struct archive *); +__LA_DECL int archive_read_support_format_lha(struct archive *); +__LA_DECL int archive_read_support_format_mtree(struct archive *); +__LA_DECL int archive_read_support_format_rar(struct archive *); +__LA_DECL int archive_read_support_format_raw(struct archive *); +__LA_DECL int archive_read_support_format_tar(struct archive *); +__LA_DECL int archive_read_support_format_warc(struct archive *); +__LA_DECL int archive_read_support_format_xar(struct archive *); +/* archive_read_support_format_zip() enables both streamable and seekable + * zip readers. */ +__LA_DECL int archive_read_support_format_zip(struct archive *); +/* Reads Zip archives as stream from beginning to end. Doesn't + * correctly handle SFX ZIP files or ZIP archives that have been modified + * in-place. */ +__LA_DECL int archive_read_support_format_zip_streamable(struct archive *); +/* Reads starting from central directory; requires seekable input. */ +__LA_DECL int archive_read_support_format_zip_seekable(struct archive *); + +/* Functions to manually set the format and filters to be used. This is + * useful to bypass the bidding process when the format and filters to use + * is known in advance. + */ +__LA_DECL int archive_read_set_format(struct archive *, int); +__LA_DECL int archive_read_append_filter(struct archive *, int); +__LA_DECL int archive_read_append_filter_program(struct archive *, + const char *); +__LA_DECL int archive_read_append_filter_program_signature + (struct archive *, const char *, const void * /* match */, size_t); + +/* Set various callbacks. */ +__LA_DECL int archive_read_set_open_callback(struct archive *, + archive_open_callback *); +__LA_DECL int archive_read_set_read_callback(struct archive *, + archive_read_callback *); +__LA_DECL int archive_read_set_seek_callback(struct archive *, + archive_seek_callback *); +__LA_DECL int archive_read_set_skip_callback(struct archive *, + archive_skip_callback *); +__LA_DECL int archive_read_set_close_callback(struct archive *, + archive_close_callback *); +/* Callback used to switch between one data object to the next */ +__LA_DECL int archive_read_set_switch_callback(struct archive *, + archive_switch_callback *); + +/* This sets the first data object. */ +__LA_DECL int archive_read_set_callback_data(struct archive *, void *); +/* This sets data object at specified index */ +__LA_DECL int archive_read_set_callback_data2(struct archive *, void *, + unsigned int); +/* This adds a data object at the specified index. */ +__LA_DECL int archive_read_add_callback_data(struct archive *, void *, + unsigned int); +/* This appends a data object to the end of list */ +__LA_DECL int archive_read_append_callback_data(struct archive *, void *); +/* This prepends a data object to the beginning of list */ +__LA_DECL int archive_read_prepend_callback_data(struct archive *, void *); + +/* Opening freezes the callbacks. */ +__LA_DECL int archive_read_open1(struct archive *); + +/* Convenience wrappers around the above. */ +__LA_DECL int archive_read_open(struct archive *, void *_client_data, + archive_open_callback *, archive_read_callback *, + archive_close_callback *); +__LA_DECL int archive_read_open2(struct archive *, void *_client_data, + archive_open_callback *, archive_read_callback *, + archive_skip_callback *, archive_close_callback *); + +/* + * A variety of shortcuts that invoke archive_read_open() with + * canned callbacks suitable for common situations. The ones that + * accept a block size handle tape blocking correctly. + */ +/* Use this if you know the filename. Note: NULL indicates stdin. */ +__LA_DECL int archive_read_open_filename(struct archive *, + const char *_filename, size_t _block_size); +/* Use this for reading multivolume files by filenames. + * NOTE: Must be NULL terminated. Sorting is NOT done. */ +__LA_DECL int archive_read_open_filenames(struct archive *, + const char **_filenames, size_t _block_size); +__LA_DECL int archive_read_open_filename_w(struct archive *, + const wchar_t *_filename, size_t _block_size); +/* archive_read_open_file() is a deprecated synonym for ..._open_filename(). */ +__LA_DECL int archive_read_open_file(struct archive *, + const char *_filename, size_t _block_size) __LA_DEPRECATED; +/* Read an archive that's stored in memory. */ +__LA_DECL int archive_read_open_memory(struct archive *, + const void * buff, size_t size); +/* A more involved version that is only used for internal testing. */ +__LA_DECL int archive_read_open_memory2(struct archive *a, const void *buff, + size_t size, size_t read_size); +/* Read an archive that's already open, using the file descriptor. */ +__LA_DECL int archive_read_open_fd(struct archive *, int _fd, + size_t _block_size); +/* Read an archive that's already open, using a FILE *. */ +/* Note: DO NOT use this with tape drives. */ +__LA_DECL int archive_read_open_FILE(struct archive *, FILE *_file); + +/* Parses and returns next entry header. */ +__LA_DECL int archive_read_next_header(struct archive *, + struct archive_entry **); + +/* Parses and returns next entry header using the archive_entry passed in */ +__LA_DECL int archive_read_next_header2(struct archive *, + struct archive_entry *); + +/* + * Retrieve the byte offset in UNCOMPRESSED data where last-read + * header started. + */ +__LA_DECL la_int64_t archive_read_header_position(struct archive *); + +/* + * Returns 1 if the archive contains at least one encrypted entry. + * If the archive format not support encryption at all + * ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED is returned. + * If for any other reason (e.g. not enough data read so far) + * we cannot say whether there are encrypted entries, then + * ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW is returned. + * In general, this function will return values below zero when the + * reader is uncertain or totally incapable of encryption support. + * When this function returns 0 you can be sure that the reader + * supports encryption detection but no encrypted entries have + * been found yet. + * + * NOTE: If the metadata/header of an archive is also encrypted, you + * cannot rely on the number of encrypted entries. That is why this + * function does not return the number of encrypted entries but# + * just shows that there are some. + */ +__LA_DECL int archive_read_has_encrypted_entries(struct archive *); + +/* + * Returns a bitmask of capabilities that are supported by the archive format reader. + * If the reader has no special capabilities, ARCHIVE_READ_FORMAT_CAPS_NONE is returned. + */ +__LA_DECL int archive_read_format_capabilities(struct archive *); + +/* Read data from the body of an entry. Similar to read(2). */ +__LA_DECL la_ssize_t archive_read_data(struct archive *, + void *, size_t); + +/* Seek within the body of an entry. Similar to lseek(2). */ +__LA_DECL la_int64_t archive_seek_data(struct archive *, la_int64_t, int); + +/* + * A zero-copy version of archive_read_data that also exposes the file offset + * of each returned block. Note that the client has no way to specify + * the desired size of the block. The API does guarantee that offsets will + * be strictly increasing and that returned blocks will not overlap. + */ +__LA_DECL int archive_read_data_block(struct archive *a, + const void **buff, size_t *size, la_int64_t *offset); + +/*- + * Some convenience functions that are built on archive_read_data: + * 'skip': skips entire entry + * 'into_buffer': writes data into memory buffer that you provide + * 'into_fd': writes data to specified filedes + */ +__LA_DECL int archive_read_data_skip(struct archive *); +__LA_DECL int archive_read_data_into_fd(struct archive *, int fd); + +/* + * Set read options. + */ +/* Apply option to the format only. */ +__LA_DECL int archive_read_set_format_option(struct archive *_a, + const char *m, const char *o, + const char *v); +/* Apply option to the filter only. */ +__LA_DECL int archive_read_set_filter_option(struct archive *_a, + const char *m, const char *o, + const char *v); +/* Apply option to both the format and the filter. */ +__LA_DECL int archive_read_set_option(struct archive *_a, + const char *m, const char *o, + const char *v); +/* Apply option string to both the format and the filter. */ +__LA_DECL int archive_read_set_options(struct archive *_a, + const char *opts); + +/* + * Add a decryption passphrase. + */ +__LA_DECL int archive_read_add_passphrase(struct archive *, const char *); +__LA_DECL int archive_read_set_passphrase_callback(struct archive *, + void *client_data, archive_passphrase_callback *); + + +/*- + * Convenience function to recreate the current entry (whose header + * has just been read) on disk. + * + * This does quite a bit more than just copy data to disk. It also: + * - Creates intermediate directories as required. + * - Manages directory permissions: non-writable directories will + * be initially created with write permission enabled; when the + * archive is closed, dir permissions are edited to the values specified + * in the archive. + * - Checks hardlinks: hardlinks will not be extracted unless the + * linked-to file was also extracted within the same session. (TODO) + */ + +/* The "flags" argument selects optional behavior, 'OR' the flags you want. */ + +/* Default: Do not try to set owner/group. */ +#define ARCHIVE_EXTRACT_OWNER (0x0001) +/* Default: Do obey umask, do not restore SUID/SGID/SVTX bits. */ +#define ARCHIVE_EXTRACT_PERM (0x0002) +/* Default: Do not restore mtime/atime. */ +#define ARCHIVE_EXTRACT_TIME (0x0004) +/* Default: Replace existing files. */ +#define ARCHIVE_EXTRACT_NO_OVERWRITE (0x0008) +/* Default: Try create first, unlink only if create fails with EEXIST. */ +#define ARCHIVE_EXTRACT_UNLINK (0x0010) +/* Default: Do not restore ACLs. */ +#define ARCHIVE_EXTRACT_ACL (0x0020) +/* Default: Do not restore fflags. */ +#define ARCHIVE_EXTRACT_FFLAGS (0x0040) +/* Default: Do not restore xattrs. */ +#define ARCHIVE_EXTRACT_XATTR (0x0080) +/* Default: Do not try to guard against extracts redirected by symlinks. */ +/* Note: With ARCHIVE_EXTRACT_UNLINK, will remove any intermediate symlink. */ +#define ARCHIVE_EXTRACT_SECURE_SYMLINKS (0x0100) +/* Default: Do not reject entries with '..' as path elements. */ +#define ARCHIVE_EXTRACT_SECURE_NODOTDOT (0x0200) +/* Default: Create parent directories as needed. */ +#define ARCHIVE_EXTRACT_NO_AUTODIR (0x0400) +/* Default: Overwrite files, even if one on disk is newer. */ +#define ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER (0x0800) +/* Detect blocks of 0 and write holes instead. */ +#define ARCHIVE_EXTRACT_SPARSE (0x1000) +/* Default: Do not restore Mac extended metadata. */ +/* This has no effect except on Mac OS. */ +#define ARCHIVE_EXTRACT_MAC_METADATA (0x2000) +/* Default: Use HFS+ compression if it was compressed. */ +/* This has no effect except on Mac OS v10.6 or later. */ +#define ARCHIVE_EXTRACT_NO_HFS_COMPRESSION (0x4000) +/* Default: Do not use HFS+ compression if it was not compressed. */ +/* This has no effect except on Mac OS v10.6 or later. */ +#define ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED (0x8000) +/* Default: Do not reject entries with absolute paths */ +#define ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS (0x10000) +/* Default: Do not clear no-change flags when unlinking object */ +#define ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS (0x20000) + +__LA_DECL int archive_read_extract(struct archive *, struct archive_entry *, + int flags); +__LA_DECL int archive_read_extract2(struct archive *, struct archive_entry *, + struct archive * /* dest */); +__LA_DECL void archive_read_extract_set_progress_callback(struct archive *, + void (*_progress_func)(void *), void *_user_data); + +/* Record the dev/ino of a file that will not be written. This is + * generally set to the dev/ino of the archive being read. */ +__LA_DECL void archive_read_extract_set_skip_file(struct archive *, + la_int64_t, la_int64_t); + +/* Close the file and release most resources. */ +__LA_DECL int archive_read_close(struct archive *); +/* Release all resources and destroy the object. */ +/* Note that archive_read_free will call archive_read_close for you. */ +__LA_DECL int archive_read_free(struct archive *); +#if ARCHIVE_VERSION_NUMBER < 4000000 +/* Synonym for archive_read_free() for backwards compatibility. */ +__LA_DECL int archive_read_finish(struct archive *) __LA_DEPRECATED; +#endif + +/*- + * To create an archive: + * 1) Ask archive_write_new for an archive writer object. + * 2) Set any global properties. In particular, you should set + * the compression and format to use. + * 3) Call archive_write_open to open the file (most people + * will use archive_write_open_file or archive_write_open_fd, + * which provide convenient canned I/O callbacks for you). + * 4) For each entry: + * - construct an appropriate struct archive_entry structure + * - archive_write_header to write the header + * - archive_write_data to write the entry data + * 5) archive_write_close to close the output + * 6) archive_write_free to cleanup the writer and release resources + */ +__LA_DECL struct archive *archive_write_new(void); +__LA_DECL int archive_write_set_bytes_per_block(struct archive *, + int bytes_per_block); +__LA_DECL int archive_write_get_bytes_per_block(struct archive *); +/* XXX This is badly misnamed; suggestions appreciated. XXX */ +__LA_DECL int archive_write_set_bytes_in_last_block(struct archive *, + int bytes_in_last_block); +__LA_DECL int archive_write_get_bytes_in_last_block(struct archive *); + +/* The dev/ino of a file that won't be archived. This is used + * to avoid recursively adding an archive to itself. */ +__LA_DECL int archive_write_set_skip_file(struct archive *, + la_int64_t, la_int64_t); + +#if ARCHIVE_VERSION_NUMBER < 4000000 +__LA_DECL int archive_write_set_compression_bzip2(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_compress(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_gzip(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_lzip(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_lzma(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_none(struct archive *) + __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_program(struct archive *, + const char *cmd) __LA_DEPRECATED; +__LA_DECL int archive_write_set_compression_xz(struct archive *) + __LA_DEPRECATED; +#endif + +/* A convenience function to set the filter based on the code. */ +__LA_DECL int archive_write_add_filter(struct archive *, int filter_code); +__LA_DECL int archive_write_add_filter_by_name(struct archive *, + const char *name); +__LA_DECL int archive_write_add_filter_b64encode(struct archive *); +__LA_DECL int archive_write_add_filter_bzip2(struct archive *); +__LA_DECL int archive_write_add_filter_compress(struct archive *); +__LA_DECL int archive_write_add_filter_grzip(struct archive *); +__LA_DECL int archive_write_add_filter_gzip(struct archive *); +__LA_DECL int archive_write_add_filter_lrzip(struct archive *); +__LA_DECL int archive_write_add_filter_lz4(struct archive *); +__LA_DECL int archive_write_add_filter_lzip(struct archive *); +__LA_DECL int archive_write_add_filter_lzma(struct archive *); +__LA_DECL int archive_write_add_filter_lzop(struct archive *); +__LA_DECL int archive_write_add_filter_none(struct archive *); +__LA_DECL int archive_write_add_filter_program(struct archive *, + const char *cmd); +__LA_DECL int archive_write_add_filter_uuencode(struct archive *); +__LA_DECL int archive_write_add_filter_xz(struct archive *); + + +/* A convenience function to set the format based on the code or name. */ +__LA_DECL int archive_write_set_format(struct archive *, int format_code); +__LA_DECL int archive_write_set_format_by_name(struct archive *, + const char *name); +/* To minimize link pollution, use one or more of the following. */ +__LA_DECL int archive_write_set_format_7zip(struct archive *); +__LA_DECL int archive_write_set_format_ar_bsd(struct archive *); +__LA_DECL int archive_write_set_format_ar_svr4(struct archive *); +__LA_DECL int archive_write_set_format_cpio(struct archive *); +__LA_DECL int archive_write_set_format_cpio_newc(struct archive *); +__LA_DECL int archive_write_set_format_gnutar(struct archive *); +__LA_DECL int archive_write_set_format_iso9660(struct archive *); +__LA_DECL int archive_write_set_format_mtree(struct archive *); +__LA_DECL int archive_write_set_format_mtree_classic(struct archive *); +/* TODO: int archive_write_set_format_old_tar(struct archive *); */ +__LA_DECL int archive_write_set_format_pax(struct archive *); +__LA_DECL int archive_write_set_format_pax_restricted(struct archive *); +__LA_DECL int archive_write_set_format_raw(struct archive *); +__LA_DECL int archive_write_set_format_shar(struct archive *); +__LA_DECL int archive_write_set_format_shar_dump(struct archive *); +__LA_DECL int archive_write_set_format_ustar(struct archive *); +__LA_DECL int archive_write_set_format_v7tar(struct archive *); +__LA_DECL int archive_write_set_format_warc(struct archive *); +__LA_DECL int archive_write_set_format_xar(struct archive *); +__LA_DECL int archive_write_set_format_zip(struct archive *); +__LA_DECL int archive_write_set_format_filter_by_ext(struct archive *a, const char *filename); +__LA_DECL int archive_write_set_format_filter_by_ext_def(struct archive *a, const char *filename, const char * def_ext); +__LA_DECL int archive_write_zip_set_compression_deflate(struct archive *); +__LA_DECL int archive_write_zip_set_compression_store(struct archive *); +__LA_DECL int archive_write_open(struct archive *, void *, + archive_open_callback *, archive_write_callback *, + archive_close_callback *); +__LA_DECL int archive_write_open_fd(struct archive *, int _fd); +__LA_DECL int archive_write_open_filename(struct archive *, const char *_file); +__LA_DECL int archive_write_open_filename_w(struct archive *, + const wchar_t *_file); +/* A deprecated synonym for archive_write_open_filename() */ +__LA_DECL int archive_write_open_file(struct archive *, const char *_file) + __LA_DEPRECATED; +__LA_DECL int archive_write_open_FILE(struct archive *, FILE *); +/* _buffSize is the size of the buffer, _used refers to a variable that + * will be updated after each write into the buffer. */ +__LA_DECL int archive_write_open_memory(struct archive *, + void *_buffer, size_t _buffSize, size_t *_used); + +/* + * Note that the library will truncate writes beyond the size provided + * to archive_write_header or pad if the provided data is short. + */ +__LA_DECL int archive_write_header(struct archive *, + struct archive_entry *); +__LA_DECL la_ssize_t archive_write_data(struct archive *, + const void *, size_t); + +/* This interface is currently only available for archive_write_disk handles. */ +__LA_DECL la_ssize_t archive_write_data_block(struct archive *, + const void *, size_t, la_int64_t); + +__LA_DECL int archive_write_finish_entry(struct archive *); +__LA_DECL int archive_write_close(struct archive *); +/* Marks the archive as FATAL so that a subsequent free() operation + * won't try to close() cleanly. Provides a fast abort capability + * when the client discovers that things have gone wrong. */ +__LA_DECL int archive_write_fail(struct archive *); +/* This can fail if the archive wasn't already closed, in which case + * archive_write_free() will implicitly call archive_write_close(). */ +__LA_DECL int archive_write_free(struct archive *); +#if ARCHIVE_VERSION_NUMBER < 4000000 +/* Synonym for archive_write_free() for backwards compatibility. */ +__LA_DECL int archive_write_finish(struct archive *) __LA_DEPRECATED; +#endif + +/* + * Set write options. + */ +/* Apply option to the format only. */ +__LA_DECL int archive_write_set_format_option(struct archive *_a, + const char *m, const char *o, + const char *v); +/* Apply option to the filter only. */ +__LA_DECL int archive_write_set_filter_option(struct archive *_a, + const char *m, const char *o, + const char *v); +/* Apply option to both the format and the filter. */ +__LA_DECL int archive_write_set_option(struct archive *_a, + const char *m, const char *o, + const char *v); +/* Apply option string to both the format and the filter. */ +__LA_DECL int archive_write_set_options(struct archive *_a, + const char *opts); + +/* + * Set a encryption passphrase. + */ +__LA_DECL int archive_write_set_passphrase(struct archive *_a, const char *p); +__LA_DECL int archive_write_set_passphrase_callback(struct archive *, + void *client_data, archive_passphrase_callback *); + +/*- + * ARCHIVE_WRITE_DISK API + * + * To create objects on disk: + * 1) Ask archive_write_disk_new for a new archive_write_disk object. + * 2) Set any global properties. In particular, you probably + * want to set the options. + * 3) For each entry: + * - construct an appropriate struct archive_entry structure + * - archive_write_header to create the file/dir/etc on disk + * - archive_write_data to write the entry data + * 4) archive_write_free to cleanup the writer and release resources + * + * In particular, you can use this in conjunction with archive_read() + * to pull entries out of an archive and create them on disk. + */ +__LA_DECL struct archive *archive_write_disk_new(void); +/* This file will not be overwritten. */ +__LA_DECL int archive_write_disk_set_skip_file(struct archive *, + la_int64_t, la_int64_t); +/* Set flags to control how the next item gets created. + * This accepts a bitmask of ARCHIVE_EXTRACT_XXX flags defined above. */ +__LA_DECL int archive_write_disk_set_options(struct archive *, + int flags); +/* + * The lookup functions are given uname/uid (or gname/gid) pairs and + * return a uid (gid) suitable for this system. These are used for + * restoring ownership and for setting ACLs. The default functions + * are naive, they just return the uid/gid. These are small, so reasonable + * for applications that don't need to preserve ownership; they + * are probably also appropriate for applications that are doing + * same-system backup and restore. + */ +/* + * The "standard" lookup functions use common system calls to lookup + * the uname/gname, falling back to the uid/gid if the names can't be + * found. They cache lookups and are reasonably fast, but can be very + * large, so they are not used unless you ask for them. In + * particular, these match the specifications of POSIX "pax" and old + * POSIX "tar". + */ +__LA_DECL int archive_write_disk_set_standard_lookup(struct archive *); +/* + * If neither the default (naive) nor the standard (big) functions suit + * your needs, you can write your own and register them. Be sure to + * include a cleanup function if you have allocated private data. + */ +__LA_DECL int archive_write_disk_set_group_lookup(struct archive *, + void * /* private_data */, + la_int64_t (*)(void *, const char *, la_int64_t), + void (* /* cleanup */)(void *)); +__LA_DECL int archive_write_disk_set_user_lookup(struct archive *, + void * /* private_data */, + la_int64_t (*)(void *, const char *, la_int64_t), + void (* /* cleanup */)(void *)); +__LA_DECL la_int64_t archive_write_disk_gid(struct archive *, const char *, la_int64_t); +__LA_DECL la_int64_t archive_write_disk_uid(struct archive *, const char *, la_int64_t); + +/* + * ARCHIVE_READ_DISK API + * + * This is still evolving and somewhat experimental. + */ +__LA_DECL struct archive *archive_read_disk_new(void); +/* The names for symlink modes here correspond to an old BSD + * command-line argument convention: -L, -P, -H */ +/* Follow all symlinks. */ +__LA_DECL int archive_read_disk_set_symlink_logical(struct archive *); +/* Follow no symlinks. */ +__LA_DECL int archive_read_disk_set_symlink_physical(struct archive *); +/* Follow symlink initially, then not. */ +__LA_DECL int archive_read_disk_set_symlink_hybrid(struct archive *); +/* TODO: Handle Linux stat32/stat64 ugliness. */ +__LA_DECL int archive_read_disk_entry_from_file(struct archive *, + struct archive_entry *, int /* fd */, const struct stat *); +/* Look up gname for gid or uname for uid. */ +/* Default implementations are very, very stupid. */ +__LA_DECL const char *archive_read_disk_gname(struct archive *, la_int64_t); +__LA_DECL const char *archive_read_disk_uname(struct archive *, la_int64_t); +/* "Standard" implementation uses getpwuid_r, getgrgid_r and caches the + * results for performance. */ +__LA_DECL int archive_read_disk_set_standard_lookup(struct archive *); +/* You can install your own lookups if you like. */ +__LA_DECL int archive_read_disk_set_gname_lookup(struct archive *, + void * /* private_data */, + const char *(* /* lookup_fn */)(void *, la_int64_t), + void (* /* cleanup_fn */)(void *)); +__LA_DECL int archive_read_disk_set_uname_lookup(struct archive *, + void * /* private_data */, + const char *(* /* lookup_fn */)(void *, la_int64_t), + void (* /* cleanup_fn */)(void *)); +/* Start traversal. */ +__LA_DECL int archive_read_disk_open(struct archive *, const char *); +__LA_DECL int archive_read_disk_open_w(struct archive *, const wchar_t *); +/* + * Request that current entry be visited. If you invoke it on every + * directory, you'll get a physical traversal. This is ignored if the + * current entry isn't a directory or a link to a directory. So, if + * you invoke this on every returned path, you'll get a full logical + * traversal. + */ +__LA_DECL int archive_read_disk_descend(struct archive *); +__LA_DECL int archive_read_disk_can_descend(struct archive *); +__LA_DECL int archive_read_disk_current_filesystem(struct archive *); +__LA_DECL int archive_read_disk_current_filesystem_is_synthetic(struct archive *); +__LA_DECL int archive_read_disk_current_filesystem_is_remote(struct archive *); +/* Request that the access time of the entry visited by traversal be restored. */ +__LA_DECL int archive_read_disk_set_atime_restored(struct archive *); +/* + * Set behavior. The "flags" argument selects optional behavior. + */ +/* Request that the access time of the entry visited by traversal be restored. + * This is the same as archive_read_disk_set_atime_restored. */ +#define ARCHIVE_READDISK_RESTORE_ATIME (0x0001) +/* Default: Do not skip an entry which has nodump flags. */ +#define ARCHIVE_READDISK_HONOR_NODUMP (0x0002) +/* Default: Skip a mac resource fork file whose prefix is "._" because of + * using copyfile. */ +#define ARCHIVE_READDISK_MAC_COPYFILE (0x0004) +/* Default: Traverse mount points. */ +#define ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS (0x0008) +/* Default: Xattrs are read from disk. */ +#define ARCHIVE_READDISK_NO_XATTR (0x0010) ++/* Default: ACLs are read from disk. */ ++#define ARCHIVE_READDISK_NO_ACL (0x0020) ++/* Default: File flags are read from disk. */ ++#define ARCHIVE_READDISK_NO_FFLAGS (0x0040) + +__LA_DECL int archive_read_disk_set_behavior(struct archive *, + int flags); + +/* + * Set archive_match object that will be used in archive_read_disk to + * know whether an entry should be skipped. The callback function + * _excluded_func will be invoked when an entry is skipped by the result + * of archive_match. + */ +__LA_DECL int archive_read_disk_set_matching(struct archive *, + struct archive *_matching, void (*_excluded_func) + (struct archive *, void *, struct archive_entry *), + void *_client_data); +__LA_DECL int archive_read_disk_set_metadata_filter_callback(struct archive *, + int (*_metadata_filter_func)(struct archive *, void *, + struct archive_entry *), void *_client_data); + +/* Simplified cleanup interface; + * This calls archive_read_free() or archive_write_free() as needed. */ +__LA_DECL int archive_free(struct archive *); + +/* + * Accessor functions to read/set various information in + * the struct archive object: + */ + +/* Number of filters in the current filter pipeline. */ +/* Filter #0 is the one closest to the format, -1 is a synonym for the + * last filter, which is always the pseudo-filter that wraps the + * client callbacks. */ +__LA_DECL int archive_filter_count(struct archive *); +__LA_DECL la_int64_t archive_filter_bytes(struct archive *, int); +__LA_DECL int archive_filter_code(struct archive *, int); +__LA_DECL const char * archive_filter_name(struct archive *, int); + +#if ARCHIVE_VERSION_NUMBER < 4000000 +/* These don't properly handle multiple filters, so are deprecated and + * will eventually be removed. */ +/* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, -1); */ +__LA_DECL la_int64_t archive_position_compressed(struct archive *) + __LA_DEPRECATED; +/* As of libarchive 3.0, this is an alias for archive_filter_bytes(a, 0); */ +__LA_DECL la_int64_t archive_position_uncompressed(struct archive *) + __LA_DEPRECATED; +/* As of libarchive 3.0, this is an alias for archive_filter_name(a, 0); */ +__LA_DECL const char *archive_compression_name(struct archive *) + __LA_DEPRECATED; +/* As of libarchive 3.0, this is an alias for archive_filter_code(a, 0); */ +__LA_DECL int archive_compression(struct archive *) + __LA_DEPRECATED; +#endif + +__LA_DECL int archive_errno(struct archive *); +__LA_DECL const char *archive_error_string(struct archive *); +__LA_DECL const char *archive_format_name(struct archive *); +__LA_DECL int archive_format(struct archive *); +__LA_DECL void archive_clear_error(struct archive *); +__LA_DECL void archive_set_error(struct archive *, int _err, + const char *fmt, ...) __LA_PRINTF(3, 4); +__LA_DECL void archive_copy_error(struct archive *dest, + struct archive *src); +__LA_DECL int archive_file_count(struct archive *); + +/* + * ARCHIVE_MATCH API + */ +__LA_DECL struct archive *archive_match_new(void); +__LA_DECL int archive_match_free(struct archive *); + +/* + * Test if archive_entry is excluded. + * This is a convenience function. This is the same as calling all + * archive_match_path_excluded, archive_match_time_excluded + * and archive_match_owner_excluded. + */ +__LA_DECL int archive_match_excluded(struct archive *, + struct archive_entry *); + +/* + * Test if pathname is excluded. The conditions are set by following functions. + */ +__LA_DECL int archive_match_path_excluded(struct archive *, + struct archive_entry *); +/* Add exclusion pathname pattern. */ +__LA_DECL int archive_match_exclude_pattern(struct archive *, const char *); +__LA_DECL int archive_match_exclude_pattern_w(struct archive *, + const wchar_t *); +/* Add exclusion pathname pattern from file. */ +__LA_DECL int archive_match_exclude_pattern_from_file(struct archive *, + const char *, int _nullSeparator); +__LA_DECL int archive_match_exclude_pattern_from_file_w(struct archive *, + const wchar_t *, int _nullSeparator); +/* Add inclusion pathname pattern. */ +__LA_DECL int archive_match_include_pattern(struct archive *, const char *); +__LA_DECL int archive_match_include_pattern_w(struct archive *, + const wchar_t *); +/* Add inclusion pathname pattern from file. */ +__LA_DECL int archive_match_include_pattern_from_file(struct archive *, + const char *, int _nullSeparator); +__LA_DECL int archive_match_include_pattern_from_file_w(struct archive *, + const wchar_t *, int _nullSeparator); +/* + * How to get statistic information for inclusion patterns. + */ +/* Return the amount number of unmatched inclusion patterns. */ +__LA_DECL int archive_match_path_unmatched_inclusions(struct archive *); +/* Return the pattern of unmatched inclusion with ARCHIVE_OK. + * Return ARCHIVE_EOF if there is no inclusion pattern. */ +__LA_DECL int archive_match_path_unmatched_inclusions_next( + struct archive *, const char **); +__LA_DECL int archive_match_path_unmatched_inclusions_next_w( + struct archive *, const wchar_t **); + +/* + * Test if a file is excluded by its time stamp. + * The conditions are set by following functions. + */ +__LA_DECL int archive_match_time_excluded(struct archive *, + struct archive_entry *); + +/* + * Flags to tell a matching type of time stamps. These are used for + * following functions. + */ +/* Time flag: mtime to be tested. */ +#define ARCHIVE_MATCH_MTIME (0x0100) +/* Time flag: ctime to be tested. */ +#define ARCHIVE_MATCH_CTIME (0x0200) +/* Comparison flag: Match the time if it is newer than. */ +#define ARCHIVE_MATCH_NEWER (0x0001) +/* Comparison flag: Match the time if it is older than. */ +#define ARCHIVE_MATCH_OLDER (0x0002) +/* Comparison flag: Match the time if it is equal to. */ +#define ARCHIVE_MATCH_EQUAL (0x0010) +/* Set inclusion time. */ +__LA_DECL int archive_match_include_time(struct archive *, int _flag, + time_t _sec, long _nsec); +/* Set inclusion time by a date string. */ +__LA_DECL int archive_match_include_date(struct archive *, int _flag, + const char *_datestr); +__LA_DECL int archive_match_include_date_w(struct archive *, int _flag, + const wchar_t *_datestr); +/* Set inclusion time by a particular file. */ +__LA_DECL int archive_match_include_file_time(struct archive *, + int _flag, const char *_pathname); +__LA_DECL int archive_match_include_file_time_w(struct archive *, + int _flag, const wchar_t *_pathname); +/* Add exclusion entry. */ +__LA_DECL int archive_match_exclude_entry(struct archive *, + int _flag, struct archive_entry *); + +/* + * Test if a file is excluded by its uid ,gid, uname or gname. + * The conditions are set by following functions. + */ +__LA_DECL int archive_match_owner_excluded(struct archive *, + struct archive_entry *); +/* Add inclusion uid, gid, uname and gname. */ +__LA_DECL int archive_match_include_uid(struct archive *, la_int64_t); +__LA_DECL int archive_match_include_gid(struct archive *, la_int64_t); +__LA_DECL int archive_match_include_uname(struct archive *, const char *); +__LA_DECL int archive_match_include_uname_w(struct archive *, + const wchar_t *); +__LA_DECL int archive_match_include_gname(struct archive *, const char *); +__LA_DECL int archive_match_include_gname_w(struct archive *, + const wchar_t *); + +/* Utility functions */ +/* Convenience function to sort a NULL terminated list of strings */ +__LA_DECL int archive_utility_string_sort(char **); + +#ifdef __cplusplus +} +#endif + +/* These are meaningless outside of this header. */ +#undef __LA_DECL + +#endif /* !ARCHIVE_H_INCLUDED */ diff --cc Utilities/cmlibarchive/libarchive/archive_entry.h index c331117,0000000..6e0225b mode 100644,000000..100644 --- a/Utilities/cmlibarchive/libarchive/archive_entry.h +++ b/Utilities/cmlibarchive/libarchive/archive_entry.h @@@ -1,699 -1,0 +1,699 @@@ +/*- + * Copyright (c) 2003-2008 Tim Kientzle + * Copyright (c) 2016 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: head/lib/libarchive/archive_entry.h 201096 2009-12-28 02:41:27Z kientzle $ + */ + +#ifndef ARCHIVE_ENTRY_H_INCLUDED +#define ARCHIVE_ENTRY_H_INCLUDED + +/* Note: Compiler will complain if this does not match archive.h! */ - #define ARCHIVE_VERSION_NUMBER 3003000 ++#define ARCHIVE_VERSION_NUMBER 3003001 + +/* + * Note: archive_entry.h is for use outside of libarchive; the + * configuration headers (config.h, archive_platform.h, etc.) are + * purely internal. Do NOT use HAVE_XXX configuration macros to + * control the behavior of this header! If you must conditionalize, + * use predefined compiler and/or platform macros. + */ + +#include +#include /* for wchar_t */ +#include + +#if defined(_WIN32) && !defined(__CYGWIN__) +#include +#endif + +/* Get a suitable 64-bit integer type. */ +#if !defined(__LA_INT64_T_DEFINED) +# if ARCHIVE_VERSION_NUMBER < 4000000 +#define __LA_INT64_T la_int64_t +# endif +#define __LA_INT64_T_DEFINED +# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__) +typedef __int64 la_int64_t; +# else +#include +# if defined(_SCO_DS) || defined(__osf__) +typedef long long la_int64_t; +# else +typedef int64_t la_int64_t; +# endif +# endif +#endif + +/* The la_ssize_t should match the type used in 'struct stat' */ +#if !defined(__LA_SSIZE_T_DEFINED) +/* Older code relied on the __LA_SSIZE_T macro; after 4.0 we'll switch to the typedef exclusively. */ +# if ARCHIVE_VERSION_NUMBER < 4000000 +#define __LA_SSIZE_T la_ssize_t +# endif +#define __LA_SSIZE_T_DEFINED +# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__) +# if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_) +typedef ssize_t la_ssize_t; +# elif defined(_WIN64) +typedef __int64 la_ssize_t; +# else +typedef long la_ssize_t; +# endif +# else +# include /* ssize_t */ +typedef ssize_t la_ssize_t; +# endif +#endif + +/* Get a suitable definition for mode_t */ +#if ARCHIVE_VERSION_NUMBER >= 3999000 +/* Switch to plain 'int' for libarchive 4.0. It's less broken than 'mode_t' */ +# define __LA_MODE_T int +#elif defined(_WIN32) && !defined(__CYGWIN__) && !defined(__BORLANDC__) && !defined(__WATCOMC__) +# define __LA_MODE_T unsigned short +#else +# define __LA_MODE_T mode_t +#endif + +/* Large file support for Android */ +#ifdef __ANDROID__ +#include "android_lf.h" +#endif + +/* + * On Windows, define LIBARCHIVE_STATIC if you're building or using a + * .lib. The default here assumes you're building a DLL. Only + * libarchive source should ever define __LIBARCHIVE_BUILD. + */ +#if ((defined __WIN32__) || (defined _WIN32) || defined(__CYGWIN__)) && (!defined LIBARCHIVE_STATIC) +# ifdef __LIBARCHIVE_BUILD +# ifdef __GNUC__ +# define __LA_DECL __attribute__((dllexport)) extern +# else +# define __LA_DECL __declspec(dllexport) +# endif +# else +# ifdef __GNUC__ +# define __LA_DECL +# else +# define __LA_DECL __declspec(dllimport) +# endif +# endif +#else +/* Static libraries on all platforms and shared libraries on non-Windows. */ +# define __LA_DECL +#endif + +/* CMake uses some deprecated APIs to build with old libarchive versions. */ +#define __LA_DEPRECATED + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Description of an archive entry. + * + * You can think of this as "struct stat" with some text fields added in. + * + * TODO: Add "comment", "charset", and possibly other entries that are + * supported by "pax interchange" format. However, GNU, ustar, cpio, + * and other variants don't support these features, so they're not an + * excruciatingly high priority right now. + * + * TODO: "pax interchange" format allows essentially arbitrary + * key/value attributes to be attached to any entry. Supporting + * such extensions may make this library useful for special + * applications (e.g., a package manager could attach special + * package-management attributes to each entry). + */ +struct archive; +struct archive_entry; + +/* + * File-type constants. These are returned from archive_entry_filetype() + * and passed to archive_entry_set_filetype(). + * + * These values match S_XXX defines on every platform I've checked, + * including Windows, AIX, Linux, Solaris, and BSD. They're + * (re)defined here because platforms generally don't define the ones + * they don't support. For example, Windows doesn't define S_IFLNK or + * S_IFBLK. Instead of having a mass of conditional logic and system + * checks to define any S_XXX values that aren't supported locally, + * I've just defined a new set of such constants so that + * libarchive-based applications can manipulate and identify archive + * entries properly even if the hosting platform can't store them on + * disk. + * + * These values are also used directly within some portable formats, + * such as cpio. If you find a platform that varies from these, the + * correct solution is to leave these alone and translate from these + * portable values to platform-native values when entries are read from + * or written to disk. + */ +/* + * In libarchive 4.0, we can drop the casts here. + * They're needed to work around Borland C's broken mode_t. + */ +#define AE_IFMT ((__LA_MODE_T)0170000) +#define AE_IFREG ((__LA_MODE_T)0100000) +#define AE_IFLNK ((__LA_MODE_T)0120000) +#define AE_IFSOCK ((__LA_MODE_T)0140000) +#define AE_IFCHR ((__LA_MODE_T)0020000) +#define AE_IFBLK ((__LA_MODE_T)0060000) +#define AE_IFDIR ((__LA_MODE_T)0040000) +#define AE_IFIFO ((__LA_MODE_T)0010000) + +/* + * Basic object manipulation + */ + +__LA_DECL struct archive_entry *archive_entry_clear(struct archive_entry *); +/* The 'clone' function does a deep copy; all of the strings are copied too. */ +__LA_DECL struct archive_entry *archive_entry_clone(struct archive_entry *); +__LA_DECL void archive_entry_free(struct archive_entry *); +__LA_DECL struct archive_entry *archive_entry_new(void); + +/* + * This form of archive_entry_new2() will pull character-set + * conversion information from the specified archive handle. The + * older archive_entry_new(void) form is equivalent to calling + * archive_entry_new2(NULL) and will result in the use of an internal + * default character-set conversion. + */ +__LA_DECL struct archive_entry *archive_entry_new2(struct archive *); + +/* + * Retrieve fields from an archive_entry. + * + * There are a number of implicit conversions among these fields. For + * example, if a regular string field is set and you read the _w wide + * character field, the entry will implicitly convert narrow-to-wide + * using the current locale. Similarly, dev values are automatically + * updated when you write devmajor or devminor and vice versa. + * + * In addition, fields can be "set" or "unset." Unset string fields + * return NULL, non-string fields have _is_set() functions to test + * whether they've been set. You can "unset" a string field by + * assigning NULL; non-string fields have _unset() functions to + * unset them. + * + * Note: There is one ambiguity in the above; string fields will + * also return NULL when implicit character set conversions fail. + * This is usually what you want. + */ +__LA_DECL time_t archive_entry_atime(struct archive_entry *); +__LA_DECL long archive_entry_atime_nsec(struct archive_entry *); +__LA_DECL int archive_entry_atime_is_set(struct archive_entry *); +__LA_DECL time_t archive_entry_birthtime(struct archive_entry *); +__LA_DECL long archive_entry_birthtime_nsec(struct archive_entry *); +__LA_DECL int archive_entry_birthtime_is_set(struct archive_entry *); +__LA_DECL time_t archive_entry_ctime(struct archive_entry *); +__LA_DECL long archive_entry_ctime_nsec(struct archive_entry *); +__LA_DECL int archive_entry_ctime_is_set(struct archive_entry *); +__LA_DECL dev_t archive_entry_dev(struct archive_entry *); +__LA_DECL int archive_entry_dev_is_set(struct archive_entry *); +__LA_DECL dev_t archive_entry_devmajor(struct archive_entry *); +__LA_DECL dev_t archive_entry_devminor(struct archive_entry *); +__LA_DECL __LA_MODE_T archive_entry_filetype(struct archive_entry *); +__LA_DECL void archive_entry_fflags(struct archive_entry *, + unsigned long * /* set */, + unsigned long * /* clear */); +__LA_DECL const char *archive_entry_fflags_text(struct archive_entry *); +__LA_DECL la_int64_t archive_entry_gid(struct archive_entry *); +__LA_DECL const char *archive_entry_gname(struct archive_entry *); +__LA_DECL const char *archive_entry_gname_utf8(struct archive_entry *); +__LA_DECL const wchar_t *archive_entry_gname_w(struct archive_entry *); +__LA_DECL const char *archive_entry_hardlink(struct archive_entry *); +__LA_DECL const char *archive_entry_hardlink_utf8(struct archive_entry *); +__LA_DECL const wchar_t *archive_entry_hardlink_w(struct archive_entry *); +__LA_DECL la_int64_t archive_entry_ino(struct archive_entry *); +__LA_DECL la_int64_t archive_entry_ino64(struct archive_entry *); +__LA_DECL int archive_entry_ino_is_set(struct archive_entry *); +__LA_DECL __LA_MODE_T archive_entry_mode(struct archive_entry *); +__LA_DECL time_t archive_entry_mtime(struct archive_entry *); +__LA_DECL long archive_entry_mtime_nsec(struct archive_entry *); +__LA_DECL int archive_entry_mtime_is_set(struct archive_entry *); +__LA_DECL unsigned int archive_entry_nlink(struct archive_entry *); +__LA_DECL const char *archive_entry_pathname(struct archive_entry *); +__LA_DECL const char *archive_entry_pathname_utf8(struct archive_entry *); +__LA_DECL const wchar_t *archive_entry_pathname_w(struct archive_entry *); +__LA_DECL __LA_MODE_T archive_entry_perm(struct archive_entry *); +__LA_DECL dev_t archive_entry_rdev(struct archive_entry *); +__LA_DECL dev_t archive_entry_rdevmajor(struct archive_entry *); +__LA_DECL dev_t archive_entry_rdevminor(struct archive_entry *); +__LA_DECL const char *archive_entry_sourcepath(struct archive_entry *); +__LA_DECL const wchar_t *archive_entry_sourcepath_w(struct archive_entry *); +__LA_DECL la_int64_t archive_entry_size(struct archive_entry *); +__LA_DECL int archive_entry_size_is_set(struct archive_entry *); +__LA_DECL const char *archive_entry_strmode(struct archive_entry *); +__LA_DECL const char *archive_entry_symlink(struct archive_entry *); +__LA_DECL const char *archive_entry_symlink_utf8(struct archive_entry *); +__LA_DECL const wchar_t *archive_entry_symlink_w(struct archive_entry *); +__LA_DECL la_int64_t archive_entry_uid(struct archive_entry *); +__LA_DECL const char *archive_entry_uname(struct archive_entry *); +__LA_DECL const char *archive_entry_uname_utf8(struct archive_entry *); +__LA_DECL const wchar_t *archive_entry_uname_w(struct archive_entry *); +__LA_DECL int archive_entry_is_data_encrypted(struct archive_entry *); +__LA_DECL int archive_entry_is_metadata_encrypted(struct archive_entry *); +__LA_DECL int archive_entry_is_encrypted(struct archive_entry *); + +/* + * Set fields in an archive_entry. + * + * Note: Before libarchive 2.4, there were 'set' and 'copy' versions + * of the string setters. 'copy' copied the actual string, 'set' just + * stored the pointer. In libarchive 2.4 and later, strings are + * always copied. + */ + +__LA_DECL void archive_entry_set_atime(struct archive_entry *, time_t, long); +__LA_DECL void archive_entry_unset_atime(struct archive_entry *); +#if defined(_WIN32) && !defined(__CYGWIN__) +__LA_DECL void archive_entry_copy_bhfi(struct archive_entry *, struct _BY_HANDLE_FILE_INFORMATION *); +#endif +__LA_DECL void archive_entry_set_birthtime(struct archive_entry *, time_t, long); +__LA_DECL void archive_entry_unset_birthtime(struct archive_entry *); +__LA_DECL void archive_entry_set_ctime(struct archive_entry *, time_t, long); +__LA_DECL void archive_entry_unset_ctime(struct archive_entry *); +__LA_DECL void archive_entry_set_dev(struct archive_entry *, dev_t); +__LA_DECL void archive_entry_set_devmajor(struct archive_entry *, dev_t); +__LA_DECL void archive_entry_set_devminor(struct archive_entry *, dev_t); +__LA_DECL void archive_entry_set_filetype(struct archive_entry *, unsigned int); +__LA_DECL void archive_entry_set_fflags(struct archive_entry *, + unsigned long /* set */, unsigned long /* clear */); +/* Returns pointer to start of first invalid token, or NULL if none. */ +/* Note that all recognized tokens are processed, regardless. */ +__LA_DECL const char *archive_entry_copy_fflags_text(struct archive_entry *, + const char *); +__LA_DECL const wchar_t *archive_entry_copy_fflags_text_w(struct archive_entry *, + const wchar_t *); +__LA_DECL void archive_entry_set_gid(struct archive_entry *, la_int64_t); +__LA_DECL void archive_entry_set_gname(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_gname_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_gname(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_gname_w(struct archive_entry *, const wchar_t *); +__LA_DECL int archive_entry_update_gname_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_hardlink(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_hardlink_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_hardlink(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_hardlink_w(struct archive_entry *, const wchar_t *); +__LA_DECL int archive_entry_update_hardlink_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_ino(struct archive_entry *, la_int64_t); +__LA_DECL void archive_entry_set_ino64(struct archive_entry *, la_int64_t); +__LA_DECL void archive_entry_set_link(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_link_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_link(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_link_w(struct archive_entry *, const wchar_t *); +__LA_DECL int archive_entry_update_link_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_mode(struct archive_entry *, __LA_MODE_T); +__LA_DECL void archive_entry_set_mtime(struct archive_entry *, time_t, long); +__LA_DECL void archive_entry_unset_mtime(struct archive_entry *); +__LA_DECL void archive_entry_set_nlink(struct archive_entry *, unsigned int); +__LA_DECL void archive_entry_set_pathname(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_pathname_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_pathname(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_pathname_w(struct archive_entry *, const wchar_t *); +__LA_DECL int archive_entry_update_pathname_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_perm(struct archive_entry *, __LA_MODE_T); +__LA_DECL void archive_entry_set_rdev(struct archive_entry *, dev_t); +__LA_DECL void archive_entry_set_rdevmajor(struct archive_entry *, dev_t); +__LA_DECL void archive_entry_set_rdevminor(struct archive_entry *, dev_t); +__LA_DECL void archive_entry_set_size(struct archive_entry *, la_int64_t); +__LA_DECL void archive_entry_unset_size(struct archive_entry *); +__LA_DECL void archive_entry_copy_sourcepath(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_sourcepath_w(struct archive_entry *, const wchar_t *); +__LA_DECL void archive_entry_set_symlink(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_symlink_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_symlink(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_symlink_w(struct archive_entry *, const wchar_t *); +__LA_DECL int archive_entry_update_symlink_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_uid(struct archive_entry *, la_int64_t); +__LA_DECL void archive_entry_set_uname(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_uname_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_uname(struct archive_entry *, const char *); +__LA_DECL void archive_entry_copy_uname_w(struct archive_entry *, const wchar_t *); +__LA_DECL int archive_entry_update_uname_utf8(struct archive_entry *, const char *); +__LA_DECL void archive_entry_set_is_data_encrypted(struct archive_entry *, char is_encrypted); +__LA_DECL void archive_entry_set_is_metadata_encrypted(struct archive_entry *, char is_encrypted); +/* + * Routines to bulk copy fields to/from a platform-native "struct + * stat." Libarchive used to just store a struct stat inside of each + * archive_entry object, but this created issues when trying to + * manipulate archives on systems different than the ones they were + * created on. + * + * TODO: On Linux and other LFS systems, provide both stat32 and + * stat64 versions of these functions and all of the macro glue so + * that archive_entry_stat is magically defined to + * archive_entry_stat32 or archive_entry_stat64 as appropriate. + */ +__LA_DECL const struct stat *archive_entry_stat(struct archive_entry *); +__LA_DECL void archive_entry_copy_stat(struct archive_entry *, const struct stat *); + +/* + * Storage for Mac OS-specific AppleDouble metadata information. + * Apple-format tar files store a separate binary blob containing + * encoded metadata with ACL, extended attributes, etc. + * This provides a place to store that blob. + */ + +__LA_DECL const void * archive_entry_mac_metadata(struct archive_entry *, size_t *); +__LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const void *, size_t); + +/* + * ACL routines. This used to simply store and return text-format ACL + * strings, but that proved insufficient for a number of reasons: + * = clients need control over uname/uid and gname/gid mappings + * = there are many different ACL text formats + * = would like to be able to read/convert archives containing ACLs + * on platforms that lack ACL libraries + * + * This last point, in particular, forces me to implement a reasonably + * complete set of ACL support routines. + */ + +/* + * Permission bits. + */ +#define ARCHIVE_ENTRY_ACL_EXECUTE 0x00000001 +#define ARCHIVE_ENTRY_ACL_WRITE 0x00000002 +#define ARCHIVE_ENTRY_ACL_READ 0x00000004 +#define ARCHIVE_ENTRY_ACL_READ_DATA 0x00000008 +#define ARCHIVE_ENTRY_ACL_LIST_DIRECTORY 0x00000008 +#define ARCHIVE_ENTRY_ACL_WRITE_DATA 0x00000010 +#define ARCHIVE_ENTRY_ACL_ADD_FILE 0x00000010 +#define ARCHIVE_ENTRY_ACL_APPEND_DATA 0x00000020 +#define ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY 0x00000020 +#define ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS 0x00000040 +#define ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS 0x00000080 +#define ARCHIVE_ENTRY_ACL_DELETE_CHILD 0x00000100 +#define ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES 0x00000200 +#define ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES 0x00000400 +#define ARCHIVE_ENTRY_ACL_DELETE 0x00000800 +#define ARCHIVE_ENTRY_ACL_READ_ACL 0x00001000 +#define ARCHIVE_ENTRY_ACL_WRITE_ACL 0x00002000 +#define ARCHIVE_ENTRY_ACL_WRITE_OWNER 0x00004000 +#define ARCHIVE_ENTRY_ACL_SYNCHRONIZE 0x00008000 + +#define ARCHIVE_ENTRY_ACL_PERMS_POSIX1E \ + (ARCHIVE_ENTRY_ACL_EXECUTE \ + | ARCHIVE_ENTRY_ACL_WRITE \ + | ARCHIVE_ENTRY_ACL_READ) + +#define ARCHIVE_ENTRY_ACL_PERMS_NFS4 \ + (ARCHIVE_ENTRY_ACL_EXECUTE \ + | ARCHIVE_ENTRY_ACL_READ_DATA \ + | ARCHIVE_ENTRY_ACL_LIST_DIRECTORY \ + | ARCHIVE_ENTRY_ACL_WRITE_DATA \ + | ARCHIVE_ENTRY_ACL_ADD_FILE \ + | ARCHIVE_ENTRY_ACL_APPEND_DATA \ + | ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY \ + | ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS \ + | ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS \ + | ARCHIVE_ENTRY_ACL_DELETE_CHILD \ + | ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES \ + | ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES \ + | ARCHIVE_ENTRY_ACL_DELETE \ + | ARCHIVE_ENTRY_ACL_READ_ACL \ + | ARCHIVE_ENTRY_ACL_WRITE_ACL \ + | ARCHIVE_ENTRY_ACL_WRITE_OWNER \ + | ARCHIVE_ENTRY_ACL_SYNCHRONIZE) + +/* + * Inheritance values (NFS4 ACLs only); included in permset. + */ +#define ARCHIVE_ENTRY_ACL_ENTRY_INHERITED 0x01000000 +#define ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT 0x02000000 +#define ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT 0x04000000 +#define ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT 0x08000000 +#define ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY 0x10000000 +#define ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS 0x20000000 +#define ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS 0x40000000 + +#define ARCHIVE_ENTRY_ACL_INHERITANCE_NFS4 \ + (ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT \ + | ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT \ + | ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT \ + | ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY \ + | ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS \ + | ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS \ + | ARCHIVE_ENTRY_ACL_ENTRY_INHERITED) + +/* We need to be able to specify combinations of these. */ +#define ARCHIVE_ENTRY_ACL_TYPE_ACCESS 0x00000100 /* POSIX.1e only */ +#define ARCHIVE_ENTRY_ACL_TYPE_DEFAULT 0x00000200 /* POSIX.1e only */ +#define ARCHIVE_ENTRY_ACL_TYPE_ALLOW 0x00000400 /* NFS4 only */ +#define ARCHIVE_ENTRY_ACL_TYPE_DENY 0x00000800 /* NFS4 only */ +#define ARCHIVE_ENTRY_ACL_TYPE_AUDIT 0x00001000 /* NFS4 only */ +#define ARCHIVE_ENTRY_ACL_TYPE_ALARM 0x00002000 /* NFS4 only */ +#define ARCHIVE_ENTRY_ACL_TYPE_POSIX1E (ARCHIVE_ENTRY_ACL_TYPE_ACCESS \ + | ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) +#define ARCHIVE_ENTRY_ACL_TYPE_NFS4 (ARCHIVE_ENTRY_ACL_TYPE_ALLOW \ + | ARCHIVE_ENTRY_ACL_TYPE_DENY \ + | ARCHIVE_ENTRY_ACL_TYPE_AUDIT \ + | ARCHIVE_ENTRY_ACL_TYPE_ALARM) + +/* Tag values mimic POSIX.1e */ +#define ARCHIVE_ENTRY_ACL_USER 10001 /* Specified user. */ +#define ARCHIVE_ENTRY_ACL_USER_OBJ 10002 /* User who owns the file. */ +#define ARCHIVE_ENTRY_ACL_GROUP 10003 /* Specified group. */ +#define ARCHIVE_ENTRY_ACL_GROUP_OBJ 10004 /* Group who owns the file. */ +#define ARCHIVE_ENTRY_ACL_MASK 10005 /* Modify group access (POSIX.1e only) */ +#define ARCHIVE_ENTRY_ACL_OTHER 10006 /* Public (POSIX.1e only) */ +#define ARCHIVE_ENTRY_ACL_EVERYONE 10107 /* Everyone (NFS4 only) */ + +/* + * Set the ACL by clearing it and adding entries one at a time. + * Unlike the POSIX.1e ACL routines, you must specify the type + * (access/default) for each entry. Internally, the ACL data is just + * a soup of entries. API calls here allow you to retrieve just the + * entries of interest. This design (which goes against the spirit of + * POSIX.1e) is useful for handling archive formats that combine + * default and access information in a single ACL list. + */ +__LA_DECL void archive_entry_acl_clear(struct archive_entry *); +__LA_DECL int archive_entry_acl_add_entry(struct archive_entry *, + int /* type */, int /* permset */, int /* tag */, + int /* qual */, const char * /* name */); +__LA_DECL int archive_entry_acl_add_entry_w(struct archive_entry *, + int /* type */, int /* permset */, int /* tag */, + int /* qual */, const wchar_t * /* name */); + +/* + * To retrieve the ACL, first "reset", then repeatedly ask for the + * "next" entry. The want_type parameter allows you to request only + * certain types of entries. + */ +__LA_DECL int archive_entry_acl_reset(struct archive_entry *, int /* want_type */); +__LA_DECL int archive_entry_acl_next(struct archive_entry *, int /* want_type */, + int * /* type */, int * /* permset */, int * /* tag */, + int * /* qual */, const char ** /* name */); +__LA_DECL int archive_entry_acl_next_w(struct archive_entry *, int /* want_type */, + int * /* type */, int * /* permset */, int * /* tag */, + int * /* qual */, const wchar_t ** /* name */); + +/* + * Construct a text-format ACL. The flags argument is a bitmask that + * can include any of the following: + * + * Flags only for archive entries with POSIX.1e ACL: + * ARCHIVE_ENTRY_ACL_TYPE_ACCESS - Include POSIX.1e "access" entries. + * ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - Include POSIX.1e "default" entries. + * ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT - Include "default:" before each + * default ACL entry. + * ARCHIVE_ENTRY_ACL_STYLE_SOLARIS - Output only one colon after "other" and + * "mask" entries. + * + * Flags only for archive entries with NFSv4 ACL: + * ARCHIVE_ENTRY_ACL_STYLE_COMPACT - Do not output the minus character for + * unset permissions and flags in NFSv4 ACL permission and flag fields + * + * Flags for for archive entries with POSIX.1e ACL or NFSv4 ACL: + * ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID - Include extra numeric ID field in + * each ACL entry. + * ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA - Separate entries with comma + * instead of newline. + */ +#define ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 0x00000001 +#define ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 0x00000002 +#define ARCHIVE_ENTRY_ACL_STYLE_SOLARIS 0x00000004 +#define ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA 0x00000008 +#define ARCHIVE_ENTRY_ACL_STYLE_COMPACT 0x00000010 + +__LA_DECL wchar_t *archive_entry_acl_to_text_w(struct archive_entry *, + la_ssize_t * /* len */, int /* flags */); +__LA_DECL char *archive_entry_acl_to_text(struct archive_entry *, + la_ssize_t * /* len */, int /* flags */); +__LA_DECL int archive_entry_acl_from_text_w(struct archive_entry *, + const wchar_t * /* wtext */, int /* type */); +__LA_DECL int archive_entry_acl_from_text(struct archive_entry *, + const char * /* text */, int /* type */); + +/* Deprecated constants */ +#define OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 1024 +#define OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 2048 + +/* Deprecated functions */ +__LA_DECL const wchar_t *archive_entry_acl_text_w(struct archive_entry *, + int /* flags */) __LA_DEPRECATED; +__LA_DECL const char *archive_entry_acl_text(struct archive_entry *, + int /* flags */) __LA_DEPRECATED; + +/* Return bitmask of ACL types in an archive entry */ +__LA_DECL int archive_entry_acl_types(struct archive_entry *); + +/* Return a count of entries matching 'want_type' */ +__LA_DECL int archive_entry_acl_count(struct archive_entry *, int /* want_type */); + +/* Return an opaque ACL object. */ +/* There's not yet anything clients can actually do with this... */ +struct archive_acl; +__LA_DECL struct archive_acl *archive_entry_acl(struct archive_entry *); + +/* + * extended attributes + */ + +__LA_DECL void archive_entry_xattr_clear(struct archive_entry *); +__LA_DECL void archive_entry_xattr_add_entry(struct archive_entry *, + const char * /* name */, const void * /* value */, + size_t /* size */); + +/* + * To retrieve the xattr list, first "reset", then repeatedly ask for the + * "next" entry. + */ + +__LA_DECL int archive_entry_xattr_count(struct archive_entry *); +__LA_DECL int archive_entry_xattr_reset(struct archive_entry *); +__LA_DECL int archive_entry_xattr_next(struct archive_entry *, + const char ** /* name */, const void ** /* value */, size_t *); + +/* + * sparse + */ + +__LA_DECL void archive_entry_sparse_clear(struct archive_entry *); +__LA_DECL void archive_entry_sparse_add_entry(struct archive_entry *, + la_int64_t /* offset */, la_int64_t /* length */); + +/* + * To retrieve the xattr list, first "reset", then repeatedly ask for the + * "next" entry. + */ + +__LA_DECL int archive_entry_sparse_count(struct archive_entry *); +__LA_DECL int archive_entry_sparse_reset(struct archive_entry *); +__LA_DECL int archive_entry_sparse_next(struct archive_entry *, + la_int64_t * /* offset */, la_int64_t * /* length */); + +/* + * Utility to match up hardlinks. + * + * The 'struct archive_entry_linkresolver' is a cache of archive entries + * for files with multiple links. Here's how to use it: + * 1. Create a lookup object with archive_entry_linkresolver_new() + * 2. Tell it the archive format you're using. + * 3. Hand each archive_entry to archive_entry_linkify(). + * That function will return 0, 1, or 2 entries that should + * be written. + * 4. Call archive_entry_linkify(resolver, NULL) until + * no more entries are returned. + * 5. Call archive_entry_linkresolver_free(resolver) to free resources. + * + * The entries returned have their hardlink and size fields updated + * appropriately. If an entry is passed in that does not refer to + * a file with multiple links, it is returned unchanged. The intention + * is that you should be able to simply filter all entries through + * this machine. + * + * To make things more efficient, be sure that each entry has a valid + * nlinks value. The hardlink cache uses this to track when all links + * have been found. If the nlinks value is zero, it will keep every + * name in the cache indefinitely, which can use a lot of memory. + * + * Note that archive_entry_size() is reset to zero if the file + * body should not be written to the archive. Pay attention! + */ +struct archive_entry_linkresolver; + +/* + * There are three different strategies for marking hardlinks. + * The descriptions below name them after the best-known + * formats that rely on each strategy: + * + * "Old cpio" is the simplest, it always returns any entry unmodified. + * As far as I know, only cpio formats use this. Old cpio archives + * store every link with the full body; the onus is on the dearchiver + * to detect and properly link the files as they are restored. + * "tar" is also pretty simple; it caches a copy the first time it sees + * any link. Subsequent appearances are modified to be hardlink + * references to the first one without any body. Used by all tar + * formats, although the newest tar formats permit the "old cpio" strategy + * as well. This strategy is very simple for the dearchiver, + * and reasonably straightforward for the archiver. + * "new cpio" is trickier. It stores the body only with the last + * occurrence. The complication is that we might not + * see every link to a particular file in a single session, so + * there's no easy way to know when we've seen the last occurrence. + * The solution here is to queue one link until we see the next. + * At the end of the session, you can enumerate any remaining + * entries by calling archive_entry_linkify(NULL) and store those + * bodies. If you have a file with three links l1, l2, and l3, + * you'll get the following behavior if you see all three links: + * linkify(l1) => NULL (the resolver stores l1 internally) + * linkify(l2) => l1 (resolver stores l2, you write l1) + * linkify(l3) => l2, l3 (all links seen, you can write both). + * If you only see l1 and l2, you'll get this behavior: + * linkify(l1) => NULL + * linkify(l2) => l1 + * linkify(NULL) => l2 (at end, you retrieve remaining links) + * As the name suggests, this strategy is used by newer cpio variants. + * It's noticeably more complex for the archiver, slightly more complex + * for the dearchiver than the tar strategy, but makes it straightforward + * to restore a file using any link by simply continuing to scan until + * you see a link that is stored with a body. In contrast, the tar + * strategy requires you to rescan the archive from the beginning to + * correctly extract an arbitrary link. + */ + +__LA_DECL struct archive_entry_linkresolver *archive_entry_linkresolver_new(void); +__LA_DECL void archive_entry_linkresolver_set_strategy( + struct archive_entry_linkresolver *, int /* format_code */); +__LA_DECL void archive_entry_linkresolver_free(struct archive_entry_linkresolver *); +__LA_DECL void archive_entry_linkify(struct archive_entry_linkresolver *, + struct archive_entry **, struct archive_entry **); +__LA_DECL struct archive_entry *archive_entry_partial_links( + struct archive_entry_linkresolver *res, unsigned int *links); + +#ifdef __cplusplus +} +#endif + +/* This is meaningless outside of this header. */ +#undef __LA_DECL + +#endif /* !ARCHIVE_ENTRY_H_INCLUDED */ diff --cc Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c index 53629ac,0000000..a5f3067 mode 100644,000000..100644 --- a/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c +++ b/Utilities/cmlibarchive/libarchive/archive_write_disk_posix.c @@@ -1,4206 -1,0 +1,4243 @@@ +/*- + * Copyright (c) 2003-2010 Tim Kientzle + * Copyright (c) 2012 Michihiro NAKAJIMA + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * 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$"); + +#if !defined(_WIN32) || defined(__CYGWIN__) + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_ACL_H +#include +#endif +#ifdef HAVE_SYS_EXTATTR_H +#include +#endif +#if defined(HAVE_SYS_XATTR_H) +#include +#elif defined(HAVE_ATTR_XATTR_H) +#include +#endif +#ifdef HAVE_SYS_EA_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_SYS_UTIME_H +#include +#endif +#ifdef HAVE_COPYFILE_H +#include +#endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_GRP_H +#include +#endif +#ifdef HAVE_LANGINFO_H +#include +#endif +#ifdef HAVE_LINUX_FS_H +#include /* for Linux file flags */ +#endif +/* + * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h. + * As the include guards don't agree, the order of include is important. + */ +#ifdef HAVE_LINUX_EXT2_FS_H +#include /* for Linux file flags */ +#endif +#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__) +#include /* Linux file flags, broken on Cygwin */ +#endif +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_PWD_H +#include +#endif +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_UTIME_H +#include +#endif +#ifdef F_GETTIMES /* Tru64 specific */ +#include +#endif + +/* + * Macro to cast st_mtime and time_t to an int64 so that 2 numbers can reliably be compared. + * + * It assumes that the input is an integer type of no more than 64 bits. + * If the number is less than zero, t must be a signed type, so it fits in + * int64_t. Otherwise, it's a nonnegative value so we can cast it to uint64_t + * without loss. But it could be a large unsigned value, so we have to clip it + * to INT64_MAX.* + */ +#define to_int64_time(t) \ + ((t) < 0 ? (int64_t)(t) : (uint64_t)(t) > (uint64_t)INT64_MAX ? INT64_MAX : (int64_t)(t)) + +#if __APPLE__ +#include +#if TARGET_OS_MAC && !TARGET_OS_EMBEDDED && HAVE_QUARANTINE_H +#include +#define HAVE_QUARANTINE 1 +#endif +#endif + +#ifdef HAVE_ZLIB_H +#include +#endif + +/* TODO: Support Mac OS 'quarantine' feature. This is really just a + * standard tag to mark files that have been downloaded as "tainted". + * On Mac OS, we should mark the extracted files as tainted if the + * archive being read was tainted. Windows has a similar feature; we + * should investigate ways to support this generically. */ + +#include "archive.h" +#include "archive_acl_private.h" +#include "archive_string.h" +#include "archive_endian.h" +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_write_disk_private.h" + +#ifndef O_BINARY +#define O_BINARY 0 +#endif +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + +/* Ignore non-int O_NOFOLLOW constant. */ +/* gnulib's fcntl.h does this on AIX, but it seems practical everywhere */ +#if defined O_NOFOLLOW && !(INT_MIN <= O_NOFOLLOW && O_NOFOLLOW <= INT_MAX) +#undef O_NOFOLLOW +#endif + +#ifndef O_NOFOLLOW +#define O_NOFOLLOW 0 +#endif + +struct fixup_entry { + struct fixup_entry *next; + struct archive_acl acl; + mode_t mode; + int64_t atime; + int64_t birthtime; + int64_t mtime; + int64_t ctime; + unsigned long atime_nanos; + unsigned long birthtime_nanos; + unsigned long mtime_nanos; + unsigned long ctime_nanos; + unsigned long fflags_set; + size_t mac_metadata_size; + void *mac_metadata; + int fixup; /* bitmask of what needs fixing */ + char *name; +}; + +/* + * We use a bitmask to track which operations remain to be done for + * this file. In particular, this helps us avoid unnecessary + * operations when it's possible to take care of one step as a + * side-effect of another. For example, mkdir() can specify the mode + * for the newly-created object but symlink() cannot. This means we + * can skip chmod() if mkdir() succeeded, but we must explicitly + * chmod() if we're trying to create a directory that already exists + * (mkdir() failed) or if we're restoring a symlink. Similarly, we + * need to verify UID/GID before trying to restore SUID/SGID bits; + * that verification can occur explicitly through a stat() call or + * implicitly because of a successful chown() call. + */ +#define TODO_MODE_FORCE 0x40000000 +#define TODO_MODE_BASE 0x20000000 +#define TODO_SUID 0x10000000 +#define TODO_SUID_CHECK 0x08000000 +#define TODO_SGID 0x04000000 +#define TODO_SGID_CHECK 0x02000000 +#define TODO_APPLEDOUBLE 0x01000000 +#define TODO_MODE (TODO_MODE_BASE|TODO_SUID|TODO_SGID) +#define TODO_TIMES ARCHIVE_EXTRACT_TIME +#define TODO_OWNER ARCHIVE_EXTRACT_OWNER +#define TODO_FFLAGS ARCHIVE_EXTRACT_FFLAGS +#define TODO_ACLS ARCHIVE_EXTRACT_ACL +#define TODO_XATTR ARCHIVE_EXTRACT_XATTR +#define TODO_MAC_METADATA ARCHIVE_EXTRACT_MAC_METADATA +#define TODO_HFS_COMPRESSION ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED + +struct archive_write_disk { + struct archive archive; + + mode_t user_umask; + struct fixup_entry *fixup_list; + struct fixup_entry *current_fixup; + int64_t user_uid; + int skip_file_set; + int64_t skip_file_dev; + int64_t skip_file_ino; + time_t start_time; + + int64_t (*lookup_gid)(void *private, const char *gname, int64_t gid); + void (*cleanup_gid)(void *private); + void *lookup_gid_data; + int64_t (*lookup_uid)(void *private, const char *uname, int64_t uid); + void (*cleanup_uid)(void *private); + void *lookup_uid_data; + + /* + * Full path of last file to satisfy symlink checks. + */ + struct archive_string path_safe; + + /* + * Cached stat data from disk for the current entry. + * If this is valid, pst points to st. Otherwise, + * pst is null. + */ + struct stat st; + struct stat *pst; + + /* Information about the object being restored right now. */ + struct archive_entry *entry; /* Entry being extracted. */ + char *name; /* Name of entry, possibly edited. */ + struct archive_string _name_data; /* backing store for 'name' */ + /* Tasks remaining for this object. */ + int todo; + /* Tasks deferred until end-of-archive. */ + int deferred; + /* Options requested by the client. */ + int flags; + /* Handle for the file we're restoring. */ + int fd; + /* Current offset for writing data to the file. */ + int64_t offset; + /* Last offset actually written to disk. */ + int64_t fd_offset; + /* Total bytes actually written to files. */ + int64_t total_bytes_written; + /* Maximum size of file, -1 if unknown. */ + int64_t filesize; + /* Dir we were in before this restore; only for deep paths. */ + int restore_pwd; + /* Mode we should use for this entry; affected by _PERM and umask. */ + mode_t mode; + /* UID/GID to use in restoring this entry. */ + int64_t uid; + int64_t gid; + /* + * HFS+ Compression. + */ + /* Xattr "com.apple.decmpfs". */ + uint32_t decmpfs_attr_size; + unsigned char *decmpfs_header_p; + /* ResourceFork set options used for fsetxattr. */ + int rsrc_xattr_options; + /* Xattr "com.apple.ResourceFork". */ + unsigned char *resource_fork; + size_t resource_fork_allocated_size; + unsigned int decmpfs_block_count; + uint32_t *decmpfs_block_info; + /* Buffer for compressed data. */ + unsigned char *compressed_buffer; + size_t compressed_buffer_size; + size_t compressed_buffer_remaining; + /* The offset of the ResourceFork where compressed data will + * be placed. */ + uint32_t compressed_rsrc_position; + uint32_t compressed_rsrc_position_v; + /* Buffer for uncompressed data. */ + char *uncompressed_buffer; + size_t block_remaining_bytes; + size_t file_remaining_bytes; +#ifdef HAVE_ZLIB_H + z_stream stream; + int stream_valid; + int decmpfs_compression_level; +#endif +}; + +/* + * Default mode for dirs created automatically (will be modified by umask). + * Note that POSIX specifies 0777 for implicitly-created dirs, "modified + * by the process' file creation mask." + */ +#define DEFAULT_DIR_MODE 0777 +/* + * Dir modes are restored in two steps: During the extraction, the permissions + * in the archive are modified to match the following limits. During + * the post-extract fixup pass, the permissions from the archive are + * applied. + */ +#define MINIMUM_DIR_MODE 0700 +#define MAXIMUM_DIR_MODE 0775 + +/* + * Maximum uncompressed size of a decmpfs block. + */ +#define MAX_DECMPFS_BLOCK_SIZE (64 * 1024) +/* + * HFS+ compression type. + */ +#define CMP_XATTR 3/* Compressed data in xattr. */ +#define CMP_RESOURCE_FORK 4/* Compressed data in resource fork. */ +/* + * HFS+ compression resource fork. + */ +#define RSRC_H_SIZE 260 /* Base size of Resource fork header. */ +#define RSRC_F_SIZE 50 /* Size of Resource fork footer. */ +/* Size to write compressed data to resource fork. */ +#define COMPRESSED_W_SIZE (64 * 1024) +/* decmpfs definitions. */ +#define MAX_DECMPFS_XATTR_SIZE 3802 +#ifndef DECMPFS_XATTR_NAME +#define DECMPFS_XATTR_NAME "com.apple.decmpfs" +#endif +#define DECMPFS_MAGIC 0x636d7066 +#define DECMPFS_COMPRESSION_MAGIC 0 +#define DECMPFS_COMPRESSION_TYPE 4 +#define DECMPFS_UNCOMPRESSED_SIZE 8 +#define DECMPFS_HEADER_SIZE 16 + +#define HFS_BLOCKS(s) ((s) >> 12) + +static void fsobj_error(int *, struct archive_string *, int, const char *, + const char *); +static int check_symlinks_fsobj(char *, int *, struct archive_string *, + int); +static int check_symlinks(struct archive_write_disk *); +static int create_filesystem_object(struct archive_write_disk *); +static struct fixup_entry *current_fixup(struct archive_write_disk *, + const char *pathname); +#if defined(HAVE_FCHDIR) && defined(PATH_MAX) +static void edit_deep_directories(struct archive_write_disk *ad); +#endif +static int cleanup_pathname_fsobj(char *, int *, struct archive_string *, + int); +static int cleanup_pathname(struct archive_write_disk *); +static int create_dir(struct archive_write_disk *, char *); +static int create_parent_dir(struct archive_write_disk *, char *); +static ssize_t hfs_write_data_block(struct archive_write_disk *, + const char *, size_t); +static int fixup_appledouble(struct archive_write_disk *, const char *); +static int older(struct stat *, struct archive_entry *); +static int restore_entry(struct archive_write_disk *); +static int set_mac_metadata(struct archive_write_disk *, const char *, + const void *, size_t); +static int set_xattrs(struct archive_write_disk *); +static int clear_nochange_fflags(struct archive_write_disk *); +static int set_fflags(struct archive_write_disk *); +static int set_fflags_platform(struct archive_write_disk *, int fd, + const char *name, mode_t mode, + unsigned long fflags_set, unsigned long fflags_clear); +static int set_ownership(struct archive_write_disk *); +static int set_mode(struct archive_write_disk *, int mode); +static int set_time(int, int, const char *, time_t, long, time_t, long); +static int set_times(struct archive_write_disk *, int, int, const char *, + time_t, long, time_t, long, time_t, long, time_t, long); +static int set_times_from_entry(struct archive_write_disk *); +static struct fixup_entry *sort_dir_list(struct fixup_entry *p); +static ssize_t write_data_block(struct archive_write_disk *, + const char *, size_t); + +static struct archive_vtable *archive_write_disk_vtable(void); + +static int _archive_write_disk_close(struct archive *); +static int _archive_write_disk_free(struct archive *); +static int _archive_write_disk_header(struct archive *, + struct archive_entry *); +static int64_t _archive_write_disk_filter_bytes(struct archive *, int); +static int _archive_write_disk_finish_entry(struct archive *); +static ssize_t _archive_write_disk_data(struct archive *, const void *, + size_t); +static ssize_t _archive_write_disk_data_block(struct archive *, const void *, + size_t, int64_t); + +static int +lazy_stat(struct archive_write_disk *a) +{ + if (a->pst != NULL) { + /* Already have stat() data available. */ + return (ARCHIVE_OK); + } +#ifdef HAVE_FSTAT + if (a->fd >= 0 && fstat(a->fd, &a->st) == 0) { + a->pst = &a->st; + return (ARCHIVE_OK); + } +#endif + /* + * XXX At this point, symlinks should not be hit, otherwise + * XXX a race occurred. Do we want to check explicitly for that? + */ + if (lstat(a->name, &a->st) == 0) { + a->pst = &a->st; + return (ARCHIVE_OK); + } + archive_set_error(&a->archive, errno, "Couldn't stat file"); + return (ARCHIVE_WARN); +} + +static struct archive_vtable * +archive_write_disk_vtable(void) +{ + static struct archive_vtable av; + static int inited = 0; + + if (!inited) { + av.archive_close = _archive_write_disk_close; + av.archive_filter_bytes = _archive_write_disk_filter_bytes; + av.archive_free = _archive_write_disk_free; + av.archive_write_header = _archive_write_disk_header; + av.archive_write_finish_entry + = _archive_write_disk_finish_entry; + av.archive_write_data = _archive_write_disk_data; + av.archive_write_data_block = _archive_write_disk_data_block; + inited = 1; + } + return (&av); +} + +static int64_t +_archive_write_disk_filter_bytes(struct archive *_a, int n) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + (void)n; /* UNUSED */ + if (n == -1 || n == 0) + return (a->total_bytes_written); + return (-1); +} + + +int +archive_write_disk_set_options(struct archive *_a, int flags) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + + a->flags = flags; + return (ARCHIVE_OK); +} + + +/* + * Extract this entry to disk. + * + * TODO: Validate hardlinks. According to the standards, we're + * supposed to check each extracted hardlink and squawk if it refers + * to a file that we didn't restore. I'm not entirely convinced this + * is a good idea, but more importantly: Is there any way to validate + * hardlinks without keeping a complete list of filenames from the + * entire archive?? Ugh. + * + */ +static int +_archive_write_disk_header(struct archive *_a, struct archive_entry *entry) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + struct fixup_entry *fe; + int ret, r; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, + "archive_write_disk_header"); + archive_clear_error(&a->archive); + if (a->archive.state & ARCHIVE_STATE_DATA) { + r = _archive_write_disk_finish_entry(&a->archive); + if (r == ARCHIVE_FATAL) + return (r); + } + + /* Set up for this particular entry. */ + a->pst = NULL; + a->current_fixup = NULL; + a->deferred = 0; + if (a->entry) { + archive_entry_free(a->entry); + a->entry = NULL; + } + a->entry = archive_entry_clone(entry); + a->fd = -1; + a->fd_offset = 0; + a->offset = 0; + a->restore_pwd = -1; + a->uid = a->user_uid; + a->mode = archive_entry_mode(a->entry); + if (archive_entry_size_is_set(a->entry)) + a->filesize = archive_entry_size(a->entry); + else + a->filesize = -1; + archive_strcpy(&(a->_name_data), archive_entry_pathname(a->entry)); + a->name = a->_name_data.s; + archive_clear_error(&a->archive); + + /* + * Clean up the requested path. This is necessary for correct + * dir restores; the dir restore logic otherwise gets messed + * up by nonsense like "dir/.". + */ + ret = cleanup_pathname(a); + if (ret != ARCHIVE_OK) + return (ret); + + /* + * Query the umask so we get predictable mode settings. + * This gets done on every call to _write_header in case the + * user edits their umask during the extraction for some + * reason. + */ + umask(a->user_umask = umask(0)); + + /* Figure out what we need to do for this entry. */ + a->todo = TODO_MODE_BASE; + if (a->flags & ARCHIVE_EXTRACT_PERM) { + a->todo |= TODO_MODE_FORCE; /* Be pushy about permissions. */ + /* + * SGID requires an extra "check" step because we + * cannot easily predict the GID that the system will + * assign. (Different systems assign GIDs to files + * based on a variety of criteria, including process + * credentials and the gid of the enclosing + * directory.) We can only restore the SGID bit if + * the file has the right GID, and we only know the + * GID if we either set it (see set_ownership) or if + * we've actually called stat() on the file after it + * was restored. Since there are several places at + * which we might verify the GID, we need a TODO bit + * to keep track. + */ + if (a->mode & S_ISGID) + a->todo |= TODO_SGID | TODO_SGID_CHECK; + /* + * Verifying the SUID is simpler, but can still be + * done in multiple ways, hence the separate "check" bit. + */ + if (a->mode & S_ISUID) + a->todo |= TODO_SUID | TODO_SUID_CHECK; + } else { + /* + * User didn't request full permissions, so don't + * restore SUID, SGID bits and obey umask. + */ + a->mode &= ~S_ISUID; + a->mode &= ~S_ISGID; + a->mode &= ~S_ISVTX; + a->mode &= ~a->user_umask; + } + if (a->flags & ARCHIVE_EXTRACT_OWNER) + a->todo |= TODO_OWNER; + if (a->flags & ARCHIVE_EXTRACT_TIME) + a->todo |= TODO_TIMES; + if (a->flags & ARCHIVE_EXTRACT_ACL) { + if (archive_entry_filetype(a->entry) == AE_IFDIR) + a->deferred |= TODO_ACLS; + else + a->todo |= TODO_ACLS; + } + if (a->flags & ARCHIVE_EXTRACT_MAC_METADATA) { + if (archive_entry_filetype(a->entry) == AE_IFDIR) + a->deferred |= TODO_MAC_METADATA; + else + a->todo |= TODO_MAC_METADATA; + } +#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_ZLIB_H) + if ((a->flags & ARCHIVE_EXTRACT_NO_HFS_COMPRESSION) == 0) { + unsigned long set, clear; + archive_entry_fflags(a->entry, &set, &clear); + if ((set & ~clear) & UF_COMPRESSED) { + a->todo |= TODO_HFS_COMPRESSION; + a->decmpfs_block_count = (unsigned)-1; + } + } + if ((a->flags & ARCHIVE_EXTRACT_HFS_COMPRESSION_FORCED) != 0 && + (a->mode & AE_IFMT) == AE_IFREG && a->filesize > 0) { + a->todo |= TODO_HFS_COMPRESSION; + a->decmpfs_block_count = (unsigned)-1; + } + { + const char *p; + + /* Check if the current file name is a type of the + * resource fork file. */ + p = strrchr(a->name, '/'); + if (p == NULL) + p = a->name; + else + p++; + if (p[0] == '.' && p[1] == '_') { + /* Do not compress "._XXX" files. */ + a->todo &= ~TODO_HFS_COMPRESSION; + if (a->filesize > 0) + a->todo |= TODO_APPLEDOUBLE; + } + } +#endif + + if (a->flags & ARCHIVE_EXTRACT_XATTR) + a->todo |= TODO_XATTR; + if (a->flags & ARCHIVE_EXTRACT_FFLAGS) + a->todo |= TODO_FFLAGS; + if (a->flags & ARCHIVE_EXTRACT_SECURE_SYMLINKS) { + ret = check_symlinks(a); + if (ret != ARCHIVE_OK) + return (ret); + } +#if defined(HAVE_FCHDIR) && defined(PATH_MAX) + /* If path exceeds PATH_MAX, shorten the path. */ + edit_deep_directories(a); +#endif + + ret = restore_entry(a); + +#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_ZLIB_H) + /* + * Check if the filesystem the file is restoring on supports + * HFS+ Compression. If not, cancel HFS+ Compression. + */ + if (a->todo | TODO_HFS_COMPRESSION) { + /* + * NOTE: UF_COMPRESSED is ignored even if the filesystem + * supports HFS+ Compression because the file should + * have at least an extended attribute "com.apple.decmpfs" + * before the flag is set to indicate that the file have + * been compressed. If the filesystem does not support + * HFS+ Compression the system call will fail. + */ + if (a->fd < 0 || fchflags(a->fd, UF_COMPRESSED) != 0) + a->todo &= ~TODO_HFS_COMPRESSION; + } +#endif + + /* + * TODO: There are rumours that some extended attributes must + * be restored before file data is written. If this is true, + * then we either need to write all extended attributes both + * before and after restoring the data, or find some rule for + * determining which must go first and which last. Due to the + * many ways people are using xattrs, this may prove to be an + * intractable problem. + */ + +#ifdef HAVE_FCHDIR + /* If we changed directory above, restore it here. */ + if (a->restore_pwd >= 0) { + r = fchdir(a->restore_pwd); + if (r != 0) { + archive_set_error(&a->archive, errno, + "chdir() failure"); + ret = ARCHIVE_FATAL; + } + close(a->restore_pwd); + a->restore_pwd = -1; + } +#endif + + /* + * Fixup uses the unedited pathname from archive_entry_pathname(), + * because it is relative to the base dir and the edited path + * might be relative to some intermediate dir as a result of the + * deep restore logic. + */ + if (a->deferred & TODO_MODE) { + fe = current_fixup(a, archive_entry_pathname(entry)); + if (fe == NULL) + return (ARCHIVE_FATAL); + fe->fixup |= TODO_MODE_BASE; + fe->mode = a->mode; + } + + if ((a->deferred & TODO_TIMES) + && (archive_entry_mtime_is_set(entry) + || archive_entry_atime_is_set(entry))) { + fe = current_fixup(a, archive_entry_pathname(entry)); + if (fe == NULL) + return (ARCHIVE_FATAL); + fe->mode = a->mode; + fe->fixup |= TODO_TIMES; + if (archive_entry_atime_is_set(entry)) { + fe->atime = archive_entry_atime(entry); + fe->atime_nanos = archive_entry_atime_nsec(entry); + } else { + /* If atime is unset, use start time. */ + fe->atime = a->start_time; + fe->atime_nanos = 0; + } + if (archive_entry_mtime_is_set(entry)) { + fe->mtime = archive_entry_mtime(entry); + fe->mtime_nanos = archive_entry_mtime_nsec(entry); + } else { + /* If mtime is unset, use start time. */ + fe->mtime = a->start_time; + fe->mtime_nanos = 0; + } + if (archive_entry_birthtime_is_set(entry)) { + fe->birthtime = archive_entry_birthtime(entry); + fe->birthtime_nanos = archive_entry_birthtime_nsec( + entry); + } else { + /* If birthtime is unset, use mtime. */ + fe->birthtime = fe->mtime; + fe->birthtime_nanos = fe->mtime_nanos; + } + } + + if (a->deferred & TODO_ACLS) { + fe = current_fixup(a, archive_entry_pathname(entry)); + if (fe == NULL) + return (ARCHIVE_FATAL); + fe->fixup |= TODO_ACLS; + archive_acl_copy(&fe->acl, archive_entry_acl(entry)); + } + + if (a->deferred & TODO_MAC_METADATA) { + const void *metadata; + size_t metadata_size; + metadata = archive_entry_mac_metadata(a->entry, &metadata_size); + if (metadata != NULL && metadata_size > 0) { + fe = current_fixup(a, archive_entry_pathname(entry)); + if (fe == NULL) + return (ARCHIVE_FATAL); + fe->mac_metadata = malloc(metadata_size); + if (fe->mac_metadata != NULL) { + memcpy(fe->mac_metadata, metadata, + metadata_size); + fe->mac_metadata_size = metadata_size; + fe->fixup |= TODO_MAC_METADATA; + } + } + } + + if (a->deferred & TODO_FFLAGS) { + fe = current_fixup(a, archive_entry_pathname(entry)); + if (fe == NULL) + return (ARCHIVE_FATAL); + fe->fixup |= TODO_FFLAGS; + /* TODO: Complete this.. defer fflags from below. */ + } + + /* We've created the object and are ready to pour data into it. */ + if (ret >= ARCHIVE_WARN) + a->archive.state = ARCHIVE_STATE_DATA; + /* + * If it's not open, tell our client not to try writing. + * In particular, dirs, links, etc, don't get written to. + */ + if (a->fd < 0) { + archive_entry_set_size(entry, 0); + a->filesize = 0; + } + + return (ret); +} + +int +archive_write_disk_set_skip_file(struct archive *_a, int64_t d, int64_t i) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_write_disk_set_skip_file"); + a->skip_file_set = 1; + a->skip_file_dev = d; + a->skip_file_ino = i; + return (ARCHIVE_OK); +} + +static ssize_t +write_data_block(struct archive_write_disk *a, const char *buff, size_t size) +{ + uint64_t start_size = size; + ssize_t bytes_written = 0; + ssize_t block_size = 0, bytes_to_write; + + if (size == 0) + return (ARCHIVE_OK); + + if (a->filesize == 0 || a->fd < 0) { + archive_set_error(&a->archive, 0, + "Attempt to write to an empty file"); + return (ARCHIVE_WARN); + } + + if (a->flags & ARCHIVE_EXTRACT_SPARSE) { +#if HAVE_STRUCT_STAT_ST_BLKSIZE + int r; + if ((r = lazy_stat(a)) != ARCHIVE_OK) + return (r); + block_size = a->pst->st_blksize; +#else + /* XXX TODO XXX Is there a more appropriate choice here ? */ + /* This needn't match the filesystem allocation size. */ + block_size = 16*1024; +#endif + } + + /* If this write would run beyond the file size, truncate it. */ + if (a->filesize >= 0 && (int64_t)(a->offset + size) > a->filesize) + start_size = size = (size_t)(a->filesize - a->offset); + + /* Write the data. */ + while (size > 0) { + if (block_size == 0) { + bytes_to_write = size; + } else { + /* We're sparsifying the file. */ + const char *p, *end; + int64_t block_end; + + /* Skip leading zero bytes. */ + for (p = buff, end = buff + size; p < end; ++p) { + if (*p != '\0') + break; + } + a->offset += p - buff; + size -= p - buff; + buff = p; + if (size == 0) + break; + + /* Calculate next block boundary after offset. */ + block_end + = (a->offset / block_size + 1) * block_size; + + /* If the adjusted write would cross block boundary, + * truncate it to the block boundary. */ + bytes_to_write = size; + if (a->offset + bytes_to_write > block_end) + bytes_to_write = block_end - a->offset; + } + /* Seek if necessary to the specified offset. */ + if (a->offset != a->fd_offset) { + if (lseek(a->fd, a->offset, SEEK_SET) < 0) { + archive_set_error(&a->archive, errno, + "Seek failed"); + return (ARCHIVE_FATAL); + } + a->fd_offset = a->offset; + } + bytes_written = write(a->fd, buff, bytes_to_write); + if (bytes_written < 0) { + archive_set_error(&a->archive, errno, "Write failed"); + return (ARCHIVE_WARN); + } + buff += bytes_written; + size -= bytes_written; + a->total_bytes_written += bytes_written; + a->offset += bytes_written; + a->fd_offset = a->offset; + } + return (start_size - size); +} + +#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_SYS_XATTR_H)\ + && defined(HAVE_ZLIB_H) + +/* + * Set UF_COMPRESSED file flag. + * This have to be called after hfs_write_decmpfs() because if the + * file does not have "com.apple.decmpfs" xattr the flag is ignored. + */ +static int +hfs_set_compressed_fflag(struct archive_write_disk *a) +{ + int r; + + if ((r = lazy_stat(a)) != ARCHIVE_OK) + return (r); + + a->st.st_flags |= UF_COMPRESSED; + if (fchflags(a->fd, a->st.st_flags) != 0) { + archive_set_error(&a->archive, errno, + "Failed to set UF_COMPRESSED file flag"); + return (ARCHIVE_WARN); + } + return (ARCHIVE_OK); +} + +/* + * HFS+ Compression decmpfs + * + * +------------------------------+ +0 + * | Magic(LE 4 bytes) | + * +------------------------------+ + * | Type(LE 4 bytes) | + * +------------------------------+ + * | Uncompressed size(LE 8 bytes)| + * +------------------------------+ +16 + * | | + * | Compressed data | + * | (Placed only if Type == 3) | + * | | + * +------------------------------+ +3802 = MAX_DECMPFS_XATTR_SIZE + * + * Type is 3: decmpfs has compressed data. + * Type is 4: Resource Fork has compressed data. + */ +/* + * Write "com.apple.decmpfs" + */ +static int +hfs_write_decmpfs(struct archive_write_disk *a) +{ + int r; + uint32_t compression_type; + + r = fsetxattr(a->fd, DECMPFS_XATTR_NAME, a->decmpfs_header_p, + a->decmpfs_attr_size, 0, 0); + if (r < 0) { + archive_set_error(&a->archive, errno, + "Cannot restore xattr:%s", DECMPFS_XATTR_NAME); + compression_type = archive_le32dec( + &a->decmpfs_header_p[DECMPFS_COMPRESSION_TYPE]); + if (compression_type == CMP_RESOURCE_FORK) + fremovexattr(a->fd, XATTR_RESOURCEFORK_NAME, + XATTR_SHOWCOMPRESSION); + return (ARCHIVE_WARN); + } + return (ARCHIVE_OK); +} + +/* + * HFS+ Compression Resource Fork + * + * +-----------------------------+ + * | Header(260 bytes) | + * +-----------------------------+ + * | Block count(LE 4 bytes) | + * +-----------------------------+ --+ + * +-- | Offset (LE 4 bytes) | | + * | | [distance from Block count] | | Block 0 + * | +-----------------------------+ | + * | | Compressed size(LE 4 bytes) | | + * | +-----------------------------+ --+ + * | | | + * | | .................. | + * | | | + * | +-----------------------------+ --+ + * | | Offset (LE 4 bytes) | | + * | +-----------------------------+ | Block (Block count -1) + * | | Compressed size(LE 4 bytes) | | + * +-> +-----------------------------+ --+ + * | Compressed data(n bytes) | Block 0 + * +-----------------------------+ + * | | + * | .................. | + * | | + * +-----------------------------+ + * | Compressed data(n bytes) | Block (Block count -1) + * +-----------------------------+ + * | Footer(50 bytes) | + * +-----------------------------+ + * + */ +/* + * Write the header of "com.apple.ResourceFork" + */ +static int +hfs_write_resource_fork(struct archive_write_disk *a, unsigned char *buff, + size_t bytes, uint32_t position) +{ + int ret; + + ret = fsetxattr(a->fd, XATTR_RESOURCEFORK_NAME, buff, bytes, + position, a->rsrc_xattr_options); + if (ret < 0) { + archive_set_error(&a->archive, errno, + "Cannot restore xattr: %s at %u pos %u bytes", + XATTR_RESOURCEFORK_NAME, + (unsigned)position, + (unsigned)bytes); + return (ARCHIVE_WARN); + } + a->rsrc_xattr_options &= ~XATTR_CREATE; + return (ARCHIVE_OK); +} + +static int +hfs_write_compressed_data(struct archive_write_disk *a, size_t bytes_compressed) +{ + int ret; + + ret = hfs_write_resource_fork(a, a->compressed_buffer, + bytes_compressed, a->compressed_rsrc_position); + if (ret == ARCHIVE_OK) + a->compressed_rsrc_position += bytes_compressed; + return (ret); +} + +static int +hfs_write_resource_fork_header(struct archive_write_disk *a) +{ + unsigned char *buff; + uint32_t rsrc_bytes; + uint32_t rsrc_header_bytes; + + /* + * Write resource fork header + block info. + */ + buff = a->resource_fork; + rsrc_bytes = a->compressed_rsrc_position - RSRC_F_SIZE; + rsrc_header_bytes = + RSRC_H_SIZE + /* Header base size. */ + 4 + /* Block count. */ + (a->decmpfs_block_count * 8);/* Block info */ + archive_be32enc(buff, 0x100); + archive_be32enc(buff + 4, rsrc_bytes); + archive_be32enc(buff + 8, rsrc_bytes - 256); + archive_be32enc(buff + 12, 0x32); + memset(buff + 16, 0, 240); + archive_be32enc(buff + 256, rsrc_bytes - 260); + return hfs_write_resource_fork(a, buff, rsrc_header_bytes, 0); +} + +static size_t +hfs_set_resource_fork_footer(unsigned char *buff, size_t buff_size) +{ + static const char rsrc_footer[RSRC_F_SIZE] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1c, 0x00, 0x32, 0x00, 0x00, 'c', 'm', + 'p', 'f', 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 + }; + if (buff_size < sizeof(rsrc_footer)) + return (0); + memcpy(buff, rsrc_footer, sizeof(rsrc_footer)); + return (sizeof(rsrc_footer)); +} + +static int +hfs_reset_compressor(struct archive_write_disk *a) +{ + int ret; + + if (a->stream_valid) + ret = deflateReset(&a->stream); + else + ret = deflateInit(&a->stream, a->decmpfs_compression_level); + + if (ret != Z_OK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to initialize compressor"); + return (ARCHIVE_FATAL); + } else + a->stream_valid = 1; + + return (ARCHIVE_OK); +} + +static int +hfs_decompress(struct archive_write_disk *a) +{ + uint32_t *block_info; + unsigned int block_count; + uint32_t data_pos, data_size; + ssize_t r; + ssize_t bytes_written, bytes_to_write; + unsigned char *b; + + block_info = (uint32_t *)(a->resource_fork + RSRC_H_SIZE); + block_count = archive_le32dec(block_info++); + while (block_count--) { + data_pos = RSRC_H_SIZE + archive_le32dec(block_info++); + data_size = archive_le32dec(block_info++); + r = fgetxattr(a->fd, XATTR_RESOURCEFORK_NAME, + a->compressed_buffer, data_size, data_pos, 0); + if (r != data_size) { + archive_set_error(&a->archive, + (r < 0)?errno:ARCHIVE_ERRNO_MISC, + "Failed to read resource fork"); + return (ARCHIVE_WARN); + } + if (a->compressed_buffer[0] == 0xff) { + bytes_to_write = data_size -1; + b = a->compressed_buffer + 1; + } else { + uLong dest_len = MAX_DECMPFS_BLOCK_SIZE; + int zr; + + zr = uncompress((Bytef *)a->uncompressed_buffer, + &dest_len, a->compressed_buffer, data_size); + if (zr != Z_OK) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "Failed to decompress resource fork"); + return (ARCHIVE_WARN); + } + bytes_to_write = dest_len; + b = (unsigned char *)a->uncompressed_buffer; + } + do { + bytes_written = write(a->fd, b, bytes_to_write); + if (bytes_written < 0) { + archive_set_error(&a->archive, errno, + "Write failed"); + return (ARCHIVE_WARN); + } + bytes_to_write -= bytes_written; + b += bytes_written; + } while (bytes_to_write > 0); + } + r = fremovexattr(a->fd, XATTR_RESOURCEFORK_NAME, 0); + if (r == -1) { + archive_set_error(&a->archive, errno, + "Failed to remove resource fork"); + return (ARCHIVE_WARN); + } + return (ARCHIVE_OK); +} + +static int +hfs_drive_compressor(struct archive_write_disk *a, const char *buff, + size_t size) +{ + unsigned char *buffer_compressed; + size_t bytes_compressed; + size_t bytes_used; + int ret; + + ret = hfs_reset_compressor(a); + if (ret != ARCHIVE_OK) + return (ret); + + if (a->compressed_buffer == NULL) { + size_t block_size; + + block_size = COMPRESSED_W_SIZE + RSRC_F_SIZE + + + compressBound(MAX_DECMPFS_BLOCK_SIZE); + a->compressed_buffer = malloc(block_size); + if (a->compressed_buffer == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Resource Fork"); + return (ARCHIVE_FATAL); + } + a->compressed_buffer_size = block_size; + a->compressed_buffer_remaining = block_size; + } + + buffer_compressed = a->compressed_buffer + + a->compressed_buffer_size - a->compressed_buffer_remaining; + a->stream.next_in = (Bytef *)(uintptr_t)(const void *)buff; + a->stream.avail_in = size; + a->stream.next_out = buffer_compressed; + a->stream.avail_out = a->compressed_buffer_remaining; + do { + ret = deflate(&a->stream, Z_FINISH); + switch (ret) { + case Z_OK: + case Z_STREAM_END: + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to compress data"); + return (ARCHIVE_FAILED); + } + } while (ret == Z_OK); + bytes_compressed = a->compressed_buffer_remaining - a->stream.avail_out; + + /* + * If the compressed size is larger than the original size, + * throw away compressed data, use uncompressed data instead. + */ + if (bytes_compressed > size) { + buffer_compressed[0] = 0xFF;/* uncompressed marker. */ + memcpy(buffer_compressed + 1, buff, size); + bytes_compressed = size + 1; + } + a->compressed_buffer_remaining -= bytes_compressed; + + /* + * If the compressed size is smaller than MAX_DECMPFS_XATTR_SIZE + * and the block count in the file is only one, store compressed + * data to decmpfs xattr instead of the resource fork. + */ + if (a->decmpfs_block_count == 1 && + (a->decmpfs_attr_size + bytes_compressed) + <= MAX_DECMPFS_XATTR_SIZE) { + archive_le32enc(&a->decmpfs_header_p[DECMPFS_COMPRESSION_TYPE], + CMP_XATTR); + memcpy(a->decmpfs_header_p + DECMPFS_HEADER_SIZE, + buffer_compressed, bytes_compressed); + a->decmpfs_attr_size += bytes_compressed; + a->compressed_buffer_remaining = a->compressed_buffer_size; + /* + * Finish HFS+ Compression. + * - Write the decmpfs xattr. + * - Set the UF_COMPRESSED file flag. + */ + ret = hfs_write_decmpfs(a); + if (ret == ARCHIVE_OK) + ret = hfs_set_compressed_fflag(a); + return (ret); + } + + /* Update block info. */ + archive_le32enc(a->decmpfs_block_info++, + a->compressed_rsrc_position_v - RSRC_H_SIZE); + archive_le32enc(a->decmpfs_block_info++, bytes_compressed); + a->compressed_rsrc_position_v += bytes_compressed; + + /* + * Write the compressed data to the resource fork. + */ + bytes_used = a->compressed_buffer_size - a->compressed_buffer_remaining; + while (bytes_used >= COMPRESSED_W_SIZE) { + ret = hfs_write_compressed_data(a, COMPRESSED_W_SIZE); + if (ret != ARCHIVE_OK) + return (ret); + bytes_used -= COMPRESSED_W_SIZE; + if (bytes_used > COMPRESSED_W_SIZE) + memmove(a->compressed_buffer, + a->compressed_buffer + COMPRESSED_W_SIZE, + bytes_used); + else + memcpy(a->compressed_buffer, + a->compressed_buffer + COMPRESSED_W_SIZE, + bytes_used); + } + a->compressed_buffer_remaining = a->compressed_buffer_size - bytes_used; + + /* + * If the current block is the last block, write the remaining + * compressed data and the resource fork footer. + */ + if (a->file_remaining_bytes == 0) { + size_t rsrc_size; + int64_t bk; + + /* Append the resource footer. */ + rsrc_size = hfs_set_resource_fork_footer( + a->compressed_buffer + bytes_used, + a->compressed_buffer_remaining); + ret = hfs_write_compressed_data(a, bytes_used + rsrc_size); + a->compressed_buffer_remaining = a->compressed_buffer_size; + + /* If the compressed size is not enough smaller than + * the uncompressed size. cancel HFS+ compression. + * TODO: study a behavior of ditto utility and improve + * the condition to fall back into no HFS+ compression. */ + bk = HFS_BLOCKS(a->compressed_rsrc_position); + bk += bk >> 7; + if (bk > HFS_BLOCKS(a->filesize)) + return hfs_decompress(a); + /* + * Write the resourcefork header. + */ + if (ret == ARCHIVE_OK) + ret = hfs_write_resource_fork_header(a); + /* + * Finish HFS+ Compression. + * - Write the decmpfs xattr. + * - Set the UF_COMPRESSED file flag. + */ + if (ret == ARCHIVE_OK) + ret = hfs_write_decmpfs(a); + if (ret == ARCHIVE_OK) + ret = hfs_set_compressed_fflag(a); + } + return (ret); +} + +static ssize_t +hfs_write_decmpfs_block(struct archive_write_disk *a, const char *buff, + size_t size) +{ + const char *buffer_to_write; + size_t bytes_to_write; + int ret; + + if (a->decmpfs_block_count == (unsigned)-1) { + void *new_block; + size_t new_size; + unsigned int block_count; + + if (a->decmpfs_header_p == NULL) { + new_block = malloc(MAX_DECMPFS_XATTR_SIZE + + sizeof(uint32_t)); + if (new_block == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for decmpfs"); + return (ARCHIVE_FATAL); + } + a->decmpfs_header_p = new_block; + } + a->decmpfs_attr_size = DECMPFS_HEADER_SIZE; + archive_le32enc(&a->decmpfs_header_p[DECMPFS_COMPRESSION_MAGIC], + DECMPFS_MAGIC); + archive_le32enc(&a->decmpfs_header_p[DECMPFS_COMPRESSION_TYPE], + CMP_RESOURCE_FORK); + archive_le64enc(&a->decmpfs_header_p[DECMPFS_UNCOMPRESSED_SIZE], + a->filesize); + + /* Calculate a block count of the file. */ + block_count = + (a->filesize + MAX_DECMPFS_BLOCK_SIZE -1) / + MAX_DECMPFS_BLOCK_SIZE; + /* + * Allocate buffer for resource fork. + * Set up related pointers; + */ + new_size = + RSRC_H_SIZE + /* header */ + 4 + /* Block count */ + (block_count * sizeof(uint32_t) * 2) + + RSRC_F_SIZE; /* footer */ + if (new_size > a->resource_fork_allocated_size) { + new_block = realloc(a->resource_fork, new_size); + if (new_block == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for ResourceFork"); + return (ARCHIVE_FATAL); + } + a->resource_fork_allocated_size = new_size; + a->resource_fork = new_block; + } + + /* Allocate uncompressed buffer */ + if (a->uncompressed_buffer == NULL) { + new_block = malloc(MAX_DECMPFS_BLOCK_SIZE); + if (new_block == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for decmpfs"); + return (ARCHIVE_FATAL); + } + a->uncompressed_buffer = new_block; + } + a->block_remaining_bytes = MAX_DECMPFS_BLOCK_SIZE; + a->file_remaining_bytes = a->filesize; + a->compressed_buffer_remaining = a->compressed_buffer_size; + + /* + * Set up a resource fork. + */ + a->rsrc_xattr_options = XATTR_CREATE; + /* Get the position where we are going to set a bunch + * of block info. */ + a->decmpfs_block_info = + (uint32_t *)(a->resource_fork + RSRC_H_SIZE); + /* Set the block count to the resource fork. */ + archive_le32enc(a->decmpfs_block_info++, block_count); + /* Get the position where we are going to set compressed + * data. */ + a->compressed_rsrc_position = + RSRC_H_SIZE + 4 + (block_count * 8); + a->compressed_rsrc_position_v = a->compressed_rsrc_position; + a->decmpfs_block_count = block_count; + } + + /* Ignore redundant bytes. */ + if (a->file_remaining_bytes == 0) + return ((ssize_t)size); + + /* Do not overrun a block size. */ + if (size > a->block_remaining_bytes) + bytes_to_write = a->block_remaining_bytes; + else + bytes_to_write = size; + /* Do not overrun the file size. */ + if (bytes_to_write > a->file_remaining_bytes) + bytes_to_write = a->file_remaining_bytes; + + /* For efficiency, if a copy length is full of the uncompressed + * buffer size, do not copy writing data to it. */ + if (bytes_to_write == MAX_DECMPFS_BLOCK_SIZE) + buffer_to_write = buff; + else { + memcpy(a->uncompressed_buffer + + MAX_DECMPFS_BLOCK_SIZE - a->block_remaining_bytes, + buff, bytes_to_write); + buffer_to_write = a->uncompressed_buffer; + } + a->block_remaining_bytes -= bytes_to_write; + a->file_remaining_bytes -= bytes_to_write; + + if (a->block_remaining_bytes == 0 || a->file_remaining_bytes == 0) { + ret = hfs_drive_compressor(a, buffer_to_write, + MAX_DECMPFS_BLOCK_SIZE - a->block_remaining_bytes); + if (ret < 0) + return (ret); + a->block_remaining_bytes = MAX_DECMPFS_BLOCK_SIZE; + } + /* Ignore redundant bytes. */ + if (a->file_remaining_bytes == 0) + return ((ssize_t)size); + return (bytes_to_write); +} + +static ssize_t +hfs_write_data_block(struct archive_write_disk *a, const char *buff, + size_t size) +{ + uint64_t start_size = size; + ssize_t bytes_written = 0; + ssize_t bytes_to_write; + + if (size == 0) + return (ARCHIVE_OK); + + if (a->filesize == 0 || a->fd < 0) { + archive_set_error(&a->archive, 0, + "Attempt to write to an empty file"); + return (ARCHIVE_WARN); + } + + /* If this write would run beyond the file size, truncate it. */ + if (a->filesize >= 0 && (int64_t)(a->offset + size) > a->filesize) + start_size = size = (size_t)(a->filesize - a->offset); + + /* Write the data. */ + while (size > 0) { + bytes_to_write = size; + /* Seek if necessary to the specified offset. */ + if (a->offset < a->fd_offset) { + /* Can't support backward move. */ + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Seek failed"); + return (ARCHIVE_FATAL); + } else if (a->offset > a->fd_offset) { + int64_t skip = a->offset - a->fd_offset; + char nullblock[1024]; + + memset(nullblock, 0, sizeof(nullblock)); + while (skip > 0) { + if (skip > (int64_t)sizeof(nullblock)) + bytes_written = hfs_write_decmpfs_block( + a, nullblock, sizeof(nullblock)); + else + bytes_written = hfs_write_decmpfs_block( + a, nullblock, skip); + if (bytes_written < 0) { + archive_set_error(&a->archive, errno, + "Write failed"); + return (ARCHIVE_WARN); + } + skip -= bytes_written; + } + + a->fd_offset = a->offset; + } + bytes_written = + hfs_write_decmpfs_block(a, buff, bytes_to_write); + if (bytes_written < 0) + return (bytes_written); + buff += bytes_written; + size -= bytes_written; + a->total_bytes_written += bytes_written; + a->offset += bytes_written; + a->fd_offset = a->offset; + } + return (start_size - size); +} +#else +static ssize_t +hfs_write_data_block(struct archive_write_disk *a, const char *buff, + size_t size) +{ + return (write_data_block(a, buff, size)); +} +#endif + +static ssize_t +_archive_write_disk_data_block(struct archive *_a, + const void *buff, size_t size, int64_t offset) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + ssize_t r; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_DATA, "archive_write_data_block"); + + a->offset = offset; + if (a->todo & TODO_HFS_COMPRESSION) + r = hfs_write_data_block(a, buff, size); + else + r = write_data_block(a, buff, size); + if (r < ARCHIVE_OK) + return (r); + if ((size_t)r < size) { + archive_set_error(&a->archive, 0, + "Too much data: Truncating file at %ju bytes", + (uintmax_t)a->filesize); + return (ARCHIVE_WARN); + } +#if ARCHIVE_VERSION_NUMBER < 3999000 + return (ARCHIVE_OK); +#else + return (size); +#endif +} + +static ssize_t +_archive_write_disk_data(struct archive *_a, const void *buff, size_t size) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_DATA, "archive_write_data"); + + if (a->todo & TODO_HFS_COMPRESSION) + return (hfs_write_data_block(a, buff, size)); + return (write_data_block(a, buff, size)); +} + +static int +_archive_write_disk_finish_entry(struct archive *_a) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + int ret = ARCHIVE_OK; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, + "archive_write_finish_entry"); + if (a->archive.state & ARCHIVE_STATE_HEADER) + return (ARCHIVE_OK); + archive_clear_error(&a->archive); + + /* Pad or truncate file to the right size. */ + if (a->fd < 0) { + /* There's no file. */ + } else if (a->filesize < 0) { + /* File size is unknown, so we can't set the size. */ + } else if (a->fd_offset == a->filesize) { + /* Last write ended at exactly the filesize; we're done. */ + /* Hopefully, this is the common case. */ +#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_ZLIB_H) + } else if (a->todo & TODO_HFS_COMPRESSION) { + char null_d[1024]; + ssize_t r; + + if (a->file_remaining_bytes) + memset(null_d, 0, sizeof(null_d)); + while (a->file_remaining_bytes) { + if (a->file_remaining_bytes > sizeof(null_d)) + r = hfs_write_data_block( + a, null_d, sizeof(null_d)); + else + r = hfs_write_data_block( + a, null_d, a->file_remaining_bytes); + if (r < 0) + return ((int)r); + } +#endif + } else { +#if HAVE_FTRUNCATE + if (ftruncate(a->fd, a->filesize) == -1 && + a->filesize == 0) { + archive_set_error(&a->archive, errno, + "File size could not be restored"); + return (ARCHIVE_FAILED); + } +#endif + /* + * Not all platforms implement the XSI option to + * extend files via ftruncate. Stat() the file again + * to see what happened. + */ + a->pst = NULL; + if ((ret = lazy_stat(a)) != ARCHIVE_OK) + return (ret); + /* We can use lseek()/write() to extend the file if + * ftruncate didn't work or isn't available. */ + if (a->st.st_size < a->filesize) { + const char nul = '\0'; + if (lseek(a->fd, a->filesize - 1, SEEK_SET) < 0) { + archive_set_error(&a->archive, errno, + "Seek failed"); + return (ARCHIVE_FATAL); + } + if (write(a->fd, &nul, 1) < 0) { + archive_set_error(&a->archive, errno, + "Write to restore size failed"); + return (ARCHIVE_FATAL); + } + a->pst = NULL; + } + } + + /* Restore metadata. */ + + /* + * This is specific to Mac OS X. + * If the current file is an AppleDouble file, it should be + * linked with the data fork file and remove it. + */ + if (a->todo & TODO_APPLEDOUBLE) { + int r2 = fixup_appledouble(a, a->name); + if (r2 == ARCHIVE_EOF) { + /* The current file has been successfully linked + * with the data fork file and removed. So there + * is nothing to do on the current file. */ + goto finish_metadata; + } + if (r2 < ret) ret = r2; + } + + /* + * Look up the "real" UID only if we're going to need it. + * TODO: the TODO_SGID condition can be dropped here, can't it? + */ + if (a->todo & (TODO_OWNER | TODO_SUID | TODO_SGID)) { + a->uid = archive_write_disk_uid(&a->archive, + archive_entry_uname(a->entry), + archive_entry_uid(a->entry)); + } + /* Look up the "real" GID only if we're going to need it. */ + /* TODO: the TODO_SUID condition can be dropped here, can't it? */ + if (a->todo & (TODO_OWNER | TODO_SGID | TODO_SUID)) { + a->gid = archive_write_disk_gid(&a->archive, + archive_entry_gname(a->entry), + archive_entry_gid(a->entry)); + } + + /* + * Restore ownership before set_mode tries to restore suid/sgid + * bits. If we set the owner, we know what it is and can skip + * a stat() call to examine the ownership of the file on disk. + */ + if (a->todo & TODO_OWNER) { + int r2 = set_ownership(a); + if (r2 < ret) ret = r2; + } + + /* + * set_mode must precede ACLs on systems such as Solaris and + * FreeBSD where setting the mode implicitly clears extended ACLs + */ + if (a->todo & TODO_MODE) { + int r2 = set_mode(a, a->mode); + if (r2 < ret) ret = r2; + } + + /* + * Security-related extended attributes (such as + * security.capability on Linux) have to be restored last, + * since they're implicitly removed by other file changes. + */ + if (a->todo & TODO_XATTR) { + int r2 = set_xattrs(a); + if (r2 < ret) ret = r2; + } + + /* + * Some flags prevent file modification; they must be restored after + * file contents are written. + */ + if (a->todo & TODO_FFLAGS) { + int r2 = set_fflags(a); + if (r2 < ret) ret = r2; + } + + /* + * Time must follow most other metadata; + * otherwise atime will get changed. + */ + if (a->todo & TODO_TIMES) { + int r2 = set_times_from_entry(a); + if (r2 < ret) ret = r2; + } + + /* + * Mac extended metadata includes ACLs. + */ + if (a->todo & TODO_MAC_METADATA) { + const void *metadata; + size_t metadata_size; + metadata = archive_entry_mac_metadata(a->entry, &metadata_size); + if (metadata != NULL && metadata_size > 0) { + int r2 = set_mac_metadata(a, archive_entry_pathname( + a->entry), metadata, metadata_size); + if (r2 < ret) ret = r2; + } + } + + /* + * ACLs must be restored after timestamps because there are + * ACLs that prevent attribute changes (including time). + */ + 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 (metadata == NULL || metadata_size == 0) { ++ 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)); + if (r2 < ret) ret = r2; +#ifdef HAVE_DARWIN_ACL + } +#endif + } + +finish_metadata: + /* If there's an fd, we can close it now. */ + if (a->fd >= 0) { + close(a->fd); + a->fd = -1; + } + /* If there's an entry, we can release it now. */ + if (a->entry) { + archive_entry_free(a->entry); + a->entry = NULL; + } + a->archive.state = ARCHIVE_STATE_HEADER; + return (ret); +} + +int +archive_write_disk_set_group_lookup(struct archive *_a, + void *private_data, + int64_t (*lookup_gid)(void *private, const char *gname, int64_t gid), + void (*cleanup_gid)(void *private)) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_write_disk_set_group_lookup"); + + if (a->cleanup_gid != NULL && a->lookup_gid_data != NULL) + (a->cleanup_gid)(a->lookup_gid_data); + + a->lookup_gid = lookup_gid; + a->cleanup_gid = cleanup_gid; + a->lookup_gid_data = private_data; + return (ARCHIVE_OK); +} + +int +archive_write_disk_set_user_lookup(struct archive *_a, + void *private_data, + int64_t (*lookup_uid)(void *private, const char *uname, int64_t uid), + void (*cleanup_uid)(void *private)) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_write_disk_set_user_lookup"); + + if (a->cleanup_uid != NULL && a->lookup_uid_data != NULL) + (a->cleanup_uid)(a->lookup_uid_data); + + a->lookup_uid = lookup_uid; + a->cleanup_uid = cleanup_uid; + a->lookup_uid_data = private_data; + return (ARCHIVE_OK); +} + +int64_t +archive_write_disk_gid(struct archive *_a, const char *name, int64_t id) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_write_disk_gid"); + if (a->lookup_gid) + return (a->lookup_gid)(a->lookup_gid_data, name, id); + return (id); +} + +int64_t +archive_write_disk_uid(struct archive *_a, const char *name, int64_t id) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_ANY, "archive_write_disk_uid"); + if (a->lookup_uid) + return (a->lookup_uid)(a->lookup_uid_data, name, id); + return (id); +} + +/* + * Create a new archive_write_disk object and initialize it with global state. + */ +struct archive * +archive_write_disk_new(void) +{ + struct archive_write_disk *a; + + a = (struct archive_write_disk *)calloc(1, sizeof(*a)); + if (a == NULL) + return (NULL); + a->archive.magic = ARCHIVE_WRITE_DISK_MAGIC; + /* We're ready to write a header immediately. */ + a->archive.state = ARCHIVE_STATE_HEADER; + a->archive.vtable = archive_write_disk_vtable(); + a->start_time = time(NULL); + /* Query and restore the umask. */ + umask(a->user_umask = umask(0)); +#ifdef HAVE_GETEUID + a->user_uid = geteuid(); +#endif /* HAVE_GETEUID */ + if (archive_string_ensure(&a->path_safe, 512) == NULL) { + free(a); + return (NULL); + } +#ifdef HAVE_ZLIB_H + a->decmpfs_compression_level = 5; +#endif + return (&a->archive); +} + + +/* + * If pathname is longer than PATH_MAX, chdir to a suitable + * intermediate dir and edit the path down to a shorter suffix. Note + * that this routine never returns an error; if the chdir() attempt + * fails for any reason, we just go ahead with the long pathname. The + * object creation is likely to fail, but any error will get handled + * at that time. + */ +#if defined(HAVE_FCHDIR) && defined(PATH_MAX) +static void +edit_deep_directories(struct archive_write_disk *a) +{ + int ret; + char *tail = a->name; + + /* If path is short, avoid the open() below. */ + if (strlen(tail) < PATH_MAX) + return; + + /* Try to record our starting dir. */ + a->restore_pwd = open(".", O_RDONLY | O_BINARY | O_CLOEXEC); + __archive_ensure_cloexec_flag(a->restore_pwd); + if (a->restore_pwd < 0) + return; + + /* As long as the path is too long... */ + while (strlen(tail) >= PATH_MAX) { + /* Locate a dir prefix shorter than PATH_MAX. */ + tail += PATH_MAX - 8; + while (tail > a->name && *tail != '/') + tail--; + /* Exit if we find a too-long path component. */ + if (tail <= a->name) + return; + /* Create the intermediate dir and chdir to it. */ + *tail = '\0'; /* Terminate dir portion */ + ret = create_dir(a, a->name); + if (ret == ARCHIVE_OK && chdir(a->name) != 0) + ret = ARCHIVE_FAILED; + *tail = '/'; /* Restore the / we removed. */ + if (ret != ARCHIVE_OK) + return; + tail++; + /* The chdir() succeeded; we've now shortened the path. */ + a->name = tail; + } + return; +} +#endif + +/* + * The main restore function. + */ +static int +restore_entry(struct archive_write_disk *a) +{ + int ret = ARCHIVE_OK, en; + + if (a->flags & ARCHIVE_EXTRACT_UNLINK && !S_ISDIR(a->mode)) { + /* + * TODO: Fix this. Apparently, there are platforms + * that still allow root to hose the entire filesystem + * by unlinking a dir. The S_ISDIR() test above + * prevents us from using unlink() here if the new + * object is a dir, but that doesn't mean the old + * object isn't a dir. + */ + if (a->flags & ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS) + (void)clear_nochange_fflags(a); + if (unlink(a->name) == 0) { + /* We removed it, reset cached stat. */ + a->pst = NULL; + } else if (errno == ENOENT) { + /* File didn't exist, that's just as good. */ + } else if (rmdir(a->name) == 0) { + /* It was a dir, but now it's gone. */ + a->pst = NULL; + } else { + /* We tried, but couldn't get rid of it. */ + archive_set_error(&a->archive, errno, + "Could not unlink"); + return(ARCHIVE_FAILED); + } + } + + /* Try creating it first; if this fails, we'll try to recover. */ + en = create_filesystem_object(a); + + if ((en == ENOTDIR || en == ENOENT) + && !(a->flags & ARCHIVE_EXTRACT_NO_AUTODIR)) { + /* If the parent dir doesn't exist, try creating it. */ + create_parent_dir(a, a->name); + /* Now try to create the object again. */ + en = create_filesystem_object(a); + } + + if ((en == ENOENT) && (archive_entry_hardlink(a->entry) != NULL)) { + archive_set_error(&a->archive, en, + "Hard-link target '%s' does not exist.", + archive_entry_hardlink(a->entry)); + return (ARCHIVE_FAILED); + } + + if ((en == EISDIR || en == EEXIST) + && (a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) { + /* If we're not overwriting, we're done. */ + archive_entry_unset_size(a->entry); + return (ARCHIVE_OK); + } + + /* + * Some platforms return EISDIR if you call + * open(O_WRONLY | O_EXCL | O_CREAT) on a directory, some + * return EEXIST. POSIX is ambiguous, requiring EISDIR + * for open(O_WRONLY) on a dir and EEXIST for open(O_EXCL | O_CREAT) + * on an existing item. + */ + if (en == EISDIR) { + /* A dir is in the way of a non-dir, rmdir it. */ + if (rmdir(a->name) != 0) { + archive_set_error(&a->archive, errno, + "Can't remove already-existing dir"); + return (ARCHIVE_FAILED); + } + a->pst = NULL; + /* Try again. */ + en = create_filesystem_object(a); + } else if (en == EEXIST) { + /* + * We know something is in the way, but we don't know what; + * we need to find out before we go any further. + */ + int r = 0; + /* + * The SECURE_SYMLINKS logic has already removed a + * symlink to a dir if the client wants that. So + * follow the symlink if we're creating a dir. + */ + if (S_ISDIR(a->mode)) + r = stat(a->name, &a->st); + /* + * If it's not a dir (or it's a broken symlink), + * then don't follow it. + */ + if (r != 0 || !S_ISDIR(a->mode)) + r = lstat(a->name, &a->st); + if (r != 0) { + archive_set_error(&a->archive, errno, + "Can't stat existing object"); + return (ARCHIVE_FAILED); + } + + /* + * NO_OVERWRITE_NEWER doesn't apply to directories. + */ + if ((a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER) + && !S_ISDIR(a->st.st_mode)) { + if (!older(&(a->st), a->entry)) { + archive_entry_unset_size(a->entry); + return (ARCHIVE_OK); + } + } + + /* If it's our archive, we're done. */ + if (a->skip_file_set && + a->st.st_dev == (dev_t)a->skip_file_dev && + a->st.st_ino == (ino_t)a->skip_file_ino) { + archive_set_error(&a->archive, 0, + "Refusing to overwrite archive"); + return (ARCHIVE_FAILED); + } + + if (!S_ISDIR(a->st.st_mode)) { + /* A non-dir is in the way, unlink it. */ + if (a->flags & ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS) + (void)clear_nochange_fflags(a); + if (unlink(a->name) != 0) { + archive_set_error(&a->archive, errno, + "Can't unlink already-existing object"); + return (ARCHIVE_FAILED); + } + a->pst = NULL; + /* Try again. */ + en = create_filesystem_object(a); + } else if (!S_ISDIR(a->mode)) { + /* A dir is in the way of a non-dir, rmdir it. */ + if (a->flags & ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS) + (void)clear_nochange_fflags(a); + if (rmdir(a->name) != 0) { + archive_set_error(&a->archive, errno, + "Can't replace existing directory with non-directory"); + return (ARCHIVE_FAILED); + } + /* Try again. */ + en = create_filesystem_object(a); + } else { + /* + * There's a dir in the way of a dir. Don't + * waste time with rmdir()/mkdir(), just fix + * up the permissions on the existing dir. + * Note that we don't change perms on existing + * dirs unless _EXTRACT_PERM is specified. + */ + if ((a->mode != a->st.st_mode) + && (a->todo & TODO_MODE_FORCE)) + a->deferred |= (a->todo & TODO_MODE); + /* Ownership doesn't need deferred fixup. */ + en = 0; /* Forget the EEXIST. */ + } + } + + if (en) { + /* Everything failed; give up here. */ + if ((&a->archive)->error == NULL) + archive_set_error(&a->archive, en, "Can't create '%s'", + a->name); + return (ARCHIVE_FAILED); + } + + a->pst = NULL; /* Cached stat data no longer valid. */ + return (ret); +} + +/* + * Returns 0 if creation succeeds, or else returns errno value from + * the failed system call. Note: This function should only ever perform + * a single system call. + */ +static int +create_filesystem_object(struct archive_write_disk *a) +{ + /* Create the entry. */ + const char *linkname; + mode_t final_mode, mode; + int r; + /* these for check_symlinks_fsobj */ + char *linkname_copy; /* non-const copy of linkname */ + struct stat st; + struct archive_string error_string; + int error_number; + + /* We identify hard/symlinks according to the link names. */ + /* Since link(2) and symlink(2) don't handle modes, we're done here. */ + linkname = archive_entry_hardlink(a->entry); + if (linkname != NULL) { +#if !HAVE_LINK + return (EPERM); +#else + archive_string_init(&error_string); + linkname_copy = strdup(linkname); + if (linkname_copy == NULL) { + return (EPERM); + } + /* + * TODO: consider using the cleaned-up path as the link + * target? + */ + r = cleanup_pathname_fsobj(linkname_copy, &error_number, + &error_string, a->flags); + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, error_number, "%s", + error_string.s); + free(linkname_copy); + archive_string_free(&error_string); + /* + * EPERM is more appropriate than error_number for our + * callers + */ + return (EPERM); + } + r = check_symlinks_fsobj(linkname_copy, &error_number, + &error_string, a->flags); + if (r != ARCHIVE_OK) { + archive_set_error(&a->archive, error_number, "%s", + error_string.s); + free(linkname_copy); + archive_string_free(&error_string); + /* + * EPERM is more appropriate than error_number for our + * callers + */ + return (EPERM); + } + free(linkname_copy); + archive_string_free(&error_string); + r = link(linkname, a->name) ? errno : 0; + /* + * New cpio and pax formats allow hardlink entries + * to carry data, so we may have to open the file + * for hardlink entries. + * + * If the hardlink was successfully created and + * the archive doesn't have carry data for it, + * consider it to be non-authoritative for meta data. + * This is consistent with GNU tar and BSD pax. + * If the hardlink does carry data, let the last + * archive entry decide ownership. + */ + if (r == 0 && a->filesize <= 0) { + a->todo = 0; + a->deferred = 0; + } else if (r == 0 && a->filesize > 0) { +#ifdef HAVE_LSTAT + r = lstat(a->name, &st); +#else + r = stat(a->name, &st); +#endif + if (r != 0) + r = errno; + else if ((st.st_mode & AE_IFMT) == AE_IFREG) { + a->fd = open(a->name, O_WRONLY | O_TRUNC | + O_BINARY | O_CLOEXEC | O_NOFOLLOW); + __archive_ensure_cloexec_flag(a->fd); + if (a->fd < 0) + r = errno; + } + } + return (r); +#endif + } + linkname = archive_entry_symlink(a->entry); + if (linkname != NULL) { +#if HAVE_SYMLINK + return symlink(linkname, a->name) ? errno : 0; +#else + return (EPERM); +#endif + } + + /* + * The remaining system calls all set permissions, so let's + * try to take advantage of that to avoid an extra chmod() + * call. (Recall that umask is set to zero right now!) + */ + + /* Mode we want for the final restored object (w/o file type bits). */ + final_mode = a->mode & 07777; + /* + * The mode that will actually be restored in this step. Note + * that SUID, SGID, etc, require additional work to ensure + * security, so we never restore them at this point. + */ + mode = final_mode & 0777 & ~a->user_umask; + + switch (a->mode & AE_IFMT) { + default: + /* POSIX requires that we fall through here. */ + /* FALLTHROUGH */ + case AE_IFREG: + a->fd = open(a->name, + O_WRONLY | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC, mode); + __archive_ensure_cloexec_flag(a->fd); + r = (a->fd < 0); + break; + case AE_IFCHR: +#ifdef HAVE_MKNOD + /* Note: we use AE_IFCHR for the case label, and + * S_IFCHR for the mknod() call. This is correct. */ + r = mknod(a->name, mode | S_IFCHR, + archive_entry_rdev(a->entry)); + break; +#else + /* TODO: Find a better way to warn about our inability + * to restore a char device node. */ + return (EINVAL); +#endif /* HAVE_MKNOD */ + case AE_IFBLK: +#ifdef HAVE_MKNOD + r = mknod(a->name, mode | S_IFBLK, + archive_entry_rdev(a->entry)); + break; +#else + /* TODO: Find a better way to warn about our inability + * to restore a block device node. */ + return (EINVAL); +#endif /* HAVE_MKNOD */ + case AE_IFDIR: + mode = (mode | MINIMUM_DIR_MODE) & MAXIMUM_DIR_MODE; + r = mkdir(a->name, mode); + if (r == 0) { + /* Defer setting dir times. */ + a->deferred |= (a->todo & TODO_TIMES); + a->todo &= ~TODO_TIMES; + /* Never use an immediate chmod(). */ + /* We can't avoid the chmod() entirely if EXTRACT_PERM + * because of SysV SGID inheritance. */ + if ((mode != final_mode) + || (a->flags & ARCHIVE_EXTRACT_PERM)) + a->deferred |= (a->todo & TODO_MODE); + a->todo &= ~TODO_MODE; + } + break; + case AE_IFIFO: +#ifdef HAVE_MKFIFO + r = mkfifo(a->name, mode); + break; +#else + /* TODO: Find a better way to warn about our inability + * to restore a fifo. */ + return (EINVAL); +#endif /* HAVE_MKFIFO */ + } + + /* All the system calls above set errno on failure. */ + if (r) + return (errno); + + /* If we managed to set the final mode, we've avoided a chmod(). */ + if (mode == final_mode) + a->todo &= ~TODO_MODE; + return (0); +} + +/* + * Cleanup function for archive_extract. Mostly, this involves processing + * the fixup list, which is used to address a number of problems: + * * Dir permissions might prevent us from restoring a file in that + * dir, so we restore the dir with minimum 0700 permissions first, + * then correct the mode at the end. + * * Similarly, the act of restoring a file touches the directory + * and changes the timestamp on the dir, so we have to touch-up dir + * timestamps at the end as well. + * * Some file flags can interfere with the restore by, for example, + * preventing the creation of hardlinks to those files. + * * Mac OS extended metadata includes ACLs, so must be deferred on dirs. + * + * Note that tar/cpio do not require that archives be in a particular + * order; there is no way to know when the last file has been restored + * within a directory, so there's no way to optimize the memory usage + * here by fixing up the directory any earlier than the + * end-of-archive. + * + * XXX TODO: Directory ACLs should be restored here, for the same + * reason we set directory perms here. XXX + */ +static int +_archive_write_disk_close(struct archive *_a) +{ + struct archive_write_disk *a = (struct archive_write_disk *)_a; + struct fixup_entry *next, *p; + int ret; + + archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_HEADER | ARCHIVE_STATE_DATA, + "archive_write_disk_close"); + ret = _archive_write_disk_finish_entry(&a->archive); + + /* Sort dir list so directories are fixed up in depth-first order. */ + p = sort_dir_list(a->fixup_list); + + while (p != NULL) { + a->pst = NULL; /* Mark stat cache as out-of-date. */ + if (p->fixup & TODO_TIMES) { + set_times(a, -1, p->mode, p->name, + p->atime, p->atime_nanos, + p->birthtime, p->birthtime_nanos, + p->mtime, p->mtime_nanos, + p->ctime, p->ctime_nanos); + } + if (p->fixup & TODO_MODE_BASE) + chmod(p->name, p->mode); + if (p->fixup & TODO_ACLS) +#ifdef HAVE_DARWIN_ACL - if (p->mac_metadata == NULL || ++ 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); + if (p->fixup & TODO_FFLAGS) + set_fflags_platform(a, -1, p->name, + p->mode, p->fflags_set, 0); + if (p->fixup & TODO_MAC_METADATA) + set_mac_metadata(a, p->name, p->mac_metadata, + p->mac_metadata_size); + next = p->next; + archive_acl_clear(&p->acl); + free(p->mac_metadata); + free(p->name); + free(p); + p = next; + } + a->fixup_list = NULL; + return (ret); +} + +static int +_archive_write_disk_free(struct archive *_a) +{ + struct archive_write_disk *a; + int ret; + if (_a == NULL) + return (ARCHIVE_OK); + archive_check_magic(_a, ARCHIVE_WRITE_DISK_MAGIC, + ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_write_disk_free"); + a = (struct archive_write_disk *)_a; + ret = _archive_write_disk_close(&a->archive); + archive_write_disk_set_group_lookup(&a->archive, NULL, NULL, NULL); + archive_write_disk_set_user_lookup(&a->archive, NULL, NULL, NULL); + if (a->entry) + archive_entry_free(a->entry); + archive_string_free(&a->_name_data); + archive_string_free(&a->archive.error_string); + archive_string_free(&a->path_safe); + a->archive.magic = 0; + __archive_clean(&a->archive); + free(a->decmpfs_header_p); + free(a->resource_fork); + free(a->compressed_buffer); + free(a->uncompressed_buffer); +#if defined(__APPLE__) && defined(UF_COMPRESSED) && defined(HAVE_SYS_XATTR_H)\ + && defined(HAVE_ZLIB_H) + if (a->stream_valid) { + switch (deflateEnd(&a->stream)) { + case Z_OK: + break; + default: + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Failed to clean up compressor"); + ret = ARCHIVE_FATAL; + break; + } + } +#endif + free(a); + return (ret); +} + +/* + * Simple O(n log n) merge sort to order the fixup list. In + * particular, we want to restore dir timestamps depth-first. + */ +static struct fixup_entry * +sort_dir_list(struct fixup_entry *p) +{ + struct fixup_entry *a, *b, *t; + + if (p == NULL) + return (NULL); + /* A one-item list is already sorted. */ + if (p->next == NULL) + return (p); + + /* Step 1: split the list. */ + t = p; + a = p->next->next; + while (a != NULL) { + /* Step a twice, t once. */ + a = a->next; + if (a != NULL) + a = a->next; + t = t->next; + } + /* Now, t is at the mid-point, so break the list here. */ + b = t->next; + t->next = NULL; + a = p; + + /* Step 2: Recursively sort the two sub-lists. */ + a = sort_dir_list(a); + b = sort_dir_list(b); + + /* Step 3: Merge the returned lists. */ + /* Pick the first element for the merged list. */ + if (strcmp(a->name, b->name) > 0) { + t = p = a; + a = a->next; + } else { + t = p = b; + b = b->next; + } + + /* Always put the later element on the list first. */ + while (a != NULL && b != NULL) { + if (strcmp(a->name, b->name) > 0) { + t->next = a; + a = a->next; + } else { + t->next = b; + b = b->next; + } + t = t->next; + } + + /* Only one list is non-empty, so just splice it on. */ + if (a != NULL) + t->next = a; + if (b != NULL) + t->next = b; + + return (p); +} + +/* + * Returns a new, initialized fixup entry. + * + * TODO: Reduce the memory requirements for this list by using a tree + * structure rather than a simple list of names. + */ +static struct fixup_entry * +new_fixup(struct archive_write_disk *a, const char *pathname) +{ + struct fixup_entry *fe; + + fe = (struct fixup_entry *)calloc(1, sizeof(struct fixup_entry)); + if (fe == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for a fixup"); + return (NULL); + } + fe->next = a->fixup_list; + a->fixup_list = fe; + fe->fixup = 0; + fe->name = strdup(pathname); + return (fe); +} + +/* + * Returns a fixup structure for the current entry. + */ +static struct fixup_entry * +current_fixup(struct archive_write_disk *a, const char *pathname) +{ + if (a->current_fixup == NULL) + a->current_fixup = new_fixup(a, pathname); + return (a->current_fixup); +} + +/* Error helper for new *_fsobj functions */ +static void +fsobj_error(int *a_eno, struct archive_string *a_estr, + int err, const char *errstr, const char *path) +{ + if (a_eno) + *a_eno = err; + if (a_estr) + archive_string_sprintf(a_estr, errstr, path); +} + +/* + * TODO: Someday, integrate this with the deep dir support; they both + * scan the path and both can be optimized by comparing against other + * recent paths. + */ +/* TODO: Extend this to support symlinks on Windows Vista and later. */ + +/* + * Checks the given path to see if any elements along it are symlinks. Returns + * ARCHIVE_OK if there are none, otherwise puts an error in errmsg. + */ +static int +check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, + int flags) +{ +#if !defined(HAVE_LSTAT) + /* Platform doesn't have lstat, so we can't look for symlinks. */ + (void)path; /* UNUSED */ + (void)error_number; /* UNUSED */ + (void)error_string; /* UNUSED */ + (void)flags; /* UNUSED */ + return (ARCHIVE_OK); +#else + int res = ARCHIVE_OK; + char *tail; + char *head; + int last; + char c; + int r; + struct stat st; + int restore_pwd; + + /* Nothing to do here if name is empty */ + if(path[0] == '\0') + return (ARCHIVE_OK); + + /* + * Guard against symlink tricks. Reject any archive entry whose + * destination would be altered by a symlink. + * + * Walk the filename in chunks separated by '/'. For each segment: + * - if it doesn't exist, continue + * - if it's symlink, abort or remove it + * - if it's a directory and it's not the last chunk, cd into it + * As we go: + * head points to the current (relative) path + * tail points to the temporary \0 terminating the segment we're + * currently examining + * c holds what used to be in *tail + * last is 1 if this is the last tail + */ + restore_pwd = open(".", O_RDONLY | O_BINARY | O_CLOEXEC); + __archive_ensure_cloexec_flag(restore_pwd); + if (restore_pwd < 0) + return (ARCHIVE_FATAL); + head = path; + tail = path; + last = 0; + /* TODO: reintroduce a safe cache here? */ + /* Skip the root directory if the path is absolute. */ + if(tail == path && tail[0] == '/') + ++tail; + /* Keep going until we've checked the entire name. + * head, tail, path all alias the same string, which is + * temporarily zeroed at tail, so be careful restoring the + * stashed (c=tail[0]) for error messages. + * Exiting the loop with break is okay; continue is not. + */ + while (!last) { + /* + * Skip the separator we just consumed, plus any adjacent ones + */ + while (*tail == '/') + ++tail; + /* Skip the next path element. */ + while (*tail != '\0' && *tail != '/') + ++tail; + /* is this the last path component? */ + last = (tail[0] == '\0') || (tail[0] == '/' && tail[1] == '\0'); + /* temporarily truncate the string here */ + c = tail[0]; + tail[0] = '\0'; + /* Check that we haven't hit a symlink. */ + r = lstat(head, &st); + if (r != 0) { + tail[0] = c; + /* We've hit a dir that doesn't exist; stop now. */ + if (errno == ENOENT) { + break; + } else { + /* + * Treat any other error as fatal - best to be + * paranoid here. + * Note: This effectively disables deep + * directory support when security checks are + * enabled. Otherwise, very long pathnames that + * trigger an error here could evade the + * sandbox. + * TODO: We could do better, but it would + * probably require merging the symlink checks + * with the deep-directory editing. + */ + fsobj_error(a_eno, a_estr, errno, + "Could not stat %s", path); + res = ARCHIVE_FAILED; + break; + } + } else if (S_ISDIR(st.st_mode)) { + if (!last) { + if (chdir(head) != 0) { + tail[0] = c; + fsobj_error(a_eno, a_estr, errno, + "Could not chdir %s", path); + res = (ARCHIVE_FATAL); + break; + } + /* Our view is now from inside this dir: */ + head = tail + 1; + } + } else if (S_ISLNK(st.st_mode)) { + if (last) { + /* + * Last element is symlink; remove it + * so we can overwrite it with the + * item being extracted. + */ + if (unlink(head)) { + tail[0] = c; + fsobj_error(a_eno, a_estr, errno, + "Could not remove symlink %s", + path); + res = ARCHIVE_FAILED; + break; + } + /* + * Even if we did remove it, a warning + * is in order. The warning is silly, + * though, if we're just replacing one + * symlink with another symlink. + */ + tail[0] = c; + /* + * FIXME: not sure how important this is to + * restore + */ + /* + if (!S_ISLNK(path)) { + fsobj_error(a_eno, a_estr, 0, + "Removing symlink %s", path); + } + */ + /* Symlink gone. No more problem! */ + res = ARCHIVE_OK; + break; + } else if (flags & ARCHIVE_EXTRACT_UNLINK) { + /* User asked us to remove problems. */ + if (unlink(head) != 0) { + tail[0] = c; + fsobj_error(a_eno, a_estr, 0, + "Cannot remove intervening " + "symlink %s", path); + res = ARCHIVE_FAILED; + break; + } + tail[0] = c; + } else if ((flags & + ARCHIVE_EXTRACT_SECURE_SYMLINKS) == 0) { + /* + * We are not the last element and we want to + * follow symlinks if they are a directory. + * + * This is needed to extract hardlinks over + * symlinks. + */ + r = stat(head, &st); + if (r != 0) { + tail[0] = c; + if (errno == ENOENT) { + break; + } else { + fsobj_error(a_eno, a_estr, + errno, + "Could not stat %s", path); + res = (ARCHIVE_FAILED); + break; + } + } else if (S_ISDIR(st.st_mode)) { + if (chdir(head) != 0) { + tail[0] = c; + fsobj_error(a_eno, a_estr, + errno, + "Could not chdir %s", path); + res = (ARCHIVE_FATAL); + break; + } + /* + * Our view is now from inside + * this dir: + */ + head = tail + 1; + } else { + tail[0] = c; + fsobj_error(a_eno, a_estr, 0, + "Cannot extract through " + "symlink %s", path); + res = ARCHIVE_FAILED; + break; + } + } else { + tail[0] = c; + fsobj_error(a_eno, a_estr, 0, + "Cannot extract through symlink %s", path); + res = ARCHIVE_FAILED; + break; + } + } + /* be sure to always maintain this */ + tail[0] = c; + if (tail[0] != '\0') + tail++; /* Advance to the next segment. */ + } + /* Catches loop exits via break */ + tail[0] = c; +#ifdef HAVE_FCHDIR + /* If we changed directory above, restore it here. */ + if (restore_pwd >= 0) { + r = fchdir(restore_pwd); + if (r != 0) { + fsobj_error(a_eno, a_estr, errno, + "chdir() failure", ""); + } + close(restore_pwd); + restore_pwd = -1; + if (r != 0) { + res = (ARCHIVE_FATAL); + } + } +#endif + /* TODO: reintroduce a safe cache here? */ + return res; +#endif +} + +/* + * Check a->name for symlinks, returning ARCHIVE_OK if its clean, otherwise + * calls archive_set_error and returns ARCHIVE_{FATAL,FAILED} + */ +static int +check_symlinks(struct archive_write_disk *a) +{ + struct archive_string error_string; + int error_number; + int rc; + archive_string_init(&error_string); + rc = check_symlinks_fsobj(a->name, &error_number, &error_string, + a->flags); + if (rc != ARCHIVE_OK) { + archive_set_error(&a->archive, error_number, "%s", + error_string.s); + } + archive_string_free(&error_string); + a->pst = NULL; /* to be safe */ + return rc; +} + + +#if defined(__CYGWIN__) +/* + * 1. Convert a path separator from '\' to '/' . + * We shouldn't check multibyte character directly because some + * character-set have been using the '\' character for a part of + * its multibyte character code. + * 2. Replace unusable characters in Windows with underscore('_'). + * See also : http://msdn.microsoft.com/en-us/library/aa365247.aspx + */ +static void +cleanup_pathname_win(char *path) +{ + wchar_t wc; + char *p; + size_t alen, l; + int mb, complete, utf8; + + alen = 0; + mb = 0; + complete = 1; + utf8 = (strcmp(nl_langinfo(CODESET), "UTF-8") == 0)? 1: 0; + for (p = path; *p != '\0'; p++) { + ++alen; + if (*p == '\\') { + /* If previous byte is smaller than 128, + * this is not second byte of multibyte characters, + * so we can replace '\' with '/'. */ + if (utf8 || !mb) + *p = '/'; + else + complete = 0;/* uncompleted. */ + } else if (*(unsigned char *)p > 127) + mb = 1; + else + mb = 0; + /* Rewrite the path name if its next character is unusable. */ + if (*p == ':' || *p == '*' || *p == '?' || *p == '"' || + *p == '<' || *p == '>' || *p == '|') + *p = '_'; + } + if (complete) + return; + + /* + * Convert path separator in wide-character. + */ + p = path; + while (*p != '\0' && alen) { + l = mbtowc(&wc, p, alen); + if (l == (size_t)-1) { + while (*p != '\0') { + if (*p == '\\') + *p = '/'; + ++p; + } + break; + } + if (l == 1 && wc == L'\\') + *p = '/'; + p += l; + alen -= l; + } +} +#endif + +/* + * Canonicalize the pathname. In particular, this strips duplicate + * '/' characters, '.' elements, and trailing '/'. It also raises an + * error for an empty path, a trailing '..', (if _SECURE_NODOTDOT is + * set) any '..' in the path or (if ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS + * is set) if the path is absolute. + */ +static int +cleanup_pathname_fsobj(char *path, int *a_eno, struct archive_string *a_estr, + int flags) +{ + char *dest, *src; + char separator = '\0'; + + dest = src = path; + if (*src == '\0') { + fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC, + "Invalid empty ", "pathname"); + return (ARCHIVE_FAILED); + } + +#if defined(__CYGWIN__) + cleanup_pathname_win(path); +#endif + /* Skip leading '/'. */ + if (*src == '/') { + if (flags & ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS) { + fsobj_error(a_eno, a_estr, ARCHIVE_ERRNO_MISC, + "Path is ", "absolute"); + return (ARCHIVE_FAILED); + } + + separator = *src++; + } + + /* Scan the pathname one element at a time. */ + for (;;) { + /* src points to first char after '/' */ + if (src[0] == '\0') { + break; + } else if (src[0] == '/') { + /* Found '//', ignore second one. */ + src++; + continue; + } else if (src[0] == '.') { + if (src[1] == '\0') { + /* Ignore trailing '.' */ + break; + } else if (src[1] == '/') { + /* Skip './'. */ + src += 2; + continue; + } else if (src[1] == '.') { + if (src[2] == '/' || src[2] == '\0') { + /* Conditionally warn about '..' */ + if (flags + & ARCHIVE_EXTRACT_SECURE_NODOTDOT) { + fsobj_error(a_eno, a_estr, + ARCHIVE_ERRNO_MISC, + "Path contains ", "'..'"); + return (ARCHIVE_FAILED); + } + } + /* + * Note: Under no circumstances do we + * remove '..' elements. In + * particular, restoring + * '/foo/../bar/' should create the + * 'foo' dir as a side-effect. + */ + } + } + + /* Copy current element, including leading '/'. */ + if (separator) + *dest++ = '/'; + while (*src != '\0' && *src != '/') { + *dest++ = *src++; + } + + if (*src == '\0') + break; + + /* Skip '/' separator. */ + separator = *src++; + } + /* + * We've just copied zero or more path elements, not including the + * final '/'. + */ + if (dest == path) { + /* + * Nothing got copied. The path must have been something + * like '.' or '/' or './' or '/././././/./'. + */ + if (separator) + *dest++ = '/'; + else + *dest++ = '.'; + } + /* Terminate the result. */ + *dest = '\0'; + return (ARCHIVE_OK); +} + +static int +cleanup_pathname(struct archive_write_disk *a) +{ + struct archive_string error_string; + int error_number; + int rc; + archive_string_init(&error_string); + rc = cleanup_pathname_fsobj(a->name, &error_number, &error_string, + a->flags); + if (rc != ARCHIVE_OK) { + archive_set_error(&a->archive, error_number, "%s", + error_string.s); + } + archive_string_free(&error_string); + return rc; +} + +/* + * Create the parent directory of the specified path, assuming path + * is already in mutable storage. + */ +static int +create_parent_dir(struct archive_write_disk *a, char *path) +{ + char *slash; + int r; + + /* Remove tail element to obtain parent name. */ + slash = strrchr(path, '/'); + if (slash == NULL) + return (ARCHIVE_OK); + *slash = '\0'; + r = create_dir(a, path); + *slash = '/'; + return (r); +} + +/* + * Create the specified dir, recursing to create parents as necessary. + * + * Returns ARCHIVE_OK if the path exists when we're done here. + * Otherwise, returns ARCHIVE_FAILED. + * Assumes path is in mutable storage; path is unchanged on exit. + */ +static int +create_dir(struct archive_write_disk *a, char *path) +{ + struct stat st; + struct fixup_entry *le; + char *slash, *base; + mode_t mode_final, mode; + int r; + + /* Check for special names and just skip them. */ + slash = strrchr(path, '/'); + if (slash == NULL) + base = path; + else + base = slash + 1; + + if (base[0] == '\0' || + (base[0] == '.' && base[1] == '\0') || + (base[0] == '.' && base[1] == '.' && base[2] == '\0')) { + /* Don't bother trying to create null path, '.', or '..'. */ + if (slash != NULL) { + *slash = '\0'; + r = create_dir(a, path); + *slash = '/'; + return (r); + } + return (ARCHIVE_OK); + } + + /* + * Yes, this should be stat() and not lstat(). Using lstat() + * here loses the ability to extract through symlinks. Also note + * that this should not use the a->st cache. + */ + if (stat(path, &st) == 0) { + if (S_ISDIR(st.st_mode)) + return (ARCHIVE_OK); + if ((a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) { + archive_set_error(&a->archive, EEXIST, + "Can't create directory '%s'", path); + return (ARCHIVE_FAILED); + } + if (unlink(path) != 0) { + archive_set_error(&a->archive, errno, + "Can't create directory '%s': " + "Conflicting file cannot be removed", + path); + return (ARCHIVE_FAILED); + } + } else if (errno != ENOENT && errno != ENOTDIR) { + /* Stat failed? */ + archive_set_error(&a->archive, errno, + "Can't test directory '%s'", path); + return (ARCHIVE_FAILED); + } else if (slash != NULL) { + *slash = '\0'; + r = create_dir(a, path); + *slash = '/'; + if (r != ARCHIVE_OK) + return (r); + } + + /* + * Mode we want for the final restored directory. Per POSIX, + * implicitly-created dirs must be created obeying the umask. + * There's no mention whether this is different for privileged + * restores (which the rest of this code handles by pretending + * umask=0). I've chosen here to always obey the user's umask for + * implicit dirs, even if _EXTRACT_PERM was specified. + */ + mode_final = DEFAULT_DIR_MODE & ~a->user_umask; + /* Mode we want on disk during the restore process. */ + mode = mode_final; + mode |= MINIMUM_DIR_MODE; + mode &= MAXIMUM_DIR_MODE; + if (mkdir(path, mode) == 0) { + if (mode != mode_final) { + le = new_fixup(a, path); + if (le == NULL) + return (ARCHIVE_FATAL); + le->fixup |=TODO_MODE_BASE; + le->mode = mode_final; + } + return (ARCHIVE_OK); + } + + /* + * Without the following check, a/b/../b/c/d fails at the + * second visit to 'b', so 'd' can't be created. Note that we + * don't add it to the fixup list here, as it's already been + * added. + */ + if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) + return (ARCHIVE_OK); + + archive_set_error(&a->archive, errno, "Failed to create dir '%s'", + path); + return (ARCHIVE_FAILED); +} + +/* + * Note: Although we can skip setting the user id if the desired user + * id matches the current user, we cannot skip setting the group, as + * many systems set the gid based on the containing directory. So + * we have to perform a chown syscall if we want to set the SGID + * bit. (The alternative is to stat() and then possibly chown(); it's + * more efficient to skip the stat() and just always chown().) Note + * that a successful chown() here clears the TODO_SGID_CHECK bit, which + * allows set_mode to skip the stat() check for the GID. + */ +static int +set_ownership(struct archive_write_disk *a) +{ +#ifndef __CYGWIN__ +/* unfortunately, on win32 there is no 'root' user with uid 0, + so we just have to try the chown and see if it works */ + + /* If we know we can't change it, don't bother trying. */ + if (a->user_uid != 0 && a->user_uid != a->uid) { + archive_set_error(&a->archive, errno, + "Can't set UID=%jd", (intmax_t)a->uid); + return (ARCHIVE_WARN); + } +#endif + +#ifdef HAVE_FCHOWN + /* If we have an fd, we can avoid a race. */ + if (a->fd >= 0 && fchown(a->fd, a->uid, a->gid) == 0) { + /* We've set owner and know uid/gid are correct. */ + a->todo &= ~(TODO_OWNER | TODO_SGID_CHECK | TODO_SUID_CHECK); + return (ARCHIVE_OK); + } +#endif + + /* We prefer lchown() but will use chown() if that's all we have. */ + /* Of course, if we have neither, this will always fail. */ +#ifdef HAVE_LCHOWN + if (lchown(a->name, a->uid, a->gid) == 0) { + /* We've set owner and know uid/gid are correct. */ + a->todo &= ~(TODO_OWNER | TODO_SGID_CHECK | TODO_SUID_CHECK); + return (ARCHIVE_OK); + } +#elif HAVE_CHOWN + if (!S_ISLNK(a->mode) && chown(a->name, a->uid, a->gid) == 0) { + /* We've set owner and know uid/gid are correct. */ + a->todo &= ~(TODO_OWNER | TODO_SGID_CHECK | TODO_SUID_CHECK); + return (ARCHIVE_OK); + } +#endif + + archive_set_error(&a->archive, errno, + "Can't set user=%jd/group=%jd for %s", + (intmax_t)a->uid, (intmax_t)a->gid, a->name); + return (ARCHIVE_WARN); +} + +/* + * Note: Returns 0 on success, non-zero on failure. + */ +static int +set_time(int fd, int mode, const char *name, + time_t atime, long atime_nsec, + time_t mtime, long mtime_nsec) +{ + /* Select the best implementation for this platform. */ +#if defined(HAVE_UTIMENSAT) && defined(HAVE_FUTIMENS) + /* + * utimensat() and futimens() are defined in + * POSIX.1-2008. They support ns resolution and setting times + * on fds and symlinks. + */ + struct timespec ts[2]; + (void)mode; /* UNUSED */ + ts[0].tv_sec = atime; + ts[0].tv_nsec = atime_nsec; + ts[1].tv_sec = mtime; + ts[1].tv_nsec = mtime_nsec; + if (fd >= 0) + return futimens(fd, ts); + return utimensat(AT_FDCWD, name, ts, AT_SYMLINK_NOFOLLOW); + +#elif HAVE_UTIMES + /* + * The utimes()-family functions support ?s-resolution and + * setting times fds and symlinks. utimes() is documented as + * LEGACY by POSIX, futimes() and lutimes() are not described + * in POSIX. + */ + struct timeval times[2]; + + times[0].tv_sec = atime; + times[0].tv_usec = atime_nsec / 1000; + times[1].tv_sec = mtime; + times[1].tv_usec = mtime_nsec / 1000; + +#ifdef HAVE_FUTIMES + if (fd >= 0) + return (futimes(fd, times)); +#else + (void)fd; /* UNUSED */ +#endif +#ifdef HAVE_LUTIMES + (void)mode; /* UNUSED */ + return (lutimes(name, times)); +#else + if (S_ISLNK(mode)) + return (0); + return (utimes(name, times)); +#endif + +#elif defined(HAVE_UTIME) + /* + * utime() is POSIX-standard but only supports 1s resolution and + * does not support fds or symlinks. + */ + struct utimbuf times; + (void)fd; /* UNUSED */ + (void)name; /* UNUSED */ + (void)atime_nsec; /* UNUSED */ + (void)mtime_nsec; /* UNUSED */ + times.actime = atime; + times.modtime = mtime; + if (S_ISLNK(mode)) + return (ARCHIVE_OK); + return (utime(name, ×)); + +#else + /* + * We don't know how to set the time on this platform. + */ + (void)fd; /* UNUSED */ + (void)mode; /* UNUSED */ + (void)name; /* UNUSED */ + (void)atime_nsec; /* UNUSED */ + (void)mtime_nsec; /* UNUSED */ + return (ARCHIVE_WARN); +#endif +} + +#ifdef F_SETTIMES +static int +set_time_tru64(int fd, int mode, const char *name, + time_t atime, long atime_nsec, + time_t mtime, long mtime_nsec, + time_t ctime, long ctime_nsec) +{ + struct attr_timbuf tstamp; + tstamp.atime.tv_sec = atime; + tstamp.mtime.tv_sec = mtime; + tstamp.ctime.tv_sec = ctime; +#if defined (__hpux) && defined (__ia64) + tstamp.atime.tv_nsec = atime_nsec; + tstamp.mtime.tv_nsec = mtime_nsec; + tstamp.ctime.tv_nsec = ctime_nsec; +#else + tstamp.atime.tv_usec = atime_nsec / 1000; + tstamp.mtime.tv_usec = mtime_nsec / 1000; + tstamp.ctime.tv_usec = ctime_nsec / 1000; +#endif + return (fcntl(fd,F_SETTIMES,&tstamp)); +} +#endif /* F_SETTIMES */ + +static int +set_times(struct archive_write_disk *a, + int fd, int mode, const char *name, + time_t atime, long atime_nanos, + time_t birthtime, long birthtime_nanos, + time_t mtime, long mtime_nanos, + time_t cctime, long ctime_nanos) +{ + /* Note: set_time doesn't use libarchive return conventions! + * It uses syscall conventions. So 0 here instead of ARCHIVE_OK. */ + int r1 = 0, r2 = 0; + +#ifdef F_SETTIMES + /* + * on Tru64 try own fcntl first which can restore even the + * ctime, fall back to default code path below if it fails + * or if we are not running as root + */ + if (a->user_uid == 0 && + set_time_tru64(fd, mode, name, + atime, atime_nanos, mtime, + mtime_nanos, cctime, ctime_nanos) == 0) { + return (ARCHIVE_OK); + } +#else /* Tru64 */ + (void)cctime; /* UNUSED */ + (void)ctime_nanos; /* UNUSED */ +#endif /* Tru64 */ + +#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME + /* + * If you have struct stat.st_birthtime, we assume BSD + * birthtime semantics, in which {f,l,}utimes() updates + * birthtime to earliest mtime. So we set the time twice, + * first using the birthtime, then using the mtime. If + * birthtime == mtime, this isn't necessary, so we skip it. + * If birthtime > mtime, then this won't work, so we skip it. + */ + if (birthtime < mtime + || (birthtime == mtime && birthtime_nanos < mtime_nanos)) + r1 = set_time(fd, mode, name, + atime, atime_nanos, + birthtime, birthtime_nanos); +#else + (void)birthtime; /* UNUSED */ + (void)birthtime_nanos; /* UNUSED */ +#endif + r2 = set_time(fd, mode, name, + atime, atime_nanos, + mtime, mtime_nanos); + if (r1 != 0 || r2 != 0) { + archive_set_error(&a->archive, errno, + "Can't restore time"); + return (ARCHIVE_WARN); + } + return (ARCHIVE_OK); +} + +static int +set_times_from_entry(struct archive_write_disk *a) +{ + time_t atime, birthtime, mtime, cctime; + long atime_nsec, birthtime_nsec, mtime_nsec, ctime_nsec; + + /* Suitable defaults. */ + atime = birthtime = mtime = cctime = a->start_time; + atime_nsec = birthtime_nsec = mtime_nsec = ctime_nsec = 0; + + /* If no time was provided, we're done. */ + if (!archive_entry_atime_is_set(a->entry) +#if HAVE_STRUCT_STAT_ST_BIRTHTIME + && !archive_entry_birthtime_is_set(a->entry) +#endif + && !archive_entry_mtime_is_set(a->entry)) + return (ARCHIVE_OK); + + if (archive_entry_atime_is_set(a->entry)) { + atime = archive_entry_atime(a->entry); + atime_nsec = archive_entry_atime_nsec(a->entry); + } + if (archive_entry_birthtime_is_set(a->entry)) { + birthtime = archive_entry_birthtime(a->entry); + birthtime_nsec = archive_entry_birthtime_nsec(a->entry); + } + if (archive_entry_mtime_is_set(a->entry)) { + mtime = archive_entry_mtime(a->entry); + mtime_nsec = archive_entry_mtime_nsec(a->entry); + } + if (archive_entry_ctime_is_set(a->entry)) { + cctime = archive_entry_ctime(a->entry); + ctime_nsec = archive_entry_ctime_nsec(a->entry); + } + + return set_times(a, a->fd, a->mode, a->name, + atime, atime_nsec, + birthtime, birthtime_nsec, + mtime, mtime_nsec, + cctime, ctime_nsec); +} + +static int +set_mode(struct archive_write_disk *a, int mode) +{ + int r = ARCHIVE_OK; + mode &= 07777; /* Strip off file type bits. */ + + if (a->todo & TODO_SGID_CHECK) { + /* + * If we don't know the GID is right, we must stat() + * to verify it. We can't just check the GID of this + * process, since systems sometimes set GID from + * the enclosing dir or based on ACLs. + */ + if ((r = lazy_stat(a)) != ARCHIVE_OK) + return (r); + if (a->pst->st_gid != a->gid) { + mode &= ~ S_ISGID; + if (a->flags & ARCHIVE_EXTRACT_OWNER) { + /* + * This is only an error if you + * requested owner restore. If you + * didn't, we'll try to restore + * sgid/suid, but won't consider it a + * problem if we can't. + */ + archive_set_error(&a->archive, -1, + "Can't restore SGID bit"); + r = ARCHIVE_WARN; + } + } + /* While we're here, double-check the UID. */ + if (a->pst->st_uid != a->uid + && (a->todo & TODO_SUID)) { + mode &= ~ S_ISUID; + if (a->flags & ARCHIVE_EXTRACT_OWNER) { + archive_set_error(&a->archive, -1, + "Can't restore SUID bit"); + r = ARCHIVE_WARN; + } + } + a->todo &= ~TODO_SGID_CHECK; + a->todo &= ~TODO_SUID_CHECK; + } else if (a->todo & TODO_SUID_CHECK) { + /* + * If we don't know the UID is right, we can just check + * the user, since all systems set the file UID from + * the process UID. + */ + if (a->user_uid != a->uid) { + mode &= ~ S_ISUID; + if (a->flags & ARCHIVE_EXTRACT_OWNER) { + archive_set_error(&a->archive, -1, + "Can't make file SUID"); + r = ARCHIVE_WARN; + } + } + a->todo &= ~TODO_SUID_CHECK; + } + + if (S_ISLNK(a->mode)) { +#ifdef HAVE_LCHMOD + /* + * If this is a symlink, use lchmod(). If the + * platform doesn't support lchmod(), just skip it. A + * platform that doesn't provide a way to set + * permissions on symlinks probably ignores + * permissions on symlinks, so a failure here has no + * impact. + */ + if (lchmod(a->name, mode) != 0) { + switch (errno) { + case ENOTSUP: + case ENOSYS: +#if ENOTSUP != EOPNOTSUPP + case EOPNOTSUPP: +#endif + /* + * if lchmod is defined but the platform + * doesn't support it, silently ignore + * error + */ + break; + default: + archive_set_error(&a->archive, errno, + "Can't set permissions to 0%o", (int)mode); + r = ARCHIVE_WARN; + } + } +#endif + } else if (!S_ISDIR(a->mode)) { + /* + * If it's not a symlink and not a dir, then use + * fchmod() or chmod(), depending on whether we have + * an fd. Dirs get their perms set during the + * post-extract fixup, which is handled elsewhere. + */ +#ifdef HAVE_FCHMOD + if (a->fd >= 0) { + if (fchmod(a->fd, mode) != 0) { + archive_set_error(&a->archive, errno, + "Can't set permissions to 0%o", (int)mode); + r = ARCHIVE_WARN; + } + } else +#endif + /* If this platform lacks fchmod(), then + * we'll just use chmod(). */ + if (chmod(a->name, mode) != 0) { + archive_set_error(&a->archive, errno, + "Can't set permissions to 0%o", (int)mode); + r = ARCHIVE_WARN; + } + } + return (r); +} + +static int +set_fflags(struct archive_write_disk *a) +{ + struct fixup_entry *le; + unsigned long set, clear; + int r; + int critical_flags; + mode_t mode = archive_entry_mode(a->entry); + + /* + * Make 'critical_flags' hold all file flags that can't be + * immediately restored. For example, on BSD systems, + * SF_IMMUTABLE prevents hardlinks from being created, so + * should not be set until after any hardlinks are created. To + * preserve some semblance of portability, this uses #ifdef + * extensively. Ugly, but it works. + * + * Yes, Virginia, this does create a security race. It's mitigated + * somewhat by the practice of creating dirs 0700 until the extract + * is done, but it would be nice if we could do more than that. + * People restoring critical file systems should be wary of + * other programs that might try to muck with files as they're + * being restored. + */ + /* Hopefully, the compiler will optimize this mess into a constant. */ + critical_flags = 0; +#ifdef SF_IMMUTABLE + critical_flags |= SF_IMMUTABLE; +#endif +#ifdef UF_IMMUTABLE + critical_flags |= UF_IMMUTABLE; +#endif +#ifdef SF_APPEND + critical_flags |= SF_APPEND; +#endif +#ifdef UF_APPEND + critical_flags |= UF_APPEND; +#endif - #ifdef EXT2_APPEND_FL ++#if defined(FS_APPEND_FL) ++ critical_flags |= FS_APPEND_FL; ++#elif defined(EXT2_APPEND_FL) + critical_flags |= EXT2_APPEND_FL; +#endif - #ifdef EXT2_IMMUTABLE_FL ++#if defined(FS_IMMUTABLE_FL) ++ critical_flags |= FS_IMMUTABLE_FL; ++#elif defined(EXT2_IMMUTABLE_FL) + critical_flags |= EXT2_IMMUTABLE_FL; +#endif ++#ifdef FS_JOURNAL_DATA_FL ++ critical_flags |= FS_JOURNAL_DATA_FL; ++#endif + + if (a->todo & TODO_FFLAGS) { + archive_entry_fflags(a->entry, &set, &clear); + + /* + * The first test encourages the compiler to eliminate + * all of this if it's not necessary. + */ + if ((critical_flags != 0) && (set & critical_flags)) { + le = current_fixup(a, a->name); + if (le == NULL) + return (ARCHIVE_FATAL); + le->fixup |= TODO_FFLAGS; + le->fflags_set = set; + /* Store the mode if it's not already there. */ + if ((le->fixup & TODO_MODE) == 0) + le->mode = mode; + } else { + r = set_fflags_platform(a, a->fd, + a->name, mode, set, clear); + if (r != ARCHIVE_OK) + return (r); + } + } + return (ARCHIVE_OK); +} + +static int +clear_nochange_fflags(struct archive_write_disk *a) +{ + int nochange_flags; + mode_t mode = archive_entry_mode(a->entry); + + /* Hopefully, the compiler will optimize this mess into a constant. */ + nochange_flags = 0; +#ifdef SF_IMMUTABLE + nochange_flags |= SF_IMMUTABLE; +#endif +#ifdef UF_IMMUTABLE + nochange_flags |= UF_IMMUTABLE; +#endif +#ifdef SF_APPEND + nochange_flags |= SF_APPEND; +#endif +#ifdef UF_APPEND + nochange_flags |= UF_APPEND; +#endif +#ifdef EXT2_APPEND_FL + nochange_flags |= EXT2_APPEND_FL; +#endif +#ifdef EXT2_IMMUTABLE_FL + nochange_flags |= EXT2_IMMUTABLE_FL; +#endif + + return (set_fflags_platform(a, a->fd, a->name, mode, 0, + nochange_flags)); +} + + +#if ( defined(HAVE_LCHFLAGS) || defined(HAVE_CHFLAGS) || defined(HAVE_FCHFLAGS) ) && defined(HAVE_STRUCT_STAT_ST_FLAGS) +/* + * BSD reads flags using stat() and sets them with one of {f,l,}chflags() + */ +static int +set_fflags_platform(struct archive_write_disk *a, int fd, const char *name, + mode_t mode, unsigned long set, unsigned long clear) +{ + int r; + + (void)mode; /* UNUSED */ + if (set == 0 && clear == 0) + return (ARCHIVE_OK); + + /* + * XXX Is the stat here really necessary? Or can I just use + * the 'set' flags directly? In particular, I'm not sure + * about the correct approach if we're overwriting an existing + * file that already has flags on it. XXX + */ + if ((r = lazy_stat(a)) != ARCHIVE_OK) + return (r); + + a->st.st_flags &= ~clear; + a->st.st_flags |= set; +#ifdef HAVE_FCHFLAGS + /* If platform has fchflags() and we were given an fd, use it. */ + if (fd >= 0 && fchflags(fd, a->st.st_flags) == 0) + return (ARCHIVE_OK); +#endif + /* + * If we can't use the fd to set the flags, we'll use the + * pathname to set flags. We prefer lchflags() but will use + * chflags() if we must. + */ +#ifdef HAVE_LCHFLAGS + if (lchflags(name, a->st.st_flags) == 0) + return (ARCHIVE_OK); +#elif defined(HAVE_CHFLAGS) + if (S_ISLNK(a->st.st_mode)) { + archive_set_error(&a->archive, errno, + "Can't set file flags on symlink."); + return (ARCHIVE_WARN); + } + if (chflags(name, a->st.st_flags) == 0) + return (ARCHIVE_OK); +#endif + archive_set_error(&a->archive, errno, + "Failed to set file flags"); + return (ARCHIVE_WARN); +} + - #elif defined(EXT2_IOC_GETFLAGS) && defined(EXT2_IOC_SETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS) ++#elif (defined(FS_IOC_GETFLAGS) && defined(FS_IOC_SETFLAGS) && \ ++ defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \ ++ (defined(EXT2_IOC_GETFLAGS) && defined(EXT2_IOC_SETFLAGS) && \ ++ defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)) +/* + * Linux uses ioctl() to read and write file flags. + */ +static int +set_fflags_platform(struct archive_write_disk *a, int fd, const char *name, + mode_t mode, unsigned long set, unsigned long clear) +{ + int ret; + int myfd = fd; + int newflags, oldflags; + int sf_mask = 0; + - if (set == 0 && clear == 0) ++ if (set == 0 && clear == 0) + return (ARCHIVE_OK); + /* Only regular files and dirs can have flags. */ + if (!S_ISREG(mode) && !S_ISDIR(mode)) + return (ARCHIVE_OK); + + /* If we weren't given an fd, open it ourselves. */ + if (myfd < 0) { + myfd = open(name, O_RDONLY | O_NONBLOCK | O_BINARY | O_CLOEXEC); + __archive_ensure_cloexec_flag(myfd); + } + if (myfd < 0) + return (ARCHIVE_OK); + + /* + * Linux has no define for the flags that are only settable by + * the root user. This code may seem a little complex, but + * there seem to be some Linux systems that lack these + * defines. (?) The code below degrades reasonably gracefully + * if sf_mask is incomplete. + */ - #ifdef EXT2_IMMUTABLE_FL ++#if defined(FS_IMMUTABLE_FL) ++ sf_mask |= FS_IMMUTABLE_FL; ++#elif defined(EXT2_IMMUTABLE_FL) + sf_mask |= EXT2_IMMUTABLE_FL; +#endif - #ifdef EXT2_APPEND_FL ++#if defined(FS_APPEND_FL) ++ sf_mask |= FS_APPEND_FL; ++#elif defined(EXT2_APPEND_FL) + sf_mask |= EXT2_APPEND_FL; +#endif ++#if defined(FS_JOURNAL_DATA_FL) ++ sf_mask |= FS_JOURNAL_DATA_FL; ++#endif + /* + * XXX As above, this would be way simpler if we didn't have + * to read the current flags from disk. XXX + */ + ret = ARCHIVE_OK; + + /* Read the current file flags. */ - if (ioctl(myfd, EXT2_IOC_GETFLAGS, &oldflags) < 0) ++ if (ioctl(myfd, ++#ifdef FS_IOC_GETFLAGS ++ FS_IOC_GETFLAGS, ++#else ++ EXT2_IOC_GETFLAGS, ++#endif ++ &oldflags) < 0) + goto fail; + + /* Try setting the flags as given. */ + newflags = (oldflags & ~clear) | set; - if (ioctl(myfd, EXT2_IOC_SETFLAGS, &newflags) >= 0) ++ if (ioctl(myfd, ++#ifdef FS_IOC_SETFLAGS ++ FS_IOC_SETFLAGS, ++#else ++ EXT2_IOC_SETFLAGS, ++#endif ++ &newflags) >= 0) + goto cleanup; + if (errno != EPERM) + goto fail; + + /* If we couldn't set all the flags, try again with a subset. */ + newflags &= ~sf_mask; + oldflags &= sf_mask; + newflags |= oldflags; - if (ioctl(myfd, EXT2_IOC_SETFLAGS, &newflags) >= 0) ++ if (ioctl(myfd, ++#ifdef FS_IOC_SETFLAGS ++ FS_IOC_SETFLAGS, ++#else ++ EXT2_IOC_SETFLAGS, ++#endif ++ &newflags) >= 0) + goto cleanup; + + /* We couldn't set the flags, so report the failure. */ +fail: + archive_set_error(&a->archive, errno, + "Failed to set file flags"); + ret = ARCHIVE_WARN; +cleanup: + if (fd < 0) + close(myfd); + return (ret); +} + +#else + +/* + * Of course, some systems have neither BSD chflags() nor Linux' flags + * support through ioctl(). + */ +static int +set_fflags_platform(struct archive_write_disk *a, int fd, const char *name, + mode_t mode, unsigned long set, unsigned long clear) +{ + (void)a; /* UNUSED */ + (void)fd; /* UNUSED */ + (void)name; /* UNUSED */ + (void)mode; /* UNUSED */ + (void)set; /* UNUSED */ + (void)clear; /* UNUSED */ + return (ARCHIVE_OK); +} + +#endif /* __linux */ + +#ifndef HAVE_COPYFILE_H +/* Default is to simply drop Mac extended metadata. */ +static int +set_mac_metadata(struct archive_write_disk *a, const char *pathname, + const void *metadata, size_t metadata_size) +{ + (void)a; /* UNUSED */ + (void)pathname; /* UNUSED */ + (void)metadata; /* UNUSED */ + (void)metadata_size; /* UNUSED */ + return (ARCHIVE_OK); +} + +static int +fixup_appledouble(struct archive_write_disk *a, const char *pathname) +{ + (void)a; /* UNUSED */ + (void)pathname; /* UNUSED */ + return (ARCHIVE_OK); +} +#else + +/* + * On Mac OS, we use copyfile() to unpack the metadata and + * apply it to the target file. + */ + +#if defined(HAVE_SYS_XATTR_H) +static int +copy_xattrs(struct archive_write_disk *a, int tmpfd, int dffd) +{ + ssize_t xattr_size; + char *xattr_names = NULL, *xattr_val = NULL; + int ret = ARCHIVE_OK, xattr_i; + + xattr_size = flistxattr(tmpfd, NULL, 0, 0); + if (xattr_size == -1) { + archive_set_error(&a->archive, errno, + "Failed to read metadata(xattr)"); + ret = ARCHIVE_WARN; + goto exit_xattr; + } + xattr_names = malloc(xattr_size); + if (xattr_names == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for metadata(xattr)"); + ret = ARCHIVE_FATAL; + goto exit_xattr; + } + xattr_size = flistxattr(tmpfd, xattr_names, xattr_size, 0); + if (xattr_size == -1) { + archive_set_error(&a->archive, errno, + "Failed to read metadata(xattr)"); + ret = ARCHIVE_WARN; + goto exit_xattr; + } + for (xattr_i = 0; xattr_i < xattr_size; + xattr_i += strlen(xattr_names + xattr_i) + 1) { + char *xattr_val_saved; + ssize_t s; + int f; + + s = fgetxattr(tmpfd, xattr_names + xattr_i, NULL, 0, 0, 0); + if (s == -1) { + archive_set_error(&a->archive, errno, + "Failed to get metadata(xattr)"); + ret = ARCHIVE_WARN; + goto exit_xattr; + } + xattr_val_saved = xattr_val; + xattr_val = realloc(xattr_val, s); + if (xattr_val == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Failed to get metadata(xattr)"); + ret = ARCHIVE_WARN; + free(xattr_val_saved); + goto exit_xattr; + } + s = fgetxattr(tmpfd, xattr_names + xattr_i, xattr_val, s, 0, 0); + if (s == -1) { + archive_set_error(&a->archive, errno, + "Failed to get metadata(xattr)"); + ret = ARCHIVE_WARN; + goto exit_xattr; + } + f = fsetxattr(dffd, xattr_names + xattr_i, xattr_val, s, 0, 0); + if (f == -1) { + archive_set_error(&a->archive, errno, + "Failed to get metadata(xattr)"); + ret = ARCHIVE_WARN; + goto exit_xattr; + } + } +exit_xattr: + free(xattr_names); + free(xattr_val); + return (ret); +} +#endif + +static int +copy_acls(struct archive_write_disk *a, int tmpfd, int dffd) +{ +#ifndef HAVE_SYS_ACL_H + return 0; +#else + acl_t acl, dfacl = NULL; + int acl_r, ret = ARCHIVE_OK; + + acl = acl_get_fd(tmpfd); + if (acl == NULL) { + if (errno == ENOENT) + /* There are not any ACLs. */ + return (ret); + archive_set_error(&a->archive, errno, + "Failed to get metadata(acl)"); + ret = ARCHIVE_WARN; + goto exit_acl; + } + dfacl = acl_dup(acl); + acl_r = acl_set_fd(dffd, dfacl); + if (acl_r == -1) { + archive_set_error(&a->archive, errno, + "Failed to get metadata(acl)"); + ret = ARCHIVE_WARN; + goto exit_acl; + } +exit_acl: + if (acl) + acl_free(acl); + if (dfacl) + acl_free(dfacl); + return (ret); +#endif +} + +static int +create_tempdatafork(struct archive_write_disk *a, const char *pathname) +{ + struct archive_string tmpdatafork; + int tmpfd; + + archive_string_init(&tmpdatafork); + archive_strcpy(&tmpdatafork, "tar.md.XXXXXX"); + tmpfd = mkstemp(tmpdatafork.s); + if (tmpfd < 0) { + archive_set_error(&a->archive, errno, + "Failed to mkstemp"); + archive_string_free(&tmpdatafork); + return (-1); + } + if (copyfile(pathname, tmpdatafork.s, 0, + COPYFILE_UNPACK | COPYFILE_NOFOLLOW + | COPYFILE_ACL | COPYFILE_XATTR) < 0) { + archive_set_error(&a->archive, errno, + "Failed to restore metadata"); + close(tmpfd); + tmpfd = -1; + } + unlink(tmpdatafork.s); + archive_string_free(&tmpdatafork); + return (tmpfd); +} + +static int +copy_metadata(struct archive_write_disk *a, const char *metadata, + const char *datafork, int datafork_compressed) +{ + int ret = ARCHIVE_OK; + + if (datafork_compressed) { + int dffd, tmpfd; + + tmpfd = create_tempdatafork(a, metadata); + if (tmpfd == -1) + return (ARCHIVE_WARN); + + /* + * Do not open the data fork compressed by HFS+ compression + * with at least a writing mode(O_RDWR or O_WRONLY). it + * makes the data fork uncompressed. + */ + dffd = open(datafork, 0); + if (dffd == -1) { + archive_set_error(&a->archive, errno, + "Failed to open the data fork for metadata"); + close(tmpfd); + return (ARCHIVE_WARN); + } + +#if defined(HAVE_SYS_XATTR_H) + ret = copy_xattrs(a, tmpfd, dffd); + if (ret == ARCHIVE_OK) +#endif + ret = copy_acls(a, tmpfd, dffd); + close(tmpfd); + close(dffd); + } else { + if (copyfile(metadata, datafork, 0, + COPYFILE_UNPACK | COPYFILE_NOFOLLOW + | COPYFILE_ACL | COPYFILE_XATTR) < 0) { + archive_set_error(&a->archive, errno, + "Failed to restore metadata"); + ret = ARCHIVE_WARN; + } + } + return (ret); +} + +static int +set_mac_metadata(struct archive_write_disk *a, const char *pathname, + const void *metadata, size_t metadata_size) +{ + struct archive_string tmp; + ssize_t written; + int fd; + int ret = ARCHIVE_OK; + + /* This would be simpler if copyfile() could just accept the + * metadata as a block of memory; then we could sidestep this + * silly dance of writing the data to disk just so that + * copyfile() can read it back in again. */ + archive_string_init(&tmp); + archive_strcpy(&tmp, pathname); + archive_strcat(&tmp, ".XXXXXX"); + fd = mkstemp(tmp.s); + + if (fd < 0) { + archive_set_error(&a->archive, errno, + "Failed to restore metadata"); + archive_string_free(&tmp); + return (ARCHIVE_WARN); + } + written = write(fd, metadata, metadata_size); + close(fd); + if ((size_t)written != metadata_size) { + archive_set_error(&a->archive, errno, + "Failed to restore metadata"); + ret = ARCHIVE_WARN; + } else { + int compressed; + +#if defined(UF_COMPRESSED) + if ((a->todo & TODO_HFS_COMPRESSION) != 0 && + (ret = lazy_stat(a)) == ARCHIVE_OK) + compressed = a->st.st_flags & UF_COMPRESSED; + else +#endif + compressed = 0; + ret = copy_metadata(a, tmp.s, pathname, compressed); + } + unlink(tmp.s); + archive_string_free(&tmp); + return (ret); +} + +static int +fixup_appledouble(struct archive_write_disk *a, const char *pathname) +{ + char buff[8]; + struct stat st; + const char *p; + struct archive_string datafork; + int fd = -1, ret = ARCHIVE_OK; + + archive_string_init(&datafork); + /* Check if the current file name is a type of the resource + * fork file. */ + p = strrchr(pathname, '/'); + if (p == NULL) + p = pathname; + else + p++; + if (p[0] != '.' || p[1] != '_') + goto skip_appledouble; + + /* + * Check if the data fork file exists. + * + * TODO: Check if this write disk object has handled it. + */ + archive_strncpy(&datafork, pathname, p - pathname); + archive_strcat(&datafork, p + 2); + if (lstat(datafork.s, &st) == -1 || + (st.st_mode & AE_IFMT) != AE_IFREG) + goto skip_appledouble; + + /* + * Check if the file is in the AppleDouble form. + */ + fd = open(pathname, O_RDONLY | O_BINARY | O_CLOEXEC); + __archive_ensure_cloexec_flag(fd); + if (fd == -1) { + archive_set_error(&a->archive, errno, + "Failed to open a restoring file"); + ret = ARCHIVE_WARN; + goto skip_appledouble; + } + if (read(fd, buff, 8) == -1) { + archive_set_error(&a->archive, errno, + "Failed to read a restoring file"); + close(fd); + ret = ARCHIVE_WARN; + goto skip_appledouble; + } + close(fd); + /* Check AppleDouble Magic Code. */ + if (archive_be32dec(buff) != 0x00051607) + goto skip_appledouble; + /* Check AppleDouble Version. */ + if (archive_be32dec(buff+4) != 0x00020000) + goto skip_appledouble; + + ret = copy_metadata(a, pathname, datafork.s, +#if defined(UF_COMPRESSED) + st.st_flags & UF_COMPRESSED); +#else + 0); +#endif + if (ret == ARCHIVE_OK) { + unlink(pathname); + ret = ARCHIVE_EOF; + } +skip_appledouble: + archive_string_free(&datafork); + return (ret); +} +#endif + +#if HAVE_LSETXATTR || HAVE_LSETEA +/* + * Restore extended attributes - Linux 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; + int ret = ARCHIVE_OK; + int i = archive_entry_xattr_reset(entry); + + while (i--) { + const char *name; + const void *value; + size_t size; + 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 +#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); +#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"); + ret = ARCHIVE_WARN; + } + } + return (ret); +} +#elif HAVE_EXTATTR_SET_FILE && HAVE_DECL_EXTATTR_NAMESPACE_USER +/* + * Restore extended attributes - FreeBSD implementation + */ +static int +set_xattrs(struct archive_write_disk *a) +{ + struct archive_entry *entry = a->entry; + static int warning_done = 0; + int ret = ARCHIVE_OK; + int i = archive_entry_xattr_reset(entry); + + while (i--) { + const char *name; + const void *value; + size_t size; + archive_entry_xattr_next(entry, &name, &value, &size); + if (name != NULL) { + int e; + int namespace; + + if (strncmp(name, "user.", 5) == 0) { + /* "user." attributes go to user namespace */ + 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); + ret = ARCHIVE_WARN; + continue; + } + errno = 0; +#if HAVE_EXTATTR_SET_FD + 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( + 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"); + } + + ret = ARCHIVE_WARN; + } + } + } + return (ret); +} +#else +/* + * Restore extended attributes - stub implementation for unsupported systems + */ +static int +set_xattrs(struct archive_write_disk *a) +{ + static int warning_done = 0; + + /* If there aren't any extended attributes, then it's okay not + * to extract them, otherwise, issue a single warning. */ + if (archive_entry_xattr_count(a->entry) != 0 && !warning_done) { + warning_done = 1; + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + "Cannot restore extended attributes on this system"); + return (ARCHIVE_WARN); + } + /* Warning was already emitted; suppress further warnings. */ + return (ARCHIVE_OK); +} +#endif + +/* + * Test if file on disk is older than entry. + */ +static int +older(struct stat *st, struct archive_entry *entry) +{ + /* First, test the seconds and return if we have a definite answer. */ + /* Definitely older. */ + if (to_int64_time(st->st_mtime) < to_int64_time(archive_entry_mtime(entry))) + return (1); + /* Definitely younger. */ + if (to_int64_time(st->st_mtime) > to_int64_time(archive_entry_mtime(entry))) + return (0); + /* If this platform supports fractional seconds, try those. */ +#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC + /* Definitely older. */ + if (st->st_mtimespec.tv_nsec < archive_entry_mtime_nsec(entry)) + return (1); +#elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC + /* Definitely older. */ + if (st->st_mtim.tv_nsec < archive_entry_mtime_nsec(entry)) + return (1); +#elif HAVE_STRUCT_STAT_ST_MTIME_N + /* older. */ + if (st->st_mtime_n < archive_entry_mtime_nsec(entry)) + return (1); +#elif HAVE_STRUCT_STAT_ST_UMTIME + /* older. */ + if (st->st_umtime * 1000 < archive_entry_mtime_nsec(entry)) + return (1); +#elif HAVE_STRUCT_STAT_ST_MTIME_USEC + /* older. */ + if (st->st_mtime_usec * 1000 < archive_entry_mtime_nsec(entry)) + return (1); +#else + /* This system doesn't have high-res timestamps. */ +#endif + /* Same age or newer, so not older. */ + return (0); +} + +#endif /* !_WIN32 || __CYGWIN__ */ + https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=059aa805c9c0cb34c92eb69abf66febc40ab62db commit 059aa805c9c0cb34c92eb69abf66febc40ab62db Author: LibArchive Upstream AuthorDate: Sat Feb 25 11:31:44 2017 -0800 Commit: Brad King CommitDate: Mon Feb 27 08:47:35 2017 -0500 LibArchive 2017-02-25 (d6b1bb9f) Code extracted from: https://github.com/libarchive/libarchive.git at commit d6b1bb9f7ea7bc153b7356e8e345c9e48005821a (v3.3.1). diff --git a/CMakeLists.txt b/CMakeLists.txt index eb36b5b..1ca9d8f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ endif() # RelWithDebInfo : Release build with Debug Info # MinSizeRel : Release Min Size build IF(NOT CMAKE_BUILD_TYPE) - SET(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Build Type" FORCE) + SET(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build Type" FORCE) ENDIF(NOT CMAKE_BUILD_TYPE) # Set a value type to properly display CMAKE_BUILD_TYPE on GUI if the # value type is "UNINITIALIZED". @@ -44,13 +44,13 @@ SET(CMAKE_MACOSX_RPATH ON) # FILE(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/build/version _version) STRING(REGEX REPLACE - "^([0-9])[0-9][0-9][0-9][0-9][0-9][0-9][a-z]?$" "\\1" _major ${_version}) + "^([0-9])[0-9][0-9][0-9][0-9][0-9][0-9][a-z]*$" "\\1" _major ${_version}) STRING(REGEX REPLACE - "^[0-9]([0-9][0-9][0-9])[0-9][0-9][0-9][a-z]?$" "\\1" _minor ${_version}) + "^[0-9]([0-9][0-9][0-9])[0-9][0-9][0-9][a-z]*$" "\\1" _minor ${_version}) STRING(REGEX REPLACE - "^[0-9][0-9][0-9][0-9]([0-9][0-9][0-9])[a-z]?$" "\\1" _revision ${_version}) + "^[0-9][0-9][0-9][0-9]([0-9][0-9][0-9])[a-z]*$" "\\1" _revision ${_version}) STRING(REGEX REPLACE - "^[0-9][0-9][0-9][0-9][0-9][0-9][0-9]([a-z]?)$" "\\1" _quality ${_version}) + "^[0-9][0-9][0-9][0-9][0-9][0-9][0-9]([a-z]*)$" "\\1" _quality ${_version}) SET(_version_number ${_major}${_minor}${_revision}) STRING(REGEX REPLACE "[0]*([^0]*[0-9])$" "\\1" _trimmed_minor ${_minor}) STRING(REGEX REPLACE "[0]*([^0]*[0-9])$" "\\1" _trimmed_revision ${_revision}) @@ -462,6 +462,8 @@ ENDIF() IF(LIBLZMA_FOUND) SET(HAVE_LIBLZMA 1) SET(HAVE_LZMA_H 1) + SET(CMAKE_REQUIRED_INCLUDES ${LIBLZMA_INCLUDE_DIR}) + SET(CMAKE_REQUIRED_LIBRARIES ${LIBLZMA_LIBRARIES}) INCLUDE_DIRECTORIES(${LIBLZMA_INCLUDE_DIRS}) LIST(APPEND ADDITIONAL_LIBS ${LIBLZMA_LIBRARIES}) # Test if a macro is needed for the library. @@ -570,6 +572,11 @@ LA_CHECK_INCLUDE_FILE("limits.h" HAVE_LIMITS_H) LA_CHECK_INCLUDE_FILE("linux/types.h" HAVE_LINUX_TYPES_H) LA_CHECK_INCLUDE_FILE("linux/fiemap.h" HAVE_LINUX_FIEMAP_H) LA_CHECK_INCLUDE_FILE("linux/fs.h" HAVE_LINUX_FS_H) + +CHECK_C_SOURCE_COMPILES("#include +#include +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("memory.h" HAVE_MEMORY_H) diff --git a/build/cmake/config.h.in b/build/cmake/config.h.in index ec64d99..923a78e 100644 --- a/build/cmake/config.h.in +++ b/build/cmake/config.h.in @@ -1099,6 +1099,9 @@ typedef uint64_t uintmax_t; /* Define to 1 if you have a working EXT2_IOC_GETFLAGS */ #cmakedefine HAVE_WORKING_EXT2_IOC_GETFLAGS 1 +/* Define to 1 if you have a working FS_IOC_GETFLAGS */ +#cmakedefine HAVE_WORKING_FS_IOC_GETFLAGS 1 + /* Define to 1 if you have the header file. */ #cmakedefine HAVE_ZLIB_H 1 diff --git a/build/version b/build/version index a000b30..ef83457 100644 --- a/build/version +++ b/build/version @@ -1 +1 @@ -3003000 +3003001 diff --git a/libarchive/archive.h b/libarchive/archive.h index cd27c90..d400735 100644 --- a/libarchive/archive.h +++ b/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 3003000 +#define ARCHIVE_VERSION_NUMBER 3003001 #include #include /* for wchar_t */ @@ -155,7 +155,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.0" +#define ARCHIVE_VERSION_ONLY_STRING "3.3.1" #define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING __LA_DECL const char * archive_version_string(void); @@ -1001,6 +1001,10 @@ __LA_DECL int archive_read_disk_set_atime_restored(struct archive *); #define ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS (0x0008) /* Default: Xattrs are read from disk. */ #define ARCHIVE_READDISK_NO_XATTR (0x0010) +/* Default: ACLs are read from disk. */ +#define ARCHIVE_READDISK_NO_ACL (0x0020) +/* Default: File flags are read from disk. */ +#define ARCHIVE_READDISK_NO_FFLAGS (0x0040) __LA_DECL int archive_read_disk_set_behavior(struct archive *, int flags); diff --git a/libarchive/archive_digest_private.h b/libarchive/archive_digest_private.h index b58ffb3..b4fd6ca 100644 --- a/libarchive/archive_digest_private.h +++ b/libarchive/archive_digest_private.h @@ -143,6 +143,7 @@ defined(ARCHIVE_CRYPTO_SHA256_WIN) ||\ defined(ARCHIVE_CRYPTO_SHA384_WIN) ||\ defined(ARCHIVE_CRYPTO_SHA512_WIN) +#include #include typedef struct { int valid; diff --git a/libarchive/archive_entry.c b/libarchive/archive_entry.c index d4f061b..10eff11 100644 --- a/libarchive/archive_entry.c +++ b/libarchive/archive_entry.c @@ -1649,7 +1649,10 @@ static struct flag { { "nosappnd", L"nosappnd", SF_APPEND, 0 }, { "nosappend", L"nosappend", SF_APPEND, 0 }, #endif -#ifdef EXT2_APPEND_FL /* 'a' */ +#if defined(FS_APPEND_FL) /* 'a' */ + { "nosappnd", L"nosappnd", FS_APPEND_FL, 0 }, + { "nosappend", L"nosappend", FS_APPEND_FL, 0 }, +#elif defined(EXT2_APPEND_FL) /* 'a' */ { "nosappnd", L"nosappnd", EXT2_APPEND_FL, 0 }, { "nosappend", L"nosappend", EXT2_APPEND_FL, 0 }, #endif @@ -1662,7 +1665,11 @@ static struct flag { { "noschange", L"noschange", SF_IMMUTABLE, 0 }, { "nosimmutable", L"nosimmutable", SF_IMMUTABLE, 0 }, #endif -#ifdef EXT2_IMMUTABLE_FL /* 'i' */ +#if defined(FS_IMMUTABLE_FL) /* 'i' */ + { "noschg", L"noschg", FS_IMMUTABLE_FL, 0 }, + { "noschange", L"noschange", FS_IMMUTABLE_FL, 0 }, + { "nosimmutable", L"nosimmutable", FS_IMMUTABLE_FL, 0 }, +#elif defined(EXT2_IMMUTABLE_FL) /* 'i' */ { "noschg", L"noschg", EXT2_IMMUTABLE_FL, 0 }, { "noschange", L"noschange", EXT2_IMMUTABLE_FL, 0 }, { "nosimmutable", L"nosimmutable", EXT2_IMMUTABLE_FL, 0 }, @@ -1686,7 +1693,9 @@ static struct flag { #ifdef UF_NODUMP { "nodump", L"nodump", 0, UF_NODUMP}, #endif -#ifdef EXT2_NODUMP_FL /* 'd' */ +#if defined(FS_NODUMP_FL) /* 'd' */ + { "nodump", L"nodump", 0, FS_NODUMP_FL}, +#elif defined(EXT2_NODUMP_FL) /* 'd' */ { "nodump", L"nodump", 0, EXT2_NODUMP_FL}, #endif #ifdef UF_OPAQUE @@ -1699,65 +1708,124 @@ static struct flag { #ifdef UF_COMPRESSED { "nocompressed",L"nocompressed", UF_COMPRESSED, 0 }, #endif -#ifdef EXT2_UNRM_FL +#if defined(FS_UNRM_FL) + { "nouunlink", L"nouunlink", FS_UNRM_FL, 0}, +#elif defined(EXT2_UNRM_FL) { "nouunlink", L"nouunlink", EXT2_UNRM_FL, 0}, #endif -#ifdef EXT2_BTREE_FL +#if defined(FS_BTREE_FL) + { "nobtree", L"nobtree", FS_BTREE_FL, 0 }, +#elif defined(EXT2_BTREE_FL) { "nobtree", L"nobtree", EXT2_BTREE_FL, 0 }, #endif -#ifdef EXT2_ECOMPR_FL +#if defined(FS_ECOMPR_FL) + { "nocomperr", L"nocomperr", FS_ECOMPR_FL, 0 }, +#elif defined(EXT2_ECOMPR_FL) { "nocomperr", L"nocomperr", EXT2_ECOMPR_FL, 0 }, #endif -#ifdef EXT2_COMPR_FL /* 'c' */ +#if defined(FS_COMPR_FL) /* 'c' */ + { "nocompress", L"nocompress", FS_COMPR_FL, 0 }, +#elif defined(EXT2_COMPR_FL) /* 'c' */ { "nocompress", L"nocompress", EXT2_COMPR_FL, 0 }, #endif -#ifdef EXT2_NOATIME_FL /* 'A' */ +#if defined(FS_NOATIME_FL) /* 'A' */ + { "noatime", L"noatime", 0, FS_NOATIME_FL}, +#elif defined(EXT2_NOATIME_FL) /* 'A' */ { "noatime", L"noatime", 0, EXT2_NOATIME_FL}, #endif -#ifdef EXT2_DIRTY_FL +#if defined(FS_DIRTY_FL) + { "nocompdirty",L"nocompdirty", FS_DIRTY_FL, 0}, +#elif defined(EXT2_DIRTY_FL) { "nocompdirty",L"nocompdirty", EXT2_DIRTY_FL, 0}, #endif -#ifdef EXT2_COMPRBLK_FL -#ifdef EXT2_NOCOMPR_FL +#if defined(FS_COMPRBLK_FL) +#if defined(FS_NOCOMPR_FL) + { "nocomprblk", L"nocomprblk", FS_COMPRBLK_FL, FS_NOCOMPR_FL}, +#else + { "nocomprblk", L"nocomprblk", FS_COMPRBLK_FL, 0}, +#endif +#elif defined(EXT2_COMPRBLK_FL) +#if defined(EXT2_NOCOMPR_FL) { "nocomprblk", L"nocomprblk", EXT2_COMPRBLK_FL, EXT2_NOCOMPR_FL}, #else { "nocomprblk", L"nocomprblk", EXT2_COMPRBLK_FL, 0}, #endif #endif -#ifdef EXT2_DIRSYNC_FL +#if defined(FS_DIRSYNC_FL) + { "nodirsync", L"nodirsync", FS_DIRSYNC_FL, 0}, +#elif defined(EXT2_DIRSYNC_FL) { "nodirsync", L"nodirsync", EXT2_DIRSYNC_FL, 0}, #endif -#ifdef EXT2_INDEX_FL +#if defined(FS_INDEX_FL) + { "nohashidx", L"nohashidx", FS_INDEX_FL, 0}, +#elif defined(EXT2_INDEX_FL) { "nohashidx", L"nohashidx", EXT2_INDEX_FL, 0}, #endif -#ifdef EXT2_IMAGIC_FL +#if defined(FS_IMAGIC_FL) + { "noimagic", L"noimagic", FS_IMAGIC_FL, 0}, +#elif defined(EXT2_IMAGIC_FL) { "noimagic", L"noimagic", EXT2_IMAGIC_FL, 0}, #endif -#ifdef EXT3_JOURNAL_DATA_FL +#if defined(FS_JOURNAL_DATA_FL) + { "nojournal", L"nojournal", FS_JOURNAL_DATA_FL, 0}, +#elif defined(EXT3_JOURNAL_DATA_FL) { "nojournal", L"nojournal", EXT3_JOURNAL_DATA_FL, 0}, #endif -#ifdef EXT2_SECRM_FL +#if defined(FS_SECRM_FL) + { "nosecuredeletion",L"nosecuredeletion",FS_SECRM_FL, 0}, +#elif defined(EXT2_SECRM_FL) { "nosecuredeletion",L"nosecuredeletion",EXT2_SECRM_FL, 0}, #endif -#ifdef EXT2_SYNC_FL +#if defined(FS_SYNC_FL) + { "nosync", L"nosync", FS_SYNC_FL, 0}, +#elif defined(EXT2_SYNC_FL) { "nosync", L"nosync", EXT2_SYNC_FL, 0}, #endif -#ifdef EXT2_NOTAIL_FL +#if defined(FS_NOTAIL_FL) + { "notail", L"notail", 0, FS_NOTAIL_FL}, +#elif defined(EXT2_NOTAIL_FL) { "notail", L"notail", 0, EXT2_NOTAIL_FL}, #endif -#ifdef EXT2_TOPDIR_FL +#if defined(FS_TOPDIR_FL) + { "notopdir", L"notopdir", FS_TOPDIR_FL, 0}, +#elif defined(EXT2_TOPDIR_FL) { "notopdir", L"notopdir", EXT2_TOPDIR_FL, 0}, #endif -#ifdef EXT2_RESERVED_FL +#ifdef FS_ENCRYPT_FL + { "noencrypt", L"noencrypt", FS_ENCRYPT_FL, 0}, +#endif +#ifdef FS_HUGE_FILE_FL + { "nohugefile", L"nohugefile", FS_HUGE_FILE_FL, 0}, +#endif +#ifdef FS_EXTENT_FL + { "noextent", L"noextent", FS_EXTENT_FL, 0}, +#endif +#ifdef FS_EA_INODE_FL + { "noeainode", L"noeainode", FS_EA_INODE_FL, 0}, +#endif +#ifdef FS_EOFBLOCKS_FL + { "noeofblocks",L"noeofblocks", FS_EOFBLOCKS_FL, 0}, +#endif +#ifdef FS_NOCOW_FL + { "nocow", L"nocow", FS_NOCOW_FL, 0}, +#endif +#ifdef FS_INLINE_DATA_FL + { "noinlinedata",L"noinlinedata", FS_INLINE_DATA_FL, 0}, +#endif +#ifdef FS_PROJINHERIT_FL + { "noprojinherit",L"noprojinherit", FS_PROJINHERIT_FL, 0}, +#endif +#if defined(FS_RESERVED_FL) + { "noreserved", L"noreserved", FS_RESERVED_FL, 0}, +#elif defined(EXT2_RESERVED_FL) { "noreserved", L"noreserved", EXT2_RESERVED_FL, 0}, #endif - { NULL, NULL, 0, 0 } }; diff --git a/libarchive/archive_entry.h b/libarchive/archive_entry.h index 2dd557a..7645f0c 100644 --- a/libarchive/archive_entry.h +++ b/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 3003000 +#define ARCHIVE_VERSION_NUMBER 3003001 /* * Note: archive_entry.h is for use outside of libarchive; the @@ -66,6 +66,27 @@ typedef int64_t la_int64_t; # endif #endif +/* The la_ssize_t should match the type used in 'struct stat' */ +#if !defined(__LA_SSIZE_T_DEFINED) +/* Older code relied on the __LA_SSIZE_T macro; after 4.0 we'll switch to the typedef exclusively. */ +# if ARCHIVE_VERSION_NUMBER < 4000000 +#define __LA_SSIZE_T la_ssize_t +# endif +#define __LA_SSIZE_T_DEFINED +# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__) +# if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_) +typedef ssize_t la_ssize_t; +# elif defined(_WIN64) +typedef __int64 la_ssize_t; +# else +typedef long la_ssize_t; +# endif +# else +# include /* ssize_t */ +typedef ssize_t la_ssize_t; +# endif +#endif + /* Get a suitable definition for mode_t */ #if ARCHIVE_VERSION_NUMBER >= 3999000 /* Switch to plain 'int' for libarchive 4.0. It's less broken than 'mode_t' */ @@ -526,9 +547,9 @@ __LA_DECL int archive_entry_acl_next_w(struct archive_entry *, int /* want_type #define ARCHIVE_ENTRY_ACL_STYLE_COMPACT 0x00000010 __LA_DECL wchar_t *archive_entry_acl_to_text_w(struct archive_entry *, - ssize_t * /* len */, int /* flags */); + la_ssize_t * /* len */, int /* flags */); __LA_DECL char *archive_entry_acl_to_text(struct archive_entry *, - ssize_t * /* len */, int /* flags */); + la_ssize_t * /* len */, int /* flags */); __LA_DECL int archive_entry_acl_from_text_w(struct archive_entry *, const wchar_t * /* wtext */, int /* type */); __LA_DECL int archive_entry_acl_from_text(struct archive_entry *, diff --git a/libarchive/archive_hmac.c b/libarchive/archive_hmac.c index 1e0ae28..f299655 100644 --- a/libarchive/archive_hmac.c +++ b/libarchive/archive_hmac.c @@ -76,6 +76,10 @@ __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) #elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) +#ifndef BCRYPT_HASH_REUSABLE_FLAG +# define BCRYPT_HASH_REUSABLE_FLAG 0x00000020 +#endif + static int __hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) { diff --git a/libarchive/archive_read_disk_entry_from_file.c b/libarchive/archive_read_disk_entry_from_file.c index 591a212..b2f1d17 100644 --- a/libarchive/archive_read_disk_entry_from_file.c +++ b/libarchive/archive_read_disk_entry_from_file.c @@ -203,15 +203,17 @@ archive_read_disk_entry_from_file(struct archive *_a, #ifdef HAVE_STRUCT_STAT_ST_FLAGS /* On FreeBSD, we get flags for free with the stat. */ /* TODO: Does this belong in copy_stat()? */ - if (st->st_flags != 0) + if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0 && st->st_flags != 0) archive_entry_set_fflags(entry, st->st_flags, 0); #endif -#if defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS) +#if (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \ + (defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)) /* Linux requires an extra ioctl to pull the flags. Although * this is an extra step, it has a nice side-effect: We get an * open file descriptor which we can use in the subsequent lookups. */ - if ((S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) { + if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0 && + (S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) { if (fd < 0) { if (a->tree != NULL) fd = a->open_on_current_dir(a->tree, path, @@ -223,7 +225,13 @@ archive_read_disk_entry_from_file(struct archive *_a, } if (fd >= 0) { int stflags; - r = ioctl(fd, EXT2_IOC_GETFLAGS, &stflags); + r = ioctl(fd, +#if defined(FS_IOC_GETFLAGS) + FS_IOC_GETFLAGS, +#else + EXT2_IOC_GETFLAGS, +#endif + &stflags); if (r == 0 && stflags != 0) archive_entry_set_fflags(entry, stflags, 0); } @@ -269,13 +277,15 @@ archive_read_disk_entry_from_file(struct archive *_a, } #endif /* HAVE_READLINK || HAVE_READLINKAT */ - r = setup_acls(a, entry, &fd); - if (!a->suppress_xattr) { + r = 0; + if ((a->flags & ARCHIVE_READDISK_NO_ACL) == 0) + r = setup_acls(a, entry, &fd); + if ((a->flags & ARCHIVE_READDISK_NO_XATTR) == 0) { r1 = setup_xattrs(a, entry, &fd); if (r1 < r) r = r1; } - if (a->enable_copyfile) { + if (a->flags & ARCHIVE_READDISK_MAC_COPYFILE) { r1 = setup_mac_metadata(a, entry, &fd); if (r1 < r) r = r1; diff --git a/libarchive/archive_read_disk_posix.c b/libarchive/archive_read_disk_posix.c index b893704..6961ae6 100644 --- a/libarchive/archive_read_disk_posix.c +++ b/libarchive/archive_read_disk_posix.c @@ -465,8 +465,7 @@ archive_read_disk_new(void) a->entry = archive_entry_new2(&a->archive); a->lookup_uname = trivial_lookup_uname; a->lookup_gname = trivial_lookup_gname; - a->enable_copyfile = 1; - a->traverse_mount_points = 1; + a->flags = ARCHIVE_READDISK_MAC_COPYFILE; a->open_on_current_dir = open_on_current_dir; a->tree_current_dir_fd = tree_current_dir_fd; a->tree_enter_working_dir = tree_enter_working_dir; @@ -563,25 +562,19 @@ archive_read_disk_set_symlink_hybrid(struct archive *_a) int archive_read_disk_set_atime_restored(struct archive *_a) { -#ifndef HAVE_UTIMES - static int warning_done = 0; -#endif struct archive_read_disk *a = (struct archive_read_disk *)_a; archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_ANY, "archive_read_disk_restore_atime"); #ifdef HAVE_UTIMES - a->restore_time = 1; + a->flags |= ARCHIVE_READDISK_RESTORE_ATIME; if (a->tree != NULL) a->tree->flags |= needsRestoreTimes; return (ARCHIVE_OK); #else - if (warning_done) - /* Warning was already emitted; suppress further warnings. */ - return (ARCHIVE_OK); - + /* Display warning and unset flag */ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Cannot restore access time on this system"); - warning_done = 1; + a->flags &= ~ARCHIVE_READDISK_RESTORE_ATIME; return (ARCHIVE_WARN); #endif } @@ -595,29 +588,14 @@ archive_read_disk_set_behavior(struct archive *_a, int flags) archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_ANY, "archive_read_disk_honor_nodump"); + a->flags = flags; + if (flags & ARCHIVE_READDISK_RESTORE_ATIME) r = archive_read_disk_set_atime_restored(_a); else { - a->restore_time = 0; if (a->tree != NULL) a->tree->flags &= ~needsRestoreTimes; } - if (flags & ARCHIVE_READDISK_HONOR_NODUMP) - a->honor_nodump = 1; - else - a->honor_nodump = 0; - if (flags & ARCHIVE_READDISK_MAC_COPYFILE) - a->enable_copyfile = 1; - else - a->enable_copyfile = 0; - if (flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) - a->traverse_mount_points = 0; - else - a->traverse_mount_points = 1; - if (flags & ARCHIVE_READDISK_NO_XATTR) - a->suppress_xattr = 1; - else - a->suppress_xattr = 0; return (r); } @@ -918,7 +896,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, } while (lst == NULL); #ifdef __APPLE__ - if (a->enable_copyfile) { + if (a->flags & ARCHIVE_READDISK_MAC_COPYFILE) { /* If we're using copyfile(), ignore "._XXX" files. */ const char *bname = strrchr(tree_current_path(t), '/'); if (bname == NULL) @@ -989,7 +967,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, } if (t->initial_filesystem_id == -1) t->initial_filesystem_id = t->current_filesystem_id; - if (!a->traverse_mount_points) { + if (a->flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) { if (t->initial_filesystem_id != t->current_filesystem_id) descend = 0; } @@ -999,12 +977,14 @@ next_entry(struct archive_read_disk *a, struct tree *t, * Honor nodump flag. * If the file is marked with nodump flag, do not return this entry. */ - if (a->honor_nodump) { + if (a->flags & ARCHIVE_READDISK_HONOR_NODUMP) { #if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP) if (st->st_flags & UF_NODUMP) return (ARCHIVE_RETRY); -#elif defined(EXT2_IOC_GETFLAGS) && defined(EXT2_NODUMP_FL) &&\ - defined(HAVE_WORKING_EXT2_IOC_GETFLAGS) +#elif (defined(FS_IOC_GETFLAGS) && defined(FS_NODUMP_FL) && \ + defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \ + (defined(EXT2_IOC_GETFLAGS) && defined(EXT2_NODUMP_FL) && \ + defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)) if (S_ISREG(st->st_mode) || S_ISDIR(st->st_mode)) { int stflags; @@ -1013,9 +993,18 @@ next_entry(struct archive_read_disk *a, struct tree *t, O_RDONLY | O_NONBLOCK | O_CLOEXEC); __archive_ensure_cloexec_flag(t->entry_fd); if (t->entry_fd >= 0) { - r = ioctl(t->entry_fd, EXT2_IOC_GETFLAGS, + r = ioctl(t->entry_fd, +#ifdef FS_IOC_GETFLAGS + FS_IOC_GETFLAGS, +#else + EXT2_IOC_GETFLAGS, +#endif &stflags); +#ifdef FS_NODUMP_FL + if (r == 0 && (stflags & FS_NODUMP_FL) != 0) +#else if (r == 0 && (stflags & EXT2_NODUMP_FL) != 0) +#endif return (ARCHIVE_RETRY); } } @@ -1340,10 +1329,11 @@ _archive_read_disk_open(struct archive *_a, const char *pathname) struct archive_read_disk *a = (struct archive_read_disk *)_a; if (a->tree != NULL) - a->tree = tree_reopen(a->tree, pathname, a->restore_time); + a->tree = tree_reopen(a->tree, pathname, + a->flags & ARCHIVE_READDISK_RESTORE_ATIME); else a->tree = tree_open(pathname, a->symlink_mode, - a->restore_time); + a->flags & ARCHIVE_READDISK_RESTORE_ATIME); if (a->tree == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate tar data"); @@ -2132,7 +2122,7 @@ tree_open(const char *path, int symlink_mode, int restore_time) static struct tree * tree_reopen(struct tree *t, const char *path, int restore_time) { - t->flags = (restore_time)?needsRestoreTimes:0; + t->flags = (restore_time != 0)?needsRestoreTimes:0; t->flags |= onInitialDir; t->visit_type = 0; t->tree_errno = 0; diff --git a/libarchive/archive_read_disk_private.h b/libarchive/archive_read_disk_private.h index 2569321..b5a8328 100644 --- a/libarchive/archive_read_disk_private.h +++ b/libarchive/archive_read_disk_private.h @@ -63,16 +63,8 @@ struct archive_read_disk { int (*tree_current_dir_fd)(struct tree*); int (*tree_enter_working_dir)(struct tree*); - /* Set 1 if users request to restore atime . */ - int restore_time; - /* Set 1 if users request to honor nodump flag . */ - int honor_nodump; - /* Set 1 if users request to enable mac copyfile. */ - int enable_copyfile; - /* Set 1 if users request to traverse mount points. */ - int traverse_mount_points; - /* Set 1 if users want to suppress xattr information. */ - int suppress_xattr; + /* Bitfield with ARCHIVE_READDISK_* tunables */ + int flags; const char * (*lookup_gname)(void *private, int64_t gid); void (*cleanup_gname)(void *private); diff --git a/libarchive/archive_read_disk_windows.c b/libarchive/archive_read_disk_windows.c index 27b75e3..3b90330 100644 --- a/libarchive/archive_read_disk_windows.c +++ b/libarchive/archive_read_disk_windows.c @@ -398,8 +398,7 @@ archive_read_disk_new(void) a->entry = archive_entry_new2(&a->archive); a->lookup_uname = trivial_lookup_uname; a->lookup_gname = trivial_lookup_gname; - a->enable_copyfile = 1; - a->traverse_mount_points = 1; + a->flags = ARCHIVE_READDISK_MAC_COPYFILE; return (&a->archive); } @@ -495,7 +494,7 @@ archive_read_disk_set_atime_restored(struct archive *_a) struct archive_read_disk *a = (struct archive_read_disk *)_a; archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_ANY, "archive_read_disk_restore_atime"); - a->restore_time = 1; + a->flags |= ARCHIVE_READDISK_RESTORE_ATIME; if (a->tree != NULL) a->tree->flags |= needsRestoreTimes; return (ARCHIVE_OK); @@ -510,25 +509,14 @@ archive_read_disk_set_behavior(struct archive *_a, int flags) archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_ANY, "archive_read_disk_honor_nodump"); + a->flags = flags; + if (flags & ARCHIVE_READDISK_RESTORE_ATIME) r = archive_read_disk_set_atime_restored(_a); else { - a->restore_time = 0; if (a->tree != NULL) a->tree->flags &= ~needsRestoreTimes; } - if (flags & ARCHIVE_READDISK_HONOR_NODUMP) - a->honor_nodump = 1; - else - a->honor_nodump = 0; - if (flags & ARCHIVE_READDISK_MAC_COPYFILE) - a->enable_copyfile = 1; - else - a->enable_copyfile = 0; - if (flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) - a->traverse_mount_points = 0; - else - a->traverse_mount_points = 1; return (r); } @@ -852,7 +840,7 @@ next_entry(struct archive_read_disk *a, struct tree *t, } if (t->initial_filesystem_id == -1) t->initial_filesystem_id = t->current_filesystem_id; - if (!a->traverse_mount_points) { + if (a->flags & ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS) { if (t->initial_filesystem_id != t->current_filesystem_id) return (ARCHIVE_RETRY); } @@ -1219,9 +1207,11 @@ _archive_read_disk_open_w(struct archive *_a, const wchar_t *pathname) struct archive_read_disk *a = (struct archive_read_disk *)_a; if (a->tree != NULL) - a->tree = tree_reopen(a->tree, pathname, a->restore_time); + a->tree = tree_reopen(a->tree, pathname, + a->flags & ARCHIVE_READDISK_RESTORE_ATIME); else - a->tree = tree_open(pathname, a->symlink_mode, a->restore_time); + a->tree = tree_open(pathname, a->symlink_mode, + a->flags & ARCHIVE_READDISK_RESTORE_ATIME); if (a->tree == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate directory traversal data"); @@ -1519,7 +1509,7 @@ tree_reopen(struct tree *t, const wchar_t *path, int restore_time) struct archive_wstring ws; wchar_t *pathname, *p, *base; - t->flags = (restore_time)?needsRestoreTimes:0; + t->flags = (restore_time != 0)?needsRestoreTimes:0; t->visit_type = 0; t->tree_errno = 0; t->full_path_dir_length = 0; diff --git a/libarchive/archive_read_support_format_warc.c b/libarchive/archive_read_support_format_warc.c index 5e22438..b162465 100644 --- a/libarchive/archive_read_support_format_warc.c +++ b/libarchive/archive_read_support_format_warc.c @@ -543,7 +543,7 @@ xstrpisotime(const char *s, char **endptr) /* as a courtesy to our callers, and since this is a non-standard * routine, we skip leading whitespace */ - while (isblank((unsigned char)*s)) + while (*s == ' ' || *s == '\t') ++s; /* read year */ @@ -589,6 +589,7 @@ static unsigned int _warc_rdver(const char *buf, size_t bsz) { static const char magic[] = "WARC/"; + const char *c; unsigned int ver = 0U; unsigned int end = 0U; @@ -615,11 +616,12 @@ _warc_rdver(const char *buf, size_t bsz) * WARC below version 0.12 has a space-separated header * WARC 0.12 and above terminates the version with a CRLF */ + c = buf + 3U + end; if (ver >= 1200U) { - if (memcmp(buf + 3U + end, "\r\n", 2U) != 0) + if (memcmp(c, "\r\n", 2U) != 0) ver = 0U; } else if (ver < 1200U) { - if (!isblank(*(buf + 3U + end))) + if (*c != ' ' && *c != '\t') ver = 0U; } } @@ -643,7 +645,7 @@ _warc_rdtyp(const char *buf, size_t bsz) } /* overread whitespace */ - while (val < eol && isblank((unsigned char)*val)) + while (val < eol && (*val == ' ' || *val == '\t')) ++val; if (val + 8U == eol) { @@ -673,7 +675,7 @@ _warc_rduri(const char *buf, size_t bsz) return res; } - while (val < eol && isblank((unsigned char)*val)) + while (val < eol && (*val == ' ' || *val == '\t')) ++val; /* overread URL designators */ @@ -731,7 +733,7 @@ _warc_rdlen(const char *buf, size_t bsz) } /* skip leading whitespace */ - while (val < eol && isblank(*val)) + while (val < eol && (*val == ' ' || *val == '\t')) val++; /* there must be at least one digit */ if (!isdigit(*val)) diff --git a/libarchive/archive_write_disk_posix.c b/libarchive/archive_write_disk_posix.c index 20450ba..5a01e84 100644 --- a/libarchive/archive_write_disk_posix.c +++ b/libarchive/archive_write_disk_posix.c @@ -1712,7 +1712,8 @@ _archive_write_disk_finish_entry(struct archive *_a) const void *metadata; size_t metadata_size; metadata = archive_entry_mac_metadata(a->entry, &metadata_size); - if (metadata == NULL || metadata_size == 0) { + 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), @@ -2293,7 +2294,8 @@ _archive_write_disk_close(struct archive *_a) chmod(p->name, p->mode); if (p->fixup & TODO_ACLS) #ifdef HAVE_DARWIN_ACL - if (p->mac_metadata == NULL || + if ((p->fixup & TODO_MAC_METADATA) == 0 || + p->mac_metadata == NULL || p->mac_metadata_size == 0) #endif archive_write_disk_set_acls(&a->archive, @@ -3465,12 +3467,19 @@ set_fflags(struct archive_write_disk *a) #ifdef UF_APPEND critical_flags |= UF_APPEND; #endif -#ifdef EXT2_APPEND_FL +#if defined(FS_APPEND_FL) + critical_flags |= FS_APPEND_FL; +#elif defined(EXT2_APPEND_FL) critical_flags |= EXT2_APPEND_FL; #endif -#ifdef EXT2_IMMUTABLE_FL +#if defined(FS_IMMUTABLE_FL) + critical_flags |= FS_IMMUTABLE_FL; +#elif defined(EXT2_IMMUTABLE_FL) critical_flags |= EXT2_IMMUTABLE_FL; #endif +#ifdef FS_JOURNAL_DATA_FL + critical_flags |= FS_JOURNAL_DATA_FL; +#endif if (a->todo & TODO_FFLAGS) { archive_entry_fflags(a->entry, &set, &clear); @@ -3582,7 +3591,10 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name, return (ARCHIVE_WARN); } -#elif defined(EXT2_IOC_GETFLAGS) && defined(EXT2_IOC_SETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS) +#elif (defined(FS_IOC_GETFLAGS) && defined(FS_IOC_SETFLAGS) && \ + defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \ + (defined(EXT2_IOC_GETFLAGS) && defined(EXT2_IOC_SETFLAGS) && \ + defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)) /* * Linux uses ioctl() to read and write file flags. */ @@ -3595,7 +3607,7 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name, int newflags, oldflags; int sf_mask = 0; - if (set == 0 && clear == 0) + if (set == 0 && clear == 0) return (ARCHIVE_OK); /* Only regular files and dirs can have flags. */ if (!S_ISREG(mode) && !S_ISDIR(mode)) @@ -3616,12 +3628,19 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name, * defines. (?) The code below degrades reasonably gracefully * if sf_mask is incomplete. */ -#ifdef EXT2_IMMUTABLE_FL +#if defined(FS_IMMUTABLE_FL) + sf_mask |= FS_IMMUTABLE_FL; +#elif defined(EXT2_IMMUTABLE_FL) sf_mask |= EXT2_IMMUTABLE_FL; #endif -#ifdef EXT2_APPEND_FL +#if defined(FS_APPEND_FL) + sf_mask |= FS_APPEND_FL; +#elif defined(EXT2_APPEND_FL) sf_mask |= EXT2_APPEND_FL; #endif +#if defined(FS_JOURNAL_DATA_FL) + sf_mask |= FS_JOURNAL_DATA_FL; +#endif /* * XXX As above, this would be way simpler if we didn't have * to read the current flags from disk. XXX @@ -3629,12 +3648,24 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name, ret = ARCHIVE_OK; /* Read the current file flags. */ - if (ioctl(myfd, EXT2_IOC_GETFLAGS, &oldflags) < 0) + if (ioctl(myfd, +#ifdef FS_IOC_GETFLAGS + FS_IOC_GETFLAGS, +#else + EXT2_IOC_GETFLAGS, +#endif + &oldflags) < 0) goto fail; /* Try setting the flags as given. */ newflags = (oldflags & ~clear) | set; - if (ioctl(myfd, EXT2_IOC_SETFLAGS, &newflags) >= 0) + if (ioctl(myfd, +#ifdef FS_IOC_SETFLAGS + FS_IOC_SETFLAGS, +#else + EXT2_IOC_SETFLAGS, +#endif + &newflags) >= 0) goto cleanup; if (errno != EPERM) goto fail; @@ -3643,7 +3674,13 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name, newflags &= ~sf_mask; oldflags &= sf_mask; newflags |= oldflags; - if (ioctl(myfd, EXT2_IOC_SETFLAGS, &newflags) >= 0) + if (ioctl(myfd, +#ifdef FS_IOC_SETFLAGS + FS_IOC_SETFLAGS, +#else + EXT2_IOC_SETFLAGS, +#endif + &newflags) >= 0) goto cleanup; /* We couldn't set the flags, so report the failure. */ diff --git a/libarchive/archive_write_set_format_iso9660.c b/libarchive/archive_write_set_format_iso9660.c index 4e91097..c0ca435 100644 --- a/libarchive/archive_write_set_format_iso9660.c +++ b/libarchive/archive_write_set_format_iso9660.c @@ -4074,8 +4074,10 @@ write_information_block(struct archive_write *a) memset(info.s, 0, info_size); opt = 0; #if defined(HAVE__CTIME64_S) - __time64_t iso9660_birth_time_tmp = (__time64_t) iso9660->birth_time; //time_t may be shorter than 64 bits - _ctime64_s(buf, sizeof(buf), &(iso9660_birth_time_tmp)); + { + __time64_t iso9660_birth_time_tmp = (__time64_t) iso9660->birth_time; //time_t may be shorter than 64 bits + _ctime64_s(buf, sizeof(buf), &(iso9660_birth_time_tmp)); + } #elif defined(HAVE_CTIME_R) ctime_r(&(iso9660->birth_time), buf); #else https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=5fee76606b7a1f252e75e95c3d8303777459938d commit 5fee76606b7a1f252e75e95c3d8303777459938d Author: Brad King AuthorDate: Mon Feb 27 08:47:11 2017 -0500 Commit: Brad King CommitDate: Mon Feb 27 08:47:11 2017 -0500 libarchive: Update script to get 3.3.1 diff --git a/Utilities/Scripts/update-libarchive.bash b/Utilities/Scripts/update-libarchive.bash index 6c4eeb0..41c6a66 100755 --- a/Utilities/Scripts/update-libarchive.bash +++ b/Utilities/Scripts/update-libarchive.bash @@ -8,7 +8,7 @@ readonly name="LibArchive" readonly ownership="LibArchive Upstream " readonly subtree="Utilities/cmlibarchive" readonly repo="https://github.com/libarchive/libarchive.git" -readonly tag="v3.3.0" +readonly tag="v3.3.1" readonly shortlog=false readonly paths=" CMakeLists.txt ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- Utilities/Scripts/update-libarchive.bash | 2 +- Utilities/cmlibarchive/CMakeLists.txt | 13 ++- Utilities/cmlibarchive/build/cmake/config.h.in | 3 + Utilities/cmlibarchive/build/version | 2 +- Utilities/cmlibarchive/libarchive/archive.h | 8 +- .../libarchive/archive_digest_private.h | 1 + Utilities/cmlibarchive/libarchive/archive_entry.c | 110 ++++++++++++++++---- Utilities/cmlibarchive/libarchive/archive_entry.h | 2 +- Utilities/cmlibarchive/libarchive/archive_hmac.c | 4 + .../libarchive/archive_read_disk_entry_from_file.c | 24 +++-- .../libarchive/archive_read_disk_posix.c | 64 +++++------- .../libarchive/archive_read_disk_private.h | 12 +-- .../libarchive/archive_read_disk_windows.c | 30 ++---- .../libarchive/archive_read_support_format_warc.c | 18 ++-- .../libarchive/archive_write_disk_posix.c | 59 +++++++++-- 16 files changed, 228 insertions(+), 126 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 27 09:11:19 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 27 Feb 2017 09:11:19 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-302-g73909e2 Message-ID: <20170227141119.2FE0EC2168@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 73909e242138ba01c1ce5ebe04fa16a9a8e2e675 (commit) via 666ad1df2dc5b181a40d831c125529fe7e9bf0b4 (commit) from adcade6088a8bbe19002ac88f724d25ac95597c5 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=73909e242138ba01c1ce5ebe04fa16a9a8e2e675 commit 73909e242138ba01c1ce5ebe04fa16a9a8e2e675 Merge: adcade6 666ad1d Author: Brad King AuthorDate: Mon Feb 27 09:11:17 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 27 09:11:17 2017 -0500 Merge topic 'ninja-no-full-path' 666ad1df Revert "Ninja: Use full path for all source files" diff --cc Source/cmNinjaTargetGenerator.cxx index f096416,5c85dfa..b1f26e4 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@@ -380,12 -373,11 +380,12 @@@ void cmNinjaTargetGenerator::WriteLangu void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) { - cmLocalGenerator::RuleVariables vars; - vars.RuleLauncher = "RULE_LAUNCH_COMPILE"; - vars.CMTarget = this->GetGeneratorTarget(); + cmRulePlaceholderExpander::RuleVariables vars; + vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str(); + vars.CMTargetType = + cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()); vars.Language = lang.c_str(); - vars.Source = "$IN_ABS"; + vars.Source = "$in"; vars.Object = "$out"; vars.Defines = "$DEFINES"; vars.Includes = "$INCLUDES"; ----------------------------------------------------------------------- Summary of changes: Source/cmNinjaTargetGenerator.cxx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 27 09:11:22 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 27 Feb 2017 09:11:22 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-305-g9b02283 Message-ID: <20170227141122.13501E202B@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 9b02283a1fdb63b0cf9755ae37a0d22fc6f4dbf4 (commit) via b35a949bb6ce6ae5204de2cf867dac903cb71262 (commit) via 01347954187ebccf83fc7540163f150a5f430c36 (commit) from 73909e242138ba01c1ce5ebe04fa16a9a8e2e675 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9b02283a1fdb63b0cf9755ae37a0d22fc6f4dbf4 commit 9b02283a1fdb63b0cf9755ae37a0d22fc6f4dbf4 Merge: 73909e2 b35a949 Author: Brad King AuthorDate: Mon Feb 27 09:11:20 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 27 09:11:20 2017 -0500 Merge topic 'test-objlib-deps-cleanup' b35a949b Tests: Change RunCMake.ObjectLibrary dependencies case to C 01347954 Tests: Fix RunCMake.ObjectLibrary dependency delay ----------------------------------------------------------------------- Summary of changes: Tests/RunCMake/ObjectLibrary/Dependencies.cmake | 10 +++------- Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake | 20 +++++++++++++------- Tests/RunCMake/ObjectLibrary/depends_lib.c | 7 +++++++ Tests/RunCMake/ObjectLibrary/depends_lib.cpp | 7 ------- Tests/RunCMake/ObjectLibrary/depends_main.c | 7 +++++++ Tests/RunCMake/ObjectLibrary/depends_main.cpp | 7 ------- Tests/RunCMake/ObjectLibrary/depends_obj0.c | 4 ++++ Tests/RunCMake/ObjectLibrary/depends_obj0.cpp | 4 ---- Tests/RunCMake/ObjectLibrary/depends_obj1.c | 4 ++++ Tests/RunCMake/ObjectLibrary/depends_obj1.cpp | 4 ---- 10 files changed, 38 insertions(+), 36 deletions(-) create mode 100644 Tests/RunCMake/ObjectLibrary/depends_lib.c delete mode 100644 Tests/RunCMake/ObjectLibrary/depends_lib.cpp create mode 100644 Tests/RunCMake/ObjectLibrary/depends_main.c delete mode 100644 Tests/RunCMake/ObjectLibrary/depends_main.cpp create mode 100644 Tests/RunCMake/ObjectLibrary/depends_obj0.c delete mode 100644 Tests/RunCMake/ObjectLibrary/depends_obj0.cpp create mode 100644 Tests/RunCMake/ObjectLibrary/depends_obj1.c delete mode 100644 Tests/RunCMake/ObjectLibrary/depends_obj1.cpp hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 27 09:11:24 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 27 Feb 2017 09:11:24 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-307-ge348d8d Message-ID: <20170227141124.C7EEEE513E@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via e348d8db559fd1d79f936d42582eb628779d23ad (commit) via feff52d42ca18a52fd99e8fdfd3093c3a94eb498 (commit) from 9b02283a1fdb63b0cf9755ae37a0d22fc6f4dbf4 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e348d8db559fd1d79f936d42582eb628779d23ad commit e348d8db559fd1d79f936d42582eb628779d23ad Merge: 9b02283 feff52d4 Author: Brad King AuthorDate: Mon Feb 27 09:11:22 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 27 09:11:22 2017 -0500 Merge topic 'object-library-compile-pdb' feff52d4 Fix COMPILE_PDB_NAME when used on an OBJECT library ----------------------------------------------------------------------- Summary of changes: Source/cmGeneratorTarget.cxx | 2 +- Tests/ObjectLibrary/A/CMakeLists.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 27 09:11:27 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 27 Feb 2017 09:11:27 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-309-gf79efea Message-ID: <20170227141127.70E80E551B@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via f79efeac7939663e0fd67b4087f6ead08402189f (commit) via a9fa6a2c777bf68ac1c6d885fd07b21bf98e3f77 (commit) from e348d8db559fd1d79f936d42582eb628779d23ad (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f79efeac7939663e0fd67b4087f6ead08402189f commit f79efeac7939663e0fd67b4087f6ead08402189f Merge: e348d8d a9fa6a2 Author: Brad King AuthorDate: Mon Feb 27 09:11:25 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 27 09:11:25 2017 -0500 Merge topic 'ExternalProject-checkout-clarify' a9fa6a2c ExternalProject: Run `git checkout` with `--` to clarify arguments ----------------------------------------------------------------------- Summary of changes: Modules/ExternalProject.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 27 09:11:42 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 27 Feb 2017 09:11:42 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-583-g6687a54 Message-ID: <20170227141142.DF75CE2CD5@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 6687a5410d28c9eb5d1c074b068e74049f120fe4 (commit) via f79efeac7939663e0fd67b4087f6ead08402189f (commit) via e348d8db559fd1d79f936d42582eb628779d23ad (commit) via 9b02283a1fdb63b0cf9755ae37a0d22fc6f4dbf4 (commit) via 73909e242138ba01c1ce5ebe04fa16a9a8e2e675 (commit) from 013e7ec9100fe5fd850a4c4f89d34359d12f6dd9 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6687a5410d28c9eb5d1c074b068e74049f120fe4 commit 6687a5410d28c9eb5d1c074b068e74049f120fe4 Merge: 013e7ec f79efea Author: Brad King AuthorDate: Mon Feb 27 09:11:34 2017 -0500 Commit: Brad King CommitDate: Mon Feb 27 09:11:34 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 27 09:13:40 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 27 Feb 2017 09:13:40 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-315-gcdb6d7d Message-ID: <20170227141340.E889CF72D7@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via cdb6d7df970fcaaf6cda1bef9955351222e1bcde (commit) via aa45291e7f90749cd6e0f1d7d02f9536c30731ce (commit) via dab2ff3e237f1c3c2430e0661281719185ef4eb1 (commit) via ad3bf56dd210888c94fac33238b35ddccf3a8053 (commit) via 8ea060f960c1aa9d2fd2da6a035f03a64d08863b (commit) via 52a3022df62c0b2ec6c51f70e8eb862dbcde3c9a (commit) from f79efeac7939663e0fd67b4087f6ead08402189f (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 27 09:13:41 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 27 Feb 2017 09:13:41 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-590-gcff4986 Message-ID: <20170227141341.86651F72A8@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via cff4986415b485168d151c09e1cddb24b81efb56 (commit) via cdb6d7df970fcaaf6cda1bef9955351222e1bcde (commit) via aa45291e7f90749cd6e0f1d7d02f9536c30731ce (commit) via dab2ff3e237f1c3c2430e0661281719185ef4eb1 (commit) via ad3bf56dd210888c94fac33238b35ddccf3a8053 (commit) via 8ea060f960c1aa9d2fd2da6a035f03a64d08863b (commit) via 52a3022df62c0b2ec6c51f70e8eb862dbcde3c9a (commit) from 6687a5410d28c9eb5d1c074b068e74049f120fe4 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=cff4986415b485168d151c09e1cddb24b81efb56 commit cff4986415b485168d151c09e1cddb24b81efb56 Merge: 6687a54 cdb6d7d Author: Brad King AuthorDate: Mon Feb 27 09:12:47 2017 -0500 Commit: Brad King CommitDate: Mon Feb 27 09:12:47 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 27 09:13:41 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 27 Feb 2017 09:13:41 -0500 (EST) Subject: [Cmake-commits] CMake branch, release, updated. v3.8.0-rc1-56-gdab2ff3 Message-ID: <20170227141341.DB4A6F73B3@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, release has been updated via dab2ff3e237f1c3c2430e0661281719185ef4eb1 (commit) via a9fa6a2c777bf68ac1c6d885fd07b21bf98e3f77 (commit) via ad3bf56dd210888c94fac33238b35ddccf3a8053 (commit) via feff52d42ca18a52fd99e8fdfd3093c3a94eb498 (commit) via 8ea060f960c1aa9d2fd2da6a035f03a64d08863b (commit) via 666ad1df2dc5b181a40d831c125529fe7e9bf0b4 (commit) via efac65d67b32c407044db6536da4f43ed9546be7 (commit) from 5eb4d9d80bbdbf316a1ccb2b062dcc9f34f95c3a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- Summary of changes: Modules/ExternalProject.cmake | 2 +- Source/cmGeneratorTarget.cxx | 2 +- Source/cmNinjaTargetGenerator.cxx | 7 +++---- Tests/ObjectLibrary/A/CMakeLists.txt | 1 + 4 files changed, 6 insertions(+), 6 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 27 09:14:48 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 27 Feb 2017 09:14:48 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-592-g77ca7ea Message-ID: <20170227141448.4DCE8F936E@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 77ca7ea3169bdbd0e02b17bd7f2f3776dbdaab75 (commit) via ded616bdad46a445ea7ae05d47ae8f32026b13b5 (commit) from cff4986415b485168d151c09e1cddb24b81efb56 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=77ca7ea3169bdbd0e02b17bd7f2f3776dbdaab75 commit 77ca7ea3169bdbd0e02b17bd7f2f3776dbdaab75 Merge: cff4986 ded616b Author: Brad King AuthorDate: Mon Feb 27 09:14:47 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 27 09:14:47 2017 -0500 Merge topic '16607-error-out-on-non-seekable-input-files' into next ded616bd cmListFileLexer: bail out on seek-errors https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ded616bdad46a445ea7ae05d47ae8f32026b13b5 commit ded616bdad46a445ea7ae05d47ae8f32026b13b5 Author: Gregor Jasny AuthorDate: Sun Feb 19 18:26:44 2017 +0100 Commit: Brad King CommitDate: Mon Feb 27 09:14:28 2017 -0500 cmListFileLexer: bail out on seek-errors If we are given a FIFO, for example, we cannot seek back after trying to read a Byte-Order-Mark. Closes: #16607 diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index b1cd889..23b666e 100644 --- a/Source/cmListFileCache.cxx +++ b/Source/cmListFileCache.cxx @@ -80,6 +80,13 @@ bool cmListFileParser::ParseFile() return false; } + if (bom == cmListFileLexer_BOM_Broken) { + cmListFileLexer_SetFileName(this->Lexer, CM_NULLPTR, CM_NULLPTR); + this->IssueFileOpenError("Error while reading Byte-Order-Mark. " + "File not seekable?"); + return false; + } + // Verify the Byte-Order-Mark, if any. if (bom != cmListFileLexer_BOM_None && bom != cmListFileLexer_BOM_UTF8) { cmListFileLexer_SetFileName(this->Lexer, CM_NULLPTR, CM_NULLPTR); diff --git a/Source/cmListFileLexer.c b/Source/cmListFileLexer.c index 56559f6..44d0894 100644 --- a/Source/cmListFileLexer.c +++ b/Source/cmListFileLexer.c @@ -2559,11 +2559,15 @@ static cmListFileLexer_BOM cmListFileLexer_ReadBOM(FILE* f) if (fread(b, 1, 2, f) == 2 && b[0] == 0 && b[1] == 0) { return cmListFileLexer_BOM_UTF32LE; } - fsetpos(f, &p); + if (fsetpos(f, &p) != 0) { + return cmListFileLexer_BOM_Broken; + } return cmListFileLexer_BOM_UTF16LE; } } - rewind(f); + if (fseek(f, 0, SEEK_SET) != 0) { + return cmListFileLexer_BOM_Broken; + } return cmListFileLexer_BOM_None; } diff --git a/Source/cmListFileLexer.h b/Source/cmListFileLexer.h index c9fb6da..f243010a 100644 --- a/Source/cmListFileLexer.h +++ b/Source/cmListFileLexer.h @@ -32,6 +32,7 @@ struct cmListFileLexer_Token_s enum cmListFileLexer_BOM_e { cmListFileLexer_BOM_None, + cmListFileLexer_BOM_Broken, cmListFileLexer_BOM_UTF8, cmListFileLexer_BOM_UTF16BE, cmListFileLexer_BOM_UTF16LE, diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index bd92013..6423bfd 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -290,7 +290,7 @@ add_RunCMake_test(target_link_libraries) add_RunCMake_test(target_compile_features) add_RunCMake_test(CheckModules) -add_RunCMake_test(CommandLine) +add_RunCMake_test(CommandLine -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}) add_RunCMake_test(CommandLineTar) add_RunCMake_test(install) diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index 0c4f71c..b213ee2 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -1,3 +1,5 @@ +cmake_minimum_required(VERSION 3.1) + include(RunCMake) run_cmake_command(NoArgs ${CMAKE_COMMAND}) @@ -301,3 +303,14 @@ set(CMAKE_RELATIVE_PATH_TOP_BINARY \"${RunCMake_TEST_BINARY_DIR}\") ) endfunction() run_cmake_depends() + +function(reject_fifo) + find_program(BASH_EXECUTABLE bash) + if(BASH_EXECUTABLE) + set(BASH_COMMAND_ARGUMENT "'${CMAKE_COMMAND}' -P <(echo 'return()')") + run_cmake_command(reject_fifo ${BASH_EXECUTABLE} -c ${BASH_COMMAND_ARGUMENT}) + endif() +endfunction() +if(CMAKE_HOST_UNIX AND NOT CMAKE_SYSTEM_NAME STREQUAL "CYGWIN") + reject_fifo() +endif() diff --git a/Tests/RunCMake/CommandLine/reject_fifo-result.txt b/Tests/RunCMake/CommandLine/reject_fifo-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/reject_fifo-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/reject_fifo-stderr.txt b/Tests/RunCMake/CommandLine/reject_fifo-stderr.txt new file mode 100644 index 0000000..7a335c3 --- /dev/null +++ b/Tests/RunCMake/CommandLine/reject_fifo-stderr.txt @@ -0,0 +1,2 @@ +CMake Error in .* + Error while reading Byte-Order-Mark\. File not seekable\? ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 27 09:24:37 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 27 Feb 2017 09:24:37 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-594-gaf064e5 Message-ID: <20170227142437.78ED9FA24F@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via af064e58c0fdde06bb4f1c93d4c9e7acd94efc07 (commit) via 07747be837dfe4baf76d5af451841cb25b7ac9dc (commit) from 77ca7ea3169bdbd0e02b17bd7f2f3776dbdaab75 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=af064e58c0fdde06bb4f1c93d4c9e7acd94efc07 commit af064e58c0fdde06bb4f1c93d4c9e7acd94efc07 Merge: 77ca7ea 07747be Author: Brad King AuthorDate: Mon Feb 27 09:24:36 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 27 09:24:36 2017 -0500 Merge topic 'autogen_json_fix' into next 07747be8 Revert "Autogen: Fix for Q_PLUGIN_METADATA change detection test" https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=07747be837dfe4baf76d5af451841cb25b7ac9dc commit 07747be837dfe4baf76d5af451841cb25b7ac9dc Author: Brad King AuthorDate: Mon Feb 27 09:24:21 2017 -0500 Commit: Brad King CommitDate: Mon Feb 27 09:24:21 2017 -0500 Revert "Autogen: Fix for Q_PLUGIN_METADATA change detection test" This reverts commit 73ad60499b429f6e38de1a6b564300286c468477. diff --git a/Tests/QtAutogen/CMakeLists.txt b/Tests/QtAutogen/CMakeLists.txt index dfecff7..257c187 100644 --- a/Tests/QtAutogen/CMakeLists.txt +++ b/Tests/QtAutogen/CMakeLists.txt @@ -233,10 +233,10 @@ if (NOT QT_TEST_VERSION STREQUAL 4) set(timeformat "%Y%j%H%M%S") set(mocPluginBinDir "${CMAKE_CURRENT_BINARY_DIR}/mocPlugin") - find_library(style_a_file "PluginStyleA" PATHS "${mocPluginBinDir}" NO_DEFAULT_PATH) - find_library(style_b_file "PluginStyleB" PATHS "${mocPluginBinDir}" NO_DEFAULT_PATH) - find_library(style_c_file "PluginStyleC" PATHS "${mocPluginBinDir}" NO_DEFAULT_PATH) - find_library(style_d_file "PluginStyleD" PATHS "${mocPluginBinDir}" NO_DEFAULT_PATH) + find_library(style_a_file "PluginStyleA" "${mocPluginBinDir}") + find_library(style_b_file "PluginStyleB" "${mocPluginBinDir}") + find_library(style_c_file "PluginStyleC" "${mocPluginBinDir}") + find_library(style_d_file "PluginStyleD" "${mocPluginBinDir}") file(TIMESTAMP "${style_a_file}" style_a_before "${timeformat}") file(TIMESTAMP "${style_b_file}" style_b_before "${timeformat}") ----------------------------------------------------------------------- Summary of changes: Tests/QtAutogen/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 27 09:26:13 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 27 Feb 2017 09:26:13 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-596-geedc69b Message-ID: <20170227142613.B243EFA2DB@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via eedc69b8a1f119f40fa48d7ed950974ea7140fd4 (commit) via 73a6d4566a9fa13ffaef2f1111be808a220ba867 (commit) from af064e58c0fdde06bb4f1c93d4c9e7acd94efc07 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=eedc69b8a1f119f40fa48d7ed950974ea7140fd4 commit eedc69b8a1f119f40fa48d7ed950974ea7140fd4 Merge: af064e5 73a6d45 Author: Brad King AuthorDate: Mon Feb 27 09:26:13 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 27 09:26:13 2017 -0500 Merge topic 'cache-xaml-resx-headers' into next 73a6d456 VS: Cache the list of xaml and resx headers https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=73a6d4566a9fa13ffaef2f1111be808a220ba867 commit 73a6d4566a9fa13ffaef2f1111be808a220ba867 Author: Dmitry Kochkin AuthorDate: Sat Feb 25 22:56:13 2017 +0100 Commit: Brad King CommitDate: Mon Feb 27 09:22:08 2017 -0500 VS: Cache the list of xaml and resx headers Speed up VS project generation with many such headers. diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 5815210..47d685d 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -711,12 +711,18 @@ void cmGeneratorTarget::GetExternalObjects( IMPLEMENT_VISIT(ExternalObjects); } -void cmGeneratorTarget::GetExpectedResxHeaders(std::set& srcs, +void cmGeneratorTarget::GetExpectedResxHeaders(std::set& headers, const std::string& config) const { - ResxData data; - IMPLEMENT_VISIT_IMPL(Resx, COMMA cmGeneratorTarget::ResxData) - srcs = data.ExpectedResxHeaders; + HeadersCacheType::const_iterator it = this->ResxHeadersCache.find(config); + if (it == this->ResxHeadersCache.end()) { + ResxData data; + IMPLEMENT_VISIT_IMPL(Resx, COMMA cmGeneratorTarget::ResxData) + it = this->ResxHeadersCache + .insert(std::make_pair(config, data.ExpectedResxHeaders)) + .first; + } + headers = it->second; } void cmGeneratorTarget::GetResxSources(std::vector& srcs, @@ -748,9 +754,15 @@ void cmGeneratorTarget::GetCertificates(std::vector& data, void cmGeneratorTarget::GetExpectedXamlHeaders(std::set& headers, const std::string& config) const { - XamlData data; - IMPLEMENT_VISIT_IMPL(Xaml, COMMA cmGeneratorTarget::XamlData) - headers = data.ExpectedXamlHeaders; + HeadersCacheType::const_iterator it = this->XamlHeadersCache.find(config); + if (it == this->XamlHeadersCache.end()) { + XamlData data; + IMPLEMENT_VISIT_IMPL(Xaml, COMMA cmGeneratorTarget::XamlData) + it = this->XamlHeadersCache + .insert(std::make_pair(config, data.ExpectedXamlHeaders)) + .first; + } + headers = it->second; } void cmGeneratorTarget::GetExpectedXamlSources(std::set& srcs, diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 689fbda..e72e0a6 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -739,6 +739,10 @@ private: bool ComputePDBOutputDir(const std::string& kind, const std::string& config, std::string& out) const; + typedef std::map > HeadersCacheType; + mutable HeadersCacheType ResxHeadersCache; + mutable HeadersCacheType XamlHeadersCache; + public: const std::vector& GetLinkImplementationClosure( const std::string& config) const; ----------------------------------------------------------------------- Summary of changes: Source/cmGeneratorTarget.cxx | 26 +++++++++++++++++++------- Source/cmGeneratorTarget.h | 4 ++++ 2 files changed, 23 insertions(+), 7 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 27 09:28:03 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 27 Feb 2017 09:28:03 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-598-g539150d Message-ID: <20170227142803.29F2BFA356@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 539150dd10ab582f5bc2d95dffe82b40cf4cd597 (commit) via 48b56504bf2c9be2151cc507aaf5d59e50f456ae (commit) from eedc69b8a1f119f40fa48d7ed950974ea7140fd4 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=539150dd10ab582f5bc2d95dffe82b40cf4cd597 commit 539150dd10ab582f5bc2d95dffe82b40cf4cd597 Merge: eedc69b 48b5650 Author: Brad King AuthorDate: Mon Feb 27 09:28:02 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 27 09:28:02 2017 -0500 Merge topic 'autogen_json_fix' into next 48b56504 Autogen: Fix for Q_PLUGIN_METADATA change detection test https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=48b56504bf2c9be2151cc507aaf5d59e50f456ae commit 48b56504bf2c9be2151cc507aaf5d59e50f456ae Author: Sebastian Holtermann AuthorDate: Fri Feb 24 18:27:41 2017 +0100 Commit: Sebastian Holtermann CommitDate: Sun Feb 26 19:05:56 2017 +0100 Autogen: Fix for Q_PLUGIN_METADATA change detection test diff --git a/Tests/QtAutogen/CMakeLists.txt b/Tests/QtAutogen/CMakeLists.txt index 257c187..dc631c6 100644 --- a/Tests/QtAutogen/CMakeLists.txt +++ b/Tests/QtAutogen/CMakeLists.txt @@ -232,55 +232,56 @@ if (NOT QT_TEST_VERSION STREQUAL 4) endif() set(timeformat "%Y%j%H%M%S") - set(mocPluginBinDir "${CMAKE_CURRENT_BINARY_DIR}/mocPlugin") - find_library(style_a_file "PluginStyleA" "${mocPluginBinDir}") - find_library(style_b_file "PluginStyleB" "${mocPluginBinDir}") - find_library(style_c_file "PluginStyleC" "${mocPluginBinDir}") - find_library(style_d_file "PluginStyleD" "${mocPluginBinDir}") - - file(TIMESTAMP "${style_a_file}" style_a_before "${timeformat}") - file(TIMESTAMP "${style_b_file}" style_b_before "${timeformat}") - file(TIMESTAMP "${style_c_file}" style_c_before "${timeformat}") - file(TIMESTAMP "${style_d_file}" style_d_before "${timeformat}") - - # Ensure that the timestamp will change and touch the json files + set(mocPlugSrcDir "${CMAKE_CURRENT_SOURCE_DIR}/mocPlugin") + set(mocPlugBinDir "${CMAKE_CURRENT_BINARY_DIR}/mocPlugin") + find_library(plAFile "PlugA" PATHS "${mocPlugBinDir}" NO_DEFAULT_PATH) + find_library(plBFile "PlugB" PATHS "${mocPlugBinDir}" NO_DEFAULT_PATH) + find_library(plCFile "PlugC" PATHS "${mocPlugBinDir}" NO_DEFAULT_PATH) + find_library(plDFile "PlugD" PATHS "${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) - execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${mocPluginBinDir}/jsonFiles/StyleC.json") - execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${mocPluginBinDir}/jsonFiles/sub/StyleD.json") - execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${mocPluginBinDir}") + 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 "${style_a_file}" style_a_after "${timeformat}") - file(TIMESTAMP "${style_b_file}" style_b_after "${timeformat}") - file(TIMESTAMP "${style_c_file}" style_c_after "${timeformat}") - file(TIMESTAMP "${style_d_file}" style_d_after "${timeformat}") + file(TIMESTAMP "${plAFile}" plAAfter "${timeformat}") + file(TIMESTAMP "${plBFile}" plBAfter "${timeformat}") + file(TIMESTAMP "${plCFile}" plCAfter "${timeformat}") + file(TIMESTAMP "${plDFile}" plDAfter "${timeformat}") - if (style_a_after GREATER style_a_before) - message(SEND_ERROR "file (${style_a_file}) should not have changed!") + if (plAAfter GREATER plABefore) + message(SEND_ERROR "file (${plAFile}) should not have changed!") endif() - if (style_b_after GREATER style_b_before) - message(SEND_ERROR "file (${style_b_file}) should not have changed!") + if (plBAfter GREATER plBBefore) + message(SEND_ERROR "file (${plBFile}) should not have changed!") endif() - if (NOT style_c_after GREATER style_c_before) - message(SEND_ERROR "file (${style_c_file}) should have changed!") + if (NOT plCAfter GREATER plCBefore) + message(SEND_ERROR "file (${plCFile}) should have changed!") endif() - if (NOT style_d_after GREATER style_d_before) - message(SEND_ERROR "file (${style_d_file}) should have changed!") + if (NOT plDAfter GREATER plDBefore) + message(SEND_ERROR "file (${plDFile}) should have changed!") endif() # Test custom macro - file(TIMESTAMP "${style_c_file}" style_c_before "${timeformat}") - file(TIMESTAMP "${style_d_file}" style_d_before "${timeformat}") + file(TIMESTAMP "${plCFile}" plCBefore "${timeformat}") + file(TIMESTAMP "${plDFile}" plDBefore "${timeformat}") execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) - execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${mocPluginBinDir}/jsonFiles/StyleC_Custom.json") - execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${mocPluginBinDir}/jsonFiles/sub/StyleD_Custom.json") - execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${mocPluginBinDir}") - file(TIMESTAMP "${style_c_file}" style_c_after "${timeformat}") - file(TIMESTAMP "${style_d_file}" style_d_after "${timeformat}") - if (NOT style_c_after GREATER style_c_before) - message(SEND_ERROR "file (${style_c_file}) should have changed!") + 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 style_d_after GREATER style_d_before) - message(SEND_ERROR "file (${style_d_file}) should have changed!") + if (NOT plDAfter GREATER plDBefore) + message(SEND_ERROR "file (${plDFile}) should have changed!") endif() endif() diff --git a/Tests/QtAutogen/mocPlugin/CMakeLists.txt b/Tests/QtAutogen/mocPlugin/CMakeLists.txt index b72b05d..4843c21 100644 --- a/Tests/QtAutogen/mocPlugin/CMakeLists.txt +++ b/Tests/QtAutogen/mocPlugin/CMakeLists.txt @@ -25,8 +25,8 @@ set(CMAKE_AUTOMOC TRUE) include_directories("${CMAKE_CURRENT_BINARY_DIR}/jsonFiles") link_libraries(Qt5::Widgets) -add_library(PluginStyleA MODULE StyleA.cpp) -add_library(PluginStyleB MODULE StyleB.cpp) -add_library(PluginStyleC MODULE StyleC.cpp) -add_library(PluginStyleD MODULE StyleD.cpp) -add_library(PluginStyleE MODULE StyleE.cpp) +add_library(PlugA STATIC StyleA.cpp) +add_library(PlugB STATIC StyleB.cpp) +add_library(PlugC STATIC StyleC.cpp) +add_library(PlugD STATIC StyleD.cpp) +add_library(PlugE STATIC StyleE.cpp) diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json b/Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json index bf17580..119aaa4 100644 --- a/Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json +++ b/Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json @@ -1 +1 @@ -{ "Keys": [ "Rocket", "StarbusterC" ] } +{ "Keys": [ "Boat", "Ship" ] } diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json b/Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json index f7fcc19..732c547 100644 --- a/Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json +++ b/Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json @@ -1 +1 @@ -{ "Keys": [ "Rocket", "StarbusterD" ] } +{ "Keys": [ "Bike", "Car" ] } ----------------------------------------------------------------------- Summary of changes: Tests/QtAutogen/CMakeLists.txt | 77 +++++++++++++------------- Tests/QtAutogen/mocPlugin/CMakeLists.txt | 10 ++-- Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json | 2 +- Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json | 2 +- 4 files changed, 46 insertions(+), 45 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 27 09:38:33 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 27 Feb 2017 09:38:33 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-600-gd8227ed Message-ID: <20170227143833.D1BAFFA4DB@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via d8227ed0bd89990b39407dd2e0486bea2c337d7e (commit) via f639bd9a60502c680fce44c5ef0b63b131b874dc (commit) from 539150dd10ab582f5bc2d95dffe82b40cf4cd597 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d8227ed0bd89990b39407dd2e0486bea2c337d7e commit d8227ed0bd89990b39407dd2e0486bea2c337d7e Merge: 539150d f639bd9 Author: Brad King AuthorDate: Mon Feb 27 09:38:33 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 27 09:38:33 2017 -0500 Merge topic 'libuv-solaris-10' into next f639bd9a libuv: Compile as C 90 on Solaris 10 https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f639bd9a60502c680fce44c5ef0b63b131b874dc commit f639bd9a60502c680fce44c5ef0b63b131b874dc Author: Brad King AuthorDate: Mon Feb 27 09:37:39 2017 -0500 Commit: Brad King CommitDate: Mon Feb 27 09:37:39 2017 -0500 libuv: Compile as C 90 on Solaris 10 diff --git a/Utilities/cmlibuv/CMakeLists.txt b/Utilities/cmlibuv/CMakeLists.txt index 1899f83..6632a1e 100644 --- a/Utilities/cmlibuv/CMakeLists.txt +++ b/Utilities/cmlibuv/CMakeLists.txt @@ -224,6 +224,9 @@ if(CMAKE_SYSTEM_NAME STREQUAL "SunOS") list(APPEND uv_defines _XOPEN_SOURCE=500 ) + if(CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 90) + endif() else() list(APPEND uv_defines _XOPEN_SOURCE=600 ----------------------------------------------------------------------- Summary of changes: Utilities/cmlibuv/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 27 10:32:51 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 27 Feb 2017 10:32:51 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-602-ga04f037 Message-ID: <20170227153253.1DEA4FA6E2@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via a04f037c1c2286856e26f7190fdf7a816ac37cc6 (commit) via c1aaf8a61defe3e01e8526b99d8919b9618d1ba9 (commit) from d8227ed0bd89990b39407dd2e0486bea2c337d7e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a04f037c1c2286856e26f7190fdf7a816ac37cc6 commit a04f037c1c2286856e26f7190fdf7a816ac37cc6 Merge: d8227ed c1aaf8a Author: Brad King AuthorDate: Mon Feb 27 10:32:50 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 27 10:32:50 2017 -0500 Merge topic 'cmake-host-system-name' into next c1aaf8a6 Fix CMAKE_HOST_SYSTEM_NAME on SunOS https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c1aaf8a61defe3e01e8526b99d8919b9618d1ba9 commit c1aaf8a61defe3e01e8526b99d8919b9618d1ba9 Author: Brad King AuthorDate: Mon Feb 27 10:30:20 2017 -0500 Commit: Brad King CommitDate: Mon Feb 27 10:30:45 2017 -0500 Fix CMAKE_HOST_SYSTEM_NAME on SunOS In commit 0bbd993f (Make CMAKE_HOST_SYSTEM_NAME available in scripting context, 2016-12-26) we added a call to `uname` that checks for a zero return value. However, on Solaris the `uname(2)` manual [1] says that on success a non-negative value is returned. Fix our return code check so that we detect the `SunOS` name correctly. [1] https://docs.oracle.com/cd/E53394_01/html/E54765/uname-2.html diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx index 80e494b..d2c9d73 100644 --- a/Source/cmStateSnapshot.cxx +++ b/Source/cmStateSnapshot.cxx @@ -308,7 +308,7 @@ void cmStateSnapshot::SetDefaultDefinitions() this->SetDefinition("CMAKE_HOST_UNIX", "1"); struct utsname uts_name; - if (uname(&uts_name) == 0) { + if (uname(&uts_name) >= 0) { this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", uts_name.sysname); } #endif ----------------------------------------------------------------------- Summary of changes: Source/cmStateSnapshot.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 27 13:12:52 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 27 Feb 2017 13:12:52 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-604-gda58882 Message-ID: <20170227181252.86160ACE1C@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via da588825475697068e2f3babc092c2cc4f09a31b (commit) via 10b2e0e479b1015c905aef19439c10d7546a0232 (commit) from a04f037c1c2286856e26f7190fdf7a816ac37cc6 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=da588825475697068e2f3babc092c2cc4f09a31b commit da588825475697068e2f3babc092c2cc4f09a31b Merge: a04f037 10b2e0e Author: Brad King AuthorDate: Mon Feb 27 13:12:51 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 27 13:12:51 2017 -0500 Merge topic 'cpack_nsis_sign_uninstaller' into next 10b2e0e4 CPack/NSIS: Sign the uninstaller https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=10b2e0e479b1015c905aef19439c10d7546a0232 commit 10b2e0e479b1015c905aef19439c10d7546a0232 Author: Roman W?ger AuthorDate: Mon Feb 27 06:47:44 2017 +0100 Commit: Roman W?ger CommitDate: Mon Feb 27 06:47:44 2017 +0100 CPack/NSIS: Sign the uninstaller diff --git a/Help/release/dev/cpack-sign-uninstaller.rst b/Help/release/dev/cpack-sign-uninstaller.rst new file mode 100644 index 0000000..ff2b402 --- /dev/null +++ b/Help/release/dev/cpack-sign-uninstaller.rst @@ -0,0 +1,5 @@ +cpack-sign_uninstaller +---------------------- + +* The :module:`CPackNSIS` module learned to sign the uninstaller + when using :variable:`CPACK_NSIS_SIGN_UNINSTALLER` variable. diff --git a/Modules/CPackNSIS.cmake b/Modules/CPackNSIS.cmake index 18d1871..37fedf3 100644 --- a/Modules/CPackNSIS.cmake +++ b/Modules/CPackNSIS.cmake @@ -133,6 +133,10 @@ # "doc/cmake- at CMake_VERSION_MAJOR@. at CMake_VERSION_MINOR@/cmake.html" # "CMake Help" "https://cmake.org" "CMake Web Site") # +# .. variable:: CPACK_NSIS_SIGN_UNINSTALLER +# +# Specify a command to use for signing the uninstaller. The command will +# be invoked a path to the uninstaller as its only argument. #FIXME we should put NSIS specific code here #FIXME but I'm not doing it because I'm not able to test it... diff --git a/Modules/NSIS.template.in b/Modules/NSIS.template.in index 9001888..a8903f6 100644 --- a/Modules/NSIS.template.in +++ b/Modules/NSIS.template.in @@ -29,6 +29,33 @@ ;-------------------------------- ;General +!ifdef INNER + OutFile "$%TEMP%\tempinstaller.exe" + SetCompress off ; for speed +!else + ; Call makensis again, defining INNER. This writes an installer for us which, when + ; it is invoked, will just write the uninstaller to some location, and then exit. + ; Be sure to substitute the name of this script here. + + !system "$\"${NSISDIR}\makensis$\" /DINNER @CPACK_TEMPORARY_DIRECTORY@/../project.nsi" = 0 + + ; So now run that installer we just created as %TEMP%\tempinstaller.exe. Since it + ; calls quit the return value isn't zero. + + !system "$%TEMP%\tempinstaller.exe" = 2 + + ; That will have written an uninstaller binary for us. Now we sign it with your + ; favourite code signing tool. + + !tempfile INCEXIST + !system 'if exist "@CPACK_NSIS_SIGN_UNINSTALLER@" echo !define HAVE_SIGN_UNINST > "${INCEXIST}"' + !include "${INCEXIST}" + !delfile "${INCEXIST}" + !ifdef HAVE_SIGN_UNINST + !system '"@CPACK_NSIS_SIGN_UNINSTALLER@" $%TEMP%\Uninstall.exe' = 0 + !endif + + ; Good. Now we can carry on writing the real installer. ;Name and file Name "@CPACK_NSIS_PACKAGE_NAME@" @@ -36,6 +63,7 @@ ;Set compression SetCompressor @CPACK_NSIS_COMPRESSOR@ +!endif ;Require administrator access RequestExecutionLevel admin @@ -559,8 +587,10 @@ FunctionEnd !insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_PAGE_FINISH +!ifdef INNER !insertmacro MUI_UNPAGE_CONFIRM !insertmacro MUI_UNPAGE_INSTFILES +!endif ;-------------------------------- ;Languages @@ -642,7 +672,10 @@ Section "-Core installation" WriteRegStr SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "" $INSTDIR ;Create uninstaller - WriteUninstaller "$INSTDIR\Uninstall.exe" +!ifndef INNER + ; this packages the signed uninstaller + File $%TEMP%\Uninstall.exe +!endif Push "DisplayName" Push "@CPACK_NSIS_DISPLAY_NAME@" Call ConditionalAddToRegisty @@ -801,6 +834,7 @@ FunctionEnd ;-------------------------------- ;Uninstaller Section +!ifdef INNER Section "Uninstall" ReadRegStr $START_MENU SHCTX \ "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "StartMenu" @@ -886,6 +920,7 @@ Section "Uninstall" Call un.RemoveFromPath doNotRemoveFromPath: SectionEnd +!endif ;-------------------------------- ; determine admin versus local install @@ -898,6 +933,14 @@ SectionEnd ; "Program Files" for AllUsers, "My Documents" for JustMe... Function .onInit +!ifdef INNER + ; If INNER is defined, then we aren't supposed to do anything except write out + ; the installer. This is better than processing a command line option as it means + ; this entire code path is not present in the final (real) installer. + + WriteUninstaller "$%TEMP%\Uninstall.exe" + Quit ; just bail out quickly when running the "inner" installer +!endif StrCmp "@CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL@" "ON" 0 inst ReadRegStr $0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "UninstallString" ----------------------------------------------------------------------- Summary of changes: Help/release/dev/cpack-sign-uninstaller.rst | 5 +++ Modules/CPackNSIS.cmake | 4 +++ Modules/NSIS.template.in | 45 ++++++++++++++++++++++++++- 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 Help/release/dev/cpack-sign-uninstaller.rst hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 27 13:16:43 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 27 Feb 2017 13:16:43 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-607-g253db69 Message-ID: <20170227181643.4B89EFA27C@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 253db6906ca42d7e02dadbb94c9a2305708a7dbe (commit) via 3f26eb3064ccbd715140cd12b6c51e84d5d8c801 (commit) via d07e1b27d9f92182a64bb7981416ea0eeb963764 (commit) from da588825475697068e2f3babc092c2cc4f09a31b (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=253db6906ca42d7e02dadbb94c9a2305708a7dbe commit 253db6906ca42d7e02dadbb94c9a2305708a7dbe Merge: da58882 3f26eb3 Author: Brad King AuthorDate: Mon Feb 27 13:16:42 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 27 13:16:42 2017 -0500 Merge topic 'cmake-xcode-schemes' into next 3f26eb30 Xcode: Add documentation for schema generator d07e1b27 Xcode: Write shared schemes based on the default files generated by Xcode https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3f26eb3064ccbd715140cd12b6c51e84d5d8c801 commit 3f26eb3064ccbd715140cd12b6c51e84d5d8c801 Author: Gregor Jasny AuthorDate: Wed Feb 22 17:51:41 2017 +0100 Commit: Brad King CommitDate: Mon Feb 27 13:15:55 2017 -0500 Xcode: Add documentation for schema generator diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 5fad10c..b4e9c1b 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -45,6 +45,7 @@ Properties of Global Scope /prop_gbl/TARGET_SUPPORTS_SHARED_LIBS /prop_gbl/USE_FOLDERS /prop_gbl/XCODE_EMIT_EFFECTIVE_PLATFORM_NAME + /prop_gbl/XCODE_GENERATE_SCHEME .. _`Directory Properties`: diff --git a/Help/prop_gbl/XCODE_GENERATE_SCHEME.rst b/Help/prop_gbl/XCODE_GENERATE_SCHEME.rst new file mode 100644 index 0000000..be8b5b0 --- /dev/null +++ b/Help/prop_gbl/XCODE_GENERATE_SCHEME.rst @@ -0,0 +1,11 @@ +XCODE_GENERATE_SCHEME +--------------------- + +If enabled, the Xcode generator will generate schema files. Those are +are useful to invoke analyze, archive, build-for-testing and test +actions from the command line. + +.. note:: + + The Xcode Schema Generator is still experimental and subject to + change. diff --git a/Help/release/dev/cmake-xcode-schemes.rst b/Help/release/dev/cmake-xcode-schemes.rst new file mode 100644 index 0000000..27c19d7 --- /dev/null +++ b/Help/release/dev/cmake-xcode-schemes.rst @@ -0,0 +1,6 @@ +cmake-xcode-schemes +------------------- + +* The :generator:`Xcode` generator got the ability to create schema files. + This is still an experimental feature and can be activated by setting the + :prop_gbl:`XCODE_GENERATE_SCHEME` global property to a ``TRUE`` value. https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d07e1b27d9f92182a64bb7981416ea0eeb963764 commit d07e1b27d9f92182a64bb7981416ea0eeb963764 Author: Gusts Kaksis AuthorDate: Wed Jan 18 16:20:09 2017 +0200 Commit: Brad King CommitDate: Mon Feb 27 13:15:03 2017 -0500 Xcode: Write shared schemes based on the default files generated by Xcode diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 3b49f72..76b98fc 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -639,6 +639,7 @@ if(APPLE) set(SRCS ${SRCS} cmXCodeObject.cxx cmXCode21Object.cxx + cmXCodeScheme.cxx cmGlobalXCodeGenerator.cxx cmGlobalXCodeGenerator.h cmLocalXCodeGenerator.cxx diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 8627cf2..8acea45 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -28,6 +28,7 @@ #include "cmTarget.h" #include "cmXCode21Object.h" #include "cmXCodeObject.h" +#include "cmXCodeScheme.h" #include "cm_auto_ptr.hxx" #include "cmake.h" @@ -3327,6 +3328,15 @@ void cmGlobalXCodeGenerator::OutputXCodeProject( return; } this->WriteXCodePBXProj(fout, root, generators); + + // Since the lowest available Xcode version for testing was 7.0, + // I'm setting this as a limit then + if (this->GetCMakeInstance()->GetState()->GetGlobalPropertyAsBool( + "XCODE_GENERATE_SCHEME") && + this->XcodeVersion >= 70) { + this->OutputXCodeSharedSchemes(xcodeDir, root); + } + this->ClearXCodeObjects(); // Since this call may have created new cache entries, save the cache: @@ -3335,6 +3345,24 @@ void cmGlobalXCodeGenerator::OutputXCodeProject( root->GetBinaryDirectory()); } +void cmGlobalXCodeGenerator::OutputXCodeSharedSchemes( + const std::string& xcProjDir, cmLocalGenerator* root) +{ + for (std::vector::const_iterator i = + this->XCodeObjects.begin(); + i != this->XCodeObjects.end(); ++i) { + cmXCodeObject* obj = *i; + if (obj->GetType() == cmXCodeObject::OBJECT && + (obj->GetIsA() == cmXCodeObject::PBXNativeTarget || + obj->GetIsA() == cmXCodeObject::PBXAggregateTarget)) { + cmXCodeScheme schm(obj, this->CurrentConfigurationTypes, + this->XcodeVersion); + schm.WriteXCodeSharedScheme(xcProjDir, + root->GetCurrentSourceDirectory()); + } + } +} + void cmGlobalXCodeGenerator::WriteXCodePBXProj(std::ostream& fout, cmLocalGenerator*, std::vector&) diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index 1aaf9c7..c9157b0 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -165,6 +165,9 @@ private: std::vector& generators); void OutputXCodeProject(cmLocalGenerator* root, std::vector& generators); + // Write shared scheme files for all the native targets + void OutputXCodeSharedSchemes(const std::string& xcProjDir, + cmLocalGenerator* root); void WriteXCodePBXProj(std::ostream& fout, cmLocalGenerator* root, std::vector& generators); cmXCodeObject* CreateXCodeFileReferenceFromPath(const std::string& fullpath, diff --git a/Source/cmXCodeScheme.cxx b/Source/cmXCodeScheme.cxx new file mode 100644 index 0000000..3c8c0b7 --- /dev/null +++ b/Source/cmXCodeScheme.cxx @@ -0,0 +1,206 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmXCodeScheme.h" + +#include +#include + +#include "cmGeneratedFileStream.h" +#include "cmGeneratorTarget.h" +#include "cmXMLSafe.h" + +cmXCodeScheme::cmXCodeScheme(cmXCodeObject* xcObj, + const std::vector& configList, + unsigned int xcVersion) + : TargetName(xcObj->GetTarget()->GetName()) + , TargetId(xcObj->GetId()) + , ConfigList(configList) + , XcodeVersion(xcVersion) +{ +} + +void cmXCodeScheme::WriteXCodeSharedScheme(const std::string& xcProjDir, + const std::string sourceRoot) +{ + // Create shared scheme sub-directory tree + // + std::string xcodeSchemeDir = xcProjDir; + xcodeSchemeDir += "/xcshareddata/xcschemes"; + cmSystemTools::MakeDirectory(xcodeSchemeDir.c_str()); + + std::string xcodeSchemeFile = xcodeSchemeDir; + xcodeSchemeFile += "/"; + xcodeSchemeFile += this->TargetName; + xcodeSchemeFile += ".xcscheme"; + + cmGeneratedFileStream fout(xcodeSchemeFile.c_str()); + fout.SetCopyIfDifferent(true); + if (!fout) { + return; + } + + std::string xcProjRelDir = xcProjDir.substr(sourceRoot.size() + 1); + WriteXCodeXCScheme(fout, xcProjRelDir); +} + +void cmXCodeScheme::WriteXCodeXCScheme(std::ostream& fout, + const std::string& xcProjDir) +{ + cmXMLWriter xout(fout); + xout.StartDocument(); + + xout.StartElement("Scheme"); + xout.BreakAttributes(); + xout.Attribute("LastUpgradeVersion", WriteVersionString()); + xout.Attribute("version", "1.3"); + + WriteBuildAction(xout, xcProjDir); + WriteTestAction(xout, FindConfiguration("Debug")); + WriteLaunchAction(xout, FindConfiguration("Debug"), xcProjDir); + WriteProfileAction(xout, FindConfiguration("Release")); + WriteAnalyzeAction(xout, FindConfiguration("Debug")); + WriteArchiveAction(xout, FindConfiguration("Release")); + + xout.EndElement(); +} + +void cmXCodeScheme::WriteBuildAction(cmXMLWriter& xout, + const std::string& xcProjDir) +{ + xout.StartElement("BuildAction"); + xout.BreakAttributes(); + xout.Attribute("parallelizeBuildables", "YES"); + xout.Attribute("buildImplicitDependencies", "YES"); + + xout.StartElement("BuildActionEntries"); + xout.StartElement("BuildActionEntry"); + xout.BreakAttributes(); + xout.Attribute("buildForTesting", "YES"); + xout.Attribute("buildForRunning", "YES"); + xout.Attribute("buildForProfiling", "YES"); + xout.Attribute("buildForArchiving", "YES"); + xout.Attribute("buildForAnalyzing", "YES"); + + xout.StartElement("BuildableReference"); + xout.BreakAttributes(); + xout.Attribute("BuildableIdentifier", "primary"); + xout.Attribute("BlueprintIdentifier", this->TargetId); + xout.Attribute("BuildableName", this->TargetName); + xout.Attribute("BlueprintName", this->TargetName); + xout.Attribute("ReferencedContainer", "container:" + xcProjDir); + xout.EndElement(); + + xout.EndElement(); // BuildActionEntry + xout.EndElement(); // BuildActionEntries + xout.EndElement(); // BuildAction +} + +void cmXCodeScheme::WriteTestAction(cmXMLWriter& xout, + std::string configuration) +{ + xout.StartElement("TestAction"); + xout.BreakAttributes(); + xout.Attribute("buildConfiguration", configuration); + xout.Attribute("selectedDebuggerIdentifier", + "Xcode.DebuggerFoundation.Debugger.LLDB"); + xout.Attribute("selectedLauncherIdentifier", + "Xcode.DebuggerFoundation.Launcher.LLDB"); + xout.Attribute("shouldUseLaunchSchemeArgsEnv", "YES"); + + xout.StartElement("Testables"); + xout.EndElement(); + + xout.StartElement("AdditionalOptions"); + xout.EndElement(); + + xout.EndElement(); // TestAction +} + +void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout, + std::string configuration, + const std::string& xcProjDir) +{ + xout.StartElement("LaunchAction"); + xout.BreakAttributes(); + xout.Attribute("buildConfiguration", configuration); + xout.Attribute("selectedDebuggerIdentifier", + "Xcode.DebuggerFoundation.Debugger.LLDB"); + xout.Attribute("selectedLauncherIdentifier", + "Xcode.DebuggerFoundation.Launcher.LLDB"); + xout.Attribute("launchStyle", "0"); + xout.Attribute("useCustomWorkingDirectory", "NO"); + xout.Attribute("ignoresPersistentStateOnLaunch", "NO"); + xout.Attribute("debugDocumentVersioning", "YES"); + xout.Attribute("debugServiceExtension", "internal"); + xout.Attribute("allowLocationSimulation", "YES"); + + xout.StartElement("MacroExpansion"); + + xout.StartElement("BuildableReference"); + xout.BreakAttributes(); + xout.Attribute("BuildableIdentifier", "primary"); + xout.Attribute("BlueprintIdentifier", this->TargetId); + xout.Attribute("BuildableName", this->TargetName); + xout.Attribute("BlueprintName", this->TargetName); + xout.Attribute("ReferencedContainer", "container:" + xcProjDir); + xout.EndElement(); + + xout.EndElement(); // MacroExpansion + + xout.StartElement("AdditionalOptions"); + xout.EndElement(); + + xout.EndElement(); // LaunchAction +} + +void cmXCodeScheme::WriteProfileAction(cmXMLWriter& xout, + std::string configuration) +{ + xout.StartElement("ProfileAction"); + xout.BreakAttributes(); + xout.Attribute("buildConfiguration", configuration); + xout.Attribute("shouldUseLaunchSchemeArgsEnv", "YES"); + xout.Attribute("savedToolIdentifier", ""); + xout.Attribute("useCustomWorkingDirectory", "NO"); + xout.Attribute("debugDocumentVersioning", "YES"); + xout.EndElement(); +} + +void cmXCodeScheme::WriteAnalyzeAction(cmXMLWriter& xout, + std::string configuration) +{ + xout.StartElement("AnalyzeAction"); + xout.BreakAttributes(); + xout.Attribute("buildConfiguration", configuration); + xout.EndElement(); +} + +void cmXCodeScheme::WriteArchiveAction(cmXMLWriter& xout, + std::string configuration) +{ + xout.StartElement("ArchiveAction"); + xout.BreakAttributes(); + xout.Attribute("buildConfiguration", configuration); + xout.Attribute("revealArchiveInOrganizer", "YES"); + xout.EndElement(); +} + +std::string cmXCodeScheme::WriteVersionString() +{ + std::ostringstream v; + v << std::setfill('0') << std::setw(4) << this->XcodeVersion * 10; + return v.str(); +} + +std::string cmXCodeScheme::FindConfiguration(const std::string& name) +{ + // Try to find the desired configuration by name, + // and if it's not found return first from the list + // + if (std::find(this->ConfigList.begin(), this->ConfigList.end(), name) == + this->ConfigList.end() && + this->ConfigList.size() > 0) + return this->ConfigList[0]; + + return name; +} diff --git a/Source/cmXCodeScheme.h b/Source/cmXCodeScheme.h new file mode 100644 index 0000000..b174c51 --- /dev/null +++ b/Source/cmXCodeScheme.h @@ -0,0 +1,46 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmXCodeScheme_h +#define cmXCodeScheme_h + +#include // IWYU pragma: keep + +#include "cmGlobalXCodeGenerator.h" +#include "cmSystemTools.h" +#include "cmXCodeObject.h" +#include "cmXMLWriter.h" + +/** \class cmXCodeScheme + * \brief Write shared schemes for native targets in Xcode project. + */ +class cmXCodeScheme +{ +public: + cmXCodeScheme(cmXCodeObject* xcObj, + const std::vector& configList, + unsigned int xcVersion); + + void WriteXCodeSharedScheme(const std::string& xcProjDir, + const std::string sourceRoot); + +private: + const std::string& TargetName; + const std::string& TargetId; + const std::vector& ConfigList; + const unsigned int XcodeVersion; + + void WriteXCodeXCScheme(std::ostream& fout, const std::string& xcProjDir); + + void WriteBuildAction(cmXMLWriter& xout, const std::string& xcProjDir); + void WriteTestAction(cmXMLWriter& xout, std::string configuration); + void WriteLaunchAction(cmXMLWriter& xout, std::string configuration, + const std::string& xcProjDir); + void WriteProfileAction(cmXMLWriter& xout, std::string configuration); + void WriteAnalyzeAction(cmXMLWriter& xout, std::string configuration); + void WriteArchiveAction(cmXMLWriter& xout, std::string configuration); + + std::string WriteVersionString(); + std::string FindConfiguration(const std::string& name); +}; + +#endif ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-properties.7.rst | 1 + Help/prop_gbl/XCODE_GENERATE_SCHEME.rst | 11 ++ Help/release/dev/cmake-xcode-schemes.rst | 6 + Source/CMakeLists.txt | 1 + Source/cmGlobalXCodeGenerator.cxx | 28 ++++ Source/cmGlobalXCodeGenerator.h | 3 + Source/cmXCodeScheme.cxx | 206 ++++++++++++++++++++++++++++++ Source/cmXCodeScheme.h | 46 +++++++ 8 files changed, 302 insertions(+) create mode 100644 Help/prop_gbl/XCODE_GENERATE_SCHEME.rst create mode 100644 Help/release/dev/cmake-xcode-schemes.rst create mode 100644 Source/cmXCodeScheme.cxx create mode 100644 Source/cmXCodeScheme.h hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 27 13:25:12 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 27 Feb 2017 13:25:12 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-609-ga745016 Message-ID: <20170227182512.D414BFA5B9@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via a7450168373f48228c3eb837178867f82fcbee2c (commit) via 99d6de6c1a5871ba03fa008c984cd5408940c3cd (commit) from 253db6906ca42d7e02dadbb94c9a2305708a7dbe (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a7450168373f48228c3eb837178867f82fcbee2c commit a7450168373f48228c3eb837178867f82fcbee2c Merge: 253db69 99d6de6 Author: Brad King AuthorDate: Mon Feb 27 13:25:11 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 27 13:25:11 2017 -0500 Merge topic 'ExternalProject-fix-download-log' into next 99d6de6c ExternalProject: only append `COMMAND` if actually adding a command https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=99d6de6c1a5871ba03fa008c984cd5408940c3cd commit 99d6de6c1a5871ba03fa008c984cd5408940c3cd Author: Ben Boeckel AuthorDate: Mon Feb 27 11:30:13 2017 -0500 Commit: Ben Boeckel CommitDate: Mon Feb 27 11:33:31 2017 -0500 ExternalProject: only append `COMMAND` if actually adding a command Fixes #16544. diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake index 00781d6..97438e6 100644 --- a/Modules/ExternalProject.cmake +++ b/Modules/ExternalProject.cmake @@ -1987,11 +1987,10 @@ function(_ep_add_download_command name) set(comment "Performing download step (${steps}) for '${name}'") _ep_write_verifyfile_script("${stamp_dir}/verify-${name}.cmake" "${file}" "${hash}") endif() - list(APPEND cmd ${CMAKE_COMMAND} -P ${stamp_dir}/verify-${name}.cmake - COMMAND) + list(APPEND cmd ${CMAKE_COMMAND} -P ${stamp_dir}/verify-${name}.cmake) if (NOT no_extract) _ep_write_extractfile_script("${stamp_dir}/extract-${name}.cmake" "${name}" "${file}" "${source_dir}") - list(APPEND cmd ${CMAKE_COMMAND} -P ${stamp_dir}/extract-${name}.cmake) + list(APPEND cmd COMMAND ${CMAKE_COMMAND} -P ${stamp_dir}/extract-${name}.cmake) else () set_property(TARGET ${name} PROPERTY _EP_DOWNLOADED_FILE ${file}) endif () diff --git a/Tests/ExternalProject/CMakeLists.txt b/Tests/ExternalProject/CMakeLists.txt index 72c20eb..6b73563 100644 --- a/Tests/ExternalProject/CMakeLists.txt +++ b/Tests/ExternalProject/CMakeLists.txt @@ -90,6 +90,16 @@ ExternalProject_Add(${proj} ) set_property(TARGET ${proj} PROPERTY FOLDER "") +set(proj NoExtractLogDownload) +ExternalProject_Add(${proj} + URL ${CMAKE_CURRENT_SOURCE_DIR}/gitrepo.tgz + DOWNLOAD_NO_EXTRACT 1 + LOG_DOWNLOAD 1 + BUILD_COMMAND "" + CONFIGURE_COMMAND "" + INSTALL_COMMAND "" +) + # CVS-based tests: # ----------------------------------------------------------------------- Summary of changes: Modules/ExternalProject.cmake | 5 ++--- Tests/ExternalProject/CMakeLists.txt | 10 ++++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Mon Feb 27 13:49:28 2017 From: brad.king at kitware.com (Brad King) Date: Mon, 27 Feb 2017 13:49:28 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-612-gfd27403 Message-ID: <20170227184928.23724F6BEB@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via fd27403b79c6bb2f8e2568c456cf2fb615944a75 (commit) via f77420cfc934303ffc3d65e798b64e1631eb5d98 (commit) via ae6607af470e1f3faa287310dc80f1fcd6d18ab8 (commit) from a7450168373f48228c3eb837178867f82fcbee2c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=fd27403b79c6bb2f8e2568c456cf2fb615944a75 commit fd27403b79c6bb2f8e2568c456cf2fb615944a75 Merge: a745016 f77420c Author: Brad King AuthorDate: Mon Feb 27 13:49:27 2017 -0500 Commit: CMake Topic Stage CommitDate: Mon Feb 27 13:49:27 2017 -0500 Merge topic 'update-kwiml' into next f77420cf Merge branch 'upstream-KWIML' into update-kwiml ae6607af KWIML 2017-02-27 (aa3a7733) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f77420cfc934303ffc3d65e798b64e1631eb5d98 commit f77420cfc934303ffc3d65e798b64e1631eb5d98 Merge: cdb6d7d ae6607a Author: Brad King AuthorDate: Mon Feb 27 13:49:07 2017 -0500 Commit: Brad King CommitDate: Mon Feb 27 13:49:07 2017 -0500 Merge branch 'upstream-KWIML' into update-kwiml * upstream-KWIML: KWIML 2017-02-27 (aa3a7733) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ae6607af470e1f3faa287310dc80f1fcd6d18ab8 commit ae6607af470e1f3faa287310dc80f1fcd6d18ab8 Author: KWIML Upstream AuthorDate: Mon Feb 27 13:43:26 2017 -0500 Commit: Brad King CommitDate: Mon Feb 27 13:49:07 2017 -0500 KWIML 2017-02-27 (aa3a7733) Code extracted from: https://gitlab.kitware.com/utils/kwiml.git at commit aa3a7733039afb11047fb7d4d71fb26e1775c106 (master). Upstream Shortlog ----------------- Orion Poplawski (1): aa3a7733 test: Add -Wno-format-security to tolerate -Werror=format-security diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 4f6f37b..1bf93bb 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -10,7 +10,7 @@ endif() # Suppress printf/scanf format warnings; we test if the sizes match. foreach(lang C CXX) if(KWIML_LANGUAGE_${lang} AND CMAKE_${lang}_COMPILER_ID STREQUAL "GNU") - set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} -Wno-format") + set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} -Wno-format -Wno-format-security") endif() endforeach() ----------------------------------------------------------------------- Summary of changes: Utilities/KWIML/test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From kwrobot at kitware.com Tue Feb 28 00:01:11 2017 From: kwrobot at kitware.com (Kitware Robot) Date: Tue, 28 Feb 2017 00:01:11 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-316-g8bfa6a0 Message-ID: <20170228050111.CC8CDFA62F@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 8bfa6a00ea7181b49ca4f604c6b8eeab277f0e7e (commit) from cdb6d7df970fcaaf6cda1bef9955351222e1bcde (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8bfa6a00ea7181b49ca4f604c6b8eeab277f0e7e commit 8bfa6a00ea7181b49ca4f604c6b8eeab277f0e7e Author: Kitware Robot AuthorDate: Tue Feb 28 00:01:08 2017 -0500 Commit: Kitware Robot CommitDate: Tue Feb 28 00:01:08 2017 -0500 CMake Nightly Date Stamp diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 13bd07b..28cbbe4 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 8) -set(CMake_VERSION_PATCH 20170227) +set(CMake_VERSION_PATCH 20170228) #set(CMake_VERSION_RC 1) ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 28 08:53:30 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 28 Feb 2017 08:53:30 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-614-g7d1a842 Message-ID: <20170228135330.8E462FA448@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 7d1a84228d336288da78fc0efac3a94e651fbdd0 (commit) via 7ce4ccc8503cdfce400ccc809b1cb52c6624f906 (commit) from fd27403b79c6bb2f8e2568c456cf2fb615944a75 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7d1a84228d336288da78fc0efac3a94e651fbdd0 commit 7d1a84228d336288da78fc0efac3a94e651fbdd0 Merge: fd27403 7ce4ccc Author: Brad King AuthorDate: Tue Feb 28 08:53:29 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 28 08:53:29 2017 -0500 Merge topic 'cpack_nsis_sign_uninstaller' into next 7ce4ccc8 Revert "CPack/NSIS: Sign the uninstaller" https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7ce4ccc8503cdfce400ccc809b1cb52c6624f906 commit 7ce4ccc8503cdfce400ccc809b1cb52c6624f906 Author: Brad King AuthorDate: Tue Feb 28 08:53:10 2017 -0500 Commit: Brad King CommitDate: Tue Feb 28 08:53:10 2017 -0500 Revert "CPack/NSIS: Sign the uninstaller" This reverts commit 10b2e0e479b1015c905aef19439c10d7546a0232. diff --git a/Help/release/dev/cpack-sign-uninstaller.rst b/Help/release/dev/cpack-sign-uninstaller.rst deleted file mode 100644 index ff2b402..0000000 --- a/Help/release/dev/cpack-sign-uninstaller.rst +++ /dev/null @@ -1,5 +0,0 @@ -cpack-sign_uninstaller ----------------------- - -* The :module:`CPackNSIS` module learned to sign the uninstaller - when using :variable:`CPACK_NSIS_SIGN_UNINSTALLER` variable. diff --git a/Modules/CPackNSIS.cmake b/Modules/CPackNSIS.cmake index 37fedf3..18d1871 100644 --- a/Modules/CPackNSIS.cmake +++ b/Modules/CPackNSIS.cmake @@ -133,10 +133,6 @@ # "doc/cmake- at CMake_VERSION_MAJOR@. at CMake_VERSION_MINOR@/cmake.html" # "CMake Help" "https://cmake.org" "CMake Web Site") # -# .. variable:: CPACK_NSIS_SIGN_UNINSTALLER -# -# Specify a command to use for signing the uninstaller. The command will -# be invoked a path to the uninstaller as its only argument. #FIXME we should put NSIS specific code here #FIXME but I'm not doing it because I'm not able to test it... diff --git a/Modules/NSIS.template.in b/Modules/NSIS.template.in index a8903f6..9001888 100644 --- a/Modules/NSIS.template.in +++ b/Modules/NSIS.template.in @@ -29,33 +29,6 @@ ;-------------------------------- ;General -!ifdef INNER - OutFile "$%TEMP%\tempinstaller.exe" - SetCompress off ; for speed -!else - ; Call makensis again, defining INNER. This writes an installer for us which, when - ; it is invoked, will just write the uninstaller to some location, and then exit. - ; Be sure to substitute the name of this script here. - - !system "$\"${NSISDIR}\makensis$\" /DINNER @CPACK_TEMPORARY_DIRECTORY@/../project.nsi" = 0 - - ; So now run that installer we just created as %TEMP%\tempinstaller.exe. Since it - ; calls quit the return value isn't zero. - - !system "$%TEMP%\tempinstaller.exe" = 2 - - ; That will have written an uninstaller binary for us. Now we sign it with your - ; favourite code signing tool. - - !tempfile INCEXIST - !system 'if exist "@CPACK_NSIS_SIGN_UNINSTALLER@" echo !define HAVE_SIGN_UNINST > "${INCEXIST}"' - !include "${INCEXIST}" - !delfile "${INCEXIST}" - !ifdef HAVE_SIGN_UNINST - !system '"@CPACK_NSIS_SIGN_UNINSTALLER@" $%TEMP%\Uninstall.exe' = 0 - !endif - - ; Good. Now we can carry on writing the real installer. ;Name and file Name "@CPACK_NSIS_PACKAGE_NAME@" @@ -63,7 +36,6 @@ ;Set compression SetCompressor @CPACK_NSIS_COMPRESSOR@ -!endif ;Require administrator access RequestExecutionLevel admin @@ -587,10 +559,8 @@ FunctionEnd !insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_PAGE_FINISH -!ifdef INNER !insertmacro MUI_UNPAGE_CONFIRM !insertmacro MUI_UNPAGE_INSTFILES -!endif ;-------------------------------- ;Languages @@ -672,10 +642,7 @@ Section "-Core installation" WriteRegStr SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "" $INSTDIR ;Create uninstaller -!ifndef INNER - ; this packages the signed uninstaller - File $%TEMP%\Uninstall.exe -!endif + WriteUninstaller "$INSTDIR\Uninstall.exe" Push "DisplayName" Push "@CPACK_NSIS_DISPLAY_NAME@" Call ConditionalAddToRegisty @@ -834,7 +801,6 @@ FunctionEnd ;-------------------------------- ;Uninstaller Section -!ifdef INNER Section "Uninstall" ReadRegStr $START_MENU SHCTX \ "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "StartMenu" @@ -920,7 +886,6 @@ Section "Uninstall" Call un.RemoveFromPath doNotRemoveFromPath: SectionEnd -!endif ;-------------------------------- ; determine admin versus local install @@ -933,14 +898,6 @@ SectionEnd ; "Program Files" for AllUsers, "My Documents" for JustMe... Function .onInit -!ifdef INNER - ; If INNER is defined, then we aren't supposed to do anything except write out - ; the installer. This is better than processing a command line option as it means - ; this entire code path is not present in the final (real) installer. - - WriteUninstaller "$%TEMP%\Uninstall.exe" - Quit ; just bail out quickly when running the "inner" installer -!endif StrCmp "@CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL@" "ON" 0 inst ReadRegStr $0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "UninstallString" ----------------------------------------------------------------------- Summary of changes: Help/release/dev/cpack-sign-uninstaller.rst | 5 --- Modules/CPackNSIS.cmake | 4 --- Modules/NSIS.template.in | 45 +-------------------------- 3 files changed, 1 insertion(+), 53 deletions(-) delete mode 100644 Help/release/dev/cpack-sign-uninstaller.rst hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 28 09:03:26 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 28 Feb 2017 09:03:26 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-617-gc3c0a0a Message-ID: <20170228140326.28C0AFA6C4@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via c3c0a0a531937bcccc5b897e8ebaf7c296038304 (commit) via a333570914ffb9756c94c31afdbc4a8429e8eaa7 (commit) via e4ac7c2b4f9523330c4811ff03da69e334665f98 (commit) from 7d1a84228d336288da78fc0efac3a94e651fbdd0 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c3c0a0a531937bcccc5b897e8ebaf7c296038304 commit c3c0a0a531937bcccc5b897e8ebaf7c296038304 Merge: 7d1a842 a333570 Author: Brad King AuthorDate: Tue Feb 28 09:03:25 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 28 09:03:25 2017 -0500 Merge topic 'libuv-solaris-10' into next a3335709 Enable libuv on Solaris 10 e4ac7c2b libuv: Compile as C 90 on Solaris 10 https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a333570914ffb9756c94c31afdbc4a8429e8eaa7 commit a333570914ffb9756c94c31afdbc4a8429e8eaa7 Author: Brad King AuthorDate: Tue Feb 21 19:45:48 2017 -0500 Commit: Brad King CommitDate: Tue Feb 28 09:03:12 2017 -0500 Enable libuv on Solaris 10 We've ported our libuv to this platform so we can build it now. diff --git a/CMakeLists.txt b/CMakeLists.txt index e613224..472c6ab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -509,12 +509,6 @@ int main(void) { return 0; } elseif(CMAKE_SYSTEM_NAME STREQUAL "HP-UX") # Disable until it can be ported. set(CMAKE_USE_LIBUV 0) - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "sparc") - # Disable until it can be ported. - set(CMAKE_USE_LIBUV 0) - elseif(CMAKE_SYSTEM STREQUAL "SunOS-5.10") - # Disable until it can be ported. - set(CMAKE_USE_LIBUV 0) endif() endif() if(CMAKE_USE_LIBUV) https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e4ac7c2b4f9523330c4811ff03da69e334665f98 commit e4ac7c2b4f9523330c4811ff03da69e334665f98 Author: Brad King AuthorDate: Mon Feb 27 09:37:39 2017 -0500 Commit: Brad King CommitDate: Tue Feb 28 09:03:12 2017 -0500 libuv: Compile as C 90 on Solaris 10 diff --git a/Utilities/cmlibuv/CMakeLists.txt b/Utilities/cmlibuv/CMakeLists.txt index 1899f83..6632a1e 100644 --- a/Utilities/cmlibuv/CMakeLists.txt +++ b/Utilities/cmlibuv/CMakeLists.txt @@ -224,6 +224,9 @@ if(CMAKE_SYSTEM_NAME STREQUAL "SunOS") list(APPEND uv_defines _XOPEN_SOURCE=500 ) + if(CMAKE_C_STANDARD) + set(CMAKE_C_STANDARD 90) + endif() else() list(APPEND uv_defines _XOPEN_SOURCE=600 ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 28 09:11:41 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 28 Feb 2017 09:11:41 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-318-gfd6b260 Message-ID: <20170228141141.CF7EEACF78@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via fd6b260c40509e1ab8a6b548e47634388b84d56b (commit) via c1aaf8a61defe3e01e8526b99d8919b9618d1ba9 (commit) from 8bfa6a00ea7181b49ca4f604c6b8eeab277f0e7e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=fd6b260c40509e1ab8a6b548e47634388b84d56b commit fd6b260c40509e1ab8a6b548e47634388b84d56b Merge: 8bfa6a0 c1aaf8a Author: Brad King AuthorDate: Tue Feb 28 09:11:40 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 28 09:11:40 2017 -0500 Merge topic 'cmake-host-system-name' c1aaf8a6 Fix CMAKE_HOST_SYSTEM_NAME on SunOS ----------------------------------------------------------------------- Summary of changes: Source/cmStateSnapshot.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 28 09:11:44 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 28 Feb 2017 09:11:44 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-324-g09a81e2 Message-ID: <20170228141144.87C81ADB71@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 09a81e29fee15bb6781d66769497fa320765fed9 (commit) via a333570914ffb9756c94c31afdbc4a8429e8eaa7 (commit) via e4ac7c2b4f9523330c4811ff03da69e334665f98 (commit) via c9b3c5625a4b35235bfe19e95db8e7d0dfbde59c (commit) via f06986926ae2ed76023956e6594711f9e65b4106 (commit) via 5651257fffc4482861c2ed6a67721fd00f0da6c0 (commit) from fd6b260c40509e1ab8a6b548e47634388b84d56b (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=09a81e29fee15bb6781d66769497fa320765fed9 commit 09a81e29fee15bb6781d66769497fa320765fed9 Merge: fd6b260 a333570 Author: Brad King AuthorDate: Tue Feb 28 09:11:42 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 28 09:11:42 2017 -0500 Merge topic 'libuv-solaris-10' a3335709 Enable libuv on Solaris 10 e4ac7c2b libuv: Compile as C 90 on Solaris 10 c9b3c562 libuv: Link to 'rt' library on Solaris 10 to get semaphores f0698692 libuv: Implement mkdtemp on Solaris 10 5651257f libuv: automatically skip ifaddrs on Solaris 10 ----------------------------------------------------------------------- Summary of changes: CMakeLists.txt | 6 ------ Utilities/cmlibuv/CMakeLists.txt | 4 ++++ Utilities/cmlibuv/src/unix/fs.c | 12 +++++++++++- Utilities/cmlibuv/src/unix/sunos.c | 4 ++++ 4 files changed, 19 insertions(+), 7 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 28 09:11:47 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 28 Feb 2017 09:11:47 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-329-g6a8da1d Message-ID: <20170228141147.32D6FC0C3A@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 6a8da1d7773ac3d50a450b1043f453406528ae29 (commit) via 29528cc33e929b3c034b1491842ddaf91b3855cf (commit) via 62d0e22325d36e5f9d61ccfbef0d68cfe1935f1b (commit) via 059aa805c9c0cb34c92eb69abf66febc40ab62db (commit) via 5fee76606b7a1f252e75e95c3d8303777459938d (commit) from 09a81e29fee15bb6781d66769497fa320765fed9 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6a8da1d7773ac3d50a450b1043f453406528ae29 commit 6a8da1d7773ac3d50a450b1043f453406528ae29 Merge: 09a81e2 29528cc Author: Brad King AuthorDate: Tue Feb 28 09:11:45 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 28 09:11:45 2017 -0500 Merge topic 'update-libarchive' 29528cc3 libarchive: Remove liblzma from introspection tests 62d0e223 Merge branch 'upstream-LibArchive' into update-libarchive 059aa805 LibArchive 2017-02-25 (d6b1bb9f) 5fee7660 libarchive: Update script to get 3.3.1 ----------------------------------------------------------------------- Summary of changes: Utilities/Scripts/update-libarchive.bash | 2 +- Utilities/cmlibarchive/CMakeLists.txt | 13 ++- Utilities/cmlibarchive/build/cmake/config.h.in | 3 + Utilities/cmlibarchive/build/version | 2 +- Utilities/cmlibarchive/libarchive/archive.h | 8 +- .../libarchive/archive_digest_private.h | 1 + Utilities/cmlibarchive/libarchive/archive_entry.c | 110 ++++++++++++++++---- Utilities/cmlibarchive/libarchive/archive_entry.h | 2 +- Utilities/cmlibarchive/libarchive/archive_hmac.c | 4 + .../libarchive/archive_read_disk_entry_from_file.c | 24 +++-- .../libarchive/archive_read_disk_posix.c | 64 +++++------- .../libarchive/archive_read_disk_private.h | 12 +-- .../libarchive/archive_read_disk_windows.c | 30 ++---- .../libarchive/archive_read_support_format_warc.c | 18 ++-- .../libarchive/archive_write_disk_posix.c | 59 +++++++++-- 15 files changed, 227 insertions(+), 125 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 28 09:11:49 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 28 Feb 2017 09:11:49 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-332-g6403cda Message-ID: <20170228141149.CA26CBB2AC@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 6403cda149e5213608b8f4889676c1e69aaf498a (commit) via f77420cfc934303ffc3d65e798b64e1631eb5d98 (commit) via ae6607af470e1f3faa287310dc80f1fcd6d18ab8 (commit) from 6a8da1d7773ac3d50a450b1043f453406528ae29 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6403cda149e5213608b8f4889676c1e69aaf498a commit 6403cda149e5213608b8f4889676c1e69aaf498a Merge: 6a8da1d f77420c Author: Brad King AuthorDate: Tue Feb 28 09:11:47 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 28 09:11:47 2017 -0500 Merge topic 'update-kwiml' f77420cf Merge branch 'upstream-KWIML' into update-kwiml ae6607af KWIML 2017-02-27 (aa3a7733) ----------------------------------------------------------------------- Summary of changes: Utilities/KWIML/test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 28 09:12:06 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 28 Feb 2017 09:12:06 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-623-g9780a18 Message-ID: <20170228141206.867DBACF78@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 9780a18290b8763870a57a315cdaad1a8b5a02a6 (commit) via 6403cda149e5213608b8f4889676c1e69aaf498a (commit) via 6a8da1d7773ac3d50a450b1043f453406528ae29 (commit) via 09a81e29fee15bb6781d66769497fa320765fed9 (commit) via fd6b260c40509e1ab8a6b548e47634388b84d56b (commit) via 8bfa6a00ea7181b49ca4f604c6b8eeab277f0e7e (commit) from c3c0a0a531937bcccc5b897e8ebaf7c296038304 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9780a18290b8763870a57a315cdaad1a8b5a02a6 commit 9780a18290b8763870a57a315cdaad1a8b5a02a6 Merge: c3c0a0a 6403cda Author: Brad King AuthorDate: Tue Feb 28 09:11:57 2017 -0500 Commit: Brad King CommitDate: Tue Feb 28 09:11:57 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: Source/CMakeVersion.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 28 09:22:25 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 28 Feb 2017 09:22:25 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-626-g1838368 Message-ID: <20170228142225.52125FA1AC@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 183836811c2ae8bce19dab4f77f1afecf84fbef0 (commit) via 7238a052b9238dc4405e90389a16a4dc61f848a6 (commit) via ffb8817b370937b02c384d9d1fd91c4e9d799553 (commit) from 9780a18290b8763870a57a315cdaad1a8b5a02a6 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=183836811c2ae8bce19dab4f77f1afecf84fbef0 commit 183836811c2ae8bce19dab4f77f1afecf84fbef0 Merge: 9780a18 7238a05 Author: Brad King AuthorDate: Tue Feb 28 09:22:24 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 28 09:22:24 2017 -0500 Merge topic 'cmake-xcode-schemes' into next 7238a052 Xcode: Add documentation for schema generator ffb8817b Xcode: Write shared schemes based on the default files generated by Xcode https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7238a052b9238dc4405e90389a16a4dc61f848a6 commit 7238a052b9238dc4405e90389a16a4dc61f848a6 Author: Gregor Jasny AuthorDate: Wed Feb 22 17:51:41 2017 +0100 Commit: Brad King CommitDate: Tue Feb 28 09:22:11 2017 -0500 Xcode: Add documentation for schema generator diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 5fad10c..b4e9c1b 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -45,6 +45,7 @@ Properties of Global Scope /prop_gbl/TARGET_SUPPORTS_SHARED_LIBS /prop_gbl/USE_FOLDERS /prop_gbl/XCODE_EMIT_EFFECTIVE_PLATFORM_NAME + /prop_gbl/XCODE_GENERATE_SCHEME .. _`Directory Properties`: diff --git a/Help/prop_gbl/XCODE_GENERATE_SCHEME.rst b/Help/prop_gbl/XCODE_GENERATE_SCHEME.rst new file mode 100644 index 0000000..be8b5b0 --- /dev/null +++ b/Help/prop_gbl/XCODE_GENERATE_SCHEME.rst @@ -0,0 +1,11 @@ +XCODE_GENERATE_SCHEME +--------------------- + +If enabled, the Xcode generator will generate schema files. Those are +are useful to invoke analyze, archive, build-for-testing and test +actions from the command line. + +.. note:: + + The Xcode Schema Generator is still experimental and subject to + change. diff --git a/Help/release/dev/cmake-xcode-schemes.rst b/Help/release/dev/cmake-xcode-schemes.rst new file mode 100644 index 0000000..27c19d7 --- /dev/null +++ b/Help/release/dev/cmake-xcode-schemes.rst @@ -0,0 +1,6 @@ +cmake-xcode-schemes +------------------- + +* The :generator:`Xcode` generator got the ability to create schema files. + This is still an experimental feature and can be activated by setting the + :prop_gbl:`XCODE_GENERATE_SCHEME` global property to a ``TRUE`` value. https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ffb8817b370937b02c384d9d1fd91c4e9d799553 commit ffb8817b370937b02c384d9d1fd91c4e9d799553 Author: Gusts Kaksis AuthorDate: Wed Jan 18 16:20:09 2017 +0200 Commit: Brad King CommitDate: Tue Feb 28 09:21:54 2017 -0500 Xcode: Write shared schemes based on the default files generated by Xcode Issue: #15441 diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 3b49f72..76b98fc 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -639,6 +639,7 @@ if(APPLE) set(SRCS ${SRCS} cmXCodeObject.cxx cmXCode21Object.cxx + cmXCodeScheme.cxx cmGlobalXCodeGenerator.cxx cmGlobalXCodeGenerator.h cmLocalXCodeGenerator.cxx diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 8627cf2..8acea45 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -28,6 +28,7 @@ #include "cmTarget.h" #include "cmXCode21Object.h" #include "cmXCodeObject.h" +#include "cmXCodeScheme.h" #include "cm_auto_ptr.hxx" #include "cmake.h" @@ -3327,6 +3328,15 @@ void cmGlobalXCodeGenerator::OutputXCodeProject( return; } this->WriteXCodePBXProj(fout, root, generators); + + // Since the lowest available Xcode version for testing was 7.0, + // I'm setting this as a limit then + if (this->GetCMakeInstance()->GetState()->GetGlobalPropertyAsBool( + "XCODE_GENERATE_SCHEME") && + this->XcodeVersion >= 70) { + this->OutputXCodeSharedSchemes(xcodeDir, root); + } + this->ClearXCodeObjects(); // Since this call may have created new cache entries, save the cache: @@ -3335,6 +3345,24 @@ void cmGlobalXCodeGenerator::OutputXCodeProject( root->GetBinaryDirectory()); } +void cmGlobalXCodeGenerator::OutputXCodeSharedSchemes( + const std::string& xcProjDir, cmLocalGenerator* root) +{ + for (std::vector::const_iterator i = + this->XCodeObjects.begin(); + i != this->XCodeObjects.end(); ++i) { + cmXCodeObject* obj = *i; + if (obj->GetType() == cmXCodeObject::OBJECT && + (obj->GetIsA() == cmXCodeObject::PBXNativeTarget || + obj->GetIsA() == cmXCodeObject::PBXAggregateTarget)) { + cmXCodeScheme schm(obj, this->CurrentConfigurationTypes, + this->XcodeVersion); + schm.WriteXCodeSharedScheme(xcProjDir, + root->GetCurrentSourceDirectory()); + } + } +} + void cmGlobalXCodeGenerator::WriteXCodePBXProj(std::ostream& fout, cmLocalGenerator*, std::vector&) diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index 1aaf9c7..c9157b0 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -165,6 +165,9 @@ private: std::vector& generators); void OutputXCodeProject(cmLocalGenerator* root, std::vector& generators); + // Write shared scheme files for all the native targets + void OutputXCodeSharedSchemes(const std::string& xcProjDir, + cmLocalGenerator* root); void WriteXCodePBXProj(std::ostream& fout, cmLocalGenerator* root, std::vector& generators); cmXCodeObject* CreateXCodeFileReferenceFromPath(const std::string& fullpath, diff --git a/Source/cmXCodeScheme.cxx b/Source/cmXCodeScheme.cxx new file mode 100644 index 0000000..3c8c0b7 --- /dev/null +++ b/Source/cmXCodeScheme.cxx @@ -0,0 +1,206 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmXCodeScheme.h" + +#include +#include + +#include "cmGeneratedFileStream.h" +#include "cmGeneratorTarget.h" +#include "cmXMLSafe.h" + +cmXCodeScheme::cmXCodeScheme(cmXCodeObject* xcObj, + const std::vector& configList, + unsigned int xcVersion) + : TargetName(xcObj->GetTarget()->GetName()) + , TargetId(xcObj->GetId()) + , ConfigList(configList) + , XcodeVersion(xcVersion) +{ +} + +void cmXCodeScheme::WriteXCodeSharedScheme(const std::string& xcProjDir, + const std::string sourceRoot) +{ + // Create shared scheme sub-directory tree + // + std::string xcodeSchemeDir = xcProjDir; + xcodeSchemeDir += "/xcshareddata/xcschemes"; + cmSystemTools::MakeDirectory(xcodeSchemeDir.c_str()); + + std::string xcodeSchemeFile = xcodeSchemeDir; + xcodeSchemeFile += "/"; + xcodeSchemeFile += this->TargetName; + xcodeSchemeFile += ".xcscheme"; + + cmGeneratedFileStream fout(xcodeSchemeFile.c_str()); + fout.SetCopyIfDifferent(true); + if (!fout) { + return; + } + + std::string xcProjRelDir = xcProjDir.substr(sourceRoot.size() + 1); + WriteXCodeXCScheme(fout, xcProjRelDir); +} + +void cmXCodeScheme::WriteXCodeXCScheme(std::ostream& fout, + const std::string& xcProjDir) +{ + cmXMLWriter xout(fout); + xout.StartDocument(); + + xout.StartElement("Scheme"); + xout.BreakAttributes(); + xout.Attribute("LastUpgradeVersion", WriteVersionString()); + xout.Attribute("version", "1.3"); + + WriteBuildAction(xout, xcProjDir); + WriteTestAction(xout, FindConfiguration("Debug")); + WriteLaunchAction(xout, FindConfiguration("Debug"), xcProjDir); + WriteProfileAction(xout, FindConfiguration("Release")); + WriteAnalyzeAction(xout, FindConfiguration("Debug")); + WriteArchiveAction(xout, FindConfiguration("Release")); + + xout.EndElement(); +} + +void cmXCodeScheme::WriteBuildAction(cmXMLWriter& xout, + const std::string& xcProjDir) +{ + xout.StartElement("BuildAction"); + xout.BreakAttributes(); + xout.Attribute("parallelizeBuildables", "YES"); + xout.Attribute("buildImplicitDependencies", "YES"); + + xout.StartElement("BuildActionEntries"); + xout.StartElement("BuildActionEntry"); + xout.BreakAttributes(); + xout.Attribute("buildForTesting", "YES"); + xout.Attribute("buildForRunning", "YES"); + xout.Attribute("buildForProfiling", "YES"); + xout.Attribute("buildForArchiving", "YES"); + xout.Attribute("buildForAnalyzing", "YES"); + + xout.StartElement("BuildableReference"); + xout.BreakAttributes(); + xout.Attribute("BuildableIdentifier", "primary"); + xout.Attribute("BlueprintIdentifier", this->TargetId); + xout.Attribute("BuildableName", this->TargetName); + xout.Attribute("BlueprintName", this->TargetName); + xout.Attribute("ReferencedContainer", "container:" + xcProjDir); + xout.EndElement(); + + xout.EndElement(); // BuildActionEntry + xout.EndElement(); // BuildActionEntries + xout.EndElement(); // BuildAction +} + +void cmXCodeScheme::WriteTestAction(cmXMLWriter& xout, + std::string configuration) +{ + xout.StartElement("TestAction"); + xout.BreakAttributes(); + xout.Attribute("buildConfiguration", configuration); + xout.Attribute("selectedDebuggerIdentifier", + "Xcode.DebuggerFoundation.Debugger.LLDB"); + xout.Attribute("selectedLauncherIdentifier", + "Xcode.DebuggerFoundation.Launcher.LLDB"); + xout.Attribute("shouldUseLaunchSchemeArgsEnv", "YES"); + + xout.StartElement("Testables"); + xout.EndElement(); + + xout.StartElement("AdditionalOptions"); + xout.EndElement(); + + xout.EndElement(); // TestAction +} + +void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout, + std::string configuration, + const std::string& xcProjDir) +{ + xout.StartElement("LaunchAction"); + xout.BreakAttributes(); + xout.Attribute("buildConfiguration", configuration); + xout.Attribute("selectedDebuggerIdentifier", + "Xcode.DebuggerFoundation.Debugger.LLDB"); + xout.Attribute("selectedLauncherIdentifier", + "Xcode.DebuggerFoundation.Launcher.LLDB"); + xout.Attribute("launchStyle", "0"); + xout.Attribute("useCustomWorkingDirectory", "NO"); + xout.Attribute("ignoresPersistentStateOnLaunch", "NO"); + xout.Attribute("debugDocumentVersioning", "YES"); + xout.Attribute("debugServiceExtension", "internal"); + xout.Attribute("allowLocationSimulation", "YES"); + + xout.StartElement("MacroExpansion"); + + xout.StartElement("BuildableReference"); + xout.BreakAttributes(); + xout.Attribute("BuildableIdentifier", "primary"); + xout.Attribute("BlueprintIdentifier", this->TargetId); + xout.Attribute("BuildableName", this->TargetName); + xout.Attribute("BlueprintName", this->TargetName); + xout.Attribute("ReferencedContainer", "container:" + xcProjDir); + xout.EndElement(); + + xout.EndElement(); // MacroExpansion + + xout.StartElement("AdditionalOptions"); + xout.EndElement(); + + xout.EndElement(); // LaunchAction +} + +void cmXCodeScheme::WriteProfileAction(cmXMLWriter& xout, + std::string configuration) +{ + xout.StartElement("ProfileAction"); + xout.BreakAttributes(); + xout.Attribute("buildConfiguration", configuration); + xout.Attribute("shouldUseLaunchSchemeArgsEnv", "YES"); + xout.Attribute("savedToolIdentifier", ""); + xout.Attribute("useCustomWorkingDirectory", "NO"); + xout.Attribute("debugDocumentVersioning", "YES"); + xout.EndElement(); +} + +void cmXCodeScheme::WriteAnalyzeAction(cmXMLWriter& xout, + std::string configuration) +{ + xout.StartElement("AnalyzeAction"); + xout.BreakAttributes(); + xout.Attribute("buildConfiguration", configuration); + xout.EndElement(); +} + +void cmXCodeScheme::WriteArchiveAction(cmXMLWriter& xout, + std::string configuration) +{ + xout.StartElement("ArchiveAction"); + xout.BreakAttributes(); + xout.Attribute("buildConfiguration", configuration); + xout.Attribute("revealArchiveInOrganizer", "YES"); + xout.EndElement(); +} + +std::string cmXCodeScheme::WriteVersionString() +{ + std::ostringstream v; + v << std::setfill('0') << std::setw(4) << this->XcodeVersion * 10; + return v.str(); +} + +std::string cmXCodeScheme::FindConfiguration(const std::string& name) +{ + // Try to find the desired configuration by name, + // and if it's not found return first from the list + // + if (std::find(this->ConfigList.begin(), this->ConfigList.end(), name) == + this->ConfigList.end() && + this->ConfigList.size() > 0) + return this->ConfigList[0]; + + return name; +} diff --git a/Source/cmXCodeScheme.h b/Source/cmXCodeScheme.h new file mode 100644 index 0000000..b174c51 --- /dev/null +++ b/Source/cmXCodeScheme.h @@ -0,0 +1,46 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmXCodeScheme_h +#define cmXCodeScheme_h + +#include // IWYU pragma: keep + +#include "cmGlobalXCodeGenerator.h" +#include "cmSystemTools.h" +#include "cmXCodeObject.h" +#include "cmXMLWriter.h" + +/** \class cmXCodeScheme + * \brief Write shared schemes for native targets in Xcode project. + */ +class cmXCodeScheme +{ +public: + cmXCodeScheme(cmXCodeObject* xcObj, + const std::vector& configList, + unsigned int xcVersion); + + void WriteXCodeSharedScheme(const std::string& xcProjDir, + const std::string sourceRoot); + +private: + const std::string& TargetName; + const std::string& TargetId; + const std::vector& ConfigList; + const unsigned int XcodeVersion; + + void WriteXCodeXCScheme(std::ostream& fout, const std::string& xcProjDir); + + void WriteBuildAction(cmXMLWriter& xout, const std::string& xcProjDir); + void WriteTestAction(cmXMLWriter& xout, std::string configuration); + void WriteLaunchAction(cmXMLWriter& xout, std::string configuration, + const std::string& xcProjDir); + void WriteProfileAction(cmXMLWriter& xout, std::string configuration); + void WriteAnalyzeAction(cmXMLWriter& xout, std::string configuration); + void WriteArchiveAction(cmXMLWriter& xout, std::string configuration); + + std::string WriteVersionString(); + std::string FindConfiguration(const std::string& name); +}; + +#endif ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 28 09:39:15 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 28 Feb 2017 09:39:15 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-335-g0aec4d3 Message-ID: <20170228143915.30FF6381@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 0aec4d38642570cc38440b5368fec4de02e09a6a (commit) via 7238a052b9238dc4405e90389a16a4dc61f848a6 (commit) via ffb8817b370937b02c384d9d1fd91c4e9d799553 (commit) from 6403cda149e5213608b8f4889676c1e69aaf498a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0aec4d38642570cc38440b5368fec4de02e09a6a commit 0aec4d38642570cc38440b5368fec4de02e09a6a Merge: 6403cda 7238a05 Author: Brad King AuthorDate: Tue Feb 28 09:39:12 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 28 09:39:12 2017 -0500 Merge topic 'cmake-xcode-schemes' 7238a052 Xcode: Add documentation for schema generator ffb8817b Xcode: Write shared schemes based on the default files generated by Xcode ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-properties.7.rst | 1 + Help/prop_gbl/XCODE_GENERATE_SCHEME.rst | 11 ++ Help/release/dev/cmake-xcode-schemes.rst | 6 + Source/CMakeLists.txt | 1 + Source/cmGlobalXCodeGenerator.cxx | 28 ++++ Source/cmGlobalXCodeGenerator.h | 3 + Source/cmXCodeScheme.cxx | 206 ++++++++++++++++++++++++++++++ Source/cmXCodeScheme.h | 46 +++++++ 8 files changed, 302 insertions(+) create mode 100644 Help/prop_gbl/XCODE_GENERATE_SCHEME.rst create mode 100644 Help/release/dev/cmake-xcode-schemes.rst create mode 100644 Source/cmXCodeScheme.cxx create mode 100644 Source/cmXCodeScheme.h hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 28 09:39:18 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 28 Feb 2017 09:39:18 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-337-g322472e Message-ID: <20170228143918.7A38C646@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 322472e571f75f803c148a8ebba25c6d0247fc82 (commit) via 73a6d4566a9fa13ffaef2f1111be808a220ba867 (commit) from 0aec4d38642570cc38440b5368fec4de02e09a6a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=322472e571f75f803c148a8ebba25c6d0247fc82 commit 322472e571f75f803c148a8ebba25c6d0247fc82 Merge: 0aec4d3 73a6d45 Author: Brad King AuthorDate: Tue Feb 28 09:39:16 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 28 09:39:16 2017 -0500 Merge topic 'cache-xaml-resx-headers' 73a6d456 VS: Cache the list of xaml and resx headers ----------------------------------------------------------------------- Summary of changes: Source/cmGeneratorTarget.cxx | 26 +++++++++++++++++++------- Source/cmGeneratorTarget.h | 4 ++++ 2 files changed, 23 insertions(+), 7 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 28 09:39:21 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 28 Feb 2017 09:39:21 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-339-gdda1805 Message-ID: <20170228143921.20ACE6EA@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via dda1805f27c40028924cf367492d6990dcf31e96 (commit) via 99d6de6c1a5871ba03fa008c984cd5408940c3cd (commit) from 322472e571f75f803c148a8ebba25c6d0247fc82 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=dda1805f27c40028924cf367492d6990dcf31e96 commit dda1805f27c40028924cf367492d6990dcf31e96 Merge: 322472e 99d6de6 Author: Brad King AuthorDate: Tue Feb 28 09:39:19 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 28 09:39:19 2017 -0500 Merge topic 'ExternalProject-fix-download-log' 99d6de6c ExternalProject: only append `COMMAND` if actually adding a command ----------------------------------------------------------------------- Summary of changes: Modules/ExternalProject.cmake | 5 ++--- Tests/ExternalProject/CMakeLists.txt | 10 ++++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 28 09:39:23 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 28 Feb 2017 09:39:23 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-341-g30243e7 Message-ID: <20170228143923.ED3788A2@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 30243e7fafee60a8ef6ffc6fb8eed09548a86aa9 (commit) via ded616bdad46a445ea7ae05d47ae8f32026b13b5 (commit) from dda1805f27c40028924cf367492d6990dcf31e96 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=30243e7fafee60a8ef6ffc6fb8eed09548a86aa9 commit 30243e7fafee60a8ef6ffc6fb8eed09548a86aa9 Merge: dda1805 ded616b Author: Brad King AuthorDate: Tue Feb 28 09:39:21 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 28 09:39:21 2017 -0500 Merge topic '16607-error-out-on-non-seekable-input-files' ded616bd cmListFileLexer: bail out on seek-errors ----------------------------------------------------------------------- Summary of changes: Source/cmListFileCache.cxx | 7 +++++++ Source/cmListFileLexer.c | 8 ++++++-- Source/cmListFileLexer.h | 1 + Tests/RunCMake/CMakeLists.txt | 2 +- Tests/RunCMake/CommandLine/RunCMakeTest.cmake | 13 +++++++++++++ .../reject_fifo-result.txt} | 0 Tests/RunCMake/CommandLine/reject_fifo-stderr.txt | 2 ++ 7 files changed, 30 insertions(+), 3 deletions(-) copy Tests/RunCMake/{Android/BadSYSROOT-result.txt => CommandLine/reject_fifo-result.txt} (100%) create mode 100644 Tests/RunCMake/CommandLine/reject_fifo-stderr.txt hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 28 09:39:52 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 28 Feb 2017 09:39:52 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-631-g2a8c67c Message-ID: <20170228143952.ECBAF8A2@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 2a8c67ccc306ab592098adb218610d2b39062633 (commit) via 30243e7fafee60a8ef6ffc6fb8eed09548a86aa9 (commit) via dda1805f27c40028924cf367492d6990dcf31e96 (commit) via 322472e571f75f803c148a8ebba25c6d0247fc82 (commit) via 0aec4d38642570cc38440b5368fec4de02e09a6a (commit) from 183836811c2ae8bce19dab4f77f1afecf84fbef0 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=2a8c67ccc306ab592098adb218610d2b39062633 commit 2a8c67ccc306ab592098adb218610d2b39062633 Merge: 1838368 30243e7 Author: Brad King AuthorDate: Tue Feb 28 09:39:41 2017 -0500 Commit: Brad King CommitDate: Tue Feb 28 09:39:41 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 28 09:43:36 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 28 Feb 2017 09:43:36 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-633-g13e3401 Message-ID: <20170228144336.3A43FF99EB@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 13e34019b22fb5930919401599c4623d2c65508c (commit) via 4ca77bb6db34edc7cae2313c82c769f564fb02ea (commit) from 2a8c67ccc306ab592098adb218610d2b39062633 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=13e34019b22fb5930919401599c4623d2c65508c commit 13e34019b22fb5930919401599c4623d2c65508c Merge: 2a8c67c 4ca77bb Author: Brad King AuthorDate: Tue Feb 28 09:43:35 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 28 09:43:35 2017 -0500 Merge topic 'kwiml-test-gcc-format-security' into next 4ca77bb6 KWIML: Add -Wno-format-security to tolerate -Werror=format-security https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4ca77bb6db34edc7cae2313c82c769f564fb02ea commit 4ca77bb6db34edc7cae2313c82c769f564fb02ea Author: Orion Poplawski AuthorDate: Mon Feb 27 11:24:39 2017 -0700 Commit: Brad King CommitDate: Mon Feb 27 13:47:00 2017 -0500 KWIML: Add -Wno-format-security to tolerate -Werror=format-security When compiling KWIML tests with `-Werror=format-security` we get error: -Wformat-security ignored without -Wformat Therefore we should disable both `format` and `format-security` together. diff --git a/Utilities/KWIML/test/CMakeLists.txt b/Utilities/KWIML/test/CMakeLists.txt index 4f6f37b..1bf93bb 100644 --- a/Utilities/KWIML/test/CMakeLists.txt +++ b/Utilities/KWIML/test/CMakeLists.txt @@ -10,7 +10,7 @@ endif() # Suppress printf/scanf format warnings; we test if the sizes match. foreach(lang C CXX) if(KWIML_LANGUAGE_${lang} AND CMAKE_${lang}_COMPILER_ID STREQUAL "GNU") - set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} -Wno-format") + set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} -Wno-format -Wno-format-security") endif() endforeach() ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 28 09:43:51 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 28 Feb 2017 09:43:51 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-343-g2ca029d Message-ID: <20170228144351.6B36EE202B@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 2ca029d9a896433c6b8681930ee0bd8d87a21122 (commit) via 4ca77bb6db34edc7cae2313c82c769f564fb02ea (commit) from 30243e7fafee60a8ef6ffc6fb8eed09548a86aa9 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=2ca029d9a896433c6b8681930ee0bd8d87a21122 commit 2ca029d9a896433c6b8681930ee0bd8d87a21122 Merge: 30243e7 4ca77bb Author: Brad King AuthorDate: Tue Feb 28 09:43:49 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 28 09:43:49 2017 -0500 Merge topic 'kwiml-test-gcc-format-security' 4ca77bb6 KWIML: Add -Wno-format-security to tolerate -Werror=format-security ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 28 09:44:37 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 28 Feb 2017 09:44:37 -0500 (EST) Subject: [Cmake-commits] CMake branch, master, updated. v3.8.0-rc1-345-g78104bd Message-ID: <20170228144437.4ADBEF9D48@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, master has been updated via 78104bd7bca4bd9b4b7a5c17622838a33843138e (commit) via 220b799c8a7ff6039254c90bbeba1890d816b523 (commit) from 2ca029d9a896433c6b8681930ee0bd8d87a21122 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 28 09:44:37 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 28 Feb 2017 09:44:37 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-637-g63f5ddc Message-ID: <20170228144437.65FA0F9DD8@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 63f5ddc0f7c158543113352593ba6999c675814c (commit) via 78104bd7bca4bd9b4b7a5c17622838a33843138e (commit) via 2ca029d9a896433c6b8681930ee0bd8d87a21122 (commit) via 220b799c8a7ff6039254c90bbeba1890d816b523 (commit) from 13e34019b22fb5930919401599c4623d2c65508c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=63f5ddc0f7c158543113352593ba6999c675814c commit 63f5ddc0f7c158543113352593ba6999c675814c Merge: 13e3401 78104bd Author: Brad King AuthorDate: Tue Feb 28 09:44:19 2017 -0500 Commit: Brad King CommitDate: Tue Feb 28 09:44:19 2017 -0500 Merge branch 'master' into next ----------------------------------------------------------------------- Summary of changes: hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 28 09:44:37 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 28 Feb 2017 09:44:37 -0500 (EST) Subject: [Cmake-commits] CMake branch, release, updated. v3.8.0-rc1-58-g220b799 Message-ID: <20170228144437.7CB45F9E06@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, release has been updated via 220b799c8a7ff6039254c90bbeba1890d816b523 (commit) via 4ca77bb6db34edc7cae2313c82c769f564fb02ea (commit) from dab2ff3e237f1c3c2430e0661281719185ef4eb1 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- Summary of changes: Utilities/KWIML/test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 28 09:53:37 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 28 Feb 2017 09:53:37 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-639-gf9ea9e5 Message-ID: <20170228145341.EB559FA4FD@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via f9ea9e5b5716a3b37799af673375bb41d5cb5816 (commit) via 85e08370d0774397f42a7d45d07f22b3a817fe10 (commit) from 63f5ddc0f7c158543113352593ba6999c675814c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f9ea9e5b5716a3b37799af673375bb41d5cb5816 commit f9ea9e5b5716a3b37799af673375bb41d5cb5816 Merge: 63f5ddc 85e0837 Author: Brad King AuthorDate: Tue Feb 28 09:53:35 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 28 09:53:35 2017 -0500 Merge topic 'export-executable-symbols' into next 85e08370 bindexplib: Always export executable symbols, even they are also readable https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=85e08370d0774397f42a7d45d07f22b3a817fe10 commit 85e08370d0774397f42a7d45d07f22b3a817fe10 Author: Zsolt Parragi AuthorDate: Fri Feb 24 10:06:43 2017 +0100 Commit: Brad King CommitDate: Tue Feb 28 09:49:12 2017 -0500 bindexplib: Always export executable symbols, even they are also readable Previously bindexplib discarded read-only non-function symbols even in executable/code sections, but in some specific cases they could still mark functions. An example is provided by nop.asm in the AuoExportDll test, which exports a function only marked by a label. This symbol can be used from C/C++ code, but without this change it would result in an unresolved external symbol when built as a DLL on Windows. diff --git a/Source/bindexplib.cxx b/Source/bindexplib.cxx index eded883..e41850a 100644 --- a/Source/bindexplib.cxx +++ b/Source/bindexplib.cxx @@ -308,7 +308,8 @@ public: this->DataSymbols.insert(symbol); } else { if ( pSymbolTable->Type || - !(SectChar & IMAGE_SCN_MEM_READ)) { + !(SectChar & IMAGE_SCN_MEM_READ) || + (SectChar & IMAGE_SCN_MEM_EXECUTE)) { this->Symbols.insert(symbol); } else { // printf(" strange symbol: %s \n",symbol.c_str()); diff --git a/Tests/RunCMake/AutoExportDll/AutoExport.cmake b/Tests/RunCMake/AutoExportDll/AutoExport.cmake index d37e896..a550005 100644 --- a/Tests/RunCMake/AutoExportDll/AutoExport.cmake +++ b/Tests/RunCMake/AutoExportDll/AutoExport.cmake @@ -11,5 +11,11 @@ if(MSVC) set_target_properties(say PROPERTIES ENABLE_EXPORTS ON) add_library(autoexport_for_exec SHARED hello2.c) target_link_libraries(autoexport_for_exec say) + if(NOT MSVC_VERSION VERSION_LESS 1600) + enable_language(ASM_MASM) + target_sources(autoexport PRIVATE nop.asm) + set_property(SOURCE nop.asm PROPERTY COMPILE_FLAGS /safeseh) + target_compile_definitions(say PRIVATE HAS_JUSTNOP) + endif() endif() target_link_libraries(say autoexport autoexport2) diff --git a/Tests/RunCMake/AutoExportDll/nop.asm b/Tests/RunCMake/AutoExportDll/nop.asm new file mode 100644 index 0000000..fd6892f --- /dev/null +++ b/Tests/RunCMake/AutoExportDll/nop.asm @@ -0,0 +1,12 @@ +IFDEF RAX +ELSE +.MODEL FLAT,C +ENDIF + +SOME SEGMENT EXECUTE READ + +public justnop +justnop: + ret + +END diff --git a/Tests/RunCMake/AutoExportDll/say.cxx b/Tests/RunCMake/AutoExportDll/say.cxx index e966b1f..51060e8 100644 --- a/Tests/RunCMake/AutoExportDll/say.cxx +++ b/Tests/RunCMake/AutoExportDll/say.cxx @@ -12,6 +12,7 @@ int WINAPI foo(); // test regular C int bar(); int objlib(); +void justnop(); } // test c++ functions @@ -42,5 +43,8 @@ int main() bar(); objlib(); printf("\n"); +#ifdef HAS_JUSTNOP + justnop(); +#endif return 0; } ----------------------------------------------------------------------- Summary of changes: Source/bindexplib.cxx | 3 ++- Tests/RunCMake/AutoExportDll/AutoExport.cmake | 6 ++++++ Tests/RunCMake/AutoExportDll/nop.asm | 12 ++++++++++++ Tests/RunCMake/AutoExportDll/say.cxx | 4 ++++ 4 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 Tests/RunCMake/AutoExportDll/nop.asm hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 28 11:10:53 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 28 Feb 2017 11:10:53 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-641-g126c84a Message-ID: <20170228161053.BCBF5ADA11@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 126c84a4bb4122c67839f60dba1a0877ff0234c0 (commit) via 8d71fa92838f9fd3d444963c6ea6ea0d7be39cf3 (commit) from f9ea9e5b5716a3b37799af673375bb41d5cb5816 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=126c84a4bb4122c67839f60dba1a0877ff0234c0 commit 126c84a4bb4122c67839f60dba1a0877ff0234c0 Merge: f9ea9e5 8d71fa9 Author: Brad King AuthorDate: Tue Feb 28 11:10:52 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 28 11:10:52 2017 -0500 Merge topic 'FindPkgConfig-version-ops' into next 8d71fa92 FindPkgConfig: use new version checking "library >= version" syntax https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8d71fa92838f9fd3d444963c6ea6ea0d7be39cf3 commit 8d71fa92838f9fd3d444963c6ea6ea0d7be39cf3 Author: Gautier Pelloux-Prayer AuthorDate: Mon Feb 27 17:15:49 2017 +0100 Commit: Gautier Pelloux-Prayer CommitDate: Tue Feb 28 10:45:25 2017 +0100 FindPkgConfig: use new version checking "library >= version" syntax Instead of the deprecated --atleast-version one. diff --git a/Modules/FindPkgConfig.cmake b/Modules/FindPkgConfig.cmake index 1958f4b..a69081f 100644 --- a/Modules/FindPkgConfig.cmake +++ b/Modules/FindPkgConfig.cmake @@ -360,38 +360,25 @@ macro(_pkg_check_modules_internal _is_required _is_silent _no_cmake_path _no_cma set(_pkg_check_modules_pkg_ver) endif() - # handle the operands - if (_pkg_check_modules_pkg_op STREQUAL ">=") - list(APPEND _pkg_check_modules_exist_query --atleast-version) - endif() - - if (_pkg_check_modules_pkg_op STREQUAL "=") - list(APPEND _pkg_check_modules_exist_query --exact-version) - endif() + _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_VERSION) + _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_PREFIX) + _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_INCLUDEDIR) + _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_LIBDIR) - if (_pkg_check_modules_pkg_op STREQUAL "<=") - list(APPEND _pkg_check_modules_exist_query --max-version) - endif() + list(APPEND _pkg_check_modules_packages "${_pkg_check_modules_pkg_name}") # create the final query which is of the format: - # * --atleast-version - # * --exact-version - # * --max-version + # * >= + # * = + # * <= # * --exists + list(APPEND _pkg_check_modules_exist_query --print-errors --short-errors) if (_pkg_check_modules_pkg_op) - list(APPEND _pkg_check_modules_exist_query "${_pkg_check_modules_pkg_ver}") + list(APPEND _pkg_check_modules_exist_query "${_pkg_check_modules_pkg_name} ${_pkg_check_modules_pkg_op} ${_pkg_check_modules_pkg_ver}") else() list(APPEND _pkg_check_modules_exist_query --exists) + list(APPEND _pkg_check_modules_exist_query "${_pkg_check_modules_pkg_name}") endif() - list(APPEND _pkg_check_modules_exist_query --print-errors --short-errors) - - _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_VERSION) - _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_PREFIX) - _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_INCLUDEDIR) - _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_LIBDIR) - - list(APPEND _pkg_check_modules_exist_query "${_pkg_check_modules_pkg_name}") - list(APPEND _pkg_check_modules_packages "${_pkg_check_modules_pkg_name}") # execute the query execute_process( diff --git a/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.bat b/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.bat index f2f86b0..b038370 100755 --- a/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.bat +++ b/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.bat @@ -1,7 +1,11 @@ @ECHO OFF + +:LOOP + IF "%1"=="" ( EXIT /B 255 ) + IF "%1"=="--version" ( ECHO 0.0-cmake-dummy EXIT /B 0 @@ -13,6 +17,11 @@ IF "%1"=="--exists" ( ECHO Found: %PKG_CONFIG_PATH% IF NOT "%*"=="%PKG_CONFIG_PATH%" ( EXIT /B 1 + ) ELSE ( + EXIT /B 0 ) ) -EXIT /B 0 +SHIFT +IF NOT "%~1"=="" GOTO LOOP + +EXIT /B 255 diff --git a/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.sh b/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.sh index abe14bf..56bba30 100755 --- a/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.sh +++ b/Tests/RunCMake/FindPkgConfig/dummy-pkg-config.sh @@ -4,18 +4,20 @@ # to the --exists argument with the PKG_CONFIG_PATH environment variable # and returns 1 if they are different. -case $1 in - --version) - echo "0.0-cmake-dummy" - ;; - --exists) - shift - eval last=\${$#} - echo "Expected: ${last}" - echo "Found: ${PKG_CONFIG_PATH}" - [ "${last}" = "${PKG_CONFIG_PATH}" ] || exit 1 - ;; - *) - exit 255 - ;; -esac +while [ $# -gt 0 ]; do + case $1 in + --version) + echo "0.0-cmake-dummy" + exit 0 + ;; + --exists) + shift + eval last=\${$#} + echo "Expected: ${last}" + echo "Found: ${PKG_CONFIG_PATH}" + [ "${last}" = "${PKG_CONFIG_PATH}" ] && exit 0 || exit 1 + ;; + esac + shift +done +exit 255 ----------------------------------------------------------------------- Summary of changes: Modules/FindPkgConfig.cmake | 35 +++++++-------------- Tests/RunCMake/FindPkgConfig/dummy-pkg-config.bat | 11 ++++++- Tests/RunCMake/FindPkgConfig/dummy-pkg-config.sh | 32 ++++++++++--------- 3 files changed, 38 insertions(+), 40 deletions(-) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 28 11:36:55 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 28 Feb 2017 11:36:55 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-645-g29c967e Message-ID: <20170228163655.71A39FA7C3@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 29c967ef21bf0248e965cac171cfa2fb51fbaf1c (commit) via 44d3cdc45b83c0cdca61513022f36f2dcc569169 (commit) via 8dc32b8b86c65c3ab201f22c3bf3570a72513355 (commit) via 434492e3c038d2fe18442c8f43daa3078b3cd58c (commit) from 126c84a4bb4122c67839f60dba1a0877ff0234c0 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=29c967ef21bf0248e965cac171cfa2fb51fbaf1c commit 29c967ef21bf0248e965cac171cfa2fb51fbaf1c Merge: 126c84a 44d3cdc Author: Brad King AuthorDate: Tue Feb 28 11:36:53 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 28 11:36:53 2017 -0500 Merge topic 'csproj_add_free_source_tags' into next 44d3cdc4 VS: add test for VS_CSHARP_* source file property 8dc32b8b VS: add CSharpUtilities module 434492e3 VS: add VS_CSHARP_ sourcefile property https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=44d3cdc45b83c0cdca61513022f36f2dcc569169 commit 44d3cdc45b83c0cdca61513022f36f2dcc569169 Author: Michael St?rmer AuthorDate: Fri Feb 24 09:28:13 2017 +0100 Commit: Brad King CommitDate: Tue Feb 28 10:55:45 2017 -0500 VS: add test for VS_CSHARP_* source file property diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 7848dca..7f270db 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -735,7 +735,7 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup() if (!value.empty()) { this->WriteString("<", 3); (*this->BuildFileStream) << tagName << ">"; - (*this->BuildFileStream) << value; + (*this->BuildFileStream) << cmVS10EscapeXML(value); (*this->BuildFileStream) << "\n"; } } diff --git a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake index bc1ec97..3af877f 100644 --- a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake +++ b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake @@ -3,3 +3,4 @@ run_cmake(VsConfigurationType) run_cmake(VsTargetsFileReferences) run_cmake(VsCustomProps) run_cmake(VsDebuggerWorkingDir) +run_cmake(VsCSharpCustomTags) diff --git a/Tests/RunCMake/VS10Project/VsCSharpCustomTags-check.cmake b/Tests/RunCMake/VS10Project/VsCSharpCustomTags-check.cmake new file mode 100644 index 0000000..70ea193 --- /dev/null +++ b/Tests/RunCMake/VS10Project/VsCSharpCustomTags-check.cmake @@ -0,0 +1,23 @@ +set(csProjectFile "${RunCMake_TEST_BINARY_DIR}/foo.csproj") +if(NOT EXISTS "${csProjectFile}") + set(RunCMake_TEST_FAILED "Project file ${csProjectFile} does not exist.") + return() +endif() + +set(tagFound FALSE) + +set(tagName "MyCustomTag") +set(tagValue "MyCustomValue") + +file(STRINGS "${csProjectFile}" lines) +foreach(line IN LISTS lines) + if(line MATCHES "^ *<${tagName}>${tagValue}") + message(STATUS "foo.csproj has tag ${tagName} with value ${tagValue} defined") + set(tagFound TRUE) + endif() +endforeach() + +if(NOT tagFound) + set(RunCMake_TEST_FAILED "Source file tag ${tagName} with value ${tagValue} not found.") + return() +endif() diff --git a/Tests/RunCMake/VS10Project/VsCSharpCustomTags.cmake b/Tests/RunCMake/VS10Project/VsCSharpCustomTags.cmake new file mode 100644 index 0000000..c51e9c3 --- /dev/null +++ b/Tests/RunCMake/VS10Project/VsCSharpCustomTags.cmake @@ -0,0 +1,11 @@ +enable_language(CSharp) +add_library(foo foo.cs) + +set(props_file "${CMAKE_CURRENT_SOURCE_DIR}/my.props") + +set(tagName "MyCustomTag") +set(tagValue "MyCustomValue") + +set_source_files_properties(foo.cs + PROPERTIES + VS_CSHARP_${tagName} "${tagValue}") diff --git a/Tests/RunCMake/VS10Project/foo.cs b/Tests/RunCMake/VS10Project/foo.cs new file mode 100644 index 0000000..3695dc9 --- /dev/null +++ b/Tests/RunCMake/VS10Project/foo.cs @@ -0,0 +1,3 @@ +void foo() +{ +} https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8dc32b8b86c65c3ab201f22c3bf3570a72513355 commit 8dc32b8b86c65c3ab201f22c3bf3570a72513355 Author: Michael St?rmer AuthorDate: Thu Feb 23 16:49:37 2017 +0100 Commit: Brad King CommitDate: Tue Feb 28 10:55:45 2017 -0500 VS: add CSharpUtilities module diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst index 2dd56c7..5e96d79 100644 --- a/Help/manual/cmake-modules.7.rst +++ b/Help/manual/cmake-modules.7.rst @@ -66,6 +66,7 @@ All Modules /module/CPackRPM /module/CPack /module/CPackWIX + /module/CSharpUtilities /module/CTest /module/CTestCoverageCollectGCOV /module/CTestScriptMode diff --git a/Help/module/CSharpUtilities.rst b/Help/module/CSharpUtilities.rst new file mode 100644 index 0000000..3621bbc --- /dev/null +++ b/Help/module/CSharpUtilities.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../Modules/CSharpUtilities.cmake diff --git a/Help/release/dev/CSharpUtilities.rst b/Help/release/dev/CSharpUtilities.rst new file mode 100644 index 0000000..e33bd88 --- /dev/null +++ b/Help/release/dev/CSharpUtilities.rst @@ -0,0 +1,7 @@ +CSharpUtilities +--------------- + +* A new :module:`CSharpUtilities` module was added to make parameterization + of Visual Studio CSharp targets easier and more flexible. Provided functions + allow automated setting of source file properties to support Windows Forms, + WPF/XAML or other technologies as needed. diff --git a/Modules/CSharpUtilities.cmake b/Modules/CSharpUtilities.cmake new file mode 100644 index 0000000..ddad85a --- /dev/null +++ b/Modules/CSharpUtilities.cmake @@ -0,0 +1,298 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +CSharpUtilities +--------------- + +Functions to make configuration of CSharp/.NET targets easier. + +A collection of CMake utility functions useful for dealing with CSharp +targets for Visual Studio generators from version 2010 and later. + +The following functions are provided by this module: + +**Main functions** + +- :command:`csharp_set_windows_forms_properties` +- :command:`csharp_set_designer_cs_properties` +- :command:`csharp_set_xaml_cs_properties` + +**Helper functions** + +- :command:`csharp_get_filename_keys` +- :command:`csharp_get_filename_key_base` +- :command:`csharp_get_dependentupon_name` + +Main functions provided by the module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. command:: csharp_set_windows_forms_properties + + Sets source file properties for use of Windows Forms. Use this, if your CSharp + target uses windows forms:: + + csharp_set_windows_forms_properties([ [ [...]]]) + + ```` + List of all source files which are relevant for setting the + :prop_sf:`VS_CSHARP_` properties (including ``.cs``, ``.resx`` and + ``.Designer.cs`` extensions). + + In the list of all given files for all files ending with ``.Designer.cs`` and + ``.resx`` is searched. For every *designer* or *resource* file a file with the + same base name but only ``.cs`` as extension is searched. If this is found, the + :prop_sf:`VS_CSHARP_` properties are set as follows: + + for the **.cs** file: + - VS_CSHARP_SubType "Form" + + for the **.Designer.cs** file (if it exists): + - VS_CSHARP_DependentUpon + - VS_CSHARP_DesignTime "" (delete tag if previously defined) + - VS_CSHARP_AutoGen ""(delete tag if previously defined) + + for the **.resx** file (if it exists): + - VS_RESOURCE_GENERATOR "" (delete tag if previously defined) + - VS_CSHARP_DependentUpon + - VS_CSHARP_SubType "Designer" + +.. command:: csharp_set_designer_cs_properties + + Sets source file properties for use of WPF/XAML. Use this, if your CSharp + target uses WPF/XAML:: + + csharp_set_designer_cs_properties([ [ [...]]]) + + ```` + List of all source files which are relevant for setting the + :prop_sf:`VS_CSHARP_` properties (including ``.cs``, + ``.resx``, ``.settings`` and ``.Designer.cs`` extensions). + + In the list of all given files for all files ending with + ``.Designer.cs`` is searched. For every *designer* file all files + with the same base name but different extensions are searched. If + a match is found, the source file properties of the *designer* file + are set depending on the extension of the matched file: + + if match is **.resx** file: + - VS_CSHARP_AutoGen "True" + - VS_CSHARP_DesignTime "True" + - VS_CSHARP_DependentUpon + + if match is **.cs** file: + - VS_CSHARP_DependentUpon + + if match is **.settings** file: + - VS_CSHARP_AutoGen "True" + - VS_CSHARP_DesignTimeSharedInput "True" + - VS_CSHARP_DependentUpon + +.. command:: csharp_set_xaml_cs_properties + + Sets source file properties for use of WPF/XAML. Use this, if your + CSharp target uses WPF/XAML:: + + csharp_set_xaml_cs_properties([ [ [...]]]) + + ```` + List of all source files which are relevant for setting the + :prop_sf:`VS_CSHARP_` properties (including ``.cs``, + ``.xaml``, and ``.xaml.cs`` extensions). + + In the list of all given files for all files ending with + ``.xaml.cs`` is searched. For every xaml file, a file + with the same base name but extension ``.xaml`` is searched. + If a match is found, the source file properties of the ``.xaml.cs`` + file are set: + + - VS_CSHARP_DependentUpon + +Helper functions which are used by the above ones +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. command:: csharp_get_filename_keys + + Helper function which computes a list of key values to identify + source files independently of relative/absolute paths given in cmake + and eliminates case sensitivity:: + + csharp_get_filename_keys(OUT [ [ [...]]]) + + ``OUT`` + name of the variable in which the list of keys is stored + + ```` + filename as given to to CSharp target using :command:`add_library` + or :command:`add_executable` + + In some way the function applies a canonicalization to the source names. + This is necessary to find file matches if the files have been added to + the target with different directory prefixes: + + .. code-block:: cmake + + add_library(lib + myfile.cs + ${CMAKE_CURRENT_SOURCE_DIR}/myfile.Designer.cs) + + set_source_files_properties(myfile.Designer.cs PROPERTIES + VS_CSHARP_DependentUpon myfile.cs) + + # this will fail, because in cmake + # - ${CMAKE_CURRENT_SOURCE_DIR}/myfile.Designer.cs + # - myfile.Designer.cs + # are not the same source file. The source file property is not set. + +.. command:: csharp_get_filename_key_base + + Returns the full filepath and name **withouth** extension of a key. + KEY is expected to be a key from csharp_get_filename_keys. In BASE + the value of KEY without the file extension is returned:: + + csharp_get_filename_key_base(BASE KEY) + + ``BASE`` + The computed "base" of ``KEY``. + + ``KEY`` + The key of which the base will be computed. Expected to be a + upper case full filename. + +.. command:: csharp_get_dependentupon_name + + Computes a string which can be used as value for the source file property + :prop_sf:`VS_CSHARP_` with *target* being ``DependentUpon``:: + + csharp_get_dependentupon_name(NAME FILE) + + ``NAME`` + result value + + ``FILE`` + filename to convert to DependentUpon value + + Actually this is only the filename without any path given at the moment. + +#]=======================================================================] + +function(csharp_get_filename_keys OUT) + set(${OUT} "") + foreach(f ${ARGN}) + get_filename_component(f ${f} REALPATH) + string(TOUPPER ${f} f) + list(APPEND ${OUT} ${f}) + endforeach() + set(${OUT} "${${OUT}}" PARENT_SCOPE) +endfunction() + +function(csharp_get_filename_key_base base key) + get_filename_component(dir ${key} DIRECTORY) + get_filename_component(fil ${key} NAME_WE) + set(${base} "${dir}/${fil}" PARENT_SCOPE) +endfunction() + +function(csharp_get_dependentupon_name out in) + get_filename_component(${out} ${in} NAME) + set(${out} ${${out}} PARENT_SCOPE) +endfunction() + +function(csharp_set_windows_forms_properties) + csharp_get_filename_keys(fileKeys ${ARGN}) + foreach(key ${fileKeys}) + get_filename_component(ext ${key} EXT) + if(${ext} STREQUAL ".DESIGNER.CS" OR + ${ext} STREQUAL ".RESX") + csharp_get_filename_key_base(NAME_BASE ${key}) + list(FIND fileKeys "${NAME_BASE}.CS" FILE_INDEX) + if(NOT ${FILE_INDEX} EQUAL -1) + list(GET ARGN ${FILE_INDEX} FILE_NAME) + # set properties of main form file + set_source_files_properties("${FILE_NAME}" + PROPERTIES + VS_CSHARP_SubType "Form") + csharp_get_dependentupon_name(LINK "${FILE_NAME}") + # set properties of designer file (if found) + list(FIND fileKeys "${NAME_BASE}.DESIGNER.CS" FILE_INDEX) + if(NOT ${FILE_INDEX} EQUAL -1) + list(GET ARGN ${FILE_INDEX} FILE_NAME) + set_source_files_properties("${FILE_NAME}" + PROPERTIES + VS_CSHARP_DependentUpon "${LINK}" + VS_CSHARP_DesignTime "" + VS_CSHARP_AutoGen "") + endif() + # set properties of corresponding resource file (if found) + list(FIND fileKeys "${NAME_BASE}.RESX" FILE_INDEX) + if(NOT ${FILE_INDEX} EQUAL -1) + list(GET ARGN ${FILE_INDEX} FILE_NAME) + set_source_files_properties("${FILE_NAME}" + PROPERTIES + VS_RESOURCE_GENERATOR "" + VS_CSHARP_DependentUpon "${LINK}" + VS_CSHARP_SubType "Designer") + endif() + endif() + endif() + endforeach() +endfunction() + +function(csharp_set_designer_cs_properties) + csharp_get_filename_keys(fileKeys ${ARGN}) + set(INDEX -1) + foreach(key ${fileKeys}) + math(EXPR INDEX "${INDEX}+1") + list(GET ARGN ${INDEX} source) + get_filename_component(ext ${key} EXT) + if(${ext} STREQUAL ".DESIGNER.CS") + csharp_get_filename_key_base(NAME_BASE ${key}) + if("${NAME_BASE}.RESX" IN_LIST fileKeys) + list(FIND fileKeys "${NAME_BASE}.RESX" FILE_INDEX) + list(GET ARGN ${FILE_INDEX} FILE_NAME) + csharp_get_dependentupon_name(LINK "${FILE_NAME}") + set_source_files_properties("${source}" + PROPERTIES + VS_CSHARP_AutoGen "True" + VS_CSHARP_DesignTime "True" + VS_CSHARP_DependentUpon "${LINK}") + elseif("${NAME_BASE}.CS" IN_LIST fileKeys) + list(FIND fileKeys "${NAME_BASE}.CS" FILE_INDEX) + list(GET ARGN ${FILE_INDEX} FILE_NAME) + csharp_get_dependentupon_name(LINK "${FILE_NAME}") + set_source_files_properties("${source}" + PROPERTIES + VS_CSHARP_DependentUpon "${LINK}") + elseif("${NAME_BASE}.SETTINGS" IN_LIST fileKeys) + list(FIND fileKeys "${NAME_BASE}.SETTINGS" FILE_INDEX) + list(GET ARGN ${FILE_INDEX} FILE_NAME) + csharp_get_dependentupon_name(LINK "${FILE_NAME}") + set_source_files_properties("${source}" + PROPERTIES + VS_CSHARP_AutoGen "True" + VS_CSHARP_DesignTimeSharedInput "True" + VS_CSHARP_DependentUpon "${LINK}") + endif() + endif() + endforeach() +endfunction() + +function(csharp_set_xaml_cs_properties) + csharp_get_filename_keys(fileKeys ${ARGN}) + set(INDEX -1) + foreach(key ${fileKeys}) + math(EXPR INDEX "${INDEX}+1") + list(GET ARGN ${INDEX} source) + get_filename_component(ext ${key} EXT) + if(${ext} STREQUAL ".XAML.CS") + csharp_get_filename_key_base(NAME_BASE ${key}) + if("${NAME_BASE}.XAML" IN_LIST fileKeys) + list(FIND fileKeys "${NAME_BASE}.XAML" FILE_INDEX) + list(GET ARGN ${FILE_INDEX} FILE_NAME) + csharp_get_dependentupon_name(LINK "${FILE_NAME}") + set_source_files_properties("${source}" + PROPERTIES + VS_CSHARP_DependentUpon "${LINK}") + endif() + endif() + endforeach() +endfunction() https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=434492e3c038d2fe18442c8f43daa3078b3cd58c commit 434492e3c038d2fe18442c8f43daa3078b3cd58c Author: Michael St?rmer AuthorDate: Thu Feb 23 16:48:16 2017 +0100 Commit: Brad King CommitDate: Mon Feb 27 13:06:38 2017 -0500 VS: add VS_CSHARP_ sourcefile property diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 5fad10c..ac21d48 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -367,6 +367,7 @@ Properties on Source Files /prop_sf/SKIP_AUTOUIC /prop_sf/SYMBOLIC /prop_sf/VS_COPY_TO_OUT_DIR + /prop_sf/VS_CSHARP_tagname /prop_sf/VS_DEPLOYMENT_CONTENT /prop_sf/VS_DEPLOYMENT_LOCATION /prop_sf/VS_INCLUDE_IN_VSIX diff --git a/Help/prop_sf/VS_CSHARP_tagname.rst b/Help/prop_sf/VS_CSHARP_tagname.rst new file mode 100644 index 0000000..d42159f --- /dev/null +++ b/Help/prop_sf/VS_CSHARP_tagname.rst @@ -0,0 +1,19 @@ +VS_CSHARP_ +------------------- + +Visual Studio and CSharp source-file-specific configuration. + +Tell the Visual Studio generator to set the source file tag +```` to a given value in the generated Visual Studio CSharp +project. Ignored on other generators and languages. This property +can be used to define dependencies between source files or set any +other Visual Studio specific parameters. + +Example usage: + +.. code-block:: cmake + + set_source_files_property( + PROPERTIES + VS_CSHARP_DependentUpon + VS_CSHARP_SubType "Form") diff --git a/Help/release/dev/VS_CSHARP_tagname.rst b/Help/release/dev/VS_CSHARP_tagname.rst new file mode 100644 index 0000000..3fce83d --- /dev/null +++ b/Help/release/dev/VS_CSHARP_tagname.rst @@ -0,0 +1,6 @@ +VS_CSHARP_ +------------------- + +* :ref:`Visual Studio Generators` for VS 2010 and above learned a + new :prop_sf:`VS_CSHARP_` source file property to specify + custom ``.csproj`` content for source files. diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h index b193f65..bbcc300 100644 --- a/Source/cmSourceFile.h +++ b/Source/cmSourceFile.h @@ -86,6 +86,7 @@ public: // Get the properties cmPropertyMap& GetProperties() { return this->Properties; } + const cmPropertyMap& GetProperties() const { return this->Properties; } /** * Check whether the given source file location could refer to this diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index e3853ed..7848dca 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -706,20 +706,40 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup() if (const char* g = (*oi)->GetProperty("VS_RESOURCE_GENERATOR")) { generator = g; } - this->WriteString("", 3); - (*this->BuildFileStream) << cmVS10EscapeXML(generator) - << "\n"; - if (designerResource.find(srcDir) == 0) { - designerResource = designerResource.substr(srcDir.length() + 1); - } else if (designerResource.find(binDir) == 0) { - designerResource = designerResource.substr(binDir.length() + 1); - } else { - designerResource = - cmsys::SystemTools::GetFilenameName(designerResource); + if (!generator.empty()) { + this->WriteString("", 3); + (*this->BuildFileStream) << cmVS10EscapeXML(generator) + << "\n"; + if (designerResource.find(srcDir) == 0) { + designerResource = designerResource.substr(srcDir.length() + 1); + } else if (designerResource.find(binDir) == 0) { + designerResource = designerResource.substr(binDir.length() + 1); + } else { + designerResource = + cmsys::SystemTools::GetFilenameName(designerResource); + } + this->ConvertToWindowsSlash(designerResource); + this->WriteString("", 3); + (*this->BuildFileStream) << designerResource + << "\n"; + } + } + const cmPropertyMap& props = (*oi)->GetProperties(); + for (cmPropertyMap::const_iterator p = props.begin(); p != props.end(); + ++p) { + static const std::string propNamePrefix = "VS_CSHARP_"; + if (p->first.find(propNamePrefix.c_str()) == 0) { + std::string tagName = p->first.substr(propNamePrefix.length()); + if (!tagName.empty()) { + std::string value = props.GetPropertyValue(p->first); + if (!value.empty()) { + this->WriteString("<", 3); + (*this->BuildFileStream) << tagName << ">"; + (*this->BuildFileStream) << value; + (*this->BuildFileStream) << "\n"; + } + } } - this->ConvertToWindowsSlash(designerResource); - this->WriteString("", 3); - (*this->BuildFileStream) << designerResource << "\n"; } } @@ -1968,42 +1988,21 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( sourceFileTags["Link"] = link; } } - // check if file is a generated .Designer.cs or .xaml.cs file - // to add additional necessary tags - const std::string fileExtension = - cmsys::SystemTools::GetFilenameExtension(f); - if (fileExtension == ".Designer.cs" || fileExtension == ".xaml.cs") { - f = f.substr(0, f.length() - fileExtension.length()); - if (sourceFileTags.find("Link") == sourceFileTags.end() && - !this->InSourceBuild) { - // add link fallback - sourceFileTags["Link"] = - cmsys::SystemTools::GetFilenameName(f) + fileExtension; - } - std::vector extensions; - extensions.push_back(".resx"); - extensions.push_back(".settings"); - extensions.push_back(".xaml"); - extensions.push_back(".cs"); - std::string dependencyExtension; - for (std::vector::iterator i = extensions.begin(); - i != extensions.end(); ++i) { - if (cmsys::SystemTools::FileExists(f + *i)) { - dependencyExtension = *i; - // There should never be more than one match. Otherwise - // one cannot tell on which match the file depends. - break; + const cmPropertyMap& props = sf.GetProperties(); + for (cmPropertyMap::const_iterator p = props.begin(); p != props.end(); + ++p) { + static const std::string propNamePrefix = "VS_CSHARP_"; + if (p->first.find(propNamePrefix.c_str()) == 0) { + std::string tagName = p->first.substr(propNamePrefix.length()); + if (!tagName.empty()) { + const std::string val = props.GetPropertyValue(p->first); + if (!val.empty()) { + sourceFileTags[tagName] = val; + } else { + sourceFileTags.erase(tagName); + } } } - if (dependencyExtension == ".resx") { - sourceFileTags["DesignTime"] = "True"; - sourceFileTags["AutoGen"] = "True"; - } else if (dependencyExtension == ".settings") { - sourceFileTags["DesignTimeSharedInput"] = "True"; - sourceFileTags["AutoGen"] = "True"; - } - sourceFileTags["DependentUpon"] = - cmsys::SystemTools::GetFilenameName(f) + dependencyExtension; } // write source file specific tags if (!sourceFileTags.empty()) { ----------------------------------------------------------------------- Summary of changes: Help/manual/cmake-modules.7.rst | 1 + Help/manual/cmake-properties.7.rst | 1 + Help/module/CSharpUtilities.rst | 1 + Help/prop_sf/VS_CSHARP_tagname.rst | 19 ++ Help/release/dev/CSharpUtilities.rst | 7 + Help/release/dev/VS_CSHARP_tagname.rst | 6 + Modules/CSharpUtilities.cmake | 298 ++++++++++++++++++++ Source/cmSourceFile.h | 1 + Source/cmVisualStudio10TargetGenerator.cxx | 93 +++--- Tests/RunCMake/VS10Project/RunCMakeTest.cmake | 1 + .../VS10Project/VsCSharpCustomTags-check.cmake | 23 ++ .../RunCMake/VS10Project/VsCSharpCustomTags.cmake | 11 + .../foo.cpp => RunCMake/VS10Project/foo.cs} | 0 13 files changed, 415 insertions(+), 47 deletions(-) create mode 100644 Help/module/CSharpUtilities.rst create mode 100644 Help/prop_sf/VS_CSHARP_tagname.rst create mode 100644 Help/release/dev/CSharpUtilities.rst create mode 100644 Help/release/dev/VS_CSHARP_tagname.rst create mode 100644 Modules/CSharpUtilities.cmake create mode 100644 Tests/RunCMake/VS10Project/VsCSharpCustomTags-check.cmake create mode 100644 Tests/RunCMake/VS10Project/VsCSharpCustomTags.cmake copy Tests/{CTestCoverageCollectGCOV/TestProject/3rdparty/foo.cpp => RunCMake/VS10Project/foo.cs} (100%) hooks/post-receive -- CMake From brad.king at kitware.com Tue Feb 28 15:23:27 2017 From: brad.king at kitware.com (Brad King) Date: Tue, 28 Feb 2017 15:23:27 -0500 (EST) Subject: [Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-648-g0412b80 Message-ID: <20170228202328.04FA3F9C41@public.kitware.com> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "CMake". The branch, next has been updated via 0412b809f4d426ad1826c10e7f4b2d172906b0ee (commit) via 6f5aede71642b05a351d5cf92e0c884ed9b4fd3c (commit) via e67963ed7316768bf0ebfbe42137d028c0d1d2a4 (commit) from 29c967ef21bf0248e965cac171cfa2fb51fbaf1c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0412b809f4d426ad1826c10e7f4b2d172906b0ee commit 0412b809f4d426ad1826c10e7f4b2d172906b0ee Merge: 29c967e 6f5aede Author: Brad King AuthorDate: Tue Feb 28 15:23:21 2017 -0500 Commit: CMake Topic Stage CommitDate: Tue Feb 28 15:23:21 2017 -0500 Merge topic 'find-libarch-not-symlink' into next 6f5aede7 find_library: Skip 'lib => lib' searches if one symlinks the other e67963ed cmFindLibraryCommand: Refactor AddArchitecturePath logic https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6f5aede71642b05a351d5cf92e0c884ed9b4fd3c commit 6f5aede71642b05a351d5cf92e0c884ed9b4fd3c Author: Brad King AuthorDate: Tue Feb 28 13:51:35 2017 -0500 Commit: Brad King CommitDate: Tue Feb 28 14:56:54 2017 -0500 find_library: Skip 'lib => lib' searches if one symlinks the other The `FIND_LIBRARY_USE_LIB_PATHS` global properties ask `find_library` to look in `lib` directories automatically before corresponding `lib` directories. However, if `lib` is just a symlink to `lib` (or vice-versa) then we should skip adding the `lib` path. Such symlinks typically only exist to satisfy software that expects the `lib` path to be available. Fixes: #16687 diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx index 58d92aa..412d573 100644 --- a/Source/cmFindLibraryCommand.cxx +++ b/Source/cmFindLibraryCommand.cxx @@ -72,6 +72,18 @@ void cmFindLibraryCommand::AddArchitecturePaths(const char* suffix) } } +static bool cmLibDirsLinked(std::string const& l, std::string const& r) +{ + // Compare the real paths of the two directories. + // Since our caller only changed the trailing component of each + // directory, the real paths can be the same only if at least one of + // the trailing components is a symlink. Use this as an optimization + // to avoid excessive realpath calls. + return (cmSystemTools::FileIsSymlink(l) || + cmSystemTools::FileIsSymlink(r)) && + cmSystemTools::GetRealPath(l) == cmSystemTools::GetRealPath(r); +} + void cmFindLibraryCommand::AddArchitecturePath( std::string const& dir, std::string::size_type start_pos, const char* suffix, bool fresh) @@ -87,6 +99,11 @@ void cmFindLibraryCommand::AddArchitecturePath( std::string libX = lib + suffix; bool use_libX = cmSystemTools::FileIsDirectory(libX); + // Avoid copies of the same directory due to symlinks. + if (use_libX && use_lib && cmLibDirsLinked(libX, lib)) { + use_libX = false; + } + if (use_libX) { libX += dir.substr(pos + 3); std::string::size_type libX_pos = pos + 3 + strlen(suffix) + 1; @@ -106,6 +123,11 @@ void cmFindLibraryCommand::AddArchitecturePath( std::string dirX = dir + suffix; bool use_dirX = cmSystemTools::FileIsDirectory(dirX); + // Avoid copies of the same directory due to symlinks. + if (use_dirX && use_dir && cmLibDirsLinked(dirX, dir)) { + use_dirX = false; + } + if (use_dirX) { dirX += "/"; this->SearchPaths.push_back(dirX); diff --git a/Tests/RunCMake/find_library/LibArchLink-stderr.txt b/Tests/RunCMake/find_library/LibArchLink-stderr.txt new file mode 100644 index 0000000..139e077 --- /dev/null +++ b/Tests/RunCMake/find_library/LibArchLink-stderr.txt @@ -0,0 +1,2 @@ +TOP_LIBRARY='[^']*/Tests/RunCMake/find_library/LibArchLink-build/lib/libtop.a' +SUB_LIBRARY='[^']*/Tests/RunCMake/find_library/LibArchLink-build/lib/sub/libsub.a' diff --git a/Tests/RunCMake/find_library/LibArchLink.cmake b/Tests/RunCMake/find_library/LibArchLink.cmake new file mode 100644 index 0000000..c91381d --- /dev/null +++ b/Tests/RunCMake/find_library/LibArchLink.cmake @@ -0,0 +1,24 @@ +set(CMAKE_SIZEOF_VOID_P 4) +set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB32_PATHS ON) +list(APPEND CMAKE_FIND_LIBRARY_PREFIXES lib) +list(APPEND CMAKE_FIND_LIBRARY_SUFFIXES .a) + +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib) +execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink lib ${CMAKE_CURRENT_BINARY_DIR}/lib32) +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib/libtop.a" "top") +find_library(TOP_LIBRARY + NAMES top + PATHS ${CMAKE_CURRENT_BINARY_DIR}/lib + NO_DEFAULT_PATH + ) +message("TOP_LIBRARY='${TOP_LIBRARY}'") + +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib/sub) +execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink . ${CMAKE_CURRENT_BINARY_DIR}/lib/sub/32) +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib/sub/libsub.a" "sub") +find_library(SUB_LIBRARY + NAMES sub + PATHS ${CMAKE_CURRENT_BINARY_DIR}/lib/sub + NO_DEFAULT_PATH + ) +message("SUB_LIBRARY='${SUB_LIBRARY}'") diff --git a/Tests/RunCMake/find_library/RunCMakeTest.cmake b/Tests/RunCMake/find_library/RunCMakeTest.cmake index 5733965..e7e8db3 100644 --- a/Tests/RunCMake/find_library/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_library/RunCMakeTest.cmake @@ -1,6 +1,9 @@ include(RunCMake) run_cmake(Created) +if(CMAKE_HOST_UNIX) + run_cmake(LibArchLink) +endif() if(WIN32 OR CYGWIN) run_cmake(PrefixInPATH) endif() https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e67963ed7316768bf0ebfbe42137d028c0d1d2a4 commit e67963ed7316768bf0ebfbe42137d028c0d1d2a4 Author: Brad King AuthorDate: Tue Feb 28 11:30:14 2017 -0500 Commit: Brad King CommitDate: Tue Feb 28 14:56:13 2017 -0500 cmFindLibraryCommand: Refactor AddArchitecturePath logic Use boolean variables to save results and rename variables to more closely represent their roles. diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx index 082350f..58d92aa 100644 --- a/Source/cmFindLibraryCommand.cxx +++ b/Source/cmFindLibraryCommand.cxx @@ -77,31 +77,41 @@ void cmFindLibraryCommand::AddArchitecturePath( bool fresh) { std::string::size_type pos = dir.find("lib/", start_pos); + if (pos != std::string::npos) { - std::string cur_dir = dir.substr(0, pos + 3); - - // Follow "lib". - std::string next_dir = cur_dir + suffix; - if (cmSystemTools::FileIsDirectory(next_dir)) { - next_dir += dir.substr(pos + 3); - std::string::size_type next_pos = pos + 3 + strlen(suffix) + 1; - this->AddArchitecturePath(next_dir, next_pos, suffix); + // Check for "lib". + std::string lib = dir.substr(0, pos + 3); + bool use_lib = cmSystemTools::FileIsDirectory(lib); + + // Check for "lib" and use it first. + std::string libX = lib + suffix; + bool use_libX = cmSystemTools::FileIsDirectory(libX); + + if (use_libX) { + libX += dir.substr(pos + 3); + std::string::size_type libX_pos = pos + 3 + strlen(suffix) + 1; + this->AddArchitecturePath(libX, libX_pos, suffix); } - // Follow "lib". - if (cmSystemTools::FileIsDirectory(cur_dir)) { + if (use_lib) { this->AddArchitecturePath(dir, pos + 3 + 1, suffix, false); } } + if (fresh) { - // Check for /. - std::string cur_dir = dir + suffix + "/"; - if (cmSystemTools::FileIsDirectory(cur_dir)) { - this->SearchPaths.push_back(cur_dir); + // Check for the original unchanged path. + bool use_dir = cmSystemTools::FileIsDirectory(dir); + + // Check for / and use it first. + std::string dirX = dir + suffix; + bool use_dirX = cmSystemTools::FileIsDirectory(dirX); + + if (use_dirX) { + dirX += "/"; + this->SearchPaths.push_back(dirX); } - // Now add the original unchanged path - if (cmSystemTools::FileIsDirectory(dir)) { + if (use_dir) { this->SearchPaths.push_back(dir); } } ----------------------------------------------------------------------- Summary of changes: Source/cmFindLibraryCommand.cxx | 64 +++++++++++++++----- Tests/RunCMake/find_library/LibArchLink-stderr.txt | 2 + Tests/RunCMake/find_library/LibArchLink.cmake | 24 ++++++++ Tests/RunCMake/find_library/RunCMakeTest.cmake | 3 + 4 files changed, 77 insertions(+), 16 deletions(-) create mode 100644 Tests/RunCMake/find_library/LibArchLink-stderr.txt create mode 100644 Tests/RunCMake/find_library/LibArchLink.cmake hooks/post-receive -- CMake