libuv 1.47.0.

git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4615 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
2023-11-07 17:30:39 +00:00
parent 889773c38d
commit ee9cb63327
226 changed files with 6648 additions and 6444 deletions

244
deps/libuv/src/idna.c vendored
View File

@ -1,4 +1,4 @@
/* Copyright (c) 2011, 2018 Ben Noordhuis <info@bnoordhuis.nl>
/* Copyright libuv contributors. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -18,11 +18,56 @@
*/
#include "uv.h"
#include "uv-common.h"
#include "idna.h"
#include <assert.h>
#include <string.h>
#include <limits.h> /* UINT_MAX */
static int32_t uv__wtf8_decode1(const char** input) {
uint32_t code_point;
uint8_t b1;
uint8_t b2;
uint8_t b3;
uint8_t b4;
b1 = **input;
if (b1 <= 0x7F)
return b1; /* ASCII code point */
if (b1 < 0xC2)
return -1; /* invalid: continuation byte */
code_point = b1;
b2 = *++*input;
if ((b2 & 0xC0) != 0x80)
return -1; /* invalid: not a continuation byte */
code_point = (code_point << 6) | (b2 & 0x3F);
if (b1 <= 0xDF)
return 0x7FF & code_point; /* two-byte character */
b3 = *++*input;
if ((b3 & 0xC0) != 0x80)
return -1; /* invalid: not a continuation byte */
code_point = (code_point << 6) | (b3 & 0x3F);
if (b1 <= 0xEF)
return 0xFFFF & code_point; /* three-byte character */
b4 = *++*input;
if ((b4 & 0xC0) != 0x80)
return -1; /* invalid: not a continuation byte */
code_point = (code_point << 6) | (b4 & 0x3F);
if (b1 <= 0xF4) {
code_point &= 0x1FFFFF;
if (code_point <= 0x10FFFF)
return code_point; /* four-byte character */
}
/* code point too large */
return -1;
}
static unsigned uv__utf8_decode1_slow(const char** p,
const char* pe,
unsigned a) {
@ -89,6 +134,7 @@ static unsigned uv__utf8_decode1_slow(const char** p,
return a;
}
unsigned uv__utf8_decode1(const char** p, const char* pe) {
unsigned a;
@ -102,6 +148,7 @@ unsigned uv__utf8_decode1(const char** p, const char* pe) {
return uv__utf8_decode1_slow(p, pe, a);
}
static int uv__idna_toascii_label(const char* s, const char* se,
char** d, char* de) {
static const char alphabet[] = "abcdefghijklmnopqrstuvwxyz0123456789";
@ -267,7 +314,8 @@ static int uv__idna_toascii_label(const char* s, const char* se,
return 0;
}
long uv__idna_toascii(const char* s, const char* se, char* d, char* de) {
ssize_t uv__idna_toascii(const char* s, const char* se, char* d, char* de) {
const char* si;
const char* st;
unsigned c;
@ -313,3 +361,195 @@ long uv__idna_toascii(const char* s, const char* se, char* d, char* de) {
return d - ds; /* Number of bytes written. */
}
ssize_t uv_wtf8_length_as_utf16(const char* source_ptr) {
size_t w_target_len = 0;
int32_t code_point;
do {
code_point = uv__wtf8_decode1(&source_ptr);
if (code_point < 0)
return -1;
if (code_point > 0xFFFF)
w_target_len++;
w_target_len++;
} while (*source_ptr++);
return w_target_len;
}
void uv_wtf8_to_utf16(const char* source_ptr,
uint16_t* w_target,
size_t w_target_len) {
int32_t code_point;
do {
code_point = uv__wtf8_decode1(&source_ptr);
/* uv_wtf8_length_as_utf16 should have been called and checked first. */
assert(code_point >= 0);
if (code_point > 0x10000) {
assert(code_point < 0x10FFFF);
*w_target++ = (((code_point - 0x10000) >> 10) + 0xD800);
*w_target++ = ((code_point - 0x10000) & 0x3FF) + 0xDC00;
w_target_len -= 2;
} else {
*w_target++ = code_point;
w_target_len -= 1;
}
} while (*source_ptr++);
assert(w_target_len == 0);
}
static int32_t uv__get_surrogate_value(const uint16_t* w_source_ptr,
ssize_t w_source_len) {
uint16_t u;
uint16_t next;
u = w_source_ptr[0];
if (u >= 0xD800 && u <= 0xDBFF && w_source_len != 1) {
next = w_source_ptr[1];
if (next >= 0xDC00 && next <= 0xDFFF)
return 0x10000 + ((u - 0xD800) << 10) + (next - 0xDC00);
}
return u;
}
size_t uv_utf16_length_as_wtf8(const uint16_t* w_source_ptr,
ssize_t w_source_len) {
size_t target_len;
int32_t code_point;
target_len = 0;
while (w_source_len) {
code_point = uv__get_surrogate_value(w_source_ptr, w_source_len);
/* Can be invalid UTF-8 but must be valid WTF-8. */
assert(code_point >= 0);
if (w_source_len < 0 && code_point == 0)
break;
if (code_point < 0x80)
target_len += 1;
else if (code_point < 0x800)
target_len += 2;
else if (code_point < 0x10000)
target_len += 3;
else {
target_len += 4;
w_source_ptr++;
if (w_source_len > 0)
w_source_len--;
}
w_source_ptr++;
if (w_source_len > 0)
w_source_len--;
}
return target_len;
}
int uv_utf16_to_wtf8(const uint16_t* w_source_ptr,
ssize_t w_source_len,
char** target_ptr,
size_t* target_len_ptr) {
size_t target_len;
char* target;
char* target_end;
int32_t code_point;
/* If *target_ptr is provided, then *target_len_ptr must be its length
* (excluding space for NUL), otherwise we will compute the target_len_ptr
* length and may return a new allocation in *target_ptr if target_ptr is
* provided. */
if (target_ptr == NULL || *target_ptr == NULL) {
target_len = uv_utf16_length_as_wtf8(w_source_ptr, w_source_len);
if (target_len_ptr != NULL)
*target_len_ptr = target_len;
} else {
target_len = *target_len_ptr;
}
if (target_ptr == NULL)
return 0;
if (*target_ptr == NULL) {
target = uv__malloc(target_len + 1);
if (target == NULL) {
return UV_ENOMEM;
}
*target_ptr = target;
} else {
target = *target_ptr;
}
target_end = target + target_len;
while (target != target_end && w_source_len) {
code_point = uv__get_surrogate_value(w_source_ptr, w_source_len);
/* Can be invalid UTF-8 but must be valid WTF-8. */
assert(code_point >= 0);
if (w_source_len < 0 && code_point == 0) {
w_source_len = 0;
break;
}
if (code_point < 0x80) {
*target++ = code_point;
} else if (code_point < 0x800) {
*target++ = 0xC0 | (code_point >> 6);
if (target == target_end)
break;
*target++ = 0x80 | (code_point & 0x3F);
} else if (code_point < 0x10000) {
*target++ = 0xE0 | (code_point >> 12);
if (target == target_end)
break;
*target++ = 0x80 | ((code_point >> 6) & 0x3F);
if (target == target_end)
break;
*target++ = 0x80 | (code_point & 0x3F);
} else {
*target++ = 0xF0 | (code_point >> 18);
if (target == target_end)
break;
*target++ = 0x80 | ((code_point >> 12) & 0x3F);
if (target == target_end)
break;
*target++ = 0x80 | ((code_point >> 6) & 0x3F);
if (target == target_end)
break;
*target++ = 0x80 | (code_point & 0x3F);
/* uv__get_surrogate_value consumed 2 input characters */
w_source_ptr++;
if (w_source_len > 0)
w_source_len--;
}
target_len = target - *target_ptr;
w_source_ptr++;
if (w_source_len > 0)
w_source_len--;
}
if (target != target_end && target_len_ptr != NULL)
/* Did not fill all of the provided buffer, so update the target_len_ptr
* output with the space used. */
*target_len_ptr = target - *target_ptr;
/* Check if input fit into target exactly. */
if (w_source_len < 0 && target == target_end && w_source_ptr[0] == 0)
w_source_len = 0;
*target++ = '\0';
/* Characters remained after filling the buffer, compute the remaining length now. */
if (w_source_len) {
if (target_len_ptr != NULL)
*target_len_ptr = target_len + uv_utf16_length_as_wtf8(w_source_ptr, w_source_len);
return UV_ENOBUFS;
}
return 0;
}

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2011, 2018 Ben Noordhuis <info@bnoordhuis.nl>
/* Copyright libuv contributors. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -26,6 +26,6 @@ unsigned uv__utf8_decode1(const char** p, const char* pe);
* is the number of bytes written to |d|, including the trailing nul byte.
* A return value < 0 is a libuv error code. |s| and |d| can not overlap.
*/
long uv__idna_toascii(const char* s, const char* se, char* d, char* de);
ssize_t uv__idna_toascii(const char* s, const char* se, char* d, char* de);
#endif /* UV_SRC_IDNA_H_ */

View File

@ -209,7 +209,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
if (cpuspeed == 0)
/* If sysctl hw.cputype == CPU_TYPE_ARM64, the correct value is unavailable
* from Apple, but we can hard-code it here to a plausible value. */
cpuspeed = 2400000000;
cpuspeed = 2400000000U;
if (host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numcpus,
(processor_info_array_t*)&info,
@ -235,7 +235,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
cpu_info->cpu_times.irq = 0;
cpu_info->model = uv__strdup(model);
cpu_info->speed = cpuspeed/1000000;
cpu_info->speed = (int)(cpuspeed / 1000000);
}
vm_deallocate(mach_task_self(), (vm_address_t)info, msg_type);

View File

@ -41,25 +41,10 @@
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <pthread.h>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
#if defined(__DragonFly__) || \
defined(__FreeBSD__) || \
defined(__OpenBSD__) || \
defined(__NetBSD__)
# define HAVE_PREADV 1
#else
# define HAVE_PREADV 0
#endif
/* preadv() and pwritev() were added in Android N (level 24) */
#if defined(__linux__) && !(defined(__ANDROID__) && __ANDROID_API__ < 24)
# define TRY_PREADV 1
#endif
#if defined(__linux__)
# include <sys/sendfile.h>
#endif
@ -97,6 +82,15 @@
# include <sys/statfs.h>
#endif
#if defined(__CYGWIN__) || \
(defined(__HAIKU__) && B_HAIKU_VERSION < B_HAIKU_VERSION_1_PRE_BETA_5) || \
(defined(__sun) && !defined(__illumos__))
#define preadv(fd, bufs, nbufs, off) \
pread(fd, (bufs)->iov_base, (bufs)->iov_len, off)
#define pwritev(fd, bufs, nbufs, off) \
pwrite(fd, (bufs)->iov_base, (bufs)->iov_len, off)
#endif
#if defined(_AIX) && _XOPEN_SOURCE <= 600
extern char *mkdtemp(char *template); /* See issue #740 on AIX < 7 */
#endif
@ -410,123 +404,57 @@ static ssize_t uv__fs_open(uv_fs_t* req) {
}
#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 TRY_PREADV
static _Atomic int no_preadv;
#endif
const struct iovec* bufs;
unsigned int iovmax;
ssize_t result;
size_t nbufs;
ssize_t r;
off_t off;
int fd;
fd = req->file;
off = req->off;
bufs = (const struct iovec*) req->bufs;
nbufs = req->nbufs;
iovmax = uv__getiovmax();
if (req->nbufs > iovmax)
req->nbufs = iovmax;
if (nbufs > iovmax)
nbufs = iovmax;
if (req->off < 0) {
if (req->nbufs == 1)
result = read(req->file, req->bufs[0].base, req->bufs[0].len);
else
result = readv(req->file, (struct iovec*) req->bufs, req->nbufs);
r = 0;
if (off < 0) {
if (nbufs == 1)
r = read(fd, bufs->iov_base, bufs->iov_len);
else if (nbufs > 1)
r = readv(fd, bufs, nbufs);
} else {
if (req->nbufs == 1) {
result = pread(req->file, req->bufs[0].base, req->bufs[0].len, req->off);
goto done;
}
#if HAVE_PREADV
result = preadv(req->file, (struct iovec*) req->bufs, req->nbufs, req->off);
#else
# if TRY_PREADV
if (atomic_load_explicit(&no_preadv, memory_order_relaxed)) retry:
# endif
{
result = uv__fs_preadv(req->file, req->bufs, req->nbufs, req->off);
}
# if TRY_PREADV
else {
result = preadv(req->file,
(struct iovec*) req->bufs,
req->nbufs,
req->off);
if (result == -1 && errno == ENOSYS) {
atomic_store_explicit(&no_preadv, 1, memory_order_relaxed);
goto retry;
}
}
# endif
#endif
if (nbufs == 1)
r = pread(fd, bufs->iov_base, bufs->iov_len, off);
else if (nbufs > 1)
r = preadv(fd, bufs, nbufs, off);
}
done:
/* Early cleanup of bufs allocation, since we're done with it. */
if (req->bufs != req->bufsml)
uv__free(req->bufs);
req->bufs = NULL;
req->nbufs = 0;
#ifdef __PASE__
/* PASE returns EOPNOTSUPP when reading a directory, convert to EISDIR */
if (result == -1 && errno == EOPNOTSUPP) {
if (r == -1 && errno == EOPNOTSUPP) {
struct stat buf;
ssize_t rc;
rc = uv__fstat(req->file, &buf);
rc = uv__fstat(fd, &buf);
if (rc == 0 && S_ISDIR(buf.st_mode)) {
errno = EISDIR;
}
}
#endif
return result;
/* We don't own the buffer list in the synchronous case. */
if (req->cb != NULL)
if (req->bufs != req->bufsml)
uv__free(req->bufs);
req->bufs = NULL;
req->nbufs = 0;
return r;
}
@ -1161,65 +1089,34 @@ static ssize_t uv__fs_lutime(uv_fs_t* req) {
static ssize_t uv__fs_write(uv_fs_t* req) {
#if TRY_PREADV
static _Atomic int no_pwritev;
#endif
const struct iovec* bufs;
size_t nbufs;
ssize_t r;
off_t off;
int fd;
/* Serialize writes on OS X, concurrent write() and pwrite() calls result in
* data loss. We can't use a per-file descriptor lock, the descriptor may be
* a dup().
*/
#if defined(__APPLE__)
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
fd = req->file;
off = req->off;
bufs = (const struct iovec*) req->bufs;
nbufs = req->nbufs;
if (pthread_mutex_lock(&lock))
abort();
#endif
if (req->off < 0) {
if (req->nbufs == 1)
r = write(req->file, req->bufs[0].base, req->bufs[0].len);
else
r = writev(req->file, (struct iovec*) req->bufs, req->nbufs);
r = 0;
if (off < 0) {
if (nbufs == 1)
r = write(fd, bufs->iov_base, bufs->iov_len);
else if (nbufs > 1)
r = writev(fd, bufs, nbufs);
} else {
if (req->nbufs == 1) {
r = pwrite(req->file, req->bufs[0].base, req->bufs[0].len, req->off);
goto done;
}
#if HAVE_PREADV
r = pwritev(req->file, (struct iovec*) req->bufs, req->nbufs, req->off);
#else
# if TRY_PREADV
if (atomic_load_explicit(&no_pwritev, memory_order_relaxed)) retry:
# endif
{
r = pwrite(req->file, req->bufs[0].base, req->bufs[0].len, req->off);
}
# if TRY_PREADV
else {
r = pwritev(req->file,
(struct iovec*) req->bufs,
req->nbufs,
req->off);
if (r == -1 && errno == ENOSYS) {
atomic_store_explicit(&no_pwritev, 1, memory_order_relaxed);
goto retry;
}
}
# endif
#endif
if (nbufs == 1)
r = pwrite(fd, bufs->iov_base, bufs->iov_len, off);
else if (nbufs > 1)
r = pwritev(fd, bufs, nbufs, off);
}
done:
#if defined(__APPLE__)
if (pthread_mutex_unlock(&lock))
abort();
#endif
return r;
}
static ssize_t uv__fs_copyfile(uv_fs_t* req) {
uv_fs_t fs_req;
uv_file srcfd;
@ -1979,9 +1876,14 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req,
if (bufs == NULL || nbufs == 0)
return UV_EINVAL;
req->off = off;
req->file = file;
req->bufs = (uv_buf_t*) bufs; /* Safe, doesn't mutate |bufs| */
req->nbufs = nbufs;
if (cb == NULL)
goto post;
req->bufs = req->bufsml;
if (nbufs > ARRAY_SIZE(req->bufsml))
req->bufs = uv__malloc(nbufs * sizeof(*bufs));
@ -1991,12 +1893,10 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req,
memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
req->off = off;
if (cb != NULL)
if (uv__iou_fs_read_or_write(loop, req, /* is_read */ 1))
return 0;
if (uv__iou_fs_read_or_write(loop, req, /* is_read */ 1))
return 0;
post:
POST;
}

View File

@ -30,6 +30,9 @@
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#if defined(__FreeBSD__)
#include <sys/user.h>
#endif
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
@ -262,6 +265,9 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
if (nfds == -1)
assert(errno == EINTR);
else if (nfds == 0)
/* Unlimited timeout should only return with events or signal. */
assert(timeout != -1);
if (pset != NULL)
pthread_sigmask(SIG_UNBLOCK, pset, NULL);
@ -286,8 +292,6 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
timeout = user_timeout;
reset_timeout = 0;
} else if (nfds == 0) {
/* Reached the user timeout value. */
assert(timeout != -1);
return;
}
@ -479,6 +483,16 @@ static void uv__fs_event(uv_loop_t* loop, uv__io_t* w, unsigned int fflags) {
*/
if (fcntl(handle->event_watcher.fd, F_GETPATH, pathbuf) == 0)
path = uv__basename_r(pathbuf);
#elif defined(F_KINFO)
/* We try to get the file info reference from the file descriptor.
* the struct's kf_structsize must be initialised beforehand
* whether with the KINFO_FILE_SIZE constant or this way.
*/
struct kinfo_file kf;
kf.kf_structsize = sizeof(kf);
if (fcntl(handle->event_watcher.fd, F_KINFO, &kf) == 0)
path = uv__basename_r(kf.kf_path);
#endif
handle->cb(handle, path, events, 0);

View File

@ -79,6 +79,8 @@
# define __NR_copy_file_range 379
# elif defined(__arc__)
# define __NR_copy_file_range 285
# elif defined(__riscv)
# define __NR_copy_file_range 285
# endif
#endif /* __NR_copy_file_range */
@ -95,6 +97,8 @@
# define __NR_statx 383
# elif defined(__s390__)
# define __NR_statx 379
# elif defined(__riscv)
# define __NR_statx 291
# endif
#endif /* __NR_statx */
@ -111,6 +115,8 @@
# define __NR_getrandom 359
# elif defined(__s390__)
# define __NR_getrandom 349
# elif defined(__riscv)
# define __NR_getrandom 278
# endif
#endif /* __NR_getrandom */
@ -317,17 +323,64 @@ unsigned uv__kernel_version(void) {
unsigned major;
unsigned minor;
unsigned patch;
char v_sig[256];
char* needle;
version = atomic_load_explicit(&cached_version, memory_order_relaxed);
if (version != 0)
return version;
/* Check /proc/version_signature first as it's the way to get the mainline
* kernel version in Ubuntu. The format is:
* Ubuntu ubuntu_kernel_version mainline_kernel_version
* For example:
* Ubuntu 5.15.0-79.86-generic 5.15.111
*/
if (0 == uv__slurp("/proc/version_signature", v_sig, sizeof(v_sig)))
if (3 == sscanf(v_sig, "Ubuntu %*s %u.%u.%u", &major, &minor, &patch))
goto calculate_version;
if (-1 == uname(&u))
return 0;
/* In Debian we need to check `version` instead of `release` to extract the
* mainline kernel version. This is an example of how it looks like:
* #1 SMP Debian 5.10.46-4 (2021-08-03)
*/
needle = strstr(u.version, "Debian ");
if (needle != NULL)
if (3 == sscanf(needle, "Debian %u.%u.%u", &major, &minor, &patch))
goto calculate_version;
if (3 != sscanf(u.release, "%u.%u.%u", &major, &minor, &patch))
return 0;
/* Handle it when the process runs under the UNAME26 personality:
*
* - kernels >= 3.x identify as 2.6.40+x
* - kernels >= 4.x identify as 2.6.60+x
*
* UNAME26 is a poorly conceived hack that doesn't let us distinguish
* between 4.x kernels and 5.x/6.x kernels so we conservatively assume
* that 2.6.60+x means 4.x.
*
* Fun fact of the day: it's technically possible to observe the actual
* kernel version for a brief moment because uname() first copies out the
* real release string before overwriting it with the backcompat string.
*/
if (major == 2 && minor == 6) {
if (patch >= 60) {
major = 4;
minor = patch - 60;
patch = 0;
} else if (patch >= 40) {
major = 3;
minor = patch - 40;
patch = 0;
}
}
calculate_version:
version = major * 65536 + minor * 256 + patch;
atomic_store_explicit(&cached_version, version, memory_order_relaxed);
@ -422,6 +475,9 @@ int uv__io_uring_register(int fd, unsigned opcode, void* arg, unsigned nargs) {
static int uv__use_io_uring(void) {
#if defined(__ANDROID_API__)
return 0; /* Possibly available but blocked by seccomp. */
#elif defined(__arm__) && __SIZEOF_POINTER__ == 4
/* See https://github.com/libuv/libuv/issues/4158. */
return 0; /* All 32 bits kernels appear buggy. */
#else
/* Ternary: unknown=0, yes=1, no=-1 */
static _Atomic int use_io_uring;
@ -431,8 +487,14 @@ static int uv__use_io_uring(void) {
use = atomic_load_explicit(&use_io_uring, memory_order_relaxed);
if (use == 0) {
/* Older kernels have a bug where the sqpoll thread uses 100% CPU. */
use = uv__kernel_version() >= /* 5.10.186 */ 0x050ABA ? 1 : -1;
/* But users can still enable it if they so desire. */
val = getenv("UV_USE_IO_URING");
use = val == NULL || atoi(val) ? 1 : -1;
if (val != NULL)
use = atoi(val) ? 1 : -1;
atomic_store_explicit(&use_io_uring, use, memory_order_relaxed);
}
@ -756,7 +818,9 @@ static void uv__iou_submit(struct uv__iou* iou) {
int uv__iou_fs_close(uv_loop_t* loop, uv_fs_t* req) {
struct uv__io_uring_sqe* sqe;
struct uv__iou* iou;
int kv;
kv = uv__kernel_version();
/* Work around a poorly understood bug in older kernels where closing a file
* descriptor pointing to /foo/bar results in ETXTBSY errors when trying to
* execve("/foo/bar") later on. The bug seems to have been fixed somewhere
@ -764,10 +828,17 @@ int uv__iou_fs_close(uv_loop_t* loop, uv_fs_t* req) {
* but good candidates are the several data race fixes. Interestingly, it
* seems to manifest only when running under Docker so the possibility of
* a Docker bug can't be completely ruled out either. Yay, computers.
* Also, disable on non-longterm versions between 5.16.0 (non-longterm) and
* 6.1.0 (longterm). Starting with longterm 6.1.x, the issue seems to be
* solved.
*/
if (uv__kernel_version() < /* 5.15.90 */ 0x050F5A)
if (kv < /* 5.15.90 */ 0x050F5A)
return 0;
if (kv >= /* 5.16.0 */ 0x050A00 && kv < /* 6.1.0 */ 0x060100)
return 0;
iou = &uv__get_internal_fields(loop)->iou;
sqe = uv__iou_get_sqe(iou, loop, req);
@ -1364,41 +1435,20 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
*/
SAVE_ERRNO(uv__update_time(loop));
if (nfds == 0) {
if (nfds == -1)
assert(errno == EINTR);
else if (nfds == 0)
/* Unlimited timeout should only return with events or signal. */
assert(timeout != -1);
if (nfds == 0 || nfds == -1) {
if (reset_timeout != 0) {
timeout = user_timeout;
reset_timeout = 0;
} else if (nfds == 0) {
return;
}
if (timeout == -1)
continue;
if (timeout == 0)
break;
/* We may have been inside the system call for longer than |timeout|
* milliseconds so we need to update the timestamp to avoid drift.
*/
goto update_timeout;
}
if (nfds == -1) {
if (errno != EINTR)
abort();
if (reset_timeout != 0) {
timeout = user_timeout;
reset_timeout = 0;
}
if (timeout == -1)
continue;
if (timeout == 0)
break;
/* Interrupted by a signal. Update timeout and poll again. */
goto update_timeout;
}
@ -1509,13 +1559,13 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
break;
}
update_timeout:
if (timeout == 0)
break;
if (timeout == -1)
continue;
update_timeout:
assert(timeout > 0);
real_timeout -= (loop->time - base);
@ -1718,7 +1768,8 @@ int uv_cpu_info(uv_cpu_info_t** ci, int* count) {
return UV__ERR(errno);
}
fgets(buf, sizeof(buf), fp); /* Skip first line. */
if (NULL == fgets(buf, sizeof(buf), fp))
abort();
for (;;) {
memset(&t, 0, sizeof(t));
@ -1729,7 +1780,8 @@ int uv_cpu_info(uv_cpu_info_t** ci, int* count) {
if (n != 7)
break;
fgets(buf, sizeof(buf), fp); /* Skip rest of line. */
if (NULL == fgets(buf, sizeof(buf), fp))
abort();
if (cpu >= ARRAY_SIZE(*cpus))
continue;
@ -1809,7 +1861,8 @@ nocpuinfo:
if (fp == NULL)
continue;
fscanf(fp, "%llu", &(*cpus)[cpu].freq);
if (1 != fscanf(fp, "%llu", &(*cpus)[cpu].freq))
abort();
fclose(fp);
fp = NULL;
}

View File

@ -19,6 +19,7 @@
* IN THE SOFTWARE.
*/
#include "uv.h"
#include "internal.h"
#include <sys/ioctl.h>
#include <net/if.h>
@ -30,6 +31,7 @@
#include <sys/msg.h>
#include <sys/resource.h>
#include "zos-base.h"
#include "zos-sys-info.h"
#if defined(__clang__)
#include "csrsic.h"
#else
@ -66,9 +68,6 @@
/* Total number of frames currently on all available frame queues. */
#define RCEAFC_OFFSET 0x088
/* CPC model length from the CSRSI Service. */
#define CPCMODEL_LENGTH 16
/* Pointer to the home (current) ASCB. */
#define PSAAOLD 0x224
@ -258,9 +257,12 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
idx = 0;
while (idx < *count) {
cpu_info->speed = *(int*)(info.siv1v2si22v1.si22v1cpucapability);
cpu_info->model = uv__malloc(CPCMODEL_LENGTH + 1);
memset(cpu_info->model, '\0', CPCMODEL_LENGTH + 1);
memcpy(cpu_info->model, info.siv1v2si11v1.si11v1cpcmodel, CPCMODEL_LENGTH);
cpu_info->model = uv__malloc(ZOSCPU_MODEL_LENGTH + 1);
if (cpu_info->model == NULL) {
uv_free_cpu_info(*cpu_infos, idx);
return UV_ENOMEM;
}
__get_cpu_model(cpu_info->model, ZOSCPU_MODEL_LENGTH + 1);
cpu_info->cpu_times.user = cpu_usage_avg;
/* TODO: implement the following */
cpu_info->cpu_times.sys = 0;

View File

@ -279,6 +279,8 @@ static int uv__signal_loop_once_init(uv_loop_t* loop) {
int uv__signal_loop_fork(uv_loop_t* loop) {
struct uv__queue* q;
if (loop->signal_pipefd[0] == -1)
return 0;
uv__io_stop(loop, &loop->signal_io_watcher, POLLIN);
@ -286,6 +288,19 @@ int uv__signal_loop_fork(uv_loop_t* loop) {
uv__close(loop->signal_pipefd[1]);
loop->signal_pipefd[0] = -1;
loop->signal_pipefd[1] = -1;
uv__queue_foreach(q, &loop->handle_queue) {
uv_handle_t* handle = uv__queue_data(q, uv_handle_t, handle_queue);
uv_signal_t* sh;
if (handle->type != UV_SIGNAL)
continue;
sh = (uv_signal_t*) handle;
sh->caught_signals = 0;
sh->dispatched_signals = 0;
}
return uv__signal_loop_once_init(loop);
}

View File

@ -27,6 +27,17 @@
#include <assert.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#if defined(__PASE__)
#include <as400_protos.h>
#define ifaddrs ifaddrs_pase
#define getifaddrs Qp2getifaddrs
#define freeifaddrs Qp2freeifaddrs
#else
#include <ifaddrs.h>
#endif
static int maybe_bind_socket(int fd) {
union uv__sockaddr s;
@ -198,11 +209,50 @@ int uv__tcp_bind(uv_tcp_t* tcp,
}
static int uv__is_ipv6_link_local(const struct sockaddr* addr) {
const struct sockaddr_in6* a6;
uint8_t b[2];
if (addr->sa_family != AF_INET6)
return 0;
a6 = (const struct sockaddr_in6*) addr;
memcpy(b, &a6->sin6_addr, sizeof(b));
return b[0] == 0xFE && b[1] == 0x80;
}
static int uv__ipv6_link_local_scope_id(void) {
struct sockaddr_in6* a6;
struct ifaddrs* ifa;
struct ifaddrs* p;
int rv;
if (getifaddrs(&ifa))
return 0;
for (p = ifa; p != NULL; p = p->ifa_next)
if (uv__is_ipv6_link_local(p->ifa_addr))
break;
rv = 0;
if (p != NULL) {
a6 = (struct sockaddr_in6*) p->ifa_addr;
rv = a6->sin6_scope_id;
}
freeifaddrs(ifa);
return rv;
}
int uv__tcp_connect(uv_connect_t* req,
uv_tcp_t* handle,
const struct sockaddr* addr,
unsigned int addrlen,
uv_connect_cb cb) {
struct sockaddr_in6 tmp6;
int err;
int r;
@ -220,6 +270,14 @@ int uv__tcp_connect(uv_connect_t* req,
if (err)
return err;
if (uv__is_ipv6_link_local(addr)) {
memcpy(&tmp6, addr, sizeof(tmp6));
if (tmp6.sin6_scope_id == 0) {
tmp6.sin6_scope_id = uv__ipv6_link_local_scope_id();
addr = (void*) &tmp6;
}
}
do {
errno = 0;
r = connect(uv__stream_fd(handle), addr, addrlen);
@ -374,28 +432,39 @@ int uv__tcp_nodelay(int fd, int on) {
int uv__tcp_keepalive(int fd, int on, unsigned int delay) {
int intvl;
int cnt;
(void) &intvl;
(void) &cnt;
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)))
return UV__ERR(errno);
if (!on)
return 0;
#ifdef TCP_KEEPIDLE
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);
}
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &delay, sizeof(delay)))
return UV__ERR(errno);
/* Solaris/SmartOS, if you don't support keep-alive,
* then don't advertise it in your system headers...
*/
/* FIXME(bnoordhuis) That's possibly because sizeof(delay) should be 1. */
#elif defined(TCP_KEEPALIVE) && !defined(__sun)
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &delay, sizeof(delay)))
return UV__ERR(errno);
#endif
/* Solaris/SmartOS, if you don't support keep-alive,
* then don't advertise it in your system headers...
*/
/* FIXME(bnoordhuis) That's possibly because sizeof(delay) should be 1. */
#if defined(TCP_KEEPALIVE) && !defined(__sun)
if (on && setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &delay, sizeof(delay)))
#ifdef TCP_KEEPINTVL
intvl = 1; /* 1 second; same as default on Win32 */
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl)))
return UV__ERR(errno);
#endif
#ifdef TCP_KEEPCNT
cnt = 10; /* 10 retries; same as hardcoded on Win32 */
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt)))
return UV__ERR(errno);
#endif

View File

@ -789,11 +789,33 @@ void uv_cond_broadcast(uv_cond_t* cond) {
abort();
}
#if defined(__APPLE__) && defined(__MACH__)
void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
int r;
errno = 0;
r = pthread_cond_wait(cond, mutex);
/* Workaround for a bug in OS X at least up to 13.6
* See https://github.com/libuv/libuv/issues/4165
*/
if (r == EINVAL)
if (errno == EBUSY)
return;
if (r)
abort();
}
#else /* !(defined(__APPLE__) && defined(__MACH__)) */
void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
if (pthread_cond_wait(cond, mutex))
abort();
}
#endif
int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) {
int r;

View File

@ -559,6 +559,9 @@ static void uv__print_handles(uv_loop_t* loop, int only_active, FILE* stream) {
if (loop == NULL)
loop = uv_default_loop();
if (stream == NULL)
stream = stderr;
uv__queue_foreach(q, &loop->handle_queue) {
h = uv__queue_data(q, uv_handle_t, handle_queue);

View File

@ -27,18 +27,17 @@ static int uv__dlerror(uv_lib_t* lib, const char* filename, DWORD errorno);
int uv_dlopen(const char* filename, uv_lib_t* lib) {
WCHAR filename_w[32768];
ssize_t r;
lib->handle = NULL;
lib->errmsg = NULL;
if (!MultiByteToWideChar(CP_UTF8,
0,
filename,
-1,
filename_w,
ARRAY_SIZE(filename_w))) {
return uv__dlerror(lib, filename, GetLastError());
}
r = uv_wtf8_length_as_utf16(filename);
if (r < 0)
return uv__dlerror(lib, filename, ERROR_NO_UNICODE_TRANSLATION);
if ((size_t) r > ARRAY_SIZE(filename_w))
return uv__dlerror(lib, filename, ERROR_INSUFFICIENT_BUFFER);
uv_wtf8_to_utf16(filename, filename_w, r);
lib->handle = LoadLibraryExW(filename_w, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
if (lib->handle == NULL) {

View File

@ -157,7 +157,8 @@ int uv_fs_event_start(uv_fs_event_t* handle,
uv_fs_event_cb cb,
const char* path,
unsigned int flags) {
int name_size, is_path_dir, size;
int is_path_dir;
size_t size;
DWORD attr, last_error;
WCHAR* dir = NULL, *dir_to_watch, *pathw = NULL;
DWORD short_path_buffer_len;
@ -176,23 +177,9 @@ int uv_fs_event_start(uv_fs_event_t* handle,
uv__handle_start(handle);
/* Convert name to UTF16. */
name_size = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0) *
sizeof(WCHAR);
pathw = (WCHAR*)uv__malloc(name_size);
if (!pathw) {
uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
if (!MultiByteToWideChar(CP_UTF8,
0,
path,
-1,
pathw,
name_size / sizeof(WCHAR))) {
return uv_translate_sys_error(GetLastError());
}
last_error = uv__convert_utf8_to_utf16(path, &pathw);
if (last_error)
goto error_uv;
/* Determine whether path is a file or a directory. */
attr = GetFileAttributesW(pathw);
@ -333,6 +320,9 @@ short_path_done:
return 0;
error:
last_error = uv_translate_sys_error(last_error);
error_uv:
if (handle->path) {
uv__free(handle->path);
handle->path = NULL;
@ -365,7 +355,7 @@ error:
uv__free(short_path);
return uv_translate_sys_error(last_error);
return last_error;
}

View File

@ -31,13 +31,16 @@
#include <stdio.h>
#include "uv.h"
/* <winioctl.h> requires <windows.h>, included via "uv.h" above, but needs to
be included before our "winapi.h", included via "internal.h" below. */
#include <winioctl.h>
#include "internal.h"
#include "req-inl.h"
#include "handle-inl.h"
#include "fs-fd-hash-inl.h"
#include <winioctl.h>
#define UV_FS_FREE_PATHS 0x0002
#define UV_FS_FREE_PTR 0x0008
@ -144,279 +147,6 @@ void uv__fs_init(void) {
}
static int32_t fs__decode_wtf8_char(const char** input) {
uint32_t code_point;
uint8_t b1;
uint8_t b2;
uint8_t b3;
uint8_t b4;
b1 = **input;
if (b1 <= 0x7F)
return b1; /* ASCII code point */
if (b1 < 0xC2)
return -1; /* invalid: continuation byte */
code_point = b1;
b2 = *++*input;
if ((b2 & 0xC0) != 0x80)
return -1; /* invalid: not a continuation byte */
code_point = (code_point << 6) | (b2 & 0x3F);
if (b1 <= 0xDF)
return 0x7FF & code_point; /* two-byte character */
b3 = *++*input;
if ((b3 & 0xC0) != 0x80)
return -1; /* invalid: not a continuation byte */
code_point = (code_point << 6) | (b3 & 0x3F);
if (b1 <= 0xEF)
return 0xFFFF & code_point; /* three-byte character */
b4 = *++*input;
if ((b4 & 0xC0) != 0x80)
return -1; /* invalid: not a continuation byte */
code_point = (code_point << 6) | (b4 & 0x3F);
if (b1 <= 0xF4)
if (code_point <= 0x10FFFF)
return code_point; /* four-byte character */
/* code point too large */
return -1;
}
static ssize_t fs__get_length_wtf8(const char* source_ptr) {
size_t w_target_len = 0;
int32_t code_point;
do {
code_point = fs__decode_wtf8_char(&source_ptr);
if (code_point < 0)
return -1;
if (code_point > 0xFFFF)
w_target_len++;
w_target_len++;
} while (*source_ptr++);
return w_target_len;
}
static void fs__wtf8_to_wide(const char* source_ptr, WCHAR* w_target) {
int32_t code_point;
do {
code_point = fs__decode_wtf8_char(&source_ptr);
/* fs__get_length_wtf8 should have been called and checked first. */
assert(code_point >= 0);
if (code_point > 0x10000) {
assert(code_point < 0x10FFFF);
*w_target++ = (((code_point - 0x10000) >> 10) + 0xD800);
*w_target++ = ((code_point - 0x10000) & 0x3FF) + 0xDC00;
} else {
*w_target++ = code_point;
}
} while (*source_ptr++);
}
INLINE static int fs__capture_path(uv_fs_t* req, const char* path,
const char* new_path, const int copy_path) {
WCHAR* buf;
WCHAR* pos;
size_t buf_sz = 0;
size_t path_len = 0;
ssize_t pathw_len = 0;
ssize_t new_pathw_len = 0;
/* new_path can only be set if path is also set. */
assert(new_path == NULL || path != NULL);
if (path != NULL) {
pathw_len = fs__get_length_wtf8(path);
if (pathw_len < 0)
return ERROR_INVALID_NAME;
buf_sz += pathw_len * sizeof(WCHAR);
}
if (path != NULL && copy_path) {
path_len = 1 + strlen(path);
buf_sz += path_len;
}
if (new_path != NULL) {
new_pathw_len = fs__get_length_wtf8(new_path);
if (new_pathw_len < 0)
return ERROR_INVALID_NAME;
buf_sz += new_pathw_len * sizeof(WCHAR);
}
if (buf_sz == 0) {
req->file.pathw = NULL;
req->fs.info.new_pathw = NULL;
req->path = NULL;
return 0;
}
buf = uv__malloc(buf_sz);
if (buf == NULL) {
return ERROR_OUTOFMEMORY;
}
pos = buf;
if (path != NULL) {
fs__wtf8_to_wide(path, pos);
req->file.pathw = pos;
pos += pathw_len;
} else {
req->file.pathw = NULL;
}
if (new_path != NULL) {
fs__wtf8_to_wide(new_path, pos);
req->fs.info.new_pathw = pos;
pos += new_pathw_len;
} else {
req->fs.info.new_pathw = NULL;
}
req->path = path;
if (path != NULL && copy_path) {
memcpy(pos, path, path_len);
assert(path_len == buf_sz - (pos - buf) * sizeof(WCHAR));
req->path = (char*) pos;
}
req->flags |= UV_FS_FREE_PATHS;
return 0;
}
INLINE static void uv__fs_req_init(uv_loop_t* loop, uv_fs_t* req,
uv_fs_type fs_type, const uv_fs_cb cb) {
uv__once_init();
UV_REQ_INIT(req, UV_FS);
req->loop = loop;
req->flags = 0;
req->fs_type = fs_type;
req->sys_errno_ = 0;
req->result = 0;
req->ptr = NULL;
req->path = NULL;
req->cb = cb;
memset(&req->fs, 0, sizeof(req->fs));
}
static int32_t fs__get_surrogate_value(const WCHAR* w_source_ptr,
size_t w_source_len) {
WCHAR u;
WCHAR next;
u = w_source_ptr[0];
if (u >= 0xD800 && u <= 0xDBFF && w_source_len > 1) {
next = w_source_ptr[1];
if (next >= 0xDC00 && next <= 0xDFFF)
return 0x10000 + ((u - 0xD800) << 10) + (next - 0xDC00);
}
return u;
}
static size_t fs__get_length_wide(const WCHAR* w_source_ptr,
size_t w_source_len) {
size_t target_len;
int32_t code_point;
target_len = 0;
for (; w_source_len; w_source_len--, w_source_ptr++) {
code_point = fs__get_surrogate_value(w_source_ptr, w_source_len);
/* Can be invalid UTF-8 but must be valid WTF-8. */
assert(code_point >= 0);
if (code_point < 0x80)
target_len += 1;
else if (code_point < 0x800)
target_len += 2;
else if (code_point < 0x10000)
target_len += 3;
else {
target_len += 4;
w_source_ptr++;
w_source_len--;
}
}
return target_len;
}
static int fs__wide_to_wtf8(WCHAR* w_source_ptr,
size_t w_source_len,
char** target_ptr,
size_t* target_len_ptr) {
size_t target_len;
char* target;
int32_t code_point;
/* If *target_ptr is provided, then *target_len_ptr must be its length
* (excluding space for null), otherwise we will compute the target_len_ptr
* length and may return a new allocation in *target_ptr if target_ptr is
* provided. */
if (target_ptr == NULL || *target_ptr == NULL) {
target_len = fs__get_length_wide(w_source_ptr, w_source_len);
if (target_len_ptr != NULL)
*target_len_ptr = target_len;
} else {
target_len = *target_len_ptr;
}
if (target_ptr == NULL)
return 0;
if (*target_ptr == NULL) {
target = uv__malloc(target_len + 1);
if (target == NULL) {
SetLastError(ERROR_OUTOFMEMORY);
return -1;
}
*target_ptr = target;
} else {
target = *target_ptr;
}
for (; w_source_len; w_source_len--, w_source_ptr++) {
code_point = fs__get_surrogate_value(w_source_ptr, w_source_len);
/* Can be invalid UTF-8 but must be valid WTF-8. */
assert(code_point >= 0);
if (code_point < 0x80) {
*target++ = code_point;
} else if (code_point < 0x800) {
*target++ = 0xC0 | (code_point >> 6);
*target++ = 0x80 | (code_point & 0x3F);
} else if (code_point < 0x10000) {
*target++ = 0xE0 | (code_point >> 12);
*target++ = 0x80 | ((code_point >> 6) & 0x3F);
*target++ = 0x80 | (code_point & 0x3F);
} else {
*target++ = 0xF0 | (code_point >> 18);
*target++ = 0x80 | ((code_point >> 12) & 0x3F);
*target++ = 0x80 | ((code_point >> 6) & 0x3F);
*target++ = 0x80 | (code_point & 0x3F);
w_source_ptr++;
w_source_len--;
}
}
assert((size_t) (target - *target_ptr) == target_len);
*target++ = '\0';
return 0;
}
INLINE static int fs__readlink_handle(HANDLE handle,
char** target_ptr,
size_t* target_len_ptr) {
@ -550,7 +280,98 @@ INLINE static int fs__readlink_handle(HANDLE handle,
}
assert(target_ptr == NULL || *target_ptr == NULL);
return fs__wide_to_wtf8(w_target, w_target_len, target_ptr, target_len_ptr);
return uv_utf16_to_wtf8(w_target, w_target_len, target_ptr, target_len_ptr);
}
INLINE static int fs__capture_path(uv_fs_t* req, const char* path,
const char* new_path, const int copy_path) {
WCHAR* buf;
WCHAR* pos;
size_t buf_sz = 0;
size_t path_len = 0;
ssize_t pathw_len = 0;
ssize_t new_pathw_len = 0;
/* new_path can only be set if path is also set. */
assert(new_path == NULL || path != NULL);
if (path != NULL) {
pathw_len = uv_wtf8_length_as_utf16(path);
if (pathw_len < 0)
return ERROR_INVALID_NAME;
buf_sz += pathw_len * sizeof(WCHAR);
}
if (path != NULL && copy_path) {
path_len = 1 + strlen(path);
buf_sz += path_len;
}
if (new_path != NULL) {
new_pathw_len = uv_wtf8_length_as_utf16(new_path);
if (new_pathw_len < 0)
return ERROR_INVALID_NAME;
buf_sz += new_pathw_len * sizeof(WCHAR);
}
if (buf_sz == 0) {
req->file.pathw = NULL;
req->fs.info.new_pathw = NULL;
req->path = NULL;
return 0;
}
buf = uv__malloc(buf_sz);
if (buf == NULL) {
return ERROR_OUTOFMEMORY;
}
pos = buf;
if (path != NULL) {
uv_wtf8_to_utf16(path, pos, pathw_len);
req->file.pathw = pos;
pos += pathw_len;
} else {
req->file.pathw = NULL;
}
if (new_path != NULL) {
uv_wtf8_to_utf16(new_path, pos, new_pathw_len);
req->fs.info.new_pathw = pos;
pos += new_pathw_len;
} else {
req->fs.info.new_pathw = NULL;
}
req->path = path;
if (path != NULL && copy_path) {
memcpy(pos, path, path_len);
assert(path_len == buf_sz - (pos - buf) * sizeof(WCHAR));
req->path = (char*) pos;
}
req->flags |= UV_FS_FREE_PATHS;
return 0;
}
INLINE static void uv__fs_req_init(uv_loop_t* loop, uv_fs_t* req,
uv_fs_type fs_type, const uv_fs_cb cb) {
uv__once_init();
UV_REQ_INIT(req, UV_FS);
req->loop = loop;
req->flags = 0;
req->fs_type = fs_type;
req->sys_errno_ = 0;
req->result = 0;
req->ptr = NULL;
req->path = NULL;
req->cb = cb;
memset(&req->fs, 0, sizeof(req->fs));
}
@ -1569,7 +1390,7 @@ void fs__scandir(uv_fs_t* req) {
continue;
/* Compute the space required to store the filename as WTF-8. */
wtf8_len = fs__get_length_wide(&info->FileName[0], wchar_len);
wtf8_len = uv_utf16_length_as_wtf8(&info->FileName[0], wchar_len);
/* Resize the dirent array if needed. */
if (dirents_used >= dirents_size) {
@ -1597,8 +1418,8 @@ void fs__scandir(uv_fs_t* req) {
/* Convert file name to UTF-8. */
wtf8 = &dirent->d_name[0];
if (fs__wide_to_wtf8(&info->FileName[0], wchar_len, &wtf8, &wtf8_len) == -1)
goto win32_error;
if (uv_utf16_to_wtf8(&info->FileName[0], wchar_len, &wtf8, &wtf8_len) != 0)
goto out_of_memory_error;
/* Fill out the type field. */
if (info->FileAttributes & FILE_ATTRIBUTE_DEVICE)
@ -2824,7 +2645,7 @@ static ssize_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) {
}
assert(*realpath_ptr == NULL);
r = fs__wide_to_wtf8(w_realpath_ptr, w_realpath_len, realpath_ptr, NULL);
r = uv_utf16_to_wtf8(w_realpath_ptr, w_realpath_len, realpath_ptr, NULL);
uv__free(w_realpath_buf);
return r;
}

View File

@ -104,13 +104,14 @@ static void uv__getaddrinfo_work(struct uv__work* w) {
*/
static void uv__getaddrinfo_done(struct uv__work* w, int status) {
uv_getaddrinfo_t* req;
int addrinfo_len = 0;
int name_len = 0;
size_t addrinfo_len = 0;
ssize_t name_len = 0;
size_t addrinfo_struct_len = ALIGNED_SIZE(sizeof(struct addrinfo));
struct addrinfoW* addrinfow_ptr;
struct addrinfo* addrinfo_ptr;
char* alloc_ptr = NULL;
char* cur_ptr = NULL;
int r;
req = container_of(w, uv_getaddrinfo_t, work_req);
@ -131,19 +132,12 @@ static void uv__getaddrinfo_done(struct uv__work* w, int status) {
addrinfo_len += addrinfo_struct_len +
ALIGNED_SIZE(addrinfow_ptr->ai_addrlen);
if (addrinfow_ptr->ai_canonname != NULL) {
name_len = WideCharToMultiByte(CP_UTF8,
0,
addrinfow_ptr->ai_canonname,
-1,
NULL,
0,
NULL,
NULL);
if (name_len == 0) {
req->retcode = uv_translate_sys_error(GetLastError());
name_len = uv_utf16_length_as_wtf8(addrinfow_ptr->ai_canonname, -1);
if (name_len < 0) {
req->retcode = name_len;
goto complete;
}
addrinfo_len += ALIGNED_SIZE(name_len);
addrinfo_len += ALIGNED_SIZE(name_len + 1);
}
addrinfow_ptr = addrinfow_ptr->ai_next;
}
@ -182,27 +176,14 @@ static void uv__getaddrinfo_done(struct uv__work* w, int status) {
/* convert canonical name to UTF-8 */
if (addrinfow_ptr->ai_canonname != NULL) {
name_len = WideCharToMultiByte(CP_UTF8,
0,
addrinfow_ptr->ai_canonname,
-1,
NULL,
0,
NULL,
NULL);
assert(name_len > 0);
assert(cur_ptr + name_len <= alloc_ptr + addrinfo_len);
name_len = WideCharToMultiByte(CP_UTF8,
0,
addrinfow_ptr->ai_canonname,
-1,
cur_ptr,
name_len,
NULL,
NULL);
assert(name_len > 0);
name_len = alloc_ptr + addrinfo_len - cur_ptr;
r = uv__copy_utf16_to_utf8(addrinfow_ptr->ai_canonname,
-1,
cur_ptr,
(size_t*)&name_len);
assert(r == 0);
addrinfo_ptr->ai_canonname = cur_ptr;
cur_ptr += ALIGNED_SIZE(name_len);
cur_ptr += ALIGNED_SIZE(name_len + 1);
}
assert(cur_ptr <= alloc_ptr + addrinfo_len);
@ -261,12 +242,11 @@ int uv_getaddrinfo(uv_loop_t* loop,
const char* service,
const struct addrinfo* hints) {
char hostname_ascii[256];
int nodesize = 0;
int servicesize = 0;
int hintssize = 0;
size_t nodesize = 0;
size_t servicesize = 0;
size_t hintssize = 0;
char* alloc_ptr = NULL;
int err;
long rc;
ssize_t rc;
if (req == NULL || (node == NULL && service == NULL)) {
return UV_EINVAL;
@ -286,56 +266,36 @@ int uv_getaddrinfo(uv_loop_t* loop,
hostname_ascii + sizeof(hostname_ascii));
if (rc < 0)
return rc;
nodesize = ALIGNED_SIZE(MultiByteToWideChar(CP_UTF8, 0, hostname_ascii,
-1, NULL, 0) * sizeof(WCHAR));
if (nodesize == 0) {
err = GetLastError();
goto error;
}
nodesize = strlen(hostname_ascii) + 1;
node = hostname_ascii;
}
if (service != NULL) {
servicesize = ALIGNED_SIZE(MultiByteToWideChar(CP_UTF8,
0,
service,
-1,
NULL,
0) *
sizeof(WCHAR));
if (servicesize == 0) {
err = GetLastError();
goto error;
}
rc = uv_wtf8_length_as_utf16(service);
if (rc < 0)
return rc;
servicesize = rc;
}
if (hints != NULL) {
hintssize = ALIGNED_SIZE(sizeof(struct addrinfoW));
}
/* allocate memory for inputs, and partition it as needed */
alloc_ptr = (char*)uv__malloc(nodesize + servicesize + hintssize);
if (!alloc_ptr) {
err = WSAENOBUFS;
goto error;
}
alloc_ptr = uv__malloc(ALIGNED_SIZE(nodesize * sizeof(WCHAR)) +
ALIGNED_SIZE(servicesize * sizeof(WCHAR)) +
hintssize);
if (!alloc_ptr)
return UV_ENOMEM;
/* save alloc_ptr now so we can free if error */
req->alloc = (void*)alloc_ptr;
req->alloc = (void*) alloc_ptr;
/* Convert node string to UTF16 into allocated memory and save pointer in the
* request. */
* request. The node here has been converted to ascii. */
if (node != NULL) {
req->node = (WCHAR*)alloc_ptr;
if (MultiByteToWideChar(CP_UTF8,
0,
node,
-1,
(WCHAR*) alloc_ptr,
nodesize / sizeof(WCHAR)) == 0) {
err = GetLastError();
goto error;
}
alloc_ptr += nodesize;
req->node = (WCHAR*) alloc_ptr;
uv_wtf8_to_utf16(node, (WCHAR*) alloc_ptr, nodesize);
alloc_ptr += ALIGNED_SIZE(nodesize * sizeof(WCHAR));
} else {
req->node = NULL;
}
@ -343,24 +303,16 @@ int uv_getaddrinfo(uv_loop_t* loop,
/* Convert service string to UTF16 into allocated memory and save pointer in
* the req. */
if (service != NULL) {
req->service = (WCHAR*)alloc_ptr;
if (MultiByteToWideChar(CP_UTF8,
0,
service,
-1,
(WCHAR*) alloc_ptr,
servicesize / sizeof(WCHAR)) == 0) {
err = GetLastError();
goto error;
}
alloc_ptr += servicesize;
req->service = (WCHAR*) alloc_ptr;
uv_wtf8_to_utf16(service, (WCHAR*) alloc_ptr, servicesize);
alloc_ptr += ALIGNED_SIZE(servicesize * sizeof(WCHAR));
} else {
req->service = NULL;
}
/* copy hints to allocated memory and save pointer in req */
if (hints != NULL) {
req->addrinfow = (struct addrinfoW*)alloc_ptr;
req->addrinfow = (struct addrinfoW*) alloc_ptr;
req->addrinfow->ai_family = hints->ai_family;
req->addrinfow->ai_socktype = hints->ai_socktype;
req->addrinfow->ai_protocol = hints->ai_protocol;
@ -387,19 +339,11 @@ int uv_getaddrinfo(uv_loop_t* loop,
uv__getaddrinfo_done(&req->work_req, 0);
return req->retcode;
}
error:
if (req != NULL) {
uv__free(req->alloc);
req->alloc = NULL;
}
return uv_translate_sys_error(err);
}
int uv_if_indextoname(unsigned int ifindex, char* buffer, size_t* size) {
NET_LUID luid;
wchar_t wname[NDIS_IF_MAX_STRING_SIZE + 1]; /* Add one for the NUL. */
DWORD bufsize;
int r;
if (buffer == NULL || size == NULL || *size == 0)
@ -415,31 +359,7 @@ int uv_if_indextoname(unsigned int ifindex, char* buffer, size_t* size) {
if (r != 0)
return uv_translate_sys_error(r);
/* Check how much space we need */
bufsize = WideCharToMultiByte(CP_UTF8, 0, wname, -1, NULL, 0, NULL, NULL);
if (bufsize == 0) {
return uv_translate_sys_error(GetLastError());
} else if (bufsize > *size) {
*size = bufsize;
return UV_ENOBUFS;
}
/* Convert to UTF-8 */
bufsize = WideCharToMultiByte(CP_UTF8,
0,
wname,
-1,
buffer,
*size,
NULL,
NULL);
if (bufsize == 0)
return uv_translate_sys_error(GetLastError());
*size = bufsize - 1;
return 0;
return uv__copy_utf16_to_utf8(wname, -1, buffer, size);
}
int uv_if_indextoiid(unsigned int ifindex, char* buffer, size_t* size) {

View File

@ -42,6 +42,7 @@ static void uv__getnameinfo_work(struct uv__work* w) {
uv_getnameinfo_t* req;
WCHAR host[NI_MAXHOST];
WCHAR service[NI_MAXSERV];
size_t size;
int ret;
req = container_of(w, uv_getnameinfo_t, work_req);
@ -57,29 +58,17 @@ static void uv__getnameinfo_work(struct uv__work* w) {
return;
}
ret = WideCharToMultiByte(CP_UTF8,
0,
host,
-1,
req->host,
sizeof(req->host),
NULL,
NULL);
if (ret == 0) {
req->retcode = uv_translate_sys_error(GetLastError());
size = sizeof(req->host);
ret = uv__copy_utf16_to_utf8(host, -1, req->host, &size);
if (ret < 0) {
req->retcode = ret;
return;
}
ret = WideCharToMultiByte(CP_UTF8,
0,
service,
-1,
req->service,
sizeof(req->service),
NULL,
NULL);
if (ret == 0) {
req->retcode = uv_translate_sys_error(GetLastError());
size = sizeof(req->service);
ret = uv__copy_utf16_to_utf8(service, -1, req->service, &size);
if (ret < 0) {
req->retcode = ret;
}
}

View File

@ -257,8 +257,9 @@ void uv__util_init(void);
uint64_t uv__hrtime(unsigned int scale);
__declspec(noreturn) void uv_fatal_error(const int errorno, const char* syscall);
int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8);
int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16);
int uv__convert_utf16_to_utf8(const WCHAR* utf16, size_t utf16len, char** utf8);
int uv__copy_utf16_to_utf8(const WCHAR* utf16, size_t utf16len, char* utf8, size_t *size);
int uv__convert_utf8_to_utf16(const char* utf8, WCHAR** utf16);
typedef int (WINAPI *uv__peersockfunc)(SOCKET, struct sockaddr*, int*);

View File

@ -49,7 +49,7 @@ static const int default_pending_pipe_instances = 4;
/* Pipe prefix */
static char pipe_prefix[] = "\\\\?\\pipe";
static const int pipe_prefix_len = sizeof(pipe_prefix) - 1;
static const size_t pipe_prefix_len = sizeof(pipe_prefix) - 1;
/* IPC incoming xfer queue item. */
typedef struct {
@ -703,7 +703,7 @@ int uv_pipe_bind2(uv_pipe_t* handle,
size_t namelen,
unsigned int flags) {
uv_loop_t* loop = handle->loop;
int i, err, nameSize;
int i, err;
uv_pipe_accept_t* req;
if (flags & ~UV_PIPE_NO_TRUNCATE) {
@ -742,9 +742,8 @@ int uv_pipe_bind2(uv_pipe_t* handle,
handle->pipe.serv.accept_reqs = (uv_pipe_accept_t*)
uv__malloc(sizeof(uv_pipe_accept_t) * handle->pipe.serv.pending_instances);
if (!handle->pipe.serv.accept_reqs) {
uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
if (!handle->pipe.serv.accept_reqs)
return UV_ENOMEM;
for (i = 0; i < handle->pipe.serv.pending_instances; i++) {
req = &handle->pipe.serv.accept_reqs[i];
@ -754,22 +753,9 @@ int uv_pipe_bind2(uv_pipe_t* handle,
req->next_pending = NULL;
}
/* Convert name to UTF16. */
nameSize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0) * sizeof(WCHAR);
handle->name = uv__malloc(nameSize);
if (!handle->name) {
uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
if (!MultiByteToWideChar(CP_UTF8,
0,
name,
-1,
handle->name,
nameSize / sizeof(WCHAR))) {
err = GetLastError();
goto error;
}
err = uv__convert_utf8_to_utf16(name, &handle->name);
if (err)
return err;
/*
* Attempt to create the first pipe with FILE_FLAG_FIRST_PIPE_INSTANCE.
@ -795,10 +781,8 @@ int uv_pipe_bind2(uv_pipe_t* handle,
return 0;
error:
if (handle->name) {
uv__free(handle->name);
handle->name = NULL;
}
uv__free(handle->name);
handle->name = NULL;
return uv_translate_sys_error(err);
}
@ -861,7 +845,8 @@ int uv_pipe_connect2(uv_connect_t* req,
unsigned int flags,
uv_connect_cb cb) {
uv_loop_t* loop = handle->loop;
int err, nameSize;
int err;
size_t nameSize;
HANDLE pipeHandle = INVALID_HANDLE_VALUE;
DWORD duplex_flags;
@ -904,26 +889,16 @@ int uv_pipe_connect2(uv_connect_t* req,
}
uv__pipe_connection_init(handle);
/* Convert name to UTF16. */
nameSize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0) * sizeof(WCHAR);
handle->name = uv__malloc(nameSize);
if (!handle->name) {
uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
if (!MultiByteToWideChar(CP_UTF8,
0,
name,
-1,
handle->name,
nameSize / sizeof(WCHAR))) {
err = GetLastError();
err = uv__convert_utf8_to_utf16(name, &handle->name);
if (err) {
err = ERROR_NO_UNICODE_TRANSLATION;
goto error;
}
pipeHandle = open_named_pipe(handle->name, &duplex_flags);
if (pipeHandle == INVALID_HANDLE_VALUE) {
if (GetLastError() == ERROR_PIPE_BUSY) {
nameSize = (wcslen(handle->name) + 1) * sizeof(WCHAR);
req->u.connect.name = uv__malloc(nameSize);
if (!req->u.connect.name) {
uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
@ -2439,7 +2414,6 @@ static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size)
FILE_NAME_INFORMATION tmp_name_info;
FILE_NAME_INFORMATION* name_info;
WCHAR* name_buf;
unsigned int addrlen;
unsigned int name_size;
unsigned int name_len;
int err;
@ -2450,46 +2424,7 @@ static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size)
if (handle->name != NULL) {
/* The user might try to query the name before we are connected,
* and this is just easier to return the cached value if we have it. */
name_buf = handle->name;
name_len = wcslen(name_buf);
/* check how much space we need */
addrlen = WideCharToMultiByte(CP_UTF8,
0,
name_buf,
name_len,
NULL,
0,
NULL,
NULL);
if (!addrlen) {
*size = 0;
err = uv_translate_sys_error(GetLastError());
return err;
} else if (addrlen >= *size) {
*size = addrlen + 1;
err = UV_ENOBUFS;
goto error;
}
addrlen = WideCharToMultiByte(CP_UTF8,
0,
name_buf,
name_len,
buffer,
addrlen,
NULL,
NULL);
if (!addrlen) {
*size = 0;
err = uv_translate_sys_error(GetLastError());
return err;
}
*size = addrlen;
buffer[addrlen] = '\0';
return 0;
return uv__copy_utf16_to_utf8(handle->name, -1, buffer, size);
}
if (handle->handle == INVALID_HANDLE_VALUE) {
@ -2517,8 +2452,7 @@ static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size)
name_info = uv__malloc(name_size);
if (!name_info) {
*size = 0;
err = UV_ENOMEM;
goto cleanup;
return UV_ENOMEM;
}
nt_status = pNtQueryInformationFile(handle->handle,
@ -2551,51 +2485,19 @@ static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size)
name_len /= sizeof(WCHAR);
/* check how much space we need */
addrlen = WideCharToMultiByte(CP_UTF8,
0,
name_buf,
name_len,
NULL,
0,
NULL,
NULL);
if (!addrlen) {
/* "\\\\.\\pipe" + name */
if (*size < pipe_prefix_len) {
*size = 0;
err = uv_translate_sys_error(GetLastError());
goto error;
} else if (pipe_prefix_len + addrlen >= *size) {
/* "\\\\.\\pipe" + name */
*size = pipe_prefix_len + addrlen + 1;
err = UV_ENOBUFS;
goto error;
}
memcpy(buffer, pipe_prefix, pipe_prefix_len);
addrlen = WideCharToMultiByte(CP_UTF8,
0,
name_buf,
name_len,
buffer+pipe_prefix_len,
*size-pipe_prefix_len,
NULL,
NULL);
if (!addrlen) {
*size = 0;
err = uv_translate_sys_error(GetLastError());
goto error;
else {
memcpy(buffer, pipe_prefix, pipe_prefix_len);
*size -= pipe_prefix_len;
}
addrlen += pipe_prefix_len;
*size = addrlen;
buffer[addrlen] = '\0';
err = 0;
err = uv__copy_utf16_to_utf8(name_buf, name_len, buffer+pipe_prefix_len, size);
*size += pipe_prefix_len;
error:
uv__free(name_info);
cleanup:
return err;
}

View File

@ -105,38 +105,26 @@ static void uv__init_global_job_handle(void) {
&info,
sizeof info))
uv_fatal_error(GetLastError(), "SetInformationJobObject");
if (!AssignProcessToJobObject(uv_global_job_handle_, GetCurrentProcess())) {
/* Make sure this handle is functional. The Windows kernel has a bug that
* if the first use of AssignProcessToJobObject is for a Windows Store
* program, subsequent attempts to use the handle with fail with
* INVALID_PARAMETER (87). This is possibly because all uses of the handle
* must be for the same Terminal Services session. We can ensure it is tied
* to our current session now by adding ourself to it. We could remove
* ourself afterwards, but there doesn't seem to be a reason to.
*/
DWORD err = GetLastError();
if (err != ERROR_ACCESS_DENIED)
uv_fatal_error(err, "AssignProcessToJobObject");
}
}
static int uv__utf8_to_utf16_alloc(const char* s, WCHAR** ws_ptr) {
int ws_len, r;
WCHAR* ws;
ws_len = MultiByteToWideChar(CP_UTF8,
0,
s,
-1,
NULL,
0);
if (ws_len <= 0) {
return GetLastError();
}
ws = (WCHAR*) uv__malloc(ws_len * sizeof(WCHAR));
if (ws == NULL) {
return ERROR_OUTOFMEMORY;
}
r = MultiByteToWideChar(CP_UTF8,
0,
s,
-1,
ws,
ws_len);
assert(r == ws_len);
*ws_ptr = ws;
return 0;
return uv__convert_utf8_to_utf16(s, ws_ptr);
}
@ -396,7 +384,7 @@ static WCHAR* search_path(const WCHAR *file,
name_has_ext);
while (result == NULL) {
if (*dir_end == L'\0') {
if (dir_end == NULL || *dir_end == L'\0') {
break;
}
@ -539,21 +527,15 @@ int make_program_args(char** args, int verbatim_arguments, WCHAR** dst_ptr) {
/* Count the required size. */
for (arg = args; *arg; arg++) {
DWORD arg_len;
ssize_t arg_len;
arg_len = MultiByteToWideChar(CP_UTF8,
0,
*arg,
-1,
NULL,
0);
if (arg_len == 0) {
return GetLastError();
}
arg_len = uv_wtf8_length_as_utf16(*arg);
if (arg_len < 0)
return arg_len;
dst_len += arg_len;
if (arg_len > temp_buffer_len)
if ((size_t) arg_len > temp_buffer_len)
temp_buffer_len = arg_len;
arg_count++;
@ -564,34 +546,28 @@ int make_program_args(char** args, int verbatim_arguments, WCHAR** dst_ptr) {
dst_len = dst_len * 2 + arg_count * 2;
/* Allocate buffer for the final command line. */
dst = (WCHAR*) uv__malloc(dst_len * sizeof(WCHAR));
dst = uv__malloc(dst_len * sizeof(WCHAR));
if (dst == NULL) {
err = ERROR_OUTOFMEMORY;
err = UV_ENOMEM;
goto error;
}
/* Allocate temporary working buffer. */
temp_buffer = (WCHAR*) uv__malloc(temp_buffer_len * sizeof(WCHAR));
temp_buffer = uv__malloc(temp_buffer_len * sizeof(WCHAR));
if (temp_buffer == NULL) {
err = ERROR_OUTOFMEMORY;
err = UV_ENOMEM;
goto error;
}
pos = dst;
for (arg = args; *arg; arg++) {
DWORD arg_len;
ssize_t arg_len;
/* Convert argument to wide char. */
arg_len = MultiByteToWideChar(CP_UTF8,
0,
*arg,
-1,
temp_buffer,
(int) (dst + dst_len - pos));
if (arg_len == 0) {
err = GetLastError();
goto error;
}
arg_len = uv_wtf8_length_as_utf16(*arg);
assert(arg_len > 0);
assert(temp_buffer_len >= (size_t) arg_len);
uv_wtf8_to_utf16(*arg, temp_buffer, arg_len);
if (verbatim_arguments) {
/* Copy verbatim. */
@ -603,6 +579,7 @@ int make_program_args(char** args, int verbatim_arguments, WCHAR** dst_ptr) {
}
*pos++ = *(arg + 1) ? L' ' : L'\0';
assert(pos <= dst + dst_len);
}
uv__free(temp_buffer);
@ -688,55 +665,43 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) {
WCHAR* ptr;
char** env;
size_t env_len = 0;
int len;
size_t len;
size_t i;
DWORD var_size;
size_t var_size;
size_t env_block_count = 1; /* 1 for null-terminator */
WCHAR* dst_copy;
WCHAR** ptr_copy;
WCHAR** env_copy;
DWORD required_vars_value_len[ARRAY_SIZE(required_vars)];
size_t required_vars_value_len[ARRAY_SIZE(required_vars)];
/* first pass: determine size in UTF-16 */
for (env = env_block; *env; env++) {
int len;
ssize_t len;
if (strchr(*env, '=')) {
len = MultiByteToWideChar(CP_UTF8,
0,
*env,
-1,
NULL,
0);
if (len <= 0) {
return GetLastError();
}
len = uv_wtf8_length_as_utf16(*env);
if (len < 0)
return len;
env_len += len;
env_block_count++;
}
}
/* second pass: copy to UTF-16 environment block */
dst_copy = (WCHAR*)uv__malloc(env_len * sizeof(WCHAR));
dst_copy = uv__malloc(env_len * sizeof(WCHAR));
if (dst_copy == NULL && env_len > 0) {
return ERROR_OUTOFMEMORY;
return UV_ENOMEM;
}
env_copy = alloca(env_block_count * sizeof(WCHAR*));
ptr = dst_copy;
ptr_copy = env_copy;
for (env = env_block; *env; env++) {
ssize_t len;
if (strchr(*env, '=')) {
len = MultiByteToWideChar(CP_UTF8,
0,
*env,
-1,
ptr,
(int) (env_len - (ptr - dst_copy)));
if (len <= 0) {
DWORD err = GetLastError();
uv__free(dst_copy);
return err;
}
len = uv_wtf8_length_as_utf16(*env);
assert(len > 0);
assert((size_t) len <= env_len - (ptr - dst_copy));
uv_wtf8_to_utf16(*env, ptr, len);
*ptr_copy++ = ptr;
ptr += len;
}
@ -754,7 +719,7 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) {
cmp = -1;
} else {
cmp = env_strncmp(required_vars[i].wide_eq,
required_vars[i].len,
required_vars[i].len,
*ptr_copy);
}
if (cmp < 0) {
@ -777,7 +742,7 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) {
dst = uv__malloc((1+env_len) * sizeof(WCHAR));
if (!dst) {
uv__free(dst_copy);
return ERROR_OUTOFMEMORY;
return UV_ENOMEM;
}
for (ptr = dst, ptr_copy = env_copy, i = 0;
@ -975,26 +940,26 @@ int uv_spawn(uv_loop_t* loop,
err = uv__utf8_to_utf16_alloc(options->file, &application);
if (err)
goto done;
goto done_uv;
err = make_program_args(
options->args,
options->flags & UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS,
&arguments);
if (err)
goto done;
goto done_uv;
if (options->env) {
err = make_program_env(options->env, &env);
if (err)
goto done;
goto done_uv;
}
if (options->cwd) {
/* Explicit cwd */
err = uv__utf8_to_utf16_alloc(options->cwd, &cwd);
if (err)
goto done;
goto done_uv;
} else {
/* Inherit cwd */
@ -1025,22 +990,19 @@ int uv_spawn(uv_loop_t* loop,
DWORD path_len, r;
path_len = GetEnvironmentVariableW(L"PATH", NULL, 0);
if (path_len == 0) {
err = GetLastError();
goto done;
}
if (path_len != 0) {
alloc_path = (WCHAR*) uv__malloc(path_len * sizeof(WCHAR));
if (alloc_path == NULL) {
err = ERROR_OUTOFMEMORY;
goto done;
}
path = alloc_path;
alloc_path = (WCHAR*) uv__malloc(path_len * sizeof(WCHAR));
if (alloc_path == NULL) {
err = ERROR_OUTOFMEMORY;
goto done;
}
path = alloc_path;
r = GetEnvironmentVariableW(L"PATH", path, path_len);
if (r == 0 || r >= path_len) {
err = GetLastError();
goto done;
r = GetEnvironmentVariableW(L"PATH", path, path_len);
if (r == 0 || r >= path_len) {
err = GetLastError();
goto done;
}
}
}
@ -1102,6 +1064,7 @@ int uv_spawn(uv_loop_t* loop,
* breakaway.
*/
process_flags |= DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP;
process_flags |= CREATE_SUSPENDED;
}
if (!CreateProcessW(application_path,
@ -1119,11 +1082,6 @@ int uv_spawn(uv_loop_t* loop,
goto done;
}
/* Spawn succeeded. Beyond this point, failure is reported asynchronously. */
process->process_handle = info.hProcess;
process->pid = info.dwProcessId;
/* If the process isn't spawned as detached, assign to the global job object
* so windows will kill it when the parent process dies. */
if (!(options->flags & UV_PROCESS_DETACHED)) {
@ -1146,6 +1104,19 @@ int uv_spawn(uv_loop_t* loop,
}
}
if (process_flags & CREATE_SUSPENDED) {
if (ResumeThread(info.hThread) == ((DWORD)-1)) {
err = GetLastError();
TerminateProcess(info.hProcess, 1);
goto done;
}
}
/* Spawn succeeded. Beyond this point, failure is reported asynchronously. */
process->process_handle = info.hProcess;
process->pid = info.dwProcessId;
/* Set IPC pid to all IPC pipes. */
for (i = 0; i < options->stdio_count; i++) {
const uv_stdio_container_t* fdopt = &options->stdio[i];
@ -1173,8 +1144,13 @@ int uv_spawn(uv_loop_t* loop,
* made or the handle is closed, whichever happens first. */
uv__handle_start(process);
goto done_uv;
/* Cleanup, whether we succeeded or failed. */
done:
err = uv_translate_sys_error(err);
done_uv:
uv__free(application);
uv__free(application_path);
uv__free(arguments);
@ -1188,7 +1164,7 @@ int uv_spawn(uv_loop_t* loop,
child_stdio_buffer = NULL;
}
return uv_translate_sys_error(err);
return err;
}

View File

@ -482,9 +482,11 @@ static DWORD CALLBACK uv_tty_line_read_thread(void* data) {
uv_loop_t* loop;
uv_tty_t* handle;
uv_req_t* req;
DWORD bytes, read_bytes;
DWORD bytes;
size_t read_bytes;
WCHAR utf16[MAX_INPUT_BUFFER_LENGTH / 3];
DWORD chars, read_chars;
DWORD chars;
DWORD read_chars;
LONG status;
COORD pos;
BOOL read_console_success;
@ -525,16 +527,13 @@ static DWORD CALLBACK uv_tty_line_read_thread(void* data) {
NULL);
if (read_console_success) {
read_bytes = WideCharToMultiByte(CP_UTF8,
0,
utf16,
read_chars,
handle->tty.rd.read_line_buffer.base,
bytes,
NULL,
NULL);
read_bytes = bytes;
uv_utf16_to_wtf8(utf16,
read_chars,
&handle->tty.rd.read_line_buffer.base,
&read_bytes);
SET_REQ_SUCCESS(req);
req->u.io.overlapped.InternalHigh = read_bytes;
req->u.io.overlapped.InternalHigh = (DWORD) read_bytes;
} else {
SET_REQ_ERROR(req, GetLastError());
}
@ -798,7 +797,9 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
}
if (KEV.uChar.UnicodeChar != 0) {
int prefix_len, char_len;
int prefix_len;
size_t char_len;
char* last_key_buf;
/* Character key pressed */
if (KEV.uChar.UnicodeChar >= 0xD800 &&
@ -819,38 +820,31 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
prefix_len = 0;
}
if (KEV.uChar.UnicodeChar >= 0xDC00 &&
KEV.uChar.UnicodeChar < 0xE000) {
char_len = sizeof handle->tty.rd.last_key;
last_key_buf = &handle->tty.rd.last_key[prefix_len];
if (handle->tty.rd.last_utf16_high_surrogate) {
/* UTF-16 surrogate pair */
WCHAR utf16_buffer[2];
utf16_buffer[0] = handle->tty.rd.last_utf16_high_surrogate;
utf16_buffer[1] = KEV.uChar.UnicodeChar;
char_len = WideCharToMultiByte(CP_UTF8,
0,
utf16_buffer,
2,
&handle->tty.rd.last_key[prefix_len],
sizeof handle->tty.rd.last_key,
NULL,
NULL);
if (uv_utf16_to_wtf8(utf16_buffer,
2,
&last_key_buf,
&char_len))
char_len = 0;
handle->tty.rd.last_utf16_high_surrogate = 0;
} else {
/* Single UTF-16 character */
char_len = WideCharToMultiByte(CP_UTF8,
0,
&KEV.uChar.UnicodeChar,
1,
&handle->tty.rd.last_key[prefix_len],
sizeof handle->tty.rd.last_key,
NULL,
NULL);
if (uv_utf16_to_wtf8(&KEV.uChar.UnicodeChar,
1,
&last_key_buf,
&char_len))
char_len = 0;
}
/* Whatever happened, the last character wasn't a high surrogate. */
handle->tty.rd.last_utf16_high_surrogate = 0;
/* If the utf16 character(s) couldn't be converted something must be
* wrong. */
if (!char_len) {
if (char_len == 0) {
handle->flags &= ~UV_HANDLE_READING;
DECREASE_ACTIVE_COUNT(loop, handle);
handle->read_cb((uv_stream_t*) handle,

View File

@ -95,7 +95,7 @@ void uv__util_init(void) {
int uv_exepath(char* buffer, size_t* size_ptr) {
int utf8_len, utf16_buffer_len, utf16_len;
size_t utf8_len, utf16_buffer_len, utf16_len;
WCHAR* utf16_buffer;
int err;
@ -123,25 +123,17 @@ int uv_exepath(char* buffer, size_t* size_ptr) {
}
/* Convert to UTF-8 */
utf8_len = WideCharToMultiByte(CP_UTF8,
0,
utf16_buffer,
-1,
buffer,
(int) *size_ptr,
NULL,
NULL);
if (utf8_len == 0) {
err = GetLastError();
goto error;
utf8_len = *size_ptr - 1; /* Reserve space for NUL */
err = uv_utf16_to_wtf8(utf16_buffer, utf16_len, &buffer, &utf8_len);
if (err == UV_ENOBUFS) {
utf8_len = *size_ptr - 1;
err = 0;
}
*size_ptr = utf8_len;
uv__free(utf16_buffer);
/* utf8_len *does* include the terminating null at this point, but the
* returned size shouldn't. */
*size_ptr = utf8_len - 1;
return 0;
return err;
error:
uv__free(utf16_buffer);
@ -204,45 +196,14 @@ int uv_cwd(char* buffer, size_t* size) {
}
r = uv__cwd(&utf16_buffer, &utf16_len);
if (r < 0) {
if (r < 0)
return r;
}
/* Check how much space we need */
r = WideCharToMultiByte(CP_UTF8,
0,
utf16_buffer,
-1,
NULL,
0,
NULL,
NULL);
if (r == 0) {
uv__free(utf16_buffer);
return uv_translate_sys_error(GetLastError());
} else if (r > (int) *size) {
uv__free(utf16_buffer);
*size = r;
return UV_ENOBUFS;
}
r = uv__copy_utf16_to_utf8(utf16_buffer, utf16_len, buffer, size);
/* Convert to UTF-8 */
r = WideCharToMultiByte(CP_UTF8,
0,
utf16_buffer,
-1,
buffer,
*size > INT_MAX ? INT_MAX : (int) *size,
NULL,
NULL);
uv__free(utf16_buffer);
if (r == 0) {
return uv_translate_sys_error(GetLastError());
}
*size = r - 1;
return 0;
return r;
}
@ -252,33 +213,10 @@ int uv_chdir(const char* dir) {
WCHAR drive_letter, env_var[4];
int r;
if (dir == NULL) {
return UV_EINVAL;
}
utf16_len = MultiByteToWideChar(CP_UTF8,
0,
dir,
-1,
NULL,
0);
if (utf16_len == 0) {
return uv_translate_sys_error(GetLastError());
}
utf16_buffer = uv__malloc(utf16_len * sizeof(WCHAR));
if (utf16_buffer == NULL) {
return UV_ENOMEM;
}
if (MultiByteToWideChar(CP_UTF8,
0,
dir,
-1,
utf16_buffer,
utf16_len) == 0) {
uv__free(utf16_buffer);
return uv_translate_sys_error(GetLastError());
}
/* Convert to UTF-16 */
r = uv__convert_utf8_to_utf16(dir, &utf16_buffer);
if (r)
return r;
if (!SetCurrentDirectoryW(utf16_buffer)) {
uv__free(utf16_buffer);
@ -416,29 +354,14 @@ int uv_set_process_title(const char* title) {
uv__once_init();
/* Find out how big the buffer for the wide-char title must be */
length = MultiByteToWideChar(CP_UTF8, 0, title, -1, NULL, 0);
if (!length) {
err = GetLastError();
goto done;
}
/* Convert to wide-char string */
title_w = (WCHAR*)uv__malloc(sizeof(WCHAR) * length);
if (!title_w) {
uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
}
length = MultiByteToWideChar(CP_UTF8, 0, title, -1, title_w, length);
if (!length) {
err = GetLastError();
goto done;
}
err = uv__convert_utf8_to_utf16(title, &title_w);
if (err)
return err;
/* If the title must be truncated insert a \0 terminator there */
if (length > MAX_TITLE_LENGTH) {
length = wcslen(title_w);
if (length >= MAX_TITLE_LENGTH)
title_w[MAX_TITLE_LENGTH - 1] = L'\0';
}
if (!SetConsoleTitleW(title_w)) {
err = GetLastError();
@ -460,20 +383,19 @@ done:
static int uv__get_process_title(void) {
WCHAR title_w[MAX_TITLE_LENGTH];
DWORD wlen;
if (!GetConsoleTitleW(title_w, sizeof(title_w) / sizeof(WCHAR))) {
return -1;
}
wlen = GetConsoleTitleW(title_w, sizeof(title_w) / sizeof(WCHAR));
if (wlen == 0)
return uv_translate_sys_error(GetLastError());
if (uv__convert_utf16_to_utf8(title_w, -1, &process_title) != 0)
return -1;
return 0;
return uv__convert_utf16_to_utf8(title_w, wlen, &process_title);
}
int uv_get_process_title(char* buffer, size_t size) {
size_t len;
int r;
if (buffer == NULL || size == 0)
return UV_EINVAL;
@ -485,9 +407,12 @@ int uv_get_process_title(char* buffer, size_t size) {
* If the process_title was never read before nor explicitly set,
* we must query it with getConsoleTitleW
*/
if (!process_title && uv__get_process_title() == -1) {
LeaveCriticalSection(&process_title_lock);
return uv_translate_sys_error(GetLastError());
if (process_title == NULL) {
r = uv__get_process_title();
if (r) {
LeaveCriticalSection(&process_title_lock);
return r;
}
}
assert(process_title);
@ -833,19 +758,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
continue;
/* Compute the size of the interface name. */
name_size = WideCharToMultiByte(CP_UTF8,
0,
adapter->FriendlyName,
-1,
NULL,
0,
NULL,
FALSE);
if (name_size <= 0) {
uv__free(win_address_buf);
return uv_translate_sys_error(GetLastError());
}
uv_address_buf_size += name_size;
name_size = uv_utf16_length_as_wtf8(adapter->FriendlyName, -1);
uv_address_buf_size += name_size + 1;
/* Count the number of addresses associated with this interface, and
* compute the size. */
@ -875,30 +789,25 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
adapter != NULL;
adapter = adapter->Next) {
IP_ADAPTER_UNICAST_ADDRESS* unicast_address;
int name_size;
size_t max_name_size;
size_t name_size;
int r;
if (adapter->OperStatus != IfOperStatusUp ||
adapter->FirstUnicastAddress == NULL)
continue;
/* Convert the interface name to UTF8. */
max_name_size = (char*) uv_address_buf + uv_address_buf_size - name_buf;
if (max_name_size > (size_t) INT_MAX)
max_name_size = INT_MAX;
name_size = WideCharToMultiByte(CP_UTF8,
0,
adapter->FriendlyName,
-1,
name_buf,
(int) max_name_size,
NULL,
FALSE);
if (name_size <= 0) {
name_size = (char*) uv_address_buf + uv_address_buf_size - name_buf;
r = uv__copy_utf16_to_utf8(adapter->FriendlyName,
-1,
name_buf,
&name_size);
if (r) {
uv__free(win_address_buf);
uv__free(uv_address_buf);
return uv_translate_sys_error(GetLastError());
return r;
}
name_size += 1; /* Add NUL byte. */
/* Add an uv_interface_address_t element for every unicast address. */
for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS*)
@ -1061,7 +970,6 @@ int uv_os_homedir(char* buffer, size_t* size) {
int uv_os_tmpdir(char* buffer, size_t* size) {
wchar_t *path;
DWORD bufsize;
size_t len;
if (buffer == NULL || size == NULL || *size == 0)
@ -1078,7 +986,7 @@ int uv_os_tmpdir(char* buffer, size_t* size) {
if (path == NULL) {
return UV_ENOMEM;
}
len = GetTempPathW(len, path);
len = GetTempPathW(len, path);
if (len == 0) {
uv__free(path);
@ -1093,34 +1001,7 @@ int uv_os_tmpdir(char* buffer, size_t* size) {
path[len] = L'\0';
}
/* Check how much space we need */
bufsize = WideCharToMultiByte(CP_UTF8, 0, path, -1, NULL, 0, NULL, NULL);
if (bufsize == 0) {
uv__free(path);
return uv_translate_sys_error(GetLastError());
} else if (bufsize > *size) {
uv__free(path);
*size = bufsize;
return UV_ENOBUFS;
}
/* Convert to UTF-8 */
bufsize = WideCharToMultiByte(CP_UTF8,
0,
path,
-1,
buffer,
*size,
NULL,
NULL);
uv__free(path);
if (bufsize == 0)
return uv_translate_sys_error(GetLastError());
*size = bufsize - 1;
return 0;
return uv__copy_utf16_to_utf8(path, len, buffer, size);
}
@ -1131,95 +1012,71 @@ int uv_os_tmpdir(char* buffer, size_t* size) {
* If utf16 is null terminated, utf16len can be set to -1, otherwise it must
* be specified.
*/
int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8) {
DWORD bufsize;
int uv__convert_utf16_to_utf8(const WCHAR* utf16, size_t utf16len, char** utf8) {
size_t utf8_len = 0;
if (utf16 == NULL)
return UV_EINVAL;
/* Check how much space we need */
bufsize = WideCharToMultiByte(CP_UTF8,
0,
utf16,
utf16len,
NULL,
0,
NULL,
NULL);
if (bufsize == 0)
return uv_translate_sys_error(GetLastError());
/* Allocate the destination buffer adding an extra byte for the terminating
* NULL. If utf16len is not -1 WideCharToMultiByte will not add it, so
* we do it ourselves always, just in case. */
*utf8 = uv__malloc(bufsize + 1);
if (*utf8 == NULL)
return UV_ENOMEM;
/* Convert to UTF-8 */
bufsize = WideCharToMultiByte(CP_UTF8,
0,
utf16,
utf16len,
*utf8,
bufsize,
NULL,
NULL);
if (bufsize == 0) {
uv__free(*utf8);
*utf8 = NULL;
return uv_translate_sys_error(GetLastError());
}
(*utf8)[bufsize] = '\0';
return 0;
*utf8 = NULL;
return uv_utf16_to_wtf8(utf16, utf16len, utf8, &utf8_len);
}
/*
* Converts a UTF-8 string into a UTF-16 one. The resulting string is
* null-terminated.
*
* If utf8 is null terminated, utf8len can be set to -1, otherwise it must
* be specified.
*/
int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16) {
int uv__convert_utf8_to_utf16(const char* utf8, WCHAR** utf16) {
int bufsize;
if (utf8 == NULL)
return UV_EINVAL;
/* Check how much space we need */
bufsize = MultiByteToWideChar(CP_UTF8, 0, utf8, utf8len, NULL, 0);
/* Check how much space we need (including NUL). */
bufsize = uv_wtf8_length_as_utf16(utf8);
if (bufsize < 0)
return UV__EINVAL;
if (bufsize == 0)
return uv_translate_sys_error(GetLastError());
/* Allocate the destination buffer adding an extra byte for the terminating
* NULL. If utf8len is not -1 MultiByteToWideChar will not add it, so
* we do it ourselves always, just in case. */
*utf16 = uv__malloc(sizeof(WCHAR) * (bufsize + 1));
/* Allocate the destination buffer. */
*utf16 = uv__malloc(sizeof(WCHAR) * bufsize);
if (*utf16 == NULL)
return UV_ENOMEM;
/* Convert to UTF-16 */
bufsize = MultiByteToWideChar(CP_UTF8, 0, utf8, utf8len, *utf16, bufsize);
uv_wtf8_to_utf16(utf8, *utf16, bufsize);
if (bufsize == 0) {
uv__free(*utf16);
*utf16 = NULL;
return uv_translate_sys_error(GetLastError());
}
(*utf16)[bufsize] = L'\0';
return 0;
}
/*
* Converts a UTF-16 string into a UTF-8 one in an existing buffer. The
* resulting string is null-terminated.
*
* If utf16 is null terminated, utf16len can be set to -1, otherwise it must
* be specified.
*/
int uv__copy_utf16_to_utf8(const WCHAR* utf16buffer, size_t utf16len, char* utf8, size_t *size) {
int r;
if (utf8 == NULL || size == NULL)
return UV_EINVAL;
if (*size == 0) {
*size = uv_utf16_length_as_wtf8(utf16buffer, utf16len);
r = UV_ENOBUFS;
} else {
*size -= 1; /* Reserve space for NUL. */
r = uv_utf16_to_wtf8(utf16buffer, utf16len, &utf8, size);
}
if (r == UV_ENOBUFS)
*size += 1; /* Add space for NUL. */
return r;
}
static int uv__getpwuid_r(uv_passwd_t* pwd) {
HANDLE token;
wchar_t username[UNLEN + 1];
@ -1384,14 +1241,13 @@ int uv_os_getenv(const char* name, char* buffer, size_t* size) {
wchar_t* var;
DWORD varlen;
wchar_t* name_w;
DWORD bufsize;
size_t len;
int r;
if (name == NULL || buffer == NULL || size == NULL || *size == 0)
return UV_EINVAL;
r = uv__convert_utf8_to_utf16(name, -1, &name_w);
r = uv__convert_utf8_to_utf16(name, &name_w);
if (r != 0)
return r;
@ -1432,35 +1288,7 @@ int uv_os_getenv(const char* name, char* buffer, size_t* size) {
}
}
/* Check how much space we need */
bufsize = WideCharToMultiByte(CP_UTF8, 0, var, -1, NULL, 0, NULL, NULL);
if (bufsize == 0) {
r = uv_translate_sys_error(GetLastError());
goto fail;
} else if (bufsize > *size) {
*size = bufsize;
r = UV_ENOBUFS;
goto fail;
}
/* Convert to UTF-8 */
bufsize = WideCharToMultiByte(CP_UTF8,
0,
var,
-1,
buffer,
*size,
NULL,
NULL);
if (bufsize == 0) {
r = uv_translate_sys_error(GetLastError());
goto fail;
}
*size = bufsize - 1;
r = 0;
r = uv__copy_utf16_to_utf8(var, len, buffer, size);
fail:
@ -1482,12 +1310,12 @@ int uv_os_setenv(const char* name, const char* value) {
if (name == NULL || value == NULL)
return UV_EINVAL;
r = uv__convert_utf8_to_utf16(name, -1, &name_w);
r = uv__convert_utf8_to_utf16(name, &name_w);
if (r != 0)
return r;
r = uv__convert_utf8_to_utf16(value, -1, &value_w);
r = uv__convert_utf8_to_utf16(value, &value_w);
if (r != 0) {
uv__free(name_w);
@ -1512,7 +1340,7 @@ int uv_os_unsetenv(const char* name) {
if (name == NULL)
return UV_EINVAL;
r = uv__convert_utf8_to_utf16(name, -1, &name_w);
r = uv__convert_utf8_to_utf16(name, &name_w);
if (r != 0)
return r;
@ -1529,9 +1357,6 @@ int uv_os_unsetenv(const char* name) {
int uv_os_gethostname(char* buffer, size_t* size) {
WCHAR buf[UV_MAXHOSTNAMESIZE];
size_t len;
char* utf8_str;
int convert_result;
if (buffer == NULL || size == NULL || *size == 0)
return UV_EINVAL;
@ -1544,22 +1369,7 @@ int uv_os_gethostname(char* buffer, size_t* size) {
if (pGetHostNameW(buf, UV_MAXHOSTNAMESIZE) != 0)
return uv_translate_sys_error(WSAGetLastError());
convert_result = uv__convert_utf16_to_utf8(buf, -1, &utf8_str);
if (convert_result != 0)
return convert_result;
len = strlen(utf8_str);
if (len >= *size) {
*size = len + 1;
uv__free(utf8_str);
return UV_ENOBUFS;
}
memcpy(buffer, utf8_str, len + 1);
uv__free(utf8_str);
*size = len;
return 0;
return uv__copy_utf16_to_utf8(buf, -1, buffer, size);
}
@ -1665,7 +1475,7 @@ int uv_os_uname(uv_utsname_t* buffer) {
HKEY registry_key;
WCHAR product_name_w[256];
DWORD product_name_w_size;
int version_size;
size_t version_size;
int processor_level;
int r;
@ -1696,7 +1506,7 @@ int uv_os_uname(uv_utsname_t* buffer) {
r = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
0,
KEY_QUERY_VALUE,
KEY_QUERY_VALUE | KEY_WOW64_64KEY,
&registry_key);
if (r == ERROR_SUCCESS) {
@ -1727,37 +1537,29 @@ int uv_os_uname(uv_utsname_t* buffer) {
}
}
version_size = WideCharToMultiByte(CP_UTF8,
0,
product_name_w,
-1,
buffer->version,
sizeof(buffer->version),
NULL,
NULL);
if (version_size == 0) {
r = uv_translate_sys_error(GetLastError());
version_size = sizeof(buffer->version);
r = uv__copy_utf16_to_utf8(product_name_w,
-1,
buffer->version,
&version_size);
if (r)
goto error;
}
}
}
/* Append service pack information to the version if present. */
if (os_info.szCSDVersion[0] != L'\0') {
if (version_size > 0)
buffer->version[version_size - 1] = ' ';
buffer->version[version_size++] = ' ';
if (WideCharToMultiByte(CP_UTF8,
0,
os_info.szCSDVersion,
-1,
buffer->version + version_size,
sizeof(buffer->version) - version_size,
NULL,
NULL) == 0) {
r = uv_translate_sys_error(GetLastError());
version_size = sizeof(buffer->version) - version_size;
r = uv__copy_utf16_to_utf8(os_info.szCSDVersion,
-1,
buffer->version +
sizeof(buffer->version) - version_size,
&version_size);
if (r)
goto error;
}
}
/* Populate the sysname field. */