summaryrefslogtreecommitdiff
path: root/Utilities/cmlibuv/src/unix
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2020-04-06 11:58:14 -0400
committerBrad King <brad.king@kitware.com>2020-04-06 11:58:14 -0400
commit722d6b41053c6f143e10468d2ea25146a3dcf7a5 (patch)
tree1cd58dcc2f2a255d6cc388f45d4883b0757d262a /Utilities/cmlibuv/src/unix
parent21c5a311c60da34d4e66a1d1a778106110f9b5d2 (diff)
parent394b07af40e1bdbdca0033e53ca803585454da18 (diff)
downloadcmake-722d6b41053c6f143e10468d2ea25146a3dcf7a5.tar.gz
Merge branch 'upstream-libuv' into update-libuv
* upstream-libuv: libuv 2020-04-06 (d21f5aea)
Diffstat (limited to 'Utilities/cmlibuv/src/unix')
-rw-r--r--Utilities/cmlibuv/src/unix/aix-common.c142
-rw-r--r--Utilities/cmlibuv/src/unix/aix.c180
-rw-r--r--Utilities/cmlibuv/src/unix/android-ifaddrs.c3
-rw-r--r--Utilities/cmlibuv/src/unix/async.c84
-rw-r--r--Utilities/cmlibuv/src/unix/atomic-ops.h4
-rw-r--r--Utilities/cmlibuv/src/unix/bsd-ifaddrs.c2
-rw-r--r--Utilities/cmlibuv/src/unix/core.c292
-rw-r--r--Utilities/cmlibuv/src/unix/cygwin.c5
-rw-r--r--Utilities/cmlibuv/src/unix/darwin-proctitle.c153
-rw-r--r--Utilities/cmlibuv/src/unix/darwin.c17
-rw-r--r--Utilities/cmlibuv/src/unix/freebsd.c34
-rw-r--r--Utilities/cmlibuv/src/unix/fs.c341
-rw-r--r--Utilities/cmlibuv/src/unix/fsevents.c11
-rw-r--r--Utilities/cmlibuv/src/unix/haiku.c9
-rw-r--r--Utilities/cmlibuv/src/unix/ibmi.c264
-rw-r--r--Utilities/cmlibuv/src/unix/internal.h46
-rw-r--r--Utilities/cmlibuv/src/unix/kqueue.c44
-rw-r--r--Utilities/cmlibuv/src/unix/linux-core.c81
-rw-r--r--Utilities/cmlibuv/src/unix/linux-inotify.c67
-rw-r--r--Utilities/cmlibuv/src/unix/linux-syscalls.c214
-rw-r--r--Utilities/cmlibuv/src/unix/linux-syscalls.h80
-rw-r--r--Utilities/cmlibuv/src/unix/netbsd.c30
-rw-r--r--Utilities/cmlibuv/src/unix/openbsd.c63
-rw-r--r--Utilities/cmlibuv/src/unix/os390-syscalls.c117
-rw-r--r--Utilities/cmlibuv/src/unix/os390-syscalls.h6
-rw-r--r--Utilities/cmlibuv/src/unix/os390.c9
-rw-r--r--Utilities/cmlibuv/src/unix/pipe.c8
-rw-r--r--Utilities/cmlibuv/src/unix/posix-poll.c2
-rw-r--r--Utilities/cmlibuv/src/unix/process.c80
-rw-r--r--Utilities/cmlibuv/src/unix/proctitle.c69
-rw-r--r--Utilities/cmlibuv/src/unix/random-devurandom.c93
-rw-r--r--Utilities/cmlibuv/src/unix/random-getentropy.c57
-rw-r--r--Utilities/cmlibuv/src/unix/random-getrandom.c88
-rw-r--r--Utilities/cmlibuv/src/unix/random-sysctl-linux.c99
-rw-r--r--Utilities/cmlibuv/src/unix/signal.c21
-rw-r--r--Utilities/cmlibuv/src/unix/stream.c13
-rw-r--r--Utilities/cmlibuv/src/unix/sunos.c10
-rw-r--r--Utilities/cmlibuv/src/unix/tcp.c29
-rw-r--r--Utilities/cmlibuv/src/unix/thread.c18
-rw-r--r--Utilities/cmlibuv/src/unix/tty.c37
-rw-r--r--Utilities/cmlibuv/src/unix/udp.c368
41 files changed, 2191 insertions, 1099 deletions
diff --git a/Utilities/cmlibuv/src/unix/aix-common.c b/Utilities/cmlibuv/src/unix/aix-common.c
index e9697e9c27..44c87b10a0 100644
--- a/Utilities/cmlibuv/src/unix/aix-common.c
+++ b/Utilities/cmlibuv/src/unix/aix-common.c
@@ -34,6 +34,7 @@
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
+#include <netinet/in6_var.h>
#include <arpa/inet.h>
#include <sys/time.h>
@@ -155,144 +156,3 @@ int uv_exepath(char* buffer, size_t* size) {
}
}
-void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
- int i;
-
- for (i = 0; i < count; ++i) {
- uv__free(cpu_infos[i].model);
- }
-
- uv__free(cpu_infos);
-}
-
-
-int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
- uv_interface_address_t* address;
- int sockfd, inet6, size = 1;
- struct ifconf ifc;
- struct ifreq *ifr, *p, flg;
- struct sockaddr_dl* sa_addr;
-
- *count = 0;
- *addresses = NULL;
-
- if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) {
- return UV__ERR(errno);
- }
-
- if (ioctl(sockfd, SIOCGSIZIFCONF, &size) == -1) {
- uv__close(sockfd);
- return UV__ERR(errno);
- }
-
- ifc.ifc_req = (struct ifreq*)uv__malloc(size);
- ifc.ifc_len = size;
- if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) {
- uv__close(sockfd);
- return UV__ERR(errno);
- }
-
-#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p))
-
- /* Count all up and running ipv4/ipv6 addresses */
- ifr = ifc.ifc_req;
- while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
- p = ifr;
- ifr = (struct ifreq*)
- ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr));
-
- if (!(p->ifr_addr.sa_family == AF_INET6 ||
- p->ifr_addr.sa_family == AF_INET))
- continue;
-
- memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
- if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
- uv__close(sockfd);
- return UV__ERR(errno);
- }
-
- if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
- continue;
-
- (*count)++;
- }
-
- if (*count == 0) {
- uv__close(sockfd);
- return 0;
- }
-
- /* Alloc the return interface structs */
- *addresses = uv__malloc(*count * sizeof(uv_interface_address_t));
- if (!(*addresses)) {
- uv__close(sockfd);
- return UV_ENOMEM;
- }
- address = *addresses;
-
- ifr = ifc.ifc_req;
- while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
- p = ifr;
- ifr = (struct ifreq*)
- ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr));
-
- if (!(p->ifr_addr.sa_family == AF_INET6 ||
- p->ifr_addr.sa_family == AF_INET))
- continue;
-
- inet6 = (p->ifr_addr.sa_family == AF_INET6);
-
- memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
- if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
- uv__close(sockfd);
- return UV_ENOSYS;
- }
-
- if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
- continue;
-
- /* All conditions above must match count loop */
-
- address->name = uv__strdup(p->ifr_name);
-
- if (inet6)
- address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr);
- else
- address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr);
-
- sa_addr = (struct sockaddr_dl*) &p->ifr_addr;
- memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
-
- if (ioctl(sockfd, SIOCGIFNETMASK, p) == -1) {
- uv__close(sockfd);
- return UV_ENOSYS;
- }
-
- if (inet6)
- address->netmask.netmask6 = *((struct sockaddr_in6*) &p->ifr_addr);
- else
- address->netmask.netmask4 = *((struct sockaddr_in*) &p->ifr_addr);
-
- address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0;
-
- address++;
- }
-
-#undef ADDR_SIZE
-
- uv__close(sockfd);
- return 0;
-}
-
-
-void uv_free_interface_addresses(uv_interface_address_t* addresses,
- int count) {
- int i;
-
- for (i = 0; i < count; ++i) {
- uv__free(addresses[i].name);
- }
-
- uv__free(addresses);
-}
-
diff --git a/Utilities/cmlibuv/src/unix/aix.c b/Utilities/cmlibuv/src/unix/aix.c
index 1f36926c02..417ee5512f 100644
--- a/Utilities/cmlibuv/src/unix/aix.c
+++ b/Utilities/cmlibuv/src/unix/aix.c
@@ -1039,6 +1039,186 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
}
+int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
+ uv_interface_address_t* address;
+ int sockfd, sock6fd, inet6, i, r, size = 1;
+ struct ifconf ifc;
+ struct ifreq *ifr, *p, flg;
+ struct in6_ifreq if6;
+ struct sockaddr_dl* sa_addr;
+
+ ifc.ifc_req = NULL;
+ sock6fd = -1;
+ r = 0;
+ *count = 0;
+ *addresses = NULL;
+
+ if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) {
+ r = UV__ERR(errno);
+ goto cleanup;
+ }
+
+ if (0 > (sock6fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP))) {
+ r = UV__ERR(errno);
+ goto cleanup;
+ }
+
+ if (ioctl(sockfd, SIOCGSIZIFCONF, &size) == -1) {
+ r = UV__ERR(errno);
+ goto cleanup;
+ }
+
+ ifc.ifc_req = (struct ifreq*)uv__malloc(size);
+ if (ifc.ifc_req == NULL) {
+ r = UV_ENOMEM;
+ goto cleanup;
+ }
+ ifc.ifc_len = size;
+ if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) {
+ r = UV__ERR(errno);
+ goto cleanup;
+ }
+
+#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p))
+
+ /* Count all up and running ipv4/ipv6 addresses */
+ ifr = ifc.ifc_req;
+ while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
+ p = ifr;
+ ifr = (struct ifreq*)
+ ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr));
+
+ if (!(p->ifr_addr.sa_family == AF_INET6 ||
+ p->ifr_addr.sa_family == AF_INET))
+ continue;
+
+ memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
+ if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
+ r = UV__ERR(errno);
+ goto cleanup;
+ }
+
+ if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
+ continue;
+
+ (*count)++;
+ }
+
+ if (*count == 0)
+ goto cleanup;
+
+ /* Alloc the return interface structs */
+ *addresses = uv__calloc(*count, sizeof(**addresses));
+ if (!(*addresses)) {
+ r = UV_ENOMEM;
+ goto cleanup;
+ }
+ address = *addresses;
+
+ ifr = ifc.ifc_req;
+ while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
+ p = ifr;
+ ifr = (struct ifreq*)
+ ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr));
+
+ if (!(p->ifr_addr.sa_family == AF_INET6 ||
+ p->ifr_addr.sa_family == AF_INET))
+ continue;
+
+ inet6 = (p->ifr_addr.sa_family == AF_INET6);
+
+ memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
+ if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1)
+ goto syserror;
+
+ if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
+ continue;
+
+ /* All conditions above must match count loop */
+
+ address->name = uv__strdup(p->ifr_name);
+
+ if (inet6)
+ address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr);
+ else
+ address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr);
+
+ if (inet6) {
+ memset(&if6, 0, sizeof(if6));
+ r = uv__strscpy(if6.ifr_name, p->ifr_name, sizeof(if6.ifr_name));
+ if (r == UV_E2BIG)
+ goto cleanup;
+ r = 0;
+ memcpy(&if6.ifr_Addr, &p->ifr_addr, sizeof(if6.ifr_Addr));
+ if (ioctl(sock6fd, SIOCGIFNETMASK6, &if6) == -1)
+ goto syserror;
+ address->netmask.netmask6 = *((struct sockaddr_in6*) &if6.ifr_Addr);
+ /* Explicitly set family as the ioctl call appears to return it as 0. */
+ address->netmask.netmask6.sin6_family = AF_INET6;
+ } else {
+ if (ioctl(sockfd, SIOCGIFNETMASK, p) == -1)
+ goto syserror;
+ address->netmask.netmask4 = *((struct sockaddr_in*) &p->ifr_addr);
+ /* Explicitly set family as the ioctl call appears to return it as 0. */
+ address->netmask.netmask4.sin_family = AF_INET;
+ }
+
+ address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0;
+
+ address++;
+ }
+
+ /* Fill in physical addresses. */
+ ifr = ifc.ifc_req;
+ while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
+ p = ifr;
+ ifr = (struct ifreq*)
+ ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr));
+
+ if (p->ifr_addr.sa_family != AF_LINK)
+ continue;
+
+ address = *addresses;
+ for (i = 0; i < *count; i++) {
+ if (strcmp(address->name, p->ifr_name) == 0) {
+ sa_addr = (struct sockaddr_dl*) &p->ifr_addr;
+ memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr));
+ }
+ address++;
+ }
+ }
+
+#undef ADDR_SIZE
+ goto cleanup;
+
+syserror:
+ uv_free_interface_addresses(*addresses, *count);
+ *addresses = NULL;
+ *count = 0;
+ r = UV_ENOSYS;
+
+cleanup:
+ if (sockfd != -1)
+ uv__close(sockfd);
+ if (sock6fd != -1)
+ uv__close(sock6fd);
+ uv__free(ifc.ifc_req);
+ return r;
+}
+
+
+void uv_free_interface_addresses(uv_interface_address_t* addresses,
+ int count) {
+ int i;
+
+ for (i = 0; i < count; ++i) {
+ uv__free(addresses[i].name);
+ }
+
+ uv__free(addresses);
+}
+
+
void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
struct pollfd* events;
uintptr_t i;
diff --git a/Utilities/cmlibuv/src/unix/android-ifaddrs.c b/Utilities/cmlibuv/src/unix/android-ifaddrs.c
index 99fb25a43b..4765cc06b5 100644
--- a/Utilities/cmlibuv/src/unix/android-ifaddrs.c
+++ b/Utilities/cmlibuv/src/unix/android-ifaddrs.c
@@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <netinet/in.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
+#include <linux/if_packet.h>
typedef struct NetlinkList
{
@@ -469,12 +470,14 @@ static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList,
{
case IFA_ADDRESS:
case IFA_LOCAL:
+ l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
if((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) && !l_addedNetmask)
{
/* Make room for netmask */
l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
l_addedNetmask = 1;
}
+ break;
case IFA_BROADCAST:
l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
break;
diff --git a/Utilities/cmlibuv/src/unix/async.c b/Utilities/cmlibuv/src/unix/async.c
index a5c47bca05..26d337e0a4 100644
--- a/Utilities/cmlibuv/src/unix/async.c
+++ b/Utilities/cmlibuv/src/unix/async.c
@@ -33,9 +33,12 @@
#include <string.h>
#include <unistd.h>
+#ifdef __linux__
+#include <sys/eventfd.h>
+#endif
+
static void uv__async_send(uv_loop_t* loop);
static int uv__async_start(uv_loop_t* loop);
-static int uv__async_eventfd(void);
int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) {
@@ -190,36 +193,18 @@ static int uv__async_start(uv_loop_t* loop) {
if (loop->async_io_watcher.fd != -1)
return 0;
- err = uv__async_eventfd();
- if (err >= 0) {
- pipefd[0] = err;
- pipefd[1] = -1;
- }
- else if (err == UV_ENOSYS) {
- err = uv__make_pipe(pipefd, UV__F_NONBLOCK);
-#if defined(__linux__)
- /* Save a file descriptor by opening one of the pipe descriptors as
- * read/write through the procfs. That file descriptor can then
- * function as both ends of the pipe.
- */
- if (err == 0) {
- char buf[32];
- int fd;
-
- snprintf(buf, sizeof(buf), "/proc/self/fd/%d", pipefd[0]);
- fd = uv__open_cloexec(buf, O_RDWR);
- if (fd >= 0) {
- uv__close(pipefd[0]);
- uv__close(pipefd[1]);
- pipefd[0] = fd;
- pipefd[1] = fd;
- }
- }
-#endif
- }
+#ifdef __linux__
+ err = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
+ if (err < 0)
+ return UV__ERR(errno);
+ pipefd[0] = err;
+ pipefd[1] = -1;
+#else
+ err = uv__make_pipe(pipefd, UV__F_NONBLOCK);
if (err < 0)
return err;
+#endif
uv__io_init(&loop->async_io_watcher, uv__async_io, pipefd[0]);
uv__io_start(loop, &loop->async_io_watcher, POLLIN);
@@ -253,46 +238,3 @@ void uv__async_stop(uv_loop_t* loop) {
uv__close(loop->async_io_watcher.fd);
loop->async_io_watcher.fd = -1;
}
-
-
-static int uv__async_eventfd(void) {
-#if defined(__linux__)
- static int no_eventfd2;
- static int no_eventfd;
- int fd;
-
- if (no_eventfd2)
- goto skip_eventfd2;
-
- fd = uv__eventfd2(0, UV__EFD_CLOEXEC | UV__EFD_NONBLOCK);
- if (fd != -1)
- return fd;
-
- if (errno != ENOSYS)
- return UV__ERR(errno);
-
- no_eventfd2 = 1;
-
-skip_eventfd2:
-
- if (no_eventfd)
- goto skip_eventfd;
-
- fd = uv__eventfd(0);
- if (fd != -1) {
- uv__cloexec(fd, 1);
- uv__nonblock(fd, 1);
- return fd;
- }
-
- if (errno != ENOSYS)
- return UV__ERR(errno);
-
- no_eventfd = 1;
-
-skip_eventfd:
-
-#endif
-
- return UV_ENOSYS;
-}
diff --git a/Utilities/cmlibuv/src/unix/atomic-ops.h b/Utilities/cmlibuv/src/unix/atomic-ops.h
index 995aca63ac..bc37c0d45d 100644
--- a/Utilities/cmlibuv/src/unix/atomic-ops.h
+++ b/Utilities/cmlibuv/src/unix/atomic-ops.h
@@ -36,10 +36,6 @@ UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) {
: "r" (newval), "0" (oldval)
: "memory");
return out;
-#elif defined(_AIX) && (defined(__xlC__) || defined(__ibmxl__))
- const int out = (*(volatile int*) ptr);
- __compare_and_swap(ptr, &oldval, newval);
- return out;
#elif defined(__MVS__)
unsigned int op4;
if (__plo_CSST(ptr, (unsigned int*) &oldval, newval,
diff --git a/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c b/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c
index 0d7bbe662a..a3385af17c 100644
--- a/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c
+++ b/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c
@@ -69,7 +69,9 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
struct ifaddrs* addrs;
struct ifaddrs* ent;
uv_interface_address_t* address;
+#if !(defined(__CYGWIN__) || defined(__MSYS__))
int i;
+#endif
*count = 0;
*addresses = NULL;
diff --git a/Utilities/cmlibuv/src/unix/core.c b/Utilities/cmlibuv/src/unix/core.c
index cf7dea050b..d1e9baa56a 100644
--- a/Utilities/cmlibuv/src/unix/core.c
+++ b/Utilities/cmlibuv/src/unix/core.c
@@ -30,7 +30,7 @@
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <fcntl.h>
+#include <fcntl.h> /* O_CLOEXEC */
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/un.h>
@@ -50,37 +50,36 @@
# include <sys/wait.h>
#endif
-#ifdef __APPLE__
-# include <mach-o/dyld.h> /* _NSGetExecutablePath */
+#if defined(__APPLE__)
# include <sys/filio.h>
-# if defined(O_CLOEXEC)
-# define UV__O_CLOEXEC O_CLOEXEC
-# endif
-#endif
+# endif /* defined(__APPLE__) */
+
+
+#if defined(__APPLE__) && !TARGET_OS_IPHONE
+# include <crt_externs.h>
+# include <mach-o/dyld.h> /* _NSGetExecutablePath */
+# define environ (*_NSGetEnviron())
+#else /* defined(__APPLE__) && !TARGET_OS_IPHONE */
+extern char** environ;
+#endif /* !(defined(__APPLE__) && !TARGET_OS_IPHONE) */
+
#if defined(__DragonFly__) || \
defined(__FreeBSD__) || \
defined(__FreeBSD_kernel__) || \
- defined(__NetBSD__)
+ defined(__NetBSD__) || \
+ defined(__OpenBSD__)
# include <sys/sysctl.h>
# include <sys/filio.h>
# include <sys/wait.h>
# include <sys/param.h>
# include <sys/cpuset.h>
-# define UV__O_CLOEXEC O_CLOEXEC
-# if defined(__FreeBSD__) && __FreeBSD__ >= 10
+# if defined(__FreeBSD__) || defined(__linux__)
# define uv__accept4 accept4
# endif
# if defined(__NetBSD__)
# define uv__accept4(a, b, c, d) paccept((a), (b), (c), NULL, (d))
# endif
-# if (defined(__FreeBSD__) && __FreeBSD__ >= 10) || defined(__NetBSD__)
-# define UV__SOCK_NONBLOCK SOCK_NONBLOCK
-# define UV__SOCK_CLOEXEC SOCK_CLOEXEC
-# endif
-# if !defined(F_DUP2FD_CLOEXEC) && defined(_F_DUP2FD_CLOEXEC)
-# define F_DUP2FD_CLOEXEC _F_DUP2FD_CLOEXEC
-# endif
#endif
#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
@@ -175,9 +174,7 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
case UV_SIGNAL:
uv__signal_close((uv_signal_t*) handle);
- /* Signal handles may not be closed immediately. The signal code will
- * itself close uv__make_close_pending whenever appropriate. */
- return;
+ break;
default:
assert(0);
@@ -242,6 +239,8 @@ int uv__getiovmax(void) {
static void uv__finish_close(uv_handle_t* handle) {
+ uv_signal_t* sh;
+
/* Note: while the handle is in the UV_HANDLE_CLOSING state now, it's still
* possible for it to be active in the sense that uv__is_active() returns
* true.
@@ -264,7 +263,20 @@ static void uv__finish_close(uv_handle_t* handle) {
case UV_FS_EVENT:
case UV_FS_POLL:
case UV_POLL:
+ break;
+
case UV_SIGNAL:
+ /* If there are any caught signals "trapped" in the signal pipe,
+ * we can't call the close callback yet. Reinserting the handle
+ * into the closing queue makes the event loop spin but that's
+ * okay because we only need to deliver the pending events.
+ */
+ sh = (uv_signal_t*) handle;
+ if (sh->caught_signals > sh->dispatched_signals) {
+ handle->flags ^= UV_HANDLE_CLOSED;
+ uv__make_close_pending(handle); /* Back into the queue. */
+ return;
+ }
break;
case UV_NAMED_PIPE:
@@ -468,52 +480,32 @@ int uv__accept(int sockfd) {
int peerfd;
int err;
+ (void) &err;
assert(sockfd >= 0);
- while (1) {
-#if defined(__linux__) || \
- (defined(__FreeBSD__) && __FreeBSD__ >= 10) || \
- defined(__NetBSD__)
- static int no_accept4;
-
- if (no_accept4)
- goto skip;
-
- peerfd = uv__accept4(sockfd,
- NULL,
- NULL,
- UV__SOCK_NONBLOCK|UV__SOCK_CLOEXEC);
- if (peerfd != -1)
- return peerfd;
-
- if (errno == EINTR)
- continue;
-
- if (errno != ENOSYS)
- return UV__ERR(errno);
-
- no_accept4 = 1;
-skip:
-#endif
-
+ do
+#ifdef uv__accept4
+ peerfd = uv__accept4(sockfd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
+#else
peerfd = accept(sockfd, NULL, NULL);
- if (peerfd == -1) {
- if (errno == EINTR)
- continue;
- return UV__ERR(errno);
- }
+#endif
+ while (peerfd == -1 && errno == EINTR);
- err = uv__cloexec(peerfd, 1);
- if (err == 0)
- err = uv__nonblock(peerfd, 1);
+ if (peerfd == -1)
+ return UV__ERR(errno);
- if (err) {
- uv__close(peerfd);
- return err;
- }
+#ifndef uv__accept4
+ err = uv__cloexec(peerfd, 1);
+ if (err == 0)
+ err = uv__nonblock(peerfd, 1);
- return peerfd;
+ if (err != 0) {
+ uv__close(peerfd);
+ return err;
}
+#endif
+
+ return peerfd;
}
@@ -529,7 +521,7 @@ int uv__close_nocancel(int fd) {
#if defined(__APPLE__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdollar-in-identifier-extension"
-#if defined(__LP64__)
+#if defined(__LP64__) || defined(TARGET_OS_IPHONE)
extern int close$NOCANCEL(int);
return close$NOCANCEL(fd);
#else
@@ -704,16 +696,38 @@ ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) {
int uv_cwd(char* buffer, size_t* size) {
+ char scratch[1 + UV__PATH_MAX];
+
if (buffer == NULL || size == NULL)
return UV_EINVAL;
- if (getcwd(buffer, *size) == NULL)
+ /* Try to read directly into the user's buffer first... */
+ if (getcwd(buffer, *size) != NULL)
+ goto fixup;
+
+ if (errno != ERANGE)
+ return UV__ERR(errno);
+
+ /* ...or into scratch space if the user's buffer is too small
+ * so we can report how much space to provide on the next try.
+ */
+ if (getcwd(scratch, sizeof(scratch)) == NULL)
return UV__ERR(errno);
+ buffer = scratch;
+
+fixup:
+
*size = strlen(buffer);
+
if (*size > 1 && buffer[*size - 1] == '/') {
- buffer[*size-1] = '\0';
- (*size)--;
+ *size -= 1;
+ buffer[*size] = '\0';
+ }
+
+ if (buffer == scratch) {
+ *size += 1;
+ return UV_ENOBUFS;
}
return 0;
@@ -823,8 +837,8 @@ static void maybe_resize(uv_loop_t* loop, unsigned int len) {
}
nwatchers = next_power_of_two(len + 2) - 2;
- watchers = uv__realloc(loop->watchers,
- (nwatchers + 2) * sizeof(loop->watchers[0]));
+ watchers = uv__reallocf(loop->watchers,
+ (nwatchers + 2) * sizeof(loop->watchers[0]));
if (watchers == NULL)
abort();
@@ -977,24 +991,17 @@ int uv_getrusage(uv_rusage_t* rusage) {
int uv__open_cloexec(const char* path, int flags) {
- int err;
+#if defined(O_CLOEXEC)
int fd;
-#if defined(UV__O_CLOEXEC)
- static int no_cloexec;
-
- if (!no_cloexec) {
- fd = open(path, flags | UV__O_CLOEXEC);
- if (fd != -1)
- return fd;
-
- if (errno != EINVAL)
- return UV__ERR(errno);
+ fd = open(path, flags | O_CLOEXEC);
+ if (fd == -1)
+ return UV__ERR(errno);
- /* O_CLOEXEC not supported. */
- no_cloexec = 1;
- }
-#endif
+ return fd;
+#else /* O_CLOEXEC */
+ int err;
+ int fd;
fd = open(path, flags);
if (fd == -1)
@@ -1007,58 +1014,35 @@ int uv__open_cloexec(const char* path, int flags) {
}
return fd;
+#endif /* O_CLOEXEC */
}
int uv__dup2_cloexec(int oldfd, int newfd) {
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__linux__)
int r;
-#if (defined(__FreeBSD__) && __FreeBSD__ >= 10) || defined(__NetBSD__)
+
r = dup3(oldfd, newfd, O_CLOEXEC);
if (r == -1)
return UV__ERR(errno);
+
return r;
-#elif defined(__FreeBSD__) && defined(F_DUP2FD_CLOEXEC)
- r = fcntl(oldfd, F_DUP2FD_CLOEXEC, newfd);
- if (r != -1)
- return r;
- if (errno != EINVAL)
- return UV__ERR(errno);
- /* Fall through. */
-#elif defined(__linux__)
- static int no_dup3;
- if (!no_dup3) {
- do
- r = uv__dup3(oldfd, newfd, UV__O_CLOEXEC);
- while (r == -1 && errno == EBUSY);
- if (r != -1)
- return r;
- if (errno != ENOSYS)
- return UV__ERR(errno);
- /* Fall through. */
- no_dup3 = 1;
- }
-#endif
- {
- int err;
- do
- r = dup2(oldfd, newfd);
-#if defined(__linux__)
- while (r == -1 && errno == EBUSY);
#else
- while (0); /* Never retry. */
-#endif
-
- if (r == -1)
- return UV__ERR(errno);
+ int err;
+ int r;
- err = uv__cloexec(newfd, 1);
- if (err) {
- uv__close(newfd);
- return err;
- }
+ r = dup2(oldfd, newfd); /* Never retry. */
+ if (r == -1)
+ return UV__ERR(errno);
- return r;
+ err = uv__cloexec(newfd, 1);
+ if (err != 0) {
+ uv__close(newfd);
+ return err;
}
+
+ return r;
+#endif
}
@@ -1265,6 +1249,62 @@ int uv_translate_sys_error(int sys_errno) {
}
+int uv_os_environ(uv_env_item_t** envitems, int* count) {
+ int i, j, cnt;
+ uv_env_item_t* envitem;
+
+ *envitems = NULL;
+ *count = 0;
+
+ for (i = 0; environ[i] != NULL; i++);
+
+ *envitems = uv__calloc(i, sizeof(**envitems));
+
+ if (envitems == NULL)
+ return UV_ENOMEM;
+
+ for (j = 0, cnt = 0; j < i; j++) {
+ char* buf;
+ char* ptr;
+
+ if (environ[j] == NULL)
+ break;
+
+ buf = uv__strdup(environ[j]);
+ if (buf == NULL)
+ goto fail;
+
+ ptr = strchr(buf, '=');
+ if (ptr == NULL) {
+ uv__free(buf);
+ continue;
+ }
+
+ *ptr = '\0';
+
+ envitem = &(*envitems)[cnt];
+ envitem->name = buf;
+ envitem->value = ptr + 1;
+
+ cnt++;
+ }
+
+ *count = cnt;
+ return 0;
+
+fail:
+ for (i = 0; i < cnt; i++) {
+ envitem = &(*envitems)[cnt];
+ uv__free(envitem->name);
+ }
+ uv__free(*envitems);
+
+ *envitems = NULL;
+ *count = 0;
+ return UV_ENOMEM;
+}
+
+
int uv_os_getenv(const char* name, char* buffer, size_t* size) {
char* var;
size_t len;
@@ -1488,3 +1528,17 @@ int uv_gettimeofday(uv_timeval64_t* tv) {
tv->tv_usec = (int32_t) time.tv_usec;
return 0;
}
+
+void uv_sleep(unsigned int msec) {
+ struct timespec timeout;
+ int rc;
+
+ timeout.tv_sec = msec / 1000;
+ timeout.tv_nsec = (msec % 1000) * 1000 * 1000;
+
+ do
+ rc = nanosleep(&timeout, &timeout);
+ while (rc == -1 && errno == EINTR);
+
+ assert(rc == 0);
+}
diff --git a/Utilities/cmlibuv/src/unix/cygwin.c b/Utilities/cmlibuv/src/unix/cygwin.c
index 9da20e203a..169958d55f 100644
--- a/Utilities/cmlibuv/src/unix/cygwin.c
+++ b/Utilities/cmlibuv/src/unix/cygwin.c
@@ -48,7 +48,6 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
return UV_ENOSYS;
}
-void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
- (void)cpu_infos;
- (void)count;
+uint64_t uv_get_constrained_memory(void) {
+ return 0; /* Memory constraints are unknown. */
}
diff --git a/Utilities/cmlibuv/src/unix/darwin-proctitle.c b/Utilities/cmlibuv/src/unix/darwin-proctitle.c
index e505bdd23f..2daf3e3474 100644
--- a/Utilities/cmlibuv/src/unix/darwin-proctitle.c
+++ b/Utilities/cmlibuv/src/unix/darwin-proctitle.c
@@ -23,6 +23,7 @@
#include <dlfcn.h>
#include <errno.h>
+#include <pthread.h>
#include <stdlib.h>
#include <string.h>
@@ -33,56 +34,51 @@
# include <ApplicationServices/ApplicationServices.h>
#endif
-#define S(s) pCFStringCreateWithCString(NULL, (s), kCFStringEncodingUTF8)
+static int uv__pthread_setname_np(const char* name) {
+ char namebuf[64]; /* MAXTHREADNAMESIZE */
+ int err;
-static int (*dynamic_pthread_setname_np)(const char* name);
-#if !TARGET_OS_IPHONE
-static CFStringRef (*pCFStringCreateWithCString)(CFAllocatorRef,
- const char*,
- CFStringEncoding);
-static CFBundleRef (*pCFBundleGetBundleWithIdentifier)(CFStringRef);
-static void *(*pCFBundleGetDataPointerForName)(CFBundleRef, CFStringRef);
-static void *(*pCFBundleGetFunctionPointerForName)(CFBundleRef, CFStringRef);
-static CFTypeRef (*pLSGetCurrentApplicationASN)(void);
-static OSStatus (*pLSSetApplicationInformationItem)(int,
- CFTypeRef,
- CFStringRef,
- CFStringRef,
- CFDictionaryRef*);
-static void* application_services_handle;
-static void* core_foundation_handle;
-static CFBundleRef launch_services_bundle;
-static CFStringRef* display_name_key;
-static CFDictionaryRef (*pCFBundleGetInfoDictionary)(CFBundleRef);
-static CFBundleRef (*pCFBundleGetMainBundle)(void);
-static CFBundleRef hi_services_bundle;
-static OSStatus (*pSetApplicationIsDaemon)(int);
-static CFDictionaryRef (*pLSApplicationCheckIn)(int, CFDictionaryRef);
-static void (*pLSSetApplicationLaunchServicesServerConnectionStatus)(uint64_t,
- void*);
-
-
-UV_DESTRUCTOR(static void uv__set_process_title_platform_fini(void)) {
- if (core_foundation_handle != NULL) {
- dlclose(core_foundation_handle);
- core_foundation_handle = NULL;
- }
+ strncpy(namebuf, name, sizeof(namebuf) - 1);
+ namebuf[sizeof(namebuf) - 1] = '\0';
- if (application_services_handle != NULL) {
- dlclose(application_services_handle);
- application_services_handle = NULL;
- }
-}
-#endif /* !TARGET_OS_IPHONE */
+ err = pthread_setname_np(namebuf);
+ if (err)
+ return UV__ERR(err);
+ return 0;
+}
-void uv__set_process_title_platform_init(void) {
- /* pthread_setname_np() first appeared in OS X 10.6 and iOS 3.2. */
- *(void **)(&dynamic_pthread_setname_np) =
- dlsym(RTLD_DEFAULT, "pthread_setname_np");
-#if !TARGET_OS_IPHONE
+int uv__set_process_title(const char* title) {
+#if TARGET_OS_IPHONE
+ return uv__pthread_setname_np(title);
+#else
+ CFStringRef (*pCFStringCreateWithCString)(CFAllocatorRef,
+ const char*,
+ CFStringEncoding);
+ CFBundleRef (*pCFBundleGetBundleWithIdentifier)(CFStringRef);
+ void *(*pCFBundleGetDataPointerForName)(CFBundleRef, CFStringRef);
+ void *(*pCFBundleGetFunctionPointerForName)(CFBundleRef, CFStringRef);
+ CFTypeRef (*pLSGetCurrentApplicationASN)(void);
+ OSStatus (*pLSSetApplicationInformationItem)(int,
+ CFTypeRef,
+ CFStringRef,
+ CFStringRef,
+ CFDictionaryRef*);
+ void* application_services_handle;
+ void* core_foundation_handle;
+ CFBundleRef launch_services_bundle;
+ CFStringRef* display_name_key;
+ CFDictionaryRef (*pCFBundleGetInfoDictionary)(CFBundleRef);
+ CFBundleRef (*pCFBundleGetMainBundle)(void);
+ CFDictionaryRef (*pLSApplicationCheckIn)(int, CFDictionaryRef);
+ void (*pLSSetApplicationLaunchServicesServerConnectionStatus)(uint64_t,
+ void*);
+ CFTypeRef asn;
+ int err;
+
+ err = UV_ENOENT;
application_services_handle = dlopen("/System/Library/Frameworks/"
"ApplicationServices.framework/"
"Versions/A/ApplicationServices",
@@ -111,6 +107,8 @@ void uv__set_process_title_platform_init(void) {
goto out;
}
+#define S(s) pCFStringCreateWithCString(NULL, (s), kCFStringEncodingUTF8)
+
launch_services_bundle =
pCFBundleGetBundleWithIdentifier(S("com.apple.LaunchServices"));
@@ -141,58 +139,55 @@ void uv__set_process_title_platform_init(void) {
"CFBundleGetInfoDictionary");
*(void **)(&pCFBundleGetMainBundle) = dlsym(core_foundation_handle,
"CFBundleGetMainBundle");
-
if (pCFBundleGetInfoDictionary == NULL || pCFBundleGetMainBundle == NULL)
goto out;
- /* Black 10.9 magic, to remove (Not responding) mark in Activity Monitor */
- hi_services_bundle =
- pCFBundleGetBundleWithIdentifier(S("com.apple.HIServices"));
-
- if (hi_services_bundle == NULL)
- goto out;
-
- *(void **)(&pSetApplicationIsDaemon) = pCFBundleGetFunctionPointerForName(
- hi_services_bundle,
- S("SetApplicationIsDaemon"));
*(void **)(&pLSApplicationCheckIn) = pCFBundleGetFunctionPointerForName(
launch_services_bundle,
S("_LSApplicationCheckIn"));
+
+ if (pLSApplicationCheckIn == NULL)
+ goto out;
+
*(void **)(&pLSSetApplicationLaunchServicesServerConnectionStatus) =
pCFBundleGetFunctionPointerForName(
launch_services_bundle,
S("_LSSetApplicationLaunchServicesServerConnectionStatus"));
- if (pSetApplicationIsDaemon == NULL ||
- pLSApplicationCheckIn == NULL ||
- pLSSetApplicationLaunchServicesServerConnectionStatus == NULL) {
+ if (pLSSetApplicationLaunchServicesServerConnectionStatus == NULL)
+ goto out;
+
+ pLSSetApplicationLaunchServicesServerConnectionStatus(0, NULL);
+
+ /* Check into process manager?! */
+ pLSApplicationCheckIn(-2,
+ pCFBundleGetInfoDictionary(pCFBundleGetMainBundle()));
+
+ asn = pLSGetCurrentApplicationASN();
+
+ err = UV_EBUSY;
+ if (asn == NULL)
+ goto out;
+
+ err = UV_EINVAL;
+ if (pLSSetApplicationInformationItem(-2, /* Magic value. */
+ asn,
+ *display_name_key,
+ S(title),
+ NULL) != noErr) {
goto out;
}
- return;
+ uv__pthread_setname_np(title); /* Don't care if it fails. */
+ err = 0;
out:
- uv__set_process_title_platform_fini();
-#endif /* !TARGET_OS_IPHONE */
-}
+ if (core_foundation_handle != NULL)
+ dlclose(core_foundation_handle);
+ if (application_services_handle != NULL)
+ dlclose(application_services_handle);
-void uv__set_process_title(const char* title) {
-#if !TARGET_OS_IPHONE
- if (core_foundation_handle != NULL && pSetApplicationIsDaemon(1) != noErr) {
- CFTypeRef asn;
- pLSSetApplicationLaunchServicesServerConnectionStatus(0, NULL);
- pLSApplicationCheckIn(/* Magic value */ -2,
- pCFBundleGetInfoDictionary(pCFBundleGetMainBundle()));
- asn = pLSGetCurrentApplicationASN();
- pLSSetApplicationInformationItem(/* Magic value */ -2, asn,
- *display_name_key, S(title), NULL);
- }
+ return err;
#endif /* !TARGET_OS_IPHONE */
-
- if (dynamic_pthread_setname_np != NULL) {
- char namebuf[64]; /* MAXTHREADNAMESIZE */
- uv__strscpy(namebuf, title, sizeof(namebuf));
- dynamic_pthread_setname_np(namebuf);
- }
}
diff --git a/Utilities/cmlibuv/src/unix/darwin.c b/Utilities/cmlibuv/src/unix/darwin.c
index e4cd8ff7e0..654aba26b1 100644
--- a/Utilities/cmlibuv/src/unix/darwin.c
+++ b/Utilities/cmlibuv/src/unix/darwin.c
@@ -110,7 +110,7 @@ uint64_t uv_get_total_memory(void) {
int which[] = {CTL_HW, HW_MEMSIZE};
size_t size = sizeof(info);
- if (sysctl(which, 2, &info, &size, NULL, 0))
+ if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0))
return UV__ERR(errno);
return (uint64_t) info;
@@ -127,7 +127,7 @@ void uv_loadavg(double avg[3]) {
size_t size = sizeof(info);
int which[] = {CTL_VM, VM_LOADAVG};
- if (sysctl(which, 2, &info, &size, NULL, 0) < 0) return;
+ if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0) < 0) return;
avg[0] = (double) info.ldavg[0] / info.fscale;
avg[1] = (double) info.ldavg[1] / info.fscale;
@@ -162,7 +162,7 @@ int uv_uptime(double* uptime) {
size_t size = sizeof(info);
static int which[] = {CTL_KERN, KERN_BOOTTIME};
- if (sysctl(which, 2, &info, &size, NULL, 0))
+ if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0))
return UV__ERR(errno);
now = time(NULL);
@@ -223,14 +223,3 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
return 0;
}
-
-
-void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
- int i;
-
- for (i = 0; i < count; i++) {
- uv__free(cpu_infos[i].model);
- }
-
- uv__free(cpu_infos);
-}
diff --git a/Utilities/cmlibuv/src/unix/freebsd.c b/Utilities/cmlibuv/src/unix/freebsd.c
index 7de88d6a52..ef77e127c2 100644
--- a/Utilities/cmlibuv/src/unix/freebsd.c
+++ b/Utilities/cmlibuv/src/unix/freebsd.c
@@ -95,7 +95,7 @@ int uv_exepath(char* buffer, size_t* size) {
mib[3] = -1;
abspath_size = sizeof abspath;
- if (sysctl(mib, 4, abspath, &abspath_size, NULL, 0))
+ if (sysctl(mib, ARRAY_SIZE(mib), abspath, &abspath_size, NULL, 0))
return UV__ERR(errno);
assert(abspath_size > 0);
@@ -130,7 +130,7 @@ uint64_t uv_get_total_memory(void) {
size_t size = sizeof(info);
- if (sysctl(which, 2, &info, &size, NULL, 0))
+ if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0))
return UV__ERR(errno);
return (uint64_t) info;
@@ -147,7 +147,7 @@ void uv_loadavg(double avg[3]) {
size_t size = sizeof(info);
int which[] = {CTL_VM, VM_LOADAVG};
- if (sysctl(which, 2, &info, &size, NULL, 0) < 0) return;
+ if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0) < 0) return;
avg[0] = (double) info.ldavg[0] / info.fscale;
avg[1] = (double) info.ldavg[1] / info.fscale;
@@ -168,7 +168,7 @@ int uv_resident_set_memory(size_t* rss) {
kinfo_size = sizeof(kinfo);
- if (sysctl(mib, 4, &kinfo, &kinfo_size, NULL, 0))
+ if (sysctl(mib, ARRAY_SIZE(mib), &kinfo, &kinfo_size, NULL, 0))
return UV__ERR(errno);
page_size = getpagesize();
@@ -290,12 +290,26 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
}
-void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
- int i;
+int uv__sendmmsg(int fd,
+ struct uv__mmsghdr* mmsg,
+ unsigned int vlen,
+ unsigned int flags) {
+#if __FreeBSD__ >= 11
+ return sendmmsg(fd, mmsg, vlen, flags);
+#else
+ return errno = ENOSYS, -1;
+#endif
+}
- for (i = 0; i < count; i++) {
- uv__free(cpu_infos[i].model);
- }
- uv__free(cpu_infos);
+int uv__recvmmsg(int fd,
+ struct uv__mmsghdr* mmsg,
+ unsigned int vlen,
+ unsigned int flags,
+ struct timespec* timeout) {
+#if __FreeBSD__ >= 11
+ return recvmmsg(fd, mmsg, vlen, flags, timeout);
+#else
+ return errno = ENOSYS, -1;
+#endif
}
diff --git a/Utilities/cmlibuv/src/unix/fs.c b/Utilities/cmlibuv/src/unix/fs.c
index 5fb34f1be8..70fe21aeb0 100644
--- a/Utilities/cmlibuv/src/unix/fs.c
+++ b/Utilities/cmlibuv/src/unix/fs.c
@@ -30,6 +30,7 @@
#include "internal.h"
#include <errno.h>
+#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -70,6 +71,20 @@
# include <utime.h>
#endif
+#if defined(__APPLE__) || \
+ defined(__DragonFly__) || \
+ defined(__FreeBSD__) || \
+ defined(__FreeBSD_kernel__) || \
+ defined(__OpenBSD__) || \
+ defined(__NetBSD__)
+# include <sys/param.h>
+# include <sys/mount.h>
+#elif defined(__sun) || defined(__MVS__) || defined(__NetBSD__) || defined(__HAIKU__)
+# include <sys/statvfs.h>
+#else
+# include <sys/statfs.h>
+#endif
+
#if defined(_AIX) && _XOPEN_SOURCE <= 600
extern char *mkdtemp(char *template); /* See issue #740 on AIX < 7 */
#endif
@@ -202,7 +217,11 @@ static ssize_t uv__fs_futime(uv_fs_t* req) {
ts[0].tv_nsec = (uint64_t)(req->atime * 1000000) % 1000000 * 1000;
ts[1].tv_sec = req->mtime;
ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000;
+#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
+ return utimensat(req->file, NULL, ts, 0);
+#else
return futimens(req->file, ts);
+#endif
#elif defined(__APPLE__) \
|| defined(__DragonFly__) \
|| defined(__FreeBSD__) \
@@ -250,23 +269,99 @@ static ssize_t uv__fs_mkdtemp(uv_fs_t* req) {
}
-static ssize_t uv__fs_open(uv_fs_t* req) {
- static int no_cloexec_support;
+static int (*uv__mkostemp)(char*, int);
+
+
+static void uv__mkostemp_initonce(void) {
+ /* z/os doesn't have RTLD_DEFAULT but that's okay
+ * because it doesn't have mkostemp(O_CLOEXEC) either.
+ */
+#ifdef RTLD_DEFAULT
+ uv__mkostemp = (int (*)(char*, int)) dlsym(RTLD_DEFAULT, "mkostemp");
+
+ /* We don't care about errors, but we do want to clean them up.
+ * If there has been no error, then dlerror() will just return
+ * NULL.
+ */
+ dlerror();
+#endif /* RTLD_DEFAULT */
+}
+
+
+static int uv__fs_mkstemp(uv_fs_t* req) {
+ static uv_once_t once = UV_ONCE_INIT;
int r;
+#ifdef O_CLOEXEC
+ static int no_cloexec_support;
+#endif
+ static const char pattern[] = "XXXXXX";
+ static const size_t pattern_size = sizeof(pattern) - 1;
+ char* path;
+ size_t path_length;
+
+ path = (char*) req->path;
+ path_length = strlen(path);
+
+ /* EINVAL can be returned for 2 reasons:
+ 1. The template's last 6 characters were not XXXXXX
+ 2. open() didn't support O_CLOEXEC
+ We want to avoid going to the fallback path in case
+ of 1, so it's manually checked before. */
+ if (path_length < pattern_size ||
+ strcmp(path + path_length - pattern_size, pattern)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ uv_once(&once, uv__mkostemp_initonce);
- /* Try O_CLOEXEC before entering locks */
- if (no_cloexec_support == 0) {
#ifdef O_CLOEXEC
- r = open(req->path, req->flags | O_CLOEXEC, req->mode);
+ if (no_cloexec_support == 0 && uv__mkostemp != NULL) {
+ r = uv__mkostemp(path, O_CLOEXEC);
+
if (r >= 0)
return r;
+
+ /* If mkostemp() returns EINVAL, it means the kernel doesn't
+ support O_CLOEXEC, so we just fallback to mkstemp() below. */
if (errno != EINVAL)
return r;
+
+ /* We set the static variable so that next calls don't even
+ try to use mkostemp. */
no_cloexec_support = 1;
+ }
#endif /* O_CLOEXEC */
+
+ if (req->cb != NULL)
+ uv_rwlock_rdlock(&req->loop->cloexec_lock);
+
+ r = mkstemp(path);
+
+ /* In case of failure `uv__cloexec` will leave error in `errno`,
+ * so it is enough to just set `r` to `-1`.
+ */
+ if (r >= 0 && uv__cloexec(r, 1) != 0) {
+ r = uv__close(r);
+ if (r != 0)
+ abort();
+ r = -1;
}
if (req->cb != NULL)
+ uv_rwlock_rdunlock(&req->loop->cloexec_lock);
+
+ return r;
+}
+
+
+static ssize_t uv__fs_open(uv_fs_t* req) {
+#ifdef O_CLOEXEC
+ return open(req->path, req->flags | O_CLOEXEC, req->mode);
+#else /* O_CLOEXEC */
+ int r;
+
+ if (req->cb != NULL)
uv_rwlock_rdlock(&req->loop->cloexec_lock);
r = open(req->path, req->flags, req->mode);
@@ -285,9 +380,60 @@ static ssize_t uv__fs_open(uv_fs_t* req) {
uv_rwlock_rdunlock(&req->loop->cloexec_lock);
return r;
+#endif /* O_CLOEXEC */
}
+#if !HAVE_PREADV
+static ssize_t uv__fs_preadv(uv_file fd,
+ uv_buf_t* bufs,
+ unsigned int nbufs,
+ off_t off) {
+ uv_buf_t* buf;
+ uv_buf_t* end;
+ ssize_t result;
+ ssize_t rc;
+ size_t pos;
+
+ assert(nbufs > 0);
+
+ result = 0;
+ pos = 0;
+ buf = bufs + 0;
+ end = bufs + nbufs;
+
+ for (;;) {
+ do
+ rc = pread(fd, buf->base + pos, buf->len - pos, off + result);
+ while (rc == -1 && errno == EINTR);
+
+ if (rc == 0)
+ break;
+
+ if (rc == -1 && result == 0)
+ return UV__ERR(errno);
+
+ if (rc == -1)
+ break; /* We read some data so return that, ignore the error. */
+
+ pos += rc;
+ result += rc;
+
+ if (pos < buf->len)
+ continue;
+
+ pos = 0;
+ buf += 1;
+
+ if (buf == end)
+ break;
+ }
+
+ return result;
+}
+#endif
+
+
static ssize_t uv__fs_read(uv_fs_t* req) {
#if defined(__linux__)
static int no_preadv;
@@ -317,7 +463,7 @@ static ssize_t uv__fs_read(uv_fs_t* req) {
if (no_preadv) retry:
# endif
{
- result = pread(req->file, req->bufs[0].base, req->bufs[0].len, req->off);
+ result = uv__fs_preadv(req->file, req->bufs, req->nbufs, req->off);
}
# if defined(__linux__)
else {
@@ -481,14 +627,39 @@ static int uv__fs_closedir(uv_fs_t* req) {
return 0;
}
-#if defined(_POSIX_PATH_MAX)
-# define UV__FS_PATH_MAX _POSIX_PATH_MAX
-#elif defined(PATH_MAX)
-# define UV__FS_PATH_MAX PATH_MAX
+static int uv__fs_statfs(uv_fs_t* req) {
+ uv_statfs_t* stat_fs;
+#if defined(__sun) || defined(__MVS__) || defined(__NetBSD__) || defined(__HAIKU__)
+ struct statvfs buf;
+
+ if (0 != statvfs(req->path, &buf))
+#else
+ struct statfs buf;
+
+ if (0 != statfs(req->path, &buf))
+#endif /* defined(__sun) */
+ return -1;
+
+ stat_fs = uv__malloc(sizeof(*stat_fs));
+ if (stat_fs == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+#if defined(__sun) || defined(__MVS__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__HAIKU__)
+ stat_fs->f_type = 0; /* f_type is not supported. */
#else
-# define UV__FS_PATH_MAX_FALLBACK 8192
-# define UV__FS_PATH_MAX UV__FS_PATH_MAX_FALLBACK
+ stat_fs->f_type = buf.f_type;
#endif
+ stat_fs->f_bsize = buf.f_bsize;
+ stat_fs->f_blocks = buf.f_blocks;
+ stat_fs->f_bfree = buf.f_bfree;
+ stat_fs->f_bavail = buf.f_bavail;
+ stat_fs->f_files = buf.f_files;
+ stat_fs->f_ffree = buf.f_ffree;
+ req->ptr = stat_fs;
+ return 0;
+}
static ssize_t uv__fs_pathmax_size(const char* path) {
ssize_t pathmax;
@@ -496,7 +667,7 @@ static ssize_t uv__fs_pathmax_size(const char* path) {
pathmax = pathconf(path, _PC_PATH_MAX);
if (pathmax == -1)
- pathmax = UV__FS_PATH_MAX;
+ pathmax = UV__PATH_MAX;
return pathmax;
}
@@ -505,9 +676,10 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) {
ssize_t maxlen;
ssize_t len;
char* buf;
- char* newbuf;
-#if defined(UV__FS_PATH_MAX_FALLBACK)
+#if defined(_POSIX_PATH_MAX) || defined(PATH_MAX)
+ maxlen = uv__fs_pathmax_size(req->path);
+#else
/* We may not have a real PATH_MAX. Read size of link. */
struct stat st;
int ret;
@@ -525,8 +697,6 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) {
for some symlinks, such as those in /proc or /sys. */
if (maxlen == 0)
maxlen = uv__fs_pathmax_size(req->path);
-#else
- maxlen = uv__fs_pathmax_size(req->path);
#endif
buf = uv__malloc(maxlen);
@@ -549,14 +719,10 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) {
/* Uncommon case: resize to make room for the trailing nul byte. */
if (len == maxlen) {
- newbuf = uv__realloc(buf, len + 1);
+ buf = uv__reallocf(buf, len + 1);
- if (newbuf == NULL) {
- uv__free(buf);
+ if (buf == NULL)
return -1;
- }
-
- buf = newbuf;
}
buf[len] = '\0';
@@ -918,12 +1084,14 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
uv_fs_t fs_req;
uv_file srcfd;
uv_file dstfd;
- struct stat statsbuf;
+ struct stat src_statsbuf;
+ struct stat dst_statsbuf;
int dst_flags;
int result;
int err;
size_t bytes_to_send;
int64_t in_offset;
+ ssize_t bytes_written;
dstfd = -1;
err = 0;
@@ -936,7 +1104,7 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
return srcfd;
/* Get the source file's mode. */
- if (fstat(srcfd, &statsbuf)) {
+ if (fstat(srcfd, &src_statsbuf)) {
err = UV__ERR(errno);
goto out;
}
@@ -951,7 +1119,7 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
&fs_req,
req->new_path,
dst_flags,
- statsbuf.st_mode,
+ src_statsbuf.st_mode,
NULL);
uv_fs_req_cleanup(&fs_req);
@@ -960,26 +1128,55 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
goto out;
}
- if (fchmod(dstfd, statsbuf.st_mode) == -1) {
+ /* Get the destination file's mode. */
+ if (fstat(dstfd, &dst_statsbuf)) {
err = UV__ERR(errno);
goto out;
}
+ /* Check if srcfd and dstfd refer to the same file */
+ if (src_statsbuf.st_dev == dst_statsbuf.st_dev &&
+ src_statsbuf.st_ino == dst_statsbuf.st_ino) {
+ goto out;
+ }
+
+ if (fchmod(dstfd, src_statsbuf.st_mode) == -1) {
+ err = UV__ERR(errno);
+#ifdef __linux__
+ if (err != UV_EPERM)
+ goto out;
+
+ {
+ struct statfs s;
+
+ /* fchmod() on CIFS shares always fails with EPERM unless the share is
+ * mounted with "noperm". As fchmod() is a meaningless operation on such
+ * shares anyway, detect that condition and squelch the error.
+ */
+ if (fstatfs(dstfd, &s) == -1)
+ goto out;
+
+ if (s.f_type != /* CIFS */ 0xFF534D42u)
+ goto out;
+ }
+
+ err = 0;
+#else /* !__linux__ */
+ goto out;
+#endif /* !__linux__ */
+ }
+
#ifdef FICLONE
if (req->flags & UV_FS_COPYFILE_FICLONE ||
req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
- if (ioctl(dstfd, FICLONE, srcfd) == -1) {
- /* If an error occurred that the sendfile fallback also won't handle, or
- this is a force clone then exit. Otherwise, fall through to try using
- sendfile(). */
- if (errno != ENOTTY && errno != EOPNOTSUPP && errno != EXDEV) {
- err = UV__ERR(errno);
- goto out;
- } else if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
- err = UV_ENOTSUP;
- goto out;
- }
- } else {
+ if (ioctl(dstfd, FICLONE, srcfd) == 0) {
+ /* ioctl() with FICLONE succeeded. */
+ goto out;
+ }
+ /* If an error occurred and force was set, return the error to the caller;
+ * fall back to sendfile() when force was not set. */
+ if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
+ err = UV__ERR(errno);
goto out;
}
}
@@ -990,21 +1187,20 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
}
#endif
- bytes_to_send = statsbuf.st_size;
+ bytes_to_send = src_statsbuf.st_size;
in_offset = 0;
while (bytes_to_send != 0) {
- err = uv_fs_sendfile(NULL,
- &fs_req,
- dstfd,
- srcfd,
- in_offset,
- bytes_to_send,
- NULL);
+ uv_fs_sendfile(NULL, &fs_req, dstfd, srcfd, in_offset, bytes_to_send, NULL);
+ bytes_written = fs_req.result;
uv_fs_req_cleanup(&fs_req);
- if (err < 0)
+
+ if (bytes_written < 0) {
+ err = bytes_written;
break;
- bytes_to_send -= fs_req.result;
- in_offset += fs_req.result;
+ }
+
+ bytes_to_send -= bytes_written;
+ in_offset += bytes_written;
}
out:
@@ -1151,13 +1347,22 @@ static int uv__fs_statx(int fd,
rc = uv__statx(dirfd, path, flags, mode, &statxbuf);
- if (rc == -1) {
+ switch (rc) {
+ case 0:
+ break;
+ case -1:
/* EPERM happens when a seccomp filter rejects the system call.
* Has been observed with libseccomp < 2.3.3 and docker < 18.04.
*/
if (errno != EINVAL && errno != EPERM && errno != ENOSYS)
return -1;
-
+ /* Fall through. */
+ default:
+ /* Normally on success, zero is returned and On error, -1 is returned.
+ * Observed on S390 RHEL running in a docker container with statx not
+ * implemented, rc might return 1 with 0 set as the error code in which
+ * case we return ENOSYS.
+ */
no_statx = 1;
return UV_ENOSYS;
}
@@ -1332,6 +1537,7 @@ static void uv__fs_work(struct uv__work* w) {
X(LINK, link(req->path, req->new_path));
X(MKDIR, mkdir(req->path, req->mode));
X(MKDTEMP, uv__fs_mkdtemp(req));
+ X(MKSTEMP, uv__fs_mkstemp(req));
X(OPEN, uv__fs_open(req));
X(READ, uv__fs_read(req));
X(SCANDIR, uv__fs_scandir(req));
@@ -1344,6 +1550,7 @@ static void uv__fs_work(struct uv__work* w) {
X(RMDIR, rmdir(req->path));
X(SENDFILE, uv__fs_sendfile(req));
X(STAT, uv__fs_stat(req->path, &req->statbuf));
+ X(STATFS, uv__fs_statfs(req));
X(SYMLINK, symlink(req->path, req->new_path));
X(UNLINK, unlink(req->path));
X(UTIME, uv__fs_utime(req));
@@ -1555,6 +1762,18 @@ int uv_fs_mkdtemp(uv_loop_t* loop,
}
+int uv_fs_mkstemp(uv_loop_t* loop,
+ uv_fs_t* req,
+ const char* tpl,
+ uv_fs_cb cb) {
+ INIT(MKSTEMP);
+ req->path = uv__strdup(tpl);
+ if (req->path == NULL)
+ return UV_ENOMEM;
+ POST;
+}
+
+
int uv_fs_open(uv_loop_t* loop,
uv_fs_t* req,
const char* path,
@@ -1773,10 +1992,12 @@ void uv_fs_req_cleanup(uv_fs_t* req) {
/* Only necessary for asychronous requests, i.e., requests with a callback.
* Synchronous ones don't copy their arguments and have req->path and
- * req->new_path pointing to user-owned memory. UV_FS_MKDTEMP is the
- * exception to the rule, it always allocates memory.
+ * req->new_path pointing to user-owned memory. UV_FS_MKDTEMP and
+ * UV_FS_MKSTEMP are the exception to the rule, they always allocate memory.
*/
- if (req->path != NULL && (req->cb != NULL || req->fs_type == UV_FS_MKDTEMP))
+ if (req->path != NULL &&
+ (req->cb != NULL ||
+ req->fs_type == UV_FS_MKDTEMP || req->fs_type == UV_FS_MKSTEMP))
uv__free((void*) req->path); /* Memory is shared with req->new_path. */
req->path = NULL;
@@ -1816,3 +2037,13 @@ int uv_fs_copyfile(uv_loop_t* loop,
req->flags = flags;
POST;
}
+
+
+int uv_fs_statfs(uv_loop_t* loop,
+ uv_fs_t* req,
+ const char* path,
+ uv_fs_cb cb) {
+ INIT(STATFS);
+ PATH;
+ POST;
+}
diff --git a/Utilities/cmlibuv/src/unix/fsevents.c b/Utilities/cmlibuv/src/unix/fsevents.c
index ddacda31fe..448921f813 100644
--- a/Utilities/cmlibuv/src/unix/fsevents.c
+++ b/Utilities/cmlibuv/src/unix/fsevents.c
@@ -263,10 +263,12 @@ static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef,
if (len < handle->realpath_len)
continue;
+ /* Make sure that realpath actually named a directory,
+ * (unless watching root, which alone keeps a trailing slash on the realpath)
+ * or that we matched the whole string */
if (handle->realpath_len != len &&
+ handle->realpath_len > 1 &&
path[handle->realpath_len] != '/')
- /* Make sure that realpath actually named a directory,
- * or that we matched the whole string */
continue;
if (memcmp(path, handle->realpath, handle->realpath_len) != 0)
@@ -745,6 +747,8 @@ static void* uv__cf_loop_runner(void* arg) {
state->signal_source,
*pkCFRunLoopDefaultMode);
+ state->loop = NULL;
+
return NULL;
}
@@ -797,13 +801,14 @@ int uv__cf_loop_signal(uv_loop_t* loop,
uv_mutex_lock(&loop->cf_mutex);
QUEUE_INSERT_TAIL(&loop->cf_signals, &item->member);
- uv_mutex_unlock(&loop->cf_mutex);
state = loop->cf_state;
assert(state != NULL);
pCFRunLoopSourceSignal(state->signal_source);
pCFRunLoopWakeUp(state->loop);
+ uv_mutex_unlock(&loop->cf_mutex);
+
return 0;
}
diff --git a/Utilities/cmlibuv/src/unix/haiku.c b/Utilities/cmlibuv/src/unix/haiku.c
index 7708851c2a..cf17d836b4 100644
--- a/Utilities/cmlibuv/src/unix/haiku.c
+++ b/Utilities/cmlibuv/src/unix/haiku.c
@@ -165,12 +165,3 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
return 0;
}
-
-void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
- int i;
-
- for (i = 0; i < count; i++)
- uv__free(cpu_infos[i].model);
-
- uv__free(cpu_infos);
-}
diff --git a/Utilities/cmlibuv/src/unix/ibmi.c b/Utilities/cmlibuv/src/unix/ibmi.c
index c7e105136e..e4c5122bc9 100644
--- a/Utilities/cmlibuv/src/unix/ibmi.c
+++ b/Utilities/cmlibuv/src/unix/ibmi.c
@@ -56,6 +56,7 @@
#include <sys/vnode.h>
#include <as400_protos.h>
+#include <as400_types.h>
typedef struct {
@@ -98,24 +99,91 @@ typedef struct {
} SSTS0200;
+typedef struct {
+ char header[208];
+ unsigned char loca_adapter_address[12];
+} LIND0500;
+
+
+typedef struct {
+ int bytes_provided;
+ int bytes_available;
+ char msgid[7];
+} errcode_s;
+
+
+static const unsigned char e2a[256] = {
+ 0, 1, 2, 3, 156, 9, 134, 127, 151, 141, 142, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 157, 133, 8, 135, 24, 25, 146, 143, 28, 29, 30, 31,
+ 128, 129, 130, 131, 132, 10, 23, 27, 136, 137, 138, 139, 140, 5, 6, 7,
+ 144, 145, 22, 147, 148, 149, 150, 4, 152, 153, 154, 155, 20, 21, 158, 26,
+ 32, 160, 161, 162, 163, 164, 165, 166, 167, 168, 91, 46, 60, 40, 43, 33,
+ 38, 169, 170, 171, 172, 173, 174, 175, 176, 177, 93, 36, 42, 41, 59, 94,
+ 45, 47, 178, 179, 180, 181, 182, 183, 184, 185, 124, 44, 37, 95, 62, 63,
+ 186, 187, 188, 189, 190, 191, 192, 193, 194, 96, 58, 35, 64, 39, 61, 34,
+ 195, 97, 98, 99, 100, 101, 102, 103, 104, 105, 196, 197, 198, 199, 200, 201,
+ 202, 106, 107, 108, 109, 110, 111, 112, 113, 114, 203, 204, 205, 206, 207, 208,
+ 209, 126, 115, 116, 117, 118, 119, 120, 121, 122, 210, 211, 212, 213, 214, 215,
+ 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231,
+ 123, 65, 66, 67, 68, 69, 70, 71, 72, 73, 232, 233, 234, 235, 236, 237,
+ 125, 74, 75, 76, 77, 78, 79, 80, 81, 82, 238, 239, 240, 241, 242, 243,
+ 92, 159, 83, 84, 85, 86, 87, 88, 89, 90, 244, 245, 246, 247, 248, 249,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 250, 251, 252, 253, 254, 255};
+
+
+static const unsigned char a2e[256] = {
+ 0, 1, 2, 3, 55, 45, 46, 47, 22, 5, 37, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 60, 61, 50, 38, 24, 25, 63, 39, 28, 29, 30, 31,
+ 64, 79, 127, 123, 91, 108, 80, 125, 77, 93, 92, 78, 107, 96, 75, 97,
+ 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 122, 94, 76, 126, 110, 111,
+ 124, 193, 194, 195, 196, 197, 198, 199, 200, 201, 209, 210, 211, 212, 213, 214,
+ 215, 216, 217, 226, 227, 228, 229, 230, 231, 232, 233, 74, 224, 90, 95, 109,
+ 121, 129, 130, 131, 132, 133, 134, 135, 136, 137, 145, 146, 147, 148, 149, 150,
+ 151, 152, 153, 162, 163, 164, 165, 166, 167, 168, 169, 192, 106, 208, 161, 7,
+ 32, 33, 34, 35, 36, 21, 6, 23, 40, 41, 42, 43, 44, 9, 10, 27,
+ 48, 49, 26, 51, 52, 53, 54, 8, 56, 57, 58, 59, 4, 20, 62, 225,
+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 98, 99, 100, 101, 102, 103, 104, 105, 112, 113, 114, 115, 116, 117,
+ 118, 119, 120, 128, 138, 139, 140, 141, 142, 143, 144, 154, 155, 156, 157, 158,
+ 159, 160, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183,
+ 184, 185, 186, 187, 188, 189, 190, 191, 202, 203, 204, 205, 206, 207, 218, 219,
+ 220, 221, 222, 223, 234, 235, 236, 237, 238, 239, 250, 251, 252, 253, 254, 255};
+
+
+static void iconv_e2a(unsigned char src[], unsigned char dst[], size_t length) {
+ size_t i;
+ for (i = 0; i < length; i++)
+ dst[i] = e2a[src[i]];
+}
+
+
+static void iconv_a2e(const char* src, unsigned char dst[], size_t length) {
+ size_t srclen;
+ size_t i;
+
+ srclen = strlen(src);
+ if (srclen > length)
+ abort();
+ for (i = 0; i < srclen; i++)
+ dst[i] = a2e[src[i]];
+ /* padding the remaining part with spaces */
+ for (; i < length; i++)
+ dst[i] = a2e[' '];
+}
+
+
static int get_ibmi_system_status(SSTS0200* rcvr) {
/* rcvrlen is input parameter 2 to QWCRSSTS */
unsigned int rcvrlen = sizeof(*rcvr);
+ unsigned char format[8], reset_status[10];
- /* format is input parameter 3 to QWCRSSTS ("SSTS0200" in EBCDIC) */
- unsigned char format[] = {0xE2, 0xE2, 0xE3, 0xE2, 0xF0, 0xF2, 0xF0, 0xF0};
-
- /* reset_status is input parameter 4 to QWCRSSTS ("*NO " in EBCDIC) */
- unsigned char reset_status[] = {
- 0x5C, 0xD5, 0xD6, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40
- };
+ /* format is input parameter 3 to QWCRSSTS */
+ iconv_a2e("SSTS0200", format, sizeof(format));
+ /* reset_status is input parameter 4 */
+ iconv_a2e("*NO", reset_status, sizeof(reset_status));
/* errcode is input parameter 5 to QWCRSSTS */
- struct _errcode {
- int bytes_provided;
- int bytes_available;
- char msgid[7];
- } errcode;
+ errcode_s errcode;
/* qwcrssts_pointer is the 16-byte tagged system pointer to QWCRSSTS */
ILEpointer __attribute__((aligned(16))) qwcrssts_pointer;
@@ -145,7 +213,7 @@ static int get_ibmi_system_status(SSTS0200* rcvr) {
qwcrssts_argv[5] = NULL;
/* Call the IBM i QWCRSSTS API from PASE */
- rc = _PGMCALL(&qwcrssts_pointer, (void**)&qwcrssts_argv, 0);
+ rc = _PGMCALL(&qwcrssts_pointer, qwcrssts_argv, 0);
return rc;
}
@@ -157,19 +225,7 @@ uint64_t uv_get_free_memory(void) {
if (get_ibmi_system_status(&rcvr))
return 0;
- /* The amount of main storage, in kilobytes, in the system. */
- uint64_t main_storage_size = rcvr.main_storage_size;
-
- /* The current amount of storage in use for temporary objects.
- * in millions (M) of bytes.
- */
- uint64_t current_unprotected_storage_used =
- rcvr.current_unprotected_storage_used * 1024ULL;
-
- uint64_t free_storage_size =
- (main_storage_size - current_unprotected_storage_used) * 1024ULL;
-
- return free_storage_size < 0 ? 0 : free_storage_size;
+ return (uint64_t)rcvr.main_storage_size * 1024ULL;
}
@@ -248,3 +304,159 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
return 0;
}
+
+static int get_ibmi_physical_address(const char* line, char (*phys_addr)[6]) {
+ LIND0500 rcvr;
+ /* rcvrlen is input parameter 2 to QDCRLIND */
+ unsigned int rcvrlen = sizeof(rcvr);
+ unsigned char format[8], line_name[10];
+ unsigned char mac_addr[sizeof(rcvr.loca_adapter_address)];
+ int c[6];
+
+ /* format is input parameter 3 to QDCRLIND */
+ iconv_a2e("LIND0500", format, sizeof(format));
+
+ /* line_name is input parameter 4 to QDCRLIND */
+ iconv_a2e(line, line_name, sizeof(line_name));
+
+ /* err is input parameter 5 to QDCRLIND */
+ errcode_s err;
+
+ /* qwcrssts_pointer is the 16-byte tagged system pointer to QDCRLIND */
+ ILEpointer __attribute__((aligned(16))) qdcrlind_pointer;
+
+ /* qwcrssts_argv is the array of argument pointers to QDCRLIND */
+ void* qdcrlind_argv[6];
+
+ /* Set the IBM i pointer to the QSYS/QDCRLIND *PGM object */
+ int rc = _RSLOBJ2(&qdcrlind_pointer, RSLOBJ_TS_PGM, "QDCRLIND", "QSYS");
+
+ if (rc != 0)
+ return rc;
+
+ /* initialize the QDCRLIND returned info structure */
+ memset(&rcvr, 0, sizeof(rcvr));
+
+ /* initialize the QDCRLIND error code structure */
+ memset(&err, 0, sizeof(err));
+ err.bytes_provided = sizeof(err);
+
+ /* initialize the array of argument pointers for the QDCRLIND API */
+ qdcrlind_argv[0] = &rcvr;
+ qdcrlind_argv[1] = &rcvrlen;
+ qdcrlind_argv[2] = &format;
+ qdcrlind_argv[3] = &line_name;
+ qdcrlind_argv[4] = &err;
+ qdcrlind_argv[5] = NULL;
+
+ /* Call the IBM i QDCRLIND API from PASE */
+ rc = _PGMCALL(&qdcrlind_pointer, qdcrlind_argv, 0);
+ if (rc != 0)
+ return rc;
+
+ /* convert ebcdic loca_adapter_address to ascii first */
+ iconv_e2a(rcvr.loca_adapter_address, mac_addr,
+ sizeof(rcvr.loca_adapter_address));
+
+ /* convert loca_adapter_address(char[12]) to phys_addr(char[6]) */
+ int r = sscanf(mac_addr, "%02x%02x%02x%02x%02x%02x",
+ &c[0], &c[1], &c[2], &c[3], &c[4], &c[5]);
+
+ if (r == ARRAY_SIZE(c)) {
+ (*phys_addr)[0] = c[0];
+ (*phys_addr)[1] = c[1];
+ (*phys_addr)[2] = c[2];
+ (*phys_addr)[3] = c[3];
+ (*phys_addr)[4] = c[4];
+ (*phys_addr)[5] = c[5];
+ } else {
+ memset(*phys_addr, 0, sizeof(*phys_addr));
+ rc = -1;
+ }
+ return rc;
+}
+
+
+int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
+ uv_interface_address_t* address;
+ struct ifaddrs_pase *ifap = NULL, *cur;
+ int inet6, r = 0;
+
+ *count = 0;
+ *addresses = NULL;
+
+ if (Qp2getifaddrs(&ifap))
+ return UV_ENOSYS;
+
+ /* The first loop to get the size of the array to be allocated */
+ for (cur = ifap; cur; cur = cur->ifa_next) {
+ if (!(cur->ifa_addr->sa_family == AF_INET6 ||
+ cur->ifa_addr->sa_family == AF_INET))
+ continue;
+
+ if (!(cur->ifa_flags & IFF_UP && cur->ifa_flags & IFF_RUNNING))
+ continue;
+
+ (*count)++;
+ }
+
+ if (*count == 0) {
+ Qp2freeifaddrs(ifap);
+ return 0;
+ }
+
+ /* Alloc the return interface structs */
+ *addresses = uv__calloc(*count, sizeof(**addresses));
+ if (*addresses == NULL) {
+ Qp2freeifaddrs(ifap);
+ return UV_ENOMEM;
+ }
+ address = *addresses;
+
+ /* The second loop to fill in the array */
+ for (cur = ifap; cur; cur = cur->ifa_next) {
+ if (!(cur->ifa_addr->sa_family == AF_INET6 ||
+ cur->ifa_addr->sa_family == AF_INET))
+ continue;
+
+ if (!(cur->ifa_flags & IFF_UP && cur->ifa_flags & IFF_RUNNING))
+ continue;
+
+ address->name = uv__strdup(cur->ifa_name);
+
+ inet6 = (cur->ifa_addr->sa_family == AF_INET6);
+
+ if (inet6) {
+ address->address.address6 = *((struct sockaddr_in6*)cur->ifa_addr);
+ address->netmask.netmask6 = *((struct sockaddr_in6*)cur->ifa_netmask);
+ address->netmask.netmask6.sin6_family = AF_INET6;
+ } else {
+ address->address.address4 = *((struct sockaddr_in*)cur->ifa_addr);
+ address->netmask.netmask4 = *((struct sockaddr_in*)cur->ifa_netmask);
+ address->netmask.netmask4.sin_family = AF_INET;
+ }
+ address->is_internal = cur->ifa_flags & IFF_LOOPBACK ? 1 : 0;
+ if (!address->is_internal) {
+ int rc = get_ibmi_physical_address(address->name, &address->phys_addr);
+ if (rc != 0)
+ r = rc;
+ }
+
+ address++;
+ }
+
+ Qp2freeifaddrs(ifap);
+ return r;
+}
+
+
+void uv_free_interface_addresses(uv_interface_address_t* addresses, int count) {
+ int i;
+
+ for (i = 0; i < count; ++i) {
+ uv__free(addresses[i].name);
+ }
+
+ uv__free(addresses);
+}
+
diff --git a/Utilities/cmlibuv/src/unix/internal.h b/Utilities/cmlibuv/src/unix/internal.h
index b43c0b1906..2276b78413 100644
--- a/Utilities/cmlibuv/src/unix/internal.h
+++ b/Utilities/cmlibuv/src/unix/internal.h
@@ -25,11 +25,13 @@
#include "uv-common.h"
#include <assert.h>
+#include <limits.h> /* _POSIX_PATH_MAX, PATH_MAX */
#include <stdlib.h> /* abort */
#include <string.h> /* strrchr */
-#include <fcntl.h> /* O_CLOEXEC, may be */
+#include <fcntl.h> /* O_CLOEXEC and O_NONBLOCK, if supported. */
#include <stdio.h>
#include <errno.h>
+#include <sys/socket.h>
#if defined(__STRICT_ANSI__)
# define inline __inline
@@ -60,6 +62,14 @@
# include <AvailabilityMacros.h>
#endif
+#if defined(_POSIX_PATH_MAX)
+# define UV__PATH_MAX _POSIX_PATH_MAX
+#elif defined(PATH_MAX)
+# define UV__PATH_MAX PATH_MAX
+#else
+# define UV__PATH_MAX 8192
+#endif
+
#if defined(CMAKE_BOOTSTRAP)
# undef pthread_atfork
# define pthread_atfork(prepare, parent, child) \
@@ -271,6 +281,12 @@ uv_handle_type uv__handle_type(int fd);
FILE* uv__open_file(const char* path);
int uv__getpwuid_r(uv_passwd_t* pwd);
+/* random */
+int uv__random_devurandom(void* buf, size_t buflen);
+int uv__random_getrandom(void* buf, size_t buflen);
+int uv__random_getentropy(void* buf, size_t buflen);
+int uv__random_readpath(const char* path, void* buf, size_t buflen);
+int uv__random_sysctl(void* buf, size_t buflen);
#if defined(__APPLE__) && !defined(CMAKE_BOOTSTRAP)
int uv___stream_fd(const uv_stream_t* handle);
@@ -279,13 +295,12 @@ int uv___stream_fd(const uv_stream_t* handle);
#define uv__stream_fd(handle) ((handle)->io_watcher.fd)
#endif /* defined(__APPLE__) */
-#ifdef UV__O_NONBLOCK
-# define UV__F_NONBLOCK UV__O_NONBLOCK
+#ifdef O_NONBLOCK
+# define UV__F_NONBLOCK O_NONBLOCK
#else
# define UV__F_NONBLOCK 1
#endif
-int uv__make_socketpair(int fds[2], int flags);
int uv__make_pipe(int fds[2], int flags);
#if defined(__APPLE__)
@@ -323,4 +338,27 @@ int uv__getsockpeername(const uv_handle_t* handle,
struct sockaddr* name,
int* namelen);
+#if defined(__linux__) || \
+ defined(__FreeBSD__) || \
+ defined(__FreeBSD_kernel__)
+#define HAVE_MMSG 1
+struct uv__mmsghdr {
+ struct msghdr msg_hdr;
+ unsigned int msg_len;
+};
+
+int uv__recvmmsg(int fd,
+ struct uv__mmsghdr* mmsg,
+ unsigned int vlen,
+ unsigned int flags,
+ struct timespec* timeout);
+int uv__sendmmsg(int fd,
+ struct uv__mmsghdr* mmsg,
+ unsigned int vlen,
+ unsigned int flags);
+#else
+#define HAVE_MMSG 0
+#endif
+
+
#endif /* UV_UNIX_INTERNAL_H_ */
diff --git a/Utilities/cmlibuv/src/unix/kqueue.c b/Utilities/cmlibuv/src/unix/kqueue.c
index c04e7a485c..ad09f40313 100644
--- a/Utilities/cmlibuv/src/unix/kqueue.c
+++ b/Utilities/cmlibuv/src/unix/kqueue.c
@@ -454,10 +454,26 @@ int uv_fs_event_start(uv_fs_event_t* handle,
const char* path,
unsigned int flags) {
int fd;
+#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
+ struct stat statbuf;
+#endif
if (uv__is_active(handle))
return UV_EINVAL;
+ handle->cb = cb;
+ handle->path = uv__strdup(path);
+ if (handle->path == NULL)
+ return UV_ENOMEM;
+
+ /* TODO open asynchronously - but how do we report back errors? */
+ fd = open(handle->path, O_RDONLY);
+ if (fd == -1) {
+ uv__free(handle->path);
+ handle->path = NULL;
+ return UV__ERR(errno);
+ }
+
#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
/* Nullify field to perform checks later */
handle->cf_cb = NULL;
@@ -465,14 +481,17 @@ int uv_fs_event_start(uv_fs_event_t* handle,
handle->realpath_len = 0;
handle->cf_flags = flags;
+ if (fstat(fd, &statbuf))
+ goto fallback;
+ /* FSEvents works only with directories */
+ if (!(statbuf.st_mode & S_IFDIR))
+ goto fallback;
+
if (!uv__has_forked_with_cfrunloop) {
int r;
- /* The fallback fd is not used */
+ /* The fallback fd is no longer needed */
+ uv__close_nocheckstdio(fd);
handle->event_watcher.fd = -1;
- handle->path = uv__strdup(path);
- if (handle->path == NULL)
- return UV_ENOMEM;
- handle->cb = cb;
r = uv__fsevents_init(handle);
if (r == 0) {
uv__handle_start(handle);
@@ -482,20 +501,9 @@ int uv_fs_event_start(uv_fs_event_t* handle,
}
return r;
}
+fallback:
#endif /* #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
- /* TODO open asynchronously - but how do we report back errors? */
- fd = open(path, O_RDONLY);
- if (fd == -1)
- return UV__ERR(errno);
-
- handle->path = uv__strdup(path);
- if (handle->path == NULL) {
- uv__close_nocheckstdio(fd);
- return UV_ENOMEM;
- }
-
- handle->cb = cb;
uv__handle_start(handle);
uv__io_init(&handle->event_watcher, uv__fs_event, fd);
uv__io_start(handle->loop, &handle->event_watcher, POLLIN);
@@ -514,7 +522,7 @@ int uv_fs_event_stop(uv_fs_event_t* handle) {
uv__handle_stop(handle);
#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
- if (!uv__has_forked_with_cfrunloop)
+ if (!uv__has_forked_with_cfrunloop && handle->cf_cb != NULL)
r = uv__fsevents_close(handle);
#endif
diff --git a/Utilities/cmlibuv/src/unix/linux-core.c b/Utilities/cmlibuv/src/unix/linux-core.c
index b539beb86a..f8d9ff5868 100644
--- a/Utilities/cmlibuv/src/unix/linux-core.c
+++ b/Utilities/cmlibuv/src/unix/linux-core.c
@@ -90,7 +90,12 @@ int uv__platform_loop_init(uv_loop_t* loop) {
* a.k.a. Lollipop. Since EPOLL_CLOEXEC is an alias for O_CLOEXEC on all
* architectures, we just use that instead.
*/
+#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
+ fd = -1;
+ errno = ENOSYS;
+#else
fd = epoll_create1(O_CLOEXEC);
+#endif
/* epoll_create1() can fail either because it's not implemented (old kernel)
* or because it doesn't understand the O_CLOEXEC flag.
@@ -203,6 +208,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
* that being the largest value I have seen in the wild (and only once.)
*/
static const int max_safe_timeout = 1789569;
+ static int no_epoll_pwait;
+ static int no_epoll_wait;
struct epoll_event events[1024];
struct epoll_event* pe;
struct epoll_event e;
@@ -210,7 +217,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
QUEUE* q;
uv__io_t* w;
sigset_t sigset;
- sigset_t* psigset;
+ uint64_t sigmask;
uint64_t base;
int have_signals;
int nevents;
@@ -262,11 +269,11 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
w->events = w->pevents;
}
- psigset = NULL;
+ sigmask = 0;
if (loop->flags & UV_LOOP_BLOCK_SIGPROF) {
sigemptyset(&sigset);
sigaddset(&sigset, SIGPROF);
- psigset = &sigset;
+ sigmask |= 1 << (SIGPROF - 1);
}
assert(timeout >= -1);
@@ -281,11 +288,35 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout)
timeout = max_safe_timeout;
- nfds = epoll_pwait(loop->backend_fd,
- events,
- ARRAY_SIZE(events),
- timeout,
- psigset);
+ if (sigmask != 0 && no_epoll_pwait != 0)
+ if (pthread_sigmask(SIG_BLOCK, &sigset, NULL))
+ abort();
+
+ if (no_epoll_wait != 0 || (sigmask != 0 && no_epoll_pwait == 0)) {
+#if defined(__ANDROID_API__) && __ANDROID_API__ < 21
+ nfds = -1;
+ errno = ENOSYS;
+#else
+ nfds = epoll_pwait(loop->backend_fd,
+ events,
+ ARRAY_SIZE(events),
+ timeout,
+ &sigset);
+#endif
+ if (nfds == -1 && errno == ENOSYS)
+ no_epoll_pwait = 1;
+ } else {
+ nfds = epoll_wait(loop->backend_fd,
+ events,
+ ARRAY_SIZE(events),
+ timeout);
+ if (nfds == -1 && errno == ENOSYS)
+ no_epoll_wait = 1;
+ }
+
+ if (sigmask != 0 && no_epoll_pwait != 0)
+ if (pthread_sigmask(SIG_UNBLOCK, &sigset, NULL))
+ abort();
/* Update loop->time unconditionally. It's tempting to skip the update when
* timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the
@@ -306,6 +337,12 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
}
if (nfds == -1) {
+ if (errno == ENOSYS) {
+ /* epoll_wait() or epoll_pwait() failed, try the other system call. */
+ assert(no_epoll_wait == 0 || no_epoll_pwait == 0);
+ continue;
+ }
+
if (errno != EINTR)
abort();
@@ -322,9 +359,19 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
have_signals = 0;
nevents = 0;
- assert(loop->watchers != NULL);
- loop->watchers[loop->nwatchers] = (void*) events;
- loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds;
+ {
+ /* Squelch a -Waddress-of-packed-member warning with gcc >= 9. */
+ union {
+ struct epoll_event* events;
+ uv__io_t* watchers;
+ } x;
+
+ x.events = events;
+ assert(loop->watchers != NULL);
+ loop->watchers[loop->nwatchers] = x.watchers;
+ loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds;
+ }
+
for (i = 0; i < nfds; i++) {
pe = events + i;
fd = pe->data.fd;
@@ -812,16 +859,6 @@ static uint64_t read_cpufreq(unsigned int cpunum) {
}
-void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
- int i;
-
- for (i = 0; i < count; i++) {
- uv__free(cpu_infos[i].model);
- }
-
- uv__free(cpu_infos);
-}
-
static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)))
return 1;
@@ -953,7 +990,7 @@ static uint64_t uv__read_proc_meminfo(const char* what) {
rc = 0;
fd = uv__open_cloexec("/proc/meminfo", O_RDONLY);
- if (fd == -1)
+ if (fd < 0)
return 0;
n = read(fd, buf, sizeof(buf) - 1);
diff --git a/Utilities/cmlibuv/src/unix/linux-inotify.c b/Utilities/cmlibuv/src/unix/linux-inotify.c
index 9b26202fb3..42b601adbf 100644
--- a/Utilities/cmlibuv/src/unix/linux-inotify.c
+++ b/Utilities/cmlibuv/src/unix/linux-inotify.c
@@ -29,6 +29,7 @@
#include <assert.h>
#include <errno.h>
+#include <sys/inotify.h>
#include <sys/types.h>
#include <unistd.h>
@@ -64,45 +65,17 @@ static void uv__inotify_read(uv_loop_t* loop,
static void maybe_free_watcher_list(struct watcher_list* w,
uv_loop_t* loop);
-static int new_inotify_fd(void) {
- int err;
- int fd;
-
- fd = uv__inotify_init1(UV__IN_NONBLOCK | UV__IN_CLOEXEC);
- if (fd != -1)
- return fd;
-
- if (errno != ENOSYS)
- return UV__ERR(errno);
-
- fd = uv__inotify_init();
- if (fd == -1)
- return UV__ERR(errno);
-
- err = uv__cloexec(fd, 1);
- if (err == 0)
- err = uv__nonblock(fd, 1);
-
- if (err) {
- uv__close(fd);
- return err;
- }
-
- return fd;
-}
-
-
static int init_inotify(uv_loop_t* loop) {
- int err;
+ int fd;
if (loop->inotify_fd != -1)
return 0;
- err = new_inotify_fd();
- if (err < 0)
- return err;
+ fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
+ if (fd < 0)
+ return UV__ERR(errno);
- loop->inotify_fd = err;
+ loop->inotify_fd = fd;
uv__io_init(&loop->inotify_read_watcher, uv__inotify_read, loop->inotify_fd);
uv__io_start(loop, &loop->inotify_read_watcher, POLLIN);
@@ -186,7 +159,7 @@ static void maybe_free_watcher_list(struct watcher_list* w, uv_loop_t* loop) {
if ((!w->iterating) && QUEUE_EMPTY(&w->watchers)) {
/* No watchers left for this path. Clean up. */
RB_REMOVE(watcher_root, CAST(&loop->inotify_watchers), w);
- uv__inotify_rm_watch(loop->inotify_fd, w->wd);
+ inotify_rm_watch(loop->inotify_fd, w->wd);
uv__free(w);
}
}
@@ -194,7 +167,7 @@ static void maybe_free_watcher_list(struct watcher_list* w, uv_loop_t* loop) {
static void uv__inotify_read(uv_loop_t* loop,
uv__io_t* dummy,
unsigned int events) {
- const struct uv__inotify_event* e;
+ const struct inotify_event* e;
struct watcher_list* w;
uv_fs_event_t* h;
QUEUE queue;
@@ -219,12 +192,12 @@ static void uv__inotify_read(uv_loop_t* loop,
/* Now we have one or more inotify_event structs. */
for (p = buf; p < buf + size; p += sizeof(*e) + e->len) {
- e = (const struct uv__inotify_event*)p;
+ e = (const struct inotify_event*) p;
events = 0;
- if (e->mask & (UV__IN_ATTRIB|UV__IN_MODIFY))
+ if (e->mask & (IN_ATTRIB|IN_MODIFY))
events |= UV_CHANGE;
- if (e->mask & ~(UV__IN_ATTRIB|UV__IN_MODIFY))
+ if (e->mask & ~(IN_ATTRIB|IN_MODIFY))
events |= UV_RENAME;
w = find_watcher(loop, e->wd);
@@ -290,16 +263,16 @@ int uv_fs_event_start(uv_fs_event_t* handle,
if (err)
return err;
- events = UV__IN_ATTRIB
- | UV__IN_CREATE
- | UV__IN_MODIFY
- | UV__IN_DELETE
- | UV__IN_DELETE_SELF
- | UV__IN_MOVE_SELF
- | UV__IN_MOVED_FROM
- | UV__IN_MOVED_TO;
+ events = IN_ATTRIB
+ | IN_CREATE
+ | IN_MODIFY
+ | IN_DELETE
+ | IN_DELETE_SELF
+ | IN_MOVE_SELF
+ | IN_MOVED_FROM
+ | IN_MOVED_TO;
- wd = uv__inotify_add_watch(handle->loop->inotify_fd, path, events);
+ wd = inotify_add_watch(handle->loop->inotify_fd, path, events);
if (wd == -1)
return UV__ERR(errno);
diff --git a/Utilities/cmlibuv/src/unix/linux-syscalls.c b/Utilities/cmlibuv/src/unix/linux-syscalls.c
index 5637cf98a7..742f26ada8 100644
--- a/Utilities/cmlibuv/src/unix/linux-syscalls.c
+++ b/Utilities/cmlibuv/src/unix/linux-syscalls.c
@@ -26,19 +26,6 @@
#include <sys/types.h>
#include <errno.h>
-#if defined(__has_feature)
-# if __has_feature(memory_sanitizer)
-# define MSAN_ACTIVE 1
-# include <sanitizer/msan_interface.h>
-# endif
-#endif
-
-#if defined(__i386__)
-# ifndef __NR_socketcall
-# define __NR_socketcall 102
-# endif
-#endif
-
#if defined(__arm__)
# if defined(__thumb__) || defined(__ARM_EABI__)
# define UV_SYSCALL_BASE 0
@@ -47,86 +34,6 @@
# endif
#endif /* __arm__ */
-#ifndef __NR_accept4
-# if defined(__x86_64__)
-# define __NR_accept4 288
-# elif defined(__i386__)
- /* Nothing. Handled through socketcall(). */
-# elif defined(__arm__)
-# define __NR_accept4 (UV_SYSCALL_BASE + 366)
-# endif
-#endif /* __NR_accept4 */
-
-#ifndef __NR_eventfd
-# if defined(__x86_64__)
-# define __NR_eventfd 284
-# elif defined(__i386__)
-# define __NR_eventfd 323
-# elif defined(__arm__)
-# define __NR_eventfd (UV_SYSCALL_BASE + 351)
-# endif
-#endif /* __NR_eventfd */
-
-#ifndef __NR_eventfd2
-# if defined(__x86_64__)
-# define __NR_eventfd2 290
-# elif defined(__i386__)
-# define __NR_eventfd2 328
-# elif defined(__arm__)
-# define __NR_eventfd2 (UV_SYSCALL_BASE + 356)
-# endif
-#endif /* __NR_eventfd2 */
-
-#ifndef __NR_inotify_init
-# if defined(__x86_64__)
-# define __NR_inotify_init 253
-# elif defined(__i386__)
-# define __NR_inotify_init 291
-# elif defined(__arm__)
-# define __NR_inotify_init (UV_SYSCALL_BASE + 316)
-# endif
-#endif /* __NR_inotify_init */
-
-#ifndef __NR_inotify_init1
-# if defined(__x86_64__)
-# define __NR_inotify_init1 294
-# elif defined(__i386__)
-# define __NR_inotify_init1 332
-# elif defined(__arm__)
-# define __NR_inotify_init1 (UV_SYSCALL_BASE + 360)
-# endif
-#endif /* __NR_inotify_init1 */
-
-#ifndef __NR_inotify_add_watch
-# if defined(__x86_64__)
-# define __NR_inotify_add_watch 254
-# elif defined(__i386__)
-# define __NR_inotify_add_watch 292
-# elif defined(__arm__)
-# define __NR_inotify_add_watch (UV_SYSCALL_BASE + 317)
-# endif
-#endif /* __NR_inotify_add_watch */
-
-#ifndef __NR_inotify_rm_watch
-# if defined(__x86_64__)
-# define __NR_inotify_rm_watch 255
-# elif defined(__i386__)
-# define __NR_inotify_rm_watch 293
-# elif defined(__arm__)
-# define __NR_inotify_rm_watch (UV_SYSCALL_BASE + 318)
-# endif
-#endif /* __NR_inotify_rm_watch */
-
-#ifndef __NR_pipe2
-# if defined(__x86_64__)
-# define __NR_pipe2 293
-# elif defined(__i386__)
-# define __NR_pipe2 331
-# elif defined(__arm__)
-# define __NR_pipe2 (UV_SYSCALL_BASE + 359)
-# endif
-#endif /* __NR_pipe2 */
-
#ifndef __NR_recvmmsg
# if defined(__x86_64__)
# define __NR_recvmmsg 299
@@ -203,103 +110,23 @@
# endif
#endif /* __NR_statx */
-int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags) {
-#if defined(__i386__)
- unsigned long args[4];
- int r;
-
- args[0] = (unsigned long) fd;
- args[1] = (unsigned long) addr;
- args[2] = (unsigned long) addrlen;
- args[3] = (unsigned long) flags;
-
- r = syscall(__NR_socketcall, 18 /* SYS_ACCEPT4 */, args);
-
- /* socketcall() raises EINVAL when SYS_ACCEPT4 is not supported but so does
- * a bad flags argument. Try to distinguish between the two cases.
- */
- if (r == -1)
- if (errno == EINVAL)
- if ((flags & ~(UV__SOCK_CLOEXEC|UV__SOCK_NONBLOCK)) == 0)
- errno = ENOSYS;
-
- return r;
-#elif defined(__NR_accept4)
- return syscall(__NR_accept4, fd, addr, addrlen, flags);
-#else
- return errno = ENOSYS, -1;
-#endif
-}
-
-
-int uv__eventfd(unsigned int count) {
-#if defined(__NR_eventfd)
- return syscall(__NR_eventfd, count);
-#else
- return errno = ENOSYS, -1;
-#endif
-}
-
-
-int uv__eventfd2(unsigned int count, int flags) {
-#if defined(__NR_eventfd2)
- return syscall(__NR_eventfd2, count, flags);
-#else
- return errno = ENOSYS, -1;
-#endif
-}
-
-
-int uv__inotify_init(void) {
-#if defined(__NR_inotify_init)
- return syscall(__NR_inotify_init);
-#else
- return errno = ENOSYS, -1;
-#endif
-}
-
-
-int uv__inotify_init1(int flags) {
-#if defined(__NR_inotify_init1)
- return syscall(__NR_inotify_init1, flags);
-#else
- return errno = ENOSYS, -1;
-#endif
-}
-
-
-int uv__inotify_add_watch(int fd, const char* path, uint32_t mask) {
-#if defined(__NR_inotify_add_watch)
- return syscall(__NR_inotify_add_watch, fd, path, mask);
-#else
- return errno = ENOSYS, -1;
-#endif
-}
-
-
-int uv__inotify_rm_watch(int fd, int32_t wd) {
-#if defined(__NR_inotify_rm_watch)
- return syscall(__NR_inotify_rm_watch, fd, wd);
-#else
- return errno = ENOSYS, -1;
-#endif
-}
-
-
-int uv__pipe2(int pipefd[2], int flags) {
-#if defined(__NR_pipe2)
- int result;
- result = syscall(__NR_pipe2, pipefd, flags);
-#if MSAN_ACTIVE
- if (!result)
- __msan_unpoison(pipefd, sizeof(int[2]));
-#endif
- return result;
-#else
- return errno = ENOSYS, -1;
-#endif
-}
+#ifndef __NR_getrandom
+# if defined(__x86_64__)
+# define __NR_getrandom 318
+# elif defined(__i386__)
+# define __NR_getrandom 355
+# elif defined(__aarch64__)
+# define __NR_getrandom 384
+# elif defined(__arm__)
+# define __NR_getrandom (UV_SYSCALL_BASE + 384)
+# elif defined(__ppc__)
+# define __NR_getrandom 359
+# elif defined(__s390__)
+# define __NR_getrandom 349
+# endif
+#endif /* __NR_getrandom */
+struct uv__mmsghdr;
int uv__sendmmsg(int fd,
struct uv__mmsghdr* mmsg,
@@ -367,3 +194,12 @@ int uv__statx(int dirfd,
return errno = ENOSYS, -1;
#endif
}
+
+
+ssize_t uv__getrandom(void* buf, size_t buflen, unsigned flags) {
+#if defined(__NR_getrandom)
+ return syscall(__NR_getrandom, buf, buflen, flags);
+#else
+ return errno = ENOSYS, -1;
+#endif
+}
diff --git a/Utilities/cmlibuv/src/unix/linux-syscalls.h b/Utilities/cmlibuv/src/unix/linux-syscalls.h
index 7e58bfa218..2e8fa2a519 100644
--- a/Utilities/cmlibuv/src/unix/linux-syscalls.h
+++ b/Utilities/cmlibuv/src/unix/linux-syscalls.h
@@ -31,55 +31,6 @@
#include <sys/time.h>
#include <sys/socket.h>
-#if defined(__alpha__)
-# define UV__O_CLOEXEC 0x200000
-#elif defined(__hppa__)
-# define UV__O_CLOEXEC 0x200000
-#elif defined(__sparc__)
-# define UV__O_CLOEXEC 0x400000
-#else
-# define UV__O_CLOEXEC 0x80000
-#endif
-
-#if defined(__alpha__)
-# define UV__O_NONBLOCK 0x4
-#elif defined(__hppa__)
-# define UV__O_NONBLOCK O_NONBLOCK
-#elif defined(__mips__)
-# define UV__O_NONBLOCK 0x80
-#elif defined(__sparc__)
-# define UV__O_NONBLOCK 0x4000
-#else
-# define UV__O_NONBLOCK 0x800
-#endif
-
-#define UV__EFD_CLOEXEC UV__O_CLOEXEC
-#define UV__EFD_NONBLOCK UV__O_NONBLOCK
-
-#define UV__IN_CLOEXEC UV__O_CLOEXEC
-#define UV__IN_NONBLOCK UV__O_NONBLOCK
-
-#define UV__SOCK_CLOEXEC UV__O_CLOEXEC
-#if defined(SOCK_NONBLOCK)
-# define UV__SOCK_NONBLOCK SOCK_NONBLOCK
-#else
-# define UV__SOCK_NONBLOCK UV__O_NONBLOCK
-#endif
-
-/* inotify flags */
-#define UV__IN_ACCESS 0x001
-#define UV__IN_MODIFY 0x002
-#define UV__IN_ATTRIB 0x004
-#define UV__IN_CLOSE_WRITE 0x008
-#define UV__IN_CLOSE_NOWRITE 0x010
-#define UV__IN_OPEN 0x020
-#define UV__IN_MOVED_FROM 0x040
-#define UV__IN_MOVED_TO 0x080
-#define UV__IN_CREATE 0x100
-#define UV__IN_DELETE 0x200
-#define UV__IN_DELETE_SELF 0x400
-#define UV__IN_MOVE_SELF 0x800
-
struct uv__statx_timestamp {
int64_t tv_sec;
uint32_t tv_nsec;
@@ -110,36 +61,6 @@ struct uv__statx {
uint64_t unused1[14];
};
-struct uv__inotify_event {
- int32_t wd;
- uint32_t mask;
- uint32_t cookie;
- uint32_t len;
- /* char name[0]; */
-};
-
-struct uv__mmsghdr {
- struct msghdr msg_hdr;
- unsigned int msg_len;
-};
-
-int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags);
-int uv__eventfd(unsigned int count);
-int uv__eventfd2(unsigned int count, int flags);
-int uv__inotify_init(void);
-int uv__inotify_init1(int flags);
-int uv__inotify_add_watch(int fd, const char* path, uint32_t mask);
-int uv__inotify_rm_watch(int fd, int32_t wd);
-int uv__pipe2(int pipefd[2], int flags);
-int uv__recvmmsg(int fd,
- struct uv__mmsghdr* mmsg,
- unsigned int vlen,
- unsigned int flags,
- struct timespec* timeout);
-int uv__sendmmsg(int fd,
- struct uv__mmsghdr* mmsg,
- unsigned int vlen,
- unsigned int flags);
ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, int64_t offset);
ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, int64_t offset);
int uv__dup3(int oldfd, int newfd, int flags);
@@ -148,5 +69,6 @@ int uv__statx(int dirfd,
int flags,
unsigned int mask,
struct uv__statx* statxbuf);
+ssize_t uv__getrandom(void* buf, size_t buflen, unsigned flags);
#endif /* UV_LINUX_SYSCALL_H_ */
diff --git a/Utilities/cmlibuv/src/unix/netbsd.c b/Utilities/cmlibuv/src/unix/netbsd.c
index c649bb375f..c66333f522 100644
--- a/Utilities/cmlibuv/src/unix/netbsd.c
+++ b/Utilities/cmlibuv/src/unix/netbsd.c
@@ -55,7 +55,7 @@ void uv_loadavg(double avg[3]) {
size_t size = sizeof(info);
int which[] = {CTL_VM, VM_LOADAVG};
- if (sysctl(which, 2, &info, &size, NULL, 0) == -1) return;
+ if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0) == -1) return;
avg[0] = (double) info.ldavg[0] / info.fscale;
avg[1] = (double) info.ldavg[1] / info.fscale;
@@ -102,7 +102,7 @@ uint64_t uv_get_free_memory(void) {
size_t size = sizeof(info);
int which[] = {CTL_VM, VM_UVMEXP};
- if (sysctl(which, 2, &info, &size, NULL, 0))
+ if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0))
return UV__ERR(errno);
return (uint64_t) info.free * sysconf(_SC_PAGESIZE);
@@ -119,7 +119,7 @@ uint64_t uv_get_total_memory(void) {
#endif
size_t size = sizeof(info);
- if (sysctl(which, 2, &info, &size, NULL, 0))
+ if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0))
return UV__ERR(errno);
return (uint64_t) info;
@@ -167,7 +167,7 @@ int uv_uptime(double* uptime) {
size_t size = sizeof(info);
static int which[] = {CTL_KERN, KERN_BOOTTIME};
- if (sysctl(which, 2, &info, &size, NULL, 0))
+ if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0))
return UV__ERR(errno);
now = time(NULL);
@@ -235,13 +235,25 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
return 0;
}
+int uv__random_sysctl(void* buf, size_t len) {
+ static int name[] = {CTL_KERN, KERN_ARND};
+ size_t count, req;
+ unsigned char* p;
-void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
- int i;
+ p = buf;
+ while (len) {
+ req = len < 32 ? len : 32;
+ count = req;
+
+ if (sysctl(name, ARRAY_SIZE(name), p, &count, NULL, 0) == -1)
+ return UV__ERR(errno);
- for (i = 0; i < count; i++) {
- uv__free(cpu_infos[i].model);
+ if (count != req)
+ return UV_EIO; /* Can't happen. */
+
+ p += count;
+ len -= count;
}
- uv__free(cpu_infos);
+ return 0;
}
diff --git a/Utilities/cmlibuv/src/unix/openbsd.c b/Utilities/cmlibuv/src/unix/openbsd.c
index ffae7683d8..f32a94df38 100644
--- a/Utilities/cmlibuv/src/unix/openbsd.c
+++ b/Utilities/cmlibuv/src/unix/openbsd.c
@@ -50,7 +50,7 @@ void uv_loadavg(double avg[3]) {
size_t size = sizeof(info);
int which[] = {CTL_VM, VM_LOADAVG};
- if (sysctl(which, 2, &info, &size, NULL, 0) < 0) return;
+ if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0) < 0) return;
avg[0] = (double) info.ldavg[0] / info.fscale;
avg[1] = (double) info.ldavg[1] / info.fscale;
@@ -61,7 +61,6 @@ void uv_loadavg(double avg[3]) {
int uv_exepath(char* buffer, size_t* size) {
int mib[4];
char **argsbuf = NULL;
- char **argsbuf_tmp;
size_t argsbuf_size = 100U;
size_t exepath_size;
pid_t mypid;
@@ -73,15 +72,14 @@ int uv_exepath(char* buffer, size_t* size) {
mypid = getpid();
for (;;) {
err = UV_ENOMEM;
- argsbuf_tmp = uv__realloc(argsbuf, argsbuf_size);
- if (argsbuf_tmp == NULL)
+ argsbuf = uv__reallocf(argsbuf, argsbuf_size);
+ if (argsbuf == NULL)
goto out;
- argsbuf = argsbuf_tmp;
mib[0] = CTL_KERN;
mib[1] = KERN_PROC_ARGS;
mib[2] = mypid;
mib[3] = KERN_PROC_ARGV;
- if (sysctl(mib, 4, argsbuf, &argsbuf_size, NULL, 0) == 0) {
+ if (sysctl(mib, ARRAY_SIZE(mib), argsbuf, &argsbuf_size, NULL, 0) == 0) {
break;
}
if (errno != ENOMEM) {
@@ -117,7 +115,7 @@ uint64_t uv_get_free_memory(void) {
size_t size = sizeof(info);
int which[] = {CTL_VM, VM_UVMEXP};
- if (sysctl(which, 2, &info, &size, NULL, 0))
+ if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0))
return UV__ERR(errno);
return (uint64_t) info.free * sysconf(_SC_PAGESIZE);
@@ -129,7 +127,7 @@ uint64_t uv_get_total_memory(void) {
int which[] = {CTL_HW, HW_PHYSMEM64};
size_t size = sizeof(info);
- if (sysctl(which, 2, &info, &size, NULL, 0))
+ if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0))
return UV__ERR(errno);
return (uint64_t) info;
@@ -154,7 +152,7 @@ int uv_resident_set_memory(size_t* rss) {
mib[4] = sizeof(struct kinfo_proc);
mib[5] = 1;
- if (sysctl(mib, 6, &kinfo, &size, NULL, 0) < 0)
+ if (sysctl(mib, ARRAY_SIZE(mib), &kinfo, &size, NULL, 0) < 0)
return UV__ERR(errno);
*rss = kinfo.p_vm_rssize * page_size;
@@ -168,7 +166,7 @@ int uv_uptime(double* uptime) {
size_t size = sizeof(info);
static int which[] = {CTL_KERN, KERN_BOOTTIME};
- if (sysctl(which, 2, &info, &size, NULL, 0))
+ if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0))
return UV__ERR(errno);
now = time(NULL);
@@ -184,43 +182,38 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
uint64_t info[CPUSTATES];
char model[512];
int numcpus = 1;
- int which[] = {CTL_HW,HW_MODEL,0};
+ int which[] = {CTL_HW,HW_MODEL};
+ int percpu[] = {CTL_KERN,KERN_CPTIME2,0};
size_t size;
- int i;
+ int i, j;
uv_cpu_info_t* cpu_info;
size = sizeof(model);
- if (sysctl(which, 2, &model, &size, NULL, 0))
+ if (sysctl(which, ARRAY_SIZE(which), &model, &size, NULL, 0))
return UV__ERR(errno);
- which[1] = HW_NCPU;
+ which[1] = HW_NCPUONLINE;
size = sizeof(numcpus);
- if (sysctl(which, 2, &numcpus, &size, NULL, 0))
+ if (sysctl(which, ARRAY_SIZE(which), &numcpus, &size, NULL, 0))
return UV__ERR(errno);
*cpu_infos = uv__malloc(numcpus * sizeof(**cpu_infos));
if (!(*cpu_infos))
return UV_ENOMEM;
+ i = 0;
*count = numcpus;
which[1] = HW_CPUSPEED;
size = sizeof(cpuspeed);
- if (sysctl(which, 2, &cpuspeed, &size, NULL, 0)) {
- uv__free(*cpu_infos);
- return UV__ERR(errno);
- }
+ if (sysctl(which, ARRAY_SIZE(which), &cpuspeed, &size, NULL, 0))
+ goto error;
size = sizeof(info);
- which[0] = CTL_KERN;
- which[1] = KERN_CPTIME2;
for (i = 0; i < numcpus; i++) {
- which[2] = i;
- size = sizeof(info);
- if (sysctl(which, 3, &info, &size, NULL, 0)) {
- uv__free(*cpu_infos);
- return UV__ERR(errno);
- }
+ percpu[2] = i;
+ if (sysctl(percpu, ARRAY_SIZE(percpu), &info, &size, NULL, 0))
+ goto error;
cpu_info = &(*cpu_infos)[i];
@@ -235,15 +228,13 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
}
return 0;
-}
+error:
+ *count = 0;
+ for (j = 0; j < i; j++)
+ uv__free((*cpu_infos)[j].model);
-void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
- int i;
-
- for (i = 0; i < count; i++) {
- uv__free(cpu_infos[i].model);
- }
-
- uv__free(cpu_infos);
+ uv__free(*cpu_infos);
+ *cpu_infos = NULL;
+ return UV__ERR(errno);
}
diff --git a/Utilities/cmlibuv/src/unix/os390-syscalls.c b/Utilities/cmlibuv/src/unix/os390-syscalls.c
index 1040d66979..424cc486a8 100644
--- a/Utilities/cmlibuv/src/unix/os390-syscalls.c
+++ b/Utilities/cmlibuv/src/unix/os390-syscalls.c
@@ -23,11 +23,11 @@
#include "os390-syscalls.h"
#include <errno.h>
#include <stdlib.h>
-#include <assert.h>
#include <search.h>
#include <termios.h>
#include <sys/msg.h>
+#define CW_INTRPT 1
#define CW_CONDVAR 32
#pragma linkage(BPX4CTW, OS)
@@ -43,6 +43,7 @@ int scandir(const char* maindir, struct dirent*** namelist,
int (*compar)(const struct dirent**,
const struct dirent **)) {
struct dirent** nl;
+ struct dirent** nl_copy;
struct dirent* dirent;
unsigned count;
size_t allocated;
@@ -62,19 +63,17 @@ int scandir(const char* maindir, struct dirent*** namelist,
if (!filter || filter(dirent)) {
struct dirent* copy;
copy = uv__malloc(sizeof(*copy));
- if (!copy) {
- while (count) {
- dirent = nl[--count];
- uv__free(dirent);
- }
- uv__free(nl);
- closedir(mdir);
- errno = ENOMEM;
- return -1;
- }
+ if (!copy)
+ goto error;
memcpy(copy, dirent, sizeof(*copy));
- nl = uv__realloc(nl, sizeof(*copy) * (count + 1));
+ nl_copy = uv__realloc(nl, sizeof(*copy) * (count + 1));
+ if (nl_copy == NULL) {
+ uv__free(copy);
+ goto error;
+ }
+
+ nl = nl_copy;
nl[count++] = copy;
}
}
@@ -86,6 +85,16 @@ int scandir(const char* maindir, struct dirent*** namelist,
*namelist = nl;
return count;
+
+error:
+ while (count > 0) {
+ dirent = nl[--count];
+ uv__free(dirent);
+ }
+ uv__free(nl);
+ closedir(mdir);
+ errno = ENOMEM;
+ return -1;
}
@@ -119,7 +128,7 @@ static void maybe_resize(uv__os390_epoll* lst, unsigned int len) {
}
newsize = next_power_of_two(len);
- newlst = uv__realloc(lst->items, newsize * sizeof(lst->items[0]));
+ newlst = uv__reallocf(lst->items, newsize * sizeof(lst->items[0]));
if (newlst == NULL)
abort();
@@ -269,6 +278,8 @@ int epoll_ctl(uv__os390_epoll* lst,
return 0;
}
+#define EP_MAX_PFDS (ULONG_MAX / sizeof(struct pollfd))
+#define EP_MAX_EVENTS (INT_MAX / sizeof(struct epoll_event))
int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events,
int maxevents, int timeout) {
@@ -277,18 +288,41 @@ int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events,
int pollret;
int reventcount;
int nevents;
+ struct pollfd msg_fd;
+ int i;
- _SET_FDS_MSGS(size, 1, lst->size - 1);
+ if (!lst || !lst->items || !events) {
+ errno = EFAULT;
+ return -1;
+ }
+
+ if (lst->size > EP_MAX_PFDS) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (maxevents <= 0 || maxevents > EP_MAX_EVENTS) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (lst->size > 0)
+ _SET_FDS_MSGS(size, 1, lst->size - 1);
+ else
+ _SET_FDS_MSGS(size, 0, 0);
pfds = lst->items;
pollret = poll(pfds, size, timeout);
if (pollret <= 0)
return pollret;
+ assert(lst->size > 0);
+
pollret = _NFDS(pollret) + _NMSGS(pollret);
reventcount = 0;
nevents = 0;
- for (int i = 0;
+ msg_fd = pfds[lst->size - 1];
+ for (i = 0;
i < lst->size && i < maxevents && reventcount < pollret; ++i) {
struct epoll_event ev;
struct pollfd* pfd;
@@ -299,6 +333,7 @@ int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events,
ev.fd = pfd->fd;
ev.events = pfd->revents;
+ ev.is_msg = 0;
if (pfd->revents & POLLIN && pfd->revents & POLLOUT)
reventcount += 2;
else if (pfd->revents & (POLLIN | POLLOUT))
@@ -308,6 +343,10 @@ int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events,
events[nevents++] = ev;
}
+ if (msg_fd.revents != 0 && msg_fd.fd != -1)
+ if (i == lst->size)
+ events[nevents - 1].is_msg = 1;
+
return nevents;
}
@@ -350,27 +389,36 @@ int nanosleep(const struct timespec* req, struct timespec* rem) {
unsigned secrem;
unsigned nanorem;
int rv;
- int rc;
+ int err;
int rsn;
nano = (int)req->tv_nsec;
seconds = req->tv_sec;
- events = CW_CONDVAR;
+ events = CW_CONDVAR | CW_INTRPT;
+ secrem = 0;
+ nanorem = 0;
#if defined(_LP64)
- BPX4CTW(&seconds, &nano, &events, &secrem, &nanorem, &rv, &rc, &rsn);
+ BPX4CTW(&seconds, &nano, &events, &secrem, &nanorem, &rv, &err, &rsn);
#else
- BPX1CTW(&seconds, &nano, &events, &secrem, &nanorem, &rv, &rc, &rsn);
+ BPX1CTW(&seconds, &nano, &events, &secrem, &nanorem, &rv, &err, &rsn);
#endif
- assert(rv == -1 && errno == EAGAIN);
+ /* Don't clobber errno unless BPX1CTW/BPX4CTW errored.
+ * Don't leak EAGAIN, that just means the timeout expired.
+ */
+ if (rv == -1)
+ if (err == EAGAIN)
+ rv = 0;
+ else
+ errno = err;
- if(rem != NULL) {
+ if (rem != NULL && (rv == 0 || err == EINTR)) {
rem->tv_nsec = nanorem;
rem->tv_sec = secrem;
}
- return 0;
+ return rv;
}
@@ -510,3 +558,28 @@ size_t strnlen(const char* str, size_t maxlen) {
else
return p - str;
}
+
+
+int sem_init(UV_PLATFORM_SEM_T* semid, int pshared, unsigned int value) {
+ UNREACHABLE();
+}
+
+
+int sem_destroy(UV_PLATFORM_SEM_T* semid) {
+ UNREACHABLE();
+}
+
+
+int sem_post(UV_PLATFORM_SEM_T* semid) {
+ UNREACHABLE();
+}
+
+
+int sem_trywait(UV_PLATFORM_SEM_T* semid) {
+ UNREACHABLE();
+}
+
+
+int sem_wait(UV_PLATFORM_SEM_T* semid) {
+ UNREACHABLE();
+}
diff --git a/Utilities/cmlibuv/src/unix/os390-syscalls.h b/Utilities/cmlibuv/src/unix/os390-syscalls.h
index ea599107b3..86416bbc55 100644
--- a/Utilities/cmlibuv/src/unix/os390-syscalls.h
+++ b/Utilities/cmlibuv/src/unix/os390-syscalls.h
@@ -40,6 +40,7 @@
struct epoll_event {
int events;
int fd;
+ int is_msg;
};
typedef struct {
@@ -64,5 +65,10 @@ int scandir(const char* maindir, struct dirent*** namelist,
char *mkdtemp(char* path);
ssize_t os390_readlink(const char* path, char* buf, size_t len);
size_t strnlen(const char* str, size_t maxlen);
+int sem_init(UV_PLATFORM_SEM_T* semid, int pshared, unsigned int value);
+int sem_destroy(UV_PLATFORM_SEM_T* semid);
+int sem_post(UV_PLATFORM_SEM_T* semid);
+int sem_trywait(UV_PLATFORM_SEM_T* semid);
+int sem_wait(UV_PLATFORM_SEM_T* semid);
#endif /* UV_OS390_SYSCALL_H_ */
diff --git a/Utilities/cmlibuv/src/unix/os390.c b/Utilities/cmlibuv/src/unix/os390.c
index 273ded7ca5..dce169b9fb 100644
--- a/Utilities/cmlibuv/src/unix/os390.c
+++ b/Utilities/cmlibuv/src/unix/os390.c
@@ -433,13 +433,6 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
}
-void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
- for (int i = 0; i < count; ++i)
- uv__free(cpu_infos[i].model);
- uv__free(cpu_infos);
-}
-
-
static int uv__interface_addresses_v6(uv_interface_address_t** addresses,
int* count) {
uv_interface_address_t* address;
@@ -930,7 +923,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
continue;
ep = loop->ep;
- if (fd == ep->msg_queue) {
+ if (pe->is_msg) {
os390_message_queue_handler(ep);
continue;
}
diff --git a/Utilities/cmlibuv/src/unix/pipe.c b/Utilities/cmlibuv/src/unix/pipe.c
index 7d97550ae2..52a8fd52fa 100644
--- a/Utilities/cmlibuv/src/unix/pipe.c
+++ b/Utilities/cmlibuv/src/unix/pipe.c
@@ -93,8 +93,12 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
if (uv__stream_fd(handle) == -1)
return UV_EINVAL;
-#if defined(__MVS__)
+ if (handle->ipc)
+ return UV_EINVAL;
+
+#if defined(__MVS__) || defined(__PASE__)
/* On zOS, backlog=0 has undefined behaviour */
+ /* On IBMi PASE, backlog=0 leads to "Connection refused" error */
if (backlog == 0)
backlog = 1;
else if (backlog < 0)
@@ -259,7 +263,7 @@ static int uv__pipe_getsockpeername(const uv_pipe_t* handle,
addrlen = strlen(sa.sun_path);
- if (addrlen >= *size) {
+ if ((size_t)addrlen >= *size) {
*size = addrlen + 1;
return UV_ENOBUFS;
}
diff --git a/Utilities/cmlibuv/src/unix/posix-poll.c b/Utilities/cmlibuv/src/unix/posix-poll.c
index a3b9f2196d..766e83205d 100644
--- a/Utilities/cmlibuv/src/unix/posix-poll.c
+++ b/Utilities/cmlibuv/src/unix/posix-poll.c
@@ -61,7 +61,7 @@ static void uv__pollfds_maybe_resize(uv_loop_t* loop) {
return;
n = loop->poll_fds_size ? loop->poll_fds_size * 2 : 64;
- p = uv__realloc(loop->poll_fds, n * sizeof(*loop->poll_fds));
+ p = uv__reallocf(loop->poll_fds, n * sizeof(*loop->poll_fds));
if (p == NULL)
abort();
diff --git a/Utilities/cmlibuv/src/unix/process.c b/Utilities/cmlibuv/src/unix/process.c
index f4826bf62a..08aa2f3cc6 100644
--- a/Utilities/cmlibuv/src/unix/process.c
+++ b/Utilities/cmlibuv/src/unix/process.c
@@ -123,72 +123,64 @@ static void uv__chld(uv_signal_t* handle, int signum) {
}
-int uv__make_socketpair(int fds[2], int flags) {
-#if defined(__linux__)
- static int no_cloexec;
-
- if (no_cloexec)
- goto skip;
-
- if (socketpair(AF_UNIX, SOCK_STREAM | UV__SOCK_CLOEXEC | flags, 0, fds) == 0)
- return 0;
-
- /* Retry on EINVAL, it means SOCK_CLOEXEC is not supported.
- * Anything else is a genuine error.
- */
- if (errno != EINVAL)
+static int uv__make_socketpair(int fds[2]) {
+#if defined(__FreeBSD__) || defined(__linux__)
+ if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, fds))
return UV__ERR(errno);
- no_cloexec = 1;
-
-skip:
-#endif
+ return 0;
+#else
+ int err;
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds))
return UV__ERR(errno);
- uv__cloexec(fds[0], 1);
- uv__cloexec(fds[1], 1);
+ err = uv__cloexec(fds[0], 1);
+ if (err == 0)
+ err = uv__cloexec(fds[1], 1);
- if (flags & UV__F_NONBLOCK) {
- uv__nonblock(fds[0], 1);
- uv__nonblock(fds[1], 1);
+ if (err != 0) {
+ uv__close(fds[0]);
+ uv__close(fds[1]);
+ return UV__ERR(errno);
}
return 0;
+#endif
}
int uv__make_pipe(int fds[2], int flags) {
-#if defined(__linux__)
- static int no_pipe2;
-
- if (no_pipe2)
- goto skip;
-
- if (uv__pipe2(fds, flags | UV__O_CLOEXEC) == 0)
- return 0;
-
- if (errno != ENOSYS)
+#if defined(__FreeBSD__) || defined(__linux__)
+ if (pipe2(fds, flags | O_CLOEXEC))
return UV__ERR(errno);
- no_pipe2 = 1;
-
-skip:
-#endif
-
+ return 0;
+#else
if (pipe(fds))
return UV__ERR(errno);
- uv__cloexec(fds[0], 1);
- uv__cloexec(fds[1], 1);
+ if (uv__cloexec(fds[0], 1))
+ goto fail;
+
+ if (uv__cloexec(fds[1], 1))
+ goto fail;
if (flags & UV__F_NONBLOCK) {
- uv__nonblock(fds[0], 1);
- uv__nonblock(fds[1], 1);
+ if (uv__nonblock(fds[0], 1))
+ goto fail;
+
+ if (uv__nonblock(fds[1], 1))
+ goto fail;
}
return 0;
+
+fail:
+ uv__close(fds[0]);
+ uv__close(fds[1]);
+ return UV__ERR(errno);
+#endif
}
@@ -211,7 +203,7 @@ static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) {
if (container->data.stream->type != UV_NAMED_PIPE)
return UV_EINVAL;
else
- return uv__make_socketpair(fds, 0);
+ return uv__make_socketpair(fds);
case UV_INHERIT_FD:
case UV_INHERIT_STREAM:
@@ -260,7 +252,7 @@ static int uv__process_open_stream(uv_stdio_container_t* container,
static void uv__process_close_stream(uv_stdio_container_t* container) {
if (!(container->flags & UV_CREATE_PIPE)) return;
- uv__stream_close((uv_stream_t*)container->data.stream);
+ uv__stream_close(container->data.stream);
}
diff --git a/Utilities/cmlibuv/src/unix/proctitle.c b/Utilities/cmlibuv/src/unix/proctitle.c
index a5ce2030c5..d124d3c7fc 100644
--- a/Utilities/cmlibuv/src/unix/proctitle.c
+++ b/Utilities/cmlibuv/src/unix/proctitle.c
@@ -24,28 +24,27 @@
#include <stdlib.h>
#include <string.h>
-extern void uv__set_process_title_platform_init(void);
+struct uv__process_title {
+ char* str;
+ size_t len; /* Length of the current process title. */
+ size_t cap; /* Maximum capacity. Computed once in uv_setup_args(). */
+};
+
extern void uv__set_process_title(const char* title);
static uv_mutex_t process_title_mutex;
static uv_once_t process_title_mutex_once = UV_ONCE_INIT;
+static struct uv__process_title process_title;
static void* args_mem;
-static struct {
- char* str;
- size_t len;
-} process_title;
-
static void init_process_title_mutex_once(void) {
uv_mutex_init(&process_title_mutex);
-#ifdef __APPLE__
- uv__set_process_title_platform_init();
-#endif
}
char** uv_setup_args(int argc, char** argv) {
+ struct uv__process_title pt;
char** new_argv;
size_t size;
char* s;
@@ -54,53 +53,69 @@ char** uv_setup_args(int argc, char** argv) {
if (argc <= 0)
return argv;
+ pt.str = argv[0];
+ pt.len = strlen(argv[0]);
+ pt.cap = pt.len + 1;
+
/* Calculate how much memory we need for the argv strings. */
- size = 0;
- for (i = 0; i < argc; i++)
+ size = pt.cap;
+ for (i = 1; i < argc; i++)
size += strlen(argv[i]) + 1;
-#if defined(__MVS__)
- /* argv is not adjacent. So just use argv[0] */
- process_title.str = argv[0];
- process_title.len = strlen(argv[0]);
-#else
- process_title.str = argv[0];
- process_title.len = argv[argc - 1] + strlen(argv[argc - 1]) - argv[0];
- assert(process_title.len + 1 == size); /* argv memory should be adjacent. */
-#endif
-
/* Add space for the argv pointers. */
size += (argc + 1) * sizeof(char*);
new_argv = uv__malloc(size);
if (new_argv == NULL)
return argv;
- args_mem = new_argv;
/* Copy over the strings and set up the pointer table. */
+ i = 0;
s = (char*) &new_argv[argc + 1];
- for (i = 0; i < argc; i++) {
+ size = pt.cap;
+ goto loop;
+
+ for (/* empty */; i < argc; i++) {
size = strlen(argv[i]) + 1;
+ loop:
memcpy(s, argv[i], size);
new_argv[i] = s;
s += size;
}
new_argv[i] = NULL;
+ /* argv is not adjacent on z/os, we use just argv[0] on that platform. */
+#ifndef __MVS__
+ pt.cap = argv[i - 1] + size - argv[0];
+#endif
+
+ args_mem = new_argv;
+ process_title = pt;
+
return new_argv;
}
int uv_set_process_title(const char* title) {
+ struct uv__process_title* pt;
+ size_t len;
+
+ pt = &process_title;
+ len = strlen(title);
+
uv_once(&process_title_mutex_once, init_process_title_mutex_once);
uv_mutex_lock(&process_title_mutex);
- if (process_title.len != 0) {
- /* No need to terminate, byte after is always '\0'. */
- strncpy(process_title.str, title, process_title.len);
- uv__set_process_title(title);
+ if (len >= pt->cap) {
+ len = 0;
+ if (pt->cap > 0)
+ len = pt->cap - 1;
}
+ memcpy(pt->str, title, len);
+ memset(pt->str + len, '\0', pt->cap - len);
+ pt->len = len;
+
uv_mutex_unlock(&process_title_mutex);
return 0;
diff --git a/Utilities/cmlibuv/src/unix/random-devurandom.c b/Utilities/cmlibuv/src/unix/random-devurandom.c
new file mode 100644
index 0000000000..05e52a56a3
--- /dev/null
+++ b/Utilities/cmlibuv/src/unix/random-devurandom.c
@@ -0,0 +1,93 @@
+/* Copyright libuv contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "internal.h"
+
+#include <sys/stat.h>
+#include <unistd.h>
+
+static uv_once_t once = UV_ONCE_INIT;
+static int status;
+
+
+int uv__random_readpath(const char* path, void* buf, size_t buflen) {
+ struct stat s;
+ size_t pos;
+ ssize_t n;
+ int fd;
+
+ fd = uv__open_cloexec(path, O_RDONLY);
+
+ if (fd < 0)
+ return fd;
+
+ if (fstat(fd, &s)) {
+ uv__close(fd);
+ return UV__ERR(errno);
+ }
+
+ if (!S_ISCHR(s.st_mode)) {
+ uv__close(fd);
+ return UV_EIO;
+ }
+
+ for (pos = 0; pos != buflen; pos += n) {
+ do
+ n = read(fd, (char*) buf + pos, buflen - pos);
+ while (n == -1 && errno == EINTR);
+
+ if (n == -1) {
+ uv__close(fd);
+ return UV__ERR(errno);
+ }
+
+ if (n == 0) {
+ uv__close(fd);
+ return UV_EIO;
+ }
+ }
+
+ uv__close(fd);
+ return 0;
+}
+
+
+static void uv__random_devurandom_init(void) {
+ char c;
+
+ /* Linux's random(4) man page suggests applications should read at least
+ * once from /dev/random before switching to /dev/urandom in order to seed
+ * the system RNG. Reads from /dev/random can of course block indefinitely
+ * until entropy is available but that's the point.
+ */
+ status = uv__random_readpath("/dev/random", &c, 1);
+}
+
+
+int uv__random_devurandom(void* buf, size_t buflen) {
+ uv_once(&once, uv__random_devurandom_init);
+
+ if (status != 0)
+ return status;
+
+ return uv__random_readpath("/dev/urandom", buf, buflen);
+}
diff --git a/Utilities/cmlibuv/src/unix/random-getentropy.c b/Utilities/cmlibuv/src/unix/random-getentropy.c
new file mode 100644
index 0000000000..c45d9fd4a2
--- /dev/null
+++ b/Utilities/cmlibuv/src/unix/random-getentropy.c
@@ -0,0 +1,57 @@
+/* Copyright libuv contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "internal.h"
+
+#include <stddef.h>
+#include <dlfcn.h>
+
+typedef int (*uv__getentropy_cb)(void *, size_t);
+
+static uv__getentropy_cb uv__getentropy;
+static uv_once_t once = UV_ONCE_INIT;
+
+
+static void uv__random_getentropy_init(void) {
+ uv__getentropy = (uv__getentropy_cb) dlsym(RTLD_DEFAULT, "getentropy");
+}
+
+
+int uv__random_getentropy(void* buf, size_t buflen) {
+ size_t pos;
+ size_t stride;
+
+ uv_once(&once, uv__random_getentropy_init);
+
+ if (uv__getentropy == NULL)
+ return UV_ENOSYS;
+
+ /* getentropy() returns an error for requests > 256 bytes. */
+ for (pos = 0, stride = 256; pos + stride < buflen; pos += stride)
+ if (uv__getentropy((char *) buf + pos, stride))
+ return UV__ERR(errno);
+
+ if (uv__getentropy((char *) buf + pos, buflen - pos))
+ return UV__ERR(errno);
+
+ return 0;
+}
diff --git a/Utilities/cmlibuv/src/unix/random-getrandom.c b/Utilities/cmlibuv/src/unix/random-getrandom.c
new file mode 100644
index 0000000000..bcc94089bc
--- /dev/null
+++ b/Utilities/cmlibuv/src/unix/random-getrandom.c
@@ -0,0 +1,88 @@
+/* Copyright libuv contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "internal.h"
+
+#ifdef __linux__
+
+#include "linux-syscalls.h"
+
+#define uv__random_getrandom_init() 0
+
+#else /* !__linux__ */
+
+#include <stddef.h>
+#include <dlfcn.h>
+
+typedef ssize_t (*uv__getrandom_cb)(void *, size_t, unsigned);
+
+static uv__getrandom_cb uv__getrandom;
+static uv_once_t once = UV_ONCE_INIT;
+
+static void uv__random_getrandom_init_once(void) {
+ uv__getrandom = (uv__getrandom_cb) dlsym(RTLD_DEFAULT, "getrandom");
+}
+
+static int uv__random_getrandom_init(void) {
+ uv_once(&once, uv__random_getrandom_init_once);
+
+ if (uv__getrandom == NULL)
+ return UV_ENOSYS;
+
+ return 0;
+}
+
+#endif /* !__linux__ */
+
+int uv__random_getrandom(void* buf, size_t buflen) {
+ ssize_t n;
+ size_t pos;
+ int rc;
+
+ rc = uv__random_getrandom_init();
+ if (rc != 0)
+ return rc;
+
+ for (pos = 0; pos != buflen; pos += n) {
+ do {
+ n = buflen - pos;
+
+ /* Most getrandom() implementations promise that reads <= 256 bytes
+ * will always succeed and won't be interrupted by signals.
+ * It's therefore useful to split it up in smaller reads because
+ * one big read may, in theory, continuously fail with EINTR.
+ */
+ if (n > 256)
+ n = 256;
+
+ n = uv__getrandom((char *) buf + pos, n, 0);
+ } while (n == -1 && errno == EINTR);
+
+ if (n == -1)
+ return UV__ERR(errno);
+
+ if (n == 0)
+ return UV_EIO;
+ }
+
+ return 0;
+}
diff --git a/Utilities/cmlibuv/src/unix/random-sysctl-linux.c b/Utilities/cmlibuv/src/unix/random-sysctl-linux.c
new file mode 100644
index 0000000000..66ba8d74ec
--- /dev/null
+++ b/Utilities/cmlibuv/src/unix/random-sysctl-linux.c
@@ -0,0 +1,99 @@
+/* Copyright libuv contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "internal.h"
+
+#include <errno.h>
+#include <string.h>
+
+#include <syscall.h>
+#include <unistd.h>
+
+
+struct uv__sysctl_args {
+ int* name;
+ int nlen;
+ void* oldval;
+ size_t* oldlenp;
+ void* newval;
+ size_t newlen;
+ unsigned long unused[4];
+};
+
+
+int uv__random_sysctl(void* buf, size_t buflen) {
+ static int name[] = {1 /*CTL_KERN*/, 40 /*KERN_RANDOM*/, 6 /*RANDOM_UUID*/};
+ struct uv__sysctl_args args;
+ char uuid[16];
+ char* p;
+ char* pe;
+ size_t n;
+
+ p = buf;
+ pe = p + buflen;
+
+ while (p < pe) {
+ memset(&args, 0, sizeof(args));
+
+ args.name = name;
+ args.nlen = ARRAY_SIZE(name);
+ args.oldval = uuid;
+ args.oldlenp = &n;
+ n = sizeof(uuid);
+
+ /* Emits a deprecation warning with some kernels but that seems like
+ * an okay trade-off for the fallback of the fallback: this function is
+ * only called when neither getrandom(2) nor /dev/urandom are available.
+ * Fails with ENOSYS on kernels configured without CONFIG_SYSCTL_SYSCALL.
+ * At least arm64 never had a _sysctl system call and therefore doesn't
+ * have a SYS__sysctl define either.
+ */
+#ifdef SYS__sysctl
+ if (syscall(SYS__sysctl, &args) == -1)
+ return UV__ERR(errno);
+#else
+ {
+ (void) &args;
+ return UV_ENOSYS;
+ }
+#endif
+
+ if (n != sizeof(uuid))
+ return UV_EIO; /* Can't happen. */
+
+ /* uuid[] is now a type 4 UUID. Bytes 6 and 8 (counting from zero) contain
+ * 4 and 5 bits of entropy, respectively. For ease of use, we skip those
+ * and only use 14 of the 16 bytes.
+ */
+ uuid[6] = uuid[14];
+ uuid[8] = uuid[15];
+
+ n = pe - p;
+ if (n > 14)
+ n = 14;
+
+ memcpy(p, uuid, n);
+ p += n;
+ }
+
+ return 0;
+}
diff --git a/Utilities/cmlibuv/src/unix/signal.c b/Utilities/cmlibuv/src/unix/signal.c
index 01aa55f3fe..1e7e8ac574 100644
--- a/Utilities/cmlibuv/src/unix/signal.c
+++ b/Utilities/cmlibuv/src/unix/signal.c
@@ -331,16 +331,7 @@ int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle) {
void uv__signal_close(uv_signal_t* handle) {
-
uv__signal_stop(handle);
-
- /* If there are any caught signals "trapped" in the signal pipe, we can't
- * call the close callback yet. Otherwise, add the handle to the finish_close
- * queue.
- */
- if (handle->caught_signals == handle->dispatched_signals) {
- uv__make_close_pending((uv_handle_t*) handle);
- }
}
@@ -375,7 +366,7 @@ static int uv__signal_start(uv_signal_t* handle,
/* Short circuit: if the signal watcher is already watching {signum} don't
* go through the process of deregistering and registering the handler.
- * Additionally, this avoids pending signals getting lost in the small time
+ * Additionally, this avoids pending signals getting lost in the small
* time frame that handle->signum == 0.
*/
if (signum == handle->signum) {
@@ -472,15 +463,6 @@ static void uv__signal_event(uv_loop_t* loop,
if (handle->flags & UV_SIGNAL_ONE_SHOT)
uv__signal_stop(handle);
-
- /* If uv_close was called while there were caught signals that were not
- * yet dispatched, the uv__finish_close was deferred. Make close pending
- * now if this has happened.
- */
- if ((handle->flags & UV_HANDLE_CLOSING) &&
- (handle->caught_signals == handle->dispatched_signals)) {
- uv__make_close_pending((uv_handle_t*) handle);
- }
}
bytes -= end;
@@ -563,6 +545,7 @@ static void uv__signal_stop(uv_signal_t* handle) {
if (first_oneshot && !rem_oneshot) {
ret = uv__signal_register_handler(handle->signum, 1);
assert(ret == 0);
+ (void)ret;
}
}
diff --git a/Utilities/cmlibuv/src/unix/stream.c b/Utilities/cmlibuv/src/unix/stream.c
index 8121f64644..3b6da8d464 100644
--- a/Utilities/cmlibuv/src/unix/stream.c
+++ b/Utilities/cmlibuv/src/unix/stream.c
@@ -1000,12 +1000,12 @@ uv_handle_type uv__handle_type(int fd) {
static void uv__stream_eof(uv_stream_t* stream, const uv_buf_t* buf) {
stream->flags |= UV_HANDLE_READ_EOF;
+ stream->flags &= ~UV_HANDLE_READING;
uv__io_stop(stream->loop, &stream->io_watcher, POLLIN);
if (!uv__io_active(&stream->io_watcher, POLLOUT))
uv__handle_stop(stream);
uv__stream_osx_interrupt_select(stream);
stream->read_cb(stream, UV_EOF, buf);
- stream->flags &= ~UV_HANDLE_READING;
}
@@ -1048,7 +1048,12 @@ static int uv__stream_queue_fd(uv_stream_t* stream, int fd) {
}
-#define UV__CMSG_FD_COUNT 64
+#if defined(__PASE__)
+/* on IBMi PASE the control message length can not exceed 256. */
+# define UV__CMSG_FD_COUNT 60
+#else
+# define UV__CMSG_FD_COUNT 64
+#endif
#define UV__CMSG_FD_SIZE (UV__CMSG_FD_COUNT * sizeof(int))
@@ -1403,7 +1408,7 @@ int uv_write2(uv_write_t* req,
return UV_EBADF;
if (!(stream->flags & UV_HANDLE_WRITABLE))
- return -EPIPE;
+ return UV_EPIPE;
if (send_handle) {
if (stream->type != UV_NAMED_PIPE || !((uv_pipe_t*)stream)->ipc)
@@ -1557,7 +1562,7 @@ int uv_read_start(uv_stream_t* stream,
return UV_EINVAL;
if (!(stream->flags & UV_HANDLE_READABLE))
- return -ENOTCONN;
+ return UV_ENOTCONN;
/* The UV_HANDLE_READING flag is irrelevant of the state of the tcp - it just
* expresses the desired state of the user.
diff --git a/Utilities/cmlibuv/src/unix/sunos.c b/Utilities/cmlibuv/src/unix/sunos.c
index 0cd25c10a3..9697648054 100644
--- a/Utilities/cmlibuv/src/unix/sunos.c
+++ b/Utilities/cmlibuv/src/unix/sunos.c
@@ -700,16 +700,6 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
}
-void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
- int i;
-
- for (i = 0; i < count; i++) {
- uv__free(cpu_infos[i].model);
- }
-
- uv__free(cpu_infos);
-}
-
#ifdef SUNOS_NO_IFADDRS
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
*count = 0;
diff --git a/Utilities/cmlibuv/src/unix/tcp.c b/Utilities/cmlibuv/src/unix/tcp.c
index 8cedcd6027..d47e9433db 100644
--- a/Utilities/cmlibuv/src/unix/tcp.c
+++ b/Utilities/cmlibuv/src/unix/tcp.c
@@ -308,6 +308,23 @@ int uv_tcp_getpeername(const uv_tcp_t* handle,
}
+int uv_tcp_close_reset(uv_tcp_t* handle, uv_close_cb close_cb) {
+ int fd;
+ struct linger l = { 1, 0 };
+
+ /* Disallow setting SO_LINGER to zero due to some platform inconsistencies */
+ if (handle->flags & UV_HANDLE_SHUTTING)
+ return UV_EINVAL;
+
+ fd = uv__stream_fd(handle);
+ if (0 != setsockopt(fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l)))
+ return UV__ERR(errno);
+
+ uv_close((uv_handle_t*) handle, close_cb);
+ return 0;
+}
+
+
int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
static int single_accept = -1;
unsigned long flags;
@@ -362,8 +379,16 @@ int uv__tcp_keepalive(int fd, int on, unsigned int delay) {
return UV__ERR(errno);
#ifdef TCP_KEEPIDLE
- if (on && setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &delay, sizeof(delay)))
- return UV__ERR(errno);
+ if (on) {
+ int intvl = 1; /* 1 second; same as default on Win32 */
+ int cnt = 10; /* 10 retries; same as hardcoded on Win32 */
+ if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &delay, sizeof(delay)))
+ return UV__ERR(errno);
+ if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl)))
+ return UV__ERR(errno);
+ if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt)))
+ return UV__ERR(errno);
+ }
#endif
/* Solaris/SmartOS, if you don't support keep-alive,
diff --git a/Utilities/cmlibuv/src/unix/thread.c b/Utilities/cmlibuv/src/unix/thread.c
index 045322170c..f93aa532ff 100644
--- a/Utilities/cmlibuv/src/unix/thread.c
+++ b/Utilities/cmlibuv/src/unix/thread.c
@@ -37,7 +37,7 @@
#include <sys/sem.h>
#endif
-#ifdef __GLIBC__
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
#include <gnu/libc-version.h> /* gnu_get_libc_version() */
#endif
@@ -222,6 +222,12 @@ int uv_thread_create_ex(uv_thread_t* tid,
size_t pagesize;
size_t stack_size;
+ /* Used to squelch a -Wcast-function-type warning. */
+ union {
+ void (*in)(void*);
+ void* (*out)(void*);
+ } f;
+
stack_size =
params->flags & UV_THREAD_HAS_STACK_SIZE ? params->stack_size : 0;
@@ -248,7 +254,8 @@ int uv_thread_create_ex(uv_thread_t* tid,
abort();
}
- err = pthread_create(tid, attr, (void*(*)(void*)) entry, arg);
+ f.in = entry;
+ err = pthread_create(tid, attr, f.out, arg);
if (attr != NULL)
pthread_attr_destroy(attr);
@@ -474,7 +481,7 @@ int uv_sem_trywait(uv_sem_t* sem) {
#else /* !(defined(__APPLE__) && defined(__MACH__)) */
-#ifdef __GLIBC__
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
/* Hack around https://sourceware.org/bugzilla/show_bug.cgi?id=12674
* by providing a custom implementation for glibc < 2.21 in terms of other
@@ -510,7 +517,8 @@ typedef struct uv_semaphore_s {
unsigned int value;
} uv_semaphore_t;
-#if defined(__GLIBC__) || platform_needs_custom_semaphore
+#if (defined(__GLIBC__) && !defined(__UCLIBC__)) || \
+ platform_needs_custom_semaphore
STATIC_ASSERT(sizeof(uv_sem_t) >= sizeof(uv_semaphore_t*));
#endif
@@ -639,7 +647,7 @@ static int uv__sem_trywait(uv_sem_t* sem) {
}
int uv_sem_init(uv_sem_t* sem, unsigned int value) {
-#ifdef __GLIBC__
+#if defined(__GLIBC__) && !defined(__UCLIBC__)
uv_once(&glibc_version_check_once, glibc_version_check);
#endif
diff --git a/Utilities/cmlibuv/src/unix/tty.c b/Utilities/cmlibuv/src/unix/tty.c
index db479d61bf..82cd723d74 100644
--- a/Utilities/cmlibuv/src/unix/tty.c
+++ b/Utilities/cmlibuv/src/unix/tty.c
@@ -34,6 +34,34 @@
#define IMAXBEL 0
#endif
+#if defined(__PASE__)
+/* On IBM i PASE, for better compatibility with running interactive programs in
+ * a 5250 environment, isatty() will return true for the stdin/stdout/stderr
+ * streams created by QSH/QP2TERM.
+ *
+ * For more, see docs on PASE_STDIO_ISATTY in
+ * https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_74/apis/pase_environ.htm
+ *
+ * This behavior causes problems for Node as it expects that if isatty() returns
+ * true that TTY ioctls will be supported by that fd (which is not an
+ * unreasonable expectation) and when they don't it crashes with assertion
+ * errors.
+ *
+ * Here, we create our own version of isatty() that uses ioctl() to identify
+ * whether the fd is *really* a TTY or not.
+ */
+static int isreallyatty(int file) {
+ int rc;
+
+ rc = !ioctl(file, TXISATTY + 0x81, NULL);
+ if (!rc && errno != EBADF)
+ errno = ENOTTY;
+
+ return rc;
+}
+#define isatty(fd) isreallyatty(fd)
+#endif
+
static int orig_termios_fd = -1;
static struct termios orig_termios;
static uv_spinlock_t termios_spinlock = UV_SPINLOCK_INITIALIZER;
@@ -136,7 +164,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int unused) {
* slave device.
*/
if (uv__tty_is_slave(fd) && ttyname_r(fd, path, sizeof(path)) == 0)
- r = uv__open_cloexec(path, mode);
+ r = uv__open_cloexec(path, mode | O_NOCTTY);
else
r = -1;
@@ -362,3 +390,10 @@ int uv_tty_reset_mode(void) {
return err;
}
+
+void uv_tty_set_vterm_state(uv_tty_vtermstate_t state) {
+}
+
+int uv_tty_get_vterm_state(uv_tty_vtermstate_t* state) {
+ return UV_ENOTSUP;
+}
diff --git a/Utilities/cmlibuv/src/unix/udp.c b/Utilities/cmlibuv/src/unix/udp.c
index b578e7bc10..f2fcae1760 100644
--- a/Utilities/cmlibuv/src/unix/udp.c
+++ b/Utilities/cmlibuv/src/unix/udp.c
@@ -32,6 +32,8 @@
#endif
#include <sys/un.h>
+#define UV__UDP_DGRAM_MAXSIZE (64 * 1024)
+
#if defined(IPV6_JOIN_GROUP) && !defined(IPV6_ADD_MEMBERSHIP)
# define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
#endif
@@ -49,6 +51,36 @@ static int uv__udp_maybe_deferred_bind(uv_udp_t* handle,
int domain,
unsigned int flags);
+#if HAVE_MMSG
+
+#define UV__MMSG_MAXWIDTH 20
+
+static int uv__udp_recvmmsg(uv_udp_t* handle, uv_buf_t* buf);
+static void uv__udp_sendmmsg(uv_udp_t* handle);
+
+static int uv__recvmmsg_avail;
+static int uv__sendmmsg_avail;
+static uv_once_t once = UV_ONCE_INIT;
+
+static void uv__udp_mmsg_init(void) {
+ int ret;
+ int s;
+ s = uv__socket(AF_INET, SOCK_DGRAM, 0);
+ if (s < 0)
+ return;
+ ret = uv__sendmmsg(s, NULL, 0, 0);
+ if (ret == 0 || errno != ENOSYS) {
+ uv__sendmmsg_avail = 1;
+ uv__recvmmsg_avail = 1;
+ } else {
+ ret = uv__recvmmsg(s, NULL, 0, 0, NULL);
+ if (ret == 0 || errno != ENOSYS)
+ uv__recvmmsg_avail = 1;
+ }
+ uv__close(s);
+}
+
+#endif
void uv__udp_close(uv_udp_t* handle) {
uv__io_close(handle->loop, &handle->io_watcher);
@@ -148,6 +180,61 @@ static void uv__udp_io(uv_loop_t* loop, uv__io_t* w, unsigned int revents) {
}
}
+#if HAVE_MMSG
+static int uv__udp_recvmmsg(uv_udp_t* handle, uv_buf_t* buf) {
+ struct sockaddr_in6 peers[UV__MMSG_MAXWIDTH];
+ struct iovec iov[UV__MMSG_MAXWIDTH];
+ struct uv__mmsghdr msgs[UV__MMSG_MAXWIDTH];
+ ssize_t nread;
+ uv_buf_t chunk_buf;
+ size_t chunks;
+ int flags;
+ size_t k;
+
+ /* prepare structures for recvmmsg */
+ chunks = buf->len / UV__UDP_DGRAM_MAXSIZE;
+ if (chunks > ARRAY_SIZE(iov))
+ chunks = ARRAY_SIZE(iov);
+ for (k = 0; k < chunks; ++k) {
+ iov[k].iov_base = buf->base + k * UV__UDP_DGRAM_MAXSIZE;
+ iov[k].iov_len = UV__UDP_DGRAM_MAXSIZE;
+ msgs[k].msg_hdr.msg_iov = iov + k;
+ msgs[k].msg_hdr.msg_iovlen = 1;
+ msgs[k].msg_hdr.msg_name = peers + k;
+ msgs[k].msg_hdr.msg_namelen = sizeof(peers[0]);
+ }
+
+ do
+ nread = uv__recvmmsg(handle->io_watcher.fd, msgs, chunks, 0, NULL);
+ while (nread == -1 && errno == EINTR);
+
+ if (nread < 1) {
+ if (nread == 0 || errno == EAGAIN || errno == EWOULDBLOCK)
+ handle->recv_cb(handle, 0, buf, NULL, 0);
+ else
+ handle->recv_cb(handle, UV__ERR(errno), buf, NULL, 0);
+ } else {
+ /* pass each chunk to the application */
+ for (k = 0; k < (size_t) nread && handle->recv_cb != NULL; k++) {
+ flags = UV_UDP_MMSG_CHUNK;
+ if (msgs[k].msg_hdr.msg_flags & MSG_TRUNC)
+ flags |= UV_UDP_PARTIAL;
+
+ chunk_buf = uv_buf_init(iov[k].iov_base, iov[k].iov_len);
+ handle->recv_cb(handle,
+ msgs[k].msg_len,
+ &chunk_buf,
+ msgs[k].msg_hdr.msg_name,
+ flags);
+ }
+
+ /* one last callback so the original buffer is freed */
+ if (handle->recv_cb != NULL)
+ handle->recv_cb(handle, 0, buf, NULL, 0);
+ }
+ return nread;
+}
+#endif
static void uv__udp_recvmsg(uv_udp_t* handle) {
struct sockaddr_storage peer;
@@ -165,18 +252,32 @@ static void uv__udp_recvmsg(uv_udp_t* handle) {
*/
count = 32;
- memset(&h, 0, sizeof(h));
- h.msg_name = &peer;
-
do {
buf = uv_buf_init(NULL, 0);
- handle->alloc_cb((uv_handle_t*) handle, 64 * 1024, &buf);
+ handle->alloc_cb((uv_handle_t*) handle, UV__UDP_DGRAM_MAXSIZE, &buf);
if (buf.base == NULL || buf.len == 0) {
handle->recv_cb(handle, UV_ENOBUFS, &buf, NULL, 0);
return;
}
assert(buf.base != NULL);
+#if HAVE_MMSG
+ uv_once(&once, uv__udp_mmsg_init);
+ if (uv__recvmmsg_avail) {
+ /* Returned space for more than 1 datagram, use it to receive
+ * multiple datagrams. */
+ if (buf.len >= 2 * UV__UDP_DGRAM_MAXSIZE) {
+ nread = uv__udp_recvmmsg(handle, &buf);
+ if (nread > 0)
+ count -= nread;
+ continue;
+ }
+ }
+#endif
+
+ memset(&h, 0, sizeof(h));
+ memset(&peer, 0, sizeof(peer));
+ h.msg_name = &peer;
h.msg_namelen = sizeof(peer);
h.msg_iov = (void*) &buf;
h.msg_iovlen = 1;
@@ -193,33 +294,126 @@ static void uv__udp_recvmsg(uv_udp_t* handle) {
handle->recv_cb(handle, UV__ERR(errno), &buf, NULL, 0);
}
else {
- const struct sockaddr *addr;
- if (h.msg_namelen == 0)
- addr = NULL;
- else
- addr = (const struct sockaddr*) &peer;
-
flags = 0;
if (h.msg_flags & MSG_TRUNC)
flags |= UV_UDP_PARTIAL;
- handle->recv_cb(handle, nread, &buf, addr, flags);
+ handle->recv_cb(handle, nread, &buf, (const struct sockaddr*) &peer, flags);
}
+ count--;
}
/* recv_cb callback may decide to pause or close the handle */
while (nread != -1
- && count-- > 0
+ && count > 0
&& handle->io_watcher.fd != -1
&& handle->recv_cb != NULL);
}
+#if HAVE_MMSG
+static void uv__udp_sendmmsg(uv_udp_t* handle) {
+ uv_udp_send_t* req;
+ struct uv__mmsghdr h[UV__MMSG_MAXWIDTH];
+ struct uv__mmsghdr *p;
+ QUEUE* q;
+ ssize_t npkts;
+ size_t pkts;
+ size_t i;
+
+ if (QUEUE_EMPTY(&handle->write_queue))
+ return;
+
+write_queue_drain:
+ for (pkts = 0, q = QUEUE_HEAD(&handle->write_queue);
+ pkts < UV__MMSG_MAXWIDTH && q != &handle->write_queue;
+ ++pkts, q = QUEUE_HEAD(q)) {
+ assert(q != NULL);
+ req = QUEUE_DATA(q, uv_udp_send_t, queue);
+ assert(req != NULL);
+
+ p = &h[pkts];
+ memset(p, 0, sizeof(*p));
+ if (req->addr.ss_family == AF_UNSPEC) {
+ p->msg_hdr.msg_name = NULL;
+ p->msg_hdr.msg_namelen = 0;
+ } else {
+ p->msg_hdr.msg_name = &req->addr;
+ if (req->addr.ss_family == AF_INET6)
+ p->msg_hdr.msg_namelen = sizeof(struct sockaddr_in6);
+ else if (req->addr.ss_family == AF_INET)
+ p->msg_hdr.msg_namelen = sizeof(struct sockaddr_in);
+ else if (req->addr.ss_family == AF_UNIX)
+ p->msg_hdr.msg_namelen = sizeof(struct sockaddr_un);
+ else {
+ assert(0 && "unsupported address family");
+ abort();
+ }
+ }
+ h[pkts].msg_hdr.msg_iov = (struct iovec*) req->bufs;
+ h[pkts].msg_hdr.msg_iovlen = req->nbufs;
+ }
+
+ do
+ npkts = uv__sendmmsg(handle->io_watcher.fd, h, pkts, 0);
+ while (npkts == -1 && errno == EINTR);
+
+ if (npkts < 1) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS)
+ return;
+ for (i = 0, q = QUEUE_HEAD(&handle->write_queue);
+ i < pkts && q != &handle->write_queue;
+ ++i, q = QUEUE_HEAD(q)) {
+ assert(q != NULL);
+ req = QUEUE_DATA(q, uv_udp_send_t, queue);
+ assert(req != NULL);
+
+ req->status = UV__ERR(errno);
+ QUEUE_REMOVE(&req->queue);
+ QUEUE_INSERT_TAIL(&handle->write_completed_queue, &req->queue);
+ }
+ uv__io_feed(handle->loop, &handle->io_watcher);
+ return;
+ }
+
+ for (i = 0, q = QUEUE_HEAD(&handle->write_queue);
+ i < pkts && q != &handle->write_queue;
+ ++i, q = QUEUE_HEAD(&handle->write_queue)) {
+ assert(q != NULL);
+ req = QUEUE_DATA(q, uv_udp_send_t, queue);
+ assert(req != NULL);
+
+ req->status = req->bufs[0].len;
+
+ /* Sending a datagram is an atomic operation: either all data
+ * is written or nothing is (and EMSGSIZE is raised). That is
+ * why we don't handle partial writes. Just pop the request
+ * off the write queue and onto the completed queue, done.
+ */
+ QUEUE_REMOVE(&req->queue);
+ QUEUE_INSERT_TAIL(&handle->write_completed_queue, &req->queue);
+ }
+
+ /* couldn't batch everything, continue sending (jump to avoid stack growth) */
+ if (!QUEUE_EMPTY(&handle->write_queue))
+ goto write_queue_drain;
+ uv__io_feed(handle->loop, &handle->io_watcher);
+ return;
+}
+#endif
static void uv__udp_sendmsg(uv_udp_t* handle) {
uv_udp_send_t* req;
- QUEUE* q;
struct msghdr h;
+ QUEUE* q;
ssize_t size;
+#if HAVE_MMSG
+ uv_once(&once, uv__udp_mmsg_init);
+ if (uv__sendmmsg_avail) {
+ uv__udp_sendmmsg(handle);
+ return;
+ }
+#endif
+
while (!QUEUE_EMPTY(&handle->write_queue)) {
q = QUEUE_HEAD(&handle->write_queue);
assert(q != NULL);
@@ -269,7 +463,6 @@ static void uv__udp_sendmsg(uv_udp_t* handle) {
}
}
-
/* On the BSDs, SO_REUSEPORT implies SO_REUSEADDR but with some additional
* refinements for programs that use multicast.
*
@@ -659,6 +852,100 @@ static int uv__udp_set_membership6(uv_udp_t* handle,
}
+#if !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__ANDROID__)
+static int uv__udp_set_source_membership4(uv_udp_t* handle,
+ const struct sockaddr_in* multicast_addr,
+ const char* interface_addr,
+ const struct sockaddr_in* source_addr,
+ uv_membership membership) {
+ struct ip_mreq_source mreq;
+ int optname;
+ int err;
+
+ err = uv__udp_maybe_deferred_bind(handle, AF_INET, UV_UDP_REUSEADDR);
+ if (err)
+ return err;
+
+ memset(&mreq, 0, sizeof(mreq));
+
+ if (interface_addr != NULL) {
+ err = uv_inet_pton(AF_INET, interface_addr, &mreq.imr_interface.s_addr);
+ if (err)
+ return err;
+ } else {
+ mreq.imr_interface.s_addr = htonl(INADDR_ANY);
+ }
+
+ mreq.imr_multiaddr.s_addr = multicast_addr->sin_addr.s_addr;
+ mreq.imr_sourceaddr.s_addr = source_addr->sin_addr.s_addr;
+
+ if (membership == UV_JOIN_GROUP)
+ optname = IP_ADD_SOURCE_MEMBERSHIP;
+ else if (membership == UV_LEAVE_GROUP)
+ optname = IP_DROP_SOURCE_MEMBERSHIP;
+ else
+ return UV_EINVAL;
+
+ if (setsockopt(handle->io_watcher.fd,
+ IPPROTO_IP,
+ optname,
+ &mreq,
+ sizeof(mreq))) {
+ return UV__ERR(errno);
+ }
+
+ return 0;
+}
+
+
+static int uv__udp_set_source_membership6(uv_udp_t* handle,
+ const struct sockaddr_in6* multicast_addr,
+ const char* interface_addr,
+ const struct sockaddr_in6* source_addr,
+ uv_membership membership) {
+ struct group_source_req mreq;
+ struct sockaddr_in6 addr6;
+ int optname;
+ int err;
+
+ err = uv__udp_maybe_deferred_bind(handle, AF_INET6, UV_UDP_REUSEADDR);
+ if (err)
+ return err;
+
+ memset(&mreq, 0, sizeof(mreq));
+
+ if (interface_addr != NULL) {
+ err = uv_ip6_addr(interface_addr, 0, &addr6);
+ if (err)
+ return err;
+ mreq.gsr_interface = addr6.sin6_scope_id;
+ } else {
+ mreq.gsr_interface = 0;
+ }
+
+ memcpy(&mreq.gsr_group, multicast_addr, sizeof(mreq.gsr_group));
+ memcpy(&mreq.gsr_source, source_addr, sizeof(mreq.gsr_source));
+
+ if (membership == UV_JOIN_GROUP)
+ optname = MCAST_JOIN_SOURCE_GROUP;
+ else if (membership == UV_LEAVE_GROUP)
+ optname = MCAST_LEAVE_SOURCE_GROUP;
+ else
+ return UV_EINVAL;
+
+ if (setsockopt(handle->io_watcher.fd,
+ IPPROTO_IPV6,
+ optname,
+ &mreq,
+ sizeof(mreq))) {
+ return UV__ERR(errno);
+ }
+
+ return 0;
+}
+#endif
+
+
int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) {
int domain;
int err;
@@ -748,11 +1035,60 @@ int uv_udp_set_membership(uv_udp_t* handle,
}
}
+
+int uv_udp_set_source_membership(uv_udp_t* handle,
+ const char* multicast_addr,
+ const char* interface_addr,
+ const char* source_addr,
+ uv_membership membership) {
+#if !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__ANDROID__)
+ int err;
+ struct sockaddr_storage mcast_addr;
+ struct sockaddr_in* mcast_addr4;
+ struct sockaddr_in6* mcast_addr6;
+ struct sockaddr_storage src_addr;
+ struct sockaddr_in* src_addr4;
+ struct sockaddr_in6* src_addr6;
+
+ mcast_addr4 = (struct sockaddr_in*)&mcast_addr;
+ mcast_addr6 = (struct sockaddr_in6*)&mcast_addr;
+ src_addr4 = (struct sockaddr_in*)&src_addr;
+ src_addr6 = (struct sockaddr_in6*)&src_addr;
+
+ err = uv_ip4_addr(multicast_addr, 0, mcast_addr4);
+ if (err) {
+ err = uv_ip6_addr(multicast_addr, 0, mcast_addr6);
+ if (err)
+ return err;
+ err = uv_ip6_addr(source_addr, 0, src_addr6);
+ if (err)
+ return err;
+ return uv__udp_set_source_membership6(handle,
+ mcast_addr6,
+ interface_addr,
+ src_addr6,
+ membership);
+ }
+
+ err = uv_ip4_addr(source_addr, 0, src_addr4);
+ if (err)
+ return err;
+ return uv__udp_set_source_membership4(handle,
+ mcast_addr4,
+ interface_addr,
+ src_addr4,
+ membership);
+#else
+ return UV_ENOSYS;
+#endif
+}
+
+
static int uv__setsockopt(uv_udp_t* handle,
int option4,
int option6,
const void* val,
- size_t size) {
+ socklen_t size) {
int r;
if (handle->flags & UV_HANDLE_IPV6)
@@ -875,7 +1211,7 @@ int uv_udp_set_multicast_loop(uv_udp_t* handle, int on) {
* and use the general uv__setsockopt_maybe_char call otherwise.
*/
#if defined(__sun) || defined(_AIX) || defined(__OpenBSD__) || \
- defined(__MVS__)
+ defined(__MVS__)
if (handle->flags & UV_HANDLE_IPV6)
return uv__setsockopt(handle,
IP_MULTICAST_LOOP,