summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.clang-format2
-rw-r--r--Copyright.txt1
-rw-r--r--Help/command/ctest_start.rst89
-rw-r--r--Help/command/file.rst319
-rw-r--r--Help/command/install.rst42
-rw-r--r--Help/command/list.rst82
-rw-r--r--Help/command/string.rst111
-rw-r--r--Help/command/target_link_libraries.rst2
-rw-r--r--Help/manual/OPTIONS_BUILD.txt2
-rw-r--r--Help/manual/cmake-modules.7.rst2
-rw-r--r--Help/manual/cmake-properties.7.rst2
-rw-r--r--Help/manual/cmake-variables.7.rst1
-rw-r--r--Help/module/CPackNuGet.rst1
-rw-r--r--Help/module/FindODBC.rst1
-rw-r--r--Help/prop_gbl/ECLIPSE_EXTRA_CPROJECT_CONTENTS.rst12
-rw-r--r--Help/prop_gbl/ECLIPSE_EXTRA_NATURES.rst2
-rw-r--r--Help/prop_sf/COMPILE_FLAGS.rst10
-rw-r--r--Help/prop_sf/COMPILE_OPTIONS.rst4
-rw-r--r--Help/prop_tgt/DOTNET_TARGET_FRAMEWORK_VERSION.rst13
-rw-r--r--Help/prop_tgt/PDB_OUTPUT_DIRECTORY.rst10
-rw-r--r--Help/prop_tgt/PDB_OUTPUT_DIRECTORY_CONFIG.rst3
-rw-r--r--Help/prop_tgt/VS_DOTNET_TARGET_FRAMEWORK_VERSION.rst3
-rw-r--r--Help/release/3.11.rst15
-rw-r--r--Help/release/dev/FindODBC-module.rst5
-rw-r--r--Help/release/dev/FindPkgConfig-LINK_LIBRARIES.rst6
-rw-r--r--Help/release/dev/PDBDirectoryGenExpression.rst5
-rw-r--r--Help/release/dev/copy_directory.rst6
-rw-r--r--Help/release/dev/cpack-nuget.rst7
-rw-r--r--Help/release/dev/ctest-start-args-rework.rst7
-rw-r--r--Help/release/dev/dotnet-target-framework-ver-init.rst11
-rw-r--r--Help/release/dev/subdirectory-linking.rst5
-rw-r--r--Help/variable/CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION.rst16
-rw-r--r--Modules/CMakeCUDAInformation.cmake6
-rw-r--r--Modules/CPack.NuGet.nuspec.in24
-rw-r--r--Modules/CPack.cmake680
-rw-r--r--Modules/CPackNuGet.cmake556
-rw-r--r--Modules/CPackRPM.cmake28
-rw-r--r--Modules/FindBLAS.cmake11
-rw-r--r--Modules/FindBZip2.cmake24
-rw-r--r--Modules/FindBoost.cmake68
-rw-r--r--Modules/FindCUDA.cmake12
-rw-r--r--Modules/FindDoxygen.cmake12
-rw-r--r--Modules/FindJNI.cmake4
-rw-r--r--Modules/FindJPEG.cmake2
-rw-r--r--Modules/FindJava.cmake2
-rw-r--r--Modules/FindLua.cmake134
-rw-r--r--Modules/FindODBC.cmake227
-rw-r--r--Modules/FindPerl.cmake1
-rw-r--r--Modules/FindPkgConfig.cmake47
-rw-r--r--Modules/FindQt4.cmake46
-rw-r--r--Modules/InstallRequiredSystemLibraries.cmake18
-rw-r--r--Modules/Platform/Windows-NVIDIA-CUDA.cmake8
-rw-r--r--Modules/Qt4Macros.cmake25
-rw-r--r--Source/CMakeLists.txt1
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/CPack/cmCPackGeneratorFactory.cxx5
-rw-r--r--Source/CPack/cmCPackNuGetGenerator.cxx140
-rw-r--r--Source/CPack/cmCPackNuGetGenerator.h37
-rw-r--r--Source/CTest/cmCTestLaunch.cxx100
-rw-r--r--Source/CTest/cmCTestLaunch.h12
-rw-r--r--Source/CTest/cmCTestStartCommand.cxx73
-rw-r--r--Source/cmAddLibraryCommand.cxx8
-rw-r--r--Source/cmCTest.cxx60
-rw-r--r--Source/cmCTest.h7
-rw-r--r--Source/cmCustomCommandGenerator.cxx8
-rw-r--r--Source/cmExtraEclipseCDT4Generator.cxx7
-rw-r--r--Source/cmFileCommand.cxx8
-rw-r--r--Source/cmForEachCommand.cxx6
-rw-r--r--Source/cmFunctionCommand.cxx7
-rw-r--r--Source/cmGeneratorTarget.cxx23
-rw-r--r--Source/cmIfCommand.cxx16
-rw-r--r--Source/cmListFileCache.cxx8
-rw-r--r--Source/cmListFileCache.h19
-rw-r--r--Source/cmMacroCommand.cxx6
-rw-r--r--Source/cmMakefile.cxx23
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx13
-rw-r--r--Source/cmQtAutoGenInitializer.cxx3
-rw-r--r--Source/cmRST.cxx68
-rw-r--r--Source/cmRST.h2
-rw-r--r--Source/cmState.cxx10
-rw-r--r--Source/cmState.h4
-rw-r--r--Source/cmSystemTools.cxx26
-rw-r--r--Source/cmTarget.cxx4
-rw-r--r--Source/cmTargetLinkLibrariesCommand.cxx11
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx1395
-rw-r--r--Source/cmVisualStudio10TargetGenerator.h18
-rw-r--r--Source/cmWhileCommand.cxx6
-rw-r--r--Source/cmXMLWriter.h6
-rw-r--r--Source/cmake.h2
-rw-r--r--Source/kwsys/CMakeLists.txt27
-rw-r--r--Source/kwsys/RegularExpression.hxx.in12
-rw-r--r--Source/kwsys/SystemInformation.cxx4
-rw-r--r--Source/kwsys/SystemTools.cxx52
-rw-r--r--Source/kwsys/SystemTools.hxx.in5
-rw-r--r--Source/kwsys/testCommandLineArguments.cxx2
-rw-r--r--Source/kwsys/testDirectory.cxx33
-rw-r--r--Source/kwsys/testSystemTools.cxx74
-rw-r--r--Tests/CMakeLib/testRST.expect4
-rw-r--r--Tests/CMakeLib/testRST.rst4
-rw-r--r--Tests/CMakeLists.txt29
-rw-r--r--Tests/CPackComponentsForAll/CMakeLists.txt12
-rw-r--r--Tests/CPackComponentsForAll/MyLibCPackConfig-AllInOne.cmake.in4
-rw-r--r--Tests/CPackComponentsForAll/MyLibCPackConfig-IgnoreGroup.cmake.in4
-rw-r--r--Tests/CPackComponentsForAll/MyLibCPackConfig-OnePackPerGroup.cmake.in4
-rw-r--r--Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake60
-rw-r--r--Tests/FindDoxygen/AllTarget/CMakeLists.txt42
-rw-r--r--Tests/FindDoxygen/CMakeLists.txt10
-rw-r--r--Tests/FindODBC/CMakeLists.txt10
-rw-r--r--Tests/FindODBC/Test/CMakeLists.txt14
-rw-r--r--Tests/FindODBC/Test/main.c12
-rw-r--r--Tests/PDBDirectoryAndName/CMakeLists.txt10
-rw-r--r--Tests/QtAutogen/CommonTests.cmake3
-rw-r--r--Tests/QtAutogen/LowMinimumVersion/CMakeLists.txt16
-rw-r--r--Tests/QtAutogen/LowMinimumVersion/example.qrc5
-rw-r--r--Tests/QtAutogen/LowMinimumVersion/item.cpp19
-rw-r--r--Tests/QtAutogen/LowMinimumVersion/item.hpp15
-rw-r--r--Tests/QtAutogen/LowMinimumVersion/main.cpp10
-rw-r--r--Tests/QtAutogen/LowMinimumVersion/someText.txt1
-rw-r--r--Tests/QtAutogen/LowMinimumVersion/view.ui24
-rw-r--r--Tests/RunCMake/CMakeLists.txt1
-rw-r--r--Tests/RunCMake/FindLua/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/FindLua/FindLuaTest.cmake87
-rw-r--r--Tests/RunCMake/FindLua/RunCMakeTest.cmake3
-rw-r--r--Tests/RunCMake/FindLua/prefix1/include/lua.h8
-rw-r--r--Tests/RunCMake/FindLua/prefix2/include/lua5.1/lua.h8
-rw-r--r--Tests/RunCMake/FindLua/prefix2/include/lua5.2/lua.h8
-rw-r--r--Tests/RunCMake/FindLua/prefix2/include/lua5.3/lua.h8
-rw-r--r--Tests/RunCMake/FindLua/prefix2/include/lua5.9/lua.h8
-rw-r--r--Tests/RunCMake/FindPkgConfig/FindPkgConfig_IMPORTED_TARGET.cmake12
-rw-r--r--Tests/RunCMake/VS10Project/VsCSharpCustomTags-stderr.txt3
-rw-r--r--Tests/RunCMake/VS10Project/VsCSharpReferenceProps-stderr.txt8
-rw-r--r--Tests/RunCMake/add_custom_target/CommandExpandsEmpty.cmake1
-rw-r--r--Tests/RunCMake/add_custom_target/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/alias_targets/imported-target-stderr.txt10
-rw-r--r--Tests/RunCMake/ctest_start/AppendDifferentModel-check.cmake1
-rw-r--r--Tests/RunCMake/ctest_start/AppendDifferentModel-stderr.txt1
-rw-r--r--Tests/RunCMake/ctest_start/AppendDifferentModel-stdout.txt8
-rw-r--r--Tests/RunCMake/ctest_start/AppendDifferentTrack-stderr.txt1
-rw-r--r--Tests/RunCMake/ctest_start/AppendDifferentTrack-stdout.txt9
-rw-r--r--Tests/RunCMake/ctest_start/AppendNoMatchingTrack-stdout.txt8
-rw-r--r--Tests/RunCMake/ctest_start/AppendNoModel-check.cmake1
-rw-r--r--Tests/RunCMake/ctest_start/AppendNoModel-stdout.txt8
-rw-r--r--Tests/RunCMake/ctest_start/AppendOldContinuous-stdout.txt8
-rw-r--r--Tests/RunCMake/ctest_start/AppendOldNoModel-result.txt1
-rw-r--r--Tests/RunCMake/ctest_start/AppendOldNoModel-stderr.txt3
-rw-r--r--Tests/RunCMake/ctest_start/AppendOldNoModel-stdout.txt6
-rw-r--r--Tests/RunCMake/ctest_start/AppendSameModel-check.cmake1
-rw-r--r--Tests/RunCMake/ctest_start/AppendSameModel-stdout.txt8
-rw-r--r--Tests/RunCMake/ctest_start/MissingTrackArg-result.txt1
-rw-r--r--Tests/RunCMake/ctest_start/MissingTrackArg-stderr.txt2
-rw-r--r--Tests/RunCMake/ctest_start/MissingTrackArgAppend-result.txt1
-rw-r--r--Tests/RunCMake/ctest_start/MissingTrackArgAppend-stderr.txt2
-rw-r--r--Tests/RunCMake/ctest_start/MissingTrackArgQuiet-result.txt1
-rw-r--r--Tests/RunCMake/ctest_start/MissingTrackArgQuiet-stderr.txt2
-rw-r--r--Tests/RunCMake/ctest_start/NoModel-result.txt1
-rw-r--r--Tests/RunCMake/ctest_start/NoModel-stderr.txt3
-rw-r--r--Tests/RunCMake/ctest_start/RunCMakeTest.cmake33
-rw-r--r--Tests/RunCMake/ctest_start/TooManyArgs-result.txt1
-rw-r--r--Tests/RunCMake/ctest_start/TooManyArgs-stderr.txt2
-rw-r--r--Tests/RunCMake/ctest_start/WriteModelToTagContinuous-check.cmake1
-rw-r--r--Tests/RunCMake/ctest_start/WriteModelToTagExperimental-check.cmake1
-rw-r--r--Tests/RunCMake/ctest_start/WriteModelToTagNightly-check.cmake1
-rw-r--r--Tests/RunCMake/ctest_start/WriteModelToTagNoMatchingTrack-check.cmake1
-rw-r--r--Tests/RunCMake/ctest_start/test.cmake.in12
-rw-r--r--Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake3
-rw-r--r--Tests/RunCMake/target_link_libraries/SubDirImportedTarget-stdout.txt4
-rw-r--r--Tests/RunCMake/target_link_libraries/SubDirImportedTarget.cmake17
-rw-r--r--Tests/RunCMake/target_link_libraries/SubDirImportedTarget/CMakeLists.txt13
-rw-r--r--Tests/RunCMake/target_link_libraries/SubDirTarget-UNKNOWN-IMPORTED-GLOBAL-stdout.txt2
-rw-r--r--Tests/RunCMake/target_link_libraries/SubDirTarget-UNKNOWN-IMPORTED-GLOBAL.cmake11
-rw-r--r--Tests/RunCMake/target_link_libraries/SubDirTarget-UNKNOWN-IMPORTED-GLOBAL/CMakeLists.txt7
-rw-r--r--Tests/RunCMake/target_link_libraries/SubDirTarget-UNKNOWN-IMPORTED-stdout.txt2
-rw-r--r--Tests/RunCMake/target_link_libraries/SubDirTarget-UNKNOWN-IMPORTED.cmake11
-rw-r--r--Tests/RunCMake/target_link_libraries/SubDirTarget-UNKNOWN-IMPORTED/CMakeLists.txt7
-rw-r--r--Tests/RunCMake/target_link_libraries/SubDirTarget-result.txt1
-rw-r--r--Tests/RunCMake/target_link_libraries/SubDirTarget-stderr.txt5
-rw-r--r--Tests/RunCMake/target_link_libraries/SubDirTarget-stdout.txt2
-rw-r--r--Tests/RunCMake/target_link_libraries/SubDirTarget.cmake10
-rw-r--r--Tests/RunCMake/target_link_libraries/SubDirTarget/CMakeLists.txt6
-rwxr-xr-xUtilities/Scripts/clang-format.bash7
-rwxr-xr-xUtilities/Scripts/regenerate-lexers.bash39
-rwxr-xr-xUtilities/Scripts/regenerate-parsers.bash37
-rwxr-xr-xUtilities/Scripts/update-curl.bash2
-rw-r--r--Utilities/Sphinx/conf.py.in1
-rw-r--r--Utilities/Sphinx/static/cmake.css10
-rw-r--r--Utilities/cmcurl/CMake/FindBrotli.cmake20
-rw-r--r--Utilities/cmcurl/CMakeLists.txt34
-rw-r--r--Utilities/cmcurl/include/curl/curl.h35
-rw-r--r--Utilities/cmcurl/include/curl/curlver.h10
-rw-r--r--Utilities/cmcurl/include/curl/multi.h6
-rw-r--r--Utilities/cmcurl/include/curl/system.h4
-rw-r--r--Utilities/cmcurl/include/curl/typecheck-gcc.h13
-rw-r--r--Utilities/cmcurl/lib/Makefile.inc12
-rw-r--r--Utilities/cmcurl/lib/asyn-thread.c67
-rw-r--r--Utilities/cmcurl/lib/connect.c35
-rw-r--r--Utilities/cmcurl/lib/connect.h7
-rw-r--r--Utilities/cmcurl/lib/content_encoding.c5
-rw-r--r--Utilities/cmcurl/lib/cookie.c276
-rw-r--r--Utilities/cmcurl/lib/cookie.h8
-rw-r--r--Utilities/cmcurl/lib/curl_addrinfo.c10
-rw-r--r--Utilities/cmcurl/lib/curl_config.h.cmake3
-rw-r--r--Utilities/cmcurl/lib/curl_ctype.c133
-rw-r--r--Utilities/cmcurl/lib/curl_ctype.h81
-rw-r--r--Utilities/cmcurl/lib/curl_fnmatch.c327
-rw-r--r--Utilities/cmcurl/lib/curl_gssapi.c7
-rw-r--r--Utilities/cmcurl/lib/curl_memrchr.c19
-rw-r--r--Utilities/cmcurl/lib/curl_ntlm_core.c15
-rw-r--r--Utilities/cmcurl/lib/curl_ntlm_wb.c2
-rw-r--r--Utilities/cmcurl/lib/curl_path.h5
-rw-r--r--Utilities/cmcurl/lib/curl_range.c95
-rw-r--r--Utilities/cmcurl/lib/curl_range.h30
-rw-r--r--Utilities/cmcurl/lib/curl_sasl.c34
-rw-r--r--Utilities/cmcurl/lib/curl_setup.h46
-rw-r--r--Utilities/cmcurl/lib/curl_setup_once.h23
-rw-r--r--Utilities/cmcurl/lib/easy.c32
-rw-r--r--Utilities/cmcurl/lib/file.c70
-rw-r--r--Utilities/cmcurl/lib/fileinfo.c7
-rw-r--r--Utilities/cmcurl/lib/fileinfo.h5
-rw-r--r--Utilities/cmcurl/lib/formdata.c64
-rw-r--r--Utilities/cmcurl/lib/ftp.c183
-rw-r--r--Utilities/cmcurl/lib/ftp.h4
-rw-r--r--Utilities/cmcurl/lib/ftplistparser.c31
-rw-r--r--Utilities/cmcurl/lib/getinfo.c12
-rw-r--r--Utilities/cmcurl/lib/hash.c6
-rw-r--r--Utilities/cmcurl/lib/hostcheck.c2
-rw-r--r--Utilities/cmcurl/lib/hostip.c202
-rw-r--r--Utilities/cmcurl/lib/hostip.h13
-rw-r--r--Utilities/cmcurl/lib/http.c223
-rw-r--r--Utilities/cmcurl/lib/http.h15
-rw-r--r--Utilities/cmcurl/lib/http2.c279
-rw-r--r--Utilities/cmcurl/lib/http_chunks.c30
-rw-r--r--Utilities/cmcurl/lib/http_negotiate.c2
-rw-r--r--Utilities/cmcurl/lib/http_ntlm.c14
-rw-r--r--Utilities/cmcurl/lib/http_proxy.c12
-rw-r--r--Utilities/cmcurl/lib/krb5.c6
-rw-r--r--Utilities/cmcurl/lib/md5.c7
-rw-r--r--Utilities/cmcurl/lib/mime.c22
-rw-r--r--Utilities/cmcurl/lib/mime.h5
-rw-r--r--Utilities/cmcurl/lib/multi.c166
-rw-r--r--Utilities/cmcurl/lib/multihandle.h1
-rw-r--r--Utilities/cmcurl/lib/multiif.h7
-rw-r--r--Utilities/cmcurl/lib/non-ascii.c16
-rw-r--r--Utilities/cmcurl/lib/nwlib.c4
-rw-r--r--Utilities/cmcurl/lib/openldap.c66
-rw-r--r--Utilities/cmcurl/lib/parsedate.c101
-rw-r--r--Utilities/cmcurl/lib/pingpong.c5
-rw-r--r--Utilities/cmcurl/lib/progress.c113
-rw-r--r--Utilities/cmcurl/lib/progress.h13
-rw-r--r--Utilities/cmcurl/lib/rtsp.c33
-rw-r--r--Utilities/cmcurl/lib/sendf.c65
-rw-r--r--Utilities/cmcurl/lib/sendf.h4
-rw-r--r--Utilities/cmcurl/lib/setopt.c69
-rw-r--r--Utilities/cmcurl/lib/sha256.c12
-rw-r--r--Utilities/cmcurl/lib/smb.c29
-rw-r--r--Utilities/cmcurl/lib/smtp.c5
-rw-r--r--Utilities/cmcurl/lib/ssh-libssh.c11
-rw-r--r--Utilities/cmcurl/lib/ssh.c101
-rw-r--r--Utilities/cmcurl/lib/strerror.c6
-rw-r--r--Utilities/cmcurl/lib/strtoofft.c2
-rw-r--r--Utilities/cmcurl/lib/telnet.c6
-rw-r--r--Utilities/cmcurl/lib/tftp.c4
-rw-r--r--Utilities/cmcurl/lib/timeval.c4
-rw-r--r--Utilities/cmcurl/lib/transfer.c75
-rw-r--r--Utilities/cmcurl/lib/transfer.h3
-rw-r--r--Utilities/cmcurl/lib/url.c106
-rw-r--r--Utilities/cmcurl/lib/urldata.h55
-rw-r--r--Utilities/cmcurl/lib/vauth/cleartext.c14
-rw-r--r--Utilities/cmcurl/lib/vauth/krb5_sspi.c10
-rw-r--r--Utilities/cmcurl/lib/vauth/ntlm.c12
-rw-r--r--Utilities/cmcurl/lib/vauth/ntlm.h8
-rw-r--r--Utilities/cmcurl/lib/vauth/ntlm_sspi.c20
-rw-r--r--Utilities/cmcurl/lib/vauth/spnego_sspi.c10
-rw-r--r--Utilities/cmcurl/lib/vauth/vauth.c6
-rw-r--r--Utilities/cmcurl/lib/vauth/vauth.h2
-rw-r--r--Utilities/cmcurl/lib/version.c4
-rw-r--r--Utilities/cmcurl/lib/vtls/axtls.c10
-rw-r--r--Utilities/cmcurl/lib/vtls/cyassl.c31
-rw-r--r--Utilities/cmcurl/lib/vtls/darwinssl.c90
-rw-r--r--Utilities/cmcurl/lib/vtls/gskit.c10
-rw-r--r--Utilities/cmcurl/lib/vtls/gtls.c31
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls.c21
-rw-r--r--Utilities/cmcurl/lib/vtls/nss.c27
-rw-r--r--Utilities/cmcurl/lib/vtls/openssl.c227
-rw-r--r--Utilities/cmcurl/lib/vtls/polarssl.c16
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel.c483
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel.h40
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel_verify.c551
-rw-r--r--Utilities/cmcurl/lib/vtls/vtls.c25
-rw-r--r--Utilities/cmcurl/lib/vtls/vtls.h21
-rw-r--r--Utilities/cmcurl/lib/warnless.h2
-rw-r--r--Utilities/cmcurl/lib/wildcard.c20
-rw-r--r--Utilities/cmcurl/lib/wildcard.h8
-rw-r--r--Utilities/cmlibuv/include/uv-errno.h132
-rw-r--r--Utilities/cmlibuv/include/uv-os390.h2
-rw-r--r--Utilities/cmlibuv/include/uv-unix.h2
-rw-r--r--Utilities/cmlibuv/include/uv-version.h4
-rw-r--r--Utilities/cmlibuv/include/uv.h21
-rw-r--r--Utilities/cmlibuv/src/unix/aix-common.c26
-rw-r--r--Utilities/cmlibuv/src/unix/aix.c46
-rw-r--r--Utilities/cmlibuv/src/unix/async.c8
-rw-r--r--Utilities/cmlibuv/src/unix/bsd-ifaddrs.c4
-rw-r--r--Utilities/cmlibuv/src/unix/core.c125
-rw-r--r--Utilities/cmlibuv/src/unix/cygwin.c2
-rw-r--r--Utilities/cmlibuv/src/unix/darwin-proctitle.c13
-rw-r--r--Utilities/cmlibuv/src/unix/darwin.c24
-rw-r--r--Utilities/cmlibuv/src/unix/freebsd.c34
-rw-r--r--Utilities/cmlibuv/src/unix/fs.c105
-rw-r--r--Utilities/cmlibuv/src/unix/fsevents.c26
-rw-r--r--Utilities/cmlibuv/src/unix/getaddrinfo.c10
-rw-r--r--Utilities/cmlibuv/src/unix/getnameinfo.c2
-rw-r--r--Utilities/cmlibuv/src/unix/ibmi.c2
-rw-r--r--Utilities/cmlibuv/src/unix/internal.h17
-rw-r--r--Utilities/cmlibuv/src/unix/kqueue.c8
-rw-r--r--Utilities/cmlibuv/src/unix/linux-core.c34
-rw-r--r--Utilities/cmlibuv/src/unix/linux-inotify.c10
-rw-r--r--Utilities/cmlibuv/src/unix/loop-watcher.c2
-rw-r--r--Utilities/cmlibuv/src/unix/loop.c3
-rw-r--r--Utilities/cmlibuv/src/unix/netbsd.c28
-rw-r--r--Utilities/cmlibuv/src/unix/no-fsevents.c6
-rw-r--r--Utilities/cmlibuv/src/unix/no-proctitle.c2
-rw-r--r--Utilities/cmlibuv/src/unix/openbsd.c32
-rw-r--r--Utilities/cmlibuv/src/unix/os390-syscalls.c2
-rw-r--r--Utilities/cmlibuv/src/unix/os390.c38
-rw-r--r--Utilities/cmlibuv/src/unix/pipe.c63
-rw-r--r--Utilities/cmlibuv/src/unix/poll.c4
-rw-r--r--Utilities/cmlibuv/src/unix/posix-poll.c18
-rw-r--r--Utilities/cmlibuv/src/unix/process.c57
-rw-r--r--Utilities/cmlibuv/src/unix/procfs-exepath.c4
-rw-r--r--Utilities/cmlibuv/src/unix/proctitle.c4
-rw-r--r--Utilities/cmlibuv/src/unix/signal.c4
-rw-r--r--Utilities/cmlibuv/src/unix/stream.c90
-rw-r--r--Utilities/cmlibuv/src/unix/sunos.c42
-rw-r--r--Utilities/cmlibuv/src/unix/tcp.c66
-rw-r--r--Utilities/cmlibuv/src/unix/thread.c256
-rw-r--r--Utilities/cmlibuv/src/unix/timer.c4
-rw-r--r--Utilities/cmlibuv/src/unix/tty.c16
-rw-r--r--Utilities/cmlibuv/src/unix/udp.c76
-rw-r--r--Utilities/cmlibuv/src/uv-common.c2
-rw-r--r--Utilities/cmlibuv/src/uv-common.h12
-rw-r--r--Utilities/cmlibuv/src/win/core.c6
-rw-r--r--Utilities/cmlibuv/src/win/fs-event.c29
-rw-r--r--Utilities/cmlibuv/src/win/fs.c15
-rw-r--r--Utilities/cmlibuv/src/win/getaddrinfo.c10
-rw-r--r--Utilities/cmlibuv/src/win/internal.h10
-rw-r--r--Utilities/cmlibuv/src/win/pipe.c8
-rw-r--r--Utilities/cmlibuv/src/win/process.c11
-rw-r--r--Utilities/cmlibuv/src/win/stream-inl.h10
-rw-r--r--Utilities/cmlibuv/src/win/tcp.c15
-rw-r--r--Utilities/cmlibuv/src/win/tty.c10
-rw-r--r--Utilities/cmlibuv/src/win/util.c99
-rw-r--r--Utilities/cmlibuv/src/win/winapi.c11
-rw-r--r--Utilities/cmlibuv/src/win/winapi.h15
-rw-r--r--Utilities/cmlibuv/src/win/winsock.c6
-rwxr-xr-xbootstrap10
354 files changed, 8712 insertions, 4322 deletions
diff --git a/.clang-format b/.clang-format
index 88bfbd3..c0b5cc3 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1,5 +1,5 @@
---
-# This configuration requires clang-format 3.8 or higher.
+# This configuration requires clang-format version 3.8 exactly.
BasedOnStyle: Mozilla
AlignOperands: false
AlwaysBreakAfterReturnType: None
diff --git a/Copyright.txt b/Copyright.txt
index 660455f..743c634 100644
--- a/Copyright.txt
+++ b/Copyright.txt
@@ -78,6 +78,7 @@ The following individuals and institutions are among the Contributors:
* Nikita Krupen'ko <krnekit@gmail.com>
* NVIDIA Corporation <www.nvidia.com>
* OpenGamma Ltd. <opengamma.com>
+* Patrick Stotko <stotko@cs.uni-bonn.de>
* Per Øyvind Karlsen <peroyvind@mandriva.org>
* Peter Collingbourne <peter@pcc.me.uk>
* Petr Gotthard <gotthard@honeywell.com>
diff --git a/Help/command/ctest_start.rst b/Help/command/ctest_start.rst
index 63db32f..6db9a48 100644
--- a/Help/command/ctest_start.rst
+++ b/Help/command/ctest_start.rst
@@ -5,21 +5,78 @@ Starts the testing for a given model
::
- ctest_start(Model [TRACK <track>] [APPEND] [source [binary]] [QUIET])
+ ctest_start(<model> [<source> [<binary>]] [TRACK <track>] [QUIET])
+
+ ctest_start([<model> [<source> [<binary>]]] [TRACK <track>] APPEND [QUIET])
Starts the testing for a given model. The command should be called
-after the binary directory is initialized. If the 'source' and
-'binary' directory are not specified, it reads the
-:variable:`CTEST_SOURCE_DIRECTORY` and :variable:`CTEST_BINARY_DIRECTORY`.
-If the track is
-specified, the submissions will go to the specified track. If APPEND
-is used, the existing TAG is used rather than creating a new one based
-on the current time stamp. If ``QUIET`` is used, CTest will suppress any
-non-error messages that it otherwise would have printed to the console.
-
-If the :variable:`CTEST_CHECKOUT_COMMAND` variable
-(or the :variable:`CTEST_CVS_CHECKOUT` variable)
-is set, its content is treated as command-line. The command is
-invoked with the current working directory set to the parent of the source
-directory, even if the source directory already exists. This can be used
-to create the source tree from a version control repository.
+after the binary directory is initialized.
+
+The parameters are as follows:
+
+``<model>``
+ Set the dashboard model. Must be one of ``Experimental``, ``Continuous``, or
+ ``Nightly``. This parameter is required unless ``APPEND`` is specified.
+
+``<source>``
+ Set the source directory. If not specified, the value of
+ :variable:`CTEST_SOURCE_DIRECTORY` is used instead.
+
+``<binary>``
+ Set the binary directory. If not specified, the value of
+ :variable:`CTEST_BINARY_DIRECTORY` is used instead.
+
+``TRACK <track>``
+ If ``TRACK`` is used, the submissions will go to the specified track on the
+ CDash server. If no ``TRACK`` is specified, the name of the model is used by
+ default.
+
+``APPEND``
+ If ``APPEND`` is used, the existing ``TAG`` is used rather than creating a new
+ one based on the current time stamp. If you use ``APPEND``, you can omit the
+ ``<model>`` and ``TRACK <track>`` parameters, because they will be read from
+ the generated ``TAG`` file. For example:
+
+ .. code-block:: cmake
+
+ ctest_start(Experimental TRACK TrackExperimental)
+
+ Later, in another ``ctest -S`` script:
+
+ .. code-block:: cmake
+
+ ctest_start(APPEND)
+
+ When the second script runs ``ctest_start(APPEND)``, it will read the
+ ``Experimental`` model and ``TrackExperimental`` track from the ``TAG`` file
+ generated by the first ``ctest_start()`` command. Please note that if you
+ call ``ctest_start(APPEND)`` and specify a different model or track than
+ in the first ``ctest_start()`` command, a warning will be issued, and the
+ new model and track will be used.
+
+``QUIET``
+ If ``QUIET`` is used, CTest will suppress any non-error messages that it
+ otherwise would have printed to the console.
+
+The parameters for ``ctest_start()`` can be issued in any order, with the
+exception that ``<model>``, ``<source>``, and ``<binary>`` have to appear
+in that order with respect to each other. The following are all valid and
+equivalent:
+
+.. code-block:: cmake
+
+ ctest_start(Experimental path/to/source path/to/binary TRACK SomeTrack QUIET APPEND)
+
+ ctest_start(TRACK SomeTrack Experimental QUIET path/to/source APPEND path/to/binary)
+
+ ctest_start(APPEND QUIET Experimental path/to/source TRACK SomeTrack path/to/binary)
+
+However, for the sake of readability, it is recommended that you order your
+parameters in the order listed at the top of this page.
+
+If the :variable:`CTEST_CHECKOUT_COMMAND` variable (or the
+:variable:`CTEST_CVS_CHECKOUT` variable) is set, its content is treated as
+command-line. The command is invoked with the current working directory set
+to the parent of the source directory, even if the source directory already
+exists. This can be used to create the source tree from a version control
+repository.
diff --git a/Help/command/file.rst b/Help/command/file.rst
index 43ce3d9..d4a6006 100644
--- a/Help/command/file.rst
+++ b/Help/command/file.rst
@@ -3,23 +3,44 @@ file
File manipulation command.
-------------------------------------------------------------------------------
+Synopsis
+^^^^^^^^
-::
+.. parsed-literal::
- file(WRITE <filename> <content>...)
- file(APPEND <filename> <content>...)
+ `Reading`_
+ file(`READ`_ <filename> <out-var> [...])
+ file(`STRINGS`_ <filename> <out-var> [...])
+ file(`\<HASH\> <HASH_>`_ <filename> <out-var>)
+ file(`TIMESTAMP`_ <filename> <out-var> [...])
-Write ``<content>`` into a file called ``<filename>``. If the file does
-not exist, it will be created. If the file already exists, ``WRITE``
-mode will overwrite it and ``APPEND`` mode will append to the end.
-Any directories in the path specified by ``<filename>`` that do not
-exist will be created.
+ `Writing`_
+ file({`WRITE`_ | `APPEND`_} <filename> <content>...)
+ file({`TOUCH`_ | `TOUCH_NOCREATE`_} [<file>...])
+ file(`GENERATE`_ OUTPUT <output-file> [...])
-If the file is a build input, use the :command:`configure_file` command
-to update the file only when its content changes.
+ `Filesystem`_
+ file({`GLOB`_ | `GLOB_RECURSE`_} <out-var> [...] [<globbing-expr>...])
+ file(`RENAME`_ <oldname> <newname>)
+ file({`REMOVE`_ | `REMOVE_RECURSE`_ } [<files>...])
+ file(`MAKE_DIRECTORY`_ [<dir>...])
+ file({`COPY`_ | `INSTALL`_} <file>... DESTINATION <dir> [...])
+
+ `Path Conversion`_
+ file(`RELATIVE_PATH`_ <out-var> <directory> <file>)
+ file({`TO_CMAKE_PATH`_ | `TO_NATIVE_PATH`_} <path> <out-var>)
+
+ `Transfer`_
+ file(`DOWNLOAD`_ <url> <file> [...])
+ file(`UPLOAD`_ <file> <url> [...])
-------------------------------------------------------------------------------
+ `Locking`_
+ file(`LOCK`_ <path> [...])
+
+Reading
+^^^^^^^
+
+.. _READ:
::
@@ -31,7 +52,7 @@ Read content from a file called ``<filename>`` and store it in a
read at most ``<max-in>`` bytes. The ``HEX`` option causes data to
be converted to a hexadecimal representation (useful for binary data).
-------------------------------------------------------------------------------
+.. _STRINGS:
::
@@ -82,7 +103,7 @@ For example, the code
stores a list in the variable ``myfile`` in which each item is a line
from the input file.
-------------------------------------------------------------------------------
+.. _HASH:
::
@@ -93,7 +114,108 @@ store it in a ``<variable>``. The supported ``<HASH>`` algorithm names
are those listed by the :ref:`string(\<HASH\>) <Supported Hash Algorithms>`
command.
-------------------------------------------------------------------------------
+.. _TIMESTAMP:
+
+::
+
+ file(TIMESTAMP <filename> <variable> [<format>] [UTC])
+
+Compute a string representation of the modification time of ``<filename>``
+and store it in ``<variable>``. Should the command be unable to obtain a
+timestamp variable will be set to the empty string ("").
+
+See the :command:`string(TIMESTAMP)` command for documentation of
+the ``<format>`` and ``UTC`` options.
+
+Writing
+^^^^^^^
+
+.. _WRITE:
+.. _APPEND:
+
+::
+
+ file(WRITE <filename> <content>...)
+ file(APPEND <filename> <content>...)
+
+Write ``<content>`` into a file called ``<filename>``. If the file does
+not exist, it will be created. If the file already exists, ``WRITE``
+mode will overwrite it and ``APPEND`` mode will append to the end.
+Any directories in the path specified by ``<filename>`` that do not
+exist will be created.
+
+If the file is a build input, use the :command:`configure_file` command
+to update the file only when its content changes.
+
+.. _TOUCH:
+.. _TOUCH_NOCREATE:
+
+::
+
+ file(TOUCH [<files>...])
+ file(TOUCH_NOCREATE [<files>...])
+
+Create a file with no content if it does not yet exist. If the file already
+exists, its access and/or modification will be updated to the time when the
+function call is executed.
+
+Use TOUCH_NOCREATE to touch a file if it exists but not create it. If a file
+does not exist it will be silently ignored.
+
+With TOUCH and TOUCH_NOCREATE the contents of an existing file will not be
+modified.
+
+.. _GENERATE:
+
+::
+
+ file(GENERATE OUTPUT output-file
+ <INPUT input-file|CONTENT content>
+ [CONDITION expression])
+
+Generate an output file for each build configuration supported by the current
+:manual:`CMake Generator <cmake-generators(7)>`. Evaluate
+:manual:`generator expressions <cmake-generator-expressions(7)>`
+from the input content to produce the output content. The options are:
+
+``CONDITION <condition>``
+ Generate the output file for a particular configuration only if
+ the condition is true. The condition must be either ``0`` or ``1``
+ after evaluating generator expressions.
+
+``CONTENT <content>``
+ Use the content given explicitly as input.
+
+``INPUT <input-file>``
+ Use the content from a given file as input.
+ A relative path is treated with respect to the value of
+ :variable:`CMAKE_CURRENT_SOURCE_DIR`. See policy :policy:`CMP0070`.
+
+``OUTPUT <output-file>``
+ Specify the output file name to generate. Use generator expressions
+ such as ``$<CONFIG>`` to specify a configuration-specific output file
+ name. Multiple configurations may generate the same output file only
+ if the generated content is identical. Otherwise, the ``<output-file>``
+ must evaluate to an unique name for each configuration.
+ A relative path (after evaluating generator expressions) is treated
+ with respect to the value of :variable:`CMAKE_CURRENT_BINARY_DIR`.
+ See policy :policy:`CMP0070`.
+
+Exactly one ``CONTENT`` or ``INPUT`` option must be given. A specific
+``OUTPUT`` file may be named by at most one invocation of ``file(GENERATE)``.
+Generated files are modified and their timestamp updated on subsequent cmake
+runs only if their content is changed.
+
+Note also that ``file(GENERATE)`` does not create the output file until the
+generation phase. The output file will not yet have been written when the
+``file(GENERATE)`` command returns, it is written only after processing all
+of a project's ``CMakeLists.txt`` files.
+
+Filesystem
+^^^^^^^^^^
+
+.. _GLOB:
+.. _GLOB_RECURSE:
::
@@ -148,7 +270,7 @@ Examples of recursive globbing include::
/dir/*.py - match all python files in /dir and subdirectories
-------------------------------------------------------------------------------
+.. _RENAME:
::
@@ -157,7 +279,8 @@ Examples of recursive globbing include::
Move a file or directory within a filesystem from ``<oldname>`` to
``<newname>``, replacing the destination atomically.
-------------------------------------------------------------------------------
+.. _REMOVE:
+.. _REMOVE_RECURSE:
::
@@ -168,7 +291,7 @@ Remove the given files. The ``REMOVE_RECURSE`` mode will remove the given
files and directories, also non-empty directories. No error is emitted if a
given file does not exist.
-------------------------------------------------------------------------------
+.. _MAKE_DIRECTORY:
::
@@ -176,7 +299,44 @@ given file does not exist.
Create the given directories and their parents as needed.
-------------------------------------------------------------------------------
+.. _COPY:
+.. _INSTALL:
+
+::
+
+ file(<COPY|INSTALL> <files>... DESTINATION <dir>
+ [FILE_PERMISSIONS <permissions>...]
+ [DIRECTORY_PERMISSIONS <permissions>...]
+ [NO_SOURCE_PERMISSIONS] [USE_SOURCE_PERMISSIONS]
+ [FILES_MATCHING]
+ [[PATTERN <pattern> | REGEX <regex>]
+ [EXCLUDE] [PERMISSIONS <permissions>...]] [...])
+
+The ``COPY`` signature copies files, directories, and symlinks to a
+destination folder. Relative input paths are evaluated with respect
+to the current source directory, and a relative destination is
+evaluated with respect to the current build directory. Copying
+preserves input file timestamps, and optimizes out a file if it exists
+at the destination with the same timestamp. Copying preserves input
+permissions unless explicit permissions or ``NO_SOURCE_PERMISSIONS``
+are given (default is ``USE_SOURCE_PERMISSIONS``).
+
+See the :command:`install(DIRECTORY)` command for documentation of
+permissions, ``FILES_MATCHING``, ``PATTERN``, ``REGEX``, and
+``EXCLUDE`` options. Copying directories preserves the structure
+of their content even if options are used to select a subset of
+files.
+
+The ``INSTALL`` signature differs slightly from ``COPY``: it prints
+status messages (subject to the :variable:`CMAKE_INSTALL_MESSAGE` variable),
+and ``NO_SOURCE_PERMISSIONS`` is default.
+Installation scripts generated by the :command:`install` command
+use this signature (with some undocumented options for internal use).
+
+Path Conversion
+^^^^^^^^^^^^^^^
+
+.. _RELATIVE_PATH:
::
@@ -185,7 +345,8 @@ Create the given directories and their parents as needed.
Compute the relative path from a ``<directory>`` to a ``<file>`` and
store it in the ``<variable>``.
-------------------------------------------------------------------------------
+.. _TO_CMAKE_PATH:
+.. _TO_NATIVE_PATH:
::
@@ -203,7 +364,11 @@ path with platform-specific slashes (``\`` on Windows and ``/`` elsewhere).
Always use double quotes around the ``<path>`` to be sure it is treated
as a single argument to this command.
-------------------------------------------------------------------------------
+Transfer
+^^^^^^^^
+
+.. _DOWNLOAD:
+.. _UPLOAD:
::
@@ -290,116 +455,10 @@ check certificates and/or use ``EXPECTED_HASH`` to verify downloaded content.
If neither ``TLS`` option is given CMake will check variables
``CMAKE_TLS_VERIFY`` and ``CMAKE_TLS_CAINFO``, respectively.
-------------------------------------------------------------------------------
-
-::
-
- file(TOUCH [<files>...])
- file(TOUCH_NOCREATE [<files>...])
-
-Create a file with no content if it does not yet exist. If the file already
-exists, its access and/or modification will be updated to the time when the
-function call is executed.
-
-Use TOUCH_NOCREATE to touch a file if it exists but not create it. If a file
-does not exist it will be silently ignored.
-
-With TOUCH and TOUCH_NOCREATE the contents of an existing file will not be
-modified.
-
-------------------------------------------------------------------------------
-
-::
-
- file(TIMESTAMP <filename> <variable> [<format>] [UTC])
-
-Compute a string representation of the modification time of ``<filename>``
-and store it in ``<variable>``. Should the command be unable to obtain a
-timestamp variable will be set to the empty string ("").
-
-See the :command:`string(TIMESTAMP)` command for documentation of
-the ``<format>`` and ``UTC`` options.
-
-------------------------------------------------------------------------------
-
-::
-
- file(GENERATE OUTPUT output-file
- <INPUT input-file|CONTENT content>
- [CONDITION expression])
-
-Generate an output file for each build configuration supported by the current
-:manual:`CMake Generator <cmake-generators(7)>`. Evaluate
-:manual:`generator expressions <cmake-generator-expressions(7)>`
-from the input content to produce the output content. The options are:
-
-``CONDITION <condition>``
- Generate the output file for a particular configuration only if
- the condition is true. The condition must be either ``0`` or ``1``
- after evaluating generator expressions.
-
-``CONTENT <content>``
- Use the content given explicitly as input.
-
-``INPUT <input-file>``
- Use the content from a given file as input.
- A relative path is treated with respect to the value of
- :variable:`CMAKE_CURRENT_SOURCE_DIR`. See policy :policy:`CMP0070`.
-
-``OUTPUT <output-file>``
- Specify the output file name to generate. Use generator expressions
- such as ``$<CONFIG>`` to specify a configuration-specific output file
- name. Multiple configurations may generate the same output file only
- if the generated content is identical. Otherwise, the ``<output-file>``
- must evaluate to an unique name for each configuration.
- A relative path (after evaluating generator expressions) is treated
- with respect to the value of :variable:`CMAKE_CURRENT_BINARY_DIR`.
- See policy :policy:`CMP0070`.
-
-Exactly one ``CONTENT`` or ``INPUT`` option must be given. A specific
-``OUTPUT`` file may be named by at most one invocation of ``file(GENERATE)``.
-Generated files are modified and their timestamp updated on subsequent cmake
-runs only if their content is changed.
-
-Note also that ``file(GENERATE)`` does not create the output file until the
-generation phase. The output file will not yet have been written when the
-``file(GENERATE)`` command returns, it is written only after processing all
-of a project's ``CMakeLists.txt`` files.
-
-------------------------------------------------------------------------------
-
-::
-
- file(<COPY|INSTALL> <files>... DESTINATION <dir>
- [FILE_PERMISSIONS <permissions>...]
- [DIRECTORY_PERMISSIONS <permissions>...]
- [NO_SOURCE_PERMISSIONS] [USE_SOURCE_PERMISSIONS]
- [FILES_MATCHING]
- [[PATTERN <pattern> | REGEX <regex>]
- [EXCLUDE] [PERMISSIONS <permissions>...]] [...])
-
-The ``COPY`` signature copies files, directories, and symlinks to a
-destination folder. Relative input paths are evaluated with respect
-to the current source directory, and a relative destination is
-evaluated with respect to the current build directory. Copying
-preserves input file timestamps, and optimizes out a file if it exists
-at the destination with the same timestamp. Copying preserves input
-permissions unless explicit permissions or ``NO_SOURCE_PERMISSIONS``
-are given (default is ``USE_SOURCE_PERMISSIONS``).
-
-See the :command:`install(DIRECTORY)` command for documentation of
-permissions, ``FILES_MATCHING``, ``PATTERN``, ``REGEX``, and
-``EXCLUDE`` options. Copying directories preserves the structure
-of their content even if options are used to select a subset of
-files.
-
-The ``INSTALL`` signature differs slightly from ``COPY``: it prints
-status messages (subject to the :variable:`CMAKE_INSTALL_MESSAGE` variable),
-and ``NO_SOURCE_PERMISSIONS`` is default.
-Installation scripts generated by the :command:`install` command
-use this signature (with some undocumented options for internal use).
+Locking
+^^^^^^^
-------------------------------------------------------------------------------
+.. _LOCK:
::
diff --git a/Help/command/install.rst b/Help/command/install.rst
index a81714f..6cea996 100644
--- a/Help/command/install.rst
+++ b/Help/command/install.rst
@@ -1,19 +1,19 @@
install
-------
-.. only:: html
-
- .. contents::
-
Specify rules to run at install time.
-This command accepts several signatures:
+Synopsis
+^^^^^^^^
-* :ref:`install(TARGETS) <install-targets>`
-* :ref:`install(FILES|PROGRAMS) <install-files>`
-* :ref:`install(DIRECTORY) <install-directory>`
-* :ref:`install(SCRIPT|CODE) <install-script>`
-* :ref:`install(EXPORT|EXPORT_ANDROID_MK) <install-export>`
+.. parsed-literal::
+
+ install(`TARGETS`_ <target>... [...])
+ install({`FILES`_ | `PROGRAMS`_} <file>... DESTINATION <dir> [...])
+ install(`DIRECTORY`_ <dir>... DESTINATION <dir> [...])
+ install(`SCRIPT`_ <file> [...])
+ install(`CODE`_ <code> [...])
+ install(`EXPORT`_ <export-name> DESTINATION <dir> [...])
Introduction
^^^^^^^^^^^^
@@ -89,11 +89,11 @@ Command signatures that install files may print messages during
installation. Use the :variable:`CMAKE_INSTALL_MESSAGE` variable
to control which messages are printed.
-.. _install-targets:
-
Installing Targets
^^^^^^^^^^^^^^^^^^
+.. _TARGETS:
+
::
install(TARGETS targets... [EXPORT <export-name>]
@@ -284,11 +284,12 @@ The install destination given to the target install ``DESTINATION`` may
use "generator expressions" with the syntax ``$<...>``. See the
:manual:`cmake-generator-expressions(7)` manual for available expressions.
-.. _install-files:
-
Installing Files
^^^^^^^^^^^^^^^^
+.. _FILES:
+.. _PROGRAMS:
+
::
install(<FILES|PROGRAMS> files... DESTINATION <dir>
@@ -319,11 +320,11 @@ The install destination given to the files install ``DESTINATION`` may
use "generator expressions" with the syntax ``$<...>``. See the
:manual:`cmake-generator-expressions(7)` manual for available expressions.
-.. _install-directory:
-
Installing Directories
^^^^^^^^^^^^^^^^^^^^^^
+.. _DIRECTORY:
+
::
install(DIRECTORY dirs... DESTINATION <dir>
@@ -402,11 +403,12 @@ given to the directory install ``DESTINATION`` may use "generator expressions"
with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
manual for available expressions.
-.. _install-script:
-
Custom Installation Logic
^^^^^^^^^^^^^^^^^^^^^^^^^
+.. _CODE:
+.. _SCRIPT:
+
::
install([[SCRIPT <file>] [CODE <code>]]
@@ -425,11 +427,11 @@ example, the code
will print a message during installation.
-.. _install-export:
-
Installing Exports
^^^^^^^^^^^^^^^^^^
+.. _EXPORT:
+
::
install(EXPORT <export-name> DESTINATION <dir>
diff --git a/Help/command/list.rst b/Help/command/list.rst
index 67e9743..589e572 100644
--- a/Help/command/list.rst
+++ b/Help/command/list.rst
@@ -1,11 +1,37 @@
list
----
-.. only:: html
+List operations.
- .. contents::
+Synopsis
+^^^^^^^^
-List operations.
+.. parsed-literal::
+
+ `Reading`_
+ list(`LENGTH`_ <list> <out-var>)
+ list(`GET`_ <list> <element index> [<index> ...] <out-var>)
+ list(`JOIN`_ <list> <glue> <out-var>)
+ list(`SUBLIST`_ <list> <begin> <length> <out-var>)
+
+ `Search`_
+ list(`FIND`_ <list> <value> <out-var>)
+
+ `Modification`_
+ list(`APPEND`_ <list> [<element>...])
+ list(`FILTER`_ <list> {INCLUDE | EXCLUDE} REGEX <regex>)
+ list(`INSERT`_ <list> <index> [<element>...])
+ list(`REMOVE_ITEM`_ <list> <value>...)
+ list(`REMOVE_AT`_ <list> <index>...)
+ list(`REMOVE_DUPLICATES`_ <list>)
+ list(`TRANSFORM`_ <list> <ACTION> [...])
+
+ `Ordering`_
+ list(`REVERSE`_ <list>)
+ list(`SORT`_ <list>)
+
+Introduction
+^^^^^^^^^^^^
The list subcommands ``APPEND``, ``INSERT``, ``FILTER``, ``REMOVE_AT``,
``REMOVE_ITEM``, ``REMOVE_DUPLICATES``, ``REVERSE`` and ``SORT`` may create
@@ -33,11 +59,10 @@ scope. To propagate the results of these operations upwards, use
Be careful when counting with negative indices: they do not start from
0. -0 is equivalent to 0, the first list element.
-Capacity and Element access
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Reading
+^^^^^^^
-LENGTH
-""""""
+.. _LENGTH:
::
@@ -45,8 +70,7 @@ LENGTH
Returns the list's length.
-GET
-"""
+.. _GET:
::
@@ -54,8 +78,7 @@ GET
Returns the list of elements specified by indices from the list.
-JOIN
-""""
+.. _JOIN:
::
@@ -65,8 +88,7 @@ Returns a string joining all list's elements using the glue string.
To join multiple strings, which are not part of a list, use ``JOIN`` operator
from :command:`string` command.
-SUBLIST
-"""""""
+.. _SUBLIST:
::
@@ -80,8 +102,7 @@ the remaining elements of the list starting at ``<begin>`` will be returned.
Search
^^^^^^
-FIND
-""""
+.. _FIND:
::
@@ -93,8 +114,7 @@ if it wasn't found.
Modification
^^^^^^^^^^^^
-APPEND
-""""""
+.. _APPEND:
::
@@ -102,8 +122,7 @@ APPEND
Appends elements to the list.
-FILTER
-""""""
+.. _FILTER:
::
@@ -115,8 +134,7 @@ In ``REGEX`` mode, items will be matched against the given regular expression.
For more information on regular expressions see also the
:command:`string` command.
-INSERT
-""""""
+.. _INSERT:
::
@@ -124,8 +142,7 @@ INSERT
Inserts elements to the list to the specified location.
-REMOVE_ITEM
-"""""""""""
+.. _REMOVE_ITEM:
::
@@ -133,8 +150,7 @@ REMOVE_ITEM
Removes the given items from the list.
-REMOVE_AT
-"""""""""
+.. _REMOVE_AT:
::
@@ -142,8 +158,7 @@ REMOVE_AT
Removes items at given indices from the list.
-REMOVE_DUPLICATES
-"""""""""""""""""
+.. _REMOVE_DUPLICATES:
::
@@ -151,8 +166,7 @@ REMOVE_DUPLICATES
Removes duplicated items in the list.
-TRANSFORM
-"""""""""
+.. _TRANSFORM:
::
@@ -224,11 +238,10 @@ expression will be transformed. ::
list(TRANSFORM <list> <ACTION> REGEX <regular_expression> ...)
-Sorting
-^^^^^^^
+Ordering
+^^^^^^^^
-REVERSE
-"""""""
+.. _REVERSE:
::
@@ -236,8 +249,7 @@ REVERSE
Reverses the contents of the list in-place.
-SORT
-""""
+.. _SORT:
::
diff --git a/Help/command/string.rst b/Help/command/string.rst
index e84f788..efa923b 100644
--- a/Help/command/string.rst
+++ b/Help/command/string.rst
@@ -1,17 +1,52 @@
string
------
-.. only:: html
-
- .. contents::
-
String operations.
+Synopsis
+^^^^^^^^
+
+.. parsed-literal::
+
+ `Search and Replace`_
+ string(`FIND`_ <string> <substring> <out-var> [...])
+ string(`REPLACE`_ <match-string> <replace-string> <out-var> <input>...)
+
+ `Regular Expressions`_
+ string(`REGEX MATCH`_ <match-regex> <out-var> <input>...)
+ string(`REGEX MATCHALL`_ <match-regex> <out-var> <input>...)
+ string(`REGEX REPLACE`_ <match-regex> <replace-expr> <out-var> <input>...)
+
+ `Manipulation`_
+ string(`APPEND`_ <string-var> [<input>...])
+ string(`PREPEND`_ <string-var> [<input>...])
+ string(`CONCAT`_ <out-var> [<input>...])
+ string(`JOIN`_ <glue> <out-var> [<input>...])
+ string(`TOLOWER`_ <string1> <out-var>)
+ string(`TOUPPER`_ <string1> <out-var>)
+ string(`LENGTH`_ <string> <out-var>)
+ string(`SUBSTRING`_ <string> <begin> <length> <out-var>)
+ string(`STRIP`_ <string> <out-var>)
+ string(`GENEX_STRIP`_ <string> <out-var>)
+
+ `Comparison`_
+ string(`COMPARE`_ <op> <string1> <string2> <out-var>)
+
+ `Hashing`_
+ string(`\<HASH\> <HASH_>`_ <out-var> <input>)
+
+ `Generation`_
+ string(`ASCII`_ <number>... <out-var>)
+ string(`CONFIGURE`_ <string1> <out-var> [...])
+ string(`MAKE_C_IDENTIFIER`_ <string> <out-var>)
+ string(`RANDOM`_ [<option>...] <out-var>)
+ string(`TIMESTAMP`_ <out-var> [<format string>] [UTC])
+ string(`UUID`_ <out-var> ...)
+
Search and Replace
^^^^^^^^^^^^^^^^^^
-FIND
-""""
+.. _FIND:
::
@@ -22,8 +57,7 @@ the supplied string. If the ``REVERSE`` flag was used, the command will
search for the position of the last occurrence of the specified
substring. If the substring is not found, a position of -1 is returned.
-REPLACE
-"""""""
+.. _REPLACE:
::
@@ -37,8 +71,7 @@ with ``replace_string`` and store the result in the output.
Regular Expressions
^^^^^^^^^^^^^^^^^^^
-REGEX MATCH
-"""""""""""
+.. _`REGEX MATCH`:
::
@@ -48,8 +81,7 @@ REGEX MATCH
Match the regular expression once and store the match in the output variable.
All ``<input>`` arguments are concatenated before matching.
-REGEX MATCHALL
-""""""""""""""
+.. _`REGEX MATCHALL`:
::
@@ -60,8 +92,7 @@ Match the regular expression as many times as possible and store the matches
in the output variable as a list.
All ``<input>`` arguments are concatenated before matching.
-REGEX REPLACE
-"""""""""""""
+.. _`REGEX REPLACE`:
::
@@ -123,8 +154,7 @@ expression ``^(ab|cd)$`` matches ``ab`` but not ``abd``.
Manipulation
^^^^^^^^^^^^
-APPEND
-""""""
+.. _APPEND:
::
@@ -132,8 +162,7 @@ APPEND
Append all the input arguments to the string.
-PREPEND
-"""""""
+.. _PREPEND:
::
@@ -141,8 +170,7 @@ PREPEND
Prepend all the input arguments to the string.
-CONCAT
-""""""
+.. _CONCAT:
::
@@ -151,8 +179,7 @@ CONCAT
Concatenate all the input arguments together and store
the result in the named output variable.
-JOIN
-""""
+.. _JOIN:
::
@@ -165,8 +192,7 @@ To join list's elements, use preferably the ``JOIN`` operator
from :command:`list` command. This allows for the elements to have
special characters like ``;`` in them.
-TOLOWER
-"""""""
+.. _TOLOWER:
::
@@ -174,8 +200,7 @@ TOLOWER
Convert string to lower characters.
-TOUPPER
-"""""""
+.. _TOUPPER:
::
@@ -183,8 +208,7 @@ TOUPPER
Convert string to upper characters.
-LENGTH
-""""""
+.. _LENGTH:
::
@@ -192,8 +216,7 @@ LENGTH
Store in an output variable a given string's length.
-SUBSTRING
-"""""""""
+.. _SUBSTRING:
::
@@ -207,8 +230,7 @@ If string is shorter than length then end of string is used instead.
CMake 3.1 and below reported an error if length pointed past
the end of string.
-STRIP
-"""""
+.. _STRIP:
::
@@ -217,8 +239,7 @@ STRIP
Store in an output variable a substring of a given string with leading and
trailing spaces removed.
-GENEX_STRIP
-"""""""""""
+.. _GENEX_STRIP:
::
@@ -230,6 +251,8 @@ from the ``input string`` and store the result in the ``output variable``.
Comparison
^^^^^^^^^^
+.. _COMPARE:
+
::
string(COMPARE LESS <string1> <string2> <output variable>)
@@ -246,6 +269,8 @@ Compare the strings and store true or false in the output variable.
Hashing
^^^^^^^
+.. _`HASH`:
+
::
string(<HASH> <output variable> <input>)
@@ -277,8 +302,7 @@ The supported ``<HASH>`` algorithm names are:
Generation
^^^^^^^^^^
-ASCII
-"""""
+.. _ASCII:
::
@@ -286,8 +310,7 @@ ASCII
Convert all numbers into corresponding ASCII characters.
-CONFIGURE
-"""""""""
+.. _CONFIGURE:
::
@@ -296,8 +319,7 @@ CONFIGURE
Transform a string like :command:`configure_file` transforms a file.
-MAKE_C_IDENTIFIER
-"""""""""""""""""
+.. _MAKE_C_IDENTIFIER:
::
@@ -308,8 +330,7 @@ underscore and store the result in the ``<output variable>``. If the first
character of the string is a digit, an underscore will also be prepended to
the result.
-RANDOM
-""""""
+.. _RANDOM:
::
@@ -322,8 +343,7 @@ and default alphabet is all numbers and upper and lower case letters.
If an integer ``RANDOM_SEED`` is given, its value will be used to seed the
random number generator.
-TIMESTAMP
-"""""""""
+.. _TIMESTAMP:
::
@@ -378,8 +398,7 @@ If no explicit ``<format string>`` is given it will default to:
its value will be used instead of the current time.
See https://reproducible-builds.org/specs/source-date-epoch/ for details.
-UUID
-""""
+.. _UUID:
::
diff --git a/Help/command/target_link_libraries.rst b/Help/command/target_link_libraries.rst
index fcc2c07..6379730 100644
--- a/Help/command/target_link_libraries.rst
+++ b/Help/command/target_link_libraries.rst
@@ -18,7 +18,7 @@ All of them have the general form::
target_link_libraries(<target> ... <item>... ...)
-The named ``<target>`` must have been created in the current directory by
+The named ``<target>`` must have been created by
a command such as :command:`add_executable` or :command:`add_library` and
must not be an :ref:`ALIAS target <Alias Targets>`.
Repeated calls for the same ``<target>`` append items in the order called.
diff --git a/Help/manual/OPTIONS_BUILD.txt b/Help/manual/OPTIONS_BUILD.txt
index e8b87c9..33d27af 100644
--- a/Help/manual/OPTIONS_BUILD.txt
+++ b/Help/manual/OPTIONS_BUILD.txt
@@ -11,7 +11,7 @@
cache-format file.
``-D <var>:<type>=<value>, -D <var>=<value>``
- Create a cmake cache entry.
+ Create or update a cmake cache entry.
When cmake is first run in an empty build tree, it creates a
CMakeCache.txt file and populates it with customizable settings for
diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst
index 070c6ed..8ef4d7d 100644
--- a/Help/manual/cmake-modules.7.rst
+++ b/Help/manual/cmake-modules.7.rst
@@ -64,6 +64,7 @@ All Modules
/module/CPackIFW
/module/CPackIFWConfigureFile
/module/CPackNSIS
+ /module/CPackNuGet
/module/CPackPackageMaker
/module/CPackProductBuild
/module/CPackRPM
@@ -155,6 +156,7 @@ All Modules
/module/FindMPEG2
/module/FindMPEG
/module/FindMPI
+ /module/FindODBC
/module/FindOpenACC
/module/FindOpenAL
/module/FindOpenCL
diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst
index b3e2fec..9f9c53f 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -40,6 +40,7 @@ Properties of Global Scope
/prop_gbl/JOB_POOLS
/prop_gbl/PREDEFINED_TARGETS_FOLDER
/prop_gbl/ECLIPSE_EXTRA_NATURES
+ /prop_gbl/ECLIPSE_EXTRA_CPROJECT_CONTENTS
/prop_gbl/REPORT_UNDEFINED_PROPERTIES
/prop_gbl/RULE_LAUNCH_COMPILE
/prop_gbl/RULE_LAUNCH_CUSTOM
@@ -171,6 +172,7 @@ Properties on Targets
/prop_tgt/DEBUG_POSTFIX
/prop_tgt/DEFINE_SYMBOL
/prop_tgt/DEPLOYMENT_REMOTE_DIRECTORY
+ /prop_tgt/DOTNET_TARGET_FRAMEWORK_VERSION
/prop_tgt/EchoString
/prop_tgt/ENABLE_EXPORTS
/prop_tgt/EXCLUDE_FROM_ALL
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index 7636305..0f8502c 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -34,6 +34,7 @@ Variables that Provide Information
/variable/CMAKE_CURRENT_SOURCE_DIR
/variable/CMAKE_DIRECTORY_LABELS
/variable/CMAKE_DL_LIBS
+ /variable/CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION
/variable/CMAKE_EDIT_COMMAND
/variable/CMAKE_EXECUTABLE_SUFFIX
/variable/CMAKE_EXTRA_GENERATOR
diff --git a/Help/module/CPackNuGet.rst b/Help/module/CPackNuGet.rst
new file mode 100644
index 0000000..a4cbb59
--- /dev/null
+++ b/Help/module/CPackNuGet.rst
@@ -0,0 +1 @@
+.. cmake-module:: ../../Modules/CPackNuGet.cmake
diff --git a/Help/module/FindODBC.rst b/Help/module/FindODBC.rst
new file mode 100644
index 0000000..8558334
--- /dev/null
+++ b/Help/module/FindODBC.rst
@@ -0,0 +1 @@
+.. cmake-module:: ../../Modules/FindODBC.cmake
diff --git a/Help/prop_gbl/ECLIPSE_EXTRA_CPROJECT_CONTENTS.rst b/Help/prop_gbl/ECLIPSE_EXTRA_CPROJECT_CONTENTS.rst
new file mode 100644
index 0000000..50c41a9
--- /dev/null
+++ b/Help/prop_gbl/ECLIPSE_EXTRA_CPROJECT_CONTENTS.rst
@@ -0,0 +1,12 @@
+ECLIPSE_EXTRA_CPROJECT_CONTENTS
+-------------------------------
+
+Additional contents to be inserted into the generated Eclipse cproject file.
+
+The cproject file defines the CDT specific information. Some third party IDE's
+are based on Eclipse with the addition of other information specific to that IDE.
+Through this property, it is possible to add this additional contents to
+the generated project.
+It is expected to contain valid XML.
+
+Also see the :prop_gbl:`ECLIPSE_EXTRA_NATURES` property.
diff --git a/Help/prop_gbl/ECLIPSE_EXTRA_NATURES.rst b/Help/prop_gbl/ECLIPSE_EXTRA_NATURES.rst
index 6d1529d..a46575f 100644
--- a/Help/prop_gbl/ECLIPSE_EXTRA_NATURES.rst
+++ b/Help/prop_gbl/ECLIPSE_EXTRA_NATURES.rst
@@ -6,3 +6,5 @@ List of natures to add to the generated Eclipse project file.
Eclipse projects specify language plugins by using natures. This property
should be set to the unique identifier for a nature (which looks like a Java
package name).
+
+Also see the :prop_gbl:`ECLIPSE_EXTRA_CPROJECT_CONTENTS` property.
diff --git a/Help/prop_sf/COMPILE_FLAGS.rst b/Help/prop_sf/COMPILE_FLAGS.rst
index be81cf6..c211b89 100644
--- a/Help/prop_sf/COMPILE_FLAGS.rst
+++ b/Help/prop_sf/COMPILE_FLAGS.rst
@@ -3,9 +3,9 @@ COMPILE_FLAGS
Additional flags to be added when compiling this source file.
-The ``COMPILE_FLAGS`` property sets additional compiler flags used to build
-source files. Use :prop_sf:`COMPILE_DEFINITIONS` to pass additional
-preprocessor definitions.
+The ``COMPILE_FLAGS`` property, managed as a string, sets additional compiler
+flags used to build source files. Use :prop_sf:`COMPILE_DEFINITIONS` to pass
+additional preprocessor definitions.
Contents of ``COMPILE_FLAGS`` may use "generator expressions"
with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
@@ -13,3 +13,7 @@ manual for available expressions. However, :generator:`Xcode`
does not support per-config per-source settings, so expressions
that depend on the build configuration are not allowed with that
generator.
+
+.. note::
+
+ This property has been superseded by the :prop_sf:`COMPILE_OPTIONS` property.
diff --git a/Help/prop_sf/COMPILE_OPTIONS.rst b/Help/prop_sf/COMPILE_OPTIONS.rst
index 157c0b0..3b2bc8d 100644
--- a/Help/prop_sf/COMPILE_OPTIONS.rst
+++ b/Help/prop_sf/COMPILE_OPTIONS.rst
@@ -15,3 +15,7 @@ for available expressions. However, :generator:`Xcode`
does not support per-config per-source settings, so expressions
that depend on the build configuration are not allowed with that
generator.
+
+.. note::
+
+ This property should be preferred over the :prop_sf:`COMPILE_FLAGS` property.
diff --git a/Help/prop_tgt/DOTNET_TARGET_FRAMEWORK_VERSION.rst b/Help/prop_tgt/DOTNET_TARGET_FRAMEWORK_VERSION.rst
new file mode 100644
index 0000000..a2f7d7d
--- /dev/null
+++ b/Help/prop_tgt/DOTNET_TARGET_FRAMEWORK_VERSION.rst
@@ -0,0 +1,13 @@
+DOTNET_TARGET_FRAMEWORK_VERSION
+-------------------------------
+
+Specify the .NET target framework version.
+
+Used to specify the .NET target framework version for C++/CLI. For
+example, "v4.5".
+
+This property is only evaluated for :ref:`Visual Studio Generators`
+VS 2010 and above.
+
+Can be initialized for all targets using the variable
+:variable:`CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION`.
diff --git a/Help/prop_tgt/PDB_OUTPUT_DIRECTORY.rst b/Help/prop_tgt/PDB_OUTPUT_DIRECTORY.rst
index 730cf57..2f667f3 100644
--- a/Help/prop_tgt/PDB_OUTPUT_DIRECTORY.rst
+++ b/Help/prop_tgt/PDB_OUTPUT_DIRECTORY.rst
@@ -5,8 +5,14 @@ Output directory for the MS debug symbols ``.pdb`` file
generated by the linker for an executable or shared library target.
This property specifies the directory into which the MS debug symbols
-will be placed by the linker. This property is initialized by the
-value of the :variable:`CMAKE_PDB_OUTPUT_DIRECTORY` variable if it is
+will be placed by the linker. The property value may use
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
+Multi-configuration generators append a per-configuration
+subdirectory to the specified directory unless a generator expression
+is used.
+
+This property is initialized by the value of the
+:variable:`CMAKE_PDB_OUTPUT_DIRECTORY` variable if it is
set when a target is created.
.. |COMPILE_PDB_XXX| replace:: :prop_tgt:`COMPILE_PDB_OUTPUT_DIRECTORY`
diff --git a/Help/prop_tgt/PDB_OUTPUT_DIRECTORY_CONFIG.rst b/Help/prop_tgt/PDB_OUTPUT_DIRECTORY_CONFIG.rst
index 6037fa0..77fda90 100644
--- a/Help/prop_tgt/PDB_OUTPUT_DIRECTORY_CONFIG.rst
+++ b/Help/prop_tgt/PDB_OUTPUT_DIRECTORY_CONFIG.rst
@@ -11,5 +11,8 @@ property is initialized by the value of the
:variable:`CMAKE_PDB_OUTPUT_DIRECTORY_<CONFIG>` variable if it is
set when a target is created.
+Contents of ``PDB_OUTPUT_DIRECTORY_<CONFIG>`` may use
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
+
.. |COMPILE_PDB_XXX| replace:: :prop_tgt:`COMPILE_PDB_OUTPUT_DIRECTORY_<CONFIG>`
.. include:: PDB_NOTE.txt
diff --git a/Help/prop_tgt/VS_DOTNET_TARGET_FRAMEWORK_VERSION.rst b/Help/prop_tgt/VS_DOTNET_TARGET_FRAMEWORK_VERSION.rst
index 829d696..9f5a313 100644
--- a/Help/prop_tgt/VS_DOTNET_TARGET_FRAMEWORK_VERSION.rst
+++ b/Help/prop_tgt/VS_DOTNET_TARGET_FRAMEWORK_VERSION.rst
@@ -5,3 +5,6 @@ Specify the .NET target framework version.
Used to specify the .NET target framework version for C++/CLI. For
example, "v4.5".
+
+This property is deprecated and should not be used anymore. Use
+:prop_tgt:`DOTNET_TARGET_FRAMEWORK_VERSION` instead.
diff --git a/Help/release/3.11.rst b/Help/release/3.11.rst
index dbaa8af..971b3e2 100644
--- a/Help/release/3.11.rst
+++ b/Help/release/3.11.rst
@@ -283,3 +283,18 @@ Changes made since CMake 3.11.0 include the following.
CMake 3.11.0. This has been reverted due to changing behavior of
checks for existing projects. It may be restored in the future
with a policy for compatibility.
+
+3.11.2
+------
+
+* Calling :command:`add_library` to create an alias of an imported
+ target that is not globally visible now causes an error again as
+ it did prior to 3.11.0. This diagnostic was accidentally dropped
+ from CMake 3.11.0 and 3.11.1 by the change to allow globally visible
+ imported targets to be aliased.
+
+* The :module:`FindQt4` module ``qt4_wrap_cpp``, ``qt4_wrap_ui`` and
+ ``qt4_add_resources`` macros now set :prop_sf:`SKIP_AUTOMOC` and
+ :prop_sf:`SKIP_AUTOUIC` on their generated files. These files never
+ need to be processed by moc or uic, and we must say so explicitly to
+ account for policy :policy:`CMP0071`.
diff --git a/Help/release/dev/FindODBC-module.rst b/Help/release/dev/FindODBC-module.rst
new file mode 100644
index 0000000..f270e8e
--- /dev/null
+++ b/Help/release/dev/FindODBC-module.rst
@@ -0,0 +1,5 @@
+FindODBC-module
+---------------
+
+* A :module:`FindODBC` module was added to find an Open Database Connectivity
+ (ODBC) library.
diff --git a/Help/release/dev/FindPkgConfig-LINK_LIBRARIES.rst b/Help/release/dev/FindPkgConfig-LINK_LIBRARIES.rst
new file mode 100644
index 0000000..b915556
--- /dev/null
+++ b/Help/release/dev/FindPkgConfig-LINK_LIBRARIES.rst
@@ -0,0 +1,6 @@
+FindPkgConfig-LINK_LIBRARIES
+----------------------------
+
+* The :module:`FindPkgConfig` module has learned to export the found libraries
+ with full path for direct consumption with the :command:`target_link_libraries`
+ command.
diff --git a/Help/release/dev/PDBDirectoryGenExpression.rst b/Help/release/dev/PDBDirectoryGenExpression.rst
new file mode 100644
index 0000000..0b93a77
--- /dev/null
+++ b/Help/release/dev/PDBDirectoryGenExpression.rst
@@ -0,0 +1,5 @@
+PDBDirectoryGenExpression
+-------------------------
+
+* The :prop_tgt:`PDB_OUTPUT_DIRECTORY` property learned to support
+ :manual:`generator expressions <cmake-generator-expressions(7)>`.
diff --git a/Help/release/dev/copy_directory.rst b/Help/release/dev/copy_directory.rst
new file mode 100644
index 0000000..71b9fdf
--- /dev/null
+++ b/Help/release/dev/copy_directory.rst
@@ -0,0 +1,6 @@
+copy_directory
+--------------
+
+* The :manual:`cmake(1)` ``-E copy_directory`` tool now fails when the
+ source directory does not exist. Previously it succeeded by creating
+ an empty destination directory.
diff --git a/Help/release/dev/cpack-nuget.rst b/Help/release/dev/cpack-nuget.rst
new file mode 100644
index 0000000..03cb101
--- /dev/null
+++ b/Help/release/dev/cpack-nuget.rst
@@ -0,0 +1,7 @@
+cpack-nuget
+-----------
+
+* :manual:`cpack(1)` gained basic support for `NuGet`_.
+ See the :module:`CPackNuGet` module.
+
+.. _NuGet: https://docs.microsoft.com/en-us/nuget/what-is-nuget
diff --git a/Help/release/dev/ctest-start-args-rework.rst b/Help/release/dev/ctest-start-args-rework.rst
new file mode 100644
index 0000000..cbe6652
--- /dev/null
+++ b/Help/release/dev/ctest-start-args-rework.rst
@@ -0,0 +1,7 @@
+ctest-start-args-rework
+-----------------------
+
+* The :command:`ctest_start` command has been reworked so that you can simply
+ call ``ctest_start(APPEND)`` and it will read all the needed information from
+ the TAG file. The argument parsing has also been relaxed so that the order of
+ the arguments is less significant.
diff --git a/Help/release/dev/dotnet-target-framework-ver-init.rst b/Help/release/dev/dotnet-target-framework-ver-init.rst
new file mode 100644
index 0000000..fd1490c
--- /dev/null
+++ b/Help/release/dev/dotnet-target-framework-ver-init.rst
@@ -0,0 +1,11 @@
+dotnet-target-fw-initialization
+-------------------------------
+
+* The :prop_tgt:`DOTNET_TARGET_FRAMEWORK_VERSION` target property
+ was introduced as replacement for
+ :prop_tgt:`VS_DOTNET_TARGET_FRAMEWORK_VERSION`, which is considered
+ deprecated now.
+
+* The :variable:`CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION` variable
+ was defined to initialize all
+ :prop_tgt:`DOTNET_TARGET_FRAMEWORK_VERSION` target properties.
diff --git a/Help/release/dev/subdirectory-linking.rst b/Help/release/dev/subdirectory-linking.rst
new file mode 100644
index 0000000..1909c36
--- /dev/null
+++ b/Help/release/dev/subdirectory-linking.rst
@@ -0,0 +1,5 @@
+subdirectory-linking
+--------------------
+
+* The :command:`target_link_libraries` command may now be called
+ to modify targets created outside the current directory.
diff --git a/Help/variable/CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION.rst b/Help/variable/CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION.rst
new file mode 100644
index 0000000..124fefe
--- /dev/null
+++ b/Help/variable/CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION.rst
@@ -0,0 +1,16 @@
+CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION
+-------------------------------------
+
+Default value for :prop_tgt:`DOTNET_TARGET_FRAMEWORK_VERSION`
+property of targets.
+
+This variable is used to initialize the
+:prop_tgt:`DOTNET_TARGET_FRAMEWORK_VERSION` property on all
+targets. See that target property for additional information.
+
+Setting ``CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION`` may be necessary
+when working with ``C#`` and newer .NET framework versions to
+avoid referencing errors with the ``ALL_BUILD`` CMake target.
+
+This variable is only evaluated for :ref:`Visual Studio Generators`
+VS 2010 and above.
diff --git a/Modules/CMakeCUDAInformation.cmake b/Modules/CMakeCUDAInformation.cmake
index 479493b..8e62941 100644
--- a/Modules/CMakeCUDAInformation.cmake
+++ b/Modules/CMakeCUDAInformation.cmake
@@ -168,7 +168,7 @@ endif()
# compile a cu file into an executable
if(NOT CMAKE_CUDA_LINK_EXECUTABLE)
set(CMAKE_CUDA_LINK_EXECUTABLE
- "<CMAKE_CUDA_HOST_LINK_LAUNCHER> <CMAKE_CUDA_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICT_LINKS}")
+ "<CMAKE_CUDA_HOST_LINK_LAUNCHER> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICT_LINKS}")
endif()
if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "8.0.0")
@@ -194,11 +194,11 @@ unset(__IMPLICT_DLINK_DIRS)
#These are used when linking relocatable (dc) cuda code
if(NOT CMAKE_CUDA_DEVICE_LINK_LIBRARY)
set(CMAKE_CUDA_DEVICE_LINK_LIBRARY
- "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <CMAKE_CUDA_LINK_FLAGS> <LANGUAGE_COMPILE_FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICT_DLINK_FLAGS}")
+ "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <LANGUAGE_COMPILE_FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICT_DLINK_FLAGS}")
endif()
if(NOT CMAKE_CUDA_DEVICE_LINK_EXECUTABLE)
set(CMAKE_CUDA_DEVICE_LINK_EXECUTABLE
- "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <FLAGS> <CMAKE_CUDA_LINK_FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICT_DLINK_FLAGS}")
+ "<CMAKE_CUDA_COMPILER> ${CMAKE_CUDA_HOST_FLAGS} <FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICT_DLINK_FLAGS}")
endif()
unset(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS)
diff --git a/Modules/CPack.NuGet.nuspec.in b/Modules/CPack.NuGet.nuspec.in
new file mode 100644
index 0000000..b7beb5d
--- /dev/null
+++ b/Modules/CPack.NuGet.nuspec.in
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
+ <metadata>
+ <!-- Required elements-->
+ <id>@CPACK_NUGET_PACKAGE_NAME@</id>
+ <version>@CPACK_NUGET_PACKAGE_VERSION@</version>
+ <description>@CPACK_NUGET_PACKAGE_DESCRIPTION@</description>
+ <authors>@CPACK_NUGET_PACKAGE_AUTHORS@</authors>
+
+ <!-- Optional elements -->
+ @_CPACK_NUGET_TITLE_TAG@
+ @_CPACK_NUGET_OWNERS_TAG@
+ @_CPACK_NUGET_PROJECTURL_TAG@
+ @_CPACK_NUGET_LICENSEURL_TAG@
+ @_CPACK_NUGET_ICONURL_TAG@
+ @_CPACK_NUGET_REQUIRELICENSEACCEPTANCE_TAG@
+ @_CPACK_NUGET_SUMMARY_TAG@
+ @_CPACK_NUGET_RELEASENOTES_TAG@
+ @_CPACK_NUGET_COPYRIGHT_TAG@
+ @_CPACK_NUGET_TAGS_TAG@
+ @_CPACK_NUGET_DEPENDENCIES_TAG@
+ </metadata>
+ @_CPACK_NUGET_FILES_TAG@
+</package>
diff --git a/Modules/CPack.cmake b/Modules/CPack.cmake
index f6d74c5..8070869 100644
--- a/Modules/CPack.cmake
+++ b/Modules/CPack.cmake
@@ -1,326 +1,342 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
-#.rst:
-# CPack
-# -----
-#
-# Build binary and source package installers.
-#
-# Variables common to all CPack generators
-# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-#
-# The
-# CPack module generates binary and source installers in a variety of
-# formats using the cpack program. Inclusion of the CPack module adds
-# two new targets to the resulting makefiles, package and
-# package_source, which build the binary and source installers,
-# respectively. The generated binary installers contain everything
-# installed via CMake's INSTALL command (and the deprecated
-# INSTALL_FILES, INSTALL_PROGRAMS, and INSTALL_TARGETS commands).
-#
-# For certain kinds of binary installers (including the graphical
-# installers on Mac OS X and Windows), CPack generates installers that
-# allow users to select individual application components to install.
-# See CPackComponent module for that.
-#
-# The CPACK_GENERATOR variable has different meanings in different
-# contexts. In your CMakeLists.txt file, CPACK_GENERATOR is a *list of
-# generators*: when run with no other arguments, CPack will iterate over
-# that list and produce one package for each generator. In a
-# CPACK_PROJECT_CONFIG_FILE, though, CPACK_GENERATOR is a *string naming
-# a single generator*. If you need per-cpack- generator logic to
-# control *other* cpack settings, then you need a
-# CPACK_PROJECT_CONFIG_FILE.
-#
-# The CMake source tree itself contains a CPACK_PROJECT_CONFIG_FILE.
-# See the top level file CMakeCPackOptions.cmake.in for an example.
-#
-# If set, the CPACK_PROJECT_CONFIG_FILE is included automatically on a
-# per-generator basis. It only need contain overrides.
-#
-# Here's how it works:
-#
-# * cpack runs
-# * it includes CPackConfig.cmake
-# * it iterates over the generators given by the ``-G`` command line option,
-# or if no such option was specified, over the list of generators given by
-# the CPACK_GENERATOR variable set in the CPackConfig.cmake input file.
-# * foreach generator, it then
-#
-# - sets CPACK_GENERATOR to the one currently being iterated
-# - includes the CPACK_PROJECT_CONFIG_FILE
-# - produces the package for that generator
-#
-# This is the key: For each generator listed in CPACK_GENERATOR in
-# CPackConfig.cmake, cpack will *reset* CPACK_GENERATOR internally to
-# *the one currently being used* and then include the
-# CPACK_PROJECT_CONFIG_FILE.
-#
-# Before including this CPack module in your CMakeLists.txt file, there
-# are a variety of variables that can be set to customize the resulting
-# installers. The most commonly-used variables are:
-#
-# .. variable:: CPACK_PACKAGE_NAME
-#
-# The name of the package (or application). If not specified, defaults to
-# the project name.
-#
-# .. variable:: CPACK_PACKAGE_VENDOR
-#
-# The name of the package vendor. (e.g., "Kitware"). Default is "Humanity".
-#
-# .. variable:: CPACK_PACKAGE_DIRECTORY
-#
-# The directory in which CPack is doing its packaging. If it is not set
-# then this will default (internally) to the build dir. This variable may
-# be defined in CPack config file or from the cpack command line option
-# "-B". If set the command line option override the value found in the
-# config file.
-#
-# .. variable:: CPACK_PACKAGE_VERSION_MAJOR
-#
-# Package major version. This variable will always be set, but its default
-# value depends on whether or not version details were given to the
-# :command:`project` command in the top level CMakeLists.txt file. If version
-# details were given, the default value will be
-# :variable:`CMAKE_PROJECT_VERSION_MAJOR`. If no version details were given,
-# a default version of 0.1.1 will be assumed, leading to
-# ``CPACK_PACKAGE_VERSION_MAJOR`` having a default value of 0.
-#
-# .. variable:: CPACK_PACKAGE_VERSION_MINOR
-#
-# Package minor version. The default value is determined based on whether or
-# not version details were given to the :command:`project` command in the top
-# level CMakeLists.txt file. If version details were given, the default
-# value will be :variable:`CMAKE_PROJECT_VERSION_MINOR`, but if no minor
-# version component was specified then ``CPACK_PACKAGE_VERSION_MINOR`` will be
-# left unset. If no project version was given at all, a default version of
-# 0.1.1 will be assumed, leading to ``CPACK_PACKAGE_VERSION_MINOR`` having a
-# default value of 1.
-#
-# .. variable:: CPACK_PACKAGE_VERSION_PATCH
-#
-# Package patch version. The default value is determined based on whether or
-# not version details were given to the :command:`project` command in the top
-# level CMakeLists.txt file. If version details were given, the default
-# value will be :variable:`CMAKE_PROJECT_VERSION_PATCH`, but if no patch
-# version component was specified then ``CPACK_PACKAGE_VERSION_PATCH`` will be
-# left unset. If no project version was given at all, a default version of
-# 0.1.1 will be assumed, leading to ``CPACK_PACKAGE_VERSION_PATCH`` having a
-# default value of 1.
-#
-# .. variable:: CPACK_PACKAGE_DESCRIPTION_FILE
-#
-# A text file used to describe the project. Used, for example, the
-# introduction screen of a CPack-generated Windows installer to describe
-# the project.
-#
-# .. variable:: CPACK_PACKAGE_DESCRIPTION_SUMMARY
-#
-# Short description of the project (only a few words). Default value is::
-#
-# ${CMAKE_PROJECT_DESCRIPTION}
-#
-# if DESCRIPTION has given to the project() call or
-# CMake generated string with PROJECT_NAME otherwise.
-#
-# .. variable:: CPACK_PACKAGE_HOMEPAGE_URL
-#
-# Project homepage URL. Default value is::
-#
-# ${CMAKE_PROJECT_HOMEPAGE_URL}
-#
-# if HOMEPAGE_URL has given to the project().
-#
-# .. variable:: CPACK_PACKAGE_FILE_NAME
-#
-# The name of the package file to generate, not including the
-# extension. For example, cmake-2.6.1-Linux-i686. The default value is::
-#
-# ${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CPACK_SYSTEM_NAME}.
-#
-# .. variable:: CPACK_PACKAGE_INSTALL_DIRECTORY
-#
-# Installation directory on the target system. This may be used by some
-# CPack generators like NSIS to create an installation directory e.g.,
-# "CMake 2.5" below the installation prefix. All installed element will be
-# put inside this directory.
-#
-# .. variable:: CPACK_PACKAGE_ICON
-#
-# A branding image that will be displayed inside the installer (used by GUI
-# installers).
-#
-# .. variable:: CPACK_PACKAGE_CHECKSUM
-#
-# An algorithm that will be used to generate additional file with checksum
-# of the package. Output file name will be::
-#
-# ${CPACK_PACKAGE_FILE_NAME}.${CPACK_PACKAGE_CHECKSUM}
-#
-# Supported algorithms are those listed by the
-# :ref:`string(\<HASH\>) <Supported Hash Algorithms>`
-# command.
-#
-# .. variable:: CPACK_PROJECT_CONFIG_FILE
-#
-# CPack-time project CPack configuration file. This file included at cpack
-# time, once per generator after CPack has set CPACK_GENERATOR to the
-# actual generator being used. It allows per-generator setting of CPACK_*
-# variables at cpack time.
-#
-# .. variable:: CPACK_RESOURCE_FILE_LICENSE
-#
-# License to be embedded in the installer. It will typically be displayed
-# to the user by the produced installer (often with an explicit "Accept"
-# button, for graphical installers) prior to installation. This license
-# file is NOT added to installed file but is used by some CPack generators
-# like NSIS. If you want to install a license file (may be the same as this
-# one) along with your project you must add an appropriate CMake INSTALL
-# command in your CMakeLists.txt.
-#
-# .. variable:: CPACK_RESOURCE_FILE_README
-#
-# ReadMe file to be embedded in the installer. It typically describes in
-# some detail the purpose of the project during the installation. Not all
-# CPack generators uses this file.
-#
-# .. variable:: CPACK_RESOURCE_FILE_WELCOME
-#
-# Welcome file to be embedded in the installer. It welcomes users to this
-# installer. Typically used in the graphical installers on Windows and Mac
-# OS X.
-#
-# .. variable:: CPACK_MONOLITHIC_INSTALL
-#
-# Disables the component-based installation mechanism. When set the
-# component specification is ignored and all installed items are put in a
-# single "MONOLITHIC" package. Some CPack generators do monolithic
-# packaging by default and may be asked to do component packaging by
-# setting CPACK_<GENNAME>_COMPONENT_INSTALL to 1/TRUE.
-#
-# .. variable:: CPACK_GENERATOR
-#
-# List of CPack generators to use. If not specified, CPack will create a
-# set of options CPACK_BINARY_<GENNAME> (e.g., CPACK_BINARY_NSIS) allowing
-# the user to enable/disable individual generators. If the ``-G`` option
-# is given on the :manual:`cpack <cpack(1)>` command line, it will override
-# this variable and any CPACK_BINARY_<GENNAME> options.
-#
-# .. variable:: CPACK_OUTPUT_CONFIG_FILE
-#
-# The name of the CPack binary configuration file. This file is the CPack
-# configuration generated by the CPack module for binary
-# installers. Defaults to CPackConfig.cmake.
-#
-# .. variable:: CPACK_PACKAGE_EXECUTABLES
-#
-# Lists each of the executables and associated text label to be used to
-# create Start Menu shortcuts. For example, setting this to the list
-# ccmake;CMake will create a shortcut named "CMake" that will execute the
-# installed executable ccmake. Not all CPack generators use it (at least
-# NSIS, WIX and OSXX11 do).
-#
-# .. variable:: CPACK_STRIP_FILES
-#
-# List of files to be stripped. Starting with CMake 2.6.0 CPACK_STRIP_FILES
-# will be a boolean variable which enables stripping of all files (a list
-# of files evaluates to TRUE in CMake, so this change is compatible).
-#
-# .. variable:: CPACK_VERBATIM_VARIABLES
-#
-# If set to TRUE, values of variables prefixed with CPACK_ will be escaped
-# before being written to the configuration files, so that the cpack program
-# receives them exactly as they were specified. If not, characters like quotes
-# and backslashes can cause parsing errors or alter the value received by the
-# cpack program. Defaults to FALSE for backwards compatibility.
-#
-# * Mandatory : NO
-# * Default : FALSE
-#
-# The following CPack variables are specific to source packages, and
-# will not affect binary packages:
-#
-# .. variable:: CPACK_SOURCE_PACKAGE_FILE_NAME
-#
-# The name of the source package. For example cmake-2.6.1.
-#
-# .. variable:: CPACK_SOURCE_STRIP_FILES
-#
-# List of files in the source tree that will be stripped. Starting with
-# CMake 2.6.0 CPACK_SOURCE_STRIP_FILES will be a boolean variable which
-# enables stripping of all files (a list of files evaluates to TRUE in
-# CMake, so this change is compatible).
-#
-# .. variable:: CPACK_SOURCE_GENERATOR
-#
-# List of generators used for the source packages. As with CPACK_GENERATOR,
-# if this is not specified then CPack will create a set of options (e.g.,
-# CPACK_SOURCE_ZIP) allowing users to select which packages will be
-# generated.
-#
-# .. variable:: CPACK_SOURCE_OUTPUT_CONFIG_FILE
-#
-# The name of the CPack source configuration file. This file is the CPack
-# configuration generated by the CPack module for source
-# installers. Defaults to CPackSourceConfig.cmake.
-#
-# .. variable:: CPACK_SOURCE_IGNORE_FILES
-#
-# Pattern of files in the source tree that won't be packaged when building
-# a source package. This is a list of regular expression patterns (that
-# must be properly escaped), e.g.,
-# /CVS/;/\\.svn/;\\.swp$;\\.#;/#;.*~;cscope.*
-#
-# The following variables are for advanced uses of CPack:
-#
-# .. variable:: CPACK_CMAKE_GENERATOR
-#
-# What CMake generator should be used if the project is CMake
-# project. Defaults to the value of CMAKE_GENERATOR few users will want to
-# change this setting.
-#
-# .. variable:: CPACK_INSTALL_CMAKE_PROJECTS
-#
-# List of four values that specify what project to install. The four values
-# are: Build directory, Project Name, Project Component, Directory. If
-# omitted, CPack will build an installer that installs everything.
-#
-# .. variable:: CPACK_SYSTEM_NAME
-#
-# System name, defaults to the value of ${CMAKE_SYSTEM_NAME}, except on
-# Windows where it will be "win32" or "win64".
-#
-# .. variable:: CPACK_PACKAGE_VERSION
-#
-# Package full version, used internally. By default, this is built from
-# CPACK_PACKAGE_VERSION_MAJOR, CPACK_PACKAGE_VERSION_MINOR, and
-# CPACK_PACKAGE_VERSION_PATCH.
-#
-# .. variable:: CPACK_TOPLEVEL_TAG
-#
-# Directory for the installed files.
-#
-# .. variable:: CPACK_INSTALL_COMMANDS
-#
-# Extra commands to install components.
-#
-# .. variable:: CPACK_INSTALLED_DIRECTORIES
-#
-# Extra directories to install.
-#
-# .. variable:: CPACK_PACKAGE_INSTALL_REGISTRY_KEY
-#
-# Registry key used when installing this project. This is only used by
-# installer for Windows. The default value is based on the installation
-# directory.
-#
-# .. variable:: CPACK_CREATE_DESKTOP_LINKS
-#
-# List of desktop links to create.
-# Each desktop link requires a corresponding start menu shortcut
-# as created by :variable:`CPACK_PACKAGE_EXECUTABLES`.
+#[=======================================================================[.rst:
+CPack
+-----
+
+Build binary and source package installers.
+
+Variables common to all CPack generators
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The CPack module generates binary and source installers in a variety of
+formats using the cpack program. Inclusion of the CPack module adds
+two new build targets, ``package`` and ``package_source``, which build
+the binary and source installers respectively. The generated binary
+installers contain everything installed via CMake's :command:`install`
+command (and the deprecated :command:`install_files`,
+:command:`install_programs` and :command:`install_targets` commands).
+
+For certain kinds of binary installers (including the graphical
+installers on Mac OS X and Windows), CPack generates installers that
+allow users to select individual application components to install.
+See :module:`CPackComponent` module for further details.
+
+The :variable:`CPACK_GENERATOR` variable has different meanings in different
+contexts. In a ``CMakeLists.txt`` file, :variable:`CPACK_GENERATOR` is a
+*list of generators*: and when :manual:`cpack <cpack(1)>` is run with no other
+arguments, it will iterate over that list and produce one package for each
+generator. In a :variable:`CPACK_PROJECT_CONFIG_FILE`,
+:variable:`CPACK_GENERATOR` is a *string naming a single generator*. If you
+need per-cpack-generator logic to control *other* cpack settings, then you
+need a :variable:`CPACK_PROJECT_CONFIG_FILE`.
+
+The CMake source tree itself contains a :variable:`CPACK_PROJECT_CONFIG_FILE`.
+See the top level file ``CMakeCPackOptions.cmake.in`` for an example.
+
+If set, the :variable:`CPACK_PROJECT_CONFIG_FILE` is included automatically
+on a per-generator basis. It only need contain overrides.
+
+Here's how it works:
+
+* :manual:`cpack <cpack(1)>` runs
+* it includes ``CPackConfig.cmake``
+* it iterates over the generators given by the ``-G`` command line option,
+ or if no such option was specified, over the list of generators given by
+ the :variable:`CPACK_GENERATOR` variable set in the ``CPackConfig.cmake``
+ input file.
+* foreach generator, it then
+
+ - sets :variable:`CPACK_GENERATOR` to the one currently being iterated
+ - includes the :variable:`CPACK_PROJECT_CONFIG_FILE`
+ - produces the package for that generator
+
+This is the key: For each generator listed in :variable:`CPACK_GENERATOR` in
+``CPackConfig.cmake``, cpack will *reset* :variable:`CPACK_GENERATOR`
+internally to *the one currently being used* and then include the
+:variable:`CPACK_PROJECT_CONFIG_FILE`.
+
+Before including this CPack module in your ``CMakeLists.txt`` file, there
+are a variety of variables that can be set to customize the resulting
+installers. The most commonly-used variables are:
+
+.. variable:: CPACK_PACKAGE_NAME
+
+ The name of the package (or application). If not specified, it defaults to
+ the project name.
+
+.. variable:: CPACK_PACKAGE_VENDOR
+
+ The name of the package vendor. (e.g., "Kitware"). The default is "Humanity".
+
+.. variable:: CPACK_PACKAGE_DIRECTORY
+
+ The directory in which CPack is doing its packaging. If it is not set
+ then this will default (internally) to the build dir. This variable may
+ be defined in a CPack config file or from the :manual:`cpack <cpack(1)>`
+ command line option ``-B``. If set, the command line option overrides the
+ value found in the config file.
+
+.. variable:: CPACK_PACKAGE_VERSION_MAJOR
+
+ Package major version. This variable will always be set, but its default
+ value depends on whether or not version details were given to the
+ :command:`project` command in the top level CMakeLists.txt file. If version
+ details were given, the default value will be
+ :variable:`CMAKE_PROJECT_VERSION_MAJOR`. If no version details were given,
+ a default version of 0.1.1 will be assumed, leading to
+ ``CPACK_PACKAGE_VERSION_MAJOR`` having a default value of 0.
+
+.. variable:: CPACK_PACKAGE_VERSION_MINOR
+
+ Package minor version. The default value is determined based on whether or
+ not version details were given to the :command:`project` command in the top
+ level CMakeLists.txt file. If version details were given, the default
+ value will be :variable:`CMAKE_PROJECT_VERSION_MINOR`, but if no minor
+ version component was specified then ``CPACK_PACKAGE_VERSION_MINOR`` will be
+ left unset. If no project version was given at all, a default version of
+ 0.1.1 will be assumed, leading to ``CPACK_PACKAGE_VERSION_MINOR`` having a
+ default value of 1.
+
+.. variable:: CPACK_PACKAGE_VERSION_PATCH
+
+ Package patch version. The default value is determined based on whether or
+ not version details were given to the :command:`project` command in the top
+ level CMakeLists.txt file. If version details were given, the default
+ value will be :variable:`CMAKE_PROJECT_VERSION_PATCH`, but if no patch
+ version component was specified then ``CPACK_PACKAGE_VERSION_PATCH`` will be
+ left unset. If no project version was given at all, a default version of
+ 0.1.1 will be assumed, leading to ``CPACK_PACKAGE_VERSION_PATCH`` having a
+ default value of 1.
+
+.. variable:: CPACK_PACKAGE_DESCRIPTION
+
+ A description of the project, used in places such as the introduction
+ screen of CPack-generated Windows installers. If not set, the value of
+ this variable is populated from the file named by
+ :variable:`CPACK_PACKAGE_DESCRIPTION_FILE`.
+
+.. variable:: CPACK_PACKAGE_DESCRIPTION_FILE
+
+ A text file used to describe the project when
+ :variable:`CPACK_PACKAGE_DESCRIPTION` is not explicitly set. The default
+ value for ``CPACK_PACKAGE_DESCRIPTION_FILE`` points to a built-in template
+ file ``Templates/CPack.GenericDescription.txt``.
+
+.. variable:: CPACK_PACKAGE_DESCRIPTION_SUMMARY
+
+ Short description of the project (only a few words). If the
+ :variable:`CMAKE_PROJECT_DESCRIPTION` variable is set, it is used as the
+ default value, otherwise the default will be a string generated by CMake
+ based on :variable:`CMAKE_PROJECT_NAME`.
+
+.. variable:: CPACK_PACKAGE_HOMEPAGE_URL
+
+ Project homepage URL. The default value is taken from the
+ :variable:`CMAKE_PROJECT_HOMEPAGE_URL` variable, which is set by the top
+ level :command:`project` command, or else the default will be empty if no
+ URL was provided to :command:`project`.
+
+.. variable:: CPACK_PACKAGE_FILE_NAME
+
+ The name of the package file to generate, not including the
+ extension. For example, ``cmake-2.6.1-Linux-i686``. The default value
+ is::
+
+ ${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CPACK_SYSTEM_NAME}
+
+.. variable:: CPACK_PACKAGE_INSTALL_DIRECTORY
+
+ Installation directory on the target system. This may be used by some
+ CPack generators like NSIS to create an installation directory e.g.,
+ "CMake 2.5" below the installation prefix. All installed elements will be
+ put inside this directory.
+
+.. variable:: CPACK_PACKAGE_ICON
+
+ A branding image that will be displayed inside the installer (used by GUI
+ installers).
+
+.. variable:: CPACK_PACKAGE_CHECKSUM
+
+ An algorithm that will be used to generate an additional file with the
+ checksum of the package. The output file name will be::
+
+ ${CPACK_PACKAGE_FILE_NAME}.${CPACK_PACKAGE_CHECKSUM}
+
+ Supported algorithms are those listed by the
+ :ref:`string(\<HASH\>) <Supported Hash Algorithms>` command.
+
+.. variable:: CPACK_PROJECT_CONFIG_FILE
+
+ CPack-time project CPack configuration file. This file is included at cpack
+ time, once per generator after CPack has set :variable:`CPACK_GENERATOR`
+ to the actual generator being used. It allows per-generator setting of
+ ``CPACK_*`` variables at cpack time.
+
+.. variable:: CPACK_RESOURCE_FILE_LICENSE
+
+ License to be embedded in the installer. It will typically be displayed
+ to the user by the produced installer (often with an explicit "Accept"
+ button, for graphical installers) prior to installation. This license
+ file is NOT added to the installed files but is used by some CPack generators
+ like NSIS. If you want to install a license file (may be the same as this
+ one) along with your project, you must add an appropriate CMake
+ :command:`install` command in your ``CMakeLists.txt``.
+
+.. variable:: CPACK_RESOURCE_FILE_README
+
+ ReadMe file to be embedded in the installer. It typically describes in
+ some detail the purpose of the project during the installation. Not all
+ CPack generators use this file.
+
+.. variable:: CPACK_RESOURCE_FILE_WELCOME
+
+ Welcome file to be embedded in the installer. It welcomes users to this
+ installer. Typically used in the graphical installers on Windows and Mac
+ OS X.
+
+.. variable:: CPACK_MONOLITHIC_INSTALL
+
+ Disables the component-based installation mechanism. When set, the
+ component specification is ignored and all installed items are put in a
+ single "MONOLITHIC" package. Some CPack generators do monolithic
+ packaging by default and may be asked to do component packaging by
+ setting ``CPACK_<GENNAME>_COMPONENT_INSTALL`` to ``TRUE``.
+
+.. variable:: CPACK_GENERATOR
+
+ List of CPack generators to use. If not specified, CPack will create a
+ set of options following the naming pattern
+ :variable:`CPACK_BINARY_<GENNAME>` (e.g. ``CPACK_BINARY_NSIS``) allowing
+ the user to enable/disable individual generators. If the ``-G`` option is
+ given on the :manual:`cpack <cpack(1)>` command line, it will override this
+ variable and any ``CPACK_BINARY_<GENNAME>`` options.
+
+.. variable:: CPACK_OUTPUT_CONFIG_FILE
+
+ The name of the CPack binary configuration file. This file is the CPack
+ configuration generated by the CPack module for binary installers.
+ Defaults to ``CPackConfig.cmake``.
+
+.. variable:: CPACK_PACKAGE_EXECUTABLES
+
+ Lists each of the executables and associated text label to be used to
+ create Start Menu shortcuts. For example, setting this to the list
+ ``ccmake;CMake`` will create a shortcut named "CMake" that will execute the
+ installed executable ``ccmake``. Not all CPack generators use it (at least
+ NSIS, WIX and OSXX11 do).
+
+.. variable:: CPACK_STRIP_FILES
+
+ List of files to be stripped. Starting with CMake 2.6.0,
+ ``CPACK_STRIP_FILES`` will be a boolean variable which enables
+ stripping of all files (a list of files evaluates to ``TRUE`` in CMake,
+ so this change is compatible).
+
+.. variable:: CPACK_VERBATIM_VARIABLES
+
+ If set to ``TRUE``, values of variables prefixed with ``CPACK_`` will be
+ escaped before being written to the configuration files, so that the cpack
+ program receives them exactly as they were specified. If not, characters
+ like quotes and backslashes can cause parsing errors or alter the value
+ received by the cpack program. Defaults to ``FALSE`` for backwards
+ compatibility.
+
+The following CPack variables are specific to source packages, and
+will not affect binary packages:
+
+.. variable:: CPACK_SOURCE_PACKAGE_FILE_NAME
+
+ The name of the source package. For example ``cmake-2.6.1``.
+
+.. variable:: CPACK_SOURCE_STRIP_FILES
+
+ List of files in the source tree that will be stripped. Starting with
+ CMake 2.6.0, ``CPACK_SOURCE_STRIP_FILES`` will be a boolean
+ variable which enables stripping of all files (a list of files evaluates
+ to ``TRUE`` in CMake, so this change is compatible).
+
+.. variable:: CPACK_SOURCE_GENERATOR
+
+ List of generators used for the source packages. As with
+ :variable:`CPACK_GENERATOR`, if this is not specified then CPack will
+ create a set of options (e.g. ``CPACK_SOURCE_ZIP``) allowing
+ users to select which packages will be generated.
+
+.. variable:: CPACK_SOURCE_OUTPUT_CONFIG_FILE
+
+ The name of the CPack source configuration file. This file is the CPack
+ configuration generated by the CPack module for source installers.
+ Defaults to ``CPackSourceConfig.cmake``.
+
+.. variable:: CPACK_SOURCE_IGNORE_FILES
+
+ Pattern of files in the source tree that won't be packaged when building
+ a source package. This is a list of regular expression patterns (that
+ must be properly escaped), e.g.,
+ ``/CVS/;/\\.svn/;\\.swp$;\\.#;/#;.*~;cscope.*``
+
+The following variables are for advanced uses of CPack:
+
+.. variable:: CPACK_CMAKE_GENERATOR
+
+ What CMake generator should be used if the project is a CMake
+ project. Defaults to the value of :variable:`CMAKE_GENERATOR`. Few users
+ will want to change this setting.
+
+.. variable:: CPACK_INSTALL_CMAKE_PROJECTS
+
+ List of four values that specify what project to install. The four values
+ are: Build directory, Project Name, Project Component, Directory. If
+ omitted, CPack will build an installer that installs everything.
+
+.. variable:: CPACK_SYSTEM_NAME
+
+ System name, defaults to the value of :variable:`CMAKE_SYSTEM_NAME`,
+ except on Windows where it will be ``win32`` or ``win64``.
+
+.. variable:: CPACK_PACKAGE_VERSION
+
+ Package full version, used internally. By default, this is built from
+ :variable:`CPACK_PACKAGE_VERSION_MAJOR`,
+ :variable:`CPACK_PACKAGE_VERSION_MINOR`, and
+ :variable:`CPACK_PACKAGE_VERSION_PATCH`.
+
+.. variable:: CPACK_TOPLEVEL_TAG
+
+ Directory for the installed files.
+
+.. variable:: CPACK_INSTALL_COMMANDS
+
+ Extra commands to install components.
+
+.. variable:: CPACK_INSTALLED_DIRECTORIES
+
+ Extra directories to install.
+
+.. variable:: CPACK_PACKAGE_INSTALL_REGISTRY_KEY
+
+ Registry key used when installing this project. This is only used by
+ installers for Windows. The default value is based on the installation
+ directory.
+
+.. variable:: CPACK_CREATE_DESKTOP_LINKS
+
+ List of desktop links to create. Each desktop link requires a
+ corresponding start menu shortcut as created by
+ :variable:`CPACK_PACKAGE_EXECUTABLES`.
+
+.. variable:: CPACK_BINARY_<GENNAME>
+
+ CPack generated options for binary generators. The ``CPack.cmake`` module
+ generates (when :variable:`CPACK_GENERATOR` is not set) a set of CMake
+ options (see CMake :command:`option` command) which may then be used to
+ select the CPack generator(s) to be used when building the ``package``
+ target or when running :manual:`cpack <cpack(1)>` without the ``-G`` option.
+
+#]=======================================================================]
# Define this var in order to avoid (or warn) concerning multiple inclusion
if(CPack_CMake_INCLUDED)
@@ -501,16 +517,9 @@ macro(cpack_optional_append _list _cond _item)
endif()
endmacro()
-#.rst:
-# .. variable:: CPACK_BINARY_<GENNAME>
-#
-# CPack generated options for binary generators. The CPack.cmake module
-# generates (when CPACK_GENERATOR is not set) a set of CMake options (see
-# CMake option command) which may then be used to select the CPack
-# generator(s) to be used when launching the package target.
-#
-# Provide options to choose generators we might check here if the required
-# tools for the generates exist and set the defaults according to the results
+# Provide options to choose generators we might check here if the required
+# tools for the generators exist and set the defaults according to the
+# results.
if(NOT CPACK_GENERATOR)
if(UNIX)
if(CYGWIN)
@@ -535,10 +544,11 @@ if(NOT CPACK_GENERATOR)
option(CPACK_BINARY_TXZ "Enable to build TXZ packages" OFF)
endif()
else()
- option(CPACK_BINARY_7Z "Enable to build 7-Zip packages" OFF)
- option(CPACK_BINARY_NSIS "Enable to build NSIS packages" ON)
- option(CPACK_BINARY_WIX "Enable to build WiX packages" OFF)
- option(CPACK_BINARY_ZIP "Enable to build ZIP packages" OFF)
+ option(CPACK_BINARY_7Z "Enable to build 7-Zip packages" OFF)
+ option(CPACK_BINARY_NSIS "Enable to build NSIS packages" ON)
+ option(CPACK_BINARY_NUGET "Enable to build NuGet packages" OFF)
+ option(CPACK_BINARY_WIX "Enable to build WiX packages" OFF)
+ option(CPACK_BINARY_ZIP "Enable to build ZIP packages" OFF)
endif()
option(CPACK_BINARY_IFW "Enable to build IFW packages" OFF)
@@ -550,6 +560,7 @@ if(NOT CPACK_GENERATOR)
cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_FREEBSD FREEBSD)
cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_IFW IFW)
cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_NSIS NSIS)
+ cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_NUGET NuGet)
cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_OSXX11 OSXX11)
cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_PACKAGEMAKER PackageMaker)
cpack_optional_append(CPACK_GENERATOR CPACK_BINARY_PRODUCTBUILD productbuild)
@@ -602,6 +613,7 @@ mark_as_advanced(
CPACK_BINARY_FREEBSD
CPACK_BINARY_IFW
CPACK_BINARY_NSIS
+ CPACK_BINARY_NUGET
CPACK_BINARY_OSXX11
CPACK_BINARY_PACKAGEMAKER
CPACK_BINARY_PRODUCTBUILD
diff --git a/Modules/CPackNuGet.cmake b/Modules/CPackNuGet.cmake
new file mode 100644
index 0000000..29d4296
--- /dev/null
+++ b/Modules/CPackNuGet.cmake
@@ -0,0 +1,556 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+CPackNuGet
+----------
+
+When build a NuGet pacakge there is no direct way to control an output
+filename due a lack of the corresponding CLI option of NuGet, so there
+is no ``CPACK_NUGET_PACKAGE_FILENAME`` variable. To form the output filename
+NuGet uses the package name and the version according to its built-in rules.
+
+Also, be aware that including a top level directory
+(``CPACK_INCLUDE_TOPLEVEL_DIRECTORY``) is ignored by this generator.
+
+
+Variables specific to CPack NuGet generator
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+CPackNuGet may be used to create NuGet packages using :module:`CPack`.
+CPackNuGet is a :module:`CPack` generator thus it uses the ``CPACK_XXX``
+variables used by :module:`CPack`.
+
+CPackNuGet has specific features which are controlled by the specifics
+:code:`CPACK_NUGET_XXX` variables. In the "one per group" mode
+(see :variable:`CPACK_COMPONENTS_GROUPING`), ``<compName>`` placeholder
+in the variables below would contain a group name (uppercased and turned into
+a "C" identifier).
+
+List of CPackNuGet specific variables:
+
+.. variable:: CPACK_NUGET_COMPONENT_INSTALL
+
+ Enable component packaging for CPackNuGet
+
+ * Mandatory : NO
+ * Default : OFF
+
+.. variable:: CPACK_NUGET_PACKAGE_NAME
+ CPACK_NUGET_<compName>_PACKAGE_NAME
+
+ The NUGET package name.
+
+ * Mandatory : YES
+ * Default : :variable:`CPACK_PACKAGE_NAME`
+
+.. variable:: CPACK_NUGET_PACKAGE_VERSION
+ CPACK_NUGET_<compName>_PACKAGE_VERSION
+
+ The NuGet package version.
+
+ * Mandatory : YES
+ * Default : :variable:`CPACK_PACKAGE_VERSION`
+
+.. variable:: CPACK_NUGET_PACKAGE_DESCRIPTION
+ CPACK_NUGET_<compName>_PACKAGE_DESCRIPTION
+
+ A long description of the package for UI display.
+
+ * Mandatory : YES
+ * Default :
+ - :variable:`CPACK_COMPONENT_<compName>_DESCRIPTION`,
+ - ``CPACK_COMPONENT_GROUP_<groupName>_DESCRIPTION``,
+ - :variable:`CPACK_PACKAGE_DESCRIPTION`
+
+ .. variable:: CPACK_NUGET_PACKAGE_AUTHORS
+ CPACK_NUGET_<compName>_PACKAGE_AUTHORS
+
+ A comma-separated list of packages authors, matching the profile names
+ on nuget.org_. These are displayed in the NuGet Gallery on
+ nuget.org_ and are used to cross-reference packages by the same
+ authors.
+
+ * Mandatory : YES
+ * Default : :variable:`CPACK_PACKAGE_VENDOR`
+
+.. variable:: CPACK_NUGET_PACKAGE_TITLE
+ CPACK_NUGET_<compName>_PACKAGE_TITLE
+
+ A human-friendly title of the package, typically used in UI displays
+ as on nuget.org_ and the Package Manager in Visual Studio. If not
+ specified, the package ID is used.
+
+ * Mandatory : NO
+ * Default :
+ - :variable:`CPACK_COMPONENT_<compName>_DISPLAY_NAME`,
+ - ``CPACK_COMPONENT_GROUP_<groupName>_DISPLAY_NAME``
+
+.. variable:: CPACK_NUGET_PACKAGE_OWNERS
+ CPACK_NUGET_<compName>_PACKAGE_OWNERS
+
+ A comma-separated list of the package creators using profile names
+ on nuget.org_. This is often the same list as in authors,
+ and is ignored when uploading the package to nuget.org_.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_NUGET_PACKAGE_HOMEPAGE_URL
+ CPACK_NUGET_<compName>_PACKAGE_HOMEPAGE_URL
+
+ A URL for the package's home page, often shown in UI displays as well
+ as nuget.org_.
+
+ * Mandatory : NO
+ * Default : :variable:`CPACK_PACKAGE_HOMEPAGE_URL`
+
+.. variable:: CPACK_NUGET_PACKAGE_LICENSEURL
+ CPACK_NUGET_<compName>_PACKAGE_LICENSEURL
+
+ A URL for the package's license, often shown in UI displays as well
+ as nuget.org_.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_NUGET_PACKAGE_ICONURL
+ CPACK_NUGET_<compName>_PACKAGE_ICONURL
+
+ A URL for a 64x64 image with transparency background to use as the
+ icon for the package in UI display.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_NUGET_PACKAGE_DESCRIPTION_SUMMARY
+ CPACK_NUGET_<compName>_PACKAGE_DESCRIPTION_SUMMARY
+
+ A short description of the package for UI display. If omitted, a
+ truncated version of description is used.
+
+ * Mandatory : NO
+ * Default : :variable:`CPACK_PACKAGE_DESCRIPTION_SUMMARY`
+
+.. variable:: CPACK_NUGET_PACKAGE_RELEASE_NOTES
+ CPACK_NUGET_<compName>_PACKAGE_RELEASE_NOTES
+
+ A description of the changes made in this release of the package,
+ often used in UI like the Updates tab of the Visual Studio Package
+ Manager in place of the package description.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_NUGET_PACKAGE_COPYRIGHT
+ CPACK_NUGET_<compName>_PACKAGE_COPYRIGHT
+
+ Copyright details for the package.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_NUGET_PACKAGE_TAGS
+ CPACK_NUGET_<compName>_PACKAGE_TAGS
+
+ A space-delimited list of tags and keywords that describe the
+ package and aid discoverability of packages through search and
+ filtering.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_NUGET_PACKAGE_DEPENDENCIES
+ CPACK_NUGET_<compName>_PACKAGE_DEPENDENCIES
+
+ A list of package dependencies.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_NUGET_PACKAGE_DEPENDENCIES_<dependency>_VERSION
+ CPACK_NUGET_<compName>_PACKAGE_DEPENDENCIES_<dependency>_VERSION
+
+ A `version specification`_ for the particular dependency, where
+ ``<dependency>`` is an item of the dependency list (see above)
+ transformed with ``MAKE_C_IDENTIFIER`` function of :command:`string`
+ command.
+
+ * Mandatory : NO
+ * Default : -
+
+.. variable:: CPACK_NUGET_PACKAGE_DEBUG
+
+ Enable debug messages while executing ``CPackNuGet.cmake``.
+
+ * Mandatory : NO
+ * Default : OFF
+
+
+.. _nuget.org: http://nuget.org
+.. _version specification: https://docs.microsoft.com/en-us/nuget/reference/package-versioning#version-ranges-and-wildcards
+
+.. NuGet spec docs https://docs.microsoft.com/en-us/nuget/reference/nuspec
+
+#]=======================================================================]
+
+# Author: Alex Turbov
+
+if(CMAKE_BINARY_DIR)
+ message(FATAL_ERROR "CPackNuGet.cmake may only be used by CPack internally.")
+endif()
+
+function(_cpack_nuget_debug)
+ if(CPACK_NUGET_PACKAGE_DEBUG)
+ message("CPackNuGet:Debug: " ${ARGN})
+ endif()
+endfunction()
+
+function(_cpack_nuget_debug_var NAME)
+ if(CPACK_NUGET_PACKAGE_DEBUG)
+ message("CPackNuGet:Debug: ${NAME}=`${${NAME}}`")
+ endif()
+endfunction()
+
+function(_cpack_nuget_variable_fallback OUTPUT_VAR_NAME NUGET_VAR_NAME)
+ if(ARGN)
+ list(JOIN ARGN "`, `" _va_args)
+ set(_va_args ", ARGN: `${_va_args}`")
+ endif()
+ _cpack_nuget_debug(
+ "_cpack_nuget_variable_fallback: "
+ "OUTPUT_VAR_NAME=`${OUTPUT_VAR_NAME}`, "
+ "NUGET_VAR_NAME=`${NUGET_VAR_NAME}`"
+ "${_va_args}"
+ )
+
+ set(_options USE_CDATA)
+ set(_one_value_args LIST_GLUE)
+ set(_multi_value_args FALLBACK_VARS)
+ cmake_parse_arguments(PARSE_ARGV 0 _args "${_options}" "${_one_value_args}" "${_multi_value_args}")
+
+ if(CPACK_NUGET_PACKAGE_COMPONENT)
+ string(
+ TOUPPER "${CPACK_NUGET_PACKAGE_COMPONENT}"
+ CPACK_NUGET_PACKAGE_COMPONENT_UPPER
+ )
+ endif()
+
+ if(CPACK_NUGET_PACKAGE_COMPONENT
+ AND CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT}_PACKAGE_${NUGET_VAR_NAME}
+ )
+ set(
+ _result
+ "${CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT}_PACKAGE_${NUGET_VAR_NAME}}"
+ )
+ _cpack_nuget_debug(
+ " CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT}_PACKAGE_${NUGET_VAR_NAME}: "
+ "OUTPUT_VAR_NAME->${OUTPUT_VAR_NAME}=`${_result}`"
+ )
+
+ elseif(CPACK_NUGET_PACKAGE_COMPONENT_UPPER
+ AND CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT_UPPER}_PACKAGE_${NUGET_VAR_NAME}
+ )
+ set(
+ _result
+ "${CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT_UPPER}_PACKAGE_${NUGET_VAR_NAME}}"
+ )
+ _cpack_nuget_debug(
+ " CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT_UPPER}_PACKAGE_${NUGET_VAR_NAME}: "
+ "OUTPUT_VAR_NAME->${OUTPUT_VAR_NAME}=`${_result}`"
+ )
+
+ elseif(CPACK_NUGET_PACKAGE_${NUGET_VAR_NAME})
+ set(_result "${CPACK_NUGET_PACKAGE_${NUGET_VAR_NAME}}")
+ _cpack_nuget_debug(
+ " CPACK_NUGET_PACKAGE_${NUGET_VAR_NAME}: "
+ "OUTPUT_VAR_NAME->${OUTPUT_VAR_NAME}=`${_result}`"
+ )
+
+ else()
+ foreach(_var IN LISTS _args_FALLBACK_VARS)
+ _cpack_nuget_debug(" Fallback: ${_var} ...")
+ if(${_var})
+ _cpack_nuget_debug(" ${_var}=`${${_var}}`")
+ set(_result "${${_var}}")
+ _cpack_nuget_debug(
+ " ${_var}: OUTPUT_VAR_NAME->${OUTPUT_VAR_NAME}=`${_result}`"
+ )
+ break()
+ endif()
+ endforeach()
+ endif()
+
+ if(_result)
+ if(_args_USE_CDATA)
+ set(_value_before "<![CDATA[")
+ set(_value_after "]]>")
+ endif()
+
+ list(LENGTH _result _result_len)
+ if(_result_len GREATER 1 AND _args_LIST_GLUE)
+ list(JOIN _result "${_args_LIST_GLUE}" _result)
+ endif()
+
+ set(${OUTPUT_VAR_NAME} "${_value_before}${_result}${_value_after}" PARENT_SCOPE)
+ endif()
+
+endfunction()
+
+function(_cpack_nuget_variable_fallback_and_wrap_into_element ELEMENT NUGET_VAR_NAME)
+ set(_options)
+ set(_one_value_args)
+ set(_multi_value_args FALLBACK_VARS)
+ cmake_parse_arguments(PARSE_ARGV 0 _args "${_options}" "${_one_value_args}" "${_multi_value_args}")
+
+ _cpack_nuget_variable_fallback(_value ${NUGET_VAR_NAME} ${ARGN} USE_CDATA)
+
+ if(_value)
+ string(TOUPPER "${ELEMENT}" _ELEMENT_UP)
+ set(
+ _CPACK_NUGET_${_ELEMENT_UP}_TAG
+ "<${ELEMENT}>${_value}</${ELEMENT}>"
+ PARENT_SCOPE
+ )
+ endif()
+endfunction()
+
+# Print some debug info
+_cpack_nuget_debug("---[CPack NuGet Input Variables]---")
+_cpack_nuget_debug_var(CPACK_PACKAGE_NAME)
+_cpack_nuget_debug_var(CPACK_PACKAGE_VERSION)
+_cpack_nuget_debug_var(CPACK_TOPLEVEL_TAG)
+_cpack_nuget_debug_var(CPACK_TOPLEVEL_DIRECTORY)
+_cpack_nuget_debug_var(CPACK_TEMPORARY_DIRECTORY)
+_cpack_nuget_debug_var(CPACK_NUGET_GROUPS)
+if(CPACK_NUGET_GROUPS)
+ foreach(_group IN LISTS CPACK_NUGET_GROUPS)
+ string(MAKE_C_IDENTIFIER "${_group}" _group_up)
+ string(TOUPPER "${_group_up}" _group_up)
+ _cpack_nuget_debug_var(CPACK_NUGET_${_group_up}_GROUP_COMPONENTS)
+ endforeach()
+endif()
+_cpack_nuget_debug_var(CPACK_NUGET_COMPONENTS)
+_cpack_nuget_debug_var(CPACK_NUGET_ALL_IN_ONE)
+_cpack_nuget_debug_var(CPACK_NUGET_ORDINAL_MONOLITIC)
+_cpack_nuget_debug("-----------------------------------")
+
+function(_cpack_nuget_render_spec)
+ # Make a variable w/ upper-cased component name
+ if(CPACK_NUGET_PACKAGE_COMPONENT)
+ string(TOUPPER "${CPACK_NUGET_PACKAGE_COMPONENT}" CPACK_NUGET_PACKAGE_COMPONENT_UPPER)
+ endif()
+
+ # Set mandatory variables (not wrapped into XML elements)
+ # https://docs.microsoft.com/en-us/nuget/reference/nuspec#required-metadata-elements
+ if(CPACK_NUGET_PACKAGE_COMPONENT)
+ if(CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT_UPPER}_PACKAGE_NAME)
+ set(
+ CPACK_NUGET_PACKAGE_NAME
+ "${CPACK_NUGET_${CPACK_NUGET_PACKAGE_COMPONENT_UPPER}_PACKAGE_NAME}"
+ )
+ elseif(NOT CPACK_NUGET_PACKAGE_COMPONENT STREQUAL "Unspecified")
+ set(
+ CPACK_NUGET_PACKAGE_NAME
+ "${CPACK_PACKAGE_NAME}.${CPACK_NUGET_PACKAGE_COMPONENT}"
+ )
+ else()
+ set(CPACK_NUGET_PACKAGE_NAME "${CPACK_PACKAGE_NAME}")
+ endif()
+ elseif(NOT CPACK_NUGET_PACKAGE_NAME)
+ set(CPACK_NUGET_PACKAGE_NAME "${CPACK_PACKAGE_NAME}")
+ endif()
+
+ _cpack_nuget_variable_fallback(
+ CPACK_NUGET_PACKAGE_VERSION VERSION
+ FALLBACK_VARS
+ CPACK_PACKAGE_VERSION
+ )
+ _cpack_nuget_variable_fallback(
+ CPACK_NUGET_PACKAGE_DESCRIPTION DESCRIPTION
+ FALLBACK_VARS
+ CPACK_COMPONENT_${CPACK_NUGET_PACKAGE_COMPONENT}_DESCRIPTION
+ CPACK_COMPONENT_${CPACK_NUGET_PACKAGE_COMPONENT_UPPER}_DESCRIPTION
+ CPACK_COMPONENT_GROUP_${CPACK_NUGET_PACKAGE_COMPONENT_UPPER}_DESCRIPTION
+ CPACK_PACKAGE_DESCRIPTION
+ USE_CDATA
+ )
+ _cpack_nuget_variable_fallback(
+ CPACK_NUGET_PACKAGE_AUTHORS AUTHORS
+ FALLBACK_VARS
+ CPACK_PACKAGE_VENDOR
+ USE_CDATA
+ LIST_GLUE ","
+ )
+
+ # Set optional variables (wrapped into XML elements)
+ # https://docs.microsoft.com/en-us/nuget/reference/nuspec#optional-metadata-elements
+ _cpack_nuget_variable_fallback_and_wrap_into_element(
+ title
+ TITLE
+ FALLBACK_VARS
+ CPACK_COMPONENT_${CPACK_NUGET_PACKAGE_COMPONENT}_DISPLAY_NAME
+ CPACK_COMPONENT_${CPACK_NUGET_PACKAGE_COMPONENT_UPPER}_DISPLAY_NAME
+ CPACK_COMPONENT_GROUP_${CPACK_NUGET_PACKAGE_COMPONENT_UPPER}_DISPLAY_NAME
+ )
+ _cpack_nuget_variable_fallback_and_wrap_into_element(owners OWNERS LIST_GLUE ",")
+ _cpack_nuget_variable_fallback_and_wrap_into_element(
+ projectUrl
+ HOMEPAGE_URL
+ FALLBACK_VARS
+ CPACK_PACKAGE_HOMEPAGE_URL
+ )
+ _cpack_nuget_variable_fallback_and_wrap_into_element(licenseUrl LICENSEURL)
+ _cpack_nuget_variable_fallback_and_wrap_into_element(iconUrl ICONURL)
+ _cpack_nuget_variable_fallback_and_wrap_into_element(
+ summary DESCRIPTION_SUMMARY
+ FALLBACK_VARS
+ CPACK_PACKAGE_DESCRIPTION_SUMMARY
+ )
+ if(CPACK_NUGET_PACKAGE_REQUIRE_LICENSE_ACCEPTANCE)
+ set(
+ _CPACK_NUGET_REQUIRELICENSEACCEPTANCE_TAG
+ "<requireLicenseAcceptance>true</requireLicenseAcceptance>"
+ )
+ endif()
+ _cpack_nuget_variable_fallback_and_wrap_into_element(releaseNotes RELEASE_NOTES)
+ _cpack_nuget_variable_fallback_and_wrap_into_element(copyright COPYRIGHT)
+ _cpack_nuget_variable_fallback_and_wrap_into_element(tags TAGS LIST_GLUE " ")
+
+ # Handle dependencies
+ _cpack_nuget_variable_fallback(_deps DEPENDENCIES)
+ set(_collected_deps)
+ foreach(_dep IN LISTS _deps)
+ _cpack_nuget_debug(" checking dependency `${_dep}`")
+
+ string(MAKE_C_IDENTIFIER "${_dep}" _dep_id)
+
+ _cpack_nuget_variable_fallback(_ver DEPENDENCIES_${_dep_id}_VERSION)
+
+ if(NOT _ver)
+ string(TOUPPER "${_dep_id}" _dep_id)
+ _cpack_nuget_variable_fallback(_ver DEPENDENCIES_${_dep_id}_VERSION)
+ endif()
+
+ if(_ver)
+ _cpack_nuget_debug(" got `${_dep}` dependency version ${_ver}")
+ list(APPEND _collected_deps "<dependency id=\"${_dep}\" version=\"${_ver}\" />")
+ endif()
+ endforeach()
+
+ # Render deps into the variable
+ if(_collected_deps)
+ set(_CPACK_NUGET_DEPENDENCIES_TAG "<dependencies>\n")
+ foreach(_line IN LISTS _collected_deps)
+ string(
+ APPEND _CPACK_NUGET_DEPENDENCIES_TAG
+ " ${_line}\n"
+ )
+ endforeach()
+ string(APPEND _CPACK_NUGET_DEPENDENCIES_TAG " </dependencies>")
+ endif()
+
+ # Render the spec file
+ # NOTE The spec filename doesn't matter. Being included into a package,
+ # NuGet will name it properly.
+ _cpack_nuget_debug("Rendering `${CPACK_TEMPORARY_DIRECTORY}/CPack.NuGet.nuspec` file...")
+ configure_file(
+ "${CMAKE_CURRENT_LIST_DIR}/CPack.NuGet.nuspec.in"
+ "${CPACK_TEMPORARY_DIRECTORY}/CPack.NuGet.nuspec"
+ @ONLY
+ )
+endfunction()
+
+function(_cpack_nuget_make_files_tag)
+ set(_files)
+ foreach(_comp IN LISTS ARGN)
+ string(APPEND _files " <file src=\"${_comp}\\**\" target=\".\" />\n")
+ endforeach()
+ set(_CPACK_NUGET_FILES_TAG "<files>\n${_files} </files>" PARENT_SCOPE)
+endfunction()
+
+find_program(NUGET_EXECUTABLE NuGet)
+_cpack_nuget_debug_var(NUGET_EXECUTABLE)
+if(NOT NUGET_EXECUTABLE)
+ message(FATAL_ERROR "NuGet executable not found")
+endif()
+
+# Add details for debug run
+if(CPACK_NUGET_PACKAGE_DEBUG)
+ list(APPEND CPACK_NUGET_PACK_ADDITIONAL_OPTIONS "-Verbosity" "detailed")
+endif()
+
+# Case one: ordinal all-in-one package
+if(CPACK_NUGET_ORDINAL_MONOLITIC)
+ # This variable `CPACK_NUGET_ALL_IN_ONE` set by C++ code:
+ # Meaning to pack all installed files into a single package
+ _cpack_nuget_debug("---[Making an ordinal monolitic package]---")
+ _cpack_nuget_render_spec()
+ execute_process(
+ COMMAND "${NUGET_EXECUTABLE}" pack ${CPACK_NUGET_PACK_ADDITIONAL_OPTIONS}
+ WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
+ )
+
+elseif(CPACK_NUGET_ALL_IN_ONE)
+ # This variable `CPACK_NUGET_ALL_IN_ONE` set by C++ code:
+ # Meaning to pack all installed components into a single package
+ _cpack_nuget_debug("---[Making a monolitic package from installed components]---")
+
+ # Prepare the `files` element which include files from several components
+ _cpack_nuget_make_files_tag(${CPACK_NUGET_COMPONENTS})
+ _cpack_nuget_render_spec()
+ execute_process(
+ COMMAND "${NUGET_EXECUTABLE}" pack ${CPACK_NUGET_PACK_ADDITIONAL_OPTIONS}
+ WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
+ )
+
+else()
+ # Is there any grouped component?
+ if(CPACK_NUGET_GROUPS)
+ _cpack_nuget_debug("---[Making grouped component(s) package(s)]---")
+ foreach(_group IN LISTS CPACK_NUGET_GROUPS)
+ _cpack_nuget_debug("Starting to make the pacakge for group `${_group}`")
+ string(MAKE_C_IDENTIFIER "${_group}" _group_up)
+ string(TOUPPER "${_group_up}" _group_up)
+
+ # Render a spec file which includes all components in the current group
+ unset(_CPACK_NUGET_FILES_TAG)
+ _cpack_nuget_make_files_tag(${CPACK_NUGET_${_group_up}_GROUP_COMPONENTS})
+ # Temporary set `CPACK_NUGET_PACKAGE_COMPONENT` to the group name
+ # to properly collect various per group settings
+ set(CPACK_NUGET_PACKAGE_COMPONENT ${_group})
+ _cpack_nuget_render_spec()
+ unset(CPACK_NUGET_PACKAGE_COMPONENT)
+ execute_process(
+ COMMAND "${NUGET_EXECUTABLE}" pack ${CPACK_NUGET_PACK_ADDITIONAL_OPTIONS}
+ WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
+ )
+ endforeach()
+ endif()
+ # Is there any single component package needed?
+ if(CPACK_NUGET_COMPONENTS)
+ _cpack_nuget_debug("---[Making single-component(s) package(s)]---")
+ foreach(_comp IN LISTS CPACK_NUGET_COMPONENTS)
+ _cpack_nuget_debug("Starting to make the pacakge for component `${_comp}`")
+ # Render a spec file which includes only given component
+ unset(_CPACK_NUGET_FILES_TAG)
+ _cpack_nuget_make_files_tag(${_comp})
+ # Temporary set `CPACK_NUGET_PACKAGE_COMPONENT` to the the current
+ # component name to properly collect various per group settings
+ set(CPACK_NUGET_PACKAGE_COMPONENT ${_comp})
+ _cpack_nuget_render_spec()
+ unset(CPACK_NUGET_PACKAGE_COMPONENT)
+ execute_process(
+ COMMAND "${NUGET_EXECUTABLE}" pack ${CPACK_NUGET_PACK_ADDITIONAL_OPTIONS}
+ WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
+ )
+ endforeach()
+ endif()
+endif()
+
+file(GLOB_RECURSE GEN_CPACK_OUTPUT_FILES "${CPACK_TEMPORARY_DIRECTORY}/*.nupkg")
+if(NOT GEN_CPACK_OUTPUT_FILES)
+ message(FATAL_ERROR "NuGet package was not generated at `${CPACK_TEMPORARY_DIRECTORY}`!")
+endif()
+
+_cpack_nuget_debug("Generated files: ${GEN_CPACK_OUTPUT_FILES}")
diff --git a/Modules/CPackRPM.cmake b/Modules/CPackRPM.cmake
index 8d8eab3..60b3abe 100644
--- a/Modules/CPackRPM.cmake
+++ b/Modules/CPackRPM.cmake
@@ -410,17 +410,17 @@
#
# .. variable:: CPACK_RPM_SPEC_INSTALL_POST
#
-# Deprecated - use :variable:`CPACK_RPM_POST_INSTALL_SCRIPT_FILE` instead.
+# Deprecated - use :variable:`CPACK_RPM_SPEC_MORE_DEFINE` instead.
#
# * Mandatory : NO
# * Default : -
# * Deprecated: YES
#
-# This way of specifying post-install script is deprecated, use
-# :variable:`CPACK_RPM_POST_INSTALL_SCRIPT_FILE`.
-# May be used to set an RPM post-install command inside the spec file.
-# For example setting it to ``/bin/true`` may be used to prevent
-# rpmbuild to strip binaries.
+# May be used to override the ``__spec_install_post`` section within the
+# generated spec file. This affects the install step during package creation,
+# not during package installation. For adding operations to be performed
+# during package installation, use
+# :variable:`CPACK_RPM_POST_INSTALL_SCRIPT_FILE` instead.
#
# .. variable:: CPACK_RPM_SPEC_MORE_DEFINE
#
@@ -429,7 +429,11 @@
# * Mandatory : NO
# * Default : -
#
-# May be used to add any ``%define`` lines to the generated spec file.
+# May be used to add any ``%define`` lines to the generated spec file. An
+# example of its use is to prevent stripping of executables (but note that
+# this may also disable other default post install processing)::
+#
+# set(CPACK_RPM_SPEC_MORE_DEFINE "%define __spec_install_post /bin/true")
#
# .. variable:: CPACK_RPM_PACKAGE_DEBUG
#
@@ -877,9 +881,9 @@
# variable while usually using :variable:`CPACK_INSTALLED_DIRECTORIES` variable
# to provide directory containing CMakeLists.txt and source files.
#
-# For CMake projects SRPM package would be product by executing:
+# For CMake projects SRPM package would be produced by executing::
#
-# ``cpack -G RPM --config ./CPackSourceConfig.cmake``
+# cpack -G RPM --config ./CPackSourceConfig.cmake
#
# .. note::
#
@@ -892,10 +896,10 @@
#
# Once the SRPM package is generated it can be used to generate binary packages
# by creating a directory structure for rpm generation and executing rpmbuild
-# tool:
+# tool::
#
-# ``mkdir -p build_dir/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}``
-# ``rpmbuild --define "_topdir <path_to_build_dir>" --rebuild <SRPM_file_name>``
+# mkdir -p build_dir/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
+# rpmbuild --define "_topdir <path_to_build_dir>" --rebuild <SRPM_file_name>
#
# Generated packages will be located in build_dir/RPMS directory or its sub
# directories.
diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake
index 5223b1d..5ee703a 100644
--- a/Modules/FindBLAS.cmake
+++ b/Modules/FindBLAS.cmake
@@ -88,16 +88,9 @@ endif()
if(BLA_PREFER_PKGCONFIG)
find_package(PkgConfig)
- pkg_check_modules(PKGC_BLAS IMPORTED_TARGET blas)
+ pkg_check_modules(PKGC_BLAS blas)
if(PKGC_BLAS_FOUND)
- # FIXME: We should not interpret the INTERFACE_LINK_LIBRARIES property
- # because it could have generator expressions and such. This is a
- # workaround for pkg_check_modules not providing a first-class way to
- # get the list of libraries.
- get_property(BLAS_LIBRARIES TARGET PkgConfig::PKGC_BLAS PROPERTY INTERFACE_LINK_LIBRARIES)
- find_package_handle_standard_args(BLAS
- REQUIRED_VARS BLAS_LIBRARIES
- VERSION_VAR PKGC_BLAS_VERSION)
+ set(BLAS_LIBRARIES "${PKGC_BLAS_LINK_LIBRARIES}")
return()
endif()
endif()
diff --git a/Modules/FindBZip2.cmake b/Modules/FindBZip2.cmake
index 0375b09..4d7123d 100644
--- a/Modules/FindBZip2.cmake
+++ b/Modules/FindBZip2.cmake
@@ -18,13 +18,24 @@
#
# This module defines the following variables:
#
-# ::
+# ``BZIP2_FOUND``
+# system has BZip2
+# ``BZIP2_INCLUDE_DIRS``
+# the BZip2 include directories
+# ``BZIP2_LIBRARIES``
+# Link these to use BZip2
+# ``BZIP2_NEED_PREFIX``
+# this is set if the functions are prefixed with ``BZ2_``
+# ``BZIP2_VERSION_STRING``
+# the version of BZip2 found
#
-# BZIP2_FOUND - system has BZip2
-# BZIP2_INCLUDE_DIR - the BZip2 include directory
-# BZIP2_LIBRARIES - Link these to use BZip2
-# BZIP2_NEED_PREFIX - this is set if the functions are prefixed with BZ2_
-# BZIP2_VERSION_STRING - the version of BZip2 found (since CMake 2.8.8)
+# Cache variables
+# ^^^^^^^^^^^^^^^
+#
+# The following cache variables may also be set:
+#
+# ``BZIP2_INCLUDE_DIR``
+# the BZip2 include directory
set(_BZIP2_PATHS PATHS
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\GnuWin32\\Bzip2;InstallPath]"
@@ -53,6 +64,7 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(BZip2
VERSION_VAR BZIP2_VERSION_STRING)
if (BZIP2_FOUND)
+ set(BZIP2_INCLUDE_DIRS ${BZIP2_INCLUDE_DIR})
include(${CMAKE_CURRENT_LIST_DIR}/CheckSymbolExists.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/CMakePushCheckState.cmake)
cmake_push_check_state()
diff --git a/Modules/FindBoost.cmake b/Modules/FindBoost.cmake
index 5b5002a..08d9762 100644
--- a/Modules/FindBoost.cmake
+++ b/Modules/FindBoost.cmake
@@ -585,7 +585,7 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret)
set(_Boost_FILESYSTEM_DEPENDENCIES system)
set(_Boost_IOSTREAMS_DEPENDENCIES regex)
set(_Boost_MPI_DEPENDENCIES serialization)
- set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization)
+ set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization)
set(_Boost_WAVE_DEPENDENCIES filesystem system thread)
set(_Boost_WSERIALIZATION_DEPENDENCIES serialization)
elseif(NOT Boost_VERSION VERSION_LESS 103600 AND Boost_VERSION VERSION_LESS 103800)
@@ -593,7 +593,7 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret)
set(_Boost_IOSTREAMS_DEPENDENCIES regex)
set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l)
set(_Boost_MPI_DEPENDENCIES serialization)
- set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization)
+ set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization)
set(_Boost_WAVE_DEPENDENCIES filesystem system thread)
set(_Boost_WSERIALIZATION_DEPENDENCIES serialization)
elseif(NOT Boost_VERSION VERSION_LESS 103800 AND Boost_VERSION VERSION_LESS 104300)
@@ -601,7 +601,7 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret)
set(_Boost_IOSTREAMS_DEPENDENCIES regex)
set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l)
set(_Boost_MPI_DEPENDENCIES serialization)
- set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization)
+ set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization)
set(_Boost_THREAD_DEPENDENCIES date_time)
set(_Boost_WAVE_DEPENDENCIES filesystem system thread date_time)
set(_Boost_WSERIALIZATION_DEPENDENCIES serialization)
@@ -610,7 +610,7 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret)
set(_Boost_IOSTREAMS_DEPENDENCIES regex)
set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l random)
set(_Boost_MPI_DEPENDENCIES serialization)
- set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization)
+ set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization)
set(_Boost_THREAD_DEPENDENCIES date_time)
set(_Boost_WAVE_DEPENDENCIES filesystem system thread date_time)
set(_Boost_WSERIALIZATION_DEPENDENCIES serialization)
@@ -619,7 +619,7 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret)
set(_Boost_IOSTREAMS_DEPENDENCIES regex)
set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l random serialization)
set(_Boost_MPI_DEPENDENCIES serialization)
- set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization)
+ set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization)
set(_Boost_THREAD_DEPENDENCIES date_time)
set(_Boost_WAVE_DEPENDENCIES serialization filesystem system thread date_time)
set(_Boost_WSERIALIZATION_DEPENDENCIES serialization)
@@ -628,7 +628,7 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret)
set(_Boost_IOSTREAMS_DEPENDENCIES regex)
set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l random)
set(_Boost_MPI_DEPENDENCIES serialization)
- set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization)
+ set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization)
set(_Boost_THREAD_DEPENDENCIES date_time)
set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread date_time)
set(_Boost_WSERIALIZATION_DEPENDENCIES serialization)
@@ -638,7 +638,7 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret)
set(_Boost_IOSTREAMS_DEPENDENCIES regex)
set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l random)
set(_Boost_MPI_DEPENDENCIES serialization)
- set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization)
+ set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization)
set(_Boost_THREAD_DEPENDENCIES date_time)
set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread date_time)
set(_Boost_WSERIALIZATION_DEPENDENCIES serialization)
@@ -648,7 +648,7 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret)
set(_Boost_IOSTREAMS_DEPENDENCIES regex)
set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l random)
set(_Boost_MPI_DEPENDENCIES serialization)
- set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization)
+ set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization)
set(_Boost_THREAD_DEPENDENCIES date_time)
set(_Boost_TIMER_DEPENDENCIES chrono system)
set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread date_time)
@@ -659,7 +659,7 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret)
set(_Boost_IOSTREAMS_DEPENDENCIES regex)
set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l regex random)
set(_Boost_MPI_DEPENDENCIES serialization)
- set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization)
+ set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization)
set(_Boost_THREAD_DEPENDENCIES chrono system date_time)
set(_Boost_TIMER_DEPENDENCIES chrono system)
set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time)
@@ -671,7 +671,7 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret)
set(_Boost_IOSTREAMS_DEPENDENCIES regex)
set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l regex random)
set(_Boost_MPI_DEPENDENCIES serialization)
- set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization)
+ set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization)
set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic)
set(_Boost_TIMER_DEPENDENCIES chrono system)
set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time)
@@ -684,7 +684,7 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret)
set(_Boost_LOG_DEPENDENCIES log_setup date_time system filesystem thread regex chrono)
set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l regex random)
set(_Boost_MPI_DEPENDENCIES serialization)
- set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization)
+ set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization)
set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic)
set(_Boost_TIMER_DEPENDENCIES chrono system)
set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic)
@@ -697,7 +697,7 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret)
set(_Boost_LOG_DEPENDENCIES log_setup date_time system filesystem thread regex chrono)
set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l regex random)
set(_Boost_MPI_DEPENDENCIES serialization)
- set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization)
+ set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization)
set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic)
set(_Boost_TIMER_DEPENDENCIES chrono system)
set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic)
@@ -710,7 +710,7 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret)
set(_Boost_LOG_DEPENDENCIES log_setup date_time system filesystem thread regex chrono)
set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic)
set(_Boost_MPI_DEPENDENCIES serialization)
- set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization)
+ set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization)
set(_Boost_RANDOM_DEPENDENCIES system)
set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic)
set(_Boost_TIMER_DEPENDENCIES chrono system)
@@ -724,7 +724,7 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret)
set(_Boost_LOG_DEPENDENCIES log_setup date_time system filesystem thread regex chrono atomic)
set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic)
set(_Boost_MPI_DEPENDENCIES serialization)
- set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization)
+ set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization)
set(_Boost_RANDOM_DEPENDENCIES system)
set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic)
set(_Boost_TIMER_DEPENDENCIES chrono system)
@@ -738,7 +738,7 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret)
set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic)
set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic)
set(_Boost_MPI_DEPENDENCIES serialization)
- set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization)
+ set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization)
set(_Boost_RANDOM_DEPENDENCIES system)
set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic)
set(_Boost_TIMER_DEPENDENCIES chrono system)
@@ -753,7 +753,7 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret)
set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic)
set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic)
set(_Boost_MPI_DEPENDENCIES serialization)
- set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization)
+ set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization)
set(_Boost_RANDOM_DEPENDENCIES system)
set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic)
set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic)
@@ -768,7 +768,7 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret)
set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic)
set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic)
set(_Boost_MPI_DEPENDENCIES serialization)
- set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization)
+ set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization)
set(_Boost_RANDOM_DEPENDENCIES system)
set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic)
set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic)
@@ -784,28 +784,28 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret)
set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic)
set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic)
set(_Boost_MPI_DEPENDENCIES serialization)
- set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization)
+ set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization)
set(_Boost_RANDOM_DEPENDENCIES system)
set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic)
set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic)
set(_Boost_WSERIALIZATION_DEPENDENCIES serialization)
elseif(NOT Boost_VERSION VERSION_LESS 106500 AND Boost_VERSION VERSION_LESS 106700)
- set(_Boost_CHRONO_DEPENDENCIES system)
- set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time)
- set(_Boost_COROUTINE_DEPENDENCIES context system)
- set(_Boost_FIBER_DEPENDENCIES context thread chrono system date_time)
- set(_Boost_FILESYSTEM_DEPENDENCIES system)
- set(_Boost_IOSTREAMS_DEPENDENCIES regex)
- set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic)
- set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic)
- set(_Boost_MPI_DEPENDENCIES serialization)
- set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization)
- set(_Boost_NUMPY_DEPENDENCIES python)
- set(_Boost_RANDOM_DEPENDENCIES system)
- set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic)
- set(_Boost_TIMER_DEPENDENCIES chrono system)
- set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic)
- set(_Boost_WSERIALIZATION_DEPENDENCIES serialization)
+ set(_Boost_CHRONO_DEPENDENCIES system)
+ set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time)
+ set(_Boost_COROUTINE_DEPENDENCIES context system)
+ set(_Boost_FIBER_DEPENDENCIES context thread chrono system date_time)
+ set(_Boost_FILESYSTEM_DEPENDENCIES system)
+ set(_Boost_IOSTREAMS_DEPENDENCIES regex)
+ set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic)
+ set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic)
+ set(_Boost_MPI_DEPENDENCIES serialization)
+ set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization)
+ set(_Boost_NUMPY_DEPENDENCIES python${component_python_version})
+ set(_Boost_RANDOM_DEPENDENCIES system)
+ set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic)
+ set(_Boost_TIMER_DEPENDENCIES chrono system)
+ set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic)
+ set(_Boost_WSERIALIZATION_DEPENDENCIES serialization)
else()
if(NOT Boost_VERSION VERSION_LESS 106700)
set(_Boost_CHRONO_DEPENDENCIES system)
diff --git a/Modules/FindCUDA.cmake b/Modules/FindCUDA.cmake
index a0e4aa9..874fb89 100644
--- a/Modules/FindCUDA.cmake
+++ b/Modules/FindCUDA.cmake
@@ -557,10 +557,10 @@ else()
set(c_compiler_realpath "")
endif()
set(CUDA_HOST_COMPILER "${c_compiler_realpath}" CACHE FILEPATH "Host side compiler used by NVCC")
- elseif(MSVC AND "${CMAKE_C_COMPILER}" MATCHES "clcache")
- # NVCC does not think it will work if it is passed clcache.exe as the host
- # compiler, which means that builds with CC=cl.exe won't work. Best to just
- # feed it whatever the actual cl.exe is as the host compiler.
+ elseif(MSVC AND "${CMAKE_C_COMPILER}" MATCHES "clcache|sccache")
+ # NVCC does not think it will work if it is passed clcache.exe or sccache.exe
+ # as the host compiler, which means that builds with CC=cl.exe won't work.
+ # Best to just feed it whatever the actual cl.exe is as the host compiler.
set(CUDA_HOST_COMPILER "cl.exe" CACHE FILEPATH "Host side compiler used by NVCC")
else()
set(CUDA_HOST_COMPILER "${CMAKE_C_COMPILER}"
@@ -1769,7 +1769,7 @@ function(CUDA_LINK_SEPARABLE_COMPILATION_OBJECTS output_file cuda_target options
add_custom_command(
OUTPUT ${output_file}
DEPENDS ${object_files}
- COMMAND ${CUDA_NVCC_EXECUTABLE} ${nvcc_flags} -dlink ${object_files} ${CUDA_cublas_device_LIBRARY} -o ${output_file}
+ COMMAND ${CUDA_NVCC_EXECUTABLE} ${nvcc_flags} -dlink ${object_files} -o ${output_file}
${flags}
COMMENT "Building NVCC intermediate link file ${output_file_relative_path}"
COMMAND_EXPAND_LISTS
@@ -1782,7 +1782,7 @@ function(CUDA_LINK_SEPARABLE_COMPILATION_OBJECTS output_file cuda_target options
PRE_LINK
COMMAND ${CMAKE_COMMAND} -E echo "Building NVCC intermediate link file ${output_file_relative_path}"
COMMAND ${CMAKE_COMMAND} -E make_directory "${output_file_dir}"
- COMMAND ${CUDA_NVCC_EXECUTABLE} ${nvcc_flags} ${flags} -dlink ${object_files} ${CUDA_cublas_device_LIBRARY} -o "${output_file}"
+ COMMAND ${CUDA_NVCC_EXECUTABLE} ${nvcc_flags} ${flags} -dlink ${object_files} -o "${output_file}"
COMMAND_EXPAND_LISTS
${_verbatim}
)
diff --git a/Modules/FindDoxygen.cmake b/Modules/FindDoxygen.cmake
index 599d799..945ee0e 100644
--- a/Modules/FindDoxygen.cmake
+++ b/Modules/FindDoxygen.cmake
@@ -69,6 +69,7 @@ Functions
doxygen_add_docs(targetName
[filesOrDirs...]
+ [ALL]
[WORKING_DIRECTORY dir]
[COMMENT comment])
@@ -91,6 +92,8 @@ Functions
the :command:`add_custom_target` command used to create the custom target
internally.
+ If ALL is set, the target will be added to the default build target.
+
The contents of the generated ``Doxyfile`` can be customized by setting CMake
variables before calling ``doxygen_add_docs()``. Any variable with a name of
the form ``DOXYGEN_<tag>`` will have its value substituted for the
@@ -788,7 +791,7 @@ function(doxygen_list_to_quoted_strings LIST_VARIABLE)
endfunction()
function(doxygen_add_docs targetName)
- set(_options)
+ set(_options ALL)
set(_one_value_args WORKING_DIRECTORY COMMENT)
set(_multi_value_args)
cmake_parse_arguments(_args
@@ -1089,8 +1092,13 @@ doxygen_add_docs() for target ${targetName}")
set(_target_doxyfile "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile.${targetName}")
configure_file("${_doxyfile_template}" "${_target_doxyfile}")
+ unset(_all)
+ if(${_args_ALL})
+ set(_all ALL)
+ endif()
+
# Add the target
- add_custom_target( ${targetName} VERBATIM
+ add_custom_target( ${targetName} ${_all} VERBATIM
COMMAND ${CMAKE_COMMAND} -E make_directory ${_original_doxygen_output_dir}
COMMAND "${DOXYGEN_EXECUTABLE}" "${_target_doxyfile}"
WORKING_DIRECTORY "${_args_WORKING_DIRECTORY}"
diff --git a/Modules/FindJNI.cmake b/Modules/FindJNI.cmake
index ff8d353..4913e05 100644
--- a/Modules/FindJNI.cmake
+++ b/Modules/FindJNI.cmake
@@ -128,7 +128,7 @@ if (WIN32)
OUTPUT_VARIABLE _JNI_VERSIONS
ERROR_QUIET)
if (NOT _JNI_RESULT)
- string (REGEX MATCHALL "HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\JavaSoft\\\\JDK\\\\[0-9\.]+" _JNI_VERSIONS "${_JNI_VERSIONS}")
+ string (REGEX MATCHALL "HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\JavaSoft\\\\JDK\\\\[0-9.]+" _JNI_VERSIONS "${_JNI_VERSIONS}")
if (_JNI_VERSIONS)
# sort versions. Most recent first
## handle version 9 apart from other versions to get correct ordering
@@ -141,7 +141,7 @@ if (WIN32)
list (REVERSE _JNI_V9)
list (APPEND _JNI_VERSIONS ${_JNI_V9})
foreach (_JNI_HINT IN LISTS _JNI_VERSIONS)
- list(APPEND _JNI_HINTS "[${_JNI_HINT}\\MSI;INSTALLDIR]")
+ list(APPEND _JNI_HINTS "[${_JNI_HINT};JavaHome]")
endforeach()
endif()
endif()
diff --git a/Modules/FindJPEG.cmake b/Modules/FindJPEG.cmake
index 9542f69..61a2213 100644
--- a/Modules/FindJPEG.cmake
+++ b/Modules/FindJPEG.cmake
@@ -51,7 +51,7 @@
find_path(JPEG_INCLUDE_DIR jpeglib.h)
-set(jpeg_names ${JPEG_NAMES} jpeg libjpeg)
+set(jpeg_names ${JPEG_NAMES} jpeg jpeg-static libjpeg libjpeg-static)
foreach(name ${JPEG_NAMES})
list(APPEND jpeg_names_debug "${name}d")
endforeach()
diff --git a/Modules/FindJava.cmake b/Modules/FindJava.cmake
index 95e551f..cddc5d2 100644
--- a/Modules/FindJava.cmake
+++ b/Modules/FindJava.cmake
@@ -97,7 +97,7 @@ if (WIN32)
list (REVERSE _JAVA_V9)
list (APPEND _JAVA_VERSIONS ${_JAVA_V9})
foreach (_JAVA_HINT IN LISTS _JAVA_VERSIONS)
- list(APPEND _JAVA_HINTS "[${_JAVA_HINT}\\MSI;INSTALLDIR]/bin")
+ list(APPEND _JAVA_HINTS "[${_JAVA_HINT};JavaHome]/bin")
endforeach()
endif()
endif()
diff --git a/Modules/FindLua.cmake b/Modules/FindLua.cmake
index 7eba206..8f35fc7 100644
--- a/Modules/FindLua.cmake
+++ b/Modules/FindLua.cmake
@@ -39,9 +39,16 @@
unset(_lua_include_subdirs)
unset(_lua_library_names)
unset(_lua_append_versions)
+set(_lua_additional_paths
+ ~/Library/Frameworks
+ /Library/Frameworks
+ /sw # Fink
+ /opt/local # DarwinPorts
+ /opt/csw # Blastwave
+ /opt)
# this is a function only to have all the variables inside go away automatically
-function(_lua_set_version_vars)
+function(_lua_get_versions)
set(LUA_VERSIONS5 5.3 5.2 5.1 5.0)
if (Lua_FIND_VERSION_EXACT)
@@ -59,6 +66,10 @@ function(_lua_set_version_vars)
list(APPEND _lua_append_versions ${subver})
endif ()
endforeach ()
+ # New version -> Search for it (heuristic only! Defines in include might have changed)
+ if (NOT _lua_append_versions)
+ set(_lua_append_versions ${Lua_FIND_VERSION_MAJOR}.${Lua_FIND_VERSION_MINOR})
+ endif()
endif ()
endif ()
else ()
@@ -66,22 +77,42 @@ function(_lua_set_version_vars)
set(_lua_append_versions ${LUA_VERSIONS5})
endif ()
- list(APPEND _lua_include_subdirs "include/lua" "include")
+ if (LUA_Debug)
+ message(STATUS "Considering following Lua versions: ${_lua_append_versions}")
+ endif()
+
+ set(_lua_append_versions "${_lua_append_versions}" PARENT_SCOPE)
+endfunction()
+
+function(_lua_set_version_vars)
+ set(_lua_include_subdirs_raw "lua")
foreach (ver IN LISTS _lua_append_versions)
string(REGEX MATCH "^([0-9]+)\\.([0-9]+)$" _ver "${ver}")
- list(APPEND _lua_include_subdirs
- include/lua${CMAKE_MATCH_1}${CMAKE_MATCH_2}
- include/lua${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
- include/lua-${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
+ list(APPEND _lua_include_subdirs_raw
+ lua${CMAKE_MATCH_1}${CMAKE_MATCH_2}
+ lua${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
+ lua-${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
)
endforeach ()
+ # Prepend "include/" to each path directly after the path
+ set(_lua_include_subdirs "include")
+ foreach (dir IN LISTS _lua_include_subdirs_raw)
+ list(APPEND _lua_include_subdirs "${dir}" "include/${dir}")
+ endforeach ()
+
set(_lua_include_subdirs "${_lua_include_subdirs}" PARENT_SCOPE)
- set(_lua_append_versions "${_lua_append_versions}" PARENT_SCOPE)
endfunction(_lua_set_version_vars)
-function(_lua_check_header_version _hdr_file)
+function(_lua_get_header_version)
+ unset(LUA_VERSION_STRING PARENT_SCOPE)
+ set(_hdr_file "${LUA_INCLUDE_DIR}/lua.h")
+
+ if (NOT EXISTS "${_hdr_file}")
+ return()
+ endif ()
+
# At least 5.[012] have different ways to express the version
# so all of them need to be tested. Lua 5.2 defines LUA_VERSION
# and LUA_RELEASE as joined by the C preprocessor, so avoid those.
@@ -111,39 +142,54 @@ function(_lua_check_header_version _hdr_file)
return()
endif ()
endforeach ()
-endfunction(_lua_check_header_version)
-
-_lua_set_version_vars()
-
-if (LUA_INCLUDE_DIR AND EXISTS "${LUA_INCLUDE_DIR}/lua.h")
- _lua_check_header_version("${LUA_INCLUDE_DIR}/lua.h")
-endif ()
-
-if (NOT LUA_VERSION_STRING)
- foreach (subdir IN LISTS _lua_include_subdirs)
- unset(LUA_INCLUDE_PREFIX CACHE)
- unset(LUA_INCLUDE_PREFIX)
- find_path(LUA_INCLUDE_PREFIX ${subdir}/lua.h
- HINTS
- ENV LUA_DIR
- PATHS
- ~/Library/Frameworks
- /Library/Frameworks
- /sw # Fink
- /opt/local # DarwinPorts
- /opt/csw # Blastwave
- /opt
- )
- if (LUA_INCLUDE_PREFIX)
- _lua_check_header_version("${LUA_INCLUDE_PREFIX}/${subdir}/lua.h")
- if (LUA_VERSION_STRING)
- set(LUA_INCLUDE_DIR "${LUA_INCLUDE_PREFIX}/${subdir}")
+endfunction(_lua_get_header_version)
+
+function(_lua_find_header)
+ _lua_set_version_vars()
+
+ # Initialize as local variable
+ set(CMAKE_IGNORE_PATH ${CMAKE_IGNORE_PATH})
+ while (TRUE)
+ # Find the next header to test. Check each possible subdir in order
+ # This prefers e.g. higher versions as they are earlier in the list
+ # It is also consistent with previous versions of FindLua
+ foreach (subdir IN LISTS _lua_include_subdirs)
+ find_path(LUA_INCLUDE_DIR lua.h
+ HINTS
+ ENV LUA_DIR
+ PATH_SUFFIXES ${subdir}
+ PATHS ${_lua_additional_paths}
+ )
+ if (LUA_INCLUDE_DIR)
break()
- endif ()
- endif ()
- endforeach ()
-endif ()
-unset(_lua_include_subdirs)
+ endif()
+ endforeach()
+ # Did not found header -> Fail
+ if (NOT LUA_INCLUDE_DIR)
+ return()
+ endif()
+ _lua_get_header_version()
+ # Found accepted version -> Ok
+ if (LUA_VERSION_STRING)
+ if (LUA_Debug)
+ message(STATUS "Found suitable version ${LUA_VERSION_STRING} in ${LUA_INCLUDE_DIR}/lua.h")
+ endif()
+ return()
+ endif()
+ # Found wrong version -> Ignore this path and retry
+ if (LUA_Debug)
+ message(STATUS "Ignoring unsuitable version in ${LUA_INCLUDE_DIR}")
+ endif()
+ list(APPEND CMAKE_IGNORE_PATH "${LUA_INCLUDE_DIR}")
+ unset(LUA_INCLUDE_DIR CACHE)
+ unset(LUA_INCLUDE_DIR)
+ unset(LUA_INCLUDE_DIR PARENT_SCOPE)
+ endwhile ()
+endfunction()
+
+_lua_get_versions()
+_lua_find_header()
+_lua_get_header_version()
unset(_lua_append_versions)
if (LUA_VERSION_STRING)
@@ -160,13 +206,7 @@ find_library(LUA_LIBRARY
HINTS
ENV LUA_DIR
PATH_SUFFIXES lib
- PATHS
- ~/Library/Frameworks
- /Library/Frameworks
- /sw
- /opt/local
- /opt/csw
- /opt
+ PATHS ${_lua_additional_paths}
)
unset(_lua_library_names)
diff --git a/Modules/FindODBC.cmake b/Modules/FindODBC.cmake
new file mode 100644
index 0000000..c8ca477
--- /dev/null
+++ b/Modules/FindODBC.cmake
@@ -0,0 +1,227 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+FindODBC
+--------
+
+Find an Open Database Connectivity (ODBC) include directory and library.
+
+On Windows, when building with Visual Studio, this module assumes the ODBC
+library is provided by the available Windows SDK.
+
+On Unix, this module allows to search for ODBC library provided by
+unixODBC or iODBC implementations of ODBC API.
+This module reads hint about location of the config program:
+
+.. variable:: ODBC_CONFIG
+
+ Location of odbc_config or iodbc-config program
+
+Otherwise, this module tries to find the config program,
+first from unixODBC, then from iODBC.
+If no config program found, this module searches for ODBC header
+and library in list of known locations.
+
+Imported targets
+^^^^^^^^^^^^^^^^
+
+This module defines the following :prop_tgt:`IMPORTED` targets:
+
+.. variable:: ODBC::ODBC
+
+ Imported target for using the ODBC library, if found.
+
+Result variables
+^^^^^^^^^^^^^^^^
+
+.. variable:: ODBC_FOUND
+
+ Set to true if ODBC library found, otherwise false or undefined.
+
+.. variable:: ODBC_INCLUDE_DIRS
+
+ Paths to include directories listed in one variable for use by ODBC client.
+ May be empty on Windows, where the include directory corresponding to the
+ expected Windows SDK is already available in the compilation environment.
+
+.. variable:: ODBC_LIBRARIES
+
+ Paths to libraries to linked against to use ODBC.
+ May just a library name on Windows, where the library directory corresponding
+ to the expected Windows SDK is already available in the compilation environment.
+
+.. variable:: ODBC_CONFIG
+
+ Path to unixODBC or iODBC config program, if found or specified.
+
+Cache variables
+^^^^^^^^^^^^^^^
+
+For users who wish to edit and control the module behavior, this module
+reads hints about search locations from the following variables:
+
+.. variable:: ODBC_INCLUDE_DIR
+
+ Path to ODBC include directory with ``sql.h`` header.
+
+.. variable:: ODBC_LIBRARY
+
+ Path to ODBC library to be linked.
+
+These variables should not be used directly by project code.
+
+Limitations
+^^^^^^^^^^^
+
+On Windows, this module does not search for iODBC.
+On Unix, there is no way to prefer unixODBC over iODBC, or vice versa,
+other than providing the config program location using the ``ODBC_CONFIG``.
+This module does not allow to search for a specific ODBC driver.
+
+#]=======================================================================]
+
+# Define lists used internally
+set(_odbc_include_paths)
+set(_odbc_lib_paths)
+set(_odbc_lib_names)
+set(_odbc_required_libs_names)
+
+### Try Windows Kits ##########################################################
+if(WIN32)
+ # List names of ODBC libraries on Windows
+ set(ODBC_LIBRARY odbc32.lib)
+ set(_odbc_lib_names odbc32;)
+
+ # List additional libraries required to use ODBC library
+ if(MSVC OR CMAKE_CXX_COMPILER_ID MATCHES "Intel")
+ set(_odbc_required_libs_names odbccp32;ws2_32)
+ elseif(MINGW)
+ set(_odbc_required_libs_names odbccp32)
+ endif()
+endif()
+
+### Try unixODBC or iODBC config program ######################################
+if (UNIX)
+ find_program(ODBC_CONFIG
+ NAMES odbc_config iodbc-config
+ DOC "Path to unixODBC or iODBC config program")
+ mark_as_advanced(ODBC_CONFIG)
+endif()
+
+if (UNIX AND ODBC_CONFIG)
+ # unixODBC and iODBC accept unified command line options
+ execute_process(COMMAND ${ODBC_CONFIG} --cflags
+ OUTPUT_VARIABLE _cflags OUTPUT_STRIP_TRAILING_WHITESPACE)
+ execute_process(COMMAND ${ODBC_CONFIG} --libs
+ OUTPUT_VARIABLE _libs OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+ # Collect paths of include directories from CFLAGS
+ separate_arguments(_cflags NATIVE_COMMAND "${_cflags}")
+ foreach(arg IN LISTS _cflags)
+ if("${arg}" MATCHES "^-I(.*)$")
+ list(APPEND _odbc_include_paths "${CMAKE_MATCH_1}")
+ endif()
+ endforeach()
+ unset(_cflags)
+
+ # Collect paths of library names and directories from LIBS
+ separate_arguments(_libs NATIVE_COMMAND "${_libs}")
+ foreach(arg IN LISTS _libs)
+ if("${arg}" MATCHES "^-L(.*)$")
+ list(APPEND _odbc_lib_paths "${CMAKE_MATCH_1}")
+ elseif("${arg}" MATCHES "^-l(.*)$")
+ set(_lib_name ${CMAKE_MATCH_1})
+ string(REGEX MATCH "odbc" _is_odbc ${_lib_name})
+ if(_is_odbc)
+ list(APPEND _odbc_lib_names ${_lib_name})
+ else()
+ list(APPEND _odbc_required_libs_names ${_lib_name})
+ endif()
+ unset(_lib_name)
+ endif()
+ endforeach()
+ unset(_libs)
+endif()
+
+### Try unixODBC or iODBC in include/lib filesystems ##########################
+if (UNIX AND NOT ODBC_CONFIG)
+ # List names of both ODBC libraries, unixODBC and iODBC
+ set(_odbc_lib_names odbc;iodbc;unixodbc;)
+endif()
+
+### Find include directories ##################################################
+find_path(ODBC_INCLUDE_DIR
+ NAMES sql.h
+ PATHS ${_odbc_include_paths})
+
+if(NOT ODBC_INCLUDE_DIR AND WIN32)
+ set(ODBC_INCLUDE_DIR "")
+endif()
+
+### Find libraries ############################################################
+if(NOT ODBC_LIBRARY)
+ find_library(ODBC_LIBRARY
+ NAMES ${_odbc_lib_names}
+ PATHS ${_odbc_lib_paths}
+ PATH_SUFFIXES odbc)
+
+ foreach(_lib IN LISTS _odbc_required_libs_names)
+ find_library(_lib_path
+ NAMES ${_lib}
+ PATHS ${_odbc_lib_paths} # system parths or collected from ODBC_CONFIG
+ PATH_SUFFIXES odbc)
+ if(_lib_path)
+ list(APPEND _odbc_required_libs_paths ${_lib_path})
+ endif()
+ unset(_lib_path CACHE)
+ endforeach()
+endif()
+
+# Unset internal lists as no longer used
+unset(_odbc_include_paths)
+unset(_odbc_lib_paths)
+unset(_odbc_lib_names)
+unset(_odbc_required_libs_names)
+
+### Set result variables ######################################################
+set(_odbc_required_vars ODBC_LIBRARY)
+if(NOT WIN32)
+ list(APPEND _odbc_required_vars ODBC_INCLUDE_DIR)
+endif()
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(ODBC DEFAULT_MSG ${_odbc_required_vars})
+
+unset(_odbc_required_vars)
+
+mark_as_advanced(ODBC_LIBRARY ODBC_INCLUDE_DIR)
+
+set(ODBC_INCLUDE_DIRS ${ODBC_INCLUDE_DIR})
+list(APPEND ODBC_LIBRARIES ${ODBC_LIBRARY})
+list(APPEND ODBC_LIBRARIES ${_odbc_required_libs_paths})
+
+### Import targets ############################################################
+if(ODBC_FOUND)
+ if(NOT TARGET ODBC::ODBC)
+ if(IS_ABSOLUTE "${ODBC_LIBRARY}")
+ add_library(ODBC::ODBC UNKNOWN IMPORTED)
+ set_target_properties(ODBC::ODBC PROPERTIES
+ IMPORTED_LINK_INTERFACE_LANGUAGES "C"
+ IMPORTED_LOCATION "${ODBC_LIBRARY}")
+ else()
+ add_library(ODBC::ODBC INTERFACE IMPORTED)
+ set_target_properties(ODBC::ODBC PROPERTIES
+ IMPORTED_LIBNAME "${ODBC_LIBRARY}")
+ endif()
+ set_target_properties(ODBC::ODBC PROPERTIES
+ INTERFACE_INCLUDE_DIRECTORIES "${ODBC_INCLUDE_DIR}")
+
+ if(_odbc_required_libs_paths)
+ set_property(TARGET ODBC::ODBC APPEND PROPERTY
+ INTERFACE_LINK_LIBRARIES "${_odbc_required_libs_paths}")
+ endif()
+ endif()
+endif()
+
+unset(_odbc_required_libs_paths)
diff --git a/Modules/FindPerl.cmake b/Modules/FindPerl.cmake
index 423fc69..c38527c 100644
--- a/Modules/FindPerl.cmake
+++ b/Modules/FindPerl.cmake
@@ -28,6 +28,7 @@ if(WIN32)
NAME)
set(PERL_POSSIBLE_BIN_PATHS ${PERL_POSSIBLE_BIN_PATHS}
"C:/Perl/bin"
+ "C:/Strawberry/perl/bin"
[HKEY_LOCAL_MACHINE\\SOFTWARE\\ActiveState\\ActivePerl\\${ActivePerl_CurrentVersion}]/bin
)
endif()
diff --git a/Modules/FindPkgConfig.cmake b/Modules/FindPkgConfig.cmake
index 415e914..775a9d7 100644
--- a/Modules/FindPkgConfig.cmake
+++ b/Modules/FindPkgConfig.cmake
@@ -183,8 +183,8 @@ endfunction()
# scan the LDFLAGS returned by pkg-config for library directories and
# libraries, figure out the absolute paths of that libraries in the
-# given directories, and create an imported target from them
-function(_pkg_create_imp_target _prefix _no_cmake_path _no_cmake_environment_path)
+# given directories
+function(_pkg_find_libs _prefix _no_cmake_path _no_cmake_environment_path)
unset(_libs)
unset(_find_opts)
@@ -200,9 +200,7 @@ function(_pkg_create_imp_target _prefix _no_cmake_path _no_cmake_environment_pat
unset(_search_paths)
foreach (flag IN LISTS ${_prefix}_LDFLAGS)
if (flag MATCHES "^-L(.*)")
- # only look into the given paths from now on
list(APPEND _search_paths ${CMAKE_MATCH_1})
- set(_find_opts HINTS ${_search_paths} NO_DEFAULT_PATH)
continue()
endif()
if (flag MATCHES "^-l(.*)")
@@ -211,24 +209,35 @@ function(_pkg_create_imp_target _prefix _no_cmake_path _no_cmake_environment_pat
continue()
endif()
+ if(_search_paths)
+ # Firstly search in -L paths
+ find_library(pkgcfg_lib_${_prefix}_${_pkg_search}
+ NAMES ${_pkg_search}
+ HINTS ${_search_paths} NO_DEFAULT_PATH)
+ endif()
find_library(pkgcfg_lib_${_prefix}_${_pkg_search}
NAMES ${_pkg_search}
${_find_opts})
list(APPEND _libs "${pkgcfg_lib_${_prefix}_${_pkg_search}}")
endforeach()
+ set(${_prefix}_LINK_LIBRARIES "${_libs}" PARENT_SCOPE)
+endfunction()
+
+# create an imported target from all the information returned by pkg-config
+function(_pkg_create_imp_target _prefix)
# only create the target if it is linkable, i.e. no executables
if (NOT TARGET PkgConfig::${_prefix}
- AND ( ${_prefix}_INCLUDE_DIRS OR _libs OR ${_prefix}_CFLAGS_OTHER ))
+ AND ( ${_prefix}_INCLUDE_DIRS OR ${_prefix}_LINK_LIBRARIES OR ${_prefix}_CFLAGS_OTHER ))
add_library(PkgConfig::${_prefix} INTERFACE IMPORTED)
if(${_prefix}_INCLUDE_DIRS)
set_property(TARGET PkgConfig::${_prefix} PROPERTY
INTERFACE_INCLUDE_DIRECTORIES "${${_prefix}_INCLUDE_DIRS}")
endif()
- if(_libs)
+ if(${_prefix}_LINK_LIBRARIES)
set_property(TARGET PkgConfig::${_prefix} PROPERTY
- INTERFACE_LINK_LIBRARIES "${_libs}")
+ INTERFACE_LINK_LIBRARIES "${${_prefix}_LINK_LIBRARIES}")
endif()
if(${_prefix}_CFLAGS_OTHER)
set_property(TARGET PkgConfig::${_prefix} PROPERTY
@@ -237,6 +246,15 @@ function(_pkg_create_imp_target _prefix _no_cmake_path _no_cmake_environment_pat
endif()
endfunction()
+# recalculate the dynamic output
+# this is a macro and not a function so the result of _pkg_find_libs is automatically propagated
+macro(_pkg_recalculate _prefix _no_cmake_path _no_cmake_environment_path _imp_target)
+ _pkg_find_libs(${_prefix} ${_no_cmake_path} ${_no_cmake_environment_path})
+ if(${_imp_target})
+ _pkg_create_imp_target(${_prefix})
+ endif()
+endmacro()
+
###
macro(_pkg_check_modules_internal _is_required _is_silent _no_cmake_path _no_cmake_environment_path _imp_target _prefix)
_pkgconfig_unset(${_prefix}_FOUND)
@@ -456,9 +474,7 @@ macro(_pkg_check_modules_internal _is_required _is_silent _no_cmake_path _no_cma
_pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" CFLAGS "" --cflags )
_pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" CFLAGS_OTHER "" --cflags-only-other )
- if (_imp_target)
- _pkg_create_imp_target("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path})
- endif()
+ _pkg_recalculate("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target})
endif()
if(NOT "${_extra_paths}" STREQUAL "")
@@ -521,6 +537,7 @@ endmacro()
<XXX>_FOUND ... set to 1 if module(s) exist
<XXX>_LIBRARIES ... only the libraries (without the '-l')
+ <XXX>_LINK_LIBRARIES ... the libraries and their absolute paths
<XXX>_LIBRARY_DIRS ... the paths of the libraries (without the '-L')
<XXX>_LDFLAGS ... all required linker flags
<XXX>_LDFLAGS_OTHER ... all other linker flags
@@ -588,8 +605,10 @@ macro(pkg_check_modules _prefix _module0)
if (${_prefix}_FOUND)
_pkgconfig_set(__pkg_config_arguments_${_prefix} "${_module0};${ARGN}")
endif()
- elseif (${_prefix}_FOUND AND ${_imp_target})
- _pkg_create_imp_target("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path})
+ else()
+ if (${_prefix}_FOUND)
+ _pkg_recalculate("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target})
+ endif()
endif()
endmacro()
@@ -642,8 +661,8 @@ macro(pkg_search_module _prefix _module0)
endif()
_pkgconfig_set(__pkg_config_checked_${_prefix} ${PKG_CONFIG_VERSION})
- elseif (${_prefix}_FOUND AND ${_imp_target})
- _pkg_create_imp_target("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path})
+ elseif (${_prefix}_FOUND)
+ _pkg_recalculate("${_prefix}" ${_no_cmake_path} ${_no_cmake_environment_path} ${_imp_target})
endif()
endmacro()
diff --git a/Modules/FindQt4.cmake b/Modules/FindQt4.cmake
index 5a7eadb..847a798 100644
--- a/Modules/FindQt4.cmake
+++ b/Modules/FindQt4.cmake
@@ -547,15 +547,11 @@ if (QT_QMAKE_EXECUTABLE AND
if(NOT WIN32)
string(REPLACE ":" ";" qt_mkspecs_dirs "${qt_mkspecs_dirs}")
endif()
- set(qt_cross_paths)
- foreach(qt_cross_path ${CMAKE_FIND_ROOT_PATH})
- set(qt_cross_paths ${qt_cross_paths} "${qt_cross_path}/mkspecs")
- endforeach()
- set(QT_MKSPECS_DIR NOTFOUND)
+
find_path(QT_MKSPECS_DIR NAMES qconfig.pri
- HINTS ${qt_cross_paths} ${qt_mkspecs_dirs}
- DOC "The location of the Qt mkspecs containing qconfig.pri"
- NO_CMAKE_FIND_ROOT_PATH)
+ HINTS ${qt_mkspecs_dirs}
+ PATH_SUFFIXES mkspecs share/qt4/mkspecs
+ DOC "The location of the Qt mkspecs containing qconfig.pri")
endif()
if(EXISTS "${QT_MKSPECS_DIR}/qconfig.pri")
@@ -709,14 +705,15 @@ if (QT_QMAKE_EXECUTABLE AND
# ask qmake for the plugins directory
if (QT_LIBRARY_DIR AND NOT QT_PLUGINS_DIR OR QT_QMAKE_CHANGED)
_qt4_query_qmake(QT_INSTALL_PLUGINS qt_plugins_dir)
- set(QT_PLUGINS_DIR NOTFOUND)
- foreach(qt_cross_path ${CMAKE_FIND_ROOT_PATH})
- set(qt_cross_paths ${qt_cross_paths} "${qt_cross_path}/plugins")
- endforeach()
- find_path(QT_PLUGINS_DIR NAMES accessible imageformats sqldrivers codecs designer
- HINTS ${qt_cross_paths} ${qt_plugins_dir}
- DOC "The location of the Qt plugins"
- NO_CMAKE_FIND_ROOT_PATH)
+ if(CMAKE_CROSSCOMPILING OR NOT qt_plugins_dir)
+ find_path(QT_PLUGINS_DIR
+ NAMES accessible bearer codecs designer graphicssystems iconengines imageformats inputmethods qmltooling script sqldrivers
+ HINTS ${qt_plugins_dir}
+ PATH_SUFFIXES plugins lib/qt4/plugins
+ DOC "The location of the Qt plugins")
+ else()
+ set(QT_PLUGINS_DIR ${qt_plugins_dir} CACHE PATH "The location of the Qt plugins")
+ endif()
endif ()
# ask qmake for the translations directory
@@ -728,18 +725,13 @@ if (QT_QMAKE_EXECUTABLE AND
# ask qmake for the imports directory
if (QT_LIBRARY_DIR AND NOT QT_IMPORTS_DIR OR QT_QMAKE_CHANGED)
_qt4_query_qmake(QT_INSTALL_IMPORTS qt_imports_dir)
- if(qt_imports_dir)
- set(QT_IMPORTS_DIR NOTFOUND)
- foreach(qt_cross_path ${CMAKE_FIND_ROOT_PATH})
- set(qt_cross_paths ${qt_cross_paths} "${qt_cross_path}/imports")
- endforeach()
+ if(CMAKE_CROSSCOMPILING OR NOT qt_imports_dir)
find_path(QT_IMPORTS_DIR NAMES Qt
- HINTS ${qt_cross_paths} ${qt_imports_dir}
- DOC "The location of the Qt imports"
- NO_CMAKE_FIND_ROOT_PATH
- NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- mark_as_advanced(QT_IMPORTS_DIR)
+ HINTS ${qt_imports_dir}
+ PATH_SUFFIXES imports lib/qt4/imports
+ DOC "The location of the Qt imports")
+ else()
+ set(QT_IMPORTS_DIR ${qt_imports_dir} CACHE PATH "The location of the Qt imports")
endif()
endif ()
diff --git a/Modules/InstallRequiredSystemLibraries.cmake b/Modules/InstallRequiredSystemLibraries.cmake
index 0fd76c0..36dd0a0 100644
--- a/Modules/InstallRequiredSystemLibraries.cmake
+++ b/Modules/InstallRequiredSystemLibraries.cmake
@@ -584,8 +584,10 @@ if(_IRSL_HAVE_Intel)
foreach(__Intel_lib IN ITEMS libchkp.dylib libcilkrts.5.dylib libcilkrts.dylib libimf.dylib libintlc.dylib libirc.dylib libirng.dylib libsvml.dylib)
list(APPEND __install_libs "${_Intel_redistdir}/${__Intel_lib}")
endforeach()
- if(_Intel_compiler_ver VERSION_LESS 17)
- list(APPEND __install_libs "${_Intel_redistdir}/libistrconv.dylib")
+ if(CMAKE_C_COMPILER_ID STREQUAL Intel OR CMAKE_CXX_COMPILER_ID STREQUAL Intel)
+ if(_Intel_compiler_ver VERSION_LESS 17)
+ list(APPEND __install_libs "${_Intel_redistdir}/libistrconv.dylib")
+ endif()
endif()
if(CMAKE_Fortran_COMPILER_ID STREQUAL Intel)
foreach(__Intel_lib IN ITEMS libifcore.dylib libifcoremt.dylib libifport.dylib libifportmt.dylib)
@@ -594,8 +596,7 @@ if(_IRSL_HAVE_Intel)
endforeach()
endif()
else()
- set(__install_dirs "${_Intel_redistdir}/irml")
- foreach(__Intel_lib IN ITEMS cilk_db.so libchkp.so libcilkrts.so libcilkrts.so.5 libimf.so libintlc.so libintlc.so.5 libirc.so libpdbx.so libpdbx.so.5 libsvml.so)
+ foreach(__Intel_lib IN ITEMS libchkp.so libcilkrts.so libcilkrts.so.5 libimf.so libintlc.so libintlc.so.5 libirc.so libpdbx.so libpdbx.so.5 libsvml.so)
list(APPEND __install_libs "${_Intel_redistdir}/${__Intel_lib}")
endforeach()
@@ -605,10 +606,11 @@ if(_IRSL_HAVE_Intel)
list(APPEND __install_libs "${_Intel_redistdir}/${__Intel_lib}")
endforeach()
endif()
- if(_Intel_compiler_ver VERSION_GREATER_EQUAL 15)
- list(APPEND __install_libs "${_Intel_redistdir}/libistrconv.so")
- if(CMAKE_C_COMPILER_ID STREQUAL Intel OR CMAKE_CXX_COMPILER_ID STREQUAL Intel)
- list(APPEND __install_libs "${_Intel_redistdir}/libgfxoffload.so")
+ if(CMAKE_C_COMPILER_ID STREQUAL Intel OR CMAKE_CXX_COMPILER_ID STREQUAL Intel)
+ set(__install_dirs "${_Intel_redistdir}/irml")
+ list(APPEND __install_libs "${_Intel_redistdir}/cilk_db.so")
+ if(_Intel_compiler_ver VERSION_GREATER_EQUAL 15)
+ list(APPEND __install_libs "${_Intel_redistdir}/libistrconv.so" "${_Intel_redistdir}/libgfxoffload.so")
endif()
endif()
if(_Intel_compiler_ver VERSION_GREATER_EQUAL 16)
diff --git a/Modules/Platform/Windows-NVIDIA-CUDA.cmake b/Modules/Platform/Windows-NVIDIA-CUDA.cmake
index 0c11e55..f1c1f2d 100644
--- a/Modules/Platform/Windows-NVIDIA-CUDA.cmake
+++ b/Modules/Platform/Windows-NVIDIA-CUDA.cmake
@@ -15,7 +15,7 @@ foreach(lib ${CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES})
string(APPEND __IMPLICT_LINKS " \"${lib}\"")
endforeach()
set(CMAKE_CUDA_LINK_EXECUTABLE
- "<CMAKE_CUDA_HOST_LINK_LAUNCHER> <CMAKE_CUDA_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> <LINK_LIBRARIES>${__IMPLICT_LINKS}")
+ "<CMAKE_CUDA_HOST_LINK_LAUNCHER> <LINK_FLAGS> <OBJECTS> /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> <LINK_LIBRARIES>${__IMPLICT_LINKS}")
set(_CMAKE_VS_LINK_DLL "<CMAKE_COMMAND> -E vs_link_dll --intdir=<OBJECT_DIR> --manifests <MANIFESTS> -- ")
set(_CMAKE_VS_LINK_EXE "<CMAKE_COMMAND> -E vs_link_exe --intdir=<OBJECT_DIR> --manifests <MANIFESTS> -- ")
@@ -26,7 +26,7 @@ set(CMAKE_CUDA_CREATE_SHARED_MODULE ${CMAKE_CUDA_CREATE_SHARED_LIBRARY})
set(CMAKE_CUDA_CREATE_STATIC_LIBRARY "<CMAKE_LINKER> /lib ${CMAKE_CL_NOLOGO} <LINK_FLAGS> /out:<TARGET> <OBJECTS> ")
set(CMAKE_CUDA_LINKER_SUPPORTS_PDB ON)
set(CMAKE_CUDA_LINK_EXECUTABLE
- "${_CMAKE_VS_LINK_EXE}<CMAKE_LINKER> ${CMAKE_CL_NOLOGO} <OBJECTS> ${CMAKE_START_TEMP_FILE} /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} <CMAKE_CUDA_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES>${__IMPLICT_LINKS} ${CMAKE_END_TEMP_FILE}")
+ "${_CMAKE_VS_LINK_EXE}<CMAKE_LINKER> ${CMAKE_CL_NOLOGO} <OBJECTS> ${CMAKE_START_TEMP_FILE} /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} <LINK_FLAGS> <LINK_LIBRARIES>${__IMPLICT_LINKS} ${CMAKE_END_TEMP_FILE}")
unset(_CMAKE_VS_LINK_EXE)
unset(_CMAKE_VS_LINK_EXE)
@@ -51,9 +51,9 @@ endforeach()
unset(__IMPLICT_DLINK_DIRS)
set(CMAKE_CUDA_DEVICE_LINK_LIBRARY
- "<CMAKE_CUDA_COMPILER> <CMAKE_CUDA_LINK_FLAGS> <LANGUAGE_COMPILE_FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS${__IMPLICT_DLINK_FLAGS}")
+ "<CMAKE_CUDA_COMPILER> <LANGUAGE_COMPILE_FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS${__IMPLICT_DLINK_FLAGS}")
set(CMAKE_CUDA_DEVICE_LINK_EXECUTABLE
- "<CMAKE_CUDA_COMPILER> <FLAGS> <CMAKE_CUDA_LINK_FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS${__IMPLICT_DLINK_FLAGS}")
+ "<CMAKE_CUDA_COMPILER> <FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS${__IMPLICT_DLINK_FLAGS}")
unset(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS)
unset(__IMPLICT_DLINK_FLAGS)
diff --git a/Modules/Qt4Macros.cmake b/Modules/Qt4Macros.cmake
index aee4028..a2c8d85 100644
--- a/Modules/Qt4Macros.cmake
+++ b/Modules/Qt4Macros.cmake
@@ -151,7 +151,8 @@ macro (QT4_GENERATE_MOC infile outfile )
set(moc_target ${ARGV3})
endif()
QT4_CREATE_MOC_COMMAND(${abs_infile} ${_outfile} "${moc_flags}" "" "${moc_target}")
- set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOMOC TRUE) # don't run automoc on this file
+ set_property(SOURCE ${outfile} PROPERTY SKIP_AUTOMOC TRUE) # don't run automoc on this file
+ set_property(SOURCE ${outfile} PROPERTY SKIP_AUTOUIC TRUE) # don't run autouic on this file
endmacro ()
@@ -166,6 +167,8 @@ macro (QT4_WRAP_CPP outfiles )
get_filename_component(it ${it} ABSOLUTE)
QT4_MAKE_OUTPUT_FILE(${it} moc_ cxx outfile)
QT4_CREATE_MOC_COMMAND(${it} ${outfile} "${moc_flags}" "${moc_options}" "${moc_target}")
+ set_property(SOURCE ${outfile} PROPERTY SKIP_AUTOMOC TRUE) # don't run automoc on this file
+ set_property(SOURCE ${outfile} PROPERTY SKIP_AUTOUIC TRUE) # don't run autouic on this file
set(${outfiles} ${${outfiles}} ${outfile})
endforeach()
@@ -185,6 +188,8 @@ macro (QT4_WRAP_UI outfiles )
COMMAND Qt4::uic
ARGS ${ui_options} -o ${outfile} ${infile}
MAIN_DEPENDENCY ${infile} VERBATIM)
+ set_property(SOURCE ${outfile} PROPERTY SKIP_AUTOMOC TRUE) # don't run automoc on this file
+ set_property(SOURCE ${outfile} PROPERTY SKIP_AUTOUIC TRUE) # don't run autouic on this file
set(${outfiles} ${${outfiles}} ${outfile})
endforeach ()
@@ -233,6 +238,8 @@ macro (QT4_ADD_RESOURCES outfiles )
ARGS ${rcc_options} -name ${outfilename} -o ${outfile} ${infile}
MAIN_DEPENDENCY ${infile}
DEPENDS ${_RC_DEPENDS} "${out_depends}" VERBATIM)
+ set_property(SOURCE ${outfile} PROPERTY SKIP_AUTOMOC TRUE) # don't run automoc on this file
+ set_property(SOURCE ${outfile} PROPERTY SKIP_AUTOUIC TRUE) # don't run autouic on this file
set(${outfiles} ${${outfiles}} ${outfile})
endforeach ()
@@ -245,19 +252,19 @@ macro(QT4_ADD_DBUS_INTERFACE _sources _interface _basename)
set(_impl "${CMAKE_CURRENT_BINARY_DIR}/${_basename}.cpp")
set(_moc "${CMAKE_CURRENT_BINARY_DIR}/${_basename}.moc")
- get_source_file_property(_nonamespace ${_interface} NO_NAMESPACE)
+ get_property(_nonamespace SOURCE ${_interface} PROPERTY NO_NAMESPACE)
if(_nonamespace)
set(_params -N -m)
else()
set(_params -m)
endif()
- get_source_file_property(_classname ${_interface} CLASSNAME)
+ get_property(_classname SOURCE ${_interface} PROPERTY CLASSNAME)
if(_classname)
set(_params ${_params} -c ${_classname})
endif()
- get_source_file_property(_include ${_interface} INCLUDE)
+ get_property(_include SOURCE ${_interface} PROPERTY INCLUDE)
if(_include)
set(_params ${_params} -i ${_include})
endif()
@@ -266,7 +273,8 @@ macro(QT4_ADD_DBUS_INTERFACE _sources _interface _basename)
COMMAND Qt4::qdbusxml2cpp ${_params} -p ${_basename} ${_infile}
DEPENDS ${_infile} VERBATIM)
- set_source_files_properties("${_impl}" PROPERTIES SKIP_AUTOMOC TRUE)
+ set_property(SOURCE ${_impl} PROPERTY SKIP_AUTOMOC TRUE) # don't run automoc on this file
+ set_property(SOURCE ${_impl} PROPERTY SKIP_AUTOUIC TRUE) # don't run autouic on this file
QT4_GENERATE_MOC("${_header}" "${_moc}")
@@ -350,7 +358,8 @@ macro(QT4_ADD_DBUS_ADAPTOR _sources _xml_file _include _parentClass) # _optional
endif()
QT4_GENERATE_MOC("${_header}" "${_moc}")
- set_source_files_properties("${_impl}" PROPERTIES SKIP_AUTOMOC TRUE)
+ set_property(SOURCE ${_impl} PROPERTY SKIP_AUTOMOC TRUE) # don't run automoc on this file
+ set_property(SOURCE ${_impl} PROPERTY SKIP_AUTOUIC TRUE) # don't run autouic on this file
MACRO_ADD_FILE_DEPENDENCIES("${_impl}" "${_moc}")
list(APPEND ${_sources} "${_impl}" "${_header}" "${_moc}")
@@ -374,7 +383,7 @@ macro(QT4_AUTOMOC)
# cmake is run for the very first time on them -> however the .cpp files might
# exist at a later run. at that time we need to skip them, so that we don't add two
# different rules for the same moc file
- get_source_file_property(_skip ${_abs_FILE} SKIP_AUTOMOC)
+ get_property(_skip SOURCE ${_abs_FILE} PROPERTY SKIP_AUTOMOC)
if ( NOT _skip AND EXISTS ${_abs_FILE} )
@@ -454,7 +463,7 @@ macro(QT4_ADD_TRANSLATION _qm_files)
foreach (_current_FILE ${ARGN})
get_filename_component(_abs_FILE ${_current_FILE} ABSOLUTE)
get_filename_component(qm ${_abs_FILE} NAME_WE)
- get_source_file_property(output_location ${_abs_FILE} OUTPUT_LOCATION)
+ get_property(output_location SOURCE ${_abs_FILE} PROPERTY OUTPUT_LOCATION)
if(output_location)
file(MAKE_DIRECTORY "${output_location}")
set(qm "${output_location}/${qm}.qm")
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index d9e07e5..316d50b 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -886,6 +886,7 @@ set(CPACK_SRCS
CPack/cmCPackGenerator.cxx
CPack/cmCPackLog.cxx
CPack/cmCPackNSISGenerator.cxx
+ CPack/cmCPackNuGetGenerator.cxx
CPack/cmCPackSTGZGenerator.cxx
CPack/cmCPackTGZGenerator.cxx
CPack/cmCPackTXZGenerator.cxx
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index c439e9e..d3930be 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 11)
-set(CMake_VERSION_PATCH 20180506)
+set(CMake_VERSION_PATCH 20180529)
#set(CMake_VERSION_RC 1)
diff --git a/Source/CPack/cmCPackGeneratorFactory.cxx b/Source/CPack/cmCPackGeneratorFactory.cxx
index 47e7527..a395a8f 100644
--- a/Source/CPack/cmCPackGeneratorFactory.cxx
+++ b/Source/CPack/cmCPackGeneratorFactory.cxx
@@ -15,6 +15,7 @@
#include "cmCPackGenerator.h"
#include "cmCPackLog.h"
#include "cmCPackNSISGenerator.h"
+#include "cmCPackNuGetGenerator.h"
#include "cmCPackSTGZGenerator.h"
#include "cmCPackTGZGenerator.h"
#include "cmCPackTXZGenerator.h"
@@ -105,6 +106,10 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory()
this->RegisterGenerator("DEB", "Debian packages",
cmCPackDebGenerator::CreateGenerator);
}
+ if (cmCPackNuGetGenerator::CanGenerate()) {
+ this->RegisterGenerator("NuGet", "NuGet packages",
+ cmCPackNuGetGenerator::CreateGenerator);
+ }
#ifdef __APPLE__
if (cmCPackDragNDropGenerator::CanGenerate()) {
this->RegisterGenerator("DragNDrop", "Mac OSX Drag And Drop",
diff --git a/Source/CPack/cmCPackNuGetGenerator.cxx b/Source/CPack/cmCPackNuGetGenerator.cxx
new file mode 100644
index 0000000..2ebfb3d
--- /dev/null
+++ b/Source/CPack/cmCPackNuGetGenerator.cxx
@@ -0,0 +1,140 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCPackNuGetGenerator.h"
+
+#include "cmAlgorithms.h"
+#include "cmCPackComponentGroup.h"
+#include "cmCPackLog.h"
+#include "cmSystemTools.h"
+
+#include <algorithm>
+#include <iterator>
+#include <map>
+#include <ostream>
+#include <string>
+#include <utility>
+#include <vector>
+
+bool cmCPackNuGetGenerator::SupportsComponentInstallation() const
+{
+ return IsOn("CPACK_NUGET_COMPONENT_INSTALL");
+}
+
+int cmCPackNuGetGenerator::PackageFiles()
+{
+ cmCPackLogger(cmCPackLog::LOG_DEBUG, "Toplevel: " << toplevel << std::endl);
+
+ /* Reset package file name list it will be populated after the
+ * `CPackNuGet.cmake` run */
+ packageFileNames.clear();
+
+ /* Are we in the component packaging case */
+ if (WantsComponentInstallation()) {
+ if (componentPackageMethod == ONE_PACKAGE) {
+ // CASE 1 : COMPONENT ALL-IN-ONE package
+ // Meaning that all per-component pre-installed files
+ // goes into the single package.
+ this->SetOption("CPACK_NUGET_ALL_IN_ONE", "TRUE");
+ SetupGroupComponentVariables(true);
+ } else {
+ // CASE 2 : COMPONENT CLASSICAL package(s) (i.e. not all-in-one)
+ // There will be 1 package for each component group
+ // however one may require to ignore component group and
+ // in this case you'll get 1 package for each component.
+ SetupGroupComponentVariables(componentPackageMethod ==
+ ONE_PACKAGE_PER_COMPONENT);
+ }
+ } else {
+ // CASE 3 : NON COMPONENT package.
+ this->SetOption("CPACK_NUGET_ORDINAL_MONOLITIC", "TRUE");
+ }
+
+ auto retval = this->ReadListFile("CPackNuGet.cmake");
+ if (retval) {
+ AddGeneratedPackageNames();
+ } else {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error while execution CPackNuGet.cmake" << std::endl);
+ }
+
+ return retval;
+}
+
+void cmCPackNuGetGenerator::SetupGroupComponentVariables(bool ignoreGroup)
+{
+ // The default behavior is to have one package by component group
+ // unless CPACK_COMPONENTS_IGNORE_GROUP is specified.
+ if (!ignoreGroup) {
+ std::vector<std::string> groups;
+ for (auto const& compG : this->ComponentGroups) {
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "Packaging component group: " << compG.first << std::endl);
+ groups.push_back(compG.first);
+ auto compGUp =
+ cmSystemTools::UpperCase(cmSystemTools::MakeCidentifier(compG.first));
+
+ // Collect components for this group
+ std::vector<std::string> components;
+ std::transform(begin(compG.second.Components),
+ end(compG.second.Components),
+ std::back_inserter(components),
+ [](cmCPackComponent const* comp) { return comp->Name; });
+ this->SetOption("CPACK_NUGET_" + compGUp + "_GROUP_COMPONENTS",
+ cmJoin(components, ";").c_str());
+ }
+ if (!groups.empty()) {
+ this->SetOption("CPACK_NUGET_GROUPS", cmJoin(groups, ";").c_str());
+ }
+
+ // Handle Orphan components (components not belonging to any groups)
+ std::vector<std::string> components;
+ for (auto const& comp : this->Components) {
+ // Does the component belong to a group?
+ if (comp.second.Group == nullptr) {
+ cmCPackLogger(
+ cmCPackLog::LOG_VERBOSE, "Component <"
+ << comp.second.Name
+ << "> does not belong to any group, package it separately."
+ << std::endl);
+ components.push_back(comp.first);
+ }
+ }
+ if (!components.empty()) {
+ this->SetOption("CPACK_NUGET_COMPONENTS",
+ cmJoin(components, ";").c_str());
+ }
+
+ } else {
+ std::vector<std::string> components;
+ components.reserve(this->Components.size());
+ std::transform(begin(this->Components), end(this->Components),
+ std::back_inserter(components),
+ [](std::pair<std::string, cmCPackComponent> const& comp) {
+ return comp.first;
+ });
+ this->SetOption("CPACK_NUGET_COMPONENTS", cmJoin(components, ";").c_str());
+ }
+}
+
+void cmCPackNuGetGenerator::AddGeneratedPackageNames()
+{
+ const char* const files_list = this->GetOption("GEN_CPACK_OUTPUT_FILES");
+ if (!files_list) {
+ cmCPackLogger(
+ cmCPackLog::LOG_ERROR,
+ "Error while execution CPackNuGet.cmake: No NuGet package has generated"
+ << std::endl);
+ return;
+ }
+ // add the generated packages to package file names list
+ std::string fileNames{ files_list };
+ const char sep = ';';
+ std::string::size_type pos1 = 0;
+ std::string::size_type pos2 = fileNames.find(sep, pos1 + 1);
+ while (pos2 != std::string::npos) {
+ packageFileNames.push_back(fileNames.substr(pos1, pos2 - pos1));
+ pos1 = pos2 + 1;
+ pos2 = fileNames.find(sep, pos1 + 1);
+ }
+ packageFileNames.push_back(fileNames.substr(pos1, pos2 - pos1));
+}
diff --git a/Source/CPack/cmCPackNuGetGenerator.h b/Source/CPack/cmCPackNuGetGenerator.h
new file mode 100644
index 0000000..a59db2d
--- /dev/null
+++ b/Source/CPack/cmCPackNuGetGenerator.h
@@ -0,0 +1,37 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCPackNuGetGenerator_h
+#define cmCPackNuGetGenerator_h
+
+#include "cmCPackGenerator.h"
+
+/** \class cmCPackNuGetGenerator
+ * \brief A generator for RPM packages
+ */
+class cmCPackNuGetGenerator : public cmCPackGenerator
+{
+public:
+ cmCPackTypeMacro(cmCPackNuGetGenerator, cmCPackGenerator);
+
+ // NOTE In fact, it is possible to have NuGet not only for Windows...
+ // https://docs.microsoft.com/en-us/nuget/install-nuget-client-tools
+ static bool CanGenerate() { return true; }
+
+protected:
+ bool SupportsComponentInstallation() const override;
+ int PackageFiles() override;
+
+ const char* GetOutputExtension() override { return ".nupkg"; }
+ bool SupportsAbsoluteDestination() const override { return false; }
+ /**
+ * The method used to prepare variables when component
+ * install is used.
+ */
+ void SetupGroupComponentVariables(bool ignoreGroup);
+ /**
+ * Populate \c packageFileNames vector of built packages.
+ */
+ void AddGeneratedPackageNames();
+};
+
+#endif
diff --git a/Source/CTest/cmCTestLaunch.cxx b/Source/CTest/cmCTestLaunch.cxx
index 30f76a9..e078645 100644
--- a/Source/CTest/cmCTestLaunch.cxx
+++ b/Source/CTest/cmCTestLaunch.cxx
@@ -347,28 +347,27 @@ void cmCTestLaunch::WriteXML()
// Use cmGeneratedFileStream to atomically create the report file.
cmGeneratedFileStream fxml(logXML.c_str());
cmXMLWriter xml(fxml, 2);
- xml.StartElement("Failure");
- xml.Attribute("type", this->IsError() ? "Error" : "Warning");
- this->WriteXMLAction(xml);
- this->WriteXMLCommand(xml);
- this->WriteXMLResult(xml);
- this->WriteXMLLabels(xml);
- xml.EndElement(); // Failure
+ cmXMLElement e2(xml, "Failure");
+ e2.Attribute("type", this->IsError() ? "Error" : "Warning");
+ this->WriteXMLAction(e2);
+ this->WriteXMLCommand(e2);
+ this->WriteXMLResult(e2);
+ this->WriteXMLLabels(e2);
}
-void cmCTestLaunch::WriteXMLAction(cmXMLWriter& xml)
+void cmCTestLaunch::WriteXMLAction(cmXMLElement& e2)
{
- xml.Comment("Meta-information about the build action");
- xml.StartElement("Action");
+ e2.Comment("Meta-information about the build action");
+ cmXMLElement e3(e2, "Action");
// TargetName
if (!this->OptionTargetName.empty()) {
- xml.Element("TargetName", this->OptionTargetName);
+ e3.Element("TargetName", this->OptionTargetName);
}
// Language
if (!this->OptionLanguage.empty()) {
- xml.Element("Language", this->OptionLanguage);
+ e3.Element("Language", this->OptionLanguage);
}
// SourceFile
@@ -383,12 +382,12 @@ void cmCTestLaunch::WriteXMLAction(cmXMLWriter& xml)
source = cmSystemTools::RelativePath(this->SourceDir, source);
}
- xml.Element("SourceFile", source);
+ e3.Element("SourceFile", source);
}
// OutputFile
if (!this->OptionOutput.empty()) {
- xml.Element("OutputFile", this->OptionOutput);
+ e3.Element("OutputFile", this->OptionOutput);
}
// OutputType
@@ -407,97 +406,88 @@ void cmCTestLaunch::WriteXMLAction(cmXMLWriter& xml)
outputType = "object file";
}
if (outputType) {
- xml.Element("OutputType", outputType);
+ e3.Element("OutputType", outputType);
}
-
- xml.EndElement(); // Action
}
-void cmCTestLaunch::WriteXMLCommand(cmXMLWriter& xml)
+void cmCTestLaunch::WriteXMLCommand(cmXMLElement& e2)
{
- xml.Comment("Details of command");
- xml.StartElement("Command");
+ e2.Comment("Details of command");
+ cmXMLElement e3(e2, "Command");
if (!this->CWD.empty()) {
- xml.Element("WorkingDirectory", this->CWD);
+ e3.Element("WorkingDirectory", this->CWD);
}
for (std::string const& realArg : this->RealArgs) {
- xml.Element("Argument", realArg);
+ e3.Element("Argument", realArg);
}
- xml.EndElement(); // Command
}
-void cmCTestLaunch::WriteXMLResult(cmXMLWriter& xml)
+void cmCTestLaunch::WriteXMLResult(cmXMLElement& e2)
{
- xml.Comment("Result of command");
- xml.StartElement("Result");
+ e2.Comment("Result of command");
+ cmXMLElement e3(e2, "Result");
// StdOut
- xml.StartElement("StdOut");
- this->DumpFileToXML(xml, this->LogOut);
- xml.EndElement(); // StdOut
+ this->DumpFileToXML(e3, "StdOut", this->LogOut);
// StdErr
- xml.StartElement("StdErr");
- this->DumpFileToXML(xml, this->LogErr);
- xml.EndElement(); // StdErr
+ this->DumpFileToXML(e3, "StdErr", this->LogErr);
// ExitCondition
- xml.StartElement("ExitCondition");
+ cmXMLElement e4(e3, "ExitCondition");
cmsysProcess* cp = this->Process;
switch (cmsysProcess_GetState(cp)) {
case cmsysProcess_State_Starting:
- xml.Content("No process has been executed");
+ e4.Content("No process has been executed");
break;
case cmsysProcess_State_Executing:
- xml.Content("The process is still executing");
+ e4.Content("The process is still executing");
break;
case cmsysProcess_State_Disowned:
- xml.Content("Disowned");
+ e4.Content("Disowned");
break;
case cmsysProcess_State_Killed:
- xml.Content("Killed by parent");
+ e4.Content("Killed by parent");
break;
case cmsysProcess_State_Expired:
- xml.Content("Killed when timeout expired");
+ e4.Content("Killed when timeout expired");
break;
case cmsysProcess_State_Exited:
- xml.Content(this->ExitCode);
+ e4.Content(this->ExitCode);
break;
case cmsysProcess_State_Exception:
- xml.Content("Terminated abnormally: ");
- xml.Content(cmsysProcess_GetExceptionString(cp));
+ e4.Content("Terminated abnormally: ");
+ e4.Content(cmsysProcess_GetExceptionString(cp));
break;
case cmsysProcess_State_Error:
- xml.Content("Error administrating child process: ");
- xml.Content(cmsysProcess_GetErrorString(cp));
+ e4.Content("Error administrating child process: ");
+ e4.Content(cmsysProcess_GetErrorString(cp));
break;
- };
- xml.EndElement(); // ExitCondition
-
- xml.EndElement(); // Result
+ }
}
-void cmCTestLaunch::WriteXMLLabels(cmXMLWriter& xml)
+void cmCTestLaunch::WriteXMLLabels(cmXMLElement& e2)
{
this->LoadLabels();
if (!this->Labels.empty()) {
- xml.Comment("Interested parties");
- xml.StartElement("Labels");
+ e2.Comment("Interested parties");
+ cmXMLElement e3(e2, "Labels");
for (std::string const& label : this->Labels) {
- xml.Element("Label", label);
+ e3.Element("Label", label);
}
- xml.EndElement(); // Labels
}
}
-void cmCTestLaunch::DumpFileToXML(cmXMLWriter& xml, std::string const& fname)
+void cmCTestLaunch::DumpFileToXML(cmXMLElement& e3, const char* tag,
+ std::string const& fname)
{
cmsys::ifstream fin(fname.c_str(), std::ios::in | std::ios::binary);
std::string line;
const char* sep = "";
+ cmXMLElement e4(e3, tag);
while (cmSystemTools::GetLineFromStream(fin, line)) {
if (MatchesFilterPrefix(line)) {
continue;
@@ -507,8 +497,8 @@ void cmCTestLaunch::DumpFileToXML(cmXMLWriter& xml, std::string const& fname)
} else if (this->Match(line, this->RegexWarning)) {
line = "[CTest: warning matched] " + line;
}
- xml.Content(sep);
- xml.Content(line);
+ e4.Content(sep);
+ e4.Content(line);
sep = "\n";
}
}
diff --git a/Source/CTest/cmCTestLaunch.h b/Source/CTest/cmCTestLaunch.h
index 29986ff..debbe59 100644
--- a/Source/CTest/cmCTestLaunch.h
+++ b/Source/CTest/cmCTestLaunch.h
@@ -10,7 +10,7 @@
#include <string>
#include <vector>
-class cmXMLWriter;
+class cmXMLElement;
/** \class cmCTestLaunch
* \brief Launcher for make rules to report results for ctest
@@ -89,11 +89,11 @@ private:
// Methods to generate the xml fragment.
void WriteXML();
- void WriteXMLAction(cmXMLWriter& xml);
- void WriteXMLCommand(cmXMLWriter& xml);
- void WriteXMLResult(cmXMLWriter& xml);
- void WriteXMLLabels(cmXMLWriter& xml);
- void DumpFileToXML(cmXMLWriter& xml, std::string const& fname);
+ void WriteXMLAction(cmXMLElement&);
+ void WriteXMLCommand(cmXMLElement&);
+ void WriteXMLResult(cmXMLElement&);
+ void WriteXMLLabels(cmXMLElement&);
+ void DumpFileToXML(cmXMLElement&, const char* tag, std::string const& fname);
// Configuration
void LoadConfig();
diff --git a/Source/CTest/cmCTestStartCommand.cxx b/Source/CTest/cmCTestStartCommand.cxx
index 38ee623..367616c 100644
--- a/Source/CTest/cmCTestStartCommand.cxx
+++ b/Source/CTest/cmCTestStartCommand.cxx
@@ -28,41 +28,41 @@ bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args,
}
size_t cnt = 0;
- const char* smodel = args[cnt].c_str();
+ const char* smodel = nullptr;
const char* src_dir = nullptr;
const char* bld_dir = nullptr;
- cnt++;
-
- this->CTest->SetSpecificTrack(nullptr);
- if (cnt < args.size() - 1) {
+ while (cnt < args.size()) {
if (args[cnt] == "TRACK") {
cnt++;
+ if (cnt >= args.size() || args[cnt] == "APPEND" ||
+ args[cnt] == "QUIET") {
+ this->SetError("TRACK argument missing track name");
+ return false;
+ }
this->CTest->SetSpecificTrack(args[cnt].c_str());
cnt++;
- }
- }
-
- if (cnt < args.size()) {
- if (args[cnt] == "APPEND") {
+ } else if (args[cnt] == "APPEND") {
cnt++;
this->CreateNewTag = false;
- }
- }
- if (cnt < args.size()) {
- if (args[cnt] == "QUIET") {
+ } else if (args[cnt] == "QUIET") {
cnt++;
this->Quiet = true;
- }
- }
-
- if (cnt < args.size()) {
- src_dir = args[cnt].c_str();
- cnt++;
- if (cnt < args.size()) {
+ } else if (!smodel) {
+ smodel = args[cnt].c_str();
+ cnt++;
+ } else if (!src_dir) {
+ src_dir = args[cnt].c_str();
+ cnt++;
+ } else if (!bld_dir) {
bld_dir = args[cnt].c_str();
+ cnt++;
+ } else {
+ this->SetError("Too many arguments");
+ return false;
}
}
+
if (!src_dir) {
src_dir = this->Makefile->GetDefinition("CTEST_SOURCE_DIRECTORY");
}
@@ -79,6 +79,11 @@ bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args,
"as an argument or set CTEST_BINARY_DIRECTORY");
return false;
}
+ if (!smodel && this->CreateNewTag) {
+ this->SetError("no test model specified and APPEND not specified. Specify "
+ "either a test model or the APPEND argument");
+ return false;
+ }
cmSystemTools::AddKeepPath(src_dir);
cmSystemTools::AddKeepPath(bld_dir);
@@ -92,11 +97,20 @@ bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args,
this->CTest->SetCTestConfiguration("BuildDirectory", binaryDir.c_str(),
this->Quiet);
- cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "Run dashboard with model "
- << smodel << std::endl
- << " Source directory: " << src_dir << std::endl
- << " Build directory: " << bld_dir << std::endl,
- this->Quiet);
+ if (smodel) {
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "Run dashboard with model "
+ << smodel << std::endl
+ << " Source directory: " << src_dir << std::endl
+ << " Build directory: " << bld_dir << std::endl,
+ this->Quiet);
+ } else {
+ cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "Run dashboard with "
+ "to-be-determined model"
+ << std::endl
+ << " Source directory: " << src_dir << std::endl
+ << " Build directory: " << bld_dir << std::endl,
+ this->Quiet);
+ }
const char* track = this->CTest->GetSpecificTrack();
if (track) {
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
@@ -128,7 +142,12 @@ bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args,
this->CTest->SetRunCurrentScript(false);
this->CTest->SetSuppressUpdatingCTestConfiguration(true);
- int model = this->CTest->GetTestModelFromString(smodel);
+ int model;
+ if (smodel) {
+ model = this->CTest->GetTestModelFromString(smodel);
+ } else {
+ model = cmCTest::UNKNOWN;
+ }
this->CTest->SetTestModel(model);
this->CTest->SetProduceXML(true);
diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx
index 1278232..7792235 100644
--- a/Source/cmAddLibraryCommand.cxx
+++ b/Source/cmAddLibraryCommand.cxx
@@ -228,6 +228,14 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
this->SetError(e.str());
return false;
}
+ if (aliasedTarget->IsImported() &&
+ !aliasedTarget->IsImportedGloballyVisible()) {
+ std::ostringstream e;
+ e << "cannot create ALIAS target \"" << libName << "\" because target \""
+ << aliasedName << "\" is imported but not globally visible.";
+ this->SetError(e.str());
+ return false;
+ }
this->Makefile->AddAlias(libName, aliasedName);
return true;
}
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index 3fccc38..2c32dea 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -474,11 +474,13 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command)
day != lctime->tm_mday) {
tag.clear();
}
- std::string tagmode;
- if (cmSystemTools::GetLineFromStream(tfin, tagmode)) {
- if (tagmode.size() > 4 && !this->Parts[PartStart]) {
- this->TestModel = cmCTest::GetTestModelFromString(tagmode.c_str());
- }
+ std::string track;
+ if (cmSystemTools::GetLineFromStream(tfin, track)) {
+ this->SpecificTrack = track;
+ }
+ std::string model;
+ if (cmSystemTools::GetLineFromStream(tfin, model)) {
+ this->TestModel = GetTestModelFromString(model.c_str());
}
tfin.close();
}
@@ -502,6 +504,17 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command)
if (ofs) {
ofs << tag << std::endl;
ofs << this->GetTestModelString() << std::endl;
+ switch (this->TestModel) {
+ case cmCTest::EXPERIMENTAL:
+ ofs << "Experimental" << std::endl;
+ break;
+ case cmCTest::NIGHTLY:
+ ofs << "Nightly" << std::endl;
+ break;
+ case cmCTest::CONTINUOUS:
+ ofs << "Continuous" << std::endl;
+ break;
+ }
}
ofs.close();
if (nullptr == command) {
@@ -512,8 +525,16 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command)
}
}
} else {
+ std::string track;
+ std::string modelStr;
+ int model = cmCTest::UNKNOWN;
+
if (tfin) {
cmSystemTools::GetLineFromStream(tfin, tag);
+ cmSystemTools::GetLineFromStream(tfin, track);
+ if (cmSystemTools::GetLineFromStream(tfin, modelStr)) {
+ model = GetTestModelFromString(modelStr.c_str());
+ }
tfin.close();
}
@@ -523,6 +544,35 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command)
return 0;
}
+ if (this->TestModel == cmCTest::UNKNOWN) {
+ if (model == cmCTest::UNKNOWN) {
+ cmCTestLog(this, ERROR_MESSAGE,
+ "TAG file does not contain model and "
+ "no model specified in start command"
+ << std::endl);
+ return 0;
+ }
+
+ this->SetTestModel(model);
+ }
+
+ if (model != this->TestModel && model != cmCTest::UNKNOWN &&
+ this->TestModel != cmCTest::UNKNOWN) {
+ cmCTestOptionalLog(this, WARNING, "Model given in TAG does not match "
+ "model given in ctest_start()"
+ << std::endl,
+ quiet);
+ }
+
+ if (!this->SpecificTrack.empty() && track != this->SpecificTrack) {
+ cmCTestOptionalLog(this, WARNING, "Track given in TAG does not match "
+ "track given in ctest_start()"
+ << std::endl,
+ quiet);
+ } else {
+ this->SpecificTrack = track;
+ }
+
cmCTestOptionalLog(this, OUTPUT, " Use existing tag: "
<< tag << " - " << this->GetTestModelString()
<< std::endl,
diff --git a/Source/cmCTest.h b/Source/cmCTest.h
index b2f4f25..603bb41 100644
--- a/Source/cmCTest.h
+++ b/Source/cmCTest.h
@@ -295,9 +295,10 @@ public:
enum
{
- EXPERIMENTAL,
- NIGHTLY,
- CONTINUOUS
+ UNKNOWN = -1,
+ EXPERIMENTAL = 0,
+ NIGHTLY = 1,
+ CONTINUOUS = 2,
};
/** provide some more detailed info on the return code for ctest */
diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx
index 136cf39..6c9f9d6 100644
--- a/Source/cmCustomCommandGenerator.cxx
+++ b/Source/cmCustomCommandGenerator.cxx
@@ -40,6 +40,14 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc,
argv.push_back(std::move(parsed_arg));
}
}
+
+ // Later code assumes at least one entry exists, but expanding
+ // lists on an empty command may have left this empty.
+ // FIXME: Should we define behavior for removing empty commands?
+ if (argv.empty()) {
+ argv.push_back(std::string());
+ }
+
this->CommandLines.push_back(std::move(argv));
}
diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx
index 258c9ca..e7279d9 100644
--- a/Source/cmExtraEclipseCDT4Generator.cxx
+++ b/Source/cmExtraEclipseCDT4Generator.cxx
@@ -1001,6 +1001,13 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
xml.EndElement(); // project
xml.EndElement(); // storageModule
+
+ // Append additional cproject contents without applying any XML formatting
+ if (const char* extraCProjectContents =
+ mf->GetState()->GetGlobalProperty("ECLIPSE_EXTRA_CPROJECT_CONTENTS")) {
+ fout << extraCProjectContents;
+ }
+
xml.EndElement(); // cproject
}
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 6c1a869..1e47687 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -232,6 +232,14 @@ bool cmFileCommand::HandleWriteCommand(std::vector<std::string> const& args,
}
std::string message = cmJoin(cmMakeRange(i, args.end()), std::string());
file << message;
+ if (!file) {
+ std::string error = "write failed (";
+ error += cmSystemTools::GetLastSystemError();
+ error += "):\n ";
+ error += fileName;
+ this->SetError(error);
+ return false;
+ }
file.close();
if (mode) {
cmSystemTools::SetPermissions(fileName.c_str(), mode);
diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx
index df288bd..9ff967c 100644
--- a/Source/cmForEachCommand.cxx
+++ b/Source/cmForEachCommand.cxx
@@ -29,10 +29,10 @@ bool cmForEachFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
cmMakefile& mf,
cmExecutionStatus& inStatus)
{
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "foreach")) {
+ if (lff.Name.Lower == "foreach") {
// record the number of nested foreach commands
this->Depth++;
- } else if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endforeach")) {
+ } else if (lff.Name.Lower == "endforeach") {
// if this is the endofreach for this statement
if (!this->Depth) {
// Remove the function blocker for this scope or bail.
@@ -97,7 +97,7 @@ bool cmForEachFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
bool cmForEachFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
cmMakefile& mf)
{
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endforeach")) {
+ if (lff.Name.Lower == "endforeach") {
std::vector<std::string> expandedArguments;
mf.ExpandArguments(lff.Arguments, expandedArguments);
// if the endforeach has arguments then make sure
diff --git a/Source/cmFunctionCommand.cxx b/Source/cmFunctionCommand.cxx
index 774df84..67c9e9a 100644
--- a/Source/cmFunctionCommand.cxx
+++ b/Source/cmFunctionCommand.cxx
@@ -9,7 +9,6 @@
#include "cmMakefile.h"
#include "cmPolicies.h"
#include "cmState.h"
-#include "cmSystemTools.h"
// define the class for function commands
class cmFunctionHelperCommand : public cmCommand
@@ -128,9 +127,9 @@ bool cmFunctionFunctionBlocker::IsFunctionBlocked(
{
// record commands until we hit the ENDFUNCTION
// at the ENDFUNCTION call we shift gears and start looking for invocations
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "function")) {
+ if (lff.Name.Lower == "function") {
this->Depth++;
- } else if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endfunction")) {
+ } else if (lff.Name.Lower == "endfunction") {
// if this is the endfunction for this function then execute
if (!this->Depth) {
// create a new command and add it to cmake
@@ -157,7 +156,7 @@ bool cmFunctionFunctionBlocker::IsFunctionBlocked(
bool cmFunctionFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
cmMakefile& mf)
{
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endfunction")) {
+ if (lff.Name.Lower == "endfunction") {
std::vector<std::string> expandedArguments;
mf.ExpandArguments(lff.Arguments, expandedArguments,
this->GetStartingContext().FilePath.c_str());
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index bf5ff65..0c99ed4 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -4612,13 +4612,24 @@ bool cmGeneratorTarget::ComputePDBOutputDir(const std::string& kind,
// Select an output directory.
if (const char* config_outdir = this->GetProperty(configProp)) {
// Use the user-specified per-configuration output directory.
- out = config_outdir;
+ cmGeneratorExpression ge;
+ std::unique_ptr<cmCompiledGeneratorExpression> cge =
+ ge.Parse(config_outdir);
+ out = cge->Evaluate(this->LocalGenerator, config);
// Skip per-configuration subdirectory.
conf.clear();
} else if (const char* outdir = this->GetProperty(propertyName)) {
// Use the user-specified output directory.
- out = outdir;
+ cmGeneratorExpression ge;
+ std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(outdir);
+ out = cge->Evaluate(this->LocalGenerator, config);
+
+ // Skip per-configuration subdirectory if the value contained a
+ // generator expression.
+ if (out != outdir) {
+ conf.clear();
+ }
}
if (out.empty()) {
return false;
@@ -5510,12 +5521,14 @@ cmGeneratorTarget::ManagedType cmGeneratorTarget::GetManagedType(
const std::string& config) const
{
// Only libraries and executables can be managed targets.
- if (this->GetType() != cmStateEnums::SHARED_LIBRARY &&
- this->GetType() != cmStateEnums::STATIC_LIBRARY &&
- this->GetType() != cmStateEnums::EXECUTABLE) {
+ if (this->GetType() > cmStateEnums::SHARED_LIBRARY) {
return ManagedType::Undefined;
}
+ if (this->GetType() == cmStateEnums::STATIC_LIBRARY) {
+ return ManagedType::Native;
+ }
+
// Check imported target.
if (this->IsImported()) {
if (cmGeneratorTarget::ImportInfo const* info =
diff --git a/Source/cmIfCommand.cxx b/Source/cmIfCommand.cxx
index 4926f22..ae4041d 100644
--- a/Source/cmIfCommand.cxx
+++ b/Source/cmIfCommand.cxx
@@ -30,9 +30,9 @@ bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
cmExecutionStatus& inStatus)
{
// we start by recording all the functions
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "if")) {
+ if (lff.Name.Lower == "if") {
this->ScopeDepth++;
- } else if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endif")) {
+ } else if (lff.Name.Lower == "endif") {
this->ScopeDepth--;
// if this is the endif for this if statement, then start executing
if (!this->ScopeDepth) {
@@ -48,15 +48,14 @@ bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
int scopeDepth = 0;
for (cmListFileFunction const& func : this->Functions) {
// keep track of scope depth
- if (!cmSystemTools::Strucmp(func.Name.c_str(), "if")) {
+ if (func.Name.Lower == "if") {
scopeDepth++;
}
- if (!cmSystemTools::Strucmp(func.Name.c_str(), "endif")) {
+ if (func.Name.Lower == "endif") {
scopeDepth--;
}
// watch for our state change
- if (scopeDepth == 0 &&
- !cmSystemTools::Strucmp(func.Name.c_str(), "else")) {
+ if (scopeDepth == 0 && func.Name.Lower == "else") {
if (this->ElseSeen) {
cmListFileBacktrace bt = mf.GetBacktrace(func);
@@ -76,8 +75,7 @@ bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
if (!this->IsBlocking && mf.GetCMakeInstance()->GetTrace()) {
mf.PrintCommandTrace(func);
}
- } else if (scopeDepth == 0 &&
- !cmSystemTools::Strucmp(func.Name.c_str(), "elseif")) {
+ } else if (scopeDepth == 0 && func.Name.Lower == "elseif") {
if (this->ElseSeen) {
cmListFileBacktrace bt = mf.GetBacktrace(func);
mf.GetCMakeInstance()->IssueMessage(
@@ -163,7 +161,7 @@ bool cmIfFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
bool cmIfFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
cmMakefile&)
{
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endif")) {
+ if (lff.Name.Lower == "endif") {
// if the endif has arguments, then make sure
// they match the arguments of the matching if
if (lff.Arguments.empty() || lff.Arguments == this->Args) {
diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx
index 64e634f..b468257 100644
--- a/Source/cmListFileCache.cxx
+++ b/Source/cmListFileCache.cxx
@@ -13,6 +13,14 @@
#include <assert.h>
#include <sstream>
+cmCommandContext::cmCommandName& cmCommandContext::cmCommandName::operator=(
+ std::string const& name)
+{
+ this->Original = name;
+ this->Lower = cmSystemTools::LowerCase(name);
+ return *this;
+}
+
struct cmListFileParser
{
cmListFileParser(cmListFile* lf, cmListFileBacktrace const& lfbt,
diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h
index 1f9e374..70f7166 100644
--- a/Source/cmListFileCache.h
+++ b/Source/cmListFileCache.h
@@ -23,11 +23,22 @@ class cmMessenger;
struct cmCommandContext
{
- std::string Name;
+ struct cmCommandName
+ {
+ std::string Lower;
+ std::string Original;
+ cmCommandName() {}
+ cmCommandName(std::string const& name) { *this = name; }
+ cmCommandName& operator=(std::string const& name);
+ } Name;
long Line;
cmCommandContext()
- : Name()
- , Line(0)
+ : Line(0)
+ {
+ }
+ cmCommandContext(const char* name, int line)
+ : Name(name)
+ , Line(line)
{
}
};
@@ -81,7 +92,7 @@ public:
cmListFileContext lfc;
lfc.FilePath = fileName;
lfc.Line = lfcc.Line;
- lfc.Name = lfcc.Name;
+ lfc.Name = lfcc.Name.Original;
return lfc;
}
};
diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx
index 6f4b930..23d93a3 100644
--- a/Source/cmMacroCommand.cxx
+++ b/Source/cmMacroCommand.cxx
@@ -161,9 +161,9 @@ bool cmMacroFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
{
// record commands until we hit the ENDMACRO
// at the ENDMACRO call we shift gears and start looking for invocations
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "macro")) {
+ if (lff.Name.Lower == "macro") {
this->Depth++;
- } else if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endmacro")) {
+ } else if (lff.Name.Lower == "endmacro") {
// if this is the endmacro for this macro then execute
if (!this->Depth) {
mf.AppendProperty("MACROS", this->Args[0].c_str());
@@ -191,7 +191,7 @@ bool cmMacroFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
bool cmMacroFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
cmMakefile& mf)
{
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endmacro")) {
+ if (lff.Name.Lower == "endmacro") {
std::vector<std::string> expandedArguments;
mf.ExpandArguments(lff.Arguments, expandedArguments,
this->GetStartingContext().FilePath.c_str());
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index f41c2f0..d67d280 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -224,7 +224,7 @@ cmListFileBacktrace cmMakefile::GetBacktrace() const
cmListFileBacktrace cmMakefile::GetBacktrace(cmCommandContext const& cc) const
{
cmListFileContext lfc;
- lfc.Name = cc.Name;
+ lfc.Name = cc.Name.Original;
lfc.Line = cc.Line;
lfc.FilePath = this->StateSnapshot.GetExecutionListFile();
return this->Backtrace.Push(lfc);
@@ -265,7 +265,7 @@ void cmMakefile::PrintCommandTrace(const cmListFileFunction& lff) const
std::ostringstream msg;
msg << full_path << "(" << lff.Line << "): ";
- msg << lff.Name << "(";
+ msg << lff.Name.Original << "(";
bool expand = this->GetCMakeInstance()->GetTraceExpand();
std::string temp;
for (cmListFileArgument const& arg : lff.Arguments) {
@@ -317,14 +317,13 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff,
return result;
}
- std::string name = lff.Name;
-
// Place this call on the call stack.
cmMakefileCall stack_manager(this, lff, status);
static_cast<void>(stack_manager);
// Lookup the command prototype.
- if (cmCommand* proto = this->GetState()->GetCommand(name)) {
+ if (cmCommand* proto =
+ this->GetState()->GetCommandByExactName(lff.Name.Lower)) {
// Clone the prototype.
std::unique_ptr<cmCommand> pcmd(proto->Clone());
pcmd->SetMakefile(this);
@@ -341,7 +340,8 @@ 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();
+ std::string const error =
+ std::string(lff.Name.Original) + " " + pcmd->GetError();
this->IssueMessage(cmake::FATAL_ERROR, error);
}
result = false;
@@ -356,7 +356,7 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff,
} else {
if (!cmSystemTools::GetFatalErrorOccured()) {
std::string error = "Unknown CMake command \"";
- error += lff.Name;
+ error += lff.Name.Original;
error += "\".";
this->IssueMessage(cmake::FATAL_ERROR, error);
result = false;
@@ -1454,7 +1454,7 @@ void cmMakefile::Configure()
bool hasVersion = false;
// search for the right policy command
for (cmListFileFunction const& func : listFile.Functions) {
- if (cmSystemTools::LowerCase(func.Name) == "cmake_minimum_required") {
+ if (func.Name.Lower == "cmake_minimum_required") {
hasVersion = true;
break;
}
@@ -1481,8 +1481,7 @@ void cmMakefile::Configure()
allowedCommands.insert("message");
isProblem = false;
for (cmListFileFunction const& func : listFile.Functions) {
- std::string name = cmSystemTools::LowerCase(func.Name);
- if (allowedCommands.find(name) == allowedCommands.end()) {
+ if (allowedCommands.find(func.Name.Lower) == allowedCommands.end()) {
isProblem = true;
break;
}
@@ -1501,7 +1500,7 @@ void cmMakefile::Configure()
bool hasProject = false;
// search for a project command
for (cmListFileFunction const& func : listFile.Functions) {
- if (cmSystemTools::LowerCase(func.Name) == "project") {
+ if (func.Name.Lower == "project") {
hasProject = true;
break;
}
@@ -1509,7 +1508,7 @@ void cmMakefile::Configure()
// if no project command is found, add one
if (!hasProject) {
cmListFileFunction project;
- project.Name = "PROJECT";
+ project.Name.Lower = "project";
project.Arguments.emplace_back("Project", cmListFileArgument::Unquoted,
0);
listFile.Functions.insert(listFile.Functions.begin(), project);
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index 27fae04..c538992 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -5,6 +5,7 @@
#include <algorithm>
#include <memory> // IWYU pragma: keep
#include <sstream>
+#include <stddef.h>
#include <vector>
#include "cmGeneratedFileStream.h"
@@ -732,10 +733,14 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
// Archiving rules never use a response file.
useResponseFileForObjects = false;
- // Limit the length of individual object lists to less than the
- // 32K command line length limit on Windows. We could make this a
- // platform file variable but this should work everywhere.
- archiveCommandLimit = 30000;
+ // Limit the length of individual object lists to less than half of
+ // the command line length limit (leaving half for other flags).
+ // This may result in several calls to the archiver.
+ if (size_t limit = cmSystemTools::CalculateCommandLineLengthLimit()) {
+ archiveCommandLimit = limit / 2;
+ } else {
+ archiveCommandLimit = 8000;
+ }
}
// Expand the rule variables.
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index 93c78b5..566a2a9 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -994,6 +994,9 @@ void cmQtAutoGenInitializer::SetupCustomTargets()
// Generate auto RCC info files
if (this->RccEnabled) {
for (Qrc const& qrc : this->Qrcs) {
+ // Register rcc info file as generated
+ makefile->AddCMakeOutputFile(qrc.InfoFile);
+
cmGeneratedFileStream ofs;
ofs.SetCopyIfDifferent(true);
ofs.Open(qrc.InfoFile.c_str(), false, true);
diff --git a/Source/cmRST.cxx b/Source/cmRST.cxx
index edcbc22..d9e5bcb 100644
--- a/Source/cmRST.cxx
+++ b/Source/cmRST.cxx
@@ -39,6 +39,8 @@ cmRST::cmRST(std::ostream& os, std::string const& docroot)
"prop_test|prop_tgt|"
"manual"
"):`(<*([^`<]|[^` \t]<)*)([ \t]+<[^`]*>)?`")
+ , InlineLink("`(<*([^`<]|[^` \t]<)*)([ \t]+<[^`]*>)?`_")
+ , InlineLiteral("``([^`]*)``")
, Substitution("(^|[^A-Za-z0-9_])"
"((\\|[^| \t\r\n]([^|\r\n]*[^| \t\r\n])?\\|)(__|_|))"
"([^A-Za-z0-9_]|$)")
@@ -245,18 +247,62 @@ void cmRST::OutputLine(std::string const& line_in, bool inlineMarkup)
if (inlineMarkup) {
std::string line = this->ReplaceSubstitutions(line_in);
std::string::size_type pos = 0;
- while (this->CMakeRole.find(line.c_str() + pos)) {
- this->OS << line.substr(pos, this->CMakeRole.start());
- std::string text = this->CMakeRole.match(3);
- // If a command reference has no explicit target and
- // no explicit "(...)" then add "()" to the text.
- if (this->CMakeRole.match(2) == "command" &&
- this->CMakeRole.match(5).empty() &&
- text.find_first_of("()") == std::string::npos) {
- text += "()";
+ for (;;) {
+ std::string::size_type* first = nullptr;
+ std::string::size_type role_start = std::string::npos;
+ std::string::size_type link_start = std::string::npos;
+ std::string::size_type lit_start = std::string::npos;
+ if (this->CMakeRole.find(line.c_str() + pos)) {
+ role_start = this->CMakeRole.start();
+ first = &role_start;
+ }
+ if (this->InlineLiteral.find(line.c_str() + pos)) {
+ lit_start = this->InlineLiteral.start();
+ if (!first || lit_start < *first) {
+ first = &lit_start;
+ }
+ }
+ if (this->InlineLink.find(line.c_str() + pos)) {
+ link_start = this->InlineLink.start();
+ if (!first || link_start < *first) {
+ first = &link_start;
+ }
+ }
+ if (first == &role_start) {
+ this->OS << line.substr(pos, role_start);
+ std::string text = this->CMakeRole.match(3);
+ // If a command reference has no explicit target and
+ // no explicit "(...)" then add "()" to the text.
+ if (this->CMakeRole.match(2) == "command" &&
+ this->CMakeRole.match(5).empty() &&
+ text.find_first_of("()") == std::string::npos) {
+ text += "()";
+ }
+ this->OS << "``" << text << "``";
+ pos += this->CMakeRole.end();
+ } else if (first == &lit_start) {
+ this->OS << line.substr(pos, lit_start);
+ std::string text = this->InlineLiteral.match(1);
+ pos += this->InlineLiteral.end();
+ this->OS << "``" << text << "``";
+ } else if (first == &link_start) {
+ this->OS << line.substr(pos, link_start);
+ std::string text = this->InlineLink.match(1);
+ bool escaped = false;
+ for (char c : text) {
+ if (escaped) {
+ escaped = false;
+ this->OS << c;
+ } else if (c == '\\') {
+ escaped = true;
+ } else {
+ this->OS << c;
+ }
+ }
+ pos += this->InlineLink.end();
+ } else {
+ break;
}
- this->OS << "``" << text << "``";
- pos += this->CMakeRole.end();
}
this->OS << line.substr(pos) << "\n";
} else {
diff --git a/Source/cmRST.h b/Source/cmRST.h
index d1a8e27..ee47867 100644
--- a/Source/cmRST.h
+++ b/Source/cmRST.h
@@ -85,6 +85,8 @@ private:
cmsys::RegularExpression NoteDirective;
cmsys::RegularExpression ModuleRST;
cmsys::RegularExpression CMakeRole;
+ cmsys::RegularExpression InlineLink;
+ cmsys::RegularExpression InlineLiteral;
cmsys::RegularExpression Substitution;
cmsys::RegularExpression TocTreeLink;
diff --git a/Source/cmState.cxx b/Source/cmState.cxx
index a93fb11..a57be4d 100644
--- a/Source/cmState.cxx
+++ b/Source/cmState.cxx
@@ -462,13 +462,17 @@ void cmState::AddScriptedCommand(std::string const& name, cmCommand* command)
cmCommand* cmState::GetCommand(std::string const& name) const
{
- std::string sName = cmSystemTools::LowerCase(name);
+ return GetCommandByExactName(cmSystemTools::LowerCase(name));
+}
+
+cmCommand* cmState::GetCommandByExactName(std::string const& name) const
+{
std::map<std::string, cmCommand*>::const_iterator pos;
- pos = this->ScriptedCommands.find(sName);
+ pos = this->ScriptedCommands.find(name);
if (pos != this->ScriptedCommands.end()) {
return pos->second;
}
- pos = this->BuiltinCommands.find(sName);
+ pos = this->BuiltinCommands.find(name);
if (pos != this->BuiltinCommands.end()) {
return pos->second;
}
diff --git a/Source/cmState.h b/Source/cmState.h
index 4c6fc69..38bdfec 100644
--- a/Source/cmState.h
+++ b/Source/cmState.h
@@ -125,7 +125,11 @@ public:
bool GetIsGeneratorMultiConfig() const;
void SetIsGeneratorMultiConfig(bool b);
+ // Returns a command from its name, case insensitive, or nullptr
cmCommand* GetCommand(std::string const& name) const;
+ // Returns a command from its name, or nullptr
+ cmCommand* GetCommandByExactName(std::string const& name) const;
+
void AddBuiltinCommand(std::string const& name, cmCommand* command);
void AddDisallowedCommand(std::string const& name, cmCommand* command,
cmPolicies::PolicyID policy, const char* message);
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 94c5ee8..169b525 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -1696,7 +1696,8 @@ void list_item_verbose(FILE* out, struct archive_entry* entry)
fflush(out);
}
-long copy_data(struct archive* ar, struct archive* aw)
+// Return 'true' on success
+bool copy_data(struct archive* ar, struct archive* aw)
{
long r;
const void* buff;
@@ -1708,22 +1709,28 @@ long copy_data(struct archive* ar, struct archive* aw)
#endif
for (;;) {
+ // Return value:
+ // * ARCHIVE_OK - read succeed
+ // * ARCHIVE_EOF - no more data to read left
r = archive_read_data_block(ar, &buff, &size, &offset);
if (r == ARCHIVE_EOF) {
- return (ARCHIVE_OK);
+ return true;
}
if (r != ARCHIVE_OK) {
- return (r);
+ return false;
}
- r = archive_write_data_block(aw, buff, size, offset);
- if (r != ARCHIVE_OK) {
+ // Return value:
+ // * >= ARCHIVE_OK - write succeed
+ // * < ARCHIVE_OK - write failed
+ const la_ssize_t w_size = archive_write_data_block(aw, buff, size, offset);
+ if (w_size < ARCHIVE_OK) {
cmSystemTools::Message("archive_write_data_block()",
archive_error_string(aw));
- return (r);
+ return false;
}
}
#if !defined(__clang__) && !defined(__HP_aCC)
- return r; /* this should not happen but it quiets some compilers */
+ return false; /* this should not happen but it quiets some compilers */
#endif
}
@@ -1776,7 +1783,10 @@ bool extract_tar(const char* outFileName, bool verbose, bool extract)
r = archive_write_header(ext, entry);
if (r == ARCHIVE_OK) {
- copy_data(a, ext);
+ if (!copy_data(a, ext)) {
+ cmSystemTools::Error("Problem with copy_data");
+ break;
+ }
r = archive_write_finish_entry(ext);
if (r != ARCHIVE_OK) {
cmSystemTools::Error("Problem with archive_write_finish_entry(): ",
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index d17a85a..7dcba74 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -399,6 +399,10 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
this->SetPropertyDefault("JOB_POOL_COMPILE", nullptr);
this->SetPropertyDefault("JOB_POOL_LINK", nullptr);
}
+
+ if (this->TargetTypeValue <= cmStateEnums::UTILITY) {
+ this->SetPropertyDefault("DOTNET_TARGET_FRAMEWORK_VERSION", nullptr);
+ }
}
cmGlobalGenerator* cmTarget::GetGlobalGenerator() const
diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx
index 699fff8..53f1213 100644
--- a/Source/cmTargetLinkLibrariesCommand.cxx
+++ b/Source/cmTargetLinkLibrariesCommand.cxx
@@ -364,7 +364,7 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib,
if (this->CurrentProcessingState != ProcessingKeywordLinkInterface &&
this->CurrentProcessingState != ProcessingPlainLinkInterface) {
- // Assure that the target on the LHS was created in the current directory.
+ // Find target on the LHS locally
cmTarget* t =
this->Makefile->FindLocalNonAliasTarget(this->Target->GetName());
if (!t) {
@@ -377,11 +377,18 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib,
}
}
}
+
+ // If no local target has been found, find it in the global scope
+ if (!t) {
+ t = this->Makefile->GetGlobalGenerator()->FindTarget(
+ this->Target->GetName(), true);
+ }
+
if (!t) {
std::ostringstream e;
e << "Attempt to add link library \"" << lib << "\" to target \""
<< this->Target->GetName()
- << "\" which is not built in this directory.";
+ << "\" which does not exist or is an alias target.";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
return false;
}
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 7a7c647..f3b9c84 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -40,13 +40,14 @@ static std::string cmVS10EscapeAttr(std::string arg)
struct cmVisualStudio10TargetGenerator::Elem
{
std::ostream& S;
- int Indent;
+ const int Indent;
bool HasElements = false;
+ bool HasContent = false;
std::string Tag;
- Elem(std::ostream& s, int i)
+ Elem(std::ostream& s)
: S(s)
- , Indent(i)
+ , Indent(0)
{
}
Elem(const Elem&) = delete;
@@ -77,46 +78,54 @@ struct cmVisualStudio10TargetGenerator::Elem
this->WriteString("<") << tag;
return *this;
}
- template <typename T>
- void WriteElem(const char* tag, const T& val)
- {
- this->WriteString("<") << tag << ">" << val << "</" << tag << ">\n";
- }
void Element(const char* tag, const std::string& val)
{
- Elem(*this).WriteElem(tag, cmVS10EscapeXML(val));
- }
- template <typename T>
- void Attr(const char* an, const T& av)
- {
- this->S << " " << an << "=\"" << av << "\"";
+ Elem(*this, tag).Content(val);
}
Elem& Attribute(const char* an, const std::string& av)
{
- Attr(an, cmVS10EscapeAttr(av));
+ this->S << " " << an << "=\"" << cmVS10EscapeAttr(av) << "\"";
return *this;
}
// This method for now assumes that this->Tag has been set, e.g. by calling
- // StartElement(). Also, it finishes the element so it should be the last
- // one called
+ // StartElement().
void Content(const std::string& val)
{
- S << ">" << cmVS10EscapeXML(val) << "</" << this->Tag << ">\n";
+ if (!this->HasContent) {
+ this->S << ">";
+ this->HasContent = true;
+ }
+ this->S << cmVS10EscapeXML(val);
}
- void WriteEndTag(const std::string& tag)
+ ~Elem()
{
+ // Do not emit element which has not been started
+ if (Tag.empty()) {
+ return;
+ }
+
if (HasElements) {
- this->WriteString("</") << tag << ">\n";
+ this->WriteString("</") << this->Tag << ">";
+ if (this->Indent > 0) {
+ this->S << '\n';
+ } else {
+ // special case: don't print EOL at EOF
+ }
+ } else if (HasContent) {
+ this->S << "</" << this->Tag << ">\n";
} else {
this->S << " />\n";
}
}
- void EndElement() { this->WriteEndTag(this->Tag); }
+
+ void WritePlatformConfigTag(const char* tag, const std::string& cond,
+ const std::string& content);
};
class cmVS10GeneratorOptions : public cmVisualStudioGeneratorOptions
{
public:
+ typedef cmVisualStudio10TargetGenerator::Elem Elem;
cmVS10GeneratorOptions(cmLocalVisualStudioGenerator* lg, Tool tool,
cmVS7FlagTable const* table,
cmVisualStudio10TargetGenerator* g = nullptr)
@@ -125,48 +134,51 @@ public:
{
}
- void OutputFlag(std::ostream& fout, int indent, const char* tag,
+ void OutputFlag(std::ostream& /*fout*/, int /*indent*/, const char* tag,
const std::string& content) override
{
if (!this->GetConfiguration().empty()) {
// if there are configuration specific flags, then
// use the configuration specific tag for PreprocessorDefinitions
- this->TargetGenerator->WritePlatformConfigTag(
- tag, this->GetConfiguration(), indent, content);
+ const std::string cond =
+ this->TargetGenerator->CalcCondition(this->GetConfiguration());
+ this->Parent->WritePlatformConfigTag(tag, cond, content);
} else {
- fout.fill(' ');
- fout.width(indent * 2);
- // write an empty string to get the fill level indent to print
- fout << "";
- fout << "<" << tag << ">";
- fout << cmVS10EscapeXML(content);
- fout << "</" << tag << ">\n";
+ this->Parent->Element(tag, content);
}
}
private:
- cmVisualStudio10TargetGenerator* TargetGenerator;
+ cmVisualStudio10TargetGenerator* const TargetGenerator;
+ Elem* Parent = nullptr;
+ friend cmVisualStudio10TargetGenerator::OptionsHelper;
};
-inline void cmVisualStudio10TargetGenerator::WriteElem(const char* tag,
- const char* val,
- int indentLevel)
-{
- Elem(*this->BuildFileStream, indentLevel).WriteElem(tag, val);
-}
-
-inline void cmVisualStudio10TargetGenerator::WriteElem(const char* tag,
- std::string const& val,
- int indentLevel)
+struct cmVisualStudio10TargetGenerator::OptionsHelper
{
- Elem(*this->BuildFileStream, indentLevel).WriteElem(tag, val);
-}
+ cmVS10GeneratorOptions& O;
+ OptionsHelper(cmVS10GeneratorOptions& o, Elem& e)
+ : O(o)
+ {
+ O.Parent = &e;
+ }
+ ~OptionsHelper() { O.Parent = nullptr; }
-inline void cmVisualStudio10TargetGenerator::WriteElemEscapeXML(
- const char* tag, std::string const& val, int indentLevel)
-{
- this->WriteElem(tag, cmVS10EscapeXML(val), indentLevel);
-}
+ void OutputPreprocessorDefinitions(const std::string& lang)
+ {
+ O.OutputPreprocessorDefinitions(O.Parent->S, O.Parent->Indent + 1, lang);
+ }
+ void OutputAdditionalIncludeDirectories(const std::string& lang)
+ {
+ O.OutputAdditionalIncludeDirectories(O.Parent->S, O.Parent->Indent + 1,
+ lang);
+ }
+ void OutputFlagMap() { O.OutputFlagMap(O.Parent->S, O.Parent->Indent + 1); }
+ void PrependInheritedString(std::string const& key)
+ {
+ O.PrependInheritedString(key);
+ }
+};
static std::string cmVS10EscapeComment(std::string comment)
{
@@ -236,7 +248,6 @@ cmVisualStudio10TargetGenerator::cmVisualStudio10TargetGenerator(
this->MSTools = !this->NsightTegra;
this->Managed = false;
this->TargetCompileAsWinRT = false;
- this->BuildFileStream = 0;
this->IsMissingFiles = false;
this->DefaultArtifactDir =
this->LocalGenerator->GetCurrentBinaryDirectory() + std::string("/") +
@@ -248,13 +259,6 @@ cmVisualStudio10TargetGenerator::cmVisualStudio10TargetGenerator(
cmVisualStudio10TargetGenerator::~cmVisualStudio10TargetGenerator()
{
- if (!this->BuildFileStream) {
- return;
- }
- if (this->BuildFileStream->Close()) {
- this->GlobalGenerator->FileReplacedDuringGenerate(this->PathToProjectFile);
- }
- delete this->BuildFileStream;
}
std::string cmVisualStudio10TargetGenerator::CalcCondition(
@@ -274,19 +278,10 @@ std::string cmVisualStudio10TargetGenerator::CalcCondition(
return oss.str();
}
-void cmVisualStudio10TargetGenerator::WritePlatformConfigTag(
- const char* tag, const std::string& config, int indentLevel,
- const std::string& content)
+void cmVisualStudio10TargetGenerator::Elem::WritePlatformConfigTag(
+ const char* tag, const std::string& cond, const std::string& content)
{
- std::ostream& stream = *this->BuildFileStream;
- stream.fill(' ');
- stream.width(indentLevel * 2);
- stream << ""; // applies indentation
- stream << "<" << tag << " Condition=\"";
- stream << this->CalcCondition(config);
- stream << "\"";
- stream << ">" << cmVS10EscapeXML(content);
- stream << "</" << tag << ">\n";
+ Elem(*this, tag).Attribute("Condition", cond).Content(content);
}
std::ostream& cmVisualStudio10TargetGenerator::Elem::WriteString(
@@ -300,12 +295,6 @@ std::ostream& cmVisualStudio10TargetGenerator::Elem::WriteString(
return this->S;
}
-void cmVisualStudio10TargetGenerator::WriteString(const char* line,
- int indentLevel)
-{
- Elem(*this->BuildFileStream, indentLevel).WriteString(line);
-}
-
#define VS10_CXX_DEFAULT_PROPS "$(VCTargetsPath)\\Microsoft.Cpp.Default.props"
#define VS10_CXX_PROPS "$(VCTargetsPath)\\Microsoft.Cpp.props"
#define VS10_CXX_USER_PROPS \
@@ -327,20 +316,28 @@ void cmVisualStudio10TargetGenerator::Generate()
this->GeneratorTarget->GetProperty("EXTERNAL_MSPROJECT")) {
return;
}
- this->ProjectFileExtension = computeProjectFileExtension(
+ const std::string ProjectFileExtension = computeProjectFileExtension(
this->GeneratorTarget, *this->Configurations.begin());
- if (this->ProjectFileExtension == ".vcxproj") {
+ if (ProjectFileExtension == ".vcxproj") {
this->ProjectType = vcxproj;
this->Managed = false;
- } else if (this->ProjectFileExtension == ".csproj") {
+ } else if (ProjectFileExtension == ".csproj") {
+ if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) {
+ std::string message = "The C# target \"" +
+ this->GeneratorTarget->GetName() +
+ "\" is of type STATIC_LIBRARY. This is discouraged (and may be "
+ "disabled in future). Make it a SHARED library instead.";
+ this->Makefile->IssueMessage(cmake::MessageType::DEPRECATION_WARNING,
+ message);
+ }
this->ProjectType = csproj;
this->Managed = true;
}
// Tell the global generator the name of the project file
this->GeneratorTarget->Target->SetProperty("GENERATOR_FILE_NAME",
this->Name.c_str());
- this->GeneratorTarget->Target->SetProperty(
- "GENERATOR_FILE_NAME_EXT", this->ProjectFileExtension.c_str());
+ this->GeneratorTarget->Target->SetProperty("GENERATOR_FILE_NAME_EXT",
+ ProjectFileExtension.c_str());
this->DotNetHintReferences.clear();
this->AdditionalUsingDirectories.clear();
if (this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY) {
@@ -372,337 +369,336 @@ void cmVisualStudio10TargetGenerator::Generate()
std::string path = this->LocalGenerator->GetCurrentBinaryDirectory();
path += "/";
path += this->Name;
- path += this->ProjectFileExtension;
- this->BuildFileStream = new cmGeneratedFileStream(path.c_str());
- this->PathToProjectFile = path;
- this->BuildFileStream->SetCopyIfDifferent(true);
+ path += ProjectFileExtension;
+ cmGeneratedFileStream BuildFileStream(path.c_str());
+ const std::string PathToProjectFile = path;
+ BuildFileStream.SetCopyIfDifferent(true);
// Write the encoding header into the file
char magic[] = { char(0xEF), char(0xBB), char(0xBF) };
- this->BuildFileStream->write(magic, 3);
- (*this->BuildFileStream) << "<?xml version=\"1.0\" encoding=\"" +
- this->GlobalGenerator->Encoding() + "\"?>\n";
-
- Elem e0(*this->BuildFileStream, 0);
- e0.StartElement("Project");
- e0.Attribute("DefaultTargets", "Build");
- // get the tools version to use
- const std::string toolsVer(this->GlobalGenerator->GetToolsVersion());
- e0.Attribute("ToolsVersion", toolsVer);
- e0.Attribute("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
- e0.SetHasElements();
-
- if (this->NsightTegra) {
- Elem e1(e0, "PropertyGroup");
- e1.Attribute("Label", "NsightTegraProject");
- const unsigned int nsightTegraMajorVersion = this->NsightTegraVersion[0];
- const unsigned int nsightTegraMinorVersion = this->NsightTegraVersion[1];
- if (nsightTegraMajorVersion >= 2) {
- if (nsightTegraMajorVersion > 3 ||
- (nsightTegraMajorVersion == 3 && nsightTegraMinorVersion >= 1)) {
- e1.Element("NsightTegraProjectRevisionNumber", "11");
+ BuildFileStream.write(magic, 3);
+ BuildFileStream << "<?xml version=\"1.0\" encoding=\""
+ << this->GlobalGenerator->Encoding() << "\"?>"
+ << "\n";
+ {
+ Elem e0(BuildFileStream);
+ e0.StartElement("Project");
+ e0.Attribute("DefaultTargets", "Build");
+ e0.Attribute("ToolsVersion", this->GlobalGenerator->GetToolsVersion());
+ e0.Attribute("xmlns",
+ "http://schemas.microsoft.com/developer/msbuild/2003");
+
+ if (this->NsightTegra) {
+ Elem e1(e0, "PropertyGroup");
+ e1.Attribute("Label", "NsightTegraProject");
+ const unsigned int nsightTegraMajorVersion = this->NsightTegraVersion[0];
+ const unsigned int nsightTegraMinorVersion = this->NsightTegraVersion[1];
+ if (nsightTegraMajorVersion >= 2) {
+ if (nsightTegraMajorVersion > 3 ||
+ (nsightTegraMajorVersion == 3 && nsightTegraMinorVersion >= 1)) {
+ e1.Element("NsightTegraProjectRevisionNumber", "11");
+ } else {
+ // Nsight Tegra 2.0 uses project revision 9.
+ e1.Element("NsightTegraProjectRevisionNumber", "9");
+ }
+ // Tell newer versions to upgrade silently when loading.
+ e1.Element("NsightTegraUpgradeOnceWithoutPrompt", "true");
} else {
- // Nsight Tegra 2.0 uses project revision 9.
- e1.Element("NsightTegraProjectRevisionNumber", "9");
+ // Require Nsight Tegra 1.6 for JCompile support.
+ e1.Element("NsightTegraProjectRevisionNumber", "7");
}
- // Tell newer versions to upgrade silently when loading.
- e1.Element("NsightTegraUpgradeOnceWithoutPrompt", "true");
- } else {
- // Require Nsight Tegra 1.6 for JCompile support.
- e1.Element("NsightTegraProjectRevisionNumber", "7");
}
- e1.EndElement();
- }
-
- if (const char* hostArch =
- this->GlobalGenerator->GetPlatformToolsetHostArchitecture()) {
- Elem e1(e0, "PropertyGroup");
- e1.Element("PreferredToolArchitecture", hostArch);
- e1.EndElement();
- }
-
- if (this->ProjectType != csproj) {
- this->WriteProjectConfigurations(e0);
- }
- {
- Elem e1(e0, "PropertyGroup");
- e1.Attribute("Label", "Globals");
- e1.Element("ProjectGuid", "{" + this->GUID + "}");
-
- if (this->MSTools &&
- this->GeneratorTarget->GetType() <= cmStateEnums::GLOBAL_TARGET) {
- this->WriteApplicationTypeSettings(e1);
- this->VerifyNecessaryFiles();
+ if (const char* hostArch =
+ this->GlobalGenerator->GetPlatformToolsetHostArchitecture()) {
+ Elem e1(e0, "PropertyGroup");
+ e1.Element("PreferredToolArchitecture", hostArch);
}
- const char* vsProjectTypes =
- this->GeneratorTarget->GetProperty("VS_GLOBAL_PROJECT_TYPES");
- if (vsProjectTypes) {
- std::string tagName = "ProjectTypes";
- if (this->ProjectType == csproj) {
- tagName = "ProjectTypeGuids";
- }
- e1.Element(tagName.c_str(), vsProjectTypes);
+ if (this->ProjectType != csproj) {
+ this->WriteProjectConfigurations(e0);
}
- const char* vsProjectName =
- this->GeneratorTarget->GetProperty("VS_SCC_PROJECTNAME");
- const char* vsLocalPath =
- this->GeneratorTarget->GetProperty("VS_SCC_LOCALPATH");
- const char* vsProvider =
- this->GeneratorTarget->GetProperty("VS_SCC_PROVIDER");
+ {
+ Elem e1(e0, "PropertyGroup");
+ e1.Attribute("Label", "Globals");
+ e1.Element("ProjectGuid", "{" + this->GUID + "}");
- if (vsProjectName && vsLocalPath && vsProvider) {
- e1.Element("SccProjectName", vsProjectName);
- e1.Element("SccLocalPath", vsLocalPath);
- e1.Element("SccProvider", vsProvider);
+ if (this->MSTools &&
+ this->GeneratorTarget->GetType() <= cmStateEnums::GLOBAL_TARGET) {
+ this->WriteApplicationTypeSettings(e1);
+ this->VerifyNecessaryFiles();
+ }
- const char* vsAuxPath =
- this->GeneratorTarget->GetProperty("VS_SCC_AUXPATH");
- if (vsAuxPath) {
- e1.Element("SccAuxPath", vsAuxPath);
+ const char* vsProjectTypes =
+ this->GeneratorTarget->GetProperty("VS_GLOBAL_PROJECT_TYPES");
+ if (vsProjectTypes) {
+ const char* tagName = "ProjectTypes";
+ if (this->ProjectType == csproj) {
+ tagName = "ProjectTypeGuids";
+ }
+ e1.Element(tagName, vsProjectTypes);
}
- }
- if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT")) {
- e1.Element("WinMDAssembly", "true");
- }
+ const char* vsProjectName =
+ this->GeneratorTarget->GetProperty("VS_SCC_PROJECTNAME");
+ const char* vsLocalPath =
+ this->GeneratorTarget->GetProperty("VS_SCC_LOCALPATH");
+ const char* vsProvider =
+ this->GeneratorTarget->GetProperty("VS_SCC_PROVIDER");
+
+ if (vsProjectName && vsLocalPath && vsProvider) {
+ e1.Element("SccProjectName", vsProjectName);
+ e1.Element("SccLocalPath", vsLocalPath);
+ e1.Element("SccProvider", vsProvider);
+
+ const char* vsAuxPath =
+ this->GeneratorTarget->GetProperty("VS_SCC_AUXPATH");
+ if (vsAuxPath) {
+ e1.Element("SccAuxPath", vsAuxPath);
+ }
+ }
- const char* vsGlobalKeyword =
- this->GeneratorTarget->GetProperty("VS_GLOBAL_KEYWORD");
- if (!vsGlobalKeyword) {
- e1.Element("Keyword", "Win32Proj");
- } else {
- e1.Element("Keyword", vsGlobalKeyword);
- }
+ if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT")) {
+ e1.Element("WinMDAssembly", "true");
+ }
- const char* vsGlobalRootNamespace =
- this->GeneratorTarget->GetProperty("VS_GLOBAL_ROOTNAMESPACE");
- if (vsGlobalRootNamespace) {
- e1.Element("RootNamespace", vsGlobalRootNamespace);
- }
+ const char* vsGlobalKeyword =
+ this->GeneratorTarget->GetProperty("VS_GLOBAL_KEYWORD");
+ if (!vsGlobalKeyword) {
+ e1.Element("Keyword", "Win32Proj");
+ } else {
+ e1.Element("Keyword", vsGlobalKeyword);
+ }
- e1.Element("Platform", this->Platform);
- const char* projLabel =
- this->GeneratorTarget->GetProperty("PROJECT_LABEL");
- if (!projLabel) {
- projLabel = this->Name.c_str();
- }
- e1.Element("ProjectName", projLabel);
- if (const char* targetFrameworkVersion =
+ const char* vsGlobalRootNamespace =
+ this->GeneratorTarget->GetProperty("VS_GLOBAL_ROOTNAMESPACE");
+ if (vsGlobalRootNamespace) {
+ e1.Element("RootNamespace", vsGlobalRootNamespace);
+ }
+
+ e1.Element("Platform", this->Platform);
+ const char* projLabel =
+ this->GeneratorTarget->GetProperty("PROJECT_LABEL");
+ if (!projLabel) {
+ projLabel = this->Name.c_str();
+ }
+ e1.Element("ProjectName", projLabel);
+ {
+ // TODO: add deprecation warning for VS_* property?
+ const char* targetFrameworkVersion =
this->GeneratorTarget->GetProperty(
- "VS_DOTNET_TARGET_FRAMEWORK_VERSION")) {
- e1.Element("TargetFrameworkVersion", targetFrameworkVersion);
- }
+ "VS_DOTNET_TARGET_FRAMEWORK_VERSION");
+ if (!targetFrameworkVersion) {
+ targetFrameworkVersion = this->GeneratorTarget->GetProperty(
+ "DOTNET_TARGET_FRAMEWORK_VERSION");
+ }
+ if (targetFrameworkVersion) {
+ e1.Element("TargetFrameworkVersion", targetFrameworkVersion);
+ }
+ }
- // Disable the project upgrade prompt that is displayed the first time a
- // project using an older toolset version is opened in a newer version of
- // the IDE (respected by VS 2013 and above).
- if (this->GlobalGenerator->GetVersion() >=
- cmGlobalVisualStudioGenerator::VS12) {
- e1.Element("VCProjectUpgraderObjectName", "NoUpgrade");
- }
+ // Disable the project upgrade prompt that is displayed the first time a
+ // project using an older toolset version is opened in a newer version of
+ // the IDE (respected by VS 2013 and above).
+ if (this->GlobalGenerator->GetVersion() >=
+ cmGlobalVisualStudioGenerator::VS12) {
+ e1.Element("VCProjectUpgraderObjectName", "NoUpgrade");
+ }
- std::vector<std::string> keys = this->GeneratorTarget->GetPropertyKeys();
- for (std::string const& keyIt : keys) {
- static const char* prefix = "VS_GLOBAL_";
- if (keyIt.find(prefix) != 0)
- continue;
- std::string globalKey = keyIt.substr(strlen(prefix));
- // Skip invalid or separately-handled properties.
- if (globalKey.empty() || globalKey == "PROJECT_TYPES" ||
- globalKey == "ROOTNAMESPACE" || globalKey == "KEYWORD") {
- continue;
+ std::vector<std::string> keys = this->GeneratorTarget->GetPropertyKeys();
+ for (std::string const& keyIt : keys) {
+ static const char* prefix = "VS_GLOBAL_";
+ if (keyIt.find(prefix) != 0)
+ continue;
+ std::string globalKey = keyIt.substr(strlen(prefix));
+ // Skip invalid or separately-handled properties.
+ if (globalKey.empty() || globalKey == "PROJECT_TYPES" ||
+ globalKey == "ROOTNAMESPACE" || globalKey == "KEYWORD") {
+ continue;
+ }
+ const char* value = this->GeneratorTarget->GetProperty(keyIt);
+ if (!value)
+ continue;
+ e1.Element(globalKey.c_str(), value);
}
- const char* value = this->GeneratorTarget->GetProperty(keyIt);
- if (!value)
- continue;
- e1.Element(globalKey.c_str(), value);
- }
- if (this->Managed) {
- std::string outputType;
- switch (this->GeneratorTarget->GetType()) {
- case cmStateEnums::OBJECT_LIBRARY:
- case cmStateEnums::STATIC_LIBRARY:
- case cmStateEnums::SHARED_LIBRARY:
- outputType = "Library";
- break;
- case cmStateEnums::MODULE_LIBRARY:
- outputType = "Module";
- break;
- case cmStateEnums::EXECUTABLE:
- if (this->GeneratorTarget->Target->GetPropertyAsBool(
- "WIN32_EXECUTABLE")) {
- outputType = "WinExe";
- } else {
- outputType = "Exe";
- }
- break;
- case cmStateEnums::UTILITY:
- case cmStateEnums::GLOBAL_TARGET:
- outputType = "Utility";
- break;
- case cmStateEnums::UNKNOWN_LIBRARY:
- case cmStateEnums::INTERFACE_LIBRARY:
- break;
+ if (this->Managed) {
+ std::string outputType;
+ switch (this->GeneratorTarget->GetType()) {
+ case cmStateEnums::OBJECT_LIBRARY:
+ case cmStateEnums::STATIC_LIBRARY:
+ case cmStateEnums::SHARED_LIBRARY:
+ outputType = "Library";
+ break;
+ case cmStateEnums::MODULE_LIBRARY:
+ outputType = "Module";
+ break;
+ case cmStateEnums::EXECUTABLE:
+ if (this->GeneratorTarget->Target->GetPropertyAsBool(
+ "WIN32_EXECUTABLE")) {
+ outputType = "WinExe";
+ } else {
+ outputType = "Exe";
+ }
+ break;
+ case cmStateEnums::UTILITY:
+ case cmStateEnums::GLOBAL_TARGET:
+ outputType = "Utility";
+ break;
+ case cmStateEnums::UNKNOWN_LIBRARY:
+ case cmStateEnums::INTERFACE_LIBRARY:
+ break;
+ }
+ e1.Element("OutputType", outputType);
+ e1.Element("AppDesignerFolder", "Properties");
}
- e1.Element("OutputType", outputType);
- e1.Element("AppDesignerFolder", "Properties");
}
- e1.EndElement();
- }
-
- switch (this->ProjectType) {
- case vcxproj:
- Elem(e0, "Import")
- .Attribute("Project", VS10_CXX_DEFAULT_PROPS)
- .EndElement();
- break;
- case csproj:
- Elem(e0, "Import")
- .Attribute("Project", VS10_CSharp_DEFAULT_PROPS)
- .Attribute("Condition", "Exists('" VS10_CSharp_DEFAULT_PROPS "')")
- .EndElement();
- break;
- }
+ switch (this->ProjectType) {
+ case vcxproj:
+ Elem(e0, "Import").Attribute("Project", VS10_CXX_DEFAULT_PROPS);
+ break;
+ case csproj:
+ Elem(e0, "Import")
+ .Attribute("Project", VS10_CSharp_DEFAULT_PROPS)
+ .Attribute("Condition", "Exists('" VS10_CSharp_DEFAULT_PROPS "')");
+ break;
+ }
- this->WriteProjectConfigurationValues(e0);
+ this->WriteProjectConfigurationValues(e0);
- if (this->ProjectType == vcxproj) {
- Elem(e0, "Import").Attribute("Project", VS10_CXX_PROPS).EndElement();
- }
- {
- Elem e1(e0, "ImportGroup");
- e1.Attribute("Label", "ExtensionSettings");
- e1.SetHasElements();
-
- if (this->GlobalGenerator->IsCudaEnabled()) {
- Elem(e1, "Import")
- .Attribute("Project", "$(VCTargetsPath)\\BuildCustomizations\\CUDA " +
- this->GlobalGenerator->GetPlatformToolsetCudaString() +
- ".props")
- .EndElement();
- }
- if (this->GlobalGenerator->IsMasmEnabled()) {
- Elem(e1, "Import")
- .Attribute("Project",
- "$(VCTargetsPath)\\BuildCustomizations\\masm.props")
- .EndElement();
+ if (this->ProjectType == vcxproj) {
+ Elem(e0, "Import").Attribute("Project", VS10_CXX_PROPS);
}
- if (this->GlobalGenerator->IsNasmEnabled()) {
- // Always search in the standard modules location.
- std::string propsTemplate =
- GetCMakeFilePath("Templates/MSBuild/nasm.props.in");
+ {
+ Elem e1(e0, "ImportGroup");
+ e1.Attribute("Label", "ExtensionSettings");
+ e1.SetHasElements();
- std::string propsLocal;
- propsLocal += this->DefaultArtifactDir;
- propsLocal += "\\nasm.props";
- ConvertToWindowsSlash(propsLocal);
- this->Makefile->ConfigureFile(propsTemplate.c_str(), propsLocal.c_str(),
- false, true, true);
- Elem(e1, "Import").Attribute("Project", propsLocal).EndElement();
+ if (this->GlobalGenerator->IsCudaEnabled()) {
+ Elem(e1, "Import")
+ .Attribute("Project",
+ "$(VCTargetsPath)\\BuildCustomizations\\CUDA " +
+ this->GlobalGenerator->GetPlatformToolsetCudaString() +
+ ".props");
+ }
+ if (this->GlobalGenerator->IsMasmEnabled()) {
+ Elem(e1, "Import")
+ .Attribute("Project",
+ "$(VCTargetsPath)\\BuildCustomizations\\masm.props");
+ }
+ 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";
+ ConvertToWindowsSlash(propsLocal);
+ this->Makefile->ConfigureFile(propsTemplate.c_str(),
+ propsLocal.c_str(), false, true, true);
+ Elem(e1, "Import").Attribute("Project", propsLocal);
+ }
}
- e1.EndElement();
- }
- {
- Elem e1(e0, "ImportGroup");
- e1.Attribute("Label", "PropertySheets");
- std::string props;
+ {
+ Elem e1(e0, "ImportGroup");
+ e1.Attribute("Label", "PropertySheets");
+ std::string props;
+ switch (this->ProjectType) {
+ case vcxproj:
+ props = VS10_CXX_USER_PROPS;
+ break;
+ case csproj:
+ props = VS10_CSharp_USER_PROPS;
+ break;
+ }
+ if (const char* p =
+ this->GeneratorTarget->GetProperty("VS_USER_PROPS")) {
+ props = p;
+ }
+ if (!props.empty()) {
+ ConvertToWindowsSlash(props);
+ Elem(e1, "Import")
+ .Attribute("Project", props)
+ .Attribute("Condition", "exists('" + props + "')")
+ .Attribute("Label", "LocalAppDataPlatform");
+ }
+
+ this->WritePlatformExtensions(e1);
+ }
+ Elem(e0, "PropertyGroup").Attribute("Label", "UserMacros");
+ this->WriteWinRTPackageCertificateKeyFile(e0);
+ this->WritePathAndIncrementalLinkOptions(e0);
+ this->WriteItemDefinitionGroups(e0);
+ this->WriteCustomCommands(e0);
+ this->WriteAllSources(e0);
+ this->WriteDotNetReferences(e0);
+ this->WriteEmbeddedResourceGroup(e0);
+ this->WriteXamlFilesGroup(e0);
+ this->WriteWinRTReferences(e0);
+ this->WriteProjectReferences(e0);
+ this->WriteSDKReferences(e0);
switch (this->ProjectType) {
case vcxproj:
- props = VS10_CXX_USER_PROPS;
+ Elem(e0, "Import").Attribute("Project", VS10_CXX_TARGETS);
break;
case csproj:
- props = VS10_CSharp_USER_PROPS;
+ Elem(e0, "Import").Attribute("Project", VS10_CSharp_TARGETS);
break;
}
- if (const char* p = this->GeneratorTarget->GetProperty("VS_USER_PROPS")) {
- props = p;
- }
- if (!props.empty()) {
- ConvertToWindowsSlash(props);
- Elem(e1, "Import")
- .Attribute("Project", props)
- .Attribute("Condition", "exists('" + props + "')")
- .Attribute("Label", "LocalAppDataPlatform")
- .EndElement();
- }
-
- this->WritePlatformExtensions(e1);
- e1.EndElement();
- }
- Elem(e0, "PropertyGroup").Attribute("Label", "UserMacros").EndElement();
- this->WriteWinRTPackageCertificateKeyFile(e0);
- this->WritePathAndIncrementalLinkOptions(e0);
- this->WriteItemDefinitionGroups(e0);
- this->WriteCustomCommands(e0);
- this->WriteAllSources(e0);
- this->WriteDotNetReferences(e0);
- this->WriteEmbeddedResourceGroup(e0);
- this->WriteXamlFilesGroup(e0);
- this->WriteWinRTReferences(e0);
- this->WriteProjectReferences(e0);
- this->WriteSDKReferences(e0);
- switch (this->ProjectType) {
- case vcxproj:
- Elem(e0, "Import").Attribute("Project", VS10_CXX_TARGETS).EndElement();
- break;
- case csproj:
- Elem(e0, "Import")
- .Attribute("Project", VS10_CSharp_TARGETS)
- .EndElement();
- break;
- }
- this->WriteTargetSpecificReferences(e0);
- {
- Elem e1(e0, "ImportGroup");
- e1.Attribute("Label", "ExtensionTargets");
- e1.SetHasElements();
- this->WriteTargetsFileReferences(e1);
- if (this->GlobalGenerator->IsCudaEnabled()) {
- Elem(e1, "Import")
- .Attribute("Project", "$(VCTargetsPath)\\BuildCustomizations\\CUDA " +
- this->GlobalGenerator->GetPlatformToolsetCudaString() +
- ".targets");
- }
- if (this->GlobalGenerator->IsMasmEnabled()) {
- Elem(e1, "Import")
- .Attribute("Project",
- "$(VCTargetsPath)\\BuildCustomizations\\masm.targets")
- .EndElement();
- }
- if (this->GlobalGenerator->IsNasmEnabled()) {
- std::string nasmTargets =
- GetCMakeFilePath("Templates/MSBuild/nasm.targets");
- Elem(e1, "Import").Attribute("Project", nasmTargets).EndElement();
- }
- e1.EndElement();
- }
- if (this->ProjectType == csproj) {
- for (std::string const& i : this->Configurations) {
- Elem e1(e0, "PropertyGroup");
- e1.Attribute("Condition", "'$(Configuration)' == '" + i + "'");
+ this->WriteTargetSpecificReferences(e0);
+ {
+ Elem e1(e0, "ImportGroup");
+ e1.Attribute("Label", "ExtensionTargets");
e1.SetHasElements();
- this->WriteEvents(e1, i);
- e1.EndElement();
+ this->WriteTargetsFileReferences(e1);
+ if (this->GlobalGenerator->IsCudaEnabled()) {
+ Elem(e1, "Import")
+ .Attribute("Project",
+ "$(VCTargetsPath)\\BuildCustomizations\\CUDA " +
+ this->GlobalGenerator->GetPlatformToolsetCudaString() +
+ ".targets");
+ }
+ if (this->GlobalGenerator->IsMasmEnabled()) {
+ Elem(e1, "Import")
+ .Attribute("Project",
+ "$(VCTargetsPath)\\BuildCustomizations\\masm.targets");
+ }
+ if (this->GlobalGenerator->IsNasmEnabled()) {
+ std::string nasmTargets =
+ GetCMakeFilePath("Templates/MSBuild/nasm.targets");
+ Elem(e1, "Import").Attribute("Project", nasmTargets);
+ }
}
- // make sure custom commands are executed before build (if necessary)
- Elem e1(e0, "PropertyGroup");
- e1.SetHasElements();
- this->WriteString("<BuildDependsOn>\n", 2);
- for (std::string const& i : this->CSharpCustomCommandNames) {
- this->WriteString(i.c_str(), 3);
- (*this->BuildFileStream) << ";\n";
+ if (this->ProjectType == csproj) {
+ for (std::string const& c : this->Configurations) {
+ Elem e1(e0, "PropertyGroup");
+ e1.Attribute("Condition", "'$(Configuration)' == '" + c + "'");
+ e1.SetHasElements();
+ this->WriteEvents(e1, c);
+ }
+ // make sure custom commands are executed before build (if necessary)
+ {
+ Elem e1(e0, "PropertyGroup");
+ std::ostringstream oss;
+ oss << "\n";
+ for (std::string const& i : this->CSharpCustomCommandNames) {
+ oss << " " << i << ";\n";
+ }
+ oss << " "
+ << "$(BuildDependsOn)\n";
+ e1.Element("BuildDependsOn", oss.str());
+ }
}
- this->WriteString("$(BuildDependsOn)\n", 3);
- this->WriteString("</BuildDependsOn>\n", 2);
- e1.EndElement();
}
- this->WriteString("</Project>", 0);
+
+ if (BuildFileStream.Close()) {
+ this->GlobalGenerator->FileReplacedDuringGenerate(PathToProjectFile);
+ }
+
// The groups are stored in a separate file for VS 10
this->WriteGroups();
}
@@ -752,7 +748,6 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferences(Elem& e0)
this->WriteDotNetReference(e1, i.first, i.second, h.first);
}
}
- e1.EndElement();
}
}
@@ -782,7 +777,6 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReference(
e2.Element("HintPath", hint);
}
this->WriteDotNetReferenceCustomTags(e2, ref);
- e2.EndElement();
}
void cmVisualStudio10TargetGenerator::WriteDotNetReferenceCustomTags(
@@ -839,7 +833,7 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0)
std::string hFileName = obj.substr(0, obj.find_last_of(".")) + ".h";
e2.Element("DependentUpon", hFileName);
- for (std::string const& i : this->Configurations) {
+ for (std::string const& c : this->Configurations) {
std::string s;
if (this->GeneratorTarget->GetProperty("VS_GLOBAL_ROOTNAMESPACE") ||
// Handle variant of VS_GLOBAL_<variable> for RootNamespace.
@@ -847,7 +841,7 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0)
s = "$(RootNamespace).";
}
s += "%(Filename).resources";
- this->WritePlatformConfigTag("LogicalName", i, e2.Indent + 1, s);
+ e2.WritePlatformConfigTag("LogicalName", this->CalcCondition(c), s);
}
} else {
std::string binDir = this->Makefile->GetCurrentBinaryDirectory();
@@ -905,10 +899,7 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0)
}
}
}
-
- e2.EndElement();
}
- e1.EndElement();
}
}
@@ -917,8 +908,7 @@ void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup(Elem& e0)
std::vector<cmSourceFile const*> xamlObjs;
this->GeneratorTarget->GetXamlSources(xamlObjs, "");
if (!xamlObjs.empty()) {
- Elem e1(e0);
- e1.StartElement("ItemGroup");
+ Elem e1(e0, "ItemGroup");
for (cmSourceFile const* oi : xamlObjs) {
std::string obj = oi->GetFullPath();
const char* xamlType;
@@ -950,9 +940,7 @@ void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup(Elem& e0)
}
}
e2.Element("SubType", "Designer");
- e2.EndElement();
}
- e1.EndElement();
}
}
@@ -965,8 +953,7 @@ void cmVisualStudio10TargetGenerator::WriteTargetSpecificReferences(Elem& e0)
.Attribute("Project",
"$(MSBuildExtensionsPath)\\Microsoft\\WindowsPhone\\v"
"$(TargetPlatformVersion)\\Microsoft.Cpp.WindowsPhone."
- "$(TargetPlatformVersion).targets")
- .EndElement();
+ "$(TargetPlatformVersion).targets");
}
}
}
@@ -989,8 +976,7 @@ void cmVisualStudio10TargetGenerator::WriteTargetsFileReferences(Elem& e1)
Elem(e1, "Import")
.Attribute("Project", tac.File)
- .Attribute("Condition", oss.str())
- .EndElement();
+ .Attribute("Condition", oss.str());
}
}
@@ -1013,9 +999,7 @@ void cmVisualStudio10TargetGenerator::WriteWinRTReferences(Elem& e0)
Elem e2(e1, "Reference");
e2.Attribute("Include", ri);
e2.Element("IsWinMDFile", "true");
- e2.EndElement();
}
- e1.EndElement();
}
}
@@ -1030,16 +1014,13 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurations(Elem& e0)
e2.Attribute("Include", c + "|" + this->Platform);
e2.Element("Configuration", c);
e2.Element("Platform", this->Platform);
- e2.EndElement();
}
- e1.EndElement();
}
void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues(Elem& e0)
{
for (std::string const& c : this->Configurations) {
- Elem e1(e0);
- e1.StartElement("PropertyGroup");
+ Elem e1(e0, "PropertyGroup");
e1.Attribute("Condition", this->CalcCondition(c));
e1.Attribute("Label", "Configuration");
@@ -1047,7 +1028,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues(Elem& e0)
std::string configType;
if (const char* vsConfigurationType =
this->GeneratorTarget->GetProperty("VS_CONFIGURATION_TYPE")) {
- configType = cmVS10EscapeXML(vsConfigurationType);
+ configType = vsConfigurationType;
} else {
switch (this->GeneratorTarget->GetType()) {
case cmStateEnums::SHARED_LIBRARY:
@@ -1093,8 +1074,6 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues(Elem& e0)
} else if (this->NsightTegra) {
this->WriteNsightTegraConfigurationValues(e1, c);
}
-
- e1.EndElement();
}
}
@@ -1179,7 +1158,8 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged(
e1.Element("StartProgram", outDir + assemblyName + ".exe");
}
- o.OutputFlagMap(e1.S, e1.Indent + 1);
+ OptionsHelper oh(o, e1);
+ oh.OutputFlagMap();
}
//----------------------------------------------------------------------------
@@ -1276,12 +1256,16 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
}
cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
- Elem e1(e0, "ItemGroup");
- Elem e2(e1);
+ std::unique_ptr<Elem> spe1;
+ std::unique_ptr<Elem> spe2;
if (this->ProjectType != csproj) {
- this->WriteSource(e2, "CustomBuild", source);
- e2.SetHasElements();
+ spe1 = cm::make_unique<Elem>(e0, "ItemGroup");
+ spe2 = cm::make_unique<Elem>(*spe1);
+ this->WriteSource(*spe2, "CustomBuild", source);
+ spe2->SetHasElements();
} else {
+ Elem e1(e0, "ItemGroup");
+ Elem e2(e1);
std::string link;
this->GetCSharpSourceLink(source, link);
this->WriteSource(e2, "None", source);
@@ -1289,8 +1273,6 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
if (!link.empty()) {
e2.Element("Link", link);
}
- e2.EndElement();
- e1.EndElement();
}
for (std::string const& c : this->Configurations) {
cmCustomCommandGenerator ccg(command, c, lg);
@@ -1322,14 +1304,10 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
this->WriteCustomRuleCSharp(e0, c, name, script, inputs.str(),
outputs.str(), comment);
} else {
- this->WriteCustomRuleCpp(e2, c, script, inputs.str(), outputs.str(),
+ this->WriteCustomRuleCpp(*spe2, c, script, inputs.str(), outputs.str(),
comment);
}
}
- if (this->ProjectType != csproj) {
- e2.EndElement();
- e1.EndElement();
- }
}
void cmVisualStudio10TargetGenerator::WriteCustomRuleCpp(
@@ -1338,16 +1316,15 @@ void cmVisualStudio10TargetGenerator::WriteCustomRuleCpp(
std::string const& comment)
{
const std::string cond = this->CalcCondition(config);
- Elem(e2, "Message").Attribute("Condition", cond).Content(comment);
- Elem(e2, "Command").Attribute("Condition", cond).Content(script);
- Elem(e2, "AdditionalInputs")
- .Attribute("Condition", cond)
- .Content(inputs + ";%(AdditionalInputs)");
- Elem(e2, "Outputs").Attribute("Condition", cond).Content(outputs);
+ e2.WritePlatformConfigTag("Message", cond, comment);
+ e2.WritePlatformConfigTag("Command", cond, script);
+ e2.WritePlatformConfigTag("AdditionalInputs", cond,
+ inputs + ";%(AdditionalInputs)");
+ e2.WritePlatformConfigTag("Outputs", cond, outputs);
if (this->LocalGenerator->GetVersion() >
cmGlobalVisualStudioGenerator::VS10) {
// VS >= 11 let us turn off linking of custom command outputs.
- Elem(e2, "LinkObjects").Attribute("Condition", cond).Content("false");
+ e2.WritePlatformConfigTag("LinkObjects", cond, "false");
}
}
@@ -1363,10 +1340,9 @@ void cmVisualStudio10TargetGenerator::WriteCustomRuleCSharp(
e1.S << "\n Inputs=\"" << cmVS10EscapeAttr(inputs) << "\"";
e1.S << "\n Outputs=\"" << cmVS10EscapeAttr(outputs) << "\"";
if (!comment.empty()) {
- Elem(e1, "Exec").Attribute("Command", "echo " + comment).EndElement();
+ Elem(e1, "Exec").Attribute("Command", "echo " + comment);
}
- Elem(e1, "Exec").Attribute("Command", script).EndElement();
- e1.EndElement();
+ Elem(e1, "Exec").Attribute("Command", script);
}
std::string cmVisualStudio10TargetGenerator::ConvertPath(
@@ -1422,102 +1398,93 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
char magic[] = { char(0xEF), char(0xBB), char(0xBF) };
fout.write(magic, 3);
- // get the tools version to use
- const std::string toolsVer(this->GlobalGenerator->GetToolsVersion());
fout << "<?xml version=\"1.0\" encoding=\""
- << this->GlobalGenerator->Encoding() << "\"?>\n";
+ << this->GlobalGenerator->Encoding() << "\"?>"
+ << "\n";
+ {
+ Elem e0(fout);
+ e0.StartElement("Project");
+ e0.Attribute("ToolsVersion", this->GlobalGenerator->GetToolsVersion());
+ e0.Attribute("xmlns",
+ "http://schemas.microsoft.com/developer/msbuild/2003");
- Elem e0(fout, 0);
- e0.StartElement("Project");
- e0.Attribute("ToolsVersion", toolsVer);
- e0.Attribute("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003");
- e0.SetHasElements();
+ for (auto const& ti : this->Tools) {
+ this->WriteGroupSources(e0, ti.first, ti.second, sourceGroups);
+ }
- for (auto const& ti : this->Tools) {
- this->WriteGroupSources(e0, ti.first, ti.second, sourceGroups);
- }
+ // Added files are images and the manifest.
+ if (!this->AddedFiles.empty()) {
+ Elem e1(e0, "ItemGroup");
+ e1.SetHasElements();
+ for (std::string const& oi : this->AddedFiles) {
+ std::string fileName =
+ cmSystemTools::LowerCase(cmSystemTools::GetFilenameName(oi));
+ if (fileName == "wmappmanifest.xml") {
+ Elem e2(e1, "XML");
+ e2.Attribute("Include", oi);
+ e2.Element("Filter", "Resource Files");
+ } else if (cmSystemTools::GetFilenameExtension(fileName) ==
+ ".appxmanifest") {
+ Elem e2(e1, "AppxManifest");
+ e2.Attribute("Include", oi);
+ e2.Element("Filter", "Resource Files");
+ } else if (cmSystemTools::GetFilenameExtension(fileName) == ".pfx") {
+ Elem e2(e1, "None");
+ e2.Attribute("Include", oi);
+ e2.Element("Filter", "Resource Files");
+ } else {
+ Elem e2(e1, "Image");
+ e2.Attribute("Include", oi);
+ e2.Element("Filter", "Resource Files");
+ }
+ }
+ }
- // Added files are images and the manifest.
- if (!this->AddedFiles.empty()) {
- Elem e1(e0, "ItemGroup");
- e1.SetHasElements();
- for (std::string const& oi : this->AddedFiles) {
- std::string fileName =
- cmSystemTools::LowerCase(cmSystemTools::GetFilenameName(oi));
- if (fileName == "wmappmanifest.xml") {
- Elem e2(e1, "XML");
- e2.Attribute("Include", oi);
- e2.Element("Filter", "Resource Files");
- e2.EndElement();
- } else if (cmSystemTools::GetFilenameExtension(fileName) ==
- ".appxmanifest") {
- Elem e2(e1, "AppxManifest");
- e2.Attribute("Include", oi);
+ std::vector<cmSourceFile const*> resxObjs;
+ this->GeneratorTarget->GetResxSources(resxObjs, "");
+ if (!resxObjs.empty()) {
+ Elem e1(e0, "ItemGroup");
+ for (cmSourceFile const* oi : resxObjs) {
+ std::string obj = oi->GetFullPath();
+ ConvertToWindowsSlash(obj);
+ Elem e2(e1, "EmbeddedResource");
+ e2.Attribute("Include", obj);
e2.Element("Filter", "Resource Files");
- e2.EndElement();
- } else if (cmSystemTools::GetFilenameExtension(fileName) == ".pfx") {
- Elem e2(e1, "None");
- e2.Attribute("Include", oi);
- e2.Element("Filter", "Resource Files");
- e2.EndElement();
- } else {
- Elem e2(e1, "Image");
- e2.Attribute("Include", oi);
- e2.Element("Filter", "Resource Files");
- e2.EndElement();
}
}
- e1.EndElement();
- }
+ {
+ Elem e1(e0, "ItemGroup");
+ e1.SetHasElements();
+ std::vector<cmSourceGroup*> groupsVec(groupsUsed.begin(),
+ groupsUsed.end());
+ std::sort(groupsVec.begin(), groupsVec.end(),
+ [](cmSourceGroup* l, cmSourceGroup* r) {
+ return l->GetFullName() < r->GetFullName();
+ });
+ for (cmSourceGroup* sg : groupsVec) {
+ std::string const& name = sg->GetFullName();
+ if (!name.empty()) {
+ std::string guidName = "SG_Filter_" + name;
+ std::string guid = this->GlobalGenerator->GetGUID(guidName);
+ Elem e2(e1, "Filter");
+ e2.Attribute("Include", name);
+ e2.Element("UniqueIdentifier", "{" + guid + "}");
+ }
+ }
- std::vector<cmSourceFile const*> resxObjs;
- this->GeneratorTarget->GetResxSources(resxObjs, "");
- if (!resxObjs.empty()) {
- Elem e1(e0, "ItemGroup");
- for (cmSourceFile const* oi : resxObjs) {
- std::string obj = oi->GetFullPath();
- ConvertToWindowsSlash(obj);
- Elem e2(e1, "EmbeddedResource");
- e2.Attribute("Include", obj);
- e2.Element("Filter", "Resource Files");
- e2.EndElement();
+ if (!resxObjs.empty() || !this->AddedFiles.empty()) {
+ std::string guidName = "SG_Filter_Resource Files";
+ std::string guid = this->GlobalGenerator->GetGUID(guidName);
+ Elem e2(e1, "Filter");
+ e2.Attribute("Include", "Resource Files");
+ e2.Element("UniqueIdentifier", "{" + guid + "}");
+ e2.Element("Extensions",
+ "rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;"
+ "gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms");
+ }
}
- e1.EndElement();
}
-
- Elem e1(e0, "ItemGroup");
- e1.SetHasElements();
- std::vector<cmSourceGroup*> groupsVec(groupsUsed.begin(), groupsUsed.end());
- std::sort(groupsVec.begin(), groupsVec.end(),
- [](cmSourceGroup* l, cmSourceGroup* r) {
- return l->GetFullName() < r->GetFullName();
- });
- for (cmSourceGroup* sg : groupsVec) {
- std::string const& name = sg->GetFullName();
- if (!name.empty()) {
- std::string guidName = "SG_Filter_" + name;
- std::string guid = this->GlobalGenerator->GetGUID(guidName);
- Elem e2(e1, "Filter");
- e2.Attribute("Include", name);
- e2.Element("UniqueIdentifier", "{" + guid + "}");
- e2.EndElement();
- }
- }
-
- if (!resxObjs.empty() || !this->AddedFiles.empty()) {
- std::string guidName = "SG_Filter_Resource Files";
- std::string guid = this->GlobalGenerator->GetGUID(guidName);
- Elem e2(e1, "Filter");
- e2.Attribute("Include", "Resource Files");
- e2.Element("UniqueIdentifier", "{" + guid + "}");
- e2.Element("Extensions",
- "rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;"
- "gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms");
- e2.EndElement();
- }
-
- e1.EndElement();
- e0.EndElement();
+ fout << '\n';
if (fout.Close()) {
this->GlobalGenerator->FileReplacedDuringGenerate(path);
@@ -1580,9 +1547,7 @@ void cmVisualStudio10TargetGenerator::WriteGroupSources(
if (!filter.empty()) {
e2.Element("Filter", filter);
}
- e2.EndElement();
}
- e1.EndElement();
}
void cmVisualStudio10TargetGenerator::WriteHeaderSource(Elem& e1,
@@ -1597,7 +1562,6 @@ void cmVisualStudio10TargetGenerator::WriteHeaderSource(Elem& e1,
std::string xamlFileName = fileName.substr(0, fileName.find_last_of("."));
e2.Element("DependentUpon", xamlFileName);
}
- e2.EndElement();
}
void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1,
@@ -1776,15 +1740,15 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1,
if (0 == strcmp(cge->Evaluate(this->LocalGenerator,
this->Configurations[i]),
"1")) {
- Elem e3(e2, "DeploymentContent");
- e3.Attribute("Condition", "'$(Configuration)|$(Platform)'=='" +
- this->Configurations[i] + "|" + this->Platform + "'");
- e3.Content("true");
+ e2.WritePlatformConfigTag(
+ "DeploymentContent", "'$(Configuration)|$(Platform)'=='" +
+ this->Configurations[i] + "|" + this->Platform + "'",
+ "true");
} else {
- Elem e3(e2, "ExcludedFromBuild");
- e3.Attribute("Condition", "'$(Configuration)|$(Platform)'=='" +
- this->Configurations[i] + "|" + this->Platform + "'");
- e3.Content("true");
+ e2.WritePlatformConfigTag(
+ "ExcludedFromBuild", "'$(Configuration)|$(Platform)'=='" +
+ this->Configurations[i] + "|" + this->Platform + "'",
+ "true");
}
}
}
@@ -1799,18 +1763,18 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1,
}
if (!outputHeaderFile.empty()) {
for (size_t i = 0; i != this->Configurations.size(); ++i) {
- Elem e3(e2, "HeaderFileOutput");
- e3.Attribute("Condition", "'$(Configuration)|$(Platform)'=='" +
- this->Configurations[i] + "|" + this->Platform + "'");
- e3.Content(outputHeaderFile);
+ e2.WritePlatformConfigTag(
+ "HeaderFileOutput", "'$(Configuration)|$(Platform)'=='" +
+ this->Configurations[i] + "|" + this->Platform + "'",
+ outputHeaderFile);
}
}
if (!variableName.empty()) {
for (size_t i = 0; i != this->Configurations.size(); ++i) {
- Elem e3(e2, "VariableName");
- e3.Attribute("Condition", "'$(Configuration)|$(Platform)'=='" +
- this->Configurations[i] + "|" + this->Platform + "'");
- e3.Content(variableName);
+ e2.WritePlatformConfigTag(
+ "VariableName", "'$(Configuration)|$(Platform)'=='" +
+ this->Configurations[i] + "|" + this->Platform + "'",
+ variableName);
}
}
if (!shaderEnableDebug.empty()) {
@@ -1822,10 +1786,10 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1,
const char* enableDebug =
cge->Evaluate(this->LocalGenerator, this->Configurations[i]);
if (strlen(enableDebug) > 0) {
- Elem e3(e2, "EnableDebuggingInformation");
- e3.Attribute("Condition", "'$(Configuration)|$(Platform)'=='" +
- this->Configurations[i] + "|" + this->Platform + "'");
- e3.Content(cmSystemTools::IsOn(enableDebug) ? "true" : "false");
+ e2.WritePlatformConfigTag(
+ "EnableDebuggingInformation", "'$(Configuration)|$(Platform)'=='" +
+ this->Configurations[i] + "|" + this->Platform + "'",
+ cmSystemTools::IsOn(enableDebug) ? "true" : "false");
}
}
}
@@ -1838,11 +1802,10 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1,
const char* disableOptimizations =
cge->Evaluate(this->LocalGenerator, this->Configurations[i]);
if (strlen(disableOptimizations) > 0) {
- Elem e3(e2, "DisableOptimizations");
- e3.Attribute("Condition", "'$(Configuration)|$(Platform)'=='" +
- this->Configurations[i] + "|" + this->Platform + "'");
- e3.Content(cmSystemTools::IsOn(disableOptimizations) ? "true"
- : "false");
+ e2.WritePlatformConfigTag(
+ "DisableOptimizations", "'$(Configuration)|$(Platform)'=='" +
+ this->Configurations[i] + "|" + this->Platform + "'",
+ (cmSystemTools::IsOn(disableOptimizations) ? "true" : "false"));
}
}
}
@@ -1873,7 +1836,6 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1,
// write source file specific tags
this->WriteCSharpSourceProperties(e2, sourceFileTags);
}
- e2.WriteEndTag(tool);
}
void cmVisualStudio10TargetGenerator::WriteSource(Elem& e2,
@@ -1926,6 +1888,7 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0)
return;
}
Elem e1(e0, "ItemGroup");
+ e1.SetHasElements();
std::vector<size_t> all_configs;
for (size_t ci = 0; ci < this->Configurations.size(); ++ci) {
@@ -2028,15 +1991,12 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0)
if (!exclude_configs.empty()) {
this->WriteExcludeFromBuild(e2, exclude_configs);
}
- e2.EndElement();
}
}
if (this->IsMissingFiles) {
this->WriteMissingFiles(e1);
}
-
- e1.EndElement();
}
void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
@@ -2103,7 +2063,6 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
// for the first time we need a new line if there is something
// produced here.
if (!objectName.empty()) {
- e2.SetHasElements();
if (lang == "CUDA") {
e2.Element("CompileOut", "$(IntDir)/" + objectName);
} else {
@@ -2127,7 +2086,6 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
// use them
if (!flags.empty() || !options.empty() || !configDefines.empty() ||
!includes.empty() || compileAs || noWinRT) {
- e2.SetHasElements();
cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
cmIDEFlagTable const* flagtable = nullptr;
const std::string& srclang = source->GetLanguage();
@@ -2193,14 +2151,14 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
}
clOptions.AddIncludes(includeList);
clOptions.SetConfiguration(config);
- clOptions.PrependInheritedString("AdditionalOptions");
- clOptions.OutputAdditionalIncludeDirectories(e2.S, e2.Indent + 1, lang);
- clOptions.OutputFlagMap(e2.S, e2.Indent + 1);
- clOptions.OutputPreprocessorDefinitions(e2.S, e2.Indent + 1, lang);
+ OptionsHelper oh(clOptions, e2);
+ oh.PrependInheritedString("AdditionalOptions");
+ oh.OutputAdditionalIncludeDirectories(lang);
+ oh.OutputFlagMap();
+ oh.OutputPreprocessorDefinitions(lang);
}
}
if (this->IsXamlSource(source->GetFullPath())) {
- e2.SetHasElements();
const std::string& fileName = source->GetFullPath();
std::string xamlFileName = fileName.substr(0, fileName.find_last_of("."));
e2.Element("DependentUpon", xamlFileName);
@@ -2227,10 +2185,10 @@ void cmVisualStudio10TargetGenerator::WriteExcludeFromBuild(
Elem& e2, std::vector<size_t> const& exclude_configs)
{
for (size_t ci : exclude_configs) {
- Elem e3(e2, "ExcludedFromBuild");
- e3.Attribute("Condition", "'$(Configuration)|$(Platform)'=='" +
- this->Configurations[ci] + "|" + this->Platform + "'");
- e3.Content("true");
+ e2.WritePlatformConfigTag(
+ "ExcludedFromBuild", "'$(Configuration)|$(Platform)'=='" +
+ this->Configurations[ci] + "|" + this->Platform + "'",
+ "true");
}
}
@@ -2248,10 +2206,10 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions(
Elem e1(e0, "PropertyGroup");
e1.Element("_ProjectFileVersion", "10.0.20506.1");
for (std::string const& config : this->Configurations) {
+ const std::string cond = this->CalcCondition(config);
if (ttype >= cmStateEnums::UTILITY) {
- this->WritePlatformConfigTag(
- "IntDir", config, e1.Indent + 1,
- "$(Platform)\\$(Configuration)\\$(ProjectName)\\");
+ e1.WritePlatformConfigTag(
+ "IntDir", cond, "$(Platform)\\$(Configuration)\\$(ProjectName)\\");
} else {
std::string intermediateDir =
this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
@@ -2271,68 +2229,63 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions(
ConvertToWindowsSlash(intermediateDir);
ConvertToWindowsSlash(outDir);
- this->WritePlatformConfigTag("OutDir", config, e1.Indent + 1, outDir);
+ e1.WritePlatformConfigTag("OutDir", cond, outDir);
- this->WritePlatformConfigTag("IntDir", config, e1.Indent + 1,
- intermediateDir);
+ e1.WritePlatformConfigTag("IntDir", cond, intermediateDir);
if (const char* sdkExecutableDirectories = this->Makefile->GetDefinition(
"CMAKE_VS_SDK_EXECUTABLE_DIRECTORIES")) {
- this->WritePlatformConfigTag("ExecutablePath", config, e1.Indent + 1,
- sdkExecutableDirectories);
+ e1.WritePlatformConfigTag("ExecutablePath", cond,
+ sdkExecutableDirectories);
}
if (const char* sdkIncludeDirectories = this->Makefile->GetDefinition(
"CMAKE_VS_SDK_INCLUDE_DIRECTORIES")) {
- this->WritePlatformConfigTag("IncludePath", config, e1.Indent + 1,
- sdkIncludeDirectories);
+ e1.WritePlatformConfigTag("IncludePath", cond, sdkIncludeDirectories);
}
if (const char* sdkReferenceDirectories = this->Makefile->GetDefinition(
"CMAKE_VS_SDK_REFERENCE_DIRECTORIES")) {
- this->WritePlatformConfigTag("ReferencePath", config, e1.Indent + 1,
- sdkReferenceDirectories);
+ e1.WritePlatformConfigTag("ReferencePath", cond,
+ sdkReferenceDirectories);
}
if (const char* sdkLibraryDirectories = this->Makefile->GetDefinition(
"CMAKE_VS_SDK_LIBRARY_DIRECTORIES")) {
- this->WritePlatformConfigTag("LibraryPath", config, e1.Indent + 1,
- sdkLibraryDirectories);
+ e1.WritePlatformConfigTag("LibraryPath", cond, sdkLibraryDirectories);
}
if (const char* sdkLibraryWDirectories = this->Makefile->GetDefinition(
"CMAKE_VS_SDK_LIBRARY_WINRT_DIRECTORIES")) {
- this->WritePlatformConfigTag("LibraryWPath", config, e1.Indent + 1,
- sdkLibraryWDirectories);
+ e1.WritePlatformConfigTag("LibraryWPath", cond,
+ sdkLibraryWDirectories);
}
if (const char* sdkSourceDirectories =
this->Makefile->GetDefinition("CMAKE_VS_SDK_SOURCE_DIRECTORIES")) {
- this->WritePlatformConfigTag("SourcePath", config, e1.Indent + 1,
- sdkSourceDirectories);
+ e1.WritePlatformConfigTag("SourcePath", cond, sdkSourceDirectories);
}
if (const char* sdkExcludeDirectories = this->Makefile->GetDefinition(
"CMAKE_VS_SDK_EXCLUDE_DIRECTORIES")) {
- this->WritePlatformConfigTag("ExcludePath", config, e1.Indent + 1,
- sdkExcludeDirectories);
+ e1.WritePlatformConfigTag("ExcludePath", cond, sdkExcludeDirectories);
}
if (const char* workingDir = this->GeneratorTarget->GetProperty(
"VS_DEBUGGER_WORKING_DIRECTORY")) {
- this->WritePlatformConfigTag("LocalDebuggerWorkingDirectory", config,
- e1.Indent + 1, workingDir);
+ e1.WritePlatformConfigTag("LocalDebuggerWorkingDirectory", cond,
+ workingDir);
}
if (const char* debuggerCommand =
this->GeneratorTarget->GetProperty("VS_DEBUGGER_COMMAND")) {
- this->WritePlatformConfigTag("LocalDebuggerCommand", config,
- e1.Indent + 1, debuggerCommand);
+ e1.WritePlatformConfigTag("LocalDebuggerCommand", cond,
+ debuggerCommand);
}
std::string name =
cmSystemTools::GetFilenameWithoutLastExtension(targetNameFull);
- this->WritePlatformConfigTag("TargetName", config, e1.Indent + 1, name);
+ e1.WritePlatformConfigTag("TargetName", cond, name);
std::string ext =
cmSystemTools::GetFilenameLastExtension(targetNameFull);
@@ -2341,12 +2294,11 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions(
// A single "." appears to be treated as an empty extension.
ext = ".";
}
- this->WritePlatformConfigTag("TargetExt", config, e1.Indent + 1, ext);
+ e1.WritePlatformConfigTag("TargetExt", cond, ext);
this->OutputLinkIncremental(e1, config);
}
}
- e1.EndElement();
}
void cmVisualStudio10TargetGenerator::OutputLinkIncremental(
@@ -2365,15 +2317,16 @@ void cmVisualStudio10TargetGenerator::OutputLinkIncremental(
return;
}
Options& linkOptions = *(this->LinkOptions[configName]);
+ const std::string cond = this->CalcCondition(configName);
const char* incremental = linkOptions.GetFlag("LinkIncremental");
- this->WritePlatformConfigTag("LinkIncremental", configName, e1.Indent + 1,
- (incremental ? incremental : "true"));
+ e1.WritePlatformConfigTag("LinkIncremental", cond,
+ (incremental ? incremental : "true"));
linkOptions.RemoveFlag("LinkIncremental");
const char* manifest = linkOptions.GetFlag("GenerateManifest");
- this->WritePlatformConfigTag("GenerateManifest", configName, e1.Indent + 1,
- (manifest ? manifest : "true"));
+ e1.WritePlatformConfigTag("GenerateManifest", cond,
+ (manifest ? manifest : "true"));
linkOptions.RemoveFlag("GenerateManifest");
// Some link options belong here. Use them now and remove them so that
@@ -2382,7 +2335,7 @@ void cmVisualStudio10TargetGenerator::OutputLinkIncremental(
for (const char** f = flags; *f; ++f) {
const char* flag = *f;
if (const char* value = linkOptions.GetFlag(flag)) {
- this->WritePlatformConfigTag(flag, configName, e1.Indent + 1, value);
+ e1.WritePlatformConfigTag(flag, cond, value);
linkOptions.RemoveFlag(flag);
}
}
@@ -2402,8 +2355,8 @@ std::vector<std::string> cmVisualStudio10TargetGenerator::GetIncludes(
bool cmVisualStudio10TargetGenerator::ComputeClOptions()
{
- for (std::string const& i : this->Configurations) {
- if (!this->ComputeClOptions(i)) {
+ for (std::string const& c : this->Configurations) {
+ if (!this->ComputeClOptions(c)) {
return false;
}
}
@@ -2612,13 +2565,11 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
return;
}
Elem e2(e1, "ClCompile");
- e2.SetHasElements();
- clOptions.PrependInheritedString("AdditionalOptions");
- clOptions.OutputAdditionalIncludeDirectories(e2.S, e2.Indent + 1,
- this->LangForClCompile);
- clOptions.OutputFlagMap(e2.S, e2.Indent + 1);
- clOptions.OutputPreprocessorDefinitions(e2.S, e2.Indent + 1,
- this->LangForClCompile);
+ OptionsHelper oh(clOptions, e2);
+ oh.PrependInheritedString("AdditionalOptions");
+ oh.OutputAdditionalIncludeDirectories(this->LangForClCompile);
+ oh.OutputFlagMap();
+ oh.OutputPreprocessorDefinitions(this->LangForClCompile);
if (this->NsightTegra) {
if (const char* processMax =
@@ -2643,7 +2594,6 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
if (!clOptions.IsDebug()) {
Elem e3(e2, "DebugInformationFormat");
e3.SetHasElements();
- e3.EndElement();
}
// Specify the compiler program database file if configured.
@@ -2665,14 +2615,12 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
e2.Element("AdditionalUsingDirectories", dirs);
}
}
-
- e2.EndElement();
}
bool cmVisualStudio10TargetGenerator::ComputeRcOptions()
{
- for (std::string const& i : this->Configurations) {
- if (!this->ComputeRcOptions(i)) {
+ for (std::string const& c : this->Configurations) {
+ if (!this->ComputeRcOptions(c)) {
return false;
}
}
@@ -2714,15 +2662,12 @@ void cmVisualStudio10TargetGenerator::WriteRCOptions(
return;
}
Elem e2(e1, "ResourceCompile");
- e2.SetHasElements();
- Options& rcOptions = *(this->RcOptions[configName]);
- rcOptions.OutputPreprocessorDefinitions(e2.S, e2.Indent + 1, "RC");
- rcOptions.OutputAdditionalIncludeDirectories(e2.S, e2.Indent + 1, "RC");
+ OptionsHelper rcOptions(*(this->RcOptions[configName]), e2);
+ rcOptions.OutputPreprocessorDefinitions("RC");
+ rcOptions.OutputAdditionalIncludeDirectories("RC");
rcOptions.PrependInheritedString("AdditionalOptions");
- rcOptions.OutputFlagMap(e2.S, e2.Indent + 1);
-
- e2.EndElement();
+ rcOptions.OutputFlagMap();
}
bool cmVisualStudio10TargetGenerator::ComputeCudaOptions()
@@ -2730,8 +2675,8 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions()
if (!this->GlobalGenerator->IsCudaEnabled()) {
return true;
}
- for (std::string const& i : this->Configurations) {
- if (!this->ComputeCudaOptions(i)) {
+ for (std::string const& c : this->Configurations) {
+ if (!this->ComputeCudaOptions(c)) {
return false;
}
}
@@ -2863,15 +2808,12 @@ void cmVisualStudio10TargetGenerator::WriteCudaOptions(
return;
}
Elem e2(e1, "CudaCompile");
- e2.SetHasElements();
- Options& cudaOptions = *(this->CudaOptions[configName]);
- cudaOptions.OutputAdditionalIncludeDirectories(e2.S, e2.Indent + 1, "CUDA");
- cudaOptions.OutputPreprocessorDefinitions(e2.S, e2.Indent + 1, "CUDA");
+ OptionsHelper cudaOptions(*(this->CudaOptions[configName]), e2);
+ cudaOptions.OutputAdditionalIncludeDirectories("CUDA");
+ cudaOptions.OutputPreprocessorDefinitions("CUDA");
cudaOptions.PrependInheritedString("AdditionalOptions");
- cudaOptions.OutputFlagMap(e2.S, e2.Indent + 1);
-
- e2.EndElement();
+ cudaOptions.OutputFlagMap();
}
bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions()
@@ -2879,8 +2821,8 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions()
if (!this->GlobalGenerator->IsCudaEnabled()) {
return true;
}
- for (std::string const& i : this->Configurations) {
- if (!this->ComputeCudaLinkOptions(i)) {
+ for (std::string const& c : this->Configurations) {
+ if (!this->ComputeCudaLinkOptions(c)) {
return false;
}
}
@@ -2937,10 +2879,8 @@ void cmVisualStudio10TargetGenerator::WriteCudaLinkOptions(
}
Elem e2(e1, "CudaLink");
- e2.SetHasElements();
- Options& cudaLinkOptions = *(this->CudaLinkOptions[configName]);
- cudaLinkOptions.OutputFlagMap(e2.S, e2.Indent + 1);
- e2.EndElement();
+ OptionsHelper cudaLinkOptions(*(this->CudaLinkOptions[configName]), e2);
+ cudaLinkOptions.OutputFlagMap();
}
bool cmVisualStudio10TargetGenerator::ComputeMasmOptions()
@@ -2948,8 +2888,8 @@ bool cmVisualStudio10TargetGenerator::ComputeMasmOptions()
if (!this->GlobalGenerator->IsMasmEnabled()) {
return true;
}
- for (std::string const& i : this->Configurations) {
- if (!this->ComputeMasmOptions(i)) {
+ for (std::string const& c : this->Configurations) {
+ if (!this->ComputeMasmOptions(c)) {
return false;
}
}
@@ -2987,19 +2927,15 @@ void cmVisualStudio10TargetGenerator::WriteMasmOptions(
return;
}
Elem e2(e1, "MASM");
- e2.SetHasElements();
// Preprocessor definitions and includes are shared with clOptions.
- Options& clOptions = *(this->ClOptions[configName]);
- clOptions.OutputPreprocessorDefinitions(e2.S, e2.Indent + 1, "ASM_MASM");
+ OptionsHelper clOptions(*(this->ClOptions[configName]), e2);
+ clOptions.OutputPreprocessorDefinitions("ASM_MASM");
- Options& masmOptions = *(this->MasmOptions[configName]);
- masmOptions.OutputAdditionalIncludeDirectories(e2.S, e2.Indent + 1,
- "ASM_MASM");
+ OptionsHelper masmOptions(*(this->MasmOptions[configName]), e2);
+ masmOptions.OutputAdditionalIncludeDirectories("ASM_MASM");
masmOptions.PrependInheritedString("AdditionalOptions");
- masmOptions.OutputFlagMap(e2.S, e2.Indent + 1);
-
- e2.EndElement();
+ masmOptions.OutputFlagMap();
}
bool cmVisualStudio10TargetGenerator::ComputeNasmOptions()
@@ -3007,8 +2943,8 @@ bool cmVisualStudio10TargetGenerator::ComputeNasmOptions()
if (!this->GlobalGenerator->IsNasmEnabled()) {
return true;
}
- for (std::string const& i : this->Configurations) {
- if (!this->ComputeNasmOptions(i)) {
+ for (std::string const& c : this->Configurations) {
+ if (!this->ComputeNasmOptions(c)) {
return false;
}
}
@@ -3047,22 +2983,18 @@ void cmVisualStudio10TargetGenerator::WriteNasmOptions(
return;
}
Elem e2(e1, "NASM");
- e2.SetHasElements();
std::vector<std::string> includes =
this->GetIncludes(configName, "ASM_NASM");
- Options& nasmOptions = *(this->NasmOptions[configName]);
- nasmOptions.OutputAdditionalIncludeDirectories(e2.S, e2.Indent + 1,
- "ASM_NASM");
- nasmOptions.OutputFlagMap(e2.S, e2.Indent + 1);
+ OptionsHelper nasmOptions(*(this->NasmOptions[configName]), e2);
+ nasmOptions.OutputAdditionalIncludeDirectories("ASM_NASM");
+ nasmOptions.OutputFlagMap();
nasmOptions.PrependInheritedString("AdditionalOptions");
- nasmOptions.OutputPreprocessorDefinitions(e2.S, e2.Indent + 1, "ASM_NASM");
+ nasmOptions.OutputPreprocessorDefinitions("ASM_NASM");
// Preprocessor definitions and includes are shared with clOptions.
- Options& clOptions = *(this->ClOptions[configName]);
- clOptions.OutputPreprocessorDefinitions(e2.S, e2.Indent + 1, "ASM_NASM");
-
- e2.EndElement();
+ OptionsHelper clOptions(*(this->ClOptions[configName]), e2);
+ clOptions.OutputPreprocessorDefinitions("ASM_NASM");
}
void cmVisualStudio10TargetGenerator::WriteLibOptions(
@@ -3077,15 +3009,14 @@ void cmVisualStudio10TargetGenerator::WriteLibOptions(
libflags, cmSystemTools::UpperCase(config), this->GeneratorTarget);
if (!libflags.empty()) {
Elem e2(e1, "Lib");
- e2.SetHasElements();
cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
cmVS10GeneratorOptions libOptions(this->LocalGenerator,
cmVisualStudioGeneratorOptions::Linker,
gg->GetLibFlagTable(), this);
libOptions.Parse(libflags.c_str());
- libOptions.PrependInheritedString("AdditionalOptions");
- libOptions.OutputFlagMap(e2.S, e2.Indent + 1);
- e2.EndElement();
+ OptionsHelper oh(libOptions, e2);
+ oh.PrependInheritedString("AdditionalOptions");
+ oh.OutputFlagMap();
}
// We cannot generate metadata for static libraries. WindowsPhone
@@ -3095,7 +3026,6 @@ void cmVisualStudio10TargetGenerator::WriteLibOptions(
this->GlobalGenerator->TargetsWindowsStore()) {
Elem e2(e1, "Link");
e2.Element("GenerateWindowsMetadata", "false");
- e2.EndElement();
}
}
@@ -3119,7 +3049,6 @@ void cmVisualStudio10TargetGenerator::WriteManifestOptions(
}
Elem e2(e1, "Manifest");
e2.Element("AdditionalManifestFiles", oss.str());
- e2.EndElement();
}
}
@@ -3141,8 +3070,8 @@ void cmVisualStudio10TargetGenerator::WriteAntBuildOptions(
}
}
- Elem e2(e1, "AntBuild");
// Tell MSBuild to launch Ant.
+ Elem e2(e1, "AntBuild");
{
std::string antBuildPath = rootDir;
ConvertToWindowsSlash(antBuildPath);
@@ -3224,8 +3153,6 @@ void cmVisualStudio10TargetGenerator::WriteAntBuildOptions(
e2.Element("AdditionalOptions",
std::string(antAdditionalOptions) + " %(AdditionalOptions)");
}
-
- e2.EndElement();
}
bool cmVisualStudio10TargetGenerator::ComputeLinkOptions()
@@ -3233,8 +3160,8 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions()
if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE ||
this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) {
- for (std::string const& i : this->Configurations) {
- if (!this->ComputeLinkOptions(i)) {
+ for (std::string const& c : this->Configurations) {
+ if (!this->ComputeLinkOptions(c)) {
return false;
}
}
@@ -3310,9 +3237,11 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
"CUDA") != linkClosure->Languages.end()) {
switch (this->CudaOptions[config]->GetCudaRuntime()) {
case cmVisualStudioGeneratorOptions::CudaRuntimeStatic:
+ libVec.push_back("cudadevrt.lib");
libVec.push_back("cudart_static.lib");
break;
case cmVisualStudioGeneratorOptions::CudaRuntimeShared:
+ libVec.push_back("cudadevrt.lib");
libVec.push_back("cudart.lib");
break;
case cmVisualStudioGeneratorOptions::CudaRuntimeNone:
@@ -3466,8 +3395,8 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
bool cmVisualStudio10TargetGenerator::ComputeLibOptions()
{
if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) {
- for (std::string const& i : this->Configurations) {
- if (!this->ComputeLibOptions(i)) {
+ for (std::string const& c : this->Configurations) {
+ if (!this->ComputeLibOptions(c)) {
return false;
}
}
@@ -3514,21 +3443,18 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions(
if (this->ProjectType == csproj) {
return;
}
- Options& linkOptions = *(this->LinkOptions[config]);
{
Elem e2(e1, "Link");
- e2.SetHasElements();
+ OptionsHelper linkOptions(*(this->LinkOptions[config]), e2);
linkOptions.PrependInheritedString("AdditionalOptions");
- linkOptions.OutputFlagMap(e2.S, e2.Indent + 1);
- e2.EndElement();
+ linkOptions.OutputFlagMap();
}
if (!this->GlobalGenerator->NeedLinkLibraryDependencies(
this->GeneratorTarget)) {
Elem e2(e1, "ProjectReference");
e2.Element("LinkLibraryDependencies", "false");
- e2.EndElement();
}
}
@@ -3645,16 +3571,15 @@ void cmVisualStudio10TargetGenerator::WriteMidlOptions(
for (std::string const& i : includes) {
oss << i << ";";
}
+ oss << "%(AdditionalIncludeDirectories)";
Elem e2(e1, "Midl");
- e2.Element("AdditionalIncludeDirectories",
- oss.str() + "%(AdditionalIncludeDirectories)");
+ e2.Element("AdditionalIncludeDirectories", oss.str());
e2.Element("OutputDirectory", "$(ProjectDir)/$(IntDir)");
e2.Element("HeaderFileName", "%(Filename).h");
e2.Element("TypeLibraryName", "%(Filename).tlb");
e2.Element("InterfaceIdentifierFileName", "%(Filename)_i.c");
e2.Element("ProxyFileName", "%(Filename)_p.c");
- e2.EndElement();
}
void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups(Elem& e0)
@@ -3662,38 +3587,37 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups(Elem& e0)
if (this->ProjectType == csproj) {
return;
}
- for (const auto& i : this->Configurations) {
+ for (const std::string& c : this->Configurations) {
Elem e1(e0, "ItemDefinitionGroup");
- e1.Attribute("Condition", this->CalcCondition(i));
+ e1.Attribute("Condition", this->CalcCondition(c));
// output cl compile flags <ClCompile></ClCompile>
if (this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY) {
- this->WriteClOptions(e1, i);
+ this->WriteClOptions(e1, c);
// output rc compile flags <ResourceCompile></ResourceCompile>
- this->WriteRCOptions(e1, i);
- this->WriteCudaOptions(e1, i);
- this->WriteMasmOptions(e1, i);
- this->WriteNasmOptions(e1, i);
+ this->WriteRCOptions(e1, c);
+ this->WriteCudaOptions(e1, c);
+ this->WriteMasmOptions(e1, c);
+ this->WriteNasmOptions(e1, c);
}
// output midl flags <Midl></Midl>
- this->WriteMidlOptions(e1, i);
+ this->WriteMidlOptions(e1, c);
// write events
if (this->ProjectType != csproj) {
- this->WriteEvents(e1, i);
+ this->WriteEvents(e1, c);
}
// output link flags <Link></Link>
- this->WriteLinkOptions(e1, i);
- this->WriteCudaLinkOptions(e1, i);
+ this->WriteLinkOptions(e1, c);
+ this->WriteCudaLinkOptions(e1, c);
// output lib flags <Lib></Lib>
- this->WriteLibOptions(e1, i);
+ this->WriteLibOptions(e1, c);
// output manifest flags <Manifest></Manifest>
- this->WriteManifestOptions(e1, i);
+ this->WriteManifestOptions(e1, c);
if (this->NsightTegra &&
this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE &&
this->GeneratorTarget->GetPropertyAsBool("ANDROID_GUI")) {
- this->WriteAntBuildOptions(e1, i);
+ this->WriteAntBuildOptions(e1, c);
}
- e1.EndElement();
}
}
@@ -3728,13 +3652,12 @@ void cmVisualStudio10TargetGenerator::WriteEvent(
if (commands.empty()) {
return;
}
- Elem e2(e1, name);
cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
std::string script;
const char* pre = "";
std::string comment;
- for (cmCustomCommand const& i : commands) {
- cmCustomCommandGenerator ccg(i, configName, this->LocalGenerator);
+ for (cmCustomCommand const& cc : commands) {
+ cmCustomCommandGenerator ccg(cc, configName, lg);
if (!ccg.HasOnlyEmptyCommandLines()) {
comment += pre;
comment += lg->ConstructComment(ccg);
@@ -3745,9 +3668,9 @@ void cmVisualStudio10TargetGenerator::WriteEvent(
}
comment = cmVS10EscapeComment(comment);
if (this->ProjectType != csproj) {
+ Elem e2(e1, name);
e2.Element("Message", comment);
e2.Element("Command", script);
- e2.EndElement();
} else {
std::string strippedComment = comment;
strippedComment.erase(
@@ -3758,7 +3681,7 @@ void cmVisualStudio10TargetGenerator::WriteEvent(
oss << "echo " << comment << "\n";
}
oss << script << "\n";
- e2.Content(oss.str());
+ e1.Element(name, oss.str());
}
}
@@ -3771,8 +3694,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences(Elem& e0)
OrderedTargetDependSet depends(unordered, CMAKE_CHECK_BUILD_SYSTEM_TARGET);
Elem e1(e0, "ItemGroup");
e1.SetHasElements();
- for (cmTargetDepend const& i : depends) {
- cmGeneratorTarget const* dt = i;
+ for (cmGeneratorTarget const* dt : depends) {
if (dt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
@@ -3803,24 +3725,29 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences(Elem& e0)
// If the dependency target is not managed (compiled with /clr or
// C# target) we cannot reference it and have to set
// 'ReferenceOutputAssembly' to false.
- cmGeneratorTarget::ManagedType check =
- cmGeneratorTarget::ManagedType::Mixed;
- // FIXME: These (5) lines should be removed. They are here to allow
- // manual setting of the /clr flag in compiler options. Setting
- // /clr manually makes cmGeneratorTarget::GetManagedType() return
- // 'Native' instead of 'Mixed' or 'Managed'.
- check = cmGeneratorTarget::ManagedType::Native;
- bool unmanagedStatic = false;
- if (dt->GetType() == cmStateEnums::STATIC_LIBRARY) {
- unmanagedStatic = !dt->HasLanguage("CSharp", "");
+ auto referenceNotManaged =
+ dt->GetManagedType("") < cmGeneratorTarget::ManagedType::Mixed;
+ // Workaround to check for manually set /clr flags.
+ if (referenceNotManaged) {
+ if (const auto* flags = dt->GetProperty("COMPILE_OPTIONS")) {
+ std::string flagsStr = flags;
+ if (flagsStr.find("clr") != std::string::npos) {
+ // There is a warning already issued when building the flags.
+ referenceNotManaged = false;
+ }
+ }
}
- if (dt->GetManagedType("") < check || unmanagedStatic) {
+ // Workaround for static library C# targets
+ if (referenceNotManaged &&
+ dt->GetType() == cmStateEnums::STATIC_LIBRARY) {
+ referenceNotManaged = !dt->HasLanguage("CSharp", "");
+ }
+ if (referenceNotManaged) {
e2.Element("ReferenceOutputAssembly", "false");
+ e2.Element("CopyToOutputDirectory", "Never");
}
}
- e2.EndElement();
}
- e1.EndElement();
}
void cmVisualStudio10TargetGenerator::WritePlatformExtensions(Elem& e1)
@@ -3846,25 +3773,17 @@ void cmVisualStudio10TargetGenerator::WritePlatformExtensions(Elem& e1)
void cmVisualStudio10TargetGenerator::WriteSinglePlatformExtension(
Elem& e1, std::string const& extension, std::string const& version)
{
+ const std::string s = "$([Microsoft.Build.Utilities.ToolLocationHelper]"
+ "::GetPlatformExtensionSDKLocation(`" +
+ extension + ", Version=" + version +
+ "`, $(TargetPlatformIdentifier), $(TargetPlatformVersion), null, "
+ "$(ExtensionSDKDirectoryRoot), null))"
+ "\\DesignTime\\CommonConfiguration\\Neutral\\" +
+ extension + ".props";
+
Elem e2(e1, "Import");
- e2.Attribute(
- "Project", "$([Microsoft.Build.Utilities.ToolLocationHelper]"
- "::GetPlatformExtensionSDKLocation(`" +
- extension + ", Version=" + version +
- "`, $(TargetPlatformIdentifier), $(TargetPlatformVersion), null, "
- "$(ExtensionSDKDirectoryRoot), null))"
- "\\DesignTime\\CommonConfiguration\\Neutral\\" +
- extension + ".props");
- e2.Attribute(
- "Condition", "exists('$("
- "[Microsoft.Build.Utilities.ToolLocationHelper]"
- "::GetPlatformExtensionSDKLocation(`" +
- extension + ", Version=" + version +
- "`, $(TargetPlatformIdentifier), $(TargetPlatformVersion), null, "
- "$(ExtensionSDKDirectoryRoot), null))"
- "\\DesignTime\\CommonConfiguration\\Neutral\\" +
- extension + ".props')");
- e2.EndElement();
+ e2.Attribute("Project", s);
+ e2.Attribute("Condition", "exists('" + s + "')");
}
void cmVisualStudio10TargetGenerator::WriteSDKReferences(Elem& e0)
@@ -3878,7 +3797,7 @@ void cmVisualStudio10TargetGenerator::WriteSDKReferences(Elem& e0)
e1.StartElement("ItemGroup");
hasWrittenItemGroup = true;
for (std::string const& ri : sdkReferences) {
- Elem(e1, "SDKReference").Attribute("Include", ri).EndElement();
+ Elem(e1, "SDKReference").Attribute("Include", ri);
}
}
@@ -3896,7 +3815,6 @@ void cmVisualStudio10TargetGenerator::WriteSDKReferences(Elem& e0)
iotExtensionsVersion) {
if (!hasWrittenItemGroup) {
e1.StartElement("ItemGroup");
- hasWrittenItemGroup = true;
}
if (desktopExtensionsVersion) {
this->WriteSingleSDKReference(e1, "WindowsDesktop",
@@ -3911,18 +3829,13 @@ void cmVisualStudio10TargetGenerator::WriteSDKReferences(Elem& e0)
}
}
}
-
- if (hasWrittenItemGroup) {
- e1.EndElement();
- }
}
void cmVisualStudio10TargetGenerator::WriteSingleSDKReference(
Elem& e1, std::string const& extension, std::string const& version)
{
Elem(e1, "SDKReference")
- .Attribute("Include", extension + ", Version=" + version)
- .EndElement();
+ .Attribute("Include", extension + ", Version=" + version);
}
void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile(
@@ -3964,6 +3877,7 @@ void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile(
pfxFile, false);
ConvertToWindowsSlash(pfxFile);
this->AddedFiles.push_back(pfxFile);
+ this->AddedDefaultCertificate = true;
}
e1.Element("PackageCertificateKeyFile", pfxFile);
@@ -3971,7 +3885,6 @@ void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile(
if (!thumb.empty()) {
e1.Element("PackageCertificateThumbprint", thumb);
}
- e1.EndElement();
} else if (!pfxFile.empty()) {
Elem e1(e0, "PropertyGroup");
e1.Element("PackageCertificateKeyFile", pfxFile);
@@ -3979,7 +3892,6 @@ void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile(
if (!thumb.empty()) {
e1.Element("PackageCertificateThumbprint", thumb);
}
- e1.EndElement();
}
}
}
@@ -4215,23 +4127,24 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWP80(Elem& e1)
std::string sourceFile = this->ConvertPath(manifestFile, false);
ConvertToWindowsSlash(sourceFile);
- Elem e2(e1, "Xml");
- e2.Attribute("Include", sourceFile);
- e2.Element("SubType", "Designer");
- e2.EndElement();
+ {
+ Elem e2(e1, "Xml");
+ e2.Attribute("Include", sourceFile);
+ e2.Element("SubType", "Designer");
+ }
this->AddedFiles.push_back(sourceFile);
std::string smallLogo = this->DefaultArtifactDir + "/SmallLogo.png";
cmSystemTools::CopyAFile(templateFolder + "/SmallLogo.png", smallLogo,
false);
ConvertToWindowsSlash(smallLogo);
- Elem(e1, "Image").Attribute("Include", smallLogo).EndElement();
+ Elem(e1, "Image").Attribute("Include", smallLogo);
this->AddedFiles.push_back(smallLogo);
std::string logo = this->DefaultArtifactDir + "/Logo.png";
cmSystemTools::CopyAFile(templateFolder + "/Logo.png", logo, false);
ConvertToWindowsSlash(logo);
- Elem(e1, "Image").Attribute("Include", logo).EndElement();
+ Elem(e1, "Image").Attribute("Include", logo);
this->AddedFiles.push_back(logo);
std::string applicationIcon =
@@ -4239,7 +4152,7 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWP80(Elem& e1)
cmSystemTools::CopyAFile(templateFolder + "/ApplicationIcon.png",
applicationIcon, false);
ConvertToWindowsSlash(applicationIcon);
- Elem(e1, "Image").Attribute("Include", applicationIcon).EndElement();
+ Elem(e1, "Image").Attribute("Include", applicationIcon);
this->AddedFiles.push_back(applicationIcon);
}
@@ -4490,50 +4403,54 @@ void cmVisualStudio10TargetGenerator::WriteCommonMissingFiles(
std::string sourceFile = this->ConvertPath(manifestFile, false);
ConvertToWindowsSlash(sourceFile);
- Elem e2(e1, "AppxManifest");
- e2.Attribute("Include", sourceFile);
- e2.Element("SubType", "Designer");
- e2.EndElement();
+ {
+ Elem e2(e1, "AppxManifest");
+ e2.Attribute("Include", sourceFile);
+ e2.Element("SubType", "Designer");
+ }
this->AddedFiles.push_back(sourceFile);
std::string smallLogo = this->DefaultArtifactDir + "/SmallLogo.png";
cmSystemTools::CopyAFile(templateFolder + "/SmallLogo.png", smallLogo,
false);
ConvertToWindowsSlash(smallLogo);
- Elem(e1, "Image").Attribute("Include", smallLogo).EndElement();
+ Elem(e1, "Image").Attribute("Include", smallLogo);
this->AddedFiles.push_back(smallLogo);
std::string smallLogo44 = this->DefaultArtifactDir + "/SmallLogo44x44.png";
cmSystemTools::CopyAFile(templateFolder + "/SmallLogo44x44.png", smallLogo44,
false);
ConvertToWindowsSlash(smallLogo44);
- Elem(e1, "Image").Attribute("Include", smallLogo44).EndElement();
+ Elem(e1, "Image").Attribute("Include", smallLogo44);
this->AddedFiles.push_back(smallLogo44);
std::string logo = this->DefaultArtifactDir + "/Logo.png";
cmSystemTools::CopyAFile(templateFolder + "/Logo.png", logo, false);
ConvertToWindowsSlash(logo);
- Elem(e1, "Image").Attribute("Include", logo).EndElement();
+ Elem(e1, "Image").Attribute("Include", logo);
this->AddedFiles.push_back(logo);
std::string storeLogo = this->DefaultArtifactDir + "/StoreLogo.png";
cmSystemTools::CopyAFile(templateFolder + "/StoreLogo.png", storeLogo,
false);
ConvertToWindowsSlash(storeLogo);
- Elem(e1, "Image").Attribute("Include", storeLogo).EndElement();
+ Elem(e1, "Image").Attribute("Include", storeLogo);
this->AddedFiles.push_back(storeLogo);
std::string splashScreen = this->DefaultArtifactDir + "/SplashScreen.png";
cmSystemTools::CopyAFile(templateFolder + "/SplashScreen.png", splashScreen,
false);
ConvertToWindowsSlash(splashScreen);
- Elem(e1, "Image").Attribute("Include", splashScreen).EndElement();
+ Elem(e1, "Image").Attribute("Include", splashScreen);
this->AddedFiles.push_back(splashScreen);
- // This file has already been added to the build so don't copy it
- std::string keyFile = this->DefaultArtifactDir + "/Windows_TemporaryKey.pfx";
- ConvertToWindowsSlash(keyFile);
- Elem(e1, "None").Attribute("Include", keyFile).EndElement();
+ if (this->AddedDefaultCertificate) {
+ // This file has already been added to the build so don't copy it
+ std::string keyFile =
+ this->DefaultArtifactDir + "/Windows_TemporaryKey.pfx";
+ ConvertToWindowsSlash(keyFile);
+ Elem(e1, "None").Attribute("Include", keyFile);
+ }
}
bool cmVisualStudio10TargetGenerator::ForceOld(const std::string& source) const
diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h
index f6c5a64..15e47b4 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -32,10 +32,6 @@ public:
cmGlobalVisualStudio10Generator* gg);
~cmVisualStudio10TargetGenerator();
void Generate();
- // used by cmVisualStudioGeneratorOptions
- std::string CalcCondition(const std::string& config) const;
- void WritePlatformConfigTag(const char* tag, const std::string& config,
- int indentLevel, const std::string& content);
private:
struct ToolSource
@@ -54,13 +50,10 @@ private:
};
struct Elem;
+ struct OptionsHelper;
std::string ConvertPath(std::string const& path, bool forceRelative);
- void WriteString(const char* line, int indentLevel);
- void WriteElem(const char* tag, const char* val, int indentLevel);
- void WriteElem(const char* tag, std::string const& val, int indentLevel);
- void WriteElemEscapeXML(const char* tag, std::string const& val,
- int indentLevel);
+ std::string CalcCondition(const std::string& config) const;
void WriteProjectConfigurations(Elem& e0);
void WriteProjectConfigurationValues(Elem& e0);
void WriteMSToolConfigurationValues(Elem& e1, std::string const& config);
@@ -151,7 +144,7 @@ private:
void WriteGroups();
void WriteProjectReferences(Elem& e0);
void WriteApplicationTypeSettings(Elem& e1);
- void OutputSourceSpecificFlags(Elem&, cmSourceFile const* source);
+ void OutputSourceSpecificFlags(Elem& e2, cmSourceFile const* source);
void AddLibraries(const cmComputeLinkInformation& cli,
std::vector<std::string>& libVec,
std::vector<std::string>& vsTargetVec,
@@ -182,6 +175,7 @@ private:
void GetCSharpSourceLink(cmSourceFile const* sf, std::string& link);
private:
+ friend class cmVS10GeneratorOptions;
typedef cmVS10GeneratorOptions Options;
typedef std::map<std::string, std::unique_ptr<Options>> OptionsMap;
OptionsMap ClOptions;
@@ -192,8 +186,6 @@ private:
OptionsMap NasmOptions;
OptionsMap LinkOptions;
std::string LangForClCompile;
- std::string PathToProjectFile;
- std::string ProjectFileExtension;
enum VsProjectType
{
vcxproj,
@@ -213,12 +205,12 @@ private:
unsigned int NsightTegraVersion[4];
bool TargetCompileAsWinRT;
cmGlobalVisualStudio10Generator* const GlobalGenerator;
- cmGeneratedFileStream* BuildFileStream;
cmLocalVisualStudio10Generator* const LocalGenerator;
std::set<std::string> CSharpCustomCommandNames;
bool IsMissingFiles;
std::vector<std::string> AddedFiles;
std::string DefaultArtifactDir;
+ bool AddedDefaultCertificate = false;
// managed C++/C# relevant members
typedef std::pair<std::string, std::string> DotNetHintReference;
typedef std::vector<DotNetHintReference> DotNetHintReferenceList;
diff --git a/Source/cmWhileCommand.cxx b/Source/cmWhileCommand.cxx
index a080034..d5bcfc2 100644
--- a/Source/cmWhileCommand.cxx
+++ b/Source/cmWhileCommand.cxx
@@ -28,10 +28,10 @@ bool cmWhileFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
cmExecutionStatus& inStatus)
{
// at end of for each execute recorded commands
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "while")) {
+ if (lff.Name.Lower == "while") {
// record the number of while commands past this one
this->Depth++;
- } else if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endwhile")) {
+ } else if (lff.Name.Lower == "endwhile") {
// if this is the endwhile for this while loop then execute
if (!this->Depth) {
// Remove the function blocker for this scope or bail.
@@ -117,7 +117,7 @@ bool cmWhileFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff,
bool cmWhileFunctionBlocker::ShouldRemove(const cmListFileFunction& lff,
cmMakefile&)
{
- if (!cmSystemTools::Strucmp(lff.Name.c_str(), "endwhile")) {
+ if (lff.Name.Lower == "endwhile") {
// if the endwhile has arguments, then make sure
// they match the arguments of the matching while
if (lff.Arguments.empty() || lff.Arguments == this->Args) {
diff --git a/Source/cmXMLWriter.h b/Source/cmXMLWriter.h
index ff0df18..d124907 100644
--- a/Source/cmXMLWriter.h
+++ b/Source/cmXMLWriter.h
@@ -181,6 +181,12 @@ public:
{
xmlwr.Content(content);
}
+ template <typename T>
+ void Element(std::string const& name, T const& value)
+ {
+ xmlwr.Element(name, value);
+ }
+ void Comment(const char* comment) { xmlwr.Comment(comment); }
private:
cmXMLWriter& xmlwr;
diff --git a/Source/cmake.h b/Source/cmake.h
index 6c0d77c..53c2f45 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -553,7 +553,7 @@ private:
#define CMAKE_STANDARD_OPTIONS_TABLE \
{ "-C <initial-cache>", "Pre-load a script to populate the cache." }, \
- { "-D <var>[:<type>]=<value>", "Create a cmake cache entry." }, \
+ { "-D <var>[:<type>]=<value>", "Create or update a cmake cache entry." }, \
{ "-U <globbing_expr>", "Remove matching entries from CMake cache." }, \
{ "-G <generator-name>", "Specify a build system generator." }, \
{ "-T <toolset-name>", \
diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt
index 4fc176b..96088c8 100644
--- a/Source/kwsys/CMakeLists.txt
+++ b/Source/kwsys/CMakeLists.txt
@@ -196,6 +196,11 @@ IF(KWSYS_STANDALONE)
ENDIF()
ENDIF()
+# Choose default shared/static build if not specified.
+IF(NOT DEFINED KWSYS_BUILD_SHARED)
+ SET(KWSYS_BUILD_SHARED ${BUILD_SHARED_LIBS})
+ENDIF()
+
# Include helper macros.
INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/kwsysPlatformTests.cmake)
INCLUDE(CheckTypeSize)
@@ -230,13 +235,14 @@ ENDIF()
# Setup library install rules.
SET(KWSYS_INSTALL_LIBRARY_RULE)
+SET(KWSYS_INSTALL_NAMELINK_RULE)
IF(KWSYS_INSTALL_LIB_DIR)
IF(KWSYS_INSTALL_EXPORT_NAME)
LIST(APPEND KWSYS_INSTALL_LIBRARY_RULE EXPORT ${KWSYS_INSTALL_EXPORT_NAME})
ENDIF()
# Install the shared library to the lib directory.
SET(KWSYS_INSTALL_LIBRARY_RULE ${KWSYS_INSTALL_LIBRARY_RULE}
- LIBRARY DESTINATION ${KWSYS_INSTALL_LIB_DIR}
+ LIBRARY DESTINATION ${KWSYS_INSTALL_LIB_DIR} NAMELINK_SKIP
)
# Assign the shared library to the runtime component.
IF(KWSYS_INSTALL_COMPONENT_NAME_RUNTIME)
@@ -244,6 +250,17 @@ IF(KWSYS_INSTALL_LIB_DIR)
COMPONENT ${KWSYS_INSTALL_COMPONENT_NAME_RUNTIME}
)
ENDIF()
+ IF(KWSYS_BUILD_SHARED)
+ SET(KWSYS_INSTALL_NAMELINK_RULE ${KWSYS_INSTALL_NAMELINK_RULE}
+ LIBRARY DESTINATION ${KWSYS_INSTALL_LIB_DIR} NAMELINK_ONLY
+ )
+ # Assign the namelink to the development component.
+ IF(KWSYS_INSTALL_COMPONENT_NAME_DEVELOPMENT)
+ SET(KWSYS_INSTALL_NAMELINK_RULE ${KWSYS_INSTALL_NAMELINK_RULE}
+ COMPONENT ${KWSYS_INSTALL_COMPONENT_NAME_DEVELOPMENT}
+ )
+ ENDIF()
+ ENDIF()
# Install the archive to the lib directory.
SET(KWSYS_INSTALL_LIBRARY_RULE ${KWSYS_INSTALL_LIBRARY_RULE}
@@ -427,11 +444,6 @@ ELSE()
SET(KWSYS_NAME_IS_KWSYS 0)
ENDIF()
-# Choose default shared/static build if not specified.
-IF(KWSYS_BUILD_SHARED MATCHES "^KWSYS_BUILD_SHARED$")
- SET(KWSYS_BUILD_SHARED ${BUILD_SHARED_LIBS})
-ENDIF()
-
IF(KWSYS_BUILD_SHARED)
SET(KWSYS_BUILD_SHARED 1)
SET(KWSYS_LIBRARY_TYPE SHARED)
@@ -933,6 +945,9 @@ IF(KWSYS_C_SRCS OR KWSYS_CXX_SRCS)
IF(KWSYS_INSTALL_LIBRARY_RULE)
INSTALL(TARGETS ${KWSYS_TARGET_INSTALL} ${KWSYS_INSTALL_LIBRARY_RULE})
ENDIF()
+ IF(KWSYS_INSTALL_NAMELINK_RULE)
+ INSTALL(TARGETS ${KWSYS_TARGET_INSTALL} ${KWSYS_INSTALL_NAMELINK_RULE})
+ ENDIF()
ENDIF()
# Add a C-only library if requested.
diff --git a/Source/kwsys/RegularExpression.hxx.in b/Source/kwsys/RegularExpression.hxx.in
index 3cbbeb8..92e4b36 100644
--- a/Source/kwsys/RegularExpression.hxx.in
+++ b/Source/kwsys/RegularExpression.hxx.in
@@ -218,7 +218,7 @@ inline std::string RegularExpressionMatch::match(int n) const
* object as an argument and creates an object initialized with the
* information from the given RegularExpression object.
*
- * The find member function finds the first occurrence of the regular
+ * The find member function finds the first occurrence of the regular
* expression of that object in the string given to find as an argument. Find
* returns a boolean, and if true, mutates the private data appropriately.
* Find sets pointers to the beginning and end of the thing last found, they
@@ -230,9 +230,9 @@ inline std::string RegularExpressionMatch::match(int n) const
* the to see if the compiled regular expression is the same, and the
* deep_equal functions also checks to see if the start and end pointers are
* the same. The is_valid function returns false if program is set to NULL,
- * (i.e. there is no valid compiled exression). The set_invalid function sets
- * the program to NULL (Warning: this deletes the compiled expression). The
- * following examples may help clarify regular expression usage:
+ * (i.e. there is no valid compiled expression). The set_invalid function
+ * sets the program to NULL (Warning: this deletes the compiled expression).
+ * The following examples may help clarify regular expression usage:
*
* * The regular expression "^hello" matches a "hello" only at the
* beginning of a line. It would match "hello there" but not "hi,
@@ -270,13 +270,13 @@ inline std::string RegularExpressionMatch::match(int n) const
*
* * The regular expression "(..p)b" matches something ending with pb
* and beginning with whatever the two characters before the first p
- * encounterd in the line were. It would find "repb" in "rep drepa
+ * encountered in the line were. It would find "repb" in "rep drepa
* qrepb". The regular expression "(..p)a" would find "repa qrepb"
* in "rep drepa qrepb"
*
* * The regular expression "d(..p)" matches something ending with p,
* beginning with d, and having two characters in between that are
- * the same as the two characters before the first p encounterd in
+ * the same as the two characters before the first p encountered in
* the line. It would match "drepa qrepb" in "rep drepa qrepb".
*
* All methods of RegularExpression can be called simultaneously from
diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx
index 7426816..37dec13 100644
--- a/Source/kwsys/SystemInformation.cxx
+++ b/Source/kwsys/SystemInformation.cxx
@@ -1270,7 +1270,7 @@ public:
long GetLineNumber() const { return this->LineNumber; }
// Description:
- // Set the address where the biinary image is mapped
+ // Set the address where the binary image is mapped
// into memory.
void SetBinaryBaseAddress(void* address)
{
@@ -4061,7 +4061,7 @@ bool SystemInformationImplementation::QueryLinuxMemory()
if (linuxMajor >= 3 || ((linuxMajor >= 2) && (linuxMinor >= 6))) {
// new /proc/meminfo format since kernel 2.6.x
- // Rigorously, this test should check from the developping version 2.5.x
+ // Rigorously, this test should check from the developing version 2.5.x
// that introduced the new format...
enum
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index 52f509a..7743e4e 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -2282,7 +2282,9 @@ bool SystemTools::CopyADirectory(const std::string& source,
const std::string& destination, bool always)
{
Directory dir;
- dir.Load(source);
+ if (dir.Load(source) == 0) {
+ return false;
+ }
size_t fileNum;
if (!SystemTools::MakeDirectory(destination)) {
return false;
@@ -4030,23 +4032,16 @@ std::string SystemTools::MakeCidentifier(const std::string& s)
return str;
}
-// Due to a buggy stream library on the HP and another on Mac OS X, we
-// need this very carefully written version of getline. Returns true
+// Convenience function around std::getline which removes a trailing carriage
+// return and can truncate the buffer as needed. Returns true
// if any data were read before the end-of-file was reached.
bool SystemTools::GetLineFromStream(std::istream& is, std::string& line,
bool* has_newline /* = 0 */,
long sizeLimit /* = -1 */)
{
- const int bufferSize = 1024;
- char buffer[bufferSize];
- bool haveData = false;
- bool haveNewline = false;
-
// Start with an empty line.
line = "";
- long leftToRead = sizeLimit;
-
// Early short circuit return if stream is no good. Just return
// false and the empty line. (Probably means caller tried to
// create a file stream with a non-existent file name...)
@@ -4058,44 +4053,23 @@ bool SystemTools::GetLineFromStream(std::istream& is, std::string& line,
return false;
}
- // If no characters are read from the stream, the end of file has
- // been reached. Clear the fail bit just before reading.
- while (!haveNewline && leftToRead != 0 &&
- (static_cast<void>(is.clear(is.rdstate() & ~std::ios::failbit)),
- static_cast<void>(is.getline(buffer, bufferSize)),
- is.gcount() > 0)) {
- // We have read at least one byte.
- haveData = true;
-
- // If newline character was read the gcount includes the character
- // but the buffer does not: the end of line has been reached.
- size_t length = strlen(buffer);
- if (length < static_cast<size_t>(is.gcount())) {
- haveNewline = true;
- }
-
+ std::getline(is, line);
+ bool haveData = !line.empty() || !is.eof();
+ if (!line.empty()) {
// Avoid storing a carriage return character.
- if (length > 0 && buffer[length - 1] == '\r') {
- buffer[length - 1] = 0;
+ if (*line.rbegin() == '\r') {
+ line.resize(line.size() - 1);
}
// if we read too much then truncate the buffer
- if (leftToRead > 0) {
- if (static_cast<long>(length) > leftToRead) {
- buffer[leftToRead] = 0;
- leftToRead = 0;
- } else {
- leftToRead -= static_cast<long>(length);
- }
+ if (sizeLimit >= 0 && line.size() >= static_cast<size_t>(sizeLimit)) {
+ line.resize(sizeLimit);
}
-
- // Append the data read to the line.
- line.append(buffer);
}
// Return the results.
if (has_newline) {
- *has_newline = haveNewline;
+ *has_newline = !is.eof();
}
return haveData;
}
diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in
index e79e3fc..3898e3a 100644
--- a/Source/kwsys/SystemTools.hxx.in
+++ b/Source/kwsys/SystemTools.hxx.in
@@ -523,9 +523,8 @@ public:
static bool GetShortPath(const std::string& path, std::string& result);
/**
- * Read line from file. Make sure to get everything. Due to a buggy stream
- * library on the HP and another on Mac OS X, we need this very carefully
- * written version of getline. Returns true if any data were read before the
+ * Read line from file. Make sure to read a full line and truncates it if
+ * requested via sizeLimit. Returns true if any data were read before the
* end-of-file was reached. If the has_newline argument is specified, it will
* be true when the line read had a newline character.
*/
diff --git a/Source/kwsys/testCommandLineArguments.cxx b/Source/kwsys/testCommandLineArguments.cxx
index 78baed9..58f861c 100644
--- a/Source/kwsys/testCommandLineArguments.cxx
+++ b/Source/kwsys/testCommandLineArguments.cxx
@@ -136,7 +136,7 @@ int testCommandLineArguments(int argc, char* argv[])
arg.AddCallback("-C", argT::EQUAL_ARGUMENT, argument, random_ptr,
"Option -C takes argument after =");
arg.AddCallback("-D", argT::CONCAT_ARGUMENT, argument, random_ptr,
- "This option takes concatinated argument");
+ "This option takes concatenated argument");
arg.AddCallback("--long1", argT::NO_ARGUMENT, argument, random_ptr, "-A");
arg.AddCallback("--long2", argT::SPACE_ARGUMENT, argument, random_ptr, "-B");
arg.AddCallback("--long3", argT::EQUAL_ARGUMENT, argument, random_ptr,
diff --git a/Source/kwsys/testDirectory.cxx b/Source/kwsys/testDirectory.cxx
index 983f2c6..62a0986 100644
--- a/Source/kwsys/testDirectory.cxx
+++ b/Source/kwsys/testDirectory.cxx
@@ -73,7 +73,38 @@ int _doLongPathTest()
return res;
}
+int _copyDirectoryTest()
+{
+ using namespace kwsys;
+ const std::string source(TEST_SYSTEMTOOLS_BINARY_DIR
+ "/directory_testing/copyDirectoryTestSrc");
+ if (SystemTools::PathExists(source)) {
+ std::cerr << source << " shouldn't exist before test" << std::endl;
+ return 1;
+ }
+ const std::string destination(TEST_SYSTEMTOOLS_BINARY_DIR
+ "/directory_testing/copyDirectoryTestDst");
+ if (SystemTools::PathExists(destination)) {
+ std::cerr << destination << " shouldn't exist before test" << std::endl;
+ return 2;
+ }
+ const bool copysuccess = SystemTools::CopyADirectory(source, destination);
+ const bool destinationexists = SystemTools::PathExists(destination);
+ if (copysuccess) {
+ std::cerr << "CopyADirectory should have returned false" << std::endl;
+ SystemTools::RemoveADirectory(destination);
+ return 3;
+ }
+ if (destinationexists) {
+ std::cerr << "CopyADirectory returned false, but destination directory"
+ << " has been created" << std::endl;
+ SystemTools::RemoveADirectory(destination);
+ return 4;
+ }
+ return 0;
+}
+
int testDirectory(int, char* [])
{
- return _doLongPathTest();
+ return _doLongPathTest() + _copyDirectoryTest();
}
diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx
index a6d934b..8c928d4 100644
--- a/Source/kwsys/testSystemTools.cxx
+++ b/Source/kwsys/testSystemTools.cxx
@@ -912,6 +912,78 @@ static bool CheckGetLineFromStream()
return ret;
}
+static bool CheckGetLineFromStreamLongLine()
+{
+ const std::string fileWithLongLine("longlines.txt");
+ std::string firstLine, secondLine;
+ // First line: large buffer, containing a carriage return for some reason.
+ firstLine.assign(2050, ' ');
+ firstLine += "\rfirst";
+ secondLine.assign(2050, 'y');
+ secondLine += "second";
+
+ // Create file with long lines.
+ {
+ kwsys::ofstream out(fileWithLongLine.c_str(), std::ios::binary);
+ if (!out) {
+ std::cerr << "Problem opening for write: " << fileWithLongLine
+ << std::endl;
+ return false;
+ }
+ out << firstLine << "\r\n\n" << secondLine << "\n";
+ }
+
+ kwsys::ifstream file(fileWithLongLine.c_str(), std::ios::binary);
+ if (!file) {
+ std::cerr << "Problem opening: " << fileWithLongLine << std::endl;
+ return false;
+ }
+
+ std::string line;
+ bool has_newline = false;
+ bool result;
+
+ // Read first line.
+ result = kwsys::SystemTools::GetLineFromStream(file, line, &has_newline, -1);
+ if (!result || line != firstLine) {
+ std::cerr << "First line does not match, expected " << firstLine.size()
+ << " characters, got " << line.size() << std::endl;
+ return false;
+ }
+ if (!has_newline) {
+ std::cerr << "Expected new line to be read from first line" << std::endl;
+ return false;
+ }
+
+ // Read empty line.
+ has_newline = false;
+ result = kwsys::SystemTools::GetLineFromStream(file, line, &has_newline, -1);
+ if (!result || !line.empty()) {
+ std::cerr << "Expected successful read with an empty line, got "
+ << line.size() << " characters" << std::endl;
+ return false;
+ }
+ if (!has_newline) {
+ std::cerr << "Expected new line to be read for an empty line" << std::endl;
+ return false;
+ }
+
+ // Read second line.
+ has_newline = false;
+ result = kwsys::SystemTools::GetLineFromStream(file, line, &has_newline, -1);
+ if (!result || line != secondLine) {
+ std::cerr << "Second line does not match, expected " << secondLine.size()
+ << " characters, got " << line.size() << std::endl;
+ return false;
+ }
+ if (!has_newline) {
+ std::cerr << "Expected new line to be read from second line" << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
int testSystemTools(int, char* [])
{
bool res = true;
@@ -951,6 +1023,8 @@ int testSystemTools(int, char* [])
res &= CheckGetLineFromStream();
+ res &= CheckGetLineFromStreamLongLine();
+
res &= CheckGetFilenameName();
return res ? 0 : 1;
diff --git a/Tests/CMakeLib/testRST.expect b/Tests/CMakeLib/testRST.expect
index 4b29762..1ffd6b9 100644
--- a/Tests/CMakeLib/testRST.expect
+++ b/Tests/CMakeLib/testRST.expect
@@ -19,6 +19,10 @@ Variable ``VARIABLE_<PLACEHOLDER>`` with trailing placeholder and target.
Environment variable ``SOME_ENV_VAR``.
Environment variable ``some env var`` with space and target.
Generator ``Some Generator`` with space.
+Inline literal ``~!@#$%^&*( )_+-=\\[]{}'":;,<>.?/``.
+Inline link Link Text.
+Inline link Link Text <With \-escaped Brackets>.
+Inline literal ``__`` followed by inline link Link Text.
First TOC entry.
diff --git a/Tests/CMakeLib/testRST.rst b/Tests/CMakeLib/testRST.rst
index 9cd7257..c8587c0 100644
--- a/Tests/CMakeLib/testRST.rst
+++ b/Tests/CMakeLib/testRST.rst
@@ -26,6 +26,10 @@ Variable :variable:`VARIABLE_<PLACEHOLDER> <target>` with trailing placeholder a
Environment variable :envvar:`SOME_ENV_VAR`.
Environment variable :envvar:`some env var <SOME_ENV_VAR>` with space and target.
Generator :generator:`Some Generator` with space.
+Inline literal ``~!@#$%^&*( )_+-=\\[]{}'":;,<>.?/``.
+Inline link `Link Text <ExternalDest>`_.
+Inline link `Link Text \<With \\-escaped Brackets\> <ExternalDest>`_.
+Inline literal ``__`` followed by inline link `Link Text <InternalDest_>`_.
.. |not replaced| replace:: not replaced through toctree
.. |not replaced in literal| replace:: replaced in parsed literal
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index ea64646..0e94388 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -145,8 +145,7 @@ if(BUILD_TESTING)
set(CPACK_BINARY_RPM OFF)
endif()
- # Look for rpmbuild to use for tests.
- # The tool does not work with spaces in the path.
+ # Look for dpkg to use for tests.
find_program(DPKG_EXECUTABLE NAMES dpkg)
if(DPKG_EXECUTABLE)
@@ -155,6 +154,15 @@ if(BUILD_TESTING)
set(CPACK_BINARY_DEB OFF)
endif()
+ # Look for NuGet to use for tests.
+ find_program(NUGET_EXECUTABLE NAMES NuGet nuget)
+
+ if(NUGET_EXECUTABLE)
+ set(CPACK_BINARY_NUGET ON)
+ else()
+ set(CPACK_BINARY_NUGET OFF)
+ endif()
+
#---------------------------------------------------------------------------
# Add tests below here.
@@ -1033,6 +1041,12 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
if(CPACK_BINARY_DEB)
list(APPEND ACTIVE_CPACK_GENERATORS DEB)
endif()
+ # Check whether if NuGet command is found
+ # before adding NuGet tests
+ if(CPACK_BINARY_NUGET)
+ list(APPEND ACTIVE_CPACK_GENERATORS NUGET)
+ set(CPACK_GENERATOR_STRING_NUGET NuGet)
+ endif()
# ACTIVE_CPACK_GENERATORS variable
# now contains the list of 'active generators'
@@ -1052,7 +1066,10 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
list(APPEND CWAYLST "IgnoreGroup")
list(APPEND CWAYLST "AllInOne")
foreach(CPackGen IN LISTS ACTIVE_CPACK_GENERATORS)
- set(CPackRun_CPackGen "-DCPackGen=${CPackGen}")
+ if(NOT DEFINED CPACK_GENERATOR_STRING_${CPackGen})
+ set(CPACK_GENERATOR_STRING_${CPackGen} ${CPackGen})
+ endif()
+ set(CPackRun_CPackGen "-DCPackGen=${CPACK_GENERATOR_STRING_${CPackGen}}")
foreach(CPackComponentWay ${CWAYLST})
set(CPackRun_CPackComponentWay "-DCPackComponentWay=${CPackComponentWay}")
add_test(CPackComponentsForAll-${CPackGen}-${CPackComponentWay}
@@ -1063,7 +1080,7 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
${build_generator_args}
--build-project CPackComponentsForAll
--build-options ${build_options}
- -DCPACK_GENERATOR:STRING=${CPackGen}
+ -DCPACK_GENERATOR:STRING=${CPACK_GENERATOR_STRING_${CPackGen}}
-DCPACK_BINARY_${CPackGen}:BOOL=ON
${CPackRun_CPackComponentWay}
${CPackComponentsForAll_BUILD_OPTIONS}
@@ -1421,6 +1438,10 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
add_subdirectory(FindLTTngUST)
endif()
+ if(CMake_TEST_FindODBC)
+ add_subdirectory(FindODBC)
+ endif()
+
if(CMake_TEST_FindOpenCL)
add_subdirectory(FindOpenCL)
endif()
diff --git a/Tests/CPackComponentsForAll/CMakeLists.txt b/Tests/CPackComponentsForAll/CMakeLists.txt
index 3440843..f2e4fcd 100644
--- a/Tests/CPackComponentsForAll/CMakeLists.txt
+++ b/Tests/CPackComponentsForAll/CMakeLists.txt
@@ -168,6 +168,18 @@ set(CPACK_RPM_RELOCATION_PATHS "${CMAKE_INSTALL_INCLUDEDIR}"
# set CPACK_DEBIAN_FILE_NAME to use default package name format
set(CPACK_DEBIAN_FILE_NAME "DEB-DEFAULT")
+# set some tags for NuGet packages
+# 1. all in one pacakge
+set(CPACK_NUGET_PACKAGE_TAGS "nuget" "unit" "test" "all-in-one")
+# 2. per component packages
+set(CPACK_NUGET_APPLICATIONS_PACKAGE_TAGS "nuget" "unit" "test" "applications")
+set(CPACK_NUGET_LIBRARIES_PACKAGE_TAGS "nuget" "unit" "test" "libraries")
+set(CPACK_NUGET_HEADERS_PACKAGE_TAGS "nuget" "unit" "test" "headers")
+set(CPACK_NUGET_UNSPECIFIED_PACKAGE_TAGS "nuget" "unit" "test" "uNsP3c1FiEd")
+# 3. per group packages
+set(CPACK_NUGET_RUNTIME_PACKAGE_TAGS "nuget" "unit" "test" "run-time")
+set(CPACK_NUGET_DEVELOPMENT_PACKAGE_TAGS "nuget" "unit" "test" "development")
+
# We may use the CPack specific config file in order
# to tailor CPack behavior on a CPack generator specific way
# (Behavior would be different for RPM or TGZ or DEB ...)
diff --git a/Tests/CPackComponentsForAll/MyLibCPackConfig-AllInOne.cmake.in b/Tests/CPackComponentsForAll/MyLibCPackConfig-AllInOne.cmake.in
index 0bfbf14..1b9e658 100644
--- a/Tests/CPackComponentsForAll/MyLibCPackConfig-AllInOne.cmake.in
+++ b/Tests/CPackComponentsForAll/MyLibCPackConfig-AllInOne.cmake.in
@@ -13,6 +13,10 @@ if(CPACK_GENERATOR MATCHES "DEB")
set(CPACK_DEB_COMPONENT_INSTALL "ON")
endif()
+if(CPACK_GENERATOR MATCHES "NuGet")
+ set(CPACK_NUGET_COMPONENT_INSTALL "ON")
+endif()
+
#
# Choose grouping way
#
diff --git a/Tests/CPackComponentsForAll/MyLibCPackConfig-IgnoreGroup.cmake.in b/Tests/CPackComponentsForAll/MyLibCPackConfig-IgnoreGroup.cmake.in
index 0ffe44d..a6f6ea9 100644
--- a/Tests/CPackComponentsForAll/MyLibCPackConfig-IgnoreGroup.cmake.in
+++ b/Tests/CPackComponentsForAll/MyLibCPackConfig-IgnoreGroup.cmake.in
@@ -52,6 +52,10 @@ if(CPACK_GENERATOR MATCHES "DEB")
set(CPACK_DEB_COMPONENT_INSTALL "ON")
endif()
+if(CPACK_GENERATOR MATCHES "NuGet")
+ set(CPACK_NUGET_COMPONENT_INSTALL "ON")
+endif()
+
#
# Choose grouping way
#
diff --git a/Tests/CPackComponentsForAll/MyLibCPackConfig-OnePackPerGroup.cmake.in b/Tests/CPackComponentsForAll/MyLibCPackConfig-OnePackPerGroup.cmake.in
index ac65dc9..d41225d 100644
--- a/Tests/CPackComponentsForAll/MyLibCPackConfig-OnePackPerGroup.cmake.in
+++ b/Tests/CPackComponentsForAll/MyLibCPackConfig-OnePackPerGroup.cmake.in
@@ -18,6 +18,10 @@ if(CPACK_GENERATOR MATCHES "DragNDrop")
set(CPACK_COMPONENTS_GROUPING "ONE_PER_GROUP")
endif()
+if(CPACK_GENERATOR MATCHES "NuGet")
+ set(CPACK_NUGET_COMPONENT_INSTALL "ON")
+endif()
+
#
# Choose grouping way
#
diff --git a/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake b/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake
index 2c3a849..253d128 100644
--- a/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake
+++ b/Tests/CPackComponentsForAll/RunCPackVerifyResult.cmake
@@ -38,57 +38,69 @@ set(config_verbose )
if(CPackGen MATCHES "ZIP")
set(expected_file_mask "${CPackComponentsForAll_BINARY_DIR}/MyLib-*.zip")
- if (${CPackComponentWay} STREQUAL "default")
+ if(${CPackComponentWay} STREQUAL "default")
set(expected_count 1)
- elseif (${CPackComponentWay} STREQUAL "OnePackPerGroup")
+ elseif(${CPackComponentWay} STREQUAL "OnePackPerGroup")
set(expected_count 3)
- elseif (${CPackComponentWay} STREQUAL "IgnoreGroup")
+ elseif(${CPackComponentWay} STREQUAL "IgnoreGroup")
set(expected_count 4)
- elseif (${CPackComponentWay} STREQUAL "AllInOne")
+ elseif(${CPackComponentWay} STREQUAL "AllInOne")
set(expected_count 1)
- endif ()
-elseif (CPackGen MATCHES "RPM")
+ endif()
+elseif(CPackGen MATCHES "RPM")
set(config_verbose -D "CPACK_RPM_PACKAGE_DEBUG=1")
set(expected_file_mask "${CPackComponentsForAll_BINARY_DIR}/MyLib-*.rpm")
- if (${CPackComponentWay} STREQUAL "default")
+ if(${CPackComponentWay} STREQUAL "default")
set(expected_count 1)
- elseif (${CPackComponentWay} STREQUAL "OnePackPerGroup")
+ elseif(${CPackComponentWay} STREQUAL "OnePackPerGroup")
set(expected_count 3)
- elseif (${CPackComponentWay} STREQUAL "IgnoreGroup")
+ elseif(${CPackComponentWay} STREQUAL "IgnoreGroup")
set(expected_count 4)
- elseif (${CPackComponentWay} STREQUAL "AllInOne")
+ elseif(${CPackComponentWay} STREQUAL "AllInOne")
set(expected_count 1)
- endif ()
-elseif (CPackGen MATCHES "DEB")
+ endif()
+elseif(CPackGen MATCHES "DEB")
set(expected_file_mask "${CPackComponentsForAll_BINARY_DIR}/mylib*_1.0.2_*.deb")
- if (${CPackComponentWay} STREQUAL "default")
+ if(${CPackComponentWay} STREQUAL "default")
set(expected_count 1)
- elseif (${CPackComponentWay} STREQUAL "OnePackPerGroup")
+ elseif(${CPackComponentWay} STREQUAL "OnePackPerGroup")
set(expected_count 3)
- elseif (${CPackComponentWay} STREQUAL "IgnoreGroup")
+ elseif(${CPackComponentWay} STREQUAL "IgnoreGroup")
set(expected_count 4)
- elseif (${CPackComponentWay} STREQUAL "AllInOne")
+ elseif(${CPackComponentWay} STREQUAL "AllInOne")
set(expected_count 1)
- endif ()
+ endif()
+elseif(CPackGen MATCHES "NuGet")
+ set(config_verbose -D "CPACK_NUGET_PACKAGE_DEBUG=1")
+ set(expected_file_mask "${CPackComponentsForAll_BINARY_DIR}/MyLib*1.0.2.nupkg")
+ if(${CPackComponentWay} STREQUAL "default")
+ set(expected_count 1)
+ elseif(${CPackComponentWay} STREQUAL "OnePackPerGroup")
+ set(expected_count 3)
+ elseif(${CPackComponentWay} STREQUAL "IgnoreGroup")
+ set(expected_count 4)
+ elseif(${CPackComponentWay} STREQUAL "AllInOne")
+ set(expected_count 1)
+ endif()
endif()
if(CPackGen MATCHES "DragNDrop")
set(expected_file_mask "${CPackComponentsForAll_BINARY_DIR}/MyLib-*.dmg")
- if (${CPackComponentWay} STREQUAL "default")
+ if(${CPackComponentWay} STREQUAL "default")
set(expected_count 1)
- elseif (${CPackComponentWay} STREQUAL "OnePackPerGroup")
+ elseif(${CPackComponentWay} STREQUAL "OnePackPerGroup")
set(expected_count 3)
- elseif (${CPackComponentWay} STREQUAL "IgnoreGroup")
+ elseif(${CPackComponentWay} STREQUAL "IgnoreGroup")
set(expected_count 4)
- elseif (${CPackComponentWay} STREQUAL "AllInOne")
+ elseif(${CPackComponentWay} STREQUAL "AllInOne")
set(expected_count 1)
- endif ()
+ endif()
endif()
# clean-up previously CPack generated files
if(expected_file_mask)
file(GLOB expected_file "${expected_file_mask}")
- if (expected_file)
+ if(expected_file)
file(REMOVE ${expected_file})
endif()
endif()
@@ -101,7 +113,7 @@ execute_process(COMMAND ${CMAKE_CPACK_COMMAND} ${config_verbose} -G ${CPackGen}
ERROR_VARIABLE CPack_error
WORKING_DIRECTORY ${CPackComponentsForAll_BINARY_DIR})
-if (CPack_result)
+if(CPack_result)
message(FATAL_ERROR "error: CPack execution went wrong!, CPack_output=${CPack_output}, CPack_error=${CPack_error}")
else ()
message(STATUS "CPack_output=${CPack_output}")
diff --git a/Tests/FindDoxygen/AllTarget/CMakeLists.txt b/Tests/FindDoxygen/AllTarget/CMakeLists.txt
new file mode 100644
index 0000000..69aa518
--- /dev/null
+++ b/Tests/FindDoxygen/AllTarget/CMakeLists.txt
@@ -0,0 +1,42 @@
+cmake_minimum_required(VERSION 3.10)
+project(TestFindDoxygen VERSION 1.0 LANGUAGES NONE)
+enable_testing()
+
+find_package(Doxygen REQUIRED)
+
+file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/main.cpp [[
+/**
+ * \file
+ * \brief One C++ file w/ sample Doxygen comment just to produce any docs...
+ */
+]])
+
+set(DOXYGEN_OUTPUT_DIRECTORY outDirWithout)
+file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/${DOXYGEN_OUTPUT_DIRECTORY})
+doxygen_add_docs(docsNoAll ${CMAKE_CURRENT_BINARY_DIR}/main.cpp)
+
+set(DOXYGEN_OUTPUT_DIRECTORY outDirWith)
+file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/${DOXYGEN_OUTPUT_DIRECTORY})
+doxygen_add_docs(docsWithAll ALL ${CMAKE_CURRENT_BINARY_DIR}/main.cpp)
+
+# Define tests cases that check whether targets were built
+file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/dirExists.cmake [[
+cmake_minimum_required(VERSION 3.11)
+if(NOT EXISTS ${dirName})
+ message(FATAL_ERROR "Directory does not exist: ${dirName}")
+endif()
+]])
+
+add_test(NAME checkWith COMMAND
+ ${CMAKE_COMMAND}
+ -D dirName=${CMAKE_CURRENT_BINARY_DIR}/outDirWith
+ -P dirExists.cmake
+)
+add_test(NAME checkWithout COMMAND
+ ${CMAKE_COMMAND}
+ -D dirName=${CMAKE_CURRENT_BINARY_DIR}/outDirWithout
+ -P dirExists.cmake
+)
+set_tests_properties(checkWithout PROPERTIES
+ WILL_FAIL TRUE
+)
diff --git a/Tests/FindDoxygen/CMakeLists.txt b/Tests/FindDoxygen/CMakeLists.txt
index 69b9eed..7ce98d5 100644
--- a/Tests/FindDoxygen/CMakeLists.txt
+++ b/Tests/FindDoxygen/CMakeLists.txt
@@ -18,6 +18,16 @@ add_test(NAME FindDoxygen.QuotingTest COMMAND
--build-options ${build_options}
)
+add_test(NAME FindDoxygen.AllTarget COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindDoxygen/AllTarget"
+ "${CMake_BINARY_DIR}/Tests/FindDoxygen/AllTarget"
+ ${build_generator_args}
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+)
+
if(CMake_TEST_FindDoxygen_Dot)
add_test(NAME FindDoxygen.DotComponentTest COMMAND
${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
diff --git a/Tests/FindODBC/CMakeLists.txt b/Tests/FindODBC/CMakeLists.txt
new file mode 100644
index 0000000..6a81090
--- /dev/null
+++ b/Tests/FindODBC/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_test(NAME FindODBC.Test COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindODBC/Test"
+ "${CMake_BINARY_DIR}/Tests/FindODBC/Test"
+ ${build_generator_args}
+ --build-project TestFindODBC
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
diff --git a/Tests/FindODBC/Test/CMakeLists.txt b/Tests/FindODBC/Test/CMakeLists.txt
new file mode 100644
index 0000000..a20c0f7
--- /dev/null
+++ b/Tests/FindODBC/Test/CMakeLists.txt
@@ -0,0 +1,14 @@
+cmake_minimum_required(VERSION 3.1)
+project(TestFindODBC C)
+include(CTest)
+
+find_package(ODBC)
+
+add_executable(test_odbc_tgt main.c)
+target_link_libraries(test_odbc_tgt ODBC::ODBC)
+add_test(NAME test_odbc_tgt COMMAND test_odbc_tgt)
+
+add_executable(test_odbc_var main.c)
+target_include_directories(test_odbc_var PRIVATE ${ODBC_INCLUDE_DIRS})
+target_link_libraries(test_odbc_var PRIVATE ${ODBC_LIBRARIES})
+add_test(NAME test_odbc_var COMMAND test_odbc_var)
diff --git a/Tests/FindODBC/Test/main.c b/Tests/FindODBC/Test/main.c
new file mode 100644
index 0000000..917167b
--- /dev/null
+++ b/Tests/FindODBC/Test/main.c
@@ -0,0 +1,12 @@
+#ifdef WIN32
+#include <windows.h>
+#endif
+#include <sql.h>
+
+int main()
+{
+ SQLHENV env;
+ SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
+ SQLFreeHandle(SQL_HANDLE_ENV, env);
+ return 0;
+}
diff --git a/Tests/PDBDirectoryAndName/CMakeLists.txt b/Tests/PDBDirectoryAndName/CMakeLists.txt
index 2fb894e..6d8d6cc 100644
--- a/Tests/PDBDirectoryAndName/CMakeLists.txt
+++ b/Tests/PDBDirectoryAndName/CMakeLists.txt
@@ -19,7 +19,7 @@ set(my_targets "")
add_library(mylibA SHARED mylibA.c)
set_target_properties(mylibA PROPERTIES
PDB_NAME "mylibA_Special"
- PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mylibA_PDB"
+ PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mylibA_PDB/$<CONFIG>"
)
list(APPEND my_targets mylibA)
@@ -87,7 +87,13 @@ foreach(t ${my_targets})
if(NOT pdb_dir)
set(pdb_dir ${CMAKE_CURRENT_BINARY_DIR})
endif()
- list(APPEND pdbs ${pdb_dir}/${CMAKE_CFG_INTDIR}/${pdb_name}.pdb)
+ if (pdb_dir MATCHES "\\$<.*>")
+ # Skip per-configuration subdirectory if the value contained
+ # a generator expression.
+ list(APPEND pdbs ${pdb_dir}/${pdb_name}.pdb)
+ else()
+ list(APPEND pdbs ${pdb_dir}/${CMAKE_CFG_INTDIR}/${pdb_name}.pdb)
+ endif()
endforeach()
add_custom_target(check_pdbs ALL VERBATIM
COMMAND ${CMAKE_COMMAND} -Dconfig=$<CONFIGURATION> "-Dpdbs=${pdbs}"
diff --git a/Tests/QtAutogen/CommonTests.cmake b/Tests/QtAutogen/CommonTests.cmake
index 094a755..982a296 100644
--- a/Tests/QtAutogen/CommonTests.cmake
+++ b/Tests/QtAutogen/CommonTests.cmake
@@ -1,4 +1,6 @@
# Autogen tests common for Qt4 and Qt5
+ADD_AUTOGEN_TEST(Complex QtAutogen)
+ADD_AUTOGEN_TEST(LowMinimumVersion lowMinimumVersion)
ADD_AUTOGEN_TEST(MocOnly mocOnly)
ADD_AUTOGEN_TEST(MocOptions mocOptions)
ADD_AUTOGEN_TEST(UicOnly uicOnly)
@@ -35,7 +37,6 @@ ADD_AUTOGEN_TEST(Parallel4 parallel4)
ADD_AUTOGEN_TEST(ParallelAUTO parallelAUTO)
ADD_AUTOGEN_TEST(SameName sameName)
ADD_AUTOGEN_TEST(StaticLibraryCycle slc)
-ADD_AUTOGEN_TEST(Complex QtAutogen)
# Rerun tests
ADD_AUTOGEN_TEST(RerunMocBasic)
if(NOT QT_TEST_VERSION STREQUAL 4)
diff --git a/Tests/QtAutogen/LowMinimumVersion/CMakeLists.txt b/Tests/QtAutogen/LowMinimumVersion/CMakeLists.txt
new file mode 100644
index 0000000..a6ac338
--- /dev/null
+++ b/Tests/QtAutogen/LowMinimumVersion/CMakeLists.txt
@@ -0,0 +1,16 @@
+# Use a low minimum version
+cmake_minimum_required(VERSION 3.0)
+project(LowMinimumVersion)
+include("../AutogenTest.cmake")
+
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTOUIC ON)
+set(CMAKE_AUTORCC ON)
+add_executable(lowMinimumVersion
+ main.cpp
+ item.hpp
+ item.cpp
+ view.ui
+ someText.txt
+ example.qrc)
+target_link_libraries(lowMinimumVersion ${QT_QTCORE_TARGET})
diff --git a/Tests/QtAutogen/LowMinimumVersion/example.qrc b/Tests/QtAutogen/LowMinimumVersion/example.qrc
new file mode 100644
index 0000000..551ecc8
--- /dev/null
+++ b/Tests/QtAutogen/LowMinimumVersion/example.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="Example">
+ <file>someText.txt</file>
+ </qresource>
+</RCC>
diff --git a/Tests/QtAutogen/LowMinimumVersion/item.cpp b/Tests/QtAutogen/LowMinimumVersion/item.cpp
new file mode 100644
index 0000000..e2f19b2
--- /dev/null
+++ b/Tests/QtAutogen/LowMinimumVersion/item.cpp
@@ -0,0 +1,19 @@
+#include "item.hpp"
+#include <ui_view.h>
+
+class MocLocal : public QObject
+{
+ Q_OBJECT;
+
+public:
+ MocLocal() = default;
+ ~MocLocal() = default;
+};
+
+void Item::go()
+{
+ Ui_View ui;
+ MocLocal obj;
+}
+
+#include "item.moc"
diff --git a/Tests/QtAutogen/LowMinimumVersion/item.hpp b/Tests/QtAutogen/LowMinimumVersion/item.hpp
new file mode 100644
index 0000000..01255d4
--- /dev/null
+++ b/Tests/QtAutogen/LowMinimumVersion/item.hpp
@@ -0,0 +1,15 @@
+#ifndef ITEM_HPP
+#define ITEM_HPP
+
+#include <QObject>
+
+class Item : public QObject
+{
+ Q_OBJECT
+
+public:
+ Q_SLOT
+ void go();
+};
+
+#endif
diff --git a/Tests/QtAutogen/LowMinimumVersion/main.cpp b/Tests/QtAutogen/LowMinimumVersion/main.cpp
new file mode 100644
index 0000000..9f225a4
--- /dev/null
+++ b/Tests/QtAutogen/LowMinimumVersion/main.cpp
@@ -0,0 +1,10 @@
+#include "item.hpp"
+
+int main(int argc, char* argv[])
+{
+ Q_INIT_RESOURCE(example);
+ Item item;
+ item.go();
+
+ return 0;
+}
diff --git a/Tests/QtAutogen/LowMinimumVersion/someText.txt b/Tests/QtAutogen/LowMinimumVersion/someText.txt
new file mode 100644
index 0000000..750dae3
--- /dev/null
+++ b/Tests/QtAutogen/LowMinimumVersion/someText.txt
@@ -0,0 +1 @@
+Hello world, you're an interesting place.
diff --git a/Tests/QtAutogen/LowMinimumVersion/view.ui b/Tests/QtAutogen/LowMinimumVersion/view.ui
new file mode 100644
index 0000000..2ffe734
--- /dev/null
+++ b/Tests/QtAutogen/LowMinimumVersion/view.ui
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>View</class>
+ <widget class="QWidget" name="Base">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QTreeView" name="treeView"/>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 690c5b4..bb46144 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -152,6 +152,7 @@ add_RunCMake_test(ExternalData)
add_RunCMake_test(FeatureSummary)
add_RunCMake_test(FPHSA)
add_RunCMake_test(FindBoost)
+add_RunCMake_test(FindLua)
add_RunCMake_test(FindOpenGL)
if(NOT CMAKE_C_COMPILER_ID MATCHES "Watcom")
add_RunCMake_test(GenerateExportHeader)
diff --git a/Tests/RunCMake/FindLua/CMakeLists.txt b/Tests/RunCMake/FindLua/CMakeLists.txt
new file mode 100644
index 0000000..a2c4d98
--- /dev/null
+++ b/Tests/RunCMake/FindLua/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.4)
+project(${RunCMake_TEST} C)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/FindLua/FindLuaTest.cmake b/Tests/RunCMake/FindLua/FindLuaTest.cmake
new file mode 100644
index 0000000..610d544
--- /dev/null
+++ b/Tests/RunCMake/FindLua/FindLuaTest.cmake
@@ -0,0 +1,87 @@
+unset(VERSION)
+
+# Ignore all default paths for this test to avoid finding system Lua
+set(CMAKE_INCLUDE_PATH )
+set(CMAKE_PREFIX_PATH )
+set(CMAKE_FRAMEWORK_PATH )
+
+set(ENV{CMAKE_INCLUDE_PATH} )
+set(ENV{CMAKE_PREFIX_PATH} )
+set(ENV{CMAKE_FRAMEWORK_PATH} )
+
+set(ENV{PATH} )
+set(ENV{INCLUDE} )
+
+set(CMAKE_SYSTEM_INCLUDE_PATH )
+set(CMAKE_SYSTEM_PREFIX_PATH )
+set(CMAKE_SYSTEM_FRAMEWORK_PATH )
+
+function(require_found path version)
+ find_package(Lua ${VERSION} QUIET)
+ if(NOT "${LUA_INCLUDE_DIR}" STREQUAL "${path}")
+ message(FATAL_ERROR "LUA_INCLUDE_PATH != path: '${LUA_INCLUDE_DIR}' != '${path}'")
+ endif()
+ if(NOT LUA_VERSION_STRING MATCHES "^${version}\.[0-9]$")
+ message(FATAL_ERROR "Wrong versionfound in '${LUA_INCLUDE_DIR}': ${LUA_VERSION_STRING} != ${version}")
+ endif()
+endfunction()
+
+# Use functions for scoping and better error messages
+function(require_find path version)
+ unset(LUA_INCLUDE_DIR CACHE)
+ require_found(${lua_path} ${version})
+endfunction()
+
+function(test_prefix_path path lua_path version)
+ set(CMAKE_PREFIX_PATH ${path})
+ require_find(lua_path ${version})
+endfunction()
+
+function(test_include_path path lua_path version)
+ set(CMAKE_INCLUDE_PATH ${path})
+ require_find(lua_path ${version})
+endfunction()
+
+function(test_env_path path lua_path version)
+ set(ENV{LUA_DIR} ${path})
+ require_find(lua_path ${version})
+ unset(ENV{LUA_DIR})
+endfunction()
+
+function(test_path prefix_path lua_path version)
+ # Shortcut: Make paths relative to current list dir
+ set(prefix_path ${CMAKE_CURRENT_LIST_DIR}/${prefix_path})
+ set(lua_path ${CMAKE_CURRENT_LIST_DIR}/${lua_path})
+
+ test_prefix_path(${prefix_path} ${lua_path} ${version})
+ test_include_path(${prefix_path}/include ${lua_path} ${version})
+ test_env_path(${prefix_path} ${lua_path} ${version})
+endfunction()
+
+# Simple test
+test_path(prefix1 prefix1/include 5.3)
+# Find highest version
+test_path(prefix2 prefix2/include/lua5.3 5.3)
+foreach(ver 5.3 5.2 5.1)
+ # At least X or X.0 -> Highest
+ set(VERSION "${ver}")
+ test_path(prefix2 prefix2/include/lua5.3 5.3)
+ set(VERSION "${ver}.0")
+ test_path(prefix2 prefix2/include/lua5.3 5.3)
+ # Exactly X/X.0
+ set(VERSION "${ver}" EXACT)
+ test_path(prefix2 prefix2/include/lua${ver} ${ver})
+ set(VERSION "${ver}.0" EXACT)
+ test_path(prefix2 prefix2/include/lua${ver} ${ver})
+endforeach()
+
+# Find unknown version
+set(VERSION "5.9")
+test_path(prefix2 prefix2/include/lua5.9 5.9)
+set(VERSION "5.9" EXACT)
+test_path(prefix2 prefix2/include/lua5.9 5.9)
+
+# Set LUA_INCLUDE_DIR (non-cache) to unsuitable version
+set(LUA_INCLUDE_DIR ${CMAKE_CURRENT_LIST_DIR}/prefix2/include/lua5.2)
+set(VERSION "5.1" EXACT)
+test_path(prefix2 prefix2/include/lua5.1 5.1)
diff --git a/Tests/RunCMake/FindLua/RunCMakeTest.cmake b/Tests/RunCMake/FindLua/RunCMakeTest.cmake
new file mode 100644
index 0000000..3f18033
--- /dev/null
+++ b/Tests/RunCMake/FindLua/RunCMakeTest.cmake
@@ -0,0 +1,3 @@
+include(RunCMake)
+
+run_cmake(FindLuaTest)
diff --git a/Tests/RunCMake/FindLua/prefix1/include/lua.h b/Tests/RunCMake/FindLua/prefix1/include/lua.h
new file mode 100644
index 0000000..d33434a
--- /dev/null
+++ b/Tests/RunCMake/FindLua/prefix1/include/lua.h
@@ -0,0 +1,8 @@
+
+#define LUA_VERSION_MAJOR "5"
+#define LUA_VERSION_MINOR "3"
+#define LUA_VERSION_NUM 503
+#define LUA_VERSION_RELEASE "4"
+
+#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
+#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE
diff --git a/Tests/RunCMake/FindLua/prefix2/include/lua5.1/lua.h b/Tests/RunCMake/FindLua/prefix2/include/lua5.1/lua.h
new file mode 100644
index 0000000..661e62c
--- /dev/null
+++ b/Tests/RunCMake/FindLua/prefix2/include/lua5.1/lua.h
@@ -0,0 +1,8 @@
+
+#define LUA_VERSION_MAJOR "5"
+#define LUA_VERSION_MINOR "1"
+#define LUA_VERSION_NUM 501
+#define LUA_VERSION_RELEASE "4"
+
+#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
+#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE
diff --git a/Tests/RunCMake/FindLua/prefix2/include/lua5.2/lua.h b/Tests/RunCMake/FindLua/prefix2/include/lua5.2/lua.h
new file mode 100644
index 0000000..d53f326
--- /dev/null
+++ b/Tests/RunCMake/FindLua/prefix2/include/lua5.2/lua.h
@@ -0,0 +1,8 @@
+
+#define LUA_VERSION_MAJOR "5"
+#define LUA_VERSION_MINOR "2"
+#define LUA_VERSION_NUM 502
+#define LUA_VERSION_RELEASE "4"
+
+#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
+#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE
diff --git a/Tests/RunCMake/FindLua/prefix2/include/lua5.3/lua.h b/Tests/RunCMake/FindLua/prefix2/include/lua5.3/lua.h
new file mode 100644
index 0000000..d33434a
--- /dev/null
+++ b/Tests/RunCMake/FindLua/prefix2/include/lua5.3/lua.h
@@ -0,0 +1,8 @@
+
+#define LUA_VERSION_MAJOR "5"
+#define LUA_VERSION_MINOR "3"
+#define LUA_VERSION_NUM 503
+#define LUA_VERSION_RELEASE "4"
+
+#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
+#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE
diff --git a/Tests/RunCMake/FindLua/prefix2/include/lua5.9/lua.h b/Tests/RunCMake/FindLua/prefix2/include/lua5.9/lua.h
new file mode 100644
index 0000000..730f7cc
--- /dev/null
+++ b/Tests/RunCMake/FindLua/prefix2/include/lua5.9/lua.h
@@ -0,0 +1,8 @@
+
+#define LUA_VERSION_MAJOR "5"
+#define LUA_VERSION_MINOR "9"
+#define LUA_VERSION_NUM 509
+#define LUA_VERSION_RELEASE "4"
+
+#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
+#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE
diff --git a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_IMPORTED_TARGET.cmake b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_IMPORTED_TARGET.cmake
index 606b1df..1150568 100644
--- a/Tests/RunCMake/FindPkgConfig/FindPkgConfig_IMPORTED_TARGET.cmake
+++ b/Tests/RunCMake/FindPkgConfig/FindPkgConfig_IMPORTED_TARGET.cmake
@@ -85,3 +85,15 @@ pkg_check_modules(FakePackage2 REQUIRED QUIET IMPORTED_TARGET cmakeinternalfakep
if (NOT TARGET PkgConfig::FakePackage2)
message(FATAL_ERROR "No import target for fake package 2 with prefix path")
endif()
+
+# check that the full library path is also returned
+if (NOT FakePackage2_LINK_LIBRARIES STREQUAL "${fakePkgDir}/lib/libcmakeinternalfakepackage2.a")
+ message(FATAL_ERROR "FakePackage2_LINK_LIBRARIES has bad content on first run: ${FakePackage2_LINK_LIBRARIES}")
+endif()
+
+# the information in *_LINK_LIBRARIES is not cached, so ensure is also is present on second run
+unset(FakePackage2_LINK_LIBRARIES)
+pkg_check_modules(FakePackage2 REQUIRED QUIET IMPORTED_TARGET cmakeinternalfakepackage2)
+if (NOT FakePackage2_LINK_LIBRARIES STREQUAL "${fakePkgDir}/lib/libcmakeinternalfakepackage2.a")
+ message(FATAL_ERROR "FakePackage2_LINK_LIBRARIES has bad content on second run: ${FakePackage2_LINK_LIBRARIES}")
+endif()
diff --git a/Tests/RunCMake/VS10Project/VsCSharpCustomTags-stderr.txt b/Tests/RunCMake/VS10Project/VsCSharpCustomTags-stderr.txt
new file mode 100644
index 0000000..1ea3b51
--- /dev/null
+++ b/Tests/RunCMake/VS10Project/VsCSharpCustomTags-stderr.txt
@@ -0,0 +1,3 @@
+^CMake Deprecation Warning in CMakeLists.txt:
+ The C# target "foo" is of type STATIC_LIBRARY. This is discouraged \(and
+ may be disabled in future\). Make it a SHARED library instead.$
diff --git a/Tests/RunCMake/VS10Project/VsCSharpReferenceProps-stderr.txt b/Tests/RunCMake/VS10Project/VsCSharpReferenceProps-stderr.txt
new file mode 100644
index 0000000..4402b8f
--- /dev/null
+++ b/Tests/RunCMake/VS10Project/VsCSharpReferenceProps-stderr.txt
@@ -0,0 +1,8 @@
+^CMake Deprecation Warning in CMakeLists.txt:
+ The C# target "foo2" is of type STATIC_LIBRARY. This is discouraged \(and
+ may be disabled in future\). Make it a SHARED library instead.
+
+
+CMake Deprecation Warning in CMakeLists.txt:
+ The C# target "foo" is of type STATIC_LIBRARY. This is discouraged \(and
+ may be disabled in future\). Make it a SHARED library instead.$
diff --git a/Tests/RunCMake/add_custom_target/CommandExpandsEmpty.cmake b/Tests/RunCMake/add_custom_target/CommandExpandsEmpty.cmake
new file mode 100644
index 0000000..bc899a4
--- /dev/null
+++ b/Tests/RunCMake/add_custom_target/CommandExpandsEmpty.cmake
@@ -0,0 +1 @@
+add_custom_target(EmptyCustom COMMAND "" COMMAND_EXPAND_LISTS)
diff --git a/Tests/RunCMake/add_custom_target/RunCMakeTest.cmake b/Tests/RunCMake/add_custom_target/RunCMakeTest.cmake
index 6c4e91b..2caed03 100644
--- a/Tests/RunCMake/add_custom_target/RunCMakeTest.cmake
+++ b/Tests/RunCMake/add_custom_target/RunCMakeTest.cmake
@@ -1,5 +1,6 @@
include(RunCMake)
+run_cmake(CommandExpandsEmpty)
run_cmake(NoArguments)
run_cmake(BadTargetName)
run_cmake(ByproductsNoCommand)
diff --git a/Tests/RunCMake/alias_targets/imported-target-stderr.txt b/Tests/RunCMake/alias_targets/imported-target-stderr.txt
index 12ffbc2..465de03 100644
--- a/Tests/RunCMake/alias_targets/imported-target-stderr.txt
+++ b/Tests/RunCMake/alias_targets/imported-target-stderr.txt
@@ -3,7 +3,13 @@
\"test-exe\" is imported but not globally visible.
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)
-
-
++
'alias-test-exe' does not exist![?]
+*
+CMake Error at imported-target.cmake:[0-9]+ \(add_library\):
+ add_library cannot create ALIAS target "alias-test-lib" because target
+ "test-lib" is imported but not globally visible.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
++
'alias-test-lib' does not exist![?]$
diff --git a/Tests/RunCMake/ctest_start/AppendDifferentModel-check.cmake b/Tests/RunCMake/ctest_start/AppendDifferentModel-check.cmake
new file mode 100644
index 0000000..d71b1cf
--- /dev/null
+++ b/Tests/RunCMake/ctest_start/AppendDifferentModel-check.cmake
@@ -0,0 +1 @@
+check_tag_contents("^19551112-2204\nContinuousTrack\nContinuous\n$")
diff --git a/Tests/RunCMake/ctest_start/AppendDifferentModel-stderr.txt b/Tests/RunCMake/ctest_start/AppendDifferentModel-stderr.txt
new file mode 100644
index 0000000..a523f3f
--- /dev/null
+++ b/Tests/RunCMake/ctest_start/AppendDifferentModel-stderr.txt
@@ -0,0 +1 @@
+^Model given in TAG does not match model given in ctest_start\(\)$
diff --git a/Tests/RunCMake/ctest_start/AppendDifferentModel-stdout.txt b/Tests/RunCMake/ctest_start/AppendDifferentModel-stdout.txt
new file mode 100644
index 0000000..bc9a4c8
--- /dev/null
+++ b/Tests/RunCMake/ctest_start/AppendDifferentModel-stdout.txt
@@ -0,0 +1,8 @@
+Run dashboard with model Experimental
+ Source directory: .*/Tests/RunCMake/ctest_start/AppendDifferentModel
+ Build directory: .*/Tests/RunCMake/ctest_start/AppendDifferentModel-build
+ Reading ctest configuration file: .*/Tests/RunCMake/ctest_start/AppendDifferentModel/CTestConfig.cmake
+ Site: test-site
+ Build name: test-build-name
+ Use existing tag: 19551112-2204 - ContinuousTrack
+ Use ContinuousTrack tag: [0-9-]+
diff --git a/Tests/RunCMake/ctest_start/AppendDifferentTrack-stderr.txt b/Tests/RunCMake/ctest_start/AppendDifferentTrack-stderr.txt
new file mode 100644
index 0000000..0d6d19d
--- /dev/null
+++ b/Tests/RunCMake/ctest_start/AppendDifferentTrack-stderr.txt
@@ -0,0 +1 @@
+^Track given in TAG does not match track given in ctest_start\(\)$
diff --git a/Tests/RunCMake/ctest_start/AppendDifferentTrack-stdout.txt b/Tests/RunCMake/ctest_start/AppendDifferentTrack-stdout.txt
new file mode 100644
index 0000000..ab1c1f7
--- /dev/null
+++ b/Tests/RunCMake/ctest_start/AppendDifferentTrack-stdout.txt
@@ -0,0 +1,9 @@
+Run dashboard with to-be-determined model
+ Source directory: .*/Tests/RunCMake/ctest_start/AppendDifferentTrack
+ Build directory: .*/Tests/RunCMake/ctest_start/AppendDifferentTrack-build
+ Track: ExperimentalDifferent
+ Reading ctest configuration file: .*/Tests/RunCMake/ctest_start/AppendDifferentTrack/CTestConfig.cmake
+ Site: test-site
+ Build name: test-build-name
+ Use existing tag: 19551112-2204 - ExperimentalDifferent
+ Use ExperimentalDifferent tag: [0-9-]+
diff --git a/Tests/RunCMake/ctest_start/AppendNoMatchingTrack-stdout.txt b/Tests/RunCMake/ctest_start/AppendNoMatchingTrack-stdout.txt
new file mode 100644
index 0000000..55f2d8e
--- /dev/null
+++ b/Tests/RunCMake/ctest_start/AppendNoMatchingTrack-stdout.txt
@@ -0,0 +1,8 @@
+Run dashboard with model Continuous
+ Source directory: .*/Tests/RunCMake/ctest_start/AppendNoMatchingTrack
+ Build directory: .*/Tests/RunCMake/ctest_start/AppendNoMatchingTrack-build
+ Reading ctest configuration file: .*/Tests/RunCMake/ctest_start/AppendNoMatchingTrack/CTestConfig.cmake
+ Site: test-site
+ Build name: test-build-name
+ Use existing tag: 19551112-2204 - SomeWeirdTrackName
+ Use SomeWeirdTrackName tag: [0-9-]+
diff --git a/Tests/RunCMake/ctest_start/AppendNoModel-check.cmake b/Tests/RunCMake/ctest_start/AppendNoModel-check.cmake
new file mode 100644
index 0000000..d71b1cf
--- /dev/null
+++ b/Tests/RunCMake/ctest_start/AppendNoModel-check.cmake
@@ -0,0 +1 @@
+check_tag_contents("^19551112-2204\nContinuousTrack\nContinuous\n$")
diff --git a/Tests/RunCMake/ctest_start/AppendNoModel-stdout.txt b/Tests/RunCMake/ctest_start/AppendNoModel-stdout.txt
new file mode 100644
index 0000000..f909a44
--- /dev/null
+++ b/Tests/RunCMake/ctest_start/AppendNoModel-stdout.txt
@@ -0,0 +1,8 @@
+Run dashboard with to-be-determined model
+ Source directory: .*/Tests/RunCMake/ctest_start/AppendNoModel
+ Build directory: .*/Tests/RunCMake/ctest_start/AppendNoModel-build
+ Reading ctest configuration file: .*/Tests/RunCMake/ctest_start/AppendNoModel/CTestConfig.cmake
+ Site: test-site
+ Build name: test-build-name
+ Use existing tag: 19551112-2204 - ContinuousTrack
+ Use ContinuousTrack tag: [0-9-]+
diff --git a/Tests/RunCMake/ctest_start/AppendOldContinuous-stdout.txt b/Tests/RunCMake/ctest_start/AppendOldContinuous-stdout.txt
new file mode 100644
index 0000000..0660f5d
--- /dev/null
+++ b/Tests/RunCMake/ctest_start/AppendOldContinuous-stdout.txt
@@ -0,0 +1,8 @@
+Run dashboard with model Continuous
+ Source directory: .*/Tests/RunCMake/ctest_start/AppendOldContinuous
+ Build directory: .*/Tests/RunCMake/ctest_start/AppendOldContinuous-build
+ Reading ctest configuration file: .*/Tests/RunCMake/ctest_start/AppendOldContinuous/CTestConfig.cmake
+ Site: test-site
+ Build name: test-build-name
+ Use existing tag: 19551112-2204 - ContinuousTrack
+ Use ContinuousTrack tag: 19551112-2204
diff --git a/Tests/RunCMake/ctest_start/AppendOldNoModel-result.txt b/Tests/RunCMake/ctest_start/AppendOldNoModel-result.txt
new file mode 100644
index 0000000..b57e2de
--- /dev/null
+++ b/Tests/RunCMake/ctest_start/AppendOldNoModel-result.txt
@@ -0,0 +1 @@
+(-1|255)
diff --git a/Tests/RunCMake/ctest_start/AppendOldNoModel-stderr.txt b/Tests/RunCMake/ctest_start/AppendOldNoModel-stderr.txt
new file mode 100644
index 0000000..c7ca1e7
--- /dev/null
+++ b/Tests/RunCMake/ctest_start/AppendOldNoModel-stderr.txt
@@ -0,0 +1,3 @@
+^TAG file does not contain model and no model specified in start command
+CMake Error at .*/Tests/RunCMake/ctest_start/AppendOldNoModel/test.cmake:[0-9]+ \(ctest_start\):
+ ctest_start unknown error.$
diff --git a/Tests/RunCMake/ctest_start/AppendOldNoModel-stdout.txt b/Tests/RunCMake/ctest_start/AppendOldNoModel-stdout.txt
new file mode 100644
index 0000000..0bdf9e4
--- /dev/null
+++ b/Tests/RunCMake/ctest_start/AppendOldNoModel-stdout.txt
@@ -0,0 +1,6 @@
+Run dashboard with to-be-determined model
+ Source directory: .*/Tests/RunCMake/ctest_start/AppendOldNoModel
+ Build directory: .*/Tests/RunCMake/ctest_start/AppendOldNoModel-build
+ Reading ctest configuration file: .*/Tests/RunCMake/ctest_start/AppendOldNoModel/CTestConfig.cmake
+ Site: test-site
+ Build name: test-build-name
diff --git a/Tests/RunCMake/ctest_start/AppendSameModel-check.cmake b/Tests/RunCMake/ctest_start/AppendSameModel-check.cmake
new file mode 100644
index 0000000..d71b1cf
--- /dev/null
+++ b/Tests/RunCMake/ctest_start/AppendSameModel-check.cmake
@@ -0,0 +1 @@
+check_tag_contents("^19551112-2204\nContinuousTrack\nContinuous\n$")
diff --git a/Tests/RunCMake/ctest_start/AppendSameModel-stdout.txt b/Tests/RunCMake/ctest_start/AppendSameModel-stdout.txt
new file mode 100644
index 0000000..4f43626
--- /dev/null
+++ b/Tests/RunCMake/ctest_start/AppendSameModel-stdout.txt
@@ -0,0 +1,8 @@
+Run dashboard with model Continuous
+ Source directory: .*/Tests/RunCMake/ctest_start/AppendSameModel
+ Build directory: .*/Tests/RunCMake/ctest_start/AppendSameModel-build
+ Reading ctest configuration file: .*/Tests/RunCMake/ctest_start/AppendSameModel/CTestConfig.cmake
+ Site: test-site
+ Build name: test-build-name
+ Use existing tag: 19551112-2204 - ContinuousTrack
+ Use ContinuousTrack tag: [0-9-]+
diff --git a/Tests/RunCMake/ctest_start/MissingTrackArg-result.txt b/Tests/RunCMake/ctest_start/MissingTrackArg-result.txt
new file mode 100644
index 0000000..b57e2de
--- /dev/null
+++ b/Tests/RunCMake/ctest_start/MissingTrackArg-result.txt
@@ -0,0 +1 @@
+(-1|255)
diff --git a/Tests/RunCMake/ctest_start/MissingTrackArg-stderr.txt b/Tests/RunCMake/ctest_start/MissingTrackArg-stderr.txt
new file mode 100644
index 0000000..7b42bc9
--- /dev/null
+++ b/Tests/RunCMake/ctest_start/MissingTrackArg-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error at .*/Tests/RunCMake/ctest_start/MissingTrackArg/test\.cmake:[0-9]+ \(ctest_start\):
+ ctest_start TRACK argument missing track name$
diff --git a/Tests/RunCMake/ctest_start/MissingTrackArgAppend-result.txt b/Tests/RunCMake/ctest_start/MissingTrackArgAppend-result.txt
new file mode 100644
index 0000000..b57e2de
--- /dev/null
+++ b/Tests/RunCMake/ctest_start/MissingTrackArgAppend-result.txt
@@ -0,0 +1 @@
+(-1|255)
diff --git a/Tests/RunCMake/ctest_start/MissingTrackArgAppend-stderr.txt b/Tests/RunCMake/ctest_start/MissingTrackArgAppend-stderr.txt
new file mode 100644
index 0000000..695bfad
--- /dev/null
+++ b/Tests/RunCMake/ctest_start/MissingTrackArgAppend-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error at .*/Tests/RunCMake/ctest_start/MissingTrackArgAppend/test\.cmake:[0-9]+ \(ctest_start\):
+ ctest_start TRACK argument missing track name$
diff --git a/Tests/RunCMake/ctest_start/MissingTrackArgQuiet-result.txt b/Tests/RunCMake/ctest_start/MissingTrackArgQuiet-result.txt
new file mode 100644
index 0000000..b57e2de
--- /dev/null
+++ b/Tests/RunCMake/ctest_start/MissingTrackArgQuiet-result.txt
@@ -0,0 +1 @@
+(-1|255)
diff --git a/Tests/RunCMake/ctest_start/MissingTrackArgQuiet-stderr.txt b/Tests/RunCMake/ctest_start/MissingTrackArgQuiet-stderr.txt
new file mode 100644
index 0000000..9438522
--- /dev/null
+++ b/Tests/RunCMake/ctest_start/MissingTrackArgQuiet-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error at .*/Tests/RunCMake/ctest_start/MissingTrackArgQuiet/test\.cmake:[0-9]+ \(ctest_start\):
+ ctest_start TRACK argument missing track name$
diff --git a/Tests/RunCMake/ctest_start/NoModel-result.txt b/Tests/RunCMake/ctest_start/NoModel-result.txt
new file mode 100644
index 0000000..b57e2de
--- /dev/null
+++ b/Tests/RunCMake/ctest_start/NoModel-result.txt
@@ -0,0 +1 @@
+(-1|255)
diff --git a/Tests/RunCMake/ctest_start/NoModel-stderr.txt b/Tests/RunCMake/ctest_start/NoModel-stderr.txt
new file mode 100644
index 0000000..a516cf8
--- /dev/null
+++ b/Tests/RunCMake/ctest_start/NoModel-stderr.txt
@@ -0,0 +1,3 @@
+^CMake Error at .*/Tests/RunCMake/ctest_start/NoModel/test\.cmake:[0-9]+ \(ctest_start\):
+ ctest_start no test model specified and APPEND not specified. Specify
+ either a test model or the APPEND argument$
diff --git a/Tests/RunCMake/ctest_start/RunCMakeTest.cmake b/Tests/RunCMake/ctest_start/RunCMakeTest.cmake
index bf47256..2e8aa75 100644
--- a/Tests/RunCMake/ctest_start/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ctest_start/RunCMakeTest.cmake
@@ -7,11 +7,40 @@ function(run_ctest_start CASE_NAME)
run_ctest(${CASE_NAME})
endfunction()
-run_ctest_start(StartQuiet Experimental QUIET)
+function(check_tag_contents EXPECTED)
+ set(_tag_file "${RunCMake_BINARY_DIR}/${CASE_NAME}-build/Testing/TAG")
+ if(EXISTS "${_tag_file}")
+ file(READ "${_tag_file}" _tag_contents)
+ if(NOT _tag_contents MATCHES "${EXPECTED}")
+ set(RunCMake_TEST_FAILED "Testing/TAG file does not match expected value.\nActual TAG file:\n${_tag_contents}\nExpected TAG file:\n${EXPECTED}\n" PARENT_SCOPE)
+ endif()
+ else()
+ set(RunCMake_TEST_FAILED "Testing/TAG file does not exist." PARENT_SCOPE)
+ endif()
+endfunction()
+run_ctest_start(StartQuiet Experimental QUIET)
run_ctest_start(ConfigInSource Experimental)
-
run_ctest_start(FunctionScope Experimental QUIET)
+run_ctest_start(WriteModelToTagExperimental Experimental QUIET)
+run_ctest_start(WriteModelToTagContinuous Continuous QUIET)
+run_ctest_start(WriteModelToTagNightly Nightly QUIET)
+run_ctest_start(WriteModelToTagNoMatchingTrack Continuous TRACK SomeWeirdTrackName QUIET)
+run_ctest_start(AppendSameModel Continuous APPEND)
+run_ctest_start(AppendDifferentModel Experimental APPEND)
+run_ctest_start(AppendNoModel APPEND)
+run_ctest_start(AppendDifferentTrack TRACK ExperimentalDifferent APPEND)
+run_ctest_start(AppendNoMatchingTrack Continuous APPEND)
+run_ctest_start(AppendOldContinuous Continuous APPEND)
+run_ctest_start(AppendOldNoModel APPEND)
+run_ctest_start(NoModel QUIET)
+run_ctest_start(MissingTrackArg Experimental TRACK)
+run_ctest_start(MissingTrackArgAppend Experimental TRACK APPEND)
+run_ctest_start(MissingTrackArgQuiet Experimental TRACK QUIET)
+run_ctest_start(TooManyArgs Experimental
+ ${RunCMake_BINARY_DIR}/TooManyArgs-build
+ ${RunCMake_BINARY_DIR}/TooManyArgs-build
+ ${RunCMake_BINARY_DIR}/TooManyArgs-build)
function(run_ConfigInBuild)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/ConfigInBuild-build)
diff --git a/Tests/RunCMake/ctest_start/TooManyArgs-result.txt b/Tests/RunCMake/ctest_start/TooManyArgs-result.txt
new file mode 100644
index 0000000..b57e2de
--- /dev/null
+++ b/Tests/RunCMake/ctest_start/TooManyArgs-result.txt
@@ -0,0 +1 @@
+(-1|255)
diff --git a/Tests/RunCMake/ctest_start/TooManyArgs-stderr.txt b/Tests/RunCMake/ctest_start/TooManyArgs-stderr.txt
new file mode 100644
index 0000000..c1d5f22
--- /dev/null
+++ b/Tests/RunCMake/ctest_start/TooManyArgs-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error at .*/Tests/RunCMake/ctest_start/TooManyArgs/test\.cmake:[0-9]+ \(ctest_start\):
+ ctest_start Too many arguments$
diff --git a/Tests/RunCMake/ctest_start/WriteModelToTagContinuous-check.cmake b/Tests/RunCMake/ctest_start/WriteModelToTagContinuous-check.cmake
new file mode 100644
index 0000000..4e67bf5
--- /dev/null
+++ b/Tests/RunCMake/ctest_start/WriteModelToTagContinuous-check.cmake
@@ -0,0 +1 @@
+check_tag_contents("^[0-9-]+\nContinuous\nContinuous\n$")
diff --git a/Tests/RunCMake/ctest_start/WriteModelToTagExperimental-check.cmake b/Tests/RunCMake/ctest_start/WriteModelToTagExperimental-check.cmake
new file mode 100644
index 0000000..b5bf2cf
--- /dev/null
+++ b/Tests/RunCMake/ctest_start/WriteModelToTagExperimental-check.cmake
@@ -0,0 +1 @@
+check_tag_contents("^[0-9-]+\nExperimental\nExperimental\n$")
diff --git a/Tests/RunCMake/ctest_start/WriteModelToTagNightly-check.cmake b/Tests/RunCMake/ctest_start/WriteModelToTagNightly-check.cmake
new file mode 100644
index 0000000..35d0566
--- /dev/null
+++ b/Tests/RunCMake/ctest_start/WriteModelToTagNightly-check.cmake
@@ -0,0 +1 @@
+check_tag_contents("^[0-9-]+\nNightly\nNightly\n$")
diff --git a/Tests/RunCMake/ctest_start/WriteModelToTagNoMatchingTrack-check.cmake b/Tests/RunCMake/ctest_start/WriteModelToTagNoMatchingTrack-check.cmake
new file mode 100644
index 0000000..bd2862d
--- /dev/null
+++ b/Tests/RunCMake/ctest_start/WriteModelToTagNoMatchingTrack-check.cmake
@@ -0,0 +1 @@
+check_tag_contents("^[0-9-]+\nSomeWeirdTrackName\nContinuous\n$")
diff --git a/Tests/RunCMake/ctest_start/test.cmake.in b/Tests/RunCMake/ctest_start/test.cmake.in
index 0a27942..172baf7 100644
--- a/Tests/RunCMake/ctest_start/test.cmake.in
+++ b/Tests/RunCMake/ctest_start/test.cmake.in
@@ -8,11 +8,23 @@ set(CTEST_CMAKE_GENERATOR "@RunCMake_GENERATOR@")
set(CTEST_CMAKE_GENERATOR_PLATFORM "@RunCMake_GENERATOR_PLATFORM@")
set(CTEST_CMAKE_GENERATOR_TOOLSET "@RunCMake_GENERATOR_TOOLSET@")
set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}")
+set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC")
function(setup_tests)
ctest_start(${ctest_start_args})
endfunction()
+if("@CASE_NAME@" MATCHES "^Append")
+ if("@CASE_NAME@" MATCHES "^AppendNoMatchingTrack$")
+ file(WRITE "${CTEST_BINARY_DIRECTORY}/Testing/TAG" "19551112-2204\nSomeWeirdTrackName\n")
+ else()
+ file(WRITE "${CTEST_BINARY_DIRECTORY}/Testing/TAG" "19551112-2204\nContinuousTrack\n")
+ endif()
+ if(NOT "@CASE_NAME@" MATCHES "^AppendOld")
+ file(APPEND "${CTEST_BINARY_DIRECTORY}/Testing/TAG" "Continuous\n")
+ endif()
+endif()
+
set(ctest_start_args "@CASE_CTEST_START_ARGS@")
if("@CASE_NAME@" STREQUAL "FunctionScope")
setup_tests()
diff --git a/Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake b/Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake
index 97b0888..d61fa5f 100644
--- a/Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake
+++ b/Tests/RunCMake/target_link_libraries/RunCMakeTest.cmake
@@ -8,7 +8,10 @@ run_cmake(ImportedTarget)
run_cmake(ImportedTargetFailure)
run_cmake(MixedSignature)
run_cmake(Separate-PRIVATE-LINK_PRIVATE-uses)
+run_cmake(SubDirImportedTarget)
run_cmake(SubDirTarget)
+run_cmake(SubDirTarget-UNKNOWN-IMPORTED)
+run_cmake(SubDirTarget-UNKNOWN-IMPORTED-GLOBAL)
run_cmake(SharedDepNotTarget)
run_cmake(StaticPrivateDepNotExported)
run_cmake(StaticPrivateDepNotTarget)
diff --git a/Tests/RunCMake/target_link_libraries/SubDirImportedTarget-stdout.txt b/Tests/RunCMake/target_link_libraries/SubDirImportedTarget-stdout.txt
new file mode 100644
index 0000000..a7ef260
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries/SubDirImportedTarget-stdout.txt
@@ -0,0 +1,4 @@
+-- mainexeUnknownImportedGlobal: mainlib;sublib
+-- mainlibUnknownImportedGlobal: mainlib;sublib
+-- subexeUnknownImportedGlobal: mainlib;sublib
+-- sublibUnknownImportedGlobal: mainlib;sublib
diff --git a/Tests/RunCMake/target_link_libraries/SubDirImportedTarget.cmake b/Tests/RunCMake/target_link_libraries/SubDirImportedTarget.cmake
new file mode 100644
index 0000000..738280b
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries/SubDirImportedTarget.cmake
@@ -0,0 +1,17 @@
+enable_language(C)
+
+add_executable(mainexeUnknownImportedGlobal IMPORTED GLOBAL)
+add_library(mainlibUnknownImportedGlobal UNKNOWN IMPORTED GLOBAL)
+add_library(mainlib empty.c)
+
+add_subdirectory(SubDirImportedTarget)
+
+target_link_libraries(subexeUnknownImportedGlobal INTERFACE mainlib)
+target_link_libraries(subexeUnknownImportedGlobal INTERFACE sublib)
+get_property(subexeUnknownImportedGlobal_libs TARGET subexeUnknownImportedGlobal PROPERTY INTERFACE_LINK_LIBRARIES)
+message(STATUS "subexeUnknownImportedGlobal: ${subexeUnknownImportedGlobal_libs}")
+
+target_link_libraries(sublibUnknownImportedGlobal INTERFACE mainlib)
+target_link_libraries(sublibUnknownImportedGlobal INTERFACE sublib)
+get_property(sublibUnknownImportedGlobal_libs TARGET sublibUnknownImportedGlobal PROPERTY INTERFACE_LINK_LIBRARIES)
+message(STATUS "sublibUnknownImportedGlobal: ${sublibUnknownImportedGlobal_libs}")
diff --git a/Tests/RunCMake/target_link_libraries/SubDirImportedTarget/CMakeLists.txt b/Tests/RunCMake/target_link_libraries/SubDirImportedTarget/CMakeLists.txt
new file mode 100644
index 0000000..d67a01c
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries/SubDirImportedTarget/CMakeLists.txt
@@ -0,0 +1,13 @@
+add_executable(subexeUnknownImportedGlobal IMPORTED GLOBAL)
+add_library(sublibUnknownImportedGlobal UNKNOWN IMPORTED GLOBAL)
+add_library(sublib ../empty.c)
+
+target_link_libraries(mainexeUnknownImportedGlobal INTERFACE mainlib)
+target_link_libraries(mainexeUnknownImportedGlobal INTERFACE sublib)
+get_property(mainexeUnknownImportedGlobal_libs TARGET mainexeUnknownImportedGlobal PROPERTY INTERFACE_LINK_LIBRARIES)
+message(STATUS "mainexeUnknownImportedGlobal: ${mainexeUnknownImportedGlobal_libs}")
+
+target_link_libraries(mainlibUnknownImportedGlobal INTERFACE mainlib)
+target_link_libraries(mainlibUnknownImportedGlobal INTERFACE sublib)
+get_property(mainlibUnknownImportedGlobal_libs TARGET mainlibUnknownImportedGlobal PROPERTY INTERFACE_LINK_LIBRARIES)
+message(STATUS "mainlibUnknownImportedGlobal: ${mainlibUnknownImportedGlobal_libs}")
diff --git a/Tests/RunCMake/target_link_libraries/SubDirTarget-UNKNOWN-IMPORTED-GLOBAL-stdout.txt b/Tests/RunCMake/target_link_libraries/SubDirTarget-UNKNOWN-IMPORTED-GLOBAL-stdout.txt
new file mode 100644
index 0000000..a8c77cb
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries/SubDirTarget-UNKNOWN-IMPORTED-GLOBAL-stdout.txt
@@ -0,0 +1,2 @@
+-- mainexe: mainlibUnknownImportedGlobal;sublibUnknownImportedGlobal
+-- subexe: mainlibUnknownImportedGlobal;sublibUnknownImportedGlobal
diff --git a/Tests/RunCMake/target_link_libraries/SubDirTarget-UNKNOWN-IMPORTED-GLOBAL.cmake b/Tests/RunCMake/target_link_libraries/SubDirTarget-UNKNOWN-IMPORTED-GLOBAL.cmake
new file mode 100644
index 0000000..04d64e6
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries/SubDirTarget-UNKNOWN-IMPORTED-GLOBAL.cmake
@@ -0,0 +1,11 @@
+enable_language(C)
+
+add_executable(mainexe empty.c)
+add_library(mainlibUnknownImportedGlobal UNKNOWN IMPORTED GLOBAL)
+
+add_subdirectory(SubDirTarget-UNKNOWN-IMPORTED-GLOBAL)
+
+target_link_libraries(subexe mainlibUnknownImportedGlobal)
+target_link_libraries(subexe sublibUnknownImportedGlobal)
+get_property(subexe_libs TARGET subexe PROPERTY INTERFACE_LINK_LIBRARIES)
+message(STATUS "subexe: ${subexe_libs}")
diff --git a/Tests/RunCMake/target_link_libraries/SubDirTarget-UNKNOWN-IMPORTED-GLOBAL/CMakeLists.txt b/Tests/RunCMake/target_link_libraries/SubDirTarget-UNKNOWN-IMPORTED-GLOBAL/CMakeLists.txt
new file mode 100644
index 0000000..6c0c8b2
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries/SubDirTarget-UNKNOWN-IMPORTED-GLOBAL/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_executable(subexe ../empty.c)
+add_library(sublibUnknownImportedGlobal UNKNOWN IMPORTED GLOBAL)
+
+target_link_libraries(mainexe mainlibUnknownImportedGlobal)
+target_link_libraries(mainexe sublibUnknownImportedGlobal)
+get_property(mainexe_libs TARGET mainexe PROPERTY INTERFACE_LINK_LIBRARIES)
+message(STATUS "mainexe: ${mainexe_libs}")
diff --git a/Tests/RunCMake/target_link_libraries/SubDirTarget-UNKNOWN-IMPORTED-stdout.txt b/Tests/RunCMake/target_link_libraries/SubDirTarget-UNKNOWN-IMPORTED-stdout.txt
new file mode 100644
index 0000000..4980dc9
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries/SubDirTarget-UNKNOWN-IMPORTED-stdout.txt
@@ -0,0 +1,2 @@
+-- mainexe: mainlibUnknownImported;sublibUnknownImported
+-- subexe: mainlibUnknownImported;sublibUnknownImported
diff --git a/Tests/RunCMake/target_link_libraries/SubDirTarget-UNKNOWN-IMPORTED.cmake b/Tests/RunCMake/target_link_libraries/SubDirTarget-UNKNOWN-IMPORTED.cmake
new file mode 100644
index 0000000..e476a3f
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries/SubDirTarget-UNKNOWN-IMPORTED.cmake
@@ -0,0 +1,11 @@
+enable_language(C)
+
+add_executable(mainexe empty.c)
+add_library(mainlibUnknownImported UNKNOWN IMPORTED)
+
+add_subdirectory(SubDirTarget-UNKNOWN-IMPORTED)
+
+target_link_libraries(subexe mainlibUnknownImported)
+target_link_libraries(subexe sublibUnknownImported)
+get_property(subexe_libs TARGET subexe PROPERTY INTERFACE_LINK_LIBRARIES)
+message(STATUS "subexe: ${subexe_libs}")
diff --git a/Tests/RunCMake/target_link_libraries/SubDirTarget-UNKNOWN-IMPORTED/CMakeLists.txt b/Tests/RunCMake/target_link_libraries/SubDirTarget-UNKNOWN-IMPORTED/CMakeLists.txt
new file mode 100644
index 0000000..4a40a68
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries/SubDirTarget-UNKNOWN-IMPORTED/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_executable(subexe ../empty.c)
+add_library(sublibUnknownImported UNKNOWN IMPORTED)
+
+target_link_libraries(mainexe mainlibUnknownImported)
+target_link_libraries(mainexe sublibUnknownImported)
+get_property(mainexe_libs TARGET mainexe PROPERTY INTERFACE_LINK_LIBRARIES)
+message(STATUS "mainexe: ${mainexe_libs}")
diff --git a/Tests/RunCMake/target_link_libraries/SubDirTarget-result.txt b/Tests/RunCMake/target_link_libraries/SubDirTarget-result.txt
deleted file mode 100644
index d00491f..0000000
--- a/Tests/RunCMake/target_link_libraries/SubDirTarget-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/Tests/RunCMake/target_link_libraries/SubDirTarget-stderr.txt b/Tests/RunCMake/target_link_libraries/SubDirTarget-stderr.txt
deleted file mode 100644
index 5cd1f23..0000000
--- a/Tests/RunCMake/target_link_libraries/SubDirTarget-stderr.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-^CMake Error at SubDirTarget.cmake:[0-9]+ \(target_link_libraries\):
- Attempt to add link library "m" to target "subexe" which is not built in
- this directory.
-Call Stack \(most recent call first\):
- CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/target_link_libraries/SubDirTarget-stdout.txt b/Tests/RunCMake/target_link_libraries/SubDirTarget-stdout.txt
new file mode 100644
index 0000000..646f984
--- /dev/null
+++ b/Tests/RunCMake/target_link_libraries/SubDirTarget-stdout.txt
@@ -0,0 +1,2 @@
+-- mainexe: mainlib;sublib
+-- subexe: mainlib;sublib
diff --git a/Tests/RunCMake/target_link_libraries/SubDirTarget.cmake b/Tests/RunCMake/target_link_libraries/SubDirTarget.cmake
index 32431ce..55c658d 100644
--- a/Tests/RunCMake/target_link_libraries/SubDirTarget.cmake
+++ b/Tests/RunCMake/target_link_libraries/SubDirTarget.cmake
@@ -1,3 +1,11 @@
enable_language(C)
+
+add_executable(mainexe empty.c)
+add_library(mainlib empty.c)
+
add_subdirectory(SubDirTarget)
-target_link_libraries(subexe m)
+
+target_link_libraries(subexe mainlib)
+target_link_libraries(subexe sublib)
+get_property(subexe_libs TARGET subexe PROPERTY INTERFACE_LINK_LIBRARIES)
+message(STATUS "subexe: ${subexe_libs}")
diff --git a/Tests/RunCMake/target_link_libraries/SubDirTarget/CMakeLists.txt b/Tests/RunCMake/target_link_libraries/SubDirTarget/CMakeLists.txt
index b0b2380..3d956a8 100644
--- a/Tests/RunCMake/target_link_libraries/SubDirTarget/CMakeLists.txt
+++ b/Tests/RunCMake/target_link_libraries/SubDirTarget/CMakeLists.txt
@@ -1 +1,7 @@
add_executable(subexe ../empty.c)
+add_library(sublib ../empty.c)
+
+target_link_libraries(mainexe mainlib)
+target_link_libraries(mainexe sublib)
+get_property(mainexe_libs TARGET mainexe PROPERTY INTERFACE_LINK_LIBRARIES)
+message(STATUS "mainexe: ${mainexe_libs}")
diff --git a/Utilities/Scripts/clang-format.bash b/Utilities/Scripts/clang-format.bash
index 3b331a1..4c6225d 100755
--- a/Utilities/Scripts/clang-format.bash
+++ b/Utilities/Scripts/clang-format.bash
@@ -78,8 +78,8 @@ test "$#" = 0 || die "$usage"
# Find a default tool.
tools='
- clang-format
clang-format-3.8
+ clang-format
'
if test "x$clang_format" = "x"; then
for tool in $tools; do
@@ -96,6 +96,11 @@ if ! type -p "$clang_format" >/dev/null; then
exit 1
fi
+if ! "$clang_format" --version | grep 'clang-format version 3\.8' >/dev/null 2>/dev/null; then
+ echo "clang-format version 3.8 is required (exactly)"
+ exit 1
+fi
+
# Select listing mode.
case "$mode" in
'') echo "$usage"; exit 0 ;;
diff --git a/Utilities/Scripts/regenerate-lexers.bash b/Utilities/Scripts/regenerate-lexers.bash
index 22b681f..b09f25b 100755
--- a/Utilities/Scripts/regenerate-lexers.bash
+++ b/Utilities/Scripts/regenerate-lexers.bash
@@ -2,6 +2,11 @@
set -e
+forced=1
+if [[ "${1}" = "make" ]]; then
+ forced=0
+fi
+
pushd "${BASH_SOURCE%/*}/../../Source/LexerParser" > /dev/null
for lexer in \
@@ -10,23 +15,37 @@ for lexer in \
Expr \
Fortran
do
+ cxx_file=cm${lexer}Lexer.cxx
+ h_file=cm${lexer}Lexer.h
+ in_file=cm${lexer}Lexer.in.l
+
+ if [[ (${in_file} -nt ${cxx_file}) || (${in_file} -nt ${h_file}) || (${forced} -gt 0) ]]; then
echo "Generating Lexer ${lexer}"
- flex --nounistd -DFLEXINT_H --noline --header-file=cm${lexer}Lexer.h -ocm${lexer}Lexer.cxx cm${lexer}Lexer.in.l
- sed -i 's/\s*$//' cm${lexer}Lexer.h cm${lexer}Lexer.cxx # remove trailing whitespaces
- sed -i '${/^$/d;}' cm${lexer}Lexer.h cm${lexer}Lexer.cxx # remove blank line at the end
- sed -i '1i#include "cmStandardLexer.h"' cm${lexer}Lexer.cxx # add cmStandardLexer.h include
+ flex --nounistd -DFLEXINT_H --noline --header-file=${h_file} -o${cxx_file} ${in_file}
+ sed -i 's/\s*$//' ${h_file} ${cxx_file} # remove trailing whitespaces
+ sed -i '${/^$/d;}' ${h_file} ${cxx_file} # remove blank line at the end
+ sed -i '1i#include "cmStandardLexer.h"' ${cxx_file} # add cmStandardLexer.h include
+ else
+ echo "Skipped generating Lexer ${lexer}"
+ fi
done
# these lexers (at the moment only the ListFileLexer) are compiled as C and do not generate a header
for lexer in ListFile
do
-
- echo "Generating Lexer ${lexer}"
- flex --nounistd -DFLEXINT_H --noline -ocm${lexer}Lexer.c cm${lexer}Lexer.in.l
- sed -i 's/\s*$//' cm${lexer}Lexer.c # remove trailing whitespaces
- sed -i '${/^$/d;}' cm${lexer}Lexer.c # remove blank line at the end
- sed -i '1i#include "cmStandardLexer.h"' cm${lexer}Lexer.c # add cmStandardLexer.h include
+ c_file=cm${lexer}Lexer.c
+ in_file=cm${lexer}Lexer.in.l
+
+ if [[ (${in_file} -nt ${c_file}) || (${forced} -gt 0) ]]; then
+ echo "Generating Lexer ${lexer}"
+ flex --nounistd -DFLEXINT_H --noline -o${c_file} ${in_file}
+ sed -i 's/\s*$//' ${c_file} # remove trailing whitespaces
+ sed -i '${/^$/d;}' ${c_file} # remove blank line at the end
+ sed -i '1i#include "cmStandardLexer.h"' ${c_file} # add cmStandardLexer.h include
+ else
+ echo "Skipped generating Lexer ${lexer}"
+ fi
done
diff --git a/Utilities/Scripts/regenerate-parsers.bash b/Utilities/Scripts/regenerate-parsers.bash
new file mode 100755
index 0000000..6fb35c0
--- /dev/null
+++ b/Utilities/Scripts/regenerate-parsers.bash
@@ -0,0 +1,37 @@
+#!/usr/bin/env bash
+
+set -e
+
+forced=1
+if [[ "${1}" = "make" ]]; then
+ forced=0
+fi
+
+pushd "${BASH_SOURCE%/*}/../../Source/LexerParser" > /dev/null
+
+for parser in \
+ CommandArgument \
+ DependsJava \
+ Expr \
+ Fortran
+do
+ in_file=cm${parser}Parser.y
+ cxx_file=cm${parser}Parser.cxx
+ h_file=cm${parser}ParserTokens.h
+ prefix=cm${parser}_yy
+
+ if [[ (${in_file} -nt ${cxx_file}) || (${in_file} -nt ${h_file}) || (${forced} -gt 0) ]]; then
+ echo "Generating Parser ${parser}"
+ bison --yacc --name-prefix=${prefix} --defines=${h_file} -o${cxx_file} ${in_file}
+ sed -i '/\/\* Else will try to reuse/ i\
+#if 0
+/^yyerrlab1:/ a\
+#endif
+' ${cxx_file}
+ else
+ echo "Skipped generating Parser ${parser}"
+ fi
+done
+
+
+popd > /dev/null
diff --git a/Utilities/Scripts/update-curl.bash b/Utilities/Scripts/update-curl.bash
index 28803cb..b02180f 100755
--- a/Utilities/Scripts/update-curl.bash
+++ b/Utilities/Scripts/update-curl.bash
@@ -8,7 +8,7 @@ readonly name="curl"
readonly ownership="Curl Upstream <curl-library@cool.haxx.se>"
readonly subtree="Utilities/cmcurl"
readonly repo="https://github.com/curl/curl.git"
-readonly tag="curl-7_58_0"
+readonly tag="curl-7_60_0"
readonly shortlog=false
readonly paths="
CMake/*
diff --git a/Utilities/Sphinx/conf.py.in b/Utilities/Sphinx/conf.py.in
index 7878ad2..f52ccd1 100644
--- a/Utilities/Sphinx/conf.py.in
+++ b/Utilities/Sphinx/conf.py.in
@@ -17,6 +17,7 @@ version = '@conf_version@' # feature version
release = '@conf_release@' # full version string
primary_domain = 'cmake'
+highlight_language = 'none'
exclude_patterns = [
'dev', # ignore developer-only documentation
diff --git a/Utilities/Sphinx/static/cmake.css b/Utilities/Sphinx/static/cmake.css
index 2a326d4..b082ede 100644
--- a/Utilities/Sphinx/static/cmake.css
+++ b/Utilities/Sphinx/static/cmake.css
@@ -6,3 +6,13 @@
div.sphinxsidebarwrapper {
word-wrap: break-word;
}
+
+/* Make links inside parsed-literal blocks more obvious
+ by using a background color and increased line spacing
+ to make them look boxed. */
+.literal-block {
+ line-height: 1.4;
+}
+.literal-block a.reference.internal {
+ background-color: #dfdfdf;
+}
diff --git a/Utilities/cmcurl/CMake/FindBrotli.cmake b/Utilities/cmcurl/CMake/FindBrotli.cmake
new file mode 100644
index 0000000..351b8f7
--- /dev/null
+++ b/Utilities/cmcurl/CMake/FindBrotli.cmake
@@ -0,0 +1,20 @@
+include(FindPackageHandleStandardArgs)
+
+find_path(BROTLI_INCLUDE_DIR "brotli/decode.h")
+
+find_library(BROTLICOMMON_LIBRARY NAMES brotlicommon)
+find_library(BROTLIDEC_LIBRARY NAMES brotlidec)
+
+find_package_handle_standard_args(BROTLI
+ FOUND_VAR
+ BROTLI_FOUND
+ REQUIRED_VARS
+ BROTLIDEC_LIBRARY
+ BROTLICOMMON_LIBRARY
+ BROTLI_INCLUDE_DIR
+ FAIL_MESSAGE
+ "Could NOT find BROTLI"
+)
+
+set(BROTLI_INCLUDE_DIRS ${BROTLI_INCLUDE_DIR})
+set(BROTLI_LIBRARIES ${BROTLICOMMON_LIBRARY} ${BROTLIDEC_LIBRARY})
diff --git a/Utilities/cmcurl/CMakeLists.txt b/Utilities/cmcurl/CMakeLists.txt
index 148ca5d..0128214 100644
--- a/Utilities/cmcurl/CMakeLists.txt
+++ b/Utilities/cmcurl/CMakeLists.txt
@@ -90,7 +90,7 @@ endif()
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -328,16 +328,6 @@ if(BORLAND)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w-")
endif(BORLAND)
-if(CURL_WERROR)
- if(MSVC_VERSION)
- set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /WX")
- set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /WX")
- else()
- # this assumes clang or gcc style options
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
- endif()
-endif(CURL_WERROR)
-
# If we are on AIX, do the _ALL_SOURCE magic
if(${CMAKE_SYSTEM_NAME} MATCHES AIX)
set(_ALL_SOURCE 1)
@@ -398,6 +388,7 @@ 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)
+ list(APPEND CURL_LIBS "advapi32")
endif()
# check SSL libraries
@@ -644,6 +635,18 @@ if(CURL_SPECIAL_LIBZ)
set(HAVE_ZLIB_H 0)
endif()
+option(CURL_BROTLI "Set to ON to enable building curl with brotli support." OFF)
+set(HAVE_BROTLI OFF)
+if(CURL_BROTLI)
+ find_package(BROTLI QUIET)
+ if(BROTLI_FOUND)
+ set(HAVE_BROTLI ON)
+ list(APPEND CURL_LIBS ${BROTLI_LIBRARIES})
+ include_directories(${BROTLI_INCLUDE_DIRS})
+ list(APPEND CMAKE_REQUIRED_INCLUDES ${BROTLI_INCLUDE_DIRS})
+ endif()
+endif()
+
#libSSH2
option(CMAKE_USE_LIBSSH2 "Use libSSH2" ON)
mark_as_advanced(CMAKE_USE_LIBSSH2)
@@ -1237,6 +1240,15 @@ if(MSVC)
endif(CMAKE_C_FLAGS MATCHES "/W[0-4]")
endif(MSVC)
+if(CURL_WERROR)
+ if(MSVC_VERSION)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX")
+ else()
+ # this assumes clang or gcc style options
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
+ endif()
+endif(CURL_WERROR)
+
# 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)
diff --git a/Utilities/cmcurl/include/curl/curl.h b/Utilities/cmcurl/include/curl/curl.h
index a96124d..10e5c49 100644
--- a/Utilities/cmcurl/include/curl/curl.h
+++ b/Utilities/cmcurl/include/curl/curl.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -245,7 +245,9 @@ typedef size_t (*curl_write_callback)(char *buffer,
size_t nitems,
void *outstream);
-
+/* This callback will be called when a new resolver request is made */
+typedef int (*curl_resolver_start_callback)(void *resolver_state,
+ void *reserved, void *userdata);
/* enumeration of file types */
typedef enum {
@@ -577,6 +579,8 @@ typedef enum {
CURLE_SSL_INVALIDCERTSTATUS, /* 91 - invalid certificate status */
CURLE_HTTP2_STREAM, /* 92 - stream error in HTTP/2 framing layer
*/
+ CURLE_RECURSIVE_API_CALL, /* 93 - an api function was called from
+ inside a callback */
CURL_LAST /* never use! */
} CURLcode;
@@ -789,6 +793,11 @@ typedef enum {
SSL backends where such behavior is present. */
#define CURLSSLOPT_NO_REVOKE (1<<1)
+/* The default connection attempt delay in milliseconds for happy eyeballs.
+ CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 and happy-eyeballs-timeout-ms.d document
+ this value, keep them in sync. */
+#define CURL_HET_DEFAULT 200L
+
#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
the obsolete stuff removed! */
@@ -1662,7 +1671,7 @@ typedef enum {
* 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.
+ /* Set the local IPv6 address to use for outgoing DNS requests.
* Only supported by the c-ares DNS backend */
CINIT(DNS_LOCAL_IP6, STRINGPOINT, 223),
@@ -1819,6 +1828,25 @@ typedef enum {
/* Post MIME data. */
CINIT(MIMEPOST, OBJECTPOINT, 269),
+ /* Time to use with the CURLOPT_TIMECONDITION. Specified in number of
+ seconds since 1 Jan 1970. */
+ CINIT(TIMEVALUE_LARGE, OFF_T, 270),
+
+ /* Head start in milliseconds to give happy eyeballs. */
+ CINIT(HAPPY_EYEBALLS_TIMEOUT_MS, LONG, 271),
+
+ /* Function that will be called before a resolver request is made */
+ CINIT(RESOLVER_START_FUNCTION, FUNCTIONPOINT, 272),
+
+ /* User data to pass to the resolver start callback. */
+ CINIT(RESOLVER_START_DATA, OBJECTPOINT, 273),
+
+ /* send HAProxy PROXY protocol header? */
+ CINIT(HAPROXYPROTOCOL, LONG, 274),
+
+ /* shuffle addresses before use when DNS returns multiple */
+ CINIT(DNS_SHUFFLE_ADDRESSES, LONG, 275),
+
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
@@ -2459,6 +2487,7 @@ typedef enum {
CURLINFO_REQUEST_SIZE = CURLINFO_LONG + 12,
CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13,
CURLINFO_FILETIME = CURLINFO_LONG + 14,
+ CURLINFO_FILETIME_T = CURLINFO_OFF_T + 14,
CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE + 15,
CURLINFO_CONTENT_LENGTH_DOWNLOAD_T = CURLINFO_OFF_T + 15,
CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE + 16,
diff --git a/Utilities/cmcurl/include/curl/curlver.h b/Utilities/cmcurl/include/curl/curlver.h
index a47c454..2d1505a 100644
--- a/Utilities/cmcurl/include/curl/curlver.h
+++ b/Utilities/cmcurl/include/curl/curlver.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,16 +26,16 @@
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 - 2017 Daniel Stenberg, <daniel@haxx.se>."
+#define LIBCURL_COPYRIGHT "1996 - 2018 Daniel Stenberg, <daniel@haxx.se>."
/* This is the version number of the libcurl package from which this header
file origins: */
-#define LIBCURL_VERSION "7.58.0"
+#define LIBCURL_VERSION "7.60.0"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
-#define LIBCURL_VERSION_MINOR 58
+#define LIBCURL_VERSION_MINOR 60
#define LIBCURL_VERSION_PATCH 0
/* This is the numeric version of the libcurl version number, meant for easier
@@ -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 0x073A00
+#define LIBCURL_VERSION_NUM 0x073C00
/*
* This is the date and time when the full source package was created. The
diff --git a/Utilities/cmcurl/include/curl/multi.h b/Utilities/cmcurl/include/curl/multi.h
index 911c91d..b19dbaf 100644
--- a/Utilities/cmcurl/include/curl/multi.h
+++ b/Utilities/cmcurl/include/curl/multi.h
@@ -70,6 +70,8 @@ typedef enum {
CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */
CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was
attempted to get added - again */
+ CURLM_RECURSIVE_API_CALL, /* an api function was called from inside a
+ callback */
CURLM_LAST
} CURLMcode;
@@ -184,8 +186,8 @@ CURL_EXTERN CURLMcode curl_multi_wait(CURLM *multi_handle,
*
* Returns: CURLMcode type, general multi error code. *NOTE* that this only
* returns errors etc regarding the whole multi stack. There might
- * still have occurred problems on invidual transfers even when this
- * returns OK.
+ * still have occurred problems on individual transfers even when
+ * this returns OK.
*/
CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle,
int *running_handles);
diff --git a/Utilities/cmcurl/include/curl/system.h b/Utilities/cmcurl/include/curl/system.h
index 07bbd9c..eac4cfe 100644
--- a/Utilities/cmcurl/include/curl/system.h
+++ b/Utilities/cmcurl/include/curl/system.h
@@ -300,7 +300,9 @@
#elif defined(__SUNPRO_C) /* Oracle Solaris Studio */
# if !defined(__LP64) && (defined(__ILP32) || \
- defined(__i386) || defined(__sparcv8))
+ defined(__i386) || \
+ defined(__sparcv8) || \
+ defined(__sparcv8plus))
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
diff --git a/Utilities/cmcurl/include/curl/typecheck-gcc.h b/Utilities/cmcurl/include/curl/typecheck-gcc.h
index 10c74c7..3a0f253 100644
--- a/Utilities/cmcurl/include/curl/typecheck-gcc.h
+++ b/Utilities/cmcurl/include/curl/typecheck-gcc.h
@@ -54,6 +54,9 @@ __extension__ ({ \
if(_curl_is_write_cb_option(_curl_opt)) \
if(!_curl_is_write_cb(value)) \
_curl_easy_setopt_err_write_callback(); \
+ if((_curl_opt) == CURLOPT_RESOLVER_START_FUNCTION) \
+ if(!_curl_is_resolver_start_callback(value)) \
+ _curl_easy_setopt_err_resolver_start_callback(); \
if((_curl_opt) == CURLOPT_READFUNCTION) \
if(!_curl_is_read_cb(value)) \
_curl_easy_setopt_err_read_cb(); \
@@ -170,6 +173,10 @@ _CURL_WARNING(_curl_easy_setopt_err_string,
)
_CURL_WARNING(_curl_easy_setopt_err_write_callback,
"curl_easy_setopt expects a curl_write_callback argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_resolver_start_callback,
+ "curl_easy_setopt expects a "
+ "curl_resolver_start_callback argument for this option"
+ )
_CURL_WARNING(_curl_easy_setopt_err_read_cb,
"curl_easy_setopt expects a curl_read_callback argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_ioctl_cb,
@@ -354,6 +361,7 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_SSH_KEYDATA || \
(option) == CURLOPT_SSL_CTX_DATA || \
(option) == CURLOPT_WRITEDATA || \
+ (option) == CURLOPT_RESOLVER_START_DATA || \
0)
/* evaluates to true if option takes a POST data argument (void* or char*) */
@@ -504,6 +512,11 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
(__builtin_types_compatible_p(__typeof__(func), type) || \
__builtin_types_compatible_p(__typeof__(func) *, type))
+/* evaluates to true if expr is of type curl_resolver_start_callback */
+#define _curl_is_resolver_start_callback(expr) \
+ (_curl_is_NULL(expr) || \
+ _curl_callback_compatible((expr), curl_resolver_start_callback))
+
/* evaluates to true if expr is of type curl_read_callback or "similar" */
#define _curl_is_read_cb(expr) \
(_curl_is_NULL(expr) || \
diff --git a/Utilities/cmcurl/lib/Makefile.inc b/Utilities/cmcurl/lib/Makefile.inc
index 61e80cf..61c2341 100644
--- a/Utilities/cmcurl/lib/Makefile.inc
+++ b/Utilities/cmcurl/lib/Makefile.inc
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, 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,8 +29,8 @@ LIB_VAUTH_HFILES = vauth/vauth.h vauth/digest.h vauth/ntlm.h
LIB_VTLS_CFILES = vtls/openssl.c vtls/gtls.c vtls/vtls.c vtls/nss.c \
vtls/polarssl.c vtls/polarssl_threadlock.c vtls/axtls.c \
- vtls/cyassl.c vtls/schannel.c vtls/darwinssl.c vtls/gskit.c \
- vtls/mbedtls.c
+ vtls/cyassl.c vtls/schannel.c vtls/schannel_verify.c \
+ vtls/darwinssl.c vtls/gskit.c vtls/mbedtls.c
LIB_VTLS_HFILES = vtls/openssl.h vtls/vtls.h vtls/gtls.h \
vtls/nssg.h vtls/polarssl.h vtls/polarssl_threadlock.h vtls/axtls.h \
@@ -46,7 +46,7 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
http_digest.c md4.c md5.c http_negotiate.c inet_pton.c strtoofft.c \
strerror.c amigaos.c hostasyn.c hostip4.c hostip6.c hostsyn.c \
inet_ntop.c parsedate.c select.c tftp.c splay.c strdup.c socks.c \
- ssh.c ssh-libssh.c curl_addrinfo.c socks_gssapi.c socks_sspi.c \
+ ssh.c ssh-libssh.c curl_addrinfo.c socks_gssapi.c socks_sspi.c \
curl_sspi.c slist.c nonblock.c curl_memrchr.c imap.c pop3.c smtp.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 \
@@ -54,7 +54,7 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.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 \
- mime.c sha256.c setopt.c curl_path.c
+ mime.c sha256.c setopt.c curl_path.c curl_ctype.c curl_range.c
LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h if2ip.h \
@@ -74,7 +74,7 @@ LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.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 rand.h mime.h curl_sha256.h setopt.h \
- curl_path.h
+ curl_path.h curl_ctype.h curl_range.h
LIB_RCFILES = libcurl.rc
diff --git a/Utilities/cmcurl/lib/asyn-thread.c b/Utilities/cmcurl/lib/asyn-thread.c
index 1ac3fc8..b11fab2 100644
--- a/Utilities/cmcurl/lib/asyn-thread.c
+++ b/Utilities/cmcurl/lib/asyn-thread.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -79,6 +79,10 @@
#include "curl_memory.h"
#include "memdebug.h"
+struct resdata {
+ struct curltime start;
+};
+
/*
* Curl_resolver_global_init()
* Called from curl_global_init() to initialize global resolver environment.
@@ -102,11 +106,13 @@ void Curl_resolver_global_cleanup(void)
* Curl_resolver_init()
* Called from curl_easy_init() -> Curl_open() to initialize resolver
* URL-state specific environment ('resolver' member of the UrlState
- * structure). Does nothing here.
+ * structure).
*/
CURLcode Curl_resolver_init(void **resolver)
{
- (void)resolver;
+ *resolver = calloc(1, sizeof(struct resdata));
+ if(!*resolver)
+ return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
}
@@ -114,24 +120,22 @@ CURLcode Curl_resolver_init(void **resolver)
* Curl_resolver_cleanup()
* Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver
* URL-state specific environment ('resolver' member of the UrlState
- * structure). Does nothing here.
+ * structure).
*/
void Curl_resolver_cleanup(void *resolver)
{
- (void)resolver;
+ free(resolver);
}
/*
* Curl_resolver_duphandle()
* Called from curl_easy_duphandle() to duplicate resolver URL state-specific
- * environment ('resolver' member of the UrlState structure). Does nothing
- * here.
+ * environment ('resolver' member of the UrlState structure).
*/
int Curl_resolver_duphandle(void **to, void *from)
{
- (void)to;
(void)from;
- return CURLE_OK;
+ return Curl_resolver_init(to);
}
static void destroy_async_data(struct Curl_async *);
@@ -561,9 +565,22 @@ int Curl_resolver_getsock(struct connectdata *conn,
curl_socket_t *socks,
int numsocks)
{
- (void)conn;
+ time_t milli;
+ timediff_t ms;
+ struct Curl_easy *data = conn->data;
+ struct resdata *reslv = (struct resdata *)data->state.resolver;
(void)socks;
(void)numsocks;
+ ms = Curl_timediff(Curl_now(), reslv->start);
+ if(ms < 10)
+ milli = ms/3;
+ else if(ms <= 50)
+ milli = 10;
+ else if(ms <= 250)
+ milli = 50;
+ else
+ milli = 200;
+ Curl_expire(data, milli, EXPIRE_ASYNC_NAME);
return 0;
}
@@ -577,6 +594,8 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
int *waitp)
{
struct in_addr in;
+ struct Curl_easy *data = conn->data;
+ struct resdata *reslv = (struct resdata *)data->state.resolver;
*waitp = 0; /* default to synchronous response */
@@ -584,14 +603,17 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
/* This is a dotted IP address 123.123.123.123-style */
return Curl_ip2addr(AF_INET, &in, hostname, port);
+ reslv->start = Curl_now();
+
/* fire up a new resolver thread! */
if(init_resolve_thread(conn, hostname, port, NULL)) {
*waitp = 1; /* expect asynchronous response */
return NULL;
}
- /* fall-back to blocking version */
- return Curl_ipv4_resolve_r(hostname, port);
+ failf(conn->data, "getaddrinfo() thread failed\n");
+
+ return NULL;
}
#else /* !HAVE_GETADDRINFO */
@@ -605,10 +627,10 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
int *waitp)
{
struct addrinfo hints;
- Curl_addrinfo *res;
- int error;
char sbuf[12];
int pf = PF_INET;
+ struct Curl_easy *data = conn->data;
+ struct resdata *reslv = (struct resdata *)data->state.resolver;
*waitp = 0; /* default to synchronous response */
@@ -658,27 +680,16 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
snprintf(sbuf, sizeof(sbuf), "%d", port);
+ reslv->start = Curl_now();
/* fire up a new resolver thread! */
if(init_resolve_thread(conn, hostname, port, &hints)) {
*waitp = 1; /* expect asynchronous response */
return NULL;
}
- /* fall-back to blocking version */
- infof(conn->data, "init_resolve_thread() failed for %s; %s\n",
- hostname, Curl_strerror(conn, errno));
-
- error = Curl_getaddrinfo_ex(hostname, sbuf, &hints, &res);
- if(error) {
- infof(conn->data, "getaddrinfo() failed for %s:%d; %s\n",
- hostname, port, Curl_strerror(conn, SOCKERRNO));
- return NULL;
- }
- else {
- Curl_addrinfo_set_port(res, port);
- }
+ failf(data, "getaddrinfo() thread failed to start\n");
+ return NULL;
- return res;
}
#endif /* !HAVE_GETADDRINFO */
diff --git a/Utilities/cmcurl/lib/connect.c b/Utilities/cmcurl/lib/connect.c
index 3edb71e..1a27ae1 100644
--- a/Utilities/cmcurl/lib/connect.c
+++ b/Utilities/cmcurl/lib/connect.c
@@ -619,8 +619,8 @@ void Curl_persistconninfo(struct connectdata *conn)
/* retrieves ip address and port from a sockaddr structure.
note it calls Curl_inet_ntop which sets errno on fail, not SOCKERRNO. */
-static bool getaddressinfo(struct sockaddr *sa, char *addr,
- long *port)
+bool Curl_getaddressinfo(struct sockaddr *sa, char *addr,
+ long *port)
{
unsigned short us_port;
struct sockaddr_in *si = NULL;
@@ -700,16 +700,16 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
return;
}
- if(!getaddressinfo((struct sockaddr*)&ssrem,
- conn->primary_ip, &conn->primary_port)) {
+ if(!Curl_getaddressinfo((struct sockaddr*)&ssrem,
+ conn->primary_ip, &conn->primary_port)) {
failf(data, "ssrem inet_ntop() failed with errno %d: %s",
errno, Curl_strerror(conn, errno));
return;
}
memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
- if(!getaddressinfo((struct sockaddr*)&ssloc,
- conn->local_ip, &conn->local_port)) {
+ if(!Curl_getaddressinfo((struct sockaddr*)&ssloc,
+ conn->local_ip, &conn->local_port)) {
failf(data, "ssloc inet_ntop() failed with errno %d: %s",
errno, Curl_strerror(conn, errno));
return;
@@ -783,7 +783,8 @@ CURLcode Curl_is_connected(struct connectdata *conn,
/* should we try another protocol family? */
if(i == 0 && conn->tempaddr[1] == NULL &&
- Curl_timediff(now, conn->connecttime) >= HAPPY_EYEBALLS_TIMEOUT) {
+ (Curl_timediff(now, conn->connecttime) >=
+ data->set.happy_eyeballs_timeout)) {
trynextip(conn, sockindex, 1);
}
}
@@ -1005,8 +1006,8 @@ static CURLcode singleipconnect(struct connectdata *conn,
return CURLE_OK;
/* store remote address and port used in this connection attempt */
- if(!getaddressinfo((struct sockaddr*)&addr.sa_addr,
- ipaddress, &port)) {
+ if(!Curl_getaddressinfo((struct sockaddr*)&addr.sa_addr,
+ ipaddress, &port)) {
/* malformed address or bug in inet_ntop, try next address */
failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
errno, Curl_strerror(conn, errno));
@@ -1033,9 +1034,11 @@ static CURLcode singleipconnect(struct connectdata *conn,
if(data->set.fsockopt) {
/* activate callback for setting socket options */
+ Curl_set_in_callback(data, true);
error = data->set.fsockopt(data->set.sockopt_client,
sockfd,
CURLSOCKTYPE_IPCXN);
+ Curl_set_in_callback(data, false);
if(error == CURL_SOCKOPT_ALREADY_CONNECTED)
isconnected = TRUE;
@@ -1204,7 +1207,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
}
data->info.numconnects++; /* to track the number of connections made */
- Curl_expire(conn->data, HAPPY_EYEBALLS_TIMEOUT, EXPIRE_HAPPY_EYEBALLS);
+ Curl_expire(conn->data, data->set.happy_eyeballs_timeout,
+ EXPIRE_HAPPY_EYEBALLS);
return CURLE_OK;
}
@@ -1311,8 +1315,12 @@ int Curl_closesocket(struct connectdata *conn,
status */
conn->sock_accepted[SECONDARYSOCKET] = FALSE;
else {
+ int rc;
Curl_multi_closed(conn, sock);
- return conn->fclosesocket(conn->closesocket_client, sock);
+ Curl_set_in_callback(conn->data, true);
+ rc = conn->fclosesocket(conn->closesocket_client, sock);
+ Curl_set_in_callback(conn->data, false);
+ return rc;
}
}
@@ -1363,7 +1371,7 @@ CURLcode Curl_socket(struct connectdata *conn,
addr->addrlen = sizeof(struct Curl_sockaddr_storage);
memcpy(&addr->sa_addr, ai->ai_addr, addr->addrlen);
- if(data->set.fopensocket)
+ if(data->set.fopensocket) {
/*
* If the opensocket callback is set, all the destination address
* information is passed to the callback. Depending on this information the
@@ -1373,9 +1381,12 @@ CURLcode Curl_socket(struct connectdata *conn,
* might have been changed and this 'new' address will actually be used
* here to connect.
*/
+ Curl_set_in_callback(data, true);
*sockfd = data->set.fopensocket(data->set.opensocket_client,
CURLSOCKTYPE_IPCXN,
(struct curl_sockaddr *)addr);
+ Curl_set_in_callback(data, false);
+ }
else
/* opensocket callback not set, so simply create the socket now */
*sockfd = socket(addr->family, addr->socktype, addr->protocol);
diff --git a/Utilities/cmcurl/lib/connect.h b/Utilities/cmcurl/lib/connect.h
index 3974486..193dc63 100644
--- a/Utilities/cmcurl/lib/connect.h
+++ b/Utilities/cmcurl/lib/connect.h
@@ -41,8 +41,6 @@ timediff_t Curl_timeleft(struct Curl_easy *data,
bool duringconnect);
#define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */
-#define HAPPY_EYEBALLS_TIMEOUT 200 /* milliseconds to wait between
- IPv4/IPv6 connection attempts */
/*
* Used to extract socket and connectdata struct for the most recent
@@ -78,6 +76,11 @@ void Curl_persistconninfo(struct connectdata *conn);
int Curl_closesocket(struct connectdata *conn, curl_socket_t sock);
/*
+ * Get presentation format IP address and port from a sockaddr.
+ */
+bool Curl_getaddressinfo(struct sockaddr *sa, char *addr, long *port);
+
+/*
* The Curl_sockaddr_ex structure is basically libcurl's external API
* curl_sockaddr structure with enough space available to directly hold any
* protocol-specific address structures. The variable declared here will be
diff --git a/Utilities/cmcurl/lib/content_encoding.c b/Utilities/cmcurl/lib/content_encoding.c
index 46bef0c..7c979ef 100644
--- a/Utilities/cmcurl/lib/content_encoding.c
+++ b/Utilities/cmcurl/lib/content_encoding.c
@@ -726,7 +726,7 @@ static void identity_close_writer(struct connectdata *conn,
static const content_encoding identity_encoding = {
"identity",
- NULL,
+ "none",
identity_init_writer,
identity_unencode_write,
identity_close_writer,
@@ -873,10 +873,9 @@ static contenc_writer *new_unencoding_writer(struct connectdata *conn,
contenc_writer *downstream)
{
size_t sz = offsetof(contenc_writer, params) + handler->paramsize;
- contenc_writer *writer = (contenc_writer *) malloc(sz);
+ contenc_writer *writer = (contenc_writer *) calloc(1, sz);
if(writer) {
- memset(writer, 0, sz);
writer->handler = handler;
writer->downstream = downstream;
if(handler->init_writer(conn, writer)) {
diff --git a/Utilities/cmcurl/lib/cookie.c b/Utilities/cmcurl/lib/cookie.c
index 5f0f145..2c028b3 100644
--- a/Utilities/cmcurl/lib/cookie.c
+++ b/Utilities/cmcurl/lib/cookie.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -143,6 +143,28 @@ static bool tailmatch(const char *cooke_domain, const char *hostname)
}
/*
+ * Return true if the given string is an IP(v4|v6) address.
+ */
+static bool isip(const char *domain)
+{
+ struct in_addr addr;
+#ifdef ENABLE_IPV6
+ struct in6_addr addr6;
+#endif
+
+ if(Curl_inet_pton(AF_INET, domain, &addr)
+#ifdef ENABLE_IPV6
+ || Curl_inet_pton(AF_INET6, domain, &addr6)
+#endif
+ ) {
+ /* domain name given as IP address */
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*
* matching cookie path and url path
* RFC6265 5.1.4 Paths and Path-Match
*/
@@ -218,6 +240,62 @@ pathmatched:
}
/*
+ * Return the top-level domain, for optimal hashing.
+ */
+static const char *get_top_domain(const char * const domain, size_t *outlen)
+{
+ size_t len;
+ const char *first = NULL, *last;
+
+ if(!domain)
+ return NULL;
+
+ len = strlen(domain);
+ last = memrchr(domain, '.', len);
+ if(last) {
+ first = memrchr(domain, '.', (size_t) (last - domain));
+ if(first)
+ len -= (size_t) (++first - domain);
+ }
+
+ if(outlen)
+ *outlen = len;
+
+ return first? first: domain;
+}
+
+/*
+ * A case-insensitive hash for the cookie domains.
+ */
+static size_t cookie_hash_domain(const char *domain, const size_t len)
+{
+ const char *end = domain + len;
+ size_t h = 5381;
+
+ while(domain < end) {
+ h += h << 5;
+ h ^= Curl_raw_toupper(*domain++);
+ }
+
+ return (h % COOKIE_HASH_SIZE);
+}
+
+/*
+ * Hash this domain.
+ */
+static size_t cookiehash(const char * const domain)
+{
+ const char *top;
+ size_t len;
+
+ if(!domain || isip(domain))
+ return 0;
+
+ top = get_top_domain(domain, &len);
+ return cookie_hash_domain(top, len);
+}
+
+/*
* cookie path sanitize
*/
static char *sanitize_cookie_path(const char *cookie_path)
@@ -303,48 +381,29 @@ static void remove_expired(struct CookieInfo *cookies)
{
struct Cookie *co, *nx, *pv;
curl_off_t now = (curl_off_t)time(NULL);
-
- co = cookies->cookies;
- pv = NULL;
- while(co) {
- nx = co->next;
- if(co->expires && co->expires < now) {
- if(!pv) {
- cookies->cookies = co->next;
+ unsigned int i;
+
+ for(i = 0; i < COOKIE_HASH_SIZE; i++) {
+ co = cookies->cookies[i];
+ pv = NULL;
+ while(co) {
+ nx = co->next;
+ if(co->expires && co->expires < now) {
+ if(!pv) {
+ cookies->cookies[i] = co->next;
+ }
+ else {
+ pv->next = co->next;
+ }
+ cookies->numcookies--;
+ freecookie(co);
}
else {
- pv->next = co->next;
+ pv = co;
}
- cookies->numcookies--;
- freecookie(co);
- }
- else {
- pv = co;
+ co = nx;
}
- co = nx;
- }
-}
-
-/*
- * Return true if the given string is an IP(v4|v6) address.
- */
-static bool isip(const char *domain)
-{
- struct in_addr addr;
-#ifdef ENABLE_IPV6
- struct in6_addr addr6;
-#endif
-
- if(Curl_inet_pton(AF_INET, domain, &addr)
-#ifdef ENABLE_IPV6
- || Curl_inet_pton(AF_INET6, domain, &addr6)
-#endif
- ) {
- /* domain name given as IP address */
- return TRUE;
}
-
- return FALSE;
}
/****************************************************************************
@@ -368,6 +427,7 @@ Curl_cookie_add(struct Curl_easy *data,
struct CookieInfo *c,
bool httpheader, /* TRUE if HTTP header-style line */
+ bool noexpire, /* if TRUE, skip remove_expired() */
char *lineptr, /* first character of the line */
const char *domain, /* default domain */
const char *path) /* full path used when this cookie is set,
@@ -380,6 +440,7 @@ Curl_cookie_add(struct Curl_easy *data,
time_t now = time(NULL);
bool replace_old = FALSE;
bool badcookie = FALSE; /* cookies are good by default. mmmmm yummy */
+ size_t myhash;
#ifdef USE_LIBPSL
const psl_ctx_t *psl;
@@ -430,9 +491,6 @@ Curl_cookie_add(struct Curl_easy *data,
size_t nlen = strlen(name);
const char *endofn = &ptr[ nlen ];
- infof(data, "cookie size: name/val %d + %d bytes\n",
- nlen, len);
-
if(nlen >= (MAX_NAME-1) || len >= (MAX_NAME-1) ||
((nlen + len) > MAX_NAME)) {
/* too long individual name or contents, or too long combination of
@@ -470,10 +528,16 @@ Curl_cookie_add(struct Curl_easy *data,
while(*whatptr && ISBLANK(*whatptr))
whatptr++;
- if(!co->name && sep) {
+ if(!co->name) {
/* The very first name/value pair is the actual cookie name */
+ if(!sep) {
+ /* Bad name/value pair. */
+ badcookie = TRUE;
+ break;
+ }
co->name = strdup(name);
co->value = strdup(whatptr);
+ done = TRUE;
if(!co->name || !co->value) {
badcookie = TRUE;
break;
@@ -822,7 +886,8 @@ Curl_cookie_add(struct Curl_easy *data,
the same domain and path as this */
/* at first, remove expired cookies */
- remove_expired(c);
+ if(!noexpire)
+ remove_expired(c);
#ifdef USE_LIBPSL
/* Check if the domain is a Public Suffix and if yes, ignore the cookie.
@@ -839,7 +904,8 @@ Curl_cookie_add(struct Curl_easy *data,
}
#endif
- clist = c->cookies;
+ myhash = cookiehash(co->domain);
+ clist = c->cookies[myhash];
replace_old = FALSE;
while(clist) {
if(strcasecompare(clist->name, co->name)) {
@@ -925,7 +991,7 @@ Curl_cookie_add(struct Curl_easy *data,
if(lastc)
lastc->next = co;
else
- c->cookies = co;
+ c->cookies[myhash] = co;
c->numcookies++; /* one more cookie in the jar */
}
@@ -1029,9 +1095,10 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
while(*lineptr && ISBLANK(*lineptr))
lineptr++;
- Curl_cookie_add(data, c, headerline, lineptr, NULL, NULL);
+ Curl_cookie_add(data, c, headerline, TRUE, lineptr, NULL, NULL);
}
free(line); /* free the line buffer */
+ remove_expired(c); /* run this once, not on every cookie */
if(fromfile)
fclose(fp);
@@ -1137,8 +1204,9 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
struct Cookie *mainco = NULL;
size_t matches = 0;
bool is_ip;
+ const size_t myhash = cookiehash(host);
- if(!c || !c->cookies)
+ if(!c || !c->cookies[myhash])
return NULL; /* no cookie struct or no cookies in the struct */
/* at first, remove expired cookies */
@@ -1147,7 +1215,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
/* check if host is an IP(v4|v6) address */
is_ip = isip(host);
- co = c->cookies;
+ co = c->cookies[myhash];
while(co) {
/* only process this cookie if it is not expired or had no expire
@@ -1235,8 +1303,11 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
void Curl_cookie_clearall(struct CookieInfo *cookies)
{
if(cookies) {
- Curl_cookie_freelist(cookies->cookies);
- cookies->cookies = NULL;
+ unsigned int i;
+ for(i = 0; i < COOKIE_HASH_SIZE; i++) {
+ Curl_cookie_freelist(cookies->cookies[i]);
+ cookies->cookies[i] = NULL;
+ }
cookies->numcookies = 0;
}
}
@@ -1270,31 +1341,37 @@ void Curl_cookie_freelist(struct Cookie *co)
void Curl_cookie_clearsess(struct CookieInfo *cookies)
{
struct Cookie *first, *curr, *next, *prev = NULL;
+ unsigned int i;
- if(!cookies || !cookies->cookies)
+ if(!cookies)
return;
- first = curr = prev = cookies->cookies;
+ for(i = 0; i < COOKIE_HASH_SIZE; i++) {
+ if(!cookies->cookies[i])
+ continue;
- for(; curr; curr = next) {
- next = curr->next;
- if(!curr->expires) {
- if(first == curr)
- first = next;
+ first = curr = prev = cookies->cookies[i];
- if(prev == curr)
- prev = next;
- else
- prev->next = next;
+ for(; curr; curr = next) {
+ next = curr->next;
+ if(!curr->expires) {
+ if(first == curr)
+ first = next;
+
+ if(prev == curr)
+ prev = next;
+ else
+ prev->next = next;
- freecookie(curr);
- cookies->numcookies--;
+ freecookie(curr);
+ cookies->numcookies--;
+ }
+ else
+ prev = curr;
}
- else
- prev = curr;
- }
- cookies->cookies = first;
+ cookies->cookies[i] = first;
+ }
}
@@ -1307,9 +1384,12 @@ void Curl_cookie_clearsess(struct CookieInfo *cookies)
****************************************************************************/
void Curl_cookie_cleanup(struct CookieInfo *c)
{
+ unsigned int i;
+
if(c) {
free(c->filename);
- Curl_cookie_freelist(c->cookies);
+ for(i = 0; i < COOKIE_HASH_SIZE; i++)
+ Curl_cookie_freelist(c->cookies[i]);
free(c); /* free the base struct as well */
}
}
@@ -1358,6 +1438,7 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
FILE *out;
bool use_stdout = FALSE;
char *format_ptr;
+ unsigned int i;
if((NULL == c) || (0 == c->numcookies))
/* If there are no known cookies, we don't write or even create any
@@ -1367,6 +1448,10 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
/* at first, remove expired cookies */
remove_expired(c);
+ /* make sure we still have cookies after expiration */
+ if(0 == c->numcookies)
+ return 0;
+
if(!strcmp("-", dumphere)) {
/* use stdout */
out = stdout;
@@ -1383,18 +1468,20 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
"# This file was generated by libcurl! Edit at your own risk.\n\n",
out);
- for(co = c->cookies; co; co = co->next) {
- if(!co->domain)
- continue;
- format_ptr = get_netscape_format(co);
- if(format_ptr == NULL) {
- fprintf(out, "#\n# Fatal libcurl error\n");
- if(!use_stdout)
- fclose(out);
- return 1;
+ for(i = 0; i < COOKIE_HASH_SIZE; i++) {
+ for(co = c->cookies[i]; co; co = co->next) {
+ if(!co->domain)
+ continue;
+ format_ptr = get_netscape_format(co);
+ if(format_ptr == NULL) {
+ fprintf(out, "#\n# Fatal libcurl error\n");
+ if(!use_stdout)
+ fclose(out);
+ return 1;
+ }
+ fprintf(out, "%s\n", format_ptr);
+ free(format_ptr);
}
- fprintf(out, "%s\n", format_ptr);
- free(format_ptr);
}
if(!use_stdout)
@@ -1409,26 +1496,29 @@ static struct curl_slist *cookie_list(struct Curl_easy *data)
struct curl_slist *beg;
struct Cookie *c;
char *line;
+ unsigned int i;
if((data->cookies == NULL) ||
(data->cookies->numcookies == 0))
return NULL;
- for(c = data->cookies->cookies; c; c = c->next) {
- if(!c->domain)
- continue;
- line = get_netscape_format(c);
- if(!line) {
- curl_slist_free_all(list);
- return NULL;
- }
- beg = Curl_slist_append_nodup(list, line);
- if(!beg) {
- free(line);
- curl_slist_free_all(list);
- return NULL;
+ for(i = 0; i < COOKIE_HASH_SIZE; i++) {
+ for(c = data->cookies->cookies[i]; c; c = c->next) {
+ if(!c->domain)
+ continue;
+ line = get_netscape_format(c);
+ if(!line) {
+ curl_slist_free_all(list);
+ return NULL;
+ }
+ beg = Curl_slist_append_nodup(list, line);
+ if(!beg) {
+ free(line);
+ curl_slist_free_all(list);
+ return NULL;
+ }
+ list = beg;
}
- list = beg;
}
return list;
diff --git a/Utilities/cmcurl/lib/cookie.h b/Utilities/cmcurl/lib/cookie.h
index cb50b71..79b5928 100644
--- a/Utilities/cmcurl/lib/cookie.h
+++ b/Utilities/cmcurl/lib/cookie.h
@@ -45,9 +45,11 @@ struct Cookie {
bool httponly; /* true if the httponly directive is present */
};
+#define COOKIE_HASH_SIZE 256
+
struct CookieInfo {
/* linked list of cookies we know of */
- struct Cookie *cookies;
+ struct Cookie *cookies[COOKIE_HASH_SIZE];
char *filename; /* file we read from/write to */
bool running; /* state info, for cookie adding information */
@@ -67,7 +69,6 @@ struct CookieInfo {
*/
#define MAX_COOKIE_LINE 5000
-#define MAX_COOKIE_LINE_TXT "4999"
/* This is the maximum length of a cookie name or content we deal with: */
#define MAX_NAME 4096
@@ -80,7 +81,8 @@ struct Curl_easy;
*/
struct Cookie *Curl_cookie_add(struct Curl_easy *data,
- struct CookieInfo *, bool header, char *lineptr,
+ struct CookieInfo *, bool header, bool noexpiry,
+ char *lineptr,
const char *domain, const char *path);
struct Cookie *Curl_cookie_getlist(struct CookieInfo *, const char *,
diff --git a/Utilities/cmcurl/lib/curl_addrinfo.c b/Utilities/cmcurl/lib/curl_addrinfo.c
index ec76f75..55d5a39 100644
--- a/Utilities/cmcurl/lib/curl_addrinfo.c
+++ b/Utilities/cmcurl/lib/curl_addrinfo.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, 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,6 +50,10 @@
# define in_addr_t unsigned long
#endif
+#if defined(WIN32) && defined(USE_UNIX_SOCKETS)
+#include <afunix.h>
+#endif
+
#include <stddef.h>
#include "curl_addrinfo.h"
@@ -341,7 +345,7 @@ Curl_he2ai(const struct hostent *he, int port)
addr = (void *)ai->ai_addr; /* storage area for this info */
memcpy(&addr->sin_addr, curr, sizeof(struct in_addr));
- addr->sin_family = (unsigned short)(he->h_addrtype);
+ addr->sin_family = (CURL_SA_FAMILY_T)(he->h_addrtype);
addr->sin_port = htons((unsigned short)port);
break;
@@ -350,7 +354,7 @@ Curl_he2ai(const struct hostent *he, int port)
addr6 = (void *)ai->ai_addr; /* storage area for this info */
memcpy(&addr6->sin6_addr, curr, sizeof(struct in6_addr));
- addr6->sin6_family = (unsigned short)(he->h_addrtype);
+ addr6->sin6_family = (CURL_SA_FAMILY_T)(he->h_addrtype);
addr6->sin6_port = htons((unsigned short)port);
break;
#endif
diff --git a/Utilities/cmcurl/lib/curl_config.h.cmake b/Utilities/cmcurl/lib/curl_config.h.cmake
index 1d1e3d7..24d1ca0 100644
--- a/Utilities/cmcurl/lib/curl_config.h.cmake
+++ b/Utilities/cmcurl/lib/curl_config.h.cmake
@@ -389,6 +389,9 @@
/* if zlib is available */
#cmakedefine HAVE_LIBZ 1
+/* if brotli is available */
+#cmakedefine HAVE_BROTLI 1
+
/* if your compiler supports LL */
#cmakedefine HAVE_LL 1
diff --git a/Utilities/cmcurl/lib/curl_ctype.c b/Utilities/cmcurl/lib/curl_ctype.c
new file mode 100644
index 0000000..1a47fb5
--- /dev/null
+++ b/Utilities/cmcurl/lib/curl_ctype.c
@@ -0,0 +1,133 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, 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_DOES_CONVERSIONS
+
+#undef _U
+#define _U (1<<0) /* upper case */
+#undef _L
+#define _L (1<<1) /* lower case */
+#undef _N
+#define _N (1<<2) /* decimal numerical digit */
+#undef _S
+#define _S (1<<3) /* space */
+#undef _P
+#define _P (1<<4) /* punctuation */
+#undef _C
+#define _C (1<<5) /* control */
+#undef _X
+#define _X (1<<6) /* hexadecimal letter */
+#undef _B
+#define _B (1<<7) /* blank */
+
+static const unsigned char ascii[128] = {
+ _C, _C, _C, _C, _C, _C, _C, _C,
+ _C, _C|_S, _C|_S, _C|_S, _C|_S, _C|_S, _C, _C,
+ _C, _C, _C, _C, _C, _C, _C, _C,
+ _C, _C, _C, _C, _C, _C, _C, _C,
+ _S|_B, _P, _P, _P, _P, _P, _P, _P,
+ _P, _P, _P, _P, _P, _P, _P, _P,
+ _N, _N, _N, _N, _N, _N, _N, _N,
+ _N, _N, _P, _P, _P, _P, _P, _P,
+ _P, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U,
+ _U, _U, _U, _U, _U, _U, _U, _U,
+ _U, _U, _U, _U, _U, _U, _U, _U,
+ _U, _U, _U, _P, _P, _P, _P, _P,
+ _P, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L,
+ _L, _L, _L, _L, _L, _L, _L, _L,
+ _L, _L, _L, _L, _L, _L, _L, _L,
+ _L, _L, _L, _P, _P, _P, _P, _C
+};
+
+int Curl_isspace(int c)
+{
+ if((c < 0) || (c >= 0x80))
+ return FALSE;
+ return (ascii[c] & _S);
+}
+
+int Curl_isdigit(int c)
+{
+ if((c < 0) || (c >= 0x80))
+ return FALSE;
+ return (ascii[c] & _N);
+}
+
+int Curl_isalnum(int c)
+{
+ if((c < 0) || (c >= 0x80))
+ return FALSE;
+ return (ascii[c] & (_N|_U|_L));
+}
+
+int Curl_isxdigit(int c)
+{
+ if((c < 0) || (c >= 0x80))
+ return FALSE;
+ return (ascii[c] & (_N|_X));
+}
+
+int Curl_isgraph(int c)
+{
+ if((c < 0) || (c >= 0x80) || (c == ' '))
+ return FALSE;
+ return (ascii[c] & (_N|_X|_U|_L|_P|_S));
+}
+
+int Curl_isprint(int c)
+{
+ if((c < 0) || (c >= 0x80))
+ return FALSE;
+ return (ascii[c] & (_N|_X|_U|_L|_P|_S));
+}
+
+int Curl_isalpha(int c)
+{
+ if((c < 0) || (c >= 0x80))
+ return FALSE;
+ return (ascii[c] & (_U|_L));
+}
+
+int Curl_isupper(int c)
+{
+ if((c < 0) || (c >= 0x80))
+ return FALSE;
+ return (ascii[c] & (_U));
+}
+
+int Curl_islower(int c)
+{
+ if((c < 0) || (c >= 0x80))
+ return FALSE;
+ return (ascii[c] & (_L));
+}
+
+int Curl_iscntrl(int c)
+{
+ if((c < 0) || (c >= 0x80))
+ return FALSE;
+ return (ascii[c] & (_C));
+}
+
+#endif /* !CURL_DOES_CONVERSIONS */
diff --git a/Utilities/cmcurl/lib/curl_ctype.h b/Utilities/cmcurl/lib/curl_ctype.h
new file mode 100644
index 0000000..6e94bb1
--- /dev/null
+++ b/Utilities/cmcurl/lib/curl_ctype.h
@@ -0,0 +1,81 @@
+#ifndef HEADER_CURL_CTYPE_H
+#define HEADER_CURL_CTYPE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, 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 CURL_DOES_CONVERSIONS
+
+/*
+ * Uppercase macro versions of ANSI/ISO is*() functions/macros which
+ * avoid negative number inputs with argument byte codes > 127.
+ *
+ * For non-ASCII platforms the C library character classification routines
+ * are used despite being locale-dependent, because this is better than
+ * not to work at all.
+ */
+#include <ctype.h>
+
+#define ISSPACE(x) (isspace((int) ((unsigned char)x)))
+#define ISDIGIT(x) (isdigit((int) ((unsigned char)x)))
+#define ISALNUM(x) (isalnum((int) ((unsigned char)x)))
+#define ISXDIGIT(x) (isxdigit((int) ((unsigned char)x)))
+#define ISGRAPH(x) (isgraph((int) ((unsigned char)x)))
+#define ISALPHA(x) (isalpha((int) ((unsigned char)x)))
+#define ISPRINT(x) (isprint((int) ((unsigned char)x)))
+#define ISUPPER(x) (isupper((int) ((unsigned char)x)))
+#define ISLOWER(x) (islower((int) ((unsigned char)x)))
+#define ISCNTRL(x) (iscntrl((int) ((unsigned char)x)))
+#define ISASCII(x) (isascii((int) ((unsigned char)x)))
+
+#else
+
+int Curl_isspace(int c);
+int Curl_isdigit(int c);
+int Curl_isalnum(int c);
+int Curl_isxdigit(int c);
+int Curl_isgraph(int c);
+int Curl_isprint(int c);
+int Curl_isalpha(int c);
+int Curl_isupper(int c);
+int Curl_islower(int c);
+int Curl_iscntrl(int c);
+
+#define ISSPACE(x) (Curl_isspace((int) ((unsigned char)x)))
+#define ISDIGIT(x) (Curl_isdigit((int) ((unsigned char)x)))
+#define ISALNUM(x) (Curl_isalnum((int) ((unsigned char)x)))
+#define ISXDIGIT(x) (Curl_isxdigit((int) ((unsigned char)x)))
+#define ISGRAPH(x) (Curl_isgraph((int) ((unsigned char)x)))
+#define ISALPHA(x) (Curl_isalpha((int) ((unsigned char)x)))
+#define ISPRINT(x) (Curl_isprint((int) ((unsigned char)x)))
+#define ISUPPER(x) (Curl_isupper((int) ((unsigned char)x)))
+#define ISLOWER(x) (Curl_islower((int) ((unsigned char)x)))
+#define ISCNTRL(x) (Curl_iscntrl((int) ((unsigned char)x)))
+#define ISASCII(x) (((x) >= 0) && ((x) <= 0x80))
+
+#endif
+
+#define ISBLANK(x) (int)((((unsigned char)x) == ' ') || \
+ (((unsigned char)x) == '\t'))
+
+#endif /* HEADER_CURL_CTYPE_H */
diff --git a/Utilities/cmcurl/lib/curl_fnmatch.c b/Utilities/cmcurl/lib/curl_fnmatch.c
index f33bba1..0179a4f 100644
--- a/Utilities/cmcurl/lib/curl_fnmatch.c
+++ b/Utilities/cmcurl/lib/curl_fnmatch.c
@@ -47,14 +47,7 @@
#define CURLFNM_UPPER (CURLFNM_CHARSET_LEN + 10)
typedef enum {
- CURLFNM_LOOP_DEFAULT = 0,
- CURLFNM_LOOP_BACKSLASH
-} loop_state;
-
-typedef enum {
CURLFNM_SCHS_DEFAULT = 0,
- CURLFNM_SCHS_MAYRANGE,
- CURLFNM_SCHS_MAYRANGE2,
CURLFNM_SCHS_RIGHTBR,
CURLFNM_SCHS_RIGHTBRLEFTBR
} setcharset_state;
@@ -64,6 +57,13 @@ typedef enum {
CURLFNM_PKW_DDOT
} parsekey_state;
+typedef enum {
+ CCLASS_OTHER = 0,
+ CCLASS_DIGIT,
+ CCLASS_UPPER,
+ CCLASS_LOWER
+} char_class;
+
#define SETCHARSET_OK 1
#define SETCHARSET_FAIL 0
@@ -81,12 +81,12 @@ static int parsekeyword(unsigned char **pattern, unsigned char *charset)
return SETCHARSET_FAIL;
switch(state) {
case CURLFNM_PKW_INIT:
- if(ISALPHA(c) && ISLOWER(c))
+ if(ISLOWER(c))
keyword[i] = c;
else if(c == ':')
state = CURLFNM_PKW_DDOT;
else
- return 0;
+ return SETCHARSET_FAIL;
break;
case CURLFNM_PKW_DDOT:
if(c == ']')
@@ -123,14 +123,48 @@ static int parsekeyword(unsigned char **pattern, unsigned char *charset)
return SETCHARSET_OK;
}
+/* Return the character class. */
+static char_class charclass(unsigned char c)
+{
+ if(ISUPPER(c))
+ return CCLASS_UPPER;
+ if(ISLOWER(c))
+ return CCLASS_LOWER;
+ if(ISDIGIT(c))
+ return CCLASS_DIGIT;
+ return CCLASS_OTHER;
+}
+
+/* Include a character or a range in set. */
+static void setcharorrange(unsigned char **pp, unsigned char *charset)
+{
+ unsigned char *p = (*pp)++;
+ unsigned char c = *p++;
+
+ charset[c] = 1;
+ if(ISALNUM(c) && *p++ == '-') {
+ char_class cc = charclass(c);
+ unsigned char endrange = *p++;
+
+ if(endrange == '\\')
+ endrange = *p++;
+ if(endrange >= c && charclass(endrange) == cc) {
+ while(c++ != endrange)
+ if(charclass(c) == cc) /* Chars in class may be not consecutive. */
+ charset[c] = 1;
+ *pp = p;
+ }
+ }
+}
+
/* returns 1 (true) if pattern is OK, 0 if is bad ("p" is pattern pointer) */
static int setcharset(unsigned char **p, unsigned char *charset)
{
setcharset_state state = CURLFNM_SCHS_DEFAULT;
- unsigned char rangestart = 0;
- unsigned char lastchar = 0;
bool something_found = FALSE;
unsigned char c;
+
+ memset(charset, 0, CURLFNM_CHSET_SIZE);
for(;;) {
c = **p;
if(!c)
@@ -138,14 +172,7 @@ static int setcharset(unsigned char **p, unsigned char *charset)
switch(state) {
case CURLFNM_SCHS_DEFAULT:
- if(ISALNUM(c)) { /* ASCII value */
- rangestart = c;
- charset[c] = 1;
- (*p)++;
- state = CURLFNM_SCHS_MAYRANGE;
- something_found = TRUE;
- }
- else if(c == ']') {
+ if(c == ']') {
if(something_found)
return SETCHARSET_OK;
something_found = TRUE;
@@ -154,26 +181,16 @@ static int setcharset(unsigned char **p, unsigned char *charset)
(*p)++;
}
else if(c == '[') {
- char c2 = *((*p) + 1);
- if(c2 == ':') { /* there has to be a keyword */
- (*p) += 2;
- if(parsekeyword(p, charset)) {
- state = CURLFNM_SCHS_DEFAULT;
- }
- else
- return SETCHARSET_FAIL;
- }
+ unsigned char *pp = *p + 1;
+
+ if(*pp++ == ':' && parsekeyword(&pp, charset))
+ *p = pp;
else {
charset[c] = 1;
(*p)++;
}
something_found = TRUE;
}
- else if(c == '?' || c == '*') {
- something_found = TRUE;
- charset[c] = 1;
- (*p)++;
- }
else if(c == '^' || c == '!') {
if(!something_found) {
if(charset[CURLFNM_NEGATE]) {
@@ -189,82 +206,17 @@ static int setcharset(unsigned char **p, unsigned char *charset)
}
else if(c == '\\') {
c = *(++(*p));
- if(ISPRINT((c))) {
- something_found = TRUE;
- state = CURLFNM_SCHS_MAYRANGE;
- charset[c] = 1;
- rangestart = c;
- (*p)++;
- }
+ if(c)
+ setcharorrange(p, charset);
else
- return SETCHARSET_FAIL;
+ charset['\\'] = 1;
+ something_found = TRUE;
}
else {
- charset[c] = 1;
- (*p)++;
+ setcharorrange(p, charset);
something_found = TRUE;
}
break;
- case CURLFNM_SCHS_MAYRANGE:
- if(c == '-') {
- charset[c] = 1;
- (*p)++;
- lastchar = '-';
- state = CURLFNM_SCHS_MAYRANGE2;
- }
- else if(c == '[') {
- state = CURLFNM_SCHS_DEFAULT;
- }
- else if(ISALNUM(c)) {
- charset[c] = 1;
- (*p)++;
- }
- else if(c == '\\') {
- c = *(++(*p));
- if(ISPRINT(c)) {
- charset[c] = 1;
- (*p)++;
- }
- else
- return SETCHARSET_FAIL;
- }
- else if(c == ']') {
- return SETCHARSET_OK;
- }
- else
- return SETCHARSET_FAIL;
- break;
- case CURLFNM_SCHS_MAYRANGE2:
- if(c == ']') {
- return SETCHARSET_OK;
- }
- else if(c == '\\') {
- c = *(++(*p));
- if(ISPRINT(c)) {
- charset[c] = 1;
- state = CURLFNM_SCHS_DEFAULT;
- (*p)++;
- }
- else
- return SETCHARSET_FAIL;
- }
- else if(c >= rangestart) {
- if((ISLOWER(c) && ISLOWER(rangestart)) ||
- (ISDIGIT(c) && ISDIGIT(rangestart)) ||
- (ISUPPER(c) && ISUPPER(rangestart))) {
- charset[lastchar] = 0;
- rangestart++;
- while(rangestart++ <= c)
- charset[rangestart-1] = 1;
- (*p)++;
- state = CURLFNM_SCHS_DEFAULT;
- }
- else
- return SETCHARSET_FAIL;
- }
- else
- return SETCHARSET_FAIL;
- break;
case CURLFNM_SCHS_RIGHTBR:
if(c == '[') {
state = CURLFNM_SCHS_RIGHTBRLEFTBR;
@@ -286,14 +238,11 @@ static int setcharset(unsigned char **p, unsigned char *charset)
goto fail;
break;
case CURLFNM_SCHS_RIGHTBRLEFTBR:
- if(c == ']') {
+ if(c == ']')
return SETCHARSET_OK;
- }
- else {
- state = CURLFNM_SCHS_DEFAULT;
- charset[c] = 1;
- (*p)++;
- }
+ state = CURLFNM_SCHS_DEFAULT;
+ charset[c] = 1;
+ (*p)++;
break;
}
}
@@ -304,107 +253,93 @@ fail:
static int loop(const unsigned char *pattern, const unsigned char *string,
int maxstars)
{
- loop_state state = CURLFNM_LOOP_DEFAULT;
unsigned char *p = (unsigned char *)pattern;
unsigned char *s = (unsigned char *)string;
unsigned char charset[CURLFNM_CHSET_SIZE] = { 0 };
- int rc = 0;
for(;;) {
- switch(state) {
- case CURLFNM_LOOP_DEFAULT:
- if(*p == '*') {
- if(!maxstars)
- return CURL_FNMATCH_NOMATCH;
- while(*(p + 1) == '*') /* eliminate multiple stars */
- p++;
- if(*s == '\0' && *(p + 1) == '\0')
- return CURL_FNMATCH_MATCH;
- rc = loop(p + 1, s, maxstars - 1); /* *.txt matches .txt <=>
- .txt matches .txt */
- if(rc == CURL_FNMATCH_MATCH)
+ unsigned char *pp;
+
+ switch(*p) {
+ case '*':
+ if(!maxstars)
+ return CURL_FNMATCH_NOMATCH;
+ /* Regroup consecutive stars and question marks. This can be done because
+ '*?*?*' can be expressed as '??*'. */
+ for(;;) {
+ if(*++p == '\0')
return CURL_FNMATCH_MATCH;
- if(*s) /* let the star eat up one character */
- s++;
- else
- return CURL_FNMATCH_NOMATCH;
- }
- else if(*p == '?') {
- if(ISPRINT(*s)) {
- s++;
- p++;
+ if(*p == '?') {
+ if(!*s++)
+ return CURL_FNMATCH_NOMATCH;
}
- else if(*s == '\0')
- return CURL_FNMATCH_NOMATCH;
- else
- return CURL_FNMATCH_FAIL; /* cannot deal with other character */
+ else if(*p != '*')
+ break;
}
- else if(*p == '\0') {
- if(*s == '\0')
+ /* Skip string characters until we find a match with pattern suffix. */
+ for(maxstars--; *s; s++) {
+ if(loop(p, s, maxstars) == CURL_FNMATCH_MATCH)
return CURL_FNMATCH_MATCH;
- return CURL_FNMATCH_NOMATCH;
}
- else if(*p == '\\') {
- state = CURLFNM_LOOP_BACKSLASH;
+ return CURL_FNMATCH_NOMATCH;
+ case '?':
+ if(!*s)
+ return CURL_FNMATCH_NOMATCH;
+ s++;
+ p++;
+ break;
+ case '\0':
+ return *s? CURL_FNMATCH_NOMATCH: CURL_FNMATCH_MATCH;
+ case '\\':
+ if(p[1])
p++;
- }
- else if(*p == '[') {
- unsigned char *pp = p + 1; /* cannot handle with pointer to register */
- if(setcharset(&pp, charset)) {
- int found = FALSE;
- if(charset[(unsigned int)*s])
- found = TRUE;
- else if(charset[CURLFNM_ALNUM])
- found = ISALNUM(*s);
- else if(charset[CURLFNM_ALPHA])
- found = ISALPHA(*s);
- else if(charset[CURLFNM_DIGIT])
- found = ISDIGIT(*s);
- else if(charset[CURLFNM_XDIGIT])
- found = ISXDIGIT(*s);
- else if(charset[CURLFNM_PRINT])
- found = ISPRINT(*s);
- else if(charset[CURLFNM_SPACE])
- found = ISSPACE(*s);
- else if(charset[CURLFNM_UPPER])
- found = ISUPPER(*s);
- else if(charset[CURLFNM_LOWER])
- found = ISLOWER(*s);
- else if(charset[CURLFNM_BLANK])
- found = ISBLANK(*s);
- else if(charset[CURLFNM_GRAPH])
- found = ISGRAPH(*s);
+ if(*s++ != *p++)
+ return CURL_FNMATCH_NOMATCH;
+ break;
+ case '[':
+ pp = p + 1; /* Copy in case of syntax error in set. */
+ if(setcharset(&pp, charset)) {
+ int found = FALSE;
+ if(!*s)
+ return CURL_FNMATCH_NOMATCH;
+ if(charset[(unsigned int)*s])
+ found = TRUE;
+ else if(charset[CURLFNM_ALNUM])
+ found = ISALNUM(*s);
+ else if(charset[CURLFNM_ALPHA])
+ found = ISALPHA(*s);
+ else if(charset[CURLFNM_DIGIT])
+ found = ISDIGIT(*s);
+ else if(charset[CURLFNM_XDIGIT])
+ found = ISXDIGIT(*s);
+ else if(charset[CURLFNM_PRINT])
+ found = ISPRINT(*s);
+ else if(charset[CURLFNM_SPACE])
+ found = ISSPACE(*s);
+ else if(charset[CURLFNM_UPPER])
+ found = ISUPPER(*s);
+ else if(charset[CURLFNM_LOWER])
+ found = ISLOWER(*s);
+ else if(charset[CURLFNM_BLANK])
+ found = ISBLANK(*s);
+ else if(charset[CURLFNM_GRAPH])
+ found = ISGRAPH(*s);
- if(charset[CURLFNM_NEGATE])
- found = !found;
+ if(charset[CURLFNM_NEGATE])
+ found = !found;
- if(found) {
- p = pp + 1;
- if(*s)
- /* don't advance if we're matching on an empty string */
- s++;
- memset(charset, 0, CURLFNM_CHSET_SIZE);
- }
- else
- return CURL_FNMATCH_NOMATCH;
- }
- else
- return CURL_FNMATCH_FAIL;
- }
- else {
- if(*p++ != *s++)
+ if(!found)
return CURL_FNMATCH_NOMATCH;
+ p = pp + 1;
+ s++;
+ break;
}
- break;
- case CURLFNM_LOOP_BACKSLASH:
- if(ISPRINT(*p)) {
- if(*p++ == *s++)
- state = CURLFNM_LOOP_DEFAULT;
- else
- return CURL_FNMATCH_NOMATCH;
- }
- else
- return CURL_FNMATCH_FAIL;
+
+ /* Syntax error in set: this must be taken as a regular character. */
+ /* FALLTHROUGH */
+ default:
+ if(*p++ != *s++)
+ return CURL_FNMATCH_NOMATCH;
break;
}
}
diff --git a/Utilities/cmcurl/lib/curl_gssapi.c b/Utilities/cmcurl/lib/curl_gssapi.c
index 83f3fa0..f007986 100644
--- a/Utilities/cmcurl/lib/curl_gssapi.c
+++ b/Utilities/cmcurl/lib/curl_gssapi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2011 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2011 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -27,6 +27,11 @@
#include "curl_gssapi.h"
#include "sendf.h"
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
static char spnego_oid_bytes[] = "\x2b\x06\x01\x05\x05\x02";
gss_OID_desc Curl_spnego_mech_oid = { 6, &spnego_oid_bytes };
static char krb5_oid_bytes[] = "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02";
diff --git a/Utilities/cmcurl/lib/curl_memrchr.c b/Utilities/cmcurl/lib/curl_memrchr.c
index c521497..eeb3044 100644
--- a/Utilities/cmcurl/lib/curl_memrchr.c
+++ b/Utilities/cmcurl/lib/curl_memrchr.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -44,17 +44,18 @@
void *
Curl_memrchr(const void *s, int c, size_t n)
{
- const unsigned char *p = s;
- const unsigned char *q = s;
+ if(n > 0) {
+ const unsigned char *p = s;
+ const unsigned char *q = s;
- p += n - 1;
+ p += n - 1;
- while(p >= q) {
- if(*p == (unsigned char)c)
- return (void *)p;
- p--;
+ while(p >= q) {
+ if(*p == (unsigned char)c)
+ return (void *)p;
+ p--;
+ }
}
-
return NULL;
}
diff --git a/Utilities/cmcurl/lib/curl_ntlm_core.c b/Utilities/cmcurl/lib/curl_ntlm_core.c
index e896276..e27cab3 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_core.c
+++ b/Utilities/cmcurl/lib/curl_ntlm_core.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -646,15 +646,6 @@ CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen,
return CURLE_OK;
}
-#ifndef SIZE_T_MAX
-/* some limits.h headers have this defined, some don't */
-#if defined(SIZEOF_SIZE_T) && (SIZEOF_SIZE_T > 4)
-#define SIZE_T_MAX 18446744073709551615U
-#else
-#define SIZE_T_MAX 4294967295U
-#endif
-#endif
-
/* This creates the NTLMv2 hash by using NTLM hash as the key and Unicode
* (uppercase UserName + Domain) as the data
*/
@@ -754,12 +745,10 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
len = NTLM_HMAC_MD5_LEN + NTLMv2_BLOB_LEN;
/* Allocate the response */
- ptr = malloc(len);
+ ptr = calloc(1, len);
if(!ptr)
return CURLE_OUT_OF_MEMORY;
- memset(ptr, 0, len);
-
/* Create the BLOB structure */
snprintf((char *)ptr + NTLM_HMAC_MD5_LEN, NTLMv2_BLOB_LEN,
"%c%c%c%c" /* NTLMv2_BLOB_SIGNATURE */
diff --git a/Utilities/cmcurl/lib/curl_ntlm_wb.c b/Utilities/cmcurl/lib/curl_ntlm_wb.c
index 03f47a3..353a656 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_wb.c
+++ b/Utilities/cmcurl/lib/curl_ntlm_wb.c
@@ -364,7 +364,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
case NTLMSTATE_TYPE1:
default:
/* Use Samba's 'winbind' daemon to support NTLM authentication,
- * by delegating the NTLM challenge/response protocal to a helper
+ * by delegating the NTLM challenge/response protocol to a helper
* in ntlm_auth.
* http://devel.squid-cache.org/ntlm/squid_helper_protocol.html
* https://www.samba.org/samba/docs/man/manpages-3/winbindd.8.html
diff --git a/Utilities/cmcurl/lib/curl_path.h b/Utilities/cmcurl/lib/curl_path.h
index f9d4327..5ee4ff3 100644
--- a/Utilities/cmcurl/lib/curl_path.h
+++ b/Utilities/cmcurl/lib/curl_path.h
@@ -1,3 +1,5 @@
+#ifndef HEADER_CURL_PATH_H
+#define HEADER_CURL_PATH_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -5,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -42,3 +44,4 @@ CURLcode Curl_getworkingpath(struct connectdata *conn,
char **path);
CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir);
+#endif
diff --git a/Utilities/cmcurl/lib/curl_range.c b/Utilities/cmcurl/lib/curl_range.c
new file mode 100644
index 0000000..aa3c493
--- /dev/null
+++ b/Utilities/cmcurl/lib/curl_range.c
@@ -0,0 +1,95 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, 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 <curl/curl.h>
+#include "curl_range.h"
+#include "sendf.h"
+#include "strtoofft.h"
+
+/* Only include this function if one or more of FTP, FILE are enabled. */
+#if !defined(CURL_DISABLE_FTP) || !defined(CURL_DISABLE_FILE)
+
+ /*
+ Check if this is a range download, and if so, set the internal variables
+ properly.
+ */
+CURLcode Curl_range(struct connectdata *conn)
+{
+ curl_off_t from, to;
+ char *ptr;
+ char *ptr2;
+ struct Curl_easy *data = conn->data;
+
+ if(data->state.use_range && data->state.range) {
+ CURLofft from_t;
+ CURLofft to_t;
+ from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
+ if(from_t == CURL_OFFT_FLOW)
+ return CURLE_RANGE_ERROR;
+ while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
+ ptr++;
+ to_t = curlx_strtoofft(ptr, &ptr2, 0, &to);
+ if(to_t == CURL_OFFT_FLOW)
+ return CURLE_RANGE_ERROR;
+ if((to_t == CURL_OFFT_INVAL) && !from_t) {
+ /* X - */
+ data->state.resume_from = from;
+ DEBUGF(infof(data, "RANGE %" CURL_FORMAT_CURL_OFF_T " to end of file\n",
+ from));
+ }
+ else if((from_t == CURL_OFFT_INVAL) && !to_t) {
+ /* -Y */
+ data->req.maxdownload = to;
+ data->state.resume_from = -to;
+ DEBUGF(infof(data, "RANGE the last %" CURL_FORMAT_CURL_OFF_T " bytes\n",
+ to));
+ }
+ else {
+ /* X-Y */
+ curl_off_t totalsize;
+
+ /* Ensure the range is sensible - to should follow from. */
+ if(from > to)
+ return CURLE_RANGE_ERROR;
+
+ totalsize = to - from;
+ if(totalsize == CURL_OFF_T_MAX)
+ return CURLE_RANGE_ERROR;
+
+ data->req.maxdownload = totalsize + 1; /* include last byte */
+ data->state.resume_from = from;
+ DEBUGF(infof(data, "RANGE from %" CURL_FORMAT_CURL_OFF_T
+ " getting %" CURL_FORMAT_CURL_OFF_T " bytes\n",
+ from, data->req.maxdownload));
+ }
+ DEBUGF(infof(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));
+ }
+ else
+ data->req.maxdownload = -1;
+ return CURLE_OK;
+}
+
+#endif
diff --git a/Utilities/cmcurl/lib/curl_range.h b/Utilities/cmcurl/lib/curl_range.h
new file mode 100644
index 0000000..2350df9
--- /dev/null
+++ b/Utilities/cmcurl/lib/curl_range.h
@@ -0,0 +1,30 @@
+#ifndef HEADER_CURL_RANGE_H
+#define HEADER_CURL_RANGE_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, 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 "urldata.h"
+
+CURLcode Curl_range(struct connectdata *conn);
+
+#endif /* HEADER_CURL_RANGE_H */
diff --git a/Utilities/cmcurl/lib/curl_sasl.c b/Utilities/cmcurl/lib/curl_sasl.c
index 550433d..e54e487 100644
--- a/Utilities/cmcurl/lib/curl_sasl.c
+++ b/Utilities/cmcurl/lib/curl_sasl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -265,7 +265,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
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)
+#if defined(USE_KERBEROS5) || defined(USE_NTLM)
const char *service = data->set.str[STRING_SERVICE_NAME] ?
data->set.str[STRING_SERVICE_NAME] :
sasl->params->service;
@@ -333,7 +333,10 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
if(force_ir || data->set.sasl_ir)
result = Curl_auth_create_ntlm_type1_message(data,
conn->user, conn->passwd,
- &conn->ntlm, &resp, &len);
+ service,
+ hostname,
+ &conn->ntlm, &resp,
+ &len);
}
else
#endif
@@ -361,15 +364,6 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
conn->oauth_bearer,
&resp, &len);
}
- else if(enabledmechs & SASL_MECH_LOGIN) {
- mech = SASL_MECH_STRING_LOGIN;
- state1 = SASL_LOGIN;
- state2 = SASL_LOGIN_PASSWD;
- sasl->authused = SASL_MECH_LOGIN;
-
- if(force_ir || data->set.sasl_ir)
- result = Curl_auth_create_login_message(data, conn->user, &resp, &len);
- }
else if(enabledmechs & SASL_MECH_PLAIN) {
mech = SASL_MECH_STRING_PLAIN;
state1 = SASL_PLAIN;
@@ -379,6 +373,15 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
result = Curl_auth_create_plain_message(data, conn->user, conn->passwd,
&resp, &len);
}
+ else if(enabledmechs & SASL_MECH_LOGIN) {
+ mech = SASL_MECH_STRING_LOGIN;
+ state1 = SASL_LOGIN;
+ state2 = SASL_LOGIN_PASSWD;
+ sasl->authused = SASL_MECH_LOGIN;
+
+ if(force_ir || data->set.sasl_ir)
+ result = Curl_auth_create_login_message(data, conn->user, &resp, &len);
+ }
}
if(!result && mech) {
@@ -419,13 +422,11 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
char *chlg = NULL;
size_t chlglen = 0;
#endif
-#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5)
+#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
+ defined(USE_NTLM)
const char *service = data->set.str[STRING_SERVICE_NAME] ?
data->set.str[STRING_SERVICE_NAME] :
sasl->params->service;
-#endif
-#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
- defined(USE_NTLM)
char *serverdata;
#endif
size_t len = 0;
@@ -496,6 +497,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
/* Create the type-1 message */
result = Curl_auth_create_ntlm_type1_message(data,
conn->user, conn->passwd,
+ service, hostname,
&conn->ntlm, &resp, &len);
newstate = SASL_NTLM_TYPE2MSG;
break;
diff --git a/Utilities/cmcurl/lib/curl_setup.h b/Utilities/cmcurl/lib/curl_setup.h
index 16e1ccd..7e6fd5e 100644
--- a/Utilities/cmcurl/lib/curl_setup.h
+++ b/Utilities/cmcurl/lib/curl_setup.h
@@ -404,6 +404,11 @@
# define LSEEK_ERROR (off_t)-1
#endif
+#ifndef SIZEOF_TIME_T
+/* assume default size of time_t to be 32 bit */
+#define SIZEOF_TIME_T 4
+#endif
+
/*
* Default sizeof(off_t) in case it hasn't been defined in config file.
*/
@@ -439,6 +444,33 @@
#endif
#define CURL_OFF_T_MIN (-CURL_OFF_T_MAX - CURL_OFF_T_C(1))
+#if (SIZEOF_TIME_T == 4)
+# ifdef HAVE_TIME_T_UNSIGNED
+# define TIME_T_MAX UINT_MAX
+# define TIME_T_MIN 0
+# else
+# define TIME_T_MAX INT_MAX
+# define TIME_T_MIN INT_MIN
+# endif
+#else
+# ifdef HAVE_TIME_T_UNSIGNED
+# define TIME_T_MAX 0xFFFFFFFFFFFFFFFF
+# define TIME_T_MIN 0
+# else
+# define TIME_T_MAX 0x7FFFFFFFFFFFFFFF
+# define TIME_T_MIN (-TIME_T_MAX - 1)
+# endif
+#endif
+
+#ifndef SIZE_T_MAX
+/* some limits.h headers have this defined, some don't */
+#if defined(SIZEOF_SIZE_T) && (SIZEOF_SIZE_T > 4)
+#define SIZE_T_MAX 18446744073709551615U
+#else
+#define SIZE_T_MAX 4294967295U
+#endif
+#endif
+
/*
* Arg 2 type for gethostname in case it hasn't been defined in config file.
*/
@@ -622,11 +654,6 @@ int netware_init(void);
#error "Both libidn2 and WinIDN are enabled, choose one."
#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) || \
@@ -766,11 +793,11 @@ endings either CRLF or LF so 't' is appropriate.
# if defined(WIN32) || defined(__CYGWIN__)
# define USE_RECV_BEFORE_SEND_WORKAROUND
# endif
-#else /* DONT_USE_RECV_BEFORE_SEND_WORKAROUNDS */
+#else /* DONT_USE_RECV_BEFORE_SEND_WORKAROUND */
# ifdef USE_RECV_BEFORE_SEND_WORKAROUND
# undef USE_RECV_BEFORE_SEND_WORKAROUND
# endif
-#endif /* DONT_USE_RECV_BEFORE_SEND_WORKAROUNDS */
+#endif /* DONT_USE_RECV_BEFORE_SEND_WORKAROUND */
/* Detect Windows App environment which has a restricted access
* to the Win32 APIs. */
@@ -783,4 +810,9 @@ endings either CRLF or LF so 't' is appropriate.
# endif
# endif
+/* for systems that don't detect this in configure, use a sensible default */
+#ifndef CURL_SA_FAMILY_T
+#define CURL_SA_FAMILY_T unsigned short
+#endif
+
#endif /* HEADER_CURL_SETUP_H */
diff --git a/Utilities/cmcurl/lib/curl_setup_once.h b/Utilities/cmcurl/lib/curl_setup_once.h
index a5b542c..6d01ea1 100644
--- a/Utilities/cmcurl/lib/curl_setup_once.h
+++ b/Utilities/cmcurl/lib/curl_setup_once.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -101,7 +101,6 @@
# endif
#endif
-
/*
* Definition of timeval struct for platforms that don't have it.
*/
@@ -274,25 +273,6 @@ struct timeval {
# define sfcntl fcntl
#endif
-/*
- * Uppercase macro versions of ANSI/ISO is*() functions/macros which
- * avoid negative number inputs with argument byte codes > 127.
- */
-
-#define ISSPACE(x) (isspace((int) ((unsigned char)x)))
-#define ISDIGIT(x) (isdigit((int) ((unsigned char)x)))
-#define ISALNUM(x) (isalnum((int) ((unsigned char)x)))
-#define ISXDIGIT(x) (isxdigit((int) ((unsigned char)x)))
-#define ISGRAPH(x) (isgraph((int) ((unsigned char)x)))
-#define ISALPHA(x) (isalpha((int) ((unsigned char)x)))
-#define ISPRINT(x) (isprint((int) ((unsigned char)x)))
-#define ISUPPER(x) (isupper((int) ((unsigned char)x)))
-#define ISLOWER(x) (islower((int) ((unsigned char)x)))
-#define ISASCII(x) (isascii((int) ((unsigned char)x)))
-
-#define ISBLANK(x) (int)((((unsigned char)x) == ' ') || \
- (((unsigned char)x) == '\t'))
-
#define TOLOWER(x) (tolower((int) ((unsigned char)x)))
@@ -347,6 +327,7 @@ struct timeval {
#define FALSE false
#endif
+#include "curl_ctype.h"
/*
* Macro WHILE_FALSE may be used to build single-iteration do-while loops,
diff --git a/Utilities/cmcurl/lib/easy.c b/Utilities/cmcurl/lib/easy.c
index edc716d..6b91435 100644
--- a/Utilities/cmcurl/lib/easy.c
+++ b/Utilities/cmcurl/lib/easy.c
@@ -61,6 +61,7 @@
#include "strdup.h"
#include "progress.h"
#include "easyif.h"
+#include "multiif.h"
#include "select.h"
#include "sendf.h" /* for failf function prototype */
#include "connect.h" /* for Curl_getconnectinfo */
@@ -73,6 +74,7 @@
#include "sigpipe.h"
#include "ssh.h"
#include "setopt.h"
+#include "http_digest.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -744,6 +746,10 @@ static CURLcode easy_perform(struct Curl_easy *data, bool events)
if(!data)
return CURLE_BAD_FUNCTION_ARGUMENT;
+ if(data->set.errorbuffer)
+ /* clear this as early as possible */
+ data->set.errorbuffer[0] = 0;
+
if(data->multi) {
failf(data, "easy handle already used in multi handle");
return CURLE_FAILED_INIT;
@@ -760,6 +766,9 @@ static CURLcode easy_perform(struct Curl_easy *data, bool events)
data->multi_easy = multi;
}
+ if(multi->in_callback)
+ return CURLE_RECURSIVE_API_CALL;
+
/* Copy the MAXCONNECTS option to the multi handle */
curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, data->set.maxconnects);
@@ -883,6 +892,9 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
/* Duplicate mime data. */
result = Curl_mime_duppart(&dst->set.mimepost, &src->set.mimepost);
+ if(src->set.resolve)
+ dst->change.resolve = dst->set.resolve;
+
return result;
}
@@ -1017,6 +1029,7 @@ void curl_easy_reset(struct Curl_easy *data)
/* zero out authentication data: */
memset(&data->state.authhost, 0, sizeof(struct auth));
memset(&data->state.authproxy, 0, sizeof(struct auth));
+ Curl_digest_cleanup(data);
}
/*
@@ -1028,6 +1041,9 @@ void curl_easy_reset(struct Curl_easy *data)
* the pausing, you may get your write callback called at this point.
*
* Action is a bitmask consisting of CURLPAUSE_* bits in curl/curl.h
+ *
+ * NOTE: This is one of few API functions that are allowed to be called from
+ * within a callback.
*/
CURLcode curl_easy_pause(struct Curl_easy *data, int action)
{
@@ -1070,10 +1086,8 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
/* even if one function returns error, this loops through and frees all
buffers */
if(!result)
- result = Curl_client_chop_write(conn,
- writebuf[i].type,
- writebuf[i].buf,
- writebuf[i].len);
+ result = Curl_client_write(conn, writebuf[i].type, writebuf[i].buf,
+ writebuf[i].len);
free(writebuf[i].buf);
}
@@ -1092,6 +1106,10 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) )
Curl_expire(data, 0, EXPIRE_RUN_NOW); /* get this handle going again */
+ /* This transfer may have been moved in or out of the bundle, update
+ the corresponding socket callback, if used */
+ Curl_updatesocket(data);
+
return result;
}
@@ -1132,6 +1150,9 @@ CURLcode curl_easy_recv(struct Curl_easy *data, void *buffer, size_t buflen,
ssize_t n1;
struct connectdata *c;
+ if(Curl_is_in_callback(data))
+ return CURLE_RECURSIVE_API_CALL;
+
result = easy_connection(data, &sfd, &c);
if(result)
return result;
@@ -1159,6 +1180,9 @@ CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
ssize_t n1;
struct connectdata *c = NULL;
+ if(Curl_is_in_callback(data))
+ return CURLE_RECURSIVE_API_CALL;
+
result = easy_connection(data, &sfd, &c);
if(result)
return result;
diff --git a/Utilities/cmcurl/lib/file.c b/Utilities/cmcurl/lib/file.c
index 0bbc0e1..db04cc2 100644
--- a/Utilities/cmcurl/lib/file.c
+++ b/Utilities/cmcurl/lib/file.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -61,6 +61,7 @@
#include "url.h"
#include "parsedate.h" /* for the week day and month names */
#include "warnless.h"
+#include "curl_range.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -125,65 +126,6 @@ static CURLcode file_setup_connection(struct connectdata *conn)
return CURLE_OK;
}
- /*
- Check if this is a range download, and if so, set the internal variables
- properly. This code is copied from the FTP implementation and might as
- well be factored out.
- */
-static CURLcode file_range(struct connectdata *conn)
-{
- curl_off_t from, to;
- curl_off_t totalsize = -1;
- char *ptr;
- char *ptr2;
- struct Curl_easy *data = conn->data;
-
- if(data->state.use_range && data->state.range) {
- CURLofft from_t;
- CURLofft to_t;
- from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
- if(from_t == CURL_OFFT_FLOW)
- return CURLE_RANGE_ERROR;
- while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
- ptr++;
- to_t = curlx_strtoofft(ptr, &ptr2, 0, &to);
- if(to_t == CURL_OFFT_FLOW)
- return CURLE_RANGE_ERROR;
- if((to_t == CURL_OFFT_INVAL) && !from_t) {
- /* X - */
- data->state.resume_from = from;
- DEBUGF(infof(data, "RANGE %" CURL_FORMAT_CURL_OFF_T " to end of file\n",
- from));
- }
- else if((from_t == CURL_OFFT_INVAL) && !to_t) {
- /* -Y */
- data->req.maxdownload = to;
- data->state.resume_from = -to;
- DEBUGF(infof(data, "RANGE the last %" CURL_FORMAT_CURL_OFF_T " bytes\n",
- to));
- }
- else {
- /* X-Y */
- totalsize = to-from;
- if(totalsize == CURL_OFF_T_MAX)
- /* this is too big to increase, so bail out */
- return CURLE_RANGE_ERROR;
- data->req.maxdownload = totalsize + 1; /* include last byte */
- data->state.resume_from = from;
- DEBUGF(infof(data, "RANGE from %" CURL_FORMAT_CURL_OFF_T
- " getting %" CURL_FORMAT_CURL_OFF_T " bytes\n",
- from, data->req.maxdownload));
- }
- DEBUGF(infof(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));
- }
- else
- data->req.maxdownload = -1;
- return CURLE_OK;
-}
-
/*
* file_connect() gets called from Curl_protocol_connect() to allow us to
* do protocol-specific actions at connect-time. We emulate a
@@ -461,12 +403,12 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
/* we could stat it, then read out the size */
expected_size = statbuf.st_size;
/* and store the modification time */
- data->info.filetime = (long)statbuf.st_mtime;
+ data->info.filetime = statbuf.st_mtime;
fstated = TRUE;
}
if(fstated && !data->state.range && data->set.timecondition) {
- if(!Curl_meets_timecondition(data, (time_t)data->info.filetime)) {
+ if(!Curl_meets_timecondition(data, data->info.filetime)) {
*done = TRUE;
return CURLE_OK;
}
@@ -514,7 +456,9 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
}
/* Check whether file range has been specified */
- file_range(conn);
+ result = Curl_range(conn);
+ if(result)
+ return result;
/* Adjust the start offset in case we want to get the N last bytes
* of the stream iff the filesize could be determined */
diff --git a/Utilities/cmcurl/lib/fileinfo.c b/Utilities/cmcurl/lib/fileinfo.c
index 3872988..4e72e1e 100644
--- a/Utilities/cmcurl/lib/fileinfo.c
+++ b/Utilities/cmcurl/lib/fileinfo.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2010 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -33,14 +33,11 @@ struct fileinfo *Curl_fileinfo_alloc(void)
return calloc(1, sizeof(struct fileinfo));
}
-void Curl_fileinfo_dtor(void *user, void *element)
+void Curl_fileinfo_cleanup(struct fileinfo *finfo)
{
- struct fileinfo *finfo = element;
- (void) user;
if(!finfo)
return;
Curl_safefree(finfo->info.b_data);
-
free(finfo);
}
diff --git a/Utilities/cmcurl/lib/fileinfo.h b/Utilities/cmcurl/lib/fileinfo.h
index c5d0ee5..f4d8f3b 100644
--- a/Utilities/cmcurl/lib/fileinfo.h
+++ b/Utilities/cmcurl/lib/fileinfo.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010, 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2010 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -31,7 +31,6 @@ struct fileinfo {
};
struct fileinfo *Curl_fileinfo_alloc(void);
-
-void Curl_fileinfo_dtor(void *, void *);
+void Curl_fileinfo_cleanup(struct fileinfo *finfo);
#endif /* HEADER_CURL_FILEINFO_H */
diff --git a/Utilities/cmcurl/lib/formdata.c b/Utilities/cmcurl/lib/formdata.c
index d0579c5..f912410 100644
--- a/Utilities/cmcurl/lib/formdata.c
+++ b/Utilities/cmcurl/lib/formdata.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -155,60 +155,6 @@ static FormInfo * AddFormInfo(char *value,
/***************************************************************************
*
- * ContentTypeForFilename()
- *
- * Provides content type for filename if one of the known types (else
- * (either the prevtype or the default is returned).
- *
- * Returns some valid contenttype for filename.
- *
- ***************************************************************************/
-static const char *ContentTypeForFilename(const char *filename,
- const char *prevtype)
-{
- const char *contenttype = NULL;
- unsigned int i;
- /*
- * No type was specified, we scan through a few well-known
- * extensions and pick the first we match!
- */
- struct ContentType {
- const char *extension;
- const char *type;
- };
- static const struct ContentType ctts[]={
- {".gif", "image/gif"},
- {".jpg", "image/jpeg"},
- {".jpeg", "image/jpeg"},
- {".txt", "text/plain"},
- {".html", "text/html"},
- {".xml", "application/xml"}
- };
-
- if(prevtype)
- /* default to the previously set/used! */
- contenttype = prevtype;
- else
- contenttype = HTTPPOST_CONTENTTYPE_DEFAULT;
-
- if(filename) { /* in case a NULL was passed in */
- for(i = 0; i<sizeof(ctts)/sizeof(ctts[0]); i++) {
- if(strlen(filename) >= strlen(ctts[i].extension)) {
- if(strcasecompare(filename +
- strlen(filename) - strlen(ctts[i].extension),
- ctts[i].extension)) {
- contenttype = ctts[i].type;
- break;
- }
- }
- }
- }
- /* we have a contenttype by now */
- return contenttype;
-}
-
-/***************************************************************************
- *
* FormAdd()
*
* Stores a formpost parameter and builds the appropriate linked list.
@@ -627,9 +573,15 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
!form->contenttype) {
char *f = form->flags & HTTPPOST_BUFFER?
form->showfilename : form->value;
+ char const *type;
+ type = Curl_mime_contenttype(f);
+ if(!type)
+ type = prevtype;
+ if(!type)
+ type = FILE_CONTENTTYPE_DEFAULT;
/* our contenttype is missing */
- form->contenttype = strdup(ContentTypeForFilename(f, prevtype));
+ form->contenttype = strdup(type);
if(!form->contenttype) {
return_value = CURL_FORMADD_MEMORY;
break;
diff --git a/Utilities/cmcurl/lib/ftp.c b/Utilities/cmcurl/lib/ftp.c
index d3b0220..a42c0c7 100644
--- a/Utilities/cmcurl/lib/ftp.c
+++ b/Utilities/cmcurl/lib/ftp.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -59,6 +59,7 @@
#include "ftp.h"
#include "fileinfo.h"
#include "ftplistparser.h"
+#include "curl_range.h"
#include "curl_sec.h"
#include "strtoofft.h"
#include "strcase.h"
@@ -310,9 +311,11 @@ static CURLcode AcceptServerConnect(struct connectdata *conn)
int error = 0;
/* activate callback for setting socket options */
+ Curl_set_in_callback(data, true);
error = data->set.fsockopt(data->set.sockopt_client,
s,
CURLSOCKTYPE_ACCEPT);
+ Curl_set_in_callback(data, false);
if(error) {
close_secondarysocket(conn);
@@ -1471,7 +1474,7 @@ static CURLcode ftp_state_list(struct connectdata *conn)
slashPos = strrchr(inpath, '/');
n = slashPos - inpath;
}
- result = Curl_urldecode(data, inpath, n, &lstArg, NULL, FALSE);
+ result = Curl_urldecode(data, inpath, n, &lstArg, NULL, TRUE);
if(result)
return result;
}
@@ -1535,7 +1538,7 @@ static CURLcode ftp_state_type(struct connectdata *conn)
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
+ /* The SIZE command is _not_ RFC 959 specified, and therefore many servers
may not support it! It is however the only way we have to get a file's
size! */
@@ -1615,8 +1618,10 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
/* Let's read off the proper amount of bytes from the input. */
if(conn->seek_func) {
+ Curl_set_in_callback(data, true);
seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
SEEK_SET);
+ Curl_set_in_callback(data, false);
}
if(seekerr != CURL_SEEKFUNC_OK) {
@@ -1783,7 +1788,7 @@ static CURLcode ftp_epsv_disable(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
- if(conn->bits.ipv6) {
+ if(conn->bits.ipv6 && !(conn->bits.tunnel_proxy || conn->bits.socksproxy)) {
/* 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;
@@ -1905,13 +1910,13 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
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",
+ infof(data, "Skip %u.%u.%u.%u 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]);
+ ftpc->newhost = aprintf("%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
if(!ftpc->newhost)
return CURLE_OUT_OF_MEMORY;
@@ -2060,7 +2065,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
"%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(timebuf, &secs);
+ data->info.filetime = curl_getdate(timebuf, &secs);
}
#ifdef CURL_FTP_HTTPSTYLE_HEAD
@@ -2072,7 +2077,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
data->set.get_filetime &&
(data->info.filetime >= 0) ) {
char headerbuf[128];
- time_t filetime = (time_t)data->info.filetime;
+ time_t filetime = data->info.filetime;
struct tm buffer;
const struct tm *tm = &buffer;
@@ -3180,14 +3185,16 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
if(data->state.wildcardmatch) {
if(data->set.chunk_end && ftpc->file) {
+ Curl_set_in_callback(data, true);
data->set.chunk_end(data->wildcard.customptr);
+ Curl_set_in_callback(data, false);
}
ftpc->known_filesize = -1;
}
if(!result)
/* get the "raw" path */
- result = Curl_urldecode(data, path_to_use, 0, &path, NULL, FALSE);
+ result = Curl_urldecode(data, path_to_use, 0, &path, NULL, TRUE);
if(result) {
/* We can limp along anyway (and should try to since we may already be in
* the error path) */
@@ -3463,62 +3470,6 @@ ftp_pasv_verbose(struct connectdata *conn,
#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;
- struct Curl_easy *data = conn->data;
- struct ftp_conn *ftpc = &conn->proto.ftpc;
-
- if(data->state.use_range && data->state.range) {
- CURLofft from_t;
- CURLofft to_t;
- from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
- if(from_t == CURL_OFFT_FLOW)
- return CURLE_RANGE_ERROR;
- while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
- ptr++;
- to_t = curlx_strtoofft(ptr, NULL, 0, &to);
- if(to_t == CURL_OFFT_FLOW)
- return CURLE_RANGE_ERROR;
- if((to_t == CURL_OFFT_INVAL) && !from_t) {
- /* 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(!to_t && (from_t == CURL_OFFT_INVAL)) {
- /* -Y */
- data->req.maxdownload = to;
- data->state.resume_from = -to;
- DEBUGF(infof(conn->data, "FTP RANGE the last %" CURL_FORMAT_CURL_OFF_T
- " bytes\n", to));
- }
- 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; /* don't 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
@@ -3640,7 +3591,13 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
/* download */
ftp->downloadsize = -1; /* unknown as of yet */
- result = ftp_range(conn);
+ result = Curl_range(conn);
+
+ if(result == CURLE_OK && data->req.maxdownload >= 0) {
+ /* Don't check for successful transfer */
+ ftpc->dont_check = TRUE;
+ }
+
if(result)
;
else if(data->set.ftp_list_only || !ftpc->file) {
@@ -3731,10 +3688,10 @@ CURLcode ftp_perform(struct connectdata *conn,
static void wc_data_dtor(void *ptr)
{
- struct ftp_wc_tmpdata *tmp = ptr;
- if(tmp)
- Curl_ftp_parselist_data_free(&tmp->parser);
- free(tmp);
+ struct ftp_wc *ftpwc = ptr;
+ if(ftpwc && ftpwc->parser)
+ Curl_ftp_parselist_data_free(&ftpwc->parser);
+ free(ftpwc);
}
static CURLcode init_wc_data(struct connectdata *conn)
@@ -3743,7 +3700,7 @@ static CURLcode init_wc_data(struct connectdata *conn)
char *path = conn->data->state.path;
struct WildcardData *wildcard = &(conn->data->wildcard);
CURLcode result = CURLE_OK;
- struct ftp_wc_tmpdata *ftp_tmp;
+ struct ftp_wc *ftpwc = NULL;
last_slash = strrchr(conn->data->state.path, '/');
if(last_slash) {
@@ -3775,23 +3732,22 @@ static CURLcode init_wc_data(struct connectdata *conn)
/* 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;
+ /* allocate ftp protocol specific wildcard data */
+ ftpwc = calloc(1, sizeof(struct ftp_wc));
+ if(!ftpwc) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto fail;
}
/* 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;
+ ftpwc->parser = Curl_ftp_parselist_data_alloc();
+ if(!ftpwc->parser) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto fail;
}
- wildcard->tmp = ftp_tmp; /* put it to the WildcardData tmp pointer */
- wildcard->tmp_dtor = wc_data_dtor;
+ wildcard->protdata = ftpwc; /* put it to the WildcardData tmp pointer */
+ wildcard->dtor = wc_data_dtor;
/* wildcard does not support NOCWD option (assert it?) */
if(conn->data->set.ftp_filemethod == FTPFILE_NOCWD)
@@ -3800,33 +3756,36 @@ static CURLcode init_wc_data(struct connectdata *conn)
/* 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;
+ goto fail;
}
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;
+ result = CURLE_OUT_OF_MEMORY;
+ goto fail;
}
/* backup old write_function */
- ftp_tmp->backup.write_function = conn->data->set.fwrite_func;
+ ftpwc->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;
+ ftpwc->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;
+
+ fail:
+ if(ftpwc) {
+ Curl_ftp_parselist_data_free(&ftpwc->parser);
+ free(ftpwc);
+ }
+ Curl_safefree(wildcard->pattern);
+ wildcard->dtor = ZERO_NULL;
+ wildcard->protdata = NULL;
+ return result;
}
/* This is called recursively */
@@ -3847,14 +3806,14 @@ static CURLcode wc_statemach(struct connectdata *conn)
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;
+ struct ftp_wc *ftpwc = wildcard->protdata;
+ conn->data->set.fwrite_func = ftpwc->backup.write_function;
+ conn->data->set.out = ftpwc->backup.file_descriptor;
+ ftpwc->backup.write_function = ZERO_NULL;
+ ftpwc->backup.file_descriptor = NULL;
wildcard->state = CURLWC_DOWNLOADING;
- if(Curl_ftp_parselist_geterror(ftp_tmp->parser)) {
+ if(Curl_ftp_parselist_geterror(ftpwc->parser)) {
/* error found in LIST parsing */
wildcard->state = CURLWC_CLEAN;
return wc_statemach(conn);
@@ -3884,8 +3843,11 @@ static CURLcode wc_statemach(struct connectdata *conn)
infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename);
if(conn->data->set.chunk_bgn) {
- long userresponse = conn->data->set.chunk_bgn(
+ long userresponse;
+ Curl_set_in_callback(conn->data, true);
+ userresponse = conn->data->set.chunk_bgn(
finfo, wildcard->customptr, (int)wildcard->filelist.size);
+ Curl_set_in_callback(conn->data, false);
switch(userresponse) {
case CURL_CHUNK_BGN_FUNC_SKIP:
infof(conn->data, "Wildcard - \"%s\" skipped by user\n",
@@ -3921,8 +3883,11 @@ static CURLcode wc_statemach(struct connectdata *conn)
} break;
case CURLWC_SKIP: {
- if(conn->data->set.chunk_end)
+ if(conn->data->set.chunk_end) {
+ Curl_set_in_callback(conn->data, true);
conn->data->set.chunk_end(conn->data->wildcard.customptr);
+ Curl_set_in_callback(conn->data, false);
+ }
Curl_llist_remove(&wildcard->filelist, wildcard->filelist.head, NULL);
wildcard->state = (wildcard->filelist.size == 0) ?
CURLWC_CLEAN : CURLWC_DOWNLOADING;
@@ -3930,10 +3895,10 @@ static CURLcode wc_statemach(struct connectdata *conn)
}
case CURLWC_CLEAN: {
- struct ftp_wc_tmpdata *ftp_tmp = wildcard->tmp;
+ struct ftp_wc *ftpwc = wildcard->protdata;
result = CURLE_OK;
- if(ftp_tmp)
- result = Curl_ftp_parselist_geterror(ftp_tmp->parser);
+ if(ftpwc)
+ result = Curl_ftp_parselist_geterror(ftpwc->parser);
wildcard->state = result ? CURLWC_ERROR : CURLWC_DONE;
} break;
@@ -3941,6 +3906,8 @@ static CURLcode wc_statemach(struct connectdata *conn)
case CURLWC_DONE:
case CURLWC_ERROR:
case CURLWC_CLEAR:
+ if(wildcard->dtor)
+ wildcard->dtor(wildcard->protdata);
break;
}
@@ -4193,7 +4160,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
result = Curl_urldecode(conn->data, slash_pos ? cur_pos : "/",
slash_pos ? dirlen : 1,
&ftpc->dirs[0], NULL,
- FALSE);
+ TRUE);
if(result) {
freedirs(ftpc);
return result;
@@ -4300,7 +4267,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
size_t dlen;
char *path;
CURLcode result =
- Curl_urldecode(conn->data, data->state.path, 0, &path, &dlen, FALSE);
+ Curl_urldecode(conn->data, data->state.path, 0, &path, &dlen, TRUE);
if(result) {
freedirs(ftpc);
return result;
diff --git a/Utilities/cmcurl/lib/ftp.h b/Utilities/cmcurl/lib/ftp.h
index e4aa63f..7ec3391 100644
--- a/Utilities/cmcurl/lib/ftp.h
+++ b/Utilities/cmcurl/lib/ftp.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -81,7 +81,7 @@ typedef enum {
struct ftp_parselist_data; /* defined later in ftplistparser.c */
-struct ftp_wc_tmpdata {
+struct ftp_wc {
struct ftp_parselist_data *parser;
struct {
diff --git a/Utilities/cmcurl/lib/ftplistparser.c b/Utilities/cmcurl/lib/ftplistparser.c
index 262ac03..249fe09 100644
--- a/Utilities/cmcurl/lib/ftplistparser.c
+++ b/Utilities/cmcurl/lib/ftplistparser.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -49,6 +49,7 @@
#include "ftplistparser.h"
#include "curl_fnmatch.h"
#include "curl_memory.h"
+#include "multiif.h"
/* The last #include file should be: */
#include "memdebug.h"
@@ -184,10 +185,13 @@ struct ftp_parselist_data *Curl_ftp_parselist_data_alloc(void)
}
-void Curl_ftp_parselist_data_free(struct ftp_parselist_data **pl_data)
+void Curl_ftp_parselist_data_free(struct ftp_parselist_data **parserp)
{
- free(*pl_data);
- *pl_data = NULL;
+ struct ftp_parselist_data *parser = *parserp;
+ if(parser)
+ Curl_fileinfo_cleanup(parser->file_data);
+ free(parser);
+ *parserp = NULL;
}
@@ -269,9 +273,9 @@ static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
{
curl_fnmatch_callback compare;
struct WildcardData *wc = &conn->data->wildcard;
- struct ftp_wc_tmpdata *tmpdata = wc->tmp;
+ struct ftp_wc *ftpwc = wc->protdata;
struct curl_llist *llist = &wc->filelist;
- struct ftp_parselist_data *parser = tmpdata->parser;
+ struct ftp_parselist_data *parser = ftpwc->parser;
bool add = TRUE;
struct curl_fileinfo *finfo = &infop->info;
@@ -294,6 +298,7 @@ static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
compare = Curl_fnmatch;
/* filter pattern-corresponding filenames */
+ Curl_set_in_callback(conn->data, true);
if(compare(conn->data->set.fnmatch_data, wc->pattern,
finfo->filename) == 0) {
/* discard symlink which is containing multiple " -> " */
@@ -305,15 +310,16 @@ static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
else {
add = FALSE;
}
+ Curl_set_in_callback(conn->data, false);
if(add) {
Curl_llist_insert_next(llist, llist->tail, finfo, &infop->list);
}
else {
- Curl_fileinfo_dtor(NULL, finfo);
+ Curl_fileinfo_cleanup(infop);
}
- tmpdata->parser->file_data = NULL;
+ ftpwc->parser->file_data = NULL;
return CURLE_OK;
}
@@ -322,8 +328,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
{
size_t bufflen = size*nmemb;
struct connectdata *conn = (struct connectdata *)connptr;
- struct ftp_wc_tmpdata *tmpdata = conn->data->wildcard.tmp;
- struct ftp_parselist_data *parser = tmpdata->parser;
+ struct ftp_wc *ftpwc = conn->data->wildcard.protdata;
+ struct ftp_parselist_data *parser = ftpwc->parser;
struct fileinfo *infop;
struct curl_fileinfo *finfo;
unsigned long i = 0;
@@ -378,7 +384,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
finfo->b_data = tmp;
}
else {
- Curl_fileinfo_dtor(NULL, parser->file_data);
+ Curl_fileinfo_cleanup(parser->file_data);
parser->file_data = NULL;
parser->error = CURLE_OUT_OF_MEMORY;
goto fail;
@@ -1000,12 +1006,13 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
i++;
}
+ return retsize;
fail:
/* Clean up any allocated memory. */
if(parser->file_data) {
- Curl_fileinfo_dtor(NULL, parser->file_data);
+ Curl_fileinfo_cleanup(parser->file_data);
parser->file_data = NULL;
}
diff --git a/Utilities/cmcurl/lib/getinfo.c b/Utilities/cmcurl/lib/getinfo.c
index 862ced0..d280eeb 100644
--- a/Utilities/cmcurl/lib/getinfo.c
+++ b/Utilities/cmcurl/lib/getinfo.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -156,7 +156,12 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
*param_longp = data->info.httpproxycode;
break;
case CURLINFO_FILETIME:
- *param_longp = data->info.filetime;
+ if(data->info.filetime > LONG_MAX)
+ *param_longp = LONG_MAX;
+ else if(data->info.filetime < LONG_MIN)
+ *param_longp = LONG_MIN;
+ else
+ *param_longp = (long)data->info.filetime;
break;
case CURLINFO_HEADER_SIZE:
*param_longp = data->info.header_size;
@@ -253,6 +258,9 @@ static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
curl_off_t *param_offt)
{
switch(info) {
+ case CURLINFO_FILETIME_T:
+ *param_offt = (curl_off_t)data->info.filetime;
+ break;
case CURLINFO_SIZE_UPLOAD_T:
*param_offt = data->progress.uploaded;
break;
diff --git a/Utilities/cmcurl/lib/hash.c b/Utilities/cmcurl/lib/hash.c
index c99b1b6..15a128f 100644
--- a/Utilities/cmcurl/lib/hash.c
+++ b/Utilities/cmcurl/lib/hash.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -261,11 +261,11 @@ size_t Curl_hash_str(void *key, size_t key_length, size_t slots_num)
{
const char *key_str = (const char *) key;
const char *end = key_str + key_length;
- unsigned long h = 5381;
+ size_t h = 5381;
while(key_str < end) {
h += h << 5;
- h ^= (unsigned long) *key_str++;
+ h ^= *key_str++;
}
return (h % slots_num);
diff --git a/Utilities/cmcurl/lib/hostcheck.c b/Utilities/cmcurl/lib/hostcheck.c
index 37bcc12..c9d8112 100644
--- a/Utilities/cmcurl/lib/hostcheck.c
+++ b/Utilities/cmcurl/lib/hostcheck.c
@@ -25,7 +25,7 @@
#if defined(USE_OPENSSL) \
|| defined(USE_AXTLS) \
|| defined(USE_GSKIT) \
- || (defined(USE_SCHANNEL) && defined(_WIN32_WCE))
+ || defined(USE_SCHANNEL)
/* these backends use functions from this file */
#ifdef HAVE_NETINET_IN_H
diff --git a/Utilities/cmcurl/lib/hostip.c b/Utilities/cmcurl/lib/hostip.c
index 886aeec..c2f9def 100644
--- a/Utilities/cmcurl/lib/hostip.c
+++ b/Utilities/cmcurl/lib/hostip.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, 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,10 +54,12 @@
#include "sendf.h"
#include "hostip.h"
#include "hash.h"
+#include "rand.h"
#include "share.h"
#include "strerror.h"
#include "url.h"
#include "inet_ntop.h"
+#include "multiif.h"
#include "warnless.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -366,6 +368,70 @@ Curl_fetch_addr(struct connectdata *conn,
}
/*
+ * Curl_shuffle_addr() shuffles the order of addresses in a 'Curl_addrinfo'
+ * struct by re-linking its linked list.
+ *
+ * The addr argument should be the address of a pointer to the head node of a
+ * `Curl_addrinfo` list and it will be modified to point to the new head after
+ * shuffling.
+ *
+ * Not declared static only to make it easy to use in a unit test!
+ *
+ * @unittest: 1608
+ */
+CURLcode Curl_shuffle_addr(struct Curl_easy *data, Curl_addrinfo **addr)
+{
+ CURLcode result = CURLE_OK;
+ const int num_addrs = Curl_num_addresses(*addr);
+
+ if(num_addrs > 1) {
+ Curl_addrinfo **nodes;
+ infof(data, "Shuffling %i addresses", num_addrs);
+
+ nodes = malloc(num_addrs*sizeof(*nodes));
+ if(nodes) {
+ int i;
+ unsigned int *rnd;
+ const size_t rnd_size = num_addrs * sizeof(*rnd);
+
+ /* build a plain array of Curl_addrinfo pointers */
+ nodes[0] = *addr;
+ for(i = 1; i < num_addrs; i++) {
+ nodes[i] = nodes[i-1]->ai_next;
+ }
+
+ rnd = malloc(rnd_size);
+ if(rnd) {
+ /* Fisher-Yates shuffle */
+ if(Curl_rand(data, (unsigned char *)rnd, rnd_size) == CURLE_OK) {
+ Curl_addrinfo *swap_tmp;
+ for(i = num_addrs - 1; i > 0; i--) {
+ swap_tmp = nodes[rnd[i] % (i + 1)];
+ nodes[rnd[i] % (i + 1)] = nodes[i];
+ nodes[i] = swap_tmp;
+ }
+
+ /* relink list in the new order */
+ for(i = 1; i < num_addrs; i++) {
+ nodes[i-1]->ai_next = nodes[i];
+ }
+
+ nodes[num_addrs-1]->ai_next = NULL;
+ *addr = nodes[0];
+ }
+ free(rnd);
+ }
+ else
+ result = CURLE_OUT_OF_MEMORY;
+ free(nodes);
+ }
+ else
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ return result;
+}
+
+/*
* Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
*
* When calling Curl_resolv() has resulted in a response with a returned
@@ -385,6 +451,13 @@ Curl_cache_addr(struct Curl_easy *data,
struct Curl_dns_entry *dns;
struct Curl_dns_entry *dns2;
+ /* shuffle addresses if requested */
+ if(data->set.dns_shuffle_addresses) {
+ CURLcode result = Curl_shuffle_addr(data, &addr);
+ if(!result)
+ return NULL;
+ }
+
/* Create an entry id, based upon the hostname and port */
entry_id = create_hostcache_id(hostname, port);
/* If we can't create the entry id, fail */
@@ -481,6 +554,17 @@ int Curl_resolv(struct connectdata *conn,
if(!Curl_ipvalid(conn))
return CURLRESOLV_ERROR;
+ /* notify the resolver start callback */
+ if(data->set.resolver_start) {
+ int st;
+ Curl_set_in_callback(data, true);
+ st = data->set.resolver_start(data->state.resolver, NULL,
+ data->set.resolver_start_client);
+ Curl_set_in_callback(data, false);
+ if(st)
+ return CURLRESOLV_ERROR;
+ }
+
/* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a
non-zero value indicating that we need to wait for the response to the
resolve call */
@@ -781,7 +865,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
{
struct curl_slist *hostp;
char hostname[256];
- int port;
+ int port = 0;
for(hostp = data->change.resolve; hostp; hostp = hostp->next) {
if(!hostp->data)
@@ -819,32 +903,95 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
}
else {
struct Curl_dns_entry *dns;
- Curl_addrinfo *addr;
+ Curl_addrinfo *head = NULL, *tail = NULL;
char *entry_id;
size_t entry_len;
- char buffer[256];
- char *address = &buffer[0];
+ char address[64];
+ char *addresses = NULL;
+ char *addr_begin;
+ char *addr_end;
+ char *port_ptr;
+ char *end_ptr;
+ char *host_end;
+ unsigned long tmp_port;
+ bool error = true;
+
+ host_end = strchr(hostp->data, ':');
+ if(!host_end ||
+ ((host_end - hostp->data) >= (ptrdiff_t)sizeof(hostname)))
+ goto err;
+
+ memcpy(hostname, hostp->data, host_end - hostp->data);
+ hostname[host_end - hostp->data] = '\0';
+
+ port_ptr = host_end + 1;
+ tmp_port = strtoul(port_ptr, &end_ptr, 10);
+ if(tmp_port > USHRT_MAX || end_ptr == port_ptr || *end_ptr != ':')
+ goto err;
+
+ port = (int)tmp_port;
+ addresses = end_ptr + 1;
+
+ while(*end_ptr) {
+ size_t alen;
+ Curl_addrinfo *ai;
+
+ addr_begin = end_ptr + 1;
+ addr_end = strchr(addr_begin, ',');
+ if(!addr_end)
+ addr_end = addr_begin + strlen(addr_begin);
+ end_ptr = addr_end;
+
+ /* allow IP(v6) address within [brackets] */
+ if(*addr_begin == '[') {
+ if(addr_end == addr_begin || *(addr_end - 1) != ']')
+ goto err;
+ ++addr_begin;
+ --addr_end;
+ }
- if(3 != sscanf(hostp->data, "%255[^:]:%d:%255s", hostname, &port,
- address)) {
- infof(data, "Couldn't parse CURLOPT_RESOLVE entry '%s'!\n",
- hostp->data);
- continue;
- }
+ alen = addr_end - addr_begin;
+ if(!alen)
+ continue;
+
+ if(alen >= sizeof(address))
+ goto err;
- /* allow IP(v6) address within [brackets] */
- if(address[0] == '[') {
- size_t alen = strlen(address);
- if(address[alen-1] != ']')
- /* it needs to also end with ] to be valid */
+ memcpy(address, addr_begin, alen);
+ address[alen] = '\0';
+
+#ifndef ENABLE_IPV6
+ if(strchr(address, ':')) {
+ infof(data, "Ignoring resolve address '%s', missing IPv6 support.\n",
+ address);
continue;
- address[alen-1] = 0; /* zero terminate there */
- address++; /* pass the open bracket */
+ }
+#endif
+
+ ai = Curl_str2addr(address, port);
+ if(!ai) {
+ infof(data, "Resolve address '%s' found illegal!\n", address);
+ goto err;
+ }
+
+ if(tail) {
+ tail->ai_next = ai;
+ tail = tail->ai_next;
+ }
+ else {
+ head = tail = ai;
+ }
}
- addr = Curl_str2addr(address, port);
- if(!addr) {
- infof(data, "Address in '%s' found illegal!\n", hostp->data);
+ if(!head)
+ goto err;
+
+ error = false;
+ err:
+ if(error) {
+ infof(data, "Couldn't parse CURLOPT_RESOLVE entry '%s'!\n",
+ hostp->data);
+ Curl_freeaddrinfo(head);
continue;
}
@@ -852,10 +999,9 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
entry_id = create_hostcache_id(hostname, port);
/* If we can't create the entry id, fail */
if(!entry_id) {
- Curl_freeaddrinfo(addr);
+ Curl_freeaddrinfo(head);
return CURLE_OUT_OF_MEMORY;
}
-
entry_len = strlen(entry_id);
if(data->share)
@@ -869,7 +1015,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
if(!dns) {
/* if not in the cache already, put this host in the cache */
- dns = Curl_cache_addr(data, addr, hostname, port);
+ dns = Curl_cache_addr(data, head, hostname, port);
if(dns) {
dns->timestamp = 0; /* mark as added by CURLOPT_RESOLVE */
/* release the returned reference; the cache itself will keep the
@@ -880,19 +1026,19 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
else {
/* this is a duplicate, free it again */
infof(data, "RESOLVE %s:%d is already cached, %s not stored!\n",
- hostname, port, address);
- Curl_freeaddrinfo(addr);
+ hostname, port, addresses);
+ Curl_freeaddrinfo(head);
}
if(data->share)
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
if(!dns) {
- Curl_freeaddrinfo(addr);
+ Curl_freeaddrinfo(head);
return CURLE_OUT_OF_MEMORY;
}
infof(data, "Added %s:%d:%s to DNS cache\n",
- hostname, port, address);
+ hostname, port, addresses);
}
}
data->change.resolve = NULL; /* dealt with now */
diff --git a/Utilities/cmcurl/lib/hostip.h b/Utilities/cmcurl/lib/hostip.h
index 298eeeee..1de4bee 100644
--- a/Utilities/cmcurl/lib/hostip.h
+++ b/Utilities/cmcurl/lib/hostip.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -182,6 +182,17 @@ struct Curl_dns_entry *
Curl_fetch_addr(struct connectdata *conn,
const char *hostname,
int port);
+
+/*
+ * Curl_shuffle_addr() shuffles the order of addresses in a 'Curl_addrinfo'
+ * struct by re-linking its linked list.
+ *
+ * The addr argument should be the address of a pointer to the head node of a
+ * `Curl_addrinfo` list and it will be modified to point to the new head after
+ * shuffling.
+ */
+CURLcode Curl_shuffle_addr(struct Curl_easy *data, Curl_addrinfo **addr);
+
/*
* Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
*
diff --git a/Utilities/cmcurl/lib/http.c b/Utilities/cmcurl/lib/http.c
index a500767..ff1d681 100644
--- a/Utilities/cmcurl/lib/http.c
+++ b/Utilities/cmcurl/lib/http.c
@@ -92,6 +92,8 @@ static int http_getsock_do(struct connectdata *conn,
int numsocks);
static int http_should_fail(struct connectdata *conn);
+static CURLcode add_haproxy_protocol_header(struct connectdata *conn);
+
#ifdef USE_SSL
static CURLcode https_connecting(struct connectdata *conn, bool *done);
static int https_getsock(struct connectdata *conn,
@@ -177,9 +179,9 @@ CURLcode Curl_http_setup_conn(struct connectdata *conn)
* if proxy headers are not available, then it will lookup into http header
* link list
*
- * It takes a connectdata struct as input instead of the Curl_easy simply
- * to know if this is a proxy request or not, as it then might check a
- * different header list.
+ * It takes a connectdata struct as input instead of the Curl_easy simply to
+ * know if this is a proxy request or not, as it then might check a different
+ * header list. Provide the header prefix without colon!.
*/
char *Curl_checkProxyheaders(const struct connectdata *conn,
const char *thisheader)
@@ -191,7 +193,8 @@ char *Curl_checkProxyheaders(const struct connectdata *conn,
for(head = (conn->bits.proxy && data->set.sep_headers) ?
data->set.proxyheaders : data->set.headers;
head; head = head->next) {
- if(strncasecompare(head->data, thisheader, thislen))
+ if(strncasecompare(head->data, thisheader, thislen) &&
+ Curl_headersep(head->data[thislen]))
return head->data;
}
@@ -211,8 +214,6 @@ char *Curl_copy_header_value(const char *header)
char *value;
size_t len;
- DEBUGASSERT(header);
-
/* Find the end of the header name */
while(*header && (*header != ':'))
++header;
@@ -432,7 +433,7 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
data left to send, keep on sending. */
/* rewind data when completely done sending! */
- if(!conn->bits.authneg) {
+ if(!conn->bits.authneg && (conn->writesockfd != CURL_SOCKET_BAD)) {
conn->bits.rewindaftersend = TRUE;
infof(data, "Rewind stream after send\n");
}
@@ -614,9 +615,9 @@ output_auth_headers(struct connectdata *conn,
if(authstatus->picked == CURLAUTH_BASIC) {
/* Basic */
if((proxy && conn->bits.proxy_user_passwd &&
- !Curl_checkProxyheaders(conn, "Proxy-authorization:")) ||
+ !Curl_checkProxyheaders(conn, "Proxy-authorization")) ||
(!proxy && conn->bits.user_passwd &&
- !Curl_checkheaders(conn, "Authorization:"))) {
+ !Curl_checkheaders(conn, "Authorization"))) {
auth = "Basic";
result = http_output_basic(conn, proxy);
if(result)
@@ -1357,6 +1358,13 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
/* nothing else to do except wait right now - we're not done here. */
return CURLE_OK;
+ if(conn->data->set.haproxyprotocol) {
+ /* add HAProxy PROXY protocol header */
+ result = add_haproxy_protocol_header(conn);
+ if(result)
+ return result;
+ }
+
if(conn->given->protocol & CURLPROTO_HTTPS) {
/* perform SSL initialization */
result = https_connecting(conn, done);
@@ -1382,6 +1390,47 @@ static int http_getsock_do(struct connectdata *conn,
return GETSOCK_WRITESOCK(0);
}
+static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
+{
+ char proxy_header[128];
+ Curl_send_buffer *req_buffer;
+ CURLcode result;
+ char tcp_version[5];
+
+ /* Emit the correct prefix for IPv6 */
+ if(conn->bits.ipv6) {
+ strcpy(tcp_version, "TCP6");
+ }
+ else {
+ strcpy(tcp_version, "TCP4");
+ }
+
+ snprintf(proxy_header,
+ sizeof proxy_header,
+ "PROXY %s %s %s %li %li\r\n",
+ tcp_version,
+ conn->data->info.conn_local_ip,
+ conn->data->info.conn_primary_ip,
+ conn->data->info.conn_local_port,
+ conn->data->info.conn_primary_port);
+
+ req_buffer = Curl_add_buffer_init();
+ if(!req_buffer)
+ return CURLE_OUT_OF_MEMORY;
+
+ result = Curl_add_bufferf(req_buffer, proxy_header);
+ if(result)
+ return result;
+
+ result = Curl_add_buffer_send(req_buffer,
+ conn,
+ &conn->data->info.request_size,
+ 0,
+ FIRSTSOCKET);
+
+ return result;
+}
+
#ifdef USE_SSL
static CURLcode https_connecting(struct connectdata *conn, bool *done)
{
@@ -1533,7 +1582,7 @@ static CURLcode expect100(struct Curl_easy *data,
/* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an
Expect: 100-continue to the headers which actually speeds up post
operations (as there is one packet coming back from the web server) */
- ptr = Curl_checkheaders(conn, "Expect:");
+ ptr = Curl_checkheaders(conn, "Expect");
if(ptr) {
data->state.expect100header =
Curl_compareheader(ptr, "Expect:", "100-continue");
@@ -1598,7 +1647,32 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
headers = h[i];
while(headers) {
+ char *semicolonp = NULL;
ptr = strchr(headers->data, ':');
+ if(!ptr) {
+ char *optr;
+ /* no colon, semicolon? */
+ ptr = strchr(headers->data, ';');
+ if(ptr) {
+ optr = ptr;
+ ptr++; /* pass the semicolon */
+ while(*ptr && ISSPACE(*ptr))
+ ptr++;
+
+ if(*ptr) {
+ /* this may be used for something else in the future */
+ optr = NULL;
+ }
+ else {
+ if(*(--ptr) == ';') {
+ /* send no-value custom header if terminated by semicolon */
+ *ptr = ':';
+ semicolonp = ptr;
+ }
+ }
+ ptr = optr;
+ }
+ }
if(ptr) {
/* we require a colon for this to be a true header */
@@ -1606,8 +1680,9 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
while(*ptr && ISSPACE(*ptr))
ptr++;
- if(*ptr) {
- /* only send this if the contents was non-blank */
+ if(*ptr || semicolonp) {
+ /* only send this if the contents was non-blank or done special */
+ CURLcode result = CURLE_OK;
if(conn->allocptr.host &&
/* a Host: header was sent already, don't pass on any custom Host:
@@ -1645,40 +1720,12 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
!strcasecompare(data->state.first_host, conn->host.name)))
;
else {
- CURLcode result = Curl_add_bufferf(req_buffer, "%s\r\n",
- headers->data);
- if(result)
- return result;
- }
- }
- }
- else {
- ptr = strchr(headers->data, ';');
- if(ptr) {
-
- ptr++; /* pass the semicolon */
- while(*ptr && ISSPACE(*ptr))
- ptr++;
-
- if(*ptr) {
- /* this may be used for something else in the future */
- }
- else {
- if(*(--ptr) == ';') {
- CURLcode result;
-
- /* send no-value custom header if terminated by semicolon */
- *ptr = ':';
- result = Curl_add_bufferf(req_buffer, "%s\r\n",
- headers->data);
-
- /* restore the previous value */
- *ptr = ';';
-
- if(result)
- return result;
- }
+ result = Curl_add_bufferf(req_buffer, "%s\r\n", headers->data);
}
+ if(semicolonp)
+ *semicolonp = ';'; /* put back the semicolon */
+ if(result)
+ return result;
}
}
headers = headers->next;
@@ -1869,7 +1916,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
it might have been used in the proxy connect, but if we have got a header
with the user-agent string specified, we erase the previously made string
here. */
- if(Curl_checkheaders(conn, "User-Agent:")) {
+ if(Curl_checkheaders(conn, "User-Agent")) {
free(conn->allocptr.uagent);
conn->allocptr.uagent = NULL;
}
@@ -1890,7 +1937,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
conn->bits.authneg = FALSE;
Curl_safefree(conn->allocptr.ref);
- if(data->change.referer && !Curl_checkheaders(conn, "Referer:")) {
+ if(data->change.referer && !Curl_checkheaders(conn, "Referer")) {
conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
if(!conn->allocptr.ref)
return CURLE_OUT_OF_MEMORY;
@@ -1899,11 +1946,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
conn->allocptr.ref = NULL;
#if !defined(CURL_DISABLE_COOKIES)
- if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(conn, "Cookie:"))
+ if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(conn, "Cookie"))
addcookies = data->set.str[STRING_COOKIE];
#endif
- if(!Curl_checkheaders(conn, "Accept-Encoding:") &&
+ if(!Curl_checkheaders(conn, "Accept-Encoding") &&
data->set.str[STRING_ENCODING]) {
Curl_safefree(conn->allocptr.accept_encoding);
conn->allocptr.accept_encoding =
@@ -1919,22 +1966,29 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
#ifdef HAVE_LIBZ
/* we only consider transfer-encoding magic if libz support is built-in */
- if(!Curl_checkheaders(conn, "TE:") &&
+ if(!Curl_checkheaders(conn, "TE") &&
data->set.http_transfer_encoding) {
/* When we are to insert a TE: header in the request, we must also insert
TE in a Connection: header, so we need to merge the custom provided
Connection: header and prevent the original to get sent. Note that if
the user has inserted his/hers own TE: header we don't do this magic
but then assume that the user will handle it all! */
- char *cptr = Curl_checkheaders(conn, "Connection:");
+ char *cptr = Curl_checkheaders(conn, "Connection");
#define TE_HEADER "TE: gzip\r\n"
Curl_safefree(conn->allocptr.te);
+ if(cptr) {
+ cptr = Curl_copy_header_value(cptr);
+ if(!cptr)
+ return CURLE_OUT_OF_MEMORY;
+ }
+
/* Create the (updated) Connection: header */
- conn->allocptr.te = cptr? aprintf("%s, TE\r\n" TE_HEADER, cptr):
- strdup("Connection: TE\r\n" TE_HEADER);
+ conn->allocptr.te = aprintf("Connection: %s%sTE\r\n" TE_HEADER,
+ cptr ? cptr : "", (cptr && *cptr) ? ", ":"");
+ free(cptr);
if(!conn->allocptr.te)
return CURLE_OUT_OF_MEMORY;
}
@@ -1958,7 +2012,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
if(http->sendit) {
- const char *cthdr = Curl_checkheaders(conn, "Content-Type:");
+ const char *cthdr = Curl_checkheaders(conn, "Content-Type");
/* Read and seek body only. */
http->sendit->flags |= MIME_BODY_ONLY;
@@ -1982,7 +2036,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
http->postsize = Curl_mime_size(http->sendit);
}
- ptr = Curl_checkheaders(conn, "Transfer-Encoding:");
+ ptr = Curl_checkheaders(conn, "Transfer-Encoding");
if(ptr) {
/* Some kind of TE is requested, check if 'chunked' is chosen */
data->req.upload_chunky =
@@ -2016,7 +2070,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
Curl_safefree(conn->allocptr.host);
- ptr = Curl_checkheaders(conn, "Host:");
+ ptr = Curl_checkheaders(conn, "Host");
if(ptr && (!data->state.this_is_a_follow ||
strcasecompare(data->state.first_host, conn->host.name))) {
#if !defined(CURL_DISABLE_COOKIES)
@@ -2055,7 +2109,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
#endif
if(strcmp("Host:", ptr)) {
- conn->allocptr.host = aprintf("%s\r\n", ptr);
+ conn->allocptr.host = aprintf("Host:%s\r\n", &ptr[5]);
if(!conn->allocptr.host)
return CURLE_OUT_OF_MEMORY;
}
@@ -2078,7 +2132,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
host,
conn->bits.ipv6_ip?"]":"");
else
- conn->allocptr.host = aprintf("Host: %s%s%s:%hu\r\n",
+ conn->allocptr.host = aprintf("Host: %s%s%s:%d\r\n",
conn->bits.ipv6_ip?"[":"",
host,
conn->bits.ipv6_ip?"]":"",
@@ -2164,7 +2218,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
#endif /* CURL_DISABLE_PROXY */
- http->p_accept = Curl_checkheaders(conn, "Accept:")?NULL:"Accept: */*\r\n";
+ http->p_accept = Curl_checkheaders(conn, "Accept")?NULL:"Accept: */*\r\n";
if((HTTPREQ_POST == httpreq || HTTPREQ_PUT == httpreq) &&
data->state.resume_from) {
@@ -2191,8 +2245,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* Now, let's read off the proper amount of bytes from the
input. */
if(conn->seek_func) {
+ Curl_set_in_callback(data, true);
seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
SEEK_SET);
+ Curl_set_in_callback(data, false);
}
if(seekerr != CURL_SEEKFUNC_OK) {
@@ -2243,14 +2299,14 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
* ones if any such are specified.
*/
if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) &&
- !Curl_checkheaders(conn, "Range:")) {
+ !Curl_checkheaders(conn, "Range")) {
/* if a line like this was already allocated, free the previous one */
free(conn->allocptr.rangeline);
conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n",
data->state.range);
}
else if((httpreq == HTTPREQ_POST || httpreq == HTTPREQ_PUT) &&
- !Curl_checkheaders(conn, "Content-Range:")) {
+ !Curl_checkheaders(conn, "Content-Range")) {
/* if a line like this was already allocated, free the previous one */
free(conn->allocptr.rangeline);
@@ -2352,7 +2408,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
conn->allocptr.ref:"" /* Referer: <data> */,
(conn->bits.httpproxy &&
!conn->bits.tunnel_proxy &&
- !Curl_checkProxyheaders(conn, "Proxy-Connection:"))?
+ !Curl_checkProxyheaders(conn, "Proxy-Connection"))?
"Proxy-Connection: Keep-Alive\r\n":"",
te
);
@@ -2453,7 +2509,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
postsize = data->state.infilesize;
if((postsize != -1) && !data->req.upload_chunky &&
- (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length:"))) {
+ (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) {
/* only add Content-Length if not uploading chunked */
result = Curl_add_bufferf(req_buffer,
"Content-Length: %" CURL_FORMAT_CURL_OFF_T
@@ -2515,7 +2571,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
we don't upload data chunked, as RFC2616 forbids us to set both
kinds of headers (Transfer-Encoding: chunked and Content-Length) */
if(postsize != -1 && !data->req.upload_chunky &&
- (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length:"))) {
+ (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) {
/* we allow replacing this header if not during auth negotiation,
although it isn't very wise to actually set your own */
result = Curl_add_bufferf(req_buffer,
@@ -2540,7 +2596,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
the somewhat bigger ones we allow the app to disable it. Just make
sure that the expect100header is always set to the preferred value
here. */
- ptr = Curl_checkheaders(conn, "Expect:");
+ ptr = Curl_checkheaders(conn, "Expect");
if(ptr) {
data->state.expect100header =
Curl_compareheader(ptr, "Expect:", "100-continue");
@@ -2594,7 +2650,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
we don't upload data chunked, as RFC2616 forbids us to set both
kinds of headers (Transfer-Encoding: chunked and Content-Length) */
if((postsize != -1) && !data->req.upload_chunky &&
- (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length:"))) {
+ (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) {
/* we allow replacing this header if not during auth negotiation,
although it isn't very wise to actually set your own */
result = Curl_add_bufferf(req_buffer,
@@ -2604,7 +2660,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
return result;
}
- if(!Curl_checkheaders(conn, "Content-Type:")) {
+ if(!Curl_checkheaders(conn, "Content-Type")) {
result = Curl_add_bufferf(req_buffer,
"Content-Type: application/"
"x-www-form-urlencoded\r\n");
@@ -2616,7 +2672,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
the somewhat bigger ones we allow the app to disable it. Just make
sure that the expect100header is always set to the preferred value
here. */
- ptr = Curl_checkheaders(conn, "Expect:");
+ ptr = Curl_checkheaders(conn, "Expect");
if(ptr) {
data->state.expect100header =
Curl_compareheader(ptr, "Expect:", "100-continue");
@@ -2878,20 +2934,19 @@ static CURLcode header_append(struct Curl_easy *data,
struct SingleRequest *k,
size_t length)
{
- if(k->hbuflen + length >= data->state.headersize) {
+ size_t newsize = k->hbuflen + length;
+ if(newsize > CURL_MAX_HTTP_HEADER) {
+ /* 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, "Rejected %zd bytes header (max is %d)!", newsize,
+ CURL_MAX_HTTP_HEADER);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ if(newsize >= data->state.headersize) {
/* We enlarge the header buffer as it is too small */
char *newbuff;
size_t hbufp_index;
- size_t newsize;
-
- if(k->hbuflen + length > CURL_MAX_HTTP_HEADER) {
- /* 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);
- return CURLE_OUT_OF_MEMORY;
- }
newsize = CURLMAX((k->hbuflen + length) * 3 / 2, data->state.headersize*2);
hbufp_index = k->hbufp - data->state.headerbuff;
@@ -2959,6 +3014,8 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
{
CURLcode result;
struct SingleRequest *k = &data->req;
+ ssize_t onread = *nread;
+ char *ostr = k->str;
/* header line within buffer loop */
do {
@@ -3023,7 +3080,9 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
else {
/* this was all we read so it's all a bad header */
k->badheader = HEADER_ALLBAD;
- *nread = (ssize_t)rest_length;
+ *nread = onread;
+ k->str = ostr;
+ return CURLE_OK;
}
break;
}
@@ -3677,7 +3736,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
CURL_LOCK_ACCESS_SINGLE);
Curl_cookie_add(data,
- data->cookies, TRUE, k->p + 11,
+ data->cookies, TRUE, FALSE, k->p + 11,
/* If there is a custom-set Host: name, use it
here, or else use real peer host name. */
conn->allocptr.cookiehost?
@@ -3692,7 +3751,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
k->timeofdoc = curl_getdate(k->p + strlen("Last-Modified:"),
&secs);
if(data->set.get_filetime)
- data->info.filetime = (long)k->timeofdoc;
+ data->info.filetime = k->timeofdoc;
}
else if((checkprefix("WWW-Authenticate:", k->p) &&
(401 == k->httpcode)) ||
diff --git a/Utilities/cmcurl/lib/http.h b/Utilities/cmcurl/lib/http.h
index d2781bc..1d373e8 100644
--- a/Utilities/cmcurl/lib/http.h
+++ b/Utilities/cmcurl/lib/http.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -104,7 +104,7 @@ CURLcode Curl_http_perhapsrewind(struct connectdata *conn);
This value used to be fairly big (100K), but we must take into account that
if the server rejects the POST due for authentication reasons, this data
- will always be uncondtionally sent and thus it may not be larger than can
+ will always be unconditionally sent and thus it may not be larger than can
always be afforded to send twice.
It must not be greater than 64K to work on VMS.
@@ -172,8 +172,6 @@ struct HTTP {
size_t pauselen; /* the number of bytes left in data */
bool closed; /* TRUE on HTTP2 stream close */
bool close_handled; /* TRUE if stream closure is handled by libcurl */
- uint32_t error_code; /* HTTP/2 error code */
-
char *mem; /* points to a buffer in memory to store received data */
size_t len; /* size of the buffer 'mem' points to */
size_t memlen; /* size of data copied to mem */
@@ -188,9 +186,6 @@ struct HTTP {
#endif
};
-typedef int (*sending)(void); /* Curl_send */
-typedef int (*recving)(void); /* Curl_recv */
-
#ifdef USE_NGHTTP2
/* h2 settings for this connection */
struct h2settings {
@@ -199,15 +194,14 @@ struct h2settings {
};
#endif
-
struct http_conn {
#ifdef USE_NGHTTP2
#define H2_BINSETTINGS_LEN 80
nghttp2_session *h2;
uint8_t binsettings[H2_BINSETTINGS_LEN];
size_t binlen; /* length of the binsettings data */
- sending send_underlying; /* underlying send Curl_send callback */
- recving recv_underlying; /* underlying recv Curl_recv callback */
+ Curl_send *send_underlying; /* underlying send Curl_send callback */
+ Curl_recv *recv_underlying; /* underlying recv Curl_recv callback */
char *inbuf; /* buffer to receive data from underlying socket */
size_t inbuflen; /* number of bytes filled in inbuf */
size_t nread_inbuf; /* number of bytes read from in inbuf */
@@ -226,6 +220,7 @@ struct http_conn {
/* list of settings that will be sent */
nghttp2_settings_entry local_settings[3];
size_t local_settings_num;
+ uint32_t error_code; /* HTTP/2 error code */
#else
int unused; /* prevent a compiler warning */
#endif
diff --git a/Utilities/cmcurl/lib/http2.c b/Utilities/cmcurl/lib/http2.c
index 6992879..da001df 100644
--- a/Utilities/cmcurl/lib/http2.c
+++ b/Utilities/cmcurl/lib/http2.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, 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,7 @@
#include "curl_memory.h"
#include "memdebug.h"
+#define H2_BUFSIZE 32768
#define MIN(x,y) ((x)<(y)?(x):(y))
#if (NGHTTP2_VERSION_NUM < 0x010000)
@@ -65,6 +66,22 @@
#define HTTP2_HUGE_WINDOW_SIZE (1 << 30)
+#ifdef DEBUG_HTTP2
+#define H2BUGF(x) x
+#else
+#define H2BUGF(x) do { } WHILE_FALSE
+#endif
+
+
+static ssize_t http2_recv(struct connectdata *conn, int sockindex,
+ char *mem, size_t len, CURLcode *err);
+static bool http2_connisdead(struct connectdata *conn);
+static int h2_session_send(struct Curl_easy *data,
+ nghttp2_session *h2);
+static int h2_process_pending_input(struct connectdata *conn,
+ struct http_conn *httpc,
+ CURLcode *err);
+
/*
* Curl_http2_init_state() is called when the easy handle is created and
* allows for HTTP/2 specific init of state.
@@ -91,6 +108,7 @@ static int http2_perform_getsock(const struct connectdata *conn,
int numsocks)
{
const struct http_conn *c = &conn->proto.httpc;
+ struct SingleRequest *k = &conn->data->req;
int bitmap = GETSOCK_BLANK;
(void)numsocks;
@@ -102,7 +120,9 @@ static int http2_perform_getsock(const struct connectdata *conn,
always be ready for one */
bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
- if(nghttp2_session_want_write(c->h2))
+ /* we're still uploading or the HTTP/2 layer wants to send data */
+ if(((k->keepon & (KEEP_SEND|KEEP_SEND_PAUSE)) == KEEP_SEND) ||
+ nghttp2_session_want_write(c->h2))
bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
return bitmap;
@@ -140,13 +160,14 @@ static CURLcode http2_disconnect(struct connectdata *conn,
struct http_conn *c = &conn->proto.httpc;
(void)dead_connection;
- DEBUGF(infof(conn->data, "HTTP/2 DISCONNECT starts now\n"));
+ H2BUGF(infof(conn->data, "HTTP/2 DISCONNECT starts now\n"));
nghttp2_session_del(c->h2);
Curl_safefree(c->inbuf);
http2_stream_free(conn->data->req.protop);
+ conn->data->state.drain = 0;
- DEBUGF(infof(conn->data, "HTTP/2 DISCONNECT done\n"));
+ H2BUGF(infof(conn->data, "HTTP/2 DISCONNECT done\n"));
return CURLE_OK;
}
@@ -158,29 +179,54 @@ static CURLcode http2_disconnect(struct connectdata *conn,
* Instead, if it is readable, run Curl_connalive() to peek at the socket
* and distinguish between closed and data.
*/
-static bool http2_connisdead(struct connectdata *check)
+static bool http2_connisdead(struct connectdata *conn)
{
int sval;
- bool ret_val = TRUE;
+ bool dead = TRUE;
- sval = SOCKET_READABLE(check->sock[FIRSTSOCKET], 0);
+ if(conn->bits.close)
+ return TRUE;
+
+ sval = SOCKET_READABLE(conn->sock[FIRSTSOCKET], 0);
if(sval == 0) {
/* timeout */
- ret_val = FALSE;
+ dead = FALSE;
}
else if(sval & CURL_CSELECT_ERR) {
/* socket is in an error state */
- ret_val = TRUE;
+ dead = TRUE;
}
else if(sval & CURL_CSELECT_IN) {
/* readable with no error. could still be closed */
- ret_val = !Curl_connalive(check);
+ dead = !Curl_connalive(conn);
+ if(!dead) {
+ /* This happens before we've sent off a request and the connection is
+ not in use by any other thransfer, there shouldn't be any data here,
+ only "protocol frames" */
+ CURLcode result;
+ struct http_conn *httpc = &conn->proto.httpc;
+ ssize_t nread = -1;
+ if(httpc->recv_underlying)
+ /* if called "too early", this pointer isn't setup yet! */
+ nread = ((Curl_recv *)httpc->recv_underlying)(
+ conn, FIRSTSOCKET, httpc->inbuf, H2_BUFSIZE, &result);
+ if(nread != -1) {
+ infof(conn->data,
+ "%d bytes stray data read before trying h2 connection\n",
+ (int)nread);
+ httpc->nread_inbuf = 0;
+ httpc->inbuflen = nread;
+ (void)h2_process_pending_input(conn, httpc, &result);
+ }
+ else
+ /* the read failed so let's say this is dead anyway */
+ dead = TRUE;
+ }
}
- return ret_val;
+ return dead;
}
-
static unsigned int http2_conncheck(struct connectdata *check,
unsigned int checks_to_perform)
{
@@ -204,7 +250,6 @@ void Curl_http2_setup_req(struct Curl_easy *data)
http->status_code = -1;
http->pausedata = NULL;
http->pauselen = 0;
- http->error_code = NGHTTP2_NO_ERROR;
http->closed = FALSE;
http->close_handled = FALSE;
http->mem = data->state.buffer;
@@ -217,6 +262,7 @@ void Curl_http2_setup_conn(struct connectdata *conn)
{
conn->proto.httpc.settings.max_concurrent_streams =
DEFAULT_MAX_CONCURRENT_STREAMS;
+ conn->proto.httpc.error_code = NGHTTP2_NO_ERROR;
}
/*
@@ -428,7 +474,7 @@ static int push_promise(struct Curl_easy *data,
const nghttp2_push_promise *frame)
{
int rv;
- DEBUGF(infof(data, "PUSH_PROMISE received, stream %u!\n",
+ H2BUGF(infof(data, "PUSH_PROMISE received, stream %u!\n",
frame->promised_stream_id));
if(data->multi->push_cb) {
struct HTTP *stream;
@@ -448,7 +494,7 @@ static int push_promise(struct Curl_easy *data,
heads.data = data;
heads.frame = frame;
/* ask the application */
- DEBUGF(infof(data, "Got PUSH_PROMISE, ask application!\n"));
+ H2BUGF(infof(data, "Got PUSH_PROMISE, ask application!\n"));
stream = data->req.protop;
if(!stream) {
@@ -458,9 +504,11 @@ static int push_promise(struct Curl_easy *data,
goto fail;
}
+ Curl_set_in_callback(data, true);
rv = data->multi->push_cb(data, newhandle,
stream->push_headers_used, &heads,
data->multi->push_userp);
+ Curl_set_in_callback(data, false);
/* free the headers again */
for(i = 0; i<stream->push_headers_used; i++)
@@ -497,7 +545,7 @@ static int push_promise(struct Curl_easy *data,
frame->promised_stream_id, newhandle);
}
else {
- DEBUGF(infof(data, "Got PUSH_PROMISE, ignore it!\n"));
+ H2BUGF(infof(data, "Got PUSH_PROMISE, ignore it!\n"));
rv = 1;
}
fail:
@@ -511,7 +559,6 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
struct http_conn *httpc = &conn->proto.httpc;
struct Curl_easy *data_s = NULL;
struct HTTP *stream = NULL;
- static int lastStream = -1;
int rv;
size_t left, ncopy;
int32_t stream_id = frame->hd.stream_id;
@@ -520,32 +567,30 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
/* stream ID zero is for connection-oriented stuff */
if(frame->hd.type == NGHTTP2_SETTINGS) {
uint32_t max_conn = httpc->settings.max_concurrent_streams;
- DEBUGF(infof(conn->data, "Got SETTINGS\n"));
+ H2BUGF(infof(conn->data, "Got SETTINGS\n"));
httpc->settings.max_concurrent_streams =
nghttp2_session_get_remote_settings(
session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS);
httpc->settings.enable_push =
nghttp2_session_get_remote_settings(
session, NGHTTP2_SETTINGS_ENABLE_PUSH);
- DEBUGF(infof(conn->data, "MAX_CONCURRENT_STREAMS == %d\n",
+ H2BUGF(infof(conn->data, "MAX_CONCURRENT_STREAMS == %d\n",
httpc->settings.max_concurrent_streams));
- DEBUGF(infof(conn->data, "ENABLE_PUSH == %s\n",
+ H2BUGF(infof(conn->data, "ENABLE_PUSH == %s\n",
httpc->settings.enable_push?"TRUE":"false"));
if(max_conn != httpc->settings.max_concurrent_streams) {
/* only signal change if the value actually changed */
infof(conn->data,
- "Connection state changed (MAX_CONCURRENT_STREAMS updated)!\n");
+ "Connection state changed (MAX_CONCURRENT_STREAMS == %d)!\n",
+ httpc->settings.max_concurrent_streams);
Curl_multi_connchanged(conn->data->multi);
}
}
return 0;
}
data_s = nghttp2_session_get_stream_user_data(session, stream_id);
- if(lastStream != stream_id) {
- lastStream = stream_id;
- }
if(!data_s) {
- DEBUGF(infof(conn->data,
+ H2BUGF(infof(conn->data,
"No Curl_easy associated with stream: %x\n",
stream_id));
return 0;
@@ -553,12 +598,12 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
stream = data_s->req.protop;
if(!stream) {
- DEBUGF(infof(conn->data, "No proto pointer for stream: %x\n",
+ H2BUGF(infof(data_s, "No proto pointer for stream: %x\n",
stream_id));
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
- DEBUGF(infof(data_s, "on_frame_recv() header %x stream %x\n",
+ H2BUGF(infof(data_s, "on_frame_recv() header %x stream %x\n",
frame->hd.type, stream_id));
switch(frame->hd.type) {
@@ -581,8 +626,10 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
}
/* nghttp2 guarantees that :status is received, and we store it to
- stream->status_code */
- DEBUGASSERT(stream->status_code != -1);
+ stream->status_code. Fuzzing has proven this can still be reached
+ without status code having been set. */
+ if(stream->status_code == -1)
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
/* Only final status code signals the end of header */
if(stream->status_code / 100 != 1) {
@@ -600,7 +647,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
ncopy);
stream->nread_header_recvbuf += ncopy;
- DEBUGF(infof(data_s, "Store %zu bytes headers from stream %u at %p\n",
+ H2BUGF(infof(data_s, "Store %zu bytes headers from stream %u at %p\n",
ncopy, stream_id, stream->mem));
stream->len -= ncopy;
@@ -629,7 +676,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
}
break;
default:
- DEBUGF(infof(conn->data, "Got frame type %x for stream %u!\n",
+ H2BUGF(infof(data_s, "Got frame type %x for stream %u!\n",
frame->hd.type, stream_id));
break;
}
@@ -642,13 +689,13 @@ static int on_invalid_frame_recv(nghttp2_session *session,
{
struct Curl_easy *data_s = NULL;
(void)userp;
-#if !defined(DEBUGBUILD) || defined(CURL_DISABLE_VERBOSE_STRINGS)
+#if !defined(DEBUG_HTTP2) || defined(CURL_DISABLE_VERBOSE_STRINGS)
(void)lib_error_code;
#endif
data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
if(data_s) {
- DEBUGF(infof(data_s,
+ H2BUGF(infof(data_s,
"on_invalid_frame_recv() was called, error=%d:%s\n",
lib_error_code, nghttp2_strerror(lib_error_code)));
}
@@ -693,7 +740,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
if(conn->data != data_s)
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
- DEBUGF(infof(data_s, "%zu data received for stream %u "
+ H2BUGF(infof(data_s, "%zu data received for stream %u "
"(%zu left in buffer %p, total %zu)\n",
nread, stream_id,
stream->len, stream->mem,
@@ -702,7 +749,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
if(nread < len) {
stream->pausedata = data + nread;
stream->pauselen = len - nread;
- DEBUGF(infof(data_s, "NGHTTP2_ERR_PAUSE - %zu bytes out of buffer"
+ H2BUGF(infof(data_s, "NGHTTP2_ERR_PAUSE - %zu bytes out of buffer"
", stream %u\n",
len - nread, stream_id));
data_s->easy_conn->proto.httpc.pause_stream_id = stream_id;
@@ -730,7 +777,7 @@ static int before_frame_send(nghttp2_session *session,
data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
if(data_s) {
- DEBUGF(infof(data_s, "before_frame_send() was called\n"));
+ H2BUGF(infof(data_s, "before_frame_send() was called\n"));
}
return 0;
@@ -744,7 +791,7 @@ static int on_frame_send(nghttp2_session *session,
data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
if(data_s) {
- DEBUGF(infof(data_s, "on_frame_send() was called, length = %zd\n",
+ H2BUGF(infof(data_s, "on_frame_send() was called, length = %zd\n",
frame->hd.length));
}
return 0;
@@ -755,13 +802,13 @@ static int on_frame_not_send(nghttp2_session *session,
{
struct Curl_easy *data_s;
(void)userp;
-#if !defined(DEBUGBUILD) || defined(CURL_DISABLE_VERBOSE_STRINGS)
+#if !defined(DEBUG_HTTP2) || defined(CURL_DISABLE_VERBOSE_STRINGS)
(void)lib_error_code;
#endif
data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
if(data_s) {
- DEBUGF(infof(data_s,
+ H2BUGF(infof(data_s,
"on_frame_not_send() was called, lib_error_code = %d\n",
lib_error_code));
}
@@ -777,6 +824,7 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
(void)stream_id;
if(stream_id) {
+ struct http_conn *httpc;
/* get the stream from the hash based on Stream ID, stream ID zero is for
connection-oriented stuff */
data_s = nghttp2_session_get_stream_user_data(session, stream_id);
@@ -785,20 +833,21 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
decided to reject stream (e.g., PUSH_PROMISE). */
return 0;
}
- DEBUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u\n",
+ H2BUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u\n",
Curl_http2_strerror(error_code), error_code, stream_id));
stream = data_s->req.protop;
if(!stream)
return NGHTTP2_ERR_CALLBACK_FAILURE;
- stream->error_code = error_code;
stream->closed = TRUE;
data_s->state.drain++;
- conn->proto.httpc.drain_total++;
+ httpc = &conn->proto.httpc;
+ httpc->drain_total++;
+ httpc->error_code = error_code;
/* remove the entry from the hash as the stream is now gone */
nghttp2_session_set_stream_user_data(session, stream_id, 0);
- DEBUGF(infof(data_s, "Removed stream %u hash!\n", stream_id));
+ H2BUGF(infof(data_s, "Removed stream %u hash!\n", stream_id));
}
return 0;
}
@@ -815,7 +864,7 @@ static int on_begin_headers(nghttp2_session *session,
return 0;
}
- DEBUGF(infof(data_s, "on_begin_headers() was called\n"));
+ H2BUGF(infof(data_s, "on_begin_headers() was called\n"));
if(frame->hd.type != NGHTTP2_HEADERS) {
return 0;
@@ -826,16 +875,12 @@ static int on_begin_headers(nghttp2_session *session,
return 0;
}
- /* This is trailer HEADERS started. Allocate buffer for them. */
- DEBUGF(infof(data_s, "trailer field started\n"));
-
- DEBUGASSERT(stream->trailer_recvbuf == NULL);
-
- stream->trailer_recvbuf = Curl_add_buffer_init();
if(!stream->trailer_recvbuf) {
- return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
+ stream->trailer_recvbuf = Curl_add_buffer_init();
+ if(!stream->trailer_recvbuf) {
+ return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
+ }
}
-
return 0;
}
@@ -928,7 +973,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
/* 4 is for ": " and "\r\n". */
uint32_t n = (uint32_t)(namelen + valuelen + 4);
- DEBUGF(infof(data_s, "h2 trailer: %.*s: %.*s\n", namelen, name, valuelen,
+ H2BUGF(infof(data_s, "h2 trailer: %.*s: %.*s\n", namelen, name, valuelen,
value));
Curl_add_buffer(stream->trailer_recvbuf, &n, sizeof(n));
@@ -956,7 +1001,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
if(conn->data != data_s)
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
- DEBUGF(infof(data_s, "h2 status: HTTP/2 %03d (easy %p)\n",
+ H2BUGF(infof(data_s, "h2 status: HTTP/2 %03d (easy %p)\n",
stream->status_code, data_s));
return 0;
}
@@ -972,7 +1017,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
if(conn->data != data_s)
Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
- DEBUGF(infof(data_s, "h2 header: %.*s: %.*s\n", namelen, name, valuelen,
+ H2BUGF(infof(data_s, "h2 header: %.*s: %.*s\n", namelen, name, valuelen,
value));
return 0; /* 0 is successful */
@@ -1021,15 +1066,13 @@ static ssize_t data_source_read_callback(nghttp2_session *session,
else if(nread == 0)
return NGHTTP2_ERR_DEFERRED;
- DEBUGF(infof(data_s, "data_source_read_callback: "
+ H2BUGF(infof(data_s, "data_source_read_callback: "
"returns %zu bytes stream %u\n",
nread, stream_id));
return nread;
}
-#define H2_BUFSIZE 32768
-
#ifdef NGHTTP2_HAS_ERROR_CALLBACK
static int error_callback(nghttp2_session *session,
const char *msg,
@@ -1067,7 +1110,6 @@ void Curl_http2_done(struct connectdata *conn, bool premature)
struct http_conn *httpc = &conn->proto.httpc;
if(http->header_recvbuf) {
- DEBUGF(infof(data, "free header_recvbuf!!\n"));
Curl_add_buffer_free(http->header_recvbuf);
http->header_recvbuf = NULL; /* clear the pointer */
Curl_add_buffer_free(http->trailer_recvbuf);
@@ -1216,22 +1258,20 @@ static int should_close_session(struct http_conn *httpc)
!nghttp2_session_want_write(httpc->h2);
}
-static int h2_session_send(struct Curl_easy *data,
- nghttp2_session *h2);
-
/*
* h2_process_pending_input() processes pending input left in
* httpc->inbuf. Then, call h2_session_send() to send pending data.
* This function returns 0 if it succeeds, or -1 and error code will
* be assigned to *err.
*/
-static int h2_process_pending_input(struct Curl_easy *data,
+static int h2_process_pending_input(struct connectdata *conn,
struct http_conn *httpc,
CURLcode *err)
{
ssize_t nread;
char *inbuf;
ssize_t rv;
+ struct Curl_easy *data = conn->data;
nread = httpc->inbuflen - httpc->nread_inbuf;
inbuf = httpc->inbuf + httpc->nread_inbuf;
@@ -1246,7 +1286,7 @@ static int h2_process_pending_input(struct Curl_easy *data,
}
if(nread == rv) {
- DEBUGF(infof(data,
+ H2BUGF(infof(data,
"h2_process_pending_input: All data in connection buffer "
"processed\n"));
httpc->inbuflen = 0;
@@ -1254,7 +1294,7 @@ static int h2_process_pending_input(struct Curl_easy *data,
}
else {
httpc->nread_inbuf += rv;
- DEBUGF(infof(data,
+ H2BUGF(infof(data,
"h2_process_pending_input: %zu bytes left in connection "
"buffer\n",
httpc->inbuflen - httpc->nread_inbuf));
@@ -1267,9 +1307,15 @@ static int h2_process_pending_input(struct Curl_easy *data,
}
if(should_close_session(httpc)) {
- DEBUGF(infof(data,
+ H2BUGF(infof(data,
"h2_process_pending_input: nothing to do in this session\n"));
- *err = CURLE_HTTP2;
+ if(httpc->error_code)
+ *err = CURLE_HTTP2;
+ else {
+ /* not an error per se, but should still close the connection */
+ connclose(conn, "GOAWAY received");
+ *err = CURLE_OK;
+ }
return -1;
}
@@ -1300,7 +1346,7 @@ CURLcode Curl_http2_done_sending(struct connectdata *conn)
that it can signal EOF to nghttp2 */
(void)nghttp2_session_resume_data(h2, stream->stream_id);
- (void)h2_process_pending_input(conn->data, httpc, &result);
+ (void)h2_process_pending_input(conn, httpc, &result);
}
}
return result;
@@ -1324,7 +1370,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
data->state.drain = 0;
if(httpc->pause_stream_id == 0) {
- if(h2_process_pending_input(data, httpc, err) != 0) {
+ if(h2_process_pending_input(conn, httpc, err) != 0) {
return -1;
}
}
@@ -1333,17 +1379,25 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
/* Reset to FALSE to prevent infinite loop in readwrite_data function. */
stream->closed = FALSE;
- if(stream->error_code != NGHTTP2_NO_ERROR) {
+ if(httpc->error_code == NGHTTP2_REFUSED_STREAM) {
+ H2BUGF(infof(data, "REFUSED_STREAM (%d), try again on a new connection!\n",
+ stream->stream_id));
+ connclose(conn, "REFUSED_STREAM"); /* don't use this anymore */
+ data->state.refused_stream = TRUE;
+ *err = CURLE_RECV_ERROR; /* trigger Curl_retry_request() later */
+ return -1;
+ }
+ else if(httpc->error_code != NGHTTP2_NO_ERROR) {
failf(data, "HTTP/2 stream %u was not closed cleanly: %s (err %d)",
- stream->stream_id, Curl_http2_strerror(stream->error_code),
- stream->error_code);
+ stream->stream_id, Curl_http2_strerror(httpc->error_code),
+ httpc->error_code);
*err = CURLE_HTTP2_STREAM;
return -1;
}
if(!stream->bodystarted) {
failf(data, "HTTP/2 stream %u was closed cleanly, but before getting "
- " all response header fields, teated as error",
+ " all response header fields, treated as error",
stream->stream_id);
*err = CURLE_HTTP2_STREAM;
return -1;
@@ -1370,7 +1424,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
stream->close_handled = TRUE;
- DEBUGF(infof(data, "http2_recv returns 0, http2_handle_stream_close\n"));
+ H2BUGF(infof(data, "http2_recv returns 0, http2_handle_stream_close\n"));
return 0;
}
@@ -1411,7 +1465,7 @@ static int h2_session_send(struct Curl_easy *data,
h2_pri_spec(data, &pri_spec);
- DEBUGF(infof(data, "Queuing PRIORITY on stream %u (easy %p)\n",
+ H2BUGF(infof(data, "Queuing PRIORITY on stream %u (easy %p)\n",
stream->stream_id, data));
rv = nghttp2_submit_priority(h2, NGHTTP2_FLAG_NONE, stream->stream_id,
&pri_spec);
@@ -1435,7 +1489,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
(void)sockindex; /* we always do HTTP2 on sockindex 0 */
if(should_close_session(httpc)) {
- DEBUGF(infof(data,
+ H2BUGF(infof(data,
"http2_recv: nothing to do in this session\n"));
*err = CURLE_HTTP2;
return -1;
@@ -1461,16 +1515,16 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
ncopy);
stream->nread_header_recvbuf += ncopy;
- DEBUGF(infof(data, "http2_recv: Got %d bytes from header_recvbuf\n",
+ H2BUGF(infof(data, "http2_recv: Got %d bytes from header_recvbuf\n",
(int)ncopy));
return ncopy;
}
- DEBUGF(infof(data, "http2_recv: easy %p (stream %u)\n",
+ H2BUGF(infof(data, "http2_recv: easy %p (stream %u)\n",
data, stream->stream_id));
if((data->state.drain) && stream->memlen) {
- DEBUGF(infof(data, "http2_recv: DRAIN %zu bytes stream %u!! (%p => %p)\n",
+ H2BUGF(infof(data, "http2_recv: DRAIN %zu bytes stream %u!! (%p => %p)\n",
stream->memlen, stream->stream_id,
stream->mem, mem));
if(mem != stream->mem) {
@@ -1484,7 +1538,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
/* We have paused nghttp2, but we have no pause data (see
on_data_chunk_recv). */
httpc->pause_stream_id = 0;
- if(h2_process_pending_input(data, httpc, &result) != 0) {
+ if(h2_process_pending_input(conn, httpc, &result) != 0) {
*err = result;
return -1;
}
@@ -1500,7 +1554,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
infof(data, "%zu data bytes written\n", nread);
if(stream->pauselen == 0) {
- DEBUGF(infof(data, "Unpaused by stream %u\n", stream->stream_id));
+ H2BUGF(infof(data, "Unpaused by stream %u\n", stream->stream_id));
DEBUGASSERT(httpc->pause_stream_id == stream->stream_id);
httpc->pause_stream_id = 0;
@@ -1514,12 +1568,12 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
frames, then we have to call it again with 0-length data.
Without this, on_stream_close callback will not be called,
and stream could be hanged. */
- if(h2_process_pending_input(data, httpc, &result) != 0) {
+ if(h2_process_pending_input(conn, httpc, &result) != 0) {
*err = result;
return -1;
}
}
- DEBUGF(infof(data, "http2_recv: returns unpaused %zd bytes on stream %u\n",
+ H2BUGF(infof(data, "http2_recv: returns unpaused %zd bytes on stream %u\n",
nread, stream->stream_id));
return nread;
}
@@ -1532,7 +1586,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
socket is not read. But it seems that usually streams are
notified with its drain property, and socket is read again
quickly. */
- DEBUGF(infof(data, "stream %x is paused, pause id: %x\n",
+ H2BUGF(infof(data, "stream %x is paused, pause id: %x\n",
stream->stream_id, httpc->pause_stream_id));
*err = CURLE_AGAIN;
return -1;
@@ -1561,12 +1615,12 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
}
if(nread == 0) {
- failf(data, "Unexpected EOF");
- *err = CURLE_RECV_ERROR;
- return -1;
+ H2BUGF(infof(data, "end of stream\n"));
+ *err = CURLE_OK;
+ return 0;
}
- DEBUGF(infof(data, "nread=%zd\n", nread));
+ H2BUGF(infof(data, "nread=%zd\n", nread));
httpc->inbuflen = nread;
inbuf = httpc->inbuf;
@@ -1575,7 +1629,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
nread = httpc->inbuflen - httpc->nread_inbuf;
inbuf = httpc->inbuf + httpc->nread_inbuf;
- DEBUGF(infof(data, "Use data left in connection buffer, nread=%zd\n",
+ H2BUGF(infof(data, "Use data left in connection buffer, nread=%zd\n",
nread));
}
rv = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)inbuf, nread);
@@ -1586,15 +1640,15 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
*err = CURLE_RECV_ERROR;
return -1;
}
- DEBUGF(infof(data, "nghttp2_session_mem_recv() returns %zd\n", rv));
+ H2BUGF(infof(data, "nghttp2_session_mem_recv() returns %zd\n", rv));
if(nread == rv) {
- DEBUGF(infof(data, "All data in connection buffer processed\n"));
+ H2BUGF(infof(data, "All data in connection buffer processed\n"));
httpc->inbuflen = 0;
httpc->nread_inbuf = 0;
}
else {
httpc->nread_inbuf += rv;
- DEBUGF(infof(data, "%zu bytes left in connection buffer\n",
+ H2BUGF(infof(data, "%zu bytes left in connection buffer\n",
httpc->inbuflen - httpc->nread_inbuf));
}
/* Always send pending frames in nghttp2 session, because
@@ -1606,21 +1660,21 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
}
if(should_close_session(httpc)) {
- DEBUGF(infof(data, "http2_recv: nothing to do in this session\n"));
+ H2BUGF(infof(data, "http2_recv: nothing to do in this session\n"));
*err = CURLE_HTTP2;
return -1;
}
}
if(stream->memlen) {
ssize_t retlen = stream->memlen;
- DEBUGF(infof(data, "http2_recv: returns %zd for stream %u\n",
+ H2BUGF(infof(data, "http2_recv: returns %zd for stream %u\n",
retlen, stream->stream_id));
stream->memlen = 0;
if(httpc->pause_stream_id == stream->stream_id) {
/* data for this stream is returned now, but this stream caused a pause
already so we need it called again asap */
- DEBUGF(infof(data, "Data returned for PAUSED stream %u\n",
+ H2BUGF(infof(data, "Data returned for PAUSED stream %u\n",
stream->stream_id));
}
else if(!stream->closed) {
@@ -1637,7 +1691,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
return http2_handle_stream_close(conn, data, stream, err);
}
*err = CURLE_AGAIN;
- DEBUGF(infof(data, "http2_recv returns AGAIN for stream %u\n",
+ H2BUGF(infof(data, "http2_recv returns AGAIN for stream %u\n",
stream->stream_id));
return -1;
}
@@ -1739,7 +1793,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
(void)sockindex;
- DEBUGF(infof(conn->data, "http2_send len=%zu\n", len));
+ H2BUGF(infof(conn->data, "http2_send len=%zu\n", len));
if(stream->stream_id != -1) {
if(stream->close_handled) {
@@ -1768,7 +1822,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
stream->upload_len = 0;
if(should_close_session(httpc)) {
- DEBUGF(infof(conn->data, "http2_send: nothing to do in this session\n"));
+ H2BUGF(infof(conn->data, "http2_send: nothing to do in this session\n"));
*err = CURLE_HTTP2;
return -1;
}
@@ -1781,7 +1835,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
nghttp2_session_resume_data(h2, stream->stream_id);
}
- DEBUGF(infof(conn->data, "http2_send returns %zu for stream %u\n", len,
+ H2BUGF(infof(conn->data, "http2_send returns %zu for stream %u\n", len,
stream->stream_id));
return len;
}
@@ -1809,8 +1863,11 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
return -1;
}
- /* Extract :method, :path from request line */
- line_end = strstr(hdbuf, "\r\n");
+ /* Extract :method, :path from request line
+ We do line endings with CRLF so checking for CR is enough */
+ line_end = memchr(hdbuf, '\r', len);
+ if(!line_end)
+ goto fail;
/* Method does not contain spaces */
end = memchr(hdbuf, ' ', line_end - hdbuf);
@@ -1868,8 +1925,10 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
hdbuf = line_end + 2;
- line_end = strstr(hdbuf, "\r\n");
- if(line_end == hdbuf)
+ /* check for next CR, but only within the piece of data left in the given
+ buffer */
+ line_end = memchr(hdbuf, '\r', len - (hdbuf - (char *)mem));
+ if(!line_end || (line_end == hdbuf))
goto fail;
/* header continuation lines are not supported */
@@ -1937,7 +1996,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
for(i = 0; i < nheader; ++i) {
acc += nva[i].namelen + nva[i].valuelen;
- DEBUGF(infof(conn->data, "h2 header: %.*s:%.*s\n",
+ H2BUGF(infof(conn->data, "h2 header: %.*s:%.*s\n",
nva[i].namelen, nva[i].name,
nva[i].valuelen, nva[i].value));
}
@@ -1975,7 +2034,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
Curl_safefree(nva);
if(stream_id < 0) {
- DEBUGF(infof(conn->data, "http2_send() send error\n"));
+ H2BUGF(infof(conn->data, "http2_send() send error\n"));
*err = CURLE_SEND_ERROR;
return -1;
}
@@ -1994,7 +2053,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
}
if(should_close_session(httpc)) {
- DEBUGF(infof(conn->data, "http2_send: nothing to do in this session\n"));
+ H2BUGF(infof(conn->data, "http2_send: nothing to do in this session\n"));
*err = CURLE_HTTP2;
return -1;
}
@@ -2078,8 +2137,8 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
if(result)
return result;
- httpc->recv_underlying = (recving)conn->recv[FIRSTSOCKET];
- httpc->send_underlying = (sending)conn->send[FIRSTSOCKET];
+ httpc->recv_underlying = conn->recv[FIRSTSOCKET];
+ httpc->send_underlying = conn->send[FIRSTSOCKET];
conn->recv[FIRSTSOCKET] = http2_recv;
conn->send[FIRSTSOCKET] = http2_send;
@@ -2152,7 +2211,7 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
return CURLE_HTTP2;
}
- DEBUGF(infof(data, "nghttp2_session_mem_recv() returns %zd\n", nproc));
+ H2BUGF(infof(data, "nghttp2_session_mem_recv() returns %zd\n", nproc));
if((ssize_t)nread == nproc) {
httpc->inbuflen = 0;
@@ -2172,7 +2231,7 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
}
if(should_close_session(httpc)) {
- DEBUGF(infof(data,
+ H2BUGF(infof(data,
"nghttp2_session_send(): nothing to do in this session\n"));
return CURLE_HTTP2;
}
diff --git a/Utilities/cmcurl/lib/http_chunks.c b/Utilities/cmcurl/lib/http_chunks.c
index 1616429..18dfcb2 100644
--- a/Utilities/cmcurl/lib/http_chunks.c
+++ b/Utilities/cmcurl/lib/http_chunks.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -74,14 +74,18 @@
*/
+#ifdef CURL_DOES_CONVERSIONS
/* Check for an ASCII hex digit.
- We avoid the use of isxdigit to accommodate non-ASCII hosts. */
-static bool Curl_isxdigit(char digit)
+ We avoid the use of ISXDIGIT to accommodate non-ASCII hosts. */
+static bool Curl_isxdigit_ascii(char digit)
{
- return ( (digit >= 0x30 && digit <= 0x39) /* 0-9 */
+ return (digit >= 0x30 && digit <= 0x39) /* 0-9 */
|| (digit >= 0x41 && digit <= 0x46) /* A-F */
- || (digit >= 0x61 && digit <= 0x66) /* a-f */) ? TRUE : FALSE;
+ || (digit >= 0x61 && digit <= 0x66); /* a-f */
}
+#else
+#define Curl_isxdigit_ascii(x) Curl_isxdigit(x)
+#endif
void Curl_httpchunk_init(struct connectdata *conn)
{
@@ -128,7 +132,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
while(length) {
switch(ch->state) {
case CHUNK_HEX:
- if(Curl_isxdigit(*datap)) {
+ if(Curl_isxdigit_ascii(*datap)) {
if(ch->hexindex < MAXNUM_SIZE) {
ch->hexbuffer[ch->hexindex] = *datap;
datap++;
@@ -187,15 +191,15 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
piece = curlx_sotouz((ch->datasize >= length)?length:ch->datasize);
/* Write the data portion available */
- if(conn->data->set.http_ce_skip || !k->writer_stack) {
- if(!k->ignorebody)
+ if(!conn->data->set.http_te_skip && !k->ignorebody) {
+ if(!conn->data->set.http_ce_skip && k->writer_stack)
+ result = Curl_unencode_write(conn, k->writer_stack, datap, piece);
+ else
result = Curl_client_write(conn, CLIENTWRITE_BODY, datap, piece);
- }
- else
- result = Curl_unencode_write(conn, k->writer_stack, datap, piece);
- if(result)
- return CHUNKE_WRITE_ERROR;
+ if(result)
+ return CHUNKE_WRITE_ERROR;
+ }
*wrote += piece;
ch->datasize -= piece; /* decrease amount left to expect */
diff --git a/Utilities/cmcurl/lib/http_negotiate.c b/Utilities/cmcurl/lib/http_negotiate.c
index 51375e8..ddcd65b 100644
--- a/Utilities/cmcurl/lib/http_negotiate.c
+++ b/Utilities/cmcurl/lib/http_negotiate.c
@@ -89,7 +89,7 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
}
}
- /* Initilise the security context and decode our challenge */
+ /* Initialize the security context and decode our challenge */
result = Curl_auth_decode_spnego_message(data, userp, passwdp, service,
host, header, neg_ctx);
diff --git a/Utilities/cmcurl/lib/http_ntlm.c b/Utilities/cmcurl/lib/http_ntlm.c
index 0f1edcf..fd5540b 100644
--- a/Utilities/cmcurl/lib/http_ntlm.c
+++ b/Utilities/cmcurl/lib/http_ntlm.c
@@ -121,9 +121,11 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
server, which is for a plain host or for a HTTP proxy */
char **allocuserpwd;
- /* point to the name and password for this */
+ /* point to the username, password, service and host */
const char *userp;
const char *passwdp;
+ const char *service = NULL;
+ const char *hostname = NULL;
/* point to the correct struct with this */
struct ntlmdata *ntlm;
@@ -141,6 +143,9 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
allocuserpwd = &conn->allocptr.proxyuserpwd;
userp = conn->http_proxy.user;
passwdp = conn->http_proxy.passwd;
+ service = conn->data->set.str[STRING_PROXY_SERVICE_NAME] ?
+ conn->data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
+ hostname = conn->http_proxy.host.name;
ntlm = &conn->proxyntlm;
authp = &conn->data->state.authproxy;
}
@@ -148,6 +153,9 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
allocuserpwd = &conn->allocptr.userpwd;
userp = conn->user;
passwdp = conn->passwd;
+ service = conn->data->set.str[STRING_SERVICE_NAME] ?
+ conn->data->set.str[STRING_SERVICE_NAME] : "HTTP";
+ hostname = conn->host.name;
ntlm = &conn->ntlm;
authp = &conn->data->state.authhost;
}
@@ -174,7 +182,9 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
default: /* for the weird cases we (re)start here */
/* Create a type-1 message */
result = Curl_auth_create_ntlm_type1_message(conn->data, userp, passwdp,
- ntlm, &base64, &len);
+ service, hostname,
+ ntlm, &base64,
+ &len);
if(result)
return result;
diff --git a/Utilities/cmcurl/lib/http_proxy.c b/Utilities/cmcurl/lib/http_proxy.c
index 7f50405..e10a488 100644
--- a/Utilities/cmcurl/lib/http_proxy.c
+++ b/Utilities/cmcurl/lib/http_proxy.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -221,7 +221,7 @@ static CURLcode CONNECT(struct connectdata *conn,
if(!req_buffer)
return CURLE_OUT_OF_MEMORY;
- host_port = aprintf("%s:%hu", hostname, remote_port);
+ host_port = aprintf("%s:%d", hostname, remote_port);
if(!host_port) {
Curl_add_buffer_free(req_buffer);
return CURLE_OUT_OF_MEMORY;
@@ -245,14 +245,14 @@ static CURLcode CONNECT(struct connectdata *conn,
if(hostname != conn->host.name)
ipv6_ip = (strchr(hostname, ':') != NULL);
hostheader = /* host:port with IPv6 support */
- aprintf("%s%s%s:%hu", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"",
+ aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"",
remote_port);
if(!hostheader) {
Curl_add_buffer_free(req_buffer);
return CURLE_OUT_OF_MEMORY;
}
- if(!Curl_checkProxyheaders(conn, "Host:")) {
+ if(!Curl_checkProxyheaders(conn, "Host")) {
host = aprintf("Host: %s\r\n", hostheader);
if(!host) {
free(hostheader);
@@ -260,10 +260,10 @@ static CURLcode CONNECT(struct connectdata *conn,
return CURLE_OUT_OF_MEMORY;
}
}
- if(!Curl_checkProxyheaders(conn, "Proxy-Connection:"))
+ if(!Curl_checkProxyheaders(conn, "Proxy-Connection"))
proxyconn = "Proxy-Connection: Keep-Alive\r\n";
- if(!Curl_checkProxyheaders(conn, "User-Agent:") &&
+ if(!Curl_checkProxyheaders(conn, "User-Agent") &&
data->set.str[STRING_USERAGENT])
useragent = conn->allocptr.uagent;
diff --git a/Utilities/cmcurl/lib/krb5.c b/Utilities/cmcurl/lib/krb5.c
index 70507df..59c0d71 100644
--- a/Utilities/cmcurl/lib/krb5.c
+++ b/Utilities/cmcurl/lib/krb5.c
@@ -85,7 +85,7 @@ krb5_decode(void *app_data, void *buf, int len,
enc.value = buf;
enc.length = len;
- maj = gss_unseal(&min, *context, &enc, &dec, NULL, NULL);
+ maj = gss_unwrap(&min, *context, &enc, &dec, NULL, NULL);
if(maj != GSS_S_COMPLETE) {
if(len >= 4)
strcpy(buf, "599 ");
@@ -119,11 +119,11 @@ krb5_encode(void *app_data, const void *from, int length, int level, void **to)
int len;
/* NOTE that the cast is safe, neither of the krb5, gnu gss and heimdal
- * libraries modify the input buffer in gss_seal()
+ * libraries modify the input buffer in gss_wrap()
*/
dec.value = (void *)from;
dec.length = length;
- maj = gss_seal(&min, *context,
+ maj = gss_wrap(&min, *context,
level == PROT_PRIVATE,
GSS_C_QOP_DEFAULT,
&dec, &state, &enc);
diff --git a/Utilities/cmcurl/lib/md5.c b/Utilities/cmcurl/lib/md5.c
index 80301a1..3096602 100644
--- a/Utilities/cmcurl/lib/md5.c
+++ b/Utilities/cmcurl/lib/md5.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -484,6 +484,11 @@ static void MD5_Final(unsigned char *result, MD5_CTX *ctx)
#endif /* CRYPTO LIBS */
+/* Disable this picky gcc-8 compiler warning */
+#if defined(__GNUC__) && (__GNUC__ >= 8)
+#pragma GCC diagnostic ignored "-Wcast-function-type"
+#endif
+
const HMAC_params Curl_HMAC_MD5[] = {
{
(HMAC_hinit_func) MD5_Init, /* Hash initialization function. */
diff --git a/Utilities/cmcurl/lib/mime.c b/Utilities/cmcurl/lib/mime.c
index e0853a9..4c0d2eeb 100644
--- a/Utilities/cmcurl/lib/mime.c
+++ b/Utilities/cmcurl/lib/mime.c
@@ -51,10 +51,6 @@
#endif
-#define FILE_CONTENTTYPE_DEFAULT "application/octet-stream"
-#define MULTIPART_CONTENTTYPE_DEFAULT "multipart/mixed"
-#define DISPOSITION_DEFAULT "attachment"
-
#define READ_ERROR ((size_t) -1)
/* Encoders. */
@@ -245,7 +241,7 @@ static FILE * vmsfopenread(const char *file, const char *mode)
static char *Curl_basename(char *path)
{
/* Ignore all the details above for now and make a quick and simple
- implementaion here */
+ implementation here */
char *s1;
char *s2;
@@ -1197,7 +1193,10 @@ CURLcode Curl_mime_duppart(curl_mimepart *dst, const curl_mimepart *src)
}
/* Duplicate other fields. */
- dst->encoder = src->encoder;
+ if(dst != NULL)
+ dst->encoder = src->encoder;
+ else
+ res = CURLE_WRITE_ERROR;
if(!res)
res = curl_mime_type(dst, src->mimetype);
if(!res)
@@ -1206,7 +1205,7 @@ CURLcode Curl_mime_duppart(curl_mimepart *dst, const curl_mimepart *src)
res = curl_mime_filename(dst, src->filename);
/* If an error occurred, rollback. */
- if(res)
+ if(res && dst)
Curl_mime_cleanpart(dst);
return res;
@@ -1642,8 +1641,7 @@ static CURLcode add_content_type(struct curl_slist **slp,
boundary? boundary: "");
}
-
-static const char *ContentTypeForFilename(const char *filename)
+const char *Curl_mime_contenttype(const char *filename)
{
unsigned int i;
@@ -1715,14 +1713,14 @@ CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
contenttype = MULTIPART_CONTENTTYPE_DEFAULT;
break;
case MIMEKIND_FILE:
- contenttype = ContentTypeForFilename(part->filename);
+ contenttype = Curl_mime_contenttype(part->filename);
if(!contenttype)
- contenttype = ContentTypeForFilename(part->data);
+ contenttype = Curl_mime_contenttype(part->data);
if(!contenttype && part->filename)
contenttype = FILE_CONTENTTYPE_DEFAULT;
break;
default:
- contenttype = ContentTypeForFilename(part->filename);
+ contenttype = Curl_mime_contenttype(part->filename);
break;
}
}
diff --git a/Utilities/cmcurl/lib/mime.h b/Utilities/cmcurl/lib/mime.h
index 920a8a7..4d5c704 100644
--- a/Utilities/cmcurl/lib/mime.h
+++ b/Utilities/cmcurl/lib/mime.h
@@ -30,6 +30,10 @@
#define MIME_USERHEADERS_OWNER (1 << 0)
#define MIME_BODY_ONLY (1 << 1)
+#define FILE_CONTENTTYPE_DEFAULT "application/octet-stream"
+#define MULTIPART_CONTENTTYPE_DEFAULT "multipart/mixed"
+#define DISPOSITION_DEFAULT "attachment"
+
/* Part source kinds. */
enum mimekind {
MIMEKIND_NONE = 0, /* Part not set. */
@@ -134,5 +138,6 @@ size_t Curl_mime_read(char *buffer, size_t size, size_t nitems,
void *instream);
CURLcode Curl_mime_rewind(curl_mimepart *part);
CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...);
+const char *Curl_mime_contenttype(const char *filename);
#endif /* HEADER_CURL_MIME_H */
diff --git a/Utilities/cmcurl/lib/multi.c b/Utilities/cmcurl/lib/multi.c
index 43823cc..f852846 100644
--- a/Utilities/cmcurl/lib/multi.c
+++ b/Utilities/cmcurl/lib/multi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -77,6 +77,7 @@ static CURLMcode add_next_timeout(struct curltime now,
struct Curl_easy *d);
static CURLMcode multi_timeout(struct Curl_multi *multi,
long *timeout_ms);
+static void process_pending_handles(struct Curl_multi *multi);
#ifdef DEBUGBUILD
static const char * const statename[]={
@@ -366,6 +367,9 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
if(data->multi)
return CURLM_ADDED_ALREADY;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+
/* Initialize timeout list for this handle */
Curl_llist_init(&data->state.timeoutlist, NULL);
@@ -375,6 +379,8 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
* potential multi's connection cache growing which won't be undone in this
* function no matter what.
*/
+ if(data->set.errorbuffer)
+ data->set.errorbuffer[0] = 0;
/* set the easy handle */
multistate(data, CURLM_STATE_INIT);
@@ -535,13 +541,14 @@ static CURLcode multi_done(struct connectdata **connp,
result = CURLE_ABORTED_BY_CALLBACK;
}
- if(conn->send_pipe.size + conn->recv_pipe.size != 0 &&
- !data->set.reuse_forbid &&
- !conn->bits.close) {
- /* Stop if pipeline is not empty and we do not have to close
- connection. */
+ process_pending_handles(data->multi); /* connection / multiplex */
+
+ if(conn->send_pipe.size || conn->recv_pipe.size) {
+ /* Stop if pipeline is not empty . */
data->easy_conn = NULL;
- DEBUGF(infof(data, "Connection still in use, no more multi_done now!\n"));
+ DEBUGF(infof(data, "Connection still in use %d/%d, "
+ "no more multi_done now!\n",
+ conn->send_pipe.size, conn->recv_pipe.size));
return CURLE_OK;
}
@@ -640,6 +647,9 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
if(!data->multi)
return CURLM_OK; /* it is already removed so let's say it is fine! */
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+
premature = (data->mstate < CURLM_STATE_COMPLETED) ? TRUE : FALSE;
easy_owns_conn = (data->easy_conn && (data->easy_conn->data == easy)) ?
TRUE : FALSE;
@@ -650,10 +660,6 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
/* this handle is "alive" so we need to count down the total number of
alive connections when this is removed */
multi->num_alive--;
-
- /* When this handle gets removed, other handles may be able to get the
- connection */
- Curl_multi_process_pending_handles(multi);
}
if(data->easy_conn &&
@@ -903,6 +909,9 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+
data = multi->easyp;
while(data) {
bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
@@ -956,6 +965,9 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi,
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+
/* If the internally desired timeout is actually shorter than requested from
the outside, then use the shorter time! But only if the internal timer
is actually larger than -1! */
@@ -1121,6 +1133,9 @@ CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
{
CURLMcode rc;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+
rc = curl_multi_add_handle(multi, data);
if(!rc) {
struct SingleRequest *k = &data->req;
@@ -1327,7 +1342,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(multi_ischanged(multi, TRUE)) {
DEBUGF(infof(data, "multi changed, check CONNECT_PEND queue!\n"));
- Curl_multi_process_pending_handles(multi);
+ process_pending_handles(multi); /* pipelined/multiplexed */
}
if(data->easy_conn && data->mstate > CURLM_STATE_CONNECT &&
@@ -1773,16 +1788,17 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
case CURLM_STATE_DO_DONE:
/* Move ourselves from the send to recv pipeline */
Curl_move_handle_from_send_to_recv_pipe(data, data->easy_conn);
- /* Check if we can move pending requests to send pipe */
- Curl_multi_process_pending_handles(multi);
+
+ if(data->easy_conn->bits.multiplex || data->easy_conn->send_pipe.size)
+ /* Check if we can move pending requests to send pipe */
+ process_pending_handles(multi); /* pipelined/multiplexed */
/* Only perform the transfer if there's a good socket to work with.
Having both BAD is a signal to skip immediately to DONE */
if((data->easy_conn->sockfd != CURL_SOCKET_BAD) ||
(data->easy_conn->writesockfd != CURL_SOCKET_BAD))
multistate(data, CURLM_STATE_WAITPERFORM);
- else
- {
+ else {
if(data->state.wildcardmatch &&
((data->easy_conn->handler->flags & PROTOPT_WILDCARD) == 0)) {
data->wildcard.state = CURLWC_DONE;
@@ -1811,22 +1827,26 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(!result) {
send_timeout_ms = 0;
if(data->set.max_send_speed > 0)
- send_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.uploaded,
- data->progress.ul_limit_size,
- data->set.max_send_speed,
- data->progress.ul_limit_start,
- now);
+ send_timeout_ms =
+ Curl_pgrsLimitWaitTime(data->progress.uploaded,
+ data->progress.ul_limit_size,
+ data->set.max_send_speed,
+ data->progress.ul_limit_start,
+ now);
recv_timeout_ms = 0;
if(data->set.max_recv_speed > 0)
- recv_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.downloaded,
- data->progress.dl_limit_size,
- data->set.max_recv_speed,
- data->progress.dl_limit_start,
- now);
-
- if(send_timeout_ms <= 0 && recv_timeout_ms <= 0)
+ recv_timeout_ms =
+ Curl_pgrsLimitWaitTime(data->progress.downloaded,
+ data->progress.dl_limit_size,
+ data->set.max_recv_speed,
+ data->progress.dl_limit_start,
+ now);
+
+ if(!send_timeout_ms && !recv_timeout_ms) {
multistate(data, CURLM_STATE_PERFORM);
+ Curl_ratelimit(data, now);
+ }
else if(send_timeout_ms >= recv_timeout_ms)
Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
else
@@ -1858,7 +1878,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
data->progress.dl_limit_start,
now);
- if(send_timeout_ms > 0 || recv_timeout_ms > 0) {
+ if(send_timeout_ms || recv_timeout_ms) {
+ Curl_ratelimit(data, now);
multistate(data, CURLM_STATE_TOOFAST);
if(send_timeout_ms >= recv_timeout_ms)
Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
@@ -1926,9 +1947,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(data->easy_conn->recv_pipe.head)
Curl_expire(data->easy_conn->recv_pipe.head->ptr, 0, EXPIRE_RUN_NOW);
- /* Check if we can move pending requests to send pipe */
- Curl_multi_process_pending_handles(multi);
-
/* When we follow redirects or is set to retry the connection, we must
to go back to the CONNECT state */
if(data->req.newurl || retry) {
@@ -1985,8 +2003,10 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* Remove ourselves from the receive pipeline, if we are there. */
Curl_removeHandleFromPipeline(data, &data->easy_conn->recv_pipe);
- /* Check if we can move pending requests to send pipe */
- Curl_multi_process_pending_handles(multi);
+
+ if(data->easy_conn->bits.multiplex || data->easy_conn->send_pipe.size)
+ /* Check if we can move pending requests to connection */
+ process_pending_handles(multi); /* pipelined/multiplexing */
/* post-transfer command */
res = multi_done(&data->easy_conn, result, FALSE);
@@ -2054,7 +2074,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
data->state.pipe_broke = FALSE;
/* Check if we can move pending requests to send pipe */
- Curl_multi_process_pending_handles(multi);
+ process_pending_handles(multi); /* connection */
if(data->easy_conn) {
/* if this has a connection, unsubscribe from the pipelines */
@@ -2127,6 +2147,9 @@ CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles)
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+
data = multi->easyp;
while(data) {
CURLMcode result;
@@ -2174,6 +2197,9 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
struct Curl_easy *nextdata;
if(GOOD_MULTI_HANDLE(multi)) {
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+
multi->type = 0; /* not good anymore */
/* Firsrt remove all remaining easy handles */
@@ -2234,7 +2260,9 @@ CURLMsg *curl_multi_info_read(struct Curl_multi *multi, int *msgs_in_queue)
*msgs_in_queue = 0; /* default to none */
- if(GOOD_MULTI_HANDLE(multi) && Curl_llist_count(&multi->msglist)) {
+ if(GOOD_MULTI_HANDLE(multi) &&
+ !multi->in_callback &&
+ Curl_llist_count(&multi->msglist)) {
/* there is one or more messages in the list */
struct curl_llist_element *e;
@@ -2396,6 +2424,12 @@ static void singlesocket(struct Curl_multi *multi,
data->numsocks = num;
}
+void Curl_updatesocket(struct Curl_easy *data)
+{
+ singlesocket(data->multi, data);
+}
+
+
/*
* Curl_multi_closed()
*
@@ -2624,6 +2658,9 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi,
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+
va_start(param, option);
switch(option) {
@@ -2688,7 +2725,10 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi,
CURLMcode curl_multi_socket(struct Curl_multi *multi, curl_socket_t s,
int *running_handles)
{
- CURLMcode result = multi_socket(multi, FALSE, s, 0, running_handles);
+ CURLMcode result;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+ result = multi_socket(multi, FALSE, s, 0, running_handles);
if(CURLM_OK >= result)
update_timer(multi);
return result;
@@ -2697,8 +2737,10 @@ CURLMcode curl_multi_socket(struct Curl_multi *multi, curl_socket_t s,
CURLMcode curl_multi_socket_action(struct Curl_multi *multi, curl_socket_t s,
int ev_bitmask, int *running_handles)
{
- CURLMcode result = multi_socket(multi, FALSE, s,
- ev_bitmask, running_handles);
+ CURLMcode result;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+ result = multi_socket(multi, FALSE, s, ev_bitmask, running_handles);
if(CURLM_OK >= result)
update_timer(multi);
return result;
@@ -2707,8 +2749,10 @@ CURLMcode curl_multi_socket_action(struct Curl_multi *multi, curl_socket_t s,
CURLMcode curl_multi_socket_all(struct Curl_multi *multi, int *running_handles)
{
- CURLMcode result = multi_socket(multi, TRUE, CURL_SOCKET_BAD, 0,
- running_handles);
+ CURLMcode result;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+ result = multi_socket(multi, TRUE, CURL_SOCKET_BAD, 0, running_handles);
if(CURLM_OK >= result)
update_timer(multi);
return result;
@@ -2760,6 +2804,9 @@ CURLMcode curl_multi_timeout(struct Curl_multi *multi,
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+
return multi_timeout(multi, timeout_ms);
}
@@ -2992,6 +3039,9 @@ CURLMcode curl_multi_assign(struct Curl_multi *multi, curl_socket_t s,
{
struct Curl_sh_entry *there = NULL;
+ if(multi->in_callback)
+ return CURLM_RECURSIVE_API_CALL;
+
there = sh_getentry(&multi->sockhash, s);
if(!there)
@@ -3032,28 +3082,38 @@ struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi)
return &multi->pipelining_server_bl;
}
-void Curl_multi_process_pending_handles(struct Curl_multi *multi)
+static void process_pending_handles(struct Curl_multi *multi)
{
struct curl_llist_element *e = multi->pending.head;
-
- while(e) {
+ if(e) {
struct Curl_easy *data = e->ptr;
- struct curl_llist_element *next = e->next;
- if(data->mstate == CURLM_STATE_CONNECT_PEND) {
- multistate(data, CURLM_STATE_CONNECT);
+ DEBUGASSERT(data->mstate == CURLM_STATE_CONNECT_PEND);
- /* Remove this node from the list */
- Curl_llist_remove(&multi->pending, e, NULL);
+ multistate(data, CURLM_STATE_CONNECT);
- /* Make sure that the handle will be processed soonish. */
- Curl_expire(data, 0, EXPIRE_RUN_NOW);
- }
+ /* Remove this node from the list */
+ Curl_llist_remove(&multi->pending, e, NULL);
- e = next; /* operate on next handle */
+ /* Make sure that the handle will be processed soonish. */
+ Curl_expire(data, 0, EXPIRE_RUN_NOW);
}
}
+void Curl_set_in_callback(struct Curl_easy *easy, bool value)
+{
+ if(easy->multi_easy)
+ easy->multi_easy->in_callback = value;
+ else if(easy->multi)
+ easy->multi->in_callback = value;
+}
+
+bool Curl_is_in_callback(struct Curl_easy *easy)
+{
+ return ((easy->multi && easy->multi->in_callback) ||
+ (easy->multi_easy && easy->multi_easy->in_callback));
+}
+
#ifdef DEBUGBUILD
void Curl_multi_dump(struct Curl_multi *multi)
{
diff --git a/Utilities/cmcurl/lib/multihandle.h b/Utilities/cmcurl/lib/multihandle.h
index de9a7cf..1a5017f 100644
--- a/Utilities/cmcurl/lib/multihandle.h
+++ b/Utilities/cmcurl/lib/multihandle.h
@@ -146,6 +146,7 @@ struct Curl_multi {
void *timer_userp;
struct curltime timer_lastcall; /* the fixed time for the timeout for the
previous callback */
+ bool in_callback; /* true while executing a callback */
};
#endif /* HEADER_CURL_MULTIHANDLE_H */
diff --git a/Utilities/cmcurl/lib/multiif.h b/Utilities/cmcurl/lib/multiif.h
index a877571..c8fb5ca 100644
--- a/Utilities/cmcurl/lib/multiif.h
+++ b/Utilities/cmcurl/lib/multiif.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,11 +26,14 @@
* Prototypes for library-wide functions provided by multi.c
*/
+void Curl_updatesocket(struct Curl_easy *data);
void Curl_expire(struct Curl_easy *data, time_t milli, expire_id);
void Curl_expire_clear(struct Curl_easy *data);
void Curl_expire_done(struct Curl_easy *data, expire_id id);
bool Curl_pipeline_wanted(const struct Curl_multi* multi, int bits);
void Curl_multi_handlePipeBreak(struct Curl_easy *data);
+void Curl_set_in_callback(struct Curl_easy *data, bool value);
+bool Curl_is_in_callback(struct Curl_easy *easy);
/* Internal version of curl_multi_init() accepts size parameters for the
socket and connection hashes */
@@ -56,8 +59,6 @@ struct Curl_multi *Curl_multi_handle(int hashsize, int chashsize);
void Curl_multi_dump(struct Curl_multi *multi);
#endif
-void Curl_multi_process_pending_handles(struct Curl_multi *multi);
-
/* Return the value of the CURLMOPT_MAX_HOST_CONNECTIONS option */
size_t Curl_multi_max_host_connections(struct Curl_multi *multi);
diff --git a/Utilities/cmcurl/lib/non-ascii.c b/Utilities/cmcurl/lib/non-ascii.c
index 92b2f8d..1414324 100644
--- a/Utilities/cmcurl/lib/non-ascii.c
+++ b/Utilities/cmcurl/lib/non-ascii.c
@@ -30,6 +30,7 @@
#include "formdata.h"
#include "sendf.h"
#include "urldata.h"
+#include "multiif.h"
#include "curl_memory.h"
/* The last #include file should be: */
@@ -84,7 +85,10 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data,
{
if(data && data->set.convtonetwork) {
/* use translation callback */
- CURLcode result = data->set.convtonetwork(buffer, length);
+ CURLcode result;
+ Curl_set_in_callback(data, true);
+ result = data->set.convtonetwork(buffer, length);
+ Curl_set_in_callback(data, false);
if(result) {
failf(data,
"CURLOPT_CONV_TO_NETWORK_FUNCTION callback returned %d: %s",
@@ -147,7 +151,10 @@ CURLcode Curl_convert_from_network(struct Curl_easy *data,
{
if(data && data->set.convfromnetwork) {
/* use translation callback */
- CURLcode result = data->set.convfromnetwork(buffer, length);
+ CURLcode result;
+ Curl_set_in_callback(data, true);
+ result = data->set.convfromnetwork(buffer, length);
+ Curl_set_in_callback(data, false);
if(result) {
failf(data,
"CURLOPT_CONV_FROM_NETWORK_FUNCTION callback returned %d: %s",
@@ -210,7 +217,10 @@ CURLcode Curl_convert_from_utf8(struct Curl_easy *data,
{
if(data && data->set.convfromutf8) {
/* use translation callback */
- CURLcode result = data->set.convfromutf8(buffer, length);
+ CURLcode result;
+ Curl_set_in_callback(data, true);
+ result = data->set.convfromutf8(buffer, length);
+ Curl_set_in_callback(data, false);
if(result) {
failf(data,
"CURLOPT_CONV_FROM_UTF8_FUNCTION callback returned %d: %s",
diff --git a/Utilities/cmcurl/lib/nwlib.c b/Utilities/cmcurl/lib/nwlib.c
index 290cbe3..215d933 100644
--- a/Utilities/cmcurl/lib/nwlib.c
+++ b/Utilities/cmcurl/lib/nwlib.c
@@ -186,11 +186,9 @@ int GetOrSetUpData(int id, libdata_t **appData,
app_data = (libdata_t *) get_app_data(id);
if(!app_data) {
- app_data = malloc(sizeof(libdata_t));
+ app_data = calloc(1, sizeof(libdata_t));
if(app_data) {
- memset(app_data, 0, sizeof(libdata_t));
-
app_data->tenbytes = malloc(10);
app_data->lock = NXMutexAlloc(0, 0, &liblock);
diff --git a/Utilities/cmcurl/lib/openldap.c b/Utilities/cmcurl/lib/openldap.c
index f2ffdfe..c6cb794 100644
--- a/Utilities/cmcurl/lib/openldap.c
+++ b/Utilities/cmcurl/lib/openldap.c
@@ -5,8 +5,8 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010, 2017, Howard Chu, <hyc@openldap.org>
- * Copyright (C) 2011 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2010, Howard Chu, <hyc@openldap.org>
+ * Copyright (C) 2011 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -221,7 +221,7 @@ static CURLcode ldap_connect(struct connectdata *conn, bool *done)
if(conn->handler->flags & PROTOPT_SSL)
*ptr++ = 's';
snprintf(ptr, sizeof(hosturl)-(ptr-hosturl), "://%s:%d",
- conn->host.name, conn->remote_port);
+ conn->host.name, conn->remote_port);
#ifdef CURL_OPENLDAP_DEBUG
static int do_trace = 0;
@@ -286,7 +286,7 @@ static CURLcode ldap_connecting(struct connectdata *conn, bool *done)
tvp = &tv;
-retry:
+ retry:
if(!li->didbind) {
char *binddn;
struct berval passwd;
@@ -472,8 +472,8 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
return ret;
for(ent = ldap_first_message(li->ld, msg); ent;
- ent = ldap_next_message(li->ld, ent)) {
- struct berval bv, *bvals, **bvp = &bvals;
+ ent = ldap_next_message(li->ld, ent)) {
+ struct berval bv, *bvals;
int binary = 0, msgtype;
CURLcode writeerr;
@@ -535,18 +535,40 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
}
data->req.bytecount += bv.bv_len + 5;
- for(rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp);
- rc == LDAP_SUCCESS;
- rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp)) {
+ for(rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, &bvals);
+ rc == LDAP_SUCCESS;
+ rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, &bvals)) {
int i;
- if(bv.bv_val == NULL) break;
+ if(bv.bv_val == NULL)
+ break;
if(bv.bv_len > 7 && !strncmp(bv.bv_val + bv.bv_len - 7, ";binary", 7))
binary = 1;
else
binary = 0;
+ if(bvals == NULL) {
+ writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
+ if(writeerr) {
+ *err = writeerr;
+ return -1;
+ }
+ writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val,
+ bv.bv_len);
+ if(writeerr) {
+ *err = writeerr;
+ return -1;
+ }
+ writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":\n", 2);
+ if(writeerr) {
+ *err = writeerr;
+ return -1;
+ }
+ data->req.bytecount += bv.bv_len + 3;
+ continue;
+ }
+
for(i = 0; bvals[i].bv_val != NULL; i++) {
int binval = 0;
writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
@@ -555,24 +577,24 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
return -1;
}
- writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val,
- bv.bv_len);
- if(writeerr) {
- *err = writeerr;
- return -1;
- }
+ writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val,
+ bv.bv_len);
+ if(writeerr) {
+ *err = writeerr;
+ return -1;
+ }
writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":", 1);
- if(writeerr) {
- *err = writeerr;
- return -1;
- }
+ if(writeerr) {
+ *err = writeerr;
+ return -1;
+ }
data->req.bytecount += bv.bv_len + 2;
if(!binary) {
/* check for leading or trailing whitespace */
if(ISSPACE(bvals[i].bv_val[0]) ||
- ISSPACE(bvals[i].bv_val[bvals[i].bv_len-1]))
+ ISSPACE(bvals[i].bv_val[bvals[i].bv_len-1]))
binval = 1;
else {
/* check for unprintable characters */
@@ -610,7 +632,7 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
data->req.bytecount += 2;
if(val_b64_sz > 0) {
writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, val_b64,
- val_b64_sz);
+ val_b64_sz);
if(writeerr) {
*err = writeerr;
return -1;
diff --git a/Utilities/cmcurl/lib/parsedate.c b/Utilities/cmcurl/lib/parsedate.c
index 0fabbd2..3d3c00b 100644
--- a/Utilities/cmcurl/lib/parsedate.c
+++ b/Utilities/cmcurl/lib/parsedate.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -119,6 +119,7 @@ static int parsedate(const char *date, time_t *output);
#define tDAYZONE -60 /* offset for daylight savings time */
static const struct tzinfo tz[]= {
{"GMT", 0}, /* Greenwich Mean */
+ {"UT", 0}, /* Universal Time */
{"UTC", 0}, /* Universal (Coordinated) */
{"WET", 0}, /* Western European */
{"BST", 0 tDAYZONE}, /* British Summer */
@@ -276,26 +277,23 @@ struct my_tm {
int tm_hour;
int tm_mday;
int tm_mon;
- int tm_year;
+ int tm_year; /* full year */
};
/* struct tm to time since epoch in GMT time zone.
* This is similar to the standard mktime function but for GMT only, and
* doesn't suffer from the various bugs and portability problems that
* some systems' implementations have.
+ *
+ * Returns 0 on success, otherwise non-zero.
*/
-static time_t my_timegm(struct my_tm *tm)
+static void my_timegm(struct my_tm *tm, time_t *t)
{
static const int month_days_cumulative [12] =
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
int month, year, leap_days;
- if(tm->tm_year < 70)
- /* we don't support years before 1970 as they will cause this function
- to return a negative value */
- return -1;
-
- year = tm->tm_year + 1900;
+ year = tm->tm_year;
month = tm->tm_mon;
if(month < 0) {
year += (11 - month) / 12;
@@ -310,9 +308,9 @@ static time_t my_timegm(struct my_tm *tm)
leap_days = ((leap_days / 4) - (leap_days / 100) + (leap_days / 400)
- (1969 / 4) + (1969 / 100) - (1969 / 400));
- return ((((time_t) (year - 1970) * 365
- + leap_days + month_days_cumulative [month] + tm->tm_mday - 1) * 24
- + tm->tm_hour) * 60 + tm->tm_min) * 60 + tm->tm_sec;
+ *t = ((((time_t) (year - 1970) * 365
+ + leap_days + month_days_cumulative[month] + tm->tm_mday - 1) * 24
+ + tm->tm_hour) * 60 + tm->tm_min) * 60 + tm->tm_sec;
}
/*
@@ -436,7 +434,7 @@ static int parsedate(const char *date, time_t *output)
tzoff = (val/100 * 60 + val%100)*60;
/* the + and - prefix indicates the local time compared to GMT,
- this we need ther reversed math to get what we want */
+ this we need their reversed math to get what we want */
tzoff = date[-1]=='+'?-tzoff:tzoff;
}
@@ -462,7 +460,7 @@ static int parsedate(const char *date, time_t *output)
if(!found && (dignext == DATE_YEAR) && (yearnum == -1)) {
yearnum = val;
found = TRUE;
- if(yearnum < 1900) {
+ if(yearnum < 100) {
if(yearnum > 70)
yearnum += 1900;
else
@@ -491,18 +489,39 @@ static int parsedate(const char *date, time_t *output)
/* lacks vital info, fail */
return PARSEDATE_FAIL;
-#if SIZEOF_TIME_T < 5
- /* 32 bit time_t can only hold dates to the beginning of 2038 */
- if(yearnum > 2037) {
- *output = 0x7fffffff;
- return PARSEDATE_LATER;
+#ifdef HAVE_TIME_T_UNSIGNED
+ if(yearnum < 1970) {
+ /* only positive numbers cannot return earlier */
+ *output = TIME_T_MIN;
+ return PARSEDATE_SOONER;
}
#endif
- if(yearnum < 1970) {
- *output = 0;
+#if (SIZEOF_TIME_T < 5)
+
+#ifdef HAVE_TIME_T_UNSIGNED
+ /* an unsigned 32 bit time_t can only hold dates to 2106 */
+ if(yearnum > 2105) {
+ *output = TIME_T_MAX;
+ return PARSEDATE_LATER;
+ }
+#else
+ /* a signed 32 bit time_t can only hold dates to the beginning of 2038 */
+ if(yearnum > 2037) {
+ *output = TIME_T_MAX;
+ return PARSEDATE_LATER;
+ }
+ if(yearnum < 1903) {
+ *output = TIME_T_MIN;
return PARSEDATE_SOONER;
}
+#endif
+
+#else
+ /* The Gregorian calendar was introduced 1582 */
+ if(yearnum < 1583)
+ return PARSEDATE_FAIL;
+#endif
if((mdaynum > 31) || (monnum > 11) ||
(hournum > 23) || (minnum > 59) || (secnum > 60))
@@ -513,31 +532,25 @@ static int parsedate(const char *date, time_t *output)
tm.tm_hour = hournum;
tm.tm_mday = mdaynum;
tm.tm_mon = monnum;
- tm.tm_year = yearnum - 1900;
-
- /* my_timegm() returns a time_t. time_t is often 32 bits, even on many
- architectures that feature 64 bit 'long'.
+ tm.tm_year = yearnum;
- Some systems have 64 bit time_t and deal with years beyond 2038. However,
- even on some of the systems with 64 bit time_t mktime() returns -1 for
- dates beyond 03:14:07 UTC, January 19, 2038. (Such as AIX 5100-06)
+ /* my_timegm() returns a time_t. time_t is often 32 bits, sometimes even on
+ architectures that feature 64 bit 'long' but ultimately time_t is the
+ correct data type to use.
*/
- t = my_timegm(&tm);
-
- /* time zone adjust (cast t to int to compare to negative one) */
- if(-1 != (int)t) {
+ my_timegm(&tm, &t);
- /* Add the time zone diff between local time zone and GMT. */
- long delta = (long)(tzoff!=-1?tzoff:0);
+ /* Add the time zone diff between local time zone and GMT. */
+ if(tzoff == -1)
+ tzoff = 0;
- if((delta>0) && (t > LONG_MAX - delta)) {
- *output = 0x7fffffff;
- return PARSEDATE_LATER; /* time_t overflow */
- }
-
- t += delta;
+ if((tzoff > 0) && (t > TIME_T_MAX - tzoff)) {
+ *output = TIME_T_MAX;
+ return PARSEDATE_LATER; /* time_t overflow */
}
+ t += tzoff;
+
*output = t;
return PARSEDATE_OK;
@@ -549,10 +562,10 @@ time_t curl_getdate(const char *p, const time_t *now)
int rc = parsedate(p, &parsed);
(void)now; /* legacy argument from the past that we ignore */
- switch(rc) {
- case PARSEDATE_OK:
- case PARSEDATE_LATER:
- case PARSEDATE_SOONER:
+ if(rc == PARSEDATE_OK) {
+ if(parsed == -1)
+ /* avoid returning -1 for a working scenario */
+ parsed++;
return parsed;
}
/* everything else is fail */
diff --git a/Utilities/cmcurl/lib/pingpong.c b/Utilities/cmcurl/lib/pingpong.c
index 438856a..ad370ee 100644
--- a/Utilities/cmcurl/lib/pingpong.c
+++ b/Utilities/cmcurl/lib/pingpong.c
@@ -304,7 +304,10 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
* it would have been populated with something of size int to begin
* with, even though its datatype may be larger than an int.
*/
- DEBUGASSERT((ptr + pp->cache_size) <= (buf + data->set.buffer_size + 1));
+ if((ptr + pp->cache_size) > (buf + data->set.buffer_size + 1)) {
+ failf(data, "cached response data too big to handle");
+ return CURLE_RECV_ERROR;
+ }
memcpy(ptr, pp->cache, pp->cache_size);
gotbytes = (ssize_t)pp->cache_size;
free(pp->cache); /* free the cache */
diff --git a/Utilities/cmcurl/lib/progress.c b/Utilities/cmcurl/lib/progress.c
index cc5e8be..f59faa3 100644
--- a/Utilities/cmcurl/lib/progress.c
+++ b/Utilities/cmcurl/lib/progress.c
@@ -24,9 +24,13 @@
#include "urldata.h"
#include "sendf.h"
+#include "multiif.h"
#include "progress.h"
#include "curl_printf.h"
+/* check rate limits within this many recent milliseconds, at minimum. */
+#define MIN_RATE_LIMIT_PERIOD 3000
+
/* Provide a string that is 2 + 1 + 2 + 1 + 2 = 8 letters long (plus the zero
byte) */
static void time2str(char *r, curl_off_t seconds)
@@ -234,11 +238,12 @@ void Curl_pgrsStartNow(struct Curl_easy *data)
data->progress.dl_limit_start.tv_usec = 0;
/* clear all bits except HIDE and HEADERS_OUT */
data->progress.flags &= PGRS_HIDE|PGRS_HEADERS_OUT;
+ Curl_ratelimit(data, data->progress.start);
}
/*
- * This is used to handle speed limits, calculating how much milliseconds we
- * need to wait until we're back under the speed limit, if needed.
+ * This is used to handle speed limits, calculating how many milliseconds to
+ * wait until we're back under the speed limit, if needed.
*
* The way it works is by having a "starting point" (time & amount of data
* transferred by then) used in the speed computation, to be used instead of
@@ -250,73 +255,87 @@ void Curl_pgrsStartNow(struct Curl_easy *data)
* the starting point, the limit (in bytes/s), the time of the starting point
* and the current time.
*
- * Returns -1 if no waiting is needed (not enough data transferred since
- * starting point yet), 0 when no waiting is needed but the starting point
- * should be reset (to current), or the number of milliseconds to wait to get
- * back under the speed limit.
+ * Returns 0 if no waiting is needed or when no waiting is needed but the
+ * starting point should be reset (to current); or the number of milliseconds
+ * to wait to get back under the speed limit.
*/
-long Curl_pgrsLimitWaitTime(curl_off_t cursize,
- curl_off_t startsize,
- curl_off_t limit,
- struct curltime start,
- struct curltime now)
+timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize,
+ curl_off_t startsize,
+ curl_off_t limit,
+ struct curltime start,
+ struct curltime now)
{
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)
+ if(!limit || !size)
return 0;
- /* not enough data yet */
- if(size < limit)
- return -1;
+ /*
+ * 'minimum' is the number of milliseconds 'size' should take to download to
+ * stay below 'limit'.
+ */
+ if(size < CURL_OFF_T_MAX/1000)
+ minimum = (time_t) (CURL_OFF_T_C(1000) * size / limit);
+ else {
+ minimum = (time_t) (size / limit);
+ if(minimum < TIME_T_MAX/1000)
+ minimum *= 1000;
+ else
+ minimum = TIME_T_MAX;
+ }
- minimum = (time_t) (CURL_OFF_T_C(1000) * size / limit);
+ /*
+ * 'actual' is the time in milliseconds it took to actually download the
+ * last 'size' bytes.
+ */
actual = Curl_timediff(now, start);
-
- if(actual < minimum)
- /* this is a conversion on some systems (64bit time_t => 32bit long) */
- return (long)(minimum - actual);
+ if(actual < minimum) {
+ /* if it downloaded the data faster than the limit, make it wait the
+ difference */
+ return (minimum - actual);
+ }
return 0;
}
+/*
+ * Set the number of downloaded bytes so far.
+ */
void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size)
{
- struct curltime now = Curl_now();
-
data->progress.downloaded = size;
+}
- /* download speed limit */
- if((data->set.max_recv_speed > 0) &&
- (Curl_pgrsLimitWaitTime(data->progress.downloaded,
- data->progress.dl_limit_size,
- data->set.max_recv_speed,
- data->progress.dl_limit_start,
- now) == 0)) {
- data->progress.dl_limit_start = now;
- data->progress.dl_limit_size = size;
+/*
+ * Update the timestamp and sizestamp to use for rate limit calculations.
+ */
+void Curl_ratelimit(struct Curl_easy *data, struct curltime now)
+{
+ /* don't set a new stamp unless the time since last update is long enough */
+ if(data->set.max_recv_speed > 0) {
+ if(Curl_timediff(now, data->progress.dl_limit_start) >=
+ MIN_RATE_LIMIT_PERIOD) {
+ data->progress.dl_limit_start = now;
+ data->progress.dl_limit_size = data->progress.downloaded;
+ }
+ }
+ if(data->set.max_send_speed > 0) {
+ if(Curl_timediff(now, data->progress.ul_limit_start) >=
+ MIN_RATE_LIMIT_PERIOD) {
+ data->progress.ul_limit_start = now;
+ data->progress.ul_limit_size = data->progress.uploaded;
+ }
}
}
+/*
+ * Set the number of uploaded bytes so far.
+ */
void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size)
{
- struct curltime now = Curl_now();
-
data->progress.uploaded = size;
-
- /* upload speed limit */
- if((data->set.max_send_speed > 0) &&
- (Curl_pgrsLimitWaitTime(data->progress.uploaded,
- data->progress.ul_limit_size,
- data->set.max_send_speed,
- data->progress.ul_limit_start,
- now) == 0)) {
- data->progress.ul_limit_start = now;
- data->progress.ul_limit_size = size;
- }
}
void Curl_pgrsSetDownloadSize(struct Curl_easy *data, curl_off_t size)
@@ -461,22 +480,26 @@ int Curl_pgrsUpdate(struct connectdata *conn)
if(data->set.fxferinfo) {
/* There's a callback set, call that */
+ Curl_set_in_callback(data, true);
result = data->set.fxferinfo(data->set.progress_client,
data->progress.size_dl,
data->progress.downloaded,
data->progress.size_ul,
data->progress.uploaded);
+ Curl_set_in_callback(data, false);
if(result)
failf(data, "Callback aborted");
return result;
}
if(data->set.fprogress) {
/* The older deprecated callback is set, call that */
+ Curl_set_in_callback(data, true);
result = data->set.fprogress(data->set.progress_client,
(double)data->progress.size_dl,
(double)data->progress.downloaded,
(double)data->progress.size_ul,
(double)data->progress.uploaded);
+ Curl_set_in_callback(data, false);
if(result)
failf(data, "Callback aborted");
return result;
diff --git a/Utilities/cmcurl/lib/progress.h b/Utilities/cmcurl/lib/progress.h
index 9333ab2..2baa925 100644
--- a/Utilities/cmcurl/lib/progress.h
+++ b/Utilities/cmcurl/lib/progress.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -46,14 +46,15 @@ void Curl_pgrsSetDownloadSize(struct Curl_easy *data, curl_off_t size);
void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size);
void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size);
void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size);
+void Curl_ratelimit(struct Curl_easy *data, struct curltime now);
int Curl_pgrsUpdate(struct connectdata *);
void Curl_pgrsResetTransferSizes(struct Curl_easy *data);
void Curl_pgrsTime(struct Curl_easy *data, timerid timer);
-long Curl_pgrsLimitWaitTime(curl_off_t cursize,
- curl_off_t startsize,
- curl_off_t limit,
- struct curltime start,
- struct curltime now);
+timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize,
+ curl_off_t startsize,
+ curl_off_t limit,
+ struct curltime start,
+ struct curltime now);
/* Don't show progress for sizes smaller than: */
#define LEAST_SIZE_PROGRESS BUFSIZE
diff --git a/Utilities/cmcurl/lib/rtsp.c b/Utilities/cmcurl/lib/rtsp.c
index 925da2c..41f3000 100644
--- a/Utilities/cmcurl/lib/rtsp.c
+++ b/Utilities/cmcurl/lib/rtsp.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -47,7 +47,7 @@
* -incoming server requests
* -server CSeq counter
* -digest authentication
- * -connect thru proxy
+ * -connect through proxy
* -pipelining?
*/
@@ -357,7 +357,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
}
/* Transport Header for SETUP requests */
- p_transport = Curl_checkheaders(conn, "Transport:");
+ p_transport = Curl_checkheaders(conn, "Transport");
if(rtspreq == RTSPREQ_SETUP && !p_transport) {
/* New Transport: setting? */
if(data->set.str[STRING_RTSP_TRANSPORT]) {
@@ -381,11 +381,11 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/* Accept Headers for DESCRIBE requests */
if(rtspreq == RTSPREQ_DESCRIBE) {
/* Accept Header */
- p_accept = Curl_checkheaders(conn, "Accept:")?
+ p_accept = Curl_checkheaders(conn, "Accept")?
NULL:"Accept: application/sdp\r\n";
/* Accept-Encoding header */
- if(!Curl_checkheaders(conn, "Accept-Encoding:") &&
+ if(!Curl_checkheaders(conn, "Accept-Encoding") &&
data->set.str[STRING_ENCODING]) {
Curl_safefree(conn->allocptr.accept_encoding);
conn->allocptr.accept_encoding =
@@ -402,11 +402,11 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
it might have been used in the proxy connect, but if we have got a header
with the user-agent string specified, we erase the previously made string
here. */
- if(Curl_checkheaders(conn, "User-Agent:") && conn->allocptr.uagent) {
+ if(Curl_checkheaders(conn, "User-Agent") && conn->allocptr.uagent) {
Curl_safefree(conn->allocptr.uagent);
conn->allocptr.uagent = NULL;
}
- else if(!Curl_checkheaders(conn, "User-Agent:") &&
+ else if(!Curl_checkheaders(conn, "User-Agent") &&
data->set.str[STRING_USERAGENT]) {
p_uagent = conn->allocptr.uagent;
}
@@ -421,7 +421,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/* Referrer */
Curl_safefree(conn->allocptr.ref);
- if(data->change.referer && !Curl_checkheaders(conn, "Referer:"))
+ if(data->change.referer && !Curl_checkheaders(conn, "Referer"))
conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
else
conn->allocptr.ref = NULL;
@@ -438,7 +438,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
(rtspreq & (RTSPREQ_PLAY | RTSPREQ_PAUSE | RTSPREQ_RECORD))) {
/* Check to see if there is a range set in the custom headers */
- if(!Curl_checkheaders(conn, "Range:") && data->state.range) {
+ if(!Curl_checkheaders(conn, "Range") && data->state.range) {
Curl_safefree(conn->allocptr.rangeline);
conn->allocptr.rangeline = aprintf("Range: %s\r\n", data->state.range);
p_range = conn->allocptr.rangeline;
@@ -448,11 +448,11 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/*
* Sanity check the custom headers
*/
- if(Curl_checkheaders(conn, "CSeq:")) {
+ if(Curl_checkheaders(conn, "CSeq")) {
failf(data, "CSeq cannot be set as a custom header.");
return CURLE_RTSP_CSEQ_ERROR;
}
- if(Curl_checkheaders(conn, "Session:")) {
+ if(Curl_checkheaders(conn, "Session")) {
failf(data, "Session ID cannot be set as a custom header.");
return CURLE_BAD_FUNCTION_ARGUMENT;
}
@@ -542,7 +542,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
if(putsize > 0 || postsize > 0) {
/* As stated in the http comments, it is probably not wise to
* actually set a custom Content-Length in the headers */
- if(!Curl_checkheaders(conn, "Content-Length:")) {
+ if(!Curl_checkheaders(conn, "Content-Length")) {
result = Curl_add_bufferf(req_buffer,
"Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n",
(data->set.upload ? putsize : postsize));
@@ -552,7 +552,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
if(rtspreq == RTSPREQ_SET_PARAMETER ||
rtspreq == RTSPREQ_GET_PARAMETER) {
- if(!Curl_checkheaders(conn, "Content-Type:")) {
+ if(!Curl_checkheaders(conn, "Content-Type")) {
result = Curl_add_bufferf(req_buffer,
"Content-Type: text/parameters\r\n");
if(result)
@@ -561,7 +561,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
}
if(rtspreq == RTSPREQ_ANNOUNCE) {
- if(!Curl_checkheaders(conn, "Content-Type:")) {
+ if(!Curl_checkheaders(conn, "Content-Type")) {
result = Curl_add_bufferf(req_buffer,
"Content-Type: application/sdp\r\n");
if(result)
@@ -764,13 +764,14 @@ CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len)
writeit = data->set.fwrite_rtp;
user_ptr = data->set.rtp_out;
}
- else
- {
+ else {
writeit = data->set.fwrite_func;
user_ptr = data->set.out;
}
+ Curl_set_in_callback(data, true);
wrote = writeit(ptr, 1, len, user_ptr);
+ Curl_set_in_callback(data, false);
if(CURL_WRITEFUNC_PAUSE == wrote) {
failf(data, "Cannot pause RTP");
diff --git a/Utilities/cmcurl/lib/sendf.c b/Utilities/cmcurl/lib/sendf.c
index 027f97c..27c0ccc 100644
--- a/Utilities/cmcurl/lib/sendf.c
+++ b/Utilities/cmcurl/lib/sendf.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, 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,6 +37,7 @@
#include "connect.h"
#include "vtls/vtls.h"
#include "ssh.h"
+#include "easyif.h"
#include "multiif.h"
#include "non-ascii.h"
#include "strerror.h"
@@ -388,7 +389,7 @@ ssize_t Curl_send_plain(struct connectdata *conn, int num,
(WSAEWOULDBLOCK == err)
#else
/* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
- due to its inability to send off data without blocking. We therefor
+ due to its inability to send off data without blocking. We therefore
treat both error codes the same here */
(EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err) ||
(EINPROGRESS == err)
@@ -455,7 +456,7 @@ ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf,
(WSAEWOULDBLOCK == err)
#else
/* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
- due to its inability to send off data without blocking. We therefor
+ due to its inability to send off data without blocking. We therefore
treat both error codes the same here */
(EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
#endif
@@ -540,18 +541,20 @@ static CURLcode pausewrite(struct Curl_easy *data,
}
-/* Curl_client_chop_write() writes chunks of data not larger than
- * CURL_MAX_WRITE_SIZE via client write callback(s) and
- * takes care of pause requests from the callbacks.
+/* chop_write() writes chunks of data not larger than CURL_MAX_WRITE_SIZE via
+ * client write callback(s) and takes care of pause requests from the
+ * callbacks.
*/
-CURLcode Curl_client_chop_write(struct connectdata *conn,
- int type,
- char *ptr,
- size_t len)
+static CURLcode chop_write(struct connectdata *conn,
+ int type,
+ char *optr,
+ size_t olen)
{
struct Curl_easy *data = conn->data;
curl_write_callback writeheader = NULL;
curl_write_callback writebody = NULL;
+ char *ptr = optr;
+ size_t len = olen;
if(!len)
return CURLE_OK;
@@ -597,25 +600,30 @@ CURLcode Curl_client_chop_write(struct connectdata *conn,
}
}
- if(writeheader) {
- size_t wrote = writeheader(ptr, 1, chunklen, data->set.writeheader);
-
- if(CURL_WRITEFUNC_PAUSE == wrote)
- /* here we pass in the HEADER bit only since if this was body as well
- then it was passed already and clearly that didn't trigger the
- pause, so this is saved for later with the HEADER bit only */
- return pausewrite(data, CLIENTWRITE_HEADER, ptr, len);
-
- if(wrote != chunklen) {
- failf(data, "Failed writing header");
- return CURLE_WRITE_ERROR;
- }
- }
-
ptr += chunklen;
len -= chunklen;
}
+ if(writeheader) {
+ size_t wrote;
+ ptr = optr;
+ len = olen;
+ Curl_set_in_callback(data, true);
+ wrote = writeheader(ptr, 1, len, data->set.writeheader);
+ Curl_set_in_callback(data, false);
+
+ if(CURL_WRITEFUNC_PAUSE == wrote)
+ /* here we pass in the HEADER bit only since if this was body as well
+ then it was passed already and clearly that didn't trigger the
+ pause, so this is saved for later with the HEADER bit only */
+ return pausewrite(data, CLIENTWRITE_HEADER, ptr, len);
+
+ if(wrote != len) {
+ failf(data, "Failed writing header");
+ return CURLE_WRITE_ERROR;
+ }
+ }
+
return CURLE_OK;
}
@@ -657,7 +665,7 @@ CURLcode Curl_client_write(struct connectdata *conn,
#endif /* CURL_DO_LINEEND_CONV */
}
- return Curl_client_chop_write(conn, type, ptr, len);
+ return chop_write(conn, type, ptr, len);
}
CURLcode Curl_read_plain(curl_socket_t sockfd,
@@ -798,8 +806,11 @@ static int showit(struct Curl_easy *data, curl_infotype type,
}
#endif /* CURL_DOES_CONVERSIONS */
- if(data->set.fdebug)
+ if(data->set.fdebug) {
+ Curl_set_in_callback(data, true);
rc = (*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
+ Curl_set_in_callback(data, false);
+ }
else {
switch(type) {
case CURLINFO_TEXT:
diff --git a/Utilities/cmcurl/lib/sendf.h b/Utilities/cmcurl/lib/sendf.h
index fbe4f99..7c9134d 100644
--- a/Utilities/cmcurl/lib/sendf.h
+++ b/Utilities/cmcurl/lib/sendf.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -51,8 +51,6 @@ void Curl_failf(struct Curl_easy *, const char *fmt, ...);
#define CLIENTWRITE_HEADER (1<<1)
#define CLIENTWRITE_BOTH (CLIENTWRITE_BODY|CLIENTWRITE_HEADER)
-CURLcode Curl_client_chop_write(struct connectdata *conn, int type, char *ptr,
- size_t len) WARN_UNUSED_RESULT;
CURLcode Curl_client_write(struct connectdata *conn, int type, char *ptr,
size_t len) WARN_UNUSED_RESULT;
diff --git a/Utilities/cmcurl/lib/setopt.c b/Utilities/cmcurl/lib/setopt.c
index a5ef75c..af53ee3 100644
--- a/Utilities/cmcurl/lib/setopt.c
+++ b/Utilities/cmcurl/lib/setopt.c
@@ -43,6 +43,7 @@
#include "sendf.h"
#include "http2.h"
#include "setopt.h"
+#include "multiif.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -361,6 +362,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
data->set.timevalue = (time_t)va_arg(param, long);
break;
+ case CURLOPT_TIMEVALUE_LARGE:
+ /*
+ * This is the value to compare with the remote document with the
+ * method set with CURLOPT_TIMECONDITION
+ */
+ data->set.timevalue = (time_t)va_arg(param, curl_off_t);
+ break;
+
case CURLOPT_SSLVERSION:
case CURLOPT_PROXY_SSLVERSION:
/*
@@ -772,11 +781,13 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
if(checkprefix("Set-Cookie:", argptr))
/* HTTP Header format line */
- Curl_cookie_add(data, data->cookies, TRUE, argptr + 11, NULL, NULL);
+ Curl_cookie_add(data, data->cookies, TRUE, FALSE, argptr + 11, NULL,
+ NULL);
else
/* Netscape format line */
- Curl_cookie_add(data, data->cookies, FALSE, argptr, NULL, NULL);
+ Curl_cookie_add(data, data->cookies, FALSE, FALSE, argptr, NULL,
+ NULL);
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
free(argptr);
@@ -1028,6 +1039,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
*/
data->set.socks5_gssapi_nec = (0 != va_arg(param, long)) ? TRUE : FALSE;
break;
+#endif
case CURLOPT_SOCKS5_GSSAPI_SERVICE:
case CURLOPT_PROXY_SERVICE_NAME:
@@ -1037,10 +1049,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
result = Curl_setstropt(&data->set.str[STRING_PROXY_SERVICE_NAME],
va_arg(param, char *));
break;
-#endif
-#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
- defined(USE_SPNEGO)
case CURLOPT_SERVICE_NAME:
/*
* Set authentication service name for DIGEST-MD5, Kerberos 5 and SPNEGO
@@ -1049,8 +1058,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
va_arg(param, char *));
break;
-#endif
-
case CURLOPT_HEADERDATA:
/*
* Custom pointer to pass the header write callback function
@@ -1594,6 +1601,13 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
data->set.crlf = (0 != va_arg(param, long)) ? TRUE : FALSE;
break;
+ case CURLOPT_HAPROXYPROTOCOL:
+ /*
+ * Set to send the HAProxy Proxy Protocol header
+ */
+ data->set.haproxyprotocol = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ break;
+
case CURLOPT_INTERFACE:
/*
* Set what interface or address/hostname to bind the socket to when
@@ -1734,7 +1748,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
* Set a SSL_CTX callback
*/
#ifdef USE_SSL
- if(Curl_ssl->have_ssl_ctx)
+ if(Curl_ssl->supports & SSLSUPP_SSL_CTX)
data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
else
#endif
@@ -1745,7 +1759,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
* Set a SSL_CTX callback parameter pointer
*/
#ifdef USE_SSL
- if(Curl_ssl->have_ssl_ctx)
+ if(Curl_ssl->supports & SSLSUPP_SSL_CTX)
data->set.ssl.fsslctxp = va_arg(param, void *);
else
#endif
@@ -1764,7 +1778,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
break;
case CURLOPT_CERTINFO:
#ifdef USE_SSL
- if(Curl_ssl->have_certinfo)
+ if(Curl_ssl->supports & SSLSUPP_CERTINFO)
data->set.ssl.certinfo = (0 != va_arg(param, long)) ? TRUE : FALSE;
else
#endif
@@ -1776,7 +1790,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
* Specify file name of the public key in DER format.
*/
#ifdef USE_SSL
- if(Curl_ssl->have_pinnedpubkey)
+ if(Curl_ssl->supports & SSLSUPP_PINNEDPUBKEY)
result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG],
va_arg(param, char *));
else
@@ -1789,7 +1803,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
* Specify file name of the public key in DER format.
*/
#ifdef USE_SSL
- if(Curl_ssl->have_pinnedpubkey)
+ if(Curl_ssl->supports & SSLSUPP_PINNEDPUBKEY)
result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY],
va_arg(param, char *));
else
@@ -1817,7 +1831,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
* certificates which have been prepared using openssl c_rehash utility.
*/
#ifdef USE_SSL
- if(Curl_ssl->have_ca_path)
+ if(Curl_ssl->supports & SSLSUPP_CA_PATH)
/* This does not work on windows. */
result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_ORIG],
va_arg(param, char *));
@@ -1831,7 +1845,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
* CA certificates which have been prepared using openssl c_rehash utility.
*/
#ifdef USE_SSL
- if(Curl_ssl->have_ca_path)
+ if(Curl_ssl->supports & SSLSUPP_CA_PATH)
/* This does not work on windows. */
result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY],
va_arg(param, char *));
@@ -2101,6 +2115,21 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
data->set.fclosesocket = va_arg(param, curl_closesocket_callback);
break;
+ case CURLOPT_RESOLVER_START_FUNCTION:
+ /*
+ * resolver start callback function: called before a new resolver request
+ * is started
+ */
+ data->set.resolver_start = va_arg(param, curl_resolver_start_callback);
+ break;
+
+ case CURLOPT_RESOLVER_START_DATA:
+ /*
+ * resolver start callback data pointer. Might be NULL.
+ */
+ data->set.resolver_start_client = va_arg(param, void *);
+ break;
+
case CURLOPT_CLOSESOCKETDATA:
/*
* socket callback data pointer. Might be NULL.
@@ -2524,6 +2553,15 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
case CURLOPT_SSH_COMPRESSION:
data->set.ssh_compression = (0 != va_arg(param, long))?TRUE:FALSE;
break;
+ case CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS:
+ arg = va_arg(param, long);
+ if(arg < 0)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.happy_eyeballs_timeout = arg;
+ break;
+ case CURLOPT_DNS_SHUFFLE_ADDRESSES:
+ data->set.dns_shuffle_addresses = (0 != va_arg(param, long)) ? TRUE:FALSE;
+ break;
default:
/* unknown tag and its companion, just ignore: */
result = CURLE_UNKNOWN_OPTION;
@@ -2536,6 +2574,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
/*
* curl_easy_setopt() is the external interface for setting options on an
* easy handle.
+ *
+ * NOTE: This is one of few API functions that are allowed to be called from
+ * within a callback.
*/
#undef curl_easy_setopt
diff --git a/Utilities/cmcurl/lib/sha256.c b/Utilities/cmcurl/lib/sha256.c
index cd81c02..55716c6 100644
--- a/Utilities/cmcurl/lib/sha256.c
+++ b/Utilities/cmcurl/lib/sha256.c
@@ -29,9 +29,17 @@
#if defined(USE_OPENSSL)
+#include <openssl/opensslv.h>
+
+#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
+#define USE_OPENSSL_SHA256
+#endif
+
+#endif
+
+#ifdef USE_OPENSSL_SHA256
/* When OpenSSL is available we use the SHA256-function from OpenSSL */
#include <openssl/sha.h>
-
#else
/* When no other crypto library is available we use this code segment */
@@ -234,7 +242,7 @@ static int SHA256_Final(unsigned char *out,
sha256_compress(md, md->buf);
md->curlen = 0;
}
- /* pad upto 56 bytes of zeroes */
+ /* pad up to 56 bytes of zeroes */
while(md->curlen < 56) {
md->buf[md->curlen++] = (unsigned char)0;
}
diff --git a/Utilities/cmcurl/lib/smb.c b/Utilities/cmcurl/lib/smb.c
index 6cb4083..9ac6150 100644
--- a/Utilities/cmcurl/lib/smb.c
+++ b/Utilities/cmcurl/lib/smb.c
@@ -709,14 +709,21 @@ static CURLcode smb_connection_state(struct connectdata *conn, bool *done)
}
/*
- * Convert a timestamp from the Windows world (100 nsec units from
- * 1 Jan 1601) to Posix time.
+ * Convert a timestamp from the Windows world (100 nsec units from 1 Jan 1601)
+ * to Posix time. Cap the output to fit within a time_t.
*/
-static void get_posix_time(long *out, curl_off_t timestamp)
+static void get_posix_time(time_t *out, curl_off_t timestamp)
{
timestamp -= 116444736000000000;
timestamp /= 10000000;
- *out = (long) timestamp;
+#if SIZEOF_TIME_T < SIZEOF_CURL_OFF_T
+ if(timestamp > TIME_T_MAX)
+ *out = TIME_T_MAX;
+ else if(timestamp < TIME_T_MIN)
+ *out = TIME_T_MIN;
+ else
+#endif
+ *out = (time_t) timestamp;
}
static CURLcode smb_request_state(struct connectdata *conn, bool *done)
@@ -783,10 +790,16 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
else {
smb_m = (const struct smb_nt_create_response*) msg;
conn->data->req.size = smb_swap64(smb_m->end_of_file);
- Curl_pgrsSetDownloadSize(conn->data, conn->data->req.size);
- if(conn->data->set.get_filetime)
- get_posix_time(&conn->data->info.filetime, smb_m->last_change_time);
- next_state = SMB_DOWNLOAD;
+ if(conn->data->req.size < 0) {
+ req->result = CURLE_WEIRD_SERVER_REPLY;
+ next_state = SMB_CLOSE;
+ }
+ else {
+ Curl_pgrsSetDownloadSize(conn->data, conn->data->req.size);
+ if(conn->data->set.get_filetime)
+ get_posix_time(&conn->data->info.filetime, smb_m->last_change_time);
+ next_state = SMB_DOWNLOAD;
+ }
}
break;
diff --git a/Utilities/cmcurl/lib/smtp.c b/Utilities/cmcurl/lib/smtp.c
index d9f1a85..3f3b45a 100644
--- a/Utilities/cmcurl/lib/smtp.c
+++ b/Utilities/cmcurl/lib/smtp.c
@@ -1289,6 +1289,11 @@ static CURLcode smtp_perform(struct connectdata *conn, bool *connected,
/* Store the first recipient (or NULL if not specified) */
smtp->rcpt = data->set.mail_rcpt;
+ /* Initial data character is the first character in line: it is implicitly
+ preceded by a virtual CRLF. */
+ smtp->trailing_crlf = TRUE;
+ smtp->eob = 2;
+
/* Start the first command in the DO phase */
if((data->set.upload || data->set.mimepost.kind) && data->set.mail_rcpt)
/* MAIL transfer */
diff --git a/Utilities/cmcurl/lib/ssh-libssh.c b/Utilities/cmcurl/lib/ssh-libssh.c
index 56775d7..34ef490 100644
--- a/Utilities/cmcurl/lib/ssh-libssh.c
+++ b/Utilities/cmcurl/lib/ssh-libssh.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2017 Red Hat, Inc.
+ * Copyright (C) 2017 - 2018 Red Hat, Inc.
*
* Authors: Nikos Mavrogiannopoulos, Tomas Mraz, Stanislav Zidek,
* Robert Kolcun, Andreas Schneider
@@ -383,8 +383,10 @@ static int myssh_is_known(struct connectdata *conn)
}
/* we don't have anything equivalent to knownkey. Always NULL */
+ Curl_set_in_callback(data, true);
rc = func(data, NULL, &foundkey, /* from the remote host */
keymatch, data->set.ssh_keyfunc_userp);
+ Curl_set_in_callback(data, false);
switch(rc) {
case CURLKHSTAT_FINE_ADD_TO_FILE:
@@ -1046,7 +1048,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
attrs = sftp_stat(sshc->sftp_session, protop->path);
if(attrs != 0) {
- data->info.filetime = (long)attrs->mtime;
+ data->info.filetime = attrs->mtime;
sftp_attributes_free(attrs);
}
@@ -1128,8 +1130,10 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
if(data->state.resume_from > 0) {
/* Let's read off the proper amount of bytes from the input. */
if(conn->seek_func) {
+ Curl_set_in_callback(data, true);
seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
SEEK_SET);
+ Curl_set_in_callback(data, false);
}
if(seekerr != CURL_SEEKFUNC_OK) {
@@ -2421,8 +2425,7 @@ static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
ssize_t nread;
(void)sockindex;
- if(len >= (size_t)1<<32)
- len = (size_t)(1<<31)-1;
+ DEBUGASSERT(len < CURL_MAX_READ_SIZE);
switch(conn->proto.sshc.sftp_recv_state) {
case 0:
diff --git a/Utilities/cmcurl/lib/ssh.c b/Utilities/cmcurl/lib/ssh.c
index a86ed70..bf7bd54 100644
--- a/Utilities/cmcurl/lib/ssh.c
+++ b/Utilities/cmcurl/lib/ssh.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -342,6 +342,7 @@ static void state(struct connectdata *conn, sshstate nowstate)
"SSH_AUTH_HOST",
"SSH_AUTH_KEY_INIT",
"SSH_AUTH_KEY",
+ "SSH_AUTH_GSSAPI",
"SSH_AUTH_DONE",
"SSH_SFTP_INIT",
"SSH_SFTP_REALPATH",
@@ -376,6 +377,7 @@ static void state(struct connectdata *conn, sshstate nowstate)
"SSH_SCP_TRANS_INIT",
"SSH_SCP_UPLOAD_INIT",
"SSH_SCP_DOWNLOAD_INIT",
+ "SSH_SCP_DOWNLOAD",
"SSH_SCP_DONE",
"SSH_SCP_SEND_EOF",
"SSH_SCP_WAIT_EOF",
@@ -386,6 +388,9 @@ static void state(struct connectdata *conn, sshstate nowstate)
"QUIT"
};
+ /* a precaution to make sure the lists are in sync */
+ DEBUGASSERT(sizeof(names)/sizeof(names[0]) == SSH_LAST);
+
if(sshc->state != nowstate) {
infof(conn->data, "SFTP %p state change from %s to %s\n",
(void *)sshc, names[sshc->state], names[nowstate]);
@@ -523,9 +528,11 @@ static CURLcode ssh_knownhost(struct connectdata *conn)
keymatch = (enum curl_khmatch)keycheck;
/* Ask the callback how to behave */
+ Curl_set_in_callback(data, true);
rc = func(data, knownkeyp, /* from the knownhosts file */
&foundkey, /* from the remote host */
keymatch, data->set.ssh_keyfunc_userp);
+ Curl_set_in_callback(data, false);
}
else
/* no remotekey means failure! */
@@ -777,8 +784,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
* This is done by simply passing sshc->rsa_pub = NULL.
*/
if(data->set.str[STRING_SSH_PUBLIC_KEY]
- /* treat empty string the same way as NULL */
- && data->set.str[STRING_SSH_PUBLIC_KEY][0]) {
+ /* treat empty string the same way as NULL */
+ && data->set.str[STRING_SSH_PUBLIC_KEY][0]) {
sshc->rsa_pub = strdup(data->set.str[STRING_SSH_PUBLIC_KEY]);
if(!sshc->rsa_pub)
out_of_memory = TRUE;
@@ -832,7 +839,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
state(conn, SSH_AUTH_DONE);
}
else {
- char *err_msg;
+ char *err_msg = NULL;
(void)libssh2_session_last_error(sshc->ssh_session,
&err_msg, NULL, 0);
infof(data, "SSH public key authentication failed: %s\n", err_msg);
@@ -1039,7 +1046,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
*/
sshc->sftp_session = libssh2_sftp_init(sshc->ssh_session);
if(!sshc->sftp_session) {
- char *err_msg;
+ char *err_msg = NULL;
if(libssh2_session_last_errno(sshc->ssh_session) ==
LIBSSH2_ERROR_EAGAIN) {
rc = LIBSSH2_ERROR_EAGAIN;
@@ -1246,7 +1253,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(strncasecompare(cmd, "ln ", 3) ||
- strncasecompare(cmd, "symlink ", 8)) {
+ strncasecompare(cmd, "symlink ", 8)) {
/* symbolic linking */
/* sshc->quote_path1 is the source */
/* get the destination */
@@ -1627,7 +1634,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc == 0) {
- data->info.filetime = (long)attrs.mtime;
+ data->info.filetime = attrs.mtime;
}
state(conn, SSH_SFTP_TRANS_INIT);
@@ -1747,8 +1754,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(data->state.resume_from > 0) {
/* Let's read off the proper amount of bytes from the input. */
if(conn->seek_func) {
+ Curl_set_in_callback(data, true);
seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
SEEK_SET);
+ Curl_set_in_callback(data, false);
}
if(seekerr != CURL_SEEKFUNC_OK) {
@@ -1765,9 +1774,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
(size_t)data->set.buffer_size :
curlx_sotouz(data->state.resume_from - passed);
- size_t actuallyread =
- data->state.fread_func(data->state.buffer, 1,
- readthisamountnow, data->state.in);
+ size_t actuallyread;
+ Curl_set_in_callback(data, true);
+ actuallyread = data->state.fread_func(data->state.buffer, 1,
+ readthisamountnow,
+ data->state.in);
+ Curl_set_in_callback(data, false);
passed += actuallyread;
if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
@@ -2131,8 +2143,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc ||
- !(attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) ||
- (attrs.filesize == 0)) {
+ !(attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) ||
+ (attrs.filesize == 0)) {
/*
* libssh2_sftp_open() didn't return an error, so maybe the server
* just doesn't support stat()
@@ -2264,7 +2276,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc < 0) {
- infof(data, "Failed to close libssh2 file\n");
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to close libssh2 file: %d %s\n", rc, err_msg);
}
sshc->sftp_handle = NULL;
}
@@ -2298,7 +2313,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc < 0) {
- infof(data, "Failed to close libssh2 file\n");
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session, &err_msg,
+ NULL, 0);
+ infof(data, "Failed to close libssh2 file: %d %s\n", rc, err_msg);
}
sshc->sftp_handle = NULL;
}
@@ -2353,7 +2371,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
data->state.infilesize);
if(!sshc->ssh_channel) {
int ssh_err;
- char *err_msg;
+ char *err_msg = NULL;
if(libssh2_session_last_errno(sshc->ssh_session) ==
LIBSSH2_ERROR_EAGAIN) {
@@ -2407,9 +2425,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
* be set in sb
*/
- /*
- * If support for >2GB files exists, use it.
- */
+ /*
+ * If support for >2GB files exists, use it.
+ */
/* get a fresh new channel from the ssh layer */
#if LIBSSH2_VERSION_NUM < 0x010700
@@ -2426,7 +2444,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(!sshc->ssh_channel) {
int ssh_err;
- char *err_msg;
+ char *err_msg = NULL;
if(libssh2_session_last_errno(sshc->ssh_session) ==
LIBSSH2_ERROR_EAGAIN) {
@@ -2479,7 +2497,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc) {
- infof(data, "Failed to send libssh2 channel EOF\n");
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to send libssh2 channel EOF: %d %s\n",
+ rc, err_msg);
}
}
state(conn, SSH_SCP_WAIT_EOF);
@@ -2492,7 +2514,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc) {
- infof(data, "Failed to get channel EOF: %d\n", rc);
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to get channel EOF: %d %s\n", rc, err_msg);
}
}
state(conn, SSH_SCP_WAIT_CLOSE);
@@ -2505,7 +2530,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc) {
- infof(data, "Channel failed to close: %d\n", rc);
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Channel failed to close: %d %s\n", rc, err_msg);
}
}
state(conn, SSH_SCP_CHANNEL_FREE);
@@ -2518,7 +2546,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc < 0) {
- infof(data, "Failed to free libssh2 scp subsystem\n");
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to free libssh2 scp subsystem: %d %s\n",
+ rc, err_msg);
}
sshc->ssh_channel = NULL;
}
@@ -2540,7 +2572,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc < 0) {
- infof(data, "Failed to free libssh2 scp subsystem\n");
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to free libssh2 scp subsystem: %d %s\n",
+ rc, err_msg);
}
sshc->ssh_channel = NULL;
}
@@ -2551,7 +2587,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc < 0) {
- infof(data, "Failed to disconnect libssh2 session\n");
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to disconnect libssh2 session: %d %s\n",
+ rc, err_msg);
}
}
@@ -2576,7 +2616,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc < 0) {
- infof(data, "Failed to disconnect from libssh2 agent\n");
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to disconnect from libssh2 agent: %d %s\n",
+ rc, err_msg);
}
libssh2_agent_free(sshc->ssh_agent);
sshc->ssh_agent = NULL;
@@ -2594,7 +2638,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc < 0) {
- infof(data, "Failed to free libssh2 session\n");
+ char *err_msg = NULL;
+ (void)libssh2_session_last_error(sshc->ssh_session,
+ &err_msg, NULL, 0);
+ infof(data, "Failed to free libssh2 session: %d %s\n", rc, err_msg);
}
sshc->ssh_session = NULL;
}
diff --git a/Utilities/cmcurl/lib/strerror.c b/Utilities/cmcurl/lib/strerror.c
index 83a96dd..0295d6c 100644
--- a/Utilities/cmcurl/lib/strerror.c
+++ b/Utilities/cmcurl/lib/strerror.c
@@ -312,6 +312,9 @@ curl_easy_strerror(CURLcode error)
case CURLE_HTTP2_STREAM:
return "Stream error in the HTTP/2 framing layer";
+ case CURLE_RECURSIVE_API_CALL:
+ return "API function called from within callback";
+
/* error codes not used by current libcurl */
case CURLE_OBSOLETE20:
case CURLE_OBSOLETE24:
@@ -380,6 +383,9 @@ curl_multi_strerror(CURLMcode error)
case CURLM_ADDED_ALREADY:
return "The easy handle is already added to a multi handle";
+ case CURLM_RECURSIVE_API_CALL:
+ return "API function called from within callback";
+
case CURLM_LAST:
break;
}
diff --git a/Utilities/cmcurl/lib/strtoofft.c b/Utilities/cmcurl/lib/strtoofft.c
index 3636477..546a3ff 100644
--- a/Utilities/cmcurl/lib/strtoofft.c
+++ b/Utilities/cmcurl/lib/strtoofft.c
@@ -220,8 +220,6 @@ CURLofft curlx_strtoofft(const char *str, char **endp, int base,
errno = 0;
*num = 0; /* clear by default */
- DEBUGASSERT(str);
-
while(*str && ISSPACE(*str))
str++;
if('-' == *str) {
diff --git a/Utilities/cmcurl/lib/telnet.c b/Utilities/cmcurl/lib/telnet.c
index 48b134e..d71c8e0 100644
--- a/Utilities/cmcurl/lib/telnet.c
+++ b/Utilities/cmcurl/lib/telnet.c
@@ -1203,8 +1203,7 @@ CURLcode telrcv(struct connectdata *conn,
CURL_SB_ACCUM(tn, c);
tn->telrcv_state = CURL_TS_SB;
}
- else
- {
+ else {
CURL_SB_ACCUM(tn, CURL_IAC);
CURL_SB_ACCUM(tn, CURL_SE);
tn->subpointer -= 2;
@@ -1460,7 +1459,8 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
if(n == 0) /* no bytes */
break;
- readfile_read = (DWORD)n; /* fall thru with number of bytes read */
+ /* fall through with number of bytes read */
+ readfile_read = (DWORD)n;
}
else {
/* read from stdin */
diff --git a/Utilities/cmcurl/lib/tftp.c b/Utilities/cmcurl/lib/tftp.c
index 20dc600..b32960f 100644
--- a/Utilities/cmcurl/lib/tftp.c
+++ b/Utilities/cmcurl/lib/tftp.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -1010,7 +1010,7 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done)
state->requested_blksize = blksize;
((struct sockaddr *)&state->local_addr)->sa_family =
- (unsigned short)(conn->ip_addr->ai_family);
+ (CURL_SA_FAMILY_T)(conn->ip_addr->ai_family);
tftp_set_timeouts(state);
diff --git a/Utilities/cmcurl/lib/timeval.c b/Utilities/cmcurl/lib/timeval.c
index 66f923a..f4bf835 100644
--- a/Utilities/cmcurl/lib/timeval.c
+++ b/Utilities/cmcurl/lib/timeval.c
@@ -110,7 +110,7 @@ struct curltime Curl_now(void)
usecs /= 1000;
cnow.tv_sec = usecs / 1000000;
- cnow.tv_usec = usecs % 1000000;
+ cnow.tv_usec = (int)(usecs % 1000000);
return cnow;
}
@@ -128,7 +128,7 @@ struct curltime Curl_now(void)
struct curltime ret;
(void)gettimeofday(&now, NULL);
ret.tv_sec = now.tv_sec;
- ret.tv_usec = now.tv_usec;
+ ret.tv_usec = (int)now.tv_usec;
return ret;
}
diff --git a/Utilities/cmcurl/lib/transfer.c b/Utilities/cmcurl/lib/transfer.c
index 8f15b1a..131f2dc 100644
--- a/Utilities/cmcurl/lib/transfer.c
+++ b/Utilities/cmcurl/lib/transfer.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -85,7 +85,7 @@
!defined(CURL_DISABLE_IMAP)
/*
* checkheaders() checks the linked list of custom headers for a
- * particular header (prefix).
+ * particular header (prefix). Provide the prefix without colon!
*
* Returns a pointer to the first matching header or NULL if none matched.
*/
@@ -97,7 +97,8 @@ char *Curl_checkheaders(const struct connectdata *conn,
struct Curl_easy *data = conn->data;
for(head = data->set.headers; head; head = head->next) {
- if(strncasecompare(head->data, thisheader, thislen))
+ if(strncasecompare(head->data, thisheader, thislen) &&
+ Curl_headersep(head->data[thislen]) )
return head->data;
}
@@ -135,8 +136,10 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
/* this function returns a size_t, so we typecast to int to prevent warnings
with picky compilers */
+ Curl_set_in_callback(data, true);
nread = (int)data->state.fread_func(data->req.upload_fromhere, 1,
buffersize, data->state.in);
+ Curl_set_in_callback(data, false);
if(nread == CURL_READFUNC_ABORT) {
failf(data, "operation aborted by callback");
@@ -302,7 +305,9 @@ CURLcode Curl_readrewind(struct connectdata *conn)
if(data->set.seek_func) {
int err;
+ Curl_set_in_callback(data, true);
err = (data->set.seek_func)(data->set.seek_client, 0, SEEK_SET);
+ Curl_set_in_callback(data, false);
if(err) {
failf(data, "seek callback returned error %d", (int)err);
return CURLE_SEND_FAIL_REWIND;
@@ -311,8 +316,10 @@ CURLcode Curl_readrewind(struct connectdata *conn)
else if(data->set.ioctl_func) {
curlioerr err;
+ Curl_set_in_callback(data, true);
err = (data->set.ioctl_func)(data, CURLIOCMD_RESTARTREAD,
data->set.ioctl_client);
+ Curl_set_in_callback(data, false);
infof(data, "the ioctl callback returned %d\n", (int)err);
if(err) {
@@ -710,7 +717,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
#endif /* CURL_DISABLE_HTTP */
/* Account for body content stored in the header buffer */
- if(k->badheader && !k->ignorebody) {
+ if((k->badheader == HEADER_PARTHEADER) && !k->ignorebody) {
DEBUGF(infof(data, "Increasing bytecount by %zu from hbuflen\n",
k->hbuflen));
k->bytecount += k->hbuflen;
@@ -801,10 +808,15 @@ static CURLcode readwrite_data(struct Curl_easy *data,
} /* if(!header and data to read) */
- if(conn->handler->readwrite &&
- (excess > 0 && !conn->bits.stream_was_rewound)) {
+ if(conn->handler->readwrite && excess && !conn->bits.stream_was_rewound) {
/* Parse the excess data */
k->str += nread;
+
+ if(&k->str[excess] > &k->buf[data->set.buffer_size]) {
+ /* the excess amount was too excessive(!), make sure
+ it doesn't read out of buffer */
+ excess = &k->buf[data->set.buffer_size] - k->str;
+ }
nread = (ssize_t)excess;
result = conn->handler->readwrite(data, conn, &nread, &readmore);
@@ -1435,6 +1447,16 @@ static const char *find_host_sep(const char *url)
}
/*
+ * Decide in an encoding-independent manner whether a character in an
+ * URL must be escaped. The same criterion must be used in strlen_url()
+ * and strcpy_url().
+ */
+static bool urlchar_needs_escaping(int c)
+{
+ return !(ISCNTRL(c) || ISSPACE(c) || ISGRAPH(c));
+}
+
+/*
* strlen_url() returns the length of the given URL if the spaces within the
* URL were properly URL encoded.
* URL encoding should be skipped for host names, otherwise IDN resolution
@@ -1462,7 +1484,7 @@ static size_t strlen_url(const char *url, bool relative)
left = FALSE;
/* fall through */
default:
- if(*ptr >= 0x80)
+ if(urlchar_needs_escaping(*ptr))
newlen += 2;
newlen++;
break;
@@ -1507,7 +1529,7 @@ static void strcpy_url(char *output, const char *url, bool relative)
left = FALSE;
/* fall through */
default:
- if(*iptr >= 0x80) {
+ if(urlchar_needs_escaping(*iptr)) {
snprintf(optr, 4, "%%%02x", *iptr);
optr += 3;
}
@@ -1914,7 +1936,7 @@ CURLcode Curl_retry_request(struct connectdata *conn,
char **url)
{
struct Curl_easy *data = conn->data;
-
+ bool retry = FALSE;
*url = NULL;
/* if we're talking upload, we can't do the checks below, unless the protocol
@@ -1927,7 +1949,7 @@ CURLcode Curl_retry_request(struct connectdata *conn,
conn->bits.reuse &&
(!data->set.opt_no_body
|| (conn->handler->protocol & PROTO_FAMILY_HTTP)) &&
- (data->set.rtspreq != RTSPREQ_RECEIVE)) {
+ (data->set.rtspreq != RTSPREQ_RECEIVE))
/* We got no data, we attempted to re-use a connection. For HTTP this
can be a retry so we try again regardless if we expected a body.
For other protocols we only try again only if we expected a body.
@@ -1935,6 +1957,19 @@ CURLcode Curl_retry_request(struct connectdata *conn,
This might happen if the connection was left alive when we were
done using it before, but that was closed when we wanted to read from
it again. Bad luck. Retry the same request on a fresh connect! */
+ retry = TRUE;
+ else if(data->state.refused_stream &&
+ (data->req.bytecount + data->req.headerbytecount == 0) ) {
+ /* This was sent on a refused stream, safe to rerun. A refused stream
+ error can typically only happen on HTTP/2 level if the stream is safe
+ to issue again, but the nghttp2 API can deliver the message to other
+ streams as well, which is why this adds the check the data counters
+ too. */
+ infof(conn->data, "REFUSED_STREAM, retrying a fresh connect\n");
+ data->state.refused_stream = FALSE; /* clear again */
+ retry = TRUE;
+ }
+ if(retry) {
infof(conn->data, "Connection died, retrying a fresh connect\n");
*url = strdup(conn->data->change.url);
if(!*url)
@@ -1983,11 +2018,19 @@ Curl_setup_transfer(
DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
- /* now copy all input parameters */
- conn->sockfd = sockindex == -1 ?
+ if(conn->bits.multiplex || conn->httpversion == 20) {
+ /* when multiplexing, the read/write sockets need to be the same! */
+ conn->sockfd = sockindex == -1 ?
+ ((writesockindex == -1 ? CURL_SOCKET_BAD : conn->sock[writesockindex])) :
+ conn->sock[sockindex];
+ conn->writesockfd = conn->sockfd;
+ }
+ else {
+ conn->sockfd = sockindex == -1 ?
CURL_SOCKET_BAD : conn->sock[sockindex];
- conn->writesockfd = writesockindex == -1 ?
+ conn->writesockfd = writesockindex == -1 ?
CURL_SOCKET_BAD:conn->sock[writesockindex];
+ }
k->getheader = getheader;
k->size = size;
@@ -2006,10 +2049,10 @@ Curl_setup_transfer(
/* we want header and/or body, if neither then don't do this! */
if(k->getheader || !data->set.opt_no_body) {
- if(conn->sockfd != CURL_SOCKET_BAD)
+ if(sockindex != -1)
k->keepon |= KEEP_RECV;
- if(conn->writesockfd != CURL_SOCKET_BAD) {
+ if(writesockindex != -1) {
struct HTTP *http = data->req.protop;
/* HTTP 1.1 magic:
@@ -2040,7 +2083,7 @@ Curl_setup_transfer(
/* enable the write bit when we're not waiting for continue */
k->keepon |= KEEP_SEND;
}
- } /* if(conn->writesockfd != CURL_SOCKET_BAD) */
+ } /* if(writesockindex != -1) */
} /* if(k->getheader || !data->set.opt_no_body) */
}
diff --git a/Utilities/cmcurl/lib/transfer.h b/Utilities/cmcurl/lib/transfer.h
index 72526a8..9ba398d 100644
--- a/Utilities/cmcurl/lib/transfer.h
+++ b/Utilities/cmcurl/lib/transfer.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, 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,6 +22,7 @@
*
***************************************************************************/
+#define Curl_headersep(x) ((((x)==':') || ((x)==';')))
char *Curl_checkheaders(const struct connectdata *conn,
const char *thisheader);
diff --git a/Utilities/cmcurl/lib/url.c b/Utilities/cmcurl/lib/url.c
index 74813e8..701f83a 100644
--- a/Utilities/cmcurl/lib/url.c
+++ b/Utilities/cmcurl/lib/url.c
@@ -488,25 +488,33 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
set->socks5_gssapi_nec = FALSE;
#endif
- /* This is our preferred CA cert bundle/path since install time */
+ /* Set the default CA cert bundle/path detected/specified at build time.
+ *
+ * If Schannel (WinSSL) is the selected SSL backend then these locations
+ * are ignored. We allow setting CA location for schannel only when
+ * explicitly specified by the user via CURLOPT_CAINFO / --cacert.
+ */
+ if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL) {
#if defined(CURL_CA_BUNDLE)
- result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_ORIG], CURL_CA_BUNDLE);
- if(result)
- return result;
+ result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_ORIG], CURL_CA_BUNDLE);
+ if(result)
+ return result;
- result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_PROXY], CURL_CA_BUNDLE);
- if(result)
- return result;
+ result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_PROXY],
+ CURL_CA_BUNDLE);
+ if(result)
+ return result;
#endif
#if defined(CURL_CA_PATH)
- result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_ORIG], CURL_CA_PATH);
- if(result)
- return result;
+ result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_ORIG], CURL_CA_PATH);
+ if(result)
+ return result;
- result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_PROXY], CURL_CA_PATH);
- if(result)
- return result;
+ result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_PROXY], CURL_CA_PATH);
+ if(result)
+ return result;
#endif
+ }
set->wildcard_enabled = FALSE;
set->chunk_bgn = ZERO_NULL;
@@ -527,6 +535,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
set->expect_100_timeout = 1000L; /* Wait for a second by default. */
set->sep_headers = TRUE; /* separated header lists by default */
set->buffer_size = READBUFFER_SIZE;
+ set->happy_eyeballs_timeout = CURL_HET_DEFAULT;
Curl_http2_init_userset(set);
return result;
@@ -2066,15 +2075,6 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
return CURLE_URL_MALFORMAT;
}
- if(url_has_scheme && path[0] == '/' && path[1] == '/' &&
- path[2] == '/' && path[3] == '/') {
- /* This appears to be a UNC string (usually indicating a SMB share).
- * We don't do SMB in file: URLs. (TODO?)
- */
- failf(data, "SMB shares are not supported in file: URLs.");
- return CURLE_URL_MALFORMAT;
- }
-
/* Extra handling URLs with an authority component (i.e. that start with
* "file://")
*
@@ -2113,25 +2113,6 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
ptr += 9; /* now points to the slash after the host */
}
- /*
- * RFC 8089, Appendix D, Section D.1, says:
- *
- * > In a POSIX file system, the root of the file system is represented
- * > as a directory with a zero-length name, usually written as "/"; the
- * > presence of this root in a file URI can be taken as given by the
- * > initial slash in the "path-absolute" rule.
- *
- * i.e. the first slash is part of the path.
- *
- * However in RFC 1738 the "/" between the host (or port) and the
- * URL-path was NOT part of the URL-path. Any agent that followed the
- * older spec strictly, and wanted to refer to a file with an absolute
- * path, would have included a second slash. So if there are two
- * slashes, swallow one.
- */
- if('/' == ptr[1]) /* note: the only way ptr[0]!='/' is if ptr[1]==':' */
- ptr++;
-
/* This cannot be done with strcpy, as the memory chunks overlap! */
memmove(path, ptr, strlen(ptr) + 1);
}
@@ -2573,7 +2554,15 @@ static bool check_noproxy(const char *name, const char *no_proxy)
/* NO_PROXY was specified and it wasn't just an asterisk */
no_proxy_len = strlen(no_proxy);
- endptr = strchr(name, ':');
+ if(name[0] == '[') {
+ /* IPv6 numerical address */
+ endptr = strchr(name, ']');
+ if(!endptr)
+ return FALSE;
+ name++;
+ }
+ else
+ endptr = strchr(name, ':');
if(endptr)
namelen = endptr - name;
else
@@ -2681,13 +2670,20 @@ static char *detect_proxy(struct connectdata *conn)
prox = curl_getenv(proxy_env);
}
- if(prox)
+ envp = proxy_env;
+ if(prox) {
proxy = prox; /* use this */
+ }
else {
- proxy = curl_getenv("all_proxy"); /* default proxy to use */
- if(!proxy)
- proxy = curl_getenv("ALL_PROXY");
+ envp = (char *)"all_proxy";
+ proxy = curl_getenv(envp); /* default proxy to use */
+ if(!proxy) {
+ envp = (char *)"ALL_PROXY";
+ proxy = curl_getenv(envp);
+ }
}
+ if(proxy)
+ infof(conn->data, "Uses proxy env variable %s == '%s'\n", envp, proxy);
return proxy;
}
@@ -2744,7 +2740,7 @@ static CURLcode parse_proxy(struct Curl_easy *data,
proxyptr = proxy; /* No xxx:// head: It's a HTTP proxy */
#ifdef USE_SSL
- if(!Curl_ssl->support_https_proxy)
+ if(!(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY))
#endif
if(proxytype == CURLPROXY_HTTPS) {
failf(data, "Unsupported proxy \'%s\', libcurl is built without the "
@@ -2972,9 +2968,15 @@ static CURLcode create_conn_helper_init_proxy(struct connectdata *conn)
}
if(!data->set.str[STRING_NOPROXY]) {
- no_proxy = curl_getenv("no_proxy");
- if(!no_proxy)
- no_proxy = curl_getenv("NO_PROXY");
+ const char *p = "no_proxy";
+ no_proxy = curl_getenv(p);
+ if(!no_proxy) {
+ p = "NO_PROXY";
+ no_proxy = curl_getenv(p);
+ }
+ if(no_proxy) {
+ infof(conn->data, "Uses proxy env variable %s == '%s'\n", p, no_proxy);
+ }
}
if(check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY] ?
@@ -3417,7 +3419,7 @@ static CURLcode parse_remote_port(struct Curl_easy *data,
* stripped off. It would be better to work directly from the original
* URL and simply replace the port part of it.
*/
- url = aprintf("%s://%s%s%s:%hu%s%s%s", conn->given->scheme,
+ url = aprintf("%s://%s%s%s:%d%s%s%s", conn->given->scheme,
conn->bits.ipv6_ip?"[":"", conn->host.name,
conn->bits.ipv6_ip?"]":"", conn->remote_port,
data->state.slash_removed?"/":"", data->state.path,
@@ -4116,7 +4118,7 @@ static CURLcode create_conn(struct Curl_easy *data,
*************************************************************/
if(prot_missing) {
/* We're guessing prefixes here and if we're told to use a proxy or if
- we're gonna follow a Location: later or... then we need the protocol
+ we're going to follow a Location: later or... then we need the protocol
part added so that we have a valid URL. */
char *reurl;
char *ch_lower;
diff --git a/Utilities/cmcurl/lib/urldata.h b/Utilities/cmcurl/lib/urldata.h
index 5c04ad1..7fae00f 100644
--- a/Utilities/cmcurl/lib/urldata.h
+++ b/Utilities/cmcurl/lib/urldata.h
@@ -98,6 +98,20 @@
#include "hash.h"
#include "splay.h"
+/* return the count of bytes sent, or -1 on error */
+typedef ssize_t (Curl_send)(struct connectdata *conn, /* connection data */
+ int sockindex, /* socketindex */
+ const void *buf, /* data to write */
+ size_t len, /* max amount to write */
+ CURLcode *err); /* error to return */
+
+/* return the count of bytes read, or -1 on error */
+typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */
+ int sockindex, /* socketindex */
+ char *buf, /* store data here */
+ size_t len, /* max amount to read */
+ CURLcode *err); /* error to return */
+
#include "mime.h"
#include "imap.h"
#include "pop3.h"
@@ -328,6 +342,7 @@ struct ntlmdata {
BYTE *output_token;
BYTE *input_token;
size_t input_token_len;
+ TCHAR *spn;
#else
unsigned int flags;
unsigned char nonce[8];
@@ -703,20 +718,6 @@ struct Curl_handler {
#define CONNRESULT_NONE 0 /* No extra information. */
#define CONNRESULT_DEAD (1<<0) /* The connection is dead. */
-/* return the count of bytes sent, or -1 on error */
-typedef ssize_t (Curl_send)(struct connectdata *conn, /* connection data */
- int sockindex, /* socketindex */
- const void *buf, /* data to write */
- size_t len, /* max amount to write */
- CURLcode *err); /* error to return */
-
-/* return the count of bytes read, or -1 on error */
-typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */
- int sockindex, /* socketindex */
- char *buf, /* store data here */
- size_t len, /* max amount to read */
- CURLcode *err); /* error to return */
-
#ifdef USE_RECV_BEFORE_SEND_WORKAROUND
struct postponed_data {
char *buffer; /* Temporal store for received data during
@@ -895,7 +896,7 @@ struct connectdata {
well be the same we read from.
CURL_SOCKET_BAD disables */
- /** Dynamicly allocated strings, MUST be freed before this **/
+ /** Dynamically allocated strings, MUST be freed before this **/
/** struct is killed. **/
struct dynamically_allocated_data {
char *proxyuserpwd;
@@ -1024,10 +1025,8 @@ struct PureInfo {
int httpcode; /* Recent HTTP, FTP, RTSP or SMTP response code */
int httpproxycode; /* response code from proxy when received separate */
int httpversion; /* the http version number X.Y = X*10+Y */
- long filetime; /* If requested, this is might get set. Set to -1 if the time
- was unretrievable. We cannot have this of type time_t,
- since time_t is unsigned on several platforms such as
- OpenVMS. */
+ time_t filetime; /* If requested, this is might get set. Set to -1 if the
+ time was unretrievable. */
bool timecond; /* set to TRUE if the time condition didn't match, which
thus made the document NOT get fetched */
long header_size; /* size of read header(s) in bytes */
@@ -1168,7 +1167,7 @@ struct Curl_http2_dep {
};
/*
- * This struct is for holding data that was attemped to get sent to the user's
+ * This struct is for holding data that was attempted to get sent to the user's
* callback but is held due to pausing. One instance per type (BOTH, HEADER,
* BODY).
*/
@@ -1227,7 +1226,7 @@ struct UrlState {
curl_off_t current_speed; /* the ProgressShow() function sets this,
bytes / second */
bool this_is_a_follow; /* this is a followed Location: request */
-
+ bool refused_stream; /* this was refused, try again */
char *first_host; /* host name of the first (not followed) request.
if set, this should be the host name that we will
sent authorization to, no else. Used to make Location:
@@ -1424,13 +1423,8 @@ enum dupstring {
STRING_SSH_HOST_PUBLIC_KEY_MD5, /* md5 of host public key in ascii hex */
STRING_SSH_KNOWNHOSTS, /* file name of knownhosts file */
#endif
-#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
STRING_PROXY_SERVICE_NAME, /* Proxy service name */
-#endif
-#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
- defined(USE_SPNEGO) || defined(HAVE_GSSAPI)
STRING_SERVICE_NAME, /* Service name */
-#endif
STRING_MAIL_FROM,
STRING_MAIL_AUTH,
@@ -1522,6 +1516,7 @@ struct UserDefined {
long timeout; /* in milliseconds, 0 means no timeout */
long connecttimeout; /* in milliseconds, 0 means no timeout */
long accepttimeout; /* in milliseconds, 0 means no timeout */
+ long happy_eyeballs_timeout; /* in milliseconds, 0 is a valid value */
long server_response_timeout; /* in milliseconds, 0 means no timeout */
long tftp_blksize; /* in bytes, 0 means use default */
bool tftp_no_options; /* do not send TFTP options requests */
@@ -1675,13 +1670,21 @@ struct UserDefined {
bool suppress_connect_headers; /* suppress proxy CONNECT response headers
from user callbacks */
+ bool dns_shuffle_addresses; /* whether to shuffle addresses before use */
+
struct Curl_easy *stream_depends_on;
bool stream_depends_e; /* set or don't set the Exclusive bit */
int stream_weight;
+ bool haproxyprotocol; /* whether to send HAProxy PROXY protocol header */
+
struct Curl_http2_dep *stream_dependents;
bool abstract_unix_socket;
+
+ curl_resolver_start_callback resolver_start; /* optional callback called
+ before resolver start */
+ void *resolver_start_client; /* pointer to pass to resolver start callback */
};
struct Names {
diff --git a/Utilities/cmcurl/lib/vauth/cleartext.c b/Utilities/cmcurl/lib/vauth/cleartext.c
index a761ae7..5d61ce6 100644
--- a/Utilities/cmcurl/lib/vauth/cleartext.c
+++ b/Utilities/cmcurl/lib/vauth/cleartext.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -73,16 +73,10 @@ CURLcode Curl_auth_create_plain_message(struct Curl_easy *data,
ulen = strlen(userp);
plen = strlen(passwdp);
- /* 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)
+ /* Compute binary message length. Check for overflows. */
+ if((ulen > SIZE_T_MAX/2) || (plen > (SIZE_T_MAX/2 - 2)))
return CURLE_OUT_OF_MEMORY;
+ plainlen = 2 * ulen + plen + 2;
plainauth = malloc(plainlen);
if(!plainauth)
diff --git a/Utilities/cmcurl/lib/vauth/krb5_sspi.c b/Utilities/cmcurl/lib/vauth/krb5_sspi.c
index 1b4cef4..9afb971 100644
--- a/Utilities/cmcurl/lib/vauth/krb5_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/krb5_sspi.c
@@ -135,7 +135,7 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data,
}
if(!krb5->credentials) {
- /* Do we have credientials to use or are we using single sign-on? */
+ /* Do we have credentials to use or are we using single sign-on? */
if(userp && *userp) {
/* Populate our identity structure */
result = Curl_create_sspi_identity(userp, passwdp, &krb5->identity);
@@ -150,12 +150,10 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data,
krb5->p_identity = NULL;
/* Allocate our credentials handle */
- krb5->credentials = malloc(sizeof(CredHandle));
+ krb5->credentials = calloc(1, sizeof(CredHandle));
if(!krb5->credentials)
return CURLE_OUT_OF_MEMORY;
- memset(krb5->credentials, 0, sizeof(CredHandle));
-
/* Acquire our credentials handle */
status = s_pSecFn->AcquireCredentialsHandle(NULL,
(TCHAR *)
@@ -167,11 +165,9 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data,
return CURLE_LOGIN_DENIED;
/* Allocate our new context handle */
- krb5->context = malloc(sizeof(CtxtHandle));
+ krb5->context = calloc(1, sizeof(CtxtHandle));
if(!krb5->context)
return CURLE_OUT_OF_MEMORY;
-
- memset(krb5->context, 0, sizeof(CtxtHandle));
}
if(chlg64 && *chlg64) {
diff --git a/Utilities/cmcurl/lib/vauth/ntlm.c b/Utilities/cmcurl/lib/vauth/ntlm.c
index 1e0d479..cdb8d8f 100644
--- a/Utilities/cmcurl/lib/vauth/ntlm.c
+++ b/Utilities/cmcurl/lib/vauth/ntlm.c
@@ -63,9 +63,9 @@
/* "NTLMSSP" signature is always in ASCII regardless of the platform */
#define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50"
-#define SHORTPAIR(x) ((x) & 0xff), (((x) >> 8) & 0xff)
-#define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8) & 0xff), \
- (((x) >> 16) & 0xff), (((x) >> 24) & 0xff)
+#define SHORTPAIR(x) ((int)((x) & 0xff)), ((int)(((x) >> 8) & 0xff))
+#define LONGQUARTET(x) ((int)((x) & 0xff)), ((int)(((x) >> 8) & 0xff)), \
+ ((int)(((x) >> 16) & 0xff)), ((int)(((x) >> 24) & 0xff))
#if DEBUG_ME
# define DEBUG_OUT(x) x
@@ -355,6 +355,8 @@ static void unicodecpy(unsigned char *dest, const char *src, size_t length)
* data [in] - The session handle.
* userp [in] - The user name in the format User or Domain\User.
* passdwp [in] - The user's password.
+ * service [in] - The service type such as http, smtp, pop or imap.
+ * host [in] - The host name.
* ntlm [in/out] - The NTLM data struct being used and modified.
* outptr [in/out] - The address where a pointer to newly allocated memory
* holding the result will be stored upon completion.
@@ -365,6 +367,8 @@ static void unicodecpy(unsigned char *dest, const char *src, size_t length)
CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
const char *userp,
const char *passwdp,
+ const char *service,
+ const char *hostname,
struct ntlmdata *ntlm,
char **outptr, size_t *outlen)
{
@@ -394,6 +398,8 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
domain are empty */
(void)userp;
(void)passwdp;
+ (void)service,
+ (void)hostname,
/* Clean up any former leftovers and initialise to defaults */
Curl_auth_ntlm_cleanup(ntlm);
diff --git a/Utilities/cmcurl/lib/vauth/ntlm.h b/Utilities/cmcurl/lib/vauth/ntlm.h
index f906a3c..1136b0f 100644
--- a/Utilities/cmcurl/lib/vauth/ntlm.h
+++ b/Utilities/cmcurl/lib/vauth/ntlm.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_NTLM_H
-#define HEADER_CURL_NTLM_H
+#ifndef HEADER_VAUTH_NTLM_H
+#define HEADER_VAUTH_NTLM_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -140,4 +140,4 @@
#endif /* USE_NTLM */
-#endif /* HEADER_CURL_NTLM_H */
+#endif /* HEADER_VAUTH_NTLM_H */
diff --git a/Utilities/cmcurl/lib/vauth/ntlm_sspi.c b/Utilities/cmcurl/lib/vauth/ntlm_sspi.c
index e748ce3..089c1a6 100644
--- a/Utilities/cmcurl/lib/vauth/ntlm_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/ntlm_sspi.c
@@ -70,6 +70,8 @@ bool Curl_auth_is_ntlm_supported(void)
* data [in] - The session handle.
* userp [in] - The user name in the format User or Domain\User.
* passdwp [in] - The user's password.
+ * service [in] - The service type such as http, smtp, pop or imap.
+ * host [in] - The host name.
* ntlm [in/out] - The NTLM data struct being used and modified.
* outptr [in/out] - The address where a pointer to newly allocated memory
* holding the result will be stored upon completion.
@@ -80,6 +82,8 @@ bool Curl_auth_is_ntlm_supported(void)
CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
const char *userp,
const char *passwdp,
+ const char *service,
+ const char *host,
struct ntlmdata *ntlm,
char **outptr, size_t *outlen)
{
@@ -125,12 +129,10 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
ntlm->p_identity = NULL;
/* Allocate our credentials handle */
- ntlm->credentials = malloc(sizeof(CredHandle));
+ ntlm->credentials = calloc(1, sizeof(CredHandle));
if(!ntlm->credentials)
return CURLE_OUT_OF_MEMORY;
- memset(ntlm->credentials, 0, sizeof(CredHandle));
-
/* Acquire our credentials handle */
status = s_pSecFn->AcquireCredentialsHandle(NULL,
(TCHAR *) TEXT(SP_NAME_NTLM),
@@ -141,11 +143,13 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
return CURLE_LOGIN_DENIED;
/* Allocate our new context handle */
- ntlm->context = malloc(sizeof(CtxtHandle));
+ ntlm->context = calloc(1, sizeof(CtxtHandle));
if(!ntlm->context)
return CURLE_OUT_OF_MEMORY;
- memset(ntlm->context, 0, sizeof(CtxtHandle));
+ ntlm->spn = Curl_auth_build_spn(service, host, NULL);
+ if(!ntlm->spn)
+ return CURLE_OUT_OF_MEMORY;
/* Setup the type-1 "output" security buffer */
type_1_desc.ulVersion = SECBUFFER_VERSION;
@@ -157,7 +161,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
/* Generate our type-1 message */
status = s_pSecFn->InitializeSecurityContext(ntlm->credentials, NULL,
- (TCHAR *) TEXT(""),
+ ntlm->spn,
0, 0, SECURITY_NETWORK_DREP,
NULL, 0,
ntlm->context, &type_1_desc,
@@ -275,7 +279,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
/* Generate our type-3 message */
status = s_pSecFn->InitializeSecurityContext(ntlm->credentials,
ntlm->context,
- (TCHAR *) TEXT(""),
+ ntlm->spn,
0, 0, SECURITY_NETWORK_DREP,
&type_2_desc,
0, ntlm->context,
@@ -333,6 +337,8 @@ void Curl_auth_ntlm_cleanup(struct ntlmdata *ntlm)
/* Reset any variables */
ntlm->token_max = 0;
+
+ Curl_safefree(ntlm->spn);
}
#endif /* USE_WINDOWS_SSPI && USE_NTLM */
diff --git a/Utilities/cmcurl/lib/vauth/spnego_sspi.c b/Utilities/cmcurl/lib/vauth/spnego_sspi.c
index a6797cd..1fe19e3 100644
--- a/Utilities/cmcurl/lib/vauth/spnego_sspi.c
+++ b/Utilities/cmcurl/lib/vauth/spnego_sspi.c
@@ -138,7 +138,7 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
}
if(!nego->credentials) {
- /* Do we have credientials to use or are we using single sign-on? */
+ /* Do we have credentials to use or are we using single sign-on? */
if(user && *user) {
/* Populate our identity structure */
result = Curl_create_sspi_identity(user, password, &nego->identity);
@@ -153,12 +153,10 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
nego->p_identity = NULL;
/* Allocate our credentials handle */
- nego->credentials = malloc(sizeof(CredHandle));
+ nego->credentials = calloc(1, sizeof(CredHandle));
if(!nego->credentials)
return CURLE_OUT_OF_MEMORY;
- memset(nego->credentials, 0, sizeof(CredHandle));
-
/* Acquire our credentials handle */
nego->status =
s_pSecFn->AcquireCredentialsHandle(NULL,
@@ -170,11 +168,9 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
return CURLE_LOGIN_DENIED;
/* Allocate our new context handle */
- nego->context = malloc(sizeof(CtxtHandle));
+ nego->context = calloc(1, sizeof(CtxtHandle));
if(!nego->context)
return CURLE_OUT_OF_MEMORY;
-
- memset(nego->context, 0, sizeof(CtxtHandle));
}
if(chlg64 && *chlg64) {
diff --git a/Utilities/cmcurl/lib/vauth/vauth.c b/Utilities/cmcurl/lib/vauth/vauth.c
index b995f34..502d443 100644
--- a/Utilities/cmcurl/lib/vauth/vauth.c
+++ b/Utilities/cmcurl/lib/vauth/vauth.c
@@ -115,8 +115,8 @@ TCHAR *Curl_auth_build_spn(const char *service, const char *host,
* User@Domain (User Principal Name)
*
* Note: The user name may be empty when using a GSS-API library or Windows SSPI
-* as the user and domain are either obtained from the credientals cache when
-* using GSS-API or via the currently logged in user's credientals when using
+* as the user and domain are either obtained from the credentials cache when
+* using GSS-API or via the currently logged in user's credentials when using
* Windows SSPI.
*
* Parameters:
@@ -138,7 +138,7 @@ bool Curl_auth_user_contains_domain(const char *user)
}
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
else
- /* User and domain are obtained from the GSS-API credientials cache or the
+ /* User and domain are obtained from the GSS-API credentials cache or the
currently logged in user from Windows */
valid = TRUE;
#endif
diff --git a/Utilities/cmcurl/lib/vauth/vauth.h b/Utilities/cmcurl/lib/vauth/vauth.h
index dfaf985..f430642 100644
--- a/Utilities/cmcurl/lib/vauth/vauth.h
+++ b/Utilities/cmcurl/lib/vauth/vauth.h
@@ -122,6 +122,8 @@ bool Curl_auth_is_ntlm_supported(void);
CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
const char *userp,
const char *passwdp,
+ const char *service,
+ const char *host,
struct ntlmdata *ntlm,
char **outptr,
size_t *outlen);
diff --git a/Utilities/cmcurl/lib/version.c b/Utilities/cmcurl/lib/version.c
index 1752e14..5b0d05a 100644
--- a/Utilities/cmcurl/lib/version.c
+++ b/Utilities/cmcurl/lib/version.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -399,7 +399,7 @@ curl_version_info_data *curl_version_info(CURLversion stamp)
#ifdef USE_SSL
Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer));
version_info.ssl_version = ssl_buffer;
- if(Curl_ssl->support_https_proxy)
+ if(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY)
version_info.features |= CURL_VERSION_HTTPS_PROXY;
else
version_info.features &= ~CURL_VERSION_HTTPS_PROXY;
diff --git a/Utilities/cmcurl/lib/vtls/axtls.c b/Utilities/cmcurl/lib/vtls/axtls.c
index 9294f49..5ed898b 100644
--- a/Utilities/cmcurl/lib/vtls/axtls.c
+++ b/Utilities/cmcurl/lib/vtls/axtls.c
@@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2010, DirecTV, Contact: Eric Hu, <ehu@directv.com>.
- * Copyright (C) 2010 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2010 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -703,13 +703,7 @@ static void *Curl_axtls_get_internals(struct ssl_connect_data *connssl,
const struct Curl_ssl Curl_ssl_axtls = {
{ CURLSSLBACKEND_AXTLS, "axtls" }, /* info */
-
- 0, /* have_ca_path */
- 0, /* have_certinfo */
- 0, /* have_pinnedpubkey */
- 0, /* have_ssl_ctx */
- 0, /* support_https_proxy */
-
+ 0, /* no fancy stuff */
sizeof(struct ssl_backend_data),
/*
diff --git a/Utilities/cmcurl/lib/vtls/cyassl.c b/Utilities/cmcurl/lib/vtls/cyassl.c
index 46b71bf..20ce460 100644
--- a/Utilities/cmcurl/lib/vtls/cyassl.c
+++ b/Utilities/cmcurl/lib/vtls/cyassl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -187,8 +187,13 @@ cyassl_connect_step1(struct connectdata *conn,
use_sni(TRUE);
break;
case CURL_SSLVERSION_TLSv1_0:
+#ifdef WOLFSSL_ALLOW_TLSV10
req_method = TLSv1_client_method();
use_sni(TRUE);
+#else
+ failf(data, "CyaSSL does not support TLS 1.0");
+ return CURLE_NOT_BUILT_IN;
+#endif
break;
case CURL_SSLVERSION_TLSv1_1:
req_method = TLSv1_1_client_method();
@@ -199,8 +204,14 @@ cyassl_connect_step1(struct connectdata *conn,
use_sni(TRUE);
break;
case CURL_SSLVERSION_TLSv1_3:
+#ifdef WOLFSSL_TLS13
+ req_method = wolfTLSv1_3_client_method();
+ use_sni(TRUE);
+ break;
+#else
failf(data, "CyaSSL: TLS 1.3 is not yet supported");
return CURLE_SSL_CONNECT_ERROR;
+#endif
case CURL_SSLVERSION_SSLv3:
#ifdef WOLFSSL_ALLOW_SSLV3
req_method = SSLv3_client_method();
@@ -245,7 +256,11 @@ cyassl_connect_step1(struct connectdata *conn,
*/
if((wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1) != 1) &&
(wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_1) != 1) &&
- (wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_2) != 1)) {
+ (wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_2) != 1)
+#ifdef WOLFSSL_TLS13
+ && (wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_3) != 1)
+#endif
+ ) {
failf(data, "SSL: couldn't set the minimum protocol version");
return CURLE_SSL_CONNECT_ERROR;
}
@@ -956,7 +971,7 @@ static CURLcode Curl_cyassl_random(struct Curl_easy *data,
return CURLE_OK;
}
-static void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */
+static CURLcode Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */
size_t tmplen,
unsigned char *sha256sum /* output */,
size_t unused)
@@ -966,6 +981,7 @@ static void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */
InitSha256(&SHA256pw);
Sha256Update(&SHA256pw, tmp, (word32)tmplen);
Sha256Final(&SHA256pw, sha256sum);
+ return CURLE_OK;
}
static void *Curl_cyassl_get_internals(struct ssl_connect_data *connssl,
@@ -978,15 +994,10 @@ static void *Curl_cyassl_get_internals(struct ssl_connect_data *connssl,
const struct Curl_ssl Curl_ssl_cyassl = {
{ CURLSSLBACKEND_WOLFSSL, "WolfSSL" }, /* info */
- 0, /* have_ca_path */
- 0, /* have_certinfo */
#ifdef KEEP_PEER_CERT
- 1, /* have_pinnedpubkey */
-#else
- 0, /* have_pinnedpubkey */
+ SSLSUPP_PINNEDPUBKEY |
#endif
- 1, /* have_ssl_ctx */
- 0, /* support_https_proxy */
+ SSLSUPP_SSL_CTX,
sizeof(struct ssl_backend_data),
diff --git a/Utilities/cmcurl/lib/vtls/darwinssl.c b/Utilities/cmcurl/lib/vtls/darwinssl.c
index 53a7ec3..45fe49d 100644
--- a/Utilities/cmcurl/lib/vtls/darwinssl.c
+++ b/Utilities/cmcurl/lib/vtls/darwinssl.c
@@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2012 - 2017, Nick Zitzmann, <nickzman@gmail.com>.
- * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -1135,28 +1135,79 @@ static OSStatus CopyIdentityFromPKCS12File(const char *cPath,
raise linker errors when used on that cat for some reason. */
#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
if(CFURLCreateDataAndPropertiesFromResource(NULL, pkcs_url, &pkcs_data,
- NULL, NULL, &status)) {
+ NULL, NULL, &status)) {
+ CFArrayRef items = NULL;
+
+ /* On iOS SecPKCS12Import will never add the client certificate to the
+ * Keychain.
+ *
+ * It gives us back a SecIdentityRef that we can use directly. */
+#if CURL_BUILD_IOS
const void *cKeys[] = {kSecImportExportPassphrase};
const void *cValues[] = {password};
CFDictionaryRef options = CFDictionaryCreate(NULL, cKeys, cValues,
password ? 1L : 0L, NULL, NULL);
- CFArrayRef items = NULL;
- /* Here we go: */
- status = SecPKCS12Import(pkcs_data, options, &items);
- if(status == errSecSuccess && items && CFArrayGetCount(items)) {
- CFDictionaryRef identity_and_trust = CFArrayGetValueAtIndex(items, 0L);
- const void *temp_identity = CFDictionaryGetValue(identity_and_trust,
- kSecImportItemIdentity);
+ if(options != NULL) {
+ status = SecPKCS12Import(pkcs_data, options, &items);
+ CFRelease(options);
+ }
+
+
+ /* On macOS SecPKCS12Import will always add the client certificate to
+ * the Keychain.
+ *
+ * As this doesn't match iOS, and apps may not want to see their client
+ * certificate saved in the the user's keychain, we use SecItemImport
+ * with a NULL keychain to avoid importing it.
+ *
+ * This returns a SecCertificateRef from which we can construct a
+ * SecIdentityRef.
+ */
+#elif CURL_BUILD_MAC_10_7
+ SecItemImportExportKeyParameters keyParams;
+ SecExternalFormat inputFormat = kSecFormatPKCS12;
+ SecExternalItemType inputType = kSecItemTypeCertificate;
- /* Retain the identity; we don't care about any other data... */
- CFRetain(temp_identity);
- *out_cert_and_key = (SecIdentityRef)temp_identity;
+ memset(&keyParams, 0x00, sizeof(keyParams));
+ keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
+ keyParams.passphrase = password;
+
+ status = SecItemImport(pkcs_data, NULL, &inputFormat, &inputType,
+ 0, &keyParams, NULL, &items);
+#endif
+
+
+ /* Extract the SecIdentityRef */
+ if(status == errSecSuccess && items && CFArrayGetCount(items)) {
+ CFIndex i, count;
+ count = CFArrayGetCount(items);
+
+ for(i = 0; i < count; i++) {
+ CFTypeRef item = (CFTypeRef) CFArrayGetValueAtIndex(items, i);
+ CFTypeID itemID = CFGetTypeID(item);
+
+ if(itemID == CFDictionaryGetTypeID()) {
+ CFTypeRef identity = (CFTypeRef) CFDictionaryGetValue(
+ (CFDictionaryRef) item,
+ kSecImportItemIdentity);
+ CFRetain(identity);
+ *out_cert_and_key = (SecIdentityRef) identity;
+ break;
+ }
+#if CURL_BUILD_MAC_10_7
+ else if(itemID == SecCertificateGetTypeID()) {
+ status = SecIdentityCreateWithCertificate(NULL,
+ (SecCertificateRef) item,
+ out_cert_and_key);
+ break;
+ }
+#endif
+ }
}
if(items)
CFRelease(items);
- CFRelease(options);
CFRelease(pkcs_data);
}
#endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
@@ -1340,7 +1391,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
#endif /* CURL_BUILD_MAC */
#if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
- if(SSLCreateContext != NULL) { /* use the newer API if avaialble */
+ if(SSLCreateContext != NULL) { /* use the newer API if available */
if(BACKEND->ssl_ctx)
CFRelease(BACKEND->ssl_ctx);
BACKEND->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
@@ -2843,13 +2894,14 @@ static CURLcode Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
return CURLE_OK;
}
-static void Curl_darwinssl_sha256sum(const unsigned char *tmp, /* input */
+static CURLcode Curl_darwinssl_sha256sum(const unsigned char *tmp, /* input */
size_t tmplen,
unsigned char *sha256sum, /* output */
size_t sha256len)
{
assert(sha256len >= CURL_SHA256_DIGEST_LENGTH);
(void)CC_SHA256(tmp, (CC_LONG)tmplen, sha256sum);
+ return CURLE_OK;
}
static bool Curl_darwinssl_false_start(void)
@@ -2977,15 +3029,11 @@ static void *Curl_darwinssl_get_internals(struct ssl_connect_data *connssl,
const struct Curl_ssl Curl_ssl_darwinssl = {
{ CURLSSLBACKEND_DARWINSSL, "darwinssl" }, /* info */
- 0, /* have_ca_path */
- 0, /* have_certinfo */
#ifdef DARWIN_SSL_PINNEDPUBKEY
- 1, /* have_pinnedpubkey */
+ SSLSUPP_PINNEDPUBKEY,
#else
- 0, /* have_pinnedpubkey */
+ 0,
#endif /* DARWIN_SSL_PINNEDPUBKEY */
- 0, /* have_ssl_ctx */
- 0, /* support_https_proxy */
sizeof(struct ssl_backend_data),
diff --git a/Utilities/cmcurl/lib/vtls/gskit.c b/Utilities/cmcurl/lib/vtls/gskit.c
index 8f0cc0b..b0856cd 100644
--- a/Utilities/cmcurl/lib/vtls/gskit.c
+++ b/Utilities/cmcurl/lib/vtls/gskit.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -1353,12 +1353,8 @@ static void *Curl_gskit_get_internals(struct ssl_connect_data *connssl,
const struct Curl_ssl Curl_ssl_gskit = {
{ CURLSSLBACKEND_GSKIT, "gskit" }, /* info */
- 0, /* have_ca_path */
- 1, /* have_certinfo */
- 0, /* have_pinnedpubkey */
- 0, /* have_ssl_ctx */
- /* TODO: convert to 1 and fix test #1014 (if need) */
- 0, /* support_https_proxy */
+ SSLSUPP_CERTINFO |
+ SSLSUPP_PINNEDPUBKEY,
sizeof(struct ssl_backend_data),
diff --git a/Utilities/cmcurl/lib/vtls/gtls.c b/Utilities/cmcurl/lib/vtls/gtls.c
index 30b255b..207b0fd 100644
--- a/Utilities/cmcurl/lib/vtls/gtls.c
+++ b/Utilities/cmcurl/lib/vtls/gtls.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -60,15 +60,6 @@
/* The last #include file should be: */
#include "memdebug.h"
-#ifndef GNUTLS_POINTER_TO_SOCKET_CAST
-#define GNUTLS_POINTER_TO_SOCKET_CAST(p) \
- ((curl_socket_t) ((char *)(p) - (char *)NULL))
-#endif
-#ifndef GNUTLS_SOCKET_TO_POINTER_CAST
-#define GNUTLS_SOCKET_TO_POINTER_CAST(s) \
- ((void *) ((char *)NULL + (s)))
-#endif
-
/* Enable GnuTLS debugging by defining GTLSDEBUG */
/*#define GTLSDEBUG */
@@ -161,7 +152,8 @@ static int gtls_mapped_sockerrno(void)
static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len)
{
- ssize_t ret = swrite(GNUTLS_POINTER_TO_SOCKET_CAST(s), buf, len);
+ curl_socket_t sock = *(curl_socket_t *)s;
+ ssize_t ret = swrite(sock, buf, len);
#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
if(ret < 0)
gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
@@ -171,7 +163,8 @@ static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len)
static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len)
{
- ssize_t ret = sread(GNUTLS_POINTER_TO_SOCKET_CAST(s), buf, len);
+ curl_socket_t sock = *(curl_socket_t *)s;
+ ssize_t ret = sread(sock, buf, len);
#if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS)
if(ret < 0)
gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
@@ -857,7 +850,7 @@ gtls_connect_step1(struct connectdata *conn,
}
else {
/* file descriptor for the socket */
- transport_ptr = GNUTLS_SOCKET_TO_POINTER_CAST(conn->sock[sockindex]);
+ transport_ptr = &conn->sock[sockindex];
gnutls_transport_push = Curl_gtls_push;
gnutls_transport_pull = Curl_gtls_pull;
}
@@ -1770,7 +1763,7 @@ static CURLcode Curl_gtls_md5sum(unsigned char *tmp, /* input */
return CURLE_OK;
}
-static void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
+static CURLcode Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
size_t tmplen,
unsigned char *sha256sum, /* output */
size_t sha256len)
@@ -1787,6 +1780,7 @@ static void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
memcpy(sha256sum, gcry_md_read(SHA256pw, 0), sha256len);
gcry_md_close(SHA256pw);
#endif
+ return CURLE_OK;
}
static bool Curl_gtls_cert_status_request(void)
@@ -1808,11 +1802,10 @@ static void *Curl_gtls_get_internals(struct ssl_connect_data *connssl,
const struct Curl_ssl Curl_ssl_gnutls = {
{ CURLSSLBACKEND_GNUTLS, "gnutls" }, /* info */
- 1, /* have_ca_path */
- 1, /* have_certinfo */
- 1, /* have_pinnedpubkey */
- 0, /* have_ssl_ctx */
- 1, /* support_https_proxy */
+ SSLSUPP_CA_PATH |
+ SSLSUPP_CERTINFO |
+ SSLSUPP_PINNEDPUBKEY |
+ SSLSUPP_HTTPS_PROXY,
sizeof(struct ssl_backend_data),
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls.c b/Utilities/cmcurl/lib/vtls/mbedtls.c
index 28251a3..d7759dc 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls.c
+++ b/Utilities/cmcurl/lib/vtls/mbedtls.c
@@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
- * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -815,7 +815,7 @@ static void Curl_mbedtls_session_free(void *ptr)
static size_t Curl_mbedtls_version(char *buffer, size_t size)
{
unsigned int version = mbedtls_version_get_number();
- return snprintf(buffer, size, "mbedTLS/%d.%d.%d", version>>24,
+ return snprintf(buffer, size, "mbedTLS/%u.%u.%u", version>>24,
(version>>16)&0xff, (version>>8)&0xff);
}
@@ -1023,13 +1023,20 @@ static bool Curl_mbedtls_data_pending(const struct connectdata *conn,
return mbedtls_ssl_get_bytes_avail(&BACKEND->ssl) != 0;
}
-static void Curl_mbedtls_sha256sum(const unsigned char *input,
+static CURLcode Curl_mbedtls_sha256sum(const unsigned char *input,
size_t inputlen,
unsigned char *sha256sum,
size_t sha256len UNUSED_PARAM)
{
(void)sha256len;
+#if MBEDTLS_VERSION_NUMBER < 0x02070000
mbedtls_sha256(input, inputlen, sha256sum, 0);
+#else
+ /* returns 0 on success, otherwise failure */
+ if(mbedtls_sha256_ret(input, inputlen, sha256sum, 0) != 0)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+#endif
+ return CURLE_OK;
}
static void *Curl_mbedtls_get_internals(struct ssl_connect_data *connssl,
@@ -1042,11 +1049,9 @@ static void *Curl_mbedtls_get_internals(struct ssl_connect_data *connssl,
const struct Curl_ssl Curl_ssl_mbedtls = {
{ CURLSSLBACKEND_MBEDTLS, "mbedtls" }, /* info */
- 1, /* have_ca_path */
- 0, /* have_certinfo */
- 1, /* have_pinnedpubkey */
- 1, /* have_ssl_ctx */
- 0, /* support_https_proxy */
+ SSLSUPP_CA_PATH |
+ SSLSUPP_PINNEDPUBKEY |
+ SSLSUPP_SSL_CTX,
sizeof(struct ssl_backend_data),
diff --git a/Utilities/cmcurl/lib/vtls/nss.c b/Utilities/cmcurl/lib/vtls/nss.c
index a3ef37a..7cd450c 100644
--- a/Utilities/cmcurl/lib/vtls/nss.c
+++ b/Utilities/cmcurl/lib/vtls/nss.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -440,7 +440,17 @@ static CURLcode nss_create_object(struct ssl_connect_data *connssl,
PK11_SETATTRS(attrs, attr_cnt, CKA_TRUST, pval, sizeof(*pval));
}
- obj = PK11_CreateGenericObject(slot, attrs, attr_cnt, PR_FALSE);
+ /* PK11_CreateManagedGenericObject() was introduced in NSS 3.34 because
+ * PK11_DestroyGenericObject() does not release resources allocated by
+ * PK11_CreateGenericObject() early enough. */
+ obj =
+#ifdef HAVE_PK11_CREATEMANAGEDGENERICOBJECT
+ PK11_CreateManagedGenericObject
+#else
+ PK11_CreateGenericObject
+#endif
+ (slot, attrs, attr_cnt, PR_FALSE);
+
PK11_FreeSlot(slot);
if(!obj)
return result;
@@ -2304,7 +2314,7 @@ static CURLcode Curl_nss_md5sum(unsigned char *tmp, /* input */
return CURLE_OK;
}
-static void Curl_nss_sha256sum(const unsigned char *tmp, /* input */
+static CURLcode Curl_nss_sha256sum(const unsigned char *tmp, /* input */
size_t tmplen,
unsigned char *sha256sum, /* output */
size_t sha256len)
@@ -2315,6 +2325,8 @@ static void Curl_nss_sha256sum(const unsigned char *tmp, /* input */
PK11_DigestOp(SHA256pw, tmp, curlx_uztoui(tmplen));
PK11_DigestFinal(SHA256pw, sha256sum, &SHA256out, curlx_uztoui(sha256len));
PK11_DestroyContext(SHA256pw, PR_TRUE);
+
+ return CURLE_OK;
}
static bool Curl_nss_cert_status_request(void)
@@ -2345,11 +2357,10 @@ static void *Curl_nss_get_internals(struct ssl_connect_data *connssl,
const struct Curl_ssl Curl_ssl_nss = {
{ CURLSSLBACKEND_NSS, "nss" }, /* info */
- 1, /* have_ca_path */
- 1, /* have_certinfo */
- 1, /* have_pinnedpubkey */
- 0, /* have_ssl_ctx */
- 1, /* support_https_proxy */
+ SSLSUPP_CA_PATH |
+ SSLSUPP_CERTINFO |
+ SSLSUPP_PINNEDPUBKEY |
+ SSLSUPP_HTTPS_PROXY,
sizeof(struct ssl_backend_data),
diff --git a/Utilities/cmcurl/lib/vtls/openssl.c b/Utilities/cmcurl/lib/vtls/openssl.c
index 93faa6f..f6a4bd3 100644
--- a/Utilities/cmcurl/lib/vtls/openssl.c
+++ b/Utilities/cmcurl/lib/vtls/openssl.c
@@ -104,13 +104,22 @@
#endif
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && /* OpenSSL 1.1.0+ */ \
- !defined(LIBRESSL_VERSION_NUMBER)
+ !(defined(LIBRESSL_VERSION_NUMBER) && \
+ LIBRESSL_VERSION_NUMBER < 0x20700000L)
#define SSLEAY_VERSION_NUMBER OPENSSL_VERSION_NUMBER
#define HAVE_X509_GET0_EXTENSIONS 1 /* added in 1.1.0 -pre1 */
#define HAVE_OPAQUE_EVP_PKEY 1 /* since 1.1.0 -pre3 */
#define HAVE_OPAQUE_RSA_DSA_DH 1 /* since 1.1.0 -pre5 */
#define CONST_EXTS const
#define HAVE_ERR_REMOVE_THREAD_STATE_DEPRECATED 1
+
+/* funny typecast define due to difference in API */
+#ifdef LIBRESSL_VERSION_NUMBER
+#define ARG2_X509_signature_print (X509_ALGOR *)
+#else
+#define ARG2_X509_signature_print
+#endif
+
#else
/* For OpenSSL before 1.1.0 */
#define ASN1_STRING_get0_data(x) ASN1_STRING_data(x)
@@ -128,7 +137,8 @@ static unsigned long OpenSSL_version_num(void)
#endif
#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && /* 1.0.2 or later */ \
- !defined(LIBRESSL_VERSION_NUMBER)
+ !(defined(LIBRESSL_VERSION_NUMBER) && \
+ LIBRESSL_VERSION_NUMBER < 0x20700000L)
#define HAVE_X509_GET0_SIGNATURE 1
#endif
@@ -147,7 +157,7 @@ static unsigned long OpenSSL_version_num(void)
* Whether SSL_CTX_set_keylog_callback is available.
* OpenSSL: supported since 1.1.1 https://github.com/openssl/openssl/pull/2287
* BoringSSL: supported since d28f59c27bac (committed 2015-11-19)
- * LibreSSL: unsupported in at least 2.5.1 (explicitly check for it since it
+ * LibreSSL: unsupported in at least 2.7.2 (explicitly check for it since it
* lies and pretends to be OpenSSL 2.0.0).
*/
#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && \
@@ -259,7 +269,9 @@ static void tap_ssl_key(const SSL *ssl, ssl_tap_state_t *state)
if(!session || !keylog_file_fp)
return;
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
+ !(defined(LIBRESSL_VERSION_NUMBER) && \
+ LIBRESSL_VERSION_NUMBER < 0x20700000L)
/* ssl->s3 is not checked in openssl 1.1.0-pre6, but let's assume that
* we have a valid SSL context if we have a non-NULL session. */
SSL_get_client_random(ssl, client_random, SSL3_RANDOM_SIZE);
@@ -649,18 +661,28 @@ int cert_stuff(struct connectdata *conn,
case SSL_FILETYPE_PKCS12:
{
- FILE *f;
- PKCS12 *p12;
+ BIO *fp = NULL;
+ PKCS12 *p12 = NULL;
EVP_PKEY *pri;
STACK_OF(X509) *ca = NULL;
- f = fopen(cert_file, "rb");
- if(!f) {
+ fp = BIO_new(BIO_s_file());
+ if(fp == NULL) {
+ failf(data,
+ "BIO_new return NULL, " OSSL_PACKAGE
+ " error %s",
+ ossl_strerror(ERR_get_error(), error_buffer,
+ sizeof(error_buffer)) );
+ return 0;
+ }
+
+ if(BIO_read_filename(fp, cert_file) <= 0) {
failf(data, "could not open PKCS12 file '%s'", cert_file);
+ BIO_free(fp);
return 0;
}
- p12 = d2i_PKCS12_fp(f, NULL);
- fclose(f);
+ p12 = d2i_PKCS12_bio(fp, NULL);
+ BIO_free(fp);
if(!p12) {
failf(data, "error reading PKCS12 file '%s'", cert_file);
@@ -1311,6 +1333,51 @@ static void Curl_ossl_close_all(struct Curl_easy *data)
/* ====================================================== */
+/*
+ * Match subjectAltName against the host name. This requires a conversion
+ * in CURL_DOES_CONVERSIONS builds.
+ */
+static bool subj_alt_hostcheck(struct Curl_easy *data,
+ const char *match_pattern, const char *hostname,
+ const char *dispname)
+#ifdef CURL_DOES_CONVERSIONS
+{
+ bool res = FALSE;
+
+ /* Curl_cert_hostcheck uses host encoding, but we get ASCII from
+ OpenSSl.
+ */
+ char *match_pattern2 = strdup(match_pattern);
+
+ if(match_pattern2) {
+ if(Curl_convert_from_network(data, match_pattern2,
+ strlen(match_pattern2)) == CURLE_OK) {
+ if(Curl_cert_hostcheck(match_pattern2, hostname)) {
+ res = TRUE;
+ infof(data,
+ " subjectAltName: host \"%s\" matched cert's \"%s\"\n",
+ dispname, match_pattern2);
+ }
+ }
+ free(match_pattern2);
+ }
+ else {
+ failf(data,
+ "SSL: out of memory when allocating temporary for subjectAltName");
+ }
+ return res;
+}
+#else
+{
+ if(Curl_cert_hostcheck(match_pattern, hostname)) {
+ infof(data, " subjectAltName: host \"%s\" matched cert's \"%s\"\n",
+ dispname, match_pattern);
+ return TRUE;
+ }
+ return FALSE;
+}
+#endif
+
/* Quote from RFC2818 section 3.1 "Server Identity"
@@ -1410,11 +1477,8 @@ 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, hostname)) {
+ subj_alt_hostcheck(data, altptr, hostname, dispname)) {
dnsmatched = TRUE;
- infof(data,
- " subjectAltName: host \"%s\" matched cert's \"%s\"\n",
- dispname, altptr);
}
break;
@@ -1725,13 +1789,40 @@ static const char *ssl_msg_type(int ssl_ver, int msg)
case SSL3_MT_CERTIFICATE_STATUS:
return "Certificate Status";
#endif
+#ifdef SSL3_MT_ENCRYPTED_EXTENSIONS
+ case SSL3_MT_ENCRYPTED_EXTENSIONS:
+ return "Encrypted Extensions";
+#endif
+#ifdef SSL3_MT_END_OF_EARLY_DATA
+ case SSL3_MT_END_OF_EARLY_DATA:
+ return "End of early data";
+#endif
+#ifdef SSL3_MT_KEY_UPDATE
+ case SSL3_MT_KEY_UPDATE:
+ return "Key update";
+#endif
+#ifdef SSL3_MT_NEXT_PROTO
+ case SSL3_MT_NEXT_PROTO:
+ return "Next protocol";
+#endif
+#ifdef SSL3_MT_MESSAGE_HASH
+ case SSL3_MT_MESSAGE_HASH:
+ return "Message hash";
+#endif
}
}
return "Unknown";
}
-static const char *tls_rt_type(int type)
+static const char *tls_rt_type(int type, const void *buf, size_t buflen)
{
+ (void)buf;
+ (void)buflen;
+#ifdef SSL3_RT_INNER_CONTENT_TYPE
+ if(type == SSL3_RT_INNER_CONTENT_TYPE && buf && buflen >= 1)
+ type = *(unsigned char *)buf;
+#endif
+
switch(type) {
#ifdef SSL3_RT_HEADER
case SSL3_RT_HEADER:
@@ -1759,10 +1850,7 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
void *userp)
{
struct Curl_easy *data;
- const char *msg_name, *tls_rt_name;
- char ssl_buf[1024];
char unknown[32];
- int msg_type, txt_len;
const char *verstr = NULL;
struct connectdata *conn = userp;
@@ -1810,6 +1898,10 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
}
if(ssl_ver) {
+ const char *msg_name, *tls_rt_name;
+ char ssl_buf[1024];
+ int msg_type, txt_len;
+
/* the info given when the version is zero is not that useful for us */
ssl_ver >>= 8; /* check the upper 8 bits only below */
@@ -1819,17 +1911,28 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
* is at 'buf[0]'.
*/
if(ssl_ver == SSL3_VERSION_MAJOR && content_type)
- tls_rt_name = tls_rt_type(content_type);
+ tls_rt_name = tls_rt_type(content_type, buf, len);
else
tls_rt_name = "";
- msg_type = *(char *)buf;
- msg_name = ssl_msg_type(ssl_ver, msg_type);
+#ifdef SSL3_RT_INNER_CONTENT_TYPE
+ if(content_type == SSL3_RT_INNER_CONTENT_TYPE) {
+ msg_type = 0;
+ msg_name = "[no content]";
+ }
+ else
+#endif
+ {
+ 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",
verstr, direction?"OUT":"IN",
tls_rt_name, msg_name, msg_type);
- Curl_debug(data, CURLINFO_TEXT, ssl_buf, (size_t)txt_len, NULL);
+ if(0 <= txt_len && (unsigned)txt_len < sizeof(ssl_buf)) {
+ Curl_debug(data, CURLINFO_TEXT, ssl_buf, (size_t)txt_len, NULL);
+ }
}
Curl_debug(data, (direction == 1) ? CURLINFO_SSL_DATA_OUT :
@@ -2082,8 +2185,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
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)
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
req_method = TLS_client_method();
#else
req_method = SSLv23_client_method();
@@ -2800,7 +2902,7 @@ static CURLcode get_cert_chain(struct connectdata *conn,
ASN1_STRING *a = ASN1_STRING_new();
if(a) {
X509_get0_signature(&psig, &palg, x);
- X509_signature_print(mem, palg, a);
+ X509_signature_print(mem, ARG2_X509_signature_print palg, a);
ASN1_STRING_free(a);
if(palg) {
@@ -3035,7 +3137,8 @@ static CURLcode servercert(struct connectdata *conn,
long lerr, len;
struct Curl_easy *data = conn->data;
X509 *issuer;
- FILE *fp;
+ BIO *fp = NULL;
+ char error_buffer[256]="";
char buffer[2048];
const char *ptr;
long * const certverifyresult = SSL_IS_PROXY() ?
@@ -3046,8 +3149,20 @@ static CURLcode servercert(struct connectdata *conn,
/* we've been asked to gather certificate info! */
(void)get_cert_chain(conn, connssl);
+ fp = BIO_new(BIO_s_file());
+ if(fp == NULL) {
+ failf(data,
+ "BIO_new return NULL, " OSSL_PACKAGE
+ " error %s",
+ ossl_strerror(ERR_get_error(), error_buffer,
+ sizeof(error_buffer)) );
+ BIO_free(mem);
+ return 0;
+ }
+
BACKEND->server_cert = SSL_get_peer_certificate(BACKEND->handle);
if(!BACKEND->server_cert) {
+ BIO_free(fp);
BIO_free(mem);
if(!strict)
return CURLE_OK;
@@ -3077,6 +3192,7 @@ static CURLcode servercert(struct connectdata *conn,
if(SSL_CONN_CONFIG(verifyhost)) {
result = verifyhost(conn, BACKEND->server_cert);
if(result) {
+ BIO_free(fp);
X509_free(BACKEND->server_cert);
BACKEND->server_cert = NULL;
return result;
@@ -3098,35 +3214,35 @@ static CURLcode servercert(struct connectdata *conn,
/* e.g. match issuer name with provided issuer certificate */
if(SSL_SET_OPTION(issuercert)) {
- fp = fopen(SSL_SET_OPTION(issuercert), FOPEN_READTEXT);
- if(!fp) {
+ if(BIO_read_filename(fp, SSL_SET_OPTION(issuercert)) <= 0) {
if(strict)
failf(data, "SSL: Unable to open issuer cert (%s)",
SSL_SET_OPTION(issuercert));
+ BIO_free(fp);
X509_free(BACKEND->server_cert);
BACKEND->server_cert = NULL;
return CURLE_SSL_ISSUER_ERROR;
}
- issuer = PEM_read_X509(fp, NULL, ZERO_NULL, NULL);
+ issuer = PEM_read_bio_X509(fp, NULL, ZERO_NULL, NULL);
if(!issuer) {
if(strict)
failf(data, "SSL: Unable to read issuer cert (%s)",
SSL_SET_OPTION(issuercert));
- X509_free(BACKEND->server_cert);
+ BIO_free(fp);
X509_free(issuer);
- fclose(fp);
+ X509_free(BACKEND->server_cert);
+ BACKEND->server_cert = NULL;
return CURLE_SSL_ISSUER_ERROR;
}
- fclose(fp);
-
if(X509_check_issued(issuer, BACKEND->server_cert) != X509_V_OK) {
if(strict)
failf(data, "SSL: Certificate issuer check failed (%s)",
SSL_SET_OPTION(issuercert));
- X509_free(BACKEND->server_cert);
+ BIO_free(fp);
X509_free(issuer);
+ X509_free(BACKEND->server_cert);
BACKEND->server_cert = NULL;
return CURLE_SSL_ISSUER_ERROR;
}
@@ -3161,6 +3277,7 @@ static CURLcode servercert(struct connectdata *conn,
if(SSL_CONN_CONFIG(verifystatus)) {
result = verifystatus(conn, connssl);
if(result) {
+ BIO_free(fp);
X509_free(BACKEND->server_cert);
BACKEND->server_cert = NULL;
return result;
@@ -3180,6 +3297,7 @@ static CURLcode servercert(struct connectdata *conn,
failf(data, "SSL: public key does not match pinned public key!");
}
+ BIO_free(fp);
X509_free(BACKEND->server_cert);
BACKEND->server_cert = NULL;
connssl->connecting_state = ssl_connect_done;
@@ -3580,25 +3698,34 @@ static CURLcode Curl_ossl_md5sum(unsigned char *tmp, /* input */
unsigned char *md5sum /* output */,
size_t unused)
{
- MD5_CTX MD5pw;
- (void)unused;
- MD5_Init(&MD5pw);
- MD5_Update(&MD5pw, tmp, tmplen);
- MD5_Final(md5sum, &MD5pw);
+ EVP_MD_CTX *mdctx;
+ unsigned int len = 0;
+ (void) unused;
+
+ mdctx = EVP_MD_CTX_create();
+ EVP_DigestInit_ex(mdctx, EVP_md5(), NULL);
+ EVP_DigestUpdate(mdctx, tmp, tmplen);
+ EVP_DigestFinal_ex(mdctx, md5sum, &len);
+ EVP_MD_CTX_destroy(mdctx);
return CURLE_OK;
}
#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
-static void Curl_ossl_sha256sum(const unsigned char *tmp, /* input */
+static CURLcode Curl_ossl_sha256sum(const unsigned char *tmp, /* input */
size_t tmplen,
unsigned char *sha256sum /* output */,
size_t unused)
{
- SHA256_CTX SHA256pw;
- (void)unused;
- SHA256_Init(&SHA256pw);
- SHA256_Update(&SHA256pw, tmp, tmplen);
- SHA256_Final(sha256sum, &SHA256pw);
+ EVP_MD_CTX *mdctx;
+ unsigned int len = 0;
+ (void) unused;
+
+ mdctx = EVP_MD_CTX_create();
+ EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL);
+ EVP_DigestUpdate(mdctx, tmp, tmplen);
+ EVP_DigestFinal_ex(mdctx, sha256sum, &len);
+ EVP_MD_CTX_destroy(mdctx);
+ return CURLE_OK;
}
#endif
@@ -3623,11 +3750,11 @@ static void *Curl_ossl_get_internals(struct ssl_connect_data *connssl,
const struct Curl_ssl Curl_ssl_openssl = {
{ CURLSSLBACKEND_OPENSSL, "openssl" }, /* info */
- 1, /* have_ca_path */
- 1, /* have_certinfo */
- 1, /* have_pinnedpubkey */
- 1, /* have_ssl_ctx */
- 1, /* support_https_proxy */
+ SSLSUPP_CA_PATH |
+ SSLSUPP_CERTINFO |
+ SSLSUPP_PINNEDPUBKEY |
+ SSLSUPP_SSL_CTX |
+ SSLSUPP_HTTPS_PROXY,
sizeof(struct ssl_backend_data),
diff --git a/Utilities/cmcurl/lib/vtls/polarssl.c b/Utilities/cmcurl/lib/vtls/polarssl.c
index df29fa9..604cb4c 100644
--- a/Utilities/cmcurl/lib/vtls/polarssl.c
+++ b/Utilities/cmcurl/lib/vtls/polarssl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
*
* This software is licensed as described in the file COPYING, which
@@ -620,12 +620,10 @@ polarssl_connect_step3(struct connectdata *conn,
ssl_session *our_ssl_sessionid;
void *old_ssl_sessionid = NULL;
- our_ssl_sessionid = malloc(sizeof(ssl_session));
+ our_ssl_sessionid = calloc(1, sizeof(ssl_session));
if(!our_ssl_sessionid)
return CURLE_OUT_OF_MEMORY;
- memset(our_ssl_sessionid, 0, sizeof(ssl_session));
-
ret = ssl_get_session(&BACKEND->ssl, our_ssl_sessionid);
if(ret) {
failf(data, "ssl_get_session returned -0x%x", -ret);
@@ -882,13 +880,14 @@ static bool Curl_polarssl_data_pending(const struct connectdata *conn,
return ssl_get_bytes_avail(&BACKEND->ssl) != 0;
}
-static void Curl_polarssl_sha256sum(const unsigned char *input,
+static CURLcode Curl_polarssl_sha256sum(const unsigned char *input,
size_t inputlen,
unsigned char *sha256sum,
size_t sha256len UNUSED_PARAM)
{
(void)sha256len;
sha256(input, inputlen, sha256sum, 0);
+ return CURLE_OK;
}
static void *Curl_polarssl_get_internals(struct ssl_connect_data *connssl,
@@ -901,11 +900,8 @@ static void *Curl_polarssl_get_internals(struct ssl_connect_data *connssl,
const struct Curl_ssl Curl_ssl_polarssl = {
{ CURLSSLBACKEND_POLARSSL, "polarssl" }, /* info */
- 1, /* have_ca_path */
- 0, /* have_certinfo */
- 1, /* have_pinnedpubkey */
- 0, /* have_ssl_ctx */
- 0, /* support_https_proxy */
+ SSLSUPP_CA_PATH |
+ SSLSUPP_PINNEDPUBKEY,
sizeof(struct ssl_backend_data),
diff --git a/Utilities/cmcurl/lib/vtls/schannel.c b/Utilities/cmcurl/lib/vtls/schannel.c
index 85c64cf..2cfd5c1 100644
--- a/Utilities/cmcurl/lib/vtls/schannel.c
+++ b/Utilities/cmcurl/lib/vtls/schannel.c
@@ -7,7 +7,7 @@
*
* Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de>
* Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com>
- * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -42,13 +42,12 @@
#ifdef USE_SCHANNEL
+#define EXPOSE_SCHANNEL_INTERNAL_STRUCTS
+
#ifndef USE_WINDOWS_SSPI
# error "Can't compile SCHANNEL support without SSPI."
#endif
-#include <schnlsp.h>
-#include <schannel.h>
-#include "curl_sspi.h"
#include "schannel.h"
#include "vtls.h"
#include "sendf.h"
@@ -61,7 +60,6 @@
#include "x509asn1.h"
#include "curl_printf.h"
#include "system_win32.h"
-#include "hostcheck.h"
/* The last #include file should be: */
#include "curl_memory.h"
@@ -92,6 +90,12 @@
#endif
#endif
+#ifdef UNICODE
+#define CURL_CERT_STORE_PROV_SYSTEM CERT_STORE_PROV_SYSTEM_W
+#else
+#define CURL_CERT_STORE_PROV_SYSTEM CERT_STORE_PROV_SYSTEM_A
+#endif
+
#ifndef SP_PROT_SSL2_CLIENT
#define SP_PROT_SSL2_CLIENT 0x00000008
#endif
@@ -124,50 +128,25 @@
#define CURL_SCHANNEL_BUFFER_INIT_SIZE 4096
#define CURL_SCHANNEL_BUFFER_FREE_SIZE 1024
+#define CERT_THUMBPRINT_STR_LEN 40
+#define CERT_THUMBPRINT_DATA_LEN 20
+
/* Uncomment to force verbose output
* #define infof(x, y, ...) printf(y, __VA_ARGS__)
* #define failf(x, y, ...) printf(y, __VA_ARGS__)
*/
-/* Structs to store Schannel handles */
-struct curl_schannel_cred {
- CredHandle cred_handle;
- TimeStamp time_stamp;
- int refcount;
-};
-
-struct curl_schannel_ctxt {
- CtxtHandle ctxt_handle;
- TimeStamp time_stamp;
-};
-
-struct ssl_backend_data {
- struct curl_schannel_cred *cred;
- struct curl_schannel_ctxt *ctxt;
- SecPkgContext_StreamSizes stream_sizes;
- size_t encdata_length, decdata_length;
- size_t encdata_offset, decdata_offset;
- unsigned char *encdata_buffer, *decdata_buffer;
- /* encdata_is_incomplete: if encdata contains only a partial record that
- can't be decrypted without another Curl_read_plain (that is, status is
- SEC_E_INCOMPLETE_MESSAGE) then set this true. after Curl_read_plain writes
- more bytes into encdata then set this back to false. */
- bool encdata_is_incomplete;
- unsigned long req_flags, ret_flags;
- CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */
- bool recv_sspi_close_notify; /* true if connection closed by close_notify */
- bool recv_connection_closed; /* true if connection closed, regardless how */
- bool use_alpn; /* true if ALPN is used for this connection */
-};
+#ifndef CALG_SHA_256
+# define CALG_SHA_256 0x0000800c
+#endif
#define BACKEND connssl->backend
static Curl_recv schannel_recv;
static Curl_send schannel_send;
-#ifdef _WIN32_WCE
-static CURLcode verify_certificate(struct connectdata *conn, int sockindex);
-#endif
+static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex,
+ const char *pinnedpubkey);
static void InitSecBuffer(SecBuffer *buffer, unsigned long BufType,
void *BufDataPtr, unsigned long BufByteSize)
@@ -221,6 +200,56 @@ set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct connectdata *conn)
}
static CURLcode
+get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path,
+ TCHAR **thumbprint)
+{
+ TCHAR *sep;
+ size_t store_name_len;
+
+ sep = _tcschr(path, TEXT('\\'));
+ if(sep == NULL)
+ return CURLE_SSL_CONNECT_ERROR;
+
+ store_name_len = sep - path;
+
+ if(_tcsnccmp(path, TEXT("CurrentUser"), store_name_len) == 0)
+ *store_name = CERT_SYSTEM_STORE_CURRENT_USER;
+ else if(_tcsnccmp(path, TEXT("LocalMachine"), store_name_len) == 0)
+ *store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE;
+ else if(_tcsnccmp(path, TEXT("CurrentService"), store_name_len) == 0)
+ *store_name = CERT_SYSTEM_STORE_CURRENT_SERVICE;
+ else if(_tcsnccmp(path, TEXT("Services"), store_name_len) == 0)
+ *store_name = CERT_SYSTEM_STORE_SERVICES;
+ else if(_tcsnccmp(path, TEXT("Users"), store_name_len) == 0)
+ *store_name = CERT_SYSTEM_STORE_USERS;
+ else if(_tcsnccmp(path, TEXT("CurrentUserGroupPolicy"),
+ store_name_len) == 0)
+ *store_name = CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY;
+ else if(_tcsnccmp(path, TEXT("LocalMachineGroupPolicy"),
+ store_name_len) == 0)
+ *store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY;
+ else if(_tcsnccmp(path, TEXT("LocalMachineEnterprise"),
+ store_name_len) == 0)
+ *store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE;
+ else
+ return CURLE_SSL_CONNECT_ERROR;
+
+ *store_path = sep + 1;
+
+ sep = _tcschr(*store_path, TEXT('\\'));
+ if(sep == NULL)
+ return CURLE_SSL_CONNECT_ERROR;
+
+ *sep = 0;
+
+ *thumbprint = sep + 1;
+ if(_tcslen(*thumbprint) != CERT_THUMBPRINT_STR_LEN)
+ return CURLE_SSL_CONNECT_ERROR;
+
+ return CURLE_OK;
+}
+
+static CURLcode
schannel_connect_step1(struct connectdata *conn, int sockindex)
{
ssize_t written = -1;
@@ -234,6 +263,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
unsigned char alpn_buffer[128];
#endif
SCHANNEL_CRED schannel_cred;
+ PCCERT_CONTEXT client_certs[1] = { NULL };
SECURITY_STATUS sspi_status = SEC_E_OK;
struct curl_schannel_cred *old_cred = NULL;
struct in_addr addr;
@@ -268,6 +298,26 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
BACKEND->use_alpn = false;
#endif
+#ifdef _WIN32_WCE
+ /* certificate validation on CE doesn't seem to work right; we'll
+ * do it following a more manual process. */
+ BACKEND->use_manual_cred_validation = true;
+#else
+ if(SSL_CONN_CONFIG(CAfile)) {
+ if(Curl_verify_windows_version(6, 1, PLATFORM_WINNT,
+ VERSION_GREATER_THAN_EQUAL)) {
+ BACKEND->use_manual_cred_validation = true;
+ }
+ else {
+ failf(data, "schannel: this version of Windows is too old to support "
+ "certificate verification via CA bundle file.");
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ }
+ else
+ BACKEND->use_manual_cred_validation = false;
+#endif
+
BACKEND->cred = NULL;
/* check for an existing re-usable credential handle */
@@ -291,26 +341,23 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
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. */
- schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
- SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
- SCH_CRED_IGNORE_REVOCATION_OFFLINE;
-#else
- schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION;
+ if(BACKEND->use_manual_cred_validation)
+ schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION;
+ else
+ schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION;
+
/* TODO s/data->set.ssl.no_revoke/SSL_SET_OPTION(no_revoke)/g */
- if(data->set.ssl.no_revoke)
+ 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)
+ SCH_CRED_IGNORE_REVOCATION_OFFLINE;
+
infof(data, "schannel: disabled server certificate revocation "
"checks\n");
- else
+ }
+ else {
+ schannel_cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN;
infof(data, "schannel: checking server certificate revocation\n");
+ }
}
else {
schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
@@ -354,14 +401,70 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
return CURLE_SSL_CONNECT_ERROR;
}
+ /* client certificate */
+ if(data->set.ssl.cert) {
+ DWORD cert_store_name;
+ TCHAR *cert_store_path;
+ TCHAR *cert_thumbprint_str;
+ CRYPT_HASH_BLOB cert_thumbprint;
+ BYTE cert_thumbprint_data[CERT_THUMBPRINT_DATA_LEN];
+ HCERTSTORE cert_store;
+
+ TCHAR *cert_path = Curl_convert_UTF8_to_tchar(data->set.ssl.cert);
+ if(!cert_path)
+ return CURLE_OUT_OF_MEMORY;
+
+ result = get_cert_location(cert_path, &cert_store_name,
+ &cert_store_path, &cert_thumbprint_str);
+ if(result != CURLE_OK) {
+ Curl_unicodefree(cert_path);
+ return result;
+ }
+
+ cert_store = CertOpenStore(CURL_CERT_STORE_PROV_SYSTEM, 0,
+ (HCRYPTPROV)NULL,
+ cert_store_name, cert_store_path);
+ if(!cert_store) {
+ Curl_unicodefree(cert_path);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ cert_thumbprint.pbData = cert_thumbprint_data;
+ cert_thumbprint.cbData = CERT_THUMBPRINT_DATA_LEN;
+
+ if(!CryptStringToBinary(cert_thumbprint_str, CERT_THUMBPRINT_STR_LEN,
+ CRYPT_STRING_HEX,
+ cert_thumbprint_data, &cert_thumbprint.cbData,
+ NULL, NULL)) {
+ Curl_unicodefree(cert_path);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ client_certs[0] = CertFindCertificateInStore(
+ cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0,
+ CERT_FIND_HASH, &cert_thumbprint, NULL);
+
+ Curl_unicodefree(cert_path);
+
+ if(client_certs[0]) {
+ schannel_cred.cCreds = 1;
+ schannel_cred.paCred = client_certs;
+ }
+
+ CertCloseStore(cert_store, 0);
+ }
+
/* allocate memory for the re-usable credential handle */
BACKEND->cred = (struct curl_schannel_cred *)
- malloc(sizeof(struct curl_schannel_cred));
+ calloc(1, sizeof(struct curl_schannel_cred));
if(!BACKEND->cred) {
failf(data, "schannel: unable to allocate memory");
+
+ if(client_certs[0])
+ CertFreeCertificateContext(client_certs[0]);
+
return CURLE_OUT_OF_MEMORY;
}
- memset(BACKEND->cred, 0, sizeof(struct curl_schannel_cred));
BACKEND->cred->refcount = 1;
/* https://msdn.microsoft.com/en-us/library/windows/desktop/aa374716.aspx
@@ -373,6 +476,9 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
&BACKEND->cred->cred_handle,
&BACKEND->cred->time_stamp);
+ if(client_certs[0])
+ CertFreeCertificateContext(client_certs[0]);
+
if(sspi_status != SEC_E_OK) {
if(sspi_status == SEC_E_WRONG_PRINCIPAL)
failf(data, "schannel: SNI or certificate check failed: %s",
@@ -438,8 +544,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
InitSecBuffer(&inbuf, SECBUFFER_APPLICATION_PROTOCOLS, alpn_buffer, cur);
InitSecBufferDesc(&inbuf_desc, &inbuf, 1);
}
- else
- {
+ else {
InitSecBuffer(&inbuf, SECBUFFER_EMPTY, NULL, 0);
InitSecBufferDesc(&inbuf_desc, &inbuf, 1);
}
@@ -459,12 +564,11 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
/* allocate memory for the security context handle */
BACKEND->ctxt = (struct curl_schannel_ctxt *)
- malloc(sizeof(struct curl_schannel_ctxt));
+ calloc(1, sizeof(struct curl_schannel_ctxt));
if(!BACKEND->ctxt) {
failf(data, "schannel: unable to allocate memory");
return CURLE_OUT_OF_MEMORY;
}
- memset(BACKEND->ctxt, 0, sizeof(struct curl_schannel_ctxt));
host_name = Curl_convert_UTF8_to_tchar(hostname);
if(!host_name)
@@ -542,6 +646,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
bool doread;
char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name;
+ const char *pubkey_ptr;
doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE;
@@ -761,12 +866,20 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
infof(data, "schannel: SSL/TLS handshake complete\n");
}
-#ifdef _WIN32_WCE
- /* Windows CE doesn't do any server certificate validation.
- We have to do it manually. */
- if(conn->ssl_config.verifypeer)
+ pubkey_ptr = SSL_IS_PROXY() ?
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+ if(pubkey_ptr) {
+ result = pkp_pin_peer_pubkey(conn, sockindex, pubkey_ptr);
+ if(result) {
+ failf(data, "SSL: public key does not match pinned public key!");
+ return result;
+ }
+ }
+
+ if(conn->ssl_config.verifypeer && BACKEND->use_manual_cred_validation) {
return verify_certificate(conn, sockindex);
-#endif
+ }
return CURLE_OK;
}
@@ -1669,145 +1782,136 @@ static CURLcode Curl_schannel_random(struct Curl_easy *data UNUSED_PARAM,
return CURLE_OK;
}
-#ifdef _WIN32_WCE
-static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
+static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex,
+ const char *pinnedpubkey)
{
SECURITY_STATUS status;
struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[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;
+ const char *x509_der;
+ DWORD x509_der_len;
+ curl_X509certificate x509_parsed;
+ curl_asn1Element *pubkey;
- status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
- SECPKG_ATTR_REMOTE_CERT_CONTEXT,
- &pCertContextServer);
+ /* Result is returned to caller */
+ CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
- if((status != SEC_E_OK) || (pCertContextServer == NULL)) {
- failf(data, "schannel: Failed to read remote certificate context: %s",
- Curl_sspi_strerror(conn, status));
- result = CURLE_PEER_FAILED_VERIFICATION;
- }
+ /* if a path wasn't specified, don't pin */
+ if(!pinnedpubkey)
+ return CURLE_OK;
- if(result == CURLE_OK) {
- CERT_CHAIN_PARA ChainPara;
- memset(&ChainPara, 0, sizeof(ChainPara));
- ChainPara.cbSize = sizeof(ChainPara);
-
- if(!CertGetCertificateChain(NULL,
- pCertContextServer,
- NULL,
- pCertContextServer->hCertStore,
- &ChainPara,
- (data->set.ssl.no_revoke ? 0 :
- CERT_CHAIN_REVOCATION_CHECK_CHAIN),
- NULL,
- &pChainContext)) {
- failf(data, "schannel: CertGetCertificateChain failed: %s",
- Curl_sspi_strerror(conn, GetLastError()));
- pChainContext = NULL;
- result = CURLE_PEER_FAILED_VERIFICATION;
- }
+ do {
+ status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
+ SECPKG_ATTR_REMOTE_CERT_CONTEXT,
+ &pCertContextServer);
- if(result == CURLE_OK) {
- CERT_SIMPLE_CHAIN *pSimpleChain = pChainContext->rgpChain[0];
- DWORD dwTrustErrorMask = ~(DWORD)(CERT_TRUST_IS_NOT_TIME_NESTED);
- dwTrustErrorMask &= pSimpleChain->TrustStatus.dwErrorStatus;
- if(dwTrustErrorMask) {
- if(dwTrustErrorMask & CERT_TRUST_IS_REVOKED)
- failf(data, "schannel: CertGetCertificateChain trust error"
- " CERT_TRUST_IS_REVOKED");
- else if(dwTrustErrorMask & CERT_TRUST_IS_PARTIAL_CHAIN)
- failf(data, "schannel: CertGetCertificateChain trust error"
- " CERT_TRUST_IS_PARTIAL_CHAIN");
- else if(dwTrustErrorMask & CERT_TRUST_IS_UNTRUSTED_ROOT)
- failf(data, "schannel: CertGetCertificateChain trust error"
- " CERT_TRUST_IS_UNTRUSTED_ROOT");
- else if(dwTrustErrorMask & CERT_TRUST_IS_NOT_TIME_VALID)
- failf(data, "schannel: CertGetCertificateChain trust error"
- " CERT_TRUST_IS_NOT_TIME_VALID");
- else
- failf(data, "schannel: CertGetCertificateChain error mask: 0x%08x",
- dwTrustErrorMask);
- result = CURLE_PEER_FAILED_VERIFICATION;
- }
+ if((status != SEC_E_OK) || (pCertContextServer == NULL)) {
+ failf(data, "schannel: Failed to read remote certificate context: %s",
+ Curl_sspi_strerror(conn, status));
+ break; /* failed */
}
- }
- if(result == CURLE_OK) {
- if(conn->ssl_config.verifyhost) {
- TCHAR cert_hostname_buff[256];
- DWORD len;
-
- /* 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
- (if WinCE supports that?) and run this section in a loop for each.
- https://msdn.microsoft.com/en-us/library/windows/desktop/aa376086.aspx
- curl: (51) schannel: CertGetNameString() certificate hostname
- (.google.com) did not match connection (google.com)
- */
- len = CertGetNameString(pCertContextServer,
- CERT_NAME_DNS_TYPE,
- CERT_NAME_DISABLE_IE4_UTF8_FLAG,
- NULL,
- 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 {
- failf(data,
- "schannel: CertGetNameString did not provide any "
- "certificate name information");
- result = CURLE_PEER_FAILED_VERIFICATION;
- }
+
+ if(!(((pCertContextServer->dwCertEncodingType & X509_ASN_ENCODING) != 0) &&
+ (pCertContextServer->cbCertEncoded > 0)))
+ break;
+
+ x509_der = (const char *)pCertContextServer->pbCertEncoded;
+ x509_der_len = pCertContextServer->cbCertEncoded;
+ memset(&x509_parsed, 0, sizeof x509_parsed);
+ if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len))
+ break;
+
+ pubkey = &x509_parsed.subjectPublicKeyInfo;
+ if(!pubkey->header || pubkey->end <= pubkey->header) {
+ failf(data, "SSL: failed retrieving public key from server certificate");
+ break;
}
- }
- if(pChainContext)
- CertFreeCertificateChain(pChainContext);
+ result = Curl_pin_peer_pubkey(data,
+ pinnedpubkey,
+ (const unsigned char *)pubkey->header,
+ (size_t)(pubkey->end - pubkey->header));
+ if(result) {
+ failf(data, "SSL: public key does not match pinned public key!");
+ }
+ } while(0);
if(pCertContextServer)
CertFreeCertificateContext(pCertContextServer);
return result;
}
-#endif /* _WIN32_WCE */
+
+static void Curl_schannel_checksum(const unsigned char *input,
+ size_t inputlen,
+ unsigned char *checksum,
+ size_t checksumlen,
+ DWORD provType,
+ const unsigned int algId)
+{
+ HCRYPTPROV hProv = 0;
+ HCRYPTHASH hHash = 0;
+ DWORD cbHashSize = 0;
+ DWORD dwHashSizeLen = (DWORD)sizeof(cbHashSize);
+ DWORD dwChecksumLen = (DWORD)checksumlen;
+
+ /* since this can fail in multiple ways, zero memory first so we never
+ * return old data
+ */
+ memset(checksum, 0, checksumlen);
+
+ if(!CryptAcquireContext(&hProv, NULL, NULL, provType,
+ CRYPT_VERIFYCONTEXT))
+ return; /* failed */
+
+ do {
+ if(!CryptCreateHash(hProv, algId, 0, 0, &hHash))
+ break; /* failed */
+
+ if(!CryptHashData(hHash, (const BYTE*)input, (DWORD)inputlen, 0))
+ break; /* failed */
+
+ /* get hash size */
+ if(!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE *)&cbHashSize,
+ &dwHashSizeLen, 0))
+ break; /* failed */
+
+ /* check hash size */
+ if(checksumlen < cbHashSize)
+ break; /* failed */
+
+ if(CryptGetHashParam(hHash, HP_HASHVAL, checksum, &dwChecksumLen, 0))
+ break; /* failed */
+ } while(0);
+
+ if(hHash)
+ CryptDestroyHash(hHash);
+
+ if(hProv)
+ CryptReleaseContext(hProv, 0);
+}
+
+static CURLcode Curl_schannel_md5sum(unsigned char *input,
+ size_t inputlen,
+ unsigned char *md5sum,
+ size_t md5len)
+{
+ Curl_schannel_checksum(input, inputlen, md5sum, md5len,
+ PROV_RSA_FULL, CALG_MD5);
+ return CURLE_OK;
+}
+
+static CURLcode Curl_schannel_sha256sum(const unsigned char *input,
+ size_t inputlen,
+ unsigned char *sha256sum,
+ size_t sha256len)
+{
+ Curl_schannel_checksum(input, inputlen, sha256sum, sha256len,
+ PROV_RSA_AES, CALG_SHA_256);
+ return CURLE_OK;
+}
static void *Curl_schannel_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM)
@@ -1819,11 +1923,8 @@ static void *Curl_schannel_get_internals(struct ssl_connect_data *connssl,
const struct Curl_ssl Curl_ssl_schannel = {
{ CURLSSLBACKEND_SCHANNEL, "schannel" }, /* info */
- 0, /* have_ca_path */
- 1, /* have_certinfo */
- 0, /* have_pinnedpubkey */
- 0, /* have_ssl_ctx */
- 0, /* support_https_proxy */
+ SSLSUPP_CERTINFO |
+ SSLSUPP_PINNEDPUBKEY,
sizeof(struct ssl_backend_data),
@@ -1845,8 +1946,8 @@ const struct Curl_ssl Curl_ssl_schannel = {
Curl_none_set_engine_default, /* set_engine_default */
Curl_none_engines_list, /* engines_list */
Curl_none_false_start, /* false_start */
- Curl_none_md5sum, /* md5sum */
- NULL /* sha256sum */
+ Curl_schannel_md5sum, /* md5sum */
+ Curl_schannel_sha256sum /* sha256sum */
};
#endif /* USE_SCHANNEL */
diff --git a/Utilities/cmcurl/lib/vtls/schannel.h b/Utilities/cmcurl/lib/vtls/schannel.h
index 932103d..4476900 100644
--- a/Utilities/cmcurl/lib/vtls/schannel.h
+++ b/Utilities/cmcurl/lib/vtls/schannel.h
@@ -26,9 +26,49 @@
#ifdef USE_SCHANNEL
+#include <schnlsp.h>
+#include <schannel.h>
+#include "curl_sspi.h"
+
#include "urldata.h"
extern const struct Curl_ssl Curl_ssl_schannel;
+CURLcode verify_certificate(struct connectdata *conn, int sockindex);
+
+/* structs to expose only in schannel.c and schannel_verify.c */
+#ifdef EXPOSE_SCHANNEL_INTERNAL_STRUCTS
+struct curl_schannel_cred {
+ CredHandle cred_handle;
+ TimeStamp time_stamp;
+ int refcount;
+};
+
+struct curl_schannel_ctxt {
+ CtxtHandle ctxt_handle;
+ TimeStamp time_stamp;
+};
+
+struct ssl_backend_data {
+ struct curl_schannel_cred *cred;
+ struct curl_schannel_ctxt *ctxt;
+ SecPkgContext_StreamSizes stream_sizes;
+ size_t encdata_length, decdata_length;
+ size_t encdata_offset, decdata_offset;
+ unsigned char *encdata_buffer, *decdata_buffer;
+ /* encdata_is_incomplete: if encdata contains only a partial record that
+ can't be decrypted without another Curl_read_plain (that is, status is
+ SEC_E_INCOMPLETE_MESSAGE) then set this true. after Curl_read_plain writes
+ more bytes into encdata then set this back to false. */
+ bool encdata_is_incomplete;
+ unsigned long req_flags, ret_flags;
+ CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */
+ bool recv_sspi_close_notify; /* true if connection closed by close_notify */
+ bool recv_connection_closed; /* true if connection closed, regardless how */
+ bool use_alpn; /* true if ALPN is used for this connection */
+ bool use_manual_cred_validation; /* true if manual cred validation is used */
+};
+#endif /* EXPOSE_SCHANNEL_INTERNAL_STRUCTS */
+
#endif /* USE_SCHANNEL */
#endif /* HEADER_CURL_SCHANNEL_H */
diff --git a/Utilities/cmcurl/lib/vtls/schannel_verify.c b/Utilities/cmcurl/lib/vtls/schannel_verify.c
new file mode 100644
index 0000000..db187dd
--- /dev/null
+++ b/Utilities/cmcurl/lib/vtls/schannel_verify.c
@@ -0,0 +1,551 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de>
+ * Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com>
+ * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, 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.
+ *
+ ***************************************************************************/
+
+/*
+ * Source file for SChannel-specific certificate verification. This code should
+ * only be invoked by code in schannel.c.
+ */
+
+#include "curl_setup.h"
+
+#ifdef USE_SCHANNEL
+
+#define EXPOSE_SCHANNEL_INTERNAL_STRUCTS
+
+#ifndef USE_WINDOWS_SSPI
+# error "Can't compile SCHANNEL support without SSPI."
+#endif
+
+#include "schannel.h"
+#include "vtls.h"
+#include "sendf.h"
+#include "strerror.h"
+#include "curl_multibyte.h"
+#include "curl_printf.h"
+#include "hostcheck.h"
+#include "system_win32.h"
+
+/* The last #include file should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#define BACKEND connssl->backend
+
+#define MAX_CAFILE_SIZE 1048576 /* 1 MiB */
+#define BEGIN_CERT "-----BEGIN CERTIFICATE-----\n"
+#define END_CERT "\n-----END CERTIFICATE-----"
+
+typedef struct {
+ DWORD cbSize;
+ HCERTSTORE hRestrictedRoot;
+ HCERTSTORE hRestrictedTrust;
+ HCERTSTORE hRestrictedOther;
+ DWORD cAdditionalStore;
+ HCERTSTORE *rghAdditionalStore;
+ DWORD dwFlags;
+ DWORD dwUrlRetrievalTimeout;
+ DWORD MaximumCachedCertificates;
+ DWORD CycleDetectionModulus;
+ HCERTSTORE hExclusiveRoot;
+ HCERTSTORE hExclusiveTrustedPeople;
+} CERT_CHAIN_ENGINE_CONFIG_WIN7, *PCERT_CHAIN_ENGINE_CONFIG_WIN7;
+
+
+static CURLcode add_certs_to_store(HCERTSTORE trust_store,
+ const char *ca_file,
+ struct connectdata *conn)
+{
+ CURLcode result;
+ struct Curl_easy *data = conn->data;
+ HANDLE ca_file_handle = INVALID_HANDLE_VALUE;
+ LARGE_INTEGER file_size;
+ char *ca_file_buffer = NULL;
+ char *current_ca_file_ptr = NULL;
+ const TCHAR *ca_file_tstr = NULL;
+ size_t ca_file_bufsize = 0;
+ DWORD total_bytes_read = 0;
+ bool more_certs = 0;
+ int num_certs = 0;
+ size_t END_CERT_LEN;
+
+ ca_file_tstr = Curl_convert_UTF8_to_tchar(ca_file);
+ if(!ca_file_tstr) {
+ failf(data,
+ "schannel: invalid path name for CA file '%s': %s",
+ ca_file, Curl_strerror(conn, GetLastError()));
+ result = CURLE_SSL_CACERT_BADFILE;
+ goto cleanup;
+ }
+
+ /*
+ * Read the CA file completely into memory before parsing it. This
+ * optimizes for the common case where the CA file will be relatively
+ * small ( < 1 MiB ).
+ */
+ ca_file_handle = CreateFile(ca_file_tstr,
+ GENERIC_READ,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if(ca_file_handle == INVALID_HANDLE_VALUE) {
+ failf(data,
+ "schannel: failed to open CA file '%s': %s",
+ ca_file, Curl_strerror(conn, GetLastError()));
+ result = CURLE_SSL_CACERT_BADFILE;
+ goto cleanup;
+ }
+
+ if(!GetFileSizeEx(ca_file_handle, &file_size)) {
+ failf(data,
+ "schannel: failed to determine size of CA file '%s': %s",
+ ca_file, Curl_strerror(conn, GetLastError()));
+ result = CURLE_SSL_CACERT_BADFILE;
+ goto cleanup;
+ }
+
+ if(file_size.QuadPart > MAX_CAFILE_SIZE) {
+ failf(data,
+ "schannel: CA file exceeds max size of %u bytes",
+ MAX_CAFILE_SIZE);
+ result = CURLE_OUT_OF_MEMORY;
+ goto cleanup;
+ }
+
+ ca_file_bufsize = (size_t)file_size.QuadPart;
+ ca_file_buffer = (char *)malloc(ca_file_bufsize + 1);
+ if(!ca_file_buffer) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto cleanup;
+ }
+
+ result = CURLE_OK;
+ while(total_bytes_read < ca_file_bufsize) {
+ DWORD bytes_to_read = (DWORD)(ca_file_bufsize - total_bytes_read);
+ DWORD bytes_read = 0;
+
+ if(!ReadFile(ca_file_handle, ca_file_buffer + total_bytes_read,
+ bytes_to_read, &bytes_read, NULL)) {
+
+ failf(data,
+ "schannel: failed to read from CA file '%s': %s",
+ ca_file, Curl_strerror(conn, GetLastError()));
+ result = CURLE_SSL_CACERT_BADFILE;
+ goto cleanup;
+ }
+ if(bytes_read == 0) {
+ /* Premature EOF -- adjust the bufsize to the new value */
+ ca_file_bufsize = total_bytes_read;
+ }
+ else {
+ total_bytes_read += bytes_read;
+ }
+ }
+
+ /* Null terminate the buffer */
+ ca_file_buffer[ca_file_bufsize] = '\0';
+
+ if(result != CURLE_OK) {
+ goto cleanup;
+ }
+
+ END_CERT_LEN = strlen(END_CERT);
+
+ more_certs = 1;
+ current_ca_file_ptr = ca_file_buffer;
+ while(more_certs && *current_ca_file_ptr != '\0') {
+ char *begin_cert_ptr = strstr(current_ca_file_ptr, BEGIN_CERT);
+ if(!begin_cert_ptr) {
+ more_certs = 0;
+ }
+ else {
+ char *end_cert_ptr = strstr(begin_cert_ptr, END_CERT);
+ if(!end_cert_ptr) {
+ failf(data,
+ "schannel: CA file '%s' is not correctly formatted",
+ ca_file);
+ result = CURLE_SSL_CACERT_BADFILE;
+ more_certs = 0;
+ }
+ else {
+ CERT_BLOB cert_blob;
+ CERT_CONTEXT *cert_context = NULL;
+ BOOL add_cert_result = FALSE;
+ DWORD actual_content_type = 0;
+ DWORD cert_size = (DWORD)
+ ((end_cert_ptr + END_CERT_LEN) - begin_cert_ptr);
+
+ cert_blob.pbData = (BYTE *)begin_cert_ptr;
+ cert_blob.cbData = cert_size;
+ if(!CryptQueryObject(CERT_QUERY_OBJECT_BLOB,
+ &cert_blob,
+ CERT_QUERY_CONTENT_FLAG_CERT,
+ CERT_QUERY_FORMAT_FLAG_ALL,
+ 0,
+ NULL,
+ &actual_content_type,
+ NULL,
+ NULL,
+ NULL,
+ &cert_context)) {
+
+ failf(data,
+ "schannel: failed to extract certificate from CA file "
+ "'%s': %s",
+ ca_file, Curl_strerror(conn, GetLastError()));
+ result = CURLE_SSL_CACERT_BADFILE;
+ more_certs = 0;
+ }
+ else {
+ current_ca_file_ptr = begin_cert_ptr + cert_size;
+
+ /* Sanity check that the cert_context object is the right type */
+ if(CERT_QUERY_CONTENT_CERT != actual_content_type) {
+ failf(data,
+ "schannel: unexpected content type '%d' when extracting "
+ "certificate from CA file '%s'",
+ actual_content_type, ca_file);
+ result = CURLE_SSL_CACERT_BADFILE;
+ more_certs = 0;
+ }
+ else {
+ add_cert_result =
+ CertAddCertificateContextToStore(trust_store,
+ cert_context,
+ CERT_STORE_ADD_ALWAYS,
+ NULL);
+ CertFreeCertificateContext(cert_context);
+ if(!add_cert_result) {
+ failf(data,
+ "schannel: failed to add certificate from CA file '%s'"
+ "to certificate store: %s",
+ ca_file, Curl_strerror(conn, GetLastError()));
+ result = CURLE_SSL_CACERT_BADFILE;
+ more_certs = 0;
+ }
+ else {
+ num_certs++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if(result == CURLE_OK) {
+ if(!num_certs) {
+ infof(data,
+ "schannel: did not add any certificates from CA file '%s'\n",
+ ca_file);
+ }
+ else {
+ infof(data,
+ "schannel: added %d certificate(s) from CA file '%s'\n",
+ num_certs, ca_file);
+ }
+ }
+
+cleanup:
+ if(ca_file_handle != INVALID_HANDLE_VALUE) {
+ CloseHandle(ca_file_handle);
+ }
+ Curl_safefree(ca_file_buffer);
+ Curl_unicodefree(ca_file_tstr);
+
+ return result;
+}
+
+static CURLcode verify_host(struct Curl_easy *data,
+ CERT_CONTEXT *pCertContextServer,
+ const char * const conn_hostname)
+{
+ CURLcode result = CURLE_PEER_FAILED_VERIFICATION;
+ TCHAR *cert_hostname_buff = NULL;
+ size_t cert_hostname_buff_index = 0;
+ DWORD len = 0;
+ DWORD actual_len = 0;
+
+ /* CertGetNameString will provide the 8-bit character string without
+ * any decoding */
+ DWORD name_flags = CERT_NAME_DISABLE_IE4_UTF8_FLAG;
+
+#ifdef CERT_NAME_SEARCH_ALL_NAMES_FLAG
+ name_flags |= CERT_NAME_SEARCH_ALL_NAMES_FLAG;
+#endif
+
+ /* Determine the size of the string needed for the cert hostname */
+ len = CertGetNameString(pCertContextServer,
+ CERT_NAME_DNS_TYPE,
+ name_flags,
+ NULL,
+ NULL,
+ 0);
+ if(len == 0) {
+ failf(data,
+ "schannel: CertGetNameString() returned no "
+ "certificate name information");
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ goto cleanup;
+ }
+
+ /* CertGetNameString guarantees that the returned name will not contain
+ * embedded null bytes. This appears to be undocumented behavior.
+ */
+ cert_hostname_buff = (LPTSTR)malloc(len * sizeof(TCHAR));
+ actual_len = CertGetNameString(pCertContextServer,
+ CERT_NAME_DNS_TYPE,
+ name_flags,
+ NULL,
+ (LPTSTR) cert_hostname_buff,
+ len);
+
+ /* Sanity check */
+ if(actual_len != len) {
+ failf(data,
+ "schannel: CertGetNameString() returned certificate "
+ "name information of unexpected size");
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ goto cleanup;
+ }
+
+ /* If HAVE_CERT_NAME_SEARCH_ALL_NAMES is available, the output
+ * will contain all DNS names, where each name is null-terminated
+ * and the last DNS name is double null-terminated. Due to this
+ * encoding, use the length of the buffer to iterate over all names.
+ */
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ while(cert_hostname_buff_index < len &&
+ cert_hostname_buff[cert_hostname_buff_index] != TEXT('\0') &&
+ result == CURLE_PEER_FAILED_VERIFICATION) {
+
+ 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[cert_hostname_buff_index]);
+ if(!cert_hostname) {
+ result = CURLE_OUT_OF_MEMORY;
+ }
+ else {
+ int match_result;
+
+ match_result = Curl_cert_hostcheck(cert_hostname, conn_hostname);
+ if(match_result == CURL_HOST_MATCH) {
+ infof(data,
+ "schannel: connection hostname (%s) validated "
+ "against certificate name (%s)\n",
+ conn_hostname, cert_hostname);
+ result = CURLE_OK;
+ }
+ else {
+ size_t cert_hostname_len;
+
+ infof(data,
+ "schannel: connection hostname (%s) did not match "
+ "against certificate name (%s)\n",
+ conn_hostname, cert_hostname);
+
+ cert_hostname_len = _tcslen(
+ &cert_hostname_buff[cert_hostname_buff_index]);
+
+ /* Move on to next cert name */
+ cert_hostname_buff_index += cert_hostname_len + 1;
+
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ }
+ Curl_unicodefree(cert_hostname);
+ }
+ }
+
+ if(result == CURLE_PEER_FAILED_VERIFICATION) {
+ failf(data,
+ "schannel: CertGetNameString() failed to match "
+ "connection hostname (%s) against server certificate names",
+ conn_hostname);
+ }
+ else if(result != CURLE_OK)
+ failf(data, "schannel: server certificate name verification failed");
+
+cleanup:
+ Curl_unicodefree(cert_hostname_buff);
+
+ return result;
+}
+
+CURLcode verify_certificate(struct connectdata *conn, int sockindex)
+{
+ SECURITY_STATUS status;
+ struct Curl_easy *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ CURLcode result = CURLE_OK;
+ CERT_CONTEXT *pCertContextServer = NULL;
+ const CERT_CHAIN_CONTEXT *pChainContext = NULL;
+ HCERTCHAINENGINE cert_chain_engine = NULL;
+ HCERTSTORE trust_store = NULL;
+ const char * const conn_hostname = SSL_IS_PROXY() ?
+ conn->http_proxy.host.name :
+ conn->host.name;
+
+ status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
+ SECPKG_ATTR_REMOTE_CERT_CONTEXT,
+ &pCertContextServer);
+
+ if((status != SEC_E_OK) || (pCertContextServer == NULL)) {
+ failf(data, "schannel: Failed to read remote certificate context: %s",
+ Curl_sspi_strerror(conn, status));
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ }
+
+ if(result == CURLE_OK && SSL_CONN_CONFIG(CAfile) &&
+ BACKEND->use_manual_cred_validation) {
+ /*
+ * Create a chain engine that uses the certificates in the CA file as
+ * trusted certificates. This is only supported on Windows 7+.
+ */
+
+ if(Curl_verify_windows_version(6, 1, PLATFORM_WINNT, VERSION_LESS_THAN)) {
+ failf(data, "schannel: this version of Windows is too old to support "
+ "certificate verification via CA bundle file.");
+ result = CURLE_SSL_CACERT_BADFILE;
+ }
+ else {
+ /* Open the certificate store */
+ trust_store = CertOpenStore(CERT_STORE_PROV_MEMORY,
+ 0,
+ (HCRYPTPROV)NULL,
+ CERT_STORE_CREATE_NEW_FLAG,
+ NULL);
+ if(!trust_store) {
+ failf(data, "schannel: failed to create certificate store: %s",
+ Curl_strerror(conn, GetLastError()));
+ result = CURLE_SSL_CACERT_BADFILE;
+ }
+ else {
+ result = add_certs_to_store(trust_store, SSL_CONN_CONFIG(CAfile),
+ conn);
+ }
+ }
+
+ if(result == CURLE_OK) {
+ CERT_CHAIN_ENGINE_CONFIG_WIN7 engine_config;
+ BOOL create_engine_result;
+
+ memset(&engine_config, 0, sizeof(engine_config));
+ engine_config.cbSize = sizeof(engine_config);
+ engine_config.hExclusiveRoot = trust_store;
+
+ /* CertCreateCertificateChainEngine will check the expected size of the
+ * CERT_CHAIN_ENGINE_CONFIG structure and fail if the specified size
+ * does not match the expected size. When this occurs, it indicates that
+ * CAINFO is not supported on the version of Windows in use.
+ */
+ create_engine_result =
+ CertCreateCertificateChainEngine(
+ (CERT_CHAIN_ENGINE_CONFIG *)&engine_config, &cert_chain_engine);
+ if(!create_engine_result) {
+ failf(data,
+ "schannel: failed to create certificate chain engine: %s",
+ Curl_strerror(conn, GetLastError()));
+ result = CURLE_SSL_CACERT_BADFILE;
+ }
+ }
+ }
+
+ if(result == CURLE_OK) {
+ CERT_CHAIN_PARA ChainPara;
+
+ memset(&ChainPara, 0, sizeof(ChainPara));
+ ChainPara.cbSize = sizeof(ChainPara);
+
+ if(!CertGetCertificateChain(cert_chain_engine,
+ pCertContextServer,
+ NULL,
+ pCertContextServer->hCertStore,
+ &ChainPara,
+ (data->set.ssl.no_revoke ? 0 :
+ CERT_CHAIN_REVOCATION_CHECK_CHAIN),
+ NULL,
+ &pChainContext)) {
+ failf(data, "schannel: CertGetCertificateChain failed: %s",
+ Curl_sspi_strerror(conn, GetLastError()));
+ pChainContext = NULL;
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ }
+
+ if(result == CURLE_OK) {
+ CERT_SIMPLE_CHAIN *pSimpleChain = pChainContext->rgpChain[0];
+ DWORD dwTrustErrorMask = ~(DWORD)(CERT_TRUST_IS_NOT_TIME_NESTED);
+ dwTrustErrorMask &= pSimpleChain->TrustStatus.dwErrorStatus;
+ if(dwTrustErrorMask) {
+ if(dwTrustErrorMask & CERT_TRUST_IS_REVOKED)
+ failf(data, "schannel: CertGetCertificateChain trust error"
+ " CERT_TRUST_IS_REVOKED");
+ else if(dwTrustErrorMask & CERT_TRUST_IS_PARTIAL_CHAIN)
+ failf(data, "schannel: CertGetCertificateChain trust error"
+ " CERT_TRUST_IS_PARTIAL_CHAIN");
+ else if(dwTrustErrorMask & CERT_TRUST_IS_UNTRUSTED_ROOT)
+ failf(data, "schannel: CertGetCertificateChain trust error"
+ " CERT_TRUST_IS_UNTRUSTED_ROOT");
+ else if(dwTrustErrorMask & CERT_TRUST_IS_NOT_TIME_VALID)
+ failf(data, "schannel: CertGetCertificateChain trust error"
+ " CERT_TRUST_IS_NOT_TIME_VALID");
+ else if(dwTrustErrorMask & CERT_TRUST_REVOCATION_STATUS_UNKNOWN)
+ failf(data, "schannel: CertGetCertificateChain trust error"
+ " CERT_TRUST_REVOCATION_STATUS_UNKNOWN");
+ else
+ failf(data, "schannel: CertGetCertificateChain error mask: 0x%08x",
+ dwTrustErrorMask);
+ result = CURLE_PEER_FAILED_VERIFICATION;
+ }
+ }
+ }
+
+ if(result == CURLE_OK) {
+ if(SSL_CONN_CONFIG(verifyhost)) {
+ result = verify_host(conn->data, pCertContextServer, conn_hostname);
+ }
+ }
+
+ if(cert_chain_engine) {
+ CertFreeCertificateChainEngine(cert_chain_engine);
+ }
+
+ if(trust_store) {
+ CertCloseStore(trust_store, 0);
+ }
+
+ if(pChainContext)
+ CertFreeCertificateChain(pChainContext);
+
+ if(pCertContextServer)
+ CertFreeCertificateContext(pCertContextServer);
+
+ return result;
+}
+
+#endif /* USE_SCHANNEL */
diff --git a/Utilities/cmcurl/lib/vtls/vtls.c b/Utilities/cmcurl/lib/vtls/vtls.c
index def1d30..ee5bc7a 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.c
+++ b/Utilities/cmcurl/lib/vtls/vtls.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -211,7 +211,7 @@ ssl_connect_init_proxy(struct connectdata *conn, int sockindex)
!conn->proxy_ssl[sockindex].use) {
struct ssl_backend_data *pbdata;
- if(!Curl_ssl->support_https_proxy)
+ if(!(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY))
return CURLE_NOT_BUILT_IN;
/* The pointers to the ssl backend data, which is opaque here, are swapped
@@ -511,7 +511,7 @@ void Curl_ssl_close_all(struct Curl_easy *data)
#if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
defined(USE_DARWINSSL) || defined(USE_POLARSSL) || defined(USE_NSS) || \
- defined(USE_MBEDTLS)
+ defined(USE_MBEDTLS) || defined(USE_CYASSL)
int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks,
int numsocks)
{
@@ -831,8 +831,12 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
sha256sumdigest = malloc(CURL_SHA256_DIGEST_LENGTH);
if(!sha256sumdigest)
return CURLE_OUT_OF_MEMORY;
- Curl_ssl->sha256sum(pubkey, pubkeylen,
+ encode = Curl_ssl->sha256sum(pubkey, pubkeylen,
sha256sumdigest, CURL_SHA256_DIGEST_LENGTH);
+
+ if(encode != CURLE_OK)
+ return encode;
+
encode = Curl_base64_encode(data, (char *)sha256sumdigest,
CURL_SHA256_DIGEST_LENGTH, &encoded,
&encodedlen);
@@ -1127,13 +1131,7 @@ static void Curl_multissl_close(struct connectdata *conn, int sockindex)
static const struct Curl_ssl Curl_ssl_multi = {
{ CURLSSLBACKEND_NONE, "multi" }, /* info */
-
- 0, /* have_ca_path */
- 0, /* have_certinfo */
- 0, /* have_pinnedpubkey */
- 0, /* have_ssl_ctx */
- 0, /* support_https_proxy */
-
+ 0, /* supports nothing */
(size_t)-1, /* something insanely large to be on the safe side */
Curl_multissl_init, /* init */
@@ -1300,6 +1298,9 @@ CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
{
int i;
+ if(avail)
+ *avail = (const curl_ssl_backend **)&available_backends;
+
if(Curl_ssl != &Curl_ssl_multi)
return id == Curl_ssl->info.id ? CURLSSLSET_OK : CURLSSLSET_TOO_LATE;
@@ -1311,8 +1312,6 @@ CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
}
}
- if(avail)
- *avail = (const curl_ssl_backend **)&available_backends;
return CURLSSLSET_UNKNOWN_BACKEND;
}
diff --git a/Utilities/cmcurl/lib/vtls/vtls.h b/Utilities/cmcurl/lib/vtls/vtls.h
index c5f9d4a..e7b87c4 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.h
+++ b/Utilities/cmcurl/lib/vtls/vtls.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,20 +26,19 @@
struct connectdata;
struct ssl_connect_data;
+#define SSLSUPP_CA_PATH (1<<0) /* supports CAPATH */
+#define SSLSUPP_CERTINFO (1<<1) /* supports CURLOPT_CERTINFO */
+#define SSLSUPP_PINNEDPUBKEY (1<<2) /* supports CURLOPT_PINNEDPUBLICKEY */
+#define SSLSUPP_SSL_CTX (1<<3) /* supports CURLOPT_SSL_CTX */
+#define SSLSUPP_HTTPS_PROXY (1<<4) /* supports access via HTTPS proxies */
+
struct Curl_ssl {
/*
* This *must* be the first entry to allow returning the list of available
* backends in curl_global_sslset().
*/
curl_ssl_backend info;
-
- unsigned have_ca_path:1; /* supports CAPATH */
- unsigned have_certinfo:1; /* supports CURLOPT_CERTINFO */
- unsigned have_pinnedpubkey:1; /* supports CURLOPT_PINNEDPUBLICKEY */
- unsigned have_ssl_ctx:1; /* supports CURLOPT_SSL_CTX_* */
-
- unsigned support_https_proxy:1; /* supports access via HTTPS proxies */
-
+ unsigned int supports; /* bitfield, see above */
size_t sizeof_ssl_backend_data;
int (*init)(void);
@@ -72,7 +71,7 @@ struct Curl_ssl {
CURLcode (*md5sum)(unsigned char *input, size_t inputlen,
unsigned char *md5sum, size_t md5sumlen);
- void (*sha256sum)(const unsigned char *input, size_t inputlen,
+ CURLcode (*sha256sum)(const unsigned char *input, size_t inputlen,
unsigned char *sha256sum, size_t sha256sumlen);
};
@@ -113,8 +112,10 @@ CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,
#endif
#ifndef MD5_DIGEST_LENGTH
+#ifndef LIBWOLFSSL_VERSION_HEX /* because WolfSSL borks this */
#define MD5_DIGEST_LENGTH 16 /* fixed size */
#endif
+#endif
#ifndef CURL_SHA256_DIGEST_LENGTH
#define CURL_SHA256_DIGEST_LENGTH 32 /* fixed size */
diff --git a/Utilities/cmcurl/lib/warnless.h b/Utilities/cmcurl/lib/warnless.h
index ab6d299..f6a2d74 100644
--- a/Utilities/cmcurl/lib/warnless.h
+++ b/Utilities/cmcurl/lib/warnless.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/Utilities/cmcurl/lib/wildcard.c b/Utilities/cmcurl/lib/wildcard.c
index af45c79..8ba0989 100644
--- a/Utilities/cmcurl/lib/wildcard.c
+++ b/Utilities/cmcurl/lib/wildcard.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, 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,9 +30,15 @@
#include "curl_memory.h"
#include "memdebug.h"
+static void fileinfo_dtor(void *user, void *element)
+{
+ (void)user;
+ Curl_fileinfo_cleanup(element);
+}
+
CURLcode Curl_wildcard_init(struct WildcardData *wc)
{
- Curl_llist_init(&wc->filelist, Curl_fileinfo_dtor);
+ Curl_llist_init(&wc->filelist, fileinfo_dtor);
wc->state = CURLWC_INIT;
return CURLE_OK;
@@ -43,12 +49,12 @@ void Curl_wildcard_dtor(struct WildcardData *wc)
if(!wc)
return;
- if(wc->tmp_dtor) {
- wc->tmp_dtor(wc->tmp);
- wc->tmp_dtor = ZERO_NULL;
- wc->tmp = NULL;
+ if(wc->dtor) {
+ wc->dtor(wc->protdata);
+ wc->dtor = ZERO_NULL;
+ wc->protdata = NULL;
}
- DEBUGASSERT(wc->tmp == NULL);
+ DEBUGASSERT(wc->protdata == NULL);
Curl_llist_destroy(&wc->filelist, NULL);
diff --git a/Utilities/cmcurl/lib/wildcard.h b/Utilities/cmcurl/lib/wildcard.h
index 8a5e4b7..b782612 100644
--- a/Utilities/cmcurl/lib/wildcard.h
+++ b/Utilities/cmcurl/lib/wildcard.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2010 - 2018, Daniel Stenberg, <daniel@haxx.se>, 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 @@ typedef enum {
will end */
} curl_wildcard_states;
-typedef void (*curl_wildcard_tmp_dtor)(void *ptr);
+typedef void (*curl_wildcard_dtor)(void *ptr);
/* struct keeping information about wildcard download process */
struct WildcardData {
@@ -48,8 +48,8 @@ struct WildcardData {
char *path; /* path to the directory, where we trying wildcard-match */
char *pattern; /* wildcard pattern */
struct curl_llist filelist; /* llist with struct Curl_fileinfo */
- void *tmp; /* pointer to protocol specific temporary data */
- curl_wildcard_tmp_dtor tmp_dtor;
+ void *protdata; /* pointer to protocol specific temporary data */
+ curl_wildcard_dtor dtor;
void *customptr; /* for CURLOPT_CHUNK_DATA pointer */
};
diff --git a/Utilities/cmlibuv/include/uv-errno.h b/Utilities/cmlibuv/include/uv-errno.h
index 8a41533..aa4d450 100644
--- a/Utilities/cmlibuv/include/uv-errno.h
+++ b/Utilities/cmlibuv/include/uv-errno.h
@@ -23,6 +23,11 @@
#define UV_ERRNO_H_
#include <errno.h>
+#if EDOM > 0
+# define UV__ERR(x) (-(x))
+#else
+# define UV__ERR(x) (x)
+#endif
#define UV__EOF (-4095)
#define UV__UNKNOWN (-4094)
@@ -46,355 +51,355 @@
* a fairly common practice for Windows programmers to redefine errno codes.
*/
#if defined(E2BIG) && !defined(_WIN32)
-# define UV__E2BIG (-E2BIG)
+# define UV__E2BIG UV__ERR(E2BIG)
#else
# define UV__E2BIG (-4093)
#endif
#if defined(EACCES) && !defined(_WIN32)
-# define UV__EACCES (-EACCES)
+# define UV__EACCES UV__ERR(EACCES)
#else
# define UV__EACCES (-4092)
#endif
#if defined(EADDRINUSE) && !defined(_WIN32)
-# define UV__EADDRINUSE (-EADDRINUSE)
+# define UV__EADDRINUSE UV__ERR(EADDRINUSE)
#else
# define UV__EADDRINUSE (-4091)
#endif
#if defined(EADDRNOTAVAIL) && !defined(_WIN32)
-# define UV__EADDRNOTAVAIL (-EADDRNOTAVAIL)
+# define UV__EADDRNOTAVAIL UV__ERR(EADDRNOTAVAIL)
#else
# define UV__EADDRNOTAVAIL (-4090)
#endif
#if defined(EAFNOSUPPORT) && !defined(_WIN32)
-# define UV__EAFNOSUPPORT (-EAFNOSUPPORT)
+# define UV__EAFNOSUPPORT UV__ERR(EAFNOSUPPORT)
#else
# define UV__EAFNOSUPPORT (-4089)
#endif
#if defined(EAGAIN) && !defined(_WIN32)
-# define UV__EAGAIN (-EAGAIN)
+# define UV__EAGAIN UV__ERR(EAGAIN)
#else
# define UV__EAGAIN (-4088)
#endif
#if defined(EALREADY) && !defined(_WIN32)
-# define UV__EALREADY (-EALREADY)
+# define UV__EALREADY UV__ERR(EALREADY)
#else
# define UV__EALREADY (-4084)
#endif
#if defined(EBADF) && !defined(_WIN32)
-# define UV__EBADF (-EBADF)
+# define UV__EBADF UV__ERR(EBADF)
#else
# define UV__EBADF (-4083)
#endif
#if defined(EBUSY) && !defined(_WIN32)
-# define UV__EBUSY (-EBUSY)
+# define UV__EBUSY UV__ERR(EBUSY)
#else
# define UV__EBUSY (-4082)
#endif
#if defined(ECANCELED) && !defined(_WIN32)
-# define UV__ECANCELED (-ECANCELED)
+# define UV__ECANCELED UV__ERR(ECANCELED)
#else
# define UV__ECANCELED (-4081)
#endif
#if defined(ECHARSET) && !defined(_WIN32)
-# define UV__ECHARSET (-ECHARSET)
+# define UV__ECHARSET UV__ERR(ECHARSET)
#else
# define UV__ECHARSET (-4080)
#endif
#if defined(ECONNABORTED) && !defined(_WIN32)
-# define UV__ECONNABORTED (-ECONNABORTED)
+# define UV__ECONNABORTED UV__ERR(ECONNABORTED)
#else
# define UV__ECONNABORTED (-4079)
#endif
#if defined(ECONNREFUSED) && !defined(_WIN32)
-# define UV__ECONNREFUSED (-ECONNREFUSED)
+# define UV__ECONNREFUSED UV__ERR(ECONNREFUSED)
#else
# define UV__ECONNREFUSED (-4078)
#endif
#if defined(ECONNRESET) && !defined(_WIN32)
-# define UV__ECONNRESET (-ECONNRESET)
+# define UV__ECONNRESET UV__ERR(ECONNRESET)
#else
# define UV__ECONNRESET (-4077)
#endif
#if defined(EDESTADDRREQ) && !defined(_WIN32)
-# define UV__EDESTADDRREQ (-EDESTADDRREQ)
+# define UV__EDESTADDRREQ UV__ERR(EDESTADDRREQ)
#else
# define UV__EDESTADDRREQ (-4076)
#endif
#if defined(EEXIST) && !defined(_WIN32)
-# define UV__EEXIST (-EEXIST)
+# define UV__EEXIST UV__ERR(EEXIST)
#else
# define UV__EEXIST (-4075)
#endif
#if defined(EFAULT) && !defined(_WIN32)
-# define UV__EFAULT (-EFAULT)
+# define UV__EFAULT UV__ERR(EFAULT)
#else
# define UV__EFAULT (-4074)
#endif
#if defined(EHOSTUNREACH) && !defined(_WIN32)
-# define UV__EHOSTUNREACH (-EHOSTUNREACH)
+# define UV__EHOSTUNREACH UV__ERR(EHOSTUNREACH)
#else
# define UV__EHOSTUNREACH (-4073)
#endif
#if defined(EINTR) && !defined(_WIN32)
-# define UV__EINTR (-EINTR)
+# define UV__EINTR UV__ERR(EINTR)
#else
# define UV__EINTR (-4072)
#endif
#if defined(EINVAL) && !defined(_WIN32)
-# define UV__EINVAL (-EINVAL)
+# define UV__EINVAL UV__ERR(EINVAL)
#else
# define UV__EINVAL (-4071)
#endif
#if defined(EIO) && !defined(_WIN32)
-# define UV__EIO (-EIO)
+# define UV__EIO UV__ERR(EIO)
#else
# define UV__EIO (-4070)
#endif
#if defined(EISCONN) && !defined(_WIN32)
-# define UV__EISCONN (-EISCONN)
+# define UV__EISCONN UV__ERR(EISCONN)
#else
# define UV__EISCONN (-4069)
#endif
#if defined(EISDIR) && !defined(_WIN32)
-# define UV__EISDIR (-EISDIR)
+# define UV__EISDIR UV__ERR(EISDIR)
#else
# define UV__EISDIR (-4068)
#endif
#if defined(ELOOP) && !defined(_WIN32)
-# define UV__ELOOP (-ELOOP)
+# define UV__ELOOP UV__ERR(ELOOP)
#else
# define UV__ELOOP (-4067)
#endif
#if defined(EMFILE) && !defined(_WIN32)
-# define UV__EMFILE (-EMFILE)
+# define UV__EMFILE UV__ERR(EMFILE)
#else
# define UV__EMFILE (-4066)
#endif
#if defined(EMSGSIZE) && !defined(_WIN32)
-# define UV__EMSGSIZE (-EMSGSIZE)
+# define UV__EMSGSIZE UV__ERR(EMSGSIZE)
#else
# define UV__EMSGSIZE (-4065)
#endif
#if defined(ENAMETOOLONG) && !defined(_WIN32)
-# define UV__ENAMETOOLONG (-ENAMETOOLONG)
+# define UV__ENAMETOOLONG UV__ERR(ENAMETOOLONG)
#else
# define UV__ENAMETOOLONG (-4064)
#endif
#if defined(ENETDOWN) && !defined(_WIN32)
-# define UV__ENETDOWN (-ENETDOWN)
+# define UV__ENETDOWN UV__ERR(ENETDOWN)
#else
# define UV__ENETDOWN (-4063)
#endif
#if defined(ENETUNREACH) && !defined(_WIN32)
-# define UV__ENETUNREACH (-ENETUNREACH)
+# define UV__ENETUNREACH UV__ERR(ENETUNREACH)
#else
# define UV__ENETUNREACH (-4062)
#endif
#if defined(ENFILE) && !defined(_WIN32)
-# define UV__ENFILE (-ENFILE)
+# define UV__ENFILE UV__ERR(ENFILE)
#else
# define UV__ENFILE (-4061)
#endif
#if defined(ENOBUFS) && !defined(_WIN32)
-# define UV__ENOBUFS (-ENOBUFS)
+# define UV__ENOBUFS UV__ERR(ENOBUFS)
#else
# define UV__ENOBUFS (-4060)
#endif
#if defined(ENODEV) && !defined(_WIN32)
-# define UV__ENODEV (-ENODEV)
+# define UV__ENODEV UV__ERR(ENODEV)
#else
# define UV__ENODEV (-4059)
#endif
#if defined(ENOENT) && !defined(_WIN32)
-# define UV__ENOENT (-ENOENT)
+# define UV__ENOENT UV__ERR(ENOENT)
#else
# define UV__ENOENT (-4058)
#endif
#if defined(ENOMEM) && !defined(_WIN32)
-# define UV__ENOMEM (-ENOMEM)
+# define UV__ENOMEM UV__ERR(ENOMEM)
#else
# define UV__ENOMEM (-4057)
#endif
#if defined(ENONET) && !defined(_WIN32)
-# define UV__ENONET (-ENONET)
+# define UV__ENONET UV__ERR(ENONET)
#else
# define UV__ENONET (-4056)
#endif
#if defined(ENOSPC) && !defined(_WIN32)
-# define UV__ENOSPC (-ENOSPC)
+# define UV__ENOSPC UV__ERR(ENOSPC)
#else
# define UV__ENOSPC (-4055)
#endif
#if defined(ENOSYS) && !defined(_WIN32)
-# define UV__ENOSYS (-ENOSYS)
+# define UV__ENOSYS UV__ERR(ENOSYS)
#else
# define UV__ENOSYS (-4054)
#endif
#if defined(ENOTCONN) && !defined(_WIN32)
-# define UV__ENOTCONN (-ENOTCONN)
+# define UV__ENOTCONN UV__ERR(ENOTCONN)
#else
# define UV__ENOTCONN (-4053)
#endif
#if defined(ENOTDIR) && !defined(_WIN32)
-# define UV__ENOTDIR (-ENOTDIR)
+# define UV__ENOTDIR UV__ERR(ENOTDIR)
#else
# define UV__ENOTDIR (-4052)
#endif
#if defined(ENOTEMPTY) && !defined(_WIN32)
-# define UV__ENOTEMPTY (-ENOTEMPTY)
+# define UV__ENOTEMPTY UV__ERR(ENOTEMPTY)
#else
# define UV__ENOTEMPTY (-4051)
#endif
#if defined(ENOTSOCK) && !defined(_WIN32)
-# define UV__ENOTSOCK (-ENOTSOCK)
+# define UV__ENOTSOCK UV__ERR(ENOTSOCK)
#else
# define UV__ENOTSOCK (-4050)
#endif
#if defined(ENOTSUP) && !defined(_WIN32)
-# define UV__ENOTSUP (-ENOTSUP)
+# define UV__ENOTSUP UV__ERR(ENOTSUP)
#else
# define UV__ENOTSUP (-4049)
#endif
#if defined(EPERM) && !defined(_WIN32)
-# define UV__EPERM (-EPERM)
+# define UV__EPERM UV__ERR(EPERM)
#else
# define UV__EPERM (-4048)
#endif
#if defined(EPIPE) && !defined(_WIN32)
-# define UV__EPIPE (-EPIPE)
+# define UV__EPIPE UV__ERR(EPIPE)
#else
# define UV__EPIPE (-4047)
#endif
#if defined(EPROTO) && !defined(_WIN32)
-# define UV__EPROTO (-EPROTO)
+# define UV__EPROTO UV__ERR(EPROTO)
#else
-# define UV__EPROTO (-4046)
+# define UV__EPROTO UV__ERR(4046)
#endif
#if defined(EPROTONOSUPPORT) && !defined(_WIN32)
-# define UV__EPROTONOSUPPORT (-EPROTONOSUPPORT)
+# define UV__EPROTONOSUPPORT UV__ERR(EPROTONOSUPPORT)
#else
# define UV__EPROTONOSUPPORT (-4045)
#endif
#if defined(EPROTOTYPE) && !defined(_WIN32)
-# define UV__EPROTOTYPE (-EPROTOTYPE)
+# define UV__EPROTOTYPE UV__ERR(EPROTOTYPE)
#else
# define UV__EPROTOTYPE (-4044)
#endif
#if defined(EROFS) && !defined(_WIN32)
-# define UV__EROFS (-EROFS)
+# define UV__EROFS UV__ERR(EROFS)
#else
# define UV__EROFS (-4043)
#endif
#if defined(ESHUTDOWN) && !defined(_WIN32)
-# define UV__ESHUTDOWN (-ESHUTDOWN)
+# define UV__ESHUTDOWN UV__ERR(ESHUTDOWN)
#else
# define UV__ESHUTDOWN (-4042)
#endif
#if defined(ESPIPE) && !defined(_WIN32)
-# define UV__ESPIPE (-ESPIPE)
+# define UV__ESPIPE UV__ERR(ESPIPE)
#else
# define UV__ESPIPE (-4041)
#endif
#if defined(ESRCH) && !defined(_WIN32)
-# define UV__ESRCH (-ESRCH)
+# define UV__ESRCH UV__ERR(ESRCH)
#else
# define UV__ESRCH (-4040)
#endif
#if defined(ETIMEDOUT) && !defined(_WIN32)
-# define UV__ETIMEDOUT (-ETIMEDOUT)
+# define UV__ETIMEDOUT UV__ERR(ETIMEDOUT)
#else
# define UV__ETIMEDOUT (-4039)
#endif
#if defined(ETXTBSY) && !defined(_WIN32)
-# define UV__ETXTBSY (-ETXTBSY)
+# define UV__ETXTBSY UV__ERR(ETXTBSY)
#else
# define UV__ETXTBSY (-4038)
#endif
#if defined(EXDEV) && !defined(_WIN32)
-# define UV__EXDEV (-EXDEV)
+# define UV__EXDEV UV__ERR(EXDEV)
#else
# define UV__EXDEV (-4037)
#endif
#if defined(EFBIG) && !defined(_WIN32)
-# define UV__EFBIG (-EFBIG)
+# define UV__EFBIG UV__ERR(EFBIG)
#else
# define UV__EFBIG (-4036)
#endif
#if defined(ENOPROTOOPT) && !defined(_WIN32)
-# define UV__ENOPROTOOPT (-ENOPROTOOPT)
+# define UV__ENOPROTOOPT UV__ERR(ENOPROTOOPT)
#else
# define UV__ENOPROTOOPT (-4035)
#endif
#if defined(ERANGE) && !defined(_WIN32)
-# define UV__ERANGE (-ERANGE)
+# define UV__ERANGE UV__ERR(ERANGE)
#else
# define UV__ERANGE (-4034)
#endif
#if defined(ENXIO) && !defined(_WIN32)
-# define UV__ENXIO (-ENXIO)
+# define UV__ENXIO UV__ERR(ENXIO)
#else
# define UV__ENXIO (-4033)
#endif
#if defined(EMLINK) && !defined(_WIN32)
-# define UV__EMLINK (-EMLINK)
+# define UV__EMLINK UV__ERR(EMLINK)
#else
# define UV__EMLINK (-4032)
#endif
@@ -404,7 +409,7 @@
* icky to hard-code it.
*/
#if defined(EHOSTDOWN) && !defined(_WIN32)
-# define UV__EHOSTDOWN (-EHOSTDOWN)
+# define UV__EHOSTDOWN UV__ERR(EHOSTDOWN)
#elif defined(__APPLE__) || \
defined(__DragonFly__) || \
defined(__FreeBSD__) || \
@@ -417,15 +422,16 @@
#endif
#if defined(EREMOTEIO) && !defined(_WIN32)
-# define UV__EREMOTEIO (-EREMOTEIO)
+# define UV__EREMOTEIO UV__ERR(EREMOTEIO)
#else
# define UV__EREMOTEIO (-4030)
#endif
#if defined(ENOTTY) && !defined(_WIN32)
-# define UV__ENOTTY (-ENOTTY)
+# define UV__ENOTTY UV__ERR(ENOTTY)
#else
# define UV__ENOTTY (-4029)
#endif
+
#endif /* UV_ERRNO_H_ */
diff --git a/Utilities/cmlibuv/include/uv-os390.h b/Utilities/cmlibuv/include/uv-os390.h
index 39e7384..0267d74 100644
--- a/Utilities/cmlibuv/include/uv-os390.h
+++ b/Utilities/cmlibuv/include/uv-os390.h
@@ -22,7 +22,7 @@
#ifndef UV_MVS_H
#define UV_MVS_H
-#define UV_PLATFORM_SEM_T int
+#define UV_PLATFORM_SEM_T long
#define UV_PLATFORM_LOOP_FIELDS \
void* ep; \
diff --git a/Utilities/cmlibuv/include/uv-unix.h b/Utilities/cmlibuv/include/uv-unix.h
index d8d031f..455674d 100644
--- a/Utilities/cmlibuv/include/uv-unix.h
+++ b/Utilities/cmlibuv/include/uv-unix.h
@@ -50,7 +50,7 @@
# include "uv-linux.h"
#elif defined (__MVS__)
# include "uv-os390.h"
-#elif defined(_PASE)
+#elif defined(__PASE__)
# include "uv-posix.h"
#elif defined(_AIX)
# include "uv-aix.h"
diff --git a/Utilities/cmlibuv/include/uv-version.h b/Utilities/cmlibuv/include/uv-version.h
index 1dc63e5..06c6711 100644
--- a/Utilities/cmlibuv/include/uv-version.h
+++ b/Utilities/cmlibuv/include/uv-version.h
@@ -31,8 +31,8 @@
*/
#define UV_VERSION_MAJOR 1
-#define UV_VERSION_MINOR 19
-#define UV_VERSION_PATCH 1
+#define UV_VERSION_MINOR 20
+#define UV_VERSION_PATCH 3
#define UV_VERSION_IS_RELEASE 0
#define UV_VERSION_SUFFIX "dev"
diff --git a/Utilities/cmlibuv/include/uv.h b/Utilities/cmlibuv/include/uv.h
index 875e30a..74fa00d 100644
--- a/Utilities/cmlibuv/include/uv.h
+++ b/Utilities/cmlibuv/include/uv.h
@@ -382,8 +382,7 @@ UV_EXTERN const char* uv_err_name(int err);
/* read-only */ \
uv_req_type type; \
/* private */ \
- void* active_queue[2]; \
- void* reserved[4]; \
+ void* reserved[6]; \
UV_REQ_PRIVATE_FIELDS \
/* Abstract base class of all requests. */
@@ -1209,6 +1208,18 @@ UV_EXTERN int uv_fs_write(uv_loop_t* loop,
*/
#define UV_FS_COPYFILE_EXCL 0x0001
+/*
+ * This flag can be used with uv_fs_copyfile() to attempt to create a reflink.
+ * If copy-on-write is not supported, a fallback copy mechanism is used.
+ */
+#define UV_FS_COPYFILE_FICLONE 0x0002
+
+/*
+ * This flag can be used with uv_fs_copyfile() to attempt to create a reflink.
+ * If copy-on-write is not supported, an error is returned.
+ */
+#define UV_FS_COPYFILE_FICLONE_FORCE 0x0004
+
UV_EXTERN int uv_fs_copyfile(uv_loop_t* loop,
uv_fs_t* req,
const char* path,
@@ -1549,7 +1560,10 @@ struct uv_loop_s {
/* Loop reference counting. */
unsigned int active_handles;
void* handle_queue[2];
- void* active_reqs[2];
+ union {
+ void* unused[2];
+ unsigned int count;
+ } active_reqs;
/* Internal flag to signal loop stop. */
unsigned int stop_flag;
UV_LOOP_PRIVATE_FIELDS
@@ -1577,6 +1591,7 @@ UV_EXTERN void uv_loop_set_data(uv_loop_t*, void* data);
#undef UV_SIGNAL_PRIVATE_FIELDS
#undef UV_LOOP_PRIVATE_FIELDS
#undef UV_LOOP_PRIVATE_PLATFORM_FIELDS
+#undef UV__ERR
#ifdef __cplusplus
}
diff --git a/Utilities/cmlibuv/src/unix/aix-common.c b/Utilities/cmlibuv/src/unix/aix-common.c
index c2217fb..9c11c5d 100644
--- a/Utilities/cmlibuv/src/unix/aix-common.c
+++ b/Utilities/cmlibuv/src/unix/aix-common.c
@@ -83,12 +83,12 @@ int uv_exepath(char* buffer, size_t* size) {
struct procsinfo pi;
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
pi.pi_pid = getpid();
res = getargs(&pi, sizeof(pi), args, sizeof(args));
if (res < 0)
- return -EINVAL;
+ return UV_EINVAL;
/*
* Possibilities for args:
@@ -101,7 +101,7 @@ int uv_exepath(char* buffer, size_t* size) {
/* Case i) and ii) absolute or relative paths */
if (strchr(args, '/') != NULL) {
if (realpath(args, abspath) != abspath)
- return -errno;
+ return UV__ERR(errno);
abspath_size = strlen(abspath);
@@ -121,11 +121,11 @@ int uv_exepath(char* buffer, size_t* size) {
char *path = getenv("PATH");
if (path == NULL)
- return -EINVAL;
+ return UV_EINVAL;
clonedpath = uv__strdup(path);
if (clonedpath == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
token = strtok(clonedpath, ":");
while (token != NULL) {
@@ -151,7 +151,7 @@ int uv_exepath(char* buffer, size_t* size) {
uv__free(clonedpath);
/* Out of tokens (path entries), and no match found */
- return -EINVAL;
+ return UV_EINVAL;
}
}
@@ -177,19 +177,19 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
*count = 0;
if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) {
- return -errno;
+ return UV__ERR(errno);
}
if (ioctl(sockfd, SIOCGSIZIFCONF, &size) == -1) {
uv__close(sockfd);
- return -errno;
+ return UV__ERR(errno);
}
ifc.ifc_req = (struct ifreq*)uv__malloc(size);
ifc.ifc_len = size;
if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) {
uv__close(sockfd);
- return -errno;
+ return UV__ERR(errno);
}
#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p))
@@ -208,7 +208,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
uv__close(sockfd);
- return -errno;
+ return UV__ERR(errno);
}
if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
@@ -221,7 +221,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
*addresses = uv__malloc(*count * sizeof(uv_interface_address_t));
if (!(*addresses)) {
uv__close(sockfd);
- return -ENOMEM;
+ return UV_ENOMEM;
}
address = *addresses;
@@ -240,7 +240,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
uv__close(sockfd);
- return -ENOSYS;
+ return UV_ENOSYS;
}
if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
@@ -260,7 +260,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
if (ioctl(sockfd, SIOCGIFNETMASK, p) == -1) {
uv__close(sockfd);
- return -ENOSYS;
+ return UV_ENOSYS;
}
if (inet6)
diff --git a/Utilities/cmlibuv/src/unix/aix.c b/Utilities/cmlibuv/src/unix/aix.c
index fd41309..92de814 100644
--- a/Utilities/cmlibuv/src/unix/aix.c
+++ b/Utilities/cmlibuv/src/unix/aix.c
@@ -119,7 +119,7 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) {
pc.fd = fd;
if (pollset_ctl(loop->backend_fd, &pc, 1))
- return -errno;
+ return UV__ERR(errno);
pc.cmd = PS_DELETE;
if (pollset_ctl(loop->backend_fd, &pc, 1))
@@ -409,22 +409,22 @@ static int uv__is_ahafs_mounted(void){
p = uv__malloc(siz);
if (p == NULL)
- return -errno;
+ return UV__ERR(errno);
/* Retrieve all mounted filesystems */
rv = mntctl(MCTL_QUERY, siz, (char*)p);
if (rv < 0)
- return -errno;
+ return UV__ERR(errno);
if (rv == 0) {
/* buffer was not large enough, reallocate to correct size */
siz = *(int*)p;
uv__free(p);
p = uv__malloc(siz);
if (p == NULL)
- return -errno;
+ return UV__ERR(errno);
rv = mntctl(MCTL_QUERY, siz, (char*)p);
if (rv < 0)
- return -errno;
+ return UV__ERR(errno);
}
/* Look for dev in filesystems mount info */
@@ -495,7 +495,7 @@ static int uv__make_subdirs_p(const char *filename) {
rc = uv__makedir_p(cmd);
if (rc == -1 && errno != EEXIST){
- return -errno;
+ return UV__ERR(errno);
}
return rc;
@@ -522,7 +522,7 @@ static int uv__setup_ahafs(const char* filename, int *fd) {
sprintf(mon_file, "/aha/fs/modFile.monFactory");
if ((strlen(mon_file) + strlen(filename) + 5) > PATH_MAX)
- return -ENAMETOOLONG;
+ return UV_ENAMETOOLONG;
/* Make the necessary subdirectories for the monitor file */
rc = uv__make_subdirs_p(filename);
@@ -537,7 +537,7 @@ static int uv__setup_ahafs(const char* filename, int *fd) {
/* Open the monitor file, creating it if necessary */
*fd = open(mon_file, O_CREAT|O_RDWR);
if (*fd < 0)
- return -errno;
+ return UV__ERR(errno);
/* Write out the monitoring specifications.
* In this case, we are monitoring for a state change event type
@@ -558,7 +558,7 @@ static int uv__setup_ahafs(const char* filename, int *fd) {
rc = write(*fd, mon_file_write_string, strlen(mon_file_write_string)+1);
if (rc < 0)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
@@ -716,7 +716,7 @@ int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT);
return 0;
#else
- return -ENOSYS;
+ return UV_ENOSYS;
#endif
}
@@ -771,7 +771,7 @@ int uv_fs_event_start(uv_fs_event_t* handle,
return 0;
#else
- return -ENOSYS;
+ return UV_ENOSYS;
#endif
}
@@ -796,7 +796,7 @@ int uv_fs_event_stop(uv_fs_event_t* handle) {
return 0;
#else
- return -ENOSYS;
+ return UV_ENOSYS;
#endif
}
@@ -861,7 +861,7 @@ int uv_set_process_title(const char* title) {
*/
new_title = uv__strdup(title);
if (new_title == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
uv_mutex_lock(&process_title_mutex);
@@ -888,9 +888,9 @@ 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;
+ return UV_EINVAL;
else if (size <= len)
- return -ENOBUFS;
+ return UV_ENOBUFS;
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
uv_mutex_lock(&process_title_mutex);
@@ -919,10 +919,10 @@ int uv_resident_set_memory(size_t* rss) {
fd = open(pp, O_RDONLY);
if (fd == -1)
- return -errno;
+ return UV__ERR(errno);
/* FIXME(bnoordhuis) Handle EINTR. */
- err = -EINVAL;
+ err = UV_EINVAL;
if (read(fd, &psinfo, sizeof(psinfo)) == sizeof(psinfo)) {
*rss = (size_t)psinfo.pr_rssize * 1024;
err = 0;
@@ -953,7 +953,7 @@ int uv_uptime(double* uptime) {
endutent();
if (boot_time == 0)
- return -ENOSYS;
+ return UV_ENOSYS;
*uptime = time(NULL) - boot_time;
return 0;
@@ -969,30 +969,30 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
result = perfstat_cpu_total(NULL, &ps_total, sizeof(ps_total), 1);
if (result == -1) {
- return -ENOSYS;
+ return UV_ENOSYS;
}
ncpus = result = perfstat_cpu(NULL, NULL, sizeof(perfstat_cpu_t), 0);
if (result == -1) {
- return -ENOSYS;
+ return UV_ENOSYS;
}
ps_cpus = (perfstat_cpu_t*) uv__malloc(ncpus * sizeof(perfstat_cpu_t));
if (!ps_cpus) {
- return -ENOMEM;
+ return UV_ENOMEM;
}
strcpy(cpu_id.name, FIRST_CPU);
result = perfstat_cpu(&cpu_id, ps_cpus, sizeof(perfstat_cpu_t), ncpus);
if (result == -1) {
uv__free(ps_cpus);
- return -ENOSYS;
+ return UV_ENOSYS;
}
*cpu_infos = (uv_cpu_info_t*) uv__malloc(ncpus * sizeof(uv_cpu_info_t));
if (!*cpu_infos) {
uv__free(ps_cpus);
- return -ENOMEM;
+ return UV_ENOMEM;
}
*count = ncpus;
diff --git a/Utilities/cmlibuv/src/unix/async.c b/Utilities/cmlibuv/src/unix/async.c
index 45c088e..0b450ae 100644
--- a/Utilities/cmlibuv/src/unix/async.c
+++ b/Utilities/cmlibuv/src/unix/async.c
@@ -166,7 +166,7 @@ static int uv__async_start(uv_loop_t* loop) {
pipefd[0] = err;
pipefd[1] = -1;
}
- else if (err == -ENOSYS) {
+ else if (err == UV_ENOSYS) {
err = uv__make_pipe(pipefd, UV__F_NONBLOCK);
#if defined(__linux__)
/* Save a file descriptor by opening one of the pipe descriptors as
@@ -240,7 +240,7 @@ static int uv__async_eventfd(void) {
return fd;
if (errno != ENOSYS)
- return -errno;
+ return UV__ERR(errno);
no_eventfd2 = 1;
@@ -257,7 +257,7 @@ skip_eventfd2:
}
if (errno != ENOSYS)
- return -errno;
+ return UV__ERR(errno);
no_eventfd = 1;
@@ -265,5 +265,5 @@ skip_eventfd:
#endif
- return -ENOSYS;
+ return UV_ENOSYS;
}
diff --git a/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c b/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c
index ea3166c..0d02154 100644
--- a/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c
+++ b/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c
@@ -70,7 +70,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
int i;
if (getifaddrs(&addrs) != 0)
- return -errno;
+ return UV__ERR(errno);
*count = 0;
@@ -85,7 +85,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
if (*addresses == NULL) {
freeifaddrs(addrs);
- return -ENOMEM;
+ return UV_ENOMEM;
}
address = *addresses;
diff --git a/Utilities/cmlibuv/src/unix/core.c b/Utilities/cmlibuv/src/unix/core.c
index faaf697..a357ef3 100644
--- a/Utilities/cmlibuv/src/unix/core.c
+++ b/Utilities/cmlibuv/src/unix/core.c
@@ -194,14 +194,14 @@ int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) {
socklen_t len;
if (handle == NULL || value == NULL)
- return -EINVAL;
+ return UV_EINVAL;
if (handle->type == UV_TCP || handle->type == UV_NAMED_PIPE)
fd = uv__stream_fd((uv_stream_t*) handle);
else if (handle->type == UV_UDP)
fd = ((uv_udp_t *) handle)->io_watcher.fd;
else
- return -ENOTSUP;
+ return UV_ENOTSUP;
len = sizeof(*value);
@@ -211,7 +211,7 @@ int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) {
r = setsockopt(fd, SOL_SOCKET, optname, (const void*) value, len);
if (r < 0)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
@@ -421,12 +421,12 @@ int uv__socket(int domain, int type, int protocol) {
return sockfd;
if (errno != EINVAL)
- return -errno;
+ return UV__ERR(errno);
#endif
sockfd = socket(domain, type, protocol);
if (sockfd == -1)
- return -errno;
+ return UV__ERR(errno);
err = uv__nonblock(sockfd, 1);
if (err == 0)
@@ -490,7 +490,7 @@ int uv__accept(int sockfd) {
continue;
if (errno != ENOSYS)
- return -errno;
+ return UV__ERR(errno);
no_accept4 = 1;
skip:
@@ -500,7 +500,7 @@ skip:
if (peerfd == -1) {
if (errno == EINTR)
continue;
- return -errno;
+ return UV__ERR(errno);
}
err = uv__cloexec(peerfd, 1);
@@ -526,8 +526,8 @@ int uv__close_nocheckstdio(int fd) {
saved_errno = errno;
rc = close(fd);
if (rc == -1) {
- rc = -errno;
- if (rc == -EINTR || rc == -EINPROGRESS)
+ rc = UV__ERR(errno);
+ if (rc == UV_EINTR || rc == UV__ERR(EINPROGRESS))
rc = 0; /* The close is in progress, not an error. */
errno = saved_errno;
}
@@ -539,7 +539,7 @@ 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);
+ SAVE_ERRNO(epoll_file_close(fd));
#endif
return uv__close_nocheckstdio(fd);
}
@@ -553,7 +553,7 @@ int uv__nonblock_ioctl(int fd, int set) {
while (r == -1 && errno == EINTR);
if (r)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
@@ -568,7 +568,7 @@ int uv__cloexec_ioctl(int fd, int set) {
while (r == -1 && errno == EINTR);
if (r)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
@@ -584,7 +584,7 @@ int uv__nonblock_fcntl(int fd, int set) {
while (r == -1 && errno == EINTR);
if (r == -1)
- return -errno;
+ return UV__ERR(errno);
/* Bail out now if already set/clear. */
if (!!(r & O_NONBLOCK) == !!set)
@@ -600,7 +600,7 @@ int uv__nonblock_fcntl(int fd, int set) {
while (r == -1 && errno == EINTR);
if (r)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
@@ -615,7 +615,7 @@ int uv__cloexec_fcntl(int fd, int set) {
while (r == -1 && errno == EINTR);
if (r == -1)
- return -errno;
+ return UV__ERR(errno);
/* Bail out now if already set/clear. */
if (!!(r & FD_CLOEXEC) == !!set)
@@ -631,7 +631,7 @@ int uv__cloexec_fcntl(int fd, int set) {
while (r == -1 && errno == EINTR);
if (r)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
@@ -646,7 +646,7 @@ int uv__dup(int fd) {
fd = dup(fd);
if (fd == -1)
- return -errno;
+ return UV__ERR(errno);
err = uv__cloexec(fd, 1);
if (err) {
@@ -670,10 +670,10 @@ ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) {
if (rc != -1)
return rc;
if (errno != EINVAL)
- return -errno;
+ return UV__ERR(errno);
rc = recvmsg(fd, msg, flags);
if (rc == -1)
- return -errno;
+ return UV__ERR(errno);
no_msg_cmsg_cloexec = 1;
} else {
rc = recvmsg(fd, msg, flags);
@@ -682,7 +682,7 @@ ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) {
rc = recvmsg(fd, msg, flags);
#endif
if (rc == -1)
- return -errno;
+ return UV__ERR(errno);
if (msg->msg_controllen == 0)
return rc;
for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg))
@@ -698,10 +698,10 @@ ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) {
int uv_cwd(char* buffer, size_t* size) {
if (buffer == NULL || size == NULL)
- return -EINVAL;
+ return UV_EINVAL;
if (getcwd(buffer, *size) == NULL)
- return -errno;
+ return UV__ERR(errno);
*size = strlen(buffer);
if (*size > 1 && buffer[*size - 1] == '/') {
@@ -715,7 +715,7 @@ int uv_cwd(char* buffer, size_t* size) {
int uv_chdir(const char* dir) {
if (chdir(dir))
- return -errno;
+ return UV__ERR(errno);
return 0;
}
@@ -752,11 +752,11 @@ int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd) {
break;
default:
- return -EINVAL;
+ return UV_EINVAL;
}
if (uv__is_closing(handle) || fd_out == -1)
- return -EBADF;
+ return UV_EBADF;
*fd = fd_out;
return 0;
@@ -934,7 +934,7 @@ int uv_getrusage(uv_rusage_t* rusage) {
struct rusage usage;
if (getrusage(RUSAGE_SELF, &usage))
- return -errno;
+ return UV__ERR(errno);
rusage->ru_utime.tv_sec = usage.ru_utime.tv_sec;
rusage->ru_utime.tv_usec = usage.ru_utime.tv_usec;
@@ -976,7 +976,7 @@ int uv__open_cloexec(const char* path, int flags) {
return fd;
if (errno != EINVAL)
- return -errno;
+ return UV__ERR(errno);
/* O_CLOEXEC not supported. */
no_cloexec = 1;
@@ -985,7 +985,7 @@ int uv__open_cloexec(const char* path, int flags) {
fd = open(path, flags);
if (fd == -1)
- return -errno;
+ return UV__ERR(errno);
err = uv__cloexec(fd, 1);
if (err) {
@@ -1002,14 +1002,14 @@ int uv__dup2_cloexec(int oldfd, int newfd) {
#if (defined(__FreeBSD__) && __FreeBSD__ >= 10) || defined(__NetBSD__)
r = dup3(oldfd, newfd, O_CLOEXEC);
if (r == -1)
- return -errno;
+ return UV__ERR(errno);
return r;
#elif defined(__FreeBSD__) && defined(F_DUP2FD_CLOEXEC)
r = fcntl(oldfd, F_DUP2FD_CLOEXEC, newfd);
if (r != -1)
return r;
if (errno != EINVAL)
- return -errno;
+ return UV__ERR(errno);
/* Fall through. */
#elif defined(__linux__)
static int no_dup3;
@@ -1020,7 +1020,7 @@ int uv__dup2_cloexec(int oldfd, int newfd) {
if (r != -1)
return r;
if (errno != ENOSYS)
- return -errno;
+ return UV__ERR(errno);
/* Fall through. */
no_dup3 = 1;
}
@@ -1036,7 +1036,7 @@ int uv__dup2_cloexec(int oldfd, int newfd) {
#endif
if (r == -1)
- return -errno;
+ return UV__ERR(errno);
err = uv__cloexec(newfd, 1);
if (err) {
@@ -1051,29 +1051,16 @@ int uv__dup2_cloexec(int oldfd, int newfd) {
int uv_os_homedir(char* buffer, size_t* size) {
uv_passwd_t pwd;
- char* buf;
size_t len;
int r;
- if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
-
- /* Check if the HOME environment variable is set first */
- buf = getenv("HOME");
-
- if (buf != NULL) {
- len = strlen(buf);
-
- if (len >= *size) {
- *size = len + 1;
- return -ENOBUFS;
- }
-
- memcpy(buffer, buf, len + 1);
- *size = len;
+ /* Check if the HOME environment variable is set first. The task of
+ performing input validation on buffer and size is taken care of by
+ uv_os_getenv(). */
+ r = uv_os_getenv("HOME", buffer, size);
- return 0;
- }
+ if (r != UV_ENOENT)
+ return r;
/* HOME is not set, so call uv__getpwuid_r() */
r = uv__getpwuid_r(&pwd);
@@ -1087,7 +1074,7 @@ int uv_os_homedir(char* buffer, size_t* size) {
if (len >= *size) {
*size = len + 1;
uv_os_free_passwd(&pwd);
- return -ENOBUFS;
+ return UV_ENOBUFS;
}
memcpy(buffer, pwd.homedir, len + 1);
@@ -1103,7 +1090,7 @@ int uv_os_tmpdir(char* buffer, size_t* size) {
size_t len;
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
#define CHECK_ENV_VAR(name) \
do { \
@@ -1133,7 +1120,7 @@ return_buffer:
if (len >= *size) {
*size = len + 1;
- return -ENOBUFS;
+ return UV_ENOBUFS;
}
/* The returned directory should not have a trailing slash. */
@@ -1165,11 +1152,11 @@ int uv__getpwuid_r(uv_passwd_t* pwd) {
getpwuid_r = dlsym(RTLD_DEFAULT, "getpwuid_r");
if (getpwuid_r == NULL)
- return -ENOSYS;
+ return UV_ENOSYS;
#endif
if (pwd == NULL)
- return -EINVAL;
+ return UV_EINVAL;
initsize = sysconf(_SC_GETPW_R_SIZE_MAX);
@@ -1186,7 +1173,7 @@ int uv__getpwuid_r(uv_passwd_t* pwd) {
buf = uv__malloc(bufsize);
if (buf == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
r = getpwuid_r(uid, &pw, buf, bufsize, &result);
@@ -1203,7 +1190,7 @@ int uv__getpwuid_r(uv_passwd_t* pwd) {
if (result == NULL) {
uv__free(buf);
- return -ENOENT;
+ return UV_ENOENT;
}
/* Allocate memory for the username, shell, and home directory */
@@ -1214,7 +1201,7 @@ int uv__getpwuid_r(uv_passwd_t* pwd) {
if (pwd->username == NULL) {
uv__free(buf);
- return -ENOMEM;
+ return UV_ENOMEM;
}
/* Copy the username */
@@ -1270,18 +1257,18 @@ int uv_os_getenv(const char* name, char* buffer, size_t* size) {
size_t len;
if (name == NULL || buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
var = getenv(name);
if (var == NULL)
- return -ENOENT;
+ return UV_ENOENT;
len = strlen(var);
if (len >= *size) {
*size = len + 1;
- return -ENOBUFS;
+ return UV_ENOBUFS;
}
memcpy(buffer, var, len + 1);
@@ -1293,10 +1280,10 @@ int uv_os_getenv(const char* name, char* buffer, size_t* size) {
int uv_os_setenv(const char* name, const char* value) {
if (name == NULL || value == NULL)
- return -EINVAL;
+ return UV_EINVAL;
if (setenv(name, value, 1) != 0)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
@@ -1304,10 +1291,10 @@ int uv_os_setenv(const char* name, const char* value) {
int uv_os_unsetenv(const char* name) {
if (name == NULL)
- return -EINVAL;
+ return UV_EINVAL;
if (unsetenv(name) != 0)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
@@ -1324,17 +1311,17 @@ int uv_os_gethostname(char* buffer, size_t* size) {
size_t len;
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
if (gethostname(buf, sizeof(buf)) != 0)
- return -errno;
+ return UV__ERR(errno);
buf[sizeof(buf) - 1] = '\0'; /* Null terminate, just to be safe. */
len = strlen(buf);
if (len >= *size) {
*size = len + 1;
- return -ENOBUFS;
+ return UV_ENOBUFS;
}
memcpy(buffer, buf, len + 1);
diff --git a/Utilities/cmlibuv/src/unix/cygwin.c b/Utilities/cmlibuv/src/unix/cygwin.c
index 5a887dd..9fe4093 100644
--- a/Utilities/cmlibuv/src/unix/cygwin.c
+++ b/Utilities/cmlibuv/src/unix/cygwin.c
@@ -29,7 +29,7 @@ int uv_uptime(double* uptime) {
struct sysinfo info;
if (sysinfo(&info) < 0)
- return -errno;
+ return UV__ERR(errno);
*uptime = info.uptime;
return 0;
diff --git a/Utilities/cmlibuv/src/unix/darwin-proctitle.c b/Utilities/cmlibuv/src/unix/darwin-proctitle.c
index 1142311..dabde22 100644
--- a/Utilities/cmlibuv/src/unix/darwin-proctitle.c
+++ b/Utilities/cmlibuv/src/unix/darwin-proctitle.c
@@ -18,6 +18,9 @@
* IN THE SOFTWARE.
*/
+#include "uv.h"
+#include "internal.h"
+
#include <dlfcn.h>
#include <errno.h>
#include <stdlib.h>
@@ -41,14 +44,14 @@ static int uv__pthread_setname_np(const char* name) {
dlsym(RTLD_DEFAULT, "pthread_setname_np");
if (dynamic_pthread_setname_np == NULL)
- return -ENOSYS;
+ return UV_ENOSYS;
strncpy(namebuf, name, sizeof(namebuf) - 1);
namebuf[sizeof(namebuf) - 1] = '\0';
err = dynamic_pthread_setname_np(namebuf);
if (err)
- return -err;
+ return UV__ERR(err);
return 0;
}
@@ -84,7 +87,7 @@ int uv__set_process_title(const char* title) {
CFTypeRef asn;
int err;
- err = -ENOENT;
+ err = UV_ENOENT;
application_services_handle = dlopen("/System/Library/Frameworks/"
"ApplicationServices.framework/"
"Versions/A/ApplicationServices",
@@ -151,7 +154,7 @@ int uv__set_process_title(const char* title) {
/* Black 10.9 magic, to remove (Not responding) mark in Activity Monitor */
hi_services_bundle =
pCFBundleGetBundleWithIdentifier(S("com.apple.HIServices"));
- err = -ENOENT;
+ err = UV_ENOENT;
if (hi_services_bundle == NULL)
goto out;
@@ -182,7 +185,7 @@ int uv__set_process_title(const char* title) {
asn = pLSGetCurrentApplicationASN();
- err = -EINVAL;
+ err = UV_EINVAL;
if (pLSSetApplicationInformationItem(-2, /* Magic value. */
asn,
*display_name_key,
diff --git a/Utilities/cmlibuv/src/unix/darwin.c b/Utilities/cmlibuv/src/unix/darwin.c
index df6dd1c..31ad8a9 100644
--- a/Utilities/cmlibuv/src/unix/darwin.c
+++ b/Utilities/cmlibuv/src/unix/darwin.c
@@ -37,7 +37,7 @@ int uv__platform_loop_init(uv_loop_t* loop) {
loop->cf_state = NULL;
if (uv__kqueue_init(loop))
- return -errno;
+ return UV__ERR(errno);
return 0;
}
@@ -68,18 +68,18 @@ int uv_exepath(char* buffer, size_t* size) {
size_t abspath_size;
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
exepath_size = sizeof(exepath);
if (_NSGetExecutablePath(exepath, &exepath_size))
- return -EIO;
+ return UV_EIO;
if (realpath(exepath, abspath) != abspath)
- return -errno;
+ return UV__ERR(errno);
abspath_size = strlen(abspath);
if (abspath_size == 0)
- return -EIO;
+ return UV_EIO;
*size -= 1;
if (*size > abspath_size)
@@ -98,7 +98,7 @@ uint64_t uv_get_free_memory(void) {
if (host_statistics(mach_host_self(), HOST_VM_INFO,
(host_info_t)&info, &count) != KERN_SUCCESS) {
- return -EINVAL; /* FIXME(bnoordhuis) Translate error. */
+ return UV_EINVAL; /* FIXME(bnoordhuis) Translate error. */
}
return (uint64_t) info.free_count * sysconf(_SC_PAGESIZE);
@@ -111,7 +111,7 @@ uint64_t uv_get_total_memory(void) {
size_t size = sizeof(info);
if (sysctl(which, 2, &info, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
return (uint64_t) info;
}
@@ -158,7 +158,7 @@ int uv_uptime(double* uptime) {
static int which[] = {CTL_KERN, KERN_BOOTTIME};
if (sysctl(which, 2, &info, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
now = time(NULL);
*uptime = now - info.tv_sec;
@@ -181,23 +181,23 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
size = sizeof(model);
if (sysctlbyname("machdep.cpu.brand_string", &model, &size, NULL, 0) &&
sysctlbyname("hw.model", &model, &size, NULL, 0)) {
- return -errno;
+ return UV__ERR(errno);
}
size = sizeof(cpuspeed);
if (sysctlbyname("hw.cpufrequency", &cpuspeed, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
if (host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numcpus,
(processor_info_array_t*)&info,
&msg_type) != KERN_SUCCESS) {
- return -EINVAL; /* FIXME(bnoordhuis) Translate error. */
+ return UV_EINVAL; /* FIXME(bnoordhuis) Translate error. */
}
*cpu_infos = uv__malloc(numcpus * sizeof(**cpu_infos));
if (!(*cpu_infos)) {
vm_deallocate(mach_task_self(), (vm_address_t)info, msg_type);
- return -ENOMEM;
+ return UV_ENOMEM;
}
*count = numcpus;
diff --git a/Utilities/cmlibuv/src/unix/freebsd.c b/Utilities/cmlibuv/src/unix/freebsd.c
index f2b3f24..70ccb13 100644
--- a/Utilities/cmlibuv/src/unix/freebsd.c
+++ b/Utilities/cmlibuv/src/unix/freebsd.c
@@ -72,11 +72,11 @@ int uv_exepath(char* buffer, size_t* size) {
ssize_t abspath_size;
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
abspath_size = readlink("/proc/curproc/file", abspath, sizeof(abspath));
if (abspath_size < 0)
- return -errno;
+ return UV__ERR(errno);
assert(abspath_size > 0);
*size -= 1;
@@ -96,7 +96,7 @@ int uv_exepath(char* buffer, size_t* size) {
size_t abspath_size;
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
@@ -105,7 +105,7 @@ int uv_exepath(char* buffer, size_t* size) {
abspath_size = sizeof abspath;
if (sysctl(mib, 4, abspath, &abspath_size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
assert(abspath_size > 0);
abspath_size -= 1;
@@ -126,7 +126,7 @@ uint64_t uv_get_free_memory(void) {
size_t size = sizeof(freecount);
if (sysctlbyname("vm.stats.vm.v_free_count", &freecount, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
return (uint64_t) freecount * sysconf(_SC_PAGESIZE);
@@ -140,7 +140,7 @@ uint64_t uv_get_total_memory(void) {
size_t size = sizeof(info);
if (sysctl(which, 2, &info, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
return (uint64_t) info;
}
@@ -176,7 +176,7 @@ int uv_set_process_title(const char* title) {
if (process_title == NULL) {
uv_mutex_unlock(&process_title_mutex);
- return -ENOMEM;
+ return UV_ENOMEM;
}
uv__free(process_title);
@@ -204,7 +204,7 @@ int uv_get_process_title(char* buffer, size_t size) {
size_t len;
if (buffer == NULL || size == 0)
- return -EINVAL;
+ return UV_EINVAL;
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
uv_mutex_lock(&process_title_mutex);
@@ -214,7 +214,7 @@ int uv_get_process_title(char* buffer, size_t size) {
if (size < len) {
uv_mutex_unlock(&process_title_mutex);
- return -ENOBUFS;
+ return UV_ENOBUFS;
}
memcpy(buffer, process_title, len);
@@ -243,7 +243,7 @@ int uv_resident_set_memory(size_t* rss) {
kinfo_size = sizeof(kinfo);
if (sysctl(mib, 4, &kinfo, &kinfo_size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
page_size = getpagesize();
@@ -262,7 +262,7 @@ int uv_uptime(double* uptime) {
struct timespec sp;
r = clock_gettime(CLOCK_MONOTONIC, &sp);
if (r)
- return -errno;
+ return UV__ERR(errno);
*uptime = sp.tv_sec;
return 0;
@@ -309,15 +309,15 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
size = sizeof(model);
if (sysctlbyname(model_key, &model, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
size = sizeof(numcpus);
if (sysctlbyname("hw.ncpu", &numcpus, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
*cpu_infos = uv__malloc(numcpus * sizeof(**cpu_infos));
if (!(*cpu_infos))
- return -ENOMEM;
+ return UV_ENOMEM;
*count = numcpus;
@@ -327,7 +327,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
size = sizeof(maxcpus);
if (sysctlbyname(maxcpus_key, &maxcpus, &size, NULL, 0)) {
uv__free(*cpu_infos);
- return -errno;
+ return UV__ERR(errno);
}
size = maxcpus * CPUSTATES * sizeof(long);
@@ -335,13 +335,13 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
cp_times = uv__malloc(size);
if (cp_times == NULL) {
uv__free(*cpu_infos);
- return -ENOMEM;
+ return UV_ENOMEM;
}
if (sysctlbyname(cptimes_key, cp_times, &size, NULL, 0)) {
uv__free(cp_times);
uv__free(*cpu_infos);
- return -errno;
+ return UV__ERR(errno);
}
for (i = 0; i < numcpus; i++) {
diff --git a/Utilities/cmlibuv/src/unix/fs.c b/Utilities/cmlibuv/src/unix/fs.c
index 0a4c183..4545168 100644
--- a/Utilities/cmlibuv/src/unix/fs.c
+++ b/Utilities/cmlibuv/src/unix/fs.c
@@ -62,21 +62,23 @@
#if defined(__APPLE__)
# include <copyfile.h>
+#elif defined(__linux__) && !defined(FICLONE)
+# include <sys/ioctl.h>
+# define FICLONE _IOW(0x94, 9, int)
#endif
#define INIT(subtype) \
do { \
if (req == NULL) \
- return -EINVAL; \
- req->type = UV_FS; \
- if (cb != NULL) \
- uv__req_init(loop, req, UV_FS); \
+ return UV_EINVAL; \
+ UV_REQ_INIT(req, UV_FS); \
req->fs_type = UV_FS_ ## subtype; \
req->result = 0; \
req->ptr = NULL; \
req->loop = loop; \
req->path = NULL; \
req->new_path = NULL; \
+ req->bufs = NULL; \
req->cb = cb; \
} \
while (0)
@@ -88,10 +90,8 @@
req->path = path; \
} else { \
req->path = uv__strdup(path); \
- if (req->path == NULL) { \
- uv__req_unregister(loop, req); \
- return -ENOMEM; \
- } \
+ if (req->path == NULL) \
+ return UV_ENOMEM; \
} \
} \
while (0)
@@ -107,10 +107,8 @@
path_len = strlen(path) + 1; \
new_path_len = strlen(new_path) + 1; \
req->path = uv__malloc(path_len + new_path_len); \
- if (req->path == NULL) { \
- uv__req_unregister(loop, req); \
- return -ENOMEM; \
- } \
+ if (req->path == NULL) \
+ return UV_ENOMEM; \
req->new_path = req->path + path_len; \
memcpy((void*) req->path, path, path_len); \
memcpy((void*) req->new_path, new_path, new_path_len); \
@@ -121,6 +119,7 @@
#define POST \
do { \
if (cb != NULL) { \
+ uv__req_register(loop, req); \
uv__work_submit(loop, &req->work_req, uv__fs_work, uv__fs_done); \
return 0; \
} \
@@ -804,6 +803,19 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
if (req->flags & UV_FS_COPYFILE_EXCL)
flags |= COPYFILE_EXCL;
+#ifdef COPYFILE_CLONE
+ if (req->flags & UV_FS_COPYFILE_FICLONE)
+ flags |= COPYFILE_CLONE;
+#endif
+
+ if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
+#ifdef COPYFILE_CLONE_FORCE
+ flags |= COPYFILE_CLONE_FORCE;
+#else
+ return UV_ENOSYS;
+#endif
+ }
+
return copyfile(req->path, req->new_path, NULL, flags);
#else
uv_fs_t fs_req;
@@ -828,7 +840,7 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
/* Get the source file's mode. */
if (fstat(srcfd, &statsbuf)) {
- err = -errno;
+ err = UV__ERR(errno);
goto out;
}
@@ -852,9 +864,32 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
}
if (fchmod(dstfd, statsbuf.st_mode) == -1) {
- err = -errno;
+ err = UV__ERR(errno);
+ goto out;
+ }
+
+#ifdef FICLONE
+ if (req->flags & UV_FS_COPYFILE_FICLONE ||
+ req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
+ if (ioctl(dstfd, FICLONE, srcfd) == -1) {
+ /* If an error occurred that the sendfile fallback also won't handle, or
+ this is a force clone then exit. Otherwise, fall through to try using
+ sendfile(). */
+ if ((errno != ENOTTY && errno != EOPNOTSUPP && errno != EXDEV) ||
+ req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
+ err = -errno;
+ goto out;
+ }
+ } else {
+ goto out;
+ }
+ }
+#else
+ if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
+ err = UV_ENOSYS;
goto out;
}
+#endif
bytes_to_send = statsbuf.st_size;
in_offset = 0;
@@ -1117,7 +1152,7 @@ static void uv__fs_work(struct uv__work* w) {
} while (r == -1 && errno == EINTR && retry_on_eintr);
if (r == -1)
- req->result = -errno;
+ req->result = UV__ERR(errno);
else
req->result = r;
@@ -1135,9 +1170,9 @@ static void uv__fs_done(struct uv__work* w, int status) {
req = container_of(w, uv_fs_t, work_req);
uv__req_unregister(req->loop, req);
- if (status == -ECANCELED) {
+ if (status == UV_ECANCELED) {
assert(req->result == 0);
- req->result = -ECANCELED;
+ req->result = UV_ECANCELED;
}
req->cb(req);
@@ -1298,11 +1333,8 @@ int uv_fs_mkdtemp(uv_loop_t* loop,
uv_fs_cb cb) {
INIT(MKDTEMP);
req->path = uv__strdup(tpl);
- if (req->path == NULL) {
- if (cb != NULL)
- uv__req_unregister(loop, req);
- return -ENOMEM;
- }
+ if (req->path == NULL)
+ return UV_ENOMEM;
POST;
}
@@ -1330,7 +1362,7 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req,
INIT(READ);
if (bufs == NULL || nbufs == 0)
- return -EINVAL;
+ return UV_EINVAL;
req->file = file;
@@ -1339,11 +1371,8 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req,
if (nbufs > ARRAY_SIZE(req->bufsml))
req->bufs = uv__malloc(nbufs * sizeof(*bufs));
- if (req->bufs == NULL) {
- if (cb != NULL)
- uv__req_unregister(loop, req);
- return -ENOMEM;
- }
+ if (req->bufs == NULL)
+ return UV_ENOMEM;
memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
@@ -1469,7 +1498,7 @@ int uv_fs_write(uv_loop_t* loop,
INIT(WRITE);
if (bufs == NULL || nbufs == 0)
- return -EINVAL;
+ return UV_EINVAL;
req->file = file;
@@ -1478,11 +1507,8 @@ int uv_fs_write(uv_loop_t* loop,
if (nbufs > ARRAY_SIZE(req->bufsml))
req->bufs = uv__malloc(nbufs * sizeof(*bufs));
- if (req->bufs == NULL) {
- if (cb != NULL)
- uv__req_unregister(loop, req);
- return -ENOMEM;
- }
+ if (req->bufs == NULL)
+ return UV_ENOMEM;
memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
@@ -1509,6 +1535,10 @@ void uv_fs_req_cleanup(uv_fs_t* req) {
if (req->fs_type == UV_FS_SCANDIR && req->ptr != NULL)
uv__fs_scandir_cleanup(req);
+ if (req->bufs != req->bufsml)
+ uv__free(req->bufs);
+ req->bufs = NULL;
+
if (req->ptr != &req->statbuf)
uv__free(req->ptr);
req->ptr = NULL;
@@ -1523,8 +1553,11 @@ int uv_fs_copyfile(uv_loop_t* loop,
uv_fs_cb cb) {
INIT(COPYFILE);
- if (flags & ~UV_FS_COPYFILE_EXCL)
- return -EINVAL;
+ if (flags & ~(UV_FS_COPYFILE_EXCL |
+ UV_FS_COPYFILE_FICLONE |
+ UV_FS_COPYFILE_FICLONE_FORCE)) {
+ return UV_EINVAL;
+ }
PATH2;
req->flags = flags;
diff --git a/Utilities/cmlibuv/src/unix/fsevents.c b/Utilities/cmlibuv/src/unix/fsevents.c
index 3883740..47d8024 100644
--- a/Utilities/cmlibuv/src/unix/fsevents.c
+++ b/Utilities/cmlibuv/src/unix/fsevents.c
@@ -379,7 +379,7 @@ static int uv__fsevents_create_stream(uv_loop_t* loop, CFArrayRef paths) {
if (!pFSEventStreamStart(ref)) {
pFSEventStreamInvalidate(ref);
pFSEventStreamRelease(ref);
- return -EMFILE;
+ return UV_EMFILE;
}
state->fsevent_stream = ref;
@@ -440,7 +440,7 @@ static void uv__fsevents_reschedule(uv_fs_event_t* handle,
uv__fsevents_destroy_stream(handle->loop);
/* Any failure below will be a memory failure */
- err = -ENOMEM;
+ err = UV_ENOMEM;
/* Create list of all watched paths */
uv_mutex_lock(&state->fsevent_mutex);
@@ -474,7 +474,7 @@ static void uv__fsevents_reschedule(uv_fs_event_t* handle,
/* Create new FSEventStream */
cf_paths = pCFArrayCreate(NULL, (const void**) paths, path_count, NULL);
if (cf_paths == NULL) {
- err = -ENOMEM;
+ err = UV_ENOMEM;
goto final;
}
err = uv__fsevents_create_stream(handle->loop, cf_paths);
@@ -528,7 +528,7 @@ static int uv__fsevents_global_init(void) {
* but if it ever becomes one, we can turn the dynamic library handles into
* per-event loop properties and have the dynamic linker keep track for us.
*/
- err = -ENOSYS;
+ err = UV_ENOSYS;
core_foundation_handle = dlopen("/System/Library/Frameworks/"
"CoreFoundation.framework/"
"Versions/A/CoreFoundation",
@@ -543,7 +543,7 @@ static int uv__fsevents_global_init(void) {
if (core_services_handle == NULL)
goto out;
- err = -ENOENT;
+ err = UV_ENOENT;
#define V(handle, symbol) \
do { \
*(void **)(&p ## symbol) = dlsym((handle), #symbol); \
@@ -607,7 +607,7 @@ static int uv__fsevents_loop_init(uv_loop_t* loop) {
state = uv__calloc(1, sizeof(*state));
if (state == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
err = uv_mutex_init(&loop->cf_mutex);
if (err)
@@ -636,7 +636,7 @@ static int uv__fsevents_loop_init(uv_loop_t* loop) {
ctx.perform = uv__cf_loop_cb;
state->signal_source = pCFRunLoopSourceCreate(NULL, 0, &ctx);
if (state->signal_source == NULL) {
- err = -ENOMEM;
+ err = UV_ENOMEM;
goto fail_signal_source_create;
}
@@ -655,7 +655,7 @@ static int uv__fsevents_loop_init(uv_loop_t* loop) {
loop->cf_state = state;
/* uv_thread_t is an alias for pthread_t. */
- err = -pthread_create(&loop->cf_thread, attr, uv__cf_loop_runner, loop);
+ err = UV__ERR(pthread_create(&loop->cf_thread, attr, uv__cf_loop_runner, loop));
if (attr != NULL)
pthread_attr_destroy(attr);
@@ -787,7 +787,7 @@ int uv__cf_loop_signal(uv_loop_t* loop,
item = uv__malloc(sizeof(*item));
if (item == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
item->handle = handle;
item->type = type;
@@ -817,7 +817,7 @@ int uv__fsevents_init(uv_fs_event_t* handle) {
/* Get absolute path to file */
handle->realpath = realpath(handle->path, NULL);
if (handle->realpath == NULL)
- return -errno;
+ return UV__ERR(errno);
handle->realpath_len = strlen(handle->realpath);
/* Initialize event queue */
@@ -830,7 +830,7 @@ int uv__fsevents_init(uv_fs_event_t* handle) {
*/
handle->cf_cb = uv__malloc(sizeof(*handle->cf_cb));
if (handle->cf_cb == NULL) {
- err = -ENOMEM;
+ err = UV_ENOMEM;
goto fail_cf_cb_malloc;
}
@@ -881,7 +881,7 @@ int uv__fsevents_close(uv_fs_event_t* handle) {
uv__cf_loop_state_t* state;
if (handle->cf_cb == NULL)
- return -EINVAL;
+ return UV_EINVAL;
/* Remove handle from the list */
state = handle->loop->cf_state;
@@ -895,7 +895,7 @@ int uv__fsevents_close(uv_fs_event_t* handle) {
assert(handle != NULL);
err = uv__cf_loop_signal(handle->loop, handle, kUVCFLoopSignalClosing);
if (err)
- return -err;
+ return UV__ERR(err);
/* Wait for deinitialization */
uv_sem_wait(&state->fsevent_sem);
diff --git a/Utilities/cmlibuv/src/unix/getaddrinfo.c b/Utilities/cmlibuv/src/unix/getaddrinfo.c
index 0185971..10e8afd 100644
--- a/Utilities/cmlibuv/src/unix/getaddrinfo.c
+++ b/Utilities/cmlibuv/src/unix/getaddrinfo.c
@@ -86,7 +86,7 @@ int uv__getaddrinfo_translate_error(int sys_err) {
case EAI_SOCKTYPE: return UV_EAI_SOCKTYPE;
#endif
#if defined(EAI_SYSTEM)
- case EAI_SYSTEM: return -errno;
+ case EAI_SYSTEM: return UV__ERR(errno);
#endif
}
assert(!"unknown EAI_* error code");
@@ -125,7 +125,7 @@ static void uv__getaddrinfo_done(struct uv__work* w, int status) {
req->service = NULL;
req->hostname = NULL;
- if (status == -ECANCELED) {
+ if (status == UV_ECANCELED) {
assert(req->retcode == 0);
req->retcode = UV_EAI_CANCELED;
}
@@ -148,7 +148,7 @@ int uv_getaddrinfo(uv_loop_t* loop,
char* buf;
if (req == NULL || (hostname == NULL && service == NULL))
- return -EINVAL;
+ return UV_EINVAL;
hostname_len = hostname ? strlen(hostname) + 1 : 0;
service_len = service ? strlen(service) + 1 : 0;
@@ -156,7 +156,7 @@ int uv_getaddrinfo(uv_loop_t* loop,
buf = uv__malloc(hostname_len + service_len + hints_len);
if (buf == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
uv__req_init(loop, req, UV_GETADDRINFO);
req->loop = loop;
@@ -211,7 +211,7 @@ int uv_if_indextoname(unsigned int ifindex, char* buffer, size_t* size) {
return UV_EINVAL;
if (if_indextoname(ifindex, ifname_buf) == NULL)
- return -errno;
+ return UV__ERR(errno);
len = strnlen(ifname_buf, sizeof(ifname_buf));
diff --git a/Utilities/cmlibuv/src/unix/getnameinfo.c b/Utilities/cmlibuv/src/unix/getnameinfo.c
index b2879d6..d9e6f79 100644
--- a/Utilities/cmlibuv/src/unix/getnameinfo.c
+++ b/Utilities/cmlibuv/src/unix/getnameinfo.c
@@ -61,7 +61,7 @@ static void uv__getnameinfo_done(struct uv__work* w, int status) {
uv__req_unregister(req->loop, req);
host = service = NULL;
- if (status == -ECANCELED) {
+ if (status == UV_ECANCELED) {
assert(req->retcode == 0);
req->retcode = UV_EAI_CANCELED;
} else if (req->retcode == 0) {
diff --git a/Utilities/cmlibuv/src/unix/ibmi.c b/Utilities/cmlibuv/src/unix/ibmi.c
index c19e2fc..02e90fb 100644
--- a/Utilities/cmlibuv/src/unix/ibmi.c
+++ b/Utilities/cmlibuv/src/unix/ibmi.c
@@ -92,7 +92,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
*cpu_infos = uv__malloc(numcpus * sizeof(uv_cpu_info_t));
if (!*cpu_infos) {
- return -ENOMEM;
+ return UV_ENOMEM;
}
cpu_info = *cpu_infos;
diff --git a/Utilities/cmlibuv/src/unix/internal.h b/Utilities/cmlibuv/src/unix/internal.h
index 668e576..89c6eb1 100644
--- a/Utilities/cmlibuv/src/unix/internal.h
+++ b/Utilities/cmlibuv/src/unix/internal.h
@@ -29,6 +29,7 @@
#include <string.h> /* strrchr */
#include <fcntl.h> /* O_CLOEXEC, may be */
#include <stdio.h>
+#include <errno.h>
#if defined(__STRICT_ANSI__)
# define inline __inline
@@ -184,7 +185,7 @@ struct uv__stream_queued_fds_s {
defined(__DragonFly__) || \
defined(__FreeBSD__) || \
defined(__FreeBSD_kernel__) || \
- (defined(__linux__) && !defined(__sparc__)) || \
+ defined(__linux__) || \
defined(__OpenBSD__) || \
defined(__NetBSD__)
#define uv__cloexec uv__cloexec_ioctl
@@ -194,12 +195,24 @@ struct uv__stream_queued_fds_s {
#define uv__nonblock uv__nonblock_fcntl
#endif
+/* On Linux, uv__nonblock_fcntl() and uv__nonblock_ioctl() do not commute
+ * when O_NDELAY is not equal to O_NONBLOCK. Case in point: linux/sparc32
+ * and linux/sparc64, where O_NDELAY is O_NONBLOCK + another bit.
+ *
+ * Libuv uses uv__nonblock_fcntl() directly sometimes so ensure that it
+ * commutes with uv__nonblock().
+ */
+#if defined(__linux__) && O_NDELAY != O_NONBLOCK
+#undef uv__nonblock
+#define uv__nonblock uv__nonblock_fcntl
+#endif
+
/* core */
int uv__cloexec_ioctl(int fd, int set);
int uv__cloexec_fcntl(int fd, int set);
int uv__nonblock_ioctl(int fd, int set);
int uv__nonblock_fcntl(int fd, int set);
-int uv__close(int fd);
+int uv__close(int fd); /* preserves errno */
int uv__close_nocheckstdio(int fd);
int uv__socket(int domain, int type, int protocol);
int uv__dup(int fd);
diff --git a/Utilities/cmlibuv/src/unix/kqueue.c b/Utilities/cmlibuv/src/unix/kqueue.c
index 5e89bdc..a30fd73 100644
--- a/Utilities/cmlibuv/src/unix/kqueue.c
+++ b/Utilities/cmlibuv/src/unix/kqueue.c
@@ -51,7 +51,7 @@ static void uv__fs_event(uv_loop_t* loop, uv__io_t* w, unsigned int fflags);
int uv__kqueue_init(uv_loop_t* loop) {
loop->backend_fd = kqueue();
if (loop->backend_fd == -1)
- return -errno;
+ return UV__ERR(errno);
uv__cloexec(loop->backend_fd, 1);
@@ -98,7 +98,7 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) {
rc = 0;
EV_SET(&ev, fd, EVFILT_READ, EV_ADD, 0, 0, 0);
if (kevent(loop->backend_fd, &ev, 1, NULL, 0, NULL))
- rc = -errno;
+ rc = UV__ERR(errno);
EV_SET(&ev, fd, EVFILT_READ, EV_DELETE, 0, 0, 0);
if (rc == 0)
@@ -458,12 +458,12 @@ int uv_fs_event_start(uv_fs_event_t* handle,
int fd;
if (uv__is_active(handle))
- return -EINVAL;
+ return UV_EINVAL;
/* TODO open asynchronously - but how do we report back errors? */
fd = open(path, O_RDONLY);
if (fd == -1)
- return -errno;
+ return UV__ERR(errno);
uv__handle_start(handle);
uv__io_init(&handle->event_watcher, uv__fs_event, fd);
diff --git a/Utilities/cmlibuv/src/unix/linux-core.c b/Utilities/cmlibuv/src/unix/linux-core.c
index 4d480ce..b63c25f 100644
--- a/Utilities/cmlibuv/src/unix/linux-core.c
+++ b/Utilities/cmlibuv/src/unix/linux-core.c
@@ -101,7 +101,7 @@ int uv__platform_loop_init(uv_loop_t* loop) {
loop->inotify_watchers = NULL;
if (fd == -1)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
@@ -175,7 +175,7 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) {
rc = 0;
if (uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_ADD, fd, &e))
if (errno != EEXIST)
- rc = -errno;
+ rc = UV__ERR(errno);
if (rc == 0)
if (uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_DEL, fd, &e))
@@ -485,7 +485,7 @@ int uv_resident_set_memory(size_t* rss) {
while (fd == -1 && errno == EINTR);
if (fd == -1)
- return -errno;
+ return UV__ERR(errno);
do
n = read(fd, buf, sizeof(buf) - 1);
@@ -493,7 +493,7 @@ int uv_resident_set_memory(size_t* rss) {
uv__close(fd);
if (n == -1)
- return -errno;
+ return UV__ERR(errno);
buf[n] = '\0';
s = strchr(buf, ' ');
@@ -525,7 +525,7 @@ int uv_resident_set_memory(size_t* rss) {
return 0;
err:
- return -EINVAL;
+ return UV_EINVAL;
}
@@ -547,7 +547,7 @@ int uv_uptime(double* uptime) {
}
if (r)
- return -errno;
+ return UV__ERR(errno);
*uptime = now.tv_sec;
return 0;
@@ -559,7 +559,7 @@ static int uv__cpu_num(FILE* statfile_fp, unsigned int* numcpus) {
char buf[1024];
if (!fgets(buf, sizeof(buf), statfile_fp))
- return -EIO;
+ return UV_EIO;
num = 0;
while (fgets(buf, sizeof(buf), statfile_fp)) {
@@ -569,7 +569,7 @@ static int uv__cpu_num(FILE* statfile_fp, unsigned int* numcpus) {
}
if (num == 0)
- return -EIO;
+ return UV_EIO;
*numcpus = num;
return 0;
@@ -587,13 +587,13 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
statfile_fp = uv__open_file("/proc/stat");
if (statfile_fp == NULL)
- return -errno;
+ return UV__ERR(errno);
err = uv__cpu_num(statfile_fp, &numcpus);
if (err < 0)
goto out;
- err = -ENOMEM;
+ err = UV_ENOMEM;
ci = uv__calloc(numcpus, sizeof(*ci));
if (ci == NULL)
goto out;
@@ -667,7 +667,7 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) {
defined(__x86_64__)
fp = uv__open_file("/proc/cpuinfo");
if (fp == NULL)
- return -errno;
+ return UV__ERR(errno);
while (fgets(buf, sizeof(buf), fp)) {
if (model_idx < numcpus) {
@@ -676,7 +676,7 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) {
model = uv__strndup(model, strlen(model) - 1); /* Strip newline. */
if (model == NULL) {
fclose(fp);
- return -ENOMEM;
+ return UV_ENOMEM;
}
ci[model_idx++].model = model;
continue;
@@ -695,7 +695,7 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) {
model = uv__strndup(model, strlen(model) - 1); /* Strip newline. */
if (model == NULL) {
fclose(fp);
- return -ENOMEM;
+ return UV_ENOMEM;
}
ci[model_idx++].model = model;
continue;
@@ -725,7 +725,7 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) {
while (model_idx < numcpus) {
model = uv__strndup(inferred_model, strlen(inferred_model));
if (model == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
ci[model_idx++].model = model;
}
@@ -854,7 +854,7 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
int uv_interface_addresses(uv_interface_address_t** addresses,
int* count) {
#ifndef HAVE_IFADDRS_H
- return -ENOSYS;
+ return UV_ENOSYS;
#else
struct ifaddrs *addrs, *ent;
uv_interface_address_t* address;
@@ -862,7 +862,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
struct sockaddr_ll *sll;
if (getifaddrs(&addrs))
- return -errno;
+ return UV__ERR(errno);
*count = 0;
*addresses = NULL;
@@ -881,7 +881,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
*addresses = uv__malloc(*count * sizeof(**addresses));
if (!(*addresses)) {
freeifaddrs(addrs);
- return -ENOMEM;
+ return UV_ENOMEM;
}
address = *addresses;
diff --git a/Utilities/cmlibuv/src/unix/linux-inotify.c b/Utilities/cmlibuv/src/unix/linux-inotify.c
index 5934c5d..bcad630 100644
--- a/Utilities/cmlibuv/src/unix/linux-inotify.c
+++ b/Utilities/cmlibuv/src/unix/linux-inotify.c
@@ -73,11 +73,11 @@ static int new_inotify_fd(void) {
return fd;
if (errno != ENOSYS)
- return -errno;
+ return UV__ERR(errno);
fd = uv__inotify_init();
if (fd == -1)
- return -errno;
+ return UV__ERR(errno);
err = uv__cloexec(fd, 1);
if (err == 0)
@@ -283,7 +283,7 @@ int uv_fs_event_start(uv_fs_event_t* handle,
int wd;
if (uv__is_active(handle))
- return -EINVAL;
+ return UV_EINVAL;
err = init_inotify(handle->loop);
if (err)
@@ -300,7 +300,7 @@ int uv_fs_event_start(uv_fs_event_t* handle,
wd = uv__inotify_add_watch(handle->loop->inotify_fd, path, events);
if (wd == -1)
- return -errno;
+ return UV__ERR(errno);
w = find_watcher(handle->loop, wd);
if (w)
@@ -308,7 +308,7 @@ int uv_fs_event_start(uv_fs_event_t* handle,
w = uv__malloc(sizeof(*w) + strlen(path) + 1);
if (w == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
w->wd = wd;
w->path = strcpy((char*)(w + 1), path);
diff --git a/Utilities/cmlibuv/src/unix/loop-watcher.c b/Utilities/cmlibuv/src/unix/loop-watcher.c
index 340bb0d..b8c1c2a 100644
--- a/Utilities/cmlibuv/src/unix/loop-watcher.c
+++ b/Utilities/cmlibuv/src/unix/loop-watcher.c
@@ -31,7 +31,7 @@
\
int uv_##name##_start(uv_##name##_t* handle, uv_##name##_cb cb) { \
if (uv__is_active(handle)) return 0; \
- if (cb == NULL) return -EINVAL; \
+ if (cb == NULL) return UV_EINVAL; \
QUEUE_INSERT_HEAD(&handle->loop->name##_handles, &handle->queue); \
handle->name##_cb = cb; \
uv__handle_start(handle); \
diff --git a/Utilities/cmlibuv/src/unix/loop.c b/Utilities/cmlibuv/src/unix/loop.c
index 5b5b0e0..99ead6c 100644
--- a/Utilities/cmlibuv/src/unix/loop.c
+++ b/Utilities/cmlibuv/src/unix/loop.c
@@ -38,13 +38,14 @@ int uv_loop_init(uv_loop_t* loop) {
heap_init((struct heap*) &loop->timer_heap);
QUEUE_INIT(&loop->wq);
- QUEUE_INIT(&loop->active_reqs);
QUEUE_INIT(&loop->idle_handles);
QUEUE_INIT(&loop->async_handles);
QUEUE_INIT(&loop->check_handles);
QUEUE_INIT(&loop->prepare_handles);
QUEUE_INIT(&loop->handle_queue);
+ loop->active_handles = 0;
+ loop->active_reqs.count = 0;
loop->nfds = 0;
loop->watchers = NULL;
loop->nwatchers = 0;
diff --git a/Utilities/cmlibuv/src/unix/netbsd.c b/Utilities/cmlibuv/src/unix/netbsd.c
index 7425072..2605c11 100644
--- a/Utilities/cmlibuv/src/unix/netbsd.c
+++ b/Utilities/cmlibuv/src/unix/netbsd.c
@@ -82,7 +82,7 @@ int uv_exepath(char* buffer, size_t* size) {
int mib[4];
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
mib[0] = CTL_KERN;
mib[1] = KERN_PROC_ARGS;
@@ -91,7 +91,7 @@ int uv_exepath(char* buffer, size_t* size) {
int_size = ARRAY_SIZE(int_buf);
if (sysctl(mib, 4, int_buf, &int_size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
/* Copy string from the intermediate buffer to outer one with appropriate
* length.
@@ -111,7 +111,7 @@ uint64_t uv_get_free_memory(void) {
int which[] = {CTL_VM, VM_UVMEXP};
if (sysctl(which, 2, &info, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
return (uint64_t) info.free * sysconf(_SC_PAGESIZE);
}
@@ -128,7 +128,7 @@ uint64_t uv_get_total_memory(void) {
size_t size = sizeof(info);
if (sysctl(which, 2, &info, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
return (uint64_t) info;
}
@@ -150,7 +150,7 @@ int uv_set_process_title(const char* title) {
if (process_title == NULL) {
uv_mutex_unlock(&process_title_mutex);
- return -ENOMEM;
+ return UV_ENOMEM;
}
uv__free(process_title);
@@ -167,7 +167,7 @@ int uv_get_process_title(char* buffer, size_t size) {
size_t len;
if (buffer == NULL || size == 0)
- return -EINVAL;
+ return UV_EINVAL;
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
uv_mutex_lock(&process_title_mutex);
@@ -177,7 +177,7 @@ int uv_get_process_title(char* buffer, size_t size) {
if (size < len) {
uv_mutex_unlock(&process_title_mutex);
- return -ENOBUFS;
+ return UV_ENOBUFS;
}
memcpy(buffer, process_title, len);
@@ -219,7 +219,7 @@ int uv_resident_set_memory(size_t* rss) {
error:
if (kd) kvm_close(kd);
- return -EPERM;
+ return UV_EPERM;
}
@@ -230,7 +230,7 @@ int uv_uptime(double* uptime) {
static int which[] = {CTL_KERN, KERN_BOOTTIME};
if (sysctl(which, 2, &info, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
now = time(NULL);
@@ -254,12 +254,12 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
size = sizeof(model);
if (sysctlbyname("machdep.cpu_brand", &model, &size, NULL, 0) &&
sysctlbyname("hw.model", &model, &size, NULL, 0)) {
- return -errno;
+ return UV__ERR(errno);
}
size = sizeof(numcpus);
if (sysctlbyname("hw.ncpu", &numcpus, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
*count = numcpus;
/* Only i386 and amd64 have machdep.tsc_freq */
@@ -270,16 +270,16 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
size = numcpus * CPUSTATES * sizeof(*cp_times);
cp_times = uv__malloc(size);
if (cp_times == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
if (sysctlbyname("kern.cp_time", cp_times, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
*cpu_infos = uv__malloc(numcpus * sizeof(**cpu_infos));
if (!(*cpu_infos)) {
uv__free(cp_times);
uv__free(*cpu_infos);
- return -ENOMEM;
+ return UV_ENOMEM;
}
for (i = 0; i < numcpus; i++) {
diff --git a/Utilities/cmlibuv/src/unix/no-fsevents.c b/Utilities/cmlibuv/src/unix/no-fsevents.c
index 38fb6ab..158643a 100644
--- a/Utilities/cmlibuv/src/unix/no-fsevents.c
+++ b/Utilities/cmlibuv/src/unix/no-fsevents.c
@@ -25,16 +25,16 @@
#include <errno.h>
int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
- return -ENOSYS;
+ return UV_ENOSYS;
}
int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb,
const char* filename, unsigned int flags) {
- return -ENOSYS;
+ return UV_ENOSYS;
}
int uv_fs_event_stop(uv_fs_event_t* handle) {
- return -ENOSYS;
+ return UV_ENOSYS;
}
void uv__fs_event_close(uv_fs_event_t* handle) {
diff --git a/Utilities/cmlibuv/src/unix/no-proctitle.c b/Utilities/cmlibuv/src/unix/no-proctitle.c
index a5c19fb..165740c 100644
--- a/Utilities/cmlibuv/src/unix/no-proctitle.c
+++ b/Utilities/cmlibuv/src/unix/no-proctitle.c
@@ -35,7 +35,7 @@ int uv_set_process_title(const char* title) {
int uv_get_process_title(char* buffer, size_t size) {
if (buffer == NULL || size == 0)
- return -EINVAL;
+ return UV_EINVAL;
buffer[0] = '\0';
return 0;
diff --git a/Utilities/cmlibuv/src/unix/openbsd.c b/Utilities/cmlibuv/src/unix/openbsd.c
index c0ffa56..ce937cd 100644
--- a/Utilities/cmlibuv/src/unix/openbsd.c
+++ b/Utilities/cmlibuv/src/unix/openbsd.c
@@ -78,11 +78,11 @@ int uv_exepath(char* buffer, size_t* size) {
int err;
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
mypid = getpid();
for (;;) {
- err = -ENOMEM;
+ err = UV_ENOMEM;
argsbuf_tmp = uv__realloc(argsbuf, argsbuf_size);
if (argsbuf_tmp == NULL)
goto out;
@@ -95,14 +95,14 @@ int uv_exepath(char* buffer, size_t* size) {
break;
}
if (errno != ENOMEM) {
- err = -errno;
+ err = UV__ERR(errno);
goto out;
}
argsbuf_size *= 2U;
}
if (argsbuf[0] == NULL) {
- err = -EINVAL; /* FIXME(bnoordhuis) More appropriate error. */
+ err = UV_EINVAL; /* FIXME(bnoordhuis) More appropriate error. */
goto out;
}
@@ -128,7 +128,7 @@ uint64_t uv_get_free_memory(void) {
int which[] = {CTL_VM, VM_UVMEXP};
if (sysctl(which, 2, &info, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
return (uint64_t) info.free * sysconf(_SC_PAGESIZE);
}
@@ -140,7 +140,7 @@ uint64_t uv_get_total_memory(void) {
size_t size = sizeof(info);
if (sysctl(which, 2, &info, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
return (uint64_t) info;
}
@@ -162,7 +162,7 @@ int uv_set_process_title(const char* title) {
if (process_title == NULL) {
uv_mutex_unlock(&process_title_mutex);
- return -ENOMEM;
+ return UV_ENOMEM;
}
uv__free(process_title);
@@ -179,7 +179,7 @@ int uv_get_process_title(char* buffer, size_t size) {
size_t len;
if (buffer == NULL || size == 0)
- return -EINVAL;
+ return UV_EINVAL;
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
uv_mutex_lock(&process_title_mutex);
@@ -189,7 +189,7 @@ int uv_get_process_title(char* buffer, size_t size) {
if (size < len) {
uv_mutex_unlock(&process_title_mutex);
- return -ENOBUFS;
+ return UV_ENOBUFS;
}
memcpy(buffer, process_title, len);
@@ -219,7 +219,7 @@ int uv_resident_set_memory(size_t* rss) {
mib[5] = 1;
if (sysctl(mib, 6, &kinfo, &size, NULL, 0) < 0)
- return -errno;
+ return UV__ERR(errno);
*rss = kinfo.p_vm_rssize * page_size;
return 0;
@@ -233,7 +233,7 @@ int uv_uptime(double* uptime) {
static int which[] = {CTL_KERN, KERN_BOOTTIME};
if (sysctl(which, 2, &info, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
now = time(NULL);
@@ -255,16 +255,16 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
size = sizeof(model);
if (sysctl(which, 2, &model, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
which[1] = HW_NCPU;
size = sizeof(numcpus);
if (sysctl(which, 2, &numcpus, &size, NULL, 0))
- return -errno;
+ return UV__ERR(errno);
*cpu_infos = uv__malloc(numcpus * sizeof(**cpu_infos));
if (!(*cpu_infos))
- return -ENOMEM;
+ return UV_ENOMEM;
*count = numcpus;
@@ -272,7 +272,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
size = sizeof(cpuspeed);
if (sysctl(which, 2, &cpuspeed, &size, NULL, 0)) {
uv__free(*cpu_infos);
- return -errno;
+ return UV__ERR(errno);
}
size = sizeof(info);
@@ -283,7 +283,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
size = sizeof(info);
if (sysctl(which, 3, &info, &size, NULL, 0)) {
uv__free(*cpu_infos);
- return -errno;
+ return UV__ERR(errno);
}
cpu_info = &(*cpu_infos)[i];
diff --git a/Utilities/cmlibuv/src/unix/os390-syscalls.c b/Utilities/cmlibuv/src/unix/os390-syscalls.c
index 21558ea..a5dd344 100644
--- a/Utilities/cmlibuv/src/unix/os390-syscalls.c
+++ b/Utilities/cmlibuv/src/unix/os390-syscalls.c
@@ -215,6 +215,7 @@ uv__os390_epoll* epoll_create1(int flags) {
maybe_resize(lst, 1);
lst->items[lst->size - 1].fd = lst->msg_queue;
lst->items[lst->size - 1].events = POLLIN;
+ lst->items[lst->size - 1].revents = 0;
uv_once(&once, epoll_init);
uv_mutex_lock(&global_epoll_lock);
QUEUE_INSERT_TAIL(&global_epoll_queue, &lst->member);
@@ -252,6 +253,7 @@ int epoll_ctl(uv__os390_epoll* lst,
}
lst->items[fd].fd = fd;
lst->items[fd].events = event->events;
+ lst->items[fd].revents = 0;
} else if (op == EPOLL_CTL_MOD) {
if (fd >= lst->size || lst->items[fd].fd == -1) {
uv_mutex_unlock(&global_epoll_lock);
diff --git a/Utilities/cmlibuv/src/unix/os390.c b/Utilities/cmlibuv/src/unix/os390.c
index 081438e..f766b39 100644
--- a/Utilities/cmlibuv/src/unix/os390.c
+++ b/Utilities/cmlibuv/src/unix/os390.c
@@ -122,7 +122,7 @@ int uv__platform_loop_init(uv_loop_t* loop) {
ep = epoll_create1(0);
loop->ep = ep;
if (ep == NULL)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
@@ -259,12 +259,12 @@ int uv_exepath(char* buffer, size_t* size) {
int pid;
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
pid = getpid();
res = getexe(pid, args, sizeof(args));
if (res < 0)
- return -EINVAL;
+ return UV_EINVAL;
/*
* Possibilities for args:
@@ -277,7 +277,7 @@ int uv_exepath(char* buffer, size_t* size) {
/* Case i) and ii) absolute or relative paths */
if (strchr(args, '/') != NULL) {
if (realpath(args, abspath) != abspath)
- return -errno;
+ return UV__ERR(errno);
abspath_size = strlen(abspath);
@@ -297,11 +297,11 @@ int uv_exepath(char* buffer, size_t* size) {
char* path = getenv("PATH");
if (path == NULL)
- return -EINVAL;
+ return UV_EINVAL;
clonedpath = uv__strdup(path);
if (clonedpath == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
token = strtok(clonedpath, ":");
while (token != NULL) {
@@ -327,7 +327,7 @@ int uv_exepath(char* buffer, size_t* size) {
uv__free(clonedpath);
/* Out of tokens (path entries), and no match found */
- return -EINVAL;
+ return UV_EINVAL;
}
}
@@ -407,7 +407,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
*cpu_infos = uv__malloc(*count * sizeof(uv_cpu_info_t));
if (!*cpu_infos)
- return -ENOMEM;
+ return UV_ENOMEM;
cpu_info = *cpu_infos;
idx = 0;
@@ -452,7 +452,7 @@ static int uv__interface_addresses_v6(uv_interface_address_t** addresses,
maxsize = 16384;
if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)))
- return -errno;
+ return UV__ERR(errno);
ifc.__nif6h_version = 1;
ifc.__nif6h_buflen = maxsize;
@@ -460,7 +460,7 @@ static int uv__interface_addresses_v6(uv_interface_address_t** addresses,
if (ioctl(sockfd, SIOCGIFCONF6, &ifc) == -1) {
uv__close(sockfd);
- return -errno;
+ return UV__ERR(errno);
}
@@ -484,7 +484,7 @@ static int uv__interface_addresses_v6(uv_interface_address_t** addresses,
*addresses = uv__malloc(*count * sizeof(uv_interface_address_t));
if (!(*addresses)) {
uv__close(sockfd);
- return -ENOMEM;
+ return UV_ENOMEM;
}
address = *addresses;
@@ -543,13 +543,13 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (0 > sockfd)
- return -errno;
+ return UV__ERR(errno);
ifc.ifc_req = uv__calloc(1, maxsize);
ifc.ifc_len = maxsize;
if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) {
uv__close(sockfd);
- return -errno;
+ return UV__ERR(errno);
}
#define MAX(a,b) (((a)>(b))?(a):(b))
@@ -569,7 +569,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
uv__close(sockfd);
- return -errno;
+ return UV__ERR(errno);
}
if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
@@ -584,7 +584,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
if (!(*addresses)) {
uv__close(sockfd);
- return -ENOMEM;
+ return UV_ENOMEM;
}
address = *addresses;
@@ -607,7 +607,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
uv__close(sockfd);
- return -ENOSYS;
+ return UV_ENOSYS;
}
if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
@@ -706,7 +706,7 @@ int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb,
int rc;
if (uv__is_active(handle))
- return -EINVAL;
+ return UV_EINVAL;
ep = handle->loop->ep;
assert(ep->msg_queue != -1);
@@ -718,11 +718,11 @@ int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb,
path = uv__strdup(filename);
if (path == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
rc = __w_pioctl(path, _IOCC_REGFILEINT, sizeof(reg_struct), &reg_struct);
if (rc != 0)
- return -errno;
+ return UV__ERR(errno);
uv__handle_start(handle);
handle->path = path;
diff --git a/Utilities/cmlibuv/src/unix/pipe.c b/Utilities/cmlibuv/src/unix/pipe.c
index df3aad0..42846b9 100644
--- a/Utilities/cmlibuv/src/unix/pipe.c
+++ b/Utilities/cmlibuv/src/unix/pipe.c
@@ -48,12 +48,12 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
/* Already bound? */
if (uv__stream_fd(handle) >= 0)
- return -EINVAL;
+ return UV_EINVAL;
/* Make a copy of the file name, it outlives this function's scope. */
pipe_fname = uv__strdup(name);
if (pipe_fname == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
/* We've got a copy, don't touch the original any more. */
name = NULL;
@@ -69,10 +69,10 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
saddr.sun_family = AF_UNIX;
if (bind(sockfd, (struct sockaddr*)&saddr, sizeof saddr)) {
- err = -errno;
+ err = UV__ERR(errno);
/* Convert ENOENT to EACCES for compatibility with Windows. */
- if (err == -ENOENT)
- err = -EACCES;
+ if (err == UV_ENOENT)
+ err = UV_EACCES;
uv__close(sockfd);
goto err_socket;
@@ -92,7 +92,7 @@ err_socket:
int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
if (uv__stream_fd(handle) == -1)
- return -EINVAL;
+ return UV_EINVAL;
#if defined(__MVS__)
/* On zOS, backlog=0 has undefined behaviour */
@@ -103,7 +103,7 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
#endif
if (listen(uv__stream_fd(handle), backlog))
- return -errno;
+ return UV__ERR(errno);
handle->connection_cb = cb;
handle->io_watcher.cb = uv__server_io;
@@ -178,14 +178,14 @@ void uv_pipe_connect(uv_connect_t* req,
while (r == -1 && errno == EINTR);
if (r == -1 && errno != EINPROGRESS) {
- err = -errno;
+ err = UV__ERR(errno);
#if defined(__CYGWIN__) || defined(__MSYS__)
/* EBADF is supposed to mean that the socket fd is bad, but
Cygwin reports EBADF instead of ENOTSOCK when the file is
not a socket. We do not expect to see a bad fd here
(e.g. due to new_sock), so translate the error. */
- if (err == -EBADF)
- err = -ENOTSOCK;
+ if (err == UV_EBADF)
+ err = UV_ENOTSOCK;
#endif
goto out;
}
@@ -232,7 +232,7 @@ static int uv__pipe_getsockpeername(const uv_pipe_t* handle,
err = func(uv__stream_fd(handle), (struct sockaddr*) &sa, &addrlen);
if (err < 0) {
*size = 0;
- return -errno;
+ return UV__ERR(errno);
}
#if defined(__linux__)
@@ -310,27 +310,12 @@ int uv_pipe_chmod(uv_pipe_t* handle, int mode) {
int r;
if (handle == NULL || uv__stream_fd(handle) == -1)
- return -EBADF;
+ return UV_EBADF;
if (mode != UV_READABLE &&
mode != UV_WRITABLE &&
mode != (UV_WRITABLE | UV_READABLE))
- return -EINVAL;
-
- if (fstat(uv__stream_fd(handle), &pipe_stat) == -1)
- return -errno;
-
- desired_mode = 0;
- if (mode & UV_READABLE)
- desired_mode |= S_IRUSR | S_IRGRP | S_IROTH;
- if (mode & UV_WRITABLE)
- desired_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
-
- /* Exit early if pipe already has desired mode. */
- if ((pipe_stat.st_mode & desired_mode) == desired_mode)
- return 0;
-
- pipe_stat.st_mode |= desired_mode;
+ return UV_EINVAL;
/* Unfortunately fchmod does not work on all platforms, we will use chmod. */
name_len = 0;
@@ -348,8 +333,28 @@ int uv_pipe_chmod(uv_pipe_t* handle, int mode) {
return r;
}
+ /* stat must be used as fstat has a bug on Darwin */
+ if (stat(name_buffer, &pipe_stat) == -1) {
+ uv__free(name_buffer);
+ return -errno;
+ }
+
+ desired_mode = 0;
+ if (mode & UV_READABLE)
+ desired_mode |= S_IRUSR | S_IRGRP | S_IROTH;
+ if (mode & UV_WRITABLE)
+ desired_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
+
+ /* Exit early if pipe already has desired mode. */
+ if ((pipe_stat.st_mode & desired_mode) == desired_mode) {
+ uv__free(name_buffer);
+ return 0;
+ }
+
+ pipe_stat.st_mode |= desired_mode;
+
r = chmod(name_buffer, pipe_stat.st_mode);
uv__free(name_buffer);
- return r != -1 ? 0 : -errno;
+ return r != -1 ? 0 : UV__ERR(errno);
}
diff --git a/Utilities/cmlibuv/src/unix/poll.c b/Utilities/cmlibuv/src/unix/poll.c
index 816c7dc..f3b0bf4 100644
--- a/Utilities/cmlibuv/src/unix/poll.c
+++ b/Utilities/cmlibuv/src/unix/poll.c
@@ -47,7 +47,7 @@ static void uv__poll_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
if ((events & POLLERR) && !(events & UV__POLLPRI)) {
uv__io_stop(loop, w, POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI);
uv__handle_stop(handle);
- handle->poll_cb(handle, -EBADF, 0);
+ handle->poll_cb(handle, UV_EBADF, 0);
return;
}
@@ -76,7 +76,7 @@ int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) {
* Workaround for e.g. kqueue fds not supporting ioctls.
*/
err = uv__nonblock(fd, 1);
- if (err == -ENOTTY)
+ if (err == UV_ENOTTY)
if (uv__nonblock == uv__nonblock_ioctl)
err = uv__nonblock_fcntl(fd, 1);
diff --git a/Utilities/cmlibuv/src/unix/posix-poll.c b/Utilities/cmlibuv/src/unix/posix-poll.c
index 3fba96e..f3181f9 100644
--- a/Utilities/cmlibuv/src/unix/posix-poll.c
+++ b/Utilities/cmlibuv/src/unix/posix-poll.c
@@ -107,7 +107,7 @@ static void uv__pollfds_add(uv_loop_t* loop, uv__io_t* w) {
static void uv__pollfds_del(uv_loop_t* loop, int fd) {
size_t i;
assert(!loop->poll_fds_iterating);
- for (i = 0; i < loop->poll_fds_used; ++i) {
+ for (i = 0; i < loop->poll_fds_used;) {
if (loop->poll_fds[i].fd == fd) {
/* swap to last position and remove */
--loop->poll_fds_used;
@@ -115,7 +115,17 @@ static void uv__pollfds_del(uv_loop_t* loop, int fd) {
loop->poll_fds[loop->poll_fds_used].fd = -1;
loop->poll_fds[loop->poll_fds_used].events = 0;
loop->poll_fds[loop->poll_fds_used].revents = 0;
- return;
+ /* This method is called with an fd of -1 to purge the invalidated fds,
+ * so we may possibly have multiples to remove.
+ */
+ if (-1 != fd)
+ return;
+ } else {
+ /* We must only increment the loop counter when the fds do not match.
+ * Otherwise, when we are purging an invalidated fd, the value just
+ * swapped here from the previous end of the array will be skipped.
+ */
+ ++i;
}
}
}
@@ -315,10 +325,10 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) {
while (rv == -1 && (errno == EINTR || errno == EAGAIN));
if (rv == -1)
- return -errno;
+ return UV__ERR(errno);
if (p[0].revents & POLLNVAL)
- return -EINVAL;
+ return UV_EINVAL;
return 0;
}
diff --git a/Utilities/cmlibuv/src/unix/process.c b/Utilities/cmlibuv/src/unix/process.c
index 47ab1dc..1bded8d 100644
--- a/Utilities/cmlibuv/src/unix/process.c
+++ b/Utilities/cmlibuv/src/unix/process.c
@@ -137,7 +137,7 @@ int uv__make_socketpair(int fds[2], int flags) {
* Anything else is a genuine error.
*/
if (errno != EINVAL)
- return -errno;
+ return UV__ERR(errno);
no_cloexec = 1;
@@ -145,7 +145,7 @@ skip:
#endif
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds))
- return -errno;
+ return UV__ERR(errno);
uv__cloexec(fds[0], 1);
uv__cloexec(fds[1], 1);
@@ -170,7 +170,7 @@ int uv__make_pipe(int fds[2], int flags) {
return 0;
if (errno != ENOSYS)
- return -errno;
+ return UV__ERR(errno);
no_pipe2 = 1;
@@ -178,7 +178,7 @@ skip:
#endif
if (pipe(fds))
- return -errno;
+ return UV__ERR(errno);
uv__cloexec(fds[0], 1);
uv__cloexec(fds[1], 1);
@@ -209,7 +209,7 @@ static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) {
case UV_CREATE_PIPE:
assert(container->data.stream != NULL);
if (container->data.stream->type != UV_NAMED_PIPE)
- return -EINVAL;
+ return UV_EINVAL;
else
return uv__make_socketpair(fds, 0);
@@ -221,21 +221,20 @@ static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) {
fd = uv__stream_fd(container->data.stream);
if (fd == -1)
- return -EINVAL;
+ return UV_EINVAL;
fds[1] = fd;
return 0;
default:
assert(0 && "Unexpected flags");
- return -EINVAL;
+ return UV_EINVAL;
}
}
static int uv__process_open_stream(uv_stdio_container_t* container,
- int pipefds[2],
- int writable) {
+ int pipefds[2]) {
int flags;
int err;
@@ -249,13 +248,11 @@ static int uv__process_open_stream(uv_stdio_container_t* container,
pipefds[1] = -1;
uv__nonblock(pipefds[0], 1);
- if (container->data.stream->type == UV_NAMED_PIPE &&
- ((uv_pipe_t*)container->data.stream)->ipc)
- flags = UV_STREAM_READABLE | UV_STREAM_WRITABLE;
- else if (writable)
- flags = UV_STREAM_WRITABLE;
- else
- flags = UV_STREAM_READABLE;
+ flags = 0;
+ if (container->flags & UV_WRITABLE_PIPE)
+ flags |= UV_STREAM_READABLE;
+ if (container->flags & UV_READABLE_PIPE)
+ flags |= UV_STREAM_WRITABLE;
return uv__stream_open(container->data.stream, pipefds[0], flags);
}
@@ -318,7 +315,7 @@ static void uv__process_child_init(const uv_process_options_t* options,
continue;
pipes[fd][1] = fcntl(use_fd, F_DUPFD, stdio_count);
if (pipes[fd][1] == -1) {
- uv__write_int(error_fd, -errno);
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
}
@@ -338,7 +335,7 @@ static void uv__process_child_init(const uv_process_options_t* options,
close_fd = use_fd;
if (use_fd == -1) {
- uv__write_int(error_fd, -errno);
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
}
@@ -350,7 +347,7 @@ static void uv__process_child_init(const uv_process_options_t* options,
fd = dup2(use_fd, fd);
if (fd == -1) {
- uv__write_int(error_fd, -errno);
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
@@ -369,7 +366,7 @@ static void uv__process_child_init(const uv_process_options_t* options,
}
if (options->cwd != NULL && chdir(options->cwd)) {
- uv__write_int(error_fd, -errno);
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
@@ -385,12 +382,12 @@ static void uv__process_child_init(const uv_process_options_t* options,
}
if ((options->flags & UV_PROCESS_SETGID) && setgid(options->gid)) {
- uv__write_int(error_fd, -errno);
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
if ((options->flags & UV_PROCESS_SETUID) && setuid(options->uid)) {
- uv__write_int(error_fd, -errno);
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
@@ -432,7 +429,7 @@ static void uv__process_child_init(const uv_process_options_t* options,
if (SIG_ERR != signal(n, SIG_DFL))
continue;
- uv__write_int(error_fd, -errno);
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
@@ -441,12 +438,12 @@ static void uv__process_child_init(const uv_process_options_t* options,
err = pthread_sigmask(SIG_SETMASK, &set, NULL);
if (err != 0) {
- uv__write_int(error_fd, -err);
+ uv__write_int(error_fd, UV__ERR(err));
_exit(127);
}
execvp(options->file, options->args);
- uv__write_int(error_fd, -errno);
+ uv__write_int(error_fd, UV__ERR(errno));
_exit(127);
}
#endif
@@ -457,7 +454,7 @@ int uv_spawn(uv_loop_t* loop,
const uv_process_options_t* options) {
#if defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH)
/* fork is marked __WATCHOS_PROHIBITED __TVOS_PROHIBITED. */
- return -ENOSYS;
+ return UV_ENOSYS;
#else
int signal_pipe[2] = { -1, -1 };
int pipes_storage[8][2];
@@ -498,7 +495,7 @@ int uv_spawn(uv_loop_t* loop,
if (stdio_count < 3)
stdio_count = 3;
- err = -ENOMEM;
+ err = UV_ENOMEM;
pipes = pipes_storage;
if (stdio_count > (int) ARRAY_SIZE(pipes_storage))
pipes = uv__malloc(stdio_count * sizeof(*pipes));
@@ -548,7 +545,7 @@ int uv_spawn(uv_loop_t* loop,
pid = fork();
if (pid == -1) {
- err = -errno;
+ err = UV__ERR(errno);
uv_rwlock_wrunlock(&loop->cloexec_lock);
uv__close(signal_pipe[0]);
uv__close(signal_pipe[1]);
@@ -588,7 +585,7 @@ int uv_spawn(uv_loop_t* loop,
uv__close_nocheckstdio(signal_pipe[0]);
for (i = 0; i < options->stdio_count; i++) {
- err = uv__process_open_stream(options->stdio + i, pipes[i], i == 0);
+ err = uv__process_open_stream(options->stdio + i, pipes[i]);
if (err == 0)
continue;
@@ -640,7 +637,7 @@ int uv_process_kill(uv_process_t* process, int signum) {
int uv_kill(int pid, int signum) {
if (kill(pid, signum))
- return -errno;
+ return UV__ERR(errno);
else
return 0;
}
diff --git a/Utilities/cmlibuv/src/unix/procfs-exepath.c b/Utilities/cmlibuv/src/unix/procfs-exepath.c
index 5fdb611..00dc021 100644
--- a/Utilities/cmlibuv/src/unix/procfs-exepath.c
+++ b/Utilities/cmlibuv/src/unix/procfs-exepath.c
@@ -29,14 +29,14 @@ int uv_exepath(char* buffer, size_t* size) {
ssize_t n;
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
n = *size - 1;
if (n > 0)
n = readlink("/proc/self/exe", buffer, n);
if (n == -1)
- return -errno;
+ return UV__ERR(errno);
buffer[n] = '\0';
*size = n;
diff --git a/Utilities/cmlibuv/src/unix/proctitle.c b/Utilities/cmlibuv/src/unix/proctitle.c
index 1b3a798..1a8c7a7 100644
--- a/Utilities/cmlibuv/src/unix/proctitle.c
+++ b/Utilities/cmlibuv/src/unix/proctitle.c
@@ -105,14 +105,14 @@ int uv_set_process_title(const char* title) {
int uv_get_process_title(char* buffer, size_t size) {
if (buffer == NULL || size == 0)
- return -EINVAL;
+ return UV_EINVAL;
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
uv_mutex_lock(&process_title_mutex);
if (size <= process_title.len) {
uv_mutex_unlock(&process_title_mutex);
- return -ENOBUFS;
+ return UV_ENOBUFS;
}
if (process_title.len != 0)
diff --git a/Utilities/cmlibuv/src/unix/signal.c b/Utilities/cmlibuv/src/unix/signal.c
index 3759778..b9d0a56 100644
--- a/Utilities/cmlibuv/src/unix/signal.c
+++ b/Utilities/cmlibuv/src/unix/signal.c
@@ -225,7 +225,7 @@ static int uv__signal_register_handler(int signum, int oneshot) {
/* XXX save old action so we can restore it later on? */
if (sigaction(signum, &sa, NULL))
- return -errno;
+ return UV__ERR(errno);
return 0;
}
@@ -362,7 +362,7 @@ static int uv__signal_start(uv_signal_t* handle,
* eventually.
*/
if (signum == 0)
- return -EINVAL;
+ 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.
diff --git a/Utilities/cmlibuv/src/unix/stream.c b/Utilities/cmlibuv/src/unix/stream.c
index 931e5f1..9bdd1c5 100644
--- a/Utilities/cmlibuv/src/unix/stream.c
+++ b/Utilities/cmlibuv/src/unix/stream.c
@@ -58,6 +58,12 @@ struct uv__stream_select_s {
fd_set* swrite;
size_t swrite_sz;
};
+# define WRITE_RETRY_ON_ERROR(send_handle) \
+ (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS || \
+ (errno == EMSGSIZE && send_handle))
+#else
+# define WRITE_RETRY_ON_ERROR(send_handle) \
+ (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
#endif /* defined(__APPLE__) */
static void uv__stream_connect(uv_stream_t*);
@@ -282,7 +288,7 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) {
kq = kqueue();
if (kq == -1) {
perror("(libuv) kqueue()");
- return -errno;
+ return UV__ERR(errno);
}
EV_SET(&filter[0], *fd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0);
@@ -298,7 +304,7 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) {
uv__close(kq);
if (ret == -1)
- return -errno;
+ return UV__ERR(errno);
if (ret == 0 || (events[0].flags & EV_ERROR) == 0 || events[0].data != EINVAL)
return 0;
@@ -310,7 +316,7 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) {
* NOTE: do it ahead of malloc below to allocate enough space for fd_sets
*/
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds))
- return -errno;
+ return UV__ERR(errno);
max_fd = *fd;
if (fds[1] > max_fd)
@@ -321,7 +327,7 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) {
s = uv__malloc(sizeof(*s) + sread_sz + swrite_sz);
if (s == NULL) {
- err = -ENOMEM;
+ err = UV_ENOMEM;
goto failed_malloc;
}
@@ -395,18 +401,18 @@ int uv__stream_open(uv_stream_t* stream, int fd, int flags) {
#endif
if (!(stream->io_watcher.fd == -1 || stream->io_watcher.fd == fd))
- return -EBUSY;
+ return UV_EBUSY;
assert(fd >= 0);
stream->flags |= flags;
if (stream->type == UV_TCP) {
if ((stream->flags & UV_TCP_NODELAY) && uv__tcp_nodelay(fd, 1))
- return -errno;
+ return UV__ERR(errno);
/* TODO Use delay the user passed in. */
if ((stream->flags & UV_TCP_KEEPALIVE) && uv__tcp_keepalive(fd, 1, 60))
- return -errno;
+ return UV__ERR(errno);
}
#if defined(__APPLE__)
@@ -414,7 +420,7 @@ int uv__stream_open(uv_stream_t* stream, int fd, int flags) {
if (setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, &enable, sizeof(enable)) &&
errno != ENOTSOCK &&
errno != EINVAL) {
- return -errno;
+ return UV__ERR(errno);
}
#endif
@@ -445,11 +451,11 @@ void uv__stream_destroy(uv_stream_t* stream) {
if (stream->connect_req) {
uv__req_unregister(stream->loop, stream->connect_req);
- stream->connect_req->cb(stream->connect_req, -ECANCELED);
+ stream->connect_req->cb(stream->connect_req, UV_ECANCELED);
stream->connect_req = NULL;
}
- uv__stream_flush_write_queue(stream, -ECANCELED);
+ uv__stream_flush_write_queue(stream, UV_ECANCELED);
uv__write_callbacks(stream);
if (stream->shutdown_req) {
@@ -459,7 +465,7 @@ void uv__stream_destroy(uv_stream_t* stream) {
* callee that the handle has been destroyed.
*/
uv__req_unregister(stream->loop, stream->shutdown_req);
- stream->shutdown_req->cb(stream->shutdown_req, -ECANCELED);
+ stream->shutdown_req->cb(stream->shutdown_req, UV_ECANCELED);
stream->shutdown_req = NULL;
}
@@ -483,7 +489,7 @@ static int uv__emfile_trick(uv_loop_t* loop, int accept_fd) {
int emfile_fd;
if (loop->emfile_fd == -1)
- return -EMFILE;
+ return UV_EMFILE;
uv__close(loop->emfile_fd);
loop->emfile_fd = -1;
@@ -492,7 +498,7 @@ static int uv__emfile_trick(uv_loop_t* loop, int accept_fd) {
err = uv__accept(accept_fd);
if (err >= 0)
uv__close(err);
- } while (err >= 0 || err == -EINTR);
+ } while (err >= 0 || err == UV_EINTR);
emfile_fd = uv__open_cloexec("/", O_RDONLY);
if (emfile_fd >= 0)
@@ -533,15 +539,15 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
err = uv__accept(uv__stream_fd(stream));
if (err < 0) {
- if (err == -EAGAIN || err == -EWOULDBLOCK)
+ if (err == UV_EAGAIN || err == UV__ERR(EWOULDBLOCK))
return; /* Not an error. */
- if (err == -ECONNABORTED)
+ if (err == UV_ECONNABORTED)
continue; /* Ignore. Nothing we can do about that. */
- if (err == -EMFILE || err == -ENFILE) {
+ if (err == UV_EMFILE || err == UV_ENFILE) {
err = uv__emfile_trick(loop, uv__stream_fd(stream));
- if (err == -EAGAIN || err == -EWOULDBLOCK)
+ if (err == UV_EAGAIN || err == UV__ERR(EWOULDBLOCK))
break;
}
@@ -577,7 +583,7 @@ int uv_accept(uv_stream_t* server, uv_stream_t* client) {
assert(server->loop == client->loop);
if (server->accepted_fd == -1)
- return -EAGAIN;
+ return UV_EAGAIN;
switch (client->type) {
case UV_NAMED_PIPE:
@@ -601,7 +607,7 @@ int uv_accept(uv_stream_t* server, uv_stream_t* client) {
break;
default:
- return -EINVAL;
+ return UV_EINVAL;
}
client->flags |= UV_HANDLE_BOUND;
@@ -649,7 +655,7 @@ int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) {
break;
default:
- err = -EINVAL;
+ err = UV_EINVAL;
}
if (err == 0)
@@ -680,7 +686,7 @@ static void uv__drain(uv_stream_t* stream) {
err = 0;
if (shutdown(uv__stream_fd(stream), SHUT_WR))
- err = -errno;
+ err = UV__ERR(errno);
if (err == 0)
stream->flags |= UV_STREAM_SHUT;
@@ -792,7 +798,7 @@ start:
} scratch;
if (uv__is_closing(req->send_handle)) {
- err = -EBADF;
+ err = UV_EBADF;
goto error;
}
@@ -859,8 +865,8 @@ start:
}
if (n < 0) {
- if (errno != EAGAIN && errno != EWOULDBLOCK && errno != ENOBUFS) {
- err = -errno;
+ if (!WRITE_RETRY_ON_ERROR(req->send_handle)) {
+ err = UV__ERR(errno);
goto error;
} else if (stream->flags & UV_STREAM_BLOCKING) {
/* If this is a blocking stream, try again. */
@@ -1029,7 +1035,7 @@ static int uv__stream_queue_fd(uv_stream_t* stream, int fd) {
queued_fds = uv__malloc((queue_size - 1) * sizeof(*queued_fds->fds) +
sizeof(*queued_fds));
if (queued_fds == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
queued_fds->size = queue_size;
queued_fds->offset = 0;
stream->queued_fds = queued_fds;
@@ -1046,7 +1052,7 @@ static int uv__stream_queue_fd(uv_stream_t* stream, int fd) {
* NOTE: if it is fatal - sockets will be closed in uv__stream_close
*/
if (queued_fds == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
queued_fds->size = queue_size;
stream->queued_fds = queued_fds;
}
@@ -1192,7 +1198,7 @@ static void uv__read(uv_stream_t* stream) {
#endif
} else {
/* Error. User should call uv_close(). */
- stream->read_cb(stream, -errno, &buf);
+ stream->read_cb(stream, UV__ERR(errno), &buf);
if (stream->flags & UV_STREAM_READING) {
stream->flags &= ~UV_STREAM_READING;
uv__io_stop(stream->loop, &stream->io_watcher, POLLIN);
@@ -1269,7 +1275,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) {
stream->flags & UV_STREAM_SHUT ||
stream->flags & UV_STREAM_SHUTTING ||
uv__is_closing(stream)) {
- return -ENOTCONN;
+ return UV_ENOTCONN;
}
assert(uv__stream_fd(stream) >= 0);
@@ -1368,10 +1374,10 @@ static void uv__stream_connect(uv_stream_t* stream) {
SO_ERROR,
&error,
&errorsize);
- error = -error;
+ error = UV__ERR(error);
}
- if (error == -EINPROGRESS)
+ if (error == UV__ERR(EINPROGRESS))
return;
stream->connect_req = NULL;
@@ -1388,7 +1394,7 @@ static void uv__stream_connect(uv_stream_t* stream) {
return;
if (error < 0) {
- uv__stream_flush_write_queue(stream, -ECANCELED);
+ uv__stream_flush_write_queue(stream, UV_ECANCELED);
uv__write_callbacks(stream);
}
}
@@ -1409,11 +1415,14 @@ int uv_write2(uv_write_t* req,
"uv_write (unix) does not yet support other types of streams");
if (uv__stream_fd(stream) < 0)
- return -EBADF;
+ return UV_EBADF;
+
+ if (!(stream->flags & UV_STREAM_WRITABLE))
+ return -EPIPE;
if (send_handle) {
if (stream->type != UV_NAMED_PIPE || !((uv_pipe_t*)stream)->ipc)
- return -EINVAL;
+ return UV_EINVAL;
/* XXX We abuse uv_write2() to send over UDP handles to child processes.
* Don't call uv__stream_fd() on those handles, it's a macro that on OS X
@@ -1422,12 +1431,12 @@ int uv_write2(uv_write_t* req,
* which works but only by accident.
*/
if (uv__handle_fd((uv_handle_t*) send_handle) < 0)
- return -EBADF;
+ return UV_EBADF;
#if defined(__CYGWIN__) || defined(__MSYS__)
/* Cygwin recvmsg always sets msg_controllen to zero, so we cannot send it.
See https://github.com/mirror/newlib-cygwin/blob/86fc4bf0/winsup/cygwin/fhandler_socket.cc#L1736-L1743 */
- return -ENOSYS;
+ return UV_ENOSYS;
#endif
}
@@ -1452,7 +1461,7 @@ int uv_write2(uv_write_t* req,
req->bufs = uv__malloc(nbufs * sizeof(bufs[0]));
if (req->bufs == NULL)
- return -ENOMEM;
+ return UV_ENOMEM;
memcpy(req->bufs, bufs, nbufs * sizeof(bufs[0]));
req->nbufs = nbufs;
@@ -1516,7 +1525,7 @@ int uv_try_write(uv_stream_t* stream,
/* Connecting or already writing some data */
if (stream->connect_req != NULL || stream->write_queue_size != 0)
- return -EAGAIN;
+ return UV_EAGAIN;
has_pollout = uv__io_active(&stream->io_watcher, POLLOUT);
@@ -1547,7 +1556,7 @@ int uv_try_write(uv_stream_t* stream,
}
if (written == 0 && req_size != 0)
- return -EAGAIN;
+ return UV_EAGAIN;
else
return written;
}
@@ -1560,7 +1569,10 @@ int uv_read_start(uv_stream_t* stream,
stream->type == UV_TTY);
if (stream->flags & UV_CLOSING)
- return -EINVAL;
+ return UV_EINVAL;
+
+ if (!(stream->flags & UV_STREAM_READABLE))
+ return -ENOTCONN;
/* The UV_STREAM_READING flag is irrelevant of the state of the tcp - it just
* expresses the desired state of the user.
diff --git a/Utilities/cmlibuv/src/unix/sunos.c b/Utilities/cmlibuv/src/unix/sunos.c
index d6f9527..b92888e 100644
--- a/Utilities/cmlibuv/src/unix/sunos.c
+++ b/Utilities/cmlibuv/src/unix/sunos.c
@@ -77,7 +77,7 @@ int uv__platform_loop_init(uv_loop_t* loop) {
fd = port_create();
if (fd == -1)
- return -errno;
+ return UV__ERR(errno);
err = uv__cloexec(fd, 1);
if (err) {
@@ -136,7 +136,7 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
int uv__io_check_fd(uv_loop_t* loop, int fd) {
if (port_associate(loop->backend_fd, PORT_SOURCE_FD, fd, POLLIN, 0))
- return -errno;
+ return UV__ERR(errno);
if (port_dissociate(loop->backend_fd, PORT_SOURCE_FD, fd))
abort();
@@ -346,7 +346,7 @@ int uv_exepath(char* buffer, size_t* size) {
char buf[128];
if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
+ return UV_EINVAL;
snprintf(buf, sizeof(buf), "/proc/%lu/path/a.out", (unsigned long) getpid());
@@ -355,7 +355,7 @@ int uv_exepath(char* buffer, size_t* size) {
res = readlink(buf, buffer, res);
if (res == -1)
- return -errno;
+ return UV__ERR(errno);
buffer[res] = '\0';
*size = res;
@@ -382,14 +382,14 @@ void uv_loadavg(double avg[3]) {
static int uv__fs_event_rearm(uv_fs_event_t *handle) {
if (handle->fd == -1)
- return -EBADF;
+ return UV_EBADF;
if (port_associate(handle->loop->fs_fd,
PORT_SOURCE_FILE,
(uintptr_t) &handle->fo,
FILE_ATTRIB | FILE_MODIFIED,
handle) == -1) {
- return -errno;
+ return UV__ERR(errno);
}
handle->fd = PORT_LOADED;
@@ -466,13 +466,13 @@ int uv_fs_event_start(uv_fs_event_t* handle,
int err;
if (uv__is_active(handle))
- return -EINVAL;
+ return UV_EINVAL;
first_run = 0;
if (handle->loop->fs_fd == -1) {
portfd = port_create();
if (portfd == -1)
- return -errno;
+ return UV__ERR(errno);
handle->loop->fs_fd = portfd;
first_run = 1;
}
@@ -525,7 +525,7 @@ void uv__fs_event_close(uv_fs_event_t* handle) {
#else /* !defined(PORT_SOURCE_FILE) */
int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
- return -ENOSYS;
+ return UV_ENOSYS;
}
@@ -533,12 +533,12 @@ int uv_fs_event_start(uv_fs_event_t* handle,
uv_fs_event_cb cb,
const char* filename,
unsigned int flags) {
- return -ENOSYS;
+ return UV_ENOSYS;
}
int uv_fs_event_stop(uv_fs_event_t* handle) {
- return -ENOSYS;
+ return UV_ENOSYS;
}
@@ -556,10 +556,10 @@ int uv_resident_set_memory(size_t* rss) {
fd = open("/proc/self/psinfo", O_RDONLY);
if (fd == -1)
- return -errno;
+ return UV__ERR(errno);
/* FIXME(bnoordhuis) Handle EINTR. */
- err = -EINVAL;
+ err = UV_EINVAL;
if (read(fd, &psinfo, sizeof(psinfo)) == sizeof(psinfo)) {
*rss = (size_t)psinfo.pr_rssize * 1024;
err = 0;
@@ -579,7 +579,7 @@ int uv_uptime(double* uptime) {
kc = kstat_open();
if (kc == NULL)
- return -EPERM;
+ return UV_EPERM;
ksp = kstat_lookup(kc, (char*) "unix", 0, (char*) "system_misc");
if (kstat_read(kc, ksp, NULL) == -1) {
@@ -603,7 +603,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
kc = kstat_open();
if (kc == NULL)
- return -EPERM;
+ return UV_EPERM;
/* Get count of cpus */
lookup_instance = 0;
@@ -614,7 +614,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
*cpu_infos = uv__malloc(lookup_instance * sizeof(**cpu_infos));
if (!(*cpu_infos)) {
kstat_close(kc);
- return -ENOMEM;
+ return UV_ENOMEM;
}
*count = lookup_instance;
@@ -696,7 +696,7 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
#ifdef SUNOS_NO_IFADDRS
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
- return -ENOSYS;
+ return UV_ENOSYS;
}
#else /* SUNOS_NO_IFADDRS */
/*
@@ -734,11 +734,11 @@ static int uv__set_phys_addr(uv_interface_address_t* address,
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
- return -errno;
+ return UV__ERR(errno);
if (ioctl(sockfd, SIOCGARP, (char*)&arpreq) == -1) {
uv__close(sockfd);
- return -errno;
+ return UV__ERR(errno);
}
memcpy(address->phys_addr, arpreq.arp_ha.sa_data, sizeof(address->phys_addr));
uv__close(sockfd);
@@ -763,7 +763,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
struct ifaddrs* ent;
if (getifaddrs(&addrs))
- return -errno;
+ return UV__ERR(errno);
*count = 0;
@@ -777,7 +777,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
*addresses = uv__malloc(*count * sizeof(**addresses));
if (!(*addresses)) {
freeifaddrs(addrs);
- return -ENOMEM;
+ return UV_ENOMEM;
}
address = *addresses;
diff --git a/Utilities/cmlibuv/src/unix/tcp.c b/Utilities/cmlibuv/src/unix/tcp.c
index c7c8d21..9a46793 100644
--- a/Utilities/cmlibuv/src/unix/tcp.c
+++ b/Utilities/cmlibuv/src/unix/tcp.c
@@ -49,16 +49,14 @@ static int new_socket(uv_tcp_t* handle, int domain, unsigned long flags) {
/* Bind this new socket to an arbitrary port */
slen = sizeof(saddr);
memset(&saddr, 0, sizeof(saddr));
- err = getsockname(uv__stream_fd(handle), (struct sockaddr*) &saddr, &slen);
- if (err) {
+ if (getsockname(uv__stream_fd(handle), (struct sockaddr*) &saddr, &slen)) {
uv__close(sockfd);
- return err;
+ return UV__ERR(errno);
}
- err = bind(uv__stream_fd(handle), (struct sockaddr*) &saddr, slen);
- if (err) {
+ if (bind(uv__stream_fd(handle), (struct sockaddr*) &saddr, slen)) {
uv__close(sockfd);
- return err;
+ return UV__ERR(errno);
}
}
@@ -89,7 +87,7 @@ static int maybe_new_socket(uv_tcp_t* handle, int domain, unsigned long flags) {
slen = sizeof(saddr);
memset(&saddr, 0, sizeof(saddr));
if (getsockname(uv__stream_fd(handle), (struct sockaddr*) &saddr, &slen))
- return -errno;
+ return UV__ERR(errno);
if ((saddr.ss_family == AF_INET6 &&
((struct sockaddr_in6*) &saddr)->sin6_port != 0) ||
@@ -102,7 +100,7 @@ static int maybe_new_socket(uv_tcp_t* handle, int domain, unsigned long flags) {
/* Bind to arbitrary port */
if (bind(uv__stream_fd(handle), (struct sockaddr*) &saddr, slen))
- return -errno;
+ return UV__ERR(errno);
}
handle->flags |= flags;
@@ -119,10 +117,10 @@ int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* tcp, unsigned int flags) {
/* Use the lower 8 bits for the domain */
domain = flags & 0xFF;
if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC)
- return -EINVAL;
+ return UV_EINVAL;
if (flags & ~0xFF)
- return -EINVAL;
+ return UV_EINVAL;
uv__stream_init(loop, (uv_stream_t*)tcp, UV_TCP);
@@ -156,18 +154,17 @@ int uv__tcp_bind(uv_tcp_t* tcp,
/* Cannot set IPv6-only mode on non-IPv6 socket. */
if ((flags & UV_TCP_IPV6ONLY) && addr->sa_family != AF_INET6)
- return -EINVAL;
+ return UV_EINVAL;
- err = maybe_new_socket(tcp,
- addr->sa_family,
- UV_STREAM_READABLE | UV_STREAM_WRITABLE);
+ err = maybe_new_socket(tcp, addr->sa_family, 0);
if (err)
return err;
on = 1;
if (setsockopt(tcp->io_watcher.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
- return -errno;
+ return UV__ERR(errno);
+#ifndef __OpenBSD__
#ifdef IPV6_V6ONLY
if (addr->sa_family == AF_INET6) {
on = (flags & UV_TCP_IPV6ONLY) != 0;
@@ -178,22 +175,23 @@ int uv__tcp_bind(uv_tcp_t* tcp,
sizeof on) == -1) {
#if defined(__MVS__)
if (errno == EOPNOTSUPP)
- return -EINVAL;
+ return UV_EINVAL;
#endif
- return -errno;
+ return UV__ERR(errno);
}
}
#endif
+#endif
errno = 0;
if (bind(tcp->io_watcher.fd, addr, addrlen) && errno != EADDRINUSE) {
if (errno == EAFNOSUPPORT)
/* OSX, other BSDs and SunoS fail with EAFNOSUPPORT when binding a
* socket created with AF_INET to an AF_INET6 address or vice versa. */
- return -EINVAL;
- return -errno;
+ return UV_EINVAL;
+ return UV__ERR(errno);
}
- tcp->delayed_error = -errno;
+ tcp->delayed_error = UV__ERR(errno);
tcp->flags |= UV_HANDLE_BOUND;
if (addr->sa_family == AF_INET6)
@@ -214,7 +212,7 @@ int uv__tcp_connect(uv_connect_t* req,
assert(handle->type == UV_TCP);
if (handle->connect_req != NULL)
- return -EALREADY; /* FIXME(bnoordhuis) -EINVAL or maybe -EBUSY. */
+ return UV_EALREADY; /* FIXME(bnoordhuis) UV_EINVAL or maybe UV_EBUSY. */
err = maybe_new_socket(handle,
addr->sa_family,
@@ -242,9 +240,9 @@ int uv__tcp_connect(uv_connect_t* req,
* error. Solaris wants to report immediately--other unixes want to
* wait.
*/
- handle->delayed_error = -errno;
+ handle->delayed_error = UV__ERR(errno);
else
- return -errno;
+ return UV__ERR(errno);
}
uv__req_init(handle->loop, req, UV_CONNECT);
@@ -284,13 +282,13 @@ int uv_tcp_getsockname(const uv_tcp_t* handle,
return handle->delayed_error;
if (uv__stream_fd(handle) < 0)
- return -EINVAL; /* FIXME(bnoordhuis) -EBADF */
+ return UV_EINVAL; /* FIXME(bnoordhuis) UV_EBADF */
/* sizeof(socklen_t) != sizeof(int) on some systems. */
socklen = (socklen_t) *namelen;
if (getsockname(uv__stream_fd(handle), name, &socklen))
- return -errno;
+ return UV__ERR(errno);
*namelen = (int) socklen;
return 0;
@@ -306,13 +304,13 @@ int uv_tcp_getpeername(const uv_tcp_t* handle,
return handle->delayed_error;
if (uv__stream_fd(handle) < 0)
- return -EINVAL; /* FIXME(bnoordhuis) -EBADF */
+ return UV_EINVAL; /* FIXME(bnoordhuis) UV_EBADF */
/* sizeof(socklen_t) != sizeof(int) on some systems. */
socklen = (socklen_t) *namelen;
if (getpeername(uv__stream_fd(handle), name, &socklen))
- return -errno;
+ return UV__ERR(errno);
*namelen = (int) socklen;
return 0;
@@ -335,20 +333,20 @@ int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
if (single_accept)
tcp->flags |= UV_TCP_SINGLE_ACCEPT;
- flags = UV_STREAM_READABLE;
+ flags = 0;
#if defined(__MVS__)
/* on zOS the listen call does not bind automatically
if the socket is unbound. Hence the manual binding to
an arbitrary port is required to be done manually
*/
flags |= UV_HANDLE_BOUND;
-#endif
+#endif
err = maybe_new_socket(tcp, AF_INET, flags);
if (err)
return err;
if (listen(tcp->io_watcher.fd, backlog))
- return -errno;
+ return UV__ERR(errno);
tcp->connection_cb = cb;
tcp->flags |= UV_HANDLE_BOUND;
@@ -363,18 +361,18 @@ int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
int uv__tcp_nodelay(int fd, int on) {
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)))
- return -errno;
+ return UV__ERR(errno);
return 0;
}
int uv__tcp_keepalive(int fd, int on, unsigned int delay) {
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)))
- return -errno;
+ return UV__ERR(errno);
#ifdef TCP_KEEPIDLE
if (on && setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &delay, sizeof(delay)))
- return -errno;
+ return UV__ERR(errno);
#endif
/* Solaris/SmartOS, if you don't support keep-alive,
@@ -383,7 +381,7 @@ int uv__tcp_keepalive(int fd, int on, unsigned int delay) {
/* FIXME(bnoordhuis) That's possibly because sizeof(delay) should be 1. */
#if defined(TCP_KEEPALIVE) && !defined(__sun)
if (on && setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &delay, sizeof(delay)))
- return -errno;
+ return UV__ERR(errno);
#endif
return 0;
diff --git a/Utilities/cmlibuv/src/unix/thread.c b/Utilities/cmlibuv/src/unix/thread.c
index abaca29..303bc6e 100644
--- a/Utilities/cmlibuv/src/unix/thread.c
+++ b/Utilities/cmlibuv/src/unix/thread.c
@@ -37,6 +37,10 @@
#include <sys/sem.h>
#endif
+#ifdef __GLIBC__
+#include <gnu/libc-version.h> /* gnu_get_libc_version() */
+#endif
+
#undef NANOSEC
#define NANOSEC ((uint64_t) 1e9)
@@ -200,7 +204,7 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
if (attr != NULL)
pthread_attr_destroy(attr);
- return -err;
+ return UV__ERR(err);
}
@@ -209,7 +213,7 @@ uv_thread_t uv_thread_self(void) {
}
int uv_thread_join(uv_thread_t *tid) {
- return -pthread_join(*tid, NULL);
+ return UV__ERR(pthread_join(*tid, NULL));
}
@@ -220,7 +224,7 @@ int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) {
int uv_mutex_init(uv_mutex_t* mutex) {
#if defined(NDEBUG) || !defined(PTHREAD_MUTEX_ERRORCHECK)
- return -pthread_mutex_init(mutex, NULL);
+ return UV__ERR(pthread_mutex_init(mutex, NULL));
#else
pthread_mutexattr_t attr;
int err;
@@ -236,7 +240,7 @@ int uv_mutex_init(uv_mutex_t* mutex) {
if (pthread_mutexattr_destroy(&attr))
abort();
- return -err;
+ return UV__ERR(err);
#endif
}
@@ -256,7 +260,7 @@ int uv_mutex_init_recursive(uv_mutex_t* mutex) {
if (pthread_mutexattr_destroy(&attr))
abort();
- return -err;
+ return UV__ERR(err);
}
@@ -279,7 +283,7 @@ int uv_mutex_trylock(uv_mutex_t* mutex) {
if (err) {
if (err != EBUSY && err != EAGAIN)
abort();
- return -EBUSY;
+ return UV_EBUSY;
}
return 0;
@@ -293,7 +297,7 @@ void uv_mutex_unlock(uv_mutex_t* mutex) {
int uv_rwlock_init(uv_rwlock_t* rwlock) {
- return -pthread_rwlock_init(rwlock, NULL);
+ return UV__ERR(pthread_rwlock_init(rwlock, NULL));
}
@@ -316,7 +320,7 @@ int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock) {
if (err) {
if (err != EBUSY && err != EAGAIN)
abort();
- return -EBUSY;
+ return UV_EBUSY;
}
return 0;
@@ -342,7 +346,7 @@ int uv_rwlock_trywrlock(uv_rwlock_t* rwlock) {
if (err) {
if (err != EBUSY && err != EAGAIN)
abort();
- return -EBUSY;
+ return UV_EBUSY;
}
return 0;
@@ -369,12 +373,12 @@ int uv_sem_init(uv_sem_t* sem, unsigned int value) {
if (err == KERN_SUCCESS)
return 0;
if (err == KERN_INVALID_ARGUMENT)
- return -EINVAL;
+ return UV_EINVAL;
if (err == KERN_RESOURCE_SHORTAGE)
- return -ENOMEM;
+ return UV_ENOMEM;
abort();
- return -EINVAL; /* Satisfy the compiler. */
+ return UV_EINVAL; /* Satisfy the compiler. */
}
@@ -413,115 +417,151 @@ int uv_sem_trywait(uv_sem_t* sem) {
if (err == KERN_SUCCESS)
return 0;
if (err == KERN_OPERATION_TIMED_OUT)
- return -EAGAIN;
+ return UV_EAGAIN;
abort();
- return -EINVAL; /* Satisfy the compiler. */
+ return UV_EINVAL; /* Satisfy the compiler. */
+}
+
+#else /* !(defined(__APPLE__) && defined(__MACH__)) */
+
+#ifdef __GLIBC__
+
+/* Hack around https://sourceware.org/bugzilla/show_bug.cgi?id=12674
+ * by providing a custom implementation for glibc < 2.21 in terms of other
+ * concurrency primitives.
+ * Refs: https://github.com/nodejs/node/issues/19903 */
+
+/* To preserve ABI compatibility, we treat the uv_sem_t as storage for
+ * a pointer to the actual struct we're using underneath. */
+
+static uv_once_t glibc_version_check_once = UV_ONCE_INIT;
+static int platform_needs_custom_semaphore = 0;
+
+static void glibc_version_check(void) {
+ const char* version = gnu_get_libc_version();
+ platform_needs_custom_semaphore =
+ version[0] == '2' && version[1] == '.' &&
+ atoi(version + 2) < 21;
}
#elif defined(__MVS__)
-int uv_sem_init(uv_sem_t* sem, unsigned int value) {
- uv_sem_t semid;
+#define platform_needs_custom_semaphore 1
+
+#else /* !defined(__GLIBC__) && !defined(__MVS__) */
+
+#define platform_needs_custom_semaphore 0
+
+#endif
+
+typedef struct uv_semaphore_s {
+ uv_mutex_t mutex;
+ uv_cond_t cond;
+ unsigned int value;
+} uv_semaphore_t;
+
+#if defined(__GLIBC__) || platform_needs_custom_semaphore
+STATIC_ASSERT(sizeof(uv_sem_t) >= sizeof(uv_semaphore_t*));
+#endif
+
+static int uv__custom_sem_init(uv_sem_t* sem_, unsigned int value) {
int err;
- union {
- int val;
- struct semid_ds* buf;
- unsigned short* array;
- } arg;
+ uv_semaphore_t* sem;
+ sem = uv__malloc(sizeof(*sem));
+ if (sem == NULL)
+ return UV_ENOMEM;
- semid = semget(IPC_PRIVATE, 1, S_IRUSR | S_IWUSR);
- if (semid == -1)
- return -errno;
+ if ((err = uv_mutex_init(&sem->mutex)) != 0) {
+ uv__free(sem);
+ return err;
+ }
- arg.val = value;
- if (-1 == semctl(semid, 0, SETVAL, arg)) {
- err = errno;
- if (-1 == semctl(*sem, 0, IPC_RMID))
- abort();
- return -err;
+ if ((err = uv_cond_init(&sem->cond)) != 0) {
+ uv_mutex_destroy(&sem->mutex);
+ uv__free(sem);
+ return err;
}
- *sem = semid;
+ sem->value = value;
+ *(uv_semaphore_t**)sem_ = sem;
return 0;
}
-void uv_sem_destroy(uv_sem_t* sem) {
- if (-1 == semctl(*sem, 0, IPC_RMID))
- abort();
+
+static void uv__custom_sem_destroy(uv_sem_t* sem_) {
+ uv_semaphore_t* sem;
+
+ sem = *(uv_semaphore_t**)sem_;
+ uv_cond_destroy(&sem->cond);
+ uv_mutex_destroy(&sem->mutex);
+ uv__free(sem);
}
-void uv_sem_post(uv_sem_t* sem) {
- struct sembuf buf;
- buf.sem_num = 0;
- buf.sem_op = 1;
- buf.sem_flg = 0;
+static void uv__custom_sem_post(uv_sem_t* sem_) {
+ uv_semaphore_t* sem;
- if (-1 == semop(*sem, &buf, 1))
- abort();
+ sem = *(uv_semaphore_t**)sem_;
+ uv_mutex_lock(&sem->mutex);
+ sem->value++;
+ if (sem->value == 1)
+ uv_cond_signal(&sem->cond);
+ uv_mutex_unlock(&sem->mutex);
}
-void uv_sem_wait(uv_sem_t* sem) {
- struct sembuf buf;
- int op_status;
-
- buf.sem_num = 0;
- buf.sem_op = -1;
- buf.sem_flg = 0;
- do
- op_status = semop(*sem, &buf, 1);
- while (op_status == -1 && errno == EINTR);
+static void uv__custom_sem_wait(uv_sem_t* sem_) {
+ uv_semaphore_t* sem;
- if (op_status)
- abort();
+ sem = *(uv_semaphore_t**)sem_;
+ uv_mutex_lock(&sem->mutex);
+ while (sem->value == 0)
+ uv_cond_wait(&sem->cond, &sem->mutex);
+ sem->value--;
+ uv_mutex_unlock(&sem->mutex);
}
-int uv_sem_trywait(uv_sem_t* sem) {
- struct sembuf buf;
- int op_status;
- buf.sem_num = 0;
- buf.sem_op = -1;
- buf.sem_flg = IPC_NOWAIT;
+static int uv__custom_sem_trywait(uv_sem_t* sem_) {
+ uv_semaphore_t* sem;
- do
- op_status = semop(*sem, &buf, 1);
- while (op_status == -1 && errno == EINTR);
+ sem = *(uv_semaphore_t**)sem_;
+ if (uv_mutex_trylock(&sem->mutex) != 0)
+ return UV_EAGAIN;
- if (op_status) {
- if (errno == EAGAIN)
- return -EAGAIN;
- abort();
+ if (sem->value == 0) {
+ uv_mutex_unlock(&sem->mutex);
+ return UV_EAGAIN;
}
+ sem->value--;
+ uv_mutex_unlock(&sem->mutex);
+
return 0;
}
-#else /* !(defined(__APPLE__) && defined(__MACH__)) */
-
-int uv_sem_init(uv_sem_t* sem, unsigned int value) {
+static int uv__sem_init(uv_sem_t* sem, unsigned int value) {
if (sem_init(sem, 0, value))
- return -errno;
+ return UV__ERR(errno);
return 0;
}
-void uv_sem_destroy(uv_sem_t* sem) {
+static void uv__sem_destroy(uv_sem_t* sem) {
if (sem_destroy(sem))
abort();
}
-void uv_sem_post(uv_sem_t* sem) {
+static void uv__sem_post(uv_sem_t* sem) {
if (sem_post(sem))
abort();
}
-void uv_sem_wait(uv_sem_t* sem) {
+static void uv__sem_wait(uv_sem_t* sem) {
int r;
do
@@ -533,7 +573,7 @@ void uv_sem_wait(uv_sem_t* sem) {
}
-int uv_sem_trywait(uv_sem_t* sem) {
+static int uv__sem_trywait(uv_sem_t* sem) {
int r;
do
@@ -542,20 +582,63 @@ int uv_sem_trywait(uv_sem_t* sem) {
if (r) {
if (errno == EAGAIN)
- return -EAGAIN;
+ return UV_EAGAIN;
abort();
}
return 0;
}
+int uv_sem_init(uv_sem_t* sem, unsigned int value) {
+#ifdef __GLIBC__
+ uv_once(&glibc_version_check_once, glibc_version_check);
+#endif
+
+ if (platform_needs_custom_semaphore)
+ return uv__custom_sem_init(sem, value);
+ else
+ return uv__sem_init(sem, value);
+}
+
+
+void uv_sem_destroy(uv_sem_t* sem) {
+ if (platform_needs_custom_semaphore)
+ uv__custom_sem_destroy(sem);
+ else
+ uv__sem_destroy(sem);
+}
+
+
+void uv_sem_post(uv_sem_t* sem) {
+ if (platform_needs_custom_semaphore)
+ uv__custom_sem_post(sem);
+ else
+ uv__sem_post(sem);
+}
+
+
+void uv_sem_wait(uv_sem_t* sem) {
+ if (platform_needs_custom_semaphore)
+ uv__custom_sem_wait(sem);
+ else
+ uv__sem_wait(sem);
+}
+
+
+int uv_sem_trywait(uv_sem_t* sem) {
+ if (platform_needs_custom_semaphore)
+ return uv__custom_sem_trywait(sem);
+ else
+ return uv__sem_trywait(sem);
+}
+
#endif /* defined(__APPLE__) && defined(__MACH__) */
#if defined(__APPLE__) && defined(__MACH__) || defined(__MVS__)
int uv_cond_init(uv_cond_t* cond) {
- return -pthread_cond_init(cond, NULL);
+ return UV__ERR(pthread_cond_init(cond, NULL));
}
#else /* !(defined(__APPLE__) && defined(__MACH__)) */
@@ -566,7 +649,7 @@ int uv_cond_init(uv_cond_t* cond) {
err = pthread_condattr_init(&attr);
if (err)
- return -err;
+ return UV__ERR(err);
#if !(defined(__ANDROID_API__) && __ANDROID_API__ < 21)
err = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
@@ -588,7 +671,7 @@ error:
pthread_cond_destroy(cond);
error2:
pthread_condattr_destroy(&attr);
- return -err;
+ return UV__ERR(err);
}
#endif /* defined(__APPLE__) && defined(__MACH__) */
@@ -646,13 +729,22 @@ void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) {
int r;
struct timespec ts;
+#if defined(__MVS__)
+ struct timeval tv;
+#endif
#if defined(__APPLE__) && defined(__MACH__)
ts.tv_sec = timeout / NANOSEC;
ts.tv_nsec = timeout % NANOSEC;
r = pthread_cond_timedwait_relative_np(cond, mutex, &ts);
#else
+#if defined(__MVS__)
+ if (gettimeofday(&tv, NULL))
+ abort();
+ timeout += tv.tv_sec * NANOSEC + tv.tv_usec * 1e3;
+#else
timeout += uv__hrtime(UV_CLOCK_PRECISE);
+#endif
ts.tv_sec = timeout / NANOSEC;
ts.tv_nsec = timeout % NANOSEC;
#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
@@ -672,15 +764,15 @@ int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) {
return 0;
if (r == ETIMEDOUT)
- return -ETIMEDOUT;
+ return UV_ETIMEDOUT;
abort();
- return -EINVAL; /* Satisfy the compiler. */
+ return UV_EINVAL; /* Satisfy the compiler. */
}
int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
- return -pthread_barrier_init(barrier, NULL, count);
+ return UV__ERR(pthread_barrier_init(barrier, NULL, count));
}
@@ -699,7 +791,7 @@ int uv_barrier_wait(uv_barrier_t* barrier) {
int uv_key_create(uv_key_t* key) {
- return -pthread_key_create(key, NULL);
+ return UV__ERR(pthread_key_create(key, NULL));
}
diff --git a/Utilities/cmlibuv/src/unix/timer.c b/Utilities/cmlibuv/src/unix/timer.c
index f46bdf4..54dabfe 100644
--- a/Utilities/cmlibuv/src/unix/timer.c
+++ b/Utilities/cmlibuv/src/unix/timer.c
@@ -66,7 +66,7 @@ int uv_timer_start(uv_timer_t* handle,
uint64_t clamped_timeout;
if (cb == NULL)
- return -EINVAL;
+ return UV_EINVAL;
if (uv__is_active(handle))
uv_timer_stop(handle);
@@ -105,7 +105,7 @@ int uv_timer_stop(uv_timer_t* handle) {
int uv_timer_again(uv_timer_t* handle) {
if (handle->timer_cb == NULL)
- return -EINVAL;
+ return UV_EINVAL;
if (handle->repeat) {
uv_timer_stop(handle);
diff --git a/Utilities/cmlibuv/src/unix/tty.c b/Utilities/cmlibuv/src/unix/tty.c
index fc8c3ab..e8ea302 100644
--- a/Utilities/cmlibuv/src/unix/tty.c
+++ b/Utilities/cmlibuv/src/unix/tty.c
@@ -106,7 +106,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) {
*/
type = uv_guess_handle(fd);
if (type == UV_FILE || type == UV_UNKNOWN_HANDLE)
- return -EINVAL;
+ return UV_EINVAL;
/* Reopen the file descriptor when it refers to a tty. This lets us put the
* tty in non-blocking mode without affecting other processes that share it
@@ -139,7 +139,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) {
newfd = r;
r = uv__dup2_cloexec(newfd, fd);
- if (r < 0 && r != -EINVAL) {
+ if (r < 0 && r != UV_EINVAL) {
/* EINVAL means newfd == fd which could conceivably happen if another
* thread called close(fd) between our calls to isatty() and open().
* That's a rather unlikely event but let's handle it anyway.
@@ -160,7 +160,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) {
if (saved_flags == -1) {
if (newfd != -1)
uv__close(newfd);
- return -errno;
+ return UV__ERR(errno);
}
#endif
@@ -231,7 +231,7 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
fd = uv__stream_fd(tty);
if (tty->mode == UV_TTY_MODE_NORMAL && mode != UV_TTY_MODE_NORMAL) {
if (tcgetattr(fd, &tty->orig_termios))
- return -errno;
+ return UV__ERR(errno);
/* This is used for uv_tty_reset_mode() */
uv_spinlock_lock(&termios_spinlock);
@@ -261,7 +261,7 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
/* Apply changes after draining */
if (tcsetattr(fd, TCSADRAIN, &tmp))
- return -errno;
+ return UV__ERR(errno);
tty->mode = mode;
return 0;
@@ -277,7 +277,7 @@ int uv_tty_get_winsize(uv_tty_t* tty, int* width, int* height) {
while (err == -1 && errno == EINTR);
if (err == -1)
- return -errno;
+ return UV__ERR(errno);
*width = ws.ws_col;
*height = ws.ws_row;
@@ -355,12 +355,12 @@ int uv_tty_reset_mode(void) {
saved_errno = errno;
if (!uv_spinlock_trylock(&termios_spinlock))
- return -EBUSY; /* In uv_tty_set_mode(). */
+ return UV_EBUSY; /* In uv_tty_set_mode(). */
err = 0;
if (orig_termios_fd != -1)
if (tcsetattr(orig_termios_fd, TCSANOW, &orig_termios))
- err = -errno;
+ err = UV__ERR(errno);
uv_spinlock_unlock(&termios_spinlock);
errno = saved_errno;
diff --git a/Utilities/cmlibuv/src/unix/udp.c b/Utilities/cmlibuv/src/unix/udp.c
index a475bf5..74d613b 100644
--- a/Utilities/cmlibuv/src/unix/udp.c
+++ b/Utilities/cmlibuv/src/unix/udp.c
@@ -72,7 +72,7 @@ void uv__udp_finish_close(uv_udp_t* handle) {
QUEUE_REMOVE(q);
req = QUEUE_DATA(q, uv_udp_send_t, queue);
- req->status = -ECANCELED;
+ req->status = UV_ECANCELED;
QUEUE_INSERT_TAIL(&handle->write_completed_queue, &req->queue);
}
@@ -189,7 +189,7 @@ static void uv__udp_recvmsg(uv_udp_t* handle) {
if (errno == EAGAIN || errno == EWOULDBLOCK)
handle->recv_cb(handle, 0, &buf, NULL, 0);
else
- handle->recv_cb(handle, -errno, &buf, NULL, 0);
+ handle->recv_cb(handle, UV__ERR(errno), &buf, NULL, 0);
}
else {
const struct sockaddr *addr;
@@ -242,7 +242,7 @@ static void uv__udp_sendmsg(uv_udp_t* handle) {
break;
}
- req->status = (size == -1 ? -errno : size);
+ req->status = (size == -1 ? UV__ERR(errno) : size);
/* Sending a datagram is an atomic operation: either all data
* is written or nothing is (and EMSGSIZE is raised). That is
@@ -270,11 +270,11 @@ static int uv__set_reuse(int fd) {
#if defined(SO_REUSEPORT) && !defined(__linux__)
yes = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes)))
- return -errno;
+ return UV__ERR(errno);
#else
yes = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)))
- return -errno;
+ return UV__ERR(errno);
#endif
return 0;
@@ -291,11 +291,11 @@ int uv__udp_bind(uv_udp_t* handle,
/* Check for bad flags. */
if (flags & ~(UV_UDP_IPV6ONLY | UV_UDP_REUSEADDR))
- return -EINVAL;
+ return UV_EINVAL;
/* Cannot set IPv6-only mode on non-IPv6 socket. */
if ((flags & UV_UDP_IPV6ONLY) && addr->sa_family != AF_INET6)
- return -EINVAL;
+ return UV_EINVAL;
fd = handle->io_watcher.fd;
if (fd == -1) {
@@ -316,21 +316,21 @@ int uv__udp_bind(uv_udp_t* handle,
#ifdef IPV6_V6ONLY
yes = 1;
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof yes) == -1) {
- err = -errno;
+ err = UV__ERR(errno);
return err;
}
#else
- err = -ENOTSUP;
+ err = UV_ENOTSUP;
return err;
#endif
}
if (bind(fd, addr, addrlen)) {
- err = -errno;
+ err = UV__ERR(errno);
if (errno == EAFNOSUPPORT)
/* OSX, other BSDs and SunoS fail with EAFNOSUPPORT when binding a
* socket created with AF_INET to an AF_INET6 address or vice versa. */
- err = -EINVAL;
+ err = UV_EINVAL;
return err;
}
@@ -418,7 +418,7 @@ int uv__udp_send(uv_udp_send_t* req,
if (req->bufs == NULL) {
uv__req_unregister(handle->loop, req);
- return -ENOMEM;
+ return UV_ENOMEM;
}
memcpy(req->bufs, bufs, nbufs * sizeof(bufs[0]));
@@ -457,7 +457,7 @@ int uv__udp_try_send(uv_udp_t* handle,
/* already sending a message */
if (handle->send_queue_count != 0)
- return -EAGAIN;
+ return UV_EAGAIN;
err = uv__udp_maybe_deferred_bind(handle, addr->sa_family, 0);
if (err)
@@ -475,9 +475,9 @@ int uv__udp_try_send(uv_udp_t* handle,
if (size == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
- return -EAGAIN;
+ return UV_EAGAIN;
else
- return -errno;
+ return UV__ERR(errno);
}
return size;
@@ -512,7 +512,7 @@ static int uv__udp_set_membership4(uv_udp_t* handle,
optname = IP_DROP_MEMBERSHIP;
break;
default:
- return -EINVAL;
+ return UV_EINVAL;
}
if (setsockopt(handle->io_watcher.fd,
@@ -522,9 +522,9 @@ static int uv__udp_set_membership4(uv_udp_t* handle,
sizeof(mreq))) {
#if defined(__MVS__)
if (errno == ENXIO)
- return -ENODEV;
+ return UV_ENODEV;
#endif
- return -errno;
+ return UV__ERR(errno);
}
return 0;
@@ -543,7 +543,7 @@ static int uv__udp_set_membership6(uv_udp_t* handle,
if (interface_addr) {
if (uv_ip6_addr(interface_addr, 0, &addr6))
- return -EINVAL;
+ return UV_EINVAL;
mreq.ipv6mr_interface = addr6.sin6_scope_id;
} else {
mreq.ipv6mr_interface = 0;
@@ -559,7 +559,7 @@ static int uv__udp_set_membership6(uv_udp_t* handle,
optname = IPV6_DROP_MEMBERSHIP;
break;
default:
- return -EINVAL;
+ return UV_EINVAL;
}
if (setsockopt(handle->io_watcher.fd,
@@ -569,9 +569,9 @@ static int uv__udp_set_membership6(uv_udp_t* handle,
sizeof(mreq))) {
#if defined(__MVS__)
if (errno == ENXIO)
- return -ENODEV;
+ return UV_ENODEV;
#endif
- return -errno;
+ return UV__ERR(errno);
}
return 0;
@@ -586,10 +586,10 @@ int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) {
/* Use the lower 8 bits for the domain */
domain = flags & 0xFF;
if (domain != AF_INET && domain != AF_INET6 && domain != AF_UNSPEC)
- return -EINVAL;
+ return UV_EINVAL;
if (flags & ~0xFF)
- return -EINVAL;
+ return UV_EINVAL;
if (domain != AF_UNSPEC) {
err = uv__socket(domain, SOCK_DGRAM, 0);
@@ -622,7 +622,7 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) {
/* Check for already active socket. */
if (handle->io_watcher.fd != -1)
- return -EBUSY;
+ return UV_EBUSY;
err = uv__nonblock(sock, 1);
if (err)
@@ -656,7 +656,7 @@ int uv_udp_set_membership(uv_udp_t* handle,
return err;
return uv__udp_set_membership6(handle, &addr6, interface_addr, membership);
} else {
- return -EINVAL;
+ return UV_EINVAL;
}
}
@@ -680,7 +680,7 @@ static int uv__setsockopt(uv_udp_t* handle,
val,
size);
if (r)
- return -errno;
+ return UV__ERR(errno);
return 0;
}
@@ -698,7 +698,7 @@ static int uv__setsockopt_maybe_char(uv_udp_t* handle,
#endif
if (val < 0 || val > 255)
- return -EINVAL;
+ return UV_EINVAL;
return uv__setsockopt(handle, option4, option6, &arg, sizeof(arg));
}
@@ -710,7 +710,7 @@ int uv_udp_set_broadcast(uv_udp_t* handle, int on) {
SO_BROADCAST,
&on,
sizeof(on))) {
- return -errno;
+ return UV__ERR(errno);
}
return 0;
@@ -719,11 +719,11 @@ int uv_udp_set_broadcast(uv_udp_t* handle, int on) {
int uv_udp_set_ttl(uv_udp_t* handle, int ttl) {
if (ttl < 1 || ttl > 255)
- return -EINVAL;
+ return UV_EINVAL;
#if defined(__MVS__)
if (!(handle->flags & UV_HANDLE_IPV6))
- return -ENOTSUP; /* zOS does not support setting ttl for IPv4 */
+ return UV_ENOTSUP; /* zOS does not support setting ttl for IPv4 */
#endif
/*
@@ -817,7 +817,7 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr)
} else if (uv_ip6_addr(interface_addr, 0, addr6) == 0) {
/* nothing, address was parsed */
} else {
- return -EINVAL;
+ return UV_EINVAL;
}
if (addr_st.ss_family == AF_INET) {
@@ -826,7 +826,7 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr)
IP_MULTICAST_IF,
(void*) &addr4->sin_addr,
sizeof(addr4->sin_addr)) == -1) {
- return -errno;
+ return UV__ERR(errno);
}
} else if (addr_st.ss_family == AF_INET6) {
if (setsockopt(handle->io_watcher.fd,
@@ -834,7 +834,7 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr)
IPV6_MULTICAST_IF,
&addr6->sin6_scope_id,
sizeof(addr6->sin6_scope_id)) == -1) {
- return -errno;
+ return UV__ERR(errno);
}
} else {
assert(0 && "unexpected address family");
@@ -851,13 +851,13 @@ int uv_udp_getsockname(const uv_udp_t* handle,
socklen_t socklen;
if (handle->io_watcher.fd == -1)
- return -EINVAL; /* FIXME(bnoordhuis) -EBADF */
+ return UV_EINVAL; /* FIXME(bnoordhuis) UV_EBADF */
/* sizeof(socklen_t) != sizeof(int) on some systems. */
socklen = (socklen_t) *namelen;
if (getsockname(handle->io_watcher.fd, name, &socklen))
- return -errno;
+ return UV__ERR(errno);
*namelen = (int) socklen;
return 0;
@@ -870,10 +870,10 @@ int uv__udp_recv_start(uv_udp_t* handle,
int err;
if (alloc_cb == NULL || recv_cb == NULL)
- return -EINVAL;
+ return UV_EINVAL;
if (uv__io_active(&handle->io_watcher, POLLIN))
- return -EALREADY; /* FIXME(bnoordhuis) Should be -EBUSY. */
+ return UV_EALREADY; /* FIXME(bnoordhuis) Should be UV_EBUSY. */
err = uv__udp_maybe_deferred_bind(handle, AF_INET, 0);
if (err)
diff --git a/Utilities/cmlibuv/src/uv-common.c b/Utilities/cmlibuv/src/uv-common.c
index fcb910f..15dec08 100644
--- a/Utilities/cmlibuv/src/uv-common.c
+++ b/Utilities/cmlibuv/src/uv-common.c
@@ -629,7 +629,7 @@ int uv_loop_close(uv_loop_t* loop) {
void* saved_data;
#endif
- if (!QUEUE_EMPTY(&(loop)->active_reqs))
+ if (uv__has_active_reqs(loop))
return UV_EBUSY;
QUEUE_FOREACH(q, &loop->handle_queue) {
diff --git a/Utilities/cmlibuv/src/uv-common.h b/Utilities/cmlibuv/src/uv-common.h
index 781a855..c497d01 100644
--- a/Utilities/cmlibuv/src/uv-common.h
+++ b/Utilities/cmlibuv/src/uv-common.h
@@ -41,6 +41,12 @@
#include "tree.h"
#include "queue.h"
+#if EDOM > 0
+# define UV__ERR(x) (-(x))
+#else
+# define UV__ERR(x) (x)
+#endif
+
#if !defined(snprintf) && defined(_MSC_VER) && _MSC_VER < 1900
extern int snprintf(char*, size_t, const char*, ...);
#endif
@@ -127,18 +133,18 @@ int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value);
void uv__fs_scandir_cleanup(uv_fs_t* req);
#define uv__has_active_reqs(loop) \
- (QUEUE_EMPTY(&(loop)->active_reqs) == 0)
+ ((loop)->active_reqs.count > 0)
#define uv__req_register(loop, req) \
do { \
- QUEUE_INSERT_TAIL(&(loop)->active_reqs, &(req)->active_queue); \
+ (loop)->active_reqs.count++; \
} \
while (0)
#define uv__req_unregister(loop, req) \
do { \
assert(uv__has_active_reqs(loop)); \
- QUEUE_REMOVE(&(req)->active_queue); \
+ (loop)->active_reqs.count--; \
} \
while (0)
diff --git a/Utilities/cmlibuv/src/win/core.c b/Utilities/cmlibuv/src/win/core.c
index 8d121b3..b8aad11 100644
--- a/Utilities/cmlibuv/src/win/core.c
+++ b/Utilities/cmlibuv/src/win/core.c
@@ -239,7 +239,7 @@ int uv_loop_init(uv_loop_t* loop) {
QUEUE_INIT(&loop->wq);
QUEUE_INIT(&loop->handle_queue);
- QUEUE_INIT(&loop->active_reqs);
+ loop->active_reqs.count = 0;
loop->active_handles = 0;
loop->pending_reqs_tail = NULL;
@@ -470,8 +470,8 @@ static void uv_poll_ex(uv_loop_t* loop, DWORD timeout) {
static int uv__loop_alive(const uv_loop_t* loop) {
- return loop->active_handles > 0 ||
- !QUEUE_EMPTY(&loop->active_reqs) ||
+ return uv__has_active_handles(loop) ||
+ uv__has_active_reqs(loop) ||
loop->endgame_handles != NULL;
}
diff --git a/Utilities/cmlibuv/src/win/fs-event.c b/Utilities/cmlibuv/src/win/fs-event.c
index 95f843a..14c9af9 100644
--- a/Utilities/cmlibuv/src/win/fs-event.c
+++ b/Utilities/cmlibuv/src/win/fs-event.c
@@ -69,6 +69,7 @@ static void uv_relative_path(const WCHAR* filename,
size_t relpathlen;
size_t filenamelen = wcslen(filename);
size_t dirlen = wcslen(dir);
+ assert(!_wcsnicmp(filename, dir, dirlen));
if (dirlen > 0 && dir[dirlen - 1] == '\\')
dirlen--;
relpathlen = filenamelen - dirlen - 1;
@@ -151,11 +152,11 @@ int uv_fs_event_start(uv_fs_event_t* handle,
uv_fs_event_cb cb,
const char* path,
unsigned int flags) {
- int name_size, is_path_dir;
+ int name_size, is_path_dir, size;
DWORD attr, last_error;
WCHAR* dir = NULL, *dir_to_watch, *pathw = NULL;
WCHAR short_path_buffer[MAX_PATH];
- WCHAR* short_path;
+ WCHAR* short_path, *long_path;
if (uv__is_active(handle))
return UV_EINVAL;
@@ -197,6 +198,30 @@ 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. */
+
+ /* Convert to long path. */
+ size = GetLongPathNameW(pathw, NULL, 0);
+
+ if (size) {
+ long_path = (WCHAR*)uv__malloc(size * sizeof(WCHAR));
+ if (!long_path) {
+ uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
+ }
+
+ size = GetLongPathNameW(pathw, long_path, size);
+ if (size) {
+ long_path[size] = '\0';
+ } else {
+ uv__free(long_path);
+ long_path = NULL;
+ }
+ }
+
+ if (long_path) {
+ uv__free(pathw);
+ pathw = long_path;
+ }
+
dir_to_watch = pathw;
} else {
/*
diff --git a/Utilities/cmlibuv/src/win/fs.c b/Utilities/cmlibuv/src/win/fs.c
index 097b00e..30b87ac 100644
--- a/Utilities/cmlibuv/src/win/fs.c
+++ b/Utilities/cmlibuv/src/win/fs.c
@@ -783,7 +783,9 @@ void fs__unlink(uv_fs_t* req) {
/* Remove read-only attribute */
FILE_BASIC_INFORMATION basic = { 0 };
- basic.FileAttributes = info.dwFileAttributes & ~(FILE_ATTRIBUTE_READONLY);
+ basic.FileAttributes = info.dwFileAttributes
+ & ~(FILE_ATTRIBUTE_READONLY)
+ | FILE_ATTRIBUTE_ARCHIVE;
status = pNtSetInformationFile(handle,
&iosb,
@@ -1390,6 +1392,12 @@ static void fs__copyfile(uv_fs_t* req) {
int overwrite;
flags = req->fs.info.file_flags;
+
+ if (flags & UV_FS_COPYFILE_FICLONE_FORCE) {
+ SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED);
+ return;
+ }
+
overwrite = flags & UV_FS_COPYFILE_EXCL;
if (CopyFileW(req->file.pathw, req->fs.info.new_pathw, overwrite) == 0) {
@@ -2334,8 +2342,11 @@ int uv_fs_copyfile(uv_loop_t* loop,
INIT(UV_FS_COPYFILE);
- if (flags & ~UV_FS_COPYFILE_EXCL)
+ if (flags & ~(UV_FS_COPYFILE_EXCL |
+ UV_FS_COPYFILE_FICLONE |
+ UV_FS_COPYFILE_FICLONE_FORCE)) {
return UV_EINVAL;
+ }
err = fs__capture_path(req, path, new_path, cb != NULL);
diff --git a/Utilities/cmlibuv/src/win/getaddrinfo.c b/Utilities/cmlibuv/src/win/getaddrinfo.c
index 282d919..5adc766 100644
--- a/Utilities/cmlibuv/src/win/getaddrinfo.c
+++ b/Utilities/cmlibuv/src/win/getaddrinfo.c
@@ -392,15 +392,21 @@ int uv_if_indextoname(unsigned int ifindex, char* buffer, size_t* size) {
DWORD bufsize;
int r;
+ uv__once_init();
+
if (buffer == NULL || size == NULL || *size == 0)
return UV_EINVAL;
- r = ConvertInterfaceIndexToLuid(ifindex, &luid);
+ if (pConvertInterfaceIndexToLuid == NULL)
+ return UV_ENOSYS;
+ r = pConvertInterfaceIndexToLuid(ifindex, &luid);
if (r != 0)
return uv_translate_sys_error(r);
- r = ConvertInterfaceLuidToNameW(&luid, wname, ARRAY_SIZE(wname));
+ if (pConvertInterfaceLuidToNameW == NULL)
+ return UV_ENOSYS;
+ r = pConvertInterfaceLuidToNameW(&luid, wname, ARRAY_SIZE(wname));
if (r != 0)
return uv_translate_sys_error(r);
diff --git a/Utilities/cmlibuv/src/win/internal.h b/Utilities/cmlibuv/src/win/internal.h
index 9f28f77..849bc82 100644
--- a/Utilities/cmlibuv/src/win/internal.h
+++ b/Utilities/cmlibuv/src/win/internal.h
@@ -225,10 +225,16 @@ void uv_process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle,
uv_req_t* req);
void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle,
uv_write_t* req);
-/* TODO: remove me */
+/*
+ * uv_process_tty_accept_req() is a stub to keep DELEGATE_STREAM_REQ working
+ * TODO: find a way to remove it
+ */
void uv_process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle,
uv_req_t* raw_req);
-/* TODO: remove me */
+/*
+ * uv_process_tty_connect_req() is a stub to keep DELEGATE_STREAM_REQ working
+ * TODO: find a way to remove it
+ */
void uv_process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle,
uv_connect_t* req);
diff --git a/Utilities/cmlibuv/src/win/pipe.c b/Utilities/cmlibuv/src/win/pipe.c
index 1a7c4dc..83ee4f9 100644
--- a/Utilities/cmlibuv/src/win/pipe.c
+++ b/Utilities/cmlibuv/src/win/pipe.c
@@ -735,6 +735,13 @@ void uv__pipe_unpause_read(uv_pipe_t* handle) {
void uv__pipe_stop_read(uv_pipe_t* handle) {
+ if (pCancelIoEx &&
+ !(handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) &&
+ !(handle->flags & UV_HANDLE_EMULATE_IOCP) &&
+ handle->flags & UV_HANDLE_READING &&
+ handle->read_req.type == UV_READ) {
+ pCancelIoEx(handle->handle, &handle->read_req.u.io.overlapped);
+ }
handle->flags &= ~UV_HANDLE_READING;
uv__pipe_pause_read((uv_pipe_t*)handle);
uv__pipe_unpause_read((uv_pipe_t*)handle);
@@ -847,6 +854,7 @@ static void uv_pipe_queue_accept(uv_loop_t* loop, uv_pipe_t* handle,
return;
}
+ /* Wait for completion via IOCP */
handle->reqs_pending++;
}
diff --git a/Utilities/cmlibuv/src/win/process.c b/Utilities/cmlibuv/src/win/process.c
index f5f05af..25cfe87 100644
--- a/Utilities/cmlibuv/src/win/process.c
+++ b/Utilities/cmlibuv/src/win/process.c
@@ -1067,11 +1067,16 @@ int uv_spawn(uv_loop_t* loop,
process_flags = CREATE_UNICODE_ENVIRONMENT;
if (options->flags & UV_PROCESS_WINDOWS_HIDE) {
+ /* Avoid creating console window if stdio is not inherited. */
+ for (i = 0; i < options->stdio_count; i++) {
+ if (options->stdio[i].flags & UV_INHERIT_FD)
+ break;
+ if (i == options->stdio_count - 1)
+ process_flags |= CREATE_NO_WINDOW;
+ }
+
/* Use SW_HIDE to avoid any potential process window. */
startup.wShowWindow = SW_HIDE;
-
- /* Hide console windows. */
- process_flags |= CREATE_NO_WINDOW;
} else {
startup.wShowWindow = SW_SHOWDEFAULT;
}
diff --git a/Utilities/cmlibuv/src/win/stream-inl.h b/Utilities/cmlibuv/src/win/stream-inl.h
index dba0374..40f5ddd 100644
--- a/Utilities/cmlibuv/src/win/stream-inl.h
+++ b/Utilities/cmlibuv/src/win/stream-inl.h
@@ -37,11 +37,6 @@ INLINE static void uv_stream_init(uv_loop_t* loop,
handle->write_queue_size = 0;
handle->activecnt = 0;
handle->stream.conn.shutdown_req = NULL;
-}
-
-
-INLINE static void uv_connection_init(uv_stream_t* handle) {
- handle->flags |= UV_HANDLE_CONNECTION;
handle->stream.conn.write_reqs_pending = 0;
UV_REQ_INIT(&handle->read_req, UV_READ);
@@ -51,4 +46,9 @@ INLINE static void uv_connection_init(uv_stream_t* handle) {
}
+INLINE static void uv_connection_init(uv_stream_t* handle) {
+ handle->flags |= UV_HANDLE_CONNECTION;
+}
+
+
#endif /* UV_WIN_STREAM_INL_H_ */
diff --git a/Utilities/cmlibuv/src/win/tcp.c b/Utilities/cmlibuv/src/win/tcp.c
index fd6efba..39c1ff0 100644
--- a/Utilities/cmlibuv/src/win/tcp.c
+++ b/Utilities/cmlibuv/src/win/tcp.c
@@ -459,8 +459,6 @@ static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) {
INFINITE, WT_EXECUTEINWAITTHREAD)) {
SET_REQ_ERROR(req, GetLastError());
uv_insert_pending_req(loop, (uv_req_t*)req);
- handle->reqs_pending++;
- return;
}
} else {
/* Make this req pending reporting an error. */
@@ -1173,11 +1171,14 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle,
err = 0;
if (REQ_SUCCESS(req)) {
- if (setsockopt(handle->socket,
- SOL_SOCKET,
- SO_UPDATE_CONNECT_CONTEXT,
- NULL,
- 0) == 0) {
+ if (handle->flags & UV__HANDLE_CLOSING) {
+ /* use UV_ECANCELED for consistency with Unix */
+ err = ERROR_OPERATION_ABORTED;
+ } else if (setsockopt(handle->socket,
+ SOL_SOCKET,
+ SO_UPDATE_CONNECT_CONTEXT,
+ NULL,
+ 0) == 0) {
uv_connection_init((uv_stream_t*)handle);
handle->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
loop->active_tcp_streams++;
diff --git a/Utilities/cmlibuv/src/win/tty.c b/Utilities/cmlibuv/src/win/tty.c
index 05a11e8..ecf7bc9 100644
--- a/Utilities/cmlibuv/src/win/tty.c
+++ b/Utilities/cmlibuv/src/win/tty.c
@@ -2235,14 +2235,20 @@ void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) {
}
-/* TODO: remove me */
+/*
+ * uv_process_tty_accept_req() is a stub to keep DELEGATE_STREAM_REQ working
+ * TODO: find a way to remove it
+ */
void uv_process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle,
uv_req_t* raw_req) {
abort();
}
-/* TODO: remove me */
+/*
+ * uv_process_tty_connect_req() is a stub to keep DELEGATE_STREAM_REQ working
+ * TODO: find a way to remove it
+ */
void uv_process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle,
uv_connect_t* req) {
abort();
diff --git a/Utilities/cmlibuv/src/win/util.c b/Utilities/cmlibuv/src/win/util.c
index 3100bc2..49b5bc7 100644
--- a/Utilities/cmlibuv/src/win/util.c
+++ b/Utilities/cmlibuv/src/win/util.c
@@ -37,7 +37,7 @@
#include <tlhelp32.h>
#include <windows.h>
#include <userenv.h>
-
+#include <math.h>
/*
* Max title length; the only thing MSDN tells us about the maximum length
@@ -587,8 +587,8 @@ int uv_uptime(double* uptime) {
BYTE* address = (BYTE*) object_type + object_type->DefinitionLength +
counter_definition->CounterOffset;
uint64_t value = *((uint64_t*) address);
- *uptime = (double) (object_type->PerfTime.QuadPart - value) /
- (double) object_type->PerfFreq.QuadPart;
+ *uptime = floor((double) (object_type->PerfTime.QuadPart - value) /
+ (double) object_type->PerfFreq.QuadPart);
uv__free(malloced_buffer);
return 0;
}
@@ -615,7 +615,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos_ptr, int* cpu_count_ptr) {
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* sppi;
DWORD sppi_size;
SYSTEM_INFO system_info;
- DWORD cpu_count, r, i;
+ DWORD cpu_count, i;
NTSTATUS status;
ULONG result_size;
int err;
@@ -670,34 +670,33 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos_ptr, int* cpu_count_ptr) {
assert(len > 0 && len < ARRAY_SIZE(key_name));
- r = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
- key_name,
- 0,
- KEY_QUERY_VALUE,
- &processor_key);
- if (r != ERROR_SUCCESS) {
- err = GetLastError();
+ err = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+ key_name,
+ 0,
+ KEY_QUERY_VALUE,
+ &processor_key);
+ if (err != ERROR_SUCCESS) {
goto error;
}
- if (RegQueryValueExW(processor_key,
- L"~MHz",
- NULL,
- NULL,
- (BYTE*) &cpu_speed,
- &cpu_speed_size) != ERROR_SUCCESS) {
- err = GetLastError();
+ err = RegQueryValueExW(processor_key,
+ L"~MHz",
+ NULL,
+ NULL,
+ (BYTE*)&cpu_speed,
+ &cpu_speed_size);
+ if (err != ERROR_SUCCESS) {
RegCloseKey(processor_key);
goto error;
}
- if (RegQueryValueExW(processor_key,
- L"ProcessorNameString",
- NULL,
- NULL,
- (BYTE*) &cpu_brand,
- &cpu_brand_size) != ERROR_SUCCESS) {
- err = GetLastError();
+ err = RegQueryValueExW(processor_key,
+ L"ProcessorNameString",
+ NULL,
+ NULL,
+ (BYTE*)&cpu_brand,
+ &cpu_brand_size);
+ if (err != ERROR_SUCCESS) {
RegCloseKey(processor_key);
goto error;
}
@@ -1148,53 +1147,17 @@ int uv_getrusage(uv_rusage_t *uv_rusage) {
int uv_os_homedir(char* buffer, size_t* size) {
uv_passwd_t pwd;
- wchar_t path[MAX_PATH];
- DWORD bufsize;
size_t len;
int r;
- if (buffer == NULL || size == NULL || *size == 0)
- return UV_EINVAL;
-
- /* Check if the USERPROFILE environment variable is set first */
- len = GetEnvironmentVariableW(L"USERPROFILE", path, MAX_PATH);
+ /* Check if the USERPROFILE environment variable is set first. The task of
+ performing input validation on buffer and size is taken care of by
+ uv_os_getenv(). */
+ r = uv_os_getenv("USERPROFILE", buffer, size);
- if (len == 0) {
- r = GetLastError();
-
- /* Don't return an error if USERPROFILE was not found */
- if (r != ERROR_ENVVAR_NOT_FOUND)
- return uv_translate_sys_error(r);
- } else if (len > MAX_PATH) {
- /* This should not be possible */
- return UV_EIO;
- } else {
- /* Check how much space we need */
- bufsize = WideCharToMultiByte(CP_UTF8, 0, path, -1, NULL, 0, NULL, NULL);
-
- if (bufsize == 0) {
- return uv_translate_sys_error(GetLastError());
- } else if (bufsize > *size) {
- *size = bufsize;
- return UV_ENOBUFS;
- }
-
- /* Convert to UTF-8 */
- bufsize = WideCharToMultiByte(CP_UTF8,
- 0,
- path,
- -1,
- buffer,
- *size,
- NULL,
- NULL);
-
- if (bufsize == 0)
- return uv_translate_sys_error(GetLastError());
-
- *size = bufsize - 1;
- return 0;
- }
+ /* Don't return an error if USERPROFILE was not found. */
+ if (r != UV_ENOENT)
+ return r;
/* USERPROFILE is not set, so call uv__getpwuid_r() */
r = uv__getpwuid_r(&pwd);
diff --git a/Utilities/cmlibuv/src/win/winapi.c b/Utilities/cmlibuv/src/win/winapi.c
index 4ccdf0a..c330786 100644
--- a/Utilities/cmlibuv/src/win/winapi.c
+++ b/Utilities/cmlibuv/src/win/winapi.c
@@ -55,12 +55,16 @@ sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;
/* User32.dll function pointer */
sSetWinEventHook pSetWinEventHook;
+/* iphlpapi.dll function pointer */
+sConvertInterfaceIndexToLuid pConvertInterfaceIndexToLuid = NULL;
+sConvertInterfaceLuidToNameW pConvertInterfaceLuidToNameW = NULL;
void uv_winapi_init(void) {
HMODULE ntdll_module;
HMODULE kernel32_module;
HMODULE powrprof_module;
HMODULE user32_module;
+ HMODULE iphlpapi_module;
ntdll_module = GetModuleHandleA("ntdll.dll");
if (ntdll_module == NULL) {
@@ -166,4 +170,11 @@ void uv_winapi_init(void) {
GetProcAddress(user32_module, "SetWinEventHook");
}
+ iphlpapi_module = LoadLibraryA("iphlpapi.dll");
+ if (iphlpapi_module != NULL) {
+ pConvertInterfaceIndexToLuid = (sConvertInterfaceIndexToLuid)
+ GetProcAddress(iphlpapi_module, "ConvertInterfaceIndexToLuid");
+ pConvertInterfaceLuidToNameW = (sConvertInterfaceLuidToNameW)
+ GetProcAddress(iphlpapi_module, "ConvertInterfaceLuidToNameW");
+ }
}
diff --git a/Utilities/cmlibuv/src/win/winapi.h b/Utilities/cmlibuv/src/win/winapi.h
index 8993c65..ae384b7 100644
--- a/Utilities/cmlibuv/src/win/winapi.h
+++ b/Utilities/cmlibuv/src/win/winapi.h
@@ -4784,4 +4784,19 @@ extern sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotifi
/* User32.dll function pointer */
extern sSetWinEventHook pSetWinEventHook;
+/* iphlpapi.dll function pointer */
+union _NET_LUID_LH;
+typedef DWORD (WINAPI *sConvertInterfaceIndexToLuid)(
+ ULONG InterfaceIndex,
+ union _NET_LUID_LH *InterfaceLuid);
+
+typedef DWORD (WINAPI *sConvertInterfaceLuidToNameW)(
+ const union _NET_LUID_LH *InterfaceLuid,
+ PWSTR InterfaceName,
+ size_t Length);
+
+extern sConvertInterfaceIndexToLuid pConvertInterfaceIndexToLuid;
+extern sConvertInterfaceLuidToNameW pConvertInterfaceLuidToNameW;
+
+
#endif /* UV_WIN_WINAPI_H_ */
diff --git a/Utilities/cmlibuv/src/win/winsock.c b/Utilities/cmlibuv/src/win/winsock.c
index 7cfa90f..8418895 100644
--- a/Utilities/cmlibuv/src/win/winsock.c
+++ b/Utilities/cmlibuv/src/win/winsock.c
@@ -580,8 +580,10 @@ int uv__convert_to_localhost_if_unspecified(const struct sockaddr* addr,
memcpy(dest6, addr, sizeof(*dest6));
if (memcmp(&dest6->sin6_addr,
&uv_addr_ip6_any_.sin6_addr,
- sizeof(uv_addr_ip6_any_.sin6_addr)) == 0)
- dest6->sin6_addr = (struct in6_addr) IN6ADDR_LOOPBACK_INIT;
+ sizeof(uv_addr_ip6_any_.sin6_addr)) == 0) {
+ struct in6_addr init_sin6_addr = IN6ADDR_LOOPBACK_INIT;
+ dest6->sin6_addr = init_sin6_addr;
+ }
return 0;
default:
return UV_EINVAL;
diff --git a/bootstrap b/bootstrap
index 6604f54..0aa600d 100755
--- a/bootstrap
+++ b/bootstrap
@@ -1250,6 +1250,12 @@ else
echo "${cmake_cxx_compiler} does not have <ext/stdio_filebuf.h>"
fi
+if [ -n "${cmake_ccache_enabled}" ]; then
+ echo "Building CMake with ccache"
+ cmake_c_compiler="ccache ${cmake_c_compiler}"
+ cmake_cxx_compiler="ccache ${cmake_cxx_compiler}"
+fi
+
# Just to be safe, let us store compiler and flags to the header file
cmake_bootstrap_version='$Revision$'
@@ -1536,10 +1542,6 @@ cd "${cmake_binary_dir}"
# build with same compiler and make
CC="${cmake_c_compiler}"
CXX="${cmake_cxx_compiler}"
-if [ -n "${cmake_ccache_enabled}" ]; then
- CC="ccache ${CC}"
- CXX="ccache ${CXX}"
-fi
MAKE="${cmake_make_processor}"
export CC
export CXX