Compare commits

...

22 Commits

Author SHA1 Message Date
Ben Noordhuis
16d6a0b49d
unix: handle out of memory in iface name copy (#4724)
Allocate storage upfront, that way we can never run out of memory
halfway through processing the interface list.

Fixes: https://github.com/libuv/libuv/issues/4723
2025-02-27 23:30:29 +01:00
Stacey Marshall
436c04048e
unix,sunos: enable use of sendmmsg on Solaris and Illumos (#4717)
Solaris provides sendmmsg() as of 11.3.32.
It was added at the same time as MSG_WAITFORONE.

The same is seen in Illumos guarded by __BSD_VISIBLE

Fixes: https://github.com/libuv/libuv/issues/4715
2025-02-27 12:24:40 -05:00
Tobias Nießen
feddddb56b
doc: fix rendering of threading.html (#4716) 2025-02-25 19:03:07 -05:00
Colin Ihrig
f61f9c29d8
test: handle UV_ENOTSUP in platform_output (#4714)
Fixes: https://github.com/libuv/libuv/issues/4713
2025-02-25 13:22:10 -05:00
Anna Henningsen
843b64faf5
win: add ENABLE_VIRTUAL_TERMINAL_INPUT raw tty mode (#4688)
Windows provides the `ENABLE_VIRTUAL_TERMINAL_INPUT` flag for TTY input
streams as a companion flag to `ENABLE_VIRTUAL_TERMINAL_PROCESSING`,
which libuv is already setting for TTY output streams.

Setting this flag lets the terminal emulator perform some of the
processing that libuv already currently does for input events,
but most notably enables receiving control sequences that are
otherwise entirely unavailable, e.g. for bracketed paste
(which the Node.js readline implementation added basic support for
in https://github.com/nodejs/node/commit/87af913b66eab78088acfd).

libuv currently already provides translations for key events to
control sequences, i.e. what this mode is intended to provide,
but libuv does not and cannot translate all such events.
Since the control sequences differ from the ones that Windows
has chosen to standardize on, and applications may not be expecting
this change, this is opt-in for now (but ideally will be the default
behavior starting in libuv v2.x, should that ever happen).

Another downside of this change is that not all shells reset
this mode when an application exits. For example, when running a
Node.js program with this flag enabled inside of PowerShell in
Windows terminal, if the application exits while in raw TTY input mode,
neither the shell nor the terminal emulator reset this flag, rendering
the input stream unusable.

While there's general awareness of the problem that console state is
global state rather than per-process (same as on UNIX platforms),
it seems that applications like PowerShell aren't expecting to need to
unset this flag on the input stream, only its output counterpart
(e.g. 4e7942135f/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs (L1156)).

Hence, `uv_tty_reset_mode()` is extended to reset the terminal
to its original state if the new mode is being used.

Refs: 87af913b66
Refs: https://github.com/microsoft/terminal/issues/4954
2025-02-21 23:34:53 +01:00
Ben Noordhuis
85b526f56a
unix,win: accept NAN/INFINITY as file timestamps (#4702)
Extend uv_fs_utime, uv_fs_futime and uv_fs_lutime to accept NAN and
INFINITY, with NAN meaning "don't touch the timestamp" and INFINITY
meaning "set to the current timestamp."

Ugly, but it avoids having to add uv_fs_utime2, etc.

UV_FS_UTIME_NOW and UV_FS_UTIME_OMIT constants have been added to make
it more palatable.

Fixes: https://github.com/libuv/libuv/issues/4665
2025-02-21 23:08:15 +01:00
Paolo Insogna
8a94b7b2ec
unix: enable getrusage for SunOS (#4707)
Fixes: https://github.com/libuv/libuv/issues/4706
2025-02-21 22:02:18 +01:00
rainlow
b807450e98
unix: add thread affinity support on openharmony (#4705) 2025-02-21 22:01:16 +01:00
Hüseyin Açacak
82cdfb75ff win: fix the inconsistency in volume serial number 2025-02-17 08:35:37 +01:00
Juan José Arboleda
dcace2a393 unix: remove unnecessary errno.h include in poll.c
Signed-off-by: Juan José Arboleda <soyjuanarbol@gmail.com>
2025-02-17 07:51:25 +01:00
Velikiy Kirill
378edb28f4
doc: add C3 bindings to LINKS.md (#4699) 2025-02-15 11:11:35 -05:00
Jinho Jang
7894072528
macos: increase child process stdio buffer size (#4694)
On macOS, when calling `spawn`, the child process's stdio buffer
size is 8192 bytes. This is due to the AF_UNIX socket buffer size
being 8192 bytes in the XNU kernel.

When large amounts of data are transferred through the child
process's stdio, this buffer size can cause performance issues.
To mitigate this, the buffer size has been increased to 65536
bytes, aligning it with the behavior on Linux.
2025-02-10 10:07:50 -05:00
Hüseyin Açacak
abe59d6319 win: fix order of FILE_STAT_BASIC_INFORMATION struct fields 2025-02-10 12:32:57 +01:00
Julio Jordán
e399e00e78
doc: fix README link text (#4693) 2025-02-08 09:42:12 -05:00
Andrey
51477bc711
macos,bsd: handle missing /dev/null in chroot env (#4689)
Co-authored-by: Ben Noordhuis <info@bnoordhuis.nl>
2025-02-04 21:43:18 +01:00
Morten Engelhardt Olsen
23632e9104
win: check cwd length before spawning a child process
The CreateProcess API on Windows is still not longPathAware,
even if the process itself is. So, if the cwd used for CreateProcess
is too long, then the call fails with a 'INVALID_DIRECTORY' error.

To deal with this, check the length of the cwd and shorten it if it
is longer than MAX_PATH.
2025-01-29 22:51:06 +01:00
Ben Noordhuis
a6ddf41edf
linux: try preadv64/pwritev64 before preadv/pwritev (#4683)
Fixes: https://github.com/libuv/libuv/issues/4678
Refs: https://github.com/libuv/libuv/issues/4532
2025-01-28 09:27:58 +01:00
Ben Noordhuis
82351168b3
win: lazy-load [GS]etThreadDescription symbols (#4679)
Said symbols are not by default available on Windows Server 2016 but
libuv can still use them when
api-ms-win-core-processthreads-l1-1-3.dll is present.

Fixes: https://github.com/libuv/libuv/issues/4677
2025-01-24 21:53:22 +01:00
Saúl Ibarra Corretgé
bc19beadbd docs: fix RTD build
Setting the configuration key is now mandatory: https://about.readthedocs.com/blog/2024/12/deprecate-config-files-without-sphinx-or-mkdocs-config/
2025-01-24 14:11:13 +01:00
Saúl Ibarra Corretgé
f15c602bd0 win: fix leak in uv_os_tmpdir
Fixes: https://github.com/libuv/libuv/issues/4680
2025-01-24 11:46:16 +01:00
Santiago Gimeno
0f31978c30
Now working on version 1.50.1 2025-01-15 19:11:00 +01:00
Santiago Gimeno
a2ba04f83f Add SHA to ChangeLog 2025-01-15 19:05:30 +01:00
35 changed files with 646 additions and 248 deletions

View File

@ -2,7 +2,7 @@ version: 2
sphinx:
builder: html
configuration: null
configuration: docs/src/conf.py
fail_on_warning: false
build:

View File

@ -1,4 +1,4 @@
2025.01.15, Version 1.50.0 (Stable)
2025.01.15, Version 1.50.0 (Stable), 8fb9cb919489a48880680a56efecff6a7dfb4504
Changes since version 1.49.2:

View File

@ -108,3 +108,5 @@
* [node.pas](https://github.com/vovach777/node.pas) NodeJS-like ecosystem
* Haskell
* [Z.Haskell](https://z.haskell.world)
* C3
* [libuv.c3l](https://github.com/velikoss/libuv.c3l)

View File

@ -13,7 +13,7 @@
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
AC_PREREQ(2.57)
AC_INIT([libuv], [1.50.0], [https://github.com/libuv/libuv/issues])
AC_INIT([libuv], [1.50.1-dev], [https://github.com/libuv/libuv/issues])
AC_CONFIG_MACRO_DIR([m4])
m4_include([m4/libuv-extra-automake-flags.m4])
m4_include([m4/as_case.m4])

View File

@ -430,6 +430,12 @@ API
Equivalent to :man:`utime(2)`, :man:`futimes(3)` and :man:`lutimes(3)` respectively.
Passing `UV_FS_UTIME_NOW` as the atime or mtime sets the timestamp to the
current time.
Passing `UV_FS_UTIME_OMIT` as the atime or mtime leaves the timestamp
untouched.
.. note::
z/OS: `uv_fs_lutime()` is not implemented for z/OS. It can still be called but will return
``UV_ENOSYS``.

View File

@ -58,5 +58,5 @@ libuv can be downloaded from `here <https://dist.libuv.org/dist/>`_.
Installation
------------
Installation instructions can be found in `the README <https://github.com/libuv/libuv/blob/master/README.md>`_.
Installation instructions can be found in the `README <https://github.com/libuv/libuv/blob/master/README.md>`_.

View File

@ -146,6 +146,8 @@ Threads
a thread name can be: Linux, IBM i (16), macOS (64), Windows (32767), and NetBSD (32), etc. `uv_thread_setname()`
will truncate it in case `name` is larger than the limit of the platform.
Not supported on Windows Server 2016, returns `UV_ENOSYS`.
.. versionadded:: 1.50.0
.. c:function:: int uv_thread_getname(uv_thread_t* tid, char* name, size_t* size)
@ -155,9 +157,12 @@ Threads
The buffer should be large enough to hold the name of the thread plus the trailing NUL, or it will be truncated to fit
with the trailing NUL.
Not supported on Windows Server 2016, returns `UV_ENOSYS`.
.. versionadded:: 1.50.0
.. c:function:: int uv_thread_setpriority(uv_thread_t tid, int priority)
If the function succeeds, the return value is 0.
If the function fails, the return value is less than zero.
Sets the scheduling priority of the thread specified by tid. It requires elevated
@ -165,7 +170,9 @@ Threads
The priority can be set to the following constants. UV_THREAD_PRIORITY_HIGHEST,
UV_THREAD_PRIORITY_ABOVE_NORMAL, UV_THREAD_PRIORITY_NORMAL,
UV_THREAD_PRIORITY_BELOW_NORMAL, UV_THREAD_PRIORITY_LOWEST.
.. c:function:: int uv_thread_getpriority(uv_thread_t tid, int* priority)
If the function succeeds, the return value is 0.
If the function fails, the return value is less than zero.
Retrieves the scheduling priority of the thread specified by tid. The value in the

View File

@ -27,10 +27,15 @@ Data types
typedef enum {
/* Initial/normal terminal mode */
UV_TTY_MODE_NORMAL,
/* Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also enabled) */
/*
* Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also enabled).
* May become equivalent to UV_TTY_MODE_RAW_VT in future libuv versions.
*/
UV_TTY_MODE_RAW,
/* Binary-safe I/O mode for IPC (Unix-only) */
UV_TTY_MODE_IO
UV_TTY_MODE_IO,
/* Raw input mode. On Windows ENABLE_VIRTUAL_TERMINAL_INPUT is also set. */
UV_TTY_MODE_RAW_VT
} uv_tty_mode_t;
.. c:enum:: uv_tty_vtermstate_t

View File

@ -58,6 +58,7 @@ extern "C" {
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
#include <math.h>
/* Internal type, do not use. */
struct uv__queue {
@ -805,10 +806,15 @@ struct uv_tty_s {
typedef enum {
/* Initial/normal terminal mode */
UV_TTY_MODE_NORMAL,
/* Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also enabled) */
/*
* Raw input mode (On Windows, ENABLE_WINDOW_INPUT is also enabled).
* May become equivalent to UV_TTY_MODE_RAW_VT in future libuv versions.
*/
UV_TTY_MODE_RAW,
/* Binary-safe I/O mode for IPC (Unix-only) */
UV_TTY_MODE_IO
UV_TTY_MODE_IO,
/* Raw input mode. On Windows ENABLE_VIRTUAL_TERMINAL_INPUT is also set. */
UV_TTY_MODE_RAW_VT
} uv_tty_mode_t;
typedef enum {
@ -1585,6 +1591,8 @@ UV_EXTERN int uv_fs_chmod(uv_loop_t* loop,
const char* path,
int mode,
uv_fs_cb cb);
#define UV_FS_UTIME_NOW (INFINITY)
#define UV_FS_UTIME_OMIT (NAN)
UV_EXTERN int uv_fs_utime(uv_loop_t* loop,
uv_fs_t* req,
const char* path,

View File

@ -32,9 +32,9 @@
#define UV_VERSION_MAJOR 1
#define UV_VERSION_MINOR 50
#define UV_VERSION_PATCH 0
#define UV_VERSION_IS_RELEASE 1
#define UV_VERSION_SUFFIX ""
#define UV_VERSION_PATCH 1
#define UV_VERSION_IS_RELEASE 0
#define UV_VERSION_SUFFIX "dev"
#define UV_VERSION_HEX ((UV_VERSION_MAJOR << 16) | \
(UV_VERSION_MINOR << 8) | \

View File

@ -499,8 +499,11 @@ typedef struct {
union { \
struct { \
/* Used for readable TTY handles */ \
/* TODO: remove me in v2.x. */ \
HANDLE unused_; \
union { \
/* TODO: remove me in v2.x. */ \
HANDLE unused_; \
int mode; \
} mode; \
uv_buf_t read_line_buffer; \
HANDLE read_raw_wait; \
/* Fields used for translating win keystrokes into vt100 characters */ \

View File

@ -1120,6 +1120,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
struct ifreq *ifr, *p, flg;
struct in6_ifreq if6;
struct sockaddr_dl* sa_addr;
size_t namelen;
char* name;
ifc.ifc_req = NULL;
sock6fd = -1;
@ -1156,6 +1158,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p))
/* Count all up and running ipv4/ipv6 addresses */
namelen = 0;
ifr = ifc.ifc_req;
while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
p = ifr;
@ -1175,6 +1178,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
continue;
namelen += strlen(ent->ifa_name) + 1;
(*count)++;
}
@ -1182,8 +1186,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
goto cleanup;
/* Alloc the return interface structs */
*addresses = uv__calloc(*count, sizeof(**addresses));
if (!(*addresses)) {
*addresses = uv__calloc(1, *count * sizeof(**addresses) + namelen);
if (*addresses == NULL) {
r = UV_ENOMEM;
goto cleanup;
}
@ -1210,7 +1214,9 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
/* All conditions above must match count loop */
address->name = uv__strdup(p->ifr_name);
namelen = strlen(p->ifr_name) + 1;
address->name = memcpy(name, p->ifr_name, namelen);
name += namelen;
if (inet6)
address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr);
@ -1282,13 +1288,7 @@ cleanup:
void uv_free_interface_addresses(uv_interface_address_t* addresses,
int count) {
int i;
for (i = 0; i < count; ++i) {
uv__free(addresses[i].name);
}
int count) {
uv__free(addresses);
}

View File

@ -280,7 +280,7 @@ static int uv__async_start(uv_loop_t* loop) {
* thus we create one for that, but this fd will not be actually used,
* it's just a placeholder and magic number which is going to be closed
* during the cleanup, as other FDs. */
err = uv__open_cloexec("/dev/null", O_RDONLY);
err = uv__open_cloexec("/", O_RDONLY);
if (err < 0)
return err;

View File

@ -65,13 +65,13 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
return 0;
}
/* TODO(bnoordhuis) share with linux.c */
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
uv_interface_address_t* address;
struct ifaddrs* addrs;
struct ifaddrs* ent;
uv_interface_address_t* address;
#if !(defined(__CYGWIN__) || defined(__MSYS__)) && !defined(__GNU__)
int i;
#endif
size_t namelen;
char* name;
*count = 0;
*addresses = NULL;
@ -80,9 +80,11 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
return UV__ERR(errno);
/* Count the number of interfaces */
namelen = 0;
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
continue;
namelen += strlen(ent->ifa_name) + 1;
(*count)++;
}
@ -92,20 +94,22 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
}
/* Make sure the memory is initiallized to zero using calloc() */
*addresses = uv__calloc(*count, sizeof(**addresses));
*addresses = uv__calloc(1, *count * sizeof(**addresses) + namelen);
if (*addresses == NULL) {
freeifaddrs(addrs);
return UV_ENOMEM;
}
name = (char*) &(*addresses)[*count];
address = *addresses;
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
continue;
address->name = uv__strdup(ent->ifa_name);
namelen = strlen(ent->ifa_name) + 1;
address->name = memcpy(name, ent->ifa_name, namelen);
name += namelen;
if (ent->ifa_addr->sa_family == AF_INET6) {
address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
@ -129,6 +133,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
#if !(defined(__CYGWIN__) || defined(__MSYS__)) && !defined(__GNU__)
/* Fill in physical addresses for each interface */
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
int i;
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFPHYS))
continue;
@ -151,13 +157,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
}
/* TODO(bnoordhuis) share with linux.c */
void uv_free_interface_addresses(uv_interface_address_t* addresses,
int count) {
int i;
for (i = 0; i < count; i++) {
uv__free(addresses[i].name);
}
uv__free(addresses);
}

View File

@ -1078,6 +1078,8 @@ int uv_getrusage_thread(uv_rusage_t* rusage) {
return 0;
#elif defined(RUSAGE_LWP)
return uv__getrusage(RUSAGE_LWP, rusage);
#elif defined(RUSAGE_THREAD)
return uv__getrusage(RUSAGE_THREAD, rusage);
#endif /* defined(__APPLE__) */

View File

@ -203,8 +203,23 @@ static ssize_t uv__fs_fdatasync(uv_fs_t* req) {
}
UV_UNUSED(static struct timespec uv__fs_to_timespec(double time)) {
#if defined(__APPLE__) \
|| defined(_AIX71) \
|| defined(__DragonFly__) \
|| defined(__FreeBSD__) \
|| defined(__HAIKU__) \
|| defined(__NetBSD__) \
|| defined(__OpenBSD__) \
|| defined(__linux__) \
|| defined(__sun)
static struct timespec uv__fs_to_timespec(double time) {
struct timespec ts;
if (uv__isinf(time))
return (struct timespec){UTIME_NOW, UTIME_NOW};
if (uv__isnan(time))
return (struct timespec){UTIME_OMIT, UTIME_OMIT};
ts.tv_sec = time;
ts.tv_nsec = (time - ts.tv_sec) * 1e9;
@ -221,41 +236,23 @@ UV_UNUSED(static struct timespec uv__fs_to_timespec(double time)) {
}
return ts;
}
#endif
UV_UNUSED(static struct timeval uv__fs_to_timeval(double time)) {
struct timeval tv;
tv.tv_sec = time;
tv.tv_usec = (time - tv.tv_sec) * 1e6;
if (tv.tv_usec < 0) {
tv.tv_usec += 1e6;
tv.tv_sec -= 1;
}
return tv;
}
static ssize_t uv__fs_futime(uv_fs_t* req) {
#if defined(__linux__) \
#if defined(__APPLE__) \
|| defined(_AIX71) \
|| defined(__DragonFly__) \
|| defined(__FreeBSD__) \
|| defined(__HAIKU__) \
|| defined(__GNU__)
|| defined(__NetBSD__) \
|| defined(__OpenBSD__) \
|| defined(__linux__) \
|| defined(__sun)
struct timespec ts[2];
ts[0] = uv__fs_to_timespec(req->atime);
ts[1] = uv__fs_to_timespec(req->mtime);
return futimens(req->file, ts);
#elif defined(__APPLE__) \
|| defined(__DragonFly__) \
|| defined(__FreeBSD__) \
|| defined(__NetBSD__) \
|| defined(__OpenBSD__) \
|| defined(__sun)
struct timeval tv[2];
tv[0] = uv__fs_to_timeval(req->atime);
tv[1] = uv__fs_to_timeval(req->mtime);
# if defined(__sun)
return futimesat(req->file, NULL, tv);
# else
return futimes(req->file, tv);
# endif
#elif defined(__MVS__)
attrib_t atr;
memset(&atr, 0, sizeof(atr));
@ -461,12 +458,7 @@ static ssize_t uv__pwritev_emul(int fd,
/* The function pointer cache is an uintptr_t because _Atomic void*
* doesn't work on macos/ios/etc...
* Disable optimization on armv7 to work around the bug described in
* https://github.com/libuv/libuv/issues/4532
*/
#if defined(__arm__) && (__ARM_ARCH == 7)
__attribute__((optimize("O0")))
#endif
static ssize_t uv__preadv_or_pwritev(int fd,
const struct iovec* bufs,
size_t nbufs,
@ -479,7 +471,12 @@ static ssize_t uv__preadv_or_pwritev(int fd,
p = (void*) atomic_load_explicit(cache, memory_order_relaxed);
if (p == NULL) {
#ifdef RTLD_DEFAULT
p = dlsym(RTLD_DEFAULT, is_pread ? "preadv" : "pwritev");
/* Try _LARGEFILE_SOURCE version of preadv/pwritev first,
* then fall back to the plain version, for libcs like musl.
*/
p = dlsym(RTLD_DEFAULT, is_pread ? "preadv64" : "pwritev64");
if (p == NULL)
p = dlsym(RTLD_DEFAULT, is_pread ? "preadv" : "pwritev");
dlerror(); /* Clear errors. */
#endif /* RTLD_DEFAULT */
if (p == NULL)
@ -487,10 +484,7 @@ static ssize_t uv__preadv_or_pwritev(int fd,
atomic_store_explicit(cache, (uintptr_t) p, memory_order_relaxed);
}
/* Use memcpy instead of `f = p` to work around a compiler bug,
* see https://github.com/libuv/libuv/issues/4532
*/
memcpy(&f, &p, sizeof(p));
f = p;
return f(fd, bufs, nbufs, off);
}
@ -1145,25 +1139,20 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
static ssize_t uv__fs_utime(uv_fs_t* req) {
#if defined(__linux__) \
|| defined(_AIX71) \
|| defined(__sun) \
|| defined(__HAIKU__)
#if defined(__APPLE__) \
|| defined(_AIX71) \
|| defined(__DragonFly__) \
|| defined(__FreeBSD__) \
|| defined(__HAIKU__) \
|| defined(__NetBSD__) \
|| defined(__OpenBSD__) \
|| defined(__linux__) \
|| defined(__sun)
struct timespec ts[2];
ts[0] = uv__fs_to_timespec(req->atime);
ts[1] = uv__fs_to_timespec(req->mtime);
return utimensat(AT_FDCWD, req->path, ts, 0);
#elif defined(__APPLE__) \
|| defined(__DragonFly__) \
|| defined(__FreeBSD__) \
|| defined(__NetBSD__) \
|| defined(__OpenBSD__)
struct timeval tv[2];
tv[0] = uv__fs_to_timeval(req->atime);
tv[1] = uv__fs_to_timeval(req->mtime);
return utimes(req->path, tv);
#elif defined(_AIX) \
&& !defined(_AIX71)
#elif defined(_AIX) && !defined(_AIX71)
struct utimbuf buf;
buf.actime = req->atime;
buf.modtime = req->mtime;
@ -1184,24 +1173,19 @@ static ssize_t uv__fs_utime(uv_fs_t* req) {
static ssize_t uv__fs_lutime(uv_fs_t* req) {
#if defined(__linux__) || \
defined(_AIX71) || \
defined(__sun) || \
defined(__HAIKU__) || \
defined(__GNU__) || \
defined(__OpenBSD__)
#if defined(__APPLE__) \
|| defined(_AIX71) \
|| defined(__DragonFly__) \
|| defined(__FreeBSD__) \
|| defined(__HAIKU__) \
|| defined(__NetBSD__) \
|| defined(__OpenBSD__) \
|| defined(__linux__) \
|| defined(__sun)
struct timespec ts[2];
ts[0] = uv__fs_to_timespec(req->atime);
ts[1] = uv__fs_to_timespec(req->mtime);
return utimensat(AT_FDCWD, req->path, ts, AT_SYMLINK_NOFOLLOW);
#elif defined(__APPLE__) || \
defined(__DragonFly__) || \
defined(__FreeBSD__) || \
defined(__NetBSD__)
struct timeval tv[2];
tv[0] = uv__fs_to_timeval(req->atime);
tv[1] = uv__fs_to_timeval(req->mtime);
return lutimes(req->path, tv);
#else
errno = ENOSYS;
return -1;

View File

@ -403,6 +403,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
return UV_ENOSYS;
/* The first loop to get the size of the array to be allocated */
namelen = 0;
for (cur = ifap; cur; cur = cur->ifa_next) {
if (!(cur->ifa_addr->sa_family == AF_INET6 ||
cur->ifa_addr->sa_family == AF_INET))
@ -411,6 +412,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
if (!(cur->ifa_flags & IFF_UP && cur->ifa_flags & IFF_RUNNING))
continue;
namelen += strlen(cur->ifa_name) + 1;
(*count)++;
}
@ -420,11 +422,13 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
}
/* Alloc the return interface structs */
*addresses = uv__calloc(*count, sizeof(**addresses));
*addresses = uv__calloc(1, *count * sizeof(**addresses) + namelen);
if (*addresses == NULL) {
Qp2freeifaddrs(ifap);
return UV_ENOMEM;
}
name = (char*) &(*addresses)[*count];
address = *addresses;
/* The second loop to fill in the array */
@ -436,7 +440,9 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
if (!(cur->ifa_flags & IFF_UP && cur->ifa_flags & IFF_RUNNING))
continue;
address->name = uv__strdup(cur->ifa_name);
namelen = strlen(cur->ifa_name) + 1;
address->name = memcpy(name, cur->ifa_name, namelen);
name += namelen;
inet6 = (cur->ifa_addr->sa_family == AF_INET6);
@ -497,13 +503,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
}
void uv_free_interface_addresses(uv_interface_address_t* addresses, int count) {
int i;
for (i = 0; i < count; ++i) {
uv__free(addresses[i].name);
}
void uv_free_interface_addresses(uv_interface_address_t* addresses,
int count) {
uv__free(addresses);
}

View File

@ -1954,11 +1954,15 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
return !exclude_type;
}
/* TODO(bnoordhuis) share with bsd-ifaddrs.c */
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
struct ifaddrs *addrs, *ent;
uv_interface_address_t* address;
struct sockaddr_ll* sll;
struct ifaddrs* addrs;
struct ifaddrs* ent;
size_t namelen;
char* name;
int i;
struct sockaddr_ll *sll;
*count = 0;
*addresses = NULL;
@ -1967,10 +1971,12 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
return UV__ERR(errno);
/* Count the number of interfaces */
namelen = 0;
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
continue;
namelen += strlen(ent->ifa_name) + 1;
(*count)++;
}
@ -1980,19 +1986,22 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
}
/* Make sure the memory is initiallized to zero using calloc() */
*addresses = uv__calloc(*count, sizeof(**addresses));
if (!(*addresses)) {
*addresses = uv__calloc(1, *count * sizeof(**addresses) + namelen);
if (*addresses == NULL) {
freeifaddrs(addrs);
return UV_ENOMEM;
}
name = (char*) &(*addresses)[*count];
address = *addresses;
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
continue;
address->name = uv__strdup(ent->ifa_name);
namelen = strlen(ent->ifa_name) + 1;
address->name = memcpy(name, ent->ifa_name, namelen);
name += namelen;
if (ent->ifa_addr->sa_family == AF_INET6) {
address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
@ -2036,14 +2045,9 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
}
/* TODO(bnoordhuis) share with bsd-ifaddrs.c */
void uv_free_interface_addresses(uv_interface_address_t* addresses,
int count) {
int i;
for (i = 0; i < count; i++) {
uv__free(addresses[i].name);
}
int count) {
uv__free(addresses);
}

View File

@ -24,7 +24,6 @@
#include <unistd.h>
#include <assert.h>
#include <errno.h>
static void uv__poll_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {

View File

@ -188,8 +188,12 @@ void uv__wait_children(uv_loop_t* loop) {
static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) {
int mask;
int fd;
int ret;
int size;
int i;
mask = UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD | UV_INHERIT_STREAM;
size = 64 * 1024;
switch (container->flags & mask) {
case UV_IGNORE:
@ -199,8 +203,17 @@ static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) {
assert(container->data.stream != NULL);
if (container->data.stream->type != UV_NAMED_PIPE)
return UV_EINVAL;
else
return uv_socketpair(SOCK_STREAM, 0, fds, 0, 0);
else {
ret = uv_socketpair(SOCK_STREAM, 0, fds, 0, 0);
if (ret == 0)
for (i = 0; i < 2; i++) {
setsockopt(fds[i], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
setsockopt(fds[i], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
}
}
return ret;
case UV_INHERIT_FD:
case UV_INHERIT_STREAM:

View File

@ -826,6 +826,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
uv_interface_address_t* address;
struct ifaddrs* addrs;
struct ifaddrs* ent;
size_t namelen;
char* name;
*count = 0;
*addresses = NULL;
@ -834,9 +836,11 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
return UV__ERR(errno);
/* Count the number of interfaces */
namelen = 0;
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
if (uv__ifaddr_exclude(ent))
continue;
namelen += strlen(ent->ifa_name) + 1;
(*count)++;
}
@ -845,19 +849,22 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
return 0;
}
*addresses = uv__malloc(*count * sizeof(**addresses));
if (!(*addresses)) {
*addresses = uv__calloc(1, *count * sizeof(**addresses) + namelen);
if (*addresses == NULL) {
freeifaddrs(addrs);
return UV_ENOMEM;
}
name = (char*) &(*addresses)[*count];
address = *addresses;
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
if (uv__ifaddr_exclude(ent))
continue;
address->name = uv__strdup(ent->ifa_name);
namelen = strlen(ent->ifa_name) + 1;
address->name = memcpy(name, ent->ifa_name, namelen);
name += namelen;
if (ent->ifa_addr->sa_family == AF_INET6) {
address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
@ -885,13 +892,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
#endif /* SUNOS_NO_IFADDRS */
void uv_free_interface_addresses(uv_interface_address_t* addresses,
int count) {
int i;
for (i = 0; i < count; i++) {
uv__free(addresses[i].name);
}
int count) {
uv__free(addresses);
}

View File

@ -214,7 +214,7 @@ int uv_thread_setaffinity(uv_thread_t* tid,
if (cpumask[i])
CPU_SET(i, &cpuset);
#if defined(__ANDROID__)
#if defined(__ANDROID__) || defined(__OHOS__)
if (sched_setaffinity(pthread_gettid_np(*tid), sizeof(cpuset), &cpuset))
r = errno;
else
@ -242,7 +242,7 @@ int uv_thread_getaffinity(uv_thread_t* tid,
return UV_EINVAL;
CPU_ZERO(&cpuset);
#if defined(__ANDROID__)
#if defined(__ANDROID__) || defined(__OHOS__)
if (sched_getaffinity(pthread_gettid_np(*tid), sizeof(cpuset), &cpuset))
r = errno;
else

View File

@ -284,6 +284,11 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
int fd;
int rc;
if (uv__is_raw_tty_mode(mode)) {
/* There is only a single raw TTY mode on UNIX. */
mode = UV_TTY_MODE_RAW;
}
if (tty->mode == (int) mode)
return 0;
@ -324,6 +329,8 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
case UV_TTY_MODE_IO:
uv__tty_make_raw(&tmp);
break;
default:
UNREACHABLE();
}
/* Apply changes after draining */

View File

@ -1298,7 +1298,8 @@ static int uv__udp_sendmsgv(int fd,
r = 0;
nsent = 0;
#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)
#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \
(defined(__sun__) && defined(MSG_WAITFORONE))
if (count > 1) {
for (i = 0; i < count; /*empty*/) {
struct mmsghdr m[20];
@ -1325,7 +1326,9 @@ static int uv__udp_sendmsgv(int fd,
goto exit;
}
#endif /* defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) */
#endif /* defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) ||
* (defined(__sun__) && defined(MSG_WAITFORONE))
*/
for (i = 0; i < count; i++, nsent++)
if ((r = uv__udp_sendmsg1(fd, bufs[i], nbufs[i], addrs[i])))

View File

@ -31,6 +31,7 @@
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "uv.h"
#include "uv/tree.h"
@ -125,7 +126,7 @@ enum {
/* Only used by uv_tty_t handles. */
UV_HANDLE_TTY_READABLE = 0x01000000,
UV_HANDLE_TTY_RAW = 0x02000000,
UV_HANDLE_UNUSED0 = 0x02000000,
UV_HANDLE_TTY_SAVED_POSITION = 0x04000000,
UV_HANDLE_TTY_SAVED_ATTRIBUTES = 0x08000000,
@ -140,6 +141,10 @@ enum {
UV_HANDLE_REAP = 0x10000000
};
static inline int uv__is_raw_tty_mode(uv_tty_mode_t m) {
return m == UV_TTY_MODE_RAW || m == UV_TTY_MODE_RAW_VT;
}
int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap);
void uv__loop_close(uv_loop_t* loop);
@ -448,4 +453,22 @@ struct uv__loop_internal_fields_s {
# define UV_PTHREAD_MAX_NAMELEN_NP 16
#endif
/* Open-coded so downstream users don't have to link libm. */
static inline int uv__isinf(double d) {
uint64_t v;
STATIC_ASSERT(sizeof(v) == sizeof(d));
memcpy(&v, &d, sizeof(v));
return (v << 1 >> 53) == 2047 && !(v << 12);
}
/* Open-coded so downstream users don't have to link libm. */
static inline int uv__isnan(double d) {
uint64_t v;
STATIC_ASSERT(sizeof(v) == sizeof(d));
memcpy(&v, &d, sizeof(v));
return (v << 1 >> 53) == 2047 && !!(v << 12);
}
#endif /* UV_COMMON_H_ */

View File

@ -1788,7 +1788,7 @@ INLINE static int fs__stat_handle(HANDLE handle, uv_stat_t* statbuf,
SetLastError(pRtlNtStatusToDosError(nt_status));
return -1;
} else {
stat_info.VolumeSerialNumber.QuadPart = volume_info.VolumeSerialNumber;
stat_info.VolumeSerialNumber.LowPart = volume_info.VolumeSerialNumber;
}
stat_info.DeviceType = device_info.DeviceType;
@ -1839,7 +1839,7 @@ INLINE static void fs__stat_assign_statbuf_null(uv_stat_t* statbuf) {
INLINE static void fs__stat_assign_statbuf(uv_stat_t* statbuf,
FILE_STAT_BASIC_INFORMATION stat_info, int do_lstat) {
statbuf->st_dev = stat_info.VolumeSerialNumber.QuadPart;
statbuf->st_dev = stat_info.VolumeSerialNumber.LowPart;
/* Todo: st_mode should probably always be 0666 for everyone. We might also
* want to report 0777 if the file is a .exe or a directory.
@ -2580,14 +2580,29 @@ fchmod_cleanup:
INLINE static int fs__utime_handle(HANDLE handle, double atime, double mtime) {
FILETIME filetime_a, filetime_m;
FILETIME filetime_as, *filetime_a = &filetime_as;
FILETIME filetime_ms, *filetime_m = &filetime_ms;
FILETIME now;
TIME_T_TO_FILETIME(atime, &filetime_a);
TIME_T_TO_FILETIME(mtime, &filetime_m);
if (uv__isinf(atime) || uv__isinf(mtime))
GetSystemTimeAsFileTime(&now);
if (!SetFileTime(handle, NULL, &filetime_a, &filetime_m)) {
if (uv__isinf(atime))
filetime_a = &now;
else if (uv__isnan(atime))
filetime_a = NULL;
else
TIME_T_TO_FILETIME(atime, filetime_a);
if (uv__isinf(mtime))
filetime_m = &now;
else if (uv__isnan(mtime))
filetime_m = NULL;
else
TIME_T_TO_FILETIME(mtime, filetime_m);
if (!SetFileTime(handle, NULL, filetime_a, filetime_m))
return -1;
}
return 0;
}

View File

@ -898,7 +898,7 @@ int uv_spawn(uv_loop_t* loop,
*env = NULL, *cwd = NULL;
STARTUPINFOW startup;
PROCESS_INFORMATION info;
DWORD process_flags;
DWORD process_flags, cwd_len;
BYTE* child_stdio_buffer;
uv__process_init(loop, process);
@ -947,9 +947,10 @@ int uv_spawn(uv_loop_t* loop,
if (err)
goto done_uv;
cwd_len = wcslen(cwd);
} else {
/* Inherit cwd */
DWORD cwd_len, r;
DWORD r;
cwd_len = GetCurrentDirectoryW(0, NULL);
if (!cwd_len) {
@ -970,6 +971,15 @@ int uv_spawn(uv_loop_t* loop,
}
}
/* If cwd is too long, shorten it */
if (cwd_len >= MAX_PATH) {
cwd_len = GetShortPathNameW(cwd, cwd, cwd_len);
if (cwd_len == 0) {
err = GetLastError();
goto done;
}
}
/* Get PATH environment variable. */
path = find_path(env);
if (path == NULL) {

View File

@ -57,6 +57,9 @@ STATIC_ASSERT(sizeof(uv_thread_t) <= sizeof(void*));
static uv_key_t uv__current_thread_key;
static uv_once_t uv__current_thread_init_guard = UV_ONCE_INIT;
static uv_once_t uv__thread_name_once = UV_ONCE_INIT;
HRESULT (WINAPI *pGetThreadDescription)(HANDLE, PWSTR*);
HRESULT (WINAPI *pSetThreadDescription)(HANDLE, PCWSTR);
static void uv__init_current_thread_key(void) {
@ -278,12 +281,28 @@ int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) {
}
static void uv__thread_name_init_once(void) {
HMODULE m;
m = GetModuleHandleA("api-ms-win-core-processthreads-l1-1-3.dll");
if (m != NULL) {
pGetThreadDescription = (void*) GetProcAddress(m, "GetThreadDescription");
pSetThreadDescription = (void*) GetProcAddress(m, "SetThreadDescription");
}
}
int uv_thread_setname(const char* name) {
HRESULT hr;
WCHAR* namew;
int err;
char namebuf[UV_PTHREAD_MAX_NAMELEN_NP];
uv_once(&uv__thread_name_once, uv__thread_name_init_once);
if (pSetThreadDescription == NULL)
return UV_ENOSYS;
if (name == NULL)
return UV_EINVAL;
@ -295,7 +314,7 @@ int uv_thread_setname(const char* name) {
if (err)
return err;
hr = SetThreadDescription(GetCurrentThread(), namew);
hr = pSetThreadDescription(GetCurrentThread(), namew);
uv__free(namew);
if (FAILED(hr))
return uv_translate_sys_error(HRESULT_CODE(hr));
@ -312,6 +331,11 @@ int uv_thread_getname(uv_thread_t* tid, char* name, size_t size) {
int r;
DWORD exit_code;
uv_once(&uv__thread_name_once, uv__thread_name_init_once);
if (pGetThreadDescription == NULL)
return UV_ENOSYS;
if (name == NULL || size == 0)
return UV_EINVAL;
@ -324,7 +348,7 @@ int uv_thread_getname(uv_thread_t* tid, char* name, size_t size) {
namew = NULL;
thread_name = NULL;
hr = GetThreadDescription(*tid, &namew);
hr = pGetThreadDescription(*tid, &namew);
if (FAILED(hr))
return uv_translate_sys_error(HRESULT_CODE(hr));

View File

@ -58,6 +58,9 @@
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
#endif
#ifndef ENABLE_VIRTUAL_TERMINAL_INPUT
#define ENABLE_VIRTUAL_TERMINAL_INPUT 0x0200
#endif
#define CURSOR_SIZE_SMALL 25
#define CURSOR_SIZE_LARGE 100
@ -119,7 +122,10 @@ static int uv_tty_virtual_width = -1;
* handle signalling SIGWINCH
*/
static HANDLE uv__tty_console_handle = INVALID_HANDLE_VALUE;
static HANDLE uv__tty_console_handle_out = INVALID_HANDLE_VALUE;
static HANDLE uv__tty_console_handle_in = INVALID_HANDLE_VALUE;
static DWORD uv__tty_console_in_original_mode = (DWORD)-1;
static volatile LONG uv__tty_console_in_need_mode_reset = 0;
static int uv__tty_console_height = -1;
static int uv__tty_console_width = -1;
static HANDLE uv__tty_console_resized = INVALID_HANDLE_VALUE;
@ -159,19 +165,21 @@ static uv_tty_vtermstate_t uv__vterm_state = UV_TTY_UNSUPPORTED;
static void uv__determine_vterm_state(HANDLE handle);
void uv__console_init(void) {
DWORD dwMode;
if (uv_sem_init(&uv_tty_output_lock, 1))
abort();
uv__tty_console_handle = CreateFileW(L"CONOUT$",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE,
0,
OPEN_EXISTING,
0,
0);
if (uv__tty_console_handle != INVALID_HANDLE_VALUE) {
uv__tty_console_handle_out = CreateFileW(L"CONOUT$",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE,
0,
OPEN_EXISTING,
0,
0);
if (uv__tty_console_handle_out != INVALID_HANDLE_VALUE) {
CONSOLE_SCREEN_BUFFER_INFO sb_info;
uv_mutex_init(&uv__tty_console_resize_mutex);
if (GetConsoleScreenBufferInfo(uv__tty_console_handle, &sb_info)) {
if (GetConsoleScreenBufferInfo(uv__tty_console_handle_out, &sb_info)) {
uv__tty_console_width = sb_info.dwSize.X;
uv__tty_console_height = sb_info.srWindow.Bottom - sb_info.srWindow.Top + 1;
}
@ -179,6 +187,18 @@ void uv__console_init(void) {
NULL,
WT_EXECUTELONGFUNCTION);
}
uv__tty_console_handle_in = CreateFileW(L"CONIN$",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
0,
OPEN_EXISTING,
0,
0);
if (uv__tty_console_handle_in != INVALID_HANDLE_VALUE) {
if (GetConsoleMode(uv__tty_console_handle_in, &dwMode)) {
uv__tty_console_in_original_mode = dwMode;
}
}
}
@ -253,7 +273,9 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int unused) {
/* Initialize TTY input specific fields. */
tty->flags |= UV_HANDLE_TTY_READABLE | UV_HANDLE_READABLE;
/* TODO: remove me in v2.x. */
tty->tty.rd.unused_ = NULL;
tty->tty.rd.mode.unused_ = NULL;
/* Partially overwrites unused_ again. */
tty->tty.rd.mode.mode = 0;
tty->tty.rd.read_line_buffer = uv_null_buf_;
tty->tty.rd.read_raw_wait = NULL;
@ -344,6 +366,7 @@ static void uv__tty_capture_initial_style(
int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
DWORD flags;
DWORD try_set_flags;
unsigned char was_reading;
uv_alloc_cb alloc_cb;
uv_read_cb read_cb;
@ -353,14 +376,19 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
return UV_EINVAL;
}
if (!!mode == !!(tty->flags & UV_HANDLE_TTY_RAW)) {
if ((int)mode == tty->tty.rd.mode.mode) {
return 0;
}
try_set_flags = 0;
switch (mode) {
case UV_TTY_MODE_NORMAL:
flags = ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT;
break;
case UV_TTY_MODE_RAW_VT:
try_set_flags = ENABLE_VIRTUAL_TERMINAL_INPUT;
InterlockedExchange(&uv__tty_console_in_need_mode_reset, 1);
/* fallthrough */
case UV_TTY_MODE_RAW:
flags = ENABLE_WINDOW_INPUT;
break;
@ -386,16 +414,16 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
}
uv_sem_wait(&uv_tty_output_lock);
if (!SetConsoleMode(tty->handle, flags)) {
if (!SetConsoleMode(tty->handle, flags | try_set_flags) &&
!SetConsoleMode(tty->handle, flags)) {
err = uv_translate_sys_error(GetLastError());
uv_sem_post(&uv_tty_output_lock);
return err;
}
uv_sem_post(&uv_tty_output_lock);
/* Update flag. */
tty->flags &= ~UV_HANDLE_TTY_RAW;
tty->flags |= mode ? UV_HANDLE_TTY_RAW : 0;
/* Update mode. */
tty->tty.rd.mode.mode = mode;
/* If we just stopped reading, restart. */
if (was_reading) {
@ -614,7 +642,7 @@ static void uv__tty_queue_read_line(uv_loop_t* loop, uv_tty_t* handle) {
static void uv__tty_queue_read(uv_loop_t* loop, uv_tty_t* handle) {
if (handle->flags & UV_HANDLE_TTY_RAW) {
if (uv__is_raw_tty_mode(handle->tty.rd.mode.mode)) {
uv__tty_queue_read_raw(loop, handle);
} else {
uv__tty_queue_read_line(loop, handle);
@ -702,7 +730,7 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle,
handle->flags &= ~UV_HANDLE_READ_PENDING;
if (!(handle->flags & UV_HANDLE_READING) ||
!(handle->flags & UV_HANDLE_TTY_RAW)) {
!(uv__is_raw_tty_mode(handle->tty.rd.mode.mode))) {
goto out;
}
@ -1050,7 +1078,7 @@ int uv__tty_read_stop(uv_tty_t* handle) {
if (!(handle->flags & UV_HANDLE_READ_PENDING))
return 0;
if (handle->flags & UV_HANDLE_TTY_RAW) {
if (uv__is_raw_tty_mode(handle->tty.rd.mode.mode)) {
/* Cancel raw read. Write some bullshit event to force the console wait to
* return. */
memset(&record, 0, sizeof record);
@ -2293,7 +2321,17 @@ void uv__tty_endgame(uv_loop_t* loop, uv_tty_t* handle) {
int uv_tty_reset_mode(void) {
/* Not necessary to do anything. */
/**
* Shells on Windows do know to reset output flags after a program exits,
* but not necessarily input flags, so we do that for them.
*/
if (
uv__tty_console_handle_in != INVALID_HANDLE_VALUE &&
uv__tty_console_in_original_mode != (DWORD)-1 &&
InterlockedExchange(&uv__tty_console_in_need_mode_reset, 0) != 0
) {
SetConsoleMode(uv__tty_console_handle_in, uv__tty_console_in_original_mode);
}
return 0;
}
@ -2390,7 +2428,7 @@ static void uv__tty_console_signal_resize(void) {
CONSOLE_SCREEN_BUFFER_INFO sb_info;
int width, height;
if (!GetConsoleScreenBufferInfo(uv__tty_console_handle, &sb_info))
if (!GetConsoleScreenBufferInfo(uv__tty_console_handle_out, &sb_info))
return;
width = sb_info.dwSize.X;

View File

@ -1016,6 +1016,7 @@ int uv_os_homedir(char* buffer, size_t* size) {
int uv_os_tmpdir(char* buffer, size_t* size) {
int r;
wchar_t *path;
size_t len;
@ -1054,7 +1055,9 @@ int uv_os_tmpdir(char* buffer, size_t* size) {
path[len] = L'\0';
}
return uv__copy_utf16_to_utf8(path, len, buffer, size);
r = uv__copy_utf16_to_utf8(path, len, buffer, size);
uv__free(path);
return r;
}

View File

@ -4145,8 +4145,8 @@ typedef struct _FILE_STAT_BASIC_INFORMATION {
ULONG DeviceType;
ULONG DeviceCharacteristics;
ULONG Reserved;
FILE_ID_128 FileId128;
LARGE_INTEGER VolumeSerialNumber;
FILE_ID_128 FileId128;
} FILE_STAT_BASIC_INFORMATION;
#endif
@ -4828,13 +4828,4 @@ typedef int (WINAPI *uv_sGetHostNameW)
int);
extern uv_sGetHostNameW pGetHostNameW;
/* processthreadsapi.h */
#if defined(__MINGW32__)
WINBASEAPI
HRESULT WINAPI GetThreadDescription(HANDLE hThread,
PWSTR *ppszThreadDescription);
WINBASEAPI
HRESULT WINAPI SetThreadDescription(HANDLE hThread, PCWSTR lpThreadDescription);
#endif
#endif /* UV_WIN_WINAPI_H_ */

View File

@ -59,6 +59,18 @@
#define TOO_LONG_NAME_LENGTH 65536
#define PATHMAX 4096
#ifdef _WIN32
static const int is_win32 = 1;
#else
static const int is_win32 = 0;
#endif
#if defined(__APPLE__) || defined(__SUNPRO_C)
static const int is_apple_or_sunpro_c = 1;
#else
static const int is_apple_or_sunpro_c = 0;
#endif
typedef struct {
const char* path;
double atime;
@ -827,43 +839,70 @@ static void check_utime(const char* path,
ASSERT_OK(req.result);
s = &req.statbuf;
if (s->st_atim.tv_nsec == 0 && s->st_mtim.tv_nsec == 0) {
/*
* Test sub-second timestamps only when supported (such as Windows with
if (isfinite(atime)) {
/* Test sub-second timestamps only when supported (such as Windows with
* NTFS). Some other platforms support sub-second timestamps, but that
* support is filesystem-dependent. Notably OS X (HFS Plus) does NOT
* support sub-second timestamps. But kernels may round or truncate in
* either direction, so we may accept either possible answer.
*/
#ifdef _WIN32
ASSERT_DOUBLE_EQ(atime, (long) atime);
ASSERT_DOUBLE_EQ(mtime, (long) atime);
#endif
if (atime > 0 || (long) atime == atime)
ASSERT_EQ(s->st_atim.tv_sec, (long) atime);
if (mtime > 0 || (long) mtime == mtime)
ASSERT_EQ(s->st_mtim.tv_sec, (long) mtime);
ASSERT_GE(s->st_atim.tv_sec, (long) atime - 1);
ASSERT_GE(s->st_mtim.tv_sec, (long) mtime - 1);
ASSERT_LE(s->st_atim.tv_sec, (long) atime);
ASSERT_LE(s->st_mtim.tv_sec, (long) mtime);
} else {
double st_atim;
double st_mtim;
#if !defined(__APPLE__) && !defined(__SUNPRO_C)
/* TODO(vtjnash): would it be better to normalize this? */
ASSERT_DOUBLE_GE(s->st_atim.tv_nsec, 0);
ASSERT_DOUBLE_GE(s->st_mtim.tv_nsec, 0);
#endif
st_atim = s->st_atim.tv_sec + s->st_atim.tv_nsec / 1e9;
st_mtim = s->st_mtim.tv_sec + s->st_mtim.tv_nsec / 1e9;
/*
* Linux does not allow reading reliably the atime of a symlink
* since readlink() can update it
if (s->st_atim.tv_nsec == 0) {
if (is_win32)
ASSERT_DOUBLE_EQ(atime, (long) atime);
if (atime > 0 || (long) atime == atime)
ASSERT_EQ(s->st_atim.tv_sec, (long) atime);
ASSERT_GE(s->st_atim.tv_sec, (long) atime - 1);
ASSERT_LE(s->st_atim.tv_sec, (long) atime);
} else {
double st_atim;
/* TODO(vtjnash): would it be better to normalize this? */
if (!is_apple_or_sunpro_c)
ASSERT_DOUBLE_GE(s->st_atim.tv_nsec, 0);
st_atim = s->st_atim.tv_sec + s->st_atim.tv_nsec / 1e9;
/* Linux does not allow reading reliably the atime of a symlink
* since readlink() can update it
*/
if (!test_lutime)
ASSERT_DOUBLE_EQ(st_atim, atime);
}
} else if (isinf(atime)) {
/* We test with timestamps that are in the distant past
* (if you're a Gen Z-er) so check it's more recent than that.
*/
if (!test_lutime)
ASSERT_DOUBLE_EQ(st_atim, atime);
ASSERT_DOUBLE_EQ(st_mtim, mtime);
ASSERT_GT(s->st_atim.tv_sec, 1739710000);
} else {
ASSERT_OK(0);
}
if (isfinite(mtime)) {
/* Test sub-second timestamps only when supported (such as Windows with
* NTFS). Some other platforms support sub-second timestamps, but that
* support is filesystem-dependent. Notably OS X (HFS Plus) does NOT
* support sub-second timestamps. But kernels may round or truncate in
* either direction, so we may accept either possible answer.
*/
if (s->st_mtim.tv_nsec == 0) {
if (is_win32)
ASSERT_DOUBLE_EQ(mtime, (long) atime);
if (mtime > 0 || (long) mtime == mtime)
ASSERT_EQ(s->st_mtim.tv_sec, (long) mtime);
ASSERT_GE(s->st_mtim.tv_sec, (long) mtime - 1);
ASSERT_LE(s->st_mtim.tv_sec, (long) mtime);
} else {
double st_mtim;
/* TODO(vtjnash): would it be better to normalize this? */
if (!is_apple_or_sunpro_c)
ASSERT_DOUBLE_GE(s->st_mtim.tv_nsec, 0);
st_mtim = s->st_mtim.tv_sec + s->st_mtim.tv_nsec / 1e9;
ASSERT_DOUBLE_EQ(st_mtim, mtime);
}
} else if (isinf(mtime)) {
/* We test with timestamps that are in the distant past
* (if you're a Gen Z-er) so check it's more recent than that.
*/
ASSERT_GT(s->st_mtim.tv_sec, 1739710000);
} else {
ASSERT_OK(0);
}
uv_fs_req_cleanup(&req);
@ -1607,6 +1646,50 @@ TEST_IMPL(fs_fstat) {
}
TEST_IMPL(fs_fstat_st_dev) {
uv_fs_t req;
uv_fs_t req_link;
uv_loop_t* loop = uv_default_loop();
char* test_file = "tmp_st_dev";
char* symlink_file = "tmp_st_dev_link";
unlink(test_file);
unlink(symlink_file);
// Create file
int r = uv_fs_open(NULL, &req, test_file, UV_FS_O_RDWR | UV_FS_O_CREAT,
S_IWUSR | S_IRUSR, NULL);
ASSERT_GE(r, 0);
ASSERT_GE(req.result, 0);
uv_fs_req_cleanup(&req);
// Create a symlink
r = uv_fs_symlink(loop, &req, test_file, symlink_file, 0, NULL);
ASSERT_EQ(r, 0);
uv_fs_req_cleanup(&req);
// Call uv_fs_fstat for file
r = uv_fs_stat(loop, &req, test_file, NULL);
ASSERT_EQ(r, 0);
// Call uv_fs_fstat for symlink
r = uv_fs_stat(loop, &req_link, symlink_file, NULL);
ASSERT_EQ(r, 0);
// Compare st_dev
ASSERT_EQ(((uv_stat_t*)req.ptr)->st_dev, ((uv_stat_t*)req_link.ptr)->st_dev);
// Cleanup
uv_fs_req_cleanup(&req);
uv_fs_req_cleanup(&req_link);
unlink(test_file);
unlink(symlink_file);
MAKE_VALGRIND_HAPPY(loop);
return 0;
}
TEST_IMPL(fs_fstat_stdio) {
int fd;
int res;
@ -2684,13 +2767,46 @@ TEST_IMPL(fs_utime) {
atime = mtime = 400497753.25; /* 1982-09-10 11:22:33.25 */
r = uv_fs_utime(NULL, &req, path, atime, mtime, NULL);
ASSERT_OK(r);
ASSERT_OK(uv_fs_utime(NULL, &req, path, atime, mtime, NULL));
ASSERT_OK(req.result);
uv_fs_req_cleanup(&req);
check_utime(path, atime, mtime, /* test_lutime */ 0);
ASSERT_OK(uv_fs_utime(NULL,
&req,
path,
UV_FS_UTIME_OMIT,
UV_FS_UTIME_OMIT,
NULL));
ASSERT_OK(req.result);
uv_fs_req_cleanup(&req);
check_utime(path, atime, mtime, /* test_lutime */ 0);
ASSERT_OK(uv_fs_utime(NULL,
&req,
path,
UV_FS_UTIME_NOW,
UV_FS_UTIME_OMIT,
NULL));
ASSERT_OK(req.result);
uv_fs_req_cleanup(&req);
check_utime(path, UV_FS_UTIME_NOW, mtime, /* test_lutime */ 0);
ASSERT_OK(uv_fs_utime(NULL, &req, path, atime, mtime, NULL));
ASSERT_OK(req.result);
uv_fs_req_cleanup(&req);
check_utime(path, atime, mtime, /* test_lutime */ 0);
ASSERT_OK(uv_fs_utime(NULL,
&req,
path,
UV_FS_UTIME_OMIT,
UV_FS_UTIME_NOW,
NULL));
ASSERT_OK(req.result);
uv_fs_req_cleanup(&req);
check_utime(path, atime, UV_FS_UTIME_NOW, /* test_lutime */ 0);
atime = mtime = 1291404900.25; /* 2010-12-03 20:35:00.25 - mees <3 */
checkme.path = path;
checkme.atime = atime;
@ -2824,9 +2940,43 @@ TEST_IMPL(fs_futime) {
ASSERT_OK(req.result);
#endif
uv_fs_req_cleanup(&req);
check_utime(path, atime, mtime, /* test_lutime */ 0);
ASSERT_OK(uv_fs_futime(NULL,
&req,
file,
UV_FS_UTIME_OMIT,
UV_FS_UTIME_OMIT,
NULL));
ASSERT_OK(req.result);
uv_fs_req_cleanup(&req);
check_utime(path, atime, mtime, /* test_lutime */ 0);
ASSERT_OK(uv_fs_futime(NULL,
&req,
file,
UV_FS_UTIME_NOW,
UV_FS_UTIME_OMIT,
NULL));
ASSERT_OK(req.result);
uv_fs_req_cleanup(&req);
check_utime(path, UV_FS_UTIME_NOW, mtime, /* test_lutime */ 0);
ASSERT_OK(uv_fs_futime(NULL, &req, file, atime, mtime, NULL));
ASSERT_OK(req.result);
uv_fs_req_cleanup(&req);
check_utime(path, atime, mtime, /* test_lutime */ 0);
ASSERT_OK(uv_fs_futime(NULL,
&req,
file,
UV_FS_UTIME_OMIT,
UV_FS_UTIME_NOW,
NULL));
ASSERT_OK(req.result);
uv_fs_req_cleanup(&req);
check_utime(path, atime, UV_FS_UTIME_NOW, /* test_lutime */ 0);
atime = mtime = 1291404900; /* 2010-12-03 20:35:00 - mees <3 */
checkme.atime = atime;
@ -2888,20 +3038,50 @@ TEST_IMPL(fs_lutime) {
/* Test the synchronous version. */
atime = mtime = 400497753.25; /* 1982-09-10 11:22:33.25 */
checkme.atime = atime;
checkme.mtime = mtime;
checkme.path = symlink_path;
req.data = &checkme;
r = uv_fs_lutime(NULL, &req, symlink_path, atime, mtime, NULL);
#if (defined(_AIX) && !defined(_AIX71)) || \
defined(__MVS__)
#if (defined(_AIX) && !defined(_AIX71)) || defined(__MVS__)
ASSERT_EQ(r, UV_ENOSYS);
RETURN_SKIP("lutime is not implemented for z/OS and AIX versions below 7.1");
#endif
ASSERT_OK(r);
lutime_cb(&req);
ASSERT_EQ(1, lutime_cb_count);
ASSERT_OK(req.result);
uv_fs_req_cleanup(&req);
check_utime(symlink_path, atime, mtime, /* test_lutime */ 1);
ASSERT_OK(uv_fs_lutime(NULL,
&req,
symlink_path,
UV_FS_UTIME_OMIT,
UV_FS_UTIME_OMIT,
NULL));
ASSERT_OK(req.result);
uv_fs_req_cleanup(&req);
check_utime(symlink_path, atime, mtime, /* test_lutime */ 1);
ASSERT_OK(uv_fs_lutime(NULL,
&req,
symlink_path,
UV_FS_UTIME_NOW,
UV_FS_UTIME_OMIT,
NULL));
ASSERT_OK(req.result);
uv_fs_req_cleanup(&req);
check_utime(symlink_path, UV_FS_UTIME_NOW, mtime, /* test_lutime */ 1);
ASSERT_OK(uv_fs_lutime(NULL, &req, symlink_path, atime, mtime, NULL));
ASSERT_OK(req.result);
uv_fs_req_cleanup(&req);
check_utime(symlink_path, atime, mtime, /* test_lutime */ 1);
ASSERT_OK(uv_fs_lutime(NULL,
&req,
symlink_path,
UV_FS_UTIME_OMIT,
UV_FS_UTIME_NOW,
NULL));
ASSERT_OK(req.result);
uv_fs_req_cleanup(&req);
check_utime(symlink_path, atime, UV_FS_UTIME_NOW, /* test_lutime */ 1);
/* Test the asynchronous version. */
atime = mtime = 1291404900; /* 2010-12-03 20:35:00 */
@ -2909,11 +3089,12 @@ TEST_IMPL(fs_lutime) {
checkme.atime = atime;
checkme.mtime = mtime;
checkme.path = symlink_path;
req.data = &checkme;
r = uv_fs_lutime(loop, &req, symlink_path, atime, mtime, lutime_cb);
ASSERT_OK(r);
uv_run(loop, UV_RUN_DEFAULT);
ASSERT_EQ(2, lutime_cb_count);
ASSERT_EQ(1, lutime_cb_count);
/* Cleanup. */
unlink(path);

View File

@ -53,7 +53,8 @@ TEST_DECLARE (tty_raw)
TEST_DECLARE (tty_empty_write)
TEST_DECLARE (tty_large_write)
TEST_DECLARE (tty_raw_cancel)
TEST_DECLARE (tty_duplicate_vt100_fn_key)
TEST_DECLARE (tty_duplicate_vt100_fn_key_libuv)
TEST_DECLARE (tty_duplicate_vt100_fn_key_winvt)
TEST_DECLARE (tty_duplicate_alt_modifier_key)
TEST_DECLARE (tty_composing_character)
TEST_DECLARE (tty_cursor_up)
@ -364,6 +365,7 @@ TEST_DECLARE (fs_mkdtemp)
TEST_DECLARE (fs_mkstemp)
TEST_DECLARE (fs_fstat)
TEST_DECLARE (fs_fstat_stdio)
TEST_DECLARE (fs_fstat_st_dev)
TEST_DECLARE (fs_access)
TEST_DECLARE (fs_chmod)
TEST_DECLARE (fs_copyfile)
@ -635,7 +637,8 @@ TASK_LIST_START
TEST_ENTRY (tty_empty_write)
TEST_ENTRY (tty_large_write)
TEST_ENTRY (tty_raw_cancel)
TEST_ENTRY (tty_duplicate_vt100_fn_key)
TEST_ENTRY (tty_duplicate_vt100_fn_key_libuv)
TEST_ENTRY (tty_duplicate_vt100_fn_key_winvt)
TEST_ENTRY (tty_duplicate_alt_modifier_key)
TEST_ENTRY (tty_composing_character)
TEST_ENTRY (tty_cursor_up)
@ -1083,6 +1086,7 @@ TASK_LIST_START
TEST_ENTRY (fs_mkstemp)
TEST_ENTRY (fs_fstat)
TEST_ENTRY (fs_fstat_stdio)
TEST_ENTRY (fs_fstat_st_dev)
TEST_ENTRY (fs_access)
TEST_ENTRY (fs_chmod)
TEST_ENTRY (fs_copyfile)

View File

@ -236,21 +236,24 @@ TEST_IMPL(platform_output) {
printf(" version: %s\n", uname.version);
printf(" machine: %s\n", uname.machine);
ASSERT_OK(uv_getrusage_thread(&rusage));
ASSERT_UINT64_GE(rusage.ru_utime.tv_sec, 0);
ASSERT_UINT64_GE(rusage.ru_utime.tv_usec, 0);
ASSERT_UINT64_GE(rusage.ru_stime.tv_sec, 0);
ASSERT_UINT64_GE(rusage.ru_stime.tv_usec, 0);
printf("uv_getrusage_thread:\n");
printf(" user: %llu sec %llu microsec\n",
(unsigned long long) rusage.ru_utime.tv_sec,
(unsigned long long) rusage.ru_utime.tv_usec);
printf(" system: %llu sec %llu microsec\n",
(unsigned long long) rusage.ru_stime.tv_sec,
(unsigned long long) rusage.ru_stime.tv_usec);
printf(" page faults: %llu\n", (unsigned long long) rusage.ru_majflt);
printf(" maximum resident set size: %llu\n",
(unsigned long long) rusage.ru_maxrss);
err = uv_getrusage_thread(&rusage);
if (err != UV_ENOTSUP) {
ASSERT_OK(err);
ASSERT_UINT64_GE(rusage.ru_utime.tv_sec, 0);
ASSERT_UINT64_GE(rusage.ru_utime.tv_usec, 0);
ASSERT_UINT64_GE(rusage.ru_stime.tv_sec, 0);
ASSERT_UINT64_GE(rusage.ru_stime.tv_usec, 0);
printf("uv_getrusage_thread:\n");
printf(" user: %llu sec %llu microsec\n",
(unsigned long long) rusage.ru_utime.tv_sec,
(unsigned long long) rusage.ru_utime.tv_usec);
printf(" system: %llu sec %llu microsec\n",
(unsigned long long) rusage.ru_stime.tv_sec,
(unsigned long long) rusage.ru_stime.tv_usec);
printf(" page faults: %llu\n", (unsigned long long) rusage.ru_majflt);
printf(" maximum resident set size: %llu\n",
(unsigned long long) rusage.ru_maxrss);
}
return 0;
}

View File

@ -131,7 +131,7 @@ static void make_key_event_records(WORD virt_key, DWORD ctr_key_state,
# undef KEV
}
TEST_IMPL(tty_duplicate_vt100_fn_key) {
TEST_IMPL(tty_duplicate_vt100_fn_key_libuv) {
int r;
int ttyin_fd;
uv_tty_t tty_in;
@ -163,6 +163,10 @@ TEST_IMPL(tty_duplicate_vt100_fn_key) {
r = uv_read_start((uv_stream_t*)&tty_in, tty_alloc, tty_read);
ASSERT_OK(r);
/*
* libuv has chosen to emit ESC[[A, but other terminals, and even
* Windows itself use a different escape sequence, see the test below.
*/
expect_str = ESC"[[A";
expect_nread = strlen(expect_str);
@ -184,6 +188,62 @@ TEST_IMPL(tty_duplicate_vt100_fn_key) {
return 0;
}
TEST_IMPL(tty_duplicate_vt100_fn_key_winvt) {
int r;
int ttyin_fd;
uv_tty_t tty_in;
uv_loop_t* loop;
HANDLE handle;
INPUT_RECORD records[2];
DWORD written;
loop = uv_default_loop();
/* Make sure we have an FD that refers to a tty */
handle = CreateFileA("conin$",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
ASSERT_PTR_NE(handle, INVALID_HANDLE_VALUE);
ttyin_fd = _open_osfhandle((intptr_t) handle, 0);
ASSERT_GE(ttyin_fd, 0);
ASSERT_EQ(UV_TTY, uv_guess_handle(ttyin_fd));
r = uv_tty_init(uv_default_loop(), &tty_in, ttyin_fd, 1); /* Readable. */
ASSERT_OK(r);
ASSERT(uv_is_readable((uv_stream_t*) &tty_in));
ASSERT(!uv_is_writable((uv_stream_t*) &tty_in));
r = uv_read_start((uv_stream_t*)&tty_in, tty_alloc, tty_read);
ASSERT_OK(r);
/*
* Some keys, like F1, get are assigned a different value by Windows
* in ENABLE_VIRTUAL_TERMINAL_INPUT mode vs. libuv in the test above.
*/
expect_str = ESC"OP";
expect_nread = strlen(expect_str);
/* Turn on raw mode. */
r = uv_tty_set_mode(&tty_in, UV_TTY_MODE_RAW_VT);
ASSERT_OK(r);
/*
* Send F1 keystroke.
*/
make_key_event_records(VK_F1, 0, TRUE, records);
WriteConsoleInputW(handle, records, ARRAY_SIZE(records), &written);
ASSERT_EQ(written, ARRAY_SIZE(records));
uv_run(loop, UV_RUN_DEFAULT);
MAKE_VALGRIND_HAPPY(loop);
return 0;
}
TEST_IMPL(tty_duplicate_alt_modifier_key) {
int r;
int ttyin_fd;