From 5d2944d7b65840766bd8c4efef0af4e2680c0166 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Tue, 3 Dec 2019 22:19:16 -0500 Subject: deps: upgrade to libuv 1.34.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-By: Daniel Bevenius Reviewed-By: Richard Lau Reviewed-By: Santiago Gimeno Reviewed-By: Jiawen Geng Reviewed-By: Rich Trott Reviewed-By: Trivikram Kamat Reviewed-By: Michael Dawson Reviewed-By: Ben Noordhuis --- deps/uv/src/unix/aix-common.c | 114 +++++++++++++++++++++-------- deps/uv/src/unix/core.c | 14 ++++ deps/uv/src/unix/fs.c | 129 +++++++++++++++++++++++++++++---- deps/uv/src/unix/netbsd.c | 23 ++++++ deps/uv/src/unix/os390-syscalls.c | 23 ++++-- deps/uv/src/unix/random-devurandom.c | 8 +- deps/uv/src/unix/random-sysctl-linux.c | 99 +++++++++++++++++++++++++ deps/uv/src/unix/random-sysctl.c | 100 ------------------------- 8 files changed, 351 insertions(+), 159 deletions(-) create mode 100644 deps/uv/src/unix/random-sysctl-linux.c delete mode 100644 deps/uv/src/unix/random-sysctl.c (limited to 'deps/uv/src/unix') 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 #include #include +#include #include #include @@ -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 +#include #include #include #include @@ -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 #include -#include #include #include #include +#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-linux.c b/deps/uv/src/unix/random-sysctl-linux.c new file mode 100644 index 0000000000..66ba8d74ec --- /dev/null +++ b/deps/uv/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 +#include + +#include +#include + + +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/deps/uv/src/unix/random-sysctl.c b/deps/uv/src/unix/random-sysctl.c deleted file mode 100644 index fb182ded09..0000000000 --- a/deps/uv/src/unix/random-sysctl.c +++ /dev/null @@ -1,100 +0,0 @@ -/* 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 -#include - -#include -#include - - -struct uv__sysctl_args { - int* name; - int nlen; - void* oldval; - size_t* oldlenp; - void* newval; - size_t newlen; - unsigned long unused[4]; -}; - - -/* 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; - 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; -} -- cgit v1.2.3