summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Help/manual/cmake.1.rst2
-rw-r--r--Help/release/dev/cache-newline.rst7
-rw-r--r--Help/variable/CMAKE_AUTOMOC_MACRO_NAMES.rst2
-rw-r--r--Help/variable/CMAKE_CROSSCOMPILING.rst26
-rw-r--r--Help/variable/CMAKE_LANG_COMPILER_EXTERNAL_TOOLCHAIN.rst2
-rw-r--r--Modules/CMakeCXXInformation.cmake4
-rw-r--r--Modules/CMakeFortranInformation.cmake4
-rw-r--r--Modules/CMakeGenericSystem.cmake1
-rw-r--r--Modules/FindBoost.cmake8
-rw-r--r--Modules/FindJava.cmake34
-rw-r--r--Modules/FindOpenGL.cmake1
-rw-r--r--Modules/FindOpenMP.cmake2
-rw-r--r--Modules/FindPythonInterp.cmake3
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/CPack/cpack.cxx4
-rw-r--r--Source/CursesDialog/ccmake.cxx1
-rw-r--r--Source/QtDialog/CMakeSetup.cxx1
-rw-r--r--Source/cmCacheManager.cxx74
-rw-r--r--Source/cmCacheManager.h17
-rw-r--r--Source/cmComputeLinkInformation.cxx8
-rw-r--r--Source/cmExtraCodeLiteGenerator.cxx31
-rw-r--r--Source/cmGeneratorExpressionEvaluationFile.cxx4
-rw-r--r--Source/cmQtAutoGeneratorMocUic.cxx8
-rw-r--r--Source/cmServerProtocol.cxx4
-rw-r--r--Source/cmState.cxx4
-rw-r--r--Source/cmState.h3
-rw-r--r--Source/cmSystemTools.cxx17
-rw-r--r--Source/cmSystemTools.h4
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx2
-rw-r--r--Source/cmake.cxx2
-rw-r--r--Source/cmakemain.cxx17
-rw-r--r--Source/cmcmd.cxx2
-rw-r--r--Source/ctest.cxx1
-rw-r--r--Tests/FindBoost/CMakeLists.txt14
-rw-r--r--Tests/FindBoost/Test/CMakeLists.txt11
-rw-r--r--Tests/FindBoost/TestFail/CMakeLists.txt18
-rw-r--r--Tests/FindBoost/TestFail/main.cxx24
-rw-r--r--Tests/QtAutogen/CommonTests.cmake4
-rw-r--r--Tests/QtAutogen/MocOnly/CMakeLists.txt11
-rw-r--r--Tests/QtAutogen/MocOnly/IncA.cpp19
-rw-r--r--Tests/QtAutogen/MocOnly/IncA.hpp15
-rw-r--r--Tests/QtAutogen/MocOnly/IncB.cpp19
-rw-r--r--Tests/QtAutogen/MocOnly/IncB.hpp15
-rw-r--r--Tests/QtAutogen/MocOnly/main.cpp5
-rw-r--r--Tests/QtAutogen/UicOnly/CMakeLists.txt4
-rw-r--r--Tests/QtAutogen/UicOnly/UicOnly.cpp18
-rw-r--r--Tests/QtAutogen/UicOnly/UicOnly.hpp15
-rw-r--r--Tests/QtAutogen/UicOnly/main.cpp7
-rw-r--r--Tests/QtAutogen/UicOnly/uiA.ui (renamed from Tests/QtAutogen/UicOnly/uiconly.ui)4
-rw-r--r--Tests/QtAutogen/UicOnly/uiB.ui24
-rw-r--r--Tests/QtAutogen/UicOnly/uiC.ui24
-rw-r--r--Tests/QtAutogen/UicOnly/uiD.ui24
-rw-r--r--Tests/QtAutogen/UicOnly/uiconly.cpp18
-rw-r--r--Tests/QtAutogen/UicOnly/uiconly.h20
-rw-r--r--Tests/RunCMake/CMakeLists.txt1
-rw-r--r--Tests/RunCMake/CacheNewline/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/CacheNewline/CacheNewline-check.cmake16
-rw-r--r--Tests/RunCMake/CacheNewline/CacheNewline-stderr.txt2
-rw-r--r--Tests/RunCMake/CacheNewline/CacheNewline.cmake5
-rw-r--r--Tests/RunCMake/CacheNewline/RunCMakeTest.cmake3
-rw-r--r--Tests/RunCMake/CacheNewline/cache-regex.txt6
-rw-r--r--Utilities/IWYU/mapping.imp3
-rwxr-xr-xUtilities/Scripts/update-libuv.bash2
-rw-r--r--Utilities/cmlibuv/CMakeLists.txt3
-rw-r--r--Utilities/cmlibuv/LICENSE4
-rw-r--r--Utilities/cmlibuv/include/pthread-barrier.h1
-rw-r--r--Utilities/cmlibuv/include/uv-errno.h12
-rw-r--r--Utilities/cmlibuv/include/uv-os390.h3
-rw-r--r--Utilities/cmlibuv/include/uv-unix.h96
-rw-r--r--Utilities/cmlibuv/include/uv-version.h2
-rw-r--r--Utilities/cmlibuv/include/uv-win.h28
-rw-r--r--Utilities/cmlibuv/include/uv.h63
-rw-r--r--Utilities/cmlibuv/src/threadpool.c18
-rw-r--r--Utilities/cmlibuv/src/unix/aix-common.c292
-rw-r--r--Utilities/cmlibuv/src/unix/aix.c242
-rw-r--r--Utilities/cmlibuv/src/unix/android-ifaddrs.c49
-rw-r--r--Utilities/cmlibuv/src/unix/atomic-ops.h5
-rw-r--r--Utilities/cmlibuv/src/unix/bsd-ifaddrs.c23
-rw-r--r--Utilities/cmlibuv/src/unix/core.c45
-rw-r--r--Utilities/cmlibuv/src/unix/freebsd.c87
-rw-r--r--Utilities/cmlibuv/src/unix/fs.c177
-rw-r--r--Utilities/cmlibuv/src/unix/fsevents.c28
-rw-r--r--Utilities/cmlibuv/src/unix/getaddrinfo.c30
-rw-r--r--Utilities/cmlibuv/src/unix/ibmi.c112
-rw-r--r--Utilities/cmlibuv/src/unix/internal.h15
-rw-r--r--Utilities/cmlibuv/src/unix/kqueue.c38
-rw-r--r--Utilities/cmlibuv/src/unix/linux-core.c14
-rw-r--r--Utilities/cmlibuv/src/unix/loop.c2
-rw-r--r--Utilities/cmlibuv/src/unix/netbsd.c57
-rw-r--r--Utilities/cmlibuv/src/unix/openbsd.c33
-rw-r--r--Utilities/cmlibuv/src/unix/os390-syscalls.c229
-rw-r--r--Utilities/cmlibuv/src/unix/os390-syscalls.h3
-rw-r--r--Utilities/cmlibuv/src/unix/os390.c175
-rw-r--r--Utilities/cmlibuv/src/unix/pipe.c53
-rw-r--r--Utilities/cmlibuv/src/unix/poll.c25
-rw-r--r--Utilities/cmlibuv/src/unix/process.c42
-rw-r--r--Utilities/cmlibuv/src/unix/proctitle.c35
-rw-r--r--Utilities/cmlibuv/src/unix/pthread-barrier.c121
-rw-r--r--Utilities/cmlibuv/src/unix/stream.c39
-rw-r--r--Utilities/cmlibuv/src/unix/sunos.c4
-rw-r--r--Utilities/cmlibuv/src/unix/tcp.c101
-rw-r--r--Utilities/cmlibuv/src/unix/thread.c197
-rw-r--r--Utilities/cmlibuv/src/unix/tty.c36
-rw-r--r--Utilities/cmlibuv/src/unix/udp.c8
-rw-r--r--Utilities/cmlibuv/src/uv-data-getter-setters.c96
-rw-r--r--Utilities/cmlibuv/src/win/dl.c55
-rw-r--r--Utilities/cmlibuv/src/win/error.c2
-rw-r--r--Utilities/cmlibuv/src/win/fs.c581
-rw-r--r--Utilities/cmlibuv/src/win/getaddrinfo.c71
-rw-r--r--Utilities/cmlibuv/src/win/handle.c5
-rw-r--r--Utilities/cmlibuv/src/win/internal.h1
-rw-r--r--Utilities/cmlibuv/src/win/pipe.c137
-rw-r--r--Utilities/cmlibuv/src/win/process.c31
-rw-r--r--Utilities/cmlibuv/src/win/signal.c2
-rw-r--r--Utilities/cmlibuv/src/win/stream-inl.h3
-rw-r--r--Utilities/cmlibuv/src/win/tcp.c32
-rw-r--r--Utilities/cmlibuv/src/win/thread.c6
-rw-r--r--Utilities/cmlibuv/src/win/timer.c2
-rw-r--r--Utilities/cmlibuv/src/win/tty.c121
-rw-r--r--Utilities/cmlibuv/src/win/udp.c51
-rw-r--r--Utilities/cmlibuv/src/win/util.c11
-rw-r--r--Utilities/cmlibuv/src/win/winapi.c10
-rw-r--r--Utilities/cmlibuv/src/win/winapi.h26
-rw-r--r--Utilities/cmlibuv/src/win/winsock.c28
-rw-r--r--Utilities/cmlibuv/src/win/winsock.h3
125 files changed, 3319 insertions, 1158 deletions
diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst
index ff8c6c7aa3..c2e6435e15 100644
--- a/Help/manual/cmake.1.rst
+++ b/Help/manual/cmake.1.rst
@@ -337,7 +337,7 @@ Available commands are:
``paxr`` (restricted pax, default), and ``zip``.
``time <command> [<args>...]``
- Run command and return elapsed time.
+ Run command and display elapsed time.
``touch <file>``
Touch a file.
diff --git a/Help/release/dev/cache-newline.rst b/Help/release/dev/cache-newline.rst
new file mode 100644
index 0000000000..96900bbfa9
--- /dev/null
+++ b/Help/release/dev/cache-newline.rst
@@ -0,0 +1,7 @@
+cache-newline
+-------------
+
+* Variables containing newlines in their values now get truncated before the
+ newline when they are written to the cache file. In addition, a warning
+ comment is written to the cache file, and a warning message is displayed to
+ the user on the console.
diff --git a/Help/variable/CMAKE_AUTOMOC_MACRO_NAMES.rst b/Help/variable/CMAKE_AUTOMOC_MACRO_NAMES.rst
index 5b79c40204..2c8997bbfe 100644
--- a/Help/variable/CMAKE_AUTOMOC_MACRO_NAMES.rst
+++ b/Help/variable/CMAKE_AUTOMOC_MACRO_NAMES.rst
@@ -12,7 +12,7 @@ information.
The default value is ``Q_OBJECT;Q_GADGET;Q_NAMESPACE``.
Example
--------
+^^^^^^^
Let CMake know that source files that contain ``CUSTOM_MACRO`` must be ``moc``
processed as well::
diff --git a/Help/variable/CMAKE_CROSSCOMPILING.rst b/Help/variable/CMAKE_CROSSCOMPILING.rst
index cf9865b619..9e96769a75 100644
--- a/Help/variable/CMAKE_CROSSCOMPILING.rst
+++ b/Help/variable/CMAKE_CROSSCOMPILING.rst
@@ -1,8 +1,26 @@
CMAKE_CROSSCOMPILING
--------------------
-Is CMake currently cross compiling.
+Intended to indicate whether CMake is cross compiling, but note limitations
+discussed below.
-This variable will be set to true by CMake if CMake is cross
-compiling. Specifically if the build platform is different from the
-target platform.
+This variable will be set to true by CMake if the :variable:`CMAKE_SYSTEM_NAME`
+variable has been set manually (i.e. in a toolchain file or as a cache entry
+from the :manual:`cmake <cmake(1)>` command line). In most cases, manually
+setting :variable:`CMAKE_SYSTEM_NAME` will only be done when cross compiling,
+since it will otherwise be given the same value as
+:variable:`CMAKE_HOST_SYSTEM_NAME` if not manually set, which is correct for
+the non-cross-compiling case. In the event that :variable:`CMAKE_SYSTEM_NAME`
+is manually set to the same value as :variable:`CMAKE_HOST_SYSTEM_NAME`, then
+``CMAKE_CROSSCOMPILING`` will still be set to true.
+
+Another case to be aware of is that builds targeting Apple platforms other than
+macOS are handled differently to other cross compiling scenarios. Rather than
+relying on :variable:`CMAKE_SYSTEM_NAME` to select the target platform, Apple
+device builds use :variable:`CMAKE_OSX_SYSROOT` to select the appropriate SDK,
+which indirectly determines the target platform. Furthermore, when using the
+Xcode generator, developers can switch between device and simulator builds at
+build time rather than having a single choice at configure time, so the concept
+of whether the build is cross compiling or not is more complex. Therefore, the
+use of ``CMAKE_CROSSCOMPILING`` is not recommended for projects targeting Apple
+devices.
diff --git a/Help/variable/CMAKE_LANG_COMPILER_EXTERNAL_TOOLCHAIN.rst b/Help/variable/CMAKE_LANG_COMPILER_EXTERNAL_TOOLCHAIN.rst
index 5be935bade..cbe35441e4 100644
--- a/Help/variable/CMAKE_LANG_COMPILER_EXTERNAL_TOOLCHAIN.rst
+++ b/Help/variable/CMAKE_LANG_COMPILER_EXTERNAL_TOOLCHAIN.rst
@@ -6,7 +6,7 @@ The external toolchain for cross-compiling, if supported.
Some compiler toolchains do not ship their own auxiliary utilities such as
archivers and linkers. The compiler driver may support a command-line argument
to specify the location of such tools.
-``CMAKE_<LANG>_COMPILER_EXTERNAL_TOOLCHAIN`` may be set to a path to a path to
+``CMAKE_<LANG>_COMPILER_EXTERNAL_TOOLCHAIN`` may be set to a path to
the external toolchain and will be passed to the compiler driver if supported.
This variable may only be set in a toolchain file specified by
diff --git a/Modules/CMakeCXXInformation.cmake b/Modules/CMakeCXXInformation.cmake
index 31ccef7637..9ac9560e08 100644
--- a/Modules/CMakeCXXInformation.cmake
+++ b/Modules/CMakeCXXInformation.cmake
@@ -158,10 +158,6 @@ if(NOT CMAKE_INCLUDE_FLAG_CXX)
set(CMAKE_INCLUDE_FLAG_CXX ${CMAKE_INCLUDE_FLAG_C})
endif()
-if(NOT CMAKE_INCLUDE_FLAG_SEP_CXX)
- set(CMAKE_INCLUDE_FLAG_SEP_CXX ${CMAKE_INCLUDE_FLAG_SEP_C})
-endif()
-
# for most systems a module is the same as a shared library
# so unless the variable CMAKE_MODULE_EXISTS is set just
# copy the values from the LIBRARY variables
diff --git a/Modules/CMakeFortranInformation.cmake b/Modules/CMakeFortranInformation.cmake
index 8e5c027605..5f028e4f3e 100644
--- a/Modules/CMakeFortranInformation.cmake
+++ b/Modules/CMakeFortranInformation.cmake
@@ -151,10 +151,6 @@ if(NOT CMAKE_INCLUDE_FLAG_Fortran)
set(CMAKE_INCLUDE_FLAG_Fortran ${CMAKE_INCLUDE_FLAG_C})
endif()
-if(NOT CMAKE_INCLUDE_FLAG_SEP_Fortran)
- set(CMAKE_INCLUDE_FLAG_SEP_Fortran ${CMAKE_INCLUDE_FLAG_SEP_C})
-endif()
-
set(CMAKE_VERBOSE_MAKEFILE FALSE CACHE BOOL "If this value is on, makefiles will be generated without the .SILENT directive, and all commands will be echoed to the console during the make. This is useful for debugging only. With Visual Studio IDE projects all commands are done without /nologo.")
set(CMAKE_Fortran_FLAGS_INIT "$ENV{FFLAGS} ${CMAKE_Fortran_FLAGS_INIT}")
diff --git a/Modules/CMakeGenericSystem.cmake b/Modules/CMakeGenericSystem.cmake
index 3eb86f9662..02cb464501 100644
--- a/Modules/CMakeGenericSystem.cmake
+++ b/Modules/CMakeGenericSystem.cmake
@@ -9,7 +9,6 @@ set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") # +s, flag for exe link to use
set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "") # -rpath
set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG_SEP "") # : or empty
set(CMAKE_INCLUDE_FLAG_C "-I") # -I
-set(CMAKE_INCLUDE_FLAG_C_SEP "") # , or empty
set(CMAKE_LIBRARY_PATH_FLAG "-L")
set(CMAKE_LIBRARY_PATH_TERMINATOR "") # for the Digital Mars D compiler the link paths have to be terminated with a "/"
set(CMAKE_LINK_LIBRARY_FLAG "-l")
diff --git a/Modules/FindBoost.cmake b/Modules/FindBoost.cmake
index ca2a9c5b35..4a55588862 100644
--- a/Modules/FindBoost.cmake
+++ b/Modules/FindBoost.cmake
@@ -13,6 +13,9 @@
# [version] [EXACT] # Minimum or EXACT version e.g. 1.36.0
# [REQUIRED] # Fail with error if Boost is not found
# [COMPONENTS <libs>...] # Boost libraries by their canonical name
+# # e.g. "date_time" for "libboost_date_time"
+# [OPTIONAL_COMPONENTS <libs>...]
+# # Optional Boost libraries by their canonical name)
# ) # e.g. "date_time" for "libboost_date_time"
#
# This module finds headers and requested component libraries OR a CMake
@@ -1777,10 +1780,9 @@ if(Boost_FOUND)
set(_boost_CHECKED_COMPONENT FALSE)
set(_Boost_MISSING_COMPONENTS "")
foreach(COMPONENT ${Boost_FIND_COMPONENTS})
- string(TOUPPER ${COMPONENT} COMPONENT)
+ string(TOUPPER ${COMPONENT} UPPERCOMPONENT)
set(_boost_CHECKED_COMPONENT TRUE)
- if(NOT Boost_${COMPONENT}_FOUND)
- string(TOLOWER ${COMPONENT} COMPONENT)
+ if(NOT Boost_${UPPERCOMPONENT}_FOUND AND Boost_FIND_REQUIRED_${COMPONENT})
list(APPEND _Boost_MISSING_COMPONENTS ${COMPONENT})
endif()
endforeach()
diff --git a/Modules/FindJava.cmake b/Modules/FindJava.cmake
index b913e170fb..e3f5af6c60 100644
--- a/Modules/FindJava.cmake
+++ b/Modules/FindJava.cmake
@@ -237,10 +237,18 @@ if(Java_FIND_COMPONENTS)
endif()
elseif(component STREQUAL "Development")
list(APPEND _JAVA_REQUIRED_VARS Java_JAVA_EXECUTABLE Java_JAVAC_EXECUTABLE
- Java_JAVAH_EXECUTABLE Java_JAVADOC_EXECUTABLE)
- if(Java_JAVA_EXECUTABLE AND Java_JAVAC_EXECUTABLE
- AND Java_JAVAH_EXECUTABLE AND Java_JAVADOC_EXECUTABLE)
- set(Java_Development_FOUND TRUE)
+ Java_JAVADOC_EXECUTABLE)
+ if(Java_VERSION VERSION_LESS "1.10")
+ list(APPEND _JAVA_REQUIRED_VARS Java_JAVAH_EXECUTABLE)
+ if(Java_JAVA_EXECUTABLE AND Java_JAVAC_EXECUTABLE
+ AND Java_JAVAH_EXECUTABLE AND Java_JAVADOC_EXECUTABLE)
+ set(Java_Development_FOUND TRUE)
+ endif()
+ else()
+ if(Java_JAVA_EXECUTABLE AND Java_JAVAC_EXECUTABLE
+ AND Java_JAVADOC_EXECUTABLE)
+ set(Java_Development_FOUND TRUE)
+ endif()
endif()
elseif(component STREQUAL "IdlJ")
list(APPEND _JAVA_REQUIRED_VARS Java_IDLJ_EXECUTABLE)
@@ -268,11 +276,19 @@ if(Java_FIND_COMPONENTS)
endif()
else()
# Check for Development
- find_package_handle_standard_args(Java
- REQUIRED_VARS Java_JAVA_EXECUTABLE Java_JAR_EXECUTABLE Java_JAVAC_EXECUTABLE
- Java_JAVAH_EXECUTABLE Java_JAVADOC_EXECUTABLE
- VERSION_VAR Java_VERSION_STRING
- )
+ if(Java_VERSION VERSION_LESS "1.10")
+ find_package_handle_standard_args(Java
+ REQUIRED_VARS Java_JAVA_EXECUTABLE Java_JAR_EXECUTABLE Java_JAVAC_EXECUTABLE
+ Java_JAVAH_EXECUTABLE Java_JAVADOC_EXECUTABLE
+ VERSION_VAR Java_VERSION_STRING
+ )
+ else()
+ find_package_handle_standard_args(Java
+ REQUIRED_VARS Java_JAVA_EXECUTABLE Java_JAR_EXECUTABLE Java_JAVAC_EXECUTABLE
+ Java_JAVADOC_EXECUTABLE
+ VERSION_VAR Java_VERSION_STRING
+ )
+ endif()
endif()
diff --git a/Modules/FindOpenGL.cmake b/Modules/FindOpenGL.cmake
index 9ccd46bd7b..4d0786cd2f 100644
--- a/Modules/FindOpenGL.cmake
+++ b/Modules/FindOpenGL.cmake
@@ -22,7 +22,6 @@
# Defined to the platform-specific OpenGL libraries if the system has OpenGL.
# ``OpenGL::OpenGL``
# Defined to libOpenGL if the system is GLVND-based.
-# ``OpenGL::GL``
# ``OpenGL::GLU``
# Defined if the system has GLU.
# ``OpenGL::GLX``
diff --git a/Modules/FindOpenMP.cmake b/Modules/FindOpenMP.cmake
index 893ddc60c6..ced092e5fb 100644
--- a/Modules/FindOpenMP.cmake
+++ b/Modules/FindOpenMP.cmake
@@ -470,7 +470,7 @@ foreach(LANG IN LISTS OpenMP_FINDLIST)
if(OpenMP_${LANG}_FLAGS)
separate_arguments(_OpenMP_${LANG}_OPTIONS NATIVE_COMMAND "${OpenMP_${LANG}_FLAGS}")
set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY
- INTERFACE_COMPILE_OPTIONS "${_OpenMP_${LANG}_OPTIONS}")
+ INTERFACE_COMPILE_OPTIONS "$<$<COMPILE_LANGUAGE:${LANG}>:${_OpenMP_${LANG}_OPTIONS}>")
unset(_OpenMP_${LANG}_OPTIONS)
endif()
if(OpenMP_${LANG}_LIBRARIES)
diff --git a/Modules/FindPythonInterp.cmake b/Modules/FindPythonInterp.cmake
index 64b98a8791..3ef8e9f190 100644
--- a/Modules/FindPythonInterp.cmake
+++ b/Modules/FindPythonInterp.cmake
@@ -100,6 +100,9 @@ if(NOT PYTHON_EXECUTABLE)
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-32\\InstallPath]
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-64\\InstallPath]
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-32\\InstallPath]
+ [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}-64\\InstallPath]
)
endforeach()
endif()
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 353ee61ff4..bab642bdcd 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 10)
-set(CMake_VERSION_PATCH 20180119)
+set(CMake_VERSION_PATCH 20180124)
#set(CMake_VERSION_RC 1)
diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx
index addb54ea07..3e9bce91a6 100644
--- a/Source/CPack/cpack.cxx
+++ b/Source/CPack/cpack.cxx
@@ -98,6 +98,8 @@ int main(int argc, char const* const* argv)
argc = args.argc();
argv = args.argv();
+ cmSystemTools::EnableMSVCDebugHook();
+ cmSystemTools::InitializeLibUV();
cmSystemTools::FindCMakeResources(argv[0]);
cmCPackLog log;
@@ -106,8 +108,6 @@ int main(int argc, char const* const* argv)
log.SetOutputPrefix("CPack: ");
log.SetVerbosePrefix("CPack Verbose: ");
- cmSystemTools::EnableMSVCDebugHook();
-
if (cmSystemTools::GetCurrentWorkingDirectory().empty()) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
"Current working directory cannot be established."
diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx
index 97d5579c28..17cf6289a8 100644
--- a/Source/CursesDialog/ccmake.cxx
+++ b/Source/CursesDialog/ccmake.cxx
@@ -75,6 +75,7 @@ int main(int argc, char const* const* argv)
argc = encoding_args.argc();
argv = encoding_args.argv();
+ cmSystemTools::InitializeLibUV();
cmSystemTools::FindCMakeResources(argv[0]);
cmDocumentation doc;
doc.addCMakeStandardDocSections();
diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx
index bfd43cfded..193f4d3230 100644
--- a/Source/QtDialog/CMakeSetup.cxx
+++ b/Source/QtDialog/CMakeSetup.cxx
@@ -55,6 +55,7 @@ int main(int argc, char** argv)
int argc2 = encoding_args.argc();
char const* const* argv2 = encoding_args.argv();
+ cmSystemTools::InitializeLibUV();
cmSystemTools::FindCMakeResources(argv2[0]);
// check docs first so that X is not need to get docs
// do docs, if args were given
diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx
index 44095ec147..64aa46e1d0 100644
--- a/Source/cmCacheManager.cxx
+++ b/Source/cmCacheManager.cxx
@@ -10,6 +10,7 @@
#include <string.h>
#include "cmGeneratedFileStream.h"
+#include "cmMessenger.h"
#include "cmState.h"
#include "cmSystemTools.h"
#include "cmVersion.h"
@@ -205,7 +206,8 @@ bool cmCacheManager::ReadPropertyEntry(std::string const& entryKey,
return false;
}
-void cmCacheManager::WritePropertyEntries(std::ostream& os, CacheIterator i)
+void cmCacheManager::WritePropertyEntries(std::ostream& os, CacheIterator i,
+ cmMessenger* messenger)
{
for (const char** p = this->PersistentProperties; *p; ++p) {
if (const char* value = i.GetProperty(*p)) {
@@ -221,11 +223,13 @@ void cmCacheManager::WritePropertyEntries(std::ostream& os, CacheIterator i)
os << ":INTERNAL=";
this->OutputValue(os, value);
os << "\n";
+ cmCacheManager::OutputNewlineTruncationWarning(os, key, value,
+ messenger);
}
}
}
-bool cmCacheManager::SaveCache(const std::string& path)
+bool cmCacheManager::SaveCache(const std::string& path, cmMessenger* messenger)
{
std::string cacheFile = path;
cacheFile += "/CMakeCache.txt";
@@ -316,7 +320,10 @@ bool cmCacheManager::SaveCache(const std::string& path)
this->OutputKey(fout, i.first);
fout << ":" << cmState::CacheEntryTypeToString(t) << "=";
this->OutputValue(fout, ce.Value);
- fout << "\n\n";
+ fout << "\n";
+ cmCacheManager::OutputNewlineTruncationWarning(fout, i.first, ce.Value,
+ messenger);
+ fout << "\n";
}
}
@@ -333,7 +340,7 @@ bool cmCacheManager::SaveCache(const std::string& path)
}
cmStateEnums::CacheEntryType t = i.GetType();
- this->WritePropertyEntries(fout, i);
+ this->WritePropertyEntries(fout, i, messenger);
if (t == cmStateEnums::INTERNAL) {
// Format is key:type=value
if (const char* help = i.GetProperty("HELPSTRING")) {
@@ -343,6 +350,8 @@ bool cmCacheManager::SaveCache(const std::string& path)
fout << ":" << cmState::CacheEntryTypeToString(t) << "=";
this->OutputValue(fout, i.GetValue());
fout << "\n";
+ cmCacheManager::OutputNewlineTruncationWarning(fout, i.GetName(),
+ i.GetValue(), messenger);
}
}
fout << "\n";
@@ -390,6 +399,19 @@ void cmCacheManager::OutputKey(std::ostream& fout, std::string const& key)
void cmCacheManager::OutputValue(std::ostream& fout, std::string const& value)
{
+ // look for and truncate newlines
+ std::string::size_type newline = value.find('\n');
+ if (newline != std::string::npos) {
+ std::string truncated = value.substr(0, newline);
+ OutputValueNoNewlines(fout, truncated);
+ } else {
+ OutputValueNoNewlines(fout, value);
+ }
+}
+
+void cmCacheManager::OutputValueNoNewlines(std::ostream& fout,
+ std::string const& value)
+{
// if value has trailing space or tab, enclose it in single quotes
if (!value.empty() &&
(value[value.size() - 1] == ' ' || value[value.size() - 1] == '\t')) {
@@ -423,6 +445,50 @@ void cmCacheManager::OutputHelpString(std::ostream& fout,
}
}
+void cmCacheManager::OutputWarningComment(std::ostream& fout,
+ std::string const& message,
+ bool wrapSpaces)
+{
+ std::string::size_type end = message.size();
+ std::string oneLine;
+ std::string::size_type pos = 0;
+ for (std::string::size_type i = 0; i <= end; i++) {
+ if ((i == end) || (message[i] == '\n') ||
+ ((i - pos >= 60) && (message[i] == ' ') && wrapSpaces)) {
+ fout << "# ";
+ if (message[pos] == '\n') {
+ pos++;
+ fout << "\\n";
+ }
+ oneLine = message.substr(pos, i - pos);
+ fout << oneLine << "\n";
+ pos = i;
+ }
+ }
+}
+
+void cmCacheManager::OutputNewlineTruncationWarning(std::ostream& fout,
+ std::string const& key,
+ std::string const& value,
+ cmMessenger* messenger)
+{
+ if (value.find('\n') != std::string::npos) {
+ if (messenger) {
+ std::string message = "Value of ";
+ message += key;
+ message += " contained a newline; truncating";
+ messenger->IssueMessage(cmake::WARNING, message);
+ }
+
+ std::string comment = "WARNING: Value of ";
+ comment += key;
+ comment += " contained a newline and was truncated. Original value:";
+
+ OutputWarningComment(fout, comment, true);
+ OutputWarningComment(fout, value, false);
+ }
+}
+
void cmCacheManager::RemoveCacheEntry(const std::string& key)
{
CacheEntryMap::iterator i = this->Cache.find(key);
diff --git a/Source/cmCacheManager.h b/Source/cmCacheManager.h
index 28cba853ff..73923d1f50 100644
--- a/Source/cmCacheManager.h
+++ b/Source/cmCacheManager.h
@@ -15,7 +15,7 @@
#include "cmPropertyMap.h"
#include "cmStateTypes.h"
-class cmake;
+class cmMessenger;
/** \class cmCacheManager
* \brief Control class for cmake's cache
@@ -108,7 +108,7 @@ public:
std::set<std::string>& includes);
///! Save cache for given makefile. Saves to output path/CMakeCache.txt
- bool SaveCache(const std::string& path);
+ bool SaveCache(const std::string& path, cmMessenger* messenger);
///! Delete the cache given
bool DeleteCache(const std::string& path);
@@ -218,16 +218,25 @@ protected:
unsigned int CacheMinorVersion;
private:
- cmake* CMakeInstance;
typedef std::map<std::string, CacheEntry> CacheEntryMap;
static void OutputHelpString(std::ostream& fout,
const std::string& helpString);
+ static void OutputWarningComment(std::ostream& fout,
+ std::string const& message,
+ bool wrapSpaces);
+ static void OutputNewlineTruncationWarning(std::ostream& fout,
+ std::string const& key,
+ std::string const& value,
+ cmMessenger* messenger);
static void OutputKey(std::ostream& fout, std::string const& key);
static void OutputValue(std::ostream& fout, std::string const& value);
+ static void OutputValueNoNewlines(std::ostream& fout,
+ std::string const& value);
static const char* PersistentProperties[];
bool ReadPropertyEntry(std::string const& key, CacheEntry& e);
- void WritePropertyEntries(std::ostream& os, CacheIterator i);
+ void WritePropertyEntries(std::ostream& os, CacheIterator i,
+ cmMessenger* messenger);
CacheEntryMap Cache;
// Only cmake and cmState should be able to add cache values
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index fb13a585b3..18cca5a403 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -913,11 +913,9 @@ std::string cmComputeLinkInformation::CreateExtensionRegex(
// Finish the list.
libext += ")";
- // Add an optional OpenBSD version component.
- if (this->OpenBSD) {
- libext += "(\\.[0-9]+\\.[0-9]+)?";
- } else if (type == LinkShared) {
- libext += "(\\.[0-9]+)?";
+ // Add an optional OpenBSD-style version or major.minor.version component.
+ if (this->OpenBSD || type == LinkShared) {
+ libext += "(\\.[0-9]+)*";
}
libext += "$";
diff --git a/Source/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx
index 4958007947..fad0723aca 100644
--- a/Source/cmExtraCodeLiteGenerator.cxx
+++ b/Source/cmExtraCodeLiteGenerator.cxx
@@ -198,8 +198,6 @@ std::string cmExtraCodeLiteGenerator::CollectSourceFiles(
std::map<std::string, cmSourceFile*>& cFiles,
std::set<std::string>& otherFiles)
{
- auto cm = this->GlobalGenerator->GetCMakeInstance();
-
std::string projectType;
switch (gt->GetType()) {
case cmStateEnums::EXECUTABLE: {
@@ -227,19 +225,18 @@ std::string cmExtraCodeLiteGenerator::CollectSourceFiles(
gt->GetSourceFiles(sources,
makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"));
for (cmSourceFile* s : sources) {
- // check whether it is a C/C++/CUDA implementation file
- bool isCFile = false;
- std::string lang = s->GetLanguage();
- if (lang == "C" || lang == "CXX" || lang == "CUDA") {
- std::string const& srcext = s->GetExtension();
- isCFile = cm->IsSourceExtension(srcext);
- }
-
+ // check whether it is a source or a include file
// then put it accordingly into one of the two containers
- if (isCFile) {
- cFiles[s->GetFullPath()] = s;
- } else {
- otherFiles.insert(s->GetFullPath());
+ switch (cmSystemTools::GetFileFormat(s->GetExtension().c_str())) {
+ case cmSystemTools::C_FILE_FORMAT:
+ case cmSystemTools::CXX_FILE_FORMAT:
+ case cmSystemTools::CUDA_FILE_FORMAT:
+ case cmSystemTools::FORTRAN_FILE_FORMAT: {
+ cFiles[s->GetFullPath()] = s;
+ } break;
+ default: {
+ otherFiles.insert(s->GetFullPath());
+ }
}
}
}
@@ -679,7 +676,11 @@ std::string cmExtraCodeLiteGenerator::GetSingleFileBuildCommand(
std::string generator = mf->GetSafeDefinition("CMAKE_GENERATOR");
if (generator == "Unix Makefiles" || generator == "MinGW Makefiles") {
std::ostringstream ss;
- ss << make << " -f$(ProjectPath)/Makefile $(CurrentFileName).cpp.o";
+#if defined(_WIN32)
+ ss << make << " -f$(ProjectPath)/Makefile -B $(CurrentFileFullName).obj";
+#else
+ ss << make << " -f$(ProjectPath)/Makefile -B $(CurrentFileFullName).o";
+#endif
buildCommand = ss.str();
}
return buildCommand;
diff --git a/Source/cmGeneratorExpressionEvaluationFile.cxx b/Source/cmGeneratorExpressionEvaluationFile.cxx
index 87b6b342db..c9889699be 100644
--- a/Source/cmGeneratorExpressionEvaluationFile.cxx
+++ b/Source/cmGeneratorExpressionEvaluationFile.cxx
@@ -13,6 +13,7 @@
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmSourceFile.h"
+#include "cmSourceFileLocationKind.h"
#include "cmSystemTools.h"
#include "cmake.h"
@@ -102,7 +103,8 @@ void cmGeneratorExpressionEvaluationFile::CreateOutputFile(
for (std::string const& le : enabledLanguages) {
std::string name = this->OutputFileExpr->Evaluate(
lg, config, false, nullptr, nullptr, nullptr, le);
- cmSourceFile* sf = lg->GetMakefile()->GetOrCreateSource(name);
+ cmSourceFile* sf = lg->GetMakefile()->GetOrCreateSource(
+ name, false, cmSourceFileLocationKind::Known);
sf->SetProperty("GENERATED", "1");
gg->SetFilenameTargetDepends(
diff --git a/Source/cmQtAutoGeneratorMocUic.cxx b/Source/cmQtAutoGeneratorMocUic.cxx
index 4b02e0bf87..037279a87f 100644
--- a/Source/cmQtAutoGeneratorMocUic.cxx
+++ b/Source/cmQtAutoGeneratorMocUic.cxx
@@ -221,7 +221,7 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk,
const char* contentChars = meta.Content.c_str();
cmsys::RegularExpressionMatch match;
while (wrk.Moc().RegExpInclude.find(contentChars, match)) {
- std::string incString = match.match(1);
+ std::string incString = match.match(2);
std::string incDir(SubDirPrefix(incString));
std::string incBase =
cmSystemTools::GetFilenameWithoutLastExtension(incString);
@@ -500,7 +500,7 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseUic(WorkerT& wrk,
const char* contentChars = meta.Content.c_str();
cmsys::RegularExpressionMatch match;
while (wrk.Uic().RegExpInclude.find(contentChars, match)) {
- if (!ParseUicInclude(wrk, meta, match.match(1))) {
+ if (!ParseUicInclude(wrk, meta, match.match(2))) {
success = false;
break;
}
@@ -1124,9 +1124,9 @@ cmQtAutoGeneratorMocUic::cmQtAutoGeneratorMocUic()
{
// Precompile regular expressions
Moc_.RegExpInclude.compile(
- "[\n][ \t]*#[ \t]*include[ \t]+"
+ "(^|\n)[ \t]*#[ \t]*include[ \t]+"
"[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]");
- Uic_.RegExpInclude.compile("[\n][ \t]*#[ \t]*include[ \t]+"
+ Uic_.RegExpInclude.compile("(^|\n)[ \t]*#[ \t]*include[ \t]+"
"[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]");
// Initialize libuv asynchronous iteration request
diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx
index 6b7143b583..4c0a354be6 100644
--- a/Source/cmServerProtocol.cxx
+++ b/Source/cmServerProtocol.cxx
@@ -1034,8 +1034,8 @@ static Json::Value DumpProjectList(const cmake* cm, std::string const& config)
// Project structure information:
const cmMakefile* mf = lg->GetMakefile();
- pObj[kMINIMUM_CMAKE_VERSION] =
- mf->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION");
+ auto minVersion = mf->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION");
+ pObj[kMINIMUM_CMAKE_VERSION] = minVersion ? minVersion : "";
pObj[kSOURCE_DIRECTORY_KEY] = mf->GetCurrentSourceDirectory();
pObj[kBUILD_DIRECTORY_KEY] = mf->GetCurrentBinaryDirectory();
pObj[kTARGETS_KEY] = DumpTargetsList(projectIt.second, config);
diff --git a/Source/cmState.cxx b/Source/cmState.cxx
index 5957b5bb29..00d7e9a254 100644
--- a/Source/cmState.cxx
+++ b/Source/cmState.cxx
@@ -107,9 +107,9 @@ bool cmState::LoadCache(const std::string& path, bool internal,
return this->CacheManager->LoadCache(path, internal, excludes, includes);
}
-bool cmState::SaveCache(const std::string& path)
+bool cmState::SaveCache(const std::string& path, cmMessenger* messenger)
{
- return this->CacheManager->SaveCache(path);
+ return this->CacheManager->SaveCache(path, messenger);
}
bool cmState::DeleteCache(const std::string& path)
diff --git a/Source/cmState.h b/Source/cmState.h
index e03ad8981d..7282f0abb8 100644
--- a/Source/cmState.h
+++ b/Source/cmState.h
@@ -23,6 +23,7 @@ class cmCacheManager;
class cmCommand;
class cmPropertyDefinition;
class cmStateSnapshot;
+class cmMessenger;
class cmState
{
@@ -59,7 +60,7 @@ public:
std::set<std::string>& excludes,
std::set<std::string>& includes);
- bool SaveCache(const std::string& path);
+ bool SaveCache(const std::string& path, cmMessenger* messenger);
bool DeleteCache(const std::string& path);
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index c321236220..06b0b3c233 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -51,6 +51,8 @@
// include wincrypt.h after windows.h
#include <wincrypt.h>
+#include <fcntl.h> /* _O_TEXT */
+
#include "cm_uv.h"
#else
#include <sys/time.h>
@@ -980,6 +982,21 @@ std::string cmSystemTools::GetRealPath(const std::string& path,
}
#endif
+void cmSystemTools::InitializeLibUV()
+{
+#if defined(_WIN32)
+ // Perform libuv one-time initialization now, and then un-do its
+ // global _fmode setting so that using libuv does not change the
+ // default file text/binary mode. See libuv issue 840.
+ uv_loop_close(uv_default_loop());
+#ifdef _MSC_VER
+ _set_fmode(_O_TEXT);
+#else
+ _fmode = _O_TEXT;
+#endif
+#endif
+}
+
bool cmSystemTools::RenameFile(const char* oldname, const char* newname)
{
#ifdef _WIN32
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index d29ba56dc0..25df1f1405 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -503,6 +503,10 @@ public:
static std::string GetRealPath(const std::string& path,
std::string* errorMessage = 0);
#endif
+
+ /** Perform one-time initialization of libuv. */
+ static void InitializeLibUV();
+
private:
static bool s_ForceUnixPaths;
static bool s_RunCommandHideConsole;
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 1b09600d0e..a51133716a 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -1992,7 +1992,7 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
if (si.Kind == cmGeneratorTarget::SourceKindObjectSource) {
// FIXME: refactor generation to avoid tracking XML syntax state.
- this->WriteSource(tool, si.Source, " ");
+ this->WriteSource(tool, si.Source, "");
bool have_nested = this->OutputSourceSpecificFlags(si.Source);
if (!exclude_configs.empty()) {
if (!have_nested) {
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 2341dd6641..480646e4d1 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -1771,7 +1771,7 @@ bool cmake::LoadCache(const std::string& path, bool internal,
bool cmake::SaveCache(const std::string& path)
{
- bool result = this->State->SaveCache(path);
+ bool result = this->State->SaveCache(path, this->GetMessenger());
static const char* entries[] = { "CMAKE_CACHE_MAJOR_VERSION",
"CMAKE_CACHE_MINOR_VERSION",
"CMAKE_CACHE_PATCH_VERSION",
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index 59b908a167..b185a1bc4a 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -16,10 +16,6 @@
#include "cmDynamicLoader.h"
#endif
-#ifdef _WIN32
-#include <fcntl.h> /* _O_TEXT */
-#include <stdlib.h> /* _set_fmode, _fmode */
-#endif
#include "cm_uv.h"
#include "cmsys/Encoding.hxx"
@@ -170,19 +166,8 @@ int main(int ac, char const* const* av)
ac = args.argc();
av = args.argv();
-#if defined(_WIN32)
- // Perform libuv one-time initialization now, and then un-do its
- // global _fmode setting so that using libuv does not change the
- // default file text/binary mode. See libuv issue 840.
- uv_loop_close(uv_default_loop());
-#ifdef _MSC_VER
- _set_fmode(_O_TEXT);
-#else
- _fmode = _O_TEXT;
-#endif
-#endif
-
cmSystemTools::EnableMSVCDebugHook();
+ cmSystemTools::InitializeLibUV();
cmSystemTools::FindCMakeResources(av[0]);
if (ac > 1) {
if (strcmp(av[1], "--build") == 0) {
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index f660f43d06..2c3bda2afc 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -103,7 +103,7 @@ void CMakeCommandUsage(const char* program)
<< " sleep <number>... - sleep for given number of seconds\n"
<< " tar [cxt][vf][zjJ] file.tar [file/dir1 file/dir2 ...]\n"
<< " - create or extract a tar or zip archive\n"
- << " time command [args...] - run command and return elapsed time\n"
+ << " time command [args...] - run command and display elapsed time\n"
<< " touch file - touch a file.\n"
<< " touch_nocreate file - touch a file but do not create it.\n"
#if defined(_WIN32) && !defined(__CYGWIN__)
diff --git a/Source/ctest.cxx b/Source/ctest.cxx
index ad5fec0af8..0a6d1d25dd 100644
--- a/Source/ctest.cxx
+++ b/Source/ctest.cxx
@@ -137,6 +137,7 @@ int main(int argc, char const* const* argv)
cmSystemTools::DoNotInheritStdPipes();
cmSystemTools::EnableMSVCDebugHook();
+ cmSystemTools::InitializeLibUV();
cmSystemTools::FindCMakeResources(argv[0]);
// Dispatch 'ctest --launch' mode directly.
diff --git a/Tests/FindBoost/CMakeLists.txt b/Tests/FindBoost/CMakeLists.txt
index 0e9527de02..17a8ec7009 100644
--- a/Tests/FindBoost/CMakeLists.txt
+++ b/Tests/FindBoost/CMakeLists.txt
@@ -9,6 +9,20 @@ add_test(NAME FindBoost.Test COMMAND
--test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
)
+add_test(NAME FindBoost.TestFail COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindBoost/TestFail"
+ "${CMake_BINARY_DIR}/Tests/FindBoost/TestFail"
+ ${build_generator_args}
+ --build-project TestFailFindBoost
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
+
+set_tests_properties(FindBoost.TestFail PROPERTIES
+ PASS_REGULAR_EXPRESSION "Could not find the following Boost libraries:[ \t\n]+boost_foobar")
+
add_test(NAME FindBoost.TestHeaders COMMAND
${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
--build-and-test
diff --git a/Tests/FindBoost/Test/CMakeLists.txt b/Tests/FindBoost/Test/CMakeLists.txt
index ce50fc7753..663f414720 100644
--- a/Tests/FindBoost/Test/CMakeLists.txt
+++ b/Tests/FindBoost/Test/CMakeLists.txt
@@ -2,7 +2,16 @@ cmake_minimum_required(VERSION 3.1)
project(TestFindBoost CXX)
include(CTest)
-find_package(Boost REQUIRED COMPONENTS filesystem thread)
+find_package(Boost REQUIRED COMPONENTS filesystem thread
+ OPTIONAL_COMPONENTS program_options foobar)
+
+if(Boost_FOOBAR_FOUND)
+ message(FATAL_ERROR "Optional inexistent Boost component \"foobar\" found which is unexpected")
+endif(Boost_FOOBAR_FOUND)
+
+if(NOT Boost_PROGRAM_OPTIONS_FOUND)
+ message(FATAL_ERROR "Optional Boost component \"program_options\" not found which is unexpected")
+endif(NOT Boost_PROGRAM_OPTIONS_FOUND)
add_executable(test_boost_tgt main.cxx)
target_link_libraries(test_boost_tgt
diff --git a/Tests/FindBoost/TestFail/CMakeLists.txt b/Tests/FindBoost/TestFail/CMakeLists.txt
new file mode 100644
index 0000000000..7c14a59905
--- /dev/null
+++ b/Tests/FindBoost/TestFail/CMakeLists.txt
@@ -0,0 +1,18 @@
+cmake_minimum_required(VERSION 3.1)
+project(TestFindBoost CXX)
+include(CTest)
+
+find_package(Boost REQUIRED COMPONENTS foobar filesystem thread)
+
+add_executable(test_boost_tgt main.cxx)
+target_link_libraries(test_boost_tgt
+ Boost::dynamic_linking
+ Boost::disable_autolinking
+ Boost::filesystem
+ Boost::thread)
+add_test(NAME test_boost_tgt COMMAND test_boost_tgt)
+
+add_executable(test_boost_var main.cxx)
+target_include_directories(test_boost_var PRIVATE ${Boost_INCLUDE_DIRS})
+target_link_libraries(test_boost_var PRIVATE ${Boost_FILESYSTEM_LIBRARIES} ${Boost_SYSTEM_LIBRARIES} ${Boost_THREAD_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
+add_test(NAME test_boost_var COMMAND test_boost_var)
diff --git a/Tests/FindBoost/TestFail/main.cxx b/Tests/FindBoost/TestFail/main.cxx
new file mode 100644
index 0000000000..6e8b5da630
--- /dev/null
+++ b/Tests/FindBoost/TestFail/main.cxx
@@ -0,0 +1,24 @@
+#include <boost/filesystem.hpp>
+#include <boost/thread.hpp>
+
+namespace {
+
+boost::mutex m1;
+boost::recursive_mutex m2;
+
+void threadmain()
+{
+ boost::lock_guard<boost::mutex> lock1(m1);
+ boost::lock_guard<boost::recursive_mutex> lock2(m2);
+
+ boost::filesystem::path p(boost::filesystem::current_path());
+}
+}
+
+int main()
+{
+ boost::thread foo(threadmain);
+ foo.join();
+
+ return 0;
+}
diff --git a/Tests/QtAutogen/CommonTests.cmake b/Tests/QtAutogen/CommonTests.cmake
index 2c2e6d6c04..094a75583b 100644
--- a/Tests/QtAutogen/CommonTests.cmake
+++ b/Tests/QtAutogen/CommonTests.cmake
@@ -1,9 +1,7 @@
# Autogen tests common for Qt4 and Qt5
ADD_AUTOGEN_TEST(MocOnly mocOnly)
ADD_AUTOGEN_TEST(MocOptions mocOptions)
-if(QT_TEST_ALLOW_QT_MACROS)
- ADD_AUTOGEN_TEST(UicOnly uicOnly)
-endif()
+ADD_AUTOGEN_TEST(UicOnly uicOnly)
ADD_AUTOGEN_TEST(RccOnly rccOnly)
ADD_AUTOGEN_TEST(RccEmpty rccEmpty)
ADD_AUTOGEN_TEST(RccOffMocLibrary)
diff --git a/Tests/QtAutogen/MocOnly/CMakeLists.txt b/Tests/QtAutogen/MocOnly/CMakeLists.txt
index 33feadf338..a37a2ae7ce 100644
--- a/Tests/QtAutogen/MocOnly/CMakeLists.txt
+++ b/Tests/QtAutogen/MocOnly/CMakeLists.txt
@@ -2,7 +2,14 @@ cmake_minimum_required(VERSION 3.10)
project(MocOnly)
include("../AutogenTest.cmake")
-# Test different Q_OBJECT position styles
-add_executable(mocOnly StyleA.cpp StyleB.cpp main.cpp)
+add_executable(mocOnly
+ main.cpp
+ # Test different Q_OBJECT position styles
+ StyleA.cpp
+ StyleB.cpp
+ # Test different moc_/.moc include positions
+ IncA.cpp
+ IncB.cpp
+)
set_property(TARGET mocOnly PROPERTY AUTOMOC ON)
target_link_libraries(mocOnly ${QT_LIBRARIES})
diff --git a/Tests/QtAutogen/MocOnly/IncA.cpp b/Tests/QtAutogen/MocOnly/IncA.cpp
new file mode 100644
index 0000000000..94610cd481
--- /dev/null
+++ b/Tests/QtAutogen/MocOnly/IncA.cpp
@@ -0,0 +1,19 @@
+#include "moc_IncA.cpp"
+/// AUTOMOC moc_ include on the first line of the file!
+#include "IncA.hpp"
+
+/// @brief Source local QObject
+///
+class IncAPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ IncAPrivate(){};
+};
+
+IncA::IncA()
+{
+ IncAPrivate priv;
+}
+
+#include "IncA.moc"
diff --git a/Tests/QtAutogen/MocOnly/IncA.hpp b/Tests/QtAutogen/MocOnly/IncA.hpp
new file mode 100644
index 0000000000..ecc889f9d9
--- /dev/null
+++ b/Tests/QtAutogen/MocOnly/IncA.hpp
@@ -0,0 +1,15 @@
+#ifndef INCA_HPP
+#define INCA_HPP
+
+#include <QObject>
+
+/// @brief Test moc include pattern in the source file
+///
+class IncA : public QObject
+{
+ Q_OBJECT
+public:
+ IncA();
+};
+
+#endif
diff --git a/Tests/QtAutogen/MocOnly/IncB.cpp b/Tests/QtAutogen/MocOnly/IncB.cpp
new file mode 100644
index 0000000000..bd441a978c
--- /dev/null
+++ b/Tests/QtAutogen/MocOnly/IncB.cpp
@@ -0,0 +1,19 @@
+#include "IncB.hpp"
+
+/// @brief Source local QObject
+///
+class IncBPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ IncBPrivate(){};
+};
+
+IncB::IncB()
+{
+ IncBPrivate priv;
+}
+
+/// AUTOMOC moc_ include on the last line of the file!
+#include "IncB.moc"
+#include "moc_IncB.cpp"
diff --git a/Tests/QtAutogen/MocOnly/IncB.hpp b/Tests/QtAutogen/MocOnly/IncB.hpp
new file mode 100644
index 0000000000..8331ea2b7a
--- /dev/null
+++ b/Tests/QtAutogen/MocOnly/IncB.hpp
@@ -0,0 +1,15 @@
+#ifndef INCB_HPP
+#define INCB_HPP
+
+#include <QObject>
+
+/// @brief Test moc include pattern in the source file
+///
+class IncB : public QObject
+{
+ Q_OBJECT
+public:
+ IncB();
+};
+
+#endif
diff --git a/Tests/QtAutogen/MocOnly/main.cpp b/Tests/QtAutogen/MocOnly/main.cpp
index 06f8d81060..1611f9744d 100644
--- a/Tests/QtAutogen/MocOnly/main.cpp
+++ b/Tests/QtAutogen/MocOnly/main.cpp
@@ -1,3 +1,5 @@
+#include "IncA.hpp"
+#include "IncB.hpp"
#include "StyleA.hpp"
#include "StyleB.hpp"
@@ -5,5 +7,8 @@ int main(int argv, char** args)
{
StyleA styleA;
StyleB styleB;
+ IncA incA;
+ IncB incB;
+
return 0;
}
diff --git a/Tests/QtAutogen/UicOnly/CMakeLists.txt b/Tests/QtAutogen/UicOnly/CMakeLists.txt
index 89a9a1baa6..f927f72977 100644
--- a/Tests/QtAutogen/UicOnly/CMakeLists.txt
+++ b/Tests/QtAutogen/UicOnly/CMakeLists.txt
@@ -3,8 +3,6 @@ project(UicOnly)
include("../AutogenTest.cmake")
# Test AUTOUIC being enabled only
-# The moc is provided by the Qt macro
-qtx_wrap_cpp(uicOnlyMoc uiconly.h)
-add_executable(uicOnly uiconly.cpp ${uicOnlyMoc})
+add_executable(uicOnly main.cpp UicOnly.cpp)
set_property(TARGET uicOnly PROPERTY AUTOUIC ON)
target_link_libraries(uicOnly ${QT_LIBRARIES})
diff --git a/Tests/QtAutogen/UicOnly/UicOnly.cpp b/Tests/QtAutogen/UicOnly/UicOnly.cpp
new file mode 100644
index 0000000000..8eee6d2138
--- /dev/null
+++ b/Tests/QtAutogen/UicOnly/UicOnly.cpp
@@ -0,0 +1,18 @@
+#include "ui_uiC.h"
+#include "ui_uiD.h"
+// AUTOUIC includes on the first two lines of a source file
+#include "UicOnly.hpp"
+
+UicOnly::UicOnly()
+ : uiA(new Ui::UiA)
+ , uiB(new Ui::UiB)
+{
+ Ui::UiC uiC;
+ Ui::UiD uiD;
+}
+
+UicOnly::~UicOnly()
+{
+ delete uiB;
+ delete uiA;
+}
diff --git a/Tests/QtAutogen/UicOnly/UicOnly.hpp b/Tests/QtAutogen/UicOnly/UicOnly.hpp
new file mode 100644
index 0000000000..24e1e0b946
--- /dev/null
+++ b/Tests/QtAutogen/UicOnly/UicOnly.hpp
@@ -0,0 +1,15 @@
+#include "ui_uiA.h"
+#include "ui_uiB.h"
+// AUTOUIC includes on the first two lines of a header file
+#include <QObject>
+
+class UicOnly : public QObject
+{
+public:
+ UicOnly();
+ ~UicOnly();
+
+private:
+ Ui::UiA* uiA;
+ Ui::UiB* uiB;
+};
diff --git a/Tests/QtAutogen/UicOnly/main.cpp b/Tests/QtAutogen/UicOnly/main.cpp
new file mode 100644
index 0000000000..bdd242ec29
--- /dev/null
+++ b/Tests/QtAutogen/UicOnly/main.cpp
@@ -0,0 +1,7 @@
+#include "UicOnly.hpp"
+
+int main(int argc, char* argv[])
+{
+ UicOnly uicOnly;
+ return 0;
+}
diff --git a/Tests/QtAutogen/UicOnly/uiconly.ui b/Tests/QtAutogen/UicOnly/uiA.ui
index 13fb832eb7..4c5762e82e 100644
--- a/Tests/QtAutogen/UicOnly/uiconly.ui
+++ b/Tests/QtAutogen/UicOnly/uiA.ui
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
- <class>UicOnly</class>
- <widget class="QWidget" name="UicOnly">
+ <class>UiA</class>
+ <widget class="QWidget" name="UiA">
<property name="geometry">
<rect>
<x>0</x>
diff --git a/Tests/QtAutogen/UicOnly/uiB.ui b/Tests/QtAutogen/UicOnly/uiB.ui
new file mode 100644
index 0000000000..6ca77dec36
--- /dev/null
+++ b/Tests/QtAutogen/UicOnly/uiB.ui
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>UiB</class>
+ <widget class="QWidget" name="UiB">
+ <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/QtAutogen/UicOnly/uiC.ui b/Tests/QtAutogen/UicOnly/uiC.ui
new file mode 100644
index 0000000000..6802550cb3
--- /dev/null
+++ b/Tests/QtAutogen/UicOnly/uiC.ui
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>UiC</class>
+ <widget class="QWidget" name="UiC">
+ <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/QtAutogen/UicOnly/uiD.ui b/Tests/QtAutogen/UicOnly/uiD.ui
new file mode 100644
index 0000000000..aad79cf7f4
--- /dev/null
+++ b/Tests/QtAutogen/UicOnly/uiD.ui
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>UiD</class>
+ <widget class="QWidget" name="UiD">
+ <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/QtAutogen/UicOnly/uiconly.cpp b/Tests/QtAutogen/UicOnly/uiconly.cpp
deleted file mode 100644
index 7b91b251fa..0000000000
--- a/Tests/QtAutogen/UicOnly/uiconly.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-
-#include "uiconly.h"
-
-UicOnly::UicOnly(QWidget* parent)
- : QWidget(parent)
- , ui(new Ui::UicOnly)
-{
-}
-
-UicOnly::~UicOnly()
-{
- delete ui;
-}
-
-int main()
-{
- return 0;
-}
diff --git a/Tests/QtAutogen/UicOnly/uiconly.h b/Tests/QtAutogen/UicOnly/uiconly.h
deleted file mode 100644
index 8f4eebe1e8..0000000000
--- a/Tests/QtAutogen/UicOnly/uiconly.h
+++ /dev/null
@@ -1,20 +0,0 @@
-
-#ifndef UIC_ONLY_H
-#define UIC_ONLY_H
-
-#include <QWidget>
-
-#include "ui_uiconly.h"
-
-class UicOnly : public QWidget
-{
- Q_OBJECT
-public:
- explicit UicOnly(QWidget* parent = 0);
- ~UicOnly();
-
-private:
- Ui::UicOnly* ui;
-};
-
-#endif
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index edd6c7960b..e440b7f438 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -339,6 +339,7 @@ add_RunCMake_test(CPackInstallProperties)
add_RunCMake_test(ExternalProject)
add_RunCMake_test(FetchContent)
add_RunCMake_test(CTestCommandLine)
+add_RunCMake_test(CacheNewline)
# Only run this test on unix platforms that support
# symbolic links
if(UNIX)
diff --git a/Tests/RunCMake/CacheNewline/CMakeLists.txt b/Tests/RunCMake/CacheNewline/CMakeLists.txt
new file mode 100644
index 0000000000..93ee9dfd5f
--- /dev/null
+++ b/Tests/RunCMake/CacheNewline/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.5)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/CacheNewline/CacheNewline-check.cmake b/Tests/RunCMake/CacheNewline/CacheNewline-check.cmake
new file mode 100644
index 0000000000..6534f6386d
--- /dev/null
+++ b/Tests/RunCMake/CacheNewline/CacheNewline-check.cmake
@@ -0,0 +1,16 @@
+set(CACHE_EXPECTED_FILE "${RunCMake_TEST_SOURCE_DIR}/cache-regex.txt")
+set(CACHE_ACTUAL_FILE "${RunCMake_BINARY_DIR}/CacheNewline-build/CMakeCache.txt")
+
+file(READ ${CACHE_EXPECTED_FILE} CACHE_EXPECTED)
+string(REGEX REPLACE "\r\n" "\n" CACHE_EXPECTED "${CACHE_EXPECTED}")
+string(REGEX REPLACE "\n+$" "" CACHE_EXPECTED "${CACHE_EXPECTED}")
+file(READ ${CACHE_ACTUAL_FILE} CACHE_ACTUAL)
+string(REGEX REPLACE "\r\n" "\n" CACHE_ACTUAL "${CACHE_ACTUAL}")
+string(REGEX REPLACE "\n+$" "" CACHE_ACTUAL "${CACHE_ACTUAL}")
+
+if(NOT "${CACHE_ACTUAL}" MATCHES "${CACHE_EXPECTED}")
+ set(RunCMake_TEST_FAILED "${CACHE_ACTUAL_FILE} does not match ${CACHE_EXPECTED_FILE}:
+
+CMakeCache.txt contents = [\n${CACHE_ACTUAL}\n]
+Expected = [\n${CACHE_EXPECTED}\n]")
+endif()
diff --git a/Tests/RunCMake/CacheNewline/CacheNewline-stderr.txt b/Tests/RunCMake/CacheNewline/CacheNewline-stderr.txt
new file mode 100644
index 0000000000..726c65ce02
--- /dev/null
+++ b/Tests/RunCMake/CacheNewline/CacheNewline-stderr.txt
@@ -0,0 +1,2 @@
+CMake Warning:
+ Value of NEWLINE_VARIABLE contained a newline; truncating
diff --git a/Tests/RunCMake/CacheNewline/CacheNewline.cmake b/Tests/RunCMake/CacheNewline/CacheNewline.cmake
new file mode 100644
index 0000000000..81851dbe01
--- /dev/null
+++ b/Tests/RunCMake/CacheNewline/CacheNewline.cmake
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 3.5)
+
+project(CacheNewlineTest NONE)
+
+set(NEWLINE_VARIABLE "a\nb" CACHE STRING "Offending entry")
diff --git a/Tests/RunCMake/CacheNewline/RunCMakeTest.cmake b/Tests/RunCMake/CacheNewline/RunCMakeTest.cmake
new file mode 100644
index 0000000000..5e3d2d4999
--- /dev/null
+++ b/Tests/RunCMake/CacheNewline/RunCMakeTest.cmake
@@ -0,0 +1,3 @@
+include(RunCMake)
+
+run_cmake(CacheNewline)
diff --git a/Tests/RunCMake/CacheNewline/cache-regex.txt b/Tests/RunCMake/CacheNewline/cache-regex.txt
new file mode 100644
index 0000000000..b239dbc829
--- /dev/null
+++ b/Tests/RunCMake/CacheNewline/cache-regex.txt
@@ -0,0 +1,6 @@
+//Offending entry
+NEWLINE_VARIABLE:STRING=a
+# WARNING: Value of NEWLINE_VARIABLE contained a newline and was
+# truncated\. Original value:
+# a
+# \\nb
diff --git a/Utilities/IWYU/mapping.imp b/Utilities/IWYU/mapping.imp
index 54084025ca..892cdcb1e0 100644
--- a/Utilities/IWYU/mapping.imp
+++ b/Utilities/IWYU/mapping.imp
@@ -23,8 +23,11 @@
# HACK: check whether this can be removed with next iwyu release.
{ include: [ "<bits/shared_ptr.h>", private, "<memory>", public ] },
{ include: [ "<bits/std_function.h>", private, "<functional>", public ] },
+ { include: [ "<bits/stdint-intn.h>", private, "<stdint.h>", public ] },
+ { include: [ "<bits/stdint-uintn.h>", private, "<stdint.h>", public ] },
{ include: [ "<bits/time.h>", private, "<time.h>", public ] },
{ include: [ "<bits/types/clock_t.h>", private, "<time.h>", public ] },
+ { include: [ "<bits/types/mbstate_t.h>", private, "<wchar.h>", public ] },
{ include: [ "<bits/types/struct_timespec.h>", private, "<time.h>", public ] },
{ include: [ "<bits/types/struct_timeval.h>", private, "<time.h>", public ] },
{ include: [ "<bits/types/struct_tm.h>", private, "<time.h>", public ] },
diff --git a/Utilities/Scripts/update-libuv.bash b/Utilities/Scripts/update-libuv.bash
index d7a7d1f285..6d423a7644 100755
--- a/Utilities/Scripts/update-libuv.bash
+++ b/Utilities/Scripts/update-libuv.bash
@@ -20,6 +20,8 @@ extract_source () {
git_archive
pushd "${extractdir}/${name}-reduced"
echo "* -whitespace" > .gitattributes
+ echo >> src/unix/aix-common.c
+ echo >> src/unix/ibmi.c
popd
}
diff --git a/Utilities/cmlibuv/CMakeLists.txt b/Utilities/cmlibuv/CMakeLists.txt
index 4c8e2289dc..ba1638eb0e 100644
--- a/Utilities/cmlibuv/CMakeLists.txt
+++ b/Utilities/cmlibuv/CMakeLists.txt
@@ -26,6 +26,7 @@ set(uv_sources
src/threadpool.c
src/uv-common.c
src/uv-common.h
+ src/uv-data-getter-setters.c
src/version.c
)
if(WIN32)
@@ -130,6 +131,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "AIX")
)
list(APPEND uv_sources
src/unix/aix.c
+ src/unix/aix-common.c
)
endif()
@@ -170,7 +172,6 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
src/unix/fsevents.c
src/unix/kqueue.c
src/unix/proctitle.c
- src/unix/pthread-barrier.c
)
endif()
diff --git a/Utilities/cmlibuv/LICENSE b/Utilities/cmlibuv/LICENSE
index 41ba44c285..28f17339e2 100644
--- a/Utilities/cmlibuv/LICENSE
+++ b/Utilities/cmlibuv/LICENSE
@@ -62,8 +62,8 @@ The externally maintained libraries used by libuv are:
- stdint-msvc2008.h (from msinttypes), copyright Alexander Chemeris. Three
clause BSD license.
- - pthread-fixes.h, pthread-fixes.c, copyright Google Inc. and Sony Mobile
- Communications AB. Three clause BSD license.
+ - pthread-fixes.c, copyright Google Inc. and Sony Mobile Communications AB.
+ Three clause BSD license.
- android-ifaddrs.h, android-ifaddrs.c, copyright Berkeley Software Design
Inc, Kenneth MacKay and Emergya (Cloud4all, FP7/2007-2013, grant agreement
diff --git a/Utilities/cmlibuv/include/pthread-barrier.h b/Utilities/cmlibuv/include/pthread-barrier.h
index 900ebedd30..07db9b8a6a 100644
--- a/Utilities/cmlibuv/include/pthread-barrier.h
+++ b/Utilities/cmlibuv/include/pthread-barrier.h
@@ -23,6 +23,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#endif
#define PTHREAD_BARRIER_SERIAL_THREAD 0x12345
+#define UV__PTHREAD_BARRIER_FALLBACK 1
/*
* To maintain ABI compatibility with
diff --git a/Utilities/cmlibuv/include/uv-errno.h b/Utilities/cmlibuv/include/uv-errno.h
index f1371517cc..8a41533147 100644
--- a/Utilities/cmlibuv/include/uv-errno.h
+++ b/Utilities/cmlibuv/include/uv-errno.h
@@ -416,4 +416,16 @@
# define UV__EHOSTDOWN (-4031)
#endif
+#if defined(EREMOTEIO) && !defined(_WIN32)
+# define UV__EREMOTEIO (-EREMOTEIO)
+#else
+# define UV__EREMOTEIO (-4030)
+#endif
+
+#if defined(ENOTTY) && !defined(_WIN32)
+# define UV__ENOTTY (-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 58f926111a..39e7384db3 100644
--- a/Utilities/cmlibuv/include/uv-os390.h
+++ b/Utilities/cmlibuv/include/uv-os390.h
@@ -27,4 +27,7 @@
#define UV_PLATFORM_LOOP_FIELDS \
void* ep; \
+#define UV_PLATFORM_FS_EVENT_FIELDS \
+ char rfis_rftok[8]; \
+
#endif /* UV_MVS_H */
diff --git a/Utilities/cmlibuv/include/uv-unix.h b/Utilities/cmlibuv/include/uv-unix.h
index ff59bcba08..d8d031f4db 100644
--- a/Utilities/cmlibuv/include/uv-unix.h
+++ b/Utilities/cmlibuv/include/uv-unix.h
@@ -50,6 +50,8 @@
# include "uv-linux.h"
#elif defined (__MVS__)
# include "uv-os390.h"
+#elif defined(_PASE)
+# include "uv-posix.h"
#elif defined(_AIX)
# include "uv-aix.h"
#elif defined(__sun)
@@ -125,6 +127,7 @@ typedef struct uv_buf_t {
typedef int uv_file;
typedef int uv_os_sock_t;
typedef int uv_os_fd_t;
+typedef pid_t uv_pid_t;
#ifdef CMAKE_BOOTSTRAP
#define UV_ONCE_INIT 0
@@ -379,4 +382,97 @@ typedef struct {
uv_fs_event_cb cb; \
UV_PLATFORM_FS_EVENT_FIELDS \
+/* fs open() flags supported on this platform: */
+#if defined(O_APPEND)
+# define UV_FS_O_APPEND O_APPEND
+#else
+# define UV_FS_O_APPEND 0
+#endif
+#if defined(O_CREAT)
+# define UV_FS_O_CREAT O_CREAT
+#else
+# define UV_FS_O_CREAT 0
+#endif
+#if defined(O_DIRECT)
+# define UV_FS_O_DIRECT O_DIRECT
+#else
+# define UV_FS_O_DIRECT 0
+#endif
+#if defined(O_DIRECTORY)
+# define UV_FS_O_DIRECTORY O_DIRECTORY
+#else
+# define UV_FS_O_DIRECTORY 0
+#endif
+#if defined(O_DSYNC)
+# define UV_FS_O_DSYNC O_DSYNC
+#else
+# define UV_FS_O_DSYNC 0
+#endif
+#if defined(O_EXCL)
+# define UV_FS_O_EXCL O_EXCL
+#else
+# define UV_FS_O_EXCL 0
+#endif
+#if defined(O_EXLOCK)
+# define UV_FS_O_EXLOCK O_EXLOCK
+#else
+# define UV_FS_O_EXLOCK 0
+#endif
+#if defined(O_NOATIME)
+# define UV_FS_O_NOATIME O_NOATIME
+#else
+# define UV_FS_O_NOATIME 0
+#endif
+#if defined(O_NOCTTY)
+# define UV_FS_O_NOCTTY O_NOCTTY
+#else
+# define UV_FS_O_NOCTTY 0
+#endif
+#if defined(O_NOFOLLOW)
+# define UV_FS_O_NOFOLLOW O_NOFOLLOW
+#else
+# define UV_FS_O_NOFOLLOW 0
+#endif
+#if defined(O_NONBLOCK)
+# define UV_FS_O_NONBLOCK O_NONBLOCK
+#else
+# define UV_FS_O_NONBLOCK 0
+#endif
+#if defined(O_RDONLY)
+# define UV_FS_O_RDONLY O_RDONLY
+#else
+# define UV_FS_O_RDONLY 0
+#endif
+#if defined(O_RDWR)
+# define UV_FS_O_RDWR O_RDWR
+#else
+# define UV_FS_O_RDWR 0
+#endif
+#if defined(O_SYMLINK)
+# define UV_FS_O_SYMLINK O_SYMLINK
+#else
+# define UV_FS_O_SYMLINK 0
+#endif
+#if defined(O_SYNC)
+# define UV_FS_O_SYNC O_SYNC
+#else
+# define UV_FS_O_SYNC 0
+#endif
+#if defined(O_TRUNC)
+# define UV_FS_O_TRUNC O_TRUNC
+#else
+# define UV_FS_O_TRUNC 0
+#endif
+#if defined(O_WRONLY)
+# define UV_FS_O_WRONLY O_WRONLY
+#else
+# define UV_FS_O_WRONLY 0
+#endif
+
+/* fs open() flags supported on other platforms: */
+#define UV_FS_O_RANDOM 0
+#define UV_FS_O_SHORT_LIVED 0
+#define UV_FS_O_SEQUENTIAL 0
+#define UV_FS_O_TEMPORARY 0
+
#endif /* UV_UNIX_H */
diff --git a/Utilities/cmlibuv/include/uv-version.h b/Utilities/cmlibuv/include/uv-version.h
index e16580903c..1dc63e57c1 100644
--- a/Utilities/cmlibuv/include/uv-version.h
+++ b/Utilities/cmlibuv/include/uv-version.h
@@ -31,7 +31,7 @@
*/
#define UV_VERSION_MAJOR 1
-#define UV_VERSION_MINOR 11
+#define UV_VERSION_MINOR 19
#define UV_VERSION_PATCH 1
#define UV_VERSION_IS_RELEASE 0
#define UV_VERSION_SUFFIX "dev"
diff --git a/Utilities/cmlibuv/include/uv-win.h b/Utilities/cmlibuv/include/uv-win.h
index d3e32a508c..6486aabb36 100644
--- a/Utilities/cmlibuv/include/uv-win.h
+++ b/Utilities/cmlibuv/include/uv-win.h
@@ -20,7 +20,7 @@
*/
#ifndef _WIN32_WINNT
-# define _WIN32_WINNT 0x0502
+# define _WIN32_WINNT 0x0600
#endif
#if !defined(_SSIZE_T_) && !defined(_SSIZE_T_DEFINED)
@@ -233,6 +233,7 @@ typedef struct uv_buf_t {
typedef int uv_file;
typedef SOCKET uv_os_sock_t;
typedef HANDLE uv_os_fd_t;
+typedef int uv_pid_t;
typedef HANDLE uv_thread_t;
@@ -659,3 +660,28 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
#ifndef X_OK
#define X_OK 1
#endif
+
+/* fs open() flags supported on this platform: */
+#define UV_FS_O_APPEND _O_APPEND
+#define UV_FS_O_CREAT _O_CREAT
+#define UV_FS_O_EXCL _O_EXCL
+#define UV_FS_O_RANDOM _O_RANDOM
+#define UV_FS_O_RDONLY _O_RDONLY
+#define UV_FS_O_RDWR _O_RDWR
+#define UV_FS_O_SEQUENTIAL _O_SEQUENTIAL
+#define UV_FS_O_SHORT_LIVED _O_SHORT_LIVED
+#define UV_FS_O_TEMPORARY _O_TEMPORARY
+#define UV_FS_O_TRUNC _O_TRUNC
+#define UV_FS_O_WRONLY _O_WRONLY
+
+/* fs open() flags supported on other platforms (or mapped on this platform): */
+#define UV_FS_O_DIRECT 0x02000000 /* FILE_FLAG_NO_BUFFERING */
+#define UV_FS_O_DIRECTORY 0
+#define UV_FS_O_DSYNC 0x04000000 /* FILE_FLAG_WRITE_THROUGH */
+#define UV_FS_O_EXLOCK 0x10000000 /* EXCLUSIVE SHARING MODE */
+#define UV_FS_O_NOATIME 0
+#define UV_FS_O_NOCTTY 0
+#define UV_FS_O_NOFOLLOW 0
+#define UV_FS_O_NONBLOCK 0
+#define UV_FS_O_SYMLINK 0
+#define UV_FS_O_SYNC 0x08000000 /* FILE_FLAG_WRITE_THROUGH */
diff --git a/Utilities/cmlibuv/include/uv.h b/Utilities/cmlibuv/include/uv.h
index 38f567644d..328ce9ebb7 100644
--- a/Utilities/cmlibuv/include/uv.h
+++ b/Utilities/cmlibuv/include/uv.h
@@ -144,6 +144,8 @@ extern "C" {
XX(ENXIO, "no such device or address") \
XX(EMLINK, "too many links") \
XX(EHOSTDOWN, "host is down") \
+ XX(EREMOTEIO, "remote I/O error") \
+ XX(ENOTTY, "inappropriate ioctl for device") \
#define UV_HANDLE_TYPE_MAP(XX) \
XX(ASYNC, async) \
@@ -427,7 +429,17 @@ struct uv_handle_s {
};
UV_EXTERN size_t uv_handle_size(uv_handle_type type);
+UV_EXTERN uv_handle_type uv_handle_get_type(const uv_handle_t* handle);
+UV_EXTERN const char* uv_handle_type_name(uv_handle_type type);
+UV_EXTERN void* uv_handle_get_data(const uv_handle_t* handle);
+UV_EXTERN uv_loop_t* uv_handle_get_loop(const uv_handle_t* handle);
+UV_EXTERN void uv_handle_set_data(uv_handle_t* handle, void* data);
+
UV_EXTERN size_t uv_req_size(uv_req_type type);
+UV_EXTERN void* uv_req_get_data(const uv_req_t* req);
+UV_EXTERN void uv_req_set_data(uv_req_t* req, void* data);
+UV_EXTERN uv_req_type uv_req_get_type(const uv_req_t* req);
+UV_EXTERN const char* uv_req_type_name(uv_req_type type);
UV_EXTERN int uv_is_active(const uv_handle_t* handle);
@@ -467,6 +479,8 @@ struct uv_stream_s {
UV_STREAM_FIELDS
};
+UV_EXTERN size_t uv_stream_get_write_queue_size(const uv_stream_t* stream);
+
UV_EXTERN int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb);
UV_EXTERN int uv_accept(uv_stream_t* server, uv_stream_t* client);
@@ -644,6 +658,8 @@ UV_EXTERN int uv_udp_recv_start(uv_udp_t* handle,
uv_alloc_cb alloc_cb,
uv_udp_recv_cb recv_cb);
UV_EXTERN int uv_udp_recv_stop(uv_udp_t* handle);
+UV_EXTERN size_t uv_udp_get_send_queue_size(const uv_udp_t* handle);
+UV_EXTERN size_t uv_udp_get_send_queue_count(const uv_udp_t* handle);
/*
@@ -712,6 +728,7 @@ UV_EXTERN int uv_pipe_getpeername(const uv_pipe_t* handle,
UV_EXTERN void uv_pipe_pending_instances(uv_pipe_t* handle, int count);
UV_EXTERN int uv_pipe_pending_count(uv_pipe_t* handle);
UV_EXTERN uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle);
+UV_EXTERN int uv_pipe_chmod(uv_pipe_t* handle, int flags);
struct uv_poll_s {
@@ -723,7 +740,8 @@ struct uv_poll_s {
enum uv_poll_event {
UV_READABLE = 1,
UV_WRITABLE = 2,
- UV_DISCONNECT = 4
+ UV_DISCONNECT = 4,
+ UV_PRIORITIZED = 8
};
UV_EXTERN int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd);
@@ -962,6 +980,7 @@ UV_EXTERN int uv_spawn(uv_loop_t* loop,
const uv_process_options_t* options);
UV_EXTERN int uv_process_kill(uv_process_t*, int signum);
UV_EXTERN int uv_kill(int pid, int signum);
+UV_EXTERN uv_pid_t uv_process_get_pid(const uv_process_t*);
/*
@@ -1038,6 +1057,7 @@ UV_EXTERN int uv_get_process_title(char* buffer, size_t size);
UV_EXTERN int uv_set_process_title(const char* title);
UV_EXTERN int uv_resident_set_memory(size_t* rss);
UV_EXTERN int uv_uptime(double* uptime);
+UV_EXTERN uv_os_fd_t uv_get_osfhandle(int fd);
typedef struct {
long tv_sec;
@@ -1069,6 +1089,8 @@ UV_EXTERN int uv_os_homedir(char* buffer, size_t* size);
UV_EXTERN int uv_os_tmpdir(char* buffer, size_t* size);
UV_EXTERN int uv_os_get_passwd(uv_passwd_t* pwd);
UV_EXTERN void uv_os_free_passwd(uv_passwd_t* pwd);
+UV_EXTERN uv_pid_t uv_os_getpid(void);
+UV_EXTERN uv_pid_t uv_os_getppid(void);
UV_EXTERN int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count);
UV_EXTERN void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count);
@@ -1115,7 +1137,8 @@ typedef enum {
UV_FS_READLINK,
UV_FS_CHOWN,
UV_FS_FCHOWN,
- UV_FS_REALPATH
+ UV_FS_REALPATH,
+ UV_FS_COPYFILE
} uv_fs_type;
/* uv_fs_t is a subclass of uv_req_t. */
@@ -1131,6 +1154,12 @@ struct uv_fs_s {
UV_FS_PRIVATE_FIELDS
};
+UV_EXTERN uv_fs_type uv_fs_get_type(const uv_fs_t*);
+UV_EXTERN ssize_t uv_fs_get_result(const uv_fs_t*);
+UV_EXTERN void* uv_fs_get_ptr(const uv_fs_t*);
+UV_EXTERN const char* uv_fs_get_path(const uv_fs_t*);
+UV_EXTERN uv_stat_t* uv_fs_get_statbuf(uv_fs_t*);
+
UV_EXTERN void uv_fs_req_cleanup(uv_fs_t* req);
UV_EXTERN int uv_fs_close(uv_loop_t* loop,
uv_fs_t* req,
@@ -1160,6 +1189,18 @@ UV_EXTERN int uv_fs_write(uv_loop_t* loop,
unsigned int nbufs,
int64_t offset,
uv_fs_cb cb);
+/*
+ * This flag can be used with uv_fs_copyfile() to return an error if the
+ * destination already exists.
+ */
+#define UV_FS_COPYFILE_EXCL 0x0001
+
+UV_EXTERN int uv_fs_copyfile(uv_loop_t* loop,
+ uv_fs_t* req,
+ const char* path,
+ const char* new_path,
+ int flags,
+ uv_fs_cb cb);
UV_EXTERN int uv_fs_mkdir(uv_loop_t* loop,
uv_fs_t* req,
const char* path,
@@ -1393,6 +1434,21 @@ UV_EXTERN int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size
UV_EXTERN int uv_inet_ntop(int af, const void* src, char* dst, size_t size);
UV_EXTERN int uv_inet_pton(int af, const char* src, void* dst);
+#if defined(IF_NAMESIZE)
+# define UV_IF_NAMESIZE (IF_NAMESIZE + 1)
+#elif defined(IFNAMSIZ)
+# define UV_IF_NAMESIZE (IFNAMSIZ + 1)
+#else
+# define UV_IF_NAMESIZE (16 + 1)
+#endif
+
+UV_EXTERN int uv_if_indextoname(unsigned int ifindex,
+ char* buffer,
+ size_t* size);
+UV_EXTERN int uv_if_indextoiid(unsigned int ifindex,
+ char* buffer,
+ size_t* size);
+
UV_EXTERN int uv_exepath(char* buffer, size_t* size);
UV_EXTERN int uv_cwd(char* buffer, size_t* size);
@@ -1412,6 +1468,7 @@ UV_EXTERN int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr);
UV_EXTERN const char* uv_dlerror(const uv_lib_t* lib);
UV_EXTERN int uv_mutex_init(uv_mutex_t* handle);
+UV_EXTERN int uv_mutex_init_recursive(uv_mutex_t* handle);
UV_EXTERN void uv_mutex_destroy(uv_mutex_t* handle);
UV_EXTERN void uv_mutex_lock(uv_mutex_t* handle);
UV_EXTERN int uv_mutex_trylock(uv_mutex_t* handle);
@@ -1484,6 +1541,8 @@ struct uv_loop_s {
UV_LOOP_PRIVATE_FIELDS
};
+UV_EXTERN void* uv_loop_get_data(const uv_loop_t*);
+UV_EXTERN void uv_loop_set_data(uv_loop_t*, void* data);
/* Don't export the private CPP symbols. */
#undef UV_HANDLE_TYPE_PRIVATE
diff --git a/Utilities/cmlibuv/src/threadpool.c b/Utilities/cmlibuv/src/threadpool.c
index 108934112c..413d1c204c 100644
--- a/Utilities/cmlibuv/src/threadpool.c
+++ b/Utilities/cmlibuv/src/threadpool.c
@@ -38,7 +38,6 @@ static uv_thread_t* threads;
static uv_thread_t default_threads[4];
static QUEUE exit_message;
static QUEUE wq;
-static volatile int initialized;
static void uv__cancelled(struct uv__work* w) {
@@ -53,7 +52,8 @@ static void worker(void* arg) {
struct uv__work* w;
QUEUE* q;
- (void) arg;
+ uv_sem_post((uv_sem_t*) arg);
+ arg = NULL;
for (;;) {
uv_mutex_lock(&mutex);
@@ -105,7 +105,7 @@ static void post(QUEUE* q) {
UV_DESTRUCTOR(static void cleanup(void)) {
unsigned int i;
- if (initialized == 0)
+ if (nthreads == 0)
return;
post(&exit_message);
@@ -122,7 +122,6 @@ UV_DESTRUCTOR(static void cleanup(void)) {
threads = NULL;
nthreads = 0;
- initialized = 0;
}
#endif
@@ -130,6 +129,7 @@ UV_DESTRUCTOR(static void cleanup(void)) {
static void init_threads(void) {
unsigned int i;
const char* val;
+ uv_sem_t sem;
nthreads = ARRAY_SIZE(default_threads);
val = getenv("UV_THREADPOOL_SIZE");
@@ -157,11 +157,17 @@ static void init_threads(void) {
QUEUE_INIT(&wq);
+ if (uv_sem_init(&sem, 0))
+ abort();
+
for (i = 0; i < nthreads; i++)
- if (uv_thread_create(threads + i, worker, NULL))
+ if (uv_thread_create(threads + i, worker, &sem))
abort();
- initialized = 1;
+ for (i = 0; i < nthreads; i++)
+ uv_sem_wait(&sem);
+
+ uv_sem_destroy(&sem);
}
diff --git a/Utilities/cmlibuv/src/unix/aix-common.c b/Utilities/cmlibuv/src/unix/aix-common.c
new file mode 100644
index 0000000000..c2217fb6b4
--- /dev/null
+++ b/Utilities/cmlibuv/src/unix/aix-common.c
@@ -0,0 +1,292 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "internal.h"
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <sys/time.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <utmp.h>
+#include <libgen.h>
+
+#include <sys/protosw.h>
+#include <procinfo.h>
+#include <sys/proc.h>
+#include <sys/procfs.h>
+
+#include <sys/poll.h>
+
+#include <sys/pollset.h>
+#include <ctype.h>
+
+#include <sys/mntctl.h>
+#include <sys/vmount.h>
+#include <limits.h>
+#include <strings.h>
+#include <sys/vnode.h>
+
+uint64_t uv__hrtime(uv_clocktype_t type) {
+ uint64_t G = 1000000000;
+ timebasestruct_t t;
+ read_wall_time(&t, TIMEBASE_SZ);
+ time_base_to_time(&t, TIMEBASE_SZ);
+ return (uint64_t) t.tb_high * G + t.tb_low;
+}
+
+
+/*
+ * We could use a static buffer for the path manipulations that we need outside
+ * of the function, but this function could be called by multiple consumers and
+ * we don't want to potentially create a race condition in the use of snprintf.
+ * There is no direct way of getting the exe path in AIX - either through /procfs
+ * or through some libc APIs. The below approach is to parse the argv[0]'s pattern
+ * and use it in conjunction with PATH environment variable to craft one.
+ */
+int uv_exepath(char* buffer, size_t* size) {
+ int res;
+ char args[PATH_MAX];
+ char abspath[PATH_MAX];
+ size_t abspath_size;
+ struct procsinfo pi;
+
+ if (buffer == NULL || size == NULL || *size == 0)
+ return -EINVAL;
+
+ pi.pi_pid = getpid();
+ res = getargs(&pi, sizeof(pi), args, sizeof(args));
+ if (res < 0)
+ return -EINVAL;
+
+ /*
+ * Possibilities for args:
+ * i) an absolute path such as: /home/user/myprojects/nodejs/node
+ * ii) a relative path such as: ./node or ../myprojects/nodejs/node
+ * iii) a bare filename such as "node", after exporting PATH variable
+ * to its location.
+ */
+
+ /* Case i) and ii) absolute or relative paths */
+ if (strchr(args, '/') != NULL) {
+ if (realpath(args, abspath) != abspath)
+ return -errno;
+
+ abspath_size = strlen(abspath);
+
+ *size -= 1;
+ if (*size > abspath_size)
+ *size = abspath_size;
+
+ memcpy(buffer, abspath, *size);
+ buffer[*size] = '\0';
+
+ return 0;
+ } else {
+ /* Case iii). Search PATH environment variable */
+ char trypath[PATH_MAX];
+ char *clonedpath = NULL;
+ char *token = NULL;
+ char *path = getenv("PATH");
+
+ if (path == NULL)
+ return -EINVAL;
+
+ clonedpath = uv__strdup(path);
+ if (clonedpath == NULL)
+ return -ENOMEM;
+
+ token = strtok(clonedpath, ":");
+ while (token != NULL) {
+ snprintf(trypath, sizeof(trypath) - 1, "%s/%s", token, args);
+ if (realpath(trypath, abspath) == abspath) {
+ /* Check the match is executable */
+ if (access(abspath, X_OK) == 0) {
+ abspath_size = strlen(abspath);
+
+ *size -= 1;
+ if (*size > abspath_size)
+ *size = abspath_size;
+
+ memcpy(buffer, abspath, *size);
+ buffer[*size] = '\0';
+
+ uv__free(clonedpath);
+ return 0;
+ }
+ }
+ token = strtok(NULL, ":");
+ }
+ uv__free(clonedpath);
+
+ /* Out of tokens (path entries), and no match found */
+ return -EINVAL;
+ }
+}
+
+void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
+ int i;
+
+ for (i = 0; i < count; ++i) {
+ uv__free(cpu_infos[i].model);
+ }
+
+ uv__free(cpu_infos);
+}
+
+
+int uv_interface_addresses(uv_interface_address_t** addresses,
+ int* count) {
+ uv_interface_address_t* address;
+ int sockfd, inet6, size = 1;
+ struct ifconf ifc;
+ struct ifreq *ifr, *p, flg;
+ struct sockaddr_dl* sa_addr;
+
+ *count = 0;
+
+ if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) {
+ return -errno;
+ }
+
+ if (ioctl(sockfd, SIOCGSIZIFCONF, &size) == -1) {
+ uv__close(sockfd);
+ return -errno;
+ }
+
+ ifc.ifc_req = (struct ifreq*)uv__malloc(size);
+ ifc.ifc_len = size;
+ if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) {
+ uv__close(sockfd);
+ return -errno;
+ }
+
+#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p))
+
+ /* Count all up and running ipv4/ipv6 addresses */
+ ifr = ifc.ifc_req;
+ while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
+ p = ifr;
+ ifr = (struct ifreq*)
+ ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr));
+
+ if (!(p->ifr_addr.sa_family == AF_INET6 ||
+ p->ifr_addr.sa_family == AF_INET))
+ continue;
+
+ memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
+ if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
+ uv__close(sockfd);
+ return -errno;
+ }
+
+ if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
+ continue;
+
+ (*count)++;
+ }
+
+ /* Alloc the return interface structs */
+ *addresses = uv__malloc(*count * sizeof(uv_interface_address_t));
+ if (!(*addresses)) {
+ uv__close(sockfd);
+ return -ENOMEM;
+ }
+ address = *addresses;
+
+ ifr = ifc.ifc_req;
+ while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
+ p = ifr;
+ ifr = (struct ifreq*)
+ ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr));
+
+ if (!(p->ifr_addr.sa_family == AF_INET6 ||
+ p->ifr_addr.sa_family == AF_INET))
+ continue;
+
+ inet6 = (p->ifr_addr.sa_family == AF_INET6);
+
+ memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
+ if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
+ uv__close(sockfd);
+ return -ENOSYS;
+ }
+
+ if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
+ continue;
+
+ /* All conditions above must match count loop */
+
+ address->name = uv__strdup(p->ifr_name);
+
+ if (inet6)
+ address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr);
+ else
+ address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr);
+
+ sa_addr = (struct sockaddr_dl*) &p->ifr_addr;
+ memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
+
+ if (ioctl(sockfd, SIOCGIFNETMASK, p) == -1) {
+ uv__close(sockfd);
+ return -ENOSYS;
+ }
+
+ if (inet6)
+ address->netmask.netmask6 = *((struct sockaddr_in6*) &p->ifr_addr);
+ else
+ address->netmask.netmask4 = *((struct sockaddr_in*) &p->ifr_addr);
+
+ address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0;
+
+ address++;
+ }
+
+#undef ADDR_SIZE
+
+ uv__close(sockfd);
+ return 0;
+}
+
+
+void uv_free_interface_addresses(uv_interface_address_t* addresses,
+ int count) {
+ int i;
+
+ for (i = 0; i < count; ++i) {
+ uv__free(addresses[i].name);
+ }
+
+ uv__free(addresses);
+}
diff --git a/Utilities/cmlibuv/src/unix/aix.c b/Utilities/cmlibuv/src/unix/aix.c
index 388c9cca97..fd413090fe 100644
--- a/Utilities/cmlibuv/src/unix/aix.c
+++ b/Utilities/cmlibuv/src/unix/aix.c
@@ -1,4 +1,5 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
@@ -64,11 +65,18 @@
#define RDWR_BUF_SIZE 4096
#define EQ(a,b) (strcmp(a,b) == 0)
+static uv_mutex_t process_title_mutex;
+static uv_once_t process_title_mutex_once = UV_ONCE_INIT;
static void* args_mem = NULL;
static char** process_argv = NULL;
static int process_argc = 0;
static char* process_title_ptr = NULL;
+static void init_process_title_mutex_once(void) {
+ uv_mutex_init(&process_title_mutex);
+}
+
+
int uv__platform_loop_init(uv_loop_t* loop) {
loop->fs_fd = -1;
@@ -316,104 +324,6 @@ update_timeout:
}
-uint64_t uv__hrtime(uv_clocktype_t type) {
- uint64_t G = 1000000000;
- timebasestruct_t t;
- read_wall_time(&t, TIMEBASE_SZ);
- time_base_to_time(&t, TIMEBASE_SZ);
- return (uint64_t) t.tb_high * G + t.tb_low;
-}
-
-
-/*
- * We could use a static buffer for the path manipulations that we need outside
- * of the function, but this function could be called by multiple consumers and
- * we don't want to potentially create a race condition in the use of snprintf.
- * There is no direct way of getting the exe path in AIX - either through /procfs
- * or through some libc APIs. The below approach is to parse the argv[0]'s pattern
- * and use it in conjunction with PATH environment variable to craft one.
- */
-int uv_exepath(char* buffer, size_t* size) {
- int res;
- char args[PATH_MAX];
- char abspath[PATH_MAX];
- size_t abspath_size;
- struct procsinfo pi;
-
- if (buffer == NULL || size == NULL || *size == 0)
- return -EINVAL;
-
- pi.pi_pid = getpid();
- res = getargs(&pi, sizeof(pi), args, sizeof(args));
- if (res < 0)
- return -EINVAL;
-
- /*
- * Possibilities for args:
- * i) an absolute path such as: /home/user/myprojects/nodejs/node
- * ii) a relative path such as: ./node or ../myprojects/nodejs/node
- * iii) a bare filename such as "node", after exporting PATH variable
- * to its location.
- */
-
- /* Case i) and ii) absolute or relative paths */
- if (strchr(args, '/') != NULL) {
- if (realpath(args, abspath) != abspath)
- return -errno;
-
- abspath_size = strlen(abspath);
-
- *size -= 1;
- if (*size > abspath_size)
- *size = abspath_size;
-
- memcpy(buffer, abspath, *size);
- buffer[*size] = '\0';
-
- return 0;
- } else {
- /* Case iii). Search PATH environment variable */
- char trypath[PATH_MAX];
- char *clonedpath = NULL;
- char *token = NULL;
- char *path = getenv("PATH");
-
- if (path == NULL)
- return -EINVAL;
-
- clonedpath = uv__strdup(path);
- if (clonedpath == NULL)
- return -ENOMEM;
-
- token = strtok(clonedpath, ":");
- while (token != NULL) {
- snprintf(trypath, sizeof(trypath) - 1, "%s/%s", token, args);
- if (realpath(trypath, abspath) == abspath) {
- /* Check the match is executable */
- if (access(abspath, X_OK) == 0) {
- abspath_size = strlen(abspath);
-
- *size -= 1;
- if (*size > abspath_size)
- *size = abspath_size;
-
- memcpy(buffer, abspath, *size);
- buffer[*size] = '\0';
-
- uv__free(clonedpath);
- return 0;
- }
- }
- token = strtok(NULL, ":");
- }
- uv__free(clonedpath);
-
- /* Out of tokens (path entries), and no match found */
- return -EINVAL;
- }
-}
-
-
uint64_t uv_get_free_memory(void) {
perfstat_memory_total_t mem_total;
int result = perfstat_memory_total(NULL, &mem_total, sizeof(mem_total), 1);
@@ -855,6 +765,7 @@ int uv_fs_event_start(uv_fs_event_t* handle,
uv__io_init(&handle->event_watcher, uv__ahafs_event, fd);
handle->path = uv__strdup(filename);
handle->cb = cb;
+ handle->dir_filename = NULL;
uv__io_start(handle->loop, &handle->event_watcher, POLLIN);
@@ -952,6 +863,9 @@ int uv_set_process_title(const char* title) {
if (new_title == NULL)
return -ENOMEM;
+ uv_once(&process_title_mutex_once, init_process_title_mutex_once);
+ uv_mutex_lock(&process_title_mutex);
+
/* If this is the first time this is set,
* don't free and set argv[1] to NULL.
*/
@@ -964,6 +878,8 @@ int uv_set_process_title(const char* title) {
if (process_argc > 1)
process_argv[1] = NULL;
+ uv_mutex_unlock(&process_title_mutex);
+
return 0;
}
@@ -976,8 +892,13 @@ int uv_get_process_title(char* buffer, size_t size) {
else if (size <= len)
return -ENOBUFS;
+ uv_once(&process_title_mutex_once, init_process_title_mutex_once);
+ uv_mutex_lock(&process_title_mutex);
+
memcpy(buffer, process_argv[0], len + 1);
+ uv_mutex_unlock(&process_title_mutex);
+
return 0;
}
@@ -1017,6 +938,7 @@ int uv_uptime(double* uptime) {
size_t entries = 0;
time_t boot_time;
+ boot_time = 0;
utmpname(UTMP_FILE);
setutent();
@@ -1093,130 +1015,6 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
}
-void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
- int i;
-
- for (i = 0; i < count; ++i) {
- uv__free(cpu_infos[i].model);
- }
-
- uv__free(cpu_infos);
-}
-
-
-int uv_interface_addresses(uv_interface_address_t** addresses,
- int* count) {
- uv_interface_address_t* address;
- int sockfd, size = 1;
- struct ifconf ifc;
- struct ifreq *ifr, *p, flg;
-
- *count = 0;
-
- if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) {
- return -errno;
- }
-
- if (ioctl(sockfd, SIOCGSIZIFCONF, &size) == -1) {
- uv__close(sockfd);
- return -errno;
- }
-
- ifc.ifc_req = (struct ifreq*)uv__malloc(size);
- ifc.ifc_len = size;
- if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) {
- uv__close(sockfd);
- return -errno;
- }
-
-#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p))
-
- /* Count all up and running ipv4/ipv6 addresses */
- ifr = ifc.ifc_req;
- while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
- p = ifr;
- ifr = (struct ifreq*)
- ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr));
-
- if (!(p->ifr_addr.sa_family == AF_INET6 ||
- p->ifr_addr.sa_family == AF_INET))
- continue;
-
- memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
- if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
- uv__close(sockfd);
- return -errno;
- }
-
- if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
- continue;
-
- (*count)++;
- }
-
- /* Alloc the return interface structs */
- *addresses = (uv_interface_address_t*)
- uv__malloc(*count * sizeof(uv_interface_address_t));
- if (!(*addresses)) {
- uv__close(sockfd);
- return -ENOMEM;
- }
- address = *addresses;
-
- ifr = ifc.ifc_req;
- while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
- p = ifr;
- ifr = (struct ifreq*)
- ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr));
-
- if (!(p->ifr_addr.sa_family == AF_INET6 ||
- p->ifr_addr.sa_family == AF_INET))
- continue;
-
- memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
- if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
- uv__close(sockfd);
- return -ENOSYS;
- }
-
- if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
- continue;
-
- /* All conditions above must match count loop */
-
- address->name = uv__strdup(p->ifr_name);
-
- if (p->ifr_addr.sa_family == AF_INET6) {
- address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr);
- } else {
- address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr);
- }
-
- /* TODO: Retrieve netmask using SIOCGIFNETMASK ioctl */
-
- address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0;
-
- address++;
- }
-
-#undef ADDR_SIZE
-
- uv__close(sockfd);
- return 0;
-}
-
-
-void uv_free_interface_addresses(uv_interface_address_t* addresses,
- int count) {
- int i;
-
- for (i = 0; i < count; ++i) {
- uv__free(addresses[i].name);
- }
-
- uv__free(addresses);
-}
-
void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
struct pollfd* events;
uintptr_t i;
diff --git a/Utilities/cmlibuv/src/unix/android-ifaddrs.c b/Utilities/cmlibuv/src/unix/android-ifaddrs.c
index 30f681b7d0..bf30b14179 100644
--- a/Utilities/cmlibuv/src/unix/android-ifaddrs.c
+++ b/Utilities/cmlibuv/src/unix/android-ifaddrs.c
@@ -43,9 +43,10 @@ typedef struct NetlinkList
unsigned int m_size;
} NetlinkList;
-static int netlink_socket(void)
+static int netlink_socket(pid_t *p_pid)
{
struct sockaddr_nl l_addr;
+ socklen_t l_len;
int l_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if(l_socket < 0)
@@ -61,6 +62,14 @@ static int netlink_socket(void)
return -1;
}
+ l_len = sizeof(l_addr);
+ if(getsockname(l_socket, (struct sockaddr *)&l_addr, &l_len) < 0)
+ {
+ close(l_socket);
+ return -1;
+ }
+ *p_pid = l_addr.nl_pid;
+
return l_socket;
}
@@ -128,7 +137,7 @@ static int netlink_recv(int p_socket, void *p_buffer, size_t p_len)
}
}
-static struct nlmsghdr *getNetlinkResponse(int p_socket, int *p_size, int *p_done)
+static struct nlmsghdr *getNetlinkResponse(int p_socket, pid_t p_pid, int *p_size, int *p_done)
{
size_t l_size = 4096;
void *l_buffer = NULL;
@@ -153,11 +162,10 @@ static struct nlmsghdr *getNetlinkResponse(int p_socket, int *p_size, int *p_don
}
if(l_read >= 0)
{
- pid_t l_pid = getpid();
struct nlmsghdr *l_hdr;
for(l_hdr = (struct nlmsghdr *)l_buffer; NLMSG_OK(l_hdr, (unsigned int)l_read); l_hdr = (struct nlmsghdr *)NLMSG_NEXT(l_hdr, l_read))
{
- if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
+ if((pid_t)l_hdr->nlmsg_pid != p_pid || (int)l_hdr->nlmsg_seq != p_socket)
{
continue;
}
@@ -207,7 +215,7 @@ static void freeResultList(NetlinkList *p_list)
}
}
-static NetlinkList *getResultList(int p_socket, int p_request)
+static NetlinkList *getResultList(int p_socket, int p_request, pid_t p_pid)
{
int l_size;
int l_done;
@@ -227,7 +235,7 @@ static NetlinkList *getResultList(int p_socket, int p_request)
{
NetlinkList *l_item;
- struct nlmsghdr *l_hdr = getNetlinkResponse(p_socket, &l_size, &l_done);
+ struct nlmsghdr *l_hdr = getNetlinkResponse(p_socket, p_pid, &l_size, &l_done);
/* Error */
if(!l_hdr)
{
@@ -449,7 +457,7 @@ static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList,
char *l_name;
char *l_addr;
- for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
+ for(l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
{
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
if(l_info->ifa_family == AF_PACKET)
@@ -471,7 +479,7 @@ static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList,
l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
break;
case IFA_LABEL:
- l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
+ l_nameSize += NLMSG_ALIGN(l_rtaDataSize + 1);
break;
default:
break;
@@ -496,7 +504,7 @@ static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList,
}
l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
- for(l_rta = IFLA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
+ for(l_rta = IFA_RTA(l_info); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
{
void *l_rtaData = RTA_DATA(l_rta);
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
@@ -559,7 +567,7 @@ static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList,
{
unsigned l_maxPrefix = (l_entry->ifa_addr->sa_family == AF_INET ? 32 : 128);
unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info->ifa_prefixlen);
- char l_mask[16] = {0};
+ unsigned char l_mask[16] = {0};
unsigned i;
for(i=0; i<(l_prefix/8); ++i)
{
@@ -578,18 +586,17 @@ static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList,
return 0;
}
-static int interpretLinks(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList)
+static int interpretLinks(int p_socket, pid_t p_pid, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList)
{
int l_numLinks = 0;
- pid_t l_pid = getpid();
for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
{
unsigned int l_nlsize = p_netlinkList->m_size;
struct nlmsghdr *l_hdr;
for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
{
- if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
+ if((pid_t)l_hdr->nlmsg_pid != p_pid || (int)l_hdr->nlmsg_seq != p_socket)
{
continue;
}
@@ -612,16 +619,15 @@ static int interpretLinks(int p_socket, NetlinkList *p_netlinkList, struct ifadd
return l_numLinks;
}
-static int interpretAddrs(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList, int p_numLinks)
+static int interpretAddrs(int p_socket, pid_t p_pid, NetlinkList *p_netlinkList, struct ifaddrs **p_resultList, int p_numLinks)
{
- pid_t l_pid = getpid();
for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
{
unsigned int l_nlsize = p_netlinkList->m_size;
struct nlmsghdr *l_hdr;
for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
{
- if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
+ if((pid_t)l_hdr->nlmsg_pid != p_pid || (int)l_hdr->nlmsg_seq != p_socket)
{
continue;
}
@@ -648,6 +654,7 @@ int getifaddrs(struct ifaddrs **ifap)
int l_socket;
int l_result;
int l_numLinks;
+ pid_t l_pid;
NetlinkList *l_linkResults;
NetlinkList *l_addrResults;
@@ -657,20 +664,20 @@ int getifaddrs(struct ifaddrs **ifap)
}
*ifap = NULL;
- l_socket = netlink_socket();
+ l_socket = netlink_socket(&l_pid);
if(l_socket < 0)
{
return -1;
}
- l_linkResults = getResultList(l_socket, RTM_GETLINK);
+ l_linkResults = getResultList(l_socket, RTM_GETLINK, l_pid);
if(!l_linkResults)
{
close(l_socket);
return -1;
}
- l_addrResults = getResultList(l_socket, RTM_GETADDR);
+ l_addrResults = getResultList(l_socket, RTM_GETADDR, l_pid);
if(!l_addrResults)
{
close(l_socket);
@@ -679,8 +686,8 @@ int getifaddrs(struct ifaddrs **ifap)
}
l_result = 0;
- l_numLinks = interpretLinks(l_socket, l_linkResults, ifap);
- if(l_numLinks == -1 || interpretAddrs(l_socket, l_addrResults, ifap, l_numLinks) == -1)
+ l_numLinks = interpretLinks(l_socket, l_pid, l_linkResults, ifap);
+ if(l_numLinks == -1 || interpretAddrs(l_socket, l_pid, l_addrResults, ifap, l_numLinks) == -1)
{
l_result = -1;
}
diff --git a/Utilities/cmlibuv/src/unix/atomic-ops.h b/Utilities/cmlibuv/src/unix/atomic-ops.h
index 9dac2557f8..7cac1f9889 100644
--- a/Utilities/cmlibuv/src/unix/atomic-ops.h
+++ b/Utilities/cmlibuv/src/unix/atomic-ops.h
@@ -20,7 +20,6 @@
#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
#include <atomic.h>
-#define __sync_val_compare_and_swap(p, o, n) atomic_cas_ptr(p, o, n)
#endif
UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval));
@@ -49,6 +48,8 @@ UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) {
return oldval;
else
return op4;
+#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+ return atomic_cas_uint(ptr, oldval, newval);
#else
return __sync_val_compare_and_swap(ptr, oldval, newval);
#endif
@@ -83,6 +84,8 @@ UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)) {
return oldval;
else
return op4;
+#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+ return atomic_cas_ulong(ptr, oldval, newval);
#else
return __sync_val_compare_and_swap(ptr, oldval, newval);
#endif
diff --git a/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c b/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c
index 414789451a..ea3166c5e9 100644
--- a/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c
+++ b/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c
@@ -31,11 +31,20 @@
#include <net/if_dl.h>
#endif
-static int uv__ifaddr_exclude(struct ifaddrs *ent) {
+static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
return 1;
if (ent->ifa_addr == NULL)
return 1;
+#if !defined(__CYGWIN__) && !defined(__MSYS__)
+ /*
+ * If `exclude_type` is `UV__EXCLUDE_IFPHYS`, just see whether `sa_family`
+ * equals to `AF_LINK` or not. Otherwise, the result depends on the operation
+ * system with `AF_LINK` or `PF_INET`.
+ */
+ if (exclude_type == UV__EXCLUDE_IFPHYS)
+ return (ent->ifa_addr->sa_family != AF_LINK);
+#endif
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__)
/*
* On BSD getifaddrs returns information related to the raw underlying
@@ -43,7 +52,11 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent) {
*/
if (ent->ifa_addr->sa_family == AF_LINK)
return 1;
-#elif defined(__NetBSD__) || defined(__OpenBSD__)
+#elif defined(__NetBSD__)
+ if (ent->ifa_addr->sa_family != PF_INET &&
+ ent->ifa_addr->sa_family != PF_INET6)
+ return 1;
+#elif defined(__OpenBSD__)
if (ent->ifa_addr->sa_family != PF_INET)
return 1;
#endif
@@ -63,7 +76,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
/* Count the number of interfaces */
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
- if (uv__ifaddr_exclude(ent))
+ if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
continue;
(*count)++;
}
@@ -78,7 +91,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
address = *addresses;
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
- if (uv__ifaddr_exclude(ent))
+ if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
continue;
address->name = uv__strdup(ent->ifa_name);
@@ -102,7 +115,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
/* Fill in physical addresses for each interface */
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
- if (uv__ifaddr_exclude(ent))
+ if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFPHYS))
continue;
address = *addresses;
diff --git a/Utilities/cmlibuv/src/unix/core.c b/Utilities/cmlibuv/src/unix/core.c
index 30cdaef7ba..c7e431e529 100644
--- a/Utilities/cmlibuv/src/unix/core.c
+++ b/Utilities/cmlibuv/src/unix/core.c
@@ -28,7 +28,6 @@
#include <errno.h>
#include <assert.h>
#include <unistd.h>
-#include <sys/param.h> /* MAXHOSTNAMELEN on Linux and the BSDs */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
@@ -59,13 +58,19 @@
#if defined(__DragonFly__) || \
defined(__FreeBSD__) || \
- defined(__FreeBSD_kernel__)
+ defined(__FreeBSD_kernel__) || \
+ defined(__NetBSD__)
# include <sys/sysctl.h>
# include <sys/filio.h>
# include <sys/wait.h>
# define UV__O_CLOEXEC O_CLOEXEC
# if defined(__FreeBSD__) && __FreeBSD__ >= 10
# define uv__accept4 accept4
+# endif
+# if defined(__NetBSD__)
+# define uv__accept4(a, b, c, d) paccept((a), (b), (c), NULL, (d))
+# endif
+# if (defined(__FreeBSD__) && __FreeBSD__ >= 10) || defined(__NetBSD__)
# define UV__SOCK_NONBLOCK SOCK_NONBLOCK
# define UV__SOCK_CLOEXEC SOCK_CLOEXEC
# endif
@@ -82,6 +87,10 @@
#include <sys/ioctl.h>
#endif
+#if !defined(__MVS__)
+#include <sys/param.h> /* MAXHOSTNAMELEN on Linux and the BSDs */
+#endif
+
/* Fallback for the maximum hostname length */
#ifndef MAXHOSTNAMELEN
# define MAXHOSTNAMELEN 256
@@ -459,7 +468,9 @@ int uv__accept(int sockfd) {
assert(sockfd >= 0);
while (1) {
-#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 10)
+#if defined(__linux__) || \
+ (defined(__FreeBSD__) && __FreeBSD__ >= 10) || \
+ defined(__NetBSD__)
static int no_accept4;
if (no_accept4)
@@ -835,7 +846,7 @@ void uv__io_init(uv__io_t* w, uv__io_cb cb, int fd) {
void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
- assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP)));
+ assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI)));
assert(0 != events);
assert(w->fd >= 0);
assert(w->fd < INT_MAX);
@@ -863,7 +874,7 @@ void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
- assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP)));
+ assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI)));
assert(0 != events);
if (w->fd == -1)
@@ -895,7 +906,7 @@ void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
void uv__io_close(uv_loop_t* loop, uv__io_t* w) {
- uv__io_stop(loop, w, POLLIN | POLLOUT | UV__POLLRDHUP);
+ uv__io_stop(loop, w, POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI);
QUEUE_REMOVE(&w->pending_queue);
/* Remove stale events for this file descriptor */
@@ -910,7 +921,7 @@ void uv__io_feed(uv_loop_t* loop, uv__io_t* w) {
int uv__io_active(const uv__io_t* w, unsigned int events) {
- assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP)));
+ assert(0 == (events & ~(POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI)));
assert(0 != events);
return 0 != (w->pevents & events);
}
@@ -985,7 +996,7 @@ int uv__open_cloexec(const char* path, int flags) {
int uv__dup2_cloexec(int oldfd, int newfd) {
int r;
-#if defined(__FreeBSD__) && __FreeBSD__ >= 10
+#if (defined(__FreeBSD__) && __FreeBSD__ >= 10) || defined(__NetBSD__)
r = dup3(oldfd, newfd, O_CLOEXEC);
if (r == -1)
return -errno;
@@ -1289,6 +1300,9 @@ int uv_os_setenv(const char* name, const char* value) {
int uv_os_unsetenv(const char* name) {
+ if (name == NULL)
+ return -EINVAL;
+
if (unsetenv(name) != 0)
return -errno;
@@ -1324,3 +1338,18 @@ int uv_os_gethostname(char* buffer, size_t* size) {
*size = len;
return 0;
}
+
+
+uv_os_fd_t uv_get_osfhandle(int fd) {
+ return fd;
+}
+
+
+uv_pid_t uv_os_getpid(void) {
+ return getpid();
+}
+
+
+uv_pid_t uv_os_getppid(void) {
+ return getppid();
+}
diff --git a/Utilities/cmlibuv/src/unix/freebsd.c b/Utilities/cmlibuv/src/unix/freebsd.c
index e52ae99dbe..f2b3f247a0 100644
--- a/Utilities/cmlibuv/src/unix/freebsd.c
+++ b/Utilities/cmlibuv/src/unix/freebsd.c
@@ -25,7 +25,6 @@
#include <string.h>
#include <errno.h>
-#include <kvm.h>
#include <paths.h>
#include <sys/user.h>
#include <sys/types.h>
@@ -48,9 +47,16 @@
# define CP_INTR 4
#endif
+static uv_mutex_t process_title_mutex;
+static uv_once_t process_title_mutex_once = UV_ONCE_INIT;
static char *process_title;
+static void init_process_title_mutex_once(void) {
+ uv_mutex_init(&process_title_mutex);
+}
+
+
int uv__platform_loop_init(uv_loop_t* loop) {
return uv__kqueue_init(loop);
}
@@ -161,9 +167,20 @@ char** uv_setup_args(int argc, char** argv) {
int uv_set_process_title(const char* title) {
int oid[4];
+ char* new_title;
+
+ new_title = uv__strdup(title);
+
+ uv_once(&process_title_mutex_once, init_process_title_mutex_once);
+ uv_mutex_lock(&process_title_mutex);
+
+ if (process_title == NULL) {
+ uv_mutex_unlock(&process_title_mutex);
+ return -ENOMEM;
+ }
uv__free(process_title);
- process_title = uv__strdup(title);
+ process_title = new_title;
oid[0] = CTL_KERN;
oid[1] = KERN_PROC;
@@ -177,6 +194,8 @@ int uv_set_process_title(const char* title) {
process_title,
strlen(process_title) + 1);
+ uv_mutex_unlock(&process_title_mutex);
+
return 0;
}
@@ -187,51 +206,54 @@ int uv_get_process_title(char* buffer, size_t size) {
if (buffer == NULL || size == 0)
return -EINVAL;
+ uv_once(&process_title_mutex_once, init_process_title_mutex_once);
+ uv_mutex_lock(&process_title_mutex);
+
if (process_title) {
len = strlen(process_title) + 1;
- if (size < len)
+ if (size < len) {
+ uv_mutex_unlock(&process_title_mutex);
return -ENOBUFS;
+ }
memcpy(buffer, process_title, len);
} else {
len = 0;
}
+ uv_mutex_unlock(&process_title_mutex);
+
buffer[len] = '\0';
return 0;
}
-
int uv_resident_set_memory(size_t* rss) {
- kvm_t *kd = NULL;
- struct kinfo_proc *kinfo = NULL;
- pid_t pid;
- int nprocs;
- size_t page_size = getpagesize();
+ struct kinfo_proc kinfo;
+ size_t page_size;
+ size_t kinfo_size;
+ int mib[4];
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = getpid();
- pid = getpid();
+ kinfo_size = sizeof(kinfo);
- kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "kvm_open");
- if (kd == NULL) goto error;
+ if (sysctl(mib, 4, &kinfo, &kinfo_size, NULL, 0))
+ return -errno;
- kinfo = kvm_getprocs(kd, KERN_PROC_PID, pid, &nprocs);
- if (kinfo == NULL) goto error;
+ page_size = getpagesize();
#ifdef __DragonFly__
- *rss = kinfo->kp_vm_rssize * page_size;
+ *rss = kinfo.kp_vm_rssize * page_size;
#else
- *rss = kinfo->ki_rssize * page_size;
+ *rss = kinfo.ki_rssize * page_size;
#endif
- kvm_close(kd);
-
return 0;
-
-error:
- if (kd) kvm_close(kd);
- return -EPERM;
}
@@ -254,6 +276,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
uv_cpu_info_t* cpu_info;
const char* maxcpus_key;
const char* cptimes_key;
+ const char* model_key;
char model[512];
long* cp_times;
int numcpus;
@@ -272,8 +295,20 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
cptimes_key = "kern.cp_times";
#endif
+#if defined(__arm__) || defined(__aarch64__)
+ /* The key hw.model and hw.clockrate are not available on FreeBSD ARM. */
+ model_key = "hw.machine";
+ cpuspeed = 0;
+#else
+ model_key = "hw.model";
+
+ size = sizeof(cpuspeed);
+ if (sysctlbyname("hw.clockrate", &cpuspeed, &size, NULL, 0))
+ return -errno;
+#endif
+
size = sizeof(model);
- if (sysctlbyname("hw.model", &model, &size, NULL, 0))
+ if (sysctlbyname(model_key, &model, &size, NULL, 0))
return -errno;
size = sizeof(numcpus);
@@ -286,12 +321,6 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
*count = numcpus;
- size = sizeof(cpuspeed);
- if (sysctlbyname("hw.clockrate", &cpuspeed, &size, NULL, 0)) {
- uv__free(*cpu_infos);
- return -errno;
- }
-
/* kern.cp_times on FreeBSD i386 gives an array up to maxcpus instead of
* ncpu.
*/
diff --git a/Utilities/cmlibuv/src/unix/fs.c b/Utilities/cmlibuv/src/unix/fs.c
index 82c91efb2c..0a4c183eb6 100644
--- a/Utilities/cmlibuv/src/unix/fs.c
+++ b/Utilities/cmlibuv/src/unix/fs.c
@@ -60,8 +60,14 @@
# include <sys/sendfile.h>
#endif
+#if defined(__APPLE__)
+# include <copyfile.h>
+#endif
+
#define INIT(subtype) \
do { \
+ if (req == NULL) \
+ return -EINVAL; \
req->type = UV_FS; \
if (cb != NULL) \
uv__req_init(loop, req, UV_FS); \
@@ -126,26 +132,33 @@
while (0)
-static ssize_t uv__fs_fdatasync(uv_fs_t* req) {
-#if defined(__linux__) || defined(__sun) || defined(__NetBSD__)
- return fdatasync(req->file);
-#elif defined(__APPLE__)
+static ssize_t uv__fs_fsync(uv_fs_t* req) {
+#if defined(__APPLE__)
/* Apple's fdatasync and fsync explicitly do NOT flush the drive write cache
* to the drive platters. This is in contrast to Linux's fdatasync and fsync
* which do, according to recent man pages. F_FULLFSYNC is Apple's equivalent
- * for flushing buffered data to permanent storage.
+ * for flushing buffered data to permanent storage. If F_FULLFSYNC is not
+ * supported by the file system we should fall back to fsync(). This is the
+ * same approach taken by sqlite.
*/
- return fcntl(req->file, F_FULLFSYNC);
+ int r;
+
+ r = fcntl(req->file, F_FULLFSYNC);
+ if (r != 0 && errno == ENOTTY)
+ r = fsync(req->file);
+ return r;
#else
return fsync(req->file);
#endif
}
-static ssize_t uv__fs_fsync(uv_fs_t* req) {
-#if defined(__APPLE__)
- /* See the comment in uv__fs_fdatasync. */
- return fcntl(req->file, F_FULLFSYNC);
+static ssize_t uv__fs_fdatasync(uv_fs_t* req) {
+#if defined(__linux__) || defined(__sun) || defined(__NetBSD__)
+ return fdatasync(req->file);
+#elif defined(__APPLE__)
+ /* See the comment in uv__fs_fsync. */
+ return uv__fs_fsync(req);
#else
return fsync(req->file);
#endif
@@ -442,7 +455,12 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) {
return -1;
}
+#if defined(__MVS__)
+ len = os390_readlink(req->path, buf, len);
+#else
len = readlink(req->path, buf, len);
+#endif
+
if (len == -1) {
uv__free(buf);
@@ -776,6 +794,118 @@ done:
return r;
}
+static ssize_t uv__fs_copyfile(uv_fs_t* req) {
+#if defined(__APPLE__) && !TARGET_OS_IPHONE
+ /* On macOS, use the native copyfile(3). */
+ copyfile_flags_t flags;
+
+ flags = COPYFILE_ALL;
+
+ if (req->flags & UV_FS_COPYFILE_EXCL)
+ flags |= COPYFILE_EXCL;
+
+ return copyfile(req->path, req->new_path, NULL, flags);
+#else
+ uv_fs_t fs_req;
+ uv_file srcfd;
+ uv_file dstfd;
+ struct stat statsbuf;
+ int dst_flags;
+ int result;
+ int err;
+ size_t bytes_to_send;
+ int64_t in_offset;
+
+ dstfd = -1;
+ err = 0;
+
+ /* Open the source file. */
+ srcfd = uv_fs_open(NULL, &fs_req, req->path, O_RDONLY, 0, NULL);
+ uv_fs_req_cleanup(&fs_req);
+
+ if (srcfd < 0)
+ return srcfd;
+
+ /* Get the source file's mode. */
+ if (fstat(srcfd, &statsbuf)) {
+ err = -errno;
+ goto out;
+ }
+
+ dst_flags = O_WRONLY | O_CREAT | O_TRUNC;
+
+ if (req->flags & UV_FS_COPYFILE_EXCL)
+ dst_flags |= O_EXCL;
+
+ /* Open the destination file. */
+ dstfd = uv_fs_open(NULL,
+ &fs_req,
+ req->new_path,
+ dst_flags,
+ statsbuf.st_mode,
+ NULL);
+ uv_fs_req_cleanup(&fs_req);
+
+ if (dstfd < 0) {
+ err = dstfd;
+ goto out;
+ }
+
+ if (fchmod(dstfd, statsbuf.st_mode) == -1) {
+ err = -errno;
+ goto out;
+ }
+
+ bytes_to_send = statsbuf.st_size;
+ in_offset = 0;
+ while (bytes_to_send != 0) {
+ err = uv_fs_sendfile(NULL,
+ &fs_req,
+ dstfd,
+ srcfd,
+ in_offset,
+ bytes_to_send,
+ NULL);
+ uv_fs_req_cleanup(&fs_req);
+ if (err < 0)
+ break;
+ bytes_to_send -= fs_req.result;
+ in_offset += fs_req.result;
+ }
+
+out:
+ if (err < 0)
+ result = err;
+ else
+ result = 0;
+
+ /* Close the source file. */
+ err = uv__close_nocheckstdio(srcfd);
+
+ /* Don't overwrite any existing errors. */
+ if (err != 0 && result == 0)
+ result = err;
+
+ /* Close the destination file if it is open. */
+ if (dstfd >= 0) {
+ err = uv__close_nocheckstdio(dstfd);
+
+ /* Don't overwrite any existing errors. */
+ if (err != 0 && result == 0)
+ result = err;
+
+ /* Remove the destination file if something went wrong. */
+ if (result != 0) {
+ uv_fs_unlink(NULL, &fs_req, req->new_path, NULL);
+ /* Ignore the unlink return value, as an error already happened. */
+ uv_fs_req_cleanup(&fs_req);
+ }
+ }
+
+ return result;
+#endif
+}
+
static void uv__to_stat(struct stat* src, uv_stat_t* dst) {
dst->st_dev = src->st_dev;
dst->st_mode = src->st_mode;
@@ -956,6 +1086,7 @@ static void uv__fs_work(struct uv__work* w) {
X(CHMOD, chmod(req->path, req->mode));
X(CHOWN, chown(req->path, req->uid, req->gid));
X(CLOSE, close(req->file));
+ X(COPYFILE, uv__fs_copyfile(req));
X(FCHMOD, fchmod(req->file, req->mode));
X(FCHOWN, fchown(req->file, req->uid, req->gid));
X(FDATASYNC, uv__fs_fdatasync(req));
@@ -1196,10 +1327,11 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req,
unsigned int nbufs,
int64_t off,
uv_fs_cb cb) {
+ INIT(READ);
+
if (bufs == NULL || nbufs == 0)
return -EINVAL;
- INIT(READ);
req->file = file;
req->nbufs = nbufs;
@@ -1334,10 +1466,11 @@ int uv_fs_write(uv_loop_t* loop,
unsigned int nbufs,
int64_t off,
uv_fs_cb cb) {
+ INIT(WRITE);
+
if (bufs == NULL || nbufs == 0)
return -EINVAL;
- INIT(WRITE);
req->file = file;
req->nbufs = nbufs;
@@ -1359,6 +1492,9 @@ int uv_fs_write(uv_loop_t* loop,
void uv_fs_req_cleanup(uv_fs_t* req) {
+ if (req == NULL)
+ return;
+
/* Only necessary for asychronous requests, i.e., requests with a callback.
* Synchronous ones don't copy their arguments and have req->path and
* req->new_path pointing to user-owned memory. UV_FS_MKDTEMP is the
@@ -1377,3 +1513,20 @@ void uv_fs_req_cleanup(uv_fs_t* req) {
uv__free(req->ptr);
req->ptr = NULL;
}
+
+
+int uv_fs_copyfile(uv_loop_t* loop,
+ uv_fs_t* req,
+ const char* path,
+ const char* new_path,
+ int flags,
+ uv_fs_cb cb) {
+ INIT(COPYFILE);
+
+ if (flags & ~UV_FS_COPYFILE_EXCL)
+ return -EINVAL;
+
+ PATH2;
+ req->flags = flags;
+ POST;
+}
diff --git a/Utilities/cmlibuv/src/unix/fsevents.c b/Utilities/cmlibuv/src/unix/fsevents.c
index 643e233cfe..38837406a6 100644
--- a/Utilities/cmlibuv/src/unix/fsevents.c
+++ b/Utilities/cmlibuv/src/unix/fsevents.c
@@ -230,6 +230,7 @@ static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef,
uv_loop_t* loop;
uv__cf_loop_state_t* state;
uv__fsevents_event_t* event;
+ FSEventStreamEventFlags flags;
QUEUE head;
loop = info;
@@ -245,8 +246,10 @@ static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef,
/* Process and filter out events */
for (i = 0; i < numEvents; i++) {
+ flags = eventFlags[i];
+
/* Ignore system events */
- if (eventFlags[i] & kFSEventsSystem)
+ if (flags & kFSEventsSystem)
continue;
path = paths[i];
@@ -271,6 +274,9 @@ static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef,
/* Ignore events with path equal to directory itself */
if (len == 0)
continue;
+#else
+ if (len == 0 && (flags & kFSEventStreamEventFlagItemIsDir))
+ continue;
#endif /* MAC_OS_X_VERSION_10_7 */
/* Do not emit events from subdirectories (without option set) */
@@ -291,12 +297,24 @@ static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef,
memset(event, 0, sizeof(*event));
memcpy(event->path, path, len + 1);
+ event->events = UV_RENAME;
- if ((eventFlags[i] & kFSEventsModified) != 0 &&
- (eventFlags[i] & kFSEventsRenamed) == 0)
+#ifdef MAC_OS_X_VERSION_10_7
+ if (0 != (flags & kFSEventsModified) &&
+ 0 == (flags & kFSEventsRenamed)) {
+ event->events = UV_CHANGE;
+ }
+#else
+ if (0 != (flags & kFSEventsModified) &&
+ 0 != (flags & kFSEventStreamEventFlagItemIsDir) &&
+ 0 == (flags & kFSEventStreamEventFlagItemRenamed)) {
event->events = UV_CHANGE;
- else
- event->events = UV_RENAME;
+ }
+ if (0 == (flags & kFSEventStreamEventFlagItemIsDir) &&
+ 0 == (flags & kFSEventStreamEventFlagItemRenamed)) {
+ event->events = UV_CHANGE;
+ }
+#endif /* MAC_OS_X_VERSION_10_7 */
QUEUE_INSERT_TAIL(&head, &event->member);
}
diff --git a/Utilities/cmlibuv/src/unix/getaddrinfo.c b/Utilities/cmlibuv/src/unix/getaddrinfo.c
index 2049aea2f3..0185971697 100644
--- a/Utilities/cmlibuv/src/unix/getaddrinfo.c
+++ b/Utilities/cmlibuv/src/unix/getaddrinfo.c
@@ -32,6 +32,7 @@
#include <stddef.h> /* NULL */
#include <stdlib.h>
#include <string.h>
+#include <net/if.h> /* if_indextoname() */
/* EAI_* constants. */
#include <netdb.h>
@@ -200,3 +201,32 @@ void uv_freeaddrinfo(struct addrinfo* ai) {
if (ai)
freeaddrinfo(ai);
}
+
+
+int uv_if_indextoname(unsigned int ifindex, char* buffer, size_t* size) {
+ char ifname_buf[UV_IF_NAMESIZE];
+ size_t len;
+
+ if (buffer == NULL || size == NULL || *size == 0)
+ return UV_EINVAL;
+
+ if (if_indextoname(ifindex, ifname_buf) == NULL)
+ return -errno;
+
+ len = strnlen(ifname_buf, sizeof(ifname_buf));
+
+ if (*size <= len) {
+ *size = len + 1;
+ return UV_ENOBUFS;
+ }
+
+ memcpy(buffer, ifname_buf, len);
+ buffer[len] = '\0';
+ *size = len;
+
+ return 0;
+}
+
+int uv_if_indextoiid(unsigned int ifindex, char* buffer, size_t* size) {
+ return uv_if_indextoname(ifindex, buffer, size);
+}
diff --git a/Utilities/cmlibuv/src/unix/ibmi.c b/Utilities/cmlibuv/src/unix/ibmi.c
new file mode 100644
index 0000000000..c19e2fc379
--- /dev/null
+++ b/Utilities/cmlibuv/src/unix/ibmi.c
@@ -0,0 +1,112 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "internal.h"
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <sys/time.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <utmp.h>
+#include <libgen.h>
+
+#include <sys/protosw.h>
+#include <procinfo.h>
+#include <sys/proc.h>
+#include <sys/procfs.h>
+
+#include <ctype.h>
+
+#include <sys/mntctl.h>
+#include <sys/vmount.h>
+#include <limits.h>
+#include <strings.h>
+#include <sys/vnode.h>
+
+uint64_t uv_get_free_memory(void) {
+ return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_AVPHYS_PAGES);
+}
+
+
+uint64_t uv_get_total_memory(void) {
+ return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_PHYS_PAGES);
+}
+
+
+void uv_loadavg(double avg[3]) {
+ avg[0] = avg[1] = avg[2] = 0;
+ return;
+}
+
+
+int uv_resident_set_memory(size_t* rss) {
+ return UV_ENOSYS;
+}
+
+
+int uv_uptime(double* uptime) {
+ return UV_ENOSYS;
+}
+
+
+int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
+ unsigned int numcpus, idx = 0;
+ uv_cpu_info_t* cpu_info;
+
+ *cpu_infos = NULL;
+ *count = 0;
+
+ numcpus = sysconf(_SC_NPROCESSORS_ONLN);
+
+ *cpu_infos = uv__malloc(numcpus * sizeof(uv_cpu_info_t));
+ if (!*cpu_infos) {
+ return -ENOMEM;
+ }
+
+ cpu_info = *cpu_infos;
+ for (idx = 0; idx < numcpus; idx++) {
+ cpu_info->speed = 0;
+ cpu_info->model = uv__strdup("unknown");
+ cpu_info->cpu_times.user = 0;
+ cpu_info->cpu_times.sys = 0;
+ cpu_info->cpu_times.idle = 0;
+ cpu_info->cpu_times.irq = 0;
+ cpu_info->cpu_times.nice = 0;
+ cpu_info++;
+ }
+ *count = numcpus;
+
+ return 0;
+}
diff --git a/Utilities/cmlibuv/src/unix/internal.h b/Utilities/cmlibuv/src/unix/internal.h
index e9f790850c..9cc87f0caa 100644
--- a/Utilities/cmlibuv/src/unix/internal.h
+++ b/Utilities/cmlibuv/src/unix/internal.h
@@ -120,6 +120,12 @@ int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset);
# define UV__POLLRDHUP 0x2000
#endif
+#ifdef POLLPRI
+# define UV__POLLPRI POLLPRI
+#else
+# define UV__POLLPRI 0
+#endif
+
#if !defined(O_CLOEXEC) && defined(__FreeBSD__)
/*
* It may be that we are just missing `__POSIX_VISIBLE >= 200809`.
@@ -155,6 +161,12 @@ enum {
UV_LOOP_BLOCK_SIGPROF = 1
};
+/* flags of excluding ifaddr */
+enum {
+ UV__EXCLUDE_IFPHYS,
+ UV__EXCLUDE_IFADDR
+};
+
typedef enum {
UV_CLOCK_PRECISE = 0, /* Use the highest resolution clock available. */
UV_CLOCK_FAST = 1 /* Use the fastest clock with <= 1ms granularity. */
@@ -173,7 +185,8 @@ struct uv__stream_queued_fds_s {
defined(__FreeBSD__) || \
defined(__FreeBSD_kernel__) || \
defined(__linux__) || \
- defined(__OpenBSD__)
+ defined(__OpenBSD__) || \
+ defined(__NetBSD__)
#define uv__cloexec uv__cloexec_ioctl
#define uv__nonblock uv__nonblock_ioctl
#else
diff --git a/Utilities/cmlibuv/src/unix/kqueue.c b/Utilities/cmlibuv/src/unix/kqueue.c
index 6bc60bbe46..5e89bdced4 100644
--- a/Utilities/cmlibuv/src/unix/kqueue.c
+++ b/Utilities/cmlibuv/src/unix/kqueue.c
@@ -34,6 +34,17 @@
#include <fcntl.h>
#include <time.h>
+/*
+ * Required on
+ * - Until at least FreeBSD 11.0
+ * - Older versions of Mac OS X
+ *
+ * http://www.boost.org/doc/libs/1_61_0/boost/asio/detail/kqueue_reactor.hpp
+ */
+#ifndef EV_OOBAND
+#define EV_OOBAND EV_FLAG1
+#endif
+
static void uv__fs_event(uv_loop_t* loop, uv__io_t* w, unsigned int fflags);
@@ -48,11 +59,12 @@ int uv__kqueue_init(uv_loop_t* loop) {
}
+#if defined(__APPLE__)
static int uv__has_forked_with_cfrunloop;
+#endif
int uv__io_fork(uv_loop_t* loop) {
int err;
- uv__close(loop->backend_fd);
loop->backend_fd = -1;
err = uv__kqueue_init(loop);
if (err)
@@ -166,6 +178,16 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
}
}
+ if ((w->events & UV__POLLPRI) == 0 && (w->pevents & UV__POLLPRI) != 0) {
+ EV_SET(events + nevents, w->fd, EV_OOBAND, EV_ADD, 0, 0, 0);
+
+ if (++nevents == ARRAY_SIZE(events)) {
+ if (kevent(loop->backend_fd, events, nevents, NULL, 0, NULL))
+ abort();
+ nevents = 0;
+ }
+ }
+
w->events = w->pevents;
}
@@ -275,6 +297,20 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
}
}
+ if (ev->filter == EV_OOBAND) {
+ if (w->pevents & UV__POLLPRI) {
+ revents |= UV__POLLPRI;
+ w->rcount = ev->data;
+ } else {
+ /* TODO batch up */
+ struct kevent events[1];
+ EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0);
+ if (kevent(loop->backend_fd, events, 1, NULL, 0, NULL))
+ if (errno != ENOENT)
+ abort();
+ }
+ }
+
if (ev->filter == EVFILT_WRITE) {
if (w->pevents & POLLOUT) {
revents |= POLLOUT;
diff --git a/Utilities/cmlibuv/src/unix/linux-core.c b/Utilities/cmlibuv/src/unix/linux-core.c
index 2866e93854..4d480ce10a 100644
--- a/Utilities/cmlibuv/src/unix/linux-core.c
+++ b/Utilities/cmlibuv/src/unix/linux-core.c
@@ -388,7 +388,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
* free when we switch over to edge-triggered I/O.
*/
if (pe->events == POLLERR || pe->events == POLLHUP)
- pe->events |= w->pevents & (POLLIN | POLLOUT);
+ pe->events |= w->pevents & (POLLIN | POLLOUT | UV__POLLPRI);
if (pe->events != 0) {
/* Run signal watchers last. This also affects child process watchers
@@ -837,7 +837,7 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
uv__free(cpu_infos);
}
-static int uv__ifaddr_exclude(struct ifaddrs *ent) {
+static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
return 1;
if (ent->ifa_addr == NULL)
@@ -847,8 +847,8 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent) {
* devices. We're not interested in this information yet.
*/
if (ent->ifa_addr->sa_family == PF_PACKET)
- return 1;
- return 0;
+ return exclude_type;
+ return !exclude_type;
}
int uv_interface_addresses(uv_interface_address_t** addresses,
@@ -869,7 +869,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
/* Count the number of interfaces */
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
- if (uv__ifaddr_exclude(ent))
+ if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
continue;
(*count)++;
@@ -887,7 +887,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
address = *addresses;
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
- if (uv__ifaddr_exclude(ent))
+ if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
continue;
address->name = uv__strdup(ent->ifa_name);
@@ -911,7 +911,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses,
/* Fill in physical addresses for each interface */
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
- if (uv__ifaddr_exclude(ent))
+ if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFPHYS))
continue;
address = *addresses;
diff --git a/Utilities/cmlibuv/src/unix/loop.c b/Utilities/cmlibuv/src/unix/loop.c
index bcd49242ce..5b5b0e095b 100644
--- a/Utilities/cmlibuv/src/unix/loop.c
+++ b/Utilities/cmlibuv/src/unix/loop.c
@@ -31,7 +31,6 @@ int uv_loop_init(uv_loop_t* loop) {
void* saved_data;
int err;
- uv__signal_global_once_init();
saved_data = loop->data;
memset(loop, 0, sizeof(*loop));
@@ -68,6 +67,7 @@ int uv_loop_init(uv_loop_t* loop) {
if (err)
return err;
+ uv__signal_global_once_init();
err = uv_signal_init(loop, &loop->child_watcher);
if (err)
goto fail_signal_init;
diff --git a/Utilities/cmlibuv/src/unix/netbsd.c b/Utilities/cmlibuv/src/unix/netbsd.c
index 9b5546b7e6..7425072331 100644
--- a/Utilities/cmlibuv/src/unix/netbsd.c
+++ b/Utilities/cmlibuv/src/unix/netbsd.c
@@ -40,9 +40,16 @@
#include <unistd.h>
#include <time.h>
+static uv_mutex_t process_title_mutex;
+static uv_once_t process_title_mutex_once = UV_ONCE_INIT;
static char *process_title;
+static void init_process_title_mutex_once(void) {
+ uv_mutex_init(&process_title_mutex);
+}
+
+
int uv__platform_loop_init(uv_loop_t* loop) {
return uv__kqueue_init(loop);
}
@@ -66,22 +73,32 @@ void uv_loadavg(double avg[3]) {
int uv_exepath(char* buffer, size_t* size) {
+ /* Intermediate buffer, retrieving partial path name does not work
+ * As of NetBSD-8(beta), vnode->path translator does not handle files
+ * with longer names than 31 characters.
+ */
+ char int_buf[PATH_MAX];
+ size_t int_size;
int mib[4];
- size_t cb;
- pid_t mypid;
if (buffer == NULL || size == NULL || *size == 0)
return -EINVAL;
- mypid = getpid();
mib[0] = CTL_KERN;
mib[1] = KERN_PROC_ARGS;
- mib[2] = mypid;
- mib[3] = KERN_PROC_ARGV;
+ mib[2] = -1;
+ mib[3] = KERN_PROC_PATHNAME;
+ int_size = ARRAY_SIZE(int_buf);
- cb = *size;
- if (sysctl(mib, 4, buffer, &cb, NULL, 0))
+ if (sysctl(mib, 4, int_buf, &int_size, NULL, 0))
return -errno;
+
+ /* Copy string from the intermediate buffer to outer one with appropriate
+ * length.
+ */
+ strlcpy(buffer, int_buf, *size);
+
+ /* Set new size. */
*size = strlen(buffer);
return 0;
@@ -124,11 +141,24 @@ char** uv_setup_args(int argc, char** argv) {
int uv_set_process_title(const char* title) {
- if (process_title) uv__free(process_title);
+ char* new_title;
+
+ new_title = uv__strdup(title);
+
+ uv_once(&process_title_mutex_once, init_process_title_mutex_once);
+ uv_mutex_lock(&process_title_mutex);
- process_title = uv__strdup(title);
+ if (process_title == NULL) {
+ uv_mutex_unlock(&process_title_mutex);
+ return -ENOMEM;
+ }
+
+ uv__free(process_title);
+ process_title = new_title;
setproctitle("%s", title);
+ uv_mutex_unlock(&process_title_mutex);
+
return 0;
}
@@ -139,17 +169,24 @@ int uv_get_process_title(char* buffer, size_t size) {
if (buffer == NULL || size == 0)
return -EINVAL;
+ uv_once(&process_title_mutex_once, init_process_title_mutex_once);
+ uv_mutex_lock(&process_title_mutex);
+
if (process_title) {
len = strlen(process_title) + 1;
- if (size < len)
+ if (size < len) {
+ uv_mutex_unlock(&process_title_mutex);
return -ENOBUFS;
+ }
memcpy(buffer, process_title, len);
} else {
len = 0;
}
+ uv_mutex_unlock(&process_title_mutex);
+
buffer[len] = '\0';
return 0;
diff --git a/Utilities/cmlibuv/src/unix/openbsd.c b/Utilities/cmlibuv/src/unix/openbsd.c
index 56f0af15c3..c0ffa564b4 100644
--- a/Utilities/cmlibuv/src/unix/openbsd.c
+++ b/Utilities/cmlibuv/src/unix/openbsd.c
@@ -36,9 +36,16 @@
#include <unistd.h>
+static uv_mutex_t process_title_mutex;
+static uv_once_t process_title_mutex_once = UV_ONCE_INIT;
static char *process_title;
+static void init_process_title_mutex_once(void) {
+ uv_mutex_init(&process_title_mutex);
+}
+
+
int uv__platform_loop_init(uv_loop_t* loop) {
return uv__kqueue_init(loop);
}
@@ -146,9 +153,24 @@ char** uv_setup_args(int argc, char** argv) {
int uv_set_process_title(const char* title) {
+ char* new_title;
+
+ new_title = uv__strdup(title);
+
+ uv_once(&process_title_mutex_once, init_process_title_mutex_once);
+ uv_mutex_lock(&process_title_mutex);
+
+ if (process_title == NULL) {
+ uv_mutex_unlock(&process_title_mutex);
+ return -ENOMEM;
+ }
+
uv__free(process_title);
- process_title = uv__strdup(title);
+ process_title = new_title;
setproctitle("%s", title);
+
+ uv_mutex_unlock(&process_title_mutex);
+
return 0;
}
@@ -159,17 +181,24 @@ int uv_get_process_title(char* buffer, size_t size) {
if (buffer == NULL || size == 0)
return -EINVAL;
+ uv_once(&process_title_mutex_once, init_process_title_mutex_once);
+ uv_mutex_lock(&process_title_mutex);
+
if (process_title) {
len = strlen(process_title) + 1;
- if (size < len)
+ if (size < len) {
+ uv_mutex_unlock(&process_title_mutex);
return -ENOBUFS;
+ }
memcpy(buffer, process_title, len);
} else {
len = 0;
}
+ uv_mutex_unlock(&process_title_mutex);
+
buffer[len] = '\0';
return 0;
diff --git a/Utilities/cmlibuv/src/unix/os390-syscalls.c b/Utilities/cmlibuv/src/unix/os390-syscalls.c
index 7edf2358d4..21558ea868 100644
--- a/Utilities/cmlibuv/src/unix/os390-syscalls.c
+++ b/Utilities/cmlibuv/src/unix/os390-syscalls.c
@@ -25,6 +25,8 @@
#include <stdlib.h>
#include <assert.h>
#include <search.h>
+#include <termios.h>
+#include <sys/msg.h>
#define CW_CONDVAR 32
@@ -103,10 +105,19 @@ static void maybe_resize(uv__os390_epoll* lst, unsigned int len) {
unsigned int newsize;
unsigned int i;
struct pollfd* newlst;
+ struct pollfd event;
if (len <= lst->size)
return;
+ if (lst->size == 0)
+ event.fd = -1;
+ else {
+ /* Extract the message queue at the end. */
+ event = lst->items[lst->size - 1];
+ lst->items[lst->size - 1].fd = -1;
+ }
+
newsize = next_power_of_two(len);
newlst = uv__realloc(lst->items, newsize * sizeof(lst->items[0]));
@@ -115,32 +126,101 @@ static void maybe_resize(uv__os390_epoll* lst, unsigned int len) {
for (i = lst->size; i < newsize; ++i)
newlst[i].fd = -1;
+ /* Restore the message queue at the end */
+ newlst[newsize - 1] = event;
+
lst->items = newlst;
lst->size = newsize;
}
+static void init_message_queue(uv__os390_epoll* lst) {
+ struct {
+ long int header;
+ char body;
+ } msg;
+
+ /* initialize message queue */
+ lst->msg_queue = msgget(IPC_PRIVATE, 0622 | IPC_CREAT);
+ if (lst->msg_queue == -1)
+ abort();
+
+ /*
+ On z/OS, the message queue will be affiliated with the process only
+ when a send is performed on it. Once this is done, the system
+ can be queried for all message queues belonging to our process id.
+ */
+ msg.header = 1;
+ if (msgsnd(lst->msg_queue, &msg, sizeof(msg.body), 0) != 0)
+ abort();
+
+ /* Clean up the dummy message sent above */
+ if (msgrcv(lst->msg_queue, &msg, sizeof(msg.body), 0, 0) != sizeof(msg.body))
+ abort();
+}
+
+
+static void before_fork(void) {
+ uv_mutex_lock(&global_epoll_lock);
+}
+
+
+static void after_fork(void) {
+ uv_mutex_unlock(&global_epoll_lock);
+}
+
+
+static void child_fork(void) {
+ QUEUE* q;
+ uv_once_t child_once = UV_ONCE_INIT;
+
+ /* reset once */
+ memcpy(&once, &child_once, sizeof(child_once));
+
+ /* reset epoll list */
+ while (!QUEUE_EMPTY(&global_epoll_queue)) {
+ uv__os390_epoll* lst;
+ q = QUEUE_HEAD(&global_epoll_queue);
+ QUEUE_REMOVE(q);
+ lst = QUEUE_DATA(q, uv__os390_epoll, member);
+ uv__free(lst->items);
+ lst->items = NULL;
+ lst->size = 0;
+ }
+
+ uv_mutex_unlock(&global_epoll_lock);
+ uv_mutex_destroy(&global_epoll_lock);
+}
+
+
static void epoll_init(void) {
QUEUE_INIT(&global_epoll_queue);
if (uv_mutex_init(&global_epoll_lock))
abort();
+
+ if (pthread_atfork(&before_fork, &after_fork, &child_fork))
+ abort();
}
uv__os390_epoll* epoll_create1(int flags) {
uv__os390_epoll* lst;
- uv_once(&once, epoll_init);
- uv_mutex_lock(&global_epoll_lock);
lst = uv__malloc(sizeof(*lst));
- if (lst == -1)
- return NULL;
- QUEUE_INSERT_TAIL(&global_epoll_queue, &lst->member);
- uv_mutex_unlock(&global_epoll_lock);
+ if (lst != NULL) {
+ /* initialize list */
+ lst->size = 0;
+ lst->items = NULL;
+ init_message_queue(lst);
+ maybe_resize(lst, 1);
+ lst->items[lst->size - 1].fd = lst->msg_queue;
+ lst->items[lst->size - 1].events = POLLIN;
+ uv_once(&once, epoll_init);
+ uv_mutex_lock(&global_epoll_lock);
+ QUEUE_INSERT_TAIL(&global_epoll_queue, &lst->member);
+ uv_mutex_unlock(&global_epoll_lock);
+ }
- /* initialize list */
- lst->size = 0;
- lst->items = NULL;
return lst;
}
@@ -149,22 +229,32 @@ int epoll_ctl(uv__os390_epoll* lst,
int op,
int fd,
struct epoll_event *event) {
- if(op == EPOLL_CTL_DEL) {
+ uv_mutex_lock(&global_epoll_lock);
+
+ if (op == EPOLL_CTL_DEL) {
if (fd >= lst->size || lst->items[fd].fd == -1) {
+ uv_mutex_unlock(&global_epoll_lock);
errno = ENOENT;
return -1;
}
lst->items[fd].fd = -1;
- } else if(op == EPOLL_CTL_ADD) {
- maybe_resize(lst, fd + 1);
+ } else if (op == EPOLL_CTL_ADD) {
+
+ /* Resizing to 'fd + 1' would expand the list to contain at least
+ * 'fd'. But we need to guarantee that the last index on the list
+ * is reserved for the message queue. So specify 'fd + 2' instead.
+ */
+ maybe_resize(lst, fd + 2);
if (lst->items[fd].fd != -1) {
+ uv_mutex_unlock(&global_epoll_lock);
errno = EEXIST;
return -1;
}
lst->items[fd].fd = fd;
lst->items[fd].events = event->events;
- } else if(op == EPOLL_CTL_MOD) {
+ } else if (op == EPOLL_CTL_MOD) {
if (fd >= lst->size || lst->items[fd].fd == -1) {
+ uv_mutex_unlock(&global_epoll_lock);
errno = ENOENT;
return -1;
}
@@ -172,44 +262,36 @@ int epoll_ctl(uv__os390_epoll* lst,
} else
abort();
+ uv_mutex_unlock(&global_epoll_lock);
return 0;
}
int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events,
int maxevents, int timeout) {
- size_t size;
+ nmsgsfds_t size;
struct pollfd* pfds;
int pollret;
int reventcount;
- uv_mutex_lock(&global_epoll_lock);
- uv_mutex_unlock(&global_epoll_lock);
- size = lst->size;
+ size = _SET_FDS_MSGS(size, 1, lst->size - 1);
pfds = lst->items;
pollret = poll(pfds, size, timeout);
- if(pollret == -1)
+ if (pollret <= 0)
return pollret;
+ pollret = _NFDS(pollret) + _NMSGS(pollret);
+
reventcount = 0;
- for (int i = 0; i < lst->size && i < maxevents; ++i) {
+ for (int i = 0;
+ i < lst->size && i < maxevents && reventcount < pollret; ++i) {
struct epoll_event ev;
- ev.events = 0;
- ev.fd = pfds[i].fd;
- if(!pfds[i].revents)
+ if (pfds[i].fd == -1 || pfds[i].revents == 0)
continue;
- if(pfds[i].revents & POLLRDNORM)
- ev.events = ev.events | POLLIN;
-
- if(pfds[i].revents & POLLWRNORM)
- ev.events = ev.events | POLLOUT;
-
- if(pfds[i].revents & POLLHUP)
- ev.events = ev.events | POLLHUP;
-
- pfds[i].revents = 0;
+ ev.fd = pfds[i].fd;
+ ev.events = pfds[i].revents;
events[reventcount++] = ev;
}
@@ -235,9 +317,14 @@ int epoll_file_close(int fd) {
}
void epoll_queue_close(uv__os390_epoll* lst) {
+ /* Remove epoll instance from global queue */
uv_mutex_lock(&global_epoll_lock);
QUEUE_REMOVE(&lst->member);
uv_mutex_unlock(&global_epoll_lock);
+
+ /* Free resources */
+ msgctl(lst->msg_queue, IPC_RMID, NULL);
+ lst->msg_queue = -1;
uv__free(lst->items);
lst->items = NULL;
}
@@ -332,3 +419,81 @@ char* mkdtemp(char* path) {
return path;
}
+
+
+ssize_t os390_readlink(const char* path, char* buf, size_t len) {
+ ssize_t rlen;
+ ssize_t vlen;
+ ssize_t plen;
+ char* delimiter;
+ char old_delim;
+ char* tmpbuf;
+ char realpathstr[PATH_MAX + 1];
+
+ tmpbuf = uv__malloc(len + 1);
+ if (tmpbuf == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ rlen = readlink(path, tmpbuf, len);
+ if (rlen < 0) {
+ uv__free(tmpbuf);
+ return rlen;
+ }
+
+ if (rlen < 3 || strncmp("/$", tmpbuf, 2) != 0) {
+ /* Straightforward readlink. */
+ memcpy(buf, tmpbuf, rlen);
+ uv__free(tmpbuf);
+ return rlen;
+ }
+
+ /*
+ * There is a parmlib variable at the beginning
+ * which needs interpretation.
+ */
+ tmpbuf[rlen] = '\0';
+ delimiter = strchr(tmpbuf + 2, '/');
+ if (delimiter == NULL)
+ /* No slash at the end */
+ delimiter = strchr(tmpbuf + 2, '\0');
+
+ /* Read real path of the variable. */
+ old_delim = *delimiter;
+ *delimiter = '\0';
+ if (realpath(tmpbuf, realpathstr) == NULL) {
+ uv__free(tmpbuf);
+ return -1;
+ }
+
+ /* realpathstr is not guaranteed to end with null byte.*/
+ realpathstr[PATH_MAX] = '\0';
+
+ /* Reset the delimiter and fill up the buffer. */
+ *delimiter = old_delim;
+ plen = strlen(delimiter);
+ vlen = strlen(realpathstr);
+ rlen = plen + vlen;
+ if (rlen > len) {
+ uv__free(tmpbuf);
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+ memcpy(buf, realpathstr, vlen);
+ memcpy(buf + vlen, delimiter, plen);
+
+ /* Done using temporary buffer. */
+ uv__free(tmpbuf);
+
+ return rlen;
+}
+
+
+size_t strnlen(const char* str, size_t maxlen) {
+ void* p = memchr(str, 0, maxlen);
+ if (p == NULL)
+ return maxlen;
+ else
+ return p - str;
+}
diff --git a/Utilities/cmlibuv/src/unix/os390-syscalls.h b/Utilities/cmlibuv/src/unix/os390-syscalls.h
index 61a7cee839..6e34a88cb9 100644
--- a/Utilities/cmlibuv/src/unix/os390-syscalls.h
+++ b/Utilities/cmlibuv/src/unix/os390-syscalls.h
@@ -50,6 +50,7 @@ typedef struct {
QUEUE member;
struct pollfd* items;
unsigned long size;
+ int msg_queue;
} uv__os390_epoll;
/* epoll api */
@@ -65,5 +66,7 @@ int scandir(const char* maindir, struct dirent*** namelist,
int (*compar)(const struct dirent **,
const struct dirent **));
char *mkdtemp(char* path);
+ssize_t os390_readlink(const char* path, char* buf, size_t len);
+size_t strnlen(const char* str, size_t maxlen);
#endif /* UV_OS390_SYSCALL_H_ */
diff --git a/Utilities/cmlibuv/src/unix/os390.c b/Utilities/cmlibuv/src/unix/os390.c
index 2ba5abf354..081438e8e7 100644
--- a/Utilities/cmlibuv/src/unix/os390.c
+++ b/Utilities/cmlibuv/src/unix/os390.c
@@ -25,6 +25,9 @@
#include <utmpx.h>
#include <unistd.h>
#include <sys/ps.h>
+#include <builtins.h>
+#include <termios.h>
+#include <sys/msg.h>
#if defined(__clang__)
#include "csrsic.h"
#else
@@ -32,6 +35,7 @@
#endif
#define CVT_PTR 0x10
+#define PSA_PTR 0x00
#define CSD_OFFSET 0x294
/*
@@ -69,6 +73,18 @@
/* CPC model length from the CSRSI Service. */
#define CPCMODEL_LENGTH 16
+/* Pointer to the home (current) ASCB. */
+#define PSAAOLD 0x224
+
+/* Pointer to rsm address space block extension. */
+#define ASCBRSME 0x16C
+
+/*
+ NUMBER OF FRAMES CURRENTLY IN USE BY THIS ADDRESS SPACE.
+ It does not include 2G frames.
+*/
+#define RAXFMCT 0x2C
+
/* Thread Entry constants */
#define PGTH_CURRENT 1
#define PGTH_LEN 26
@@ -76,6 +92,9 @@
#pragma linkage(BPX4GTH, OS)
#pragma linkage(BPX1GTH, OS)
+/* TOD Clock resolution in nanoseconds */
+#define TOD_RES 4.096
+
typedef unsigned data_area_ptr_assign_type;
typedef union {
@@ -100,7 +119,7 @@ void uv_loadavg(double avg[3]) {
int uv__platform_loop_init(uv_loop_t* loop) {
uv__os390_epoll* ep;
- ep = epoll_create1(UV__EPOLL_CLOEXEC);
+ ep = epoll_create1(0);
loop->ep = ep;
if (ep == NULL)
return -errno;
@@ -118,9 +137,10 @@ void uv__platform_loop_delete(uv_loop_t* loop) {
uint64_t uv__hrtime(uv_clocktype_t type) {
- struct timeval time;
- gettimeofday(&time, NULL);
- return (uint64_t) time.tv_sec * 1e9 + time.tv_usec * 1e3;
+ unsigned long long timestamp;
+ __stckf(&timestamp);
+ /* Convert to nanoseconds */
+ return timestamp / TOD_RES;
}
@@ -337,13 +357,17 @@ uint64_t uv_get_total_memory(void) {
int uv_resident_set_memory(size_t* rss) {
- W_PSPROC buf;
+ char* psa;
+ char* ascb;
+ char* rax;
+ size_t nframes;
- memset(&buf, 0, sizeof(buf));
- if (w_getpsent(0, &buf, sizeof(W_PSPROC)) == -1)
- return -EINVAL;
+ psa = PSA_PTR;
+ ascb = *(char* __ptr32 *)(psa + PSAAOLD);
+ rax = *(char* __ptr32 *)(ascb + ASCBRSME);
+ nframes = *(unsigned int*)(rax + RAXFMCT);
- *rss = buf.ps_size;
+ *rss = nframes * sysconf(_SC_PAGESIZE);
return 0;
}
@@ -364,7 +388,6 @@ int uv_uptime(double* uptime) {
int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
uv_cpu_info_t* cpu_info;
- int result;
int idx;
siv1v2 info;
data_area_ptr cvt = {0};
@@ -663,11 +686,124 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) {
return 0;
}
+
+void uv__fs_event_close(uv_fs_event_t* handle) {
+ uv_fs_event_stop(handle);
+}
+
+
+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;
+}
+
+
+int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb,
+ const char* filename, unsigned int flags) {
+ uv__os390_epoll* ep;
+ _RFIS reg_struct;
+ char* path;
+ int rc;
+
+ if (uv__is_active(handle))
+ return -EINVAL;
+
+ ep = handle->loop->ep;
+ assert(ep->msg_queue != -1);
+
+ reg_struct.__rfis_cmd = _RFIS_REG;
+ reg_struct.__rfis_qid = ep->msg_queue;
+ reg_struct.__rfis_type = 1;
+ memcpy(reg_struct.__rfis_utok, &handle, sizeof(handle));
+
+ path = uv__strdup(filename);
+ if (path == NULL)
+ return -ENOMEM;
+
+ rc = __w_pioctl(path, _IOCC_REGFILEINT, sizeof(reg_struct), &reg_struct);
+ if (rc != 0)
+ return -errno;
+
+ uv__handle_start(handle);
+ handle->path = path;
+ handle->cb = cb;
+ memcpy(handle->rfis_rftok, reg_struct.__rfis_rftok,
+ sizeof(handle->rfis_rftok));
+
+ return 0;
+}
+
+
+int uv_fs_event_stop(uv_fs_event_t* handle) {
+ uv__os390_epoll* ep;
+ _RFIS reg_struct;
+ int rc;
+
+ if (!uv__is_active(handle))
+ return 0;
+
+ ep = handle->loop->ep;
+ assert(ep->msg_queue != -1);
+
+ reg_struct.__rfis_cmd = _RFIS_UNREG;
+ reg_struct.__rfis_qid = ep->msg_queue;
+ reg_struct.__rfis_type = 1;
+ memcpy(reg_struct.__rfis_rftok, handle->rfis_rftok,
+ sizeof(handle->rfis_rftok));
+
+ /*
+ * This call will take "/" as the path argument in case we
+ * don't care to supply the correct path. The system will simply
+ * ignore it.
+ */
+ rc = __w_pioctl("/", _IOCC_REGFILEINT, sizeof(reg_struct), &reg_struct);
+ if (rc != 0 && errno != EALREADY && errno != ENOENT)
+ abort();
+
+ uv__handle_stop(handle);
+
+ return 0;
+}
+
+
+static int os390_message_queue_handler(uv__os390_epoll* ep) {
+ uv_fs_event_t* handle;
+ int msglen;
+ int events;
+ _RFIM msg;
+
+ if (ep->msg_queue == -1)
+ return 0;
+
+ msglen = msgrcv(ep->msg_queue, &msg, sizeof(msg), 0, IPC_NOWAIT);
+
+ if (msglen == -1 && errno == ENOMSG)
+ return 0;
+
+ if (msglen == -1)
+ abort();
+
+ events = 0;
+ if (msg.__rfim_event == _RFIM_ATTR || msg.__rfim_event == _RFIM_WRITE)
+ events = UV_CHANGE;
+ else if (msg.__rfim_event == _RFIM_RENAME)
+ events = UV_RENAME;
+ else
+ /* Some event that we are not interested in. */
+ return 0;
+
+ handle = *(uv_fs_event_t**)(msg.__rfim_utok);
+ handle->cb(handle, uv__basename_r(handle->path), events, 0);
+ return 1;
+}
+
+
void uv__io_poll(uv_loop_t* loop, int timeout) {
static const int max_safe_timeout = 1789569;
struct epoll_event events[1024];
struct epoll_event* pe;
struct epoll_event e;
+ uv__os390_epoll* ep;
int real_timeout;
QUEUE* q;
uv__io_t* w;
@@ -745,9 +881,11 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
SAVE_ERRNO(uv__update_time(loop));
if (nfds == 0) {
assert(timeout != -1);
- timeout = real_timeout - timeout;
- if (timeout > 0)
+
+ if (timeout > 0) {
+ timeout = real_timeout - timeout;
continue;
+ }
return;
}
@@ -779,6 +917,12 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
if (fd == -1)
continue;
+ ep = loop->ep;
+ if (fd == ep->msg_queue) {
+ os390_message_queue_handler(ep);
+ continue;
+ }
+
assert(fd >= 0);
assert((unsigned) fd < loop->nwatchers);
@@ -843,7 +987,12 @@ void uv__set_process_title(const char* title) {
}
int uv__io_fork(uv_loop_t* loop) {
- uv__platform_loop_delete(loop);
+ /*
+ Nullify the msg queue but don't close it because
+ it is still being used by the parent.
+ */
+ loop->ep = NULL;
+ uv__platform_loop_delete(loop);
return uv__platform_loop_init(loop);
}
diff --git a/Utilities/cmlibuv/src/unix/pipe.c b/Utilities/cmlibuv/src/unix/pipe.c
index e3d436d7c4..df3aad0366 100644
--- a/Utilities/cmlibuv/src/unix/pipe.c
+++ b/Utilities/cmlibuv/src/unix/pipe.c
@@ -300,3 +300,56 @@ uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) {
else
return uv__handle_type(handle->accepted_fd);
}
+
+
+int uv_pipe_chmod(uv_pipe_t* handle, int mode) {
+ unsigned desired_mode;
+ struct stat pipe_stat;
+ char* name_buffer;
+ size_t name_len;
+ int r;
+
+ if (handle == NULL || uv__stream_fd(handle) == -1)
+ return -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;
+
+ /* Unfortunately fchmod does not work on all platforms, we will use chmod. */
+ name_len = 0;
+ r = uv_pipe_getsockname(handle, NULL, &name_len);
+ if (r != UV_ENOBUFS)
+ return r;
+
+ name_buffer = uv__malloc(name_len);
+ if (name_buffer == NULL)
+ return UV_ENOMEM;
+
+ r = uv_pipe_getsockname(handle, name_buffer, &name_len);
+ if (r != 0) {
+ uv__free(name_buffer);
+ return r;
+ }
+
+ r = chmod(name_buffer, pipe_stat.st_mode);
+ uv__free(name_buffer);
+
+ return r != -1 ? 0 : -errno;
+}
diff --git a/Utilities/cmlibuv/src/unix/poll.c b/Utilities/cmlibuv/src/unix/poll.c
index 370994bd57..816c7dc2eb 100644
--- a/Utilities/cmlibuv/src/unix/poll.c
+++ b/Utilities/cmlibuv/src/unix/poll.c
@@ -33,8 +33,19 @@ static void uv__poll_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
handle = container_of(w, uv_poll_t, io_watcher);
- if (events & POLLERR) {
- uv__io_stop(loop, w, POLLIN | POLLOUT | UV__POLLRDHUP);
+ /*
+ * As documented in the kernel source fs/kernfs/file.c #780
+ * poll will return POLLERR|POLLPRI in case of sysfs
+ * polling. This does not happen in case of out-of-band
+ * TCP messages.
+ *
+ * The above is the case on (at least) FreeBSD and Linux.
+ *
+ * So to properly determine a POLLPRI or a POLLERR we need
+ * to check for both.
+ */
+ 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);
return;
@@ -43,6 +54,8 @@ static void uv__poll_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
pevents = 0;
if (events & POLLIN)
pevents |= UV_READABLE;
+ if (events & UV__POLLPRI)
+ pevents |= UV_PRIORITIZED;
if (events & POLLOUT)
pevents |= UV_WRITABLE;
if (events & UV__POLLRDHUP)
@@ -86,8 +99,9 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
static void uv__poll_stop(uv_poll_t* handle) {
uv__io_stop(handle->loop,
&handle->io_watcher,
- POLLIN | POLLOUT | UV__POLLRDHUP);
+ POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI);
uv__handle_stop(handle);
+ uv__platform_invalidate_fd(handle->loop, handle->io_watcher.fd);
}
@@ -101,7 +115,8 @@ int uv_poll_stop(uv_poll_t* handle) {
int uv_poll_start(uv_poll_t* handle, int pevents, uv_poll_cb poll_cb) {
int events;
- assert((pevents & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0);
+ assert((pevents & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT |
+ UV_PRIORITIZED)) == 0);
assert(!uv__is_closing(handle));
uv__poll_stop(handle);
@@ -112,6 +127,8 @@ int uv_poll_start(uv_poll_t* handle, int pevents, uv_poll_cb poll_cb) {
events = 0;
if (pevents & UV_READABLE)
events |= POLLIN;
+ if (pevents & UV_PRIORITIZED)
+ events |= UV__POLLPRI;
if (pevents & UV_WRITABLE)
events |= POLLOUT;
if (pevents & UV_DISCONNECT)
diff --git a/Utilities/cmlibuv/src/unix/process.c b/Utilities/cmlibuv/src/unix/process.c
index f2fe30521c..9842710d0e 100644
--- a/Utilities/cmlibuv/src/unix/process.c
+++ b/Utilities/cmlibuv/src/unix/process.c
@@ -279,9 +279,12 @@ static void uv__process_child_init(const uv_process_options_t* options,
int stdio_count,
int (*pipes)[2],
int error_fd) {
+ sigset_t set;
int close_fd;
int use_fd;
+ int err;
int fd;
+ int n;
if (options->flags & UV_PROCESS_DETACHED)
setsid();
@@ -376,6 +379,31 @@ static void uv__process_child_init(const uv_process_options_t* options,
environ = options->env;
}
+ /* Reset signal disposition. Use a hard-coded limit because NSIG
+ * is not fixed on Linux: it's either 32, 34 or 64, depending on
+ * whether RT signals are enabled. We are not allowed to touch
+ * RT signal handlers, glibc uses them internally.
+ */
+ for (n = 1; n < 32; n += 1) {
+ if (n == SIGKILL || n == SIGSTOP)
+ continue; /* Can't be changed. */
+
+ if (SIG_ERR != signal(n, SIG_DFL))
+ continue;
+
+ uv__write_int(error_fd, -errno);
+ _exit(127);
+ }
+
+ /* Reset signal mask. */
+ sigemptyset(&set);
+ err = pthread_sigmask(SIG_SETMASK, &set, NULL);
+
+ if (err != 0) {
+ uv__write_int(error_fd, -err);
+ _exit(127);
+ }
+
execvp(options->file, options->args);
uv__write_int(error_fd, -errno);
_exit(127);
@@ -391,6 +419,7 @@ int uv_spawn(uv_loop_t* loop,
return -ENOSYS;
#else
int signal_pipe[2] = { -1, -1 };
+ int pipes_storage[8][2];
int (*pipes)[2];
int stdio_count;
ssize_t r;
@@ -415,7 +444,10 @@ int uv_spawn(uv_loop_t* loop,
stdio_count = 3;
err = -ENOMEM;
- pipes = uv__malloc(stdio_count * sizeof(*pipes));
+ pipes = pipes_storage;
+ if (stdio_count > (int) ARRAY_SIZE(pipes_storage))
+ pipes = uv__malloc(stdio_count * sizeof(*pipes));
+
if (pipes == NULL)
goto error;
@@ -520,7 +552,9 @@ int uv_spawn(uv_loop_t* loop,
process->pid = pid;
process->exit_cb = options->exit_cb;
- uv__free(pipes);
+ if (pipes != pipes_storage)
+ uv__free(pipes);
+
return exec_errorno;
error:
@@ -534,7 +568,9 @@ error:
if (pipes[i][1] != -1)
uv__close_nocheckstdio(pipes[i][1]);
}
- uv__free(pipes);
+
+ if (pipes != pipes_storage)
+ uv__free(pipes);
}
return err;
diff --git a/Utilities/cmlibuv/src/unix/proctitle.c b/Utilities/cmlibuv/src/unix/proctitle.c
index 9160f7eafb..1b3a798820 100644
--- a/Utilities/cmlibuv/src/unix/proctitle.c
+++ b/Utilities/cmlibuv/src/unix/proctitle.c
@@ -26,6 +26,8 @@
extern void uv__set_process_title(const char* title);
+static uv_mutex_t process_title_mutex;
+static uv_once_t process_title_mutex_once = UV_ONCE_INIT;
static void* args_mem;
static struct {
@@ -34,6 +36,11 @@ static struct {
} process_title;
+static void init_process_title_mutex_once(void) {
+ uv_mutex_init(&process_title_mutex);
+}
+
+
char** uv_setup_args(int argc, char** argv) {
char** new_argv;
size_t size;
@@ -81,12 +88,16 @@ char** uv_setup_args(int argc, char** argv) {
int uv_set_process_title(const char* title) {
- if (process_title.len == 0)
- return 0;
+ uv_once(&process_title_mutex_once, init_process_title_mutex_once);
+ uv_mutex_lock(&process_title_mutex);
+
+ if (process_title.len != 0) {
+ /* No need to terminate, byte after is always '\0'. */
+ strncpy(process_title.str, title, process_title.len);
+ uv__set_process_title(title);
+ }
- /* No need to terminate, byte after is always '\0'. */
- strncpy(process_title.str, title, process_title.len);
- uv__set_process_title(title);
+ uv_mutex_unlock(&process_title_mutex);
return 0;
}
@@ -95,12 +106,22 @@ 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;
- else if (size <= process_title.len)
+
+ 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;
+ }
+
+ if (process_title.len != 0)
+ memcpy(buffer, process_title.str, process_title.len + 1);
- memcpy(buffer, process_title.str, process_title.len + 1);
buffer[process_title.len] = '\0';
+ uv_mutex_unlock(&process_title_mutex);
+
return 0;
}
diff --git a/Utilities/cmlibuv/src/unix/pthread-barrier.c b/Utilities/cmlibuv/src/unix/pthread-barrier.c
deleted file mode 100644
index b6e604d46d..0000000000
--- a/Utilities/cmlibuv/src/unix/pthread-barrier.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
-Copyright (c) 2016, Kari Tristan Helgason <kthelgason@gmail.com>
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-#include "uv-common.h"
-#include "pthread-barrier.h"
-
-#include <stdlib.h>
-#include <assert.h>
-
-/* TODO: support barrier_attr */
-int pthread_barrier_init(pthread_barrier_t* barrier,
- const void* barrier_attr,
- unsigned count) {
- int rc;
- _uv_barrier* b;
-
- if (barrier == NULL || count == 0)
- return EINVAL;
-
- if (barrier_attr != NULL)
- return ENOTSUP;
-
- b = uv__malloc(sizeof(*b));
- if (b == NULL)
- return ENOMEM;
-
- b->in = 0;
- b->out = 0;
- b->threshold = count;
-
- if ((rc = pthread_mutex_init(&b->mutex, NULL)) != 0)
- goto error2;
- if ((rc = pthread_cond_init(&b->cond, NULL)) != 0)
- goto error;
-
- barrier->b = b;
- return 0;
-
-error:
- pthread_mutex_destroy(&b->mutex);
-error2:
- uv__free(b);
- return rc;
-}
-
-int pthread_barrier_wait(pthread_barrier_t* barrier) {
- int rc;
- _uv_barrier* b;
-
- if (barrier == NULL || barrier->b == NULL)
- return EINVAL;
-
- b = barrier->b;
- /* Lock the mutex*/
- if ((rc = pthread_mutex_lock(&b->mutex)) != 0)
- return rc;
-
- /* Increment the count. If this is the first thread to reach the threshold,
- wake up waiters, unlock the mutex, then return
- PTHREAD_BARRIER_SERIAL_THREAD. */
- if (++b->in == b->threshold) {
- b->in = 0;
- b->out = b->threshold - 1;
- rc = pthread_cond_signal(&b->cond);
- assert(rc == 0);
-
- pthread_mutex_unlock(&b->mutex);
- return PTHREAD_BARRIER_SERIAL_THREAD;
- }
- /* Otherwise, wait for other threads until in is set to 0,
- then return 0 to indicate this is not the first thread. */
- do {
- if ((rc = pthread_cond_wait(&b->cond, &b->mutex)) != 0)
- break;
- } while (b->in != 0);
-
- /* mark thread exit */
- b->out--;
- pthread_cond_signal(&b->cond);
- pthread_mutex_unlock(&b->mutex);
- return rc;
-}
-
-int pthread_barrier_destroy(pthread_barrier_t* barrier) {
- int rc;
- _uv_barrier* b;
-
- if (barrier == NULL || barrier->b == NULL)
- return EINVAL;
-
- b = barrier->b;
-
- if ((rc = pthread_mutex_lock(&b->mutex)) != 0)
- return rc;
-
- if (b->in > 0 || b->out > 0)
- rc = EBUSY;
-
- pthread_mutex_unlock(&b->mutex);
-
- if (rc)
- return rc;
-
- pthread_cond_destroy(&b->cond);
- pthread_mutex_destroy(&b->mutex);
- uv__free(barrier->b);
- barrier->b = NULL;
- return 0;
-}
diff --git a/Utilities/cmlibuv/src/unix/stream.c b/Utilities/cmlibuv/src/unix/stream.c
index 3857bc875e..931e5f1ce1 100644
--- a/Utilities/cmlibuv/src/unix/stream.c
+++ b/Utilities/cmlibuv/src/unix/stream.c
@@ -514,7 +514,7 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
int err;
stream = container_of(w, uv_stream_t, io_watcher);
- assert(events == POLLIN);
+ assert(events & POLLIN);
assert(stream->accepted_fd == -1);
assert(!(stream->flags & UV_CLOSING));
@@ -750,6 +750,7 @@ static void uv__write(uv_stream_t* stream) {
int iovmax;
int iovcnt;
ssize_t n;
+ int err;
start:
@@ -782,14 +783,21 @@ start:
*/
if (req->send_handle) {
+ int fd_to_send;
struct msghdr msg;
struct cmsghdr *cmsg;
- int fd_to_send = uv__handle_fd((uv_handle_t*) req->send_handle);
union {
char data[64];
struct cmsghdr alias;
} scratch;
+ if (uv__is_closing(req->send_handle)) {
+ err = -EBADF;
+ goto error;
+ }
+
+ fd_to_send = uv__handle_fd((uv_handle_t*) req->send_handle);
+
memset(&scratch, 0, sizeof(scratch));
assert(fd_to_send >= 0);
@@ -851,15 +859,9 @@ start:
}
if (n < 0) {
- if (errno != EAGAIN && errno != EWOULDBLOCK) {
- /* Error */
- req->error = -errno;
- uv__write_req_finish(req);
- uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT);
- if (!uv__io_active(&stream->io_watcher, POLLIN))
- uv__handle_stop(stream);
- uv__stream_osx_interrupt_select(stream);
- return;
+ if (errno != EAGAIN && errno != EWOULDBLOCK && errno != ENOBUFS) {
+ err = -errno;
+ goto error;
} else if (stream->flags & UV_STREAM_BLOCKING) {
/* If this is a blocking stream, try again. */
goto start;
@@ -923,6 +925,16 @@ start:
/* Notify select() thread about state change */
uv__stream_osx_interrupt_select(stream);
+
+ return;
+
+error:
+ req->error = err;
+ uv__write_req_finish(req);
+ uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT);
+ if (!uv__io_active(&stream->io_watcher, POLLIN))
+ uv__handle_stop(stream);
+ uv__stream_osx_interrupt_select(stream);
}
@@ -1249,8 +1261,9 @@ static void uv__read(uv_stream_t* stream) {
int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) {
- assert((stream->type == UV_TCP || stream->type == UV_NAMED_PIPE) &&
- "uv_shutdown (unix) only supports uv_handle_t right now");
+ assert(stream->type == UV_TCP ||
+ stream->type == UV_TTY ||
+ stream->type == UV_NAMED_PIPE);
if (!(stream->flags & UV_STREAM_WRITABLE) ||
stream->flags & UV_STREAM_SHUT ||
diff --git a/Utilities/cmlibuv/src/unix/sunos.c b/Utilities/cmlibuv/src/unix/sunos.c
index 041f3f336d..d6f9527322 100644
--- a/Utilities/cmlibuv/src/unix/sunos.c
+++ b/Utilities/cmlibuv/src/unix/sunos.c
@@ -751,7 +751,8 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent) {
return 1;
if (ent->ifa_addr == NULL)
return 1;
- if (ent->ifa_addr->sa_family == PF_PACKET)
+ if (ent->ifa_addr->sa_family != AF_INET &&
+ ent->ifa_addr->sa_family != AF_INET6)
return 1;
return 0;
}
@@ -760,7 +761,6 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
uv_interface_address_t* address;
struct ifaddrs* addrs;
struct ifaddrs* ent;
- int i;
if (getifaddrs(&addrs))
return -errno;
diff --git a/Utilities/cmlibuv/src/unix/tcp.c b/Utilities/cmlibuv/src/unix/tcp.c
index c423dcb15f..c7c8d21c66 100644
--- a/Utilities/cmlibuv/src/unix/tcp.c
+++ b/Utilities/cmlibuv/src/unix/tcp.c
@@ -28,15 +28,12 @@
#include <errno.h>
-static int maybe_new_socket(uv_tcp_t* handle, int domain, int flags) {
+static int new_socket(uv_tcp_t* handle, int domain, unsigned long flags) {
+ struct sockaddr_storage saddr;
+ socklen_t slen;
int sockfd;
int err;
- if (domain == AF_UNSPEC || uv__stream_fd(handle) != -1) {
- handle->flags |= flags;
- return 0;
- }
-
err = uv__socket(domain, SOCK_STREAM, 0);
if (err < 0)
return err;
@@ -48,10 +45,74 @@ static int maybe_new_socket(uv_tcp_t* handle, int domain, int flags) {
return err;
}
+ if (flags & UV_HANDLE_BOUND) {
+ /* 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) {
+ uv__close(sockfd);
+ return err;
+ }
+
+ err = bind(uv__stream_fd(handle), (struct sockaddr*) &saddr, slen);
+ if (err) {
+ uv__close(sockfd);
+ return err;
+ }
+ }
+
return 0;
}
+static int maybe_new_socket(uv_tcp_t* handle, int domain, unsigned long flags) {
+ struct sockaddr_storage saddr;
+ socklen_t slen;
+
+ if (domain == AF_UNSPEC) {
+ handle->flags |= flags;
+ return 0;
+ }
+
+ if (uv__stream_fd(handle) != -1) {
+
+ if (flags & UV_HANDLE_BOUND) {
+
+ if (handle->flags & UV_HANDLE_BOUND) {
+ /* It is already bound to a port. */
+ handle->flags |= flags;
+ return 0;
+ }
+
+ /* Query to see if tcp socket is bound. */
+ slen = sizeof(saddr);
+ memset(&saddr, 0, sizeof(saddr));
+ if (getsockname(uv__stream_fd(handle), (struct sockaddr*) &saddr, &slen))
+ return -errno;
+
+ if ((saddr.ss_family == AF_INET6 &&
+ ((struct sockaddr_in6*) &saddr)->sin6_port != 0) ||
+ (saddr.ss_family == AF_INET &&
+ ((struct sockaddr_in*) &saddr)->sin_port != 0)) {
+ /* Handle is already bound to a port. */
+ handle->flags |= flags;
+ return 0;
+ }
+
+ /* Bind to arbitrary port */
+ if (bind(uv__stream_fd(handle), (struct sockaddr*) &saddr, slen))
+ return -errno;
+ }
+
+ handle->flags |= flags;
+ return 0;
+ }
+
+ return new_socket(handle, domain, flags);
+}
+
+
int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* tcp, unsigned int flags) {
int domain;
@@ -260,6 +321,7 @@ int uv_tcp_getpeername(const uv_tcp_t* handle,
int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
static int single_accept = -1;
+ unsigned long flags;
int err;
if (tcp->delayed_error)
@@ -273,30 +335,17 @@ int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
if (single_accept)
tcp->flags |= UV_TCP_SINGLE_ACCEPT;
- err = maybe_new_socket(tcp, AF_INET, UV_STREAM_READABLE);
- if (err)
- return err;
-
-#ifdef __MVS__
+ flags = UV_STREAM_READABLE;
+#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
*/
-
- if (!(tcp->flags & UV_HANDLE_BOUND)) {
- struct sockaddr_storage saddr;
- socklen_t slen = sizeof(saddr);
- memset(&saddr, 0, sizeof(saddr));
-
- if (getsockname(tcp->io_watcher.fd, (struct sockaddr*) &saddr, &slen))
- return -errno;
-
- if (bind(tcp->io_watcher.fd, (struct sockaddr*) &saddr, slen))
- return -errno;
-
- tcp->flags |= UV_HANDLE_BOUND;
- }
-#endif
+ flags |= UV_HANDLE_BOUND;
+#endif
+ err = maybe_new_socket(tcp, AF_INET, flags);
+ if (err)
+ return err;
if (listen(tcp->io_watcher.fd, backlog))
return -errno;
diff --git a/Utilities/cmlibuv/src/unix/thread.c b/Utilities/cmlibuv/src/unix/thread.c
index a9b5e4c02a..abaca295d2 100644
--- a/Utilities/cmlibuv/src/unix/thread.c
+++ b/Utilities/cmlibuv/src/unix/thread.c
@@ -41,36 +41,159 @@
#define NANOSEC ((uint64_t) 1e9)
-int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
- int err;
- pthread_attr_t* attr;
-#if defined(__APPLE__)
- pthread_attr_t attr_storage;
- struct rlimit lim;
+#if defined(UV__PTHREAD_BARRIER_FALLBACK)
+/* TODO: support barrier_attr */
+int pthread_barrier_init(pthread_barrier_t* barrier,
+ const void* barrier_attr,
+ unsigned count) {
+ int rc;
+ _uv_barrier* b;
+
+ if (barrier == NULL || count == 0)
+ return EINVAL;
+
+ if (barrier_attr != NULL)
+ return ENOTSUP;
+
+ b = uv__malloc(sizeof(*b));
+ if (b == NULL)
+ return ENOMEM;
+
+ b->in = 0;
+ b->out = 0;
+ b->threshold = count;
+
+ if ((rc = pthread_mutex_init(&b->mutex, NULL)) != 0)
+ goto error2;
+ if ((rc = pthread_cond_init(&b->cond, NULL)) != 0)
+ goto error;
+
+ barrier->b = b;
+ return 0;
+
+error:
+ pthread_mutex_destroy(&b->mutex);
+error2:
+ uv__free(b);
+ return rc;
+}
+
+int pthread_barrier_wait(pthread_barrier_t* barrier) {
+ int rc;
+ _uv_barrier* b;
+
+ if (barrier == NULL || barrier->b == NULL)
+ return EINVAL;
+
+ b = barrier->b;
+ /* Lock the mutex*/
+ if ((rc = pthread_mutex_lock(&b->mutex)) != 0)
+ return rc;
+
+ /* Increment the count. If this is the first thread to reach the threshold,
+ wake up waiters, unlock the mutex, then return
+ PTHREAD_BARRIER_SERIAL_THREAD. */
+ if (++b->in == b->threshold) {
+ b->in = 0;
+ b->out = b->threshold - 1;
+ rc = pthread_cond_signal(&b->cond);
+ assert(rc == 0);
+
+ pthread_mutex_unlock(&b->mutex);
+ return PTHREAD_BARRIER_SERIAL_THREAD;
+ }
+ /* Otherwise, wait for other threads until in is set to 0,
+ then return 0 to indicate this is not the first thread. */
+ do {
+ if ((rc = pthread_cond_wait(&b->cond, &b->mutex)) != 0)
+ break;
+ } while (b->in != 0);
+
+ /* mark thread exit */
+ b->out--;
+ pthread_cond_signal(&b->cond);
+ pthread_mutex_unlock(&b->mutex);
+ return rc;
+}
+
+int pthread_barrier_destroy(pthread_barrier_t* barrier) {
+ int rc;
+ _uv_barrier* b;
+
+ if (barrier == NULL || barrier->b == NULL)
+ return EINVAL;
+
+ b = barrier->b;
+
+ if ((rc = pthread_mutex_lock(&b->mutex)) != 0)
+ return rc;
+
+ if (b->in > 0 || b->out > 0)
+ rc = EBUSY;
+
+ pthread_mutex_unlock(&b->mutex);
+
+ if (rc)
+ return rc;
+
+ pthread_cond_destroy(&b->cond);
+ pthread_mutex_destroy(&b->mutex);
+ uv__free(barrier->b);
+ barrier->b = NULL;
+ return 0;
+}
#endif
- /* On OSX threads other than the main thread are created with a reduced stack
- * size by default, adjust it to RLIMIT_STACK.
- */
-#if defined(__APPLE__)
- if (getrlimit(RLIMIT_STACK, &lim))
- abort();
- attr = &attr_storage;
- if (pthread_attr_init(attr))
+/* On MacOS, threads other than the main thread are created with a reduced
+ * stack size by default. Adjust to RLIMIT_STACK aligned to the page size.
+ *
+ * On Linux, threads created by musl have a much smaller stack than threads
+ * created by glibc (80 vs. 2048 or 4096 kB.) Follow glibc for consistency.
+ */
+static size_t thread_stack_size(void) {
+#if defined(__APPLE__) || defined(__linux__)
+ struct rlimit lim;
+
+ if (getrlimit(RLIMIT_STACK, &lim))
abort();
if (lim.rlim_cur != RLIM_INFINITY) {
/* pthread_attr_setstacksize() expects page-aligned values. */
lim.rlim_cur -= lim.rlim_cur % (rlim_t) getpagesize();
-
if (lim.rlim_cur >= PTHREAD_STACK_MIN)
- if (pthread_attr_setstacksize(attr, lim.rlim_cur))
- abort();
+ return lim.rlim_cur;
}
+#endif
+
+#if !defined(__linux__)
+ return 0;
+#elif defined(__PPC__) || defined(__ppc__) || defined(__powerpc__)
+ return 4 << 20; /* glibc default. */
#else
- attr = NULL;
+ return 2 << 20; /* glibc default. */
#endif
+}
+
+
+int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
+ int err;
+ size_t stack_size;
+ pthread_attr_t* attr;
+ pthread_attr_t attr_storage;
+
+ attr = NULL;
+ stack_size = thread_stack_size();
+
+ if (stack_size > 0) {
+ attr = &attr_storage;
+
+ if (pthread_attr_init(attr))
+ abort();
+
+ if (pthread_attr_setstacksize(attr, stack_size))
+ abort();
+ }
err = pthread_create(tid, attr, (void*(*)(void*)) entry, arg);
@@ -118,6 +241,25 @@ int uv_mutex_init(uv_mutex_t* mutex) {
}
+int uv_mutex_init_recursive(uv_mutex_t* mutex) {
+ pthread_mutexattr_t attr;
+ int err;
+
+ if (pthread_mutexattr_init(&attr))
+ abort();
+
+ if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE))
+ abort();
+
+ err = pthread_mutex_init(mutex, &attr);
+
+ if (pthread_mutexattr_destroy(&attr))
+ abort();
+
+ return -err;
+}
+
+
void uv_mutex_destroy(uv_mutex_t* mutex) {
if (pthread_mutex_destroy(mutex))
abort();
@@ -281,18 +423,20 @@ int uv_sem_trywait(uv_sem_t* sem) {
int uv_sem_init(uv_sem_t* sem, unsigned int value) {
uv_sem_t semid;
- struct sembuf buf;
int err;
+ union {
+ int val;
+ struct semid_ds* buf;
+ unsigned short* array;
+ } arg;
- buf.sem_num = 0;
- buf.sem_op = value;
- buf.sem_flg = 0;
semid = semget(IPC_PRIVATE, 1, S_IRUSR | S_IWUSR);
if (semid == -1)
return -errno;
- if (-1 == semop(semid, &buf, 1)) {
+ arg.val = value;
+ if (-1 == semctl(semid, 0, SETVAL, arg)) {
err = errno;
if (-1 == semctl(*sem, 0, IPC_RMID))
abort();
@@ -424,7 +568,7 @@ int uv_cond_init(uv_cond_t* cond) {
if (err)
return -err;
-#if !(defined(__ANDROID__) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC))
+#if !(defined(__ANDROID_API__) && __ANDROID_API__ < 21)
err = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
if (err)
goto error2;
@@ -511,7 +655,8 @@ int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) {
timeout += uv__hrtime(UV_CLOCK_PRECISE);
ts.tv_sec = timeout / NANOSEC;
ts.tv_nsec = timeout % NANOSEC;
-#if defined(__ANDROID__) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC)
+#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
+
/*
* The bionic pthread implementation doesn't support CLOCK_MONOTONIC,
* but has this alternative function instead.
@@ -519,7 +664,7 @@ int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) {
r = pthread_cond_timedwait_monotonic_np(cond, mutex, &ts);
#else
r = pthread_cond_timedwait(cond, mutex, &ts);
-#endif /* __ANDROID__ */
+#endif /* __ANDROID_API__ */
#endif
diff --git a/Utilities/cmlibuv/src/unix/tty.c b/Utilities/cmlibuv/src/unix/tty.c
index ae1018fc42..fc8c3abf9d 100644
--- a/Utilities/cmlibuv/src/unix/tty.c
+++ b/Utilities/cmlibuv/src/unix/tty.c
@@ -48,6 +48,42 @@ static int uv__tty_is_slave(const int fd) {
char dummy[256];
result = ioctl(fd, TIOCPTYGNAME, &dummy) != 0;
+#elif defined(__NetBSD__)
+ /*
+ * NetBSD as an extension returns with ptsname(3) and ptsname_r(3) the slave
+ * device name for both descriptors, the master one and slave one.
+ *
+ * Implement function to compare major device number with pts devices.
+ *
+ * The major numbers are machine-dependent, on NetBSD/amd64 they are
+ * respectively:
+ * - master tty: ptc - major 6
+ * - slave tty: pts - major 5
+ */
+
+ struct stat sb;
+ /* Lookup device's major for the pts driver and cache it. */
+ static devmajor_t pts = NODEVMAJOR;
+
+ if (pts == NODEVMAJOR) {
+ pts = getdevmajor("pts", S_IFCHR);
+ if (pts == NODEVMAJOR)
+ abort();
+ }
+
+ /* Lookup stat structure behind the file descriptor. */
+ if (fstat(fd, &sb) != 0)
+ abort();
+
+ /* Assert character device. */
+ if (!S_ISCHR(sb.st_mode))
+ abort();
+
+ /* Assert valid major. */
+ if (major(sb.st_rdev) == NODEVMAJOR)
+ abort();
+
+ result = (pts == major(sb.st_rdev));
#else
/* Fallback to ptsname
*/
diff --git a/Utilities/cmlibuv/src/unix/udp.c b/Utilities/cmlibuv/src/unix/udp.c
index c556325de0..a475bf5741 100644
--- a/Utilities/cmlibuv/src/unix/udp.c
+++ b/Utilities/cmlibuv/src/unix/udp.c
@@ -237,8 +237,10 @@ static void uv__udp_sendmsg(uv_udp_t* handle) {
size = sendmsg(handle->io_watcher.fd, &h, 0);
} while (size == -1 && errno == EINTR);
- if (size == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
- break;
+ if (size == -1) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
+ break;
+ }
req->status = (size == -1 ? -errno : size);
@@ -472,7 +474,7 @@ int uv__udp_try_send(uv_udp_t* handle,
} while (size == -1 && errno == EINTR);
if (size == -1) {
- if (errno == EAGAIN || errno == EWOULDBLOCK)
+ if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
return -EAGAIN;
else
return -errno;
diff --git a/Utilities/cmlibuv/src/uv-data-getter-setters.c b/Utilities/cmlibuv/src/uv-data-getter-setters.c
new file mode 100644
index 0000000000..533e4a2fe1
--- /dev/null
+++ b/Utilities/cmlibuv/src/uv-data-getter-setters.c
@@ -0,0 +1,96 @@
+#include "uv.h"
+
+const char* uv_handle_type_name(uv_handle_type type) {
+ switch (type) {
+#define XX(uc,lc) case UV_##uc: return #lc;
+ UV_HANDLE_TYPE_MAP(XX)
+#undef XX
+ case UV_FILE: return "file";
+ case UV_HANDLE_TYPE_MAX:
+ case UV_UNKNOWN_HANDLE: return NULL;
+ }
+ return NULL;
+}
+
+uv_handle_type uv_handle_get_type(const uv_handle_t* handle) {
+ return handle->type;
+}
+
+void* uv_handle_get_data(const uv_handle_t* handle) {
+ return handle->data;
+}
+
+uv_loop_t* uv_handle_get_loop(const uv_handle_t* handle) {
+ return handle->loop;
+}
+
+void uv_handle_set_data(uv_handle_t* handle, void* data) {
+ handle->data = data;
+}
+
+const char* uv_req_type_name(uv_req_type type) {
+ switch (type) {
+#define XX(uc,lc) case UV_##uc: return #lc;
+ UV_REQ_TYPE_MAP(XX)
+#undef XX
+ case UV_REQ_TYPE_MAX:
+ case UV_UNKNOWN_REQ: return NULL;
+ }
+ return NULL;
+}
+
+uv_req_type uv_req_get_type(const uv_req_t* req) {
+ return req->type;
+}
+
+void* uv_req_get_data(const uv_req_t* req) {
+ return req->data;
+}
+
+void uv_req_set_data(uv_req_t* req, void* data) {
+ req->data = data;
+}
+
+size_t uv_stream_get_write_queue_size(const uv_stream_t* stream) {
+ return stream->write_queue_size;
+}
+
+size_t uv_udp_get_send_queue_size(const uv_udp_t* handle) {
+ return handle->send_queue_size;
+}
+
+size_t uv_udp_get_send_queue_count(const uv_udp_t* handle) {
+ return handle->send_queue_count;
+}
+
+uv_pid_t uv_process_get_pid(const uv_process_t* proc) {
+ return proc->pid;
+}
+
+uv_fs_type uv_fs_get_type(const uv_fs_t* req) {
+ return req->fs_type;
+}
+
+ssize_t uv_fs_get_result(const uv_fs_t* req) {
+ return req->result;
+}
+
+void* uv_fs_get_ptr(const uv_fs_t* req) {
+ return req->ptr;
+}
+
+const char* uv_fs_get_path(const uv_fs_t* req) {
+ return req->path;
+}
+
+uv_stat_t* uv_fs_get_statbuf(uv_fs_t* req) {
+ return &req->statbuf;
+}
+
+void* uv_loop_get_data(const uv_loop_t* loop) {
+ return loop->data;
+}
+
+void uv_loop_set_data(uv_loop_t* loop, void* data) {
+ loop->data = data;
+}
diff --git a/Utilities/cmlibuv/src/win/dl.c b/Utilities/cmlibuv/src/win/dl.c
index 39e400ab2d..97ac1c1ad1 100644
--- a/Utilities/cmlibuv/src/win/dl.c
+++ b/Utilities/cmlibuv/src/win/dl.c
@@ -22,7 +22,7 @@
#include "uv.h"
#include "internal.h"
-static int uv__dlerror(uv_lib_t* lib, int errorno);
+static int uv__dlerror(uv_lib_t* lib, const char* filename, DWORD errorno);
int uv_dlopen(const char* filename, uv_lib_t* lib) {
@@ -37,12 +37,12 @@ int uv_dlopen(const char* filename, uv_lib_t* lib) {
-1,
filename_w,
ARRAY_SIZE(filename_w))) {
- return uv__dlerror(lib, GetLastError());
+ return uv__dlerror(lib, filename, GetLastError());
}
lib->handle = LoadLibraryExW(filename_w, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
if (lib->handle == NULL) {
- return uv__dlerror(lib, GetLastError());
+ return uv__dlerror(lib, filename, GetLastError());
}
return 0;
@@ -65,7 +65,7 @@ void uv_dlclose(uv_lib_t* lib) {
int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr) {
*ptr = (void*) GetProcAddress(lib->handle, name);
- return uv__dlerror(lib, *ptr ? 0 : GetLastError());
+ return uv__dlerror(lib, "", *ptr ? 0 : GetLastError());
}
@@ -88,31 +88,46 @@ static void uv__format_fallback_error(uv_lib_t* lib, int errorno){
-static int uv__dlerror(uv_lib_t* lib, int errorno) {
+static int uv__dlerror(uv_lib_t* lib, const char* filename, DWORD errorno) {
+ DWORD_PTR arg;
DWORD res;
+ char* msg;
if (lib->errmsg) {
- LocalFree((void*)lib->errmsg);
+ LocalFree(lib->errmsg);
lib->errmsg = NULL;
}
- if (errorno) {
+ if (errorno == 0)
+ return 0;
+
+ res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
+ MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
+ (LPSTR) &lib->errmsg, 0, NULL);
+
+ if (!res && GetLastError() == ERROR_MUI_FILE_NOT_FOUND) {
res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
- MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
- (LPSTR) &lib->errmsg, 0, NULL);
- if (!res && GetLastError() == ERROR_MUI_FILE_NOT_FOUND) {
- res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorno,
- 0, (LPSTR) &lib->errmsg, 0, NULL);
- }
-
- if (!res) {
- uv__format_fallback_error(lib, errorno);
- }
+ 0, (LPSTR) &lib->errmsg, 0, NULL);
+ }
+
+ if (res && errorno == ERROR_BAD_EXE_FORMAT && strstr(lib->errmsg, "%1")) {
+ msg = lib->errmsg;
+ lib->errmsg = NULL;
+ arg = (DWORD_PTR) filename;
+ res = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_ARGUMENT_ARRAY |
+ FORMAT_MESSAGE_FROM_STRING,
+ msg,
+ 0, 0, (LPSTR) &lib->errmsg, 0, (va_list*) &arg);
+ LocalFree(msg);
}
- return errorno ? -1 : 0;
+ if (!res)
+ uv__format_fallback_error(lib, errorno);
+
+ return -1;
}
diff --git a/Utilities/cmlibuv/src/win/error.c b/Utilities/cmlibuv/src/win/error.c
index 642d1112e1..9b03bfef6b 100644
--- a/Utilities/cmlibuv/src/win/error.c
+++ b/Utilities/cmlibuv/src/win/error.c
@@ -58,7 +58,7 @@ void uv_fatal_error(const int errorno, const char* syscall) {
LocalFree(buf);
}
- *((char*)NULL) = 0xff; /* Force debug break */
+ DebugBreak();
abort();
}
diff --git a/Utilities/cmlibuv/src/win/fs.c b/Utilities/cmlibuv/src/win/fs.c
index 2d72cdc70f..097b00e08d 100644
--- a/Utilities/cmlibuv/src/win/fs.c
+++ b/Utilities/cmlibuv/src/win/fs.c
@@ -43,11 +43,26 @@
#define UV_FS_CLEANEDUP 0x0010
-#define QUEUE_FS_TP_JOB(loop, req) \
- do { \
- uv__req_register(loop, req); \
- uv__work_submit((loop), &(req)->work_req, uv__fs_work, uv__fs_done); \
- } while (0)
+#define INIT(subtype) \
+ do { \
+ if (req == NULL) \
+ return UV_EINVAL; \
+ uv_fs_req_init(loop, req, subtype, cb); \
+ } \
+ while (0)
+
+#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; \
+ } else { \
+ uv__fs_work(&req->work_req); \
+ return req->result; \
+ } \
+ } \
+ while (0)
#define SET_REQ_RESULT(req, result_value) \
do { \
@@ -113,6 +128,7 @@ const WCHAR LONG_PATH_PREFIX_LEN = 4;
const WCHAR UNC_PATH_PREFIX[] = L"\\\\?\\UNC\\";
const WCHAR UNC_PATH_PREFIX_LEN = 8;
+static int uv__file_symlink_usermode_flag = SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
void uv_fs_init(void) {
_fmode = _O_BINARY;
@@ -220,6 +236,7 @@ INLINE static int fs__capture_path(uv_fs_t* req, const char* path,
INLINE static void uv_fs_req_init(uv_loop_t* loop, uv_fs_t* req,
uv_fs_type fs_type, const uv_fs_cb cb) {
+ uv__once_init();
UV_REQ_INIT(req, UV_FS);
req->loop = loop;
req->flags = 0;
@@ -398,21 +415,21 @@ void fs__open(uv_fs_t* req) {
umask(current_umask);
/* convert flags and mode to CreateFile parameters */
- switch (flags & (_O_RDONLY | _O_WRONLY | _O_RDWR)) {
- case _O_RDONLY:
+ switch (flags & (UV_FS_O_RDONLY | UV_FS_O_WRONLY | UV_FS_O_RDWR)) {
+ case UV_FS_O_RDONLY:
access = FILE_GENERIC_READ;
break;
- case _O_WRONLY:
+ case UV_FS_O_WRONLY:
access = FILE_GENERIC_WRITE;
break;
- case _O_RDWR:
+ case UV_FS_O_RDWR:
access = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
break;
default:
goto einval;
}
- if (flags & _O_APPEND) {
+ if (flags & UV_FS_O_APPEND) {
access &= ~FILE_WRITE_DATA;
access |= FILE_APPEND_DATA;
}
@@ -422,26 +439,33 @@ void fs__open(uv_fs_t* req) {
* does. We indiscriminately use all the sharing modes, to match
* UNIX semantics. In particular, this ensures that the file can
* be deleted even whilst it's open, fixing issue #1449.
+ * We still support exclusive sharing mode, since it is necessary
+ * for opening raw block devices, otherwise Windows will prevent
+ * any attempt to write past the master boot record.
*/
- share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+ if (flags & UV_FS_O_EXLOCK) {
+ share = 0;
+ } else {
+ share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+ }
- switch (flags & (_O_CREAT | _O_EXCL | _O_TRUNC)) {
+ switch (flags & (UV_FS_O_CREAT | UV_FS_O_EXCL | UV_FS_O_TRUNC)) {
case 0:
- case _O_EXCL:
+ case UV_FS_O_EXCL:
disposition = OPEN_EXISTING;
break;
- case _O_CREAT:
+ case UV_FS_O_CREAT:
disposition = OPEN_ALWAYS;
break;
- case _O_CREAT | _O_EXCL:
- case _O_CREAT | _O_TRUNC | _O_EXCL:
+ case UV_FS_O_CREAT | UV_FS_O_EXCL:
+ case UV_FS_O_CREAT | UV_FS_O_TRUNC | UV_FS_O_EXCL:
disposition = CREATE_NEW;
break;
- case _O_TRUNC:
- case _O_TRUNC | _O_EXCL:
+ case UV_FS_O_TRUNC:
+ case UV_FS_O_TRUNC | UV_FS_O_EXCL:
disposition = TRUNCATE_EXISTING;
break;
- case _O_CREAT | _O_TRUNC:
+ case UV_FS_O_CREAT | UV_FS_O_TRUNC:
disposition = CREATE_ALWAYS;
break;
default:
@@ -449,34 +473,49 @@ void fs__open(uv_fs_t* req) {
}
attributes |= FILE_ATTRIBUTE_NORMAL;
- if (flags & _O_CREAT) {
+ if (flags & UV_FS_O_CREAT) {
if (!((req->fs.info.mode & ~current_umask) & _S_IWRITE)) {
attributes |= FILE_ATTRIBUTE_READONLY;
}
}
- if (flags & _O_TEMPORARY ) {
+ if (flags & UV_FS_O_TEMPORARY ) {
attributes |= FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_TEMPORARY;
access |= DELETE;
}
- if (flags & _O_SHORT_LIVED) {
+ if (flags & UV_FS_O_SHORT_LIVED) {
attributes |= FILE_ATTRIBUTE_TEMPORARY;
}
- switch (flags & (_O_SEQUENTIAL | _O_RANDOM)) {
+ switch (flags & (UV_FS_O_SEQUENTIAL | UV_FS_O_RANDOM)) {
case 0:
break;
- case _O_SEQUENTIAL:
+ case UV_FS_O_SEQUENTIAL:
attributes |= FILE_FLAG_SEQUENTIAL_SCAN;
break;
- case _O_RANDOM:
+ case UV_FS_O_RANDOM:
attributes |= FILE_FLAG_RANDOM_ACCESS;
break;
default:
goto einval;
}
+ if (flags & UV_FS_O_DIRECT) {
+ attributes |= FILE_FLAG_NO_BUFFERING;
+ }
+
+ switch (flags & (UV_FS_O_DSYNC | UV_FS_O_SYNC)) {
+ case 0:
+ break;
+ case UV_FS_O_DSYNC:
+ case UV_FS_O_SYNC:
+ attributes |= FILE_FLAG_WRITE_THROUGH;
+ break;
+ default:
+ goto einval;
+ }
+
/* Setting this flag makes it possible to open a directory. */
attributes |= FILE_FLAG_BACKUP_SEMANTICS;
@@ -489,9 +528,9 @@ void fs__open(uv_fs_t* req) {
NULL);
if (file == INVALID_HANDLE_VALUE) {
DWORD error = GetLastError();
- if (error == ERROR_FILE_EXISTS && (flags & _O_CREAT) &&
- !(flags & _O_EXCL)) {
- /* Special case: when ERROR_FILE_EXISTS happens and O_CREAT was */
+ if (error == ERROR_FILE_EXISTS && (flags & UV_FS_O_CREAT) &&
+ !(flags & UV_FS_O_EXCL)) {
+ /* Special case: when ERROR_FILE_EXISTS happens and UV_FS_O_CREAT was */
/* specified, it means the path referred to a directory. */
SET_REQ_UV_ERROR(req, UV_EISDIR, error);
} else {
@@ -556,9 +595,14 @@ void fs__read(uv_fs_t* req) {
DWORD error;
int result;
unsigned int index;
+ LARGE_INTEGER original_position;
+ LARGE_INTEGER zero_offset;
+ int restore_position;
VERIFY_FD(fd, req);
+ zero_offset.QuadPart = 0;
+ restore_position = 0;
handle = uv__get_osfhandle(fd);
if (handle == INVALID_HANDLE_VALUE) {
@@ -569,6 +613,10 @@ void fs__read(uv_fs_t* req) {
if (offset != -1) {
memset(&overlapped, 0, sizeof overlapped);
overlapped_ptr = &overlapped;
+ if (SetFilePointerEx(handle, zero_offset, &original_position,
+ FILE_CURRENT)) {
+ restore_position = 1;
+ }
} else {
overlapped_ptr = NULL;
}
@@ -593,6 +641,9 @@ void fs__read(uv_fs_t* req) {
++index;
} while (result && index < req->fs.info.nbufs);
+ if (restore_position)
+ SetFilePointerEx(handle, original_position, NULL, FILE_BEGIN);
+
if (result || bytes > 0) {
SET_REQ_RESULT(req, bytes);
} else {
@@ -615,9 +666,14 @@ void fs__write(uv_fs_t* req) {
DWORD bytes;
int result;
unsigned int index;
+ LARGE_INTEGER original_position;
+ LARGE_INTEGER zero_offset;
+ int restore_position;
VERIFY_FD(fd, req);
+ zero_offset.QuadPart = 0;
+ restore_position = 0;
handle = uv__get_osfhandle(fd);
if (handle == INVALID_HANDLE_VALUE) {
SET_REQ_WIN32_ERROR(req, ERROR_INVALID_HANDLE);
@@ -627,6 +683,10 @@ void fs__write(uv_fs_t* req) {
if (offset != -1) {
memset(&overlapped, 0, sizeof overlapped);
overlapped_ptr = &overlapped;
+ if (SetFilePointerEx(handle, zero_offset, &original_position,
+ FILE_CURRENT)) {
+ restore_position = 1;
+ }
} else {
overlapped_ptr = NULL;
}
@@ -651,6 +711,9 @@ void fs__write(uv_fs_t* req) {
++index;
} while (result && index < req->fs.info.nbufs);
+ if (restore_position)
+ SetFilePointerEx(handle, original_position, NULL, FILE_BEGIN);
+
if (result || bytes > 0) {
SET_REQ_RESULT(req, bytes);
} else {
@@ -1029,7 +1092,8 @@ cleanup:
}
-INLINE static int fs__stat_handle(HANDLE handle, uv_stat_t* statbuf) {
+INLINE static int fs__stat_handle(HANDLE handle, uv_stat_t* statbuf,
+ int do_lstat) {
FILE_ALL_INFORMATION file_info;
FILE_FS_VOLUME_INFORMATION volume_info;
NTSTATUS nt_status;
@@ -1084,19 +1148,25 @@ INLINE static int fs__stat_handle(HANDLE handle, uv_stat_t* statbuf) {
*/
statbuf->st_mode = 0;
- if (file_info.BasicInformation.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
+ /*
+ * On Windows, FILE_ATTRIBUTE_REPARSE_POINT is a general purpose mechanism
+ * by which filesystem drivers can intercept and alter file system requests.
+ *
+ * The only reparse points we care about are symlinks and mount points, both
+ * of which are treated as POSIX symlinks. Further, we only care when
+ * invoked via lstat, which seeks information about the link instead of its
+ * target. Otherwise, reparse points must be treated as regular files.
+ */
+ if (do_lstat &&
+ (file_info.BasicInformation.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
/*
- * It is possible for a file to have FILE_ATTRIBUTE_REPARSE_POINT but not have
- * any link data. In that case DeviceIoControl() in fs__readlink_handle() sets
- * the last error to ERROR_NOT_A_REPARSE_POINT. Then the stat result mode
- * calculated below will indicate a normal directory or file, as if
- * FILE_ATTRIBUTE_REPARSE_POINT was not present.
+ * If reading the link fails, the reparse point is not a symlink and needs
+ * to be treated as a regular file. The higher level lstat function will
+ * detect this failure and retry without do_lstat if appropriate.
*/
- if (fs__readlink_handle(handle, NULL, &statbuf->st_size) == 0) {
- statbuf->st_mode |= S_IFLNK;
- } else if (GetLastError() != ERROR_NOT_A_REPARSE_POINT) {
+ if (fs__readlink_handle(handle, NULL, &statbuf->st_size) != 0)
return -1;
- }
+ statbuf->st_mode |= S_IFLNK;
}
if (statbuf->st_mode == 0) {
@@ -1139,8 +1209,12 @@ INLINE static int fs__stat_handle(HANDLE handle, uv_stat_t* statbuf) {
*
* Therefore we'll just report a sensible value that's quite commonly okay
* on modern hardware.
+ *
+ * 4096 is the minimum required to be compatible with newer Advanced Format
+ * drives (which have 4096 bytes per physical sector), and to be backwards
+ * compatible with older drives (which have 512 bytes per physical sector).
*/
- statbuf->st_blksize = 2048;
+ statbuf->st_blksize = 4096;
/* Todo: set st_flags to something meaningful. Also provide a wrapper for
* chattr(2).
@@ -1191,9 +1265,11 @@ INLINE static void fs__stat_impl(uv_fs_t* req, int do_lstat) {
return;
}
- if (fs__stat_handle(handle, &req->statbuf) != 0) {
+ if (fs__stat_handle(handle, &req->statbuf, do_lstat) != 0) {
DWORD error = GetLastError();
- if (do_lstat && error == ERROR_SYMLINK_NOT_SUPPORTED) {
+ if (do_lstat &&
+ (error == ERROR_SYMLINK_NOT_SUPPORTED ||
+ error == ERROR_NOT_A_REPARSE_POINT)) {
/* We opened a reparse point but it was not a symlink. Try again. */
fs__stat_impl(req, 0);
@@ -1237,7 +1313,7 @@ static void fs__fstat(uv_fs_t* req) {
return;
}
- if (fs__stat_handle(handle, &req->statbuf) != 0) {
+ if (fs__stat_handle(handle, &req->statbuf, 0) != 0) {
SET_REQ_WIN32_ERROR(req, GetLastError());
return;
}
@@ -1309,6 +1385,22 @@ static void fs__ftruncate(uv_fs_t* req) {
}
+static void fs__copyfile(uv_fs_t* req) {
+ int flags;
+ int overwrite;
+
+ flags = req->fs.info.file_flags;
+ overwrite = flags & UV_FS_COPYFILE_EXCL;
+
+ if (CopyFileW(req->file.pathw, req->fs.info.new_pathw, overwrite) == 0) {
+ SET_REQ_WIN32_ERROR(req, GetLastError());
+ return;
+ }
+
+ SET_REQ_RESULT(req, 0);
+}
+
+
static void fs__sendfile(uv_fs_t* req) {
int fd_in = req->file.fd, fd_out = req->fs.info.fd_out;
size_t length = req->fs.info.bufsml[0].len;
@@ -1675,25 +1767,46 @@ error:
static void fs__symlink(uv_fs_t* req) {
- WCHAR* pathw = req->file.pathw;
- WCHAR* new_pathw = req->fs.info.new_pathw;
- int flags = req->fs.info.file_flags;
- int result;
+ WCHAR* pathw;
+ WCHAR* new_pathw;
+ int flags;
+ int err;
+ pathw = req->file.pathw;
+ new_pathw = req->fs.info.new_pathw;
- if (flags & UV_FS_SYMLINK_JUNCTION) {
+ if (req->fs.info.file_flags & UV_FS_SYMLINK_JUNCTION) {
fs__create_junction(req, pathw, new_pathw);
- } else if (pCreateSymbolicLinkW) {
- result = pCreateSymbolicLinkW(new_pathw,
- pathw,
- flags & UV_FS_SYMLINK_DIR ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0) ? 0 : -1;
- if (result == -1) {
- SET_REQ_WIN32_ERROR(req, GetLastError());
- } else {
- SET_REQ_RESULT(req, result);
- }
- } else {
+ return;
+ }
+ if (!pCreateSymbolicLinkW) {
SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED);
+ return;
+ }
+
+ if (req->fs.info.file_flags & UV_FS_SYMLINK_DIR)
+ flags = SYMBOLIC_LINK_FLAG_DIRECTORY | uv__file_symlink_usermode_flag;
+ else
+ flags = uv__file_symlink_usermode_flag;
+
+ if (pCreateSymbolicLinkW(new_pathw, pathw, flags)) {
+ SET_REQ_RESULT(req, 0);
+ return;
+ }
+
+ /* Something went wrong. We will test if it is because of user-mode
+ * symlinks.
+ */
+ err = GetLastError();
+ if (err == ERROR_INVALID_PARAMETER &&
+ flags & SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) {
+ /* This system does not support user-mode symlinks. We will clear the
+ * unsupported flag and retry.
+ */
+ uv__file_symlink_usermode_flag = 0;
+ fs__symlink(req);
+ } else {
+ SET_REQ_WIN32_ERROR(req, err);
}
}
@@ -1831,6 +1944,7 @@ static void uv__fs_work(struct uv__work* w) {
XX(CLOSE, close)
XX(READ, read)
XX(WRITE, write)
+ XX(COPYFILE, copyfile)
XX(SENDFILE, sendfile)
XX(STAT, stat)
XX(LSTAT, lstat)
@@ -1877,6 +1991,9 @@ static void uv__fs_done(struct uv__work* w, int status) {
void uv_fs_req_cleanup(uv_fs_t* req) {
+ if (req == NULL)
+ return;
+
if (req->flags & UV_FS_CLEANEDUP)
return;
@@ -1907,8 +2024,7 @@ int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
int mode, uv_fs_cb cb) {
int err;
- uv_fs_req_init(loop, req, UV_FS_OPEN, cb);
-
+ INIT(UV_FS_OPEN);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
@@ -1916,28 +2032,14 @@ int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
req->fs.info.file_flags = flags;
req->fs.info.mode = mode;
-
- if (cb) {
- QUEUE_FS_TP_JOB(loop, req);
- return 0;
- } else {
- fs__open(req);
- return req->result;
- }
+ POST;
}
int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) {
- uv_fs_req_init(loop, req, UV_FS_CLOSE, cb);
+ INIT(UV_FS_CLOSE);
req->file.fd = fd;
-
- if (cb) {
- QUEUE_FS_TP_JOB(loop, req);
- return 0;
- } else {
- fs__close(req);
- return req->result;
- }
+ POST;
}
@@ -1948,11 +2050,11 @@ int uv_fs_read(uv_loop_t* loop,
unsigned int nbufs,
int64_t offset,
uv_fs_cb cb) {
+ INIT(UV_FS_READ);
+
if (bufs == NULL || nbufs == 0)
return UV_EINVAL;
- uv_fs_req_init(loop, req, UV_FS_READ, cb);
-
req->file.fd = fd;
req->fs.info.nbufs = nbufs;
@@ -1966,14 +2068,7 @@ int uv_fs_read(uv_loop_t* loop,
memcpy(req->fs.info.bufs, bufs, nbufs * sizeof(*bufs));
req->fs.info.offset = offset;
-
- if (cb) {
- QUEUE_FS_TP_JOB(loop, req);
- return 0;
- } else {
- fs__read(req);
- return req->result;
- }
+ POST;
}
@@ -1984,11 +2079,11 @@ int uv_fs_write(uv_loop_t* loop,
unsigned int nbufs,
int64_t offset,
uv_fs_cb cb) {
+ INIT(UV_FS_WRITE);
+
if (bufs == NULL || nbufs == 0)
return UV_EINVAL;
- uv_fs_req_init(loop, req, UV_FS_WRITE, cb);
-
req->file.fd = fd;
req->fs.info.nbufs = nbufs;
@@ -2002,14 +2097,7 @@ int uv_fs_write(uv_loop_t* loop,
memcpy(req->fs.info.bufs, bufs, nbufs * sizeof(*bufs));
req->fs.info.offset = offset;
-
- if (cb) {
- QUEUE_FS_TP_JOB(loop, req);
- return 0;
- } else {
- fs__write(req);
- return req->result;
- }
+ POST;
}
@@ -2017,20 +2105,13 @@ int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
uv_fs_cb cb) {
int err;
- uv_fs_req_init(loop, req, UV_FS_UNLINK, cb);
-
+ INIT(UV_FS_UNLINK);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
}
- if (cb) {
- QUEUE_FS_TP_JOB(loop, req);
- return 0;
- } else {
- fs__unlink(req);
- return req->result;
- }
+ POST;
}
@@ -2038,22 +2119,14 @@ int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,
uv_fs_cb cb) {
int err;
- uv_fs_req_init(loop, req, UV_FS_MKDIR, cb);
-
+ INIT(UV_FS_MKDIR);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
}
req->fs.info.mode = mode;
-
- if (cb) {
- QUEUE_FS_TP_JOB(loop, req);
- return 0;
- } else {
- fs__mkdir(req);
- return req->result;
- }
+ POST;
}
@@ -2061,39 +2134,25 @@ int uv_fs_mkdtemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl,
uv_fs_cb cb) {
int err;
- uv_fs_req_init(loop, req, UV_FS_MKDTEMP, cb);
-
+ INIT(UV_FS_MKDTEMP);
err = fs__capture_path(req, tpl, NULL, TRUE);
if (err)
return uv_translate_sys_error(err);
- if (cb) {
- QUEUE_FS_TP_JOB(loop, req);
- return 0;
- } else {
- fs__mkdtemp(req);
- return req->result;
- }
+ POST;
}
int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
int err;
- uv_fs_req_init(loop, req, UV_FS_RMDIR, cb);
-
+ INIT(UV_FS_RMDIR);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
}
- if (cb) {
- QUEUE_FS_TP_JOB(loop, req);
- return 0;
- } else {
- fs__rmdir(req);
- return req->result;
- }
+ POST;
}
@@ -2101,22 +2160,14 @@ int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
uv_fs_cb cb) {
int err;
- uv_fs_req_init(loop, req, UV_FS_SCANDIR, cb);
-
+ INIT(UV_FS_SCANDIR);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
}
req->fs.info.file_flags = flags;
-
- if (cb) {
- QUEUE_FS_TP_JOB(loop, req);
- return 0;
- } else {
- fs__scandir(req);
- return req->result;
- }
+ POST;
}
@@ -2124,20 +2175,13 @@ int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path,
const char* new_path, uv_fs_cb cb) {
int err;
- uv_fs_req_init(loop, req, UV_FS_LINK, cb);
-
+ INIT(UV_FS_LINK);
err = fs__capture_path(req, path, new_path, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
}
- if (cb) {
- QUEUE_FS_TP_JOB(loop, req);
- return 0;
- } else {
- fs__link(req);
- return req->result;
- }
+ POST;
}
@@ -2145,22 +2189,14 @@ int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
const char* new_path, int flags, uv_fs_cb cb) {
int err;
- uv_fs_req_init(loop, req, UV_FS_SYMLINK, cb);
-
+ INIT(UV_FS_SYMLINK);
err = fs__capture_path(req, path, new_path, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
}
req->fs.info.file_flags = flags;
-
- if (cb) {
- QUEUE_FS_TP_JOB(loop, req);
- return 0;
- } else {
- fs__symlink(req);
- return req->result;
- }
+ POST;
}
@@ -2168,20 +2204,13 @@ int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
uv_fs_cb cb) {
int err;
- uv_fs_req_init(loop, req, UV_FS_READLINK, cb);
-
+ INIT(UV_FS_READLINK);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
}
- if (cb) {
- QUEUE_FS_TP_JOB(loop, req);
- return 0;
- } else {
- fs__readlink(req);
- return req->result;
- }
+ POST;
}
@@ -2189,24 +2218,18 @@ int uv_fs_realpath(uv_loop_t* loop, uv_fs_t* req, const char* path,
uv_fs_cb cb) {
int err;
- if (!req || !path) {
+ INIT(UV_FS_REALPATH);
+
+ if (!path) {
return UV_EINVAL;
}
- uv_fs_req_init(loop, req, UV_FS_REALPATH, cb);
-
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
}
- if (cb) {
- QUEUE_FS_TP_JOB(loop, req);
- return 0;
- } else {
- fs__realpath(req);
- return req->result;
- }
+ POST;
}
@@ -2214,88 +2237,53 @@ int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid,
uv_gid_t gid, uv_fs_cb cb) {
int err;
- uv_fs_req_init(loop, req, UV_FS_CHOWN, cb);
-
+ INIT(UV_FS_CHOWN);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
}
- if (cb) {
- QUEUE_FS_TP_JOB(loop, req);
- return 0;
- } else {
- fs__chown(req);
- return req->result;
- }
+ POST;
}
int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_uid_t uid,
uv_gid_t gid, uv_fs_cb cb) {
- uv_fs_req_init(loop, req, UV_FS_FCHOWN, cb);
-
- if (cb) {
- QUEUE_FS_TP_JOB(loop, req);
- return 0;
- } else {
- fs__fchown(req);
- return req->result;
- }
+ INIT(UV_FS_FCHOWN);
+ POST;
}
int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
int err;
- uv_fs_req_init(loop, req, UV_FS_STAT, cb);
-
+ INIT(UV_FS_STAT);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
}
- if (cb) {
- QUEUE_FS_TP_JOB(loop, req);
- return 0;
- } else {
- fs__stat(req);
- return req->result;
- }
+ POST;
}
int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
int err;
- uv_fs_req_init(loop, req, UV_FS_LSTAT, cb);
-
+ INIT(UV_FS_LSTAT);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
}
- if (cb) {
- QUEUE_FS_TP_JOB(loop, req);
- return 0;
- } else {
- fs__lstat(req);
- return req->result;
- }
+ POST;
}
int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) {
- uv_fs_req_init(loop, req, UV_FS_FSTAT, cb);
+ INIT(UV_FS_FSTAT);
req->file.fd = fd;
-
- if (cb) {
- QUEUE_FS_TP_JOB(loop, req);
- return 0;
- } else {
- fs__fstat(req);
- return req->result;
- }
+ POST;
}
@@ -2303,85 +2291,70 @@ int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path,
const char* new_path, uv_fs_cb cb) {
int err;
- uv_fs_req_init(loop, req, UV_FS_RENAME, cb);
-
+ INIT(UV_FS_RENAME);
err = fs__capture_path(req, path, new_path, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
}
- if (cb) {
- QUEUE_FS_TP_JOB(loop, req);
- return 0;
- } else {
- fs__rename(req);
- return req->result;
- }
+ POST;
}
int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) {
- uv_fs_req_init(loop, req, UV_FS_FSYNC, cb);
+ INIT(UV_FS_FSYNC);
req->file.fd = fd;
-
- if (cb) {
- QUEUE_FS_TP_JOB(loop, req);
- return 0;
- } else {
- fs__fsync(req);
- return req->result;
- }
+ POST;
}
int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) {
- uv_fs_req_init(loop, req, UV_FS_FDATASYNC, cb);
+ INIT(UV_FS_FDATASYNC);
req->file.fd = fd;
-
- if (cb) {
- QUEUE_FS_TP_JOB(loop, req);
- return 0;
- } else {
- fs__fdatasync(req);
- return req->result;
- }
+ POST;
}
int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file fd,
int64_t offset, uv_fs_cb cb) {
- uv_fs_req_init(loop, req, UV_FS_FTRUNCATE, cb);
-
+ INIT(UV_FS_FTRUNCATE);
req->file.fd = fd;
req->fs.info.offset = offset;
-
- if (cb) {
- QUEUE_FS_TP_JOB(loop, req);
- return 0;
- } else {
- fs__ftruncate(req);
- return req->result;
- }
+ POST;
}
+int uv_fs_copyfile(uv_loop_t* loop,
+ uv_fs_t* req,
+ const char* path,
+ const char* new_path,
+ int flags,
+ uv_fs_cb cb) {
+ int err;
+
+ INIT(UV_FS_COPYFILE);
+
+ if (flags & ~UV_FS_COPYFILE_EXCL)
+ return UV_EINVAL;
+
+ err = fs__capture_path(req, path, new_path, cb != NULL);
+
+ if (err)
+ return uv_translate_sys_error(err);
+
+ req->fs.info.file_flags = flags;
+ POST;
+}
+
int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file fd_out,
uv_file fd_in, int64_t in_offset, size_t length, uv_fs_cb cb) {
- uv_fs_req_init(loop, req, UV_FS_SENDFILE, cb);
-
+ INIT(UV_FS_SENDFILE);
req->file.fd = fd_in;
req->fs.info.fd_out = fd_out;
req->fs.info.offset = in_offset;
req->fs.info.bufsml[0].len = length;
-
- if (cb) {
- QUEUE_FS_TP_JOB(loop, req);
- return 0;
- } else {
- fs__sendfile(req);
- return req->result;
- }
+ POST;
}
@@ -2392,21 +2365,13 @@ int uv_fs_access(uv_loop_t* loop,
uv_fs_cb cb) {
int err;
- uv_fs_req_init(loop, req, UV_FS_ACCESS, cb);
-
+ INIT(UV_FS_ACCESS);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err)
return uv_translate_sys_error(err);
req->fs.info.mode = flags;
-
- if (cb) {
- QUEUE_FS_TP_JOB(loop, req);
- return 0;
- }
-
- fs__access(req);
- return req->result;
+ POST;
}
@@ -2414,39 +2379,23 @@ int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,
uv_fs_cb cb) {
int err;
- uv_fs_req_init(loop, req, UV_FS_CHMOD, cb);
-
+ INIT(UV_FS_CHMOD);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
}
req->fs.info.mode = mode;
-
- if (cb) {
- QUEUE_FS_TP_JOB(loop, req);
- return 0;
- } else {
- fs__chmod(req);
- return req->result;
- }
+ POST;
}
int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file fd, int mode,
uv_fs_cb cb) {
- uv_fs_req_init(loop, req, UV_FS_FCHMOD, cb);
-
+ INIT(UV_FS_FCHMOD);
req->file.fd = fd;
req->fs.info.mode = mode;
-
- if (cb) {
- QUEUE_FS_TP_JOB(loop, req);
- return 0;
- } else {
- fs__fchmod(req);
- return req->result;
- }
+ POST;
}
@@ -2454,8 +2403,7 @@ int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime,
double mtime, uv_fs_cb cb) {
int err;
- uv_fs_req_init(loop, req, UV_FS_UTIME, cb);
-
+ INIT(UV_FS_UTIME);
err = fs__capture_path(req, path, NULL, cb != NULL);
if (err) {
return uv_translate_sys_error(err);
@@ -2463,30 +2411,15 @@ int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime,
req->fs.time.atime = atime;
req->fs.time.mtime = mtime;
-
- if (cb) {
- QUEUE_FS_TP_JOB(loop, req);
- return 0;
- } else {
- fs__utime(req);
- return req->result;
- }
+ POST;
}
int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file fd, double atime,
double mtime, uv_fs_cb cb) {
- uv_fs_req_init(loop, req, UV_FS_FUTIME, cb);
-
+ INIT(UV_FS_FUTIME);
req->file.fd = fd;
req->fs.time.atime = atime;
req->fs.time.mtime = mtime;
-
- if (cb) {
- QUEUE_FS_TP_JOB(loop, req);
- return 0;
- } else {
- fs__futime(req);
- return req->result;
- }
+ POST;
}
diff --git a/Utilities/cmlibuv/src/win/getaddrinfo.c b/Utilities/cmlibuv/src/win/getaddrinfo.c
index baab838898..282d919cf7 100644
--- a/Utilities/cmlibuv/src/win/getaddrinfo.c
+++ b/Utilities/cmlibuv/src/win/getaddrinfo.c
@@ -28,6 +28,8 @@
/* EAI_* constants. */
#include <winsock2.h>
+/* Needed for ConvertInterfaceIndexToLuid and ConvertInterfaceLuidToNameA */
+#include <iphlpapi.h>
int uv__getaddrinfo_translate_error(int sys_err) {
switch (sys_err) {
@@ -73,6 +75,9 @@ int uv__getaddrinfo_translate_error(int sys_err) {
/* Do we need different versions of this for different architectures? */
#define ALIGNED_SIZE(X) ((((X) + 3) >> 2) << 2)
+#ifndef NDIS_IF_MAX_STRING_SIZE
+#define NDIS_IF_MAX_STRING_SIZE IF_MAX_STRING_SIZE
+#endif
static void uv__getaddrinfo_work(struct uv__work* w) {
uv_getaddrinfo_t* req;
@@ -380,3 +385,69 @@ error:
}
return uv_translate_sys_error(err);
}
+
+int uv_if_indextoname(unsigned int ifindex, char* buffer, size_t* size) {
+ NET_LUID luid;
+ wchar_t wname[NDIS_IF_MAX_STRING_SIZE + 1]; /* Add one for the NUL. */
+ DWORD bufsize;
+ int r;
+
+ if (buffer == NULL || size == NULL || *size == 0)
+ return UV_EINVAL;
+
+ r = ConvertInterfaceIndexToLuid(ifindex, &luid);
+
+ if (r != 0)
+ return uv_translate_sys_error(r);
+
+ r = ConvertInterfaceLuidToNameW(&luid, wname, ARRAY_SIZE(wname));
+
+ if (r != 0)
+ return uv_translate_sys_error(r);
+
+ /* Check how much space we need */
+ bufsize = WideCharToMultiByte(CP_UTF8, 0, wname, -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,
+ wname,
+ -1,
+ buffer,
+ *size,
+ NULL,
+ NULL);
+
+ if (bufsize == 0)
+ return uv_translate_sys_error(GetLastError());
+
+ *size = bufsize - 1;
+ return 0;
+}
+
+int uv_if_indextoiid(unsigned int ifindex, char* buffer, size_t* size) {
+ int r;
+
+ if (buffer == NULL || size == NULL || *size == 0)
+ return UV_EINVAL;
+
+ r = snprintf(buffer, *size, "%d", ifindex);
+
+ if (r < 0)
+ return uv_translate_sys_error(r);
+
+ if (r >= (int) *size) {
+ *size = r + 1;
+ return UV_ENOBUFS;
+ }
+
+ *size = r;
+ return 0;
+}
diff --git a/Utilities/cmlibuv/src/win/handle.c b/Utilities/cmlibuv/src/win/handle.c
index 72b49d9790..39150702dd 100644
--- a/Utilities/cmlibuv/src/win/handle.c
+++ b/Utilities/cmlibuv/src/win/handle.c
@@ -152,3 +152,8 @@ void uv_close(uv_handle_t* handle, uv_close_cb cb) {
int uv_is_closing(const uv_handle_t* handle) {
return !!(handle->flags & (UV__HANDLE_CLOSING | UV_HANDLE_CLOSED));
}
+
+
+uv_os_fd_t uv_get_osfhandle(int fd) {
+ return uv__get_osfhandle(fd);
+}
diff --git a/Utilities/cmlibuv/src/win/internal.h b/Utilities/cmlibuv/src/win/internal.h
index 83601d57a6..9f28f77e66 100644
--- a/Utilities/cmlibuv/src/win/internal.h
+++ b/Utilities/cmlibuv/src/win/internal.h
@@ -330,7 +330,6 @@ void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle);
void uv__util_init(void);
uint64_t uv__hrtime(double scale);
-int uv_parent_pid(void);
int uv_current_pid(void);
__declspec(noreturn) void uv_fatal_error(const int errorno, const char* syscall);
int uv__getpwuid_r(uv_passwd_t* pwd);
diff --git a/Utilities/cmlibuv/src/win/pipe.c b/Utilities/cmlibuv/src/win/pipe.c
index edf3002121..1a7c4dc15e 100644
--- a/Utilities/cmlibuv/src/win/pipe.c
+++ b/Utilities/cmlibuv/src/win/pipe.c
@@ -31,6 +31,9 @@
#include "stream-inl.h"
#include "req-inl.h"
+#include <aclapi.h>
+#include <accctrl.h>
+
typedef struct uv__ipc_queue_item_s uv__ipc_queue_item_t;
struct uv__ipc_queue_item_s {
@@ -202,7 +205,7 @@ int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access,
uv_unique_pipe_name(ptr, name, nameSize);
pipeHandle = CreateNamedPipeA(name,
- access | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE,
+ access | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE | WRITE_DAC,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 65536, 65536, 0,
NULL);
@@ -534,7 +537,7 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
*/
handle->pipe.serv.accept_reqs[0].pipeHandle = CreateNamedPipeW(handle->name,
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED |
- FILE_FLAG_FIRST_PIPE_INSTANCE,
+ FILE_FLAG_FIRST_PIPE_INSTANCE | WRITE_DAC,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES, 65536, 65536, 0, NULL);
@@ -803,7 +806,7 @@ static void uv_pipe_queue_accept(uv_loop_t* loop, uv_pipe_t* handle,
assert(req->pipeHandle == INVALID_HANDLE_VALUE);
req->pipeHandle = CreateNamedPipeW(handle->name,
- PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
+ PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | WRITE_DAC,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES, 65536, 65536, 0, NULL);
@@ -968,27 +971,31 @@ static DWORD WINAPI uv_pipe_zero_readfile_thread_proc(void* parameter) {
uv_mutex_unlock(m);
}
restart_readfile:
- result = ReadFile(handle->handle,
- &uv_zero_,
- 0,
- &bytes,
- NULL);
- if (!result) {
- err = GetLastError();
- if (err == ERROR_OPERATION_ABORTED &&
- handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) {
- if (handle->flags & UV_HANDLE_READING) {
- /* just a brief break to do something else */
- handle->pipe.conn.readfile_thread = NULL;
- /* resume after it is finished */
- uv_mutex_lock(m);
- handle->pipe.conn.readfile_thread = hThread;
- uv_mutex_unlock(m);
- goto restart_readfile;
- } else {
- result = 1; /* successfully stopped reading */
+ if (handle->flags & UV_HANDLE_READING) {
+ result = ReadFile(handle->handle,
+ &uv_zero_,
+ 0,
+ &bytes,
+ NULL);
+ if (!result) {
+ err = GetLastError();
+ if (err == ERROR_OPERATION_ABORTED &&
+ handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) {
+ if (handle->flags & UV_HANDLE_READING) {
+ /* just a brief break to do something else */
+ handle->pipe.conn.readfile_thread = NULL;
+ /* resume after it is finished */
+ uv_mutex_lock(m);
+ handle->pipe.conn.readfile_thread = hThread;
+ uv_mutex_unlock(m);
+ goto restart_readfile;
+ } else {
+ result = 1; /* successfully stopped reading */
+ }
}
}
+ } else {
+ result = 1; /* successfully aborted read before it even started */
}
if (hThread) {
assert(hThread == handle->pipe.conn.readfile_thread);
@@ -1515,7 +1522,10 @@ static void uv_pipe_read_error(uv_loop_t* loop, uv_pipe_t* handle, int error,
static void uv_pipe_read_error_or_eof(uv_loop_t* loop, uv_pipe_t* handle,
int error, uv_buf_t buf) {
- if (error == ERROR_BROKEN_PIPE) {
+ if (error == ERROR_OPERATION_ABORTED) {
+ /* do nothing (equivalent to EINTR) */
+ }
+ else if (error == ERROR_BROKEN_PIPE) {
uv_pipe_read_eof(loop, handle, buf);
} else {
uv_pipe_read_error(loop, handle, error, buf);
@@ -1906,6 +1916,7 @@ int uv_pipe_open(uv_pipe_t* pipe, uv_file file) {
if (os_handle == INVALID_HANDLE_VALUE)
return UV_EBADF;
+ uv__once_init();
/* In order to avoid closing a stdio file descriptor 0-2, duplicate the
* underlying OS handle and forget about the original fd.
* We could also opt to use the original OS handle and just never close it,
@@ -1961,7 +1972,7 @@ int uv_pipe_open(uv_pipe_t* pipe, uv_file file) {
if (pipe->ipc) {
assert(!(pipe->flags & UV_HANDLE_NON_OVERLAPPED_PIPE));
- pipe->pipe.conn.ipc_pid = uv_parent_pid();
+ pipe->pipe.conn.ipc_pid = uv_os_getppid();
assert(pipe->pipe.conn.ipc_pid != -1);
}
return 0;
@@ -1979,6 +1990,7 @@ static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size)
unsigned int name_len;
int err;
+ uv__once_init();
name_info = NULL;
if (handle->handle == INVALID_HANDLE_VALUE) {
@@ -2123,3 +2135,80 @@ uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) {
else
return UV_TCP;
}
+
+int uv_pipe_chmod(uv_pipe_t* handle, int mode) {
+ SID_IDENTIFIER_AUTHORITY sid_world = SECURITY_WORLD_SID_AUTHORITY;
+ PACL old_dacl, new_dacl;
+ PSECURITY_DESCRIPTOR sd;
+ EXPLICIT_ACCESS ea;
+ PSID everyone;
+ int error;
+
+ if (handle == NULL || handle->handle == INVALID_HANDLE_VALUE)
+ return UV_EBADF;
+
+ if (mode != UV_READABLE &&
+ mode != UV_WRITABLE &&
+ mode != (UV_WRITABLE | UV_READABLE))
+ return UV_EINVAL;
+
+ if (!AllocateAndInitializeSid(&sid_world,
+ 1,
+ SECURITY_WORLD_RID,
+ 0, 0, 0, 0, 0, 0, 0,
+ &everyone)) {
+ error = GetLastError();
+ goto done;
+ }
+
+ if (GetSecurityInfo(handle->handle,
+ SE_KERNEL_OBJECT,
+ DACL_SECURITY_INFORMATION,
+ NULL,
+ NULL,
+ &old_dacl,
+ NULL,
+ &sd)) {
+ error = GetLastError();
+ goto clean_sid;
+ }
+
+ memset(&ea, 0, sizeof(EXPLICIT_ACCESS));
+ if (mode & UV_READABLE)
+ ea.grfAccessPermissions |= GENERIC_READ | FILE_WRITE_ATTRIBUTES;
+ if (mode & UV_WRITABLE)
+ ea.grfAccessPermissions |= GENERIC_WRITE | FILE_READ_ATTRIBUTES;
+ ea.grfAccessPermissions |= SYNCHRONIZE;
+ ea.grfAccessMode = SET_ACCESS;
+ ea.grfInheritance = NO_INHERITANCE;
+ ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
+ ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
+ ea.Trustee.ptstrName = (LPTSTR)everyone;
+
+ if (SetEntriesInAcl(1, &ea, old_dacl, &new_dacl)) {
+ error = GetLastError();
+ goto clean_sd;
+ }
+
+ if (SetSecurityInfo(handle->handle,
+ SE_KERNEL_OBJECT,
+ DACL_SECURITY_INFORMATION,
+ NULL,
+ NULL,
+ new_dacl,
+ NULL)) {
+ error = GetLastError();
+ goto clean_dacl;
+ }
+
+ error = 0;
+
+clean_dacl:
+ LocalFree((HLOCAL) new_dacl);
+clean_sd:
+ LocalFree((HLOCAL) sd);
+clean_sid:
+ FreeSid(everyone);
+done:
+ return uv_translate_sys_error(error);
+}
diff --git a/Utilities/cmlibuv/src/win/process.c b/Utilities/cmlibuv/src/win/process.c
index d141601607..cc06d9e22a 100644
--- a/Utilities/cmlibuv/src/win/process.c
+++ b/Utilities/cmlibuv/src/win/process.c
@@ -405,8 +405,15 @@ static WCHAR* search_path(const WCHAR *file,
/* Next slice starts just after where the previous one ended */
dir_start = dir_end;
+ /* If path is quoted, find quote end */
+ if (*dir_start == L'"' || *dir_start == L'\'') {
+ dir_end = wcschr(dir_start + 1, *dir_start);
+ if (dir_end == NULL) {
+ dir_end = wcschr(dir_start, L'\0');
+ }
+ }
/* Slice until the next ; or \0 is found */
- dir_end = wcschr(dir_start, L';');
+ dir_end = wcschr(dir_end, L';');
if (dir_end == NULL) {
dir_end = wcschr(dir_start, L'\0');
}
@@ -1051,15 +1058,18 @@ int uv_spawn(uv_loop_t* loop,
startup.hStdOutput = uv__stdio_handle(process->child_stdio_buffer, 1);
startup.hStdError = uv__stdio_handle(process->child_stdio_buffer, 2);
+ process_flags = CREATE_UNICODE_ENVIRONMENT;
+
if (options->flags & UV_PROCESS_WINDOWS_HIDE) {
/* 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;
}
- process_flags = CREATE_UNICODE_ENVIRONMENT;
-
if (options->flags & UV_PROCESS_DETACHED) {
/* Note that we're not setting the CREATE_BREAKAWAY_FROM_JOB flag. That
* means that libuv might not let you create a fully daemonized process
@@ -1163,6 +1173,10 @@ int uv_spawn(uv_loop_t* loop,
static int uv__kill(HANDLE process_handle, int signum) {
+ if (signum < 0 || signum >= NSIG) {
+ return UV_EINVAL;
+ }
+
switch (signum) {
case SIGTERM:
case SIGKILL:
@@ -1227,8 +1241,15 @@ int uv_process_kill(uv_process_t* process, int signum) {
int uv_kill(int pid, int signum) {
int err;
- HANDLE process_handle = OpenProcess(PROCESS_TERMINATE |
- PROCESS_QUERY_INFORMATION, FALSE, pid);
+ HANDLE process_handle;
+
+ if (pid == 0) {
+ process_handle = GetCurrentProcess();
+ } else {
+ process_handle = OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION,
+ FALSE,
+ pid);
+ }
if (process_handle == NULL) {
err = GetLastError();
diff --git a/Utilities/cmlibuv/src/win/signal.c b/Utilities/cmlibuv/src/win/signal.c
index 7b42dd9928..a174da1f76 100644
--- a/Utilities/cmlibuv/src/win/signal.c
+++ b/Utilities/cmlibuv/src/win/signal.c
@@ -64,7 +64,7 @@ static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) {
}
-RB_GENERATE_STATIC(uv_signal_tree_s, uv_signal_s, tree_entry, uv__signal_compare);
+RB_GENERATE_STATIC(uv_signal_tree_s, uv_signal_s, tree_entry, uv__signal_compare)
/*
diff --git a/Utilities/cmlibuv/src/win/stream-inl.h b/Utilities/cmlibuv/src/win/stream-inl.h
index bf12148afe..dba0374704 100644
--- a/Utilities/cmlibuv/src/win/stream-inl.h
+++ b/Utilities/cmlibuv/src/win/stream-inl.h
@@ -36,6 +36,7 @@ INLINE static void uv_stream_init(uv_loop_t* loop,
uv__handle_init(loop, (uv_handle_t*) handle, type);
handle->write_queue_size = 0;
handle->activecnt = 0;
+ handle->stream.conn.shutdown_req = NULL;
}
@@ -47,8 +48,6 @@ INLINE static void uv_connection_init(uv_stream_t* handle) {
handle->read_req.event_handle = NULL;
handle->read_req.wait_handle = INVALID_HANDLE_VALUE;
handle->read_req.data = handle;
-
- handle->stream.conn.shutdown_req = NULL;
}
diff --git a/Utilities/cmlibuv/src/win/tcp.c b/Utilities/cmlibuv/src/win/tcp.c
index 972539f4df..fd6efbaf89 100644
--- a/Utilities/cmlibuv/src/win/tcp.c
+++ b/Utilities/cmlibuv/src/win/tcp.c
@@ -747,10 +747,15 @@ static int uv_tcp_try_connect(uv_connect_t* req,
uv_connect_cb cb) {
uv_loop_t* loop = handle->loop;
const struct sockaddr* bind_addr;
+ struct sockaddr_storage converted;
BOOL success;
DWORD bytes;
int err;
+ err = uv__convert_to_localhost_if_unspecified(addr, &converted);
+ if (err)
+ return err;
+
if (handle->delayed_error) {
return handle->delayed_error;
}
@@ -782,12 +787,12 @@ static int uv_tcp_try_connect(uv_connect_t* req,
memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped));
success = handle->tcp.conn.func_connectex(handle->socket,
- addr,
- addrlen,
- NULL,
- 0,
- &bytes,
- &req->u.io.overlapped);
+ (const struct sockaddr*) &converted,
+ addrlen,
+ NULL,
+ 0,
+ &bytes,
+ &req->u.io.overlapped);
if (UV_SUCCEEDED_WITHOUT_IOCP(success)) {
/* Process the req without IOCP. */
@@ -1446,6 +1451,8 @@ int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) {
WSAPROTOCOL_INFOW protocol_info;
int opt_len;
int err;
+ struct sockaddr_storage saddr;
+ int saddr_len;
/* Detect the address family of the socket. */
opt_len = (int) sizeof protocol_info;
@@ -1466,6 +1473,19 @@ int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) {
return uv_translate_sys_error(err);
}
+ /* Support already active socket. */
+ saddr_len = sizeof(saddr);
+ if (!uv_tcp_getsockname(handle, (struct sockaddr*) &saddr, &saddr_len)) {
+ /* Socket is already bound. */
+ handle->flags |= UV_HANDLE_BOUND;
+ saddr_len = sizeof(saddr);
+ if (!uv_tcp_getpeername(handle, (struct sockaddr*) &saddr, &saddr_len)) {
+ /* Socket is already connected. */
+ uv_connection_init((uv_stream_t*) handle);
+ handle->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE;
+ }
+ }
+
return 0;
}
diff --git a/Utilities/cmlibuv/src/win/thread.c b/Utilities/cmlibuv/src/win/thread.c
index 91684e9387..9eaad77cd0 100644
--- a/Utilities/cmlibuv/src/win/thread.c
+++ b/Utilities/cmlibuv/src/win/thread.c
@@ -182,6 +182,7 @@ int uv_thread_join(uv_thread_t *tid) {
else {
CloseHandle(*tid);
*tid = 0;
+ MemoryBarrier(); /* For feature parity with pthread_join(). */
return 0;
}
}
@@ -198,6 +199,11 @@ int uv_mutex_init(uv_mutex_t* mutex) {
}
+int uv_mutex_init_recursive(uv_mutex_t* mutex) {
+ return uv_mutex_init(mutex);
+}
+
+
void uv_mutex_destroy(uv_mutex_t* mutex) {
DeleteCriticalSection(mutex);
}
diff --git a/Utilities/cmlibuv/src/win/timer.c b/Utilities/cmlibuv/src/win/timer.c
index 27ca7716af..7e006fedfa 100644
--- a/Utilities/cmlibuv/src/win/timer.c
+++ b/Utilities/cmlibuv/src/win/timer.c
@@ -56,7 +56,7 @@ static int uv_timer_compare(uv_timer_t* a, uv_timer_t* b) {
}
-RB_GENERATE_STATIC(uv_timer_tree_s, uv_timer_s, tree_entry, uv_timer_compare);
+RB_GENERATE_STATIC(uv_timer_tree_s, uv_timer_s, tree_entry, uv_timer_compare)
int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) {
diff --git a/Utilities/cmlibuv/src/win/tty.c b/Utilities/cmlibuv/src/win/tty.c
index a6f583956f..05a11e8830 100644
--- a/Utilities/cmlibuv/src/win/tty.c
+++ b/Utilities/cmlibuv/src/win/tty.c
@@ -112,14 +112,30 @@ static int uv_tty_virtual_offset = -1;
static int uv_tty_virtual_height = -1;
static int uv_tty_virtual_width = -1;
+/* The console window size
+ * We keep this separate from uv_tty_virtual_*. We use those values to only
+ * handle signalling SIGWINCH
+ */
+
+static HANDLE uv__tty_console_handle = INVALID_HANDLE_VALUE;
+static int uv__tty_console_height = -1;
+static int uv__tty_console_width = -1;
+
+static DWORD WINAPI uv__tty_console_resize_message_loop_thread(void* param);
+static void CALLBACK uv__tty_console_resize_event(HWINEVENTHOOK hWinEventHook,
+ DWORD event,
+ HWND hwnd,
+ LONG idObject,
+ LONG idChild,
+ DWORD dwEventThread,
+ DWORD dwmsEventTime);
+
/* We use a semaphore rather than a mutex or critical section because in some
cases (uv__cancel_read_console) we need take the lock in the main thread and
release it in another thread. Using a semaphore ensures that in such
scenario the main thread will still block when trying to acquire the lock. */
static uv_sem_t uv_tty_output_lock;
-static HANDLE uv_tty_output_handle = INVALID_HANDLE_VALUE;
-
static WORD uv_tty_default_text_attributes =
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
@@ -141,6 +157,18 @@ static void uv__determine_vterm_state(HANDLE handle);
void uv_console_init(void) {
if (uv_sem_init(&uv_tty_output_lock, 1))
abort();
+ uv__tty_console_handle = CreateFileW(L"CONOUT$",
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_WRITE,
+ 0,
+ OPEN_EXISTING,
+ 0,
+ 0);
+ if (uv__tty_console_handle != NULL) {
+ QueueUserWorkItem(uv__tty_console_resize_message_loop_thread,
+ NULL,
+ WT_EXECUTELONGFUNCTION);
+ }
}
@@ -148,6 +176,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) {
HANDLE handle;
CONSOLE_SCREEN_BUFFER_INFO screen_buffer_info;
+ uv__once_init();
handle = (HANDLE) uv__get_osfhandle(fd);
if (handle == INVALID_HANDLE_VALUE)
return UV_EBADF;
@@ -183,11 +212,6 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) {
if (uv__vterm_state == UV_UNCHECKED)
uv__determine_vterm_state(handle);
- /* Store the global tty output handle. This handle is used by TTY read */
- /* streams to update the virtual window when a CONSOLE_BUFFER_SIZE_EVENT */
- /* is received. */
- uv_tty_output_handle = handle;
-
/* Remember the original console text attributes. */
uv_tty_capture_initial_style(&screen_buffer_info);
@@ -704,25 +728,7 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
}
records_left--;
- /* If the window was resized, recompute the virtual window size. This */
- /* will trigger a SIGWINCH signal if the window size changed in an */
- /* way that matters to libuv. */
- if (handle->tty.rd.last_input_record.EventType == WINDOW_BUFFER_SIZE_EVENT) {
- CONSOLE_SCREEN_BUFFER_INFO info;
-
- uv_sem_wait(&uv_tty_output_lock);
-
- if (uv_tty_output_handle != INVALID_HANDLE_VALUE &&
- GetConsoleScreenBufferInfo(uv_tty_output_handle, &info)) {
- uv_tty_update_virtual_window(&info);
- }
-
- uv_sem_post(&uv_tty_output_lock);
-
- continue;
- }
-
- /* Ignore other events that are not key or resize events. */
+ /* Ignore other events that are not key events. */
if (handle->tty.rd.last_input_record.EventType != KEY_EVENT) {
continue;
}
@@ -1102,9 +1108,6 @@ static int uv__cancel_read_console(uv_tty_t* handle) {
static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info) {
- int old_virtual_width = uv_tty_virtual_width;
- int old_virtual_height = uv_tty_virtual_height;
-
uv_tty_virtual_width = info->dwSize.X;
uv_tty_virtual_height = info->srWindow.Bottom - info->srWindow.Top + 1;
@@ -1124,14 +1127,6 @@ static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info) {
if (uv_tty_virtual_offset < 0) {
uv_tty_virtual_offset = 0;
}
-
- /* If the virtual window size changed, emit a SIGWINCH signal. Don't emit */
- /* if this was the first time the virtual window size was computed. */
- if (old_virtual_width != -1 && old_virtual_height != -1 &&
- (uv_tty_virtual_width != old_virtual_width ||
- uv_tty_virtual_height != old_virtual_height)) {
- uv__signal_dispatch(SIGWINCH);
- }
}
@@ -2279,3 +2274,55 @@ static void uv__determine_vterm_state(HANDLE handle) {
uv__vterm_state = UV_SUPPORTED;
}
+
+static DWORD WINAPI uv__tty_console_resize_message_loop_thread(void* param) {
+ CONSOLE_SCREEN_BUFFER_INFO sb_info;
+ MSG msg;
+
+ if (!GetConsoleScreenBufferInfo(uv__tty_console_handle, &sb_info))
+ return 0;
+
+ uv__tty_console_width = sb_info.dwSize.X;
+ uv__tty_console_height = sb_info.srWindow.Bottom - sb_info.srWindow.Top + 1;
+
+ if (pSetWinEventHook == NULL)
+ return 0;
+
+ if (!pSetWinEventHook(EVENT_CONSOLE_LAYOUT,
+ EVENT_CONSOLE_LAYOUT,
+ NULL,
+ uv__tty_console_resize_event,
+ 0,
+ 0,
+ WINEVENT_OUTOFCONTEXT))
+ return 0;
+
+ while (GetMessage(&msg, NULL, 0, 0)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ return 0;
+}
+
+static void CALLBACK uv__tty_console_resize_event(HWINEVENTHOOK hWinEventHook,
+ DWORD event,
+ HWND hwnd,
+ LONG idObject,
+ LONG idChild,
+ DWORD dwEventThread,
+ DWORD dwmsEventTime) {
+ CONSOLE_SCREEN_BUFFER_INFO sb_info;
+ int width, height;
+
+ if (!GetConsoleScreenBufferInfo(uv__tty_console_handle, &sb_info))
+ return;
+
+ width = sb_info.dwSize.X;
+ height = sb_info.srWindow.Bottom - sb_info.srWindow.Top + 1;
+
+ if (width != uv__tty_console_width || height != uv__tty_console_height) {
+ uv__tty_console_width = width;
+ uv__tty_console_height = height;
+ uv__signal_dispatch(SIGWINCH);
+ }
+}
diff --git a/Utilities/cmlibuv/src/win/udp.c b/Utilities/cmlibuv/src/win/udp.c
index 2fd15cfa9a..cd1d0e07b2 100644
--- a/Utilities/cmlibuv/src/win/udp.c
+++ b/Utilities/cmlibuv/src/win/udp.c
@@ -897,13 +897,12 @@ int uv__udp_send(uv_udp_send_t* req,
int err;
if (!(handle->flags & UV_HANDLE_BOUND)) {
- if (addrlen == sizeof(uv_addr_ip4_any_)) {
+ if (addrlen == sizeof(uv_addr_ip4_any_))
bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;
- } else if (addrlen == sizeof(uv_addr_ip6_any_)) {
+ else if (addrlen == sizeof(uv_addr_ip6_any_))
bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
- } else {
- abort();
- }
+ else
+ return UV_EINVAL;
err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0);
if (err)
return uv_translate_sys_error(err);
@@ -922,5 +921,45 @@ int uv__udp_try_send(uv_udp_t* handle,
unsigned int nbufs,
const struct sockaddr* addr,
unsigned int addrlen) {
- return UV_ENOSYS;
+ DWORD bytes;
+ const struct sockaddr* bind_addr;
+ struct sockaddr_storage converted;
+ int err;
+
+ assert(nbufs > 0);
+
+ err = uv__convert_to_localhost_if_unspecified(addr, &converted);
+ if (err)
+ return err;
+
+ /* Already sending a message.*/
+ if (handle->send_queue_count != 0)
+ return UV_EAGAIN;
+
+ if (!(handle->flags & UV_HANDLE_BOUND)) {
+ if (addrlen == sizeof(uv_addr_ip4_any_))
+ bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;
+ else if (addrlen == sizeof(uv_addr_ip6_any_))
+ bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
+ else
+ return UV_EINVAL;
+ err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0);
+ if (err)
+ return uv_translate_sys_error(err);
+ }
+
+ err = WSASendTo(handle->socket,
+ (WSABUF*)bufs,
+ nbufs,
+ &bytes,
+ 0,
+ (const struct sockaddr*) &converted,
+ addrlen,
+ NULL,
+ NULL);
+
+ if (err)
+ return uv_translate_sys_error(WSAGetLastError());
+
+ return bytes;
}
diff --git a/Utilities/cmlibuv/src/win/util.c b/Utilities/cmlibuv/src/win/util.c
index d2e7f772ce..3100bc23ad 100644
--- a/Utilities/cmlibuv/src/win/util.c
+++ b/Utilities/cmlibuv/src/win/util.c
@@ -331,7 +331,12 @@ uint64_t uv_get_total_memory(void) {
}
-int uv_parent_pid(void) {
+uv_pid_t uv_os_getpid(void) {
+ return GetCurrentProcessId();
+}
+
+
+uv_pid_t uv_os_getppid(void) {
int parent_pid = -1;
HANDLE handle;
PROCESSENTRY32 pe;
@@ -1388,7 +1393,7 @@ int uv__getpwuid_r(uv_passwd_t* pwd) {
if (OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token) == 0)
return uv_translate_sys_error(GetLastError());
- bufsize = sizeof(path);
+ bufsize = ARRAY_SIZE(path);
if (!GetUserProfileDirectoryW(token, path, &bufsize)) {
r = GetLastError();
CloseHandle(token);
@@ -1403,7 +1408,7 @@ int uv__getpwuid_r(uv_passwd_t* pwd) {
CloseHandle(token);
/* Get the username using GetUserNameW() */
- bufsize = sizeof(username);
+ bufsize = ARRAY_SIZE(username);
if (!GetUserNameW(username, &bufsize)) {
r = GetLastError();
diff --git a/Utilities/cmlibuv/src/win/winapi.c b/Utilities/cmlibuv/src/win/winapi.c
index aa5d719fbe..4ccdf0a5f9 100644
--- a/Utilities/cmlibuv/src/win/winapi.c
+++ b/Utilities/cmlibuv/src/win/winapi.c
@@ -52,11 +52,15 @@ sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW;
/* Powrprof.dll function pointer */
sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;
+/* User32.dll function pointer */
+sSetWinEventHook pSetWinEventHook;
+
void uv_winapi_init(void) {
HMODULE ntdll_module;
HMODULE kernel32_module;
HMODULE powrprof_module;
+ HMODULE user32_module;
ntdll_module = GetModuleHandleA("ntdll.dll");
if (ntdll_module == NULL) {
@@ -156,4 +160,10 @@ void uv_winapi_init(void) {
GetProcAddress(powrprof_module, "PowerRegisterSuspendResumeNotification");
}
+ user32_module = LoadLibraryA("user32.dll");
+ if (user32_module != NULL) {
+ pSetWinEventHook = (sSetWinEventHook)
+ GetProcAddress(user32_module, "SetWinEventHook");
+ }
+
}
diff --git a/Utilities/cmlibuv/src/win/winapi.h b/Utilities/cmlibuv/src/win/winapi.h
index 4b0eeca15b..8993c65747 100644
--- a/Utilities/cmlibuv/src/win/winapi.h
+++ b/Utilities/cmlibuv/src/win/winapi.h
@@ -4104,6 +4104,10 @@
# define JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE 0x00002000
#endif
+#ifndef SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
+# define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE 0x00000002
+#endif
+
/* from winternl.h */
typedef struct _UNICODE_STRING {
USHORT Length;
@@ -4730,6 +4734,25 @@ typedef DWORD (WINAPI *sPowerRegisterSuspendResumeNotification)
HANDLE Recipient,
_PHPOWERNOTIFY RegistrationHandle);
+/* from Winuser.h */
+typedef VOID (CALLBACK* WINEVENTPROC)
+ (HWINEVENTHOOK hWinEventHook,
+ DWORD event,
+ HWND hwnd,
+ LONG idObject,
+ LONG idChild,
+ DWORD idEventThread,
+ DWORD dwmsEventTime);
+
+typedef HWINEVENTHOOK (WINAPI *sSetWinEventHook)
+ (UINT eventMin,
+ UINT eventMax,
+ HMODULE hmodWinEventProc,
+ WINEVENTPROC lpfnWinEventProc,
+ DWORD idProcess,
+ DWORD idThread,
+ UINT dwflags);
+
/* Ntdll function pointers */
extern sRtlNtStatusToDosError pRtlNtStatusToDosError;
@@ -4758,4 +4781,7 @@ extern sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW;
/* Powrprof.dll function pointer */
extern sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification;
+/* User32.dll function pointer */
+extern sSetWinEventHook pSetWinEventHook;
+
#endif /* UV_WIN_WINAPI_H_ */
diff --git a/Utilities/cmlibuv/src/win/winsock.c b/Utilities/cmlibuv/src/win/winsock.c
index e86d76b131..7cfa90f8af 100644
--- a/Utilities/cmlibuv/src/win/winsock.c
+++ b/Utilities/cmlibuv/src/win/winsock.c
@@ -559,3 +559,31 @@ int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in,
return SOCKET_ERROR;
}
}
+
+int uv__convert_to_localhost_if_unspecified(const struct sockaddr* addr,
+ struct sockaddr_storage* storage) {
+ struct sockaddr_in* dest4;
+ struct sockaddr_in6* dest6;
+
+ if (addr == NULL)
+ return UV_EINVAL;
+
+ switch (addr->sa_family) {
+ case AF_INET:
+ dest4 = (struct sockaddr_in*) storage;
+ memcpy(dest4, addr, sizeof(*dest4));
+ if (dest4->sin_addr.s_addr == 0)
+ dest4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ return 0;
+ case AF_INET6:
+ dest6 = (struct sockaddr_in6*) storage;
+ 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;
+ return 0;
+ default:
+ return UV_EINVAL;
+ }
+}
diff --git a/Utilities/cmlibuv/src/win/winsock.h b/Utilities/cmlibuv/src/win/winsock.h
index 3115fe3d24..e8b274e1be 100644
--- a/Utilities/cmlibuv/src/win/winsock.h
+++ b/Utilities/cmlibuv/src/win/winsock.h
@@ -188,4 +188,7 @@ typedef struct _IP_ADAPTER_UNICAST_ADDRESS_LH {
#endif
+int uv__convert_to_localhost_if_unspecified(const struct sockaddr* addr,
+ struct sockaddr_storage* storage);
+
#endif /* UV_WIN_WINSOCK_H_ */