summaryrefslogtreecommitdiff
path: root/deps/uv/src/unix
diff options
context:
space:
mode:
authorcjihrig <cjihrig@gmail.com>2019-12-03 22:19:16 -0500
committercjihrig <cjihrig@gmail.com>2019-12-06 11:14:59 -0500
commit5d2944d7b65840766bd8c4efef0af4e2680c0166 (patch)
tree76d1bd0017ca8667aeb34767fec599cdf414121d /deps/uv/src/unix
parent09ea00b0c117d219ec7017e7125601e9e26f84b9 (diff)
downloadandroid-node-v8-5d2944d7b65840766bd8c4efef0af4e2680c0166.tar.gz
android-node-v8-5d2944d7b65840766bd8c4efef0af4e2680c0166.tar.bz2
android-node-v8-5d2944d7b65840766bd8c4efef0af4e2680c0166.zip
deps: upgrade to libuv 1.34.0
Notable changes: - Fix handling of large files in uv_fs_copyfile(). Fixes: https://github.com/nodejs/node/issues/30085 - Fix Android build errors. - uv_sleep() has been added. - uv_interface_addresses() IPv6 netmask support has been fixed. Fixes: https://github.com/nodejs/node/issues/30504 - uv_fs_mkstemp() has been added. PR-URL: https://github.com/nodejs/node/pull/30783 Fixes: https://github.com/nodejs/node/issues/30085 Fixes: https://github.com/nodejs/node/issues/30504 Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com> Reviewed-By: Richard Lau <riclau@uk.ibm.com> Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com> Reviewed-By: Jiawen Geng <technicalcute@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com> Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'deps/uv/src/unix')
-rw-r--r--deps/uv/src/unix/aix-common.c114
-rw-r--r--deps/uv/src/unix/core.c14
-rw-r--r--deps/uv/src/unix/fs.c129
-rw-r--r--deps/uv/src/unix/netbsd.c23
-rw-r--r--deps/uv/src/unix/os390-syscalls.c23
-rw-r--r--deps/uv/src/unix/random-devurandom.c8
-rw-r--r--deps/uv/src/unix/random-sysctl-linux.c (renamed from deps/uv/src/unix/random-sysctl.c)1
7 files changed, 252 insertions, 60 deletions
diff --git a/deps/uv/src/unix/aix-common.c b/deps/uv/src/unix/aix-common.c
index b9d313c0c5..e96e34c463 100644
--- a/deps/uv/src/unix/aix-common.c
+++ b/deps/uv/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>
@@ -158,28 +159,42 @@ int uv_exepath(char* buffer, size_t* size) {
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
uv_interface_address_t* address;
- int sockfd, inet6, size = 1;
+ 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))) {
- return UV__ERR(errno);
+ 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) {
- uv__close(sockfd);
- return UV__ERR(errno);
+ 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) {
- uv__close(sockfd);
- return UV__ERR(errno);
+ r = UV__ERR(errno);
+ goto cleanup;
}
#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p))
@@ -197,8 +212,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
- uv__close(sockfd);
- return UV__ERR(errno);
+ r = UV__ERR(errno);
+ goto cleanup;
}
if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
@@ -207,16 +222,14 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
(*count)++;
}
- if (*count == 0) {
- uv__close(sockfd);
- return 0;
- }
+ if (*count == 0)
+ goto cleanup;
/* Alloc the return interface structs */
- *addresses = uv__malloc(*count * sizeof(uv_interface_address_t));
+ *addresses = uv__calloc(*count, sizeof(**addresses));
if (!(*addresses)) {
- uv__close(sockfd);
- return UV_ENOMEM;
+ r = UV_ENOMEM;
+ goto cleanup;
}
address = *addresses;
@@ -233,10 +246,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
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 (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1)
+ goto syserror;
if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
continue;
@@ -250,28 +261,67 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
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
+ 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;
- uv__close(sockfd);
- return 0;
+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;
}
diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c
index ffce948c95..04999dce36 100644
--- a/deps/uv/src/unix/core.c
+++ b/deps/uv/src/unix/core.c
@@ -1555,3 +1555,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/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c
index b37cfbbc7a..be256bfca6 100644
--- a/deps/uv/src/unix/fs.c
+++ b/deps/uv/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>
@@ -258,6 +259,80 @@ static ssize_t uv__fs_mkdtemp(uv_fs_t* req) {
}
+static int uv__fs_mkstemp(uv_fs_t* req) {
+ int r;
+#ifdef O_CLOEXEC
+ int (*mkostemp_function)(char*, int);
+ 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;
+ }
+
+#ifdef O_CLOEXEC
+ if (no_cloexec_support == 0) {
+ *(int**)(&mkostemp_function) = 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();
+
+ if (mkostemp_function != NULL) {
+ r = mkostemp_function(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);
@@ -999,6 +1074,7 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
int err;
size_t bytes_to_send;
int64_t in_offset;
+ ssize_t bytes_written;
dstfd = -1;
err = 0;
@@ -1076,18 +1152,17 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
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:
@@ -1234,13 +1309,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;
}
@@ -1415,6 +1499,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));
@@ -1639,6 +1724,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,
@@ -1857,10 +1954,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;
diff --git a/deps/uv/src/unix/netbsd.c b/deps/uv/src/unix/netbsd.c
index cfe2c6a49d..690bd79ef9 100644
--- a/deps/uv/src/unix/netbsd.c
+++ b/deps/uv/src/unix/netbsd.c
@@ -234,3 +234,26 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
uv__free(cp_times);
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;
+
+ 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);
+
+ if (count != req)
+ return UV_EIO; /* Can't happen. */
+
+ p += count;
+ len -= count;
+ }
+
+ return 0;
+}
diff --git a/deps/uv/src/unix/os390-syscalls.c b/deps/uv/src/unix/os390-syscalls.c
index 1040d66979..d9abdebaee 100644
--- a/deps/uv/src/unix/os390-syscalls.c
+++ b/deps/uv/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)
@@ -350,27 +350,34 @@ 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)
+ errno = err;
- if(rem != NULL) {
+ if (rem != NULL && (rv == 0 || err == EINTR || err == EAGAIN)) {
rem->tv_nsec = nanorem;
rem->tv_sec = secrem;
}
- return 0;
+ return rv;
}
diff --git a/deps/uv/src/unix/random-devurandom.c b/deps/uv/src/unix/random-devurandom.c
index bfc40d20f8..9aa762e372 100644
--- a/deps/uv/src/unix/random-devurandom.c
+++ b/deps/uv/src/unix/random-devurandom.c
@@ -74,10 +74,10 @@ int uv__random_readpath(const char* path, void* buf, size_t buflen) {
static void uv__random_devurandom_init(void) {
char c;
- /* Linux's and NetBSD'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.
+ /* 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);
}
diff --git a/deps/uv/src/unix/random-sysctl.c b/deps/uv/src/unix/random-sysctl-linux.c
index fb182ded09..66ba8d74ec 100644
--- a/deps/uv/src/unix/random-sysctl.c
+++ b/deps/uv/src/unix/random-sysctl-linux.c
@@ -40,7 +40,6 @@ struct uv__sysctl_args {
};
-/* TODO(bnoordhuis) Use {CTL_KERN, KERN_ARND} on FreeBSD (and NetBSD?) */
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;