aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs
diff options
context:
space:
mode:
authoralexv-smirnov <alex@ydb.tech>2022-12-20 00:50:48 +0300
committeralexv-smirnov <alex@ydb.tech>2022-12-20 00:50:48 +0300
commit84f2cfa253cc618438ed6e9d68b33fa7c0d88cb9 (patch)
treef0cf2236e0aafb3e437199f1ac7b559e7fad554a /contrib/libs
parentbde6febc1ad3b826e72746de21d7250803e8e0b5 (diff)
downloadydb-84f2cfa253cc618438ed6e9d68b33fa7c0d88cb9.tar.gz
add windows platform to ydb github export
Diffstat (limited to 'contrib/libs')
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/net/windows/Net.cpp48
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/net/windows/SimpleUDP.cpp263
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/windows/Environment.cpp37
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/windows/FileSystem.cpp336
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/windows/OSVersionInfo.cpp138
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/windows/Security.cpp21
-rw-r--r--contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/windows/Time.cpp31
-rw-r--r--contrib/libs/crcutil/multiword_64_64_cl_i386_mmx.cc304
-rw-r--r--contrib/libs/cxxsupp/libcxx/src/support/win32/atomic_win32.cpp31
-rw-r--r--contrib/libs/cxxsupp/libcxx/src/support/win32/locale_win32.cpp141
-rw-r--r--contrib/libs/cxxsupp/libcxx/src/support/win32/new_win32.cpp28
-rw-r--r--contrib/libs/cxxsupp/libcxx/src/support/win32/support.cpp172
-rw-r--r--contrib/libs/cxxsupp/libcxx/src/support/win32/thread_win32.cpp274
-rw-r--r--contrib/libs/libc_compat/include/windows/sys/queue.h631
-rw-r--r--contrib/libs/libc_compat/include/windows/sys/uio.h25
-rw-r--r--contrib/libs/libc_compat/src/windows/sys/uio.c36
-rw-r--r--contrib/libs/libc_compat/stpcpy.c44
-rw-r--r--contrib/libs/libc_compat/strcasestr.c61
-rw-r--r--contrib/libs/libc_compat/strsep.c71
-rw-r--r--contrib/libs/libevent/buffer_iocp.c327
-rw-r--r--contrib/libs/libevent/bufferevent_async.c706
-rw-r--r--contrib/libs/libevent/event_iocp.c294
-rw-r--r--contrib/libs/libevent/evthread_win32.c341
-rw-r--r--contrib/libs/libevent/win32select.c389
-rw-r--r--contrib/libs/libfuzzer/standalone/StandaloneFuzzTargetMain.c46
-rw-r--r--contrib/libs/poco/Foundation/src/EventLogChannel.cpp327
-rw-r--r--contrib/libs/poco/Foundation/src/WindowsConsoleChannel.cpp302
-rw-r--r--contrib/libs/poco/Foundation/src/pocomsg.h158
-rw-r--r--contrib/libs/postgresql/src/backend/port/win32/crashdump.c183
-rw-r--r--contrib/libs/postgresql/src/backend/port/win32/signal.c344
-rw-r--r--contrib/libs/postgresql/src/backend/port/win32/socket.c700
-rw-r--r--contrib/libs/postgresql/src/backend/port/win32/timer.c121
-rw-r--r--contrib/libs/postgresql/src/backend/port/win32_sema.c235
-rw-r--r--contrib/libs/postgresql/src/backend/port/win32_shmem.c607
-rw-r--r--contrib/libs/postgresql/src/include/port/win32/arpa/inet.h3
-rw-r--r--contrib/libs/postgresql/src/include/port/win32/grp.h1
-rw-r--r--contrib/libs/postgresql/src/include/port/win32/netdb.h1
-rw-r--r--contrib/libs/postgresql/src/include/port/win32/netinet/in.h3
-rw-r--r--contrib/libs/postgresql/src/include/port/win32/pwd.h3
-rw-r--r--contrib/libs/postgresql/src/include/port/win32/sys/socket.h33
-rw-r--r--contrib/libs/postgresql/src/include/port/win32/sys/wait.h3
-rw-r--r--contrib/libs/postgresql/src/include/port/win32_msvc/dirent.h34
-rw-r--r--contrib/libs/postgresql/src/include/port/win32_msvc/sys/file.h1
-rw-r--r--contrib/libs/postgresql/src/include/port/win32_msvc/sys/param.h1
-rw-r--r--contrib/libs/postgresql/src/include/port/win32_msvc/sys/time.h1
-rw-r--r--contrib/libs/postgresql/src/include/port/win32_msvc/unistd.h1
-rw-r--r--contrib/libs/postgresql/src/include/port/win32_msvc/utime.h3
-rw-r--r--contrib/libs/postgresql/src/port/dirmod.c355
-rw-r--r--contrib/libs/postgresql/src/port/dlopen.c145
-rw-r--r--contrib/libs/postgresql/src/port/getaddrinfo.c396
-rw-r--r--contrib/libs/postgresql/src/port/getopt.c136
-rw-r--r--contrib/libs/postgresql/src/port/getrusage.c110
-rw-r--r--contrib/libs/postgresql/src/port/gettimeofday.c118
-rw-r--r--contrib/libs/postgresql/src/port/inet_aton.c149
-rw-r--r--contrib/libs/postgresql/src/port/kill.c97
-rw-r--r--contrib/libs/postgresql/src/port/open.c216
-rw-r--r--contrib/libs/postgresql/src/port/pread.c58
-rw-r--r--contrib/libs/postgresql/src/port/pwrite.c55
-rw-r--r--contrib/libs/postgresql/src/port/pwritev.c58
-rw-r--r--contrib/libs/postgresql/src/port/system.c117
-rw-r--r--contrib/libs/postgresql/src/port/win32env.c163
-rw-r--r--contrib/libs/postgresql/src/port/win32error.c208
-rw-r--r--contrib/libs/postgresql/src/port/win32security.c178
-rw-r--r--contrib/libs/postgresql/src/port/win32setlocale.c193
-rw-r--r--contrib/libs/postgresql/src/port/win32stat.c327
-rw-r--r--contrib/libs/pthreads_win32/config.h157
-rw-r--r--contrib/libs/pthreads_win32/include/pthread.h10
-rw-r--r--contrib/libs/pthreads_win32/include/sched.h10
-rw-r--r--contrib/libs/pthreads_win32/need_errno.h145
-rw-r--r--contrib/libs/pthreads_win32/pthread.h1416
-rw-r--r--contrib/libs/pthreads_win32/sched.h183
71 files changed, 12860 insertions, 0 deletions
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/net/windows/Net.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/net/windows/Net.cpp
new file mode 100644
index 0000000000..b1ec65b5df
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/net/windows/Net.cpp
@@ -0,0 +1,48 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <WinSock2.h>
+#include <cassert>
+#include <aws/core/utils/logging/LogMacros.h>
+
+namespace Aws
+{
+ namespace Net
+ {
+ static bool s_globalNetworkInitiated = false;
+
+ bool IsNetworkInitiated()
+ {
+ return s_globalNetworkInitiated;
+ }
+
+ void InitNetwork()
+ {
+ if (IsNetworkInitiated())
+ {
+ return;
+ }
+ // Initialize Winsock( requires winsock version 2.2)
+ WSADATA wsaData;
+ int result = WSAStartup(MAKEWORD(2, 2), &wsaData);
+ assert(result == NO_ERROR);
+ if (result != NO_ERROR)
+ {
+ AWS_LOGSTREAM_ERROR("WinSock2", "Failed to Initate WinSock2.2");
+ s_globalNetworkInitiated = false;
+ }
+ else
+ {
+ s_globalNetworkInitiated = true;
+ }
+ }
+
+ void CleanupNetwork()
+ {
+ WSACleanup();
+ s_globalNetworkInitiated = false;
+ }
+ }
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/net/windows/SimpleUDP.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/net/windows/SimpleUDP.cpp
new file mode 100644
index 0000000000..f6e36077ec
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/net/windows/SimpleUDP.cpp
@@ -0,0 +1,263 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <WinSock2.h>
+#include <Ws2ipdef.h>
+#include <Ws2tcpip.h>
+#include <cassert>
+#include <aws/core/net/SimpleUDP.h>
+#include <aws/core/utils/logging/LogMacros.h>
+namespace Aws
+{
+ namespace Net
+ {
+ static const char ALLOC_TAG[] = "SimpleUDP";
+ static const char IPV4_LOOP_BACK_ADDRESS[] = "127.0.0.1";
+ static const char IPV6_LOOP_BACK_ADDRESS[] = "::1";
+
+ static inline bool IsValidIPAddress(const char* ip, int addressFamily/*AF_INET or AF_INET6*/)
+ {
+ char buffer[128];
+ return inet_pton(addressFamily, ip, (void*)buffer) == 1 ?true :false;
+ }
+
+ static bool GetASockAddrFromHostName(const char* hostName, void* sockAddrBuffer, size_t& addrLength, int& addressFamily)
+ {
+ struct addrinfo hints, *res;
+
+ memset(&hints, 0, sizeof(hints));
+
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ if (getaddrinfo(hostName, nullptr, &hints, &res))
+ {
+ return false;
+ }
+
+ memcpy(sockAddrBuffer, res->ai_addr, res->ai_addrlen);
+ addrLength = res->ai_addrlen;
+ addressFamily = res->ai_family;
+ freeaddrinfo(res);
+ return true;
+ }
+
+ static sockaddr_in BuildAddrInfoIPV4(const char* hostIP, short port)
+ {
+ sockaddr_in addrinfo {};
+ addrinfo.sin_family = AF_INET;
+ addrinfo.sin_port = htons(port);
+ inet_pton(AF_INET, hostIP, &addrinfo.sin_addr);
+ return addrinfo;
+ }
+
+ static sockaddr_in6 BuildAddrInfoIPV6(const char* hostIP, short port)
+ {
+ sockaddr_in6 addrinfo {};
+ addrinfo.sin6_family = AF_INET6;
+ addrinfo.sin6_port = htons(port);
+ inet_pton(AF_INET6, hostIP, &addrinfo.sin6_addr);
+ return addrinfo;
+ }
+
+ SimpleUDP::SimpleUDP(int addressFamily, size_t sendBufSize, size_t receiveBufSize, bool nonBlocking):
+ m_addressFamily(addressFamily), m_connected(false), m_socket(-1), m_port(0)
+ {
+ CreateSocket(addressFamily, sendBufSize, receiveBufSize, nonBlocking);
+ }
+
+ SimpleUDP::SimpleUDP(bool IPV4, size_t sendBufSize, size_t receiveBufSize, bool nonBlocking) :
+ m_addressFamily(IPV4 ? AF_INET : AF_INET6), m_connected(false), m_socket(-1), m_port(0)
+ {
+ CreateSocket(m_addressFamily, sendBufSize, receiveBufSize, nonBlocking);
+ }
+
+ SimpleUDP::SimpleUDP(const char* host, unsigned short port, size_t sendBufSize, size_t receiveBufSize, bool nonBlocking) :
+ m_addressFamily(AF_INET), m_connected(false), m_socket(-1), m_port(port)
+ {
+ if (IsValidIPAddress(host, AF_INET))
+ {
+ m_addressFamily = AF_INET;
+ m_hostIP = Aws::String(host);
+ }
+ else if (IsValidIPAddress(host, AF_INET6))
+ {
+ m_addressFamily = AF_INET6;
+ m_hostIP = Aws::String(host);
+ }
+ else
+ {
+ char sockAddrBuffer[100];
+ char hostBuffer[100];
+ size_t addrLength = 0;
+ if (GetASockAddrFromHostName(host, (void*)sockAddrBuffer, addrLength, m_addressFamily))
+ {
+ if (m_addressFamily == AF_INET)
+ {
+ struct sockaddr_in* sockaddr = reinterpret_cast<struct sockaddr_in*>(sockAddrBuffer);
+ inet_ntop(m_addressFamily, &(sockaddr->sin_addr), hostBuffer, sizeof(hostBuffer));
+ }
+ else
+ {
+ struct sockaddr_in6* sockaddr = reinterpret_cast<struct sockaddr_in6*>(sockAddrBuffer);
+ inet_ntop(m_addressFamily, &(sockaddr->sin6_addr), hostBuffer, sizeof(hostBuffer));
+ }
+ m_hostIP = Aws::String(hostBuffer);
+ }
+ else
+ {
+ AWS_LOGSTREAM_ERROR(ALLOC_TAG, "Can't retrieve a valid ip address based on provided host: " << host);
+ }
+ }
+ CreateSocket(m_addressFamily, sendBufSize, receiveBufSize, nonBlocking);
+ }
+
+ SimpleUDP::~SimpleUDP()
+ {
+ closesocket(GetUnderlyingSocket());
+ }
+
+ void SimpleUDP::CreateSocket(int addressFamily, size_t sendBufSize, size_t receiveBufSize, bool nonBlocking)
+ {
+ SOCKET sock = socket(addressFamily, SOCK_DGRAM, IPPROTO_UDP);
+ assert(sock != INVALID_SOCKET);
+
+ // Try to set sock to nonblocking mode.
+ if (nonBlocking)
+ {
+ u_long enable = 1;
+ ioctlsocket(sock, FIONBIO, &enable);
+ }
+
+ // if sendBufSize is not zero, try to set send buffer size
+ if (sendBufSize)
+ {
+ int ret = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, reinterpret_cast<const char*>(&sendBufSize), sizeof(sendBufSize));
+ if (ret)
+ {
+ AWS_LOGSTREAM_WARN(ALLOC_TAG, "Failed to set UDP send buffer size to " << sendBufSize << " for socket " << sock << " error code: " << WSAGetLastError());
+ }
+ assert(ret == 0);
+ }
+
+ // if receiveBufSize is not zero, try to set receive buffer size
+ if (receiveBufSize)
+ {
+ int ret = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, reinterpret_cast<const char*>(&receiveBufSize), sizeof(receiveBufSize));
+ if (ret)
+ {
+ AWS_LOGSTREAM_WARN(ALLOC_TAG, "Failed to set UDP receive buffer size to " << receiveBufSize << " for socket " << sock << " error code: " << WSAGetLastError());
+ }
+ assert(ret == 0);
+ }
+
+ SetUnderlyingSocket(static_cast<int>(sock));
+ }
+
+ int SimpleUDP::Connect(const sockaddr* address, size_t addressLength)
+ {
+ int ret = connect(GetUnderlyingSocket(), address, static_cast<socklen_t>(addressLength));
+ m_connected = ret ? false : true;
+ return ret;
+ }
+
+ int SimpleUDP::ConnectToHost(const char* hostIP, unsigned short port) const
+ {
+ int ret;
+ if (m_addressFamily == AF_INET6)
+ {
+ sockaddr_in6 addrinfo = BuildAddrInfoIPV6(hostIP, port);
+ ret = connect(GetUnderlyingSocket(), reinterpret_cast<sockaddr*>(&addrinfo), sizeof(sockaddr_in6));
+ }
+ else
+ {
+ sockaddr_in addrinfo = BuildAddrInfoIPV4(hostIP, port);
+ ret = connect(GetUnderlyingSocket(), reinterpret_cast<sockaddr*>(&addrinfo), sizeof(sockaddr_in));
+ }
+ m_connected = ret ? false : true;
+ return ret;
+ }
+
+ int SimpleUDP::ConnectToLocalHost(unsigned short port) const
+ {
+ if (m_addressFamily == AF_INET6)
+ {
+ return ConnectToHost(IPV6_LOOP_BACK_ADDRESS, port);
+ }
+ else
+ {
+ return ConnectToHost(IPV4_LOOP_BACK_ADDRESS, port);
+ }
+ }
+
+ int SimpleUDP::Bind(const sockaddr* address, size_t addressLength) const
+ {
+ return bind(GetUnderlyingSocket(), address, static_cast<socklen_t>(addressLength));
+ }
+
+ int SimpleUDP::BindToLocalHost(unsigned short port) const
+ {
+ if (m_addressFamily == AF_INET6)
+ {
+ sockaddr_in6 addrinfo = BuildAddrInfoIPV6(IPV6_LOOP_BACK_ADDRESS, port);
+ return bind(GetUnderlyingSocket(), reinterpret_cast<sockaddr*>(&addrinfo), sizeof(sockaddr_in6));
+ }
+ else
+ {
+ sockaddr_in addrinfo = BuildAddrInfoIPV4(IPV4_LOOP_BACK_ADDRESS, port);
+ return bind(GetUnderlyingSocket(), reinterpret_cast<sockaddr*>(&addrinfo), sizeof(sockaddr_in));
+ }
+ }
+
+ int SimpleUDP::SendData(const uint8_t* data, size_t dataLen) const
+ {
+ if (!m_connected)
+ {
+ ConnectToHost(m_hostIP.c_str(), m_port);
+ }
+ return send(GetUnderlyingSocket(), reinterpret_cast<const char*>(data), static_cast<int>(dataLen), 0);
+ }
+
+ int SimpleUDP::SendDataTo(const sockaddr* address, size_t addressLength, const uint8_t* data, size_t dataLen) const
+ {
+ if (m_connected)
+ {
+ return send(GetUnderlyingSocket(), reinterpret_cast<const char*>(data), static_cast<int>(dataLen), 0);
+ }
+ else
+ {
+ return sendto(GetUnderlyingSocket(), reinterpret_cast<const char*>(data), static_cast<int>(dataLen), 0, address, static_cast<socklen_t>(addressLength));
+ }
+ }
+
+ int SimpleUDP::SendDataToLocalHost(const uint8_t* data, size_t dataLen, unsigned short port) const
+ {
+ if (m_connected)
+ {
+ return send(GetUnderlyingSocket(), reinterpret_cast<const char*>(data), static_cast<int>(dataLen), 0);
+ }
+ else if (m_addressFamily == AF_INET6)
+ {
+ sockaddr_in6 addrinfo = BuildAddrInfoIPV6(IPV6_LOOP_BACK_ADDRESS, port);
+ return sendto(GetUnderlyingSocket(), reinterpret_cast<const char*>(data), static_cast<int>(dataLen), 0, reinterpret_cast<sockaddr*>(&addrinfo), sizeof(sockaddr_in6));
+ }
+ else
+ {
+ sockaddr_in addrinfo = BuildAddrInfoIPV4(IPV4_LOOP_BACK_ADDRESS, port);
+ return sendto(GetUnderlyingSocket(), reinterpret_cast<const char*>(data), static_cast<int>(dataLen), 0, reinterpret_cast<sockaddr*>(&addrinfo), sizeof(sockaddr_in));
+ }
+ }
+
+ int SimpleUDP::ReceiveData(uint8_t* buffer, size_t bufferLen) const
+ {
+ return recv(GetUnderlyingSocket(), reinterpret_cast<char*>(buffer), static_cast<int>(bufferLen), 0);
+ }
+
+
+ int SimpleUDP::ReceiveDataFrom(sockaddr* address, size_t* addressLength, uint8_t* buffer, size_t bufferLen) const
+ {
+ return recvfrom(GetUnderlyingSocket(), reinterpret_cast<char*>(buffer), static_cast<int>(bufferLen), 0, address, reinterpret_cast<socklen_t*>(addressLength));
+ }
+ }
+}
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/windows/Environment.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/windows/Environment.cpp
new file mode 100644
index 0000000000..d8b5403123
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/windows/Environment.cpp
@@ -0,0 +1,37 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/platform/Environment.h>
+
+#include <stdio.h>
+#include <utility>
+
+namespace Aws
+{
+namespace Environment
+{
+
+/*
+using std::getenv generates a warning on windows so we use _dupenv_s instead. The character array returned by this function is our responsibility to clean up, so rather than returning raw strings
+that would need to be manually freed in all the client functions, just copy it into a Aws::String instead, freeing it here.
+*/
+Aws::String GetEnv(const char *variableName)
+{
+ char* variableValue = nullptr;
+ std::size_t valueSize = 0;
+ auto queryResult = _dupenv_s(&variableValue, &valueSize, variableName);
+
+ Aws::String result;
+ if(queryResult == 0 && variableValue != nullptr && valueSize > 0)
+ {
+ result.assign(variableValue, valueSize - 1); // don't copy the c-string terminator byte
+ free(variableValue);
+ }
+
+ return result;
+}
+
+} // namespace Environment
+} // namespace Aws
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/windows/FileSystem.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/windows/FileSystem.cpp
new file mode 100644
index 0000000000..2ea82de6f8
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/windows/FileSystem.cpp
@@ -0,0 +1,336 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+#include <aws/core/platform/FileSystem.h>
+
+#include <aws/core/platform/Environment.h>
+#include <aws/core/utils/logging/LogMacros.h>
+#include <aws/core/utils/StringUtils.h>
+#include <cassert>
+#include <iostream>
+#include <Userenv.h>
+
+#pragma warning( disable : 4996)
+
+using namespace Aws::Utils;
+namespace Aws
+{
+namespace FileSystem
+{
+
+static const char* FILE_SYSTEM_UTILS_LOG_TAG = "FileSystem";
+
+/**
+ * See
+ * https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
+ * to understand how could we pass long path (over 260 chars) to WinAPI
+ */
+static inline Aws::WString ToLongPath(const Aws::WString& path)
+{
+ if (path.size() > MAX_PATH - 12/*8.3 file name*/)
+ {
+ return L"\\\\?\\" + path;
+ }
+ return path;
+}
+
+class User32Directory : public Directory
+{
+public:
+ User32Directory(const Aws::String& path, const Aws::String& relativePath) : Directory(path, relativePath), m_find(INVALID_HANDLE_VALUE), m_lastError(0)
+ {
+ WIN32_FIND_DATAW ffd;
+ AWS_LOGSTREAM_TRACE(FILE_SYSTEM_UTILS_LOG_TAG, "Entering directory " << m_directoryEntry.path);
+
+ m_find = FindFirstFileW(ToLongPath(Aws::Utils::StringUtils::ToWString(m_directoryEntry.path.c_str())).c_str(), &ffd);
+ if (m_find != INVALID_HANDLE_VALUE)
+ {
+ m_directoryEntry = ParseFileInfo(ffd, false);
+ FindClose(m_find);
+ auto seachPath = Join(m_directoryEntry.path, "*");
+ m_find = FindFirstFileW(ToLongPath(Aws::Utils::StringUtils::ToWString(seachPath.c_str())).c_str(), &m_ffd);
+ }
+ else
+ {
+ AWS_LOGSTREAM_ERROR(FILE_SYSTEM_UTILS_LOG_TAG, "Could not load directory " << m_directoryEntry.path << " with error code " << GetLastError());
+ }
+ }
+
+ ~User32Directory()
+ {
+ if (m_find != INVALID_HANDLE_VALUE)
+ {
+ FindClose(m_find);
+ }
+ }
+
+ operator bool() const override { return m_directoryEntry.operator bool() && m_find != INVALID_HANDLE_VALUE; }
+
+ DirectoryEntry Next() override
+ {
+ assert(m_find != INVALID_HANDLE_VALUE);
+ DirectoryEntry entry;
+ bool invalidEntry = true;
+
+ while(invalidEntry && !m_lastError)
+ {
+ //due to the way the FindFirstFile api works,
+ //the first entry will already be loaded by the time we get here.
+ entry = ParseFileInfo(m_ffd, true);
+
+ Aws::String fileName = Aws::Utils::StringUtils::FromWString(m_ffd.cFileName);
+ if (fileName != ".." && fileName != ".")
+ {
+ AWS_LOGSTREAM_TRACE(FILE_SYSTEM_UTILS_LOG_TAG, "Found entry " << entry.path);
+ invalidEntry = false;
+ }
+ else
+ {
+ entry.fileType = FileType::None;
+ AWS_LOGSTREAM_TRACE(FILE_SYSTEM_UTILS_LOG_TAG, "Skipping . or .. entries.");
+ }
+
+ if(!FindNextFileW(m_find, &m_ffd))
+ {
+ m_lastError = GetLastError();
+ AWS_LOGSTREAM_ERROR(FILE_SYSTEM_UTILS_LOG_TAG, "Could not fetch next entry from " << m_directoryEntry.path << " with error code " << m_lastError);
+ break;
+ }
+ }
+
+ return entry;
+ }
+
+private:
+ DirectoryEntry ParseFileInfo(WIN32_FIND_DATAW& ffd, bool computePath)
+ {
+ DirectoryEntry entry;
+ LARGE_INTEGER fileSize;
+ fileSize.HighPart = ffd.nFileSizeHigh;
+ fileSize.LowPart = ffd.nFileSizeLow;
+ entry.fileSize = static_cast<int64_t>(fileSize.QuadPart);
+
+ if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ entry.fileType = FileType::Directory;
+ }
+ else
+ {
+ entry.fileType = FileType::File;
+ }
+
+ if(computePath)
+ {
+ entry.path = Join(m_directoryEntry.path, Aws::Utils::StringUtils::FromWString(ffd.cFileName));
+ entry.relativePath = m_directoryEntry.relativePath.empty() ? Aws::Utils::StringUtils::FromWString(ffd.cFileName) : Join(m_directoryEntry.relativePath, Aws::Utils::StringUtils::FromWString(ffd.cFileName));
+ }
+ else
+ {
+ entry.path = m_directoryEntry.path;
+ entry.relativePath = m_directoryEntry.relativePath;
+ }
+
+ return entry;
+ }
+
+ HANDLE m_find;
+ WIN32_FIND_DATAW m_ffd;
+ DWORD m_lastError;
+};
+
+Aws::String GetHomeDirectory()
+{
+ static const char* HOME_DIR_ENV_VAR = "USERPROFILE";
+
+ AWS_LOGSTREAM_TRACE(FILE_SYSTEM_UTILS_LOG_TAG, "Checking " << HOME_DIR_ENV_VAR << " for the home directory.");
+ Aws::String homeDir = Aws::Environment::GetEnv(HOME_DIR_ENV_VAR);
+ AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "Environment value for variable " << HOME_DIR_ENV_VAR << " is " << homeDir);
+ if(homeDir.empty())
+ {
+ AWS_LOGSTREAM_WARN(FILE_SYSTEM_UTILS_LOG_TAG, "Home dir not stored in environment, trying to fetch manually from the OS.");
+ HANDLE hToken;
+
+ if (OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &hToken))
+ {
+ DWORD len = MAX_PATH;
+ WCHAR path[MAX_PATH];
+ if (GetUserProfileDirectoryW(hToken, path, &len))
+ {
+ homeDir = Aws::Utils::StringUtils::FromWString(path);
+ }
+ CloseHandle(hToken);
+ }
+
+ AWS_LOGSTREAM_INFO(FILE_SYSTEM_UTILS_LOG_TAG, "Pulled " << homeDir << " as home directory from the OS.");
+ }
+
+ Aws::String retVal = (homeDir.size() > 0) ? Aws::Utils::StringUtils::Trim(homeDir.c_str()) : "";
+
+ if (!retVal.empty())
+ {
+ if (retVal.at(retVal.length() - 1) != Aws::FileSystem::PATH_DELIM)
+ {
+ retVal += Aws::FileSystem::PATH_DELIM;
+ }
+ }
+
+ return retVal;
+}
+
+Aws::String GetExecutableDirectory()
+{
+ static const unsigned long long bufferSize = 256;
+ WCHAR buffer[bufferSize];
+
+ memset(buffer, 0, sizeof(buffer));
+
+ if (GetModuleFileNameW(nullptr, buffer, static_cast<DWORD>(sizeof(buffer))))
+ {
+ Aws::String bufferStr(Aws::Utils::StringUtils::FromWString(buffer));
+ auto fileNameStart = bufferStr.find_last_of(PATH_DELIM);
+ if (fileNameStart != std::string::npos)
+ {
+ bufferStr = bufferStr.substr(0, fileNameStart);
+ }
+
+ return bufferStr;
+ }
+
+ return "";
+}
+
+bool CreateDirectoryIfNotExists(const char* path, bool createParentDirs)
+{
+ Aws::String directoryName = path;
+ AWS_LOGSTREAM_INFO(FILE_SYSTEM_UTILS_LOG_TAG, "Creating directory " << directoryName);
+
+ // Create intermediate directories or create the target directory once.
+ for (size_t i = createParentDirs ? 0 : directoryName.size() - 1; i < directoryName.size(); i++)
+ {
+ // Create the intermediate directory if we find a delimiter and the delimiter is not the first char, or if this is the target directory.
+ if (i != 0 && (directoryName[i] == FileSystem::PATH_DELIM || i == directoryName.size() - 1))
+ {
+ // the last delimeter can be removed safely.
+ if (directoryName[i] == FileSystem::PATH_DELIM)
+ {
+ directoryName[i] = '\0';
+ }
+ if (CreateDirectoryW(ToLongPath(StringUtils::ToWString(directoryName.c_str())).c_str(), nullptr))
+ {
+ AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "Creation of directory " << directoryName.c_str() << " succeeded.");
+ }
+ else
+ {
+ DWORD errorCode = GetLastError();
+ if (errorCode != ERROR_ALREADY_EXISTS && errorCode != NO_ERROR) // in vs2013 the errorCode is NO_ERROR
+ {
+ AWS_LOGSTREAM_ERROR(FILE_SYSTEM_UTILS_LOG_TAG, " Creation of directory " << directoryName.c_str() << " returned code: " << errorCode);
+ return false;
+ }
+ AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, " Creation of directory " << directoryName.c_str() << " returned code: " << errorCode);
+ }
+ // Restore the path. We are good even if we didn't change that char to '\0', because we are ready to return.
+ directoryName[i] = FileSystem::PATH_DELIM;
+ }
+ }
+ return true;
+}
+
+bool RemoveFileIfExists(const char* path)
+{
+ AWS_LOGSTREAM_INFO(FILE_SYSTEM_UTILS_LOG_TAG, "Deleting file: " << path);
+
+ if (DeleteFileW(ToLongPath(Aws::Utils::StringUtils::ToWString(path)).c_str()))
+ {
+ AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "Successfully deleted file: " << path);
+ return true;
+ }
+ else
+ {
+ DWORD errorCode = GetLastError();
+ AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "Deletion of file: " << path << " Returned error code: " << errorCode);
+ return errorCode == ERROR_FILE_NOT_FOUND;
+ }
+}
+
+bool RelocateFileOrDirectory(const char* from, const char* to)
+{
+ AWS_LOGSTREAM_INFO(FILE_SYSTEM_UTILS_LOG_TAG, "Moving file at " << from << " to " << to);
+
+ if(MoveFileW(ToLongPath(Aws::Utils::StringUtils::ToWString(from)).c_str(), Aws::Utils::StringUtils::ToWString(to).c_str()))
+ {
+ AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "The moving operation of file at " << from << " to " << to << " Succeeded.");
+ return true;
+ }
+ else
+ {
+ int errorCode = GetLastError();
+ AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "The moving operation of file at " << from << " to " << to << " Returned error code of " << errorCode);
+ return false;
+ }
+}
+
+bool RemoveDirectoryIfExists(const char* path)
+{
+ AWS_LOGSTREAM_INFO(FILE_SYSTEM_UTILS_LOG_TAG, "Removing directory at " << path);
+
+ if(RemoveDirectoryW(ToLongPath(Aws::Utils::StringUtils::ToWString(path)).c_str()))
+ {
+ AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "The remove operation of file at " << path << " Succeeded.");
+ return true;
+ }
+ else
+ {
+ int errorCode = GetLastError();
+ if (errorCode == ERROR_DIR_NOT_EMPTY)
+ {
+ AWS_LOGSTREAM_ERROR(FILE_SYSTEM_UTILS_LOG_TAG, "The remove operation of file at " << path << " failed. with error code because it was not empty.");
+ }
+
+ else if(errorCode == ERROR_DIRECTORY)
+ {
+ AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "The deletion of directory at " << path << " failed because it doesn't exist.");
+ return true;
+
+ }
+
+ AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "The remove operation of file at " << path << " failed. with error code " << errorCode);
+ return false;
+ }
+}
+
+Aws::String CreateTempFilePath()
+{
+#ifdef _MSC_VER
+#pragma warning(disable: 4996) // _CRT_SECURE_NO_WARNINGS
+#endif
+ char s_tempName[L_tmpnam_s+1];
+
+ /*
+ Prior to VS 2014, tmpnam/tmpnam_s generated root level files ("\filename") which were not appropriate for our usage, so for the windows version, we prepended a '.' to make it a
+ tempfile in the current directory. Starting with VS2014, the behavior of tmpnam/tmpnam_s was changed to be a full, valid filepath based on the
+ current user ("C:\Users\username\AppData\Local\Temp\...").
+
+ See the tmpnam section in http://blogs.msdn.com/b/vcblog/archive/2014/06/18/crt-features-fixes-and-breaking-changes-in-visual-studio-14-ctp1.aspx
+ for more details.
+ */
+
+#if _MSC_VER >= 1900
+ tmpnam_s(s_tempName, L_tmpnam_s);
+#else
+ s_tempName[0] = '.';
+ tmpnam_s(s_tempName + 1, L_tmpnam_s);
+#endif // _MSC_VER
+
+
+ return s_tempName;
+}
+
+Aws::UniquePtr<Directory> OpenDirectory(const Aws::String& path, const Aws::String& relativePath)
+{
+ return Aws::MakeUnique<User32Directory>(FILE_SYSTEM_UTILS_LOG_TAG, path, relativePath);
+}
+
+} // namespace FileSystem
+} // namespace Aws
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/windows/OSVersionInfo.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/windows/OSVersionInfo.cpp
new file mode 100644
index 0000000000..0180f7fbf6
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/windows/OSVersionInfo.cpp
@@ -0,0 +1,138 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/platform/OSVersionInfo.h>
+#include <aws/core/utils/StringUtils.h>
+#include <aws/core/utils/memory/stl/AWSStringStream.h>
+
+#include <iomanip>
+
+#pragma warning(disable: 4996)
+#include <windows.h>
+#include <stdio.h>
+namespace Aws
+{
+namespace OSVersionInfo
+{
+
+Aws::String GetSysCommandOutput(const char* command)
+{
+ Aws::String outputStr;
+ FILE* outputStream;
+ const int maxBufferSize = 256;
+ char outputBuffer[maxBufferSize];
+
+ outputStream = _popen(command, "r");
+
+ if (outputStream)
+ {
+ while (!feof(outputStream))
+ {
+ if (fgets(outputBuffer, maxBufferSize, outputStream) != nullptr)
+ {
+ outputStr.append(outputBuffer);
+ }
+ }
+
+ _pclose(outputStream);
+
+ return Aws::Utils::StringUtils::Trim(outputStr.c_str());
+ }
+
+ return {};
+}
+
+Aws::String ComputeOSVersionString()
+{
+ // With the release of Windows 8.1, the behavior of the GetVersionEx API has changed in the value it will return for the operating system version.
+ // The value returned by the GetVersionEx function now depends on how the application is manifested.
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724451%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
+ //
+ // This only works when the application is manifested for Windows 8.1 or 10, which we don't actually care about.
+ // Also, this will cause build headaches for folks not building with VS2015, and is overall an unusable API for us.
+ // The following is the least painful but most reliable hack I can come up with.
+ //
+ // From this article: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724429.aspx
+ // we will do the following:
+ //
+ // To obtain the full version number for the operating system, call the GetFileVersionInfo function on one of the system DLLs, such as Kernel32.dll,
+ // then call VerQueryValue to obtain the \\StringFileInfo\\<lang><codepage>\\ProductVersion subblock of the file version information.
+ //
+ Aws::StringStream ss;
+ ss << "Windows/";
+
+ DWORD uselessParameter(0);
+ static const char* FILE_TO_CHECK = "Kernel32.dll";
+ DWORD fileVersionSize = GetFileVersionInfoSizeA(FILE_TO_CHECK, &uselessParameter);
+ void* blob = Aws::Malloc("OSVersionInfo", static_cast<size_t>(fileVersionSize));
+ bool versionFound(false);
+
+ if (GetFileVersionInfoA(FILE_TO_CHECK, 0, fileVersionSize, blob))
+ {
+ struct LANGANDCODEPAGE {
+ WORD wLanguage;
+ WORD wCodePage;
+ } *lpTranslate;
+
+ UINT sizeOfCodePage(0);
+
+ if (VerQueryValueA(blob, "\\VarFileInfo\\Translation", (LPVOID*)&lpTranslate, &sizeOfCodePage))
+ {
+ //we don't actually care which language pack we get, they should all have the same windows version attached.
+ Aws::StringStream codePageSS;
+ codePageSS << "\\StringFileInfo\\";
+ codePageSS << std::setfill('0') << std::setw(4) << std::nouppercase << std::hex << lpTranslate[0].wLanguage;
+ codePageSS << std::setfill('0') << std::setw(4) << std::nouppercase << std::hex << lpTranslate[0].wCodePage;
+ codePageSS << "\\ProductVersion";
+
+ void* subBlock(nullptr);
+ UINT subBlockSize(0);
+
+ if (VerQueryValueA(blob, codePageSS.str().c_str(), &subBlock, &subBlockSize))
+ {
+ ss << static_cast<const char*>(subBlock);
+ versionFound = true;
+ }
+ }
+ }
+
+ Aws::Free(blob);
+
+ if (!versionFound)
+ {
+ ss << "Unknown Version";
+ }
+
+
+
+ SYSTEM_INFO sysInfo;
+ ZeroMemory(&sysInfo, sizeof(SYSTEM_INFO));
+ GetSystemInfo(&sysInfo);
+
+ switch (sysInfo.wProcessorArchitecture)
+ {
+ //PROCESSOR_ARCHITECTURE_AMD64
+ case 0x09:
+ ss << " AMD64";
+ break;
+ //PROCESSOR_ARCHITECTURE_IA64
+ case 0x06:
+ ss << " IA64";
+ break;
+ //PROCESSOR_ARCHITECTURE_INTEL
+ case 0x00:
+ ss << " x86";
+ break;
+ default:
+ ss << " Unknown Processor Architecture";
+ break;
+ }
+
+ return ss.str();
+}
+
+
+} // namespace OSVersionInfo
+} // namespace Aws
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/windows/Security.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/windows/Security.cpp
new file mode 100644
index 0000000000..fbf9a4e679
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/windows/Security.cpp
@@ -0,0 +1,21 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/platform/Security.h>
+
+#include <windows.h>
+
+namespace Aws
+{
+namespace Security
+{
+
+void SecureMemClear(unsigned char *data, size_t length)
+{
+ SecureZeroMemory(data, length);
+}
+
+} // namespace Security
+} // namespace Aws
diff --git a/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/windows/Time.cpp b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/windows/Time.cpp
new file mode 100644
index 0000000000..e186d21c81
--- /dev/null
+++ b/contrib/libs/aws-sdk-cpp/aws-cpp-sdk-core/source/platform/windows/Time.cpp
@@ -0,0 +1,31 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/core/platform/Time.h>
+
+#include <time.h>
+
+namespace Aws
+{
+namespace Time
+{
+
+time_t TimeGM(struct tm* const t)
+{
+ return _mkgmtime(t);
+}
+
+void LocalTime(tm* t, std::time_t time)
+{
+ localtime_s(t, &time);
+}
+
+void GMTime(tm* t, std::time_t time)
+{
+ gmtime_s(t, &time);
+}
+
+} // namespace Time
+} // namespace Aws
diff --git a/contrib/libs/crcutil/multiword_64_64_cl_i386_mmx.cc b/contrib/libs/crcutil/multiword_64_64_cl_i386_mmx.cc
new file mode 100644
index 0000000000..af7352aa46
--- /dev/null
+++ b/contrib/libs/crcutil/multiword_64_64_cl_i386_mmx.cc
@@ -0,0 +1,304 @@
+// Copyright 2010 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Implements 64-bit multiword CRC for Microsoft and Intel compilers
+// using MMX instructions (i386).
+
+#include "generic_crc.h"
+
+#if CRCUTIL_USE_ASM && HAVE_I386 && HAVE_MMX && defined(_MSC_VER)
+
+namespace crcutil {
+
+#define CRC_WORD_MMX() \
+ __asm pxor BUF0, CRC0 \
+ __asm movd TMP0, BUF0 \
+ __asm psrlq BUF0, 32 \
+ __asm movzx TEMP, TMP0L \
+ __asm shr TMP0, 8 \
+ __asm movq CRC0, [TABLE + TEMP * 8] \
+ __asm movzx TEMP, TMP0L \
+ __asm shr TMP0, 8 \
+ __asm pxor CRC0, [TABLE + TEMP * 8 + 1 * 256 * 8] \
+ __asm movzx TEMP, TMP0L \
+ __asm shr TMP0, 8 \
+ __asm pxor CRC0, [TABLE + TEMP * 8 + 2 * 256 * 8] \
+ __asm pxor CRC0, [TABLE + TMP0 * 8 + 3 * 256 * 8] \
+ __asm movd TMP0, BUF0 \
+ __asm movzx TEMP, TMP0L \
+ __asm shr TMP0, 8 \
+ __asm pxor CRC0, [TABLE + TEMP * 8 + 4 * 256 * 8] \
+ __asm movzx TEMP, TMP0L \
+ __asm shr TMP0, 8 \
+ __asm pxor CRC0, [TABLE + TEMP * 8 + 5 * 256 * 8] \
+ __asm movzx TEMP, TMP0L \
+ __asm shr TMP0, 8 \
+ __asm pxor CRC0, [TABLE + TEMP * 8 + 6 * 256 * 8] \
+ __asm pxor CRC0, [TABLE + TMP0 * 8 + 7 * 256 * 8]
+
+// frame pointer register 'ebp' modified by inline assembly code
+#pragma warning(disable: 4731)
+
+template<> uint64 GenericCrc<uint64, uint64, uint64, 4>::CrcMultiwordI386Mmx(
+ const void *data,
+ size_t bytes,
+ const uint64 &start) const {
+ const uint8 *src = static_cast<const uint8 *>(data);
+ const uint8 *end = src + bytes;
+ uint64 crc0 = start ^ this->Base().Canonize();
+
+ ALIGN_ON_WORD_BOUNDARY_IF_NEEDED(bytes, this, src, end, crc0, uint64);
+ if (src >= end) {
+ return (crc0 ^ this->Base().Canonize());
+ }
+
+#define CRC0 mm0
+#define CRC1 mm1
+#define CRC2 mm2
+#define CRC3 mm3
+#define BUF0 mm4
+#define BUF1 mm5
+#define BUF2 mm6
+#define BUF3 mm7
+#define TMP0 eax
+#define TMP0L al
+#define TMP0H ah
+#define TMP1 ebx
+#define TMP1L bl
+#define TMP1H bh
+#define TMP2 ecx
+#define TMP2L cl
+#define TMP2H ch
+#define TMP3 edx
+#define TMP3L dl
+#define TMP3H dh
+#define TEMP edi
+#define SRC esi
+#define END [esp]
+#define TABLE ebp
+
+
+ const uint64 *interleaved_table_address =
+ &this->crc_word_interleaved_[0][0];
+ const uint64 *word_table_address = &this->crc_word_[0][0];
+
+ __asm {
+ push ebp
+
+ mov TMP0, interleaved_table_address
+
+ movq CRC0, crc0
+ mov SRC, src
+ mov TMP1, end
+ sub TMP1, 2*4*8 - 1
+ cmp SRC, TMP1
+ mov TABLE, word_table_address
+ jae end_main_loop
+
+ push TABLE
+ mov TABLE, TMP0
+ push TMP1
+
+ pxor CRC1, CRC1
+ pxor CRC2, CRC2
+ pxor CRC3, CRC3
+
+ movq BUF0, [SRC]
+ movq BUF1, [SRC + 1 * 8]
+ movq BUF2, [SRC + 2 * 8]
+ movq BUF3, [SRC + 3 * 8]
+
+ main_loop:
+#if HAVE_SSE && CRCUTIL_PREFETCH_WIDTH > 0
+ prefetcht0 [SRC + CRCUTIL_PREFETCH_WIDTH]
+#endif
+ add SRC, 32
+ pxor BUF0, CRC0
+ pxor BUF1, CRC1
+ pxor BUF2, CRC2
+ pxor BUF3, CRC3
+
+ movd TMP0, BUF0
+ psrlq BUF0, 32
+ movd TMP1, BUF1
+ psrlq BUF1, 32
+ movd TMP2, BUF2
+ psrlq BUF2, 32
+ movd TMP3, BUF3
+ psrlq BUF3, 32
+
+ movzx TEMP, TMP0L
+ movq CRC0, [TABLE + TEMP * 8]
+ movzx TEMP, TMP1L
+ movq CRC1, [TABLE + TEMP * 8]
+ movzx TEMP, TMP2L
+ movq CRC2, [TABLE + TEMP * 8]
+ movzx TEMP, TMP3L
+ movq CRC3, [TABLE + TEMP * 8]
+
+ movzx TEMP, TMP0H
+ shr TMP0, 16
+ pxor CRC0, [TABLE + TEMP * 8 + 1 * 256 * 8]
+ movzx TEMP, TMP1H
+ shr TMP1, 16
+ pxor CRC1, [TABLE + TEMP * 8 + 1 * 256 * 8]
+ movzx TEMP, TMP2H
+ shr TMP2, 16
+ pxor CRC2, [TABLE + TEMP * 8 + 1 * 256 * 8]
+ movzx TEMP, TMP3H
+ shr TMP3, 16
+ pxor CRC3, [TABLE + TEMP * 8 + 1 * 256 * 8]
+
+ movzx TEMP, TMP0L
+ shr TMP0, 8
+ pxor CRC0, [TABLE + TEMP * 8 + 2 * 256 * 8]
+ movzx TEMP, TMP1L
+ shr TMP1, 8
+ pxor CRC1, [TABLE + TEMP * 8 + 2 * 256 * 8]
+ movzx TEMP, TMP2L
+ shr TMP2, 8
+ pxor CRC2, [TABLE + TEMP * 8 + 2 * 256 * 8]
+ movzx TEMP, TMP3L
+ shr TMP3, 8
+ pxor CRC3, [TABLE + TEMP * 8 + 2 * 256 * 8]
+
+ pxor CRC0, [TABLE + TMP0 * 8 + 3 * 256 * 8]
+ movd TMP0, BUF0
+ pxor CRC1, [TABLE + TMP1 * 8 + 3 * 256 * 8]
+ movd TMP1, BUF1
+ pxor CRC2, [TABLE + TMP2 * 8 + 3 * 256 * 8]
+ movd TMP2, BUF2
+ pxor CRC3, [TABLE + TMP3 * 8 + 3 * 256 * 8]
+ movd TMP3, BUF3
+
+ movzx TEMP, TMP0L
+ pxor CRC0, [TABLE + TEMP * 8 + 4 * 256 * 8]
+ movzx TEMP, TMP1L
+ pxor CRC1, [TABLE + TEMP * 8 + 4 * 256 * 8]
+ movzx TEMP, TMP2L
+ pxor CRC2, [TABLE + TEMP * 8 + 4 * 256 * 8]
+ movzx TEMP, TMP3L
+ pxor CRC3, [TABLE + TEMP * 8 + 4 * 256 * 8]
+
+ movzx TEMP, TMP0H
+ shr TMP0, 16
+ pxor CRC0, [TABLE + TEMP * 8 + 5 * 256 * 8]
+ movzx TEMP, TMP1H
+ shr TMP1, 16
+ pxor CRC1, [TABLE + TEMP * 8 + 5 * 256 * 8]
+ movzx TEMP, TMP2H
+ shr TMP2, 16
+ pxor CRC2, [TABLE + TEMP * 8 + 5 * 256 * 8]
+ movzx TEMP, TMP3H
+ shr TMP3, 16
+ pxor CRC3, [TABLE + TEMP * 8 + 5 * 256 * 8]
+
+ movzx TEMP, TMP0L
+ shr TMP0, 8
+ pxor CRC0, [TABLE + TEMP * 8 + 6 * 256 * 8]
+ movzx TEMP, TMP1L
+ shr TMP1, 8
+ pxor CRC1, [TABLE + TEMP * 8 + 6 * 256 * 8]
+ movzx TEMP, TMP2L
+ shr TMP2, 8
+ pxor CRC2, [TABLE + TEMP * 8 + 6 * 256 * 8]
+ movzx TEMP, TMP3L
+ shr TMP3, 8
+ pxor CRC3, [TABLE + TEMP * 8 + 6 * 256 * 8]
+
+ pxor CRC0, [TABLE + TMP0 * 8 + 7 * 256 * 8]
+ movq BUF0, [SRC]
+ pxor CRC1, [TABLE + TMP1 * 8 + 7 * 256 * 8]
+ movq BUF1, [SRC + 1 * 8]
+ pxor CRC2, [TABLE + TMP2 * 8 + 7 * 256 * 8]
+ movq BUF2, [SRC + 2 * 8]
+ pxor CRC3, [TABLE + TMP3 * 8 + 7 * 256 * 8]
+ movq BUF3, [SRC + 3 * 8]
+
+ cmp END, SRC
+ ja main_loop
+
+#undef END
+#define END TMP1
+ pop END
+ pop TABLE
+ add SRC, 32
+
+ CRC_WORD_MMX()
+
+ pxor BUF1, CRC1
+ movq BUF0, BUF1
+ CRC_WORD_MMX()
+
+ pxor BUF2, CRC2
+ movq BUF0, BUF2
+ CRC_WORD_MMX()
+
+ pxor BUF3, CRC3
+ movq BUF0, BUF3
+ CRC_WORD_MMX()
+
+ end_main_loop:
+ add END, 2*4*8 - 8
+ cmp SRC, END
+ jae end_word_loop
+
+ word_loop:
+ movq BUF0, [SRC]
+ add SRC, 8
+ CRC_WORD_MMX()
+ cmp END, SRC
+ ja word_loop
+ end_word_loop:
+
+#if 0 // Plain C version is faster?
+ add END, 7
+ cmp SRC, END
+ jae end_byte_loop
+
+ byte_loop:
+ movd TMP0, CRC0
+ movzx TEMP, byte ptr [SRC]
+ movzx TMP0, TMP0L
+ psrlq CRC0, 8
+ xor TEMP, TMP0
+ add SRC, 1
+ pxor CRC0, [TABLE + TEMP*8 + 7*256*8]
+ cmp END, SRC
+ ja byte_loop
+ end_byte_loop:
+#endif
+
+ pop ebp
+
+ mov src, SRC
+ movq crc0, CRC0
+
+ emms
+ }
+
+#if 1
+ // Compute CRC of remaining bytes.
+ for (;src < end; ++src) {
+ CRC_BYTE(this, crc0, *src);
+ }
+#endif
+
+ return (crc0 ^ this->Base().Canonize());
+}
+
+
+} // namespace crcutil
+
+#endif // CRCUTIL_USE_ASM && HAVE_I386 && HAVE_MMX && defined(_MSC_VER)
diff --git a/contrib/libs/cxxsupp/libcxx/src/support/win32/atomic_win32.cpp b/contrib/libs/cxxsupp/libcxx/src/support/win32/atomic_win32.cpp
new file mode 100644
index 0000000000..28cb0722ce
--- /dev/null
+++ b/contrib/libs/cxxsupp/libcxx/src/support/win32/atomic_win32.cpp
@@ -0,0 +1,31 @@
+#include <intrin.h>
+#include <cstdint>
+
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+namespace {
+static const int __msvc_locks_size = 1024;
+volatile long __msvc_locks[__msvc_locks_size];
+
+size_t __msvc_lock_hash(void* __p) {
+ uintptr_t __num = reinterpret_cast<uintptr_t>(__p);
+ return (__num ^ (__num >> 10)) & (__msvc_locks_size - 1);
+}
+}
+
+void __msvc_lock(void* __p) {
+ volatile long& __lock = __msvc_locks[__msvc_lock_hash(__p)];
+ while (_InterlockedExchange(&__lock, 1) == 0) {
+#if defined(_M_ARM) || defined(_M_ARM64)
+ __yield();
+#endif
+ }
+}
+
+void __msvc_unlock(void* __p) {
+ volatile long& __lock = __msvc_locks[__msvc_lock_hash(__p)];
+ _InterlockedExchange(&__lock, 0);
+}
+
+_LIBCPP_END_NAMESPACE_STD \ No newline at end of file
diff --git a/contrib/libs/cxxsupp/libcxx/src/support/win32/locale_win32.cpp b/contrib/libs/cxxsupp/libcxx/src/support/win32/locale_win32.cpp
new file mode 100644
index 0000000000..67f4d1341a
--- /dev/null
+++ b/contrib/libs/cxxsupp/libcxx/src/support/win32/locale_win32.cpp
@@ -0,0 +1,141 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include <locale>
+#include <cstdarg> // va_start, va_end
+#include <memory>
+#include <type_traits>
+
+int __libcpp_vasprintf(char **sptr, const char *__restrict fmt, va_list ap);
+
+using std::__libcpp_locale_guard;
+
+// FIXME: base currently unused. Needs manual work to construct the new locale
+locale_t newlocale( int mask, const char * locale, locale_t /*base*/ )
+{
+ return {_create_locale( LC_ALL, locale ), locale};
+}
+
+decltype(MB_CUR_MAX) MB_CUR_MAX_L( locale_t __l )
+{
+#if defined(_LIBCPP_MSVCRT)
+ return ___mb_cur_max_l_func(__l);
+#else
+ __libcpp_locale_guard __current(__l);
+ return MB_CUR_MAX;
+#endif
+}
+
+lconv *localeconv_l( locale_t &loc )
+{
+ __libcpp_locale_guard __current(loc);
+ lconv *lc = localeconv();
+ if (!lc)
+ return lc;
+ return loc.__store_lconv(lc);
+}
+size_t mbrlen_l( const char *__restrict s, size_t n,
+ mbstate_t *__restrict ps, locale_t loc )
+{
+ __libcpp_locale_guard __current(loc);
+ return mbrlen( s, n, ps );
+}
+size_t mbsrtowcs_l( wchar_t *__restrict dst, const char **__restrict src,
+ size_t len, mbstate_t *__restrict ps, locale_t loc )
+{
+ __libcpp_locale_guard __current(loc);
+ return mbsrtowcs( dst, src, len, ps );
+}
+size_t wcrtomb_l( char *__restrict s, wchar_t wc, mbstate_t *__restrict ps,
+ locale_t loc )
+{
+ __libcpp_locale_guard __current(loc);
+ return wcrtomb( s, wc, ps );
+}
+size_t mbrtowc_l( wchar_t *__restrict pwc, const char *__restrict s,
+ size_t n, mbstate_t *__restrict ps, locale_t loc )
+{
+ __libcpp_locale_guard __current(loc);
+ return mbrtowc( pwc, s, n, ps );
+}
+size_t mbsnrtowcs_l( wchar_t *__restrict dst, const char **__restrict src,
+ size_t nms, size_t len, mbstate_t *__restrict ps, locale_t loc )
+{
+ __libcpp_locale_guard __current(loc);
+ return mbsnrtowcs( dst, src, nms, len, ps );
+}
+size_t wcsnrtombs_l( char *__restrict dst, const wchar_t **__restrict src,
+ size_t nwc, size_t len, mbstate_t *__restrict ps, locale_t loc )
+{
+ __libcpp_locale_guard __current(loc);
+ return wcsnrtombs( dst, src, nwc, len, ps );
+}
+wint_t btowc_l( int c, locale_t loc )
+{
+ __libcpp_locale_guard __current(loc);
+ return btowc( c );
+}
+int wctob_l( wint_t c, locale_t loc )
+{
+ __libcpp_locale_guard __current(loc);
+ return wctob( c );
+}
+
+int snprintf_l(char *ret, size_t n, locale_t loc, const char *format, ...)
+{
+ va_list ap;
+ va_start( ap, format );
+#if defined(_LIBCPP_MSVCRT)
+ // FIXME: Remove usage of internal CRT function and globals.
+ int result = __stdio_common_vsprintf(
+ _CRT_INTERNAL_LOCAL_PRINTF_OPTIONS | _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR,
+ ret, n, format, loc, ap);
+#else
+ __libcpp_locale_guard __current(loc);
+ _LIBCPP_DIAGNOSTIC_PUSH
+ _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wformat-nonliteral")
+ int result = vsnprintf( ret, n, format, ap );
+ _LIBCPP_DIAGNOSTIC_POP
+#endif
+ va_end(ap);
+ return result;
+}
+
+int asprintf_l( char **ret, locale_t loc, const char *format, ... )
+{
+ va_list ap;
+ va_start( ap, format );
+ int result = vasprintf_l( ret, loc, format, ap );
+ va_end(ap);
+ return result;
+}
+int vasprintf_l( char **ret, locale_t loc, const char *format, va_list ap )
+{
+ __libcpp_locale_guard __current(loc);
+ return __libcpp_vasprintf( ret, format, ap );
+}
+
+#if !defined(_LIBCPP_MSVCRT)
+float strtof_l(const char* nptr, char** endptr, locale_t loc) {
+ __libcpp_locale_guard __current(loc);
+ return strtof(nptr, endptr);
+}
+
+long double strtold_l(const char* nptr, char** endptr, locale_t loc) {
+ __libcpp_locale_guard __current(loc);
+ return strtold(nptr, endptr);
+}
+#endif
+
+#if defined(__MINGW32__) && __MSVCRT_VERSION__ < 0x0800
+size_t strftime_l(char *ret, size_t n, const char *format, const struct tm *tm,
+ locale_t loc) {
+ __libcpp_locale_guard __current(loc);
+ return strftime(ret, n, format, tm);
+}
+#endif
diff --git a/contrib/libs/cxxsupp/libcxx/src/support/win32/new_win32.cpp b/contrib/libs/cxxsupp/libcxx/src/support/win32/new_win32.cpp
new file mode 100644
index 0000000000..00eff4abf9
--- /dev/null
+++ b/contrib/libs/cxxsupp/libcxx/src/support/win32/new_win32.cpp
@@ -0,0 +1,28 @@
+#include <atomic>
+#include <new>
+
+namespace std {
+
+void
+__throw_bad_alloc()
+{
+#ifndef _LIBCPP_NO_EXCEPTIONS
+ throw bad_alloc();
+#endif
+}
+
+static std::atomic<std::new_handler> __new_handler;
+
+new_handler
+set_new_handler(new_handler handler) _NOEXCEPT
+{
+ return __new_handler.exchange(handler);
+}
+
+new_handler
+get_new_handler() _NOEXCEPT
+{
+ return __new_handler.load();
+}
+
+} \ No newline at end of file
diff --git a/contrib/libs/cxxsupp/libcxx/src/support/win32/support.cpp b/contrib/libs/cxxsupp/libcxx/src/support/win32/support.cpp
new file mode 100644
index 0000000000..dbec4083cb
--- /dev/null
+++ b/contrib/libs/cxxsupp/libcxx/src/support/win32/support.cpp
@@ -0,0 +1,172 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include <cstdarg> // va_start, va_end
+#include <cstddef> // size_t
+#include <cstdlib> // malloc
+#include <cstdio> // vsprintf, vsnprintf
+#include <cstring> // strcpy, wcsncpy
+#include <cwchar> // mbstate_t
+
+
+// Like sprintf, but when return value >= 0 it returns
+// a pointer to a malloc'd string in *sptr.
+// If return >= 0, use free to delete *sptr.
+int __libcpp_vasprintf( char **sptr, const char *__restrict format, va_list ap )
+{
+ *sptr = NULL;
+ // Query the count required.
+ va_list ap_copy;
+ va_copy(ap_copy, ap);
+ _LIBCPP_DIAGNOSTIC_PUSH
+ _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wformat-nonliteral")
+ int count = vsnprintf( NULL, 0, format, ap_copy );
+ _LIBCPP_DIAGNOSTIC_POP
+ va_end(ap_copy);
+ if (count < 0)
+ return count;
+ size_t buffer_size = static_cast<size_t>(count) + 1;
+ char* p = static_cast<char*>(malloc(buffer_size));
+ if ( ! p )
+ return -1;
+ // If we haven't used exactly what was required, something is wrong.
+ // Maybe bug in vsnprintf. Report the error and return.
+ _LIBCPP_DIAGNOSTIC_PUSH
+ _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wformat-nonliteral")
+ if (vsnprintf(p, buffer_size, format, ap) != count) {
+ _LIBCPP_DIAGNOSTIC_POP
+ free(p);
+ return -1;
+ }
+ // All good. This is returning memory to the caller not freeing it.
+ *sptr = p;
+ return count;
+}
+
+// Returns >= 0: the number of wide characters found in the
+// multi byte sequence src (of src_size_bytes), that fit in the buffer dst
+// (of max_dest_chars elements size). The count returned excludes the
+// null terminator. When dst is NULL, no characters are copied
+// and no "out" parameters are updated.
+// Returns (size_t) -1: an incomplete sequence encountered.
+// Leaves *src pointing the next character to convert or NULL
+// if a null character was converted from *src.
+size_t mbsnrtowcs( wchar_t *__restrict dst, const char **__restrict src,
+ size_t src_size_bytes, size_t max_dest_chars, mbstate_t *__restrict ps )
+{
+ const size_t terminated_sequence = static_cast<size_t>(0);
+ //const size_t invalid_sequence = static_cast<size_t>(-1);
+ const size_t incomplete_sequence = static_cast< size_t>(-2);
+
+ size_t dest_converted = 0;
+ size_t source_converted = 0;
+ size_t source_remaining = src_size_bytes;
+ size_t result = 0;
+ bool have_result = false;
+
+ // If dst is null then max_dest_chars should be ignored according to the
+ // standard. Setting max_dest_chars to a large value has this effect.
+ if (!dst)
+ max_dest_chars = static_cast<size_t>(-1);
+
+ while ( source_remaining ) {
+ if ( dst && dest_converted >= max_dest_chars )
+ break;
+ // Converts one multi byte character.
+ // if result > 0, it's the size in bytes of that character.
+ // othewise if result is zero it indicates the null character has been found.
+ // otherwise it's an error and errno may be set.
+ size_t char_size = mbrtowc( dst ? dst + dest_converted : NULL, *src + source_converted, source_remaining, ps );
+ // Don't do anything to change errno from here on.
+ if ( char_size > 0 ) {
+ source_remaining -= char_size;
+ source_converted += char_size;
+ ++dest_converted;
+ continue;
+ }
+ result = char_size;
+ have_result = true;
+ break;
+ }
+ if ( dst ) {
+ if ( have_result && result == terminated_sequence )
+ *src = NULL;
+ else
+ *src += source_converted;
+ }
+ if ( have_result && result != terminated_sequence && result != incomplete_sequence )
+ return static_cast<size_t>(-1);
+
+ return dest_converted;
+}
+
+// Converts max_source_chars from the wide character buffer pointer to by *src,
+// into the multi byte character sequence buffer stored at dst which must be
+// dst_size_bytes bytes in size.
+// Returns >= 0: the number of bytes in the sequence
+// converted from *src, excluding the null terminator.
+// Returns size_t(-1) if an error occurs, also sets errno.
+// If dst is NULL dst_size_bytes is ignored and no bytes are copied to dst
+// and no "out" parameters are updated.
+size_t wcsnrtombs( char *__restrict dst, const wchar_t **__restrict src,
+ size_t max_source_chars, size_t dst_size_bytes, mbstate_t *__restrict ps )
+{
+ //const size_t invalid_sequence = static_cast<size_t>(-1);
+
+ size_t source_converted = 0;
+ size_t dest_converted = 0;
+ size_t dest_remaining = dst_size_bytes;
+ size_t char_size = 0;
+ const errno_t no_error = ( errno_t) 0;
+ errno_t result = ( errno_t ) 0;
+ bool have_result = false;
+ bool terminator_found = false;
+
+ // If dst is null then dst_size_bytes should be ignored according to the
+ // standard. Setting dest_remaining to a large value has this effect.
+ if (!dst)
+ dest_remaining = static_cast<size_t>(-1);
+
+ while ( source_converted != max_source_chars ) {
+ if ( ! dest_remaining )
+ break;
+ wchar_t c = (*src)[source_converted];
+ if ( dst )
+ result = wcrtomb_s( &char_size, dst + dest_converted, dest_remaining, c, ps);
+ else
+ result = wcrtomb_s( &char_size, NULL, 0, c, ps);
+ // If result is zero there is no error and char_size contains the
+ // size of the multi-byte-sequence converted.
+ // Otherwise result indicates an errno type error.
+ if ( result == no_error ) {
+ if ( c == L'\0' ) {
+ terminator_found = true;
+ break;
+ }
+ ++source_converted;
+ if ( dst )
+ dest_remaining -= char_size;
+ dest_converted += char_size;
+ continue;
+ }
+ have_result = true;
+ break;
+ }
+ if ( dst ) {
+ if ( terminator_found )
+ *src = NULL;
+ else
+ *src = *src + source_converted;
+ }
+ if ( have_result && result != no_error ) {
+ errno = result;
+ return static_cast<size_t>(-1);
+ }
+
+ return dest_converted;
+}
diff --git a/contrib/libs/cxxsupp/libcxx/src/support/win32/thread_win32.cpp b/contrib/libs/cxxsupp/libcxx/src/support/win32/thread_win32.cpp
new file mode 100644
index 0000000000..f2072b1435
--- /dev/null
+++ b/contrib/libs/cxxsupp/libcxx/src/support/win32/thread_win32.cpp
@@ -0,0 +1,274 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include <__threading_support>
+#define NOMINMAX
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <process.h>
+#include <fibersapi.h>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+static_assert(sizeof(__libcpp_mutex_t) == sizeof(SRWLOCK), "");
+static_assert(alignof(__libcpp_mutex_t) == alignof(SRWLOCK), "");
+
+static_assert(sizeof(__libcpp_recursive_mutex_t) == sizeof(CRITICAL_SECTION),
+ "");
+static_assert(alignof(__libcpp_recursive_mutex_t) == alignof(CRITICAL_SECTION),
+ "");
+
+static_assert(sizeof(__libcpp_condvar_t) == sizeof(CONDITION_VARIABLE), "");
+static_assert(alignof(__libcpp_condvar_t) == alignof(CONDITION_VARIABLE), "");
+
+static_assert(sizeof(__libcpp_exec_once_flag) == sizeof(INIT_ONCE), "");
+static_assert(alignof(__libcpp_exec_once_flag) == alignof(INIT_ONCE), "");
+
+static_assert(sizeof(__libcpp_thread_id) == sizeof(DWORD), "");
+static_assert(alignof(__libcpp_thread_id) == alignof(DWORD), "");
+
+static_assert(sizeof(__libcpp_thread_t) == sizeof(HANDLE), "");
+static_assert(alignof(__libcpp_thread_t) == alignof(HANDLE), "");
+
+static_assert(sizeof(__libcpp_tls_key) == sizeof(DWORD), "");
+static_assert(alignof(__libcpp_tls_key) == alignof(DWORD), "");
+
+// Mutex
+int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m)
+{
+ InitializeCriticalSection((LPCRITICAL_SECTION)__m);
+ return 0;
+}
+
+int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m)
+{
+ EnterCriticalSection((LPCRITICAL_SECTION)__m);
+ return 0;
+}
+
+bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m)
+{
+ return TryEnterCriticalSection((LPCRITICAL_SECTION)__m) != 0;
+}
+
+int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m)
+{
+ LeaveCriticalSection((LPCRITICAL_SECTION)__m);
+ return 0;
+}
+
+int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m)
+{
+ DeleteCriticalSection((LPCRITICAL_SECTION)__m);
+ return 0;
+}
+
+int __libcpp_mutex_lock(__libcpp_mutex_t *__m)
+{
+ AcquireSRWLockExclusive((PSRWLOCK)__m);
+ return 0;
+}
+
+bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m)
+{
+ return TryAcquireSRWLockExclusive((PSRWLOCK)__m) != 0;
+}
+
+int __libcpp_mutex_unlock(__libcpp_mutex_t *__m)
+{
+ ReleaseSRWLockExclusive((PSRWLOCK)__m);
+ return 0;
+}
+
+int __libcpp_mutex_destroy(__libcpp_mutex_t *__m)
+{
+ static_cast<void>(__m);
+ return 0;
+}
+
+// Condition Variable
+int __libcpp_condvar_signal(__libcpp_condvar_t *__cv)
+{
+ WakeConditionVariable((PCONDITION_VARIABLE)__cv);
+ return 0;
+}
+
+int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv)
+{
+ WakeAllConditionVariable((PCONDITION_VARIABLE)__cv);
+ return 0;
+}
+
+int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m)
+{
+ SleepConditionVariableSRW((PCONDITION_VARIABLE)__cv, (PSRWLOCK)__m, INFINITE, 0);
+ return 0;
+}
+
+int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
+ __libcpp_timespec_t *__ts)
+{
+ using namespace _VSTD::chrono;
+
+ auto duration = seconds(__ts->tv_sec) + nanoseconds(__ts->tv_nsec);
+ auto abstime =
+ system_clock::time_point(duration_cast<system_clock::duration>(duration));
+ auto timeout_ms = duration_cast<milliseconds>(abstime - system_clock::now());
+
+ if (!SleepConditionVariableSRW((PCONDITION_VARIABLE)__cv, (PSRWLOCK)__m,
+ timeout_ms.count() > 0 ? timeout_ms.count()
+ : 0,
+ 0))
+ {
+ auto __ec = GetLastError();
+ return __ec == ERROR_TIMEOUT ? ETIMEDOUT : __ec;
+ }
+ return 0;
+}
+
+int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv)
+{
+ static_cast<void>(__cv);
+ return 0;
+}
+
+// Execute Once
+static inline _LIBCPP_INLINE_VISIBILITY BOOL CALLBACK
+__libcpp_init_once_execute_once_thunk(PINIT_ONCE __init_once, PVOID __parameter,
+ PVOID *__context)
+{
+ static_cast<void>(__init_once);
+ static_cast<void>(__context);
+
+ void (*init_routine)(void) = reinterpret_cast<void (*)(void)>(__parameter);
+ init_routine();
+ return TRUE;
+}
+
+int __libcpp_execute_once(__libcpp_exec_once_flag *__flag,
+ void (*__init_routine)(void))
+{
+ if (!InitOnceExecuteOnce((PINIT_ONCE)__flag, __libcpp_init_once_execute_once_thunk,
+ reinterpret_cast<void *>(__init_routine), NULL))
+ return GetLastError();
+ return 0;
+}
+
+// Thread ID
+bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs,
+ __libcpp_thread_id __rhs)
+{
+ return __lhs == __rhs;
+}
+
+bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs)
+{
+ return __lhs < __rhs;
+}
+
+// Thread
+struct __libcpp_beginthreadex_thunk_data
+{
+ void *(*__func)(void *);
+ void *__arg;
+};
+
+static inline _LIBCPP_INLINE_VISIBILITY unsigned WINAPI
+__libcpp_beginthreadex_thunk(void *__raw_data)
+{
+ auto *__data =
+ static_cast<__libcpp_beginthreadex_thunk_data *>(__raw_data);
+ auto *__func = __data->__func;
+ void *__arg = __data->__arg;
+ delete __data;
+ return static_cast<unsigned>(reinterpret_cast<uintptr_t>(__func(__arg)));
+}
+
+bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) {
+ return *__t == 0;
+}
+
+int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *),
+ void *__arg)
+{
+ auto *__data = new __libcpp_beginthreadex_thunk_data;
+ __data->__func = __func;
+ __data->__arg = __arg;
+
+ *__t = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0,
+ __libcpp_beginthreadex_thunk,
+ __data, 0, nullptr));
+
+ if (*__t)
+ return 0;
+ return GetLastError();
+}
+
+__libcpp_thread_id __libcpp_thread_get_current_id()
+{
+ return GetCurrentThreadId();
+}
+
+__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t)
+{
+ return GetThreadId(*__t);
+}
+
+int __libcpp_thread_join(__libcpp_thread_t *__t)
+{
+ if (WaitForSingleObjectEx(*__t, INFINITE, FALSE) == WAIT_FAILED)
+ return GetLastError();
+ if (!CloseHandle(*__t))
+ return GetLastError();
+ return 0;
+}
+
+int __libcpp_thread_detach(__libcpp_thread_t *__t)
+{
+ if (!CloseHandle(*__t))
+ return GetLastError();
+ return 0;
+}
+
+void __libcpp_thread_yield()
+{
+ SwitchToThread();
+}
+
+void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns)
+{
+ // round-up to the nearest millisecond
+ chrono::milliseconds __ms = chrono::ceil<chrono::milliseconds>(__ns);
+ // FIXME(compnerd) this should be an alertable sleep (WFSO or SleepEx)
+ Sleep(__ms.count());
+}
+
+// Thread Local Storage
+int __libcpp_tls_create(__libcpp_tls_key* __key,
+ void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*))
+{
+ DWORD index = FlsAlloc(__at_exit);
+ if (index == FLS_OUT_OF_INDEXES)
+ return GetLastError();
+ *__key = index;
+ return 0;
+}
+
+void *__libcpp_tls_get(__libcpp_tls_key __key)
+{
+ return FlsGetValue(__key);
+}
+
+int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
+{
+ if (!FlsSetValue(__key, __p))
+ return GetLastError();
+ return 0;
+}
+
+_LIBCPP_END_NAMESPACE_STD
diff --git a/contrib/libs/libc_compat/include/windows/sys/queue.h b/contrib/libs/libc_compat/include/windows/sys/queue.h
new file mode 100644
index 0000000000..bc1568be67
--- /dev/null
+++ b/contrib/libs/libc_compat/include/windows/sys/queue.h
@@ -0,0 +1,631 @@
+/* $OpenBSD: queue.h,v 1.46 2020/12/30 13:33:12 millert Exp $ */
+/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)queue.h 8.5 (Berkeley) 8/20/94
+ */
+
+#ifndef _SYS_QUEUE_H_
+#define _SYS_QUEUE_H_
+
+/*
+ * This file defines five types of data structures: singly-linked lists,
+ * lists, simple queues, tail queues and XOR simple queues.
+ *
+ *
+ * A singly-linked list is headed by a single forward pointer. The elements
+ * are singly linked for minimum space and pointer manipulation overhead at
+ * the expense of O(n) removal for arbitrary elements. New elements can be
+ * added to the list after an existing element or at the head of the list.
+ * Elements being removed from the head of the list should use the explicit
+ * macro for this purpose for optimum efficiency. A singly-linked list may
+ * only be traversed in the forward direction. Singly-linked lists are ideal
+ * for applications with large datasets and few or no removals or for
+ * implementing a LIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A simple queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are singly
+ * linked to save space, so elements can only be removed from the
+ * head of the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the
+ * list. A simple queue may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * An XOR simple queue is used in the same way as a regular simple queue.
+ * The difference is that the head structure also includes a "cookie" that
+ * is XOR'd with the queue pointer (first, last or next) to generate the
+ * real pointer value.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ */
+
+#if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC))
+#define _Q_INVALID ((void *)-1)
+#define _Q_INVALIDATE(a) (a) = _Q_INVALID
+#else
+#define _Q_INVALIDATE(a)
+#endif
+
+/*
+ * Singly-linked List definitions.
+ */
+#define SLIST_HEAD(name, type) \
+struct name { \
+ struct type *slh_first; /* first element */ \
+}
+
+#define SLIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define SLIST_ENTRY(type) \
+struct { \
+ struct type *sle_next; /* next element */ \
+}
+
+/*
+ * Singly-linked List access methods.
+ */
+#define SLIST_FIRST(head) ((head)->slh_first)
+#define SLIST_END(head) NULL
+#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))
+#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
+
+#define SLIST_FOREACH(var, head, field) \
+ for((var) = SLIST_FIRST(head); \
+ (var) != SLIST_END(head); \
+ (var) = SLIST_NEXT(var, field))
+
+#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = SLIST_FIRST(head); \
+ (var) && ((tvar) = SLIST_NEXT(var, field), 1); \
+ (var) = (tvar))
+
+/*
+ * Singly-linked List functions.
+ */
+#define SLIST_INIT(head) { \
+ SLIST_FIRST(head) = SLIST_END(head); \
+}
+
+#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
+ (elm)->field.sle_next = (slistelm)->field.sle_next; \
+ (slistelm)->field.sle_next = (elm); \
+} while (0)
+
+#define SLIST_INSERT_HEAD(head, elm, field) do { \
+ (elm)->field.sle_next = (head)->slh_first; \
+ (head)->slh_first = (elm); \
+} while (0)
+
+#define SLIST_REMOVE_AFTER(elm, field) do { \
+ (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \
+} while (0)
+
+#define SLIST_REMOVE_HEAD(head, field) do { \
+ (head)->slh_first = (head)->slh_first->field.sle_next; \
+} while (0)
+
+#define SLIST_REMOVE(head, elm, type, field) do { \
+ if ((head)->slh_first == (elm)) { \
+ SLIST_REMOVE_HEAD((head), field); \
+ } else { \
+ struct type *curelm = (head)->slh_first; \
+ \
+ while (curelm->field.sle_next != (elm)) \
+ curelm = curelm->field.sle_next; \
+ curelm->field.sle_next = \
+ curelm->field.sle_next->field.sle_next; \
+ } \
+ _Q_INVALIDATE((elm)->field.sle_next); \
+} while (0)
+
+/*
+ * List definitions.
+ */
+#define LIST_HEAD(name, type) \
+struct name { \
+ struct type *lh_first; /* first element */ \
+}
+
+#define LIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define LIST_ENTRY(type) \
+struct { \
+ struct type *le_next; /* next element */ \
+ struct type **le_prev; /* address of previous next element */ \
+}
+
+/*
+ * List access methods.
+ */
+#define LIST_FIRST(head) ((head)->lh_first)
+#define LIST_END(head) NULL
+#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head))
+#define LIST_NEXT(elm, field) ((elm)->field.le_next)
+
+#define LIST_FOREACH(var, head, field) \
+ for((var) = LIST_FIRST(head); \
+ (var)!= LIST_END(head); \
+ (var) = LIST_NEXT(var, field))
+
+#define LIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = LIST_FIRST(head); \
+ (var) && ((tvar) = LIST_NEXT(var, field), 1); \
+ (var) = (tvar))
+
+/*
+ * List functions.
+ */
+#define LIST_INIT(head) do { \
+ LIST_FIRST(head) = LIST_END(head); \
+} while (0)
+
+#define LIST_INSERT_AFTER(listelm, elm, field) do { \
+ if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
+ (listelm)->field.le_next->field.le_prev = \
+ &(elm)->field.le_next; \
+ (listelm)->field.le_next = (elm); \
+ (elm)->field.le_prev = &(listelm)->field.le_next; \
+} while (0)
+
+#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.le_prev = (listelm)->field.le_prev; \
+ (elm)->field.le_next = (listelm); \
+ *(listelm)->field.le_prev = (elm); \
+ (listelm)->field.le_prev = &(elm)->field.le_next; \
+} while (0)
+
+#define LIST_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.le_next = (head)->lh_first) != NULL) \
+ (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
+ (head)->lh_first = (elm); \
+ (elm)->field.le_prev = &(head)->lh_first; \
+} while (0)
+
+#define LIST_REMOVE(elm, field) do { \
+ if ((elm)->field.le_next != NULL) \
+ (elm)->field.le_next->field.le_prev = \
+ (elm)->field.le_prev; \
+ *(elm)->field.le_prev = (elm)->field.le_next; \
+ _Q_INVALIDATE((elm)->field.le_prev); \
+ _Q_INVALIDATE((elm)->field.le_next); \
+} while (0)
+
+#define LIST_REPLACE(elm, elm2, field) do { \
+ if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \
+ (elm2)->field.le_next->field.le_prev = \
+ &(elm2)->field.le_next; \
+ (elm2)->field.le_prev = (elm)->field.le_prev; \
+ *(elm2)->field.le_prev = (elm2); \
+ _Q_INVALIDATE((elm)->field.le_prev); \
+ _Q_INVALIDATE((elm)->field.le_next); \
+} while (0)
+
+/*
+ * Simple queue definitions.
+ */
+#define SIMPLEQ_HEAD(name, type) \
+struct name { \
+ struct type *sqh_first; /* first element */ \
+ struct type **sqh_last; /* addr of last next element */ \
+}
+
+#define SIMPLEQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).sqh_first }
+
+#define SIMPLEQ_ENTRY(type) \
+struct { \
+ struct type *sqe_next; /* next element */ \
+}
+
+/*
+ * Simple queue access methods.
+ */
+#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
+#define SIMPLEQ_END(head) NULL
+#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
+#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
+
+#define SIMPLEQ_FOREACH(var, head, field) \
+ for((var) = SIMPLEQ_FIRST(head); \
+ (var) != SIMPLEQ_END(head); \
+ (var) = SIMPLEQ_NEXT(var, field))
+
+#define SIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = SIMPLEQ_FIRST(head); \
+ (var) && ((tvar) = SIMPLEQ_NEXT(var, field), 1); \
+ (var) = (tvar))
+
+/*
+ * Simple queue functions.
+ */
+#define SIMPLEQ_INIT(head) do { \
+ (head)->sqh_first = NULL; \
+ (head)->sqh_last = &(head)->sqh_first; \
+} while (0)
+
+#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+ (head)->sqh_first = (elm); \
+} while (0)
+
+#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.sqe_next = NULL; \
+ *(head)->sqh_last = (elm); \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+} while (0)
+
+#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+ (listelm)->field.sqe_next = (elm); \
+} while (0)
+
+#define SIMPLEQ_REMOVE_HEAD(head, field) do { \
+ if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
+ (head)->sqh_last = &(head)->sqh_first; \
+} while (0)
+
+#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \
+ if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \
+ == NULL) \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+} while (0)
+
+#define SIMPLEQ_CONCAT(head1, head2) do { \
+ if (!SIMPLEQ_EMPTY((head2))) { \
+ *(head1)->sqh_last = (head2)->sqh_first; \
+ (head1)->sqh_last = (head2)->sqh_last; \
+ SIMPLEQ_INIT((head2)); \
+ } \
+} while (0)
+
+/*
+ * XOR Simple queue definitions.
+ */
+#define XSIMPLEQ_HEAD(name, type) \
+struct name { \
+ struct type *sqx_first; /* first element */ \
+ struct type **sqx_last; /* addr of last next element */ \
+ unsigned long sqx_cookie; \
+}
+
+#define XSIMPLEQ_ENTRY(type) \
+struct { \
+ struct type *sqx_next; /* next element */ \
+}
+
+/*
+ * XOR Simple queue access methods.
+ */
+#define XSIMPLEQ_XOR(head, ptr) ((__typeof(ptr))((head)->sqx_cookie ^ \
+ (unsigned long)(ptr)))
+#define XSIMPLEQ_FIRST(head) XSIMPLEQ_XOR(head, ((head)->sqx_first))
+#define XSIMPLEQ_END(head) NULL
+#define XSIMPLEQ_EMPTY(head) (XSIMPLEQ_FIRST(head) == XSIMPLEQ_END(head))
+#define XSIMPLEQ_NEXT(head, elm, field) XSIMPLEQ_XOR(head, ((elm)->field.sqx_next))
+
+
+#define XSIMPLEQ_FOREACH(var, head, field) \
+ for ((var) = XSIMPLEQ_FIRST(head); \
+ (var) != XSIMPLEQ_END(head); \
+ (var) = XSIMPLEQ_NEXT(head, var, field))
+
+#define XSIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = XSIMPLEQ_FIRST(head); \
+ (var) && ((tvar) = XSIMPLEQ_NEXT(head, var, field), 1); \
+ (var) = (tvar))
+
+/*
+ * XOR Simple queue functions.
+ */
+#define XSIMPLEQ_INIT(head) do { \
+ arc4random_buf(&(head)->sqx_cookie, sizeof((head)->sqx_cookie)); \
+ (head)->sqx_first = XSIMPLEQ_XOR(head, NULL); \
+ (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \
+} while (0)
+
+#define XSIMPLEQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.sqx_next = (head)->sqx_first) == \
+ XSIMPLEQ_XOR(head, NULL)) \
+ (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
+ (head)->sqx_first = XSIMPLEQ_XOR(head, (elm)); \
+} while (0)
+
+#define XSIMPLEQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.sqx_next = XSIMPLEQ_XOR(head, NULL); \
+ *(XSIMPLEQ_XOR(head, (head)->sqx_last)) = XSIMPLEQ_XOR(head, (elm)); \
+ (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
+} while (0)
+
+#define XSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.sqx_next = (listelm)->field.sqx_next) == \
+ XSIMPLEQ_XOR(head, NULL)) \
+ (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
+ (listelm)->field.sqx_next = XSIMPLEQ_XOR(head, (elm)); \
+} while (0)
+
+#define XSIMPLEQ_REMOVE_HEAD(head, field) do { \
+ if (((head)->sqx_first = XSIMPLEQ_XOR(head, \
+ (head)->sqx_first)->field.sqx_next) == XSIMPLEQ_XOR(head, NULL)) \
+ (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \
+} while (0)
+
+#define XSIMPLEQ_REMOVE_AFTER(head, elm, field) do { \
+ if (((elm)->field.sqx_next = XSIMPLEQ_XOR(head, \
+ (elm)->field.sqx_next)->field.sqx_next) \
+ == XSIMPLEQ_XOR(head, NULL)) \
+ (head)->sqx_last = \
+ XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
+} while (0)
+
+
+/*
+ * Tail queue definitions.
+ */
+#define TAILQ_HEAD(name, type) \
+struct name { \
+ struct type *tqh_first; /* first element */ \
+ struct type **tqh_last; /* addr of last next element */ \
+}
+
+#define TAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).tqh_first }
+
+#define TAILQ_ENTRY(type) \
+struct { \
+ struct type *tqe_next; /* next element */ \
+ struct type **tqe_prev; /* address of previous next element */ \
+}
+
+/*
+ * Tail queue access methods.
+ */
+#define TAILQ_FIRST(head) ((head)->tqh_first)
+#define TAILQ_END(head) NULL
+#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+#define TAILQ_LAST(head, headname) \
+ (*(((struct headname *)((head)->tqh_last))->tqh_last))
+/* XXX */
+#define TAILQ_PREV(elm, headname, field) \
+ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+#define TAILQ_EMPTY(head) \
+ (TAILQ_FIRST(head) == TAILQ_END(head))
+
+#define TAILQ_FOREACH(var, head, field) \
+ for((var) = TAILQ_FIRST(head); \
+ (var) != TAILQ_END(head); \
+ (var) = TAILQ_NEXT(var, field))
+
+#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = TAILQ_FIRST(head); \
+ (var) != TAILQ_END(head) && \
+ ((tvar) = TAILQ_NEXT(var, field), 1); \
+ (var) = (tvar))
+
+
+#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
+ for((var) = TAILQ_LAST(head, headname); \
+ (var) != TAILQ_END(head); \
+ (var) = TAILQ_PREV(var, headname, field))
+
+#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
+ for ((var) = TAILQ_LAST(head, headname); \
+ (var) != TAILQ_END(head) && \
+ ((tvar) = TAILQ_PREV(var, headname, field), 1); \
+ (var) = (tvar))
+
+/*
+ * Tail queue functions.
+ */
+#define TAILQ_INIT(head) do { \
+ (head)->tqh_first = NULL; \
+ (head)->tqh_last = &(head)->tqh_first; \
+} while (0)
+
+#define TAILQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
+ (head)->tqh_first->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (head)->tqh_first = (elm); \
+ (elm)->field.tqe_prev = &(head)->tqh_first; \
+} while (0)
+
+#define TAILQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.tqe_next = NULL; \
+ (elm)->field.tqe_prev = (head)->tqh_last; \
+ *(head)->tqh_last = (elm); \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+} while (0)
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
+ (elm)->field.tqe_next->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (listelm)->field.tqe_next = (elm); \
+ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
+} while (0)
+
+#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
+ (elm)->field.tqe_next = (listelm); \
+ *(listelm)->field.tqe_prev = (elm); \
+ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
+} while (0)
+
+#define TAILQ_REMOVE(head, elm, field) do { \
+ if (((elm)->field.tqe_next) != NULL) \
+ (elm)->field.tqe_next->field.tqe_prev = \
+ (elm)->field.tqe_prev; \
+ else \
+ (head)->tqh_last = (elm)->field.tqe_prev; \
+ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
+ _Q_INVALIDATE((elm)->field.tqe_prev); \
+ _Q_INVALIDATE((elm)->field.tqe_next); \
+} while (0)
+
+#define TAILQ_REPLACE(head, elm, elm2, field) do { \
+ if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \
+ (elm2)->field.tqe_next->field.tqe_prev = \
+ &(elm2)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm2)->field.tqe_next; \
+ (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \
+ *(elm2)->field.tqe_prev = (elm2); \
+ _Q_INVALIDATE((elm)->field.tqe_prev); \
+ _Q_INVALIDATE((elm)->field.tqe_next); \
+} while (0)
+
+#define TAILQ_CONCAT(head1, head2, field) do { \
+ if (!TAILQ_EMPTY(head2)) { \
+ *(head1)->tqh_last = (head2)->tqh_first; \
+ (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
+ (head1)->tqh_last = (head2)->tqh_last; \
+ TAILQ_INIT((head2)); \
+ } \
+} while (0)
+
+/*
+ * Singly-linked Tail queue declarations.
+ */
+#define STAILQ_HEAD(name, type) \
+struct name { \
+ struct type *stqh_first; /* first element */ \
+ struct type **stqh_last; /* addr of last next element */ \
+}
+
+#define STAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).stqh_first }
+
+#define STAILQ_ENTRY(type) \
+struct { \
+ struct type *stqe_next; /* next element */ \
+}
+
+/*
+ * Singly-linked Tail queue access methods.
+ */
+#define STAILQ_FIRST(head) ((head)->stqh_first)
+#define STAILQ_END(head) NULL
+#define STAILQ_EMPTY(head) (STAILQ_FIRST(head) == STAILQ_END(head))
+#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
+
+#define STAILQ_FOREACH(var, head, field) \
+ for ((var) = STAILQ_FIRST(head); \
+ (var) != STAILQ_END(head); \
+ (var) = STAILQ_NEXT(var, field))
+
+#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = STAILQ_FIRST(head); \
+ (var) && ((tvar) = STAILQ_NEXT(var, field), 1); \
+ (var) = (tvar))
+
+/*
+ * Singly-linked Tail queue functions.
+ */
+#define STAILQ_INIT(head) do { \
+ STAILQ_FIRST((head)) = NULL; \
+ (head)->stqh_last = &STAILQ_FIRST((head)); \
+} while (0)
+
+#define STAILQ_INSERT_HEAD(head, elm, field) do { \
+ if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+ STAILQ_FIRST((head)) = (elm); \
+} while (0)
+
+#define STAILQ_INSERT_TAIL(head, elm, field) do { \
+ STAILQ_NEXT((elm), field) = NULL; \
+ *(head)->stqh_last = (elm); \
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+} while (0)
+
+#define STAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((elm), field)) == NULL)\
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+ STAILQ_NEXT((elm), field) = (elm); \
+} while (0)
+
+#define STAILQ_REMOVE_HEAD(head, field) do { \
+ if ((STAILQ_FIRST((head)) = \
+ STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
+ (head)->stqh_last = &STAILQ_FIRST((head)); \
+} while (0)
+
+#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
+ if ((STAILQ_NEXT(elm, field) = \
+ STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+} while (0)
+
+#define STAILQ_REMOVE(head, elm, type, field) do { \
+ if (STAILQ_FIRST((head)) == (elm)) { \
+ STAILQ_REMOVE_HEAD((head), field); \
+ } else { \
+ struct type *curelm = (head)->stqh_first; \
+ while (STAILQ_NEXT(curelm, field) != (elm)) \
+ curelm = STAILQ_NEXT(curelm, field); \
+ STAILQ_REMOVE_AFTER(head, curelm, field); \
+ } \
+} while (0)
+
+#define STAILQ_CONCAT(head1, head2) do { \
+ if (!STAILQ_EMPTY((head2))) { \
+ *(head1)->stqh_last = (head2)->stqh_first; \
+ (head1)->stqh_last = (head2)->stqh_last; \
+ STAILQ_INIT((head2)); \
+ } \
+} while (0)
+
+#define STAILQ_LAST(head, type, field) \
+ (STAILQ_EMPTY((head)) ? NULL : \
+ ((struct type *)(void *) \
+ ((char *)((head)->stqh_last) - offsetof(struct type, field))))
+
+#endif /* !_SYS_QUEUE_H_ */
diff --git a/contrib/libs/libc_compat/include/windows/sys/uio.h b/contrib/libs/libc_compat/include/windows/sys/uio.h
new file mode 100644
index 0000000000..47cc77784a
--- /dev/null
+++ b/contrib/libs/libc_compat/include/windows/sys/uio.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include <stddef.h>
+#include <BaseTsd.h>
+#include <WinSock2.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define IOV_MAX INT_MAX
+
+typedef SSIZE_T ssize_t;
+
+struct iovec {
+ char* iov_base;
+ size_t iov_len;
+};
+
+ssize_t readv(SOCKET sock, struct iovec const* iov, int nvecs);
+ssize_t writev(SOCKET sock, struct iovec const* iov, int nvecs);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/contrib/libs/libc_compat/src/windows/sys/uio.c b/contrib/libs/libc_compat/src/windows/sys/uio.c
new file mode 100644
index 0000000000..50c9542dc1
--- /dev/null
+++ b/contrib/libs/libc_compat/src/windows/sys/uio.c
@@ -0,0 +1,36 @@
+#include <contrib/libs/libc_compat/include/windows/sys/uio.h>
+
+#include <Windows.h>
+#include <winsock2.h>
+#include <malloc.h>
+
+ssize_t readv(SOCKET sock, struct iovec const* iov, int iovcnt) {
+ WSABUF* wsabuf = (WSABUF*)alloca(iovcnt * sizeof(WSABUF));
+ for (int i = 0; i < iovcnt; ++i) {
+ wsabuf[i].buf = iov[i].iov_base;
+ wsabuf[i].len = (u_long)iov[i].iov_len;
+ }
+ DWORD numberOfBytesRecv;
+ DWORD flags = 0;
+ int res = WSARecv(sock, wsabuf, iovcnt, &numberOfBytesRecv, &flags, NULL, NULL);
+ if (res == SOCKET_ERROR) {
+ errno = EIO;
+ return -1;
+ }
+ return numberOfBytesRecv;
+}
+
+ssize_t writev(SOCKET sock, struct iovec const* iov, int iovcnt) {
+ WSABUF* wsabuf = (WSABUF*)alloca(iovcnt * sizeof(WSABUF));
+ for (int i = 0; i < iovcnt; ++i) {
+ wsabuf[i].buf = iov[i].iov_base;
+ wsabuf[i].len = (u_long)iov[i].iov_len;
+ }
+ DWORD numberOfBytesSent;
+ int res = WSASend(sock, wsabuf, iovcnt, &numberOfBytesSent, 0, NULL, NULL);
+ if (res == SOCKET_ERROR) {
+ errno = EIO;
+ return -1;
+ }
+ return numberOfBytesSent;
+}
diff --git a/contrib/libs/libc_compat/stpcpy.c b/contrib/libs/libc_compat/stpcpy.c
new file mode 100644
index 0000000000..5a86541f08
--- /dev/null
+++ b/contrib/libs/libc_compat/stpcpy.c
@@ -0,0 +1,44 @@
+/* $OpenBSD: stpcpy.c,v 1.3 2017/11/28 06:55:49 tb Exp $ */
+
+/*
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <string.h>
+
+#if defined(APIWARN)
+__warn_references(stpcpy,
+ "stpcpy() is dangerous; do not use it");
+#endif
+
+char *
+stpcpy(char *to, const char *from)
+{
+ for (; (*to = *from) != '\0'; ++from, ++to);
+ return(to);
+}
diff --git a/contrib/libs/libc_compat/strcasestr.c b/contrib/libs/libc_compat/strcasestr.c
new file mode 100644
index 0000000000..ee299b1c01
--- /dev/null
+++ b/contrib/libs/libc_compat/strcasestr.c
@@ -0,0 +1,61 @@
+/* $OpenBSD: strcasestr.c,v 1.4 2015/08/31 02:53:57 guenther Exp $ */
+/* $NetBSD: strcasestr.c,v 1.2 2005/02/09 21:35:47 kleink Exp $ */
+
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <ctype.h>
+#include "string.h"
+
+/*
+ * Find the first occurrence of find in s, ignore case.
+ */
+char *
+strcasestr(const char *s, const char *find)
+{
+ char c, sc;
+ size_t len;
+
+ if ((c = *find++) != 0) {
+ c = (char)tolower((unsigned char)c);
+ len = strlen(find);
+ do {
+ do {
+ if ((sc = *s++) == 0)
+ return (NULL);
+ } while ((char)tolower((unsigned char)sc) != c);
+ } while (strncasecmp(s, find, len) != 0);
+ s--;
+ }
+ return ((char *)s);
+}
+
diff --git a/contrib/libs/libc_compat/strsep.c b/contrib/libs/libc_compat/strsep.c
new file mode 100644
index 0000000000..ed605bce97
--- /dev/null
+++ b/contrib/libs/libc_compat/strsep.c
@@ -0,0 +1,71 @@
+/* $OpenBSD: strsep.c,v 1.8 2015/08/31 02:53:57 guenther Exp $ */
+
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <string.h>
+
+/*
+ * Get next token from string *stringp, where tokens are possibly-empty
+ * strings separated by characters from delim.
+ *
+ * Writes NULs into the string at *stringp to end tokens.
+ * delim need not remain constant from call to call.
+ * On return, *stringp points past the last NUL written (if there might
+ * be further tokens), or is NULL (if there are definitely no more tokens).
+ *
+ * If *stringp is NULL, strsep returns NULL.
+ */
+char *
+strsep(char **stringp, const char *delim)
+{
+ char *s;
+ const char *spanp;
+ int c, sc;
+ char *tok;
+
+ if ((s = *stringp) == NULL)
+ return (NULL);
+ for (tok = s;;) {
+ c = *s++;
+ spanp = delim;
+ do {
+ if ((sc = *spanp++) == c) {
+ if (c == 0)
+ s = NULL;
+ else
+ s[-1] = 0;
+ *stringp = s;
+ return (tok);
+ }
+ } while (sc != 0);
+ }
+ /* NOTREACHED */
+}
+
diff --git a/contrib/libs/libevent/buffer_iocp.c b/contrib/libs/libevent/buffer_iocp.c
new file mode 100644
index 0000000000..2af0c49cc6
--- /dev/null
+++ b/contrib/libs/libevent/buffer_iocp.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ @file buffer_iocp.c
+
+ This module implements overlapped read and write functions for evbuffer
+ objects on Windows.
+*/
+#include "event2/event-config.h"
+#include "evconfig-private.h"
+
+#include "event2/buffer.h"
+#include "event2/buffer_compat.h"
+#include "event2/util.h"
+#include "event2/thread.h"
+#include "util-internal.h"
+#include "evthread-internal.h"
+#include "evbuffer-internal.h"
+#include "iocp-internal.h"
+#include "mm-internal.h"
+
+#include <winsock2.h>
+#include <winerror.h>
+#include <windows.h>
+#include <stdio.h>
+
+#define MAX_WSABUFS 16
+
+/** An evbuffer that can handle overlapped IO. */
+struct evbuffer_overlapped {
+ struct evbuffer buffer;
+ /** The socket that we're doing overlapped IO on. */
+ evutil_socket_t fd;
+
+ /** pending I/O type */
+ unsigned read_in_progress : 1;
+ unsigned write_in_progress : 1;
+
+ /** The first pinned chain in the buffer. */
+ struct evbuffer_chain *first_pinned;
+
+ /** How many chains are pinned; how many of the fields in buffers
+ * are we using. */
+ int n_buffers;
+ WSABUF buffers[MAX_WSABUFS];
+};
+
+/** Given an evbuffer, return the correponding evbuffer structure, or NULL if
+ * the evbuffer isn't overlapped. */
+static inline struct evbuffer_overlapped *
+upcast_evbuffer(struct evbuffer *buf)
+{
+ if (!buf || !buf->is_overlapped)
+ return NULL;
+ return EVUTIL_UPCAST(buf, struct evbuffer_overlapped, buffer);
+}
+
+/** Unpin all the chains noted as pinned in 'eo'. */
+static void
+pin_release(struct evbuffer_overlapped *eo, unsigned flag)
+{
+ int i;
+ struct evbuffer_chain *next, *chain = eo->first_pinned;
+
+ for (i = 0; i < eo->n_buffers; ++i) {
+ EVUTIL_ASSERT(chain);
+ next = chain->next;
+ evbuffer_chain_unpin_(chain, flag);
+ chain = next;
+ }
+}
+
+void
+evbuffer_commit_read_(struct evbuffer *evbuf, ev_ssize_t nBytes)
+{
+ struct evbuffer_overlapped *buf = upcast_evbuffer(evbuf);
+ struct evbuffer_chain **chainp;
+ size_t remaining, len;
+ unsigned i;
+
+ EVBUFFER_LOCK(evbuf);
+ EVUTIL_ASSERT(buf->read_in_progress && !buf->write_in_progress);
+ EVUTIL_ASSERT(nBytes >= 0); /* XXXX Can this be false? */
+
+ evbuffer_unfreeze(evbuf, 0);
+
+ chainp = evbuf->last_with_datap;
+ if (!((*chainp)->flags & EVBUFFER_MEM_PINNED_R))
+ chainp = &(*chainp)->next;
+ remaining = nBytes;
+ for (i = 0; remaining > 0 && i < (unsigned)buf->n_buffers; ++i) {
+ EVUTIL_ASSERT(*chainp);
+ len = buf->buffers[i].len;
+ if (remaining < len)
+ len = remaining;
+ (*chainp)->off += len;
+ evbuf->last_with_datap = chainp;
+ remaining -= len;
+ chainp = &(*chainp)->next;
+ }
+
+ pin_release(buf, EVBUFFER_MEM_PINNED_R);
+
+ buf->read_in_progress = 0;
+
+ evbuf->total_len += nBytes;
+ evbuf->n_add_for_cb += nBytes;
+
+ evbuffer_invoke_callbacks_(evbuf);
+
+ evbuffer_decref_and_unlock_(evbuf);
+}
+
+void
+evbuffer_commit_write_(struct evbuffer *evbuf, ev_ssize_t nBytes)
+{
+ struct evbuffer_overlapped *buf = upcast_evbuffer(evbuf);
+
+ EVBUFFER_LOCK(evbuf);
+ EVUTIL_ASSERT(buf->write_in_progress && !buf->read_in_progress);
+ evbuffer_unfreeze(evbuf, 1);
+ evbuffer_drain(evbuf, nBytes);
+ pin_release(buf,EVBUFFER_MEM_PINNED_W);
+ buf->write_in_progress = 0;
+ evbuffer_decref_and_unlock_(evbuf);
+}
+
+struct evbuffer *
+evbuffer_overlapped_new_(evutil_socket_t fd)
+{
+ struct evbuffer_overlapped *evo;
+
+ evo = mm_calloc(1, sizeof(struct evbuffer_overlapped));
+ if (!evo)
+ return NULL;
+
+ LIST_INIT(&evo->buffer.callbacks);
+ evo->buffer.refcnt = 1;
+ evo->buffer.last_with_datap = &evo->buffer.first;
+
+ evo->buffer.is_overlapped = 1;
+ evo->fd = fd;
+
+ return &evo->buffer;
+}
+
+int
+evbuffer_launch_write_(struct evbuffer *buf, ev_ssize_t at_most,
+ struct event_overlapped *ol)
+{
+ struct evbuffer_overlapped *buf_o = upcast_evbuffer(buf);
+ int r = -1;
+ int i;
+ struct evbuffer_chain *chain;
+ DWORD bytesSent;
+
+ if (!buf) {
+ /* No buffer, or it isn't overlapped */
+ return -1;
+ }
+
+ EVBUFFER_LOCK(buf);
+ EVUTIL_ASSERT(!buf_o->read_in_progress);
+ if (buf->freeze_start || buf_o->write_in_progress)
+ goto done;
+ if (!buf->total_len) {
+ /* Nothing to write */
+ r = 0;
+ goto done;
+ } else if (at_most < 0 || (size_t)at_most > buf->total_len) {
+ at_most = buf->total_len;
+ }
+ evbuffer_freeze(buf, 1);
+
+ buf_o->first_pinned = NULL;
+ buf_o->n_buffers = 0;
+ memset(buf_o->buffers, 0, sizeof(buf_o->buffers));
+
+ chain = buf_o->first_pinned = buf->first;
+
+ for (i=0; i < MAX_WSABUFS && chain; ++i, chain=chain->next) {
+ WSABUF *b = &buf_o->buffers[i];
+ b->buf = (char*)( chain->buffer + chain->misalign );
+ evbuffer_chain_pin_(chain, EVBUFFER_MEM_PINNED_W);
+
+ if ((size_t)at_most > chain->off) {
+ /* XXXX Cast is safe for now, since win32 has no
+ mmaped chains. But later, we need to have this
+ add more WSAbufs if chain->off is greater than
+ ULONG_MAX */
+ b->len = (unsigned long)chain->off;
+ at_most -= chain->off;
+ } else {
+ b->len = (unsigned long)at_most;
+ ++i;
+ break;
+ }
+ }
+
+ buf_o->n_buffers = i;
+ evbuffer_incref_(buf);
+ if (WSASend(buf_o->fd, buf_o->buffers, i, &bytesSent, 0,
+ &ol->overlapped, NULL)) {
+ int error = WSAGetLastError();
+ if (error != WSA_IO_PENDING) {
+ /* An actual error. */
+ pin_release(buf_o, EVBUFFER_MEM_PINNED_W);
+ evbuffer_unfreeze(buf, 1);
+ evbuffer_free(buf); /* decref */
+ goto done;
+ }
+ }
+
+ buf_o->write_in_progress = 1;
+ r = 0;
+done:
+ EVBUFFER_UNLOCK(buf);
+ return r;
+}
+
+int
+evbuffer_launch_read_(struct evbuffer *buf, size_t at_most,
+ struct event_overlapped *ol)
+{
+ struct evbuffer_overlapped *buf_o = upcast_evbuffer(buf);
+ int r = -1, i;
+ int nvecs;
+ int npin=0;
+ struct evbuffer_chain *chain=NULL, **chainp;
+ DWORD bytesRead;
+ DWORD flags = 0;
+ struct evbuffer_iovec vecs[MAX_WSABUFS];
+
+ if (!buf_o)
+ return -1;
+ EVBUFFER_LOCK(buf);
+ EVUTIL_ASSERT(!buf_o->write_in_progress);
+ if (buf->freeze_end || buf_o->read_in_progress)
+ goto done;
+
+ buf_o->first_pinned = NULL;
+ buf_o->n_buffers = 0;
+ memset(buf_o->buffers, 0, sizeof(buf_o->buffers));
+
+ if (evbuffer_expand_fast_(buf, at_most, MAX_WSABUFS) == -1)
+ goto done;
+ evbuffer_freeze(buf, 0);
+
+ nvecs = evbuffer_read_setup_vecs_(buf, at_most,
+ vecs, MAX_WSABUFS, &chainp, 1);
+ for (i=0;i<nvecs;++i) {
+ WSABUF_FROM_EVBUFFER_IOV(
+ &buf_o->buffers[i],
+ &vecs[i]);
+ }
+
+ buf_o->n_buffers = nvecs;
+ buf_o->first_pinned = chain = *chainp;
+
+ npin=0;
+ for ( ; chain; chain = chain->next) {
+ evbuffer_chain_pin_(chain, EVBUFFER_MEM_PINNED_R);
+ ++npin;
+ }
+ EVUTIL_ASSERT(npin == nvecs);
+
+ evbuffer_incref_(buf);
+ if (WSARecv(buf_o->fd, buf_o->buffers, nvecs, &bytesRead, &flags,
+ &ol->overlapped, NULL)) {
+ int error = WSAGetLastError();
+ if (error != WSA_IO_PENDING) {
+ /* An actual error. */
+ pin_release(buf_o, EVBUFFER_MEM_PINNED_R);
+ evbuffer_unfreeze(buf, 0);
+ evbuffer_free(buf); /* decref */
+ goto done;
+ }
+ }
+
+ buf_o->read_in_progress = 1;
+ r = 0;
+done:
+ EVBUFFER_UNLOCK(buf);
+ return r;
+}
+
+evutil_socket_t
+evbuffer_overlapped_get_fd_(struct evbuffer *buf)
+{
+ struct evbuffer_overlapped *buf_o = upcast_evbuffer(buf);
+ return buf_o ? buf_o->fd : -1;
+}
+
+void
+evbuffer_overlapped_set_fd_(struct evbuffer *buf, evutil_socket_t fd)
+{
+ struct evbuffer_overlapped *buf_o = upcast_evbuffer(buf);
+ EVBUFFER_LOCK(buf);
+ /* XXX is this right?, should it cancel current I/O operations? */
+ if (buf_o)
+ buf_o->fd = fd;
+ EVBUFFER_UNLOCK(buf);
+}
diff --git a/contrib/libs/libevent/bufferevent_async.c b/contrib/libs/libevent/bufferevent_async.c
new file mode 100644
index 0000000000..40c7c5e8d0
--- /dev/null
+++ b/contrib/libs/libevent/bufferevent_async.c
@@ -0,0 +1,706 @@
+/*
+ * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "event2/event-config.h"
+#include "evconfig-private.h"
+
+#ifdef EVENT__HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef EVENT__HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+#ifdef EVENT__HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef _WIN32
+#include <winsock2.h>
+#include <winerror.h>
+#include <ws2tcpip.h>
+#endif
+
+#include <sys/queue.h>
+
+#include "event2/util.h"
+#include "event2/bufferevent.h"
+#include "event2/buffer.h"
+#include "event2/bufferevent_struct.h"
+#include "event2/event.h"
+#include "event2/util.h"
+#include "event-internal.h"
+#include "log-internal.h"
+#include "mm-internal.h"
+#include "bufferevent-internal.h"
+#include "util-internal.h"
+#include "iocp-internal.h"
+
+#ifndef SO_UPDATE_CONNECT_CONTEXT
+/* Mingw is sometimes missing this */
+#define SO_UPDATE_CONNECT_CONTEXT 0x7010
+#endif
+
+/* prototypes */
+static int be_async_enable(struct bufferevent *, short);
+static int be_async_disable(struct bufferevent *, short);
+static void be_async_destruct(struct bufferevent *);
+static int be_async_flush(struct bufferevent *, short, enum bufferevent_flush_mode);
+static int be_async_ctrl(struct bufferevent *, enum bufferevent_ctrl_op, union bufferevent_ctrl_data *);
+
+struct bufferevent_async {
+ struct bufferevent_private bev;
+ struct event_overlapped connect_overlapped;
+ struct event_overlapped read_overlapped;
+ struct event_overlapped write_overlapped;
+ size_t read_in_progress;
+ size_t write_in_progress;
+ unsigned ok : 1;
+ unsigned read_added : 1;
+ unsigned write_added : 1;
+};
+
+const struct bufferevent_ops bufferevent_ops_async = {
+ "socket_async",
+ evutil_offsetof(struct bufferevent_async, bev.bev),
+ be_async_enable,
+ be_async_disable,
+ NULL, /* Unlink */
+ be_async_destruct,
+ bufferevent_generic_adj_timeouts_,
+ be_async_flush,
+ be_async_ctrl,
+};
+
+static inline void
+be_async_run_eventcb(struct bufferevent *bev, short what, int options)
+{ bufferevent_run_eventcb_(bev, what, options|BEV_TRIG_DEFER_CALLBACKS); }
+
+static inline void
+be_async_trigger_nolock(struct bufferevent *bev, short what, int options)
+{ bufferevent_trigger_nolock_(bev, what, options|BEV_TRIG_DEFER_CALLBACKS); }
+
+static inline int
+fatal_error(int err)
+{
+ switch (err) {
+ /* We may have already associated this fd with a port.
+ * Let's hope it's this port, and that the error code
+ * for doing this neer changes. */
+ case ERROR_INVALID_PARAMETER:
+ return 0;
+ }
+ return 1;
+}
+
+static inline struct bufferevent_async *
+upcast(struct bufferevent *bev)
+{
+ struct bufferevent_async *bev_a;
+ if (!BEV_IS_ASYNC(bev))
+ return NULL;
+ bev_a = EVUTIL_UPCAST(bev, struct bufferevent_async, bev.bev);
+ return bev_a;
+}
+
+static inline struct bufferevent_async *
+upcast_connect(struct event_overlapped *eo)
+{
+ struct bufferevent_async *bev_a;
+ bev_a = EVUTIL_UPCAST(eo, struct bufferevent_async, connect_overlapped);
+ EVUTIL_ASSERT(BEV_IS_ASYNC(&bev_a->bev.bev));
+ return bev_a;
+}
+
+static inline struct bufferevent_async *
+upcast_read(struct event_overlapped *eo)
+{
+ struct bufferevent_async *bev_a;
+ bev_a = EVUTIL_UPCAST(eo, struct bufferevent_async, read_overlapped);
+ EVUTIL_ASSERT(BEV_IS_ASYNC(&bev_a->bev.bev));
+ return bev_a;
+}
+
+static inline struct bufferevent_async *
+upcast_write(struct event_overlapped *eo)
+{
+ struct bufferevent_async *bev_a;
+ bev_a = EVUTIL_UPCAST(eo, struct bufferevent_async, write_overlapped);
+ EVUTIL_ASSERT(BEV_IS_ASYNC(&bev_a->bev.bev));
+ return bev_a;
+}
+
+static void
+bev_async_del_write(struct bufferevent_async *beva)
+{
+ struct bufferevent *bev = &beva->bev.bev;
+
+ if (beva->write_added) {
+ beva->write_added = 0;
+ event_base_del_virtual_(bev->ev_base);
+ }
+}
+
+static void
+bev_async_del_read(struct bufferevent_async *beva)
+{
+ struct bufferevent *bev = &beva->bev.bev;
+
+ if (beva->read_added) {
+ beva->read_added = 0;
+ event_base_del_virtual_(bev->ev_base);
+ }
+}
+
+static void
+bev_async_add_write(struct bufferevent_async *beva)
+{
+ struct bufferevent *bev = &beva->bev.bev;
+
+ if (!beva->write_added) {
+ beva->write_added = 1;
+ event_base_add_virtual_(bev->ev_base);
+ }
+}
+
+static void
+bev_async_add_read(struct bufferevent_async *beva)
+{
+ struct bufferevent *bev = &beva->bev.bev;
+
+ if (!beva->read_added) {
+ beva->read_added = 1;
+ event_base_add_virtual_(bev->ev_base);
+ }
+}
+
+static void
+bev_async_consider_writing(struct bufferevent_async *beva)
+{
+ size_t at_most;
+ int limit;
+ struct bufferevent *bev = &beva->bev.bev;
+
+ /* Don't write if there's a write in progress, or we do not
+ * want to write, or when there's nothing left to write. */
+ if (beva->write_in_progress || beva->bev.connecting)
+ return;
+ if (!beva->ok || !(bev->enabled&EV_WRITE) ||
+ !evbuffer_get_length(bev->output)) {
+ bev_async_del_write(beva);
+ return;
+ }
+
+ at_most = evbuffer_get_length(bev->output);
+
+ /* This is safe so long as bufferevent_get_write_max never returns
+ * more than INT_MAX. That's true for now. XXXX */
+ limit = (int)bufferevent_get_write_max_(&beva->bev);
+ if (at_most >= (size_t)limit && limit >= 0)
+ at_most = limit;
+
+ if (beva->bev.write_suspended) {
+ bev_async_del_write(beva);
+ return;
+ }
+
+ /* XXXX doesn't respect low-water mark very well. */
+ bufferevent_incref_(bev);
+ if (evbuffer_launch_write_(bev->output, at_most,
+ &beva->write_overlapped)) {
+ bufferevent_decref_(bev);
+ beva->ok = 0;
+ be_async_run_eventcb(bev, BEV_EVENT_ERROR, 0);
+ } else {
+ beva->write_in_progress = at_most;
+ bufferevent_decrement_write_buckets_(&beva->bev, at_most);
+ bev_async_add_write(beva);
+ }
+}
+
+static void
+bev_async_consider_reading(struct bufferevent_async *beva)
+{
+ size_t cur_size;
+ size_t read_high;
+ size_t at_most;
+ int limit;
+ struct bufferevent *bev = &beva->bev.bev;
+
+ /* Don't read if there is a read in progress, or we do not
+ * want to read. */
+ if (beva->read_in_progress || beva->bev.connecting)
+ return;
+ if (!beva->ok || !(bev->enabled&EV_READ)) {
+ bev_async_del_read(beva);
+ return;
+ }
+
+ /* Don't read if we're full */
+ cur_size = evbuffer_get_length(bev->input);
+ read_high = bev->wm_read.high;
+ if (read_high) {
+ if (cur_size >= read_high) {
+ bev_async_del_read(beva);
+ return;
+ }
+ at_most = read_high - cur_size;
+ } else {
+ at_most = 16384; /* FIXME totally magic. */
+ }
+
+ /* XXXX This over-commits. */
+ /* XXXX see also not above on cast on bufferevent_get_write_max_() */
+ limit = (int)bufferevent_get_read_max_(&beva->bev);
+ if (at_most >= (size_t)limit && limit >= 0)
+ at_most = limit;
+
+ if (beva->bev.read_suspended) {
+ bev_async_del_read(beva);
+ return;
+ }
+
+ bufferevent_incref_(bev);
+ if (evbuffer_launch_read_(bev->input, at_most, &beva->read_overlapped)) {
+ beva->ok = 0;
+ be_async_run_eventcb(bev, BEV_EVENT_ERROR, 0);
+ bufferevent_decref_(bev);
+ } else {
+ beva->read_in_progress = at_most;
+ bufferevent_decrement_read_buckets_(&beva->bev, at_most);
+ bev_async_add_read(beva);
+ }
+
+ return;
+}
+
+static void
+be_async_outbuf_callback(struct evbuffer *buf,
+ const struct evbuffer_cb_info *cbinfo,
+ void *arg)
+{
+ struct bufferevent *bev = arg;
+ struct bufferevent_async *bev_async = upcast(bev);
+
+ /* If we added data to the outbuf and were not writing before,
+ * we may want to write now. */
+
+ bufferevent_incref_and_lock_(bev);
+
+ if (cbinfo->n_added)
+ bev_async_consider_writing(bev_async);
+
+ bufferevent_decref_and_unlock_(bev);
+}
+
+static void
+be_async_inbuf_callback(struct evbuffer *buf,
+ const struct evbuffer_cb_info *cbinfo,
+ void *arg)
+{
+ struct bufferevent *bev = arg;
+ struct bufferevent_async *bev_async = upcast(bev);
+
+ /* If we drained data from the inbuf and were not reading before,
+ * we may want to read now */
+
+ bufferevent_incref_and_lock_(bev);
+
+ if (cbinfo->n_deleted)
+ bev_async_consider_reading(bev_async);
+
+ bufferevent_decref_and_unlock_(bev);
+}
+
+static int
+be_async_enable(struct bufferevent *buf, short what)
+{
+ struct bufferevent_async *bev_async = upcast(buf);
+
+ if (!bev_async->ok)
+ return -1;
+
+ if (bev_async->bev.connecting) {
+ /* Don't launch anything during connection attempts. */
+ return 0;
+ }
+
+ if (what & EV_READ)
+ BEV_RESET_GENERIC_READ_TIMEOUT(buf);
+ if (what & EV_WRITE)
+ BEV_RESET_GENERIC_WRITE_TIMEOUT(buf);
+
+ /* If we newly enable reading or writing, and we aren't reading or
+ writing already, consider launching a new read or write. */
+
+ if (what & EV_READ)
+ bev_async_consider_reading(bev_async);
+ if (what & EV_WRITE)
+ bev_async_consider_writing(bev_async);
+ return 0;
+}
+
+static int
+be_async_disable(struct bufferevent *bev, short what)
+{
+ struct bufferevent_async *bev_async = upcast(bev);
+ /* XXXX If we disable reading or writing, we may want to consider
+ * canceling any in-progress read or write operation, though it might
+ * not work. */
+
+ if (what & EV_READ) {
+ BEV_DEL_GENERIC_READ_TIMEOUT(bev);
+ bev_async_del_read(bev_async);
+ }
+ if (what & EV_WRITE) {
+ BEV_DEL_GENERIC_WRITE_TIMEOUT(bev);
+ bev_async_del_write(bev_async);
+ }
+
+ return 0;
+}
+
+static void
+be_async_destruct(struct bufferevent *bev)
+{
+ struct bufferevent_async *bev_async = upcast(bev);
+ struct bufferevent_private *bev_p = BEV_UPCAST(bev);
+ evutil_socket_t fd;
+
+ EVUTIL_ASSERT(!upcast(bev)->write_in_progress &&
+ !upcast(bev)->read_in_progress);
+
+ bev_async_del_read(bev_async);
+ bev_async_del_write(bev_async);
+
+ fd = evbuffer_overlapped_get_fd_(bev->input);
+ if (fd != (evutil_socket_t)EVUTIL_INVALID_SOCKET &&
+ (bev_p->options & BEV_OPT_CLOSE_ON_FREE)) {
+ evutil_closesocket(fd);
+ evbuffer_overlapped_set_fd_(bev->input, EVUTIL_INVALID_SOCKET);
+ }
+}
+
+/* GetQueuedCompletionStatus doesn't reliably yield WSA error codes, so
+ * we use WSAGetOverlappedResult to translate. */
+static void
+bev_async_set_wsa_error(struct bufferevent *bev, struct event_overlapped *eo)
+{
+ DWORD bytes, flags;
+ evutil_socket_t fd;
+
+ fd = evbuffer_overlapped_get_fd_(bev->input);
+ WSAGetOverlappedResult(fd, &eo->overlapped, &bytes, FALSE, &flags);
+}
+
+static int
+be_async_flush(struct bufferevent *bev, short what,
+ enum bufferevent_flush_mode mode)
+{
+ return 0;
+}
+
+static void
+connect_complete(struct event_overlapped *eo, ev_uintptr_t key,
+ ev_ssize_t nbytes, int ok)
+{
+ struct bufferevent_async *bev_a = upcast_connect(eo);
+ struct bufferevent *bev = &bev_a->bev.bev;
+ evutil_socket_t sock;
+
+ BEV_LOCK(bev);
+
+ EVUTIL_ASSERT(bev_a->bev.connecting);
+ bev_a->bev.connecting = 0;
+ sock = evbuffer_overlapped_get_fd_(bev_a->bev.bev.input);
+ /* XXXX Handle error? */
+ setsockopt(sock, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0);
+
+ if (ok)
+ bufferevent_async_set_connected_(bev);
+ else
+ bev_async_set_wsa_error(bev, eo);
+
+ be_async_run_eventcb(bev, ok ? BEV_EVENT_CONNECTED : BEV_EVENT_ERROR, 0);
+
+ event_base_del_virtual_(bev->ev_base);
+
+ bufferevent_decref_and_unlock_(bev);
+}
+
+static void
+read_complete(struct event_overlapped *eo, ev_uintptr_t key,
+ ev_ssize_t nbytes, int ok)
+{
+ struct bufferevent_async *bev_a = upcast_read(eo);
+ struct bufferevent *bev = &bev_a->bev.bev;
+ short what = BEV_EVENT_READING;
+ ev_ssize_t amount_unread;
+ BEV_LOCK(bev);
+ EVUTIL_ASSERT(bev_a->read_in_progress);
+
+ amount_unread = bev_a->read_in_progress - nbytes;
+ evbuffer_commit_read_(bev->input, nbytes);
+ bev_a->read_in_progress = 0;
+ if (amount_unread)
+ bufferevent_decrement_read_buckets_(&bev_a->bev, -amount_unread);
+
+ if (!ok)
+ bev_async_set_wsa_error(bev, eo);
+
+ if (bev_a->ok) {
+ if (ok && nbytes) {
+ BEV_RESET_GENERIC_READ_TIMEOUT(bev);
+ be_async_trigger_nolock(bev, EV_READ, 0);
+ bev_async_consider_reading(bev_a);
+ } else if (!ok) {
+ what |= BEV_EVENT_ERROR;
+ bev_a->ok = 0;
+ be_async_run_eventcb(bev, what, 0);
+ } else if (!nbytes) {
+ what |= BEV_EVENT_EOF;
+ bev_a->ok = 0;
+ be_async_run_eventcb(bev, what, 0);
+ }
+ }
+
+ bufferevent_decref_and_unlock_(bev);
+}
+
+static void
+write_complete(struct event_overlapped *eo, ev_uintptr_t key,
+ ev_ssize_t nbytes, int ok)
+{
+ struct bufferevent_async *bev_a = upcast_write(eo);
+ struct bufferevent *bev = &bev_a->bev.bev;
+ short what = BEV_EVENT_WRITING;
+ ev_ssize_t amount_unwritten;
+
+ BEV_LOCK(bev);
+ EVUTIL_ASSERT(bev_a->write_in_progress);
+
+ amount_unwritten = bev_a->write_in_progress - nbytes;
+ evbuffer_commit_write_(bev->output, nbytes);
+ bev_a->write_in_progress = 0;
+
+ if (amount_unwritten)
+ bufferevent_decrement_write_buckets_(&bev_a->bev,
+ -amount_unwritten);
+
+
+ if (!ok)
+ bev_async_set_wsa_error(bev, eo);
+
+ if (bev_a->ok) {
+ if (ok && nbytes) {
+ BEV_RESET_GENERIC_WRITE_TIMEOUT(bev);
+ be_async_trigger_nolock(bev, EV_WRITE, 0);
+ bev_async_consider_writing(bev_a);
+ } else if (!ok) {
+ what |= BEV_EVENT_ERROR;
+ bev_a->ok = 0;
+ be_async_run_eventcb(bev, what, 0);
+ } else if (!nbytes) {
+ what |= BEV_EVENT_EOF;
+ bev_a->ok = 0;
+ be_async_run_eventcb(bev, what, 0);
+ }
+ }
+
+ bufferevent_decref_and_unlock_(bev);
+}
+
+struct bufferevent *
+bufferevent_async_new_(struct event_base *base,
+ evutil_socket_t fd, int options)
+{
+ struct bufferevent_async *bev_a;
+ struct bufferevent *bev;
+ struct event_iocp_port *iocp;
+
+ options |= BEV_OPT_THREADSAFE;
+
+ if (!(iocp = event_base_get_iocp_(base)))
+ return NULL;
+
+ if (fd >= 0 && event_iocp_port_associate_(iocp, fd, 1)<0) {
+ if (fatal_error(GetLastError()))
+ return NULL;
+ }
+
+ if (!(bev_a = mm_calloc(1, sizeof(struct bufferevent_async))))
+ return NULL;
+
+ bev = &bev_a->bev.bev;
+ if (!(bev->input = evbuffer_overlapped_new_(fd))) {
+ mm_free(bev_a);
+ return NULL;
+ }
+ if (!(bev->output = evbuffer_overlapped_new_(fd))) {
+ evbuffer_free(bev->input);
+ mm_free(bev_a);
+ return NULL;
+ }
+
+ if (bufferevent_init_common_(&bev_a->bev, base, &bufferevent_ops_async,
+ options)<0)
+ goto err;
+
+ evbuffer_add_cb(bev->input, be_async_inbuf_callback, bev);
+ evbuffer_add_cb(bev->output, be_async_outbuf_callback, bev);
+
+ event_overlapped_init_(&bev_a->connect_overlapped, connect_complete);
+ event_overlapped_init_(&bev_a->read_overlapped, read_complete);
+ event_overlapped_init_(&bev_a->write_overlapped, write_complete);
+
+ bufferevent_init_generic_timeout_cbs_(bev);
+
+ bev_a->ok = fd >= 0;
+
+ return bev;
+err:
+ bufferevent_free(&bev_a->bev.bev);
+ return NULL;
+}
+
+void
+bufferevent_async_set_connected_(struct bufferevent *bev)
+{
+ struct bufferevent_async *bev_async = upcast(bev);
+ bev_async->ok = 1;
+ /* Now's a good time to consider reading/writing */
+ be_async_enable(bev, bev->enabled);
+}
+
+int
+bufferevent_async_can_connect_(struct bufferevent *bev)
+{
+ const struct win32_extension_fns *ext =
+ event_get_win32_extension_fns_();
+
+ if (BEV_IS_ASYNC(bev) &&
+ event_base_get_iocp_(bev->ev_base) &&
+ ext && ext->ConnectEx)
+ return 1;
+
+ return 0;
+}
+
+int
+bufferevent_async_connect_(struct bufferevent *bev, evutil_socket_t fd,
+ const struct sockaddr *sa, int socklen)
+{
+ BOOL rc;
+ struct bufferevent_async *bev_async = upcast(bev);
+ struct sockaddr_storage ss;
+ const struct win32_extension_fns *ext =
+ event_get_win32_extension_fns_();
+
+ EVUTIL_ASSERT(ext && ext->ConnectEx && fd >= 0 && sa != NULL);
+
+ /* ConnectEx() requires that the socket be bound to an address
+ * with bind() before using, otherwise it will fail. We attempt
+ * to issue a bind() here, taking into account that the error
+ * code is set to WSAEINVAL when the socket is already bound. */
+ memset(&ss, 0, sizeof(ss));
+ if (sa->sa_family == AF_INET) {
+ struct sockaddr_in *sin = (struct sockaddr_in *)&ss;
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = INADDR_ANY;
+ } else if (sa->sa_family == AF_INET6) {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss;
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_addr = in6addr_any;
+ } else {
+ /* Well, the user will have to bind() */
+ return -1;
+ }
+ if (bind(fd, (struct sockaddr *)&ss, sizeof(ss)) < 0 &&
+ WSAGetLastError() != WSAEINVAL)
+ return -1;
+
+ event_base_add_virtual_(bev->ev_base);
+ bufferevent_incref_(bev);
+ rc = ext->ConnectEx(fd, sa, socklen, NULL, 0, NULL,
+ &bev_async->connect_overlapped.overlapped);
+ if (rc || WSAGetLastError() == ERROR_IO_PENDING)
+ return 0;
+
+ event_base_del_virtual_(bev->ev_base);
+ bufferevent_decref_(bev);
+
+ return -1;
+}
+
+static int
+be_async_ctrl(struct bufferevent *bev, enum bufferevent_ctrl_op op,
+ union bufferevent_ctrl_data *data)
+{
+ switch (op) {
+ case BEV_CTRL_GET_FD:
+ data->fd = evbuffer_overlapped_get_fd_(bev->input);
+ return 0;
+ case BEV_CTRL_SET_FD: {
+ struct bufferevent_async *bev_a = upcast(bev);
+ struct event_iocp_port *iocp;
+
+ if (data->fd == evbuffer_overlapped_get_fd_(bev->input))
+ return 0;
+ if (!(iocp = event_base_get_iocp_(bev->ev_base)))
+ return -1;
+ if (event_iocp_port_associate_(iocp, data->fd, 1) < 0) {
+ if (fatal_error(GetLastError()))
+ return -1;
+ }
+ evbuffer_overlapped_set_fd_(bev->input, data->fd);
+ evbuffer_overlapped_set_fd_(bev->output, data->fd);
+ bev_a->ok = data->fd >= 0;
+ return 0;
+ }
+ case BEV_CTRL_CANCEL_ALL: {
+ struct bufferevent_async *bev_a = upcast(bev);
+ evutil_socket_t fd = evbuffer_overlapped_get_fd_(bev->input);
+ if (fd != (evutil_socket_t)EVUTIL_INVALID_SOCKET &&
+ (bev_a->bev.options & BEV_OPT_CLOSE_ON_FREE)) {
+ closesocket(fd);
+ evbuffer_overlapped_set_fd_(bev->input, EVUTIL_INVALID_SOCKET);
+ }
+ bev_a->ok = 0;
+ return 0;
+ }
+ case BEV_CTRL_GET_UNDERLYING:
+ default:
+ return -1;
+ }
+}
+
+
diff --git a/contrib/libs/libevent/event_iocp.c b/contrib/libs/libevent/event_iocp.c
new file mode 100644
index 0000000000..6b2a2e15ef
--- /dev/null
+++ b/contrib/libs/libevent/event_iocp.c
@@ -0,0 +1,294 @@
+/*
+ * Copyright (c) 2009-2012 Niels Provos, Nick Mathewson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "evconfig-private.h"
+
+#ifndef _WIN32_WINNT
+/* Minimum required for InitializeCriticalSectionAndSpinCount */
+#define _WIN32_WINNT 0x0403
+#endif
+#include <winsock2.h>
+#include <windows.h>
+#include <process.h>
+#include <stdio.h>
+#include <mswsock.h>
+
+#include "event2/util.h"
+#include "util-internal.h"
+#include "iocp-internal.h"
+#include "log-internal.h"
+#include "mm-internal.h"
+#include "event-internal.h"
+#include "evthread-internal.h"
+
+#define NOTIFICATION_KEY ((ULONG_PTR)-1)
+
+void
+event_overlapped_init_(struct event_overlapped *o, iocp_callback cb)
+{
+ memset(o, 0, sizeof(struct event_overlapped));
+ o->cb = cb;
+}
+
+static void
+handle_entry(OVERLAPPED *o, ULONG_PTR completion_key, DWORD nBytes, int ok)
+{
+ struct event_overlapped *eo =
+ EVUTIL_UPCAST(o, struct event_overlapped, overlapped);
+ eo->cb(eo, completion_key, nBytes, ok);
+}
+
+static void
+loop(void *port_)
+{
+ struct event_iocp_port *port = port_;
+ long ms = port->ms;
+ HANDLE p = port->port;
+
+ if (ms <= 0)
+ ms = INFINITE;
+
+ while (1) {
+ OVERLAPPED *overlapped=NULL;
+ ULONG_PTR key=0;
+ DWORD bytes=0;
+ int ok = GetQueuedCompletionStatus(p, &bytes, &key,
+ &overlapped, ms);
+ EnterCriticalSection(&port->lock);
+ if (port->shutdown) {
+ if (--port->n_live_threads == 0)
+ ReleaseSemaphore(port->shutdownSemaphore, 1,
+ NULL);
+ LeaveCriticalSection(&port->lock);
+ return;
+ }
+ LeaveCriticalSection(&port->lock);
+
+ if (key != NOTIFICATION_KEY && overlapped)
+ handle_entry(overlapped, key, bytes, ok);
+ else if (!overlapped)
+ break;
+ }
+ event_warnx("GetQueuedCompletionStatus exited with no event.");
+ EnterCriticalSection(&port->lock);
+ if (--port->n_live_threads == 0)
+ ReleaseSemaphore(port->shutdownSemaphore, 1, NULL);
+ LeaveCriticalSection(&port->lock);
+}
+
+int
+event_iocp_port_associate_(struct event_iocp_port *port, evutil_socket_t fd,
+ ev_uintptr_t key)
+{
+ HANDLE h;
+ h = CreateIoCompletionPort((HANDLE)fd, port->port, key, port->n_threads);
+ if (!h)
+ return -1;
+ return 0;
+}
+
+static void *
+get_extension_function(SOCKET s, const GUID *which_fn)
+{
+ void *ptr = NULL;
+ DWORD bytes=0;
+ WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER,
+ (GUID*)which_fn, sizeof(*which_fn),
+ &ptr, sizeof(ptr),
+ &bytes, NULL, NULL);
+
+ /* No need to detect errors here: if ptr is set, then we have a good
+ function pointer. Otherwise, we should behave as if we had no
+ function pointer.
+ */
+ return ptr;
+}
+
+/* Mingw doesn't have these in its mswsock.h. The values are copied from
+ wine.h. Perhaps if we copy them exactly, the cargo will come again.
+*/
+#ifndef WSAID_ACCEPTEX
+#define WSAID_ACCEPTEX \
+ {0xb5367df1,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}}
+#endif
+#ifndef WSAID_CONNECTEX
+#define WSAID_CONNECTEX \
+ {0x25a207b9,0xddf3,0x4660,{0x8e,0xe9,0x76,0xe5,0x8c,0x74,0x06,0x3e}}
+#endif
+#ifndef WSAID_GETACCEPTEXSOCKADDRS
+#define WSAID_GETACCEPTEXSOCKADDRS \
+ {0xb5367df2,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}}
+#endif
+
+static int extension_fns_initialized = 0;
+
+static void
+init_extension_functions(struct win32_extension_fns *ext)
+{
+ const GUID acceptex = WSAID_ACCEPTEX;
+ const GUID connectex = WSAID_CONNECTEX;
+ const GUID getacceptexsockaddrs = WSAID_GETACCEPTEXSOCKADDRS;
+ SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
+ if (s == EVUTIL_INVALID_SOCKET)
+ return;
+ ext->AcceptEx = get_extension_function(s, &acceptex);
+ ext->ConnectEx = get_extension_function(s, &connectex);
+ ext->GetAcceptExSockaddrs = get_extension_function(s,
+ &getacceptexsockaddrs);
+ closesocket(s);
+
+ extension_fns_initialized = 1;
+}
+
+static struct win32_extension_fns the_extension_fns;
+
+const struct win32_extension_fns *
+event_get_win32_extension_fns_(void)
+{
+ return &the_extension_fns;
+}
+
+#define N_CPUS_DEFAULT 2
+
+struct event_iocp_port *
+event_iocp_port_launch_(int n_cpus)
+{
+ struct event_iocp_port *port;
+ int i;
+
+ if (!extension_fns_initialized)
+ init_extension_functions(&the_extension_fns);
+
+ if (!(port = mm_calloc(1, sizeof(struct event_iocp_port))))
+ return NULL;
+
+ if (n_cpus <= 0)
+ n_cpus = N_CPUS_DEFAULT;
+ port->n_threads = n_cpus * 2;
+ port->threads = mm_calloc(port->n_threads, sizeof(HANDLE));
+ if (!port->threads)
+ goto err;
+
+ port->port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0,
+ n_cpus);
+ port->ms = -1;
+ if (!port->port)
+ goto err;
+
+ port->shutdownSemaphore = CreateSemaphore(NULL, 0, 1, NULL);
+ if (!port->shutdownSemaphore)
+ goto err;
+
+ for (i=0; i<port->n_threads; ++i) {
+ ev_uintptr_t th = _beginthread(loop, 0, port);
+ if (th == (ev_uintptr_t)-1)
+ goto err;
+ port->threads[i] = (HANDLE)th;
+ ++port->n_live_threads;
+ }
+
+ InitializeCriticalSectionAndSpinCount(&port->lock, 1000);
+
+ return port;
+err:
+ if (port->port)
+ CloseHandle(port->port);
+ if (port->threads)
+ mm_free(port->threads);
+ if (port->shutdownSemaphore)
+ CloseHandle(port->shutdownSemaphore);
+ mm_free(port);
+ return NULL;
+}
+
+static void
+event_iocp_port_unlock_and_free_(struct event_iocp_port *port)
+{
+ DeleteCriticalSection(&port->lock);
+ CloseHandle(port->port);
+ CloseHandle(port->shutdownSemaphore);
+ mm_free(port->threads);
+ mm_free(port);
+}
+
+static int
+event_iocp_notify_all(struct event_iocp_port *port)
+{
+ int i, r, ok=1;
+ for (i=0; i<port->n_threads; ++i) {
+ r = PostQueuedCompletionStatus(port->port, 0, NOTIFICATION_KEY,
+ NULL);
+ if (!r)
+ ok = 0;
+ }
+ return ok ? 0 : -1;
+}
+
+int
+event_iocp_shutdown_(struct event_iocp_port *port, long waitMsec)
+{
+ DWORD ms = INFINITE;
+ int n;
+
+ EnterCriticalSection(&port->lock);
+ port->shutdown = 1;
+ LeaveCriticalSection(&port->lock);
+ event_iocp_notify_all(port);
+
+ if (waitMsec >= 0)
+ ms = waitMsec;
+
+ WaitForSingleObject(port->shutdownSemaphore, ms);
+ EnterCriticalSection(&port->lock);
+ n = port->n_live_threads;
+ LeaveCriticalSection(&port->lock);
+ if (n == 0) {
+ event_iocp_port_unlock_and_free_(port);
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+int
+event_iocp_activate_overlapped_(
+ struct event_iocp_port *port, struct event_overlapped *o,
+ ev_uintptr_t key, ev_uint32_t n)
+{
+ BOOL r;
+
+ r = PostQueuedCompletionStatus(port->port, n, key, &o->overlapped);
+ return (r==0) ? -1 : 0;
+}
+
+struct event_iocp_port *
+event_base_get_iocp_(struct event_base *base)
+{
+#ifdef _WIN32
+ return base->iocp;
+#else
+ return NULL;
+#endif
+}
diff --git a/contrib/libs/libevent/evthread_win32.c b/contrib/libs/libevent/evthread_win32.c
new file mode 100644
index 0000000000..2ec80560a5
--- /dev/null
+++ b/contrib/libs/libevent/evthread_win32.c
@@ -0,0 +1,341 @@
+/*
+ * Copyright 2009-2012 Niels Provos and Nick Mathewson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "event2/event-config.h"
+#include "evconfig-private.h"
+
+#ifdef _WIN32
+#ifndef _WIN32_WINNT
+/* Minimum required for InitializeCriticalSectionAndSpinCount */
+#define _WIN32_WINNT 0x0403
+#endif
+#include <winsock2.h>
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+#include <sys/locking.h>
+#endif
+
+struct event_base;
+#include "event2/thread.h"
+
+#include "mm-internal.h"
+#include "evthread-internal.h"
+#include "time-internal.h"
+
+#define SPIN_COUNT 2000
+
+static void *
+evthread_win32_lock_create(unsigned locktype)
+{
+ CRITICAL_SECTION *lock = mm_malloc(sizeof(CRITICAL_SECTION));
+ if (!lock)
+ return NULL;
+ if (InitializeCriticalSectionAndSpinCount(lock, SPIN_COUNT) == 0) {
+ mm_free(lock);
+ return NULL;
+ }
+ return lock;
+}
+
+static void
+evthread_win32_lock_free(void *lock_, unsigned locktype)
+{
+ CRITICAL_SECTION *lock = lock_;
+ DeleteCriticalSection(lock);
+ mm_free(lock);
+}
+
+static int
+evthread_win32_lock(unsigned mode, void *lock_)
+{
+ CRITICAL_SECTION *lock = lock_;
+ if ((mode & EVTHREAD_TRY)) {
+ return ! TryEnterCriticalSection(lock);
+ } else {
+ EnterCriticalSection(lock);
+ return 0;
+ }
+}
+
+static int
+evthread_win32_unlock(unsigned mode, void *lock_)
+{
+ CRITICAL_SECTION *lock = lock_;
+ LeaveCriticalSection(lock);
+ return 0;
+}
+
+static unsigned long
+evthread_win32_get_id(void)
+{
+ return (unsigned long) GetCurrentThreadId();
+}
+
+#ifdef WIN32_HAVE_CONDITION_VARIABLES
+static void WINAPI (*InitializeConditionVariable_fn)(PCONDITION_VARIABLE)
+ = NULL;
+static BOOL WINAPI (*SleepConditionVariableCS_fn)(
+ PCONDITION_VARIABLE, PCRITICAL_SECTION, DWORD) = NULL;
+static void WINAPI (*WakeAllConditionVariable_fn)(PCONDITION_VARIABLE) = NULL;
+static void WINAPI (*WakeConditionVariable_fn)(PCONDITION_VARIABLE) = NULL;
+
+static int
+evthread_win32_condvar_init(void)
+{
+ HANDLE lib;
+
+ lib = GetModuleHandle(TEXT("kernel32.dll"));
+ if (lib == NULL)
+ return 0;
+
+#define LOAD(name) \
+ name##_fn = GetProcAddress(lib, #name)
+ LOAD(InitializeConditionVariable);
+ LOAD(SleepConditionVariableCS);
+ LOAD(WakeAllConditionVariable);
+ LOAD(WakeConditionVariable);
+
+ return InitializeConditionVariable_fn && SleepConditionVariableCS_fn &&
+ WakeAllConditionVariable_fn && WakeConditionVariable_fn;
+}
+
+/* XXXX Even if we can build this, we don't necessarily want to: the functions
+ * in question didn't exist before Vista, so we'd better LoadProc them. */
+static void *
+evthread_win32_condvar_alloc(unsigned condflags)
+{
+ CONDITION_VARIABLE *cond = mm_malloc(sizeof(CONDITION_VARIABLE));
+ if (!cond)
+ return NULL;
+ InitializeConditionVariable_fn(cond);
+ return cond;
+}
+
+static void
+evthread_win32_condvar_free(void *cond_)
+{
+ CONDITION_VARIABLE *cond = cond_;
+ /* There doesn't _seem_ to be a cleaup fn here... */
+ mm_free(cond);
+}
+
+static int
+evthread_win32_condvar_signal(void *cond, int broadcast)
+{
+ CONDITION_VARIABLE *cond = cond_;
+ if (broadcast)
+ WakeAllConditionVariable_fn(cond);
+ else
+ WakeConditionVariable_fn(cond);
+ return 0;
+}
+
+static int
+evthread_win32_condvar_wait(void *cond_, void *lock_, const struct timeval *tv)
+{
+ CONDITION_VARIABLE *cond = cond_;
+ CRITICAL_SECTION *lock = lock_;
+ DWORD ms, err;
+ BOOL result;
+
+ if (tv)
+ ms = evutil_tv_to_msec_(tv);
+ else
+ ms = INFINITE;
+ result = SleepConditionVariableCS_fn(cond, lock, ms);
+ if (result) {
+ if (GetLastError() == WAIT_TIMEOUT)
+ return 1;
+ else
+ return -1;
+ } else {
+ return 0;
+ }
+}
+#endif
+
+struct evthread_win32_cond {
+ HANDLE event;
+
+ CRITICAL_SECTION lock;
+ int n_waiting;
+ int n_to_wake;
+ int generation;
+};
+
+static void *
+evthread_win32_cond_alloc(unsigned flags)
+{
+ struct evthread_win32_cond *cond;
+ if (!(cond = mm_malloc(sizeof(struct evthread_win32_cond))))
+ return NULL;
+ if (InitializeCriticalSectionAndSpinCount(&cond->lock, SPIN_COUNT)==0) {
+ mm_free(cond);
+ return NULL;
+ }
+ if ((cond->event = CreateEvent(NULL,TRUE,FALSE,NULL)) == NULL) {
+ DeleteCriticalSection(&cond->lock);
+ mm_free(cond);
+ return NULL;
+ }
+ cond->n_waiting = cond->n_to_wake = cond->generation = 0;
+ return cond;
+}
+
+static void
+evthread_win32_cond_free(void *cond_)
+{
+ struct evthread_win32_cond *cond = cond_;
+ DeleteCriticalSection(&cond->lock);
+ CloseHandle(cond->event);
+ mm_free(cond);
+}
+
+static int
+evthread_win32_cond_signal(void *cond_, int broadcast)
+{
+ struct evthread_win32_cond *cond = cond_;
+ EnterCriticalSection(&cond->lock);
+ if (broadcast)
+ cond->n_to_wake = cond->n_waiting;
+ else
+ ++cond->n_to_wake;
+ cond->generation++;
+ SetEvent(cond->event);
+ LeaveCriticalSection(&cond->lock);
+ return 0;
+}
+
+static int
+evthread_win32_cond_wait(void *cond_, void *lock_, const struct timeval *tv)
+{
+ struct evthread_win32_cond *cond = cond_;
+ CRITICAL_SECTION *lock = lock_;
+ int generation_at_start;
+ int waiting = 1;
+ int result = -1;
+ DWORD ms = INFINITE, ms_orig = INFINITE, startTime, endTime;
+ if (tv)
+ ms_orig = ms = evutil_tv_to_msec_(tv);
+
+ EnterCriticalSection(&cond->lock);
+ ++cond->n_waiting;
+ generation_at_start = cond->generation;
+ LeaveCriticalSection(&cond->lock);
+
+ LeaveCriticalSection(lock);
+
+ startTime = GetTickCount();
+ do {
+ DWORD res;
+ res = WaitForSingleObject(cond->event, ms);
+ EnterCriticalSection(&cond->lock);
+ if (cond->n_to_wake &&
+ cond->generation != generation_at_start) {
+ --cond->n_to_wake;
+ --cond->n_waiting;
+ result = 0;
+ waiting = 0;
+ goto out;
+ } else if (res != WAIT_OBJECT_0) {
+ result = (res==WAIT_TIMEOUT) ? 1 : -1;
+ --cond->n_waiting;
+ waiting = 0;
+ goto out;
+ } else if (ms != INFINITE) {
+ endTime = GetTickCount();
+ if (startTime + ms_orig <= endTime) {
+ result = 1; /* Timeout */
+ --cond->n_waiting;
+ waiting = 0;
+ goto out;
+ } else {
+ ms = startTime + ms_orig - endTime;
+ }
+ }
+ /* If we make it here, we are still waiting. */
+ if (cond->n_to_wake == 0) {
+ /* There is nobody else who should wake up; reset
+ * the event. */
+ ResetEvent(cond->event);
+ }
+ out:
+ LeaveCriticalSection(&cond->lock);
+ } while (waiting);
+
+ EnterCriticalSection(lock);
+
+ EnterCriticalSection(&cond->lock);
+ if (!cond->n_waiting)
+ ResetEvent(cond->event);
+ LeaveCriticalSection(&cond->lock);
+
+ return result;
+}
+
+int
+evthread_use_windows_threads(void)
+{
+ struct evthread_lock_callbacks cbs = {
+ EVTHREAD_LOCK_API_VERSION,
+ EVTHREAD_LOCKTYPE_RECURSIVE,
+ evthread_win32_lock_create,
+ evthread_win32_lock_free,
+ evthread_win32_lock,
+ evthread_win32_unlock
+ };
+
+
+ struct evthread_condition_callbacks cond_cbs = {
+ EVTHREAD_CONDITION_API_VERSION,
+ evthread_win32_cond_alloc,
+ evthread_win32_cond_free,
+ evthread_win32_cond_signal,
+ evthread_win32_cond_wait
+ };
+#ifdef WIN32_HAVE_CONDITION_VARIABLES
+ struct evthread_condition_callbacks condvar_cbs = {
+ EVTHREAD_CONDITION_API_VERSION,
+ evthread_win32_condvar_alloc,
+ evthread_win32_condvar_free,
+ evthread_win32_condvar_signal,
+ evthread_win32_condvar_wait
+ };
+#endif
+
+ evthread_set_lock_callbacks(&cbs);
+ evthread_set_id_callback(evthread_win32_get_id);
+#ifdef WIN32_HAVE_CONDITION_VARIABLES
+ if (evthread_win32_condvar_init()) {
+ evthread_set_condition_callbacks(&condvar_cbs);
+ return 0;
+ }
+#endif
+ evthread_set_condition_callbacks(&cond_cbs);
+
+ return 0;
+}
+
diff --git a/contrib/libs/libevent/win32select.c b/contrib/libs/libevent/win32select.c
new file mode 100644
index 0000000000..d005b587d4
--- /dev/null
+++ b/contrib/libs/libevent/win32select.c
@@ -0,0 +1,389 @@
+/*
+ * Copyright 2007-2012 Niels Provos and Nick Mathewson
+ * Copyright 2000-2007 Niels Provos <provos@citi.umich.edu>
+ * Copyright 2003 Michael A. Davis <mike@datanerds.net>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "event2/event-config.h"
+#include "evconfig-private.h"
+
+#ifdef _WIN32
+
+#include <winsock2.h>
+#include <windows.h>
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "event2/util.h"
+#include "util-internal.h"
+#include "log-internal.h"
+#include "event2/event.h"
+#include "event-internal.h"
+#include "evmap-internal.h"
+#include "event2/thread.h"
+#include "evthread-internal.h"
+#include "time-internal.h"
+
+#define XFREE(ptr) do { if (ptr) mm_free(ptr); } while (0)
+
+extern struct event_list timequeue;
+extern struct event_list addqueue;
+
+struct win_fd_set {
+ unsigned int fd_count;
+ SOCKET fd_array[1];
+};
+
+/* MSDN says this is required to handle SIGFPE */
+volatile double SIGFPE_REQ = 0.0f;
+
+struct idx_info {
+ int read_pos_plus1;
+ int write_pos_plus1;
+};
+
+struct win32op {
+ unsigned num_fds_in_fd_sets;
+ int resize_out_sets;
+ struct win_fd_set *readset_in;
+ struct win_fd_set *writeset_in;
+ struct win_fd_set *readset_out;
+ struct win_fd_set *writeset_out;
+ struct win_fd_set *exset_out;
+ unsigned signals_are_broken : 1;
+};
+
+static void *win32_init(struct event_base *);
+static int win32_add(struct event_base *, evutil_socket_t, short old, short events, void *idx_);
+static int win32_del(struct event_base *, evutil_socket_t, short old, short events, void *idx_);
+static int win32_dispatch(struct event_base *base, struct timeval *);
+static void win32_dealloc(struct event_base *);
+
+struct eventop win32ops = {
+ "win32",
+ win32_init,
+ win32_add,
+ win32_del,
+ win32_dispatch,
+ win32_dealloc,
+ 0, /* doesn't need reinit */
+ 0, /* No features supported. */
+ sizeof(struct idx_info),
+};
+
+#define FD_SET_ALLOC_SIZE(n) ((sizeof(struct win_fd_set) + ((n)-1)*sizeof(SOCKET)))
+
+static int
+grow_fd_sets(struct win32op *op, unsigned new_num_fds)
+{
+ size_t size;
+
+ EVUTIL_ASSERT(new_num_fds >= op->readset_in->fd_count &&
+ new_num_fds >= op->writeset_in->fd_count);
+ EVUTIL_ASSERT(new_num_fds >= 1);
+
+ size = FD_SET_ALLOC_SIZE(new_num_fds);
+ if (!(op->readset_in = mm_realloc(op->readset_in, size)))
+ return (-1);
+ if (!(op->writeset_in = mm_realloc(op->writeset_in, size)))
+ return (-1);
+ op->resize_out_sets = 1;
+ op->num_fds_in_fd_sets = new_num_fds;
+ return (0);
+}
+
+static int
+do_fd_set(struct win32op *op, struct idx_info *ent, evutil_socket_t s, int read)
+{
+ struct win_fd_set *set = read ? op->readset_in : op->writeset_in;
+ if (read) {
+ if (ent->read_pos_plus1 > 0)
+ return (0);
+ } else {
+ if (ent->write_pos_plus1 > 0)
+ return (0);
+ }
+ if (set->fd_count == op->num_fds_in_fd_sets) {
+ if (grow_fd_sets(op, op->num_fds_in_fd_sets*2))
+ return (-1);
+ /* set pointer will have changed and needs reiniting! */
+ set = read ? op->readset_in : op->writeset_in;
+ }
+ set->fd_array[set->fd_count] = s;
+ if (read)
+ ent->read_pos_plus1 = set->fd_count+1;
+ else
+ ent->write_pos_plus1 = set->fd_count+1;
+ return (set->fd_count++);
+}
+
+static int
+do_fd_clear(struct event_base *base,
+ struct win32op *op, struct idx_info *ent, int read)
+{
+ int i;
+ struct win_fd_set *set = read ? op->readset_in : op->writeset_in;
+ if (read) {
+ i = ent->read_pos_plus1 - 1;
+ ent->read_pos_plus1 = 0;
+ } else {
+ i = ent->write_pos_plus1 - 1;
+ ent->write_pos_plus1 = 0;
+ }
+ if (i < 0)
+ return (0);
+ if (--set->fd_count != (unsigned)i) {
+ struct idx_info *ent2;
+ SOCKET s2;
+ s2 = set->fd_array[i] = set->fd_array[set->fd_count];
+
+ ent2 = evmap_io_get_fdinfo_(&base->io, s2);
+
+ if (!ent2) /* This indicates a bug. */
+ return (0);
+ if (read)
+ ent2->read_pos_plus1 = i+1;
+ else
+ ent2->write_pos_plus1 = i+1;
+ }
+ return (0);
+}
+
+#define NEVENT 32
+void *
+win32_init(struct event_base *base)
+{
+ struct win32op *winop;
+ size_t size;
+ if (!(winop = mm_calloc(1, sizeof(struct win32op))))
+ return NULL;
+ winop->num_fds_in_fd_sets = NEVENT;
+ size = FD_SET_ALLOC_SIZE(NEVENT);
+ if (!(winop->readset_in = mm_malloc(size)))
+ goto err;
+ if (!(winop->writeset_in = mm_malloc(size)))
+ goto err;
+ if (!(winop->readset_out = mm_malloc(size)))
+ goto err;
+ if (!(winop->writeset_out = mm_malloc(size)))
+ goto err;
+ if (!(winop->exset_out = mm_malloc(size)))
+ goto err;
+ winop->readset_in->fd_count = winop->writeset_in->fd_count = 0;
+ winop->readset_out->fd_count = winop->writeset_out->fd_count
+ = winop->exset_out->fd_count = 0;
+
+ if (evsig_init_(base) < 0)
+ winop->signals_are_broken = 1;
+
+ evutil_weakrand_seed_(&base->weakrand_seed, 0);
+
+ return (winop);
+ err:
+ XFREE(winop->readset_in);
+ XFREE(winop->writeset_in);
+ XFREE(winop->readset_out);
+ XFREE(winop->writeset_out);
+ XFREE(winop->exset_out);
+ XFREE(winop);
+ return (NULL);
+}
+
+int
+win32_add(struct event_base *base, evutil_socket_t fd,
+ short old, short events, void *idx_)
+{
+ struct win32op *win32op = base->evbase;
+ struct idx_info *idx = idx_;
+
+ if ((events & EV_SIGNAL) && win32op->signals_are_broken)
+ return (-1);
+
+ if (!(events & (EV_READ|EV_WRITE)))
+ return (0);
+
+ event_debug(("%s: adding event for %d", __func__, (int)fd));
+ if (events & EV_READ) {
+ if (do_fd_set(win32op, idx, fd, 1)<0)
+ return (-1);
+ }
+ if (events & EV_WRITE) {
+ if (do_fd_set(win32op, idx, fd, 0)<0)
+ return (-1);
+ }
+ return (0);
+}
+
+int
+win32_del(struct event_base *base, evutil_socket_t fd, short old, short events,
+ void *idx_)
+{
+ struct win32op *win32op = base->evbase;
+ struct idx_info *idx = idx_;
+
+ event_debug(("%s: Removing event for "EV_SOCK_FMT,
+ __func__, EV_SOCK_ARG(fd)));
+ if (events & EV_READ)
+ do_fd_clear(base, win32op, idx, 1);
+ if (events & EV_WRITE)
+ do_fd_clear(base, win32op, idx, 0);
+
+ return 0;
+}
+
+static void
+fd_set_copy(struct win_fd_set *out, const struct win_fd_set *in)
+{
+ out->fd_count = in->fd_count;
+ memcpy(out->fd_array, in->fd_array, in->fd_count * (sizeof(SOCKET)));
+}
+
+/*
+ static void dump_fd_set(struct win_fd_set *s)
+ {
+ unsigned int i;
+ printf("[ ");
+ for(i=0;i<s->fd_count;++i)
+ printf("%d ",(int)s->fd_array[i]);
+ printf("]\n");
+ }
+*/
+
+int
+win32_dispatch(struct event_base *base, struct timeval *tv)
+{
+ struct win32op *win32op = base->evbase;
+ int res = 0;
+ unsigned j, i;
+ int fd_count;
+ SOCKET s;
+
+ if (win32op->resize_out_sets) {
+ size_t size = FD_SET_ALLOC_SIZE(win32op->num_fds_in_fd_sets);
+ if (!(win32op->readset_out = mm_realloc(win32op->readset_out, size)))
+ return (-1);
+ if (!(win32op->exset_out = mm_realloc(win32op->exset_out, size)))
+ return (-1);
+ if (!(win32op->writeset_out = mm_realloc(win32op->writeset_out, size)))
+ return (-1);
+ win32op->resize_out_sets = 0;
+ }
+
+ fd_set_copy(win32op->readset_out, win32op->readset_in);
+ fd_set_copy(win32op->exset_out, win32op->writeset_in);
+ fd_set_copy(win32op->writeset_out, win32op->writeset_in);
+
+ fd_count =
+ (win32op->readset_out->fd_count > win32op->writeset_out->fd_count) ?
+ win32op->readset_out->fd_count : win32op->writeset_out->fd_count;
+
+ if (!fd_count) {
+ long msec = tv ? evutil_tv_to_msec_(tv) : LONG_MAX;
+ /* Sleep's DWORD argument is unsigned long */
+ if (msec < 0)
+ msec = LONG_MAX;
+ /* Windows doesn't like you to call select() with no sockets */
+ Sleep(msec);
+ return (0);
+ }
+
+ EVBASE_RELEASE_LOCK(base, th_base_lock);
+
+ res = select(fd_count,
+ (struct fd_set*)win32op->readset_out,
+ (struct fd_set*)win32op->writeset_out,
+ (struct fd_set*)win32op->exset_out, tv);
+
+ EVBASE_ACQUIRE_LOCK(base, th_base_lock);
+
+ event_debug(("%s: select returned %d", __func__, res));
+
+ if (res <= 0) {
+ event_debug(("%s: %s", __func__,
+ evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR())));
+ return res;
+ }
+
+ if (win32op->readset_out->fd_count) {
+ i = evutil_weakrand_range_(&base->weakrand_seed,
+ win32op->readset_out->fd_count);
+ for (j=0; j<win32op->readset_out->fd_count; ++j) {
+ if (++i >= win32op->readset_out->fd_count)
+ i = 0;
+ s = win32op->readset_out->fd_array[i];
+ evmap_io_active_(base, s, EV_READ);
+ }
+ }
+ if (win32op->exset_out->fd_count) {
+ i = evutil_weakrand_range_(&base->weakrand_seed,
+ win32op->exset_out->fd_count);
+ for (j=0; j<win32op->exset_out->fd_count; ++j) {
+ if (++i >= win32op->exset_out->fd_count)
+ i = 0;
+ s = win32op->exset_out->fd_array[i];
+ evmap_io_active_(base, s, EV_WRITE);
+ }
+ }
+ if (win32op->writeset_out->fd_count) {
+ i = evutil_weakrand_range_(&base->weakrand_seed,
+ win32op->writeset_out->fd_count);
+ for (j=0; j<win32op->writeset_out->fd_count; ++j) {
+ if (++i >= win32op->writeset_out->fd_count)
+ i = 0;
+ s = win32op->writeset_out->fd_array[i];
+ evmap_io_active_(base, s, EV_WRITE);
+ }
+ }
+ return (0);
+}
+
+void
+win32_dealloc(struct event_base *base)
+{
+ struct win32op *win32op = base->evbase;
+
+ evsig_dealloc_(base);
+ if (win32op->readset_in)
+ mm_free(win32op->readset_in);
+ if (win32op->writeset_in)
+ mm_free(win32op->writeset_in);
+ if (win32op->readset_out)
+ mm_free(win32op->readset_out);
+ if (win32op->writeset_out)
+ mm_free(win32op->writeset_out);
+ if (win32op->exset_out)
+ mm_free(win32op->exset_out);
+ /* XXXXX free the tree. */
+
+ memset(win32op, 0, sizeof(*win32op));
+ mm_free(win32op);
+}
+
+#endif
diff --git a/contrib/libs/libfuzzer/standalone/StandaloneFuzzTargetMain.c b/contrib/libs/libfuzzer/standalone/StandaloneFuzzTargetMain.c
new file mode 100644
index 0000000000..0417cc43f7
--- /dev/null
+++ b/contrib/libs/libfuzzer/standalone/StandaloneFuzzTargetMain.c
@@ -0,0 +1,46 @@
+/*===- StandaloneFuzzTargetMain.c - standalone main() for fuzz targets. ---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// This main() function can be linked to a fuzz target (i.e. a library
+// that exports LLVMFuzzerTestOneInput() and possibly LLVMFuzzerInitialize())
+// instead of libFuzzer. This main() function will not perform any fuzzing
+// but will simply feed all input files one by one to the fuzz target.
+//
+// Use this file to provide reproducers for bugs when linking against libFuzzer
+// or other fuzzing engine is undesirable.
+//===----------------------------------------------------------------------===*/
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size);
+#ifndef _MSC_VER
+__attribute__((weak))
+extern int LLVMFuzzerInitialize(int *argc, char ***argv);
+#endif
+int main(int argc, char **argv) {
+ fprintf(stderr, "StandaloneFuzzTargetMain: running %d inputs\n", argc - 1);
+#ifndef _MSC_VER
+ if (LLVMFuzzerInitialize)
+ LLVMFuzzerInitialize(&argc, &argv);
+#endif
+ for (int i = 1; i < argc; i++) {
+ fprintf(stderr, "Running: %s\n", argv[i]);
+ FILE *f = fopen(argv[i], "r");
+ assert(f);
+ fseek(f, 0, SEEK_END);
+ size_t len = ftell(f);
+ fseek(f, 0, SEEK_SET);
+ unsigned char *buf = (unsigned char*)malloc(len);
+ size_t n_read = fread(buf, 1, len, f);
+ fclose(f);
+ assert(n_read == len);
+ LLVMFuzzerTestOneInput(buf, len);
+ free(buf);
+ fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read);
+ }
+}
diff --git a/contrib/libs/poco/Foundation/src/EventLogChannel.cpp b/contrib/libs/poco/Foundation/src/EventLogChannel.cpp
new file mode 100644
index 0000000000..5e95f6d1b6
--- /dev/null
+++ b/contrib/libs/poco/Foundation/src/EventLogChannel.cpp
@@ -0,0 +1,327 @@
+//
+// EventLogChannel.cpp
+//
+// Library: Foundation
+// Package: Logging
+// Module: EventLogChannel
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#include "Poco/EventLogChannel.h"
+#include "Poco/Message.h"
+#include "Poco/String.h"
+#include "pocomsg.h"
+#if defined(POCO_WIN32_UTF8)
+#include "Poco/UnicodeConverter.h"
+#endif
+
+
+namespace Poco {
+
+
+const std::string EventLogChannel::PROP_NAME = "name";
+const std::string EventLogChannel::PROP_HOST = "host";
+const std::string EventLogChannel::PROP_LOGHOST = "loghost";
+const std::string EventLogChannel::PROP_LOGFILE = "logfile";
+
+
+EventLogChannel::EventLogChannel():
+ _logFile("Application"),
+ _h(0)
+{
+ const DWORD maxPathLen = MAX_PATH + 1;
+#if defined(POCO_WIN32_UTF8)
+ wchar_t name[maxPathLen];
+ int n = GetModuleFileNameW(NULL, name, maxPathLen);
+ if (n > 0)
+ {
+ wchar_t* end = name + n - 1;
+ while (end > name && *end != '\\') --end;
+ if (*end == '\\') ++end;
+ std::wstring uname(end);
+ UnicodeConverter::toUTF8(uname, _name);
+ }
+#else
+ char name[maxPathLen];
+ int n = GetModuleFileNameA(NULL, name, maxPathLen);
+ if (n > 0)
+ {
+ char* end = name + n - 1;
+ while (end > name && *end != '\\') --end;
+ if (*end == '\\') ++end;
+ _name = end;
+ }
+#endif
+}
+
+
+EventLogChannel::EventLogChannel(const std::string& name):
+ _name(name),
+ _logFile("Application"),
+ _h(0)
+{
+}
+
+
+EventLogChannel::EventLogChannel(const std::string& name, const std::string& host):
+ _name(name),
+ _host(host),
+ _logFile("Application"),
+ _h(0)
+{
+}
+
+
+EventLogChannel::~EventLogChannel()
+{
+ try
+ {
+ close();
+ }
+ catch (...)
+ {
+ poco_unexpected();
+ }
+}
+
+
+void EventLogChannel::open()
+{
+ setUpRegistry();
+#if defined(POCO_WIN32_UTF8)
+ std::wstring uhost;
+ UnicodeConverter::toUTF16(_host, uhost);
+ std::wstring uname;
+ UnicodeConverter::toUTF16(_name, uname);
+ _h = RegisterEventSourceW(uhost.empty() ? NULL : uhost.c_str(), uname.c_str());
+#else
+ _h = RegisterEventSource(_host.empty() ? NULL : _host.c_str(), _name.c_str());
+#endif
+ if (!_h) throw SystemException("cannot register event source");
+}
+
+
+void EventLogChannel::close()
+{
+ if (_h) DeregisterEventSource(_h);
+ _h = 0;
+}
+
+
+void EventLogChannel::log(const Message& msg)
+{
+ if (!_h) open();
+#if defined(POCO_WIN32_UTF8)
+ std::wstring utext;
+ UnicodeConverter::toUTF16(msg.getText(), utext);
+ const wchar_t* pMsg = utext.c_str();
+ ReportEventW(_h,
+ static_cast<WORD>(getType(msg)),
+ static_cast<WORD>(getCategory(msg)),
+ POCO_MSG_LOG,
+ NULL,
+ 1,
+ 0,
+ &pMsg,
+ NULL);
+#else
+ const char* pMsg = msg.getText().c_str();
+ ReportEvent(_h, getType(msg), getCategory(msg), POCO_MSG_LOG, NULL, 1, 0, &pMsg, NULL);
+#endif
+}
+
+
+void EventLogChannel::setProperty(const std::string& name, const std::string& value)
+{
+ if (icompare(name, PROP_NAME) == 0)
+ _name = value;
+ else if (icompare(name, PROP_HOST) == 0)
+ _host = value;
+ else if (icompare(name, PROP_LOGHOST) == 0)
+ _host = value;
+ else if (icompare(name, PROP_LOGFILE) == 0)
+ _logFile = value;
+ else
+ Channel::setProperty(name, value);
+}
+
+
+std::string EventLogChannel::getProperty(const std::string& name) const
+{
+ if (icompare(name, PROP_NAME) == 0)
+ return _name;
+ else if (icompare(name, PROP_HOST) == 0)
+ return _host;
+ else if (icompare(name, PROP_LOGHOST) == 0)
+ return _host;
+ else if (icompare(name, PROP_LOGFILE) == 0)
+ return _logFile;
+ else
+ return Channel::getProperty(name);
+}
+
+
+int EventLogChannel::getType(const Message& msg)
+{
+ switch (msg.getPriority())
+ {
+ case Message::PRIO_TRACE:
+ case Message::PRIO_DEBUG:
+ case Message::PRIO_INFORMATION:
+ return EVENTLOG_INFORMATION_TYPE;
+ case Message::PRIO_NOTICE:
+ case Message::PRIO_WARNING:
+ return EVENTLOG_WARNING_TYPE;
+ default:
+ return EVENTLOG_ERROR_TYPE;
+ }
+}
+
+
+int EventLogChannel::getCategory(const Message& msg)
+{
+ switch (msg.getPriority())
+ {
+ case Message::PRIO_TRACE:
+ return POCO_CTG_TRACE;
+ case Message::PRIO_DEBUG:
+ return POCO_CTG_DEBUG;
+ case Message::PRIO_INFORMATION:
+ return POCO_CTG_INFORMATION;
+ case Message::PRIO_NOTICE:
+ return POCO_CTG_NOTICE;
+ case Message::PRIO_WARNING:
+ return POCO_CTG_WARNING;
+ case Message::PRIO_ERROR:
+ return POCO_CTG_ERROR;
+ case Message::PRIO_CRITICAL:
+ return POCO_CTG_CRITICAL;
+ case Message::PRIO_FATAL:
+ return POCO_CTG_FATAL;
+ default:
+ return 0;
+ }
+}
+
+
+void EventLogChannel::setUpRegistry() const
+{
+ std::string key = "SYSTEM\\CurrentControlSet\\Services\\EventLog\\";
+ key.append(_logFile);
+ key.append("\\");
+ key.append(_name);
+ HKEY hKey;
+ DWORD disp;
+#if defined(POCO_WIN32_UTF8)
+ std::wstring ukey;
+ UnicodeConverter::toUTF16(key, ukey);
+ DWORD rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, ukey.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &disp);
+#else
+ DWORD rc = RegCreateKeyEx(HKEY_LOCAL_MACHINE, key.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &disp);
+#endif
+ if (rc != ERROR_SUCCESS) return;
+
+ if (disp == REG_CREATED_NEW_KEY)
+ {
+#if defined(POCO_WIN32_UTF8)
+ std::wstring path;
+ #if defined(POCO_DLL)
+ #if defined(_DEBUG)
+ #if defined(_WIN64)
+ path = findLibrary(L"PocoFoundation64d.dll");
+ #else
+ path = findLibrary(L"PocoFoundationd.dll");
+ #endif
+ #else
+ #if defined(_WIN64)
+ path = findLibrary(L"PocoFoundation64.dll");
+ #else
+ path = findLibrary(L"PocoFoundation.dll");
+ #endif
+ #endif
+ #endif
+
+ if (path.empty())
+ path = findLibrary(L"PocoMsg.dll");
+#else
+ std::string path;
+ #if defined(POCO_DLL)
+ #if defined(_DEBUG)
+ #if defined(_WIN64)
+ path = findLibrary("PocoFoundation64d.dll");
+ #else
+ path = findLibrary("PocoFoundationd.dll");
+ #endif
+ #else
+ #if defined(_WIN64)
+ path = findLibrary("PocoFoundation64.dll");
+ #else
+ path = findLibrary("PocoFoundation.dll");
+ #endif
+ #endif
+ #endif
+
+ if (path.empty())
+ path = findLibrary("PocoMsg.dll");
+#endif
+
+ if (!path.empty())
+ {
+ DWORD count = 8;
+ DWORD types = 7;
+#if defined(POCO_WIN32_UTF8)
+ RegSetValueExW(hKey, L"CategoryMessageFile", 0, REG_SZ, (const BYTE*) path.c_str(), static_cast<DWORD>(sizeof(wchar_t)*(path.size() + 1)));
+ RegSetValueExW(hKey, L"EventMessageFile", 0, REG_SZ, (const BYTE*) path.c_str(), static_cast<DWORD>(sizeof(wchar_t)*(path.size() + 1)));
+ RegSetValueExW(hKey, L"CategoryCount", 0, REG_DWORD, (const BYTE*) &count, static_cast<DWORD>(sizeof(count)));
+ RegSetValueExW(hKey, L"TypesSupported", 0, REG_DWORD, (const BYTE*) &types, static_cast<DWORD>(sizeof(types)));
+#else
+ RegSetValueEx(hKey, "CategoryMessageFile", 0, REG_SZ, (const BYTE*) path.c_str(), static_cast<DWORD>(path.size() + 1));
+ RegSetValueEx(hKey, "EventMessageFile", 0, REG_SZ, (const BYTE*) path.c_str(), static_cast<DWORD>(path.size() + 1));
+ RegSetValueEx(hKey, "CategoryCount", 0, REG_DWORD, (const BYTE*) &count, static_cast<DWORD>(sizeof(count)));
+ RegSetValueEx(hKey, "TypesSupported", 0, REG_DWORD, (const BYTE*) &types, static_cast<DWORD>(sizeof(types)));
+#endif
+ }
+ }
+ RegCloseKey(hKey);
+}
+
+
+#if defined(POCO_WIN32_UTF8)
+std::wstring EventLogChannel::findLibrary(const wchar_t* name)
+{
+ std::wstring path;
+ HMODULE dll = LoadLibraryW(name);
+ if (dll)
+ {
+ const DWORD maxPathLen = MAX_PATH + 1;
+ wchar_t moduleName[maxPathLen];
+ int n = GetModuleFileNameW(dll, moduleName, maxPathLen);
+ if (n > 0) path = moduleName;
+ FreeLibrary(dll);
+ }
+ return path;
+}
+#else
+std::string EventLogChannel::findLibrary(const char* name)
+{
+ std::string path;
+ HMODULE dll = LoadLibraryA(name);
+ if (dll)
+ {
+ const DWORD maxPathLen = MAX_PATH + 1;
+ char name[maxPathLen];
+ int n = GetModuleFileNameA(dll, name, maxPathLen);
+ if (n > 0) path = name;
+ FreeLibrary(dll);
+ }
+ return path;
+}
+#endif
+
+
+} // namespace Poco
diff --git a/contrib/libs/poco/Foundation/src/WindowsConsoleChannel.cpp b/contrib/libs/poco/Foundation/src/WindowsConsoleChannel.cpp
new file mode 100644
index 0000000000..07e352935f
--- /dev/null
+++ b/contrib/libs/poco/Foundation/src/WindowsConsoleChannel.cpp
@@ -0,0 +1,302 @@
+//
+// WindowsConsoleChannel.cpp
+//
+// Library: Foundation
+// Package: Logging
+// Module: WindowsConsoleChannel
+//
+// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#include "Poco/WindowsConsoleChannel.h"
+#include "Poco/Message.h"
+#if defined(POCO_WIN32_UTF8)
+#include "Poco/UnicodeConverter.h"
+#endif
+#include "Poco/String.h"
+#include "Poco/Exception.h"
+
+
+namespace Poco {
+
+
+WindowsConsoleChannel::WindowsConsoleChannel():
+ _isFile(false),
+ _hConsole(INVALID_HANDLE_VALUE)
+{
+ _hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
+ // check whether the console has been redirected
+ DWORD mode;
+ _isFile = (GetConsoleMode(_hConsole, &mode) == 0);
+}
+
+
+WindowsConsoleChannel::~WindowsConsoleChannel()
+{
+}
+
+
+void WindowsConsoleChannel::log(const Message& msg)
+{
+ std::string text = msg.getText();
+ text += "\r\n";
+
+#if defined(POCO_WIN32_UTF8)
+ if (_isFile)
+ {
+ DWORD written;
+ WriteFile(_hConsole, text.data(), static_cast<DWORD>(text.size()), &written, NULL);
+ }
+ else
+ {
+ std::wstring utext;
+ UnicodeConverter::toUTF16(text, utext);
+ DWORD written;
+ WriteConsoleW(_hConsole, utext.data(), static_cast<DWORD>(utext.size()), &written, NULL);
+ }
+#else
+ DWORD written;
+ WriteFile(_hConsole, text.data(), text.size(), &written, NULL);
+#endif
+}
+
+
+WindowsColorConsoleChannel::WindowsColorConsoleChannel():
+ _enableColors(true),
+ _isFile(false),
+ _hConsole(INVALID_HANDLE_VALUE)
+{
+ _hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
+ // check whether the console has been redirected
+ DWORD mode;
+ _isFile = (GetConsoleMode(_hConsole, &mode) == 0);
+ initColors();
+}
+
+
+WindowsColorConsoleChannel::~WindowsColorConsoleChannel()
+{
+}
+
+
+void WindowsColorConsoleChannel::log(const Message& msg)
+{
+ std::string text = msg.getText();
+ text += "\r\n";
+
+ if (_enableColors && !_isFile)
+ {
+ WORD attr = _colors[0];
+ attr &= 0xFFF0;
+ attr |= _colors[msg.getPriority()];
+ SetConsoleTextAttribute(_hConsole, attr);
+ }
+
+#if defined(POCO_WIN32_UTF8)
+ if (_isFile)
+ {
+ DWORD written;
+ WriteFile(_hConsole, text.data(), static_cast<DWORD>(text.size()), &written, NULL);
+ }
+ else
+ {
+ std::wstring utext;
+ UnicodeConverter::toUTF16(text, utext);
+ DWORD written;
+ WriteConsoleW(_hConsole, utext.data(), static_cast<DWORD>(utext.size()), &written, NULL);
+ }
+#else
+ DWORD written;
+ WriteFile(_hConsole, text.data(), text.size(), &written, NULL);
+#endif
+
+ if (_enableColors && !_isFile)
+ {
+ SetConsoleTextAttribute(_hConsole, _colors[0]);
+ }
+}
+
+
+void WindowsColorConsoleChannel::setProperty(const std::string& name, const std::string& value)
+{
+ if (name == "enableColors")
+ {
+ _enableColors = icompare(value, "true") == 0;
+ }
+ else if (name == "traceColor")
+ {
+ _colors[Message::PRIO_TRACE] = parseColor(value);
+ }
+ else if (name == "debugColor")
+ {
+ _colors[Message::PRIO_DEBUG] = parseColor(value);
+ }
+ else if (name == "informationColor")
+ {
+ _colors[Message::PRIO_INFORMATION] = parseColor(value);
+ }
+ else if (name == "noticeColor")
+ {
+ _colors[Message::PRIO_NOTICE] = parseColor(value);
+ }
+ else if (name == "warningColor")
+ {
+ _colors[Message::PRIO_WARNING] = parseColor(value);
+ }
+ else if (name == "errorColor")
+ {
+ _colors[Message::PRIO_ERROR] = parseColor(value);
+ }
+ else if (name == "criticalColor")
+ {
+ _colors[Message::PRIO_CRITICAL] = parseColor(value);
+ }
+ else if (name == "fatalColor")
+ {
+ _colors[Message::PRIO_FATAL] = parseColor(value);
+ }
+ else
+ {
+ Channel::setProperty(name, value);
+ }
+}
+
+
+std::string WindowsColorConsoleChannel::getProperty(const std::string& name) const
+{
+ if (name == "enableColors")
+ {
+ return _enableColors ? "true" : "false";
+ }
+ else if (name == "traceColor")
+ {
+ return formatColor(_colors[Message::PRIO_TRACE]);
+ }
+ else if (name == "debugColor")
+ {
+ return formatColor(_colors[Message::PRIO_DEBUG]);
+ }
+ else if (name == "informationColor")
+ {
+ return formatColor(_colors[Message::PRIO_INFORMATION]);
+ }
+ else if (name == "noticeColor")
+ {
+ return formatColor(_colors[Message::PRIO_NOTICE]);
+ }
+ else if (name == "warningColor")
+ {
+ return formatColor(_colors[Message::PRIO_WARNING]);
+ }
+ else if (name == "errorColor")
+ {
+ return formatColor(_colors[Message::PRIO_ERROR]);
+ }
+ else if (name == "criticalColor")
+ {
+ return formatColor(_colors[Message::PRIO_CRITICAL]);
+ }
+ else if (name == "fatalColor")
+ {
+ return formatColor(_colors[Message::PRIO_FATAL]);
+ }
+ else
+ {
+ return Channel::getProperty(name);
+ }
+}
+
+
+WORD WindowsColorConsoleChannel::parseColor(const std::string& color) const
+{
+ if (icompare(color, "default") == 0)
+ return _colors[0];
+ else if (icompare(color, "black") == 0)
+ return CC_BLACK;
+ else if (icompare(color, "red") == 0)
+ return CC_RED;
+ else if (icompare(color, "green") == 0)
+ return CC_GREEN;
+ else if (icompare(color, "brown") == 0)
+ return CC_BROWN;
+ else if (icompare(color, "blue") == 0)
+ return CC_BLUE;
+ else if (icompare(color, "magenta") == 0)
+ return CC_MAGENTA;
+ else if (icompare(color, "cyan") == 0)
+ return CC_CYAN;
+ else if (icompare(color, "gray") == 0)
+ return CC_GRAY;
+ else if (icompare(color, "darkGray") == 0)
+ return CC_DARKGRAY;
+ else if (icompare(color, "lightRed") == 0)
+ return CC_LIGHTRED;
+ else if (icompare(color, "lightGreen") == 0)
+ return CC_LIGHTGREEN;
+ else if (icompare(color, "yellow") == 0)
+ return CC_YELLOW;
+ else if (icompare(color, "lightBlue") == 0)
+ return CC_LIGHTBLUE;
+ else if (icompare(color, "lightMagenta") == 0)
+ return CC_LIGHTMAGENTA;
+ else if (icompare(color, "lightCyan") == 0)
+ return CC_LIGHTCYAN;
+ else if (icompare(color, "white") == 0)
+ return CC_WHITE;
+ else throw InvalidArgumentException("Invalid color value", color);
+}
+
+
+std::string WindowsColorConsoleChannel::formatColor(WORD color) const
+{
+ switch (color)
+ {
+ case CC_BLACK: return "black";
+ case CC_RED: return "red";
+ case CC_GREEN: return "green";
+ case CC_BROWN: return "brown";
+ case CC_BLUE: return "blue";
+ case CC_MAGENTA: return "magenta";
+ case CC_CYAN: return "cyan";
+ case CC_GRAY: return "gray";
+ case CC_DARKGRAY: return "darkGray";
+ case CC_LIGHTRED: return "lightRed";
+ case CC_LIGHTGREEN: return "lightGreen";
+ case CC_YELLOW: return "yellow";
+ case CC_LIGHTBLUE: return "lightBlue";
+ case CC_LIGHTMAGENTA: return "lightMagenta";
+ case CC_LIGHTCYAN: return "lightCyan";
+ case CC_WHITE: return "white";
+ default: return "invalid";
+ }
+}
+
+
+void WindowsColorConsoleChannel::initColors()
+{
+ if (!_isFile)
+ {
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+ GetConsoleScreenBufferInfo(_hConsole, &csbi);
+ _colors[0] = csbi.wAttributes;
+ }
+ else
+ {
+ _colors[0] = CC_WHITE;
+ }
+ _colors[Message::PRIO_FATAL] = CC_LIGHTRED;
+ _colors[Message::PRIO_CRITICAL] = CC_LIGHTRED;
+ _colors[Message::PRIO_ERROR] = CC_LIGHTRED;
+ _colors[Message::PRIO_WARNING] = CC_YELLOW;
+ _colors[Message::PRIO_NOTICE] = _colors[0];
+ _colors[Message::PRIO_INFORMATION] = _colors[0];
+ _colors[Message::PRIO_DEBUG] = CC_GRAY;
+ _colors[Message::PRIO_TRACE] = CC_GRAY;
+}
+
+
+} // namespace Poco
diff --git a/contrib/libs/poco/Foundation/src/pocomsg.h b/contrib/libs/poco/Foundation/src/pocomsg.h
new file mode 100644
index 0000000000..fe68ae436f
--- /dev/null
+++ b/contrib/libs/poco/Foundation/src/pocomsg.h
@@ -0,0 +1,158 @@
+//
+// pocomsg.mc[.h]
+//
+// $Id: //poco/1.4/Foundation/src/pocomsg.mc#1 $
+//
+// The Poco message source/header file.
+//
+// NOTE: pocomsg.h is automatically generated from pocomsg.mc.
+// Never edit pocomsg.h directly!
+//
+// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+//
+// Categories
+//
+//
+// Values are 32 bit values laid out as follows:
+//
+// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
+// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+// +---+-+-+-----------------------+-------------------------------+
+// |Sev|C|R| Facility | Code |
+// +---+-+-+-----------------------+-------------------------------+
+//
+// where
+//
+// Sev - is the severity code
+//
+// 00 - Success
+// 01 - Informational
+// 10 - Warning
+// 11 - Error
+//
+// C - is the Customer code flag
+//
+// R - is a reserved bit
+//
+// Facility - is the facility code
+//
+// Code - is the facility's status code
+//
+//
+// Define the facility codes
+//
+
+
+//
+// Define the severity codes
+//
+
+
+//
+// MessageId: POCO_CTG_FATAL
+//
+// MessageText:
+//
+// Fatal
+//
+#define POCO_CTG_FATAL 0x00000001L
+
+//
+// MessageId: POCO_CTG_CRITICAL
+//
+// MessageText:
+//
+// Critical
+//
+#define POCO_CTG_CRITICAL 0x00000002L
+
+//
+// MessageId: POCO_CTG_ERROR
+//
+// MessageText:
+//
+// Error
+//
+#define POCO_CTG_ERROR 0x00000003L
+
+//
+// MessageId: POCO_CTG_WARNING
+//
+// MessageText:
+//
+// Warning
+//
+#define POCO_CTG_WARNING 0x00000004L
+
+//
+// MessageId: POCO_CTG_NOTICE
+//
+// MessageText:
+//
+// Notice
+//
+#define POCO_CTG_NOTICE 0x00000005L
+
+//
+// MessageId: POCO_CTG_INFORMATION
+//
+// MessageText:
+//
+// Information
+//
+#define POCO_CTG_INFORMATION 0x00000006L
+
+//
+// MessageId: POCO_CTG_DEBUG
+//
+// MessageText:
+//
+// Debug
+//
+#define POCO_CTG_DEBUG 0x00000007L
+
+//
+// MessageId: POCO_CTG_TRACE
+//
+// MessageText:
+//
+// Trace
+//
+#define POCO_CTG_TRACE 0x00000008L
+
+//
+// Event Identifiers
+//
+//
+// MessageId: POCO_MSG_LOG
+//
+// MessageText:
+//
+// %1
+//
+#define POCO_MSG_LOG 0x00001000L
+
diff --git a/contrib/libs/postgresql/src/backend/port/win32/crashdump.c b/contrib/libs/postgresql/src/backend/port/win32/crashdump.c
new file mode 100644
index 0000000000..45b6696ba1
--- /dev/null
+++ b/contrib/libs/postgresql/src/backend/port/win32/crashdump.c
@@ -0,0 +1,183 @@
+/*-------------------------------------------------------------------------
+ *
+ * crashdump.c
+ * Automatic crash dump creation for PostgreSQL on Windows
+ *
+ * The crashdump feature traps unhandled win32 exceptions produced by the
+ * backend, and tries to produce a Windows MiniDump crash
+ * dump for later debugging and analysis. The machine performing the dump
+ * doesn't need any special debugging tools; the user only needs to send
+ * the dump to somebody who has the same version of PostgreSQL and has debugging
+ * tools.
+ *
+ * crashdump module originally by Craig Ringer <ringerc@ringerc.id.au>
+ *
+ * LIMITATIONS
+ * ===========
+ * This *won't* work in hard OOM situations or stack overflows.
+ *
+ * For those, it'd be necessary to take a much more complicated approach where
+ * the handler switches to a new stack (if it can) and forks a helper process
+ * to debug it self.
+ *
+ * POSSIBLE FUTURE WORK
+ * ====================
+ * For bonus points, the crash dump format permits embedding of user-supplied
+ * data. If there's anything else that should always be supplied with a crash
+ * dump (postgresql.conf? Last few lines of a log file?), it could potentially
+ * be added, though at the cost of a greater chance of the crash dump failing.
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/backend/port/win32/crashdump.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#define WIN32_LEAN_AND_MEAN
+
+/*
+ * Some versions of the MS SDK contain "typedef enum { ... } ;" which the MS
+ * compiler quite sanely complains about. Well done, Microsoft.
+ * This pragma disables the warning just while we include the header.
+ * The pragma is known to work with all (as at the time of writing) supported
+ * versions of MSVC.
+ */
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4091)
+#endif
+#include <dbghelp.h>
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+/*
+ * Much of the following code is based on CodeProject and MSDN examples,
+ * particularly
+ * http://www.codeproject.com/KB/debug/postmortemdebug_standalone1.aspx
+ *
+ * Useful MSDN articles:
+ *
+ * http://msdn.microsoft.com/en-us/library/ff805116(v=VS.85).aspx
+ * http://msdn.microsoft.com/en-us/library/ms679294(VS.85).aspx
+ *
+ * Other useful articles on working with minidumps:
+ * http://www.debuginfo.com/articles/effminidumps.html
+ */
+
+typedef BOOL (WINAPI * MINIDUMPWRITEDUMP) (HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType,
+ CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
+ CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
+ CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam
+);
+
+
+/*
+ * This function is the exception handler passed to SetUnhandledExceptionFilter.
+ * It's invoked only if there's an unhandled exception. The handler will use
+ * dbghelp.dll to generate a crash dump, then resume the normal unhandled
+ * exception process, which will generally exit with an error message from
+ * the runtime.
+ *
+ * This function is run under the unhandled exception handler, effectively
+ * in a crash context, so it should be careful with memory and avoid using
+ * any PostgreSQL functions.
+ */
+static LONG WINAPI
+crashDumpHandler(struct _EXCEPTION_POINTERS *pExceptionInfo)
+{
+ /*
+ * We only write crash dumps if the "crashdumps" directory within the
+ * postgres data directory exists.
+ */
+ DWORD attribs = GetFileAttributesA("crashdumps");
+
+ if (attribs != INVALID_FILE_ATTRIBUTES && (attribs & FILE_ATTRIBUTE_DIRECTORY))
+ {
+ /* 'crashdumps' exists and is a directory. Try to write a dump' */
+ HMODULE hDll = NULL;
+ MINIDUMPWRITEDUMP pDump = NULL;
+ MINIDUMP_TYPE dumpType;
+ char dumpPath[_MAX_PATH];
+ HANDLE selfProcHandle = GetCurrentProcess();
+ DWORD selfPid = GetProcessId(selfProcHandle);
+ HANDLE dumpFile;
+ DWORD systemTicks;
+ struct _MINIDUMP_EXCEPTION_INFORMATION ExInfo;
+
+ ExInfo.ThreadId = GetCurrentThreadId();
+ ExInfo.ExceptionPointers = pExceptionInfo;
+ ExInfo.ClientPointers = FALSE;
+
+ /* Load the dbghelp.dll library and functions */
+ hDll = LoadLibrary("dbghelp.dll");
+ if (hDll == NULL)
+ {
+ write_stderr("could not load dbghelp.dll, cannot write crash dump\n");
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+
+ pDump = (MINIDUMPWRITEDUMP) (pg_funcptr_t) GetProcAddress(hDll, "MiniDumpWriteDump");
+
+ if (pDump == NULL)
+ {
+ write_stderr("could not load required functions in dbghelp.dll, cannot write crash dump\n");
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+
+ /*
+ * Dump as much as we can, except shared memory, code segments, and
+ * memory mapped files. Exactly what we can dump depends on the
+ * version of dbghelp.dll, see:
+ * http://msdn.microsoft.com/en-us/library/ms680519(v=VS.85).aspx
+ */
+ dumpType = MiniDumpNormal | MiniDumpWithHandleData |
+ MiniDumpWithDataSegs;
+
+ if (GetProcAddress(hDll, "EnumDirTree") != NULL)
+ {
+ /* If this function exists, we have version 5.2 or newer */
+ dumpType |= MiniDumpWithIndirectlyReferencedMemory |
+ MiniDumpWithPrivateReadWriteMemory;
+ }
+
+ systemTicks = GetTickCount();
+ snprintf(dumpPath, _MAX_PATH,
+ "crashdumps\\postgres-pid%0i-%0i.mdmp",
+ (int) selfPid, (int) systemTicks);
+ dumpPath[_MAX_PATH - 1] = '\0';
+
+ dumpFile = CreateFile(dumpPath, GENERIC_WRITE, FILE_SHARE_WRITE,
+ NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (dumpFile == INVALID_HANDLE_VALUE)
+ {
+ write_stderr("could not open crash dump file \"%s\" for writing: error code %lu\n",
+ dumpPath, GetLastError());
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+
+ if ((*pDump) (selfProcHandle, selfPid, dumpFile, dumpType, &ExInfo,
+ NULL, NULL))
+ write_stderr("wrote crash dump to file \"%s\"\n", dumpPath);
+ else
+ write_stderr("could not write crash dump to file \"%s\": error code %lu\n",
+ dumpPath, GetLastError());
+
+ CloseHandle(dumpFile);
+ }
+
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+
+void
+pgwin32_install_crashdump_handler(void)
+{
+ SetUnhandledExceptionFilter(crashDumpHandler);
+}
diff --git a/contrib/libs/postgresql/src/backend/port/win32/signal.c b/contrib/libs/postgresql/src/backend/port/win32/signal.c
new file mode 100644
index 0000000000..580a517f3f
--- /dev/null
+++ b/contrib/libs/postgresql/src/backend/port/win32/signal.c
@@ -0,0 +1,344 @@
+/*-------------------------------------------------------------------------
+ *
+ * signal.c
+ * Microsoft Windows Win32 Signal Emulation Functions
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/backend/port/win32/signal.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "libpq/pqsignal.h"
+
+/*
+ * These are exported for use by the UNBLOCKED_SIGNAL_QUEUE() macro.
+ * pg_signal_queue must be volatile since it is changed by the signal
+ * handling thread and inspected without any lock by the main thread.
+ * pg_signal_mask is only changed by main thread so shouldn't need it.
+ */
+volatile int pg_signal_queue;
+int pg_signal_mask;
+
+HANDLE pgwin32_signal_event;
+HANDLE pgwin32_initial_signal_pipe = INVALID_HANDLE_VALUE;
+
+/*
+ * pg_signal_crit_sec is used to protect only pg_signal_queue. That is the only
+ * variable that can be accessed from the signal sending threads!
+ */
+static CRITICAL_SECTION pg_signal_crit_sec;
+
+/* Note that array elements 0 are unused since they correspond to signal 0 */
+static pqsigfunc pg_signal_array[PG_SIGNAL_COUNT];
+static pqsigfunc pg_signal_defaults[PG_SIGNAL_COUNT];
+
+
+/* Signal handling thread functions */
+static DWORD WINAPI pg_signal_thread(LPVOID param);
+static BOOL WINAPI pg_console_handler(DWORD dwCtrlType);
+
+
+/*
+ * pg_usleep --- delay the specified number of microseconds, but
+ * stop waiting if a signal arrives.
+ *
+ * This replaces the non-signal-aware version provided by src/port/pgsleep.c.
+ */
+void
+pg_usleep(long microsec)
+{
+ Assert(pgwin32_signal_event != NULL);
+ if (WaitForSingleObject(pgwin32_signal_event,
+ (microsec < 500 ? 1 : (microsec + 500) / 1000))
+ == WAIT_OBJECT_0)
+ {
+ pgwin32_dispatch_queued_signals();
+ errno = EINTR;
+ return;
+ }
+}
+
+
+/* Initialization */
+void
+pgwin32_signal_initialize(void)
+{
+ int i;
+ HANDLE signal_thread_handle;
+
+ InitializeCriticalSection(&pg_signal_crit_sec);
+
+ for (i = 0; i < PG_SIGNAL_COUNT; i++)
+ {
+ pg_signal_array[i] = SIG_DFL;
+ pg_signal_defaults[i] = SIG_IGN;
+ }
+ pg_signal_mask = 0;
+ pg_signal_queue = 0;
+
+ /* Create the global event handle used to flag signals */
+ pgwin32_signal_event = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (pgwin32_signal_event == NULL)
+ ereport(FATAL,
+ (errmsg_internal("could not create signal event: error code %lu", GetLastError())));
+
+ /* Create thread for handling signals */
+ signal_thread_handle = CreateThread(NULL, 0, pg_signal_thread, NULL, 0, NULL);
+ if (signal_thread_handle == NULL)
+ ereport(FATAL,
+ (errmsg_internal("could not create signal handler thread")));
+
+ /* Create console control handle to pick up Ctrl-C etc */
+ if (!SetConsoleCtrlHandler(pg_console_handler, TRUE))
+ ereport(FATAL,
+ (errmsg_internal("could not set console control handler")));
+}
+
+/*
+ * Dispatch all signals currently queued and not blocked
+ * Blocked signals are ignored, and will be fired at the time of
+ * the pqsigsetmask() call.
+ */
+void
+pgwin32_dispatch_queued_signals(void)
+{
+ int exec_mask;
+
+ Assert(pgwin32_signal_event != NULL);
+ EnterCriticalSection(&pg_signal_crit_sec);
+ while ((exec_mask = UNBLOCKED_SIGNAL_QUEUE()) != 0)
+ {
+ /* One or more unblocked signals queued for execution */
+ int i;
+
+ for (i = 1; i < PG_SIGNAL_COUNT; i++)
+ {
+ if (exec_mask & sigmask(i))
+ {
+ /* Execute this signal */
+ pqsigfunc sig = pg_signal_array[i];
+
+ if (sig == SIG_DFL)
+ sig = pg_signal_defaults[i];
+ pg_signal_queue &= ~sigmask(i);
+ if (sig != SIG_ERR && sig != SIG_IGN && sig != SIG_DFL)
+ {
+ LeaveCriticalSection(&pg_signal_crit_sec);
+ sig(i);
+ EnterCriticalSection(&pg_signal_crit_sec);
+ break; /* Restart outer loop, in case signal mask or
+ * queue has been modified inside signal
+ * handler */
+ }
+ }
+ }
+ }
+ ResetEvent(pgwin32_signal_event);
+ LeaveCriticalSection(&pg_signal_crit_sec);
+}
+
+/* signal masking. Only called on main thread, no sync required */
+int
+pqsigsetmask(int mask)
+{
+ int prevmask;
+
+ prevmask = pg_signal_mask;
+ pg_signal_mask = mask;
+
+ /*
+ * Dispatch any signals queued up right away, in case we have unblocked
+ * one or more signals previously queued
+ */
+ pgwin32_dispatch_queued_signals();
+
+ return prevmask;
+}
+
+
+/*
+ * Unix-like signal handler installation
+ *
+ * Only called on main thread, no sync required
+ */
+pqsigfunc
+pqsignal(int signum, pqsigfunc handler)
+{
+ pqsigfunc prevfunc;
+
+ if (signum >= PG_SIGNAL_COUNT || signum < 0)
+ return SIG_ERR;
+ prevfunc = pg_signal_array[signum];
+ pg_signal_array[signum] = handler;
+ return prevfunc;
+}
+
+/* Create the signal listener pipe for specified PID */
+HANDLE
+pgwin32_create_signal_listener(pid_t pid)
+{
+ char pipename[128];
+ HANDLE pipe;
+
+ snprintf(pipename, sizeof(pipename), "\\\\.\\pipe\\pgsignal_%u", (int) pid);
+
+ pipe = CreateNamedPipe(pipename, PIPE_ACCESS_DUPLEX,
+ PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
+ PIPE_UNLIMITED_INSTANCES, 16, 16, 1000, NULL);
+
+ if (pipe == INVALID_HANDLE_VALUE)
+ ereport(ERROR,
+ (errmsg("could not create signal listener pipe for PID %d: error code %lu",
+ (int) pid, GetLastError())));
+
+ return pipe;
+}
+
+
+/*
+ * All functions below execute on the signal handler thread
+ * and must be synchronized as such!
+ * NOTE! The only global variable that can be used is
+ * pg_signal_queue!
+ */
+
+
+/*
+ * Queue a signal for the main thread, by setting the flag bit and event.
+ */
+void
+pg_queue_signal(int signum)
+{
+ Assert(pgwin32_signal_event != NULL);
+ if (signum >= PG_SIGNAL_COUNT || signum <= 0)
+ return; /* ignore any bad signal number */
+
+ EnterCriticalSection(&pg_signal_crit_sec);
+ pg_signal_queue |= sigmask(signum);
+ LeaveCriticalSection(&pg_signal_crit_sec);
+
+ SetEvent(pgwin32_signal_event);
+}
+
+/* Signal handling thread */
+static DWORD WINAPI
+pg_signal_thread(LPVOID param)
+{
+ char pipename[128];
+ HANDLE pipe = pgwin32_initial_signal_pipe;
+
+ /* Set up pipe name, in case we have to re-create the pipe. */
+ snprintf(pipename, sizeof(pipename), "\\\\.\\pipe\\pgsignal_%lu", GetCurrentProcessId());
+
+ for (;;)
+ {
+ BOOL fConnected;
+
+ /* Create a new pipe instance if we don't have one. */
+ if (pipe == INVALID_HANDLE_VALUE)
+ {
+ pipe = CreateNamedPipe(pipename, PIPE_ACCESS_DUPLEX,
+ PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
+ PIPE_UNLIMITED_INSTANCES, 16, 16, 1000, NULL);
+
+ if (pipe == INVALID_HANDLE_VALUE)
+ {
+ write_stderr("could not create signal listener pipe: error code %lu; retrying\n", GetLastError());
+ SleepEx(500, FALSE);
+ continue;
+ }
+ }
+
+ /*
+ * Wait for a client to connect. If something connects before we
+ * reach here, we'll get back a "failure" with ERROR_PIPE_CONNECTED,
+ * which is actually a success (way to go, Microsoft).
+ */
+ fConnected = ConnectNamedPipe(pipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
+ if (fConnected)
+ {
+ /*
+ * We have a connection from a would-be signal sender. Process it.
+ */
+ BYTE sigNum;
+ DWORD bytes;
+
+ if (ReadFile(pipe, &sigNum, 1, &bytes, NULL) &&
+ bytes == 1)
+ {
+ /*
+ * Queue the signal before responding to the client. In this
+ * way, it's guaranteed that once kill() has returned in the
+ * signal sender, the next CHECK_FOR_INTERRUPTS() in the
+ * signal recipient will see the signal. (This is a stronger
+ * guarantee than POSIX makes; maybe we don't need it? But
+ * without it, we've seen timing bugs on Windows that do not
+ * manifest on any known Unix.)
+ */
+ pg_queue_signal(sigNum);
+
+ /*
+ * Write something back to the client, allowing its
+ * CallNamedPipe() call to terminate.
+ */
+ WriteFile(pipe, &sigNum, 1, &bytes, NULL); /* Don't care if it
+ * works or not */
+
+ /*
+ * We must wait for the client to read the data before we can
+ * disconnect, else the data will be lost. (If the WriteFile
+ * call failed, there'll be nothing in the buffer, so this
+ * shouldn't block.)
+ */
+ FlushFileBuffers(pipe);
+ }
+ else
+ {
+ /*
+ * If we fail to read a byte from the client, assume it's the
+ * client's problem and do nothing. Perhaps it'd be better to
+ * force a pipe close and reopen?
+ */
+ }
+
+ /* Disconnect from client so that we can re-use the pipe. */
+ DisconnectNamedPipe(pipe);
+ }
+ else
+ {
+ /*
+ * Connection failed. Cleanup and try again.
+ *
+ * This should never happen. If it does, there's a window where
+ * we'll miss signals until we manage to re-create the pipe.
+ * However, just trying to use the same pipe again is probably not
+ * going to work, so we have little choice.
+ */
+ CloseHandle(pipe);
+ pipe = INVALID_HANDLE_VALUE;
+ }
+ }
+ return 0;
+}
+
+
+/* Console control handler will execute on a thread created
+ by the OS at the time of invocation */
+static BOOL WINAPI
+pg_console_handler(DWORD dwCtrlType)
+{
+ if (dwCtrlType == CTRL_C_EVENT ||
+ dwCtrlType == CTRL_BREAK_EVENT ||
+ dwCtrlType == CTRL_CLOSE_EVENT ||
+ dwCtrlType == CTRL_SHUTDOWN_EVENT)
+ {
+ pg_queue_signal(SIGINT);
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/contrib/libs/postgresql/src/backend/port/win32/socket.c b/contrib/libs/postgresql/src/backend/port/win32/socket.c
new file mode 100644
index 0000000000..af151e8470
--- /dev/null
+++ b/contrib/libs/postgresql/src/backend/port/win32/socket.c
@@ -0,0 +1,700 @@
+/*-------------------------------------------------------------------------
+ *
+ * socket.c
+ * Microsoft Windows Win32 Socket Functions
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/backend/port/win32/socket.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+/*
+ * Indicate if pgwin32_recv() and pgwin32_send() should operate
+ * in non-blocking mode.
+ *
+ * Since the socket emulation layer always sets the actual socket to
+ * non-blocking mode in order to be able to deliver signals, we must
+ * specify this in a separate flag if we actually need non-blocking
+ * operation.
+ *
+ * This flag changes the behaviour *globally* for all socket operations,
+ * so it should only be set for very short periods of time.
+ */
+int pgwin32_noblock = 0;
+
+/* Undef the macros defined in win32.h, so we can access system functions */
+#undef socket
+#undef bind
+#undef listen
+#undef accept
+#undef connect
+#undef select
+#undef recv
+#undef send
+
+/*
+ * Blocking socket functions implemented so they listen on both
+ * the socket and the signal event, required for signal handling.
+ */
+
+/*
+ * Convert the last socket error code into errno
+ *
+ * Note: where there is a direct correspondence between a WSAxxx error code
+ * and a Berkeley error symbol, this mapping is actually a no-op, because
+ * in win32.h we redefine the network-related Berkeley error symbols to have
+ * the values of their WSAxxx counterparts. The point of the switch is
+ * mostly to translate near-miss error codes into something that's sensible
+ * in the Berkeley universe.
+ */
+static void
+TranslateSocketError(void)
+{
+ switch (WSAGetLastError())
+ {
+ case WSAEINVAL:
+ case WSANOTINITIALISED:
+ case WSAEINVALIDPROVIDER:
+ case WSAEINVALIDPROCTABLE:
+ case WSAEDESTADDRREQ:
+ errno = EINVAL;
+ break;
+ case WSAEINPROGRESS:
+ errno = EINPROGRESS;
+ break;
+ case WSAEFAULT:
+ errno = EFAULT;
+ break;
+ case WSAEISCONN:
+ errno = EISCONN;
+ break;
+ case WSAEMSGSIZE:
+ errno = EMSGSIZE;
+ break;
+ case WSAEAFNOSUPPORT:
+ errno = EAFNOSUPPORT;
+ break;
+ case WSAEMFILE:
+ errno = EMFILE;
+ break;
+ case WSAENOBUFS:
+ errno = ENOBUFS;
+ break;
+ case WSAEPROTONOSUPPORT:
+ case WSAEPROTOTYPE:
+ case WSAESOCKTNOSUPPORT:
+ errno = EPROTONOSUPPORT;
+ break;
+ case WSAECONNABORTED:
+ errno = ECONNABORTED;
+ break;
+ case WSAECONNREFUSED:
+ errno = ECONNREFUSED;
+ break;
+ case WSAECONNRESET:
+ errno = ECONNRESET;
+ break;
+ case WSAEINTR:
+ errno = EINTR;
+ break;
+ case WSAENOTSOCK:
+ errno = ENOTSOCK;
+ break;
+ case WSAEOPNOTSUPP:
+ errno = EOPNOTSUPP;
+ break;
+ case WSAEWOULDBLOCK:
+ errno = EWOULDBLOCK;
+ break;
+ case WSAEACCES:
+ errno = EACCES;
+ break;
+ case WSAEADDRINUSE:
+ errno = EADDRINUSE;
+ break;
+ case WSAEADDRNOTAVAIL:
+ errno = EADDRNOTAVAIL;
+ break;
+ case WSAEHOSTDOWN:
+ errno = EHOSTDOWN;
+ break;
+ case WSAEHOSTUNREACH:
+ case WSAHOST_NOT_FOUND:
+ errno = EHOSTUNREACH;
+ break;
+ case WSAENETDOWN:
+ errno = ENETDOWN;
+ break;
+ case WSAENETUNREACH:
+ errno = ENETUNREACH;
+ break;
+ case WSAENETRESET:
+ errno = ENETRESET;
+ break;
+ case WSAENOTCONN:
+ case WSAESHUTDOWN:
+ case WSAEDISCON:
+ errno = ENOTCONN;
+ break;
+ default:
+ ereport(NOTICE,
+ (errmsg_internal("unrecognized win32 socket error code: %d", WSAGetLastError())));
+ errno = EINVAL;
+ }
+}
+
+static int
+pgwin32_poll_signals(void)
+{
+ if (UNBLOCKED_SIGNAL_QUEUE())
+ {
+ pgwin32_dispatch_queued_signals();
+ errno = EINTR;
+ return 1;
+ }
+ return 0;
+}
+
+static int
+isDataGram(SOCKET s)
+{
+ int type;
+ int typelen = sizeof(type);
+
+ if (getsockopt(s, SOL_SOCKET, SO_TYPE, (char *) &type, &typelen))
+ return 1;
+
+ return (type == SOCK_DGRAM) ? 1 : 0;
+}
+
+int
+pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout)
+{
+ static HANDLE waitevent = INVALID_HANDLE_VALUE;
+ static SOCKET current_socket = INVALID_SOCKET;
+ static int isUDP = 0;
+ HANDLE events[2];
+ int r;
+
+ /* Create an event object just once and use it on all future calls */
+ if (waitevent == INVALID_HANDLE_VALUE)
+ {
+ waitevent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ if (waitevent == INVALID_HANDLE_VALUE)
+ ereport(ERROR,
+ (errmsg_internal("could not create socket waiting event: error code %lu", GetLastError())));
+ }
+ else if (!ResetEvent(waitevent))
+ ereport(ERROR,
+ (errmsg_internal("could not reset socket waiting event: error code %lu", GetLastError())));
+
+ /*
+ * Track whether socket is UDP or not. (NB: most likely, this is both
+ * useless and wrong; there is no reason to think that the behavior of
+ * WSAEventSelect is different for TCP and UDP.)
+ */
+ if (current_socket != s)
+ isUDP = isDataGram(s);
+ current_socket = s;
+
+ /*
+ * Attach event to socket. NOTE: we must detach it again before
+ * returning, since other bits of code may try to attach other events to
+ * the socket.
+ */
+ if (WSAEventSelect(s, waitevent, what) != 0)
+ {
+ TranslateSocketError();
+ return 0;
+ }
+
+ events[0] = pgwin32_signal_event;
+ events[1] = waitevent;
+
+ /*
+ * Just a workaround of unknown locking problem with writing in UDP socket
+ * under high load: Client's pgsql backend sleeps infinitely in
+ * WaitForMultipleObjectsEx, pgstat process sleeps in pgwin32_select().
+ * So, we will wait with small timeout(0.1 sec) and if socket is still
+ * blocked, try WSASend (see comments in pgwin32_select) and wait again.
+ */
+ if ((what & FD_WRITE) && isUDP)
+ {
+ for (;;)
+ {
+ r = WaitForMultipleObjectsEx(2, events, FALSE, 100, TRUE);
+
+ if (r == WAIT_TIMEOUT)
+ {
+ char c;
+ WSABUF buf;
+ DWORD sent;
+
+ buf.buf = &c;
+ buf.len = 0;
+
+ r = WSASend(s, &buf, 1, &sent, 0, NULL, NULL);
+ if (r == 0) /* Completed - means things are fine! */
+ {
+ WSAEventSelect(s, NULL, 0);
+ return 1;
+ }
+ else if (WSAGetLastError() != WSAEWOULDBLOCK)
+ {
+ TranslateSocketError();
+ WSAEventSelect(s, NULL, 0);
+ return 0;
+ }
+ }
+ else
+ break;
+ }
+ }
+ else
+ r = WaitForMultipleObjectsEx(2, events, FALSE, timeout, TRUE);
+
+ WSAEventSelect(s, NULL, 0);
+
+ if (r == WAIT_OBJECT_0 || r == WAIT_IO_COMPLETION)
+ {
+ pgwin32_dispatch_queued_signals();
+ errno = EINTR;
+ return 0;
+ }
+ if (r == WAIT_OBJECT_0 + 1)
+ return 1;
+ if (r == WAIT_TIMEOUT)
+ {
+ errno = EWOULDBLOCK;
+ return 0;
+ }
+ ereport(ERROR,
+ (errmsg_internal("unrecognized return value from WaitForMultipleObjects: %d (error code %lu)", r, GetLastError())));
+ return 0;
+}
+
+/*
+ * Create a socket, setting it to overlapped and non-blocking
+ */
+SOCKET
+pgwin32_socket(int af, int type, int protocol)
+{
+ SOCKET s;
+ unsigned long on = 1;
+
+ s = WSASocket(af, type, protocol, NULL, 0, WSA_FLAG_OVERLAPPED);
+ if (s == INVALID_SOCKET)
+ {
+ TranslateSocketError();
+ return INVALID_SOCKET;
+ }
+
+ if (ioctlsocket(s, FIONBIO, &on))
+ {
+ TranslateSocketError();
+ return INVALID_SOCKET;
+ }
+ errno = 0;
+
+ return s;
+}
+
+int
+pgwin32_bind(SOCKET s, struct sockaddr *addr, int addrlen)
+{
+ int res;
+
+ res = bind(s, addr, addrlen);
+ if (res < 0)
+ TranslateSocketError();
+ return res;
+}
+
+int
+pgwin32_listen(SOCKET s, int backlog)
+{
+ int res;
+
+ res = listen(s, backlog);
+ if (res < 0)
+ TranslateSocketError();
+ return res;
+}
+
+SOCKET
+pgwin32_accept(SOCKET s, struct sockaddr *addr, int *addrlen)
+{
+ SOCKET rs;
+
+ /*
+ * Poll for signals, but don't return with EINTR, since we don't handle
+ * that in pqcomm.c
+ */
+ pgwin32_poll_signals();
+
+ rs = WSAAccept(s, addr, addrlen, NULL, 0);
+ if (rs == INVALID_SOCKET)
+ {
+ TranslateSocketError();
+ return INVALID_SOCKET;
+ }
+ return rs;
+}
+
+
+/* No signal delivery during connect. */
+int
+pgwin32_connect(SOCKET s, const struct sockaddr *addr, int addrlen)
+{
+ int r;
+
+ r = WSAConnect(s, addr, addrlen, NULL, NULL, NULL, NULL);
+ if (r == 0)
+ return 0;
+
+ if (WSAGetLastError() != WSAEWOULDBLOCK)
+ {
+ TranslateSocketError();
+ return -1;
+ }
+
+ while (pgwin32_waitforsinglesocket(s, FD_CONNECT, INFINITE) == 0)
+ {
+ /* Loop endlessly as long as we are just delivering signals */
+ }
+
+ return 0;
+}
+
+int
+pgwin32_recv(SOCKET s, char *buf, int len, int f)
+{
+ WSABUF wbuf;
+ int r;
+ DWORD b;
+ DWORD flags = f;
+ int n;
+
+ if (pgwin32_poll_signals())
+ return -1;
+
+ wbuf.len = len;
+ wbuf.buf = buf;
+
+ r = WSARecv(s, &wbuf, 1, &b, &flags, NULL, NULL);
+ if (r != SOCKET_ERROR)
+ return b; /* success */
+
+ if (WSAGetLastError() != WSAEWOULDBLOCK)
+ {
+ TranslateSocketError();
+ return -1;
+ }
+
+ if (pgwin32_noblock)
+ {
+ /*
+ * No data received, and we are in "emulated non-blocking mode", so
+ * return indicating that we'd block if we were to continue.
+ */
+ errno = EWOULDBLOCK;
+ return -1;
+ }
+
+ /* We're in blocking mode, so wait for data */
+
+ for (n = 0; n < 5; n++)
+ {
+ if (pgwin32_waitforsinglesocket(s, FD_READ | FD_CLOSE | FD_ACCEPT,
+ INFINITE) == 0)
+ return -1; /* errno already set */
+
+ r = WSARecv(s, &wbuf, 1, &b, &flags, NULL, NULL);
+ if (r != SOCKET_ERROR)
+ return b; /* success */
+ if (WSAGetLastError() != WSAEWOULDBLOCK)
+ {
+ TranslateSocketError();
+ return -1;
+ }
+
+ /*
+ * There seem to be cases on win2k (at least) where WSARecv can return
+ * WSAEWOULDBLOCK even when pgwin32_waitforsinglesocket claims the
+ * socket is readable. In this case, just sleep for a moment and try
+ * again. We try up to 5 times - if it fails more than that it's not
+ * likely to ever come back.
+ */
+ pg_usleep(10000);
+ }
+ ereport(NOTICE,
+ (errmsg_internal("could not read from ready socket (after retries)")));
+ errno = EWOULDBLOCK;
+ return -1;
+}
+
+/*
+ * The second argument to send() is defined by SUS to be a "const void *"
+ * and so we use the same signature here to keep compilers happy when
+ * handling callers.
+ *
+ * But the buf member of a WSABUF struct is defined as "char *", so we cast
+ * the second argument to that here when assigning it, also to keep compilers
+ * happy.
+ */
+
+int
+pgwin32_send(SOCKET s, const void *buf, int len, int flags)
+{
+ WSABUF wbuf;
+ int r;
+ DWORD b;
+
+ if (pgwin32_poll_signals())
+ return -1;
+
+ wbuf.len = len;
+ wbuf.buf = (char *) buf;
+
+ /*
+ * Readiness of socket to send data to UDP socket may be not true: socket
+ * can become busy again! So loop until send or error occurs.
+ */
+ for (;;)
+ {
+ r = WSASend(s, &wbuf, 1, &b, flags, NULL, NULL);
+ if (r != SOCKET_ERROR && b > 0)
+ /* Write succeeded right away */
+ return b;
+
+ if (r == SOCKET_ERROR &&
+ WSAGetLastError() != WSAEWOULDBLOCK)
+ {
+ TranslateSocketError();
+ return -1;
+ }
+
+ if (pgwin32_noblock)
+ {
+ /*
+ * No data sent, and we are in "emulated non-blocking mode", so
+ * return indicating that we'd block if we were to continue.
+ */
+ errno = EWOULDBLOCK;
+ return -1;
+ }
+
+ /* No error, zero bytes (win2000+) or error+WSAEWOULDBLOCK (<=nt4) */
+
+ if (pgwin32_waitforsinglesocket(s, FD_WRITE | FD_CLOSE, INFINITE) == 0)
+ return -1;
+ }
+
+ return -1;
+}
+
+
+/*
+ * Wait for activity on one or more sockets.
+ * While waiting, allow signals to run
+ *
+ * NOTE! Currently does not implement exceptfds check,
+ * since it is not used in postgresql!
+ */
+int
+pgwin32_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timeval *timeout)
+{
+ WSAEVENT events[FD_SETSIZE * 2]; /* worst case is readfds totally
+ * different from writefds, so
+ * 2*FD_SETSIZE sockets */
+ SOCKET sockets[FD_SETSIZE * 2];
+ int numevents = 0;
+ int i;
+ int r;
+ DWORD timeoutval = WSA_INFINITE;
+ FD_SET outreadfds;
+ FD_SET outwritefds;
+ int nummatches = 0;
+
+ Assert(exceptfds == NULL);
+
+ if (pgwin32_poll_signals())
+ return -1;
+
+ FD_ZERO(&outreadfds);
+ FD_ZERO(&outwritefds);
+
+ /*
+ * Windows does not guarantee to log an FD_WRITE network event indicating
+ * that more data can be sent unless the previous send() failed with
+ * WSAEWOULDBLOCK. While our caller might well have made such a call, we
+ * cannot assume that here. Therefore, if waiting for write-ready, force
+ * the issue by doing a dummy send(). If the dummy send() succeeds,
+ * assume that the socket is in fact write-ready, and return immediately.
+ * Also, if it fails with something other than WSAEWOULDBLOCK, return a
+ * write-ready indication to let our caller deal with the error condition.
+ */
+ if (writefds != NULL)
+ {
+ for (i = 0; i < writefds->fd_count; i++)
+ {
+ char c;
+ WSABUF buf;
+ DWORD sent;
+
+ buf.buf = &c;
+ buf.len = 0;
+
+ r = WSASend(writefds->fd_array[i], &buf, 1, &sent, 0, NULL, NULL);
+ if (r == 0 || WSAGetLastError() != WSAEWOULDBLOCK)
+ FD_SET(writefds->fd_array[i], &outwritefds);
+ }
+
+ /* If we found any write-ready sockets, just return them immediately */
+ if (outwritefds.fd_count > 0)
+ {
+ memcpy(writefds, &outwritefds, sizeof(fd_set));
+ if (readfds)
+ FD_ZERO(readfds);
+ return outwritefds.fd_count;
+ }
+ }
+
+
+ /* Now set up for an actual select */
+
+ if (timeout != NULL)
+ {
+ /* timeoutval is in milliseconds */
+ timeoutval = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
+ }
+
+ if (readfds != NULL)
+ {
+ for (i = 0; i < readfds->fd_count; i++)
+ {
+ events[numevents] = WSACreateEvent();
+ sockets[numevents] = readfds->fd_array[i];
+ numevents++;
+ }
+ }
+ if (writefds != NULL)
+ {
+ for (i = 0; i < writefds->fd_count; i++)
+ {
+ if (!readfds ||
+ !FD_ISSET(writefds->fd_array[i], readfds))
+ {
+ /* If the socket is not in the read list */
+ events[numevents] = WSACreateEvent();
+ sockets[numevents] = writefds->fd_array[i];
+ numevents++;
+ }
+ }
+ }
+
+ for (i = 0; i < numevents; i++)
+ {
+ int flags = 0;
+
+ if (readfds && FD_ISSET(sockets[i], readfds))
+ flags |= FD_READ | FD_ACCEPT | FD_CLOSE;
+
+ if (writefds && FD_ISSET(sockets[i], writefds))
+ flags |= FD_WRITE | FD_CLOSE;
+
+ if (WSAEventSelect(sockets[i], events[i], flags) != 0)
+ {
+ TranslateSocketError();
+ /* release already-assigned event objects */
+ while (--i >= 0)
+ WSAEventSelect(sockets[i], NULL, 0);
+ for (i = 0; i < numevents; i++)
+ WSACloseEvent(events[i]);
+ return -1;
+ }
+ }
+
+ events[numevents] = pgwin32_signal_event;
+ r = WaitForMultipleObjectsEx(numevents + 1, events, FALSE, timeoutval, TRUE);
+ if (r != WAIT_TIMEOUT && r != WAIT_IO_COMPLETION && r != (WAIT_OBJECT_0 + numevents))
+ {
+ /*
+ * We scan all events, even those not signaled, in case more than one
+ * event has been tagged but Wait.. can only return one.
+ */
+ WSANETWORKEVENTS resEvents;
+
+ for (i = 0; i < numevents; i++)
+ {
+ ZeroMemory(&resEvents, sizeof(resEvents));
+ if (WSAEnumNetworkEvents(sockets[i], events[i], &resEvents) != 0)
+ elog(ERROR, "failed to enumerate network events: error code %d",
+ WSAGetLastError());
+ /* Read activity? */
+ if (readfds && FD_ISSET(sockets[i], readfds))
+ {
+ if ((resEvents.lNetworkEvents & FD_READ) ||
+ (resEvents.lNetworkEvents & FD_ACCEPT) ||
+ (resEvents.lNetworkEvents & FD_CLOSE))
+ {
+ FD_SET(sockets[i], &outreadfds);
+
+ nummatches++;
+ }
+ }
+ /* Write activity? */
+ if (writefds && FD_ISSET(sockets[i], writefds))
+ {
+ if ((resEvents.lNetworkEvents & FD_WRITE) ||
+ (resEvents.lNetworkEvents & FD_CLOSE))
+ {
+ FD_SET(sockets[i], &outwritefds);
+
+ nummatches++;
+ }
+ }
+ }
+ }
+
+ /* Clean up all the event objects */
+ for (i = 0; i < numevents; i++)
+ {
+ WSAEventSelect(sockets[i], NULL, 0);
+ WSACloseEvent(events[i]);
+ }
+
+ if (r == WSA_WAIT_TIMEOUT)
+ {
+ if (readfds)
+ FD_ZERO(readfds);
+ if (writefds)
+ FD_ZERO(writefds);
+ return 0;
+ }
+
+ /* Signal-like events. */
+ if (r == WAIT_OBJECT_0 + numevents || r == WAIT_IO_COMPLETION)
+ {
+ pgwin32_dispatch_queued_signals();
+ errno = EINTR;
+ if (readfds)
+ FD_ZERO(readfds);
+ if (writefds)
+ FD_ZERO(writefds);
+ return -1;
+ }
+
+ /* Overwrite socket sets with our resulting values */
+ if (readfds)
+ memcpy(readfds, &outreadfds, sizeof(fd_set));
+ if (writefds)
+ memcpy(writefds, &outwritefds, sizeof(fd_set));
+ return nummatches;
+}
diff --git a/contrib/libs/postgresql/src/backend/port/win32/timer.c b/contrib/libs/postgresql/src/backend/port/win32/timer.c
new file mode 100644
index 0000000000..53fdae9468
--- /dev/null
+++ b/contrib/libs/postgresql/src/backend/port/win32/timer.c
@@ -0,0 +1,121 @@
+/*-------------------------------------------------------------------------
+ *
+ * timer.c
+ * Microsoft Windows Win32 Timer Implementation
+ *
+ * Limitations of this implementation:
+ *
+ * - Does not support interval timer (value->it_interval)
+ * - Only supports ITIMER_REAL
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/backend/port/win32/timer.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+
+/* Communication area for inter-thread communication */
+typedef struct timerCA
+{
+ struct itimerval value;
+ HANDLE event;
+ CRITICAL_SECTION crit_sec;
+} timerCA;
+
+static timerCA timerCommArea;
+static HANDLE timerThreadHandle = INVALID_HANDLE_VALUE;
+
+
+/* Timer management thread */
+static DWORD WINAPI
+pg_timer_thread(LPVOID param)
+{
+ DWORD waittime;
+
+ Assert(param == NULL);
+
+ waittime = INFINITE;
+
+ for (;;)
+ {
+ int r;
+
+ r = WaitForSingleObjectEx(timerCommArea.event, waittime, FALSE);
+ if (r == WAIT_OBJECT_0)
+ {
+ /* Event signaled from main thread, change the timer */
+ EnterCriticalSection(&timerCommArea.crit_sec);
+ if (timerCommArea.value.it_value.tv_sec == 0 &&
+ timerCommArea.value.it_value.tv_usec == 0)
+ waittime = INFINITE; /* Cancel the interrupt */
+ else
+ {
+ /* WaitForSingleObjectEx() uses milliseconds, round up */
+ waittime = (timerCommArea.value.it_value.tv_usec + 999) / 1000 +
+ timerCommArea.value.it_value.tv_sec * 1000;
+ }
+ ResetEvent(timerCommArea.event);
+ LeaveCriticalSection(&timerCommArea.crit_sec);
+ }
+ else if (r == WAIT_TIMEOUT)
+ {
+ /* Timeout expired, signal SIGALRM and turn it off */
+ pg_queue_signal(SIGALRM);
+ waittime = INFINITE;
+ }
+ else
+ {
+ /* Should never happen */
+ Assert(false);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Win32 setitimer emulation by creating a persistent thread
+ * to handle the timer setting and notification upon timeout.
+ */
+int
+setitimer(int which, const struct itimerval *value, struct itimerval *ovalue)
+{
+ Assert(value != NULL);
+ Assert(value->it_interval.tv_sec == 0 && value->it_interval.tv_usec == 0);
+ Assert(which == ITIMER_REAL);
+
+ if (timerThreadHandle == INVALID_HANDLE_VALUE)
+ {
+ /* First call in this backend, create event and the timer thread */
+ timerCommArea.event = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (timerCommArea.event == NULL)
+ ereport(FATAL,
+ (errmsg_internal("could not create timer event: error code %lu",
+ GetLastError())));
+
+ MemSet(&timerCommArea.value, 0, sizeof(struct itimerval));
+
+ InitializeCriticalSection(&timerCommArea.crit_sec);
+
+ timerThreadHandle = CreateThread(NULL, 0, pg_timer_thread, NULL, 0, NULL);
+ if (timerThreadHandle == INVALID_HANDLE_VALUE)
+ ereport(FATAL,
+ (errmsg_internal("could not create timer thread: error code %lu",
+ GetLastError())));
+ }
+
+ /* Request the timer thread to change settings */
+ EnterCriticalSection(&timerCommArea.crit_sec);
+ if (ovalue)
+ *ovalue = timerCommArea.value;
+ timerCommArea.value = *value;
+ LeaveCriticalSection(&timerCommArea.crit_sec);
+ SetEvent(timerCommArea.event);
+
+ return 0;
+}
diff --git a/contrib/libs/postgresql/src/backend/port/win32_sema.c b/contrib/libs/postgresql/src/backend/port/win32_sema.c
new file mode 100644
index 0000000000..858b88adae
--- /dev/null
+++ b/contrib/libs/postgresql/src/backend/port/win32_sema.c
@@ -0,0 +1,235 @@
+/*-------------------------------------------------------------------------
+ *
+ * win32_sema.c
+ * Microsoft Windows Win32 Semaphores Emulation
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/backend/port/win32_sema.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "miscadmin.h"
+#include "storage/ipc.h"
+#include "storage/pg_sema.h"
+
+static HANDLE *mySemSet; /* IDs of sema sets acquired so far */
+static int numSems; /* number of sema sets acquired so far */
+static int maxSems; /* allocated size of mySemaSet array */
+
+static void ReleaseSemaphores(int code, Datum arg);
+
+
+/*
+ * Report amount of shared memory needed for semaphores
+ */
+Size
+PGSemaphoreShmemSize(int maxSemas)
+{
+ /* No shared memory needed on Windows */
+ return 0;
+}
+
+/*
+ * PGReserveSemaphores --- initialize semaphore support
+ *
+ * In the Win32 implementation, we acquire semaphores on-demand; the
+ * maxSemas parameter is just used to size the array that keeps track of
+ * acquired semas for subsequent releasing. We use anonymous semaphores
+ * so the semaphores are automatically freed when the last referencing
+ * process exits.
+ */
+void
+PGReserveSemaphores(int maxSemas)
+{
+ mySemSet = (HANDLE *) malloc(maxSemas * sizeof(HANDLE));
+ if (mySemSet == NULL)
+ elog(PANIC, "out of memory");
+ numSems = 0;
+ maxSems = maxSemas;
+
+ on_shmem_exit(ReleaseSemaphores, 0);
+}
+
+/*
+ * Release semaphores at shutdown or shmem reinitialization
+ *
+ * (called as an on_shmem_exit callback, hence funny argument list)
+ */
+static void
+ReleaseSemaphores(int code, Datum arg)
+{
+ int i;
+
+ for (i = 0; i < numSems; i++)
+ CloseHandle(mySemSet[i]);
+ free(mySemSet);
+}
+
+/*
+ * PGSemaphoreCreate
+ *
+ * Allocate a PGSemaphore structure with initial count 1
+ */
+PGSemaphore
+PGSemaphoreCreate(void)
+{
+ HANDLE cur_handle;
+ SECURITY_ATTRIBUTES sec_attrs;
+
+ /* Can't do this in a backend, because static state is postmaster's */
+ Assert(!IsUnderPostmaster);
+
+ if (numSems >= maxSems)
+ elog(PANIC, "too many semaphores created");
+
+ ZeroMemory(&sec_attrs, sizeof(sec_attrs));
+ sec_attrs.nLength = sizeof(sec_attrs);
+ sec_attrs.lpSecurityDescriptor = NULL;
+ sec_attrs.bInheritHandle = TRUE;
+
+ /* We don't need a named semaphore */
+ cur_handle = CreateSemaphore(&sec_attrs, 1, 32767, NULL);
+ if (cur_handle)
+ {
+ /* Successfully done */
+ mySemSet[numSems++] = cur_handle;
+ }
+ else
+ ereport(PANIC,
+ (errmsg("could not create semaphore: error code %lu",
+ GetLastError())));
+
+ return (PGSemaphore) cur_handle;
+}
+
+/*
+ * PGSemaphoreReset
+ *
+ * Reset a previously-initialized PGSemaphore to have count 0
+ */
+void
+PGSemaphoreReset(PGSemaphore sema)
+{
+ /*
+ * There's no direct API for this in Win32, so we have to ratchet the
+ * semaphore down to 0 with repeated trylock's.
+ */
+ while (PGSemaphoreTryLock(sema))
+ /* loop */ ;
+}
+
+/*
+ * PGSemaphoreLock
+ *
+ * Lock a semaphore (decrement count), blocking if count would be < 0.
+ */
+void
+PGSemaphoreLock(PGSemaphore sema)
+{
+ HANDLE wh[2];
+ bool done = false;
+
+ /*
+ * Note: pgwin32_signal_event should be first to ensure that it will be
+ * reported when multiple events are set. We want to guarantee that
+ * pending signals are serviced.
+ */
+ wh[0] = pgwin32_signal_event;
+ wh[1] = sema;
+
+ /*
+ * As in other implementations of PGSemaphoreLock, we need to check for
+ * cancel/die interrupts each time through the loop. But here, there is
+ * no hidden magic about whether the syscall will internally service a
+ * signal --- we do that ourselves.
+ */
+ while (!done)
+ {
+ DWORD rc;
+
+ CHECK_FOR_INTERRUPTS();
+
+ rc = WaitForMultipleObjectsEx(2, wh, FALSE, INFINITE, TRUE);
+ switch (rc)
+ {
+ case WAIT_OBJECT_0:
+ /* Signal event is set - we have a signal to deliver */
+ pgwin32_dispatch_queued_signals();
+ break;
+ case WAIT_OBJECT_0 + 1:
+ /* We got it! */
+ done = true;
+ break;
+ case WAIT_IO_COMPLETION:
+
+ /*
+ * The system interrupted the wait to execute an I/O
+ * completion routine or asynchronous procedure call in this
+ * thread. PostgreSQL does not provoke either of these, but
+ * atypical loaded DLLs or even other processes might do so.
+ * Now, resume waiting.
+ */
+ break;
+ case WAIT_FAILED:
+ ereport(FATAL,
+ (errmsg("could not lock semaphore: error code %lu",
+ GetLastError())));
+ break;
+ default:
+ elog(FATAL, "unexpected return code from WaitForMultipleObjectsEx(): %lu", rc);
+ break;
+ }
+ }
+}
+
+/*
+ * PGSemaphoreUnlock
+ *
+ * Unlock a semaphore (increment count)
+ */
+void
+PGSemaphoreUnlock(PGSemaphore sema)
+{
+ if (!ReleaseSemaphore(sema, 1, NULL))
+ ereport(FATAL,
+ (errmsg("could not unlock semaphore: error code %lu",
+ GetLastError())));
+}
+
+/*
+ * PGSemaphoreTryLock
+ *
+ * Lock a semaphore only if able to do so without blocking
+ */
+bool
+PGSemaphoreTryLock(PGSemaphore sema)
+{
+ DWORD ret;
+
+ ret = WaitForSingleObject(sema, 0);
+
+ if (ret == WAIT_OBJECT_0)
+ {
+ /* We got it! */
+ return true;
+ }
+ else if (ret == WAIT_TIMEOUT)
+ {
+ /* Can't get it */
+ errno = EAGAIN;
+ return false;
+ }
+
+ /* Otherwise we are in trouble */
+ ereport(FATAL,
+ (errmsg("could not try-lock semaphore: error code %lu",
+ GetLastError())));
+
+ /* keep compiler quiet */
+ return false;
+}
diff --git a/contrib/libs/postgresql/src/backend/port/win32_shmem.c b/contrib/libs/postgresql/src/backend/port/win32_shmem.c
new file mode 100644
index 0000000000..d7a71992d8
--- /dev/null
+++ b/contrib/libs/postgresql/src/backend/port/win32_shmem.c
@@ -0,0 +1,607 @@
+/*-------------------------------------------------------------------------
+ *
+ * win32_shmem.c
+ * Implement shared memory using win32 facilities
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/backend/port/win32_shmem.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "miscadmin.h"
+#include "storage/dsm.h"
+#include "storage/ipc.h"
+#include "storage/pg_shmem.h"
+
+/*
+ * Early in a process's life, Windows asynchronously creates threads for the
+ * process's "default thread pool"
+ * (https://docs.microsoft.com/en-us/windows/desktop/ProcThread/thread-pools).
+ * Occasionally, thread creation allocates a stack after
+ * PGSharedMemoryReAttach() has released UsedShmemSegAddr and before it has
+ * mapped shared memory at UsedShmemSegAddr. This would cause mapping to fail
+ * if the allocator preferred the just-released region for allocating the new
+ * thread stack. We observed such failures in some Windows Server 2016
+ * configurations. To give the system another region to prefer, reserve and
+ * release an additional, protective region immediately before reserving or
+ * releasing shared memory. The idea is that, if the allocator handed out
+ * REGION1 pages before REGION2 pages at one occasion, it will do so whenever
+ * both regions are free. Windows Server 2016 exhibits that behavior, and a
+ * system behaving differently would have less need to protect
+ * UsedShmemSegAddr. The protective region must be at least large enough for
+ * one thread stack. However, ten times as much is less than 2% of the 32-bit
+ * address space and is negligible relative to the 64-bit address space.
+ */
+#define PROTECTIVE_REGION_SIZE (10 * WIN32_STACK_RLIMIT)
+void *ShmemProtectiveRegion = NULL;
+
+HANDLE UsedShmemSegID = INVALID_HANDLE_VALUE;
+void *UsedShmemSegAddr = NULL;
+static Size UsedShmemSegSize = 0;
+
+static bool EnableLockPagesPrivilege(int elevel);
+static void pgwin32_SharedMemoryDelete(int status, Datum shmId);
+
+/*
+ * Generate shared memory segment name. Expand the data directory, to generate
+ * an identifier unique for this data directory. Then replace all backslashes
+ * with forward slashes, since backslashes aren't permitted in global object names.
+ *
+ * Store the shared memory segment in the Global\ namespace (requires NT2 TSE or
+ * 2000, but that's all we support for other reasons as well), to make sure you can't
+ * open two postmasters in different sessions against the same data directory.
+ *
+ * XXX: What happens with junctions? It's only someone breaking things on purpose,
+ * and this is still better than before, but we might want to do something about
+ * that sometime in the future.
+ */
+static char *
+GetSharedMemName(void)
+{
+ char *retptr;
+ DWORD bufsize;
+ DWORD r;
+ char *cp;
+
+ bufsize = GetFullPathName(DataDir, 0, NULL, NULL);
+ if (bufsize == 0)
+ elog(FATAL, "could not get size for full pathname of datadir %s: error code %lu",
+ DataDir, GetLastError());
+
+ retptr = malloc(bufsize + 18); /* 18 for Global\PostgreSQL: */
+ if (retptr == NULL)
+ elog(FATAL, "could not allocate memory for shared memory name");
+
+ strcpy(retptr, "Global\\PostgreSQL:");
+ r = GetFullPathName(DataDir, bufsize, retptr + 18, NULL);
+ if (r == 0 || r > bufsize)
+ elog(FATAL, "could not generate full pathname for datadir %s: error code %lu",
+ DataDir, GetLastError());
+
+ /*
+ * XXX: Intentionally overwriting the Global\ part here. This was not the
+ * original approach, but putting it in the actual Global\ namespace
+ * causes permission errors in a lot of cases, so we leave it in the
+ * default namespace for now.
+ */
+ for (cp = retptr; *cp; cp++)
+ if (*cp == '\\')
+ *cp = '/';
+
+ return retptr;
+}
+
+
+/*
+ * PGSharedMemoryIsInUse
+ *
+ * Is a previously-existing shmem segment still existing and in use?
+ *
+ * The point of this exercise is to detect the case where a prior postmaster
+ * crashed, but it left child backends that are still running. Therefore
+ * we only care about shmem segments that are associated with the intended
+ * DataDir. This is an important consideration since accidental matches of
+ * shmem segment IDs are reasonably common.
+ */
+bool
+PGSharedMemoryIsInUse(unsigned long id1, unsigned long id2)
+{
+ char *szShareMem;
+ HANDLE hmap;
+
+ szShareMem = GetSharedMemName();
+
+ hmap = OpenFileMapping(FILE_MAP_READ, FALSE, szShareMem);
+
+ free(szShareMem);
+
+ if (hmap == NULL)
+ return false;
+
+ CloseHandle(hmap);
+ return true;
+}
+
+/*
+ * EnableLockPagesPrivilege
+ *
+ * Try to acquire SeLockMemoryPrivilege so we can use large pages.
+ */
+static bool
+EnableLockPagesPrivilege(int elevel)
+{
+ HANDLE hToken;
+ TOKEN_PRIVILEGES tp;
+ LUID luid;
+
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
+ {
+ ereport(elevel,
+ (errmsg("could not enable user right \"%s\": error code %lu",
+
+ /*
+ * translator: This is a term from Windows and should be translated to
+ * match the Windows localization.
+ */
+ _("Lock pages in memory"),
+ GetLastError()),
+ errdetail("Failed system call was %s.", "OpenProcessToken")));
+ return FALSE;
+ }
+
+ if (!LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, &luid))
+ {
+ ereport(elevel,
+ (errmsg("could not enable user right \"%s\": error code %lu", _("Lock pages in memory"), GetLastError()),
+ errdetail("Failed system call was %s.", "LookupPrivilegeValue")));
+ CloseHandle(hToken);
+ return FALSE;
+ }
+ tp.PrivilegeCount = 1;
+ tp.Privileges[0].Luid = luid;
+ tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ if (!AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL))
+ {
+ ereport(elevel,
+ (errmsg("could not enable user right \"%s\": error code %lu", _("Lock pages in memory"), GetLastError()),
+ errdetail("Failed system call was %s.", "AdjustTokenPrivileges")));
+ CloseHandle(hToken);
+ return FALSE;
+ }
+
+ if (GetLastError() != ERROR_SUCCESS)
+ {
+ if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
+ ereport(elevel,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("could not enable user right \"%s\"", _("Lock pages in memory")),
+ errhint("Assign user right \"%s\" to the Windows user account which runs PostgreSQL.",
+ _("Lock pages in memory"))));
+ else
+ ereport(elevel,
+ (errmsg("could not enable user right \"%s\": error code %lu", _("Lock pages in memory"), GetLastError()),
+ errdetail("Failed system call was %s.", "AdjustTokenPrivileges")));
+ CloseHandle(hToken);
+ return FALSE;
+ }
+
+ CloseHandle(hToken);
+
+ return TRUE;
+}
+
+/*
+ * PGSharedMemoryCreate
+ *
+ * Create a shared memory segment of the given size and initialize its
+ * standard header.
+ */
+PGShmemHeader *
+PGSharedMemoryCreate(Size size,
+ PGShmemHeader **shim)
+{
+ void *memAddress;
+ PGShmemHeader *hdr;
+ HANDLE hmap,
+ hmap2;
+ char *szShareMem;
+ int i;
+ DWORD size_high;
+ DWORD size_low;
+ SIZE_T largePageSize = 0;
+ Size orig_size = size;
+ DWORD flProtect = PAGE_READWRITE;
+
+ ShmemProtectiveRegion = VirtualAlloc(NULL, PROTECTIVE_REGION_SIZE,
+ MEM_RESERVE, PAGE_NOACCESS);
+ if (ShmemProtectiveRegion == NULL)
+ elog(FATAL, "could not reserve memory region: error code %lu",
+ GetLastError());
+
+ /* Room for a header? */
+ Assert(size > MAXALIGN(sizeof(PGShmemHeader)));
+
+ szShareMem = GetSharedMemName();
+
+ UsedShmemSegAddr = NULL;
+
+ if (huge_pages == HUGE_PAGES_ON || huge_pages == HUGE_PAGES_TRY)
+ {
+ /* Does the processor support large pages? */
+ largePageSize = GetLargePageMinimum();
+ if (largePageSize == 0)
+ {
+ ereport(huge_pages == HUGE_PAGES_ON ? FATAL : DEBUG1,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("the processor does not support large pages")));
+ ereport(DEBUG1,
+ (errmsg_internal("disabling huge pages")));
+ }
+ else if (!EnableLockPagesPrivilege(huge_pages == HUGE_PAGES_ON ? FATAL : DEBUG1))
+ {
+ ereport(DEBUG1,
+ (errmsg_internal("disabling huge pages")));
+ }
+ else
+ {
+ /* Huge pages available and privilege enabled, so turn on */
+ flProtect = PAGE_READWRITE | SEC_COMMIT | SEC_LARGE_PAGES;
+
+ /* Round size up as appropriate. */
+ if (size % largePageSize != 0)
+ size += largePageSize - (size % largePageSize);
+ }
+ }
+
+retry:
+#ifdef _WIN64
+ size_high = size >> 32;
+#else
+ size_high = 0;
+#endif
+ size_low = (DWORD) size;
+
+ /*
+ * When recycling a shared memory segment, it may take a short while
+ * before it gets dropped from the global namespace. So re-try after
+ * sleeping for a second, and continue retrying 10 times. (both the 1
+ * second time and the 10 retries are completely arbitrary)
+ */
+ for (i = 0; i < 10; i++)
+ {
+ /*
+ * In case CreateFileMapping() doesn't set the error code to 0 on
+ * success
+ */
+ SetLastError(0);
+
+ hmap = CreateFileMapping(INVALID_HANDLE_VALUE, /* Use the pagefile */
+ NULL, /* Default security attrs */
+ flProtect,
+ size_high, /* Size Upper 32 Bits */
+ size_low, /* Size Lower 32 bits */
+ szShareMem);
+
+ if (!hmap)
+ {
+ if (GetLastError() == ERROR_NO_SYSTEM_RESOURCES &&
+ huge_pages == HUGE_PAGES_TRY &&
+ (flProtect & SEC_LARGE_PAGES) != 0)
+ {
+ elog(DEBUG1, "CreateFileMapping(%zu) with SEC_LARGE_PAGES failed, "
+ "huge pages disabled",
+ size);
+
+ /*
+ * Use the original size, not the rounded-up value, when
+ * falling back to non-huge pages.
+ */
+ size = orig_size;
+ flProtect = PAGE_READWRITE;
+ goto retry;
+ }
+ else
+ ereport(FATAL,
+ (errmsg("could not create shared memory segment: error code %lu", GetLastError()),
+ errdetail("Failed system call was CreateFileMapping(size=%zu, name=%s).",
+ size, szShareMem)));
+ }
+
+ /*
+ * If the segment already existed, CreateFileMapping() will return a
+ * handle to the existing one and set ERROR_ALREADY_EXISTS.
+ */
+ if (GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+ CloseHandle(hmap); /* Close the handle, since we got a valid one
+ * to the previous segment. */
+ hmap = NULL;
+ Sleep(1000);
+ continue;
+ }
+ break;
+ }
+
+ /*
+ * If the last call in the loop still returned ERROR_ALREADY_EXISTS, this
+ * shared memory segment exists and we assume it belongs to somebody else.
+ */
+ if (!hmap)
+ ereport(FATAL,
+ (errmsg("pre-existing shared memory block is still in use"),
+ errhint("Check if there are any old server processes still running, and terminate them.")));
+
+ free(szShareMem);
+
+ /*
+ * Make the handle inheritable
+ */
+ if (!DuplicateHandle(GetCurrentProcess(), hmap, GetCurrentProcess(), &hmap2, 0, TRUE, DUPLICATE_SAME_ACCESS))
+ ereport(FATAL,
+ (errmsg("could not create shared memory segment: error code %lu", GetLastError()),
+ errdetail("Failed system call was DuplicateHandle.")));
+
+ /*
+ * Close the old, non-inheritable handle. If this fails we don't really
+ * care.
+ */
+ if (!CloseHandle(hmap))
+ elog(LOG, "could not close handle to shared memory: error code %lu", GetLastError());
+
+
+ /*
+ * Get a pointer to the new shared memory segment. Map the whole segment
+ * at once, and let the system decide on the initial address.
+ */
+ memAddress = MapViewOfFileEx(hmap2, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, 0, NULL);
+ if (!memAddress)
+ ereport(FATAL,
+ (errmsg("could not create shared memory segment: error code %lu", GetLastError()),
+ errdetail("Failed system call was MapViewOfFileEx.")));
+
+
+
+ /*
+ * OK, we created a new segment. Mark it as created by this process. The
+ * order of assignments here is critical so that another Postgres process
+ * can't see the header as valid but belonging to an invalid PID!
+ */
+ hdr = (PGShmemHeader *) memAddress;
+ hdr->creatorPID = getpid();
+ hdr->magic = PGShmemMagic;
+
+ /*
+ * Initialize space allocation status for segment.
+ */
+ hdr->totalsize = size;
+ hdr->freeoffset = MAXALIGN(sizeof(PGShmemHeader));
+ hdr->dsm_control = 0;
+
+ /* Save info for possible future use */
+ UsedShmemSegAddr = memAddress;
+ UsedShmemSegSize = size;
+ UsedShmemSegID = hmap2;
+
+ /* Register on-exit routine to delete the new segment */
+ on_shmem_exit(pgwin32_SharedMemoryDelete, PointerGetDatum(hmap2));
+
+ *shim = hdr;
+ return hdr;
+}
+
+/*
+ * PGSharedMemoryReAttach
+ *
+ * This is called during startup of a postmaster child process to re-attach to
+ * an already existing shared memory segment, using the handle inherited from
+ * the postmaster.
+ *
+ * ShmemProtectiveRegion, UsedShmemSegID and UsedShmemSegAddr are implicit
+ * parameters to this routine. The caller must have already restored them to
+ * the postmaster's values.
+ */
+void
+PGSharedMemoryReAttach(void)
+{
+ PGShmemHeader *hdr;
+ void *origUsedShmemSegAddr = UsedShmemSegAddr;
+
+ Assert(ShmemProtectiveRegion != NULL);
+ Assert(UsedShmemSegAddr != NULL);
+ Assert(IsUnderPostmaster);
+
+ /*
+ * Release memory region reservations made by the postmaster
+ */
+ if (VirtualFree(ShmemProtectiveRegion, 0, MEM_RELEASE) == 0)
+ elog(FATAL, "failed to release reserved memory region (addr=%p): error code %lu",
+ ShmemProtectiveRegion, GetLastError());
+ if (VirtualFree(UsedShmemSegAddr, 0, MEM_RELEASE) == 0)
+ elog(FATAL, "failed to release reserved memory region (addr=%p): error code %lu",
+ UsedShmemSegAddr, GetLastError());
+
+ hdr = (PGShmemHeader *) MapViewOfFileEx(UsedShmemSegID, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0, UsedShmemSegAddr);
+ if (!hdr)
+ elog(FATAL, "could not reattach to shared memory (key=%p, addr=%p): error code %lu",
+ UsedShmemSegID, UsedShmemSegAddr, GetLastError());
+ if (hdr != origUsedShmemSegAddr)
+ elog(FATAL, "reattaching to shared memory returned unexpected address (got %p, expected %p)",
+ hdr, origUsedShmemSegAddr);
+ if (hdr->magic != PGShmemMagic)
+ elog(FATAL, "reattaching to shared memory returned non-PostgreSQL memory");
+ dsm_set_control_handle(hdr->dsm_control);
+
+ UsedShmemSegAddr = hdr; /* probably redundant */
+}
+
+/*
+ * PGSharedMemoryNoReAttach
+ *
+ * This is called during startup of a postmaster child process when we choose
+ * *not* to re-attach to the existing shared memory segment. We must clean up
+ * to leave things in the appropriate state.
+ *
+ * The child process startup logic might or might not call PGSharedMemoryDetach
+ * after this; make sure that it will be a no-op if called.
+ *
+ * ShmemProtectiveRegion, UsedShmemSegID and UsedShmemSegAddr are implicit
+ * parameters to this routine. The caller must have already restored them to
+ * the postmaster's values.
+ */
+void
+PGSharedMemoryNoReAttach(void)
+{
+ Assert(ShmemProtectiveRegion != NULL);
+ Assert(UsedShmemSegAddr != NULL);
+ Assert(IsUnderPostmaster);
+
+ /*
+ * Under Windows we will not have mapped the segment, so we don't need to
+ * un-map it. Just reset UsedShmemSegAddr to show we're not attached.
+ */
+ UsedShmemSegAddr = NULL;
+
+ /*
+ * We *must* close the inherited shmem segment handle, else Windows will
+ * consider the existence of this process to mean it can't release the
+ * shmem segment yet. We can now use PGSharedMemoryDetach to do that.
+ */
+ PGSharedMemoryDetach();
+}
+
+/*
+ * PGSharedMemoryDetach
+ *
+ * Detach from the shared memory segment, if still attached. This is not
+ * intended to be called explicitly by the process that originally created the
+ * segment (it will have an on_shmem_exit callback registered to do that).
+ * Rather, this is for subprocesses that have inherited an attachment and want
+ * to get rid of it.
+ *
+ * ShmemProtectiveRegion, UsedShmemSegID and UsedShmemSegAddr are implicit
+ * parameters to this routine.
+ */
+void
+PGSharedMemoryDetach(void)
+{
+ /*
+ * Releasing the protective region liberates an unimportant quantity of
+ * address space, but be tidy.
+ */
+ if (ShmemProtectiveRegion != NULL)
+ {
+ if (VirtualFree(ShmemProtectiveRegion, 0, MEM_RELEASE) == 0)
+ elog(LOG, "failed to release reserved memory region (addr=%p): error code %lu",
+ ShmemProtectiveRegion, GetLastError());
+
+ ShmemProtectiveRegion = NULL;
+ }
+
+ /* Unmap the view, if it's mapped */
+ if (UsedShmemSegAddr != NULL)
+ {
+ if (!UnmapViewOfFile(UsedShmemSegAddr))
+ elog(LOG, "could not unmap view of shared memory: error code %lu",
+ GetLastError());
+
+ UsedShmemSegAddr = NULL;
+ }
+
+ /* And close the shmem handle, if we have one */
+ if (UsedShmemSegID != INVALID_HANDLE_VALUE)
+ {
+ if (!CloseHandle(UsedShmemSegID))
+ elog(LOG, "could not close handle to shared memory: error code %lu",
+ GetLastError());
+
+ UsedShmemSegID = INVALID_HANDLE_VALUE;
+ }
+}
+
+
+/*
+ * pgwin32_SharedMemoryDelete
+ *
+ * Detach from and delete the shared memory segment
+ * (called as an on_shmem_exit callback, hence funny argument list)
+ */
+static void
+pgwin32_SharedMemoryDelete(int status, Datum shmId)
+{
+ Assert(DatumGetPointer(shmId) == UsedShmemSegID);
+ PGSharedMemoryDetach();
+}
+
+/*
+ * pgwin32_ReserveSharedMemoryRegion(hChild)
+ *
+ * Reserve the memory region that will be used for shared memory in a child
+ * process. It is called before the child process starts, to make sure the
+ * memory is available.
+ *
+ * Once the child starts, DLLs loading in different order or threads getting
+ * scheduled differently may allocate memory which can conflict with the
+ * address space we need for our shared memory. By reserving the shared
+ * memory region before the child starts, and freeing it only just before we
+ * attempt to get access to the shared memory forces these allocations to
+ * be given different address ranges that don't conflict.
+ *
+ * NOTE! This function executes in the postmaster, and should for this
+ * reason not use elog(FATAL) since that would take down the postmaster.
+ */
+int
+pgwin32_ReserveSharedMemoryRegion(HANDLE hChild)
+{
+ void *address;
+
+ Assert(ShmemProtectiveRegion != NULL);
+ Assert(UsedShmemSegAddr != NULL);
+ Assert(UsedShmemSegSize != 0);
+
+ /* ShmemProtectiveRegion */
+ address = VirtualAllocEx(hChild, ShmemProtectiveRegion,
+ PROTECTIVE_REGION_SIZE,
+ MEM_RESERVE, PAGE_NOACCESS);
+ if (address == NULL)
+ {
+ /* Don't use FATAL since we're running in the postmaster */
+ elog(LOG, "could not reserve shared memory region (addr=%p) for child %p: error code %lu",
+ ShmemProtectiveRegion, hChild, GetLastError());
+ return false;
+ }
+ if (address != ShmemProtectiveRegion)
+ {
+ /*
+ * Should never happen - in theory if allocation granularity causes
+ * strange effects it could, so check just in case.
+ *
+ * Don't use FATAL since we're running in the postmaster.
+ */
+ elog(LOG, "reserved shared memory region got incorrect address %p, expected %p",
+ address, ShmemProtectiveRegion);
+ return false;
+ }
+
+ /* UsedShmemSegAddr */
+ address = VirtualAllocEx(hChild, UsedShmemSegAddr, UsedShmemSegSize,
+ MEM_RESERVE, PAGE_READWRITE);
+ if (address == NULL)
+ {
+ elog(LOG, "could not reserve shared memory region (addr=%p) for child %p: error code %lu",
+ UsedShmemSegAddr, hChild, GetLastError());
+ return false;
+ }
+ if (address != UsedShmemSegAddr)
+ {
+ elog(LOG, "reserved shared memory region got incorrect address %p, expected %p",
+ address, UsedShmemSegAddr);
+ return false;
+ }
+
+ return true;
+}
diff --git a/contrib/libs/postgresql/src/include/port/win32/arpa/inet.h b/contrib/libs/postgresql/src/include/port/win32/arpa/inet.h
new file mode 100644
index 0000000000..ad1803179c
--- /dev/null
+++ b/contrib/libs/postgresql/src/include/port/win32/arpa/inet.h
@@ -0,0 +1,3 @@
+/* src/include/port/win32/arpa/inet.h */
+
+#include <sys/socket.h>
diff --git a/contrib/libs/postgresql/src/include/port/win32/grp.h b/contrib/libs/postgresql/src/include/port/win32/grp.h
new file mode 100644
index 0000000000..8b4f21310e
--- /dev/null
+++ b/contrib/libs/postgresql/src/include/port/win32/grp.h
@@ -0,0 +1 @@
+/* src/include/port/win32/grp.h */
diff --git a/contrib/libs/postgresql/src/include/port/win32/netdb.h b/contrib/libs/postgresql/src/include/port/win32/netdb.h
new file mode 100644
index 0000000000..ad0627e986
--- /dev/null
+++ b/contrib/libs/postgresql/src/include/port/win32/netdb.h
@@ -0,0 +1 @@
+/* src/include/port/win32/netdb.h */
diff --git a/contrib/libs/postgresql/src/include/port/win32/netinet/in.h b/contrib/libs/postgresql/src/include/port/win32/netinet/in.h
new file mode 100644
index 0000000000..a4e22f89f4
--- /dev/null
+++ b/contrib/libs/postgresql/src/include/port/win32/netinet/in.h
@@ -0,0 +1,3 @@
+/* src/include/port/win32/netinet/in.h */
+
+#include <sys/socket.h>
diff --git a/contrib/libs/postgresql/src/include/port/win32/pwd.h b/contrib/libs/postgresql/src/include/port/win32/pwd.h
new file mode 100644
index 0000000000..b8c7178fc0
--- /dev/null
+++ b/contrib/libs/postgresql/src/include/port/win32/pwd.h
@@ -0,0 +1,3 @@
+/*
+ * src/include/port/win32/pwd.h
+ */
diff --git a/contrib/libs/postgresql/src/include/port/win32/sys/socket.h b/contrib/libs/postgresql/src/include/port/win32/sys/socket.h
new file mode 100644
index 0000000000..9b2cdf3b9b
--- /dev/null
+++ b/contrib/libs/postgresql/src/include/port/win32/sys/socket.h
@@ -0,0 +1,33 @@
+/*
+ * src/include/port/win32/sys/socket.h
+ */
+#ifndef WIN32_SYS_SOCKET_H
+#define WIN32_SYS_SOCKET_H
+
+/*
+ * Unfortunately, <wingdi.h> of VC++ also defines ERROR.
+ * To avoid the conflict, we include <windows.h> here and undefine ERROR
+ * immediately.
+ *
+ * Note: Don't include <wingdi.h> directly. It causes compile errors.
+ */
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <windows.h>
+
+#undef ERROR
+#undef small
+
+/* Restore old ERROR value */
+#ifdef PGERROR
+#define ERROR PGERROR
+#endif
+
+/*
+ * we can't use the windows gai_strerror{AW} functions because
+ * they are defined inline in the MS header files. So we'll use our
+ * own
+ */
+#undef gai_strerror
+
+#endif /* WIN32_SYS_SOCKET_H */
diff --git a/contrib/libs/postgresql/src/include/port/win32/sys/wait.h b/contrib/libs/postgresql/src/include/port/win32/sys/wait.h
new file mode 100644
index 0000000000..eaeb5661c9
--- /dev/null
+++ b/contrib/libs/postgresql/src/include/port/win32/sys/wait.h
@@ -0,0 +1,3 @@
+/*
+ * src/include/port/win32/sys/wait.h
+ */
diff --git a/contrib/libs/postgresql/src/include/port/win32_msvc/dirent.h b/contrib/libs/postgresql/src/include/port/win32_msvc/dirent.h
new file mode 100644
index 0000000000..62799db001
--- /dev/null
+++ b/contrib/libs/postgresql/src/include/port/win32_msvc/dirent.h
@@ -0,0 +1,34 @@
+/*
+ * Headers for port/dirent.c, win32 native implementation of dirent functions
+ *
+ * src/include/port/win32_msvc/dirent.h
+ */
+
+#ifndef _WIN32VC_DIRENT_H
+#define _WIN32VC_DIRENT_H
+struct dirent
+{
+ long d_ino;
+ unsigned short d_reclen;
+ unsigned char d_type;
+ unsigned short d_namlen;
+ char d_name[MAX_PATH];
+};
+
+typedef struct DIR DIR;
+
+DIR *opendir(const char *);
+struct dirent *readdir(DIR *);
+int closedir(DIR *);
+
+/* File types for 'd_type'. */
+#define DT_UNKNOWN 0
+#define DT_FIFO 1
+#define DT_CHR 2
+#define DT_DIR 4
+#define DT_BLK 6
+#define DT_REG 8
+#define DT_LNK 10
+#define DT_SOCK 12
+#define DT_WHT 14
+#endif
diff --git a/contrib/libs/postgresql/src/include/port/win32_msvc/sys/file.h b/contrib/libs/postgresql/src/include/port/win32_msvc/sys/file.h
new file mode 100644
index 0000000000..76be3e7774
--- /dev/null
+++ b/contrib/libs/postgresql/src/include/port/win32_msvc/sys/file.h
@@ -0,0 +1 @@
+/* src/include/port/win32_msvc/sys/file.h */
diff --git a/contrib/libs/postgresql/src/include/port/win32_msvc/sys/param.h b/contrib/libs/postgresql/src/include/port/win32_msvc/sys/param.h
new file mode 100644
index 0000000000..160df3b25e
--- /dev/null
+++ b/contrib/libs/postgresql/src/include/port/win32_msvc/sys/param.h
@@ -0,0 +1 @@
+/* src/include/port/win32_msvc/sys/param.h */
diff --git a/contrib/libs/postgresql/src/include/port/win32_msvc/sys/time.h b/contrib/libs/postgresql/src/include/port/win32_msvc/sys/time.h
new file mode 100644
index 0000000000..9d943ecc6f
--- /dev/null
+++ b/contrib/libs/postgresql/src/include/port/win32_msvc/sys/time.h
@@ -0,0 +1 @@
+/* src/include/port/win32_msvc/sys/time.h */
diff --git a/contrib/libs/postgresql/src/include/port/win32_msvc/unistd.h b/contrib/libs/postgresql/src/include/port/win32_msvc/unistd.h
new file mode 100644
index 0000000000..b63f4770a1
--- /dev/null
+++ b/contrib/libs/postgresql/src/include/port/win32_msvc/unistd.h
@@ -0,0 +1 @@
+/* src/include/port/win32_msvc/unistd.h */
diff --git a/contrib/libs/postgresql/src/include/port/win32_msvc/utime.h b/contrib/libs/postgresql/src/include/port/win32_msvc/utime.h
new file mode 100644
index 0000000000..c78e79c33d
--- /dev/null
+++ b/contrib/libs/postgresql/src/include/port/win32_msvc/utime.h
@@ -0,0 +1,3 @@
+/* src/include/port/win32_msvc/utime.h */
+
+#include <sys/utime.h> /* for non-unicode version */
diff --git a/contrib/libs/postgresql/src/port/dirmod.c b/contrib/libs/postgresql/src/port/dirmod.c
new file mode 100644
index 0000000000..46c9c235c8
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/dirmod.c
@@ -0,0 +1,355 @@
+/*-------------------------------------------------------------------------
+ *
+ * dirmod.c
+ * directory handling functions
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * This includes replacement versions of functions that work on
+ * Win32 (NT4 and newer).
+ *
+ * IDENTIFICATION
+ * src/port/dirmod.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+/* Don't modify declarations in system headers */
+#if defined(WIN32) || defined(__CYGWIN__)
+#undef rename
+#undef unlink
+#endif
+
+#include <unistd.h>
+#include <sys/stat.h>
+
+#if defined(WIN32) || defined(__CYGWIN__)
+#ifndef __CYGWIN__
+#include <winioctl.h>
+#else
+#include <windows.h>
+#error #include <w32api/winioctl.h>
+#endif
+#endif
+
+#if defined(WIN32) || defined(__CYGWIN__)
+
+/*
+ * pgrename
+ */
+int
+pgrename(const char *from, const char *to)
+{
+ int loops = 0;
+
+ /*
+ * We need to loop because even though PostgreSQL uses flags that allow
+ * rename while the file is open, other applications might have the file
+ * open without those flags. However, we won't wait indefinitely for
+ * someone else to close the file, as the caller might be holding locks
+ * and blocking other backends.
+ */
+#if defined(WIN32) && !defined(__CYGWIN__)
+ while (!MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING))
+#else
+ while (rename(from, to) < 0)
+#endif
+ {
+#if defined(WIN32) && !defined(__CYGWIN__)
+ DWORD err = GetLastError();
+
+ _dosmaperr(err);
+
+ /*
+ * Modern NT-based Windows versions return ERROR_SHARING_VIOLATION if
+ * another process has the file open without FILE_SHARE_DELETE.
+ * ERROR_LOCK_VIOLATION has also been seen with some anti-virus
+ * software. This used to check for just ERROR_ACCESS_DENIED, so
+ * presumably you can get that too with some OS versions. We don't
+ * expect real permission errors where we currently use rename().
+ */
+ if (err != ERROR_ACCESS_DENIED &&
+ err != ERROR_SHARING_VIOLATION &&
+ err != ERROR_LOCK_VIOLATION)
+ return -1;
+#else
+ if (errno != EACCES)
+ return -1;
+#endif
+
+ if (++loops > 100) /* time out after 10 sec */
+ return -1;
+ pg_usleep(100000); /* us */
+ }
+ return 0;
+}
+
+
+/*
+ * pgunlink
+ */
+int
+pgunlink(const char *path)
+{
+ int loops = 0;
+
+ /*
+ * We need to loop because even though PostgreSQL uses flags that allow
+ * unlink while the file is open, other applications might have the file
+ * open without those flags. However, we won't wait indefinitely for
+ * someone else to close the file, as the caller might be holding locks
+ * and blocking other backends.
+ */
+ while (unlink(path))
+ {
+ if (errno != EACCES)
+ return -1;
+ if (++loops > 100) /* time out after 10 sec */
+ return -1;
+ pg_usleep(100000); /* us */
+ }
+ return 0;
+}
+
+/* We undefined these above; now redefine for possible use below */
+#define rename(from, to) pgrename(from, to)
+#define unlink(path) pgunlink(path)
+#endif /* defined(WIN32) || defined(__CYGWIN__) */
+
+
+#if defined(WIN32) && !defined(__CYGWIN__) /* Cygwin has its own symlinks */
+
+/*
+ * pgsymlink support:
+ *
+ * This struct is a replacement for REPARSE_DATA_BUFFER which is defined in VC6 winnt.h
+ * but omitted in later SDK functions.
+ * We only need the SymbolicLinkReparseBuffer part of the original struct's union.
+ */
+typedef struct
+{
+ DWORD ReparseTag;
+ WORD ReparseDataLength;
+ WORD Reserved;
+ /* SymbolicLinkReparseBuffer */
+ WORD SubstituteNameOffset;
+ WORD SubstituteNameLength;
+ WORD PrintNameOffset;
+ WORD PrintNameLength;
+ WCHAR PathBuffer[FLEXIBLE_ARRAY_MEMBER];
+} REPARSE_JUNCTION_DATA_BUFFER;
+
+#define REPARSE_JUNCTION_DATA_BUFFER_HEADER_SIZE \
+ FIELD_OFFSET(REPARSE_JUNCTION_DATA_BUFFER, SubstituteNameOffset)
+
+
+/*
+ * pgsymlink - uses Win32 junction points
+ *
+ * For reference: http://www.codeproject.com/KB/winsdk/junctionpoints.aspx
+ */
+int
+pgsymlink(const char *oldpath, const char *newpath)
+{
+ HANDLE dirhandle;
+ DWORD len;
+ char buffer[MAX_PATH * sizeof(WCHAR) + offsetof(REPARSE_JUNCTION_DATA_BUFFER, PathBuffer)];
+ char nativeTarget[MAX_PATH];
+ char *p = nativeTarget;
+ REPARSE_JUNCTION_DATA_BUFFER *reparseBuf = (REPARSE_JUNCTION_DATA_BUFFER *) buffer;
+
+ CreateDirectory(newpath, 0);
+ dirhandle = CreateFile(newpath, GENERIC_READ | GENERIC_WRITE,
+ 0, 0, OPEN_EXISTING,
+ FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, 0);
+
+ if (dirhandle == INVALID_HANDLE_VALUE)
+ return -1;
+
+ /* make sure we have an unparsed native win32 path */
+ if (memcmp("\\??\\", oldpath, 4) != 0)
+ snprintf(nativeTarget, sizeof(nativeTarget), "\\??\\%s", oldpath);
+ else
+ strlcpy(nativeTarget, oldpath, sizeof(nativeTarget));
+
+ while ((p = strchr(p, '/')) != NULL)
+ *p++ = '\\';
+
+ len = strlen(nativeTarget) * sizeof(WCHAR);
+ reparseBuf->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
+ reparseBuf->ReparseDataLength = len + 12;
+ reparseBuf->Reserved = 0;
+ reparseBuf->SubstituteNameOffset = 0;
+ reparseBuf->SubstituteNameLength = len;
+ reparseBuf->PrintNameOffset = len + sizeof(WCHAR);
+ reparseBuf->PrintNameLength = 0;
+ MultiByteToWideChar(CP_ACP, 0, nativeTarget, -1,
+ reparseBuf->PathBuffer, MAX_PATH);
+
+ /*
+ * FSCTL_SET_REPARSE_POINT is coded differently depending on SDK version;
+ * we use our own definition
+ */
+ if (!DeviceIoControl(dirhandle,
+ CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_ANY_ACCESS),
+ reparseBuf,
+ reparseBuf->ReparseDataLength + REPARSE_JUNCTION_DATA_BUFFER_HEADER_SIZE,
+ 0, 0, &len, 0))
+ {
+ LPSTR msg;
+
+ errno = 0;
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_IGNORE_INSERTS |
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, GetLastError(),
+ MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
+ (LPSTR) &msg, 0, NULL);
+#ifndef FRONTEND
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not set junction for \"%s\": %s",
+ nativeTarget, msg)));
+#else
+ fprintf(stderr, _("could not set junction for \"%s\": %s\n"),
+ nativeTarget, msg);
+#endif
+ LocalFree(msg);
+
+ CloseHandle(dirhandle);
+ RemoveDirectory(newpath);
+ return -1;
+ }
+
+ CloseHandle(dirhandle);
+
+ return 0;
+}
+
+/*
+ * pgreadlink - uses Win32 junction points
+ */
+int
+pgreadlink(const char *path, char *buf, size_t size)
+{
+ DWORD attr;
+ HANDLE h;
+ char buffer[MAX_PATH * sizeof(WCHAR) + offsetof(REPARSE_JUNCTION_DATA_BUFFER, PathBuffer)];
+ REPARSE_JUNCTION_DATA_BUFFER *reparseBuf = (REPARSE_JUNCTION_DATA_BUFFER *) buffer;
+ DWORD len;
+ int r;
+
+ attr = GetFileAttributes(path);
+ if (attr == INVALID_FILE_ATTRIBUTES)
+ {
+ _dosmaperr(GetLastError());
+ return -1;
+ }
+ if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ h = CreateFile(path,
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
+ 0);
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ _dosmaperr(GetLastError());
+ return -1;
+ }
+
+ if (!DeviceIoControl(h,
+ FSCTL_GET_REPARSE_POINT,
+ NULL,
+ 0,
+ (LPVOID) reparseBuf,
+ sizeof(buffer),
+ &len,
+ NULL))
+ {
+ LPSTR msg;
+
+ errno = 0;
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_IGNORE_INSERTS |
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, GetLastError(),
+ MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
+ (LPSTR) &msg, 0, NULL);
+#ifndef FRONTEND
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not get junction for \"%s\": %s",
+ path, msg)));
+#else
+ fprintf(stderr, _("could not get junction for \"%s\": %s\n"),
+ path, msg);
+#endif
+ LocalFree(msg);
+ CloseHandle(h);
+ errno = EINVAL;
+ return -1;
+ }
+ CloseHandle(h);
+
+ /* Got it, let's get some results from this */
+ if (reparseBuf->ReparseTag != IO_REPARSE_TAG_MOUNT_POINT)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ r = WideCharToMultiByte(CP_ACP, 0,
+ reparseBuf->PathBuffer, -1,
+ buf,
+ size,
+ NULL, NULL);
+
+ if (r <= 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /*
+ * If the path starts with "\??\", which it will do in most (all?) cases,
+ * strip those out.
+ */
+ if (r > 4 && strncmp(buf, "\\??\\", 4) == 0)
+ {
+ memmove(buf, buf + 4, strlen(buf + 4) + 1);
+ r -= 4;
+ }
+ return r;
+}
+
+/*
+ * Assumes the file exists, so will return false if it doesn't
+ * (since a nonexistent file is not a junction)
+ */
+bool
+pgwin32_is_junction(const char *path)
+{
+ DWORD attr = GetFileAttributes(path);
+
+ if (attr == INVALID_FILE_ATTRIBUTES)
+ {
+ _dosmaperr(GetLastError());
+ return false;
+ }
+ return ((attr & FILE_ATTRIBUTE_REPARSE_POINT) == FILE_ATTRIBUTE_REPARSE_POINT);
+}
+#endif /* defined(WIN32) && !defined(__CYGWIN__) */
diff --git a/contrib/libs/postgresql/src/port/dlopen.c b/contrib/libs/postgresql/src/port/dlopen.c
new file mode 100644
index 0000000000..f7948b861f
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/dlopen.c
@@ -0,0 +1,145 @@
+/*-------------------------------------------------------------------------
+ *
+ * dlopen.c
+ * dynamic loader for platforms without dlopen()
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/port/dlopen.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#if defined(__hpux)
+
+/* System includes */
+#include <a.out.h>
+#include <dl.h>
+
+void *
+dlopen(const char *file, int mode)
+{
+ int flags = 0;
+
+ if (mode & RTLD_NOW)
+ flags |= BIND_IMMEDIATE;
+#ifdef NOT_USED
+ if (mode & RTLD_LAZY)
+ flags |= BIND_DEFERRED;
+#endif
+
+ return shl_load(file, flags | BIND_VERBOSE, 0L);
+}
+
+void *
+dlsym(void *handle, const char *symbol)
+{
+ void *value;
+
+ if (shl_findsym((shl_t *) & handle, symbol, TYPE_PROCEDURE, &value) == -1)
+ return NULL;
+ return value;
+}
+
+int
+dlclose(void *handle)
+{
+ return shl_unload((shl_t) handle);
+}
+
+char *
+dlerror(void)
+{
+ static char errmsg[] = "shl_load failed";
+
+ if (errno)
+ return strerror(errno);
+
+ return errmsg;
+}
+
+#elif defined(WIN32)
+
+static char last_dyn_error[512];
+
+static void
+set_dl_error(void)
+{
+ DWORD err = GetLastError();
+
+ if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS |
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ err,
+ MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
+ last_dyn_error,
+ sizeof(last_dyn_error) - 1,
+ NULL) == 0)
+ {
+ snprintf(last_dyn_error, sizeof(last_dyn_error) - 1,
+ "unknown error %lu", err);
+ }
+}
+
+char *
+dlerror(void)
+{
+ if (last_dyn_error[0])
+ return last_dyn_error;
+ else
+ return NULL;
+}
+
+int
+dlclose(void *handle)
+{
+ if (!FreeLibrary((HMODULE) handle))
+ {
+ set_dl_error();
+ return 1;
+ }
+ last_dyn_error[0] = 0;
+ return 0;
+}
+
+void *
+dlsym(void *handle, const char *symbol)
+{
+ void *ptr;
+
+ ptr = GetProcAddress((HMODULE) handle, symbol);
+ if (!ptr)
+ {
+ set_dl_error();
+ return NULL;
+ }
+ last_dyn_error[0] = 0;
+ return ptr;
+}
+
+void *
+dlopen(const char *file, int mode)
+{
+ HMODULE h;
+ int prevmode;
+
+ /* Disable popup error messages when loading DLLs */
+ prevmode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
+ h = LoadLibrary(file);
+ SetErrorMode(prevmode);
+
+ if (!h)
+ {
+ set_dl_error();
+ return NULL;
+ }
+ last_dyn_error[0] = 0;
+ return (void *) h;
+}
+
+#endif
diff --git a/contrib/libs/postgresql/src/port/getaddrinfo.c b/contrib/libs/postgresql/src/port/getaddrinfo.c
new file mode 100644
index 0000000000..bb194da529
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/getaddrinfo.c
@@ -0,0 +1,396 @@
+/*-------------------------------------------------------------------------
+ *
+ * getaddrinfo.c
+ * Support getaddrinfo() on platforms that don't have it.
+ *
+ * We also supply getnameinfo() here, assuming that the platform will have
+ * it if and only if it has getaddrinfo(). If this proves false on some
+ * platform, we'll need to split this file and provide a separate configure
+ * test for getnameinfo().
+ *
+ * Windows may or may not have these routines, so we handle Windows specially
+ * by dynamically checking for their existence. If they already exist, we
+ * use the Windows native routines, but if not, we use our own.
+ *
+ *
+ * Copyright (c) 2003-2021, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/port/getaddrinfo.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/* This is intended to be used in both frontend and backend, so use c.h */
+#include "c.h"
+
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "getaddrinfo.h"
+#include "libpq/pqcomm.h" /* needed for struct sockaddr_storage */
+#include "port/pg_bswap.h"
+
+
+#ifdef WIN32
+/*
+ * The native routines may or may not exist on the Windows platform we are on,
+ * so we dynamically look up the routines, and call them via function pointers.
+ * Here we need to declare what the function pointers look like
+ */
+typedef int (__stdcall * getaddrinfo_ptr_t) (const char *nodename,
+ const char *servname,
+ const struct addrinfo *hints,
+ struct addrinfo **res);
+
+typedef void (__stdcall * freeaddrinfo_ptr_t) (struct addrinfo *ai);
+
+typedef int (__stdcall * getnameinfo_ptr_t) (const struct sockaddr *sa,
+ int salen,
+ char *node, int nodelen,
+ char *service, int servicelen,
+ int flags);
+
+/* static pointers to the native routines, so we only do the lookup once. */
+static getaddrinfo_ptr_t getaddrinfo_ptr = NULL;
+static freeaddrinfo_ptr_t freeaddrinfo_ptr = NULL;
+static getnameinfo_ptr_t getnameinfo_ptr = NULL;
+
+
+static bool
+haveNativeWindowsIPv6routines(void)
+{
+ void *hLibrary = NULL;
+ static bool alreadyLookedForIpv6routines = false;
+
+ if (alreadyLookedForIpv6routines)
+ return (getaddrinfo_ptr != NULL);
+
+ /*
+ * For Windows XP and later versions, the IPv6 routines are present in the
+ * WinSock 2 library (ws2_32.dll).
+ */
+ hLibrary = LoadLibraryA("ws2_32");
+
+ /* If hLibrary is null, we couldn't find a dll with functions */
+ if (hLibrary != NULL)
+ {
+ /* We found a dll, so now get the addresses of the routines */
+
+ getaddrinfo_ptr = (getaddrinfo_ptr_t) (pg_funcptr_t) GetProcAddress(hLibrary,
+ "getaddrinfo");
+ freeaddrinfo_ptr = (freeaddrinfo_ptr_t) (pg_funcptr_t) GetProcAddress(hLibrary,
+ "freeaddrinfo");
+ getnameinfo_ptr = (getnameinfo_ptr_t) (pg_funcptr_t) GetProcAddress(hLibrary,
+ "getnameinfo");
+
+ /*
+ * If any one of the routines is missing, let's play it safe and
+ * ignore them all
+ */
+ if (getaddrinfo_ptr == NULL ||
+ freeaddrinfo_ptr == NULL ||
+ getnameinfo_ptr == NULL)
+ {
+ FreeLibrary(hLibrary);
+ hLibrary = NULL;
+ getaddrinfo_ptr = NULL;
+ freeaddrinfo_ptr = NULL;
+ getnameinfo_ptr = NULL;
+ }
+ }
+
+ alreadyLookedForIpv6routines = true;
+ return (getaddrinfo_ptr != NULL);
+}
+#endif
+
+
+/*
+ * get address info for ipv4 sockets.
+ *
+ * Bugs: - only one addrinfo is set even though hintp is NULL or
+ * ai_socktype is 0
+ * - AI_CANONNAME is not supported.
+ * - servname can only be a number, not text.
+ */
+int
+getaddrinfo(const char *node, const char *service,
+ const struct addrinfo *hintp,
+ struct addrinfo **res)
+{
+ struct addrinfo *ai;
+ struct sockaddr_in sin,
+ *psin;
+ struct addrinfo hints;
+
+#ifdef WIN32
+
+ /*
+ * If Windows has native IPv6 support, use the native Windows routine.
+ * Otherwise, fall through and use our own code.
+ */
+ if (haveNativeWindowsIPv6routines())
+ return (*getaddrinfo_ptr) (node, service, hintp, res);
+#endif
+
+ if (hintp == NULL)
+ {
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_STREAM;
+ }
+ else
+ memcpy(&hints, hintp, sizeof(hints));
+
+ if (hints.ai_family != AF_INET && hints.ai_family != AF_UNSPEC)
+ return EAI_FAMILY;
+
+ if (hints.ai_socktype == 0)
+ hints.ai_socktype = SOCK_STREAM;
+
+ if (!node && !service)
+ return EAI_NONAME;
+
+ memset(&sin, 0, sizeof(sin));
+
+ sin.sin_family = AF_INET;
+
+ if (node)
+ {
+ if (node[0] == '\0')
+ sin.sin_addr.s_addr = pg_hton32(INADDR_ANY);
+ else if (hints.ai_flags & AI_NUMERICHOST)
+ {
+ if (!inet_aton(node, &sin.sin_addr))
+ return EAI_NONAME;
+ }
+ else
+ {
+ struct hostent *hp;
+
+#ifdef FRONTEND
+ struct hostent hpstr;
+ char buf[BUFSIZ];
+ int herrno = 0;
+
+ pqGethostbyname(node, &hpstr, buf, sizeof(buf),
+ &hp, &herrno);
+#else
+ hp = gethostbyname(node);
+#endif
+ if (hp == NULL)
+ {
+ switch (h_errno)
+ {
+ case HOST_NOT_FOUND:
+ case NO_DATA:
+ return EAI_NONAME;
+ case TRY_AGAIN:
+ return EAI_AGAIN;
+ case NO_RECOVERY:
+ default:
+ return EAI_FAIL;
+ }
+ }
+ if (hp->h_addrtype != AF_INET)
+ return EAI_FAIL;
+
+ memcpy(&(sin.sin_addr), hp->h_addr, hp->h_length);
+ }
+ }
+ else
+ {
+ if (hints.ai_flags & AI_PASSIVE)
+ sin.sin_addr.s_addr = pg_hton32(INADDR_ANY);
+ else
+ sin.sin_addr.s_addr = pg_hton32(INADDR_LOOPBACK);
+ }
+
+ if (service)
+ sin.sin_port = pg_hton16((unsigned short) atoi(service));
+
+#ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN
+ sin.sin_len = sizeof(sin);
+#endif
+
+ ai = malloc(sizeof(*ai));
+ if (!ai)
+ return EAI_MEMORY;
+
+ psin = malloc(sizeof(*psin));
+ if (!psin)
+ {
+ free(ai);
+ return EAI_MEMORY;
+ }
+
+ memcpy(psin, &sin, sizeof(*psin));
+
+ ai->ai_flags = 0;
+ ai->ai_family = AF_INET;
+ ai->ai_socktype = hints.ai_socktype;
+ ai->ai_protocol = hints.ai_protocol;
+ ai->ai_addrlen = sizeof(*psin);
+ ai->ai_addr = (struct sockaddr *) psin;
+ ai->ai_canonname = NULL;
+ ai->ai_next = NULL;
+
+ *res = ai;
+
+ return 0;
+}
+
+
+void
+freeaddrinfo(struct addrinfo *res)
+{
+ if (res)
+ {
+#ifdef WIN32
+
+ /*
+ * If Windows has native IPv6 support, use the native Windows routine.
+ * Otherwise, fall through and use our own code.
+ */
+ if (haveNativeWindowsIPv6routines())
+ {
+ (*freeaddrinfo_ptr) (res);
+ return;
+ }
+#endif
+
+ if (res->ai_addr)
+ free(res->ai_addr);
+ free(res);
+ }
+}
+
+
+const char *
+gai_strerror(int errcode)
+{
+#ifdef HAVE_HSTRERROR
+ int hcode;
+
+ switch (errcode)
+ {
+ case EAI_NONAME:
+ hcode = HOST_NOT_FOUND;
+ break;
+ case EAI_AGAIN:
+ hcode = TRY_AGAIN;
+ break;
+ case EAI_FAIL:
+ default:
+ hcode = NO_RECOVERY;
+ break;
+ }
+
+ return hstrerror(hcode);
+#else /* !HAVE_HSTRERROR */
+
+ switch (errcode)
+ {
+ case EAI_NONAME:
+ return "Unknown host";
+ case EAI_AGAIN:
+ return "Host name lookup failure";
+ /* Errors below are probably WIN32 only */
+#ifdef EAI_BADFLAGS
+ case EAI_BADFLAGS:
+ return "Invalid argument";
+#endif
+#ifdef EAI_FAMILY
+ case EAI_FAMILY:
+ return "Address family not supported";
+#endif
+#ifdef EAI_MEMORY
+ case EAI_MEMORY:
+ return "Not enough memory";
+#endif
+#if defined(EAI_NODATA) && EAI_NODATA != EAI_NONAME /* MSVC/WIN64 duplicate */
+ case EAI_NODATA:
+ return "No host data of that type was found";
+#endif
+#ifdef EAI_SERVICE
+ case EAI_SERVICE:
+ return "Class type not found";
+#endif
+#ifdef EAI_SOCKTYPE
+ case EAI_SOCKTYPE:
+ return "Socket type not supported";
+#endif
+ default:
+ return "Unknown server error";
+ }
+#endif /* HAVE_HSTRERROR */
+}
+
+/*
+ * Convert an ipv4 address to a hostname.
+ *
+ * Bugs: - Only supports NI_NUMERICHOST and NI_NUMERICSERV behavior.
+ * It will never resolve a hostname.
+ * - No IPv6 support.
+ */
+int
+getnameinfo(const struct sockaddr *sa, int salen,
+ char *node, int nodelen,
+ char *service, int servicelen, int flags)
+{
+#ifdef WIN32
+
+ /*
+ * If Windows has native IPv6 support, use the native Windows routine.
+ * Otherwise, fall through and use our own code.
+ */
+ if (haveNativeWindowsIPv6routines())
+ return (*getnameinfo_ptr) (sa, salen, node, nodelen,
+ service, servicelen, flags);
+#endif
+
+ /* Invalid arguments. */
+ if (sa == NULL || (node == NULL && service == NULL))
+ return EAI_FAIL;
+
+#ifdef HAVE_IPV6
+ if (sa->sa_family == AF_INET6)
+ return EAI_FAMILY;
+#endif
+
+ /* Unsupported flags. */
+ if (flags & NI_NAMEREQD)
+ return EAI_AGAIN;
+
+ if (node)
+ {
+ if (sa->sa_family == AF_INET)
+ {
+ if (pg_inet_net_ntop(AF_INET,
+ &((struct sockaddr_in *) sa)->sin_addr,
+ sa->sa_family == AF_INET ? 32 : 128,
+ node, nodelen) == NULL)
+ return EAI_MEMORY;
+ }
+ else
+ return EAI_MEMORY;
+ }
+
+ if (service)
+ {
+ int ret = -1;
+
+ if (sa->sa_family == AF_INET)
+ {
+ ret = snprintf(service, servicelen, "%d",
+ pg_ntoh16(((struct sockaddr_in *) sa)->sin_port));
+ }
+ if (ret < 0 || ret >= servicelen)
+ return EAI_MEMORY;
+ }
+
+ return 0;
+}
diff --git a/contrib/libs/postgresql/src/port/getopt.c b/contrib/libs/postgresql/src/port/getopt.c
new file mode 100644
index 0000000000..207c2836d3
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/getopt.c
@@ -0,0 +1,136 @@
+/* src/port/getopt.c */
+
+/*
+ * Copyright (c) 1987, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ */
+
+#include "c.h"
+
+#include "pg_getopt.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getopt.c 8.3 (Berkeley) 4/27/95";
+#endif /* LIBC_SCCS and not lint */
+
+
+/*
+ * On OpenBSD and some versions of Solaris, opterr and friends are defined in
+ * core libc rather than in a separate getopt module. Define these variables
+ * only if configure found they aren't there by default; otherwise, this
+ * module and its callers will just use libc's variables. (We assume that
+ * testing opterr is sufficient for all of these.)
+ */
+#ifndef HAVE_INT_OPTERR
+
+int opterr = 1, /* if error message should be printed */
+ optind = 1, /* index into parent argv vector */
+ optopt; /* character checked for validity */
+char *optarg; /* argument associated with option */
+
+#endif
+
+#define BADCH (int)'?'
+#define BADARG (int)':'
+#define EMSG ""
+
+/*
+ * getopt
+ * Parse argc/argv argument vector.
+ *
+ * This implementation does not use optreset. Instead, we guarantee that
+ * it can be restarted on a new argv array after a previous call returned -1,
+ * if the caller resets optind to 1 before the first call of the new series.
+ * (Internally, this means we must be sure to reset "place" to EMSG before
+ * returning -1.)
+ */
+int
+getopt(int nargc, char *const *nargv, const char *ostr)
+{
+ static char *place = EMSG; /* option letter processing */
+ char *oli; /* option letter list index */
+
+ if (!*place)
+ { /* update scanning pointer */
+ if (optind >= nargc || *(place = nargv[optind]) != '-')
+ {
+ place = EMSG;
+ return -1;
+ }
+ if (place[1] && *++place == '-' && place[1] == '\0')
+ { /* found "--" */
+ ++optind;
+ place = EMSG;
+ return -1;
+ }
+ } /* option letter okay? */
+ if ((optopt = (int) *place++) == (int) ':' ||
+ !(oli = strchr(ostr, optopt)))
+ {
+ /*
+ * if the user didn't specify '-' as an option, assume it means -1.
+ */
+ if (optopt == (int) '-')
+ {
+ place = EMSG;
+ return -1;
+ }
+ if (!*place)
+ ++optind;
+ if (opterr && *ostr != ':')
+ (void) fprintf(stderr,
+ "illegal option -- %c\n", optopt);
+ return BADCH;
+ }
+ if (*++oli != ':')
+ { /* don't need argument */
+ optarg = NULL;
+ if (!*place)
+ ++optind;
+ }
+ else
+ { /* need an argument */
+ if (*place) /* no white space */
+ optarg = place;
+ else if (nargc <= ++optind)
+ { /* no arg */
+ place = EMSG;
+ if (*ostr == ':')
+ return BADARG;
+ if (opterr)
+ (void) fprintf(stderr,
+ "option requires an argument -- %c\n",
+ optopt);
+ return BADCH;
+ }
+ else
+ /* white space */
+ optarg = nargv[optind];
+ place = EMSG;
+ ++optind;
+ }
+ return optopt; /* dump back option letter */
+}
diff --git a/contrib/libs/postgresql/src/port/getrusage.c b/contrib/libs/postgresql/src/port/getrusage.c
new file mode 100644
index 0000000000..99f240f6da
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/getrusage.c
@@ -0,0 +1,110 @@
+/*-------------------------------------------------------------------------
+ *
+ * getrusage.c
+ * get information about resource utilisation
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/port/getrusage.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#include "rusagestub.h"
+
+/* This code works on:
+ * solaris_i386
+ * solaris_sparc
+ * hpux 9.*
+ * win32
+ * which currently is all the supported platforms that don't have a
+ * native version of getrusage(). So, if configure decides to compile
+ * this file at all, we just use this version unconditionally.
+ */
+
+int
+getrusage(int who, struct rusage *rusage)
+{
+#ifdef WIN32
+ FILETIME starttime;
+ FILETIME exittime;
+ FILETIME kerneltime;
+ FILETIME usertime;
+ ULARGE_INTEGER li;
+
+ if (who != RUSAGE_SELF)
+ {
+ /* Only RUSAGE_SELF is supported in this implementation for now */
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (rusage == (struct rusage *) NULL)
+ {
+ errno = EFAULT;
+ return -1;
+ }
+ memset(rusage, 0, sizeof(struct rusage));
+ if (GetProcessTimes(GetCurrentProcess(),
+ &starttime, &exittime, &kerneltime, &usertime) == 0)
+ {
+ _dosmaperr(GetLastError());
+ return -1;
+ }
+
+ /* Convert FILETIMEs (0.1 us) to struct timeval */
+ memcpy(&li, &kerneltime, sizeof(FILETIME));
+ li.QuadPart /= 10L; /* Convert to microseconds */
+ rusage->ru_stime.tv_sec = li.QuadPart / 1000000L;
+ rusage->ru_stime.tv_usec = li.QuadPart % 1000000L;
+
+ memcpy(&li, &usertime, sizeof(FILETIME));
+ li.QuadPart /= 10L; /* Convert to microseconds */
+ rusage->ru_utime.tv_sec = li.QuadPart / 1000000L;
+ rusage->ru_utime.tv_usec = li.QuadPart % 1000000L;
+#else /* all but WIN32 */
+
+ struct tms tms;
+ int tick_rate = CLK_TCK; /* ticks per second */
+ clock_t u,
+ s;
+
+ if (rusage == (struct rusage *) NULL)
+ {
+ errno = EFAULT;
+ return -1;
+ }
+ if (times(&tms) < 0)
+ {
+ /* errno set by times */
+ return -1;
+ }
+ switch (who)
+ {
+ case RUSAGE_SELF:
+ u = tms.tms_utime;
+ s = tms.tms_stime;
+ break;
+ case RUSAGE_CHILDREN:
+ u = tms.tms_cutime;
+ s = tms.tms_cstime;
+ break;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+#define TICK_TO_SEC(T, RATE) ((T)/(RATE))
+#define TICK_TO_USEC(T,RATE) (((T)%(RATE)*1000000)/RATE)
+ rusage->ru_utime.tv_sec = TICK_TO_SEC(u, tick_rate);
+ rusage->ru_utime.tv_usec = TICK_TO_USEC(u, tick_rate);
+ rusage->ru_stime.tv_sec = TICK_TO_SEC(s, tick_rate);
+ rusage->ru_stime.tv_usec = TICK_TO_USEC(u, tick_rate);
+#endif /* WIN32 */
+
+ return 0;
+}
diff --git a/contrib/libs/postgresql/src/port/gettimeofday.c b/contrib/libs/postgresql/src/port/gettimeofday.c
new file mode 100644
index 0000000000..ee8fe82337
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/gettimeofday.c
@@ -0,0 +1,118 @@
+/*
+ * gettimeofday.c
+ * Win32 gettimeofday() replacement
+ *
+ * src/port/gettimeofday.c
+ *
+ * Copyright (c) 2003 SRA, Inc.
+ * Copyright (c) 2003 SKC, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose, without fee, and without a
+ * written agreement is hereby granted, provided that the above
+ * copyright notice and this paragraph and the following two
+ * paragraphs appear in all copies.
+ *
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT,
+ * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
+ * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
+ * DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS
+ * IS" BASIS, AND THE AUTHOR HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE,
+ * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#include "c.h"
+
+#include <sys/time.h>
+
+/* FILETIME of Jan 1 1970 00:00:00, the PostgreSQL epoch */
+static const unsigned __int64 epoch = UINT64CONST(116444736000000000);
+
+/*
+ * FILETIME represents the number of 100-nanosecond intervals since
+ * January 1, 1601 (UTC).
+ */
+#define FILETIME_UNITS_PER_SEC 10000000L
+#define FILETIME_UNITS_PER_USEC 10
+
+/*
+ * Both GetSystemTimeAsFileTime and GetSystemTimePreciseAsFileTime share a
+ * signature, so we can just store a pointer to whichever we find. This
+ * is the pointer's type.
+ */
+typedef VOID(WINAPI * PgGetSystemTimeFn) (LPFILETIME);
+
+/* One-time initializer function, must match that signature. */
+static void WINAPI init_gettimeofday(LPFILETIME lpSystemTimeAsFileTime);
+
+/* Storage for the function we pick at runtime */
+static PgGetSystemTimeFn pg_get_system_time = &init_gettimeofday;
+
+/*
+ * One time initializer. Determine whether GetSystemTimePreciseAsFileTime
+ * is available and if so, plan to use it; if not, fall back to
+ * GetSystemTimeAsFileTime.
+ */
+static void WINAPI
+init_gettimeofday(LPFILETIME lpSystemTimeAsFileTime)
+{
+ /*
+ * Because it's guaranteed that kernel32.dll will be linked into our
+ * address space already, we don't need to LoadLibrary it and worry about
+ * closing it afterwards, so we're not using Pg's dlopen/dlsym() wrapper.
+ *
+ * We'll just look up the address of GetSystemTimePreciseAsFileTime if
+ * present.
+ *
+ * While we could look up the Windows version and skip this on Windows
+ * versions below Windows 8 / Windows Server 2012 there isn't much point,
+ * and determining the windows version is its self somewhat Windows
+ * version and development SDK specific...
+ */
+ pg_get_system_time = (PgGetSystemTimeFn) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
+ "GetSystemTimePreciseAsFileTime");
+ if (pg_get_system_time == NULL)
+ {
+ /*
+ * The expected error from GetLastError() is ERROR_PROC_NOT_FOUND, if
+ * the function isn't present. No other error should occur.
+ *
+ * We can't report an error here because this might be running in
+ * frontend code; and even if we're in the backend, it's too early to
+ * elog(...) if we get some unexpected error. Also, it's not a
+ * serious problem, so just silently fall back to
+ * GetSystemTimeAsFileTime irrespective of why the failure occurred.
+ */
+ pg_get_system_time = &GetSystemTimeAsFileTime;
+ }
+
+ (*pg_get_system_time) (lpSystemTimeAsFileTime);
+}
+
+/*
+ * timezone information is stored outside the kernel so tzp isn't used anymore.
+ *
+ * Note: this function is not for Win32 high precision timing purposes. See
+ * elapsed_time().
+ */
+int
+gettimeofday(struct timeval *tp, struct timezone *tzp)
+{
+ FILETIME file_time;
+ ULARGE_INTEGER ularge;
+
+ (*pg_get_system_time) (&file_time);
+ ularge.LowPart = file_time.dwLowDateTime;
+ ularge.HighPart = file_time.dwHighDateTime;
+
+ tp->tv_sec = (long) ((ularge.QuadPart - epoch) / FILETIME_UNITS_PER_SEC);
+ tp->tv_usec = (long) (((ularge.QuadPart - epoch) % FILETIME_UNITS_PER_SEC)
+ / FILETIME_UNITS_PER_USEC);
+
+ return 0;
+}
diff --git a/contrib/libs/postgresql/src/port/inet_aton.c b/contrib/libs/postgresql/src/port/inet_aton.c
new file mode 100644
index 0000000000..adaf18adb3
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/inet_aton.c
@@ -0,0 +1,149 @@
+/* src/port/inet_aton.c
+ *
+ * This inet_aton() function was taken from the GNU C library and
+ * incorporated into Postgres for those systems which do not have this
+ * routine in their standard C libraries.
+ *
+ * The function was been extracted whole from the file inet_aton.c in
+ * Release 5.3.12 of the Linux C library, which is derived from the
+ * GNU C library, by Bryan Henderson in October 1996. The copyright
+ * notice from that file is below.
+ */
+
+/*
+ * Copyright (c) 1983, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE. */
+
+#include "c.h"
+
+#include <netinet/in.h>
+#include <ctype.h>
+
+#include "port/pg_bswap.h"
+
+/*
+ * Check whether "cp" is a valid ascii representation
+ * of an Internet address and convert to a binary address.
+ * Returns 1 if the address is valid, 0 if not.
+ * This replaces inet_addr, the return value from which
+ * cannot distinguish between failure and a local broadcast address.
+ */
+int
+inet_aton(const char *cp, struct in_addr *addr)
+{
+ unsigned int val;
+ int base,
+ n;
+ char c;
+ u_int parts[4];
+ u_int *pp = parts;
+
+ for (;;)
+ {
+ /*
+ * Collect number up to ``.''. Values are specified as for C: 0x=hex,
+ * 0=octal, other=decimal.
+ */
+ val = 0;
+ base = 10;
+ if (*cp == '0')
+ {
+ if (*++cp == 'x' || *cp == 'X')
+ base = 16, cp++;
+ else
+ base = 8;
+ }
+ while ((c = *cp) != '\0')
+ {
+ if (isdigit((unsigned char) c))
+ {
+ val = (val * base) + (c - '0');
+ cp++;
+ continue;
+ }
+ if (base == 16 && isxdigit((unsigned char) c))
+ {
+ val = (val << 4) +
+ (c + 10 - (islower((unsigned char) c) ? 'a' : 'A'));
+ cp++;
+ continue;
+ }
+ break;
+ }
+ if (*cp == '.')
+ {
+ /*
+ * Internet format: a.b.c.d a.b.c (with c treated as 16-bits)
+ * a.b (with b treated as 24 bits)
+ */
+ if (pp >= parts + 3 || val > 0xff)
+ return 0;
+ *pp++ = val, cp++;
+ }
+ else
+ break;
+ }
+
+ /*
+ * Check for trailing junk.
+ */
+ while (*cp)
+ if (!isspace((unsigned char) *cp++))
+ return 0;
+
+ /*
+ * Concoct the address according to the number of parts specified.
+ */
+ n = pp - parts + 1;
+ switch (n)
+ {
+
+ case 1: /* a -- 32 bits */
+ break;
+
+ case 2: /* a.b -- 8.24 bits */
+ if (val > 0xffffff)
+ return 0;
+ val |= parts[0] << 24;
+ break;
+
+ case 3: /* a.b.c -- 8.8.16 bits */
+ if (val > 0xffff)
+ return 0;
+ val |= (parts[0] << 24) | (parts[1] << 16);
+ break;
+
+ case 4: /* a.b.c.d -- 8.8.8.8 bits */
+ if (val > 0xff)
+ return 0;
+ val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
+ break;
+ }
+ if (addr)
+ addr->s_addr = pg_hton32(val);
+ return 1;
+}
diff --git a/contrib/libs/postgresql/src/port/kill.c b/contrib/libs/postgresql/src/port/kill.c
new file mode 100644
index 0000000000..99b35de45b
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/kill.c
@@ -0,0 +1,97 @@
+/*-------------------------------------------------------------------------
+ *
+ * kill.c
+ * kill()
+ *
+ * Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * This is a replacement version of kill for Win32 which sends
+ * signals that the backend can recognize.
+ *
+ * IDENTIFICATION
+ * src/port/kill.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#ifdef WIN32
+/* signal sending */
+int
+pgkill(int pid, int sig)
+{
+ char pipename[128];
+ BYTE sigData = sig;
+ BYTE sigRet = 0;
+ DWORD bytes;
+
+ /* we allow signal 0 here, but it will be ignored in pg_queue_signal */
+ if (sig >= PG_SIGNAL_COUNT || sig < 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ if (pid <= 0)
+ {
+ /* No support for process groups */
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* special case for SIGKILL: just ask the system to terminate the target */
+ if (sig == SIGKILL)
+ {
+ HANDLE prochandle;
+
+ if ((prochandle = OpenProcess(PROCESS_TERMINATE, FALSE, (DWORD) pid)) == NULL)
+ {
+ errno = ESRCH;
+ return -1;
+ }
+ if (!TerminateProcess(prochandle, 255))
+ {
+ _dosmaperr(GetLastError());
+ CloseHandle(prochandle);
+ return -1;
+ }
+ CloseHandle(prochandle);
+ return 0;
+ }
+ snprintf(pipename, sizeof(pipename), "\\\\.\\pipe\\pgsignal_%u", pid);
+
+ if (CallNamedPipe(pipename, &sigData, 1, &sigRet, 1, &bytes, 1000))
+ {
+ if (bytes != 1 || sigRet != sig)
+ {
+ errno = ESRCH;
+ return -1;
+ }
+ return 0;
+ }
+
+ switch (GetLastError())
+ {
+ case ERROR_BROKEN_PIPE:
+ case ERROR_BAD_PIPE:
+
+ /*
+ * These arise transiently as a process is exiting. Treat them
+ * like POSIX treats a zombie process, reporting success.
+ */
+ return 0;
+
+ case ERROR_FILE_NOT_FOUND:
+ /* pipe fully gone, so treat the process as gone */
+ errno = ESRCH;
+ return -1;
+ case ERROR_ACCESS_DENIED:
+ errno = EPERM;
+ return -1;
+ default:
+ errno = EINVAL; /* unexpected */
+ return -1;
+ }
+}
+
+#endif
diff --git a/contrib/libs/postgresql/src/port/open.c b/contrib/libs/postgresql/src/port/open.c
new file mode 100644
index 0000000000..14c6debba9
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/open.c
@@ -0,0 +1,216 @@
+/*-------------------------------------------------------------------------
+ *
+ * open.c
+ * Win32 open() replacement
+ *
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * src/port/open.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifdef WIN32
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include <fcntl.h>
+#include <assert.h>
+#include <sys/stat.h>
+
+
+static int
+openFlagsToCreateFileFlags(int openFlags)
+{
+ switch (openFlags & (O_CREAT | O_TRUNC | O_EXCL))
+ {
+ /* O_EXCL is meaningless without O_CREAT */
+ case 0:
+ case O_EXCL:
+ return OPEN_EXISTING;
+
+ case O_CREAT:
+ return OPEN_ALWAYS;
+
+ /* O_EXCL is meaningless without O_CREAT */
+ case O_TRUNC:
+ case O_TRUNC | O_EXCL:
+ return TRUNCATE_EXISTING;
+
+ case O_CREAT | O_TRUNC:
+ return CREATE_ALWAYS;
+
+ /* O_TRUNC is meaningless with O_CREAT */
+ case O_CREAT | O_EXCL:
+ case O_CREAT | O_TRUNC | O_EXCL:
+ return CREATE_NEW;
+ }
+
+ /* will never get here */
+ return 0;
+}
+
+/*
+ * - file attribute setting, based on fileMode?
+ */
+int
+pgwin32_open(const char *fileName, int fileFlags,...)
+{
+ int fd;
+ HANDLE h = INVALID_HANDLE_VALUE;
+ SECURITY_ATTRIBUTES sa;
+ int loops = 0;
+
+ /* Check that we can handle the request */
+ assert((fileFlags & ((O_RDONLY | O_WRONLY | O_RDWR) | O_APPEND |
+ (O_RANDOM | O_SEQUENTIAL | O_TEMPORARY) |
+ _O_SHORT_LIVED | O_DSYNC | O_DIRECT |
+ (O_CREAT | O_TRUNC | O_EXCL) | (O_TEXT | O_BINARY))) == fileFlags);
+#ifndef FRONTEND
+ Assert(pgwin32_signal_event != NULL); /* small chance of pg_usleep() */
+#endif
+
+#ifdef FRONTEND
+
+ /*
+ * Since PostgreSQL 12, those concurrent-safe versions of open() and
+ * fopen() can be used by frontends, having as side-effect to switch the
+ * file-translation mode from O_TEXT to O_BINARY if none is specified.
+ * Caller may want to enforce the binary or text mode, but if nothing is
+ * defined make sure that the default mode maps with what versions older
+ * than 12 have been doing.
+ */
+ if ((fileFlags & O_BINARY) == 0)
+ fileFlags |= O_TEXT;
+#endif
+
+ sa.nLength = sizeof(sa);
+ sa.bInheritHandle = TRUE;
+ sa.lpSecurityDescriptor = NULL;
+
+ while ((h = CreateFile(fileName,
+ /* cannot use O_RDONLY, as it == 0 */
+ (fileFlags & O_RDWR) ? (GENERIC_WRITE | GENERIC_READ) :
+ ((fileFlags & O_WRONLY) ? GENERIC_WRITE : GENERIC_READ),
+ /* These flags allow concurrent rename/unlink */
+ (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),
+ &sa,
+ openFlagsToCreateFileFlags(fileFlags),
+ FILE_ATTRIBUTE_NORMAL |
+ ((fileFlags & O_RANDOM) ? FILE_FLAG_RANDOM_ACCESS : 0) |
+ ((fileFlags & O_SEQUENTIAL) ? FILE_FLAG_SEQUENTIAL_SCAN : 0) |
+ ((fileFlags & _O_SHORT_LIVED) ? FILE_ATTRIBUTE_TEMPORARY : 0) |
+ ((fileFlags & O_TEMPORARY) ? FILE_FLAG_DELETE_ON_CLOSE : 0) |
+ ((fileFlags & O_DIRECT) ? FILE_FLAG_NO_BUFFERING : 0) |
+ ((fileFlags & O_DSYNC) ? FILE_FLAG_WRITE_THROUGH : 0),
+ NULL)) == INVALID_HANDLE_VALUE)
+ {
+ /*
+ * Sharing violation or locking error can indicate antivirus, backup
+ * or similar software that's locking the file. Wait a bit and try
+ * again, giving up after 30 seconds.
+ */
+ DWORD err = GetLastError();
+
+ if (err == ERROR_SHARING_VIOLATION ||
+ err == ERROR_LOCK_VIOLATION)
+ {
+#ifndef FRONTEND
+ if (loops == 50)
+ ereport(LOG,
+ (errmsg("could not open file \"%s\": %s", fileName,
+ (err == ERROR_SHARING_VIOLATION) ? _("sharing violation") : _("lock violation")),
+ errdetail("Continuing to retry for 30 seconds."),
+ errhint("You might have antivirus, backup, or similar software interfering with the database system.")));
+#endif
+
+ if (loops < 300)
+ {
+ pg_usleep(100000);
+ loops++;
+ continue;
+ }
+ }
+
+ /*
+ * ERROR_ACCESS_DENIED is returned if the file is deleted but not yet
+ * gone (Windows NT status code is STATUS_DELETE_PENDING). In that
+ * case we want to wait a bit and try again, giving up after 1 second
+ * (since this condition should never persist very long). However,
+ * there are other commonly-hit cases that return ERROR_ACCESS_DENIED,
+ * so care is needed. In particular that happens if we try to open a
+ * directory, or of course if there's an actual file-permissions
+ * problem. To distinguish these cases, try a stat(). In the
+ * delete-pending case, it will either also get STATUS_DELETE_PENDING,
+ * or it will see the file as gone and fail with ENOENT. In other
+ * cases it will usually succeed. The only somewhat-likely case where
+ * this coding will uselessly wait is if there's a permissions problem
+ * with a containing directory, which we hope will never happen in any
+ * performance-critical code paths.
+ */
+ if (err == ERROR_ACCESS_DENIED)
+ {
+ if (loops < 10)
+ {
+ struct stat st;
+
+ if (stat(fileName, &st) != 0)
+ {
+ pg_usleep(100000);
+ loops++;
+ continue;
+ }
+ }
+ }
+
+ _dosmaperr(err);
+ return -1;
+ }
+
+ /* _open_osfhandle will, on error, set errno accordingly */
+ if ((fd = _open_osfhandle((intptr_t) h, fileFlags & O_APPEND)) < 0)
+ CloseHandle(h); /* will not affect errno */
+ else if (fileFlags & (O_TEXT | O_BINARY) &&
+ _setmode(fd, fileFlags & (O_TEXT | O_BINARY)) < 0)
+ {
+ _close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+FILE *
+pgwin32_fopen(const char *fileName, const char *mode)
+{
+ int openmode = 0;
+ int fd;
+
+ if (strstr(mode, "r+"))
+ openmode |= O_RDWR;
+ else if (strchr(mode, 'r'))
+ openmode |= O_RDONLY;
+ if (strstr(mode, "w+"))
+ openmode |= O_RDWR | O_CREAT | O_TRUNC;
+ else if (strchr(mode, 'w'))
+ openmode |= O_WRONLY | O_CREAT | O_TRUNC;
+ if (strchr(mode, 'a'))
+ openmode |= O_WRONLY | O_CREAT | O_APPEND;
+
+ if (strchr(mode, 'b'))
+ openmode |= O_BINARY;
+ if (strchr(mode, 't'))
+ openmode |= O_TEXT;
+
+ fd = pgwin32_open(fileName, openmode);
+ if (fd == -1)
+ return NULL;
+ return _fdopen(fd, mode);
+}
+
+#endif
diff --git a/contrib/libs/postgresql/src/port/pread.c b/contrib/libs/postgresql/src/port/pread.c
new file mode 100644
index 0000000000..486f07a7df
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/pread.c
@@ -0,0 +1,58 @@
+/*-------------------------------------------------------------------------
+ *
+ * pread.c
+ * Implementation of pread(2) for platforms that lack one.
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/port/pread.c
+ *
+ * Note that this implementation changes the current file position, unlike
+ * the POSIX function, so we use the name pg_pread().
+ *
+ *-------------------------------------------------------------------------
+ */
+
+
+#include "postgres.h"
+
+#ifdef WIN32
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+
+ssize_t
+pg_pread(int fd, void *buf, size_t size, off_t offset)
+{
+#ifdef WIN32
+ OVERLAPPED overlapped = {0};
+ HANDLE handle;
+ DWORD result;
+
+ handle = (HANDLE) _get_osfhandle(fd);
+ if (handle == INVALID_HANDLE_VALUE)
+ {
+ errno = EBADF;
+ return -1;
+ }
+
+ overlapped.Offset = offset;
+ if (!ReadFile(handle, buf, size, &result, &overlapped))
+ {
+ if (GetLastError() == ERROR_HANDLE_EOF)
+ return 0;
+
+ _dosmaperr(GetLastError());
+ return -1;
+ }
+
+ return result;
+#else
+ if (lseek(fd, offset, SEEK_SET) < 0)
+ return -1;
+
+ return read(fd, buf, size);
+#endif
+}
diff --git a/contrib/libs/postgresql/src/port/pwrite.c b/contrib/libs/postgresql/src/port/pwrite.c
new file mode 100644
index 0000000000..282b27115e
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/pwrite.c
@@ -0,0 +1,55 @@
+/*-------------------------------------------------------------------------
+ *
+ * pwrite.c
+ * Implementation of pwrite(2) for platforms that lack one.
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/port/pwrite.c
+ *
+ * Note that this implementation changes the current file position, unlike
+ * the POSIX function, so we use the name pg_pwrite().
+ *
+ *-------------------------------------------------------------------------
+ */
+
+
+#include "postgres.h"
+
+#ifdef WIN32
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+
+ssize_t
+pg_pwrite(int fd, const void *buf, size_t size, off_t offset)
+{
+#ifdef WIN32
+ OVERLAPPED overlapped = {0};
+ HANDLE handle;
+ DWORD result;
+
+ handle = (HANDLE) _get_osfhandle(fd);
+ if (handle == INVALID_HANDLE_VALUE)
+ {
+ errno = EBADF;
+ return -1;
+ }
+
+ overlapped.Offset = offset;
+ if (!WriteFile(handle, buf, size, &result, &overlapped))
+ {
+ _dosmaperr(GetLastError());
+ return -1;
+ }
+
+ return result;
+#else
+ if (lseek(fd, offset, SEEK_SET) < 0)
+ return -1;
+
+ return write(fd, buf, size);
+#endif
+}
diff --git a/contrib/libs/postgresql/src/port/pwritev.c b/contrib/libs/postgresql/src/port/pwritev.c
new file mode 100644
index 0000000000..2e8ef7e378
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/pwritev.c
@@ -0,0 +1,58 @@
+/*-------------------------------------------------------------------------
+ *
+ * pwritev.c
+ * Implementation of pwritev(2) for platforms that lack one.
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/port/pwritev.c
+ *
+ * Note that this implementation changes the current file position, unlike
+ * the POSIX-like function, so we use the name pg_pwritev().
+ *
+ *-------------------------------------------------------------------------
+ */
+
+
+#include "postgres.h"
+
+#ifdef WIN32
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+
+#include "port/pg_iovec.h"
+
+ssize_t
+pg_pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset)
+{
+#ifdef HAVE_WRITEV
+ if (iovcnt == 1)
+ return pg_pwrite(fd, iov[0].iov_base, iov[0].iov_len, offset);
+ if (lseek(fd, offset, SEEK_SET) < 0)
+ return -1;
+ return writev(fd, iov, iovcnt);
+#else
+ ssize_t sum = 0;
+ ssize_t part;
+
+ for (int i = 0; i < iovcnt; ++i)
+ {
+ part = pg_pwrite(fd, iov[i].iov_base, iov[i].iov_len, offset);
+ if (part < 0)
+ {
+ if (i == 0)
+ return -1;
+ else
+ return sum;
+ }
+ sum += part;
+ offset += part;
+ if (part < iov[i].iov_len)
+ return sum;
+ }
+ return sum;
+#endif
+}
diff --git a/contrib/libs/postgresql/src/port/system.c b/contrib/libs/postgresql/src/port/system.c
new file mode 100644
index 0000000000..8618e47f97
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/system.c
@@ -0,0 +1,117 @@
+/*-------------------------------------------------------------------------
+ *
+ * system.c
+ * Win32 system() and popen() replacements
+ *
+ *
+ * Win32 needs double quotes at the beginning and end of system()
+ * strings. If not, it gets confused with multiple quoted strings.
+ * It also requires double-quotes around the executable name and
+ * any files used for redirection. Filter other args through
+ * appendShellString() to quote them.
+ *
+ * Generated using Win32 "CMD /?":
+ *
+ * 1. If all of the following conditions are met, then quote characters
+ * on the command line are preserved:
+ *
+ * - no /S switch
+ * - exactly two quote characters
+ * - no special characters between the two quote characters, where special
+ * is one of: &<>()@^|
+ * - there are one or more whitespace characters between the two quote
+ * characters
+ * - the string between the two quote characters is the name of an
+ * executable file.
+ *
+ * 2. Otherwise, old behavior is to see if the first character is a quote
+ * character and if so, strip the leading character and remove the last
+ * quote character on the command line, preserving any text after the last
+ * quote character.
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * src/port/system.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#if defined(WIN32) && !defined(__CYGWIN__)
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include <fcntl.h>
+
+#undef system
+#undef popen
+
+int
+pgwin32_system(const char *command)
+{
+ size_t cmdlen = strlen(command);
+ char *buf;
+ int save_errno;
+ int res;
+
+ /*
+ * Create a malloc'd copy of the command string, enclosed with an extra
+ * pair of quotes
+ */
+ buf = malloc(cmdlen + 2 + 1);
+ if (buf == NULL)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ buf[0] = '"';
+ memcpy(&buf[1], command, cmdlen);
+ buf[cmdlen + 1] = '"';
+ buf[cmdlen + 2] = '\0';
+
+ res = system(buf);
+
+ save_errno = errno;
+ free(buf);
+ errno = save_errno;
+
+ return res;
+}
+
+
+FILE *
+pgwin32_popen(const char *command, const char *type)
+{
+ size_t cmdlen = strlen(command);
+ char *buf;
+ int save_errno;
+ FILE *res;
+
+ /*
+ * Create a malloc'd copy of the command string, enclosed with an extra
+ * pair of quotes
+ */
+ buf = malloc(cmdlen + 2 + 1);
+ if (buf == NULL)
+ {
+ errno = ENOMEM;
+ return NULL;
+ }
+ buf[0] = '"';
+ memcpy(&buf[1], command, cmdlen);
+ buf[cmdlen + 1] = '"';
+ buf[cmdlen + 2] = '\0';
+
+ res = _popen(buf, type);
+
+ save_errno = errno;
+ free(buf);
+ errno = save_errno;
+
+ return res;
+}
+
+#endif
diff --git a/contrib/libs/postgresql/src/port/win32env.c b/contrib/libs/postgresql/src/port/win32env.c
new file mode 100644
index 0000000000..a03556078c
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/win32env.c
@@ -0,0 +1,163 @@
+/*-------------------------------------------------------------------------
+ *
+ * win32env.c
+ * putenv(), setenv(), and unsetenv() for win32.
+ *
+ * These functions update both the process environment and caches in
+ * (potentially multiple) C run-time library (CRT) versions.
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/port/win32env.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+
+/*
+ * Note that unlike POSIX putenv(), this doesn't use the passed-in string
+ * as permanent storage.
+ */
+int
+pgwin32_putenv(const char *envval)
+{
+ char *envcpy;
+ char *cp;
+ typedef int (_cdecl * PUTENVPROC) (const char *);
+ static const char *const modulenames[] = {
+ "msvcrt", /* Visual Studio 6.0 / MinGW */
+ "msvcrtd",
+ "msvcr70", /* Visual Studio 2002 */
+ "msvcr70d",
+ "msvcr71", /* Visual Studio 2003 */
+ "msvcr71d",
+ "msvcr80", /* Visual Studio 2005 */
+ "msvcr80d",
+ "msvcr90", /* Visual Studio 2008 */
+ "msvcr90d",
+ "msvcr100", /* Visual Studio 2010 */
+ "msvcr100d",
+ "msvcr110", /* Visual Studio 2012 */
+ "msvcr110d",
+ "msvcr120", /* Visual Studio 2013 */
+ "msvcr120d",
+ "ucrtbase", /* Visual Studio 2015 and later */
+ "ucrtbased",
+ NULL
+ };
+ int i;
+
+ /*
+ * Update process environment, making this change visible to child
+ * processes and to CRTs initializing in the future. Do this before the
+ * _putenv() loop, for the benefit of any CRT that initializes during this
+ * pgwin32_putenv() execution, after the loop checks that CRT.
+ *
+ * Need a copy of the string so we can modify it.
+ */
+ envcpy = strdup(envval);
+ if (!envcpy)
+ return -1;
+ cp = strchr(envcpy, '=');
+ if (cp == NULL)
+ {
+ free(envcpy);
+ return -1;
+ }
+ *cp = '\0';
+ cp++;
+ if (*cp)
+ {
+ /*
+ * Only call SetEnvironmentVariable() when we are adding a variable,
+ * not when removing it. Calling it on both crashes on at least
+ * certain versions of MinGW.
+ */
+ if (!SetEnvironmentVariable(envcpy, cp))
+ {
+ free(envcpy);
+ return -1;
+ }
+ }
+ free(envcpy);
+
+ /*
+ * Each CRT has its own _putenv() symbol and copy of the environment.
+ * Update the environment in each CRT module currently loaded, so every
+ * third-party library sees this change regardless of the CRT it links
+ * against. Addresses within these modules may become invalid the moment
+ * we call FreeLibrary(), so don't cache them.
+ */
+ for (i = 0; modulenames[i]; i++)
+ {
+ HMODULE hmodule = NULL;
+ BOOL res = GetModuleHandleEx(0, modulenames[i], &hmodule);
+
+ if (res != 0 && hmodule != NULL)
+ {
+ PUTENVPROC putenvFunc;
+
+ putenvFunc = (PUTENVPROC) (pg_funcptr_t) GetProcAddress(hmodule, "_putenv");
+ if (putenvFunc)
+ putenvFunc(envval);
+ FreeLibrary(hmodule);
+ }
+ }
+
+ /*
+ * Finally, update our "own" cache. This is redundant with the loop
+ * above, except when PostgreSQL itself links to a CRT not listed above.
+ * Ideally, the loop does visit all possible CRTs, making this redundant.
+ */
+ return _putenv(envval);
+}
+
+int
+pgwin32_setenv(const char *name, const char *value, int overwrite)
+{
+ int res;
+ char *envstr;
+
+ /* Error conditions, per POSIX */
+ if (name == NULL || name[0] == '\0' || strchr(name, '=') != NULL ||
+ value == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* No work if variable exists and we're not to replace it */
+ if (overwrite == 0 && getenv(name) != NULL)
+ return 0;
+
+ envstr = (char *) malloc(strlen(name) + strlen(value) + 2);
+ if (!envstr) /* not much we can do if no memory */
+ return -1;
+
+ sprintf(envstr, "%s=%s", name, value);
+
+ res = pgwin32_putenv(envstr);
+ free(envstr);
+ return res;
+}
+
+int
+pgwin32_unsetenv(const char *name)
+{
+ int res;
+ char *envbuf;
+
+ envbuf = (char *) malloc(strlen(name) + 2);
+ if (!envbuf)
+ return -1;
+
+ sprintf(envbuf, "%s=", name);
+ res = pgwin32_putenv(envbuf);
+ free(envbuf);
+ return res;
+}
diff --git a/contrib/libs/postgresql/src/port/win32error.c b/contrib/libs/postgresql/src/port/win32error.c
new file mode 100644
index 0000000000..0e5f91adfa
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/win32error.c
@@ -0,0 +1,208 @@
+/*-------------------------------------------------------------------------
+ *
+ * win32error.c
+ * Map win32 error codes to errno values
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/port/win32error.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+static const struct
+{
+ DWORD winerr;
+ int doserr;
+} doserrors[] =
+
+{
+ {
+ ERROR_INVALID_FUNCTION, EINVAL
+ },
+ {
+ ERROR_FILE_NOT_FOUND, ENOENT
+ },
+ {
+ ERROR_PATH_NOT_FOUND, ENOENT
+ },
+ {
+ ERROR_TOO_MANY_OPEN_FILES, EMFILE
+ },
+ {
+ ERROR_ACCESS_DENIED, EACCES
+ },
+ {
+ ERROR_INVALID_HANDLE, EBADF
+ },
+ {
+ ERROR_ARENA_TRASHED, ENOMEM
+ },
+ {
+ ERROR_NOT_ENOUGH_MEMORY, ENOMEM
+ },
+ {
+ ERROR_INVALID_BLOCK, ENOMEM
+ },
+ {
+ ERROR_BAD_ENVIRONMENT, E2BIG
+ },
+ {
+ ERROR_BAD_FORMAT, ENOEXEC
+ },
+ {
+ ERROR_INVALID_ACCESS, EINVAL
+ },
+ {
+ ERROR_INVALID_DATA, EINVAL
+ },
+ {
+ ERROR_INVALID_DRIVE, ENOENT
+ },
+ {
+ ERROR_CURRENT_DIRECTORY, EACCES
+ },
+ {
+ ERROR_NOT_SAME_DEVICE, EXDEV
+ },
+ {
+ ERROR_NO_MORE_FILES, ENOENT
+ },
+ {
+ ERROR_LOCK_VIOLATION, EACCES
+ },
+ {
+ ERROR_SHARING_VIOLATION, EACCES
+ },
+ {
+ ERROR_BAD_NETPATH, ENOENT
+ },
+ {
+ ERROR_NETWORK_ACCESS_DENIED, EACCES
+ },
+ {
+ ERROR_BAD_NET_NAME, ENOENT
+ },
+ {
+ ERROR_FILE_EXISTS, EEXIST
+ },
+ {
+ ERROR_CANNOT_MAKE, EACCES
+ },
+ {
+ ERROR_FAIL_I24, EACCES
+ },
+ {
+ ERROR_INVALID_PARAMETER, EINVAL
+ },
+ {
+ ERROR_NO_PROC_SLOTS, EAGAIN
+ },
+ {
+ ERROR_DRIVE_LOCKED, EACCES
+ },
+ {
+ ERROR_BROKEN_PIPE, EPIPE
+ },
+ {
+ ERROR_DISK_FULL, ENOSPC
+ },
+ {
+ ERROR_INVALID_TARGET_HANDLE, EBADF
+ },
+ {
+ ERROR_INVALID_HANDLE, EINVAL
+ },
+ {
+ ERROR_WAIT_NO_CHILDREN, ECHILD
+ },
+ {
+ ERROR_CHILD_NOT_COMPLETE, ECHILD
+ },
+ {
+ ERROR_DIRECT_ACCESS_HANDLE, EBADF
+ },
+ {
+ ERROR_NEGATIVE_SEEK, EINVAL
+ },
+ {
+ ERROR_SEEK_ON_DEVICE, EACCES
+ },
+ {
+ ERROR_DIR_NOT_EMPTY, ENOTEMPTY
+ },
+ {
+ ERROR_NOT_LOCKED, EACCES
+ },
+ {
+ ERROR_BAD_PATHNAME, ENOENT
+ },
+ {
+ ERROR_MAX_THRDS_REACHED, EAGAIN
+ },
+ {
+ ERROR_LOCK_FAILED, EACCES
+ },
+ {
+ ERROR_ALREADY_EXISTS, EEXIST
+ },
+ {
+ ERROR_FILENAME_EXCED_RANGE, ENOENT
+ },
+ {
+ ERROR_NESTING_NOT_ALLOWED, EAGAIN
+ },
+ {
+ ERROR_NOT_ENOUGH_QUOTA, ENOMEM
+ },
+ {
+ ERROR_DELETE_PENDING, ENOENT
+ }
+};
+
+void
+_dosmaperr(unsigned long e)
+{
+ int i;
+
+ if (e == 0)
+ {
+ errno = 0;
+ return;
+ }
+
+ for (i = 0; i < lengthof(doserrors); i++)
+ {
+ if (doserrors[i].winerr == e)
+ {
+ int doserr = doserrors[i].doserr;
+
+#ifndef FRONTEND
+ ereport(DEBUG5,
+ (errmsg_internal("mapped win32 error code %lu to %d",
+ e, doserr)));
+#elif defined(FRONTEND_DEBUG)
+ fprintf(stderr, "mapped win32 error code %lu to %d", e, doserr);
+#endif
+ errno = doserr;
+ return;
+ }
+ }
+
+#ifndef FRONTEND
+ ereport(LOG,
+ (errmsg_internal("unrecognized win32 error code: %lu",
+ e)));
+#else
+ fprintf(stderr, "unrecognized win32 error code: %lu", e);
+#endif
+
+ errno = EINVAL;
+}
diff --git a/contrib/libs/postgresql/src/port/win32security.c b/contrib/libs/postgresql/src/port/win32security.c
new file mode 100644
index 0000000000..4a673fde19
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/win32security.c
@@ -0,0 +1,178 @@
+/*-------------------------------------------------------------------------
+ *
+ * win32security.c
+ * Microsoft Windows Win32 Security Support Functions
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/port/win32security.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+
+/*
+ * Utility wrapper for frontend and backend when reporting an error
+ * message.
+ */
+static
+pg_attribute_printf(1, 2)
+void
+log_error(const char *fmt,...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+#ifndef FRONTEND
+ write_stderr(fmt, ap);
+#else
+ fprintf(stderr, fmt, ap);
+#endif
+ va_end(ap);
+}
+
+/*
+ * Returns nonzero if the current user has administrative privileges,
+ * or zero if not.
+ *
+ * Note: this cannot use ereport() because it's called too early during
+ * startup.
+ */
+int
+pgwin32_is_admin(void)
+{
+ PSID AdministratorsSid;
+ PSID PowerUsersSid;
+ SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
+ BOOL IsAdministrators;
+ BOOL IsPowerUsers;
+
+ if (!AllocateAndInitializeSid(&NtAuthority, 2,
+ SECURITY_BUILTIN_DOMAIN_RID,
+ DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0,
+ 0, &AdministratorsSid))
+ {
+ log_error(_("could not get SID for Administrators group: error code %lu\n"),
+ GetLastError());
+ exit(1);
+ }
+
+ if (!AllocateAndInitializeSid(&NtAuthority, 2,
+ SECURITY_BUILTIN_DOMAIN_RID,
+ DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0,
+ 0, &PowerUsersSid))
+ {
+ log_error(_("could not get SID for PowerUsers group: error code %lu\n"),
+ GetLastError());
+ exit(1);
+ }
+
+ if (!CheckTokenMembership(NULL, AdministratorsSid, &IsAdministrators) ||
+ !CheckTokenMembership(NULL, PowerUsersSid, &IsPowerUsers))
+ {
+ log_error(_("could not check access token membership: error code %lu\n"),
+ GetLastError());
+ exit(1);
+ }
+
+ FreeSid(AdministratorsSid);
+ FreeSid(PowerUsersSid);
+
+ if (IsAdministrators || IsPowerUsers)
+ return 1;
+ else
+ return 0;
+}
+
+/*
+ * We consider ourselves running as a service if one of the following is
+ * true:
+ *
+ * 1) We are running as LocalSystem (only used by services)
+ * 2) Our token contains SECURITY_SERVICE_RID (automatically added to the
+ * process token by the SCM when starting a service)
+ *
+ * The check for LocalSystem is needed, because surprisingly, if a service
+ * is running as LocalSystem, it does not have SECURITY_SERVICE_RID in its
+ * process token.
+ *
+ * Return values:
+ * 0 = Not service
+ * 1 = Service
+ * -1 = Error
+ *
+ * Note: we can't report errors via either ereport (we're called too early
+ * in the backend) or write_stderr (because that calls this). We are
+ * therefore reduced to writing directly on stderr, which sucks, but we
+ * have few alternatives.
+ */
+int
+pgwin32_is_service(void)
+{
+ static int _is_service = -1;
+ BOOL IsMember;
+ PSID ServiceSid;
+ PSID LocalSystemSid;
+ SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
+
+ /* Only check the first time */
+ if (_is_service != -1)
+ return _is_service;
+
+ /* First check for LocalSystem */
+ if (!AllocateAndInitializeSid(&NtAuthority, 1,
+ SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0,
+ &LocalSystemSid))
+ {
+ fprintf(stderr, "could not get SID for local system account\n");
+ return -1;
+ }
+
+ if (!CheckTokenMembership(NULL, LocalSystemSid, &IsMember))
+ {
+ fprintf(stderr, "could not check access token membership: error code %lu\n",
+ GetLastError());
+ FreeSid(LocalSystemSid);
+ return -1;
+ }
+ FreeSid(LocalSystemSid);
+
+ if (IsMember)
+ {
+ _is_service = 1;
+ return _is_service;
+ }
+
+ /* Check for service group membership */
+ if (!AllocateAndInitializeSid(&NtAuthority, 1,
+ SECURITY_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0,
+ &ServiceSid))
+ {
+ fprintf(stderr, "could not get SID for service group: error code %lu\n",
+ GetLastError());
+ return -1;
+ }
+
+ if (!CheckTokenMembership(NULL, ServiceSid, &IsMember))
+ {
+ fprintf(stderr, "could not check access token membership: error code %lu\n",
+ GetLastError());
+ FreeSid(ServiceSid);
+ return -1;
+ }
+ FreeSid(ServiceSid);
+
+ if (IsMember)
+ _is_service = 1;
+ else
+ _is_service = 0;
+
+ return _is_service;
+}
diff --git a/contrib/libs/postgresql/src/port/win32setlocale.c b/contrib/libs/postgresql/src/port/win32setlocale.c
new file mode 100644
index 0000000000..4edae05bb7
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/win32setlocale.c
@@ -0,0 +1,193 @@
+/*-------------------------------------------------------------------------
+ *
+ * win32setlocale.c
+ * Wrapper to work around bugs in Windows setlocale() implementation
+ *
+ * Copyright (c) 2011-2021, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/port/win32setlocale.c
+ *
+ *
+ * The setlocale() function in Windows is broken in two ways. First, it
+ * has a problem with locale names that have a dot in the country name. For
+ * example:
+ *
+ * "Chinese (Traditional)_Hong Kong S.A.R..950"
+ *
+ * For some reason, setlocale() doesn't accept that as argument, even though
+ * setlocale(LC_ALL, NULL) returns exactly that. Fortunately, it accepts
+ * various alternative names for such countries, so to work around the broken
+ * setlocale() function, we map the troublemaking locale names to accepted
+ * aliases, before calling setlocale().
+ *
+ * The second problem is that the locale name for "Norwegian (Bokm&aring;l)"
+ * contains a non-ASCII character. That's problematic, because it's not clear
+ * what encoding the locale name itself is supposed to be in, when you
+ * haven't yet set a locale. Also, it causes problems when the cluster
+ * contains databases with different encodings, as the locale name is stored
+ * in the pg_database system catalog. To work around that, when setlocale()
+ * returns that locale name, map it to a pure-ASCII alias for the same
+ * locale.
+ *-------------------------------------------------------------------------
+ */
+
+#include "c.h"
+
+#undef setlocale
+
+struct locale_map
+{
+ /*
+ * String in locale name to replace. Can be a single string (end is NULL),
+ * or separate start and end strings. If two strings are given, the locale
+ * name must contain both of them, and everything between them is
+ * replaced. This is used for a poor-man's regexp search, allowing
+ * replacement of "start.*end".
+ */
+ const char *locale_name_start;
+ const char *locale_name_end;
+
+ const char *replacement; /* string to replace the match with */
+};
+
+/*
+ * Mappings applied before calling setlocale(), to the argument.
+ */
+static const struct locale_map locale_map_argument[] = {
+ /*
+ * "HKG" is listed here:
+ * http://msdn.microsoft.com/en-us/library/cdax410z%28v=vs.71%29.aspx
+ * (Country/Region Strings).
+ *
+ * "ARE" is the ISO-3166 three-letter code for U.A.E. It is not on the
+ * above list, but seems to work anyway.
+ */
+ {"Hong Kong S.A.R.", NULL, "HKG"},
+ {"U.A.E.", NULL, "ARE"},
+
+ /*
+ * The ISO-3166 country code for Macau S.A.R. is MAC, but Windows doesn't
+ * seem to recognize that. And Macau isn't listed in the table of accepted
+ * abbreviations linked above. Fortunately, "ZHM" seems to be accepted as
+ * an alias for "Chinese (Traditional)_Macau S.A.R..950". I'm not sure
+ * where "ZHM" comes from, must be some legacy naming scheme. But hey, it
+ * works.
+ *
+ * Note that unlike HKG and ARE, ZHM is an alias for the *whole* locale
+ * name, not just the country part.
+ *
+ * Some versions of Windows spell it "Macau", others "Macao".
+ */
+ {"Chinese (Traditional)_Macau S.A.R..950", NULL, "ZHM"},
+ {"Chinese_Macau S.A.R..950", NULL, "ZHM"},
+ {"Chinese (Traditional)_Macao S.A.R..950", NULL, "ZHM"},
+ {"Chinese_Macao S.A.R..950", NULL, "ZHM"},
+ {NULL, NULL, NULL}
+};
+
+/*
+ * Mappings applied after calling setlocale(), to its return value.
+ */
+static const struct locale_map locale_map_result[] = {
+ /*
+ * "Norwegian (Bokm&aring;l)" locale name contains the a-ring character.
+ * Map it to a pure-ASCII alias.
+ *
+ * It's not clear what encoding setlocale() uses when it returns the
+ * locale name, so to play it safe, we search for "Norwegian (Bok*l)".
+ *
+ * Just to make life even more complicated, some versions of Windows spell
+ * the locale name without parentheses. Translate that too.
+ */
+ {"Norwegian (Bokm", "l)_Norway", "Norwegian_Norway"},
+ {"Norwegian Bokm", "l_Norway", "Norwegian_Norway"},
+ {NULL, NULL, NULL}
+};
+
+#define MAX_LOCALE_NAME_LEN 100
+
+static const char *
+map_locale(const struct locale_map *map, const char *locale)
+{
+ static char aliasbuf[MAX_LOCALE_NAME_LEN];
+ int i;
+
+ /* Check if the locale name matches any of the problematic ones. */
+ for (i = 0; map[i].locale_name_start != NULL; i++)
+ {
+ const char *needle_start = map[i].locale_name_start;
+ const char *needle_end = map[i].locale_name_end;
+ const char *replacement = map[i].replacement;
+ char *match;
+ char *match_start = NULL;
+ char *match_end = NULL;
+
+ match = strstr(locale, needle_start);
+ if (match)
+ {
+ /*
+ * Found a match for the first part. If this was a two-part
+ * replacement, find the second part.
+ */
+ match_start = match;
+ if (needle_end)
+ {
+ match = strstr(match_start + strlen(needle_start), needle_end);
+ if (match)
+ match_end = match + strlen(needle_end);
+ else
+ match_start = NULL;
+ }
+ else
+ match_end = match_start + strlen(needle_start);
+ }
+
+ if (match_start)
+ {
+ /* Found a match. Replace the matched string. */
+ int matchpos = match_start - locale;
+ int replacementlen = strlen(replacement);
+ char *rest = match_end;
+ int restlen = strlen(rest);
+
+ /* check that the result fits in the static buffer */
+ if (matchpos + replacementlen + restlen + 1 > MAX_LOCALE_NAME_LEN)
+ return NULL;
+
+ memcpy(&aliasbuf[0], &locale[0], matchpos);
+ memcpy(&aliasbuf[matchpos], replacement, replacementlen);
+ /* includes null terminator */
+ memcpy(&aliasbuf[matchpos + replacementlen], rest, restlen + 1);
+
+ return aliasbuf;
+ }
+ }
+
+ /* no match, just return the original string */
+ return locale;
+}
+
+char *
+pgwin32_setlocale(int category, const char *locale)
+{
+ const char *argument;
+ char *result;
+
+ if (locale == NULL)
+ argument = NULL;
+ else
+ argument = map_locale(locale_map_argument, locale);
+
+ /* Call the real setlocale() function */
+ result = setlocale(category, argument);
+
+ /*
+ * setlocale() is specified to return a "char *" that the caller is
+ * forbidden to modify, so casting away the "const" is innocuous.
+ */
+ if (result)
+ result = unconstify(char *, map_locale(locale_map_result, result));
+
+ return result;
+}
diff --git a/contrib/libs/postgresql/src/port/win32stat.c b/contrib/libs/postgresql/src/port/win32stat.c
new file mode 100644
index 0000000000..426e01f0ef
--- /dev/null
+++ b/contrib/libs/postgresql/src/port/win32stat.c
@@ -0,0 +1,327 @@
+/*-------------------------------------------------------------------------
+ *
+ * win32stat.c
+ * Replacements for <sys/stat.h> functions using GetFileInformationByHandle
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/port/win32stat.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifdef WIN32
+
+#include "c.h"
+#include <windows.h>
+
+/*
+ * In order to support MinGW and MSVC2013 we use NtQueryInformationFile as an
+ * alternative for GetFileInformationByHandleEx. It is loaded from the ntdll
+ * library.
+ */
+#if _WIN32_WINNT < 0x0600
+#include <winternl.h>
+
+#if !defined(__MINGW32__) && !defined(__MINGW64__)
+/* MinGW includes this in <winternl.h>, but it is missing in MSVC */
+typedef struct _FILE_STANDARD_INFORMATION
+{
+ LARGE_INTEGER AllocationSize;
+ LARGE_INTEGER EndOfFile;
+ ULONG NumberOfLinks;
+ BOOLEAN DeletePending;
+ BOOLEAN Directory;
+} FILE_STANDARD_INFORMATION;
+#define FileStandardInformation 5
+#endif /* !defined(__MINGW32__) &&
+ * !defined(__MINGW64__) */
+
+typedef NTSTATUS (NTAPI * PFN_NTQUERYINFORMATIONFILE)
+ (IN HANDLE FileHandle,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ OUT PVOID FileInformation,
+ IN ULONG Length,
+ IN FILE_INFORMATION_CLASS FileInformationClass);
+
+static PFN_NTQUERYINFORMATIONFILE _NtQueryInformationFile = NULL;
+
+static HMODULE ntdll = NULL;
+
+/*
+ * Load DLL file just once regardless of how many functions we load/call in it.
+ */
+static void
+LoadNtdll(void)
+{
+ if (ntdll != NULL)
+ return;
+ ntdll = LoadLibraryEx("ntdll.dll", NULL, 0);
+}
+
+#endif /* _WIN32_WINNT < 0x0600 */
+
+
+/*
+ * Convert a FILETIME struct into a 64 bit time_t.
+ */
+static __time64_t
+filetime_to_time(const FILETIME *ft)
+{
+ ULARGE_INTEGER unified_ft = {0};
+ static const uint64 EpochShift = UINT64CONST(116444736000000000);
+
+ unified_ft.LowPart = ft->dwLowDateTime;
+ unified_ft.HighPart = ft->dwHighDateTime;
+
+ if (unified_ft.QuadPart < EpochShift)
+ return -1;
+
+ unified_ft.QuadPart -= EpochShift;
+ unified_ft.QuadPart /= 10 * 1000 * 1000;
+
+ return unified_ft.QuadPart;
+}
+
+/*
+ * Convert WIN32 file attributes to a Unix-style mode.
+ *
+ * Only owner permissions are set.
+ */
+static unsigned short
+fileattr_to_unixmode(int attr)
+{
+ unsigned short uxmode = 0;
+
+ uxmode |= (unsigned short) ((attr & FILE_ATTRIBUTE_DIRECTORY) ?
+ (_S_IFDIR) : (_S_IFREG));
+
+ uxmode |= (unsigned short) ((attr & FILE_ATTRIBUTE_READONLY) ?
+ (_S_IREAD) : (_S_IREAD | _S_IWRITE));
+
+ /* there is no need to simulate _S_IEXEC using CMD's PATHEXT extensions */
+ uxmode |= _S_IEXEC;
+
+ return uxmode;
+}
+
+/*
+ * Convert WIN32 file information (from a HANDLE) to a struct stat.
+ */
+static int
+fileinfo_to_stat(HANDLE hFile, struct stat *buf)
+{
+ BY_HANDLE_FILE_INFORMATION fiData;
+
+ memset(buf, 0, sizeof(*buf));
+
+ /*
+ * GetFileInformationByHandle minimum supported version: Windows XP and
+ * Windows Server 2003, so it exists everywhere we care about.
+ */
+ if (!GetFileInformationByHandle(hFile, &fiData))
+ {
+ _dosmaperr(GetLastError());
+ return -1;
+ }
+
+ if (fiData.ftLastWriteTime.dwLowDateTime ||
+ fiData.ftLastWriteTime.dwHighDateTime)
+ buf->st_mtime = filetime_to_time(&fiData.ftLastWriteTime);
+
+ if (fiData.ftLastAccessTime.dwLowDateTime ||
+ fiData.ftLastAccessTime.dwHighDateTime)
+ buf->st_atime = filetime_to_time(&fiData.ftLastAccessTime);
+ else
+ buf->st_atime = buf->st_mtime;
+
+ if (fiData.ftCreationTime.dwLowDateTime ||
+ fiData.ftCreationTime.dwHighDateTime)
+ buf->st_ctime = filetime_to_time(&fiData.ftCreationTime);
+ else
+ buf->st_ctime = buf->st_mtime;
+
+ buf->st_mode = fileattr_to_unixmode(fiData.dwFileAttributes);
+ buf->st_nlink = fiData.nNumberOfLinks;
+
+ buf->st_size = ((((uint64) fiData.nFileSizeHigh) << 32) |
+ fiData.nFileSizeLow);
+
+ return 0;
+}
+
+/*
+ * Windows implementation of stat().
+ *
+ * This currently also implements lstat(), though perhaps that should change.
+ */
+int
+_pgstat64(const char *name, struct stat *buf)
+{
+ /*
+ * We must use a handle so lstat() returns the information of the target
+ * file. To have a reliable test for ERROR_DELETE_PENDING, we use
+ * NtQueryInformationFile from Windows 2000 or
+ * GetFileInformationByHandleEx from Server 2008 / Vista.
+ */
+ SECURITY_ATTRIBUTES sa;
+ HANDLE hFile;
+ int ret;
+#if _WIN32_WINNT < 0x0600
+ IO_STATUS_BLOCK ioStatus;
+ FILE_STANDARD_INFORMATION standardInfo;
+#else
+ FILE_STANDARD_INFO standardInfo;
+#endif
+
+ if (name == NULL || buf == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* fast not-exists check */
+ if (GetFileAttributes(name) == INVALID_FILE_ATTRIBUTES)
+ {
+ _dosmaperr(GetLastError());
+ return -1;
+ }
+
+ /* get a file handle as lightweight as we can */
+ sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ sa.bInheritHandle = TRUE;
+ sa.lpSecurityDescriptor = NULL;
+ hFile = CreateFile(name,
+ GENERIC_READ,
+ (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),
+ &sa,
+ OPEN_EXISTING,
+ (FILE_FLAG_NO_BUFFERING | FILE_FLAG_BACKUP_SEMANTICS |
+ FILE_FLAG_OVERLAPPED),
+ NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ DWORD err = GetLastError();
+
+ CloseHandle(hFile);
+ _dosmaperr(err);
+ return -1;
+ }
+
+ memset(&standardInfo, 0, sizeof(standardInfo));
+
+#if _WIN32_WINNT < 0x0600
+ if (_NtQueryInformationFile == NULL)
+ {
+ /* First time through: load ntdll.dll and find NtQueryInformationFile */
+ LoadNtdll();
+ if (ntdll == NULL)
+ {
+ DWORD err = GetLastError();
+
+ CloseHandle(hFile);
+ _dosmaperr(err);
+ return -1;
+ }
+
+ _NtQueryInformationFile = (PFN_NTQUERYINFORMATIONFILE) (pg_funcptr_t)
+ GetProcAddress(ntdll, "NtQueryInformationFile");
+ if (_NtQueryInformationFile == NULL)
+ {
+ DWORD err = GetLastError();
+
+ CloseHandle(hFile);
+ _dosmaperr(err);
+ return -1;
+ }
+ }
+
+ if (!NT_SUCCESS(_NtQueryInformationFile(hFile, &ioStatus, &standardInfo,
+ sizeof(standardInfo),
+ FileStandardInformation)))
+ {
+ DWORD err = GetLastError();
+
+ CloseHandle(hFile);
+ _dosmaperr(err);
+ return -1;
+ }
+#else
+ if (!GetFileInformationByHandleEx(hFile, FileStandardInfo, &standardInfo,
+ sizeof(standardInfo)))
+ {
+ DWORD err = GetLastError();
+
+ CloseHandle(hFile);
+ _dosmaperr(err);
+ return -1;
+ }
+#endif /* _WIN32_WINNT < 0x0600 */
+
+ if (standardInfo.DeletePending)
+ {
+ /*
+ * File has been deleted, but is not gone from the filesystem yet.
+ * This can happen when some process with FILE_SHARE_DELETE has it
+ * open, and it will be fully removed once that handle is closed.
+ * Meanwhile, we can't open it, so indicate that the file just doesn't
+ * exist.
+ */
+ CloseHandle(hFile);
+ errno = ENOENT;
+ return -1;
+ }
+
+ /* At last we can invoke fileinfo_to_stat */
+ ret = fileinfo_to_stat(hFile, buf);
+
+ CloseHandle(hFile);
+ return ret;
+}
+
+/*
+ * Windows implementation of fstat().
+ */
+int
+_pgfstat64(int fileno, struct stat *buf)
+{
+ HANDLE hFile = (HANDLE) _get_osfhandle(fileno);
+ BY_HANDLE_FILE_INFORMATION fiData;
+
+ if (hFile == INVALID_HANDLE_VALUE || buf == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /*
+ * Check if the fileno is a data stream. If so, unless it has been
+ * redirected to a file, getting information through its HANDLE will fail,
+ * so emulate its stat information in the most appropriate way and return
+ * it instead.
+ */
+ if ((fileno == _fileno(stdin) ||
+ fileno == _fileno(stdout) ||
+ fileno == _fileno(stderr)) &&
+ !GetFileInformationByHandle(hFile, &fiData))
+ {
+ memset(buf, 0, sizeof(*buf));
+ buf->st_mode = _S_IFCHR;
+ buf->st_dev = fileno;
+ buf->st_rdev = fileno;
+ buf->st_nlink = 1;
+ return 0;
+ }
+
+ /*
+ * Since we already have a file handle there is no need to check for
+ * ERROR_DELETE_PENDING.
+ */
+
+ return fileinfo_to_stat(hFile, buf);
+}
+
+#endif /* WIN32 */
diff --git a/contrib/libs/pthreads_win32/config.h b/contrib/libs/pthreads_win32/config.h
new file mode 100644
index 0000000000..a696333993
--- /dev/null
+++ b/contrib/libs/pthreads_win32/config.h
@@ -0,0 +1,157 @@
+/* config.h */
+
+#ifndef PTW32_CONFIG_H
+#define PTW32_CONFIG_H
+
+/*********************************************************************
+ * Defaults: see target specific redefinitions below.
+ *********************************************************************/
+
+/* We're building the pthreads-win32 library */
+#define PTW32_BUILD
+
+/* Do we know about the C type sigset_t? */
+#undef HAVE_SIGSET_T
+
+/* Define if you have the <signal.h> header file. */
+#undef HAVE_SIGNAL_H
+
+/* Define if you have the Borland TASM32 or compatible assembler. */
+#undef HAVE_TASM32
+
+/* Define if you don't have Win32 DuplicateHandle. (eg. WinCE) */
+#undef NEED_DUPLICATEHANDLE
+
+/* Define if you don't have Win32 _beginthreadex. (eg. WinCE) */
+#undef NEED_CREATETHREAD
+
+/* Define if you don't have Win32 errno. (eg. WinCE) */
+#undef NEED_ERRNO
+
+/* Define if you don't have Win32 calloc. (eg. WinCE) */
+#undef NEED_CALLOC
+
+/* Define if you don't have Win32 ftime. (eg. WinCE) */
+#undef NEED_FTIME
+
+/* Define if you don't have Win32 semaphores. (eg. WinCE 2.1 or earlier) */
+#undef NEED_SEM
+
+/* Define if you need to convert string parameters to unicode. (eg. WinCE) */
+#undef NEED_UNICODE_CONSTS
+
+/* Define if your C (not C++) compiler supports "inline" functions. */
+#undef HAVE_C_INLINE
+
+/* Do we know about type mode_t? */
+#undef HAVE_MODE_T
+
+/*
+ * Define if GCC has atomic builtins, i.e. __sync_* intrinsics
+ * __sync_lock_* is implemented in mingw32 gcc 4.5.2 at least
+ * so this define does not turn those on or off. If you get an
+ * error from __sync_lock* then consider upgrading your gcc.
+ */
+#undef HAVE_GCC_ATOMIC_BUILTINS
+
+/* Define if you have the timespec struct */
+#undef HAVE_STRUCT_TIMESPEC
+
+#if _MSC_VER >= 1900
+#define HAVE_STRUCT_TIMESPEC
+#endif
+
+/* Define if you don't have the GetProcessAffinityMask() */
+#undef NEED_PROCESS_AFFINITY_MASK
+
+/* Define if your version of Windows TLSGetValue() clears WSALastError
+ * and calling SetLastError() isn't enough restore it. You'll also need to
+ * link against wsock32.lib (or libwsock32.a for MinGW).
+ */
+#undef RETAIN_WSALASTERROR
+
+/*
+# ----------------------------------------------------------------------
+# The library can be built with some alternative behaviour to better
+# facilitate development of applications on Win32 that will be ported
+# to other POSIX systems.
+#
+# Nothing described here will make the library non-compliant and strictly
+# compliant applications will not be affected in any way, but
+# applications that make assumptions that POSIX does not guarantee are
+# not strictly compliant and may fail or misbehave with some settings.
+#
+# PTW32_THREAD_ID_REUSE_INCREMENT
+# Purpose:
+# POSIX says that applications should assume that thread IDs can be
+# recycled. However, Solaris (and some other systems) use a [very large]
+# sequence number as the thread ID, which provides virtual uniqueness.
+# This provides a very high but finite level of safety for applications
+# that are not meticulous in tracking thread lifecycles e.g. applications
+# that call functions which target detached threads without some form of
+# thread exit synchronisation.
+#
+# Usage:
+# Set to any value in the range: 0 <= value < 2^wordsize.
+# Set to 0 to emulate reusable thread ID behaviour like Linux or *BSD.
+# Set to 1 for unique thread IDs like Solaris (this is the default).
+# Set to some factor of 2^wordsize to emulate smaller word size types
+# (i.e. will wrap sooner). This might be useful to emulate some embedded
+# systems.
+#
+# define PTW32_THREAD_ID_REUSE_INCREMENT 0
+#
+# ----------------------------------------------------------------------
+ */
+#undef PTW32_THREAD_ID_REUSE_INCREMENT
+
+
+/*********************************************************************
+ * Target specific groups
+ *
+ * If you find that these are incorrect or incomplete please report it
+ * to the pthreads-win32 maintainer. Thanks.
+ *********************************************************************/
+#if defined(WINCE)
+#define NEED_DUPLICATEHANDLE
+#define NEED_CREATETHREAD
+#define NEED_ERRNO
+#define NEED_CALLOC
+#define NEED_FTIME
+/* #define NEED_SEM */
+#define NEED_UNICODE_CONSTS
+#define NEED_PROCESS_AFFINITY_MASK
+/* This may not be needed */
+#define RETAIN_WSALASTERROR
+#endif
+
+#if defined(_UWIN)
+#define HAVE_MODE_T
+#define HAVE_STRUCT_TIMESPEC
+#endif
+
+#if defined(__GNUC__)
+#define HAVE_C_INLINE
+#endif
+
+#if defined(__MINGW64__)
+#define HAVE_MODE_T
+#define HAVE_STRUCT_TIMESPEC
+#elif defined(__MINGW32__)
+#define HAVE_MODE_T
+#endif
+
+#if defined(__BORLANDC__)
+#endif
+
+#if defined(__WATCOMC__)
+#endif
+
+#if defined(__DMC__)
+#define HAVE_SIGNAL_H
+#define HAVE_C_INLINE
+#endif
+
+
+
+#endif
diff --git a/contrib/libs/pthreads_win32/include/pthread.h b/contrib/libs/pthreads_win32/include/pthread.h
new file mode 100644
index 0000000000..e0d0d52175
--- /dev/null
+++ b/contrib/libs/pthreads_win32/include/pthread.h
@@ -0,0 +1,10 @@
+#pragma once
+
+#define PTW32_STATIC_LIB
+#define PTW32_YANDEX
+
+#if _MSC_VER >= 1900
+#define HAVE_STRUCT_TIMESPEC
+#endif
+
+#include "../pthread.h"
diff --git a/contrib/libs/pthreads_win32/include/sched.h b/contrib/libs/pthreads_win32/include/sched.h
new file mode 100644
index 0000000000..c331bae6f5
--- /dev/null
+++ b/contrib/libs/pthreads_win32/include/sched.h
@@ -0,0 +1,10 @@
+#pragma once
+
+#define PTW32_STATIC_LIB
+#define PTW32_YANDEX
+
+#if _MSC_VER >= 1900
+#define HAVE_STRUCT_TIMESPEC
+#endif
+
+#include "../sched.h"
diff --git a/contrib/libs/pthreads_win32/need_errno.h b/contrib/libs/pthreads_win32/need_errno.h
new file mode 100644
index 0000000000..abf1c95574
--- /dev/null
+++ b/contrib/libs/pthreads_win32/need_errno.h
@@ -0,0 +1,145 @@
+/***
+* errno.h - system wide error numbers (set by system calls)
+*
+* Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
+*
+* Purpose:
+* This file defines the system-wide error numbers (set by
+* system calls). Conforms to the XENIX standard. Extended
+* for compatibility with Uniforum standard.
+* [System V]
+*
+* [Public]
+*
+****/
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#if !defined(_INC_ERRNO)
+#define _INC_ERRNO
+
+#if !defined(_WIN32)
+#error ERROR: Only Win32 targets supported!
+#endif
+
+#include <winsock.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+
+/* Define _CRTIMP */
+
+#ifndef _CRTIMP
+#if defined(_DLL)
+#define _CRTIMP __declspec(dllimport)
+#else /* ndef _DLL */
+#define _CRTIMP
+#endif /* _DLL */
+#endif /* _CRTIMP */
+
+
+/* Define __cdecl for non-Microsoft compilers */
+
+#if ( !defined(_MSC_VER) && !defined(__cdecl) )
+#define __cdecl
+#endif
+
+/* Define _CRTAPI1 (for compatibility with the NT SDK) */
+
+#if !defined(_CRTAPI1)
+#if _MSC_VER >= 800 && _M_IX86 >= 300
+#define _CRTAPI1 __cdecl
+#else
+#define _CRTAPI1
+#endif
+#endif
+
+#if !defined(PTW32_STATIC_LIB)
+# if defined(PTW32_BUILD)
+# define PTW32_DLLPORT __declspec (dllexport)
+# else
+# define PTW32_DLLPORT __declspec (dllimport)
+# endif
+#else
+# define PTW32_DLLPORT
+#endif
+
+/* declare reference to errno */
+
+#if (defined(_MT) || defined(_MD) || defined(_DLL)) && !defined(_MAC)
+PTW32_DLLPORT int * __cdecl _errno(void);
+#define errno (*_errno())
+#else /* ndef _MT && ndef _MD && ndef _DLL */
+_CRTIMP extern int errno;
+#endif /* _MT || _MD || _DLL */
+
+/* Error Codes */
+
+#define EPERM 1
+#define ENOENT 2
+#define ESRCH 3
+#define EINTR 4
+#define EIO 5
+#define ENXIO 6
+#define E2BIG 7
+#define ENOEXEC 8
+#define EBADF 9
+#define ECHILD 10
+#define EAGAIN 11
+#define ENOMEM 12
+#define EACCES 13
+#define EFAULT 14
+#define EBUSY 16
+#define EEXIST 17
+#define EXDEV 18
+#define ENODEV 19
+#define ENOTDIR 20
+#define EISDIR 21
+#define EINVAL 22
+#define ENFILE 23
+#define EMFILE 24
+#define ENOTTY 25
+#define EFBIG 27
+#define ENOSPC 28
+#define ESPIPE 29
+#define EROFS 30
+#define EMLINK 31
+#define EPIPE 32
+#define EDOM 33
+#define ERANGE 34
+#define EDEADLK 36
+
+/* defined differently in winsock.h on WinCE */
+#if !defined(ENAMETOOLONG)
+#define ENAMETOOLONG 38
+#endif
+
+#define ENOLCK 39
+#define ENOSYS 40
+
+/* defined differently in winsock.h on WinCE */
+#if !defined(ENOTEMPTY)
+#define ENOTEMPTY 41
+#endif
+
+#define EILSEQ 42
+
+/* POSIX 2008 - robust mutexes */
+#define EOWNERDEAD 43
+#define ENOTRECOVERABLE 44
+
+/*
+ * Support EDEADLOCK for compatibiity with older MS-C versions.
+ */
+#define EDEADLOCK EDEADLK
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* _INC_ERRNO */
diff --git a/contrib/libs/pthreads_win32/pthread.h b/contrib/libs/pthreads_win32/pthread.h
new file mode 100644
index 0000000000..4fe6399e16
--- /dev/null
+++ b/contrib/libs/pthreads_win32/pthread.h
@@ -0,0 +1,1416 @@
+/* This is an implementation of the threads API of POSIX 1003.1-2001.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#if !defined( PTHREAD_H )
+#define PTHREAD_H
+
+/*
+ * See the README file for an explanation of the pthreads-win32 version
+ * numbering scheme and how the DLL is named etc.
+ */
+#define PTW32_VERSION 2,9,1,0
+#define PTW32_VERSION_STRING "2, 9, 1, 0\0"
+
+/* There are three implementations of cancel cleanup.
+ * Note that pthread.h is included in both application
+ * compilation units and also internally for the library.
+ * The code here and within the library aims to work
+ * for all reasonable combinations of environments.
+ *
+ * The three implementations are:
+ *
+ * WIN32 SEH
+ * C
+ * C++
+ *
+ * Please note that exiting a push/pop block via
+ * "return", "exit", "break", or "continue" will
+ * lead to different behaviour amongst applications
+ * depending upon whether the library was built
+ * using SEH, C++, or C. For example, a library built
+ * with SEH will call the cleanup routine, while both
+ * C++ and C built versions will not.
+ */
+
+/*
+ * Define defaults for cleanup code.
+ * Note: Unless the build explicitly defines one of the following, then
+ * we default to standard C style cleanup. This style uses setjmp/longjmp
+ * in the cancelation and thread exit implementations and therefore won't
+ * do stack unwinding if linked to applications that have it (e.g.
+ * C++ apps). This is currently consistent with most/all commercial Unix
+ * POSIX threads implementations.
+ */
+#if !defined( __CLEANUP_SEH ) && !defined( __CLEANUP_CXX ) && !defined( __CLEANUP_C )
+# define __CLEANUP_C
+#endif
+
+#if defined( __CLEANUP_SEH ) && ( !defined( _MSC_VER ) && !defined(PTW32_RC_MSC))
+#error ERROR [__FILE__, line __LINE__]: SEH is not supported for this compiler.
+#endif
+
+/*
+ * Stop here if we are being included by the resource compiler.
+ */
+#if !defined(RC_INVOKED)
+
+#undef PTW32_LEVEL
+
+#if defined(_POSIX_SOURCE)
+#define PTW32_LEVEL 0
+/* Early POSIX */
+#endif
+
+#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 1
+/* Include 1b, 1c and 1d */
+#endif
+
+#if defined(INCLUDE_NP)
+#undef PTW32_LEVEL
+#define PTW32_LEVEL 2
+/* Include Non-Portable extensions */
+#endif
+
+#define PTW32_LEVEL_MAX 3
+
+#if ( defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112 ) || !defined(PTW32_LEVEL)
+#define PTW32_LEVEL PTW32_LEVEL_MAX
+/* Include everything */
+#endif
+
+#if defined(_UWIN)
+# define HAVE_STRUCT_TIMESPEC 1
+# define HAVE_SIGNAL_H 1
+# undef HAVE_PTW32_CONFIG_H
+# pragma comment(lib, "pthread")
+#endif
+
+/*
+ * -------------------------------------------------------------
+ *
+ *
+ * Module: pthread.h
+ *
+ * Purpose:
+ * Provides an implementation of PThreads based upon the
+ * standard:
+ *
+ * POSIX 1003.1-2001
+ * and
+ * The Single Unix Specification version 3
+ *
+ * (these two are equivalent)
+ *
+ * in order to enhance code portability between Windows,
+ * various commercial Unix implementations, and Linux.
+ *
+ * See the ANNOUNCE file for a full list of conforming
+ * routines and defined constants, and a list of missing
+ * routines and constants not defined in this implementation.
+ *
+ * Authors:
+ * There have been many contributors to this library.
+ * The initial implementation was contributed by
+ * John Bossom, and several others have provided major
+ * sections or revisions of parts of the implementation.
+ * Often significant effort has been contributed to
+ * find and fix important bugs and other problems to
+ * improve the reliability of the library, which sometimes
+ * is not reflected in the amount of code which changed as
+ * result.
+ * As much as possible, the contributors are acknowledged
+ * in the ChangeLog file in the source code distribution
+ * where their changes are noted in detail.
+ *
+ * Contributors are listed in the CONTRIBUTORS file.
+ *
+ * As usual, all bouquets go to the contributors, and all
+ * brickbats go to the project maintainer.
+ *
+ * Maintainer:
+ * The code base for this project is coordinated and
+ * eventually pre-tested, packaged, and made available by
+ *
+ * Ross Johnson <rpj@callisto.canberra.edu.au>
+ *
+ * QA Testers:
+ * Ultimately, the library is tested in the real world by
+ * a host of competent and demanding scientists and
+ * engineers who report bugs and/or provide solutions
+ * which are then fixed or incorporated into subsequent
+ * versions of the library. Each time a bug is fixed, a
+ * test case is written to prove the fix and ensure
+ * that later changes to the code don't reintroduce the
+ * same error. The number of test cases is slowly growing
+ * and therefore so is the code reliability.
+ *
+ * Compliance:
+ * See the file ANNOUNCE for the list of implemented
+ * and not-implemented routines and defined options.
+ * Of course, these are all defined is this file as well.
+ *
+ * Web site:
+ * The source code and other information about this library
+ * are available from
+ *
+ * http://sources.redhat.com/pthreads-win32/
+ *
+ * -------------------------------------------------------------
+ */
+
+/* Try to avoid including windows.h */
+#if (defined(__MINGW64__) || defined(__MINGW32__)) && defined(__cplusplus)
+#define PTW32_INCLUDE_WINDOWS_H
+#endif
+
+#if defined(PTW32_INCLUDE_WINDOWS_H)
+#include <windows.h>
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER < 1300 || defined(__DMC__)
+/*
+ * VC++6.0 or early compiler's header has no DWORD_PTR type.
+ */
+typedef unsigned long DWORD_PTR;
+typedef unsigned long ULONG_PTR;
+#endif
+/*
+ * -----------------
+ * autoconf switches
+ * -----------------
+ */
+
+#if defined(HAVE_PTW32_CONFIG_H)
+#include "config.h"
+#endif /* HAVE_PTW32_CONFIG_H */
+
+#if !defined(NEED_FTIME)
+#include <time.h>
+#else /* NEED_FTIME */
+/* use native WIN32 time API */
+#endif /* NEED_FTIME */
+
+#if defined(HAVE_SIGNAL_H)
+#include <signal.h>
+#endif /* HAVE_SIGNAL_H */
+
+#include <limits.h>
+
+/*
+ * Boolean values to make us independent of system includes.
+ */
+enum {
+ PTW32_FALSE = 0,
+ PTW32_TRUE = (! PTW32_FALSE)
+};
+
+/*
+ * This is a duplicate of what is in the autoconf config.h,
+ * which is only used when building the pthread-win32 libraries.
+ */
+
+#if !defined(PTW32_CONFIG_H)
+# if defined(WINCE)
+# define NEED_ERRNO
+# define NEED_SEM
+# endif
+# if defined(__MINGW64__)
+# define HAVE_STRUCT_TIMESPEC
+# define HAVE_MODE_T
+# elif defined(_UWIN) || defined(__MINGW32__)
+# define HAVE_MODE_T
+# endif
+#endif
+
+/*
+ *
+ */
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+#if defined(NEED_ERRNO)
+#include "need_errno.h"
+#else
+#include <errno.h>
+#endif
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+/*
+ * Several systems don't define some error numbers.
+ */
+#if !defined(ENOTSUP)
+# define ENOTSUP 48 /* This is the value in Solaris. */
+#endif
+
+#if !defined(ETIMEDOUT)
+# define ETIMEDOUT 10060 /* Same as WSAETIMEDOUT */
+#endif
+
+#if !defined(ENOSYS)
+# define ENOSYS 140 /* Semi-arbitrary value */
+#endif
+
+#if !defined(EDEADLK)
+# if defined(EDEADLOCK)
+# define EDEADLK EDEADLOCK
+# else
+# define EDEADLK 36 /* This is the value in MSVC. */
+# endif
+#endif
+
+/* POSIX 2008 - related to robust mutexes */
+#if !defined(EOWNERDEAD)
+# define EOWNERDEAD 43
+#endif
+#if !defined(ENOTRECOVERABLE)
+# define ENOTRECOVERABLE 44
+#endif
+
+#include <sched.h>
+
+/*
+ * To avoid including windows.h we define only those things that we
+ * actually need from it.
+ */
+#if !defined(PTW32_INCLUDE_WINDOWS_H)
+#if !defined(HANDLE)
+# define PTW32__HANDLE_DEF
+# define HANDLE void *
+#endif
+#if !defined(DWORD)
+# define PTW32__DWORD_DEF
+# define DWORD unsigned long
+#endif
+#endif
+
+#if !defined(HAVE_STRUCT_TIMESPEC)
+#define HAVE_STRUCT_TIMESPEC
+#if !defined(_TIMESPEC_DEFINED)
+#define _TIMESPEC_DEFINED
+struct timespec {
+ time_t tv_sec;
+ long tv_nsec;
+};
+#endif /* _TIMESPEC_DEFINED */
+#endif /* HAVE_STRUCT_TIMESPEC */
+
+#if !defined(SIG_BLOCK)
+#define SIG_BLOCK 0
+#endif /* SIG_BLOCK */
+
+#if !defined(SIG_UNBLOCK)
+#define SIG_UNBLOCK 1
+#endif /* SIG_UNBLOCK */
+
+#if !defined(SIG_SETMASK)
+#define SIG_SETMASK 2
+#endif /* SIG_SETMASK */
+
+#ifdef PTW32_YANDEX
+#if defined(__cplusplus)
+typedef void(*ptw32_zero_t)();
+
+struct ptw32_handle_t {
+ void * p; /* Pointer to actual object */
+ unsigned int x; /* Extra information - reuse count etc */
+
+ ptw32_handle_t() {}
+ ptw32_handle_t(ptw32_zero_t): p(0), x(0) {}
+ ptw32_handle_t(int): p(0), x(0) {}
+
+ friend bool operator==(const ptw32_handle_t& l, const ptw32_handle_t& r) {
+ return l.p == r.p && l.x == r.x;
+ }
+
+ friend bool operator!=(const ptw32_handle_t& l, const ptw32_zero_t&) {
+ return l.p != NULL;
+ }
+
+ friend bool operator<(const ptw32_handle_t& l, const ptw32_handle_t& r) {
+ return l.p < r.p || (l.p == r.p && l.x < r.x);
+ }
+
+ size_t hash() const {
+ return reinterpret_cast<size_t>(p) ^ x;
+ }
+
+};
+#else
+typedef struct {
+ void * p; /* Pointer to actual object */
+ unsigned int x; /* Extra information - reuse count etc */
+} ptw32_handle_t;
+#endif
+#endif
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif /* __cplusplus */
+
+/*
+ * -------------------------------------------------------------
+ *
+ * POSIX 1003.1-2001 Options
+ * =========================
+ *
+ * Options are normally set in <unistd.h>, which is not provided
+ * with pthreads-win32.
+ *
+ * For conformance with the Single Unix Specification (version 3), all of the
+ * options below are defined, and have a value of either -1 (not supported)
+ * or 200112L (supported).
+ *
+ * These options can neither be left undefined nor have a value of 0, because
+ * either indicates that sysconf(), which is not implemented, may be used at
+ * runtime to check the status of the option.
+ *
+ * _POSIX_THREADS (== 200112L)
+ * If == 200112L, you can use threads
+ *
+ * _POSIX_THREAD_ATTR_STACKSIZE (== 200112L)
+ * If == 200112L, you can control the size of a thread's
+ * stack
+ * pthread_attr_getstacksize
+ * pthread_attr_setstacksize
+ *
+ * _POSIX_THREAD_ATTR_STACKADDR (== -1)
+ * If == 200112L, you can allocate and control a thread's
+ * stack. If not supported, the following functions
+ * will return ENOSYS, indicating they are not
+ * supported:
+ * pthread_attr_getstackaddr
+ * pthread_attr_setstackaddr
+ *
+ * _POSIX_THREAD_PRIORITY_SCHEDULING (== -1)
+ * If == 200112L, you can use realtime scheduling.
+ * This option indicates that the behaviour of some
+ * implemented functions conforms to the additional TPS
+ * requirements in the standard. E.g. rwlocks favour
+ * writers over readers when threads have equal priority.
+ *
+ * _POSIX_THREAD_PRIO_INHERIT (== -1)
+ * If == 200112L, you can create priority inheritance
+ * mutexes.
+ * pthread_mutexattr_getprotocol +
+ * pthread_mutexattr_setprotocol +
+ *
+ * _POSIX_THREAD_PRIO_PROTECT (== -1)
+ * If == 200112L, you can create priority ceiling mutexes
+ * Indicates the availability of:
+ * pthread_mutex_getprioceiling
+ * pthread_mutex_setprioceiling
+ * pthread_mutexattr_getprioceiling
+ * pthread_mutexattr_getprotocol +
+ * pthread_mutexattr_setprioceiling
+ * pthread_mutexattr_setprotocol +
+ *
+ * _POSIX_THREAD_PROCESS_SHARED (== -1)
+ * If set, you can create mutexes and condition
+ * variables that can be shared with another
+ * process.If set, indicates the availability
+ * of:
+ * pthread_mutexattr_getpshared
+ * pthread_mutexattr_setpshared
+ * pthread_condattr_getpshared
+ * pthread_condattr_setpshared
+ *
+ * _POSIX_THREAD_SAFE_FUNCTIONS (== 200112L)
+ * If == 200112L you can use the special *_r library
+ * functions that provide thread-safe behaviour
+ *
+ * _POSIX_READER_WRITER_LOCKS (== 200112L)
+ * If == 200112L, you can use read/write locks
+ *
+ * _POSIX_SPIN_LOCKS (== 200112L)
+ * If == 200112L, you can use spin locks
+ *
+ * _POSIX_BARRIERS (== 200112L)
+ * If == 200112L, you can use barriers
+ *
+ * + These functions provide both 'inherit' and/or
+ * 'protect' protocol, based upon these macro
+ * settings.
+ *
+ * -------------------------------------------------------------
+ */
+
+/*
+ * POSIX Options
+ */
+#undef _POSIX_THREADS
+#define _POSIX_THREADS 200809L
+
+#undef _POSIX_READER_WRITER_LOCKS
+#define _POSIX_READER_WRITER_LOCKS 200809L
+
+#undef _POSIX_SPIN_LOCKS
+#define _POSIX_SPIN_LOCKS 200809L
+
+#undef _POSIX_BARRIERS
+#define _POSIX_BARRIERS 200809L
+
+#undef _POSIX_THREAD_SAFE_FUNCTIONS
+#define _POSIX_THREAD_SAFE_FUNCTIONS 200809L
+
+#undef _POSIX_THREAD_ATTR_STACKSIZE
+#define _POSIX_THREAD_ATTR_STACKSIZE 200809L
+
+/*
+ * The following options are not supported
+ */
+#undef _POSIX_THREAD_ATTR_STACKADDR
+#define _POSIX_THREAD_ATTR_STACKADDR -1
+
+#undef _POSIX_THREAD_PRIO_INHERIT
+#define _POSIX_THREAD_PRIO_INHERIT -1
+
+#undef _POSIX_THREAD_PRIO_PROTECT
+#define _POSIX_THREAD_PRIO_PROTECT -1
+
+/* TPS is not fully supported. */
+#undef _POSIX_THREAD_PRIORITY_SCHEDULING
+#define _POSIX_THREAD_PRIORITY_SCHEDULING -1
+
+#undef _POSIX_THREAD_PROCESS_SHARED
+#define _POSIX_THREAD_PROCESS_SHARED -1
+
+
+/*
+ * POSIX 1003.1-2001 Limits
+ * ===========================
+ *
+ * These limits are normally set in <limits.h>, which is not provided with
+ * pthreads-win32.
+ *
+ * PTHREAD_DESTRUCTOR_ITERATIONS
+ * Maximum number of attempts to destroy
+ * a thread's thread-specific data on
+ * termination (must be at least 4)
+ *
+ * PTHREAD_KEYS_MAX
+ * Maximum number of thread-specific data keys
+ * available per process (must be at least 128)
+ *
+ * PTHREAD_STACK_MIN
+ * Minimum supported stack size for a thread
+ *
+ * PTHREAD_THREADS_MAX
+ * Maximum number of threads supported per
+ * process (must be at least 64).
+ *
+ * SEM_NSEMS_MAX
+ * The maximum number of semaphores a process can have.
+ * (must be at least 256)
+ *
+ * SEM_VALUE_MAX
+ * The maximum value a semaphore can have.
+ * (must be at least 32767)
+ *
+ */
+#undef _POSIX_THREAD_DESTRUCTOR_ITERATIONS
+#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4
+
+#undef PTHREAD_DESTRUCTOR_ITERATIONS
+#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS
+
+#undef _POSIX_THREAD_KEYS_MAX
+#define _POSIX_THREAD_KEYS_MAX 128
+
+#undef PTHREAD_KEYS_MAX
+#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX
+
+#undef PTHREAD_STACK_MIN
+#define PTHREAD_STACK_MIN 0
+
+#undef _POSIX_THREAD_THREADS_MAX
+#define _POSIX_THREAD_THREADS_MAX 64
+
+ /* Arbitrary value */
+#undef PTHREAD_THREADS_MAX
+#define PTHREAD_THREADS_MAX 2019
+
+#undef _POSIX_SEM_NSEMS_MAX
+#define _POSIX_SEM_NSEMS_MAX 256
+
+ /* Arbitrary value */
+#undef SEM_NSEMS_MAX
+#define SEM_NSEMS_MAX 1024
+
+#undef _POSIX_SEM_VALUE_MAX
+#define _POSIX_SEM_VALUE_MAX 32767
+
+#undef SEM_VALUE_MAX
+#define SEM_VALUE_MAX INT_MAX
+
+
+#if defined(__GNUC__) && !defined(__declspec)
+# error Please upgrade your GNU compiler to one that supports __declspec.
+#endif
+
+/*
+ * When building the library, you should define PTW32_BUILD so that
+ * the variables/functions are exported correctly. When using the library,
+ * do NOT define PTW32_BUILD, and then the variables/functions will
+ * be imported correctly.
+ */
+#if !defined(PTW32_STATIC_LIB)
+# if defined(PTW32_BUILD)
+# define PTW32_DLLPORT __declspec (dllexport)
+# else
+# define PTW32_DLLPORT __declspec (dllimport)
+# endif
+#else
+# define PTW32_DLLPORT
+#endif
+
+/*
+ * The Open Watcom C/C++ compiler uses a non-standard calling convention
+ * that passes function args in registers unless __cdecl is explicitly specified
+ * in exposed function prototypes.
+ *
+ * We force all calls to cdecl even though this could slow Watcom code down
+ * slightly. If you know that the Watcom compiler will be used to build both
+ * the DLL and application, then you can probably define this as a null string.
+ * Remember that pthread.h (this file) is used for both the DLL and application builds.
+ */
+#define PTW32_CDECL __cdecl
+
+#if defined(_UWIN) && PTW32_LEVEL >= PTW32_LEVEL_MAX
+# include <sys/types.h>
+#else
+/*
+ * Generic handle type - intended to extend uniqueness beyond
+ * that available with a simple pointer. It should scale for either
+ * IA-32 or IA-64.
+ */
+#ifndef PTW32_YANDEX
+typedef struct {
+ void * p; /* Pointer to actual object */
+ unsigned int x; /* Extra information - reuse count etc */
+} ptw32_handle_t;
+#endif
+
+typedef ptw32_handle_t pthread_t;
+typedef struct pthread_attr_t_ * pthread_attr_t;
+typedef struct pthread_once_t_ pthread_once_t;
+typedef struct pthread_key_t_ * pthread_key_t;
+typedef struct pthread_mutex_t_ * pthread_mutex_t;
+typedef struct pthread_mutexattr_t_ * pthread_mutexattr_t;
+typedef struct pthread_cond_t_ * pthread_cond_t;
+typedef struct pthread_condattr_t_ * pthread_condattr_t;
+#endif
+typedef struct pthread_rwlock_t_ * pthread_rwlock_t;
+typedef struct pthread_rwlockattr_t_ * pthread_rwlockattr_t;
+typedef struct pthread_spinlock_t_ * pthread_spinlock_t;
+typedef struct pthread_barrier_t_ * pthread_barrier_t;
+typedef struct pthread_barrierattr_t_ * pthread_barrierattr_t;
+
+/*
+ * ====================
+ * ====================
+ * POSIX Threads
+ * ====================
+ * ====================
+ */
+
+enum {
+/*
+ * pthread_attr_{get,set}detachstate
+ */
+ PTHREAD_CREATE_JOINABLE = 0, /* Default */
+ PTHREAD_CREATE_DETACHED = 1,
+
+/*
+ * pthread_attr_{get,set}inheritsched
+ */
+ PTHREAD_INHERIT_SCHED = 0,
+ PTHREAD_EXPLICIT_SCHED = 1, /* Default */
+
+/*
+ * pthread_{get,set}scope
+ */
+ PTHREAD_SCOPE_PROCESS = 0,
+ PTHREAD_SCOPE_SYSTEM = 1, /* Default */
+
+/*
+ * pthread_setcancelstate paramters
+ */
+ PTHREAD_CANCEL_ENABLE = 0, /* Default */
+ PTHREAD_CANCEL_DISABLE = 1,
+
+/*
+ * pthread_setcanceltype parameters
+ */
+ PTHREAD_CANCEL_ASYNCHRONOUS = 0,
+ PTHREAD_CANCEL_DEFERRED = 1, /* Default */
+
+/*
+ * pthread_mutexattr_{get,set}pshared
+ * pthread_condattr_{get,set}pshared
+ */
+ PTHREAD_PROCESS_PRIVATE = 0,
+ PTHREAD_PROCESS_SHARED = 1,
+
+/*
+ * pthread_mutexattr_{get,set}robust
+ */
+ PTHREAD_MUTEX_STALLED = 0, /* Default */
+ PTHREAD_MUTEX_ROBUST = 1,
+
+/*
+ * pthread_barrier_wait
+ */
+ PTHREAD_BARRIER_SERIAL_THREAD = -1
+};
+
+/*
+ * ====================
+ * ====================
+ * Cancelation
+ * ====================
+ * ====================
+ */
+#define PTHREAD_CANCELED ((void *)(size_t) -1)
+
+
+/*
+ * ====================
+ * ====================
+ * Once Key
+ * ====================
+ * ====================
+ */
+#define PTHREAD_ONCE_INIT { PTW32_FALSE, 0, 0, 0}
+
+struct pthread_once_t_
+{
+ int done; /* indicates if user function has been executed */
+ void * lock;
+ int reserved1;
+ int reserved2;
+};
+
+
+/*
+ * ====================
+ * ====================
+ * Object initialisers
+ * ====================
+ * ====================
+ */
+#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t)(size_t) -1)
+#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER ((pthread_mutex_t)(size_t) -2)
+#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER ((pthread_mutex_t)(size_t) -3)
+
+/*
+ * Compatibility with LinuxThreads
+ */
+#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER
+#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_ERRORCHECK_MUTEX_INITIALIZER
+
+#define PTHREAD_COND_INITIALIZER ((pthread_cond_t)(size_t) -1)
+
+#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t)(size_t) -1)
+
+#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t)(size_t) -1)
+
+
+/*
+ * Mutex types.
+ */
+enum
+{
+ /* Compatibility with LinuxThreads */
+ PTHREAD_MUTEX_FAST_NP,
+ PTHREAD_MUTEX_RECURSIVE_NP,
+ PTHREAD_MUTEX_ERRORCHECK_NP,
+ PTHREAD_MUTEX_TIMED_NP = PTHREAD_MUTEX_FAST_NP,
+ PTHREAD_MUTEX_ADAPTIVE_NP = PTHREAD_MUTEX_FAST_NP,
+ /* For compatibility with POSIX */
+ PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_FAST_NP,
+ PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP,
+ PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP,
+ PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL
+};
+
+
+typedef struct ptw32_cleanup_t ptw32_cleanup_t;
+
+#if defined(_MSC_VER)
+/* Disable MSVC 'anachronism used' warning */
+#pragma warning( disable : 4229 )
+#endif
+
+typedef void (* PTW32_CDECL ptw32_cleanup_callback_t)(void *);
+
+#if defined(_MSC_VER)
+#pragma warning( default : 4229 )
+#endif
+
+struct ptw32_cleanup_t
+{
+ ptw32_cleanup_callback_t routine;
+ void *arg;
+ struct ptw32_cleanup_t *prev;
+};
+
+#if defined(__CLEANUP_SEH)
+ /*
+ * WIN32 SEH version of cancel cleanup.
+ */
+
+#define pthread_cleanup_push( _rout, _arg ) \
+ { \
+ ptw32_cleanup_t _cleanup; \
+ \
+ _cleanup.routine = (ptw32_cleanup_callback_t)(_rout); \
+ _cleanup.arg = (_arg); \
+ __try \
+ { \
+
+#define pthread_cleanup_pop( _execute ) \
+ } \
+ __finally \
+ { \
+ if( _execute || AbnormalTermination()) \
+ { \
+ (*(_cleanup.routine))( _cleanup.arg ); \
+ } \
+ } \
+ }
+
+#else /* __CLEANUP_SEH */
+
+#if defined(__CLEANUP_C)
+
+ /*
+ * C implementation of PThreads cancel cleanup
+ */
+
+#define pthread_cleanup_push( _rout, _arg ) \
+ { \
+ ptw32_cleanup_t _cleanup; \
+ \
+ ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \
+
+#define pthread_cleanup_pop( _execute ) \
+ (void) ptw32_pop_cleanup( _execute ); \
+ }
+
+#else /* __CLEANUP_C */
+
+#if defined(__CLEANUP_CXX)
+
+ /*
+ * C++ version of cancel cleanup.
+ * - John E. Bossom.
+ */
+
+ class PThreadCleanup {
+ /*
+ * PThreadCleanup
+ *
+ * Purpose
+ * This class is a C++ helper class that is
+ * used to implement pthread_cleanup_push/
+ * pthread_cleanup_pop.
+ * The destructor of this class automatically
+ * pops the pushed cleanup routine regardless
+ * of how the code exits the scope
+ * (i.e. such as by an exception)
+ */
+ ptw32_cleanup_callback_t cleanUpRout;
+ void * obj;
+ int executeIt;
+
+ public:
+ PThreadCleanup() :
+ cleanUpRout( 0 ),
+ obj( 0 ),
+ executeIt( 0 )
+ /*
+ * No cleanup performed
+ */
+ {
+ }
+
+ PThreadCleanup(
+ ptw32_cleanup_callback_t routine,
+ void * arg ) :
+ cleanUpRout( routine ),
+ obj( arg ),
+ executeIt( 1 )
+ /*
+ * Registers a cleanup routine for 'arg'
+ */
+ {
+ }
+
+ ~PThreadCleanup()
+ {
+ if ( executeIt && ((void *) cleanUpRout != (void *) 0) )
+ {
+ (void) (*cleanUpRout)( obj );
+ }
+ }
+
+ void execute( int exec )
+ {
+ executeIt = exec;
+ }
+ };
+
+ /*
+ * C++ implementation of PThreads cancel cleanup;
+ * This implementation takes advantage of a helper
+ * class who's destructor automatically calls the
+ * cleanup routine if we exit our scope weirdly
+ */
+#define pthread_cleanup_push( _rout, _arg ) \
+ { \
+ PThreadCleanup cleanup((ptw32_cleanup_callback_t)(_rout), \
+ (void *) (_arg) );
+
+#define pthread_cleanup_pop( _execute ) \
+ cleanup.execute( _execute ); \
+ }
+
+#else
+
+#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
+
+#endif /* __CLEANUP_CXX */
+
+#endif /* __CLEANUP_C */
+
+#endif /* __CLEANUP_SEH */
+
+/*
+ * ===============
+ * ===============
+ * Methods
+ * ===============
+ * ===============
+ */
+
+/*
+ * PThread Attribute Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_init (pthread_attr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_destroy (pthread_attr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getdetachstate (const pthread_attr_t * attr,
+ int *detachstate);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstackaddr (const pthread_attr_t * attr,
+ void **stackaddr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstacksize (const pthread_attr_t * attr,
+ size_t * stacksize);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setdetachstate (pthread_attr_t * attr,
+ int detachstate);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstackaddr (pthread_attr_t * attr,
+ void *stackaddr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstacksize (pthread_attr_t * attr,
+ size_t stacksize);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedparam (const pthread_attr_t *attr,
+ struct sched_param *param);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedparam (pthread_attr_t *attr,
+ const struct sched_param *param);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedpolicy (pthread_attr_t *,
+ int);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedpolicy (const pthread_attr_t *,
+ int *);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setinheritsched(pthread_attr_t * attr,
+ int inheritsched);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getinheritsched(const pthread_attr_t * attr,
+ int * inheritsched);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_setscope (pthread_attr_t *,
+ int);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_attr_getscope (const pthread_attr_t *,
+ int *);
+
+/*
+ * PThread Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_create (pthread_t * tid,
+ const pthread_attr_t * attr,
+ void *(PTW32_CDECL *start) (void *),
+ void *arg);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_detach (pthread_t tid);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_equal (pthread_t t1,
+ pthread_t t2);
+
+PTW32_DLLPORT void PTW32_CDECL pthread_exit (void *value_ptr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_join (pthread_t thread,
+ void **value_ptr);
+
+#if defined(PTW32_YANDEX) && defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable:4190) /* 'pthread_self' has C-linkage specified, but returns UDT 'ptw32_handle_t' which is incompatible with C */
+#endif
+
+PTW32_DLLPORT pthread_t PTW32_CDECL pthread_self (void);
+
+#if defined(PTW32_YANDEX) && defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cancel (pthread_t thread);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_setcancelstate (int state,
+ int *oldstate);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_setcanceltype (int type,
+ int *oldtype);
+
+PTW32_DLLPORT void PTW32_CDECL pthread_testcancel (void);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_once (pthread_once_t * once_control,
+ void (PTW32_CDECL *init_routine) (void));
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+PTW32_DLLPORT ptw32_cleanup_t * PTW32_CDECL ptw32_pop_cleanup (int execute);
+
+PTW32_DLLPORT void PTW32_CDECL ptw32_push_cleanup (ptw32_cleanup_t * cleanup,
+ ptw32_cleanup_callback_t routine,
+ void *arg);
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+/*
+ * Thread Specific Data Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_key_create (pthread_key_t * key,
+ void (PTW32_CDECL *destructor) (void *));
+
+PTW32_DLLPORT int PTW32_CDECL pthread_key_delete (pthread_key_t key);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_setspecific (pthread_key_t key,
+ const void *value);
+
+PTW32_DLLPORT void * PTW32_CDECL pthread_getspecific (pthread_key_t key);
+
+
+/*
+ * Mutex Attribute Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_init (pthread_mutexattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_destroy (pthread_mutexattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getpshared (const pthread_mutexattr_t
+ * attr,
+ int *pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setpshared (pthread_mutexattr_t * attr,
+ int pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind);
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_gettype (const pthread_mutexattr_t * attr, int *kind);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setrobust(
+ pthread_mutexattr_t *attr,
+ int robust);
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getrobust(
+ const pthread_mutexattr_t * attr,
+ int * robust);
+
+/*
+ * Barrier Attribute Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_init (pthread_barrierattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_destroy (pthread_barrierattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_getpshared (const pthread_barrierattr_t
+ * attr,
+ int *pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_setpshared (pthread_barrierattr_t * attr,
+ int pshared);
+
+/*
+ * Mutex Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_init (pthread_mutex_t * mutex,
+ const pthread_mutexattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_destroy (pthread_mutex_t * mutex);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_lock (pthread_mutex_t * mutex);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_timedlock(pthread_mutex_t * mutex,
+ const struct timespec *abstime);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_trylock (pthread_mutex_t * mutex);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_unlock (pthread_mutex_t * mutex);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_mutex_consistent (pthread_mutex_t * mutex);
+
+/*
+ * Spinlock Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_spin_init (pthread_spinlock_t * lock, int pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_spin_destroy (pthread_spinlock_t * lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_spin_lock (pthread_spinlock_t * lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_spin_trylock (pthread_spinlock_t * lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_spin_unlock (pthread_spinlock_t * lock);
+
+/*
+ * Barrier Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_barrier_init (pthread_barrier_t * barrier,
+ const pthread_barrierattr_t * attr,
+ unsigned int count);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_barrier_destroy (pthread_barrier_t * barrier);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_barrier_wait (pthread_barrier_t * barrier);
+
+/*
+ * Condition Variable Attribute Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_condattr_init (pthread_condattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_condattr_destroy (pthread_condattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_condattr_getpshared (const pthread_condattr_t * attr,
+ int *pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_condattr_setpshared (pthread_condattr_t * attr,
+ int pshared);
+
+/*
+ * Condition Variable Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_init (pthread_cond_t * cond,
+ const pthread_condattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_destroy (pthread_cond_t * cond);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_wait (pthread_cond_t * cond,
+ pthread_mutex_t * mutex);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_timedwait (pthread_cond_t * cond,
+ pthread_mutex_t * mutex,
+ const struct timespec *abstime);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_signal (pthread_cond_t * cond);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_cond_broadcast (pthread_cond_t * cond);
+
+/*
+ * Scheduling
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_setschedparam (pthread_t thread,
+ int policy,
+ const struct sched_param *param);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_getschedparam (pthread_t thread,
+ int *policy,
+ struct sched_param *param);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_setconcurrency (int);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_getconcurrency (void);
+
+/*
+ * Read-Write Lock Functions
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_init(pthread_rwlock_t *lock,
+ const pthread_rwlockattr_t *attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_destroy(pthread_rwlock_t *lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_tryrdlock(pthread_rwlock_t *);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_trywrlock(pthread_rwlock_t *);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_rdlock(pthread_rwlock_t *lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedrdlock(pthread_rwlock_t *lock,
+ const struct timespec *abstime);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_wrlock(pthread_rwlock_t *lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedwrlock(pthread_rwlock_t *lock,
+ const struct timespec *abstime);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_unlock(pthread_rwlock_t *lock);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_init (pthread_rwlockattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr,
+ int *pshared);
+
+PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr,
+ int pshared);
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX - 1
+
+/*
+ * Signal Functions. Should be defined in <signal.h> but MSVC and MinGW32
+ * already have signal.h that don't define these.
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_kill(pthread_t thread, int sig);
+
+/*
+ * Non-portable functions
+ */
+
+/*
+ * Compatibility with Linux.
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr,
+ int kind);
+PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr,
+ int *kind);
+
+/*
+ * Possibly supported by other POSIX threads implementations
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_delay_np (struct timespec * interval);
+PTW32_DLLPORT int PTW32_CDECL pthread_num_processors_np(void);
+PTW32_DLLPORT unsigned __int64 PTW32_CDECL pthread_getunique_np(pthread_t thread);
+
+/*
+ * Useful if an application wants to statically link
+ * the lib rather than load the DLL at run-time.
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_attach_np(void);
+PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_detach_np(void);
+PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_attach_np(void);
+PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_detach_np(void);
+
+/*
+ * Features that are auto-detected at load/run time.
+ */
+PTW32_DLLPORT int PTW32_CDECL pthread_win32_test_features_np(int);
+enum ptw32_features {
+ PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE = 0x0001, /* System provides it. */
+ PTW32_ALERTABLE_ASYNC_CANCEL = 0x0002 /* Can cancel blocked threads. */
+};
+
+/*
+ * Register a system time change with the library.
+ * Causes the library to perform various functions
+ * in response to the change. Should be called whenever
+ * the application's top level window receives a
+ * WM_TIMECHANGE message. It can be passed directly to
+ * pthread_create() as a new thread if desired.
+ */
+PTW32_DLLPORT void * PTW32_CDECL pthread_timechange_handler_np(void *);
+
+#endif /*PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 */
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+
+/*
+ * Returns the Win32 HANDLE for the POSIX thread.
+ */
+PTW32_DLLPORT HANDLE PTW32_CDECL pthread_getw32threadhandle_np(pthread_t thread);
+/*
+ * Returns the win32 thread ID for POSIX thread.
+ */
+PTW32_DLLPORT DWORD PTW32_CDECL pthread_getw32threadid_np (pthread_t thread);
+
+
+/*
+ * Protected Methods
+ *
+ * This function blocks until the given WIN32 handle
+ * is signaled or pthread_cancel had been called.
+ * This function allows the caller to hook into the
+ * PThreads cancel mechanism. It is implemented using
+ *
+ * WaitForMultipleObjects
+ *
+ * on 'waitHandle' and a manually reset WIN32 Event
+ * used to implement pthread_cancel. The 'timeout'
+ * argument to TimedWait is simply passed to
+ * WaitForMultipleObjects.
+ */
+PTW32_DLLPORT int PTW32_CDECL pthreadCancelableWait (HANDLE waitHandle);
+PTW32_DLLPORT int PTW32_CDECL pthreadCancelableTimedWait (HANDLE waitHandle,
+ DWORD timeout);
+
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+/*
+ * Thread-Safe C Runtime Library Mappings.
+ */
+#if !defined(_UWIN)
+# if defined(NEED_ERRNO)
+ PTW32_DLLPORT int * PTW32_CDECL _errno( void );
+# else
+# if !defined(errno)
+# if (defined(_MT) || defined(_DLL))
+ __declspec(dllimport) extern int * __cdecl _errno(void);
+# define errno (*_errno())
+# endif
+# endif
+# endif
+#endif
+
+/*
+ * Some compiler environments don't define some things.
+ */
+#if defined(__BORLANDC__)
+# define _ftime ftime
+# define _timeb timeb
+#endif
+
+#if defined(__cplusplus)
+
+/*
+ * Internal exceptions
+ */
+class ptw32_exception {};
+class ptw32_exception_cancel : public ptw32_exception {};
+class ptw32_exception_exit : public ptw32_exception {};
+
+#endif
+
+#if PTW32_LEVEL >= PTW32_LEVEL_MAX
+
+/* FIXME: This is only required if the library was built using SEH */
+/*
+ * Get internal SEH tag
+ */
+PTW32_DLLPORT DWORD PTW32_CDECL ptw32_get_exception_services_code(void);
+
+#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
+
+#if !defined(PTW32_BUILD)
+
+#if defined(__CLEANUP_SEH)
+
+/*
+ * Redefine the SEH __except keyword to ensure that applications
+ * propagate our internal exceptions up to the library's internal handlers.
+ */
+#define __except( E ) \
+ __except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \
+ ? EXCEPTION_CONTINUE_SEARCH : ( E ) )
+
+#endif /* __CLEANUP_SEH */
+
+#if defined(__CLEANUP_CXX)
+
+/*
+ * Redefine the C++ catch keyword to ensure that applications
+ * propagate our internal exceptions up to the library's internal handlers.
+ */
+#if defined(_MSC_VER)
+ /*
+ * WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll'
+ * if you want Pthread-Win32 cancelation and pthread_exit to work.
+ */
+
+#if !defined(PtW32NoCatchWarn)
+
+#pragma message("Specify \"/DPtW32NoCatchWarn\" compiler flag to skip this message.")
+#pragma message("------------------------------------------------------------------")
+#pragma message("When compiling applications with MSVC++ and C++ exception handling:")
+#pragma message(" Replace any 'catch( ... )' in routines called from POSIX threads")
+#pragma message(" with 'PtW32CatchAll' or 'CATCHALL' if you want POSIX thread")
+#pragma message(" cancelation and pthread_exit to work. For example:")
+#pragma message("")
+#pragma message(" #if defined(PtW32CatchAll)")
+#pragma message(" PtW32CatchAll")
+#pragma message(" #else")
+#pragma message(" catch(...)")
+#pragma message(" #endif")
+#pragma message(" {")
+#pragma message(" /* Catchall block processing */")
+#pragma message(" }")
+#pragma message("------------------------------------------------------------------")
+
+#endif
+
+#define PtW32CatchAll \
+ catch( ptw32_exception & ) { throw; } \
+ catch( ... )
+
+#else /* _MSC_VER */
+
+#define catch( E ) \
+ catch( ptw32_exception & ) { throw; } \
+ catch( E )
+
+#endif /* _MSC_VER */
+
+#endif /* __CLEANUP_CXX */
+
+#endif /* ! PTW32_BUILD */
+
+#if defined(__cplusplus)
+} /* End of extern "C" */
+#endif /* __cplusplus */
+
+#if defined(PTW32__HANDLE_DEF)
+# undef HANDLE
+#endif
+#if defined(PTW32__DWORD_DEF)
+# undef DWORD
+#endif
+
+#undef PTW32_LEVEL
+#undef PTW32_LEVEL_MAX
+
+#endif /* ! RC_INVOKED */
+
+#endif /* PTHREAD_H */
diff --git a/contrib/libs/pthreads_win32/sched.h b/contrib/libs/pthreads_win32/sched.h
new file mode 100644
index 0000000000..f36a97a66b
--- /dev/null
+++ b/contrib/libs/pthreads_win32/sched.h
@@ -0,0 +1,183 @@
+/*
+ * Module: sched.h
+ *
+ * Purpose:
+ * Provides an implementation of POSIX realtime extensions
+ * as defined in
+ *
+ * POSIX 1003.1b-1993 (POSIX.1b)
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2005 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@callisto.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+#if !defined(_SCHED_H)
+#define _SCHED_H
+
+#undef PTW32_SCHED_LEVEL
+
+#if defined(_POSIX_SOURCE)
+#define PTW32_SCHED_LEVEL 0
+/* Early POSIX */
+#endif
+
+#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
+#undef PTW32_SCHED_LEVEL
+#define PTW32_SCHED_LEVEL 1
+/* Include 1b, 1c and 1d */
+#endif
+
+#if defined(INCLUDE_NP)
+#undef PTW32_SCHED_LEVEL
+#define PTW32_SCHED_LEVEL 2
+/* Include Non-Portable extensions */
+#endif
+
+#define PTW32_SCHED_LEVEL_MAX 3
+
+#if ( defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112 ) || !defined(PTW32_SCHED_LEVEL)
+#define PTW32_SCHED_LEVEL PTW32_SCHED_LEVEL_MAX
+/* Include everything */
+#endif
+
+
+#if defined(__GNUC__) && !defined(__declspec)
+# error Please upgrade your GNU compiler to one that supports __declspec.
+#endif
+
+/*
+ * When building the library, you should define PTW32_BUILD so that
+ * the variables/functions are exported correctly. When using the library,
+ * do NOT define PTW32_BUILD, and then the variables/functions will
+ * be imported correctly.
+ */
+#if !defined(PTW32_STATIC_LIB)
+# if defined(PTW32_BUILD)
+# define PTW32_DLLPORT __declspec (dllexport)
+# else
+# define PTW32_DLLPORT __declspec (dllimport)
+# endif
+#else
+# define PTW32_DLLPORT
+#endif
+
+/*
+ * This is a duplicate of what is in the autoconf config.h,
+ * which is only used when building the pthread-win32 libraries.
+ */
+
+#if !defined(PTW32_CONFIG_H)
+# if defined(WINCE)
+# define NEED_ERRNO
+# define NEED_SEM
+# endif
+# if defined(__MINGW64__)
+# define HAVE_STRUCT_TIMESPEC
+# define HAVE_MODE_T
+# elif defined(_UWIN) || defined(__MINGW32__)
+# define HAVE_MODE_T
+# endif
+#endif
+
+/*
+ *
+ */
+
+#if PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX
+#if defined(NEED_ERRNO)
+#include "need_errno.h"
+#else
+#include <errno.h>
+#endif
+#endif /* PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX */
+
+#if (defined(__MINGW64__) || defined(__MINGW32__)) || defined(_UWIN)
+# if PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX
+/* For pid_t */
+# include <sys/types.h>
+/* Required by Unix 98 */
+# include <time.h>
+# else
+ typedef int pid_t;
+# endif
+#else
+ typedef int pid_t;
+#endif
+
+/* Thread scheduling policies */
+
+enum {
+ SCHED_OTHER = 0,
+ SCHED_FIFO,
+ SCHED_RR,
+ SCHED_MIN = SCHED_OTHER,
+ SCHED_MAX = SCHED_RR
+};
+
+struct sched_param {
+ int sched_priority;
+};
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif /* __cplusplus */
+
+PTW32_DLLPORT int __cdecl sched_yield (void);
+
+PTW32_DLLPORT int __cdecl sched_get_priority_min (int policy);
+
+PTW32_DLLPORT int __cdecl sched_get_priority_max (int policy);
+
+PTW32_DLLPORT int __cdecl sched_setscheduler (pid_t pid, int policy);
+
+PTW32_DLLPORT int __cdecl sched_getscheduler (pid_t pid);
+
+/*
+ * Note that this macro returns ENOTSUP rather than
+ * ENOSYS as might be expected. However, returning ENOSYS
+ * should mean that sched_get_priority_{min,max} are
+ * not implemented as well as sched_rr_get_interval.
+ * This is not the case, since we just don't support
+ * round-robin scheduling. Therefore I have chosen to
+ * return the same value as sched_setscheduler when
+ * SCHED_RR is passed to it.
+ */
+#define sched_rr_get_interval(_pid, _interval) \
+ ( errno = ENOTSUP, (int) -1 )
+
+
+#if defined(__cplusplus)
+} /* End of extern "C" */
+#endif /* __cplusplus */
+
+#undef PTW32_SCHED_LEVEL
+#undef PTW32_SCHED_LEVEL_MAX
+
+#endif /* !_SCHED_H */
+