From cfd5944b081a1b740740024c56322d2766384f02 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Wed, 15 May 2019 13:24:08 -0400 Subject: [PATCH 1/9] deps: upgrade to libuv 1.29.1 Notable changes: - uv_get_constrained_memory() has been added. - A race condition in uv_async_send() has been fixed. - uv_get_free_memory() and uv_get_total_memory() now read from /proc/meminfo, which should improve correctness when called from inside an lxc container. - A failed assertion in uv_fs_poll_stop() has been fixed. - A bug in MAC addresses for IP-aliases has been fixed. Fixes: https://github.com/nodejs/node/issues/27170 Fixes: https://github.com/nodejs/node/issues/27493 PR-URL: https://github.com/nodejs/node/pull/27718 Reviewed-By: Refael Ackermann Reviewed-By: Ali Ijaz Sheikh Reviewed-By: Ben Noordhuis Reviewed-By: Santiago Gimeno Reviewed-By: Rich Trott Reviewed-By: James M Snell --- deps/uv/.mailmap | 1 + deps/uv/AUTHORS | 6 + deps/uv/CMakeLists.txt | 3 +- deps/uv/ChangeLog | 56 ++++++++ deps/uv/Makefile.am | 3 +- deps/uv/README.md | 13 +- deps/uv/configure.ac | 2 +- deps/uv/docs/src/async.rst | 4 + deps/uv/docs/src/fs.rst | 5 +- deps/uv/docs/src/misc.rst | 13 ++ deps/uv/docs/src/sphinx-plugins/manpage.py | 1 - deps/uv/include/uv.h | 1 + deps/uv/include/uv/unix.h | 9 +- deps/uv/include/uv/version.h | 4 +- deps/uv/src/fs-poll.c | 2 +- deps/uv/src/unix/aix.c | 5 + deps/uv/src/unix/async.c | 37 ++++- deps/uv/src/unix/core.c | 29 +++- deps/uv/src/unix/darwin.c | 5 + deps/uv/src/unix/freebsd.c | 5 + deps/uv/src/unix/fs.c | 4 +- deps/uv/src/unix/fsevents.c | 3 +- deps/uv/src/unix/ibmi.c | 142 ++++++++++++++++++- deps/uv/src/unix/internal.h | 1 + deps/uv/src/unix/kqueue.c | 12 +- deps/uv/src/unix/linux-core.c | 156 ++++++++++++++++++--- deps/uv/src/unix/linux-syscalls.c | 5 +- deps/uv/src/unix/netbsd.c | 5 + deps/uv/src/unix/openbsd.c | 5 + deps/uv/src/unix/os390.c | 5 + deps/uv/src/unix/process.c | 4 +- deps/uv/src/unix/sunos.c | 5 + deps/uv/src/win/util.c | 13 +- deps/uv/test/test-fs-poll.c | 39 ++++++ deps/uv/test/test-fs.c | 50 +++++-- deps/uv/test/test-get-memory.c | 6 +- deps/uv/test/test-list.h | 6 +- deps/uv/test/test-spawn.c | 6 + deps/uv/uv.gyp | 1 - 39 files changed, 596 insertions(+), 76 deletions(-) diff --git a/deps/uv/.mailmap b/deps/uv/.mailmap index 8a559787b49a..3d95997e4fe4 100644 --- a/deps/uv/.mailmap +++ b/deps/uv/.mailmap @@ -46,3 +46,4 @@ Yuki Okumura jBarz jBarz ptlomholt +zlargon diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS index 890e6b0d1a46..af91fde4b239 100644 --- a/deps/uv/AUTHORS +++ b/deps/uv/AUTHORS @@ -376,3 +376,9 @@ Rich Trott Milad Farazmand zlargon Yury Selivanov +Oscar Waddell +FX Coudert +George Zhao +Kyle Edwards +ken-cunningham-webuse +Kelvin Jin diff --git a/deps/uv/CMakeLists.txt b/deps/uv/CMakeLists.txt index 7b25511939e6..b3890ddf57d2 100644 --- a/deps/uv/CMakeLists.txt +++ b/deps/uv/CMakeLists.txt @@ -297,8 +297,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux") src/unix/linux-inotify.c src/unix/linux-syscalls.c src/unix/procfs-exepath.c - src/unix/sysinfo-loadavg.c - src/unix/sysinfo-memory.c) + src/unix/sysinfo-loadavg.c) endif() if(CMAKE_SYSTEM_NAME STREQUAL "NetBSD") diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index 3095f9fc1029..51ed5a223a1d 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,3 +1,59 @@ +2019.05.22, Version 1.29.1 (Stable), d16e6094e1eb3b0b5981ef1dd7e03ec4d466944d + +Changes since version 1.29.0: + +* unix: simplify uv/posix.h include logic (cjihrig) + +* test: increase test timeout (cjihrig) + +* linux: fix sscanf() overflows reading from /proc (Ben Noordhuis) + + +2019.05.16, Version 1.29.0 (Stable), 43957efd92c167b352b4c948b617ca7afbee0ed1 + +Changes since version 1.28.0: + +* ibmi: read memory and CPU usage info (Xu Meng) + +* doc: update the cmake testing instruction (zlargon) + +* unix: fix race condition in uv_async_send() (Ben Noordhuis) + +* linux: use O_CLOEXEC instead of EPOLL_CLOEXEC (Ben Noordhuis) + +* doc: mark uv_async_send() as async-signal-safe (Ben Noordhuis) + +* linux: init st_flags and st_gen when using statx (Oscar Waddell) + +* linux: read free/total memory from /proc/meminfo (Ben Noordhuis) + +* test: test zero-sized uv_fs_sendfile() writes (Ben Noordhuis) + +* unix: don't assert on UV_PROCESS_WINDOWS_* flags (Ben Noordhuis) + +* linux: set correct mac address for IP-aliases (Santiago Gimeno) + +* win,util: fix null pointer dereferencing (Tobias Nießen) + +* unix,win: fix `uv_fs_poll_stop()` when active (Anna Henningsen) + +* doc: add missing uv_fs_type entries (Michele Caini) + +* doc: fix build with sphinx 2.x (FX Coudert) + +* unix: don't make statx system call on Android (George Zhao) + +* unix: fix clang scan-build warning (Kyle Edwards) + +* unix: fall back to kqueue on older macOS systems (ken-cunningham-webuse) + +* unix,win: add uv_get_constrained_memory() (Kelvin Jin) + +* darwin: fix thread cancellation fd leak (Ben Noordhuis) + +* linux: fix thread cancellation fd leak (Ben Noordhuis) + + 2019.04.16, Version 1.28.0 (Stable), 7bf8fabfa934660ee0fe889f78e151198a1165fc Changes since version 1.27.0: diff --git a/deps/uv/Makefile.am b/deps/uv/Makefile.am index 22069625e328..07224f32b48e 100644 --- a/deps/uv/Makefile.am +++ b/deps/uv/Makefile.am @@ -425,8 +425,7 @@ libuv_la_SOURCES += src/unix/linux-core.c \ src/unix/linux-syscalls.h \ src/unix/procfs-exepath.c \ src/unix/proctitle.c \ - src/unix/sysinfo-loadavg.c \ - src/unix/sysinfo-memory.c + src/unix/sysinfo-loadavg.c test_run_tests_LDFLAGS += -lutil endif diff --git a/deps/uv/README.md b/deps/uv/README.md index 4e92a8174af6..11874cdb287f 100644 --- a/deps/uv/README.md +++ b/deps/uv/README.md @@ -172,11 +172,14 @@ $ make install To build with [CMake](https://cmake.org/): ```bash -$ mkdir -p out/cmake ; cd out/cmake ; cmake -DBUILD_TESTING=ON ../.. -$ make all test -# Or manually: -$ ./uv_run_tests # shared library build -$ ./uv_run_tests_a # static library build +$ mkdir -p out/cmake ; cd out/cmake # create build directory +$ cmake ../.. -DBUILD_TESTING=ON # generate project with test +$ cmake --build . # build +$ ctest -C Debug --output-on-failure # run tests + +# Or manually run tests: +$ ./out/cmake/uv_run_tests # shared library build +$ ./out/cmake/uv_run_tests_a # static library build ``` To build with GYP, first run: diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac index 75275aa8785f..ad99f9ad380c 100644 --- a/deps/uv/configure.ac +++ b/deps/uv/configure.ac @@ -13,7 +13,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. AC_PREREQ(2.57) -AC_INIT([libuv], [1.28.0], [https://github.com/libuv/libuv/issues]) +AC_INIT([libuv], [1.29.1], [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]) diff --git a/deps/uv/docs/src/async.rst b/deps/uv/docs/src/async.rst index 02e6a58e7838..bf611692f460 100644 --- a/deps/uv/docs/src/async.rst +++ b/deps/uv/docs/src/async.rst @@ -50,6 +50,10 @@ API It's safe to call this function from any thread. The callback will be called on the loop thread. + .. note:: + :c:func:`uv_async_send` is `async-signal-safe `_. + It's safe to call this function from a signal handler. + .. warning:: libuv will coalesce calls to :c:func:`uv_async_send`, that is, not every call to it will yield an execution of the callback. For example: if :c:func:`uv_async_send` is called 5 diff --git a/deps/uv/docs/src/fs.rst b/deps/uv/docs/src/fs.rst index 177db5708426..996624b69514 100644 --- a/deps/uv/docs/src/fs.rst +++ b/deps/uv/docs/src/fs.rst @@ -96,7 +96,10 @@ Data types UV_FS_FCHOWN, UV_FS_REALPATH, UV_FS_COPYFILE, - UV_FS_LCHOWN + UV_FS_LCHOWN, + UV_FS_OPENDIR, + UV_FS_READDIR, + UV_FS_CLOSEDIR } uv_fs_type; .. c:type:: uv_dirent_t diff --git a/deps/uv/docs/src/misc.rst b/deps/uv/docs/src/misc.rst index 4ad4e40af9f7..ef70e14bff8c 100644 --- a/deps/uv/docs/src/misc.rst +++ b/deps/uv/docs/src/misc.rst @@ -461,6 +461,19 @@ API Gets memory information (in bytes). +.. c:function:: uint64_t uv_get_constrained_memory(void) + + Gets the amount of memory available to the process (in bytes) based on + limits imposed by the OS. If there is no such constraint, or the constraint + is unknown, `0` is returned. Note that it is not unusual for this value to + be less than or greater than :c:func:`uv_get_total_memory`. + + .. note:: + This function currently only returns a non-zero value on Linux, based + on cgroups if it is present. + + .. versionadded:: 1.29.0 + .. c:function:: uint64_t uv_hrtime(void) Returns the current high-resolution real time. This is expressed in diff --git a/deps/uv/docs/src/sphinx-plugins/manpage.py b/deps/uv/docs/src/sphinx-plugins/manpage.py index 1d1dc379f410..bb597e280111 100644 --- a/deps/uv/docs/src/sphinx-plugins/manpage.py +++ b/deps/uv/docs/src/sphinx-plugins/manpage.py @@ -39,7 +39,6 @@ def man_role(name, rawtext, text, lineno, inliner, options={}, content=[]): def setup(app): - app.info('Initializing manpage plugin') app.add_role('man', man_role) app.add_config_value('man_url_regex', None, 'env') return diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index df15b8367890..f97801cec2f4 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -1561,6 +1561,7 @@ UV_EXTERN int uv_chdir(const char* dir); UV_EXTERN uint64_t uv_get_free_memory(void); UV_EXTERN uint64_t uv_get_total_memory(void); +UV_EXTERN uint64_t uv_get_constrained_memory(void); UV_EXTERN uint64_t uv_hrtime(void); diff --git a/deps/uv/include/uv/unix.h b/deps/uv/include/uv/unix.h index 26df0ec17a30..f73b7b04408d 100644 --- a/deps/uv/include/uv/unix.h +++ b/deps/uv/include/uv/unix.h @@ -49,8 +49,6 @@ # include "uv/linux.h" #elif defined (__MVS__) # include "uv/os390.h" -#elif defined(__PASE__) -# include "uv/posix.h" #elif defined(_AIX) # include "uv/aix.h" #elif defined(__sun) @@ -63,9 +61,10 @@ defined(__OpenBSD__) || \ defined(__NetBSD__) # include "uv/bsd.h" -#elif defined(__CYGWIN__) || defined(__MSYS__) -# include "uv/posix.h" -#elif defined(__GNU__) +#elif defined(__PASE__) || \ + defined(__CYGWIN__) || \ + defined(__MSYS__) || \ + defined(__GNU__) # include "uv/posix.h" #endif diff --git a/deps/uv/include/uv/version.h b/deps/uv/include/uv/version.h index fcb813b31218..6d3072c73596 100644 --- a/deps/uv/include/uv/version.h +++ b/deps/uv/include/uv/version.h @@ -31,8 +31,8 @@ */ #define UV_VERSION_MAJOR 1 -#define UV_VERSION_MINOR 28 -#define UV_VERSION_PATCH 0 +#define UV_VERSION_MINOR 29 +#define UV_VERSION_PATCH 1 #define UV_VERSION_IS_RELEASE 1 #define UV_VERSION_SUFFIX "" diff --git a/deps/uv/src/fs-poll.c b/deps/uv/src/fs-poll.c index 40cb147e8de5..89864e23fbcc 100644 --- a/deps/uv/src/fs-poll.c +++ b/deps/uv/src/fs-poll.c @@ -241,7 +241,7 @@ static void timer_close_cb(uv_handle_t* timer) { handle = ctx->parent_handle; if (ctx == handle->poll_ctx) { handle->poll_ctx = ctx->previous; - if (handle->poll_ctx == NULL) + if (handle->poll_ctx == NULL && uv__is_closing(handle)) uv__make_close_pending((uv_handle_t*)handle); } else { for (last = handle->poll_ctx, it = last->previous; diff --git a/deps/uv/src/unix/aix.c b/deps/uv/src/unix/aix.c index ec1fb8b01e18..1f36926c02e2 100644 --- a/deps/uv/src/unix/aix.c +++ b/deps/uv/src/unix/aix.c @@ -344,6 +344,11 @@ uint64_t uv_get_total_memory(void) { } +uint64_t uv_get_constrained_memory(void) { + return 0; /* Memory constraints are unknown. */ +} + + void uv_loadavg(double avg[3]) { perfstat_cpu_total_t ps_total; int result = perfstat_cpu_total(NULL, &ps_total, sizeof(ps_total), 1); diff --git a/deps/uv/src/unix/async.c b/deps/uv/src/unix/async.c index 0b450ae0da7f..a5c47bca0590 100644 --- a/deps/uv/src/unix/async.c +++ b/deps/uv/src/unix/async.c @@ -61,14 +61,43 @@ int uv_async_send(uv_async_t* handle) { if (ACCESS_ONCE(int, handle->pending) != 0) return 0; - if (cmpxchgi(&handle->pending, 0, 1) == 0) - uv__async_send(handle->loop); + /* Tell the other thread we're busy with the handle. */ + if (cmpxchgi(&handle->pending, 0, 1) != 0) + return 0; + + /* Wake up the other thread's event loop. */ + uv__async_send(handle->loop); + + /* Tell the other thread we're done. */ + if (cmpxchgi(&handle->pending, 1, 2) != 1) + abort(); return 0; } +/* Only call this from the event loop thread. */ +static int uv__async_spin(uv_async_t* handle) { + int rc; + + for (;;) { + /* rc=0 -- handle is not pending. + * rc=1 -- handle is pending, other thread is still working with it. + * rc=2 -- handle is pending, other thread is done. + */ + rc = cmpxchgi(&handle->pending, 2, 0); + + if (rc != 1) + return rc; + + /* Other thread is busy with this handle, spin until it's done. */ + cpu_relax(); + } +} + + void uv__async_close(uv_async_t* handle) { + uv__async_spin(handle); QUEUE_REMOVE(&handle->queue); uv__handle_stop(handle); } @@ -109,8 +138,8 @@ static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { QUEUE_REMOVE(q); QUEUE_INSERT_TAIL(&loop->async_handles, q); - if (cmpxchgi(&h->pending, 1, 0) == 0) - continue; + if (0 == uv__async_spin(h)) + continue; /* Not pending. */ if (h->async_cb == NULL) continue; diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index e7e9f4b8c10a..3bada900ebdc 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -88,6 +88,10 @@ #include #endif +#if defined(__linux__) +#include +#endif + static int uv__run_pending(uv_loop_t* loop); /* Verify that uv_buf_t is ABI-compatible with struct iovec. */ @@ -510,6 +514,29 @@ int uv__accept(int sockfd) { } +/* close() on macos has the "interesting" quirk that it fails with EINTR + * without closing the file descriptor when a thread is in the cancel state. + * That's why libuv calls close$NOCANCEL() instead. + * + * glibc on linux has a similar issue: close() is a cancellation point and + * will unwind the thread when it's in the cancel state. Work around that + * by making the system call directly. Musl libc is unaffected. + */ +int uv__close_nocancel(int fd) { +#if defined(__APPLE__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdollar-in-identifier-extension" + extern int close$NOCANCEL(int); + return close$NOCANCEL(fd); +#pragma GCC diagnostic pop +#elif defined(__linux__) + return syscall(SYS_close, fd); +#else + return close(fd); +#endif +} + + int uv__close_nocheckstdio(int fd) { int saved_errno; int rc; @@ -517,7 +544,7 @@ int uv__close_nocheckstdio(int fd) { assert(fd > -1); /* Catch uninitialized io_watcher.fd bugs. */ saved_errno = errno; - rc = close(fd); + rc = uv__close_nocancel(fd); if (rc == -1) { rc = UV__ERR(errno); if (rc == UV_EINTR || rc == UV__ERR(EINPROGRESS)) diff --git a/deps/uv/src/unix/darwin.c b/deps/uv/src/unix/darwin.c index 31ad8a9e48a0..e4cd8ff7e0cf 100644 --- a/deps/uv/src/unix/darwin.c +++ b/deps/uv/src/unix/darwin.c @@ -117,6 +117,11 @@ uint64_t uv_get_total_memory(void) { } +uint64_t uv_get_constrained_memory(void) { + return 0; /* Memory constraints are unknown. */ +} + + void uv_loadavg(double avg[3]) { struct loadavg info; size_t size = sizeof(info); diff --git a/deps/uv/src/unix/freebsd.c b/deps/uv/src/unix/freebsd.c index 0f729cfd4776..7de88d6a52fa 100644 --- a/deps/uv/src/unix/freebsd.c +++ b/deps/uv/src/unix/freebsd.c @@ -137,6 +137,11 @@ uint64_t uv_get_total_memory(void) { } +uint64_t uv_get_constrained_memory(void) { + return 0; /* Memory constraints are unknown. */ +} + + void uv_loadavg(double avg[3]) { struct loadavg info; size_t size = sizeof(info); diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c index c6d2259adc40..24a130f5433d 100644 --- a/deps/uv/src/unix/fs.c +++ b/deps/uv/src/unix/fs.c @@ -145,7 +145,7 @@ extern char *mkdtemp(char *template); /* See issue #740 on AIX < 7 */ static int uv__fs_close(int fd) { int rc; - rc = close(fd); + rc = uv__close_nocancel(fd); if (rc == -1) if (errno == EINTR || errno == EINPROGRESS) rc = 0; /* The close is in progress, not an error. */ @@ -1165,6 +1165,8 @@ static int uv__fs_statx(int fd, buf->st_ctim.tv_nsec = statxbuf.stx_ctime.tv_nsec; buf->st_birthtim.tv_sec = statxbuf.stx_btime.tv_sec; buf->st_birthtim.tv_nsec = statxbuf.stx_btime.tv_nsec; + buf->st_flags = 0; + buf->st_gen = 0; return 0; #else diff --git a/deps/uv/src/unix/fsevents.c b/deps/uv/src/unix/fsevents.c index c430562b3729..ddacda31fef8 100644 --- a/deps/uv/src/unix/fsevents.c +++ b/deps/uv/src/unix/fsevents.c @@ -21,9 +21,10 @@ #include "uv.h" #include "internal.h" -#if TARGET_OS_IPHONE +#if TARGET_OS_IPHONE || MAC_OS_X_VERSION_MAX_ALLOWED < 1070 /* iOS (currently) doesn't provide the FSEvents-API (nor CoreServices) */ +/* macOS prior to 10.7 doesn't provide the full FSEvents API so use kqueue */ int uv__fsevents_init(uv_fs_event_t* handle) { return 0; diff --git a/deps/uv/src/unix/ibmi.c b/deps/uv/src/unix/ibmi.c index b1ab549c23f4..8b355033e29c 100644 --- a/deps/uv/src/unix/ibmi.c +++ b/deps/uv/src/unix/ibmi.c @@ -55,19 +55,155 @@ #include #include +#include + + +typedef struct { + int bytes_available; + int bytes_returned; + char current_date_and_time[8]; + char system_name[8]; + char elapsed_time[6]; + char restricted_state_flag; + char reserved; + int percent_processing_unit_used; + int jobs_in_system; + int percent_permanent_addresses; + int percent_temporary_addresses; + int system_asp; + int percent_system_asp_used; + int total_auxiliary_storage; + int current_unprotected_storage_used; + int maximum_unprotected_storage_used; + int percent_db_capability; + int main_storage_size; + int number_of_partitions; + int partition_identifier; + int reserved1; + int current_processing_capacity; + char processor_sharing_attribute; + char reserved2[3]; + int number_of_processors; + int active_jobs_in_system; + int active_threads_in_system; + int maximum_jobs_in_system; + int percent_temporary_256mb_segments_used; + int percent_temporary_4gb_segments_used; + int percent_permanent_256mb_segments_used; + int percent_permanent_4gb_segments_used; + int percent_current_interactive_performance; + int percent_uncapped_cpu_capacity_used; + int percent_shared_processor_pool_used; + long main_storage_size_long; +} SSTS0200; + + +static int get_ibmi_system_status(SSTS0200* rcvr) { + /* rcvrlen is input parameter 2 to QWCRSSTS */ + unsigned int rcvrlen = sizeof(*rcvr); + + /* format is input parameter 3 to QWCRSSTS ("SSTS0200" in EBCDIC) */ + unsigned char format[] = {0xE2, 0xE2, 0xE3, 0xE2, 0xF0, 0xF2, 0xF0, 0xF0}; + + /* reset_status is input parameter 4 to QWCRSSTS ("*NO " in EBCDIC) */ + unsigned char reset_status[] = { + 0x5C, 0xD5, 0xD6, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 + }; + + /* errcode is input parameter 5 to QWCRSSTS */ + struct _errcode { + int bytes_provided; + int bytes_available; + char msgid[7]; + } errcode; + + /* qwcrssts_pointer is the 16-byte tagged system pointer to QWCRSSTS */ + ILEpointer __attribute__((aligned(16))) qwcrssts_pointer; + + /* qwcrssts_argv is the array of argument pointers to QWCRSSTS */ + void* qwcrssts_argv[6]; + + /* Set the IBM i pointer to the QSYS/QWCRSSTS *PGM object */ + int rc = _RSLOBJ2(&qwcrssts_pointer, RSLOBJ_TS_PGM, "QWCRSSTS", "QSYS"); + + if (rc != 0) + return rc; + + /* initialize the QWCRSSTS returned info structure */ + memset(rcvr, 0, sizeof(*rcvr)); + + /* initialize the QWCRSSTS error code structure */ + memset(&errcode, 0, sizeof(errcode)); + errcode.bytes_provided = sizeof(errcode); + + /* initialize the array of argument pointers for the QWCRSSTS API */ + qwcrssts_argv[0] = rcvr; + qwcrssts_argv[1] = &rcvrlen; + qwcrssts_argv[2] = &format; + qwcrssts_argv[3] = &reset_status; + qwcrssts_argv[4] = &errcode; + qwcrssts_argv[5] = NULL; + + /* Call the IBM i QWCRSSTS API from PASE */ + rc = _PGMCALL(&qwcrssts_pointer, (void**)&qwcrssts_argv, 0); + + return rc; +} + + uint64_t uv_get_free_memory(void) { - return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_AVPHYS_PAGES); + SSTS0200 rcvr; + + if (get_ibmi_system_status(&rcvr)) + return 0; + + /* The amount of main storage, in kilobytes, in the system. */ + uint64_t main_storage_size = rcvr.main_storage_size; + + /* The current amount of storage in use for temporary objects. + * in millions (M) of bytes. + */ + uint64_t current_unprotected_storage_used = + rcvr.current_unprotected_storage_used * 1024ULL; + + uint64_t free_storage_size = + (main_storage_size - current_unprotected_storage_used) * 1024ULL; + + return free_storage_size < 0 ? 0 : free_storage_size; } uint64_t uv_get_total_memory(void) { - return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_PHYS_PAGES); + SSTS0200 rcvr; + + if (get_ibmi_system_status(&rcvr)) + return 0; + + return (uint64_t)rcvr.main_storage_size * 1024ULL; +} + + +uint64_t uv_get_constrained_memory(void) { + return 0; /* Memory constraints are unknown. */ } void uv_loadavg(double avg[3]) { + SSTS0200 rcvr; + + if (get_ibmi_system_status(&rcvr)) { avg[0] = avg[1] = avg[2] = 0; return; + } + + /* The average (in tenths) of the elapsed time during which the processing + * units were in use. For example, a value of 411 in binary would be 41.1%. + * This percentage could be greater than 100% for an uncapped partition. + */ + double processing_unit_used_percent = + rcvr.percent_processing_unit_used / 1000.0; + + avg[0] = avg[1] = avg[2] = processing_unit_used_percent; } @@ -110,4 +246,4 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { *count = numcpus; return 0; -} \ No newline at end of file +} diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h index a0846970320d..8c8ddc868ec8 100644 --- a/deps/uv/src/unix/internal.h +++ b/deps/uv/src/unix/internal.h @@ -183,6 +183,7 @@ int uv__nonblock_ioctl(int fd, int set); int uv__nonblock_fcntl(int fd, int set); int uv__close(int fd); /* preserves errno */ int uv__close_nocheckstdio(int fd); +int uv__close_nocancel(int fd); int uv__socket(int domain, int type, int protocol); ssize_t uv__recvmsg(int fd, struct msghdr *msg, int flags); void uv__make_close_pending(uv_handle_t* handle); diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c index 092005161f45..c04e7a485cf9 100644 --- a/deps/uv/src/unix/kqueue.c +++ b/deps/uv/src/unix/kqueue.c @@ -59,7 +59,7 @@ int uv__kqueue_init(uv_loop_t* loop) { } -#if defined(__APPLE__) +#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 static int uv__has_forked_with_cfrunloop; #endif @@ -70,7 +70,7 @@ int uv__io_fork(uv_loop_t* loop) { if (err) return err; -#if defined(__APPLE__) +#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 if (loop->cf_state != NULL) { /* We cannot start another CFRunloop and/or thread in the child process; CF aborts if you try or if you try to touch the thread @@ -86,7 +86,7 @@ int uv__io_fork(uv_loop_t* loop) { uv__free(loop->cf_state); loop->cf_state = NULL; } -#endif +#endif /* #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */ return err; } @@ -458,7 +458,7 @@ int uv_fs_event_start(uv_fs_event_t* handle, if (uv__is_active(handle)) return UV_EINVAL; -#if defined(__APPLE__) +#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 /* Nullify field to perform checks later */ handle->cf_cb = NULL; handle->realpath = NULL; @@ -482,7 +482,7 @@ int uv_fs_event_start(uv_fs_event_t* handle, } return r; } -#endif /* defined(__APPLE__) */ +#endif /* #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */ /* TODO open asynchronously - but how do we report back errors? */ fd = open(path, O_RDONLY); @@ -513,7 +513,7 @@ int uv_fs_event_stop(uv_fs_event_t* handle) { uv__handle_stop(handle); -#if defined(__APPLE__) +#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 if (!uv__has_forked_with_cfrunloop) r = uv__fsevents_close(handle); #endif diff --git a/deps/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c index f8973bb36be7..b539beb86ae5 100644 --- a/deps/uv/src/unix/linux-core.c +++ b/deps/uv/src/unix/linux-core.c @@ -26,6 +26,7 @@ #include "uv.h" #include "internal.h" +#include #include #include #include @@ -79,16 +80,20 @@ static int read_times(FILE* statfile_fp, unsigned int numcpus, uv_cpu_info_t* ci); static void read_speeds(unsigned int numcpus, uv_cpu_info_t* ci); -static unsigned long read_cpufreq(unsigned int cpunum); +static uint64_t read_cpufreq(unsigned int cpunum); int uv__platform_loop_init(uv_loop_t* loop) { int fd; - fd = epoll_create1(EPOLL_CLOEXEC); + /* It was reported that EPOLL_CLOEXEC is not defined on Android API < 21, + * a.k.a. Lollipop. Since EPOLL_CLOEXEC is an alias for O_CLOEXEC on all + * architectures, we just use that instead. + */ + fd = epoll_create1(O_CLOEXEC); /* epoll_create1() can fail either because it's not implemented (old kernel) - * or because it doesn't understand the EPOLL_CLOEXEC flag. + * or because it doesn't understand the O_CLOEXEC flag. */ if (fd == -1 && (errno == ENOSYS || errno == EINVAL)) { fd = epoll_create(256); @@ -715,20 +720,20 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) { static int read_times(FILE* statfile_fp, unsigned int numcpus, uv_cpu_info_t* ci) { - unsigned long clock_ticks; struct uv_cpu_times_s ts; - unsigned long user; - unsigned long nice; - unsigned long sys; - unsigned long idle; - unsigned long dummy; - unsigned long irq; - unsigned int num; - unsigned int len; + uint64_t clock_ticks; + uint64_t user; + uint64_t nice; + uint64_t sys; + uint64_t idle; + uint64_t dummy; + uint64_t irq; + uint64_t num; + uint64_t len; char buf[1024]; clock_ticks = sysconf(_SC_CLK_TCK); - assert(clock_ticks != (unsigned long) -1); + assert(clock_ticks != (uint64_t) -1); assert(clock_ticks != 0); rewind(statfile_fp); @@ -761,7 +766,8 @@ static int read_times(FILE* statfile_fp, * fields, they're not allowed in C89 mode. */ if (6 != sscanf(buf + len, - "%lu %lu %lu %lu %lu %lu", + "%" PRIu64 " %" PRIu64 " %" PRIu64 + "%" PRIu64 " %" PRIu64 " %" PRIu64, &user, &nice, &sys, @@ -783,8 +789,8 @@ static int read_times(FILE* statfile_fp, } -static unsigned long read_cpufreq(unsigned int cpunum) { - unsigned long val; +static uint64_t read_cpufreq(unsigned int cpunum) { + uint64_t val; char buf[1024]; FILE* fp; @@ -797,7 +803,7 @@ static unsigned long read_cpufreq(unsigned int cpunum) { if (fp == NULL) return 0; - if (fscanf(fp, "%lu", &val) != 1) + if (fscanf(fp, "%" PRIu64, &val) != 1) val = 0; fclose(fp); @@ -900,7 +906,10 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { address = *addresses; for (i = 0; i < (*count); i++) { - if (strcmp(address->name, ent->ifa_name) == 0) { + size_t namelen = strlen(ent->ifa_name); + /* Alias interface share the same physical address */ + if (strncmp(address->name, ent->ifa_name, namelen) == 0 && + (address->name[namelen] == 0 || address->name[namelen] == ':')) { sll = (struct sockaddr_ll*)ent->ifa_addr; memcpy(address->phys_addr, sll->sll_addr, sizeof(address->phys_addr)); } @@ -932,3 +941,114 @@ void uv__set_process_title(const char* title) { prctl(PR_SET_NAME, title); /* Only copies first 16 characters. */ #endif } + + +static uint64_t uv__read_proc_meminfo(const char* what) { + uint64_t rc; + ssize_t n; + char* p; + int fd; + char buf[4096]; /* Large enough to hold all of /proc/meminfo. */ + + rc = 0; + fd = uv__open_cloexec("/proc/meminfo", O_RDONLY); + + if (fd == -1) + return 0; + + n = read(fd, buf, sizeof(buf) - 1); + + if (n <= 0) + goto out; + + buf[n] = '\0'; + p = strstr(buf, what); + + if (p == NULL) + goto out; + + p += strlen(what); + + if (1 != sscanf(p, "%" PRIu64 " kB", &rc)) + goto out; + + rc *= 1024; + +out: + + if (uv__close_nocheckstdio(fd)) + abort(); + + return rc; +} + + +uint64_t uv_get_free_memory(void) { + struct sysinfo info; + uint64_t rc; + + rc = uv__read_proc_meminfo("MemFree:"); + + if (rc != 0) + return rc; + + if (0 == sysinfo(&info)) + return (uint64_t) info.freeram * info.mem_unit; + + return 0; +} + + +uint64_t uv_get_total_memory(void) { + struct sysinfo info; + uint64_t rc; + + rc = uv__read_proc_meminfo("MemTotal:"); + + if (rc != 0) + return rc; + + if (0 == sysinfo(&info)) + return (uint64_t) info.totalram * info.mem_unit; + + return 0; +} + + +static uint64_t uv__read_cgroups_uint64(const char* cgroup, const char* param) { + char filename[256]; + uint64_t rc; + int fd; + ssize_t n; + char buf[32]; /* Large enough to hold an encoded uint64_t. */ + + snprintf(filename, 256, "/sys/fs/cgroup/%s/%s", cgroup, param); + + rc = 0; + fd = uv__open_cloexec(filename, O_RDONLY); + + if (fd < 0) + return 0; + + n = read(fd, buf, sizeof(buf) - 1); + + if (n > 0) { + buf[n] = '\0'; + sscanf(buf, "%" PRIu64, &rc); + } + + if (uv__close_nocheckstdio(fd)) + abort(); + + return rc; +} + + +uint64_t uv_get_constrained_memory(void) { + /* + * This might return 0 if there was a problem getting the memory limit from + * cgroups. This is OK because a return value of 0 signifies that the memory + * limit is unknown. + */ + return uv__read_cgroups_uint64("memory", "memory.limit_in_bytes"); +} diff --git a/deps/uv/src/unix/linux-syscalls.c b/deps/uv/src/unix/linux-syscalls.c index beaba4ed9afd..5637cf98a7b3 100644 --- a/deps/uv/src/unix/linux-syscalls.c +++ b/deps/uv/src/unix/linux-syscalls.c @@ -358,7 +358,10 @@ int uv__statx(int dirfd, int flags, unsigned int mask, struct uv__statx* statxbuf) { -#if defined(__NR_statx) + /* __NR_statx make Android box killed by SIGSYS. + * That looks like a seccomp2 sandbox filter rejecting the system call. + */ +#if defined(__NR_statx) && !defined(__ANDROID__) return syscall(__NR_statx, dirfd, path, flags, mask, statxbuf); #else return errno = ENOSYS, -1; diff --git a/deps/uv/src/unix/netbsd.c b/deps/uv/src/unix/netbsd.c index a2a4e521542a..c649bb375f32 100644 --- a/deps/uv/src/unix/netbsd.c +++ b/deps/uv/src/unix/netbsd.c @@ -126,6 +126,11 @@ uint64_t uv_get_total_memory(void) { } +uint64_t uv_get_constrained_memory(void) { + return 0; /* Memory constraints are unknown. */ +} + + int uv_resident_set_memory(size_t* rss) { kvm_t *kd = NULL; struct kinfo_proc2 *kinfo = NULL; diff --git a/deps/uv/src/unix/openbsd.c b/deps/uv/src/unix/openbsd.c index bffb58bcd9ff..ffae7683d8b6 100644 --- a/deps/uv/src/unix/openbsd.c +++ b/deps/uv/src/unix/openbsd.c @@ -136,6 +136,11 @@ uint64_t uv_get_total_memory(void) { } +uint64_t uv_get_constrained_memory(void) { + return 0; /* Memory constraints are unknown. */ +} + + int uv_resident_set_memory(size_t* rss) { struct kinfo_proc kinfo; size_t page_size = getpagesize(); diff --git a/deps/uv/src/unix/os390.c b/deps/uv/src/unix/os390.c index 70e389ece3bc..273ded7ca5e8 100644 --- a/deps/uv/src/unix/os390.c +++ b/deps/uv/src/unix/os390.c @@ -356,6 +356,11 @@ uint64_t uv_get_total_memory(void) { } +uint64_t uv_get_constrained_memory(void) { + return 0; /* Memory constraints are unknown. */ +} + + int uv_resident_set_memory(size_t* rss) { char* ascb; char* rax; diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c index 101c9c53dfaf..b284308dd069 100644 --- a/deps/uv/src/unix/process.c +++ b/deps/uv/src/unix/process.c @@ -315,7 +315,7 @@ static void uv__process_child_init(const uv_process_options_t* options, use_fd = open("/dev/null", fd == 0 ? O_RDONLY : O_RDWR); close_fd = use_fd; - if (use_fd == -1) { + if (use_fd < 0) { uv__write_int(error_fd, UV__ERR(errno)); _exit(127); } @@ -431,6 +431,8 @@ int uv_spawn(uv_loop_t* loop, UV_PROCESS_SETGID | UV_PROCESS_SETUID | UV_PROCESS_WINDOWS_HIDE | + UV_PROCESS_WINDOWS_HIDE_CONSOLE | + UV_PROCESS_WINDOWS_HIDE_GUI | UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS))); uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS); diff --git a/deps/uv/src/unix/sunos.c b/deps/uv/src/unix/sunos.c index fb6b070fd18f..f323d1defdef 100644 --- a/deps/uv/src/unix/sunos.c +++ b/deps/uv/src/unix/sunos.c @@ -380,6 +380,11 @@ uint64_t uv_get_total_memory(void) { } +uint64_t uv_get_constrained_memory(void) { + return 0; /* Memory constraints are unknown. */ +} + + void uv_loadavg(double avg[3]) { (void) getloadavg(avg, 3); } diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c index 2c10728427b6..7ca83213a67c 100644 --- a/deps/uv/src/win/util.c +++ b/deps/uv/src/win/util.c @@ -320,6 +320,11 @@ uint64_t uv_get_total_memory(void) { } +uint64_t uv_get_constrained_memory(void) { + return 0; /* Memory constraints are unknown. */ +} + + uv_pid_t uv_os_getpid(void) { return GetCurrentProcessId(); } @@ -703,9 +708,11 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos_ptr, int* cpu_count_ptr) { return 0; error: - /* This is safe because the cpu_infos array is zeroed on allocation. */ - for (i = 0; i < cpu_count; i++) - uv__free(cpu_infos[i].model); + if (cpu_infos != NULL) { + /* This is safe because the cpu_infos array is zeroed on allocation. */ + for (i = 0; i < cpu_count; i++) + uv__free(cpu_infos[i].model); + } uv__free(cpu_infos); uv__free(sppi); diff --git a/deps/uv/test/test-fs-poll.c b/deps/uv/test/test-fs-poll.c index e19a68780fa7..9dfd5fdd6aa2 100644 --- a/deps/uv/test/test-fs-poll.c +++ b/deps/uv/test/test-fs-poll.c @@ -37,6 +37,10 @@ static void poll_cb_fail(uv_fs_poll_t* handle, int status, const uv_stat_t* prev, const uv_stat_t* curr); +static void poll_cb_noop(uv_fs_poll_t* handle, + int status, + const uv_stat_t* prev, + const uv_stat_t* curr); static uv_fs_poll_t poll_handle; static uv_timer_t timer_handle; @@ -84,6 +88,12 @@ static void poll_cb_fail(uv_fs_poll_t* handle, ASSERT(0 && "fail_cb called"); } +static void poll_cb_noop(uv_fs_poll_t* handle, + int status, + const uv_stat_t* prev, + const uv_stat_t* curr) { +} + static void poll_cb(uv_fs_poll_t* handle, int status, @@ -259,3 +269,32 @@ TEST_IMPL(fs_poll_close_request_multi_stop_start) { MAKE_VALGRIND_HAPPY(); return 0; } + +TEST_IMPL(fs_poll_close_request_stop_when_active) { + /* Regression test for https://github.com/libuv/libuv/issues/2287. */ + uv_loop_t loop; + uv_fs_poll_t poll_handle; + + remove(FIXTURE); + + ASSERT(0 == uv_loop_init(&loop)); + + /* Set up all handles. */ + ASSERT(0 == uv_fs_poll_init(&loop, &poll_handle)); + ASSERT(0 == uv_fs_poll_start(&poll_handle, poll_cb_noop, FIXTURE, 100)); + uv_run(&loop, UV_RUN_ONCE); + + /* Close the timer handle, and do not crash. */ + ASSERT(0 == uv_fs_poll_stop(&poll_handle)); + uv_run(&loop, UV_RUN_ONCE); + + /* Clean up after the test. */ + uv_close((uv_handle_t*) &poll_handle, close_cb); + uv_run(&loop, UV_RUN_ONCE); + ASSERT(close_cb_called == 1); + + ASSERT(0 == uv_loop_close(&loop)); + + MAKE_VALGRIND_HAPPY(); + return 0; +} diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c index 35f7d0c3f165..c3153c717b7c 100644 --- a/deps/uv/test/test-fs.c +++ b/deps/uv/test/test-fs.c @@ -611,6 +611,15 @@ static void sendfile_cb(uv_fs_t* req) { } +static void sendfile_nodata_cb(uv_fs_t* req) { + ASSERT(req == &sendfile_req); + ASSERT(req->fs_type == UV_FS_SENDFILE); + ASSERT(req->result == 0); + sendfile_cb_count++; + uv_fs_req_cleanup(req); +} + + static void open_noent_cb(uv_fs_t* req) { ASSERT(req->fs_type == UV_FS_OPEN); ASSERT(req->result == UV_ENOENT); @@ -1049,7 +1058,7 @@ TEST_IMPL(fs_async_dir) { } -TEST_IMPL(fs_async_sendfile) { +static int test_sendfile(void (*setup)(int), uv_fs_cb cb, off_t expected_size) { int f, r; struct stat s1, s2; @@ -1062,14 +1071,8 @@ TEST_IMPL(fs_async_sendfile) { f = open("test_file", O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR); ASSERT(f != -1); - r = write(f, "begin\n", 6); - ASSERT(r == 6); - - r = lseek(f, 65536, SEEK_CUR); - ASSERT(r == 65542); - - r = write(f, "end\n", 4); - ASSERT(r != -1); + if (setup != NULL) + setup(f); r = close(f); ASSERT(r == 0); @@ -1087,7 +1090,7 @@ TEST_IMPL(fs_async_sendfile) { uv_fs_req_cleanup(&open_req2); r = uv_fs_sendfile(loop, &sendfile_req, open_req2.result, open_req1.result, - 0, 131072, sendfile_cb); + 0, 131072, cb); ASSERT(r == 0); uv_run(loop, UV_RUN_DEFAULT); @@ -1100,9 +1103,10 @@ TEST_IMPL(fs_async_sendfile) { ASSERT(r == 0); uv_fs_req_cleanup(&close_req); - stat("test_file", &s1); - stat("test_file2", &s2); - ASSERT(65546 == s2.st_size && s1.st_size == s2.st_size); + ASSERT(0 == stat("test_file", &s1)); + ASSERT(0 == stat("test_file2", &s2)); + ASSERT(s1.st_size == s2.st_size); + ASSERT(s2.st_size == expected_size); /* Cleanup. */ unlink("test_file"); @@ -1113,6 +1117,23 @@ TEST_IMPL(fs_async_sendfile) { } +static void sendfile_setup(int f) { + ASSERT(6 == write(f, "begin\n", 6)); + ASSERT(65542 == lseek(f, 65536, SEEK_CUR)); + ASSERT(4 == write(f, "end\n", 4)); +} + + +TEST_IMPL(fs_async_sendfile) { + return test_sendfile(sendfile_setup, sendfile_cb, 65546); +} + + +TEST_IMPL(fs_async_sendfile_nodata) { + return test_sendfile(NULL, sendfile_nodata_cb, 0); +} + + TEST_IMPL(fs_mkdtemp) { int r; const char* path_template = "test_dir_XXXXXX"; @@ -1171,6 +1192,7 @@ TEST_IMPL(fs_fstat) { ASSERT(req.result == sizeof(test_buf)); uv_fs_req_cleanup(&req); + memset(&req.statbuf, 0xaa, sizeof(req.statbuf)); r = uv_fs_fstat(NULL, &req, file, NULL); ASSERT(r == 0); ASSERT(req.result == 0); @@ -1257,6 +1279,8 @@ TEST_IMPL(fs_fstat) { s->st_birthtim.tv_sec == t.st_ctim.tv_sec); ASSERT(s->st_birthtim.tv_nsec == 0 || s->st_birthtim.tv_nsec == t.st_ctim.tv_nsec); + ASSERT(s->st_flags == 0); + ASSERT(s->st_gen == 0); #endif uv_fs_req_cleanup(&req); diff --git a/deps/uv/test/test-get-memory.c b/deps/uv/test/test-get-memory.c index 2396939bcb15..0e0864038b32 100644 --- a/deps/uv/test/test-get-memory.c +++ b/deps/uv/test/test-get-memory.c @@ -25,10 +25,12 @@ TEST_IMPL(get_memory) { uint64_t free_mem = uv_get_free_memory(); uint64_t total_mem = uv_get_total_memory(); + uint64_t constrained_mem = uv_get_constrained_memory(); - printf("free_mem=%llu, total_mem=%llu\n", + printf("free_mem=%llu, total_mem=%llu, constrained_mem=%llu\n", (unsigned long long) free_mem, - (unsigned long long) total_mem); + (unsigned long long) total_mem, + (unsigned long long) constrained_mem); ASSERT(free_mem > 0); ASSERT(total_mem > 0); diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index ace501c9796f..8886b07c8a74 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -290,6 +290,7 @@ TEST_DECLARE (fs_poll_getpath) TEST_DECLARE (fs_poll_close_request) TEST_DECLARE (fs_poll_close_request_multi_start_stop) TEST_DECLARE (fs_poll_close_request_multi_stop_start) +TEST_DECLARE (fs_poll_close_request_stop_when_active) TEST_DECLARE (kill) TEST_DECLARE (kill_invalid_signum) TEST_DECLARE (fs_file_noent) @@ -300,6 +301,7 @@ TEST_DECLARE (fs_file_sync) TEST_DECLARE (fs_file_write_null_buffer) TEST_DECLARE (fs_async_dir) TEST_DECLARE (fs_async_sendfile) +TEST_DECLARE (fs_async_sendfile_nodata) TEST_DECLARE (fs_mkdtemp) TEST_DECLARE (fs_fstat) TEST_DECLARE (fs_access) @@ -843,6 +845,7 @@ TASK_LIST_START TEST_ENTRY (fs_poll_close_request) TEST_ENTRY (fs_poll_close_request_multi_start_stop) TEST_ENTRY (fs_poll_close_request_multi_stop_start) + TEST_ENTRY (fs_poll_close_request_stop_when_active) TEST_ENTRY (kill) TEST_ENTRY (kill_invalid_signum) @@ -886,6 +889,7 @@ TASK_LIST_START TEST_ENTRY (fs_file_write_null_buffer) TEST_ENTRY (fs_async_dir) TEST_ENTRY (fs_async_sendfile) + TEST_ENTRY (fs_async_sendfile_nodata) TEST_ENTRY (fs_mkdtemp) TEST_ENTRY (fs_fstat) TEST_ENTRY (fs_access) @@ -959,7 +963,7 @@ TASK_LIST_START TEST_ENTRY (strscpy) TEST_ENTRY (threadpool_queue_work_simple) TEST_ENTRY (threadpool_queue_work_einval) - TEST_ENTRY (threadpool_multiple_event_loops) + TEST_ENTRY_CUSTOM (threadpool_multiple_event_loops, 0, 0, 60000) TEST_ENTRY (threadpool_cancel_getaddrinfo) TEST_ENTRY (threadpool_cancel_getnameinfo) TEST_ENTRY (threadpool_cancel_work) diff --git a/deps/uv/test/test-spawn.c b/deps/uv/test/test-spawn.c index e5fc308a0e43..fea1165d89e0 100644 --- a/deps/uv/test/test-spawn.c +++ b/deps/uv/test/test-spawn.c @@ -1406,6 +1406,12 @@ TEST_IMPL(spawn_setuid_fails) { options.flags |= UV_PROCESS_SETUID; options.uid = 0; + /* These flags should be ignored on Unices. */ + options.flags |= UV_PROCESS_WINDOWS_HIDE; + options.flags |= UV_PROCESS_WINDOWS_HIDE_CONSOLE; + options.flags |= UV_PROCESS_WINDOWS_HIDE_GUI; + options.flags |= UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS; + r = uv_spawn(uv_default_loop(), &process, &options); #if defined(__CYGWIN__) ASSERT(r == UV_EINVAL); diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index 454751b49148..78a83587ba90 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -241,7 +241,6 @@ 'src/unix/linux-syscalls.h', 'src/unix/procfs-exepath.c', 'src/unix/sysinfo-loadavg.c', - 'src/unix/sysinfo-memory.c', ], 'link_settings': { 'libraries': [ '-ldl' ], From 2da9f9fb6a42d1e3331e6ecbfa03f599c31af98e Mon Sep 17 00:00:00 2001 From: cjihrig Date: Thu, 27 Jun 2019 10:31:58 -0400 Subject: [PATCH 2/9] deps: upgrade to libuv 1.30.0 Notable changes: - Support for the Haiku platform has been added. - The maximum UV_THREADPOOL_SIZE has been increased from 128 to 1024. - uv_fs_copyfile() now works properly when the source and destination files are the same. PR-URL: https://github.com/nodejs/node/pull/28449 Fixes: https://github.com/nodejs/node/issues/27746 Reviewed-By: Trivikram Kamat Reviewed-By: Jiawen Geng Reviewed-By: Rich Trott Reviewed-By: Ben Noordhuis --- deps/uv/.gitattributes | 1 + deps/uv/AUTHORS | 7 + deps/uv/CMakeLists.txt | 9 +- deps/uv/ChangeLog | 37 +++++ deps/uv/Makefile.am | 17 +++ deps/uv/configure.ac | 6 +- deps/uv/docs/src/design.rst | 4 +- deps/uv/docs/src/threadpool.rst | 4 +- deps/uv/include/uv/unix.h | 2 + deps/uv/include/uv/version.h | 4 +- deps/uv/src/threadpool.c | 2 +- deps/uv/src/unix/bsd-ifaddrs.c | 7 +- deps/uv/src/unix/core.c | 37 ++++- deps/uv/src/unix/fs.c | 103 ++++++++++---- deps/uv/src/unix/haiku.c | 176 ++++++++++++++++++++++++ deps/uv/src/unix/internal.h | 9 ++ deps/uv/src/unix/process.c | 7 +- deps/uv/src/unix/signal.c | 2 +- deps/uv/src/unix/stream.c | 2 +- deps/uv/src/unix/thread.c | 17 ++- deps/uv/src/win/fs.c | 60 +++++--- deps/uv/test/fixtures/lorem_ipsum.txt | 1 + deps/uv/test/test-cwd-and-chdir.c | 7 + deps/uv/test/test-fs-copyfile.c | 10 +- deps/uv/test/test-fs.c | 60 +++++++- deps/uv/test/test-list.h | 6 +- deps/uv/test/test-tcp-try-write-error.c | 109 +++++++++++++++ deps/uv/test/test.gyp | 1 + 28 files changed, 644 insertions(+), 63 deletions(-) create mode 100644 deps/uv/.gitattributes create mode 100644 deps/uv/src/unix/haiku.c create mode 100644 deps/uv/test/fixtures/lorem_ipsum.txt create mode 100644 deps/uv/test/test-tcp-try-write-error.c diff --git a/deps/uv/.gitattributes b/deps/uv/.gitattributes new file mode 100644 index 000000000000..89297cb79e3a --- /dev/null +++ b/deps/uv/.gitattributes @@ -0,0 +1 @@ +test/fixtures/lorem_ipsum.txt text eol=lf diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS index af91fde4b239..4db18540d46a 100644 --- a/deps/uv/AUTHORS +++ b/deps/uv/AUTHORS @@ -382,3 +382,10 @@ George Zhao Kyle Edwards ken-cunningham-webuse Kelvin Jin +Leorize +Vlad A +Niels Lohmann +Jenil Christo +Evgeny Ermakov +gengjiawen +Leo Chung diff --git a/deps/uv/CMakeLists.txt b/deps/uv/CMakeLists.txt index b3890ddf57d2..f2ed3722c473 100644 --- a/deps/uv/CMakeLists.txt +++ b/deps/uv/CMakeLists.txt @@ -1,7 +1,6 @@ # TODO: determine CMAKE_SYSTEM_NAME on OS/390. Currently assumes "OS/390". cmake_minimum_required(VERSION 3.0) project(libuv) -enable_testing() if(MSVC) list(APPEND uv_cflags /W4) @@ -137,6 +136,7 @@ set(uv_test_sources test/test-tcp-read-stop.c test/test-tcp-shutdown-after-write.c test/test-tcp-try-write.c + test/test-tcp-try-write-error.c test/test-tcp-unexpected-read.c test/test-tcp-write-after-connect.c test/test-tcp-write-fail.c @@ -350,8 +350,11 @@ target_compile_options(uv_a PRIVATE ${uv_cflags}) target_include_directories(uv_a PRIVATE include src) target_link_libraries(uv_a ${uv_libraries}) -if(BUILD_TESTING) - include(CTest) +option(libuv_buildtests "Build the unit tests when BUILD_TESTING is enabled." ON) + +include(CTest) +if(BUILD_TESTING AND libuv_buildtests) + enable_testing() add_executable(uv_run_tests ${uv_test_sources}) target_compile_definitions(uv_run_tests PRIVATE ${uv_defines} USING_UV_SHARED=1) diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index 51ed5a223a1d..b9ed7484a50a 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,3 +1,40 @@ +2019.06.28, Version 1.30.0 (Stable), 365b6f2a0eacda1ff52be8e57ab9381cfddc5dbb + +Changes since version 1.29.1: + +* darwin: fall back to F_BARRIERFSYNC (Ben Noordhuis) + +* darwin: add 32 bit close$NOCANCEL implementation (ken-cunningham-webuse) + +* build, core, unix: add support for Haiku (Leorize) + +* darwin,linux: more conservative minimum stack size (Ben Noordhuis) + +* threadpool: increase UV_THREADPOOL_SIZE limit (Vlad A) + +* unix: return actual error from `uv_try_write()` (Anna Henningsen) + +* darwin: fix build error with macos 10.10 (Ben Noordhuis) + +* unix: make uv_cwd() report UV_ENOBUFS (Ben Noordhuis) + +* unix: make uv_fs_read() fill all buffers (Ben Noordhuis) + +* test: give hrtime test a custom 10s timeout (Ben Noordhuis) + +* fs: fix uv_fs_copyfile if same src and dst (Santiago Gimeno) + +* build: add cmake option to skip building tests (Niels Lohmann) + +* doc: add link to nodejs.org (Jenil Christo) + +* unix: fix a comment typo in signal.c (Evgeny Ermakov) + +* unix: remove redundant cast in process.c (gengjiawen) + +* doc: fix wrong mutex function prototypes (Leo Chung) + + 2019.05.22, Version 1.29.1 (Stable), d16e6094e1eb3b0b5981ef1dd7e03ec4d466944d Changes since version 1.29.0: diff --git a/deps/uv/Makefile.am b/deps/uv/Makefile.am index 07224f32b48e..d213d8f4faec 100644 --- a/deps/uv/Makefile.am +++ b/deps/uv/Makefile.am @@ -117,6 +117,7 @@ endif # WINNT EXTRA_DIST = test/fixtures/empty_file \ test/fixtures/load_error.node \ + test/fixtures/lorem_ipsum.txt \ include \ docs \ img \ @@ -272,6 +273,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/test-tcp-writealot.c \ test/test-tcp-write-fail.c \ test/test-tcp-try-write.c \ + test/test-tcp-try-write-error.c \ test/test-tcp-write-queue-order.c \ test/test-thread-equal.c \ test/test-thread.c \ @@ -320,6 +322,10 @@ test_run_tests_CFLAGS += -D_ALL_SOURCE \ -D_LINUX_SOURCE_COMPAT endif +if HAIKU +test_run_tests_CFLAGS += -D_BSD_SOURCE +endif + if LINUX test_run_tests_CFLAGS += -D_GNU_SOURCE endif @@ -409,6 +415,17 @@ libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \ test_run_tests_LDFLAGS += -lutil endif +if HAIKU +uvinclude_HEADERS += include/uv/posix.h +libuv_la_CFLAGS += -D_BSD_SOURCE +libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \ + src/unix/haiku.c \ + src/unix/no-fsevents.c \ + src/unix/no-proctitle.c \ + src/unix/posix-hrtime.c \ + src/unix/posix-poll.c +endif + if HURD uvinclude_HEADERS += include/uv/posix.h libuv_la_SOURCES += src/unix/no-fsevents.c \ diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac index ad99f9ad380c..626ad4c7b0d9 100644 --- a/deps/uv/configure.ac +++ b/deps/uv/configure.ac @@ -13,7 +13,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. AC_PREREQ(2.57) -AC_INIT([libuv], [1.29.1], [https://github.com/libuv/libuv/issues]) +AC_INIT([libuv], [1.30.0], [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]) @@ -56,6 +56,7 @@ AM_CONDITIONAL([CYGWIN], [AS_CASE([$host_os],[cygwin*], [true], [false]) AM_CONDITIONAL([DARWIN], [AS_CASE([$host_os],[darwin*], [true], [false])]) AM_CONDITIONAL([DRAGONFLY],[AS_CASE([$host_os],[dragonfly*], [true], [false])]) AM_CONDITIONAL([FREEBSD], [AS_CASE([$host_os],[*freebsd*], [true], [false])]) +AM_CONDITIONAL([HAIKU], [AS_CASE([$host_os],[haiku], [true], [false])]) AM_CONDITIONAL([HURD], [AS_CASE([$host_os],[gnu*], [true], [false])]) AM_CONDITIONAL([LINUX], [AS_CASE([$host_os],[linux*], [true], [false])]) AM_CONDITIONAL([MSYS], [AS_CASE([$host_os],[msys*], [true], [false])]) @@ -71,6 +72,9 @@ AS_CASE([$host_os], [netbsd*], [AC_CHECK_LIB([kvm], [kvm_open])]) AS_CASE([$host_os], [kfreebsd*], [ LIBS="$LIBS -lfreebsd-glue" ]) +AS_CASE([$host_os], [haiku], [ + LIBS="$LIBS -lnetwork" +]) AC_CHECK_HEADERS([sys/ahafs_evProds.h]) AC_CONFIG_FILES([Makefile libuv.pc]) AC_CONFIG_LINKS([test/fixtures/empty_file:test/fixtures/empty_file]) diff --git a/deps/uv/docs/src/design.rst b/deps/uv/docs/src/design.rst index 001b12334d23..9594bd1a77ed 100644 --- a/deps/uv/docs/src/design.rst +++ b/deps/uv/docs/src/design.rst @@ -4,9 +4,11 @@ Design overview =============== -libuv is cross-platform support library which was originally written for NodeJS. It's designed +libuv is cross-platform support library which was originally written for `Node.js`_. It's designed around the event-driven asynchronous I/O model. +.. _Node.js: https://nodejs.org + The library provides much more than a simple abstraction over different I/O polling mechanisms: 'handles' and 'streams' provide a high level abstraction for sockets and other entities; cross-platform file I/O and threading functionality is also provided, amongst other things. diff --git a/deps/uv/docs/src/threadpool.rst b/deps/uv/docs/src/threadpool.rst index 93bd236d35e9..ed41c37fe327 100644 --- a/deps/uv/docs/src/threadpool.rst +++ b/deps/uv/docs/src/threadpool.rst @@ -10,7 +10,9 @@ operations, as well as getaddrinfo and getnameinfo requests. Its default size is 4, but it can be changed at startup time by setting the ``UV_THREADPOOL_SIZE`` environment variable to any value (the absolute maximum -is 128). +is 1024). + +.. versionchanged:: 1.29.2 the maximum UV_THREADPOOL_SIZE allowed was increased from 128 to 1024. The threadpool is global and shared across all event loops. When a particular function makes use of the threadpool (i.e. when using :c:func:`uv_queue_work`) diff --git a/deps/uv/include/uv/unix.h b/deps/uv/include/uv/unix.h index f73b7b04408d..6c93ee97de27 100644 --- a/deps/uv/include/uv/unix.h +++ b/deps/uv/include/uv/unix.h @@ -66,6 +66,8 @@ defined(__MSYS__) || \ defined(__GNU__) # include "uv/posix.h" +#elif defined(__HAIKU__) +# include "uv/posix.h" #endif #ifndef NI_MAXHOST diff --git a/deps/uv/include/uv/version.h b/deps/uv/include/uv/version.h index 6d3072c73596..eb1f0c6597ee 100644 --- a/deps/uv/include/uv/version.h +++ b/deps/uv/include/uv/version.h @@ -31,8 +31,8 @@ */ #define UV_VERSION_MAJOR 1 -#define UV_VERSION_MINOR 29 -#define UV_VERSION_PATCH 1 +#define UV_VERSION_MINOR 30 +#define UV_VERSION_PATCH 0 #define UV_VERSION_IS_RELEASE 1 #define UV_VERSION_SUFFIX "" diff --git a/deps/uv/src/threadpool.c b/deps/uv/src/threadpool.c index 4258933c7247..7aa575508fa8 100644 --- a/deps/uv/src/threadpool.c +++ b/deps/uv/src/threadpool.c @@ -27,7 +27,7 @@ #include -#define MAX_THREADPOOL_SIZE 128 +#define MAX_THREADPOOL_SIZE 1024 static uv_once_t once = UV_ONCE_INIT; static uv_cond_t cond; diff --git a/deps/uv/src/unix/bsd-ifaddrs.c b/deps/uv/src/unix/bsd-ifaddrs.c index a4c6bf9d11c7..0d7bbe662a5c 100644 --- a/deps/uv/src/unix/bsd-ifaddrs.c +++ b/deps/uv/src/unix/bsd-ifaddrs.c @@ -31,6 +31,10 @@ #include #endif +#if defined(__HAIKU__) +#define IFF_RUNNING IFF_LINK +#endif + static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) { if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) return 1; @@ -45,7 +49,8 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) { if (exclude_type == UV__EXCLUDE_IFPHYS) return (ent->ifa_addr->sa_family != AF_LINK); #endif -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__) +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__) || \ + defined(__HAIKU__) /* * On BSD getifaddrs returns information related to the raw underlying * devices. We're not interested in this information. diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index 3bada900ebdc..202c75bbb5e9 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -526,8 +526,13 @@ int uv__close_nocancel(int fd) { #if defined(__APPLE__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdollar-in-identifier-extension" +#if defined(__LP64__) extern int close$NOCANCEL(int); return close$NOCANCEL(fd); +#else + extern int close$NOCANCEL$UNIX2003(int); + return close$NOCANCEL$UNIX2003(fd); +#endif #pragma GCC diagnostic pop #elif defined(__linux__) return syscall(SYS_close, fd); @@ -579,7 +584,7 @@ int uv__nonblock_ioctl(int fd, int set) { } -#if !defined(__CYGWIN__) && !defined(__MSYS__) +#if !defined(__CYGWIN__) && !defined(__MSYS__) && !defined(__HAIKU__) int uv__cloexec_ioctl(int fd, int set) { int r; @@ -696,16 +701,38 @@ ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) { int uv_cwd(char* buffer, size_t* size) { + char scratch[1 + UV__PATH_MAX]; + if (buffer == NULL || size == NULL) return UV_EINVAL; - if (getcwd(buffer, *size) == NULL) + /* Try to read directly into the user's buffer first... */ + if (getcwd(buffer, *size) != NULL) + goto fixup; + + if (errno != ERANGE) + return UV__ERR(errno); + + /* ...or into scratch space if the user's buffer is too small + * so we can report how much space to provide on the next try. + */ + if (getcwd(scratch, sizeof(scratch)) == NULL) return UV__ERR(errno); + buffer = scratch; + +fixup: + *size = strlen(buffer); + if (*size > 1 && buffer[*size - 1] == '/') { - buffer[*size-1] = '\0'; - (*size)--; + *size -= 1; + buffer[*size] = '\0'; + } + + if (buffer == scratch) { + *size += 1; + return UV_ENOBUFS; } return 0; @@ -947,7 +974,7 @@ int uv_getrusage(uv_rusage_t* rusage) { rusage->ru_stime.tv_sec = usage.ru_stime.tv_sec; rusage->ru_stime.tv_usec = usage.ru_stime.tv_usec; -#if !defined(__MVS__) +#if !defined(__MVS__) && !defined(__HAIKU__) rusage->ru_maxrss = usage.ru_maxrss; rusage->ru_ixrss = usage.ru_ixrss; rusage->ru_idrss = usage.ru_idrss; diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c index 24a130f5433d..5138c619b02f 100644 --- a/deps/uv/src/unix/fs.c +++ b/deps/uv/src/unix/fs.c @@ -160,12 +160,15 @@ static ssize_t uv__fs_fsync(uv_fs_t* req) { * to the drive platters. This is in contrast to Linux's fdatasync and fsync * which do, according to recent man pages. F_FULLFSYNC is Apple's equivalent * for flushing buffered data to permanent storage. If F_FULLFSYNC is not - * supported by the file system we should fall back to fsync(). This is the - * same approach taken by sqlite. + * supported by the file system we fall back to F_BARRIERFSYNC or fsync(). + * This is the same approach taken by sqlite, except sqlite does not issue + * an F_BARRIERFSYNC call. */ int r; r = fcntl(req->file, F_FULLFSYNC); + if (r != 0) + r = fcntl(req->file, 85 /* F_BARRIERFSYNC */); /* fsync + barrier */ if (r != 0) r = fsync(req->file); return r; @@ -189,7 +192,8 @@ static ssize_t uv__fs_fdatasync(uv_fs_t* req) { static ssize_t uv__fs_futime(uv_fs_t* req) { #if defined(__linux__) \ - || defined(_AIX71) + || defined(_AIX71) \ + || defined(__HAIKU__) /* utimesat() has nanosecond resolution but we stick to microseconds * for the sake of consistency with other platforms. */ @@ -274,6 +278,54 @@ static ssize_t uv__fs_open(uv_fs_t* req) { } +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; +} + + static ssize_t uv__fs_read(uv_fs_t* req) { #if defined(__linux__) static int no_preadv; @@ -303,7 +355,7 @@ static ssize_t uv__fs_read(uv_fs_t* req) { if (no_preadv) retry: # endif { - result = pread(req->file, req->bufs[0].base, req->bufs[0].len, req->off); + result = uv__fs_preadv(req->file, req->bufs, req->nbufs, req->off); } # if defined(__linux__) else { @@ -467,22 +519,13 @@ static int uv__fs_closedir(uv_fs_t* req) { return 0; } -#if defined(_POSIX_PATH_MAX) -# define UV__FS_PATH_MAX _POSIX_PATH_MAX -#elif defined(PATH_MAX) -# define UV__FS_PATH_MAX PATH_MAX -#else -# define UV__FS_PATH_MAX_FALLBACK 8192 -# define UV__FS_PATH_MAX UV__FS_PATH_MAX_FALLBACK -#endif - static ssize_t uv__fs_pathmax_size(const char* path) { ssize_t pathmax; pathmax = pathconf(path, _PC_PATH_MAX); if (pathmax == -1) - pathmax = UV__FS_PATH_MAX; + pathmax = UV__PATH_MAX; return pathmax; } @@ -493,7 +536,9 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) { char* buf; char* newbuf; -#if defined(UV__FS_PATH_MAX_FALLBACK) +#if defined(_POSIX_PATH_MAX) || defined(PATH_MAX) + maxlen = uv__fs_pathmax_size(req->path); +#else /* We may not have a real PATH_MAX. Read size of link. */ struct stat st; int ret; @@ -511,8 +556,6 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) { for some symlinks, such as those in /proc or /sys. */ if (maxlen == 0) maxlen = uv__fs_pathmax_size(req->path); -#else - maxlen = uv__fs_pathmax_size(req->path); #endif buf = uv__malloc(maxlen); @@ -796,7 +839,8 @@ 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(__sun) \ + || defined(__HAIKU__) /* utimesat() has nanosecond resolution but we stick to microseconds * for the sake of consistency with other platforms. */ @@ -903,7 +947,8 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) { uv_fs_t fs_req; uv_file srcfd; uv_file dstfd; - struct stat statsbuf; + struct stat src_statsbuf; + struct stat dst_statsbuf; int dst_flags; int result; int err; @@ -921,7 +966,7 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) { return srcfd; /* Get the source file's mode. */ - if (fstat(srcfd, &statsbuf)) { + if (fstat(srcfd, &src_statsbuf)) { err = UV__ERR(errno); goto out; } @@ -936,7 +981,7 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) { &fs_req, req->new_path, dst_flags, - statsbuf.st_mode, + src_statsbuf.st_mode, NULL); uv_fs_req_cleanup(&fs_req); @@ -945,7 +990,19 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) { goto out; } - if (fchmod(dstfd, statsbuf.st_mode) == -1) { + /* Get the destination file's mode. */ + if (fstat(dstfd, &dst_statsbuf)) { + err = UV__ERR(errno); + goto out; + } + + /* Check if srcfd and dstfd refer to the same file */ + if (src_statsbuf.st_dev == dst_statsbuf.st_dev && + src_statsbuf.st_ino == dst_statsbuf.st_ino) { + goto out; + } + + if (fchmod(dstfd, src_statsbuf.st_mode) == -1) { err = UV__ERR(errno); goto out; } @@ -975,7 +1032,7 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) { } #endif - bytes_to_send = statsbuf.st_size; + bytes_to_send = src_statsbuf.st_size; in_offset = 0; while (bytes_to_send != 0) { err = uv_fs_sendfile(NULL, diff --git a/deps/uv/src/unix/haiku.c b/deps/uv/src/unix/haiku.c new file mode 100644 index 000000000000..7708851c2a5f --- /dev/null +++ b/deps/uv/src/unix/haiku.c @@ -0,0 +1,176 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "internal.h" + +#include /* find_path() */ +#include + + +void uv_loadavg(double avg[3]) { + avg[0] = 0; + avg[1] = 0; + avg[2] = 0; +} + + +int uv_exepath(char* buffer, size_t* size) { + char abspath[B_PATH_NAME_LENGTH]; + status_t status; + ssize_t abspath_len; + + if (buffer == NULL || size == NULL || *size == 0) + return UV_EINVAL; + + status = find_path(B_APP_IMAGE_SYMBOL, B_FIND_PATH_IMAGE_PATH, NULL, abspath, + sizeof(abspath)); + if (status != B_OK) + return UV__ERR(status); + + abspath_len = uv__strscpy(buffer, abspath, *size); + *size -= 1; + if (abspath_len >= 0 && *size > (size_t)abspath_len) + *size = (size_t)abspath_len; + + return 0; +} + + +uint64_t uv_get_free_memory(void) { + status_t status; + system_info sinfo; + + status = get_system_info(&sinfo); + if (status != B_OK) + return 0; + + return (sinfo.max_pages - sinfo.used_pages) * B_PAGE_SIZE; +} + + +uint64_t uv_get_total_memory(void) { + status_t status; + system_info sinfo; + + status = get_system_info(&sinfo); + if (status != B_OK) + return 0; + + return sinfo.max_pages * B_PAGE_SIZE; +} + + +uint64_t uv_get_constrained_memory(void) { + return 0; /* Memory constraints are unknown. */ +} + + +int uv_resident_set_memory(size_t* rss) { + area_info area; + ssize_t cookie; + status_t status; + thread_info thread; + + status = get_thread_info(find_thread(NULL), &thread); + if (status != B_OK) + return UV__ERR(status); + + cookie = 0; + *rss = 0; + while (get_next_area_info(thread.team, &cookie, &area) == B_OK) + *rss += area.ram_size; + + return 0; +} + + +int uv_uptime(double* uptime) { + /* system_time() returns time since booting in microseconds */ + *uptime = (double)system_time() / 1000000; + return 0; +} + + +int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { + cpu_topology_node_info* topology_infos; + int i; + status_t status; + system_info system; + uint32_t topology_count; + uint64_t cpuspeed; + uv_cpu_info_t* cpu_info; + + if (cpu_infos == NULL || count == NULL) + return UV_EINVAL; + + status = get_cpu_topology_info(NULL, &topology_count); + if (status != B_OK) + return UV__ERR(status); + + topology_infos = uv__malloc(topology_count * sizeof(*topology_infos)); + if (topology_infos == NULL) + return UV_ENOMEM; + + status = get_cpu_topology_info(topology_infos, &topology_count); + if (status != B_OK) { + uv__free(topology_infos); + return UV__ERR(status); + } + + cpuspeed = 0; + for (i = 0; i < (int)topology_count; i++) { + if (topology_infos[i].type == B_TOPOLOGY_CORE) { + cpuspeed = topology_infos[i].data.core.default_frequency; + break; + } + } + + uv__free(topology_infos); + + status = get_system_info(&system); + if (status != B_OK) + return UV__ERR(status); + + *cpu_infos = uv__calloc(system.cpu_count, sizeof(**cpu_infos)); + if (*cpu_infos == NULL) + return UV_ENOMEM; + + /* CPU time and model are not exposed by Haiku. */ + cpu_info = *cpu_infos; + for (i = 0; i < (int)system.cpu_count; i++) { + cpu_info->model = uv__strdup("unknown"); + cpu_info->speed = (int)(cpuspeed / 1000000); + cpu_info++; + } + *count = system.cpu_count; + + return 0; +} + +void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { + int i; + + for (i = 0; i < count; i++) + uv__free(cpu_infos[i].model); + + uv__free(cpu_infos); +} diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h index 8c8ddc868ec8..260616474ec1 100644 --- a/deps/uv/src/unix/internal.h +++ b/deps/uv/src/unix/internal.h @@ -25,6 +25,7 @@ #include "uv-common.h" #include +#include /* _POSIX_PATH_MAX, PATH_MAX */ #include /* abort */ #include /* strrchr */ #include /* O_CLOEXEC, may be */ @@ -60,6 +61,14 @@ # include #endif +#if defined(_POSIX_PATH_MAX) +# define UV__PATH_MAX _POSIX_PATH_MAX +#elif defined(PATH_MAX) +# define UV__PATH_MAX PATH_MAX +#else +# define UV__PATH_MAX 8192 +#endif + #if defined(__ANDROID__) int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset); # ifdef pthread_sigmask diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c index b284308dd069..bb6b76c9fa70 100644 --- a/deps/uv/src/unix/process.c +++ b/deps/uv/src/unix/process.c @@ -249,7 +249,7 @@ static int uv__process_open_stream(uv_stdio_container_t* container, static void uv__process_close_stream(uv_stdio_container_t* container) { if (!(container->flags & UV_CREATE_PIPE)) return; - uv__stream_close((uv_stream_t*)container->data.stream); + uv__stream_close(container->data.stream); } @@ -385,6 +385,11 @@ static void uv__process_child_init(const uv_process_options_t* options, if (n == SIGKILL || n == SIGSTOP) continue; /* Can't be changed. */ +#if defined(__HAIKU__) + if (n == SIGKILLTHR) + continue; /* Can't be changed. */ +#endif + if (SIG_ERR != signal(n, SIG_DFL)) continue; diff --git a/deps/uv/src/unix/signal.c b/deps/uv/src/unix/signal.c index 01aa55f3fe7c..5e89ded2d842 100644 --- a/deps/uv/src/unix/signal.c +++ b/deps/uv/src/unix/signal.c @@ -375,7 +375,7 @@ static int uv__signal_start(uv_signal_t* handle, /* Short circuit: if the signal watcher is already watching {signum} don't * go through the process of deregistering and registering the handler. - * Additionally, this avoids pending signals getting lost in the small time + * Additionally, this avoids pending signals getting lost in the small * time frame that handle->signum == 0. */ if (signum == handle->signum) { diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c index 7e4d5fc7ffd4..17b06a39a772 100644 --- a/deps/uv/src/unix/stream.c +++ b/deps/uv/src/unix/stream.c @@ -1541,7 +1541,7 @@ int uv_try_write(uv_stream_t* stream, } if (written == 0 && req_size != 0) - return UV_EAGAIN; + return req.error < 0 ? req.error : UV_EAGAIN; else return written; } diff --git a/deps/uv/src/unix/thread.c b/deps/uv/src/unix/thread.c index 9a50448e62ce..cd0b7aa6aaf9 100644 --- a/deps/uv/src/unix/thread.c +++ b/deps/uv/src/unix/thread.c @@ -178,8 +178,21 @@ static size_t thread_stack_size(void) { if (lim.rlim_cur != RLIM_INFINITY) { /* pthread_attr_setstacksize() expects page-aligned values. */ lim.rlim_cur -= lim.rlim_cur % (rlim_t) getpagesize(); - if (lim.rlim_cur >= PTHREAD_STACK_MIN) - return lim.rlim_cur; + + /* Musl's PTHREAD_STACK_MIN is 2 KB on all architectures, which is + * too small to safely receive signals on. + * + * Musl's PTHREAD_STACK_MIN + MINSIGSTKSZ == 8192 on arm64 (which has + * the largest MINSIGSTKSZ of the architectures that musl supports) so + * let's use that as a lower bound. + * + * We use a hardcoded value because PTHREAD_STACK_MIN + MINSIGSTKSZ + * is between 28 and 133 KB when compiling against glibc, depending + * on the architecture. + */ + if (lim.rlim_cur >= 8192) + if (lim.rlim_cur >= PTHREAD_STACK_MIN) + return lim.rlim_cur; } #endif diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c index 9e2f084c8d0e..7d78d466c873 100644 --- a/deps/uv/src/win/fs.c +++ b/deps/uv/src/win/fs.c @@ -1409,47 +1409,57 @@ INLINE static void fs__stat_prepare_path(WCHAR* pathw) { } -INLINE static void fs__stat_impl(uv_fs_t* req, int do_lstat) { +INLINE static DWORD fs__stat_impl_from_path(WCHAR* path, + int do_lstat, + uv_stat_t* statbuf) { HANDLE handle; DWORD flags; + DWORD ret; flags = FILE_FLAG_BACKUP_SEMANTICS; - if (do_lstat) { + if (do_lstat) flags |= FILE_FLAG_OPEN_REPARSE_POINT; - } - handle = CreateFileW(req->file.pathw, + handle = CreateFileW(path, FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, flags, NULL); - if (handle == INVALID_HANDLE_VALUE) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - return; - } - if (fs__stat_handle(handle, &req->statbuf, do_lstat) != 0) { - DWORD error = GetLastError(); + if (handle == INVALID_HANDLE_VALUE) + ret = GetLastError(); + else if (fs__stat_handle(handle, statbuf, do_lstat) != 0) + ret = GetLastError(); + else + ret = 0; + + CloseHandle(handle); + return ret; +} + + +INLINE static void fs__stat_impl(uv_fs_t* req, int do_lstat) { + DWORD error; + + error = fs__stat_impl_from_path(req->file.pathw, do_lstat, &req->statbuf); + if (error != 0) { if (do_lstat && (error == ERROR_SYMLINK_NOT_SUPPORTED || error == ERROR_NOT_A_REPARSE_POINT)) { /* We opened a reparse point but it was not a symlink. Try again. */ fs__stat_impl(req, 0); - } else { /* Stat failed. */ - SET_REQ_WIN32_ERROR(req, GetLastError()); + SET_REQ_WIN32_ERROR(req, error); } - CloseHandle(handle); return; } req->ptr = &req->statbuf; req->result = 0; - CloseHandle(handle); } @@ -1553,6 +1563,9 @@ static void fs__ftruncate(uv_fs_t* req) { static void fs__copyfile(uv_fs_t* req) { int flags; int overwrite; + DWORD error; + uv_stat_t statbuf; + uv_stat_t new_statbuf; flags = req->fs.info.file_flags; @@ -1563,12 +1576,25 @@ static void fs__copyfile(uv_fs_t* req) { overwrite = flags & UV_FS_COPYFILE_EXCL; - if (CopyFileW(req->file.pathw, req->fs.info.new_pathw, overwrite) == 0) { - SET_REQ_WIN32_ERROR(req, GetLastError()); + if (CopyFileW(req->file.pathw, req->fs.info.new_pathw, overwrite) != 0) { + SET_REQ_RESULT(req, 0); return; } - SET_REQ_RESULT(req, 0); + SET_REQ_WIN32_ERROR(req, GetLastError()); + if (req->result != UV_EBUSY) + return; + + /* if error UV_EBUSY check if src and dst file are the same */ + if (fs__stat_impl_from_path(req->file.pathw, 0, &statbuf) != 0 || + fs__stat_impl_from_path(req->fs.info.new_pathw, 0, &new_statbuf) != 0) { + return; + } + + if (statbuf.st_dev == new_statbuf.st_dev && + statbuf.st_ino == new_statbuf.st_ino) { + SET_REQ_RESULT(req, 0); + } } diff --git a/deps/uv/test/fixtures/lorem_ipsum.txt b/deps/uv/test/fixtures/lorem_ipsum.txt new file mode 100644 index 000000000000..1b376877f435 --- /dev/null +++ b/deps/uv/test/fixtures/lorem_ipsum.txt @@ -0,0 +1 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. diff --git a/deps/uv/test/test-cwd-and-chdir.c b/deps/uv/test/test-cwd-and-chdir.c index 1e95043c1775..5d43524c921c 100644 --- a/deps/uv/test/test-cwd-and-chdir.c +++ b/deps/uv/test/test-cwd-and-chdir.c @@ -33,9 +33,16 @@ TEST_IMPL(cwd_and_chdir) { size_t size2; int err; + size1 = 1; + err = uv_cwd(buffer_orig, &size1); + ASSERT(err == UV_ENOBUFS); + ASSERT(size1 > 1); + size1 = sizeof buffer_orig; err = uv_cwd(buffer_orig, &size1); ASSERT(err == 0); + ASSERT(size1 > 0); + ASSERT(buffer_orig[size1] != '/'); err = uv_chdir(buffer_orig); ASSERT(err == 0); diff --git a/deps/uv/test/test-fs-copyfile.c b/deps/uv/test/test-fs-copyfile.c index cd8a2ea7c07b..def3d967e74f 100644 --- a/deps/uv/test/test-fs-copyfile.c +++ b/deps/uv/test/test-fs-copyfile.c @@ -24,7 +24,8 @@ #if defined(__unix__) || defined(__POSIX__) || \ defined(__APPLE__) || defined(__sun) || \ - defined(_AIX) || defined(__MVS__) + defined(_AIX) || defined(__MVS__) || \ + defined(__HAIKU__) #include /* unlink, etc. */ #else # include @@ -119,6 +120,13 @@ TEST_IMPL(fs_copyfile) { ASSERT(r != 0); uv_fs_req_cleanup(&req); + /* Succeeds if src and dst files are identical. */ + touch_file(src, 12); + r = uv_fs_copyfile(NULL, &req, src, src, 0, NULL); + ASSERT(r == 0); + uv_fs_req_cleanup(&req); + unlink(src); + /* Copies file synchronously. Creates new file. */ unlink(dst); r = uv_fs_copyfile(NULL, &req, fixture, dst, 0, NULL); diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c index c3153c717b7c..2cf8f287fe33 100644 --- a/deps/uv/test/test-fs.c +++ b/deps/uv/test/test-fs.c @@ -31,7 +31,8 @@ /* FIXME we shouldn't need to branch in this file */ #if defined(__unix__) || defined(__POSIX__) || \ defined(__APPLE__) || defined(__sun) || \ - defined(_AIX) || defined(__MVS__) + defined(_AIX) || defined(__MVS__) || \ + defined(__HAIKU__) #include /* unlink, rmdir, etc. */ #else # include @@ -1653,6 +1654,8 @@ TEST_IMPL(fs_chown) { uv_run(loop, UV_RUN_DEFAULT); ASSERT(fchown_cb_count == 1); +#ifndef __HAIKU__ + /* Haiku doesn't support hardlink */ /* sync link */ r = uv_fs_link(NULL, &req, "test_file", "test_file_link", NULL); ASSERT(r == 0); @@ -1670,6 +1673,7 @@ TEST_IMPL(fs_chown) { ASSERT(r == 0); uv_run(loop, UV_RUN_DEFAULT); ASSERT(lchown_cb_count == 1); +#endif /* Close file */ r = uv_fs_close(NULL, &req, file, NULL); @@ -2717,6 +2721,60 @@ TEST_IMPL(fs_rename_to_existing_file) { } +TEST_IMPL(fs_read_bufs) { + char scratch[768]; + uv_buf_t bufs[4]; + + ASSERT(0 <= uv_fs_open(NULL, &open_req1, + "test/fixtures/lorem_ipsum.txt", + O_RDONLY, 0, NULL)); + ASSERT(open_req1.result >= 0); + uv_fs_req_cleanup(&open_req1); + + ASSERT(UV_EINVAL == uv_fs_read(NULL, &read_req, open_req1.result, + NULL, 0, 0, NULL)); + ASSERT(UV_EINVAL == uv_fs_read(NULL, &read_req, open_req1.result, + NULL, 1, 0, NULL)); + ASSERT(UV_EINVAL == uv_fs_read(NULL, &read_req, open_req1.result, + bufs, 0, 0, NULL)); + + bufs[0] = uv_buf_init(scratch + 0, 256); + bufs[1] = uv_buf_init(scratch + 256, 256); + bufs[2] = uv_buf_init(scratch + 512, 128); + bufs[3] = uv_buf_init(scratch + 640, 128); + + ASSERT(446 == uv_fs_read(NULL, + &read_req, + open_req1.result, + bufs + 0, + 2, /* 2x 256 bytes. */ + 0, /* Positional read. */ + NULL)); + ASSERT(read_req.result == 446); + uv_fs_req_cleanup(&read_req); + + ASSERT(190 == uv_fs_read(NULL, + &read_req, + open_req1.result, + bufs + 2, + 2, /* 2x 128 bytes. */ + 256, /* Positional read. */ + NULL)); + ASSERT(read_req.result == /* 446 - 256 */ 190); + uv_fs_req_cleanup(&read_req); + + ASSERT(0 == memcmp(bufs[1].base + 0, bufs[2].base, 128)); + ASSERT(0 == memcmp(bufs[1].base + 128, bufs[3].base, 190 - 128)); + + ASSERT(0 == uv_fs_close(NULL, &close_req, open_req1.result, NULL)); + ASSERT(close_req.result == 0); + uv_fs_req_cleanup(&close_req); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + TEST_IMPL(fs_read_file_eof) { #if defined(__CYGWIN__) || defined(__MSYS__) RETURN_SKIP("Cygwin pread at EOF may (incorrectly) return data!"); diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index 8886b07c8a74..a48f6f380680 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -91,6 +91,7 @@ TEST_DECLARE (tcp_write_after_connect) TEST_DECLARE (tcp_writealot) TEST_DECLARE (tcp_write_fail) TEST_DECLARE (tcp_try_write) +TEST_DECLARE (tcp_try_write_error) TEST_DECLARE (tcp_write_queue_order) TEST_DECLARE (tcp_open) TEST_DECLARE (tcp_open_twice) @@ -325,6 +326,7 @@ TEST_DECLARE (fs_utime) TEST_DECLARE (fs_futime) TEST_DECLARE (fs_file_open_append) TEST_DECLARE (fs_stat_missing_path) +TEST_DECLARE (fs_read_bufs) TEST_DECLARE (fs_read_file_eof) TEST_DECLARE (fs_event_watch_dir) TEST_DECLARE (fs_event_watch_dir_recursive) @@ -582,6 +584,7 @@ TASK_LIST_START TEST_HELPER (tcp_write_fail, tcp4_echo_server) TEST_ENTRY (tcp_try_write) + TEST_ENTRY (tcp_try_write_error) TEST_ENTRY (tcp_write_queue_order) @@ -776,7 +779,7 @@ TASK_LIST_START TEST_ENTRY (tmpdir) - TEST_ENTRY (hrtime) + TEST_ENTRY_CUSTOM (hrtime, 0, 0, 10000) TEST_ENTRY_CUSTOM (getaddrinfo_fail, 0, 0, 10000) TEST_ENTRY_CUSTOM (getaddrinfo_fail_sync, 0, 0, 10000) @@ -911,6 +914,7 @@ TASK_LIST_START TEST_ENTRY (fs_non_symlink_reparse_point) #endif TEST_ENTRY (fs_stat_missing_path) + TEST_ENTRY (fs_read_bufs) TEST_ENTRY (fs_read_file_eof) TEST_ENTRY (fs_file_open_append) TEST_ENTRY (fs_event_watch_dir) diff --git a/deps/uv/test/test-tcp-try-write-error.c b/deps/uv/test/test-tcp-try-write-error.c new file mode 100644 index 000000000000..58d4723c0903 --- /dev/null +++ b/deps/uv/test/test-tcp-try-write-error.c @@ -0,0 +1,109 @@ +/* Copyright libuv contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "task.h" + +#include +#include +#include + +static uv_tcp_t server; +static uv_tcp_t client; +static uv_tcp_t incoming; +static int connect_cb_called; +static int close_cb_called; +static int connection_cb_called; + + +static void close_cb(uv_handle_t* handle) { + close_cb_called++; +} + +static void incoming_close_cb(uv_handle_t* handle) { + uv_buf_t buf; + int r = 1; + + close_cb_called++; + + buf = uv_buf_init("meow", 4); + while (r > 0) + r = uv_try_write((uv_stream_t*) &client, &buf, 1); + fprintf(stderr, "uv_try_write error: %d %s\n", r, uv_strerror(r)); + ASSERT(r == UV_EPIPE || r == UV_ECONNABORTED); + ASSERT(client.write_queue_size == 0); +} + + +static void connect_cb(uv_connect_t* req, int status) { + ASSERT(status == 0); + connect_cb_called++; +} + + +static void connection_cb(uv_stream_t* tcp, int status) { + ASSERT(status == 0); + + ASSERT(0 == uv_tcp_init(tcp->loop, &incoming)); + ASSERT(0 == uv_accept(tcp, (uv_stream_t*) &incoming)); + + connection_cb_called++; + uv_close((uv_handle_t*) &incoming, incoming_close_cb); + uv_close((uv_handle_t*) tcp, close_cb); +} + + +static void start_server(void) { + struct sockaddr_in addr; + + ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); + + ASSERT(0 == uv_tcp_init(uv_default_loop(), &server)); + ASSERT(0 == uv_tcp_bind(&server, (struct sockaddr*) &addr, 0)); + ASSERT(0 == uv_listen((uv_stream_t*) &server, 128, connection_cb)); +} + + +TEST_IMPL(tcp_try_write_error) { + uv_connect_t connect_req; + struct sockaddr_in addr; + + start_server(); + + ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); + + ASSERT(0 == uv_tcp_init(uv_default_loop(), &client)); + ASSERT(0 == uv_tcp_connect(&connect_req, + &client, + (struct sockaddr*) &addr, + connect_cb)); + + ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); + uv_close((uv_handle_t*) &client, close_cb); + ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); + + ASSERT(connect_cb_called == 1); + ASSERT(close_cb_called == 3); + ASSERT(connection_cb_called == 1); + + MAKE_VALGRIND_HAPPY(); + return 0; +} diff --git a/deps/uv/test/test.gyp b/deps/uv/test/test.gyp index ff64ef0be8d4..a4083e917834 100644 --- a/deps/uv/test/test.gyp +++ b/deps/uv/test/test.gyp @@ -120,6 +120,7 @@ 'test-tcp-writealot.c', 'test-tcp-write-fail.c', 'test-tcp-try-write.c', + 'test-tcp-try-write-error.c', 'test-tcp-unexpected-read.c', 'test-tcp-oob.c', 'test-tcp-read-stop.c', From 511c58d9d8eb2063832850e61d87418b29e1defa Mon Sep 17 00:00:00 2001 From: cjihrig Date: Tue, 2 Jul 2019 11:07:43 -0400 Subject: [PATCH 3/9] deps: upgrade to libuv 1.30.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This upgrade is a small patch release, fixing compilation errors on Android, Cygwin, and uClibc - none of which are tested in the CI. PR-URL: https://github.com/nodejs/node/pull/28511 Reviewed-By: Saúl Ibarra Corretgé Reviewed-By: Richard Lau Reviewed-By: Santiago Gimeno Reviewed-By: Ben Noordhuis --- deps/uv/CMakeLists.txt | 3 +-- deps/uv/ChangeLog | 17 +++++++++++++++++ deps/uv/configure.ac | 2 +- deps/uv/docs/src/threadpool.rst | 2 +- deps/uv/include/uv/version.h | 2 +- deps/uv/src/unix/cygwin.c | 4 ++++ deps/uv/src/unix/thread.c | 18 +++++++++++++----- deps/uv/test/test-tcp-try-write-error.c | 2 +- 8 files changed, 39 insertions(+), 11 deletions(-) diff --git a/deps/uv/CMakeLists.txt b/deps/uv/CMakeLists.txt index f2ed3722c473..a34e5a1b80a9 100644 --- a/deps/uv/CMakeLists.txt +++ b/deps/uv/CMakeLists.txt @@ -260,8 +260,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Android") src/unix/linux-syscalls.c src/unix/procfs-exepath.c src/unix/pthread-fixes.c - src/unix/sysinfo-loadavg.c - src/unix/sysinfo-memory.c) + src/unix/sysinfo-loadavg.c) endif() if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "Android|Linux|OS/390") diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index b9ed7484a50a..a6e2786b0ed3 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,3 +1,20 @@ +2019.07.03, Version 1.30.1 (Stable), 1551969c84c2f546a429dac169c7fdac3e38115e + +Changes since version 1.30.0: + +* doc: fix incorrect versionchanged (cjihrig) + +* test: allow UV_ECONNRESET in tcp_try_write_error (cjihrig) + +* unix: add uv_get_constrained_memory() cygwin stub (cjihrig) + +* build: fix android cmake build (Ben Noordhuis) + +* unix: squelch -Wcast-function-type warning (Ben Noordhuis) + +* build: fix compile error with uClibc (zlargon) + + 2019.06.28, Version 1.30.0 (Stable), 365b6f2a0eacda1ff52be8e57ab9381cfddc5dbb Changes since version 1.29.1: diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac index 626ad4c7b0d9..52aaddcfc150 100644 --- a/deps/uv/configure.ac +++ b/deps/uv/configure.ac @@ -13,7 +13,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. AC_PREREQ(2.57) -AC_INIT([libuv], [1.30.0], [https://github.com/libuv/libuv/issues]) +AC_INIT([libuv], [1.30.1], [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]) diff --git a/deps/uv/docs/src/threadpool.rst b/deps/uv/docs/src/threadpool.rst index ed41c37fe327..cf6cdc1be0f2 100644 --- a/deps/uv/docs/src/threadpool.rst +++ b/deps/uv/docs/src/threadpool.rst @@ -12,7 +12,7 @@ Its default size is 4, but it can be changed at startup time by setting the ``UV_THREADPOOL_SIZE`` environment variable to any value (the absolute maximum is 1024). -.. versionchanged:: 1.29.2 the maximum UV_THREADPOOL_SIZE allowed was increased from 128 to 1024. +.. versionchanged:: 1.30.0 the maximum UV_THREADPOOL_SIZE allowed was increased from 128 to 1024. The threadpool is global and shared across all event loops. When a particular function makes use of the threadpool (i.e. when using :c:func:`uv_queue_work`) diff --git a/deps/uv/include/uv/version.h b/deps/uv/include/uv/version.h index eb1f0c6597ee..bf992d2d0ee6 100644 --- a/deps/uv/include/uv/version.h +++ b/deps/uv/include/uv/version.h @@ -32,7 +32,7 @@ #define UV_VERSION_MAJOR 1 #define UV_VERSION_MINOR 30 -#define UV_VERSION_PATCH 0 +#define UV_VERSION_PATCH 1 #define UV_VERSION_IS_RELEASE 1 #define UV_VERSION_SUFFIX "" diff --git a/deps/uv/src/unix/cygwin.c b/deps/uv/src/unix/cygwin.c index 9da20e203aa2..6b5cfb7ba5b8 100644 --- a/deps/uv/src/unix/cygwin.c +++ b/deps/uv/src/unix/cygwin.c @@ -52,3 +52,7 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { (void)cpu_infos; (void)count; } + +uint64_t uv_get_constrained_memory(void) { + return 0; /* Memory constraints are unknown. */ +} diff --git a/deps/uv/src/unix/thread.c b/deps/uv/src/unix/thread.c index cd0b7aa6aaf9..f10c351ebba2 100644 --- a/deps/uv/src/unix/thread.c +++ b/deps/uv/src/unix/thread.c @@ -37,7 +37,7 @@ #include #endif -#ifdef __GLIBC__ +#if defined(__GLIBC__) && !defined(__UCLIBC__) #include /* gnu_get_libc_version() */ #endif @@ -222,6 +222,12 @@ int uv_thread_create_ex(uv_thread_t* tid, size_t pagesize; size_t stack_size; + /* Used to squelch a -Wcast-function-type warning. */ + union { + void (*in)(void*); + void* (*out)(void*); + } f; + stack_size = params->flags & UV_THREAD_HAS_STACK_SIZE ? params->stack_size : 0; @@ -248,7 +254,8 @@ int uv_thread_create_ex(uv_thread_t* tid, abort(); } - err = pthread_create(tid, attr, (void*(*)(void*)) entry, arg); + f.in = entry; + err = pthread_create(tid, attr, f.out, arg); if (attr != NULL) pthread_attr_destroy(attr); @@ -474,7 +481,7 @@ int uv_sem_trywait(uv_sem_t* sem) { #else /* !(defined(__APPLE__) && defined(__MACH__)) */ -#ifdef __GLIBC__ +#if defined(__GLIBC__) && !defined(__UCLIBC__) /* Hack around https://sourceware.org/bugzilla/show_bug.cgi?id=12674 * by providing a custom implementation for glibc < 2.21 in terms of other @@ -510,7 +517,8 @@ typedef struct uv_semaphore_s { unsigned int value; } uv_semaphore_t; -#if defined(__GLIBC__) || platform_needs_custom_semaphore +#if (defined(__GLIBC__) && !defined(__UCLIBC__)) || \ + platform_needs_custom_semaphore STATIC_ASSERT(sizeof(uv_sem_t) >= sizeof(uv_semaphore_t*)); #endif @@ -639,7 +647,7 @@ static int uv__sem_trywait(uv_sem_t* sem) { } int uv_sem_init(uv_sem_t* sem, unsigned int value) { -#ifdef __GLIBC__ +#if defined(__GLIBC__) && !defined(__UCLIBC__) uv_once(&glibc_version_check_once, glibc_version_check); #endif diff --git a/deps/uv/test/test-tcp-try-write-error.c b/deps/uv/test/test-tcp-try-write-error.c index 58d4723c0903..2201d0ea61ad 100644 --- a/deps/uv/test/test-tcp-try-write-error.c +++ b/deps/uv/test/test-tcp-try-write-error.c @@ -48,7 +48,7 @@ static void incoming_close_cb(uv_handle_t* handle) { while (r > 0) r = uv_try_write((uv_stream_t*) &client, &buf, 1); fprintf(stderr, "uv_try_write error: %d %s\n", r, uv_strerror(r)); - ASSERT(r == UV_EPIPE || r == UV_ECONNABORTED); + ASSERT(r == UV_EPIPE || r == UV_ECONNABORTED || r == UV_ECONNRESET); ASSERT(client.write_queue_size == 0); } From 4f5dc2220bd1a419b4a7b263279229180e6940b7 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Fri, 9 Aug 2019 11:03:55 -0400 Subject: [PATCH 4/9] deps: upgrade to libuv 1.31.0 Notable changes: - UV_FS_O_FILEMAP has been added for faster access to memory mapped files on Windows. - uv_fs_mkdir() now returns UV_EINVAL for invalid filenames on Windows. It previously returned UV_ENOENT. - The uv_fs_statfs() API has been added. - The uv_os_environ() and uv_os_free_environ() APIs have been added. Fixes: https://github.com/nodejs/node/issues/28599 Fixes: https://github.com/nodejs/node/issues/28945 Fixes: https://github.com/nodejs/node/issues/29008 PR-URL: https://github.com/nodejs/node/pull/29070 Reviewed-By: Richard Lau Reviewed-By: Trivikram Kamat Reviewed-By: Rich Trott Reviewed-By: Ben Noordhuis Reviewed-By: Jiawen Geng --- deps/uv/.gitignore | 1 + deps/uv/.mailmap | 1 + deps/uv/AUTHORS | 7 + deps/uv/CMakeLists.txt | 2 + deps/uv/ChangeLog | 49 ++ deps/uv/Makefile.am | 21 + deps/uv/README.md | 2 +- deps/uv/configure.ac | 3 +- deps/uv/docs/src/fs.rst | 47 ++ deps/uv/docs/src/misc.rst | 28 ++ deps/uv/include/uv.h | 27 +- deps/uv/include/uv/unix.h | 6 +- deps/uv/include/uv/version.h | 4 +- deps/uv/include/uv/win.h | 1 + deps/uv/src/unix/core.c | 60 +++ deps/uv/src/unix/darwin-proctitle.c | 147 +++--- deps/uv/src/unix/fs.c | 61 +++ deps/uv/src/unix/openbsd.c | 2 +- deps/uv/src/unix/proctitle.c | 4 - deps/uv/src/unix/stream.c | 2 +- deps/uv/src/uv-common.c | 11 + deps/uv/src/win/fs-fd-hash-inl.h | 178 +++++++ deps/uv/src/win/fs.c | 458 ++++++++++++++++++- deps/uv/src/win/process.c | 4 +- deps/uv/src/win/tty.c | 21 +- deps/uv/src/win/util.c | 75 ++- deps/uv/src/win/winapi.c | 8 + deps/uv/src/win/winapi.h | 12 + deps/uv/test/runner-win.c | 6 + deps/uv/test/task.h | 4 + deps/uv/test/test-env-vars.c | 37 +- deps/uv/test/test-fs-fd-hash.c | 133 ++++++ deps/uv/test/test-fs-open-flags.c | 435 ++++++++++++++++++ deps/uv/test/test-fs.c | 332 ++++++++++++-- deps/uv/test/test-ipc.c | 4 +- deps/uv/test/test-list.h | 18 + deps/uv/test/test-pipe-getsockname.c | 2 +- deps/uv/test/test-process-title-threadsafe.c | 6 +- deps/uv/test/test-queue-foreach-delete.c | 26 +- deps/uv/test/test-spawn.c | 28 ++ deps/uv/test/test-tmpdir.c | 11 + deps/uv/test/test.gyp | 2 + 42 files changed, 2136 insertions(+), 150 deletions(-) create mode 100644 deps/uv/src/win/fs-fd-hash-inl.h create mode 100644 deps/uv/test/test-fs-fd-hash.c create mode 100644 deps/uv/test/test-fs-open-flags.c diff --git a/deps/uv/.gitignore b/deps/uv/.gitignore index c13298791762..b6abc2ab4649 100644 --- a/deps/uv/.gitignore +++ b/deps/uv/.gitignore @@ -51,6 +51,7 @@ Makefile.in /test/run-benchmarks /test/run-benchmarks.exe /test/run-benchmarks.dSYM +test_file_* *.sln *.sln.cache diff --git a/deps/uv/.mailmap b/deps/uv/.mailmap index 3d95997e4fe4..87d63bed0b14 100644 --- a/deps/uv/.mailmap +++ b/deps/uv/.mailmap @@ -38,6 +38,7 @@ Sam Roberts San-Tai Hsu Santiago Gimeno Saúl Ibarra Corretgé +Saúl Ibarra Corretgé Shigeki Ohtsu Timothy J. Fontaine Yasuhiro Matsumoto diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS index 4db18540d46a..5d5866d3ff24 100644 --- a/deps/uv/AUTHORS +++ b/deps/uv/AUTHORS @@ -389,3 +389,10 @@ Jenil Christo Evgeny Ermakov gengjiawen Leo Chung +Javier Blazquez +Mustafa M +Zach Bjornson +Nan Xiao +Ben Davies +Nhan Khong +Crunkle diff --git a/deps/uv/CMakeLists.txt b/deps/uv/CMakeLists.txt index a34e5a1b80a9..bf7990f745fe 100644 --- a/deps/uv/CMakeLists.txt +++ b/deps/uv/CMakeLists.txt @@ -53,6 +53,8 @@ set(uv_test_sources test/test-fs-poll.c test/test-fs.c test/test-fs-readdir.c + test/test-fs-fd-hash.c + test/test-fs-open-flags.c test/test-get-currentexe.c test/test-get-loadavg.c test/test-get-memory.c diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index a6e2786b0ed3..d440b5507719 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,3 +1,52 @@ +2019.08.10, Version 1.31.0 (Stable), 0a6771cee4c15184c924bfe9d397bdd0c3b206ba + +Changes since version 1.30.1: + +* win,fs: don't modify global file translation mode (Javier Blazquez) + +* win: fix uv_os_tmpdir when env var is 260 chars (Mustafa M) + +* win: prevent tty event explosion machine hang (Javier Blazquez) + +* win: add UV_FS_O_FILEMAP (João Reis) + +* win, fs: mkdir return UV_EINVAL for invalid names (Bartosz Sosnowski) + +* github: add root warning to template (cjihrig) + +* win: misc fs cleanup (cjihrig) + +* unix,win: add uv_fs_statfs() (cjihrig) + +* test: avoid AF_LOCAL (Carlo Marcelo Arenas Belón) + +* unix,win: add ability to retrieve all env variables (Saúl Ibarra Corretgé) + +* Revert "darwin: speed up uv_set_process_title()" (Ben Noordhuis) + +* doc: add %p to valgrind log-file arg (Zach Bjornson) + +* doc: fix typo in basics.rst (Nan Xiao) + +* ibmi: support Makefile build for IBM i (Xu Meng) + +* OpenBSD: only get active CPU core count (Ben Davies) + +* test: fix gcc 8 warnings for tests (Nhan Khong) + +* ibmi: use correct header files (Xu Meng) + +* unix: clear UV_HANDLE_READING flag before callback (zyxwvu Shi) + +* unix: fix unused-function warning on BSD (Nhan Khong) + +* test: fix test runner on MinGW (Crunkle) + +* win: remove try-except outside MSVC (Crunkle) + +* win: fix uv_spawn() ENOMEM on empty env (Ben Noordhuis) + + 2019.07.03, Version 1.30.1 (Stable), 1551969c84c2f546a429dac169c7fdac3e38115e Changes since version 1.30.0: diff --git a/deps/uv/Makefile.am b/deps/uv/Makefile.am index d213d8f4faec..6b11c9349ce9 100644 --- a/deps/uv/Makefile.am +++ b/deps/uv/Makefile.am @@ -184,6 +184,8 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/test-fs-poll.c \ test/test-fs.c \ test/test-fs-readdir.c \ + test/test-fs-fd-hash.c \ + test/test-fs-open-flags.c \ test/test-fork.c \ test/test-getters-setters.c \ test/test-get-currentexe.c \ @@ -322,6 +324,12 @@ test_run_tests_CFLAGS += -D_ALL_SOURCE \ -D_LINUX_SOURCE_COMPAT endif +if OS400 +test_run_tests_CFLAGS += -D_ALL_SOURCE \ + -D_XOPEN_SOURCE=500 \ + -D_LINUX_SOURCE_COMPAT +endif + if HAIKU test_run_tests_CFLAGS += -D_BSD_SOURCE endif @@ -362,6 +370,19 @@ uvinclude_HEADERS += include/uv/aix.h libuv_la_SOURCES += src/unix/aix.c src/unix/aix-common.c endif +if OS400 +libuv_la_CFLAGS += -D_ALL_SOURCE \ + -D_XOPEN_SOURCE=500 \ + -D_LINUX_SOURCE_COMPAT \ + -D_THREAD_SAFE +uvinclude_HEADERS += include/uv/posix.h +libuv_la_SOURCES += src/unix/aix-common.c \ + src/unix/ibmi.c \ + src/unix/posix-poll.c \ + src/unix/no-fsevents.c \ + src/unix/no-proctitle.c +endif + if ANDROID uvinclude_HEADERS += include/uv/android-ifaddrs.h libuv_la_SOURCES += src/unix/android-ifaddrs.c \ diff --git a/deps/uv/README.md b/deps/uv/README.md index 11874cdb287f..b55c3a9238a1 100644 --- a/deps/uv/README.md +++ b/deps/uv/README.md @@ -387,7 +387,7 @@ $ gdb --args out/Debug/run-tests TEST_NAME Use the `--trace-children=yes` parameter: ```bash -$ valgrind --trace-children=yes -v --tool=memcheck --leak-check=full --track-origins=yes --leak-resolution=high --show-reachable=yes --log-file=memcheck.log out/Debug/run-tests TEST_NAME +$ valgrind --trace-children=yes -v --tool=memcheck --leak-check=full --track-origins=yes --leak-resolution=high --show-reachable=yes --log-file=memcheck-%p.log out/Debug/run-tests TEST_NAME ``` ### Running benchmarks diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac index 52aaddcfc150..c5e29fef849e 100644 --- a/deps/uv/configure.ac +++ b/deps/uv/configure.ac @@ -13,7 +13,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. AC_PREREQ(2.57) -AC_INIT([libuv], [1.30.1], [https://github.com/libuv/libuv/issues]) +AC_INIT([libuv], [1.31.0], [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]) @@ -63,6 +63,7 @@ AM_CONDITIONAL([MSYS], [AS_CASE([$host_os],[msys*], [true], [false]) AM_CONDITIONAL([NETBSD], [AS_CASE([$host_os],[netbsd*], [true], [false])]) AM_CONDITIONAL([OPENBSD], [AS_CASE([$host_os],[openbsd*], [true], [false])]) AM_CONDITIONAL([OS390], [AS_CASE([$host_os],[openedition*], [true], [false])]) +AM_CONDITIONAL([OS400], [AS_CASE([$host_os],[os400], [true], [false])]) AM_CONDITIONAL([SUNOS], [AS_CASE([$host_os],[solaris*], [true], [false])]) AM_CONDITIONAL([WINNT], [AS_CASE([$host_os],[mingw*], [true], [false])]) AS_CASE([$host_os],[mingw*], [ diff --git a/deps/uv/docs/src/fs.rst b/deps/uv/docs/src/fs.rst index 996624b69514..aabe49b3f3a9 100644 --- a/deps/uv/docs/src/fs.rst +++ b/deps/uv/docs/src/fs.rst @@ -102,6 +102,24 @@ Data types UV_FS_CLOSEDIR } uv_fs_type; +.. c:type:: uv_statfs_t + + Reduced cross platform equivalent of ``struct statfs``. + Used in :c:func:`uv_fs_statfs`. + + :: + + typedef struct uv_statfs_s { + uint64_t f_type; + uint64_t f_bsize; + uint64_t f_blocks; + uint64_t f_bfree; + uint64_t f_bavail; + uint64_t f_files; + uint64_t f_ffree; + uint64_t f_spare[4]; + } uv_statfs_t; + .. c:type:: uv_dirent_t Cross platform (reduced) equivalent of ``struct dirent``. @@ -200,6 +218,11 @@ API Equivalent to :man:`preadv(2)`. + .. warning:: + On Windows, under non-MSVC environments (e.g. when GCC or Clang is used + to build libuv), files opened using ``UV_FS_O_FILEMAP`` may cause a fatal + crash if the memory mapped read operation fails. + .. c:function:: int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) Equivalent to :man:`unlink(2)`. @@ -208,6 +231,11 @@ API Equivalent to :man:`pwritev(2)`. + .. warning:: + On Windows, under non-MSVC environments (e.g. when GCC or Clang is used + to build libuv), files opened using ``UV_FS_O_FILEMAP`` may cause a fatal + crash if the memory mapped write operation fails. + .. c:function:: int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb) Equivalent to :man:`mkdir(2)`. @@ -290,6 +318,17 @@ API Equivalent to :man:`stat(2)`, :man:`fstat(2)` and :man:`lstat(2)` respectively. +.. c:function:: int uv_fs_statfs(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) + + Equivalent to :man:`statfs(2)`. On success, a `uv_statfs_t` is allocated + and returned via `req->ptr`. This memory is freed by `uv_fs_req_cleanup()`. + + .. note:: + Any fields in the resulting `uv_statfs_t` that are not supported by the + underlying operating system are set to zero. + + .. versionadded:: 1.31.0 + .. c:function:: int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb) Equivalent to :man:`rename(2)`. @@ -534,6 +573,14 @@ File open constants .. versionchanged:: 1.17.0 support is added for Windows. +.. c:macro:: UV_FS_O_FILEMAP + + Use a memory file mapping to access the file. When using this flag, the + file cannot be open multiple times concurrently. + + .. note:: + `UV_FS_O_FILEMAP` is only supported on Windows. + .. c:macro:: UV_FS_O_NOATIME Do not update the file access time when the file is read. diff --git a/deps/uv/docs/src/misc.rst b/deps/uv/docs/src/misc.rst index ef70e14bff8c..3ecfce486c4d 100644 --- a/deps/uv/docs/src/misc.rst +++ b/deps/uv/docs/src/misc.rst @@ -180,6 +180,17 @@ Data types char machine[256]; } uv_utsname_t; +.. c:type:: uv_env_item_t + + Data type for environment variable storage. + + :: + + typedef struct uv_env_item_s { + char* name; + char* value; + } uv_env_item_t; + API --- @@ -523,6 +534,23 @@ API .. versionadded:: 1.8.0 +.. c:function:: int uv_os_environ(uv_env_item_t** envitems, int* count) + + Retrieves all environment variables. This function will allocate memory + which must be freed by calling :c:func:`uv_os_free_environ`. + + .. warning:: + This function is not thread safe. + + .. versionadded:: 1.31.0 + +.. c:function:: void uv_os_free_environ(uv_env_item_t* envitems, int count); + + Frees the memory allocated for the environment variables by + :c:func:`uv_os_environ`. + + .. versionadded:: 1.31.0 + .. c:function:: int uv_os_getenv(const char* name, char* buffer, size_t* size) Retrieves the environment variable specified by `name`, copies its value diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index f97801cec2f4..f71767b6e9fa 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -231,11 +231,13 @@ typedef struct uv_fs_s uv_fs_t; typedef struct uv_work_s uv_work_t; /* None of the above. */ +typedef struct uv_env_item_s uv_env_item_t; typedef struct uv_cpu_info_s uv_cpu_info_t; typedef struct uv_interface_address_s uv_interface_address_t; typedef struct uv_dirent_s uv_dirent_t; typedef struct uv_passwd_s uv_passwd_t; typedef struct uv_utsname_s uv_utsname_t; +typedef struct uv_statfs_s uv_statfs_t; typedef enum { UV_LOOP_BLOCK_SIGNAL @@ -1070,6 +1072,17 @@ struct uv_utsname_s { to as meaningless in the docs. */ }; +struct uv_statfs_s { + uint64_t f_type; + uint64_t f_bsize; + uint64_t f_blocks; + uint64_t f_bfree; + uint64_t f_bavail; + uint64_t f_files; + uint64_t f_ffree; + uint64_t f_spare[4]; +}; + typedef enum { UV_DIRENT_UNKNOWN, UV_DIRENT_FILE, @@ -1150,6 +1163,13 @@ UV_EXTERN int uv_interface_addresses(uv_interface_address_t** addresses, UV_EXTERN void uv_free_interface_addresses(uv_interface_address_t* addresses, int count); +struct uv_env_item_s { + char* name; + char* value; +}; + +UV_EXTERN int uv_os_environ(uv_env_item_t** envitems, int* count); +UV_EXTERN void uv_os_free_environ(uv_env_item_t* envitems, int count); UV_EXTERN int uv_os_getenv(const char* name, char* buffer, size_t* size); UV_EXTERN int uv_os_setenv(const char* name, const char* value); UV_EXTERN int uv_os_unsetenv(const char* name); @@ -1205,7 +1225,8 @@ typedef enum { UV_FS_LCHOWN, UV_FS_OPENDIR, UV_FS_READDIR, - UV_FS_CLOSEDIR + UV_FS_CLOSEDIR, + UV_FS_STATFS } uv_fs_type; struct uv_dir_s { @@ -1433,6 +1454,10 @@ UV_EXTERN int uv_fs_lchown(uv_loop_t* loop, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb); +UV_EXTERN int uv_fs_statfs(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + uv_fs_cb cb); enum uv_fs_event { diff --git a/deps/uv/include/uv/unix.h b/deps/uv/include/uv/unix.h index 6c93ee97de27..9080352d31df 100644 --- a/deps/uv/include/uv/unix.h +++ b/deps/uv/include/uv/unix.h @@ -49,6 +49,8 @@ # include "uv/linux.h" #elif defined (__MVS__) # include "uv/os390.h" +#elif defined(__PASE__) /* __PASE__ and _AIX are both defined on IBM i */ +# include "uv/posix.h" /* IBM i needs uv/posix.h, not uv/aix.h */ #elif defined(_AIX) # include "uv/aix.h" #elif defined(__sun) @@ -61,8 +63,7 @@ defined(__OpenBSD__) || \ defined(__NetBSD__) # include "uv/bsd.h" -#elif defined(__PASE__) || \ - defined(__CYGWIN__) || \ +#elif defined(__CYGWIN__) || \ defined(__MSYS__) || \ defined(__GNU__) # include "uv/posix.h" @@ -481,6 +482,7 @@ typedef struct { #endif /* fs open() flags supported on other platforms: */ +#define UV_FS_O_FILEMAP 0 #define UV_FS_O_RANDOM 0 #define UV_FS_O_SHORT_LIVED 0 #define UV_FS_O_SEQUENTIAL 0 diff --git a/deps/uv/include/uv/version.h b/deps/uv/include/uv/version.h index bf992d2d0ee6..37a6a445b8d0 100644 --- a/deps/uv/include/uv/version.h +++ b/deps/uv/include/uv/version.h @@ -31,8 +31,8 @@ */ #define UV_VERSION_MAJOR 1 -#define UV_VERSION_MINOR 30 -#define UV_VERSION_PATCH 1 +#define UV_VERSION_MINOR 31 +#define UV_VERSION_PATCH 0 #define UV_VERSION_IS_RELEASE 1 #define UV_VERSION_SUFFIX "" diff --git a/deps/uv/include/uv/win.h b/deps/uv/include/uv/win.h index acbd958be4cd..9793eee3e1e1 100644 --- a/deps/uv/include/uv/win.h +++ b/deps/uv/include/uv/win.h @@ -668,6 +668,7 @@ typedef struct { #define UV_FS_O_APPEND _O_APPEND #define UV_FS_O_CREAT _O_CREAT #define UV_FS_O_EXCL _O_EXCL +#define UV_FS_O_FILEMAP 0x20000000 #define UV_FS_O_RANDOM _O_RANDOM #define UV_FS_O_RDONLY _O_RDONLY #define UV_FS_O_RDWR _O_RDWR diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index 202c75bbb5e9..f4b94e30cc00 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -50,11 +50,15 @@ #endif #ifdef __APPLE__ +# include # include /* _NSGetExecutablePath */ # include # if defined(O_CLOEXEC) # define UV__O_CLOEXEC O_CLOEXEC # endif +# define environ (*_NSGetEnviron()) +#else +extern char** environ; #endif #if defined(__DragonFly__) || \ @@ -1284,6 +1288,62 @@ int uv_translate_sys_error(int sys_errno) { } +int uv_os_environ(uv_env_item_t** envitems, int* count) { + int i, j, cnt; + uv_env_item_t* envitem; + + *envitems = NULL; + *count = 0; + + for (i = 0; environ[i] != NULL; i++); + + *envitems = uv__calloc(i, sizeof(**envitems)); + + if (envitems == NULL) + return UV_ENOMEM; + + for (j = 0, cnt = 0; j < i; j++) { + char* buf; + char* ptr; + + if (environ[j] == NULL) + break; + + buf = uv__strdup(environ[j]); + if (buf == NULL) + goto fail; + + ptr = strchr(buf, '='); + if (ptr == NULL) { + uv__free(buf); + continue; + } + + *ptr = '\0'; + + envitem = &(*envitems)[cnt]; + envitem->name = buf; + envitem->value = ptr + 1; + + cnt++; + } + + *count = cnt; + return 0; + +fail: + for (i = 0; i < cnt; i++) { + envitem = &(*envitems)[cnt]; + uv__free(envitem->name); + } + uv__free(*envitems); + + *envitems = NULL; + *count = 0; + return UV_ENOMEM; +} + + int uv_os_getenv(const char* name, char* buffer, size_t* size) { char* var; size_t len; diff --git a/deps/uv/src/unix/darwin-proctitle.c b/deps/uv/src/unix/darwin-proctitle.c index e505bdd23f86..dabde2239cca 100644 --- a/deps/uv/src/unix/darwin-proctitle.c +++ b/deps/uv/src/unix/darwin-proctitle.c @@ -33,56 +33,61 @@ # include #endif -#define S(s) pCFStringCreateWithCString(NULL, (s), kCFStringEncodingUTF8) - - -static int (*dynamic_pthread_setname_np)(const char* name); -#if !TARGET_OS_IPHONE -static CFStringRef (*pCFStringCreateWithCString)(CFAllocatorRef, - const char*, - CFStringEncoding); -static CFBundleRef (*pCFBundleGetBundleWithIdentifier)(CFStringRef); -static void *(*pCFBundleGetDataPointerForName)(CFBundleRef, CFStringRef); -static void *(*pCFBundleGetFunctionPointerForName)(CFBundleRef, CFStringRef); -static CFTypeRef (*pLSGetCurrentApplicationASN)(void); -static OSStatus (*pLSSetApplicationInformationItem)(int, - CFTypeRef, - CFStringRef, - CFStringRef, - CFDictionaryRef*); -static void* application_services_handle; -static void* core_foundation_handle; -static CFBundleRef launch_services_bundle; -static CFStringRef* display_name_key; -static CFDictionaryRef (*pCFBundleGetInfoDictionary)(CFBundleRef); -static CFBundleRef (*pCFBundleGetMainBundle)(void); -static CFBundleRef hi_services_bundle; -static OSStatus (*pSetApplicationIsDaemon)(int); -static CFDictionaryRef (*pLSApplicationCheckIn)(int, CFDictionaryRef); -static void (*pLSSetApplicationLaunchServicesServerConnectionStatus)(uint64_t, - void*); - - -UV_DESTRUCTOR(static void uv__set_process_title_platform_fini(void)) { - if (core_foundation_handle != NULL) { - dlclose(core_foundation_handle); - core_foundation_handle = NULL; - } - - if (application_services_handle != NULL) { - dlclose(application_services_handle); - application_services_handle = NULL; - } -} -#endif /* !TARGET_OS_IPHONE */ +static int uv__pthread_setname_np(const char* name) { + int (*dynamic_pthread_setname_np)(const char* name); + char namebuf[64]; /* MAXTHREADNAMESIZE */ + int err; -void uv__set_process_title_platform_init(void) { /* pthread_setname_np() first appeared in OS X 10.6 and iOS 3.2. */ *(void **)(&dynamic_pthread_setname_np) = dlsym(RTLD_DEFAULT, "pthread_setname_np"); -#if !TARGET_OS_IPHONE + if (dynamic_pthread_setname_np == NULL) + return UV_ENOSYS; + + strncpy(namebuf, name, sizeof(namebuf) - 1); + namebuf[sizeof(namebuf) - 1] = '\0'; + + err = dynamic_pthread_setname_np(namebuf); + if (err) + return UV__ERR(err); + + return 0; +} + + +int uv__set_process_title(const char* title) { +#if TARGET_OS_IPHONE + return uv__pthread_setname_np(title); +#else + CFStringRef (*pCFStringCreateWithCString)(CFAllocatorRef, + const char*, + CFStringEncoding); + CFBundleRef (*pCFBundleGetBundleWithIdentifier)(CFStringRef); + void *(*pCFBundleGetDataPointerForName)(CFBundleRef, CFStringRef); + void *(*pCFBundleGetFunctionPointerForName)(CFBundleRef, CFStringRef); + CFTypeRef (*pLSGetCurrentApplicationASN)(void); + OSStatus (*pLSSetApplicationInformationItem)(int, + CFTypeRef, + CFStringRef, + CFStringRef, + CFDictionaryRef*); + void* application_services_handle; + void* core_foundation_handle; + CFBundleRef launch_services_bundle; + CFStringRef* display_name_key; + CFDictionaryRef (*pCFBundleGetInfoDictionary)(CFBundleRef); + CFBundleRef (*pCFBundleGetMainBundle)(void); + CFBundleRef hi_services_bundle; + OSStatus (*pSetApplicationIsDaemon)(int); + CFDictionaryRef (*pLSApplicationCheckIn)(int, CFDictionaryRef); + void (*pLSSetApplicationLaunchServicesServerConnectionStatus)(uint64_t, + void*); + CFTypeRef asn; + int err; + + err = UV_ENOENT; application_services_handle = dlopen("/System/Library/Frameworks/" "ApplicationServices.framework/" "Versions/A/ApplicationServices", @@ -111,6 +116,8 @@ void uv__set_process_title_platform_init(void) { goto out; } +#define S(s) pCFStringCreateWithCString(NULL, (s), kCFStringEncodingUTF8) + launch_services_bundle = pCFBundleGetBundleWithIdentifier(S("com.apple.LaunchServices")); @@ -141,14 +148,13 @@ void uv__set_process_title_platform_init(void) { "CFBundleGetInfoDictionary"); *(void **)(&pCFBundleGetMainBundle) = dlsym(core_foundation_handle, "CFBundleGetMainBundle"); - if (pCFBundleGetInfoDictionary == NULL || pCFBundleGetMainBundle == NULL) goto out; /* Black 10.9 magic, to remove (Not responding) mark in Activity Monitor */ hi_services_bundle = pCFBundleGetBundleWithIdentifier(S("com.apple.HIServices")); - + err = UV_ENOENT; if (hi_services_bundle == NULL) goto out; @@ -162,37 +168,42 @@ void uv__set_process_title_platform_init(void) { pCFBundleGetFunctionPointerForName( launch_services_bundle, S("_LSSetApplicationLaunchServicesServerConnectionStatus")); - if (pSetApplicationIsDaemon == NULL || pLSApplicationCheckIn == NULL || pLSSetApplicationLaunchServicesServerConnectionStatus == NULL) { goto out; } - return; + if (pSetApplicationIsDaemon(1) != noErr) + goto out; -out: - uv__set_process_title_platform_fini(); -#endif /* !TARGET_OS_IPHONE */ -} + pLSSetApplicationLaunchServicesServerConnectionStatus(0, NULL); + /* Check into process manager?! */ + pLSApplicationCheckIn(-2, + pCFBundleGetInfoDictionary(pCFBundleGetMainBundle())); -void uv__set_process_title(const char* title) { -#if !TARGET_OS_IPHONE - if (core_foundation_handle != NULL && pSetApplicationIsDaemon(1) != noErr) { - CFTypeRef asn; - pLSSetApplicationLaunchServicesServerConnectionStatus(0, NULL); - pLSApplicationCheckIn(/* Magic value */ -2, - pCFBundleGetInfoDictionary(pCFBundleGetMainBundle())); - asn = pLSGetCurrentApplicationASN(); - pLSSetApplicationInformationItem(/* Magic value */ -2, asn, - *display_name_key, S(title), NULL); - } -#endif /* !TARGET_OS_IPHONE */ + asn = pLSGetCurrentApplicationASN(); - if (dynamic_pthread_setname_np != NULL) { - char namebuf[64]; /* MAXTHREADNAMESIZE */ - uv__strscpy(namebuf, title, sizeof(namebuf)); - dynamic_pthread_setname_np(namebuf); + err = UV_EINVAL; + if (pLSSetApplicationInformationItem(-2, /* Magic value. */ + asn, + *display_name_key, + S(title), + NULL) != noErr) { + goto out; } + + uv__pthread_setname_np(title); /* Don't care if it fails. */ + err = 0; + +out: + if (core_foundation_handle != NULL) + dlclose(core_foundation_handle); + + if (application_services_handle != NULL) + dlclose(application_services_handle); + + return err; +#endif /* !TARGET_OS_IPHONE */ } diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c index 5138c619b02f..fc80d00d5c56 100644 --- a/deps/uv/src/unix/fs.c +++ b/deps/uv/src/unix/fs.c @@ -70,6 +70,20 @@ # include #endif +#if defined(__APPLE__) || \ + defined(__DragonFly__) || \ + defined(__FreeBSD__) || \ + defined(__FreeBSD_kernel__) || \ + defined(__OpenBSD__) || \ + defined(__NetBSD__) +# include +# include +#elif defined(__sun) || defined(__MVS__) +# include +#else +# include +#endif + #if defined(_AIX) && _XOPEN_SOURCE <= 600 extern char *mkdtemp(char *template); /* See issue #740 on AIX < 7 */ #endif @@ -278,6 +292,7 @@ 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, @@ -324,6 +339,7 @@ static ssize_t uv__fs_preadv(uv_file fd, return result; } +#endif static ssize_t uv__fs_read(uv_fs_t* req) { @@ -519,6 +535,40 @@ static int uv__fs_closedir(uv_fs_t* req) { return 0; } +static int uv__fs_statfs(uv_fs_t* req) { + uv_statfs_t* stat_fs; +#if defined(__sun) || defined(__MVS__) + struct statvfs buf; + + if (0 != statvfs(req->path, &buf)) +#else + struct statfs buf; + + if (0 != statfs(req->path, &buf)) +#endif /* defined(__sun) */ + return -1; + + stat_fs = uv__malloc(sizeof(*stat_fs)); + if (stat_fs == NULL) { + errno = ENOMEM; + return -1; + } + +#if defined(__sun) || defined(__MVS__) + stat_fs->f_type = 0; /* f_type is not supported. */ +#else + stat_fs->f_type = buf.f_type; +#endif + stat_fs->f_bsize = buf.f_bsize; + stat_fs->f_blocks = buf.f_blocks; + stat_fs->f_bfree = buf.f_bfree; + stat_fs->f_bavail = buf.f_bavail; + stat_fs->f_files = buf.f_files; + stat_fs->f_ffree = buf.f_ffree; + req->ptr = stat_fs; + return 0; +} + static ssize_t uv__fs_pathmax_size(const char* path) { ssize_t pathmax; @@ -1386,6 +1436,7 @@ static void uv__fs_work(struct uv__work* w) { X(RMDIR, rmdir(req->path)); X(SENDFILE, uv__fs_sendfile(req)); X(STAT, uv__fs_stat(req->path, &req->statbuf)); + X(STATFS, uv__fs_statfs(req)); X(SYMLINK, symlink(req->path, req->new_path)); X(UNLINK, unlink(req->path)); X(UTIME, uv__fs_utime(req)); @@ -1858,3 +1909,13 @@ int uv_fs_copyfile(uv_loop_t* loop, req->flags = flags; POST; } + + +int uv_fs_statfs(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + uv_fs_cb cb) { + INIT(STATFS); + PATH; + POST; +} diff --git a/deps/uv/src/unix/openbsd.c b/deps/uv/src/unix/openbsd.c index ffae7683d8b6..b5cdc80c3e92 100644 --- a/deps/uv/src/unix/openbsd.c +++ b/deps/uv/src/unix/openbsd.c @@ -193,7 +193,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { if (sysctl(which, 2, &model, &size, NULL, 0)) return UV__ERR(errno); - which[1] = HW_NCPU; + which[1] = HW_NCPUONLINE; size = sizeof(numcpus); if (sysctl(which, 2, &numcpus, &size, NULL, 0)) return UV__ERR(errno); diff --git a/deps/uv/src/unix/proctitle.c b/deps/uv/src/unix/proctitle.c index a5ce2030c55b..1a8c7a7090e8 100644 --- a/deps/uv/src/unix/proctitle.c +++ b/deps/uv/src/unix/proctitle.c @@ -24,7 +24,6 @@ #include #include -extern void uv__set_process_title_platform_init(void); extern void uv__set_process_title(const char* title); static uv_mutex_t process_title_mutex; @@ -39,9 +38,6 @@ static struct { static void init_process_title_mutex_once(void) { uv_mutex_init(&process_title_mutex); -#ifdef __APPLE__ - uv__set_process_title_platform_init(); -#endif } diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c index 17b06a39a772..9de01e3c7840 100644 --- a/deps/uv/src/unix/stream.c +++ b/deps/uv/src/unix/stream.c @@ -1000,12 +1000,12 @@ uv_handle_type uv__handle_type(int fd) { static void uv__stream_eof(uv_stream_t* stream, const uv_buf_t* buf) { stream->flags |= UV_HANDLE_READ_EOF; + stream->flags &= ~UV_HANDLE_READING; uv__io_stop(stream->loop, &stream->io_watcher, POLLIN); if (!uv__io_active(&stream->io_watcher, POLLOUT)) uv__handle_stop(stream); uv__stream_osx_interrupt_select(stream); stream->read_cb(stream, UV_EOF, buf); - stream->flags &= ~UV_HANDLE_READING; } diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c index 066eb31d0389..d1a5e2fbe6b7 100644 --- a/deps/uv/src/uv-common.c +++ b/deps/uv/src/uv-common.c @@ -786,3 +786,14 @@ void uv_loop_delete(uv_loop_t* loop) { if (loop != default_loop) uv__free(loop); } + + +void uv_os_free_environ(uv_env_item_t* envitems, int count) { + int i; + + for (i = 0; i < count; i++) { + uv__free(envitems[i].name); + } + + uv__free(envitems); +} diff --git a/deps/uv/src/win/fs-fd-hash-inl.h b/deps/uv/src/win/fs-fd-hash-inl.h new file mode 100644 index 000000000000..7a203d232d35 --- /dev/null +++ b/deps/uv/src/win/fs-fd-hash-inl.h @@ -0,0 +1,178 @@ +#ifndef UV_WIN_FS_FD_HASH_INL_H_ +#define UV_WIN_FS_FD_HASH_INL_H_ + +#include "uv.h" +#include "internal.h" + +/* Files are only inserted in uv__fd_hash when the UV_FS_O_FILEMAP flag is + * specified. Thus, when uv__fd_hash_get returns true, the file mapping in the + * info structure should be used for read/write operations. + * + * If the file is empty, the mapping field will be set to + * INVALID_HANDLE_VALUE. This is not an issue since the file mapping needs to + * be created anyway when the file size changes. + * + * Since file descriptors are sequential integers, the modulo operator is used + * as hashing function. For each bucket, a single linked list of arrays is + * kept to minimize allocations. A statically allocated memory buffer is kept + * for the first array in each bucket. */ + + +#define UV__FD_HASH_SIZE 256 +#define UV__FD_HASH_GROUP_SIZE 16 + +struct uv__fd_info_s { + int flags; + BOOLEAN is_directory; + HANDLE mapping; + LARGE_INTEGER size; + LARGE_INTEGER current_pos; +}; + +struct uv__fd_hash_entry_s { + uv_file fd; + struct uv__fd_info_s info; +}; + +struct uv__fd_hash_entry_group_s { + struct uv__fd_hash_entry_s entries[UV__FD_HASH_GROUP_SIZE]; + struct uv__fd_hash_entry_group_s* next; +}; + +struct uv__fd_hash_bucket_s { + size_t size; + struct uv__fd_hash_entry_group_s* data; +}; + + +static uv_mutex_t uv__fd_hash_mutex; + +static struct uv__fd_hash_entry_group_s + uv__fd_hash_entry_initial[UV__FD_HASH_SIZE * UV__FD_HASH_GROUP_SIZE]; +static struct uv__fd_hash_bucket_s uv__fd_hash[UV__FD_HASH_SIZE]; + + +INLINE static void uv__fd_hash_init(void) { + int i, err; + + err = uv_mutex_init(&uv__fd_hash_mutex); + if (err) { + uv_fatal_error(err, "uv_mutex_init"); + } + + for (i = 0; i < ARRAY_SIZE(uv__fd_hash); ++i) { + uv__fd_hash[i].size = 0; + uv__fd_hash[i].data = + uv__fd_hash_entry_initial + i * UV__FD_HASH_GROUP_SIZE; + } +} + +#define FIND_COMMON_VARIABLES \ + unsigned i; \ + unsigned bucket = fd % ARRAY_SIZE(uv__fd_hash); \ + struct uv__fd_hash_entry_s* entry_ptr = NULL; \ + struct uv__fd_hash_entry_group_s* group_ptr; \ + struct uv__fd_hash_bucket_s* bucket_ptr = &uv__fd_hash[bucket]; + +#define FIND_IN_GROUP_PTR(group_size) \ + do { \ + for (i = 0; i < group_size; ++i) { \ + if (group_ptr->entries[i].fd == fd) { \ + entry_ptr = &group_ptr->entries[i]; \ + break; \ + } \ + } \ + } while (0) + +#define FIND_IN_BUCKET_PTR() \ + do { \ + size_t first_group_size = bucket_ptr->size % UV__FD_HASH_GROUP_SIZE; \ + if (bucket_ptr->size != 0 && first_group_size == 0) \ + first_group_size = UV__FD_HASH_GROUP_SIZE; \ + group_ptr = bucket_ptr->data; \ + FIND_IN_GROUP_PTR(first_group_size); \ + for (group_ptr = group_ptr->next; \ + group_ptr != NULL && entry_ptr == NULL; \ + group_ptr = group_ptr->next) \ + FIND_IN_GROUP_PTR(UV__FD_HASH_GROUP_SIZE); \ + } while (0) + +INLINE static int uv__fd_hash_get(int fd, struct uv__fd_info_s* info) { + FIND_COMMON_VARIABLES + + uv_mutex_lock(&uv__fd_hash_mutex); + + FIND_IN_BUCKET_PTR(); + + if (entry_ptr != NULL) { + *info = entry_ptr->info; + } + + uv_mutex_unlock(&uv__fd_hash_mutex); + return entry_ptr != NULL; +} + +INLINE static void uv__fd_hash_add(int fd, struct uv__fd_info_s* info) { + FIND_COMMON_VARIABLES + + uv_mutex_lock(&uv__fd_hash_mutex); + + FIND_IN_BUCKET_PTR(); + + if (entry_ptr == NULL) { + i = bucket_ptr->size % UV__FD_HASH_GROUP_SIZE; + + if (bucket_ptr->size != 0 && i == 0) { + struct uv__fd_hash_entry_group_s* new_group_ptr = + uv__malloc(sizeof(*new_group_ptr)); + if (new_group_ptr == NULL) { + uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); + } + new_group_ptr->next = bucket_ptr->data; + bucket_ptr->data = new_group_ptr; + } + + bucket_ptr->size += 1; + entry_ptr = &bucket_ptr->data->entries[i]; + entry_ptr->fd = fd; + } + + entry_ptr->info = *info; + + uv_mutex_unlock(&uv__fd_hash_mutex); +} + +INLINE static int uv__fd_hash_remove(int fd, struct uv__fd_info_s* info) { + FIND_COMMON_VARIABLES + + uv_mutex_lock(&uv__fd_hash_mutex); + + FIND_IN_BUCKET_PTR(); + + if (entry_ptr != NULL) { + *info = entry_ptr->info; + + bucket_ptr->size -= 1; + + i = bucket_ptr->size % UV__FD_HASH_GROUP_SIZE; + if (entry_ptr != &bucket_ptr->data->entries[i]) { + *entry_ptr = bucket_ptr->data->entries[i]; + } + + if (bucket_ptr->size != 0 && + bucket_ptr->size % UV__FD_HASH_GROUP_SIZE == 0) { + struct uv__fd_hash_entry_group_s* old_group_ptr = bucket_ptr->data; + bucket_ptr->data = old_group_ptr->next; + uv__free(old_group_ptr); + } + } + + uv_mutex_unlock(&uv__fd_hash_mutex); + return entry_ptr != NULL; +} + +#undef FIND_COMMON_VARIABLES +#undef FIND_IN_GROUP_PTR +#undef FIND_IN_BUCKET_PTR + +#endif /* UV_WIN_FS_FD_HASH_INL_H_ */ diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c index 7d78d466c873..5dccca77999d 100644 --- a/deps/uv/src/win/fs.c +++ b/deps/uv/src/win/fs.c @@ -34,6 +34,7 @@ #include "internal.h" #include "req-inl.h" #include "handle-inl.h" +#include "fs-fd-hash-inl.h" #include @@ -126,6 +127,8 @@ #define IS_LETTER(c) (((c) >= L'a' && (c) <= L'z') || \ ((c) >= L'A' && (c) <= L'Z')) +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) + const WCHAR JUNCTION_PREFIX[] = L"\\??\\"; const WCHAR JUNCTION_PREFIX_LEN = 4; @@ -137,8 +140,16 @@ const WCHAR UNC_PATH_PREFIX_LEN = 8; static int uv__file_symlink_usermode_flag = SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE; +static DWORD uv__allocation_granularity; + + void uv_fs_init(void) { - _fmode = _O_BINARY; + SYSTEM_INFO system_info; + + GetSystemInfo(&system_info); + uv__allocation_granularity = system_info.dwAllocationGranularity; + + uv__fd_hash_init(); } @@ -414,6 +425,27 @@ void fs__open(uv_fs_t* req) { HANDLE file; int fd, current_umask; int flags = req->fs.info.file_flags; + struct uv__fd_info_s fd_info; + + /* Adjust flags to be compatible with the memory file mapping. Save the + * original flags to emulate the correct behavior. */ + if (flags & UV_FS_O_FILEMAP) { + fd_info.flags = flags; + fd_info.current_pos.QuadPart = 0; + + if ((flags & (UV_FS_O_RDONLY | UV_FS_O_WRONLY | UV_FS_O_RDWR)) == + UV_FS_O_WRONLY) { + /* CreateFileMapping always needs read access */ + flags = (flags & ~UV_FS_O_WRONLY) | UV_FS_O_RDWR; + } + + if (flags & UV_FS_O_APPEND) { + /* Clear the append flag and ensure RDRW mode */ + flags &= ~UV_FS_O_APPEND; + flags &= ~(UV_FS_O_RDONLY | UV_FS_O_WRONLY | UV_FS_O_RDWR); + flags |= UV_FS_O_RDWR; + } + } /* Obtain the active umask. umask() never fails and returns the previous * umask. */ @@ -444,7 +476,8 @@ void fs__open(uv_fs_t* req) { * Here is where we deviate significantly from what CRT's _open() * does. We indiscriminately use all the sharing modes, to match * UNIX semantics. In particular, this ensures that the file can - * be deleted even whilst it's open, fixing issue #1449. + * be deleted even whilst it's open, fixing issue + * https://github.com/nodejs/node-v0.x-archive/issues/1449. * We still support exclusive sharing mode, since it is necessary * for opening raw block devices, otherwise Windows will prevent * any attempt to write past the master boot record. @@ -583,11 +616,55 @@ void fs__open(uv_fs_t* req) { else if (GetLastError() != ERROR_SUCCESS) SET_REQ_WIN32_ERROR(req, GetLastError()); else - SET_REQ_WIN32_ERROR(req, UV_UNKNOWN); + SET_REQ_WIN32_ERROR(req, (DWORD) UV_UNKNOWN); CloseHandle(file); return; } + if (flags & UV_FS_O_FILEMAP) { + FILE_STANDARD_INFO file_info; + if (!GetFileInformationByHandleEx(file, + FileStandardInfo, + &file_info, + sizeof file_info)) { + SET_REQ_WIN32_ERROR(req, GetLastError()); + CloseHandle(file); + return; + } + fd_info.is_directory = file_info.Directory; + + if (fd_info.is_directory) { + fd_info.size.QuadPart = 0; + fd_info.mapping = INVALID_HANDLE_VALUE; + } else { + if (!GetFileSizeEx(file, &fd_info.size)) { + SET_REQ_WIN32_ERROR(req, GetLastError()); + CloseHandle(file); + return; + } + + if (fd_info.size.QuadPart == 0) { + fd_info.mapping = INVALID_HANDLE_VALUE; + } else { + DWORD flProtect = (fd_info.flags & (UV_FS_O_RDONLY | UV_FS_O_WRONLY | + UV_FS_O_RDWR)) == UV_FS_O_RDONLY ? PAGE_READONLY : PAGE_READWRITE; + fd_info.mapping = CreateFileMapping(file, + NULL, + flProtect, + fd_info.size.HighPart, + fd_info.size.LowPart, + NULL); + if (fd_info.mapping == NULL) { + SET_REQ_WIN32_ERROR(req, GetLastError()); + CloseHandle(file); + return; + } + } + } + + uv__fd_hash_add(fd, &fd_info); + } + SET_REQ_RESULT(req, fd); return; @@ -598,9 +675,16 @@ void fs__open(uv_fs_t* req) { void fs__close(uv_fs_t* req) { int fd = req->file.fd; int result; + struct uv__fd_info_s fd_info; VERIFY_FD(fd, req); + if (uv__fd_hash_remove(fd, &fd_info)) { + if (fd_info.mapping != INVALID_HANDLE_VALUE) { + CloseHandle(fd_info.mapping); + } + } + if (fd > 2) result = _close(fd); else @@ -618,6 +702,123 @@ void fs__close(uv_fs_t* req) { } +LONG fs__filemap_ex_filter(LONG excode, PEXCEPTION_POINTERS pep, + int* perror) { + if (excode != EXCEPTION_IN_PAGE_ERROR) { + return EXCEPTION_CONTINUE_SEARCH; + } + + assert(perror != NULL); + if (pep != NULL && pep->ExceptionRecord != NULL && + pep->ExceptionRecord->NumberParameters >= 3) { + NTSTATUS status = (NTSTATUS)pep->ExceptionRecord->ExceptionInformation[3]; + *perror = pRtlNtStatusToDosError(status); + if (*perror != ERROR_SUCCESS) { + return EXCEPTION_EXECUTE_HANDLER; + } + } + *perror = UV_UNKNOWN; + return EXCEPTION_EXECUTE_HANDLER; +} + + +void fs__read_filemap(uv_fs_t* req, struct uv__fd_info_s* fd_info) { + int fd = req->file.fd; /* VERIFY_FD done in fs__read */ + int rw_flags = fd_info->flags & + (UV_FS_O_RDONLY | UV_FS_O_WRONLY | UV_FS_O_RDWR); + size_t read_size, done_read; + unsigned int index; + LARGE_INTEGER pos, end_pos; + size_t view_offset; + LARGE_INTEGER view_base; + void* view; + + if (rw_flags == UV_FS_O_WRONLY) { + SET_REQ_WIN32_ERROR(req, ERROR_ACCESS_DENIED); + return; + } + if (fd_info->is_directory) { + SET_REQ_WIN32_ERROR(req, ERROR_INVALID_FUNCTION); + return; + } + + if (req->fs.info.offset == -1) { + pos = fd_info->current_pos; + } else { + pos.QuadPart = req->fs.info.offset; + } + + /* Make sure we wont read past EOF. */ + if (pos.QuadPart >= fd_info->size.QuadPart) { + SET_REQ_RESULT(req, 0); + return; + } + + read_size = 0; + for (index = 0; index < req->fs.info.nbufs; ++index) { + read_size += req->fs.info.bufs[index].len; + } + read_size = (size_t) MIN((LONGLONG) read_size, + fd_info->size.QuadPart - pos.QuadPart); + if (read_size == 0) { + SET_REQ_RESULT(req, 0); + return; + } + + end_pos.QuadPart = pos.QuadPart + read_size; + + view_offset = pos.QuadPart % uv__allocation_granularity; + view_base.QuadPart = pos.QuadPart - view_offset; + view = MapViewOfFile(fd_info->mapping, + FILE_MAP_READ, + view_base.HighPart, + view_base.LowPart, + view_offset + read_size); + if (view == NULL) { + SET_REQ_WIN32_ERROR(req, GetLastError()); + return; + } + + done_read = 0; + for (index = 0; + index < req->fs.info.nbufs && done_read < read_size; + ++index) { + int err = 0; + size_t this_read_size = MIN(req->fs.info.bufs[index].len, + read_size - done_read); +#ifdef _MSC_VER + __try { +#endif + memcpy(req->fs.info.bufs[index].base, + (char*)view + view_offset + done_read, + this_read_size); +#ifdef _MSC_VER + } + __except (fs__filemap_ex_filter(GetExceptionCode(), + GetExceptionInformation(), &err)) { + SET_REQ_WIN32_ERROR(req, err); + UnmapViewOfFile(view); + return; + } +#endif + done_read += this_read_size; + } + assert(done_read == read_size); + + if (!UnmapViewOfFile(view)) { + SET_REQ_WIN32_ERROR(req, GetLastError()); + return; + } + + if (req->fs.info.offset == -1) { + fd_info->current_pos = end_pos; + uv__fd_hash_add(fd, fd_info); + } + + SET_REQ_RESULT(req, read_size); + return; +} + void fs__read(uv_fs_t* req) { int fd = req->file.fd; int64_t offset = req->fs.info.offset; @@ -631,9 +832,15 @@ void fs__read(uv_fs_t* req) { LARGE_INTEGER original_position; LARGE_INTEGER zero_offset; int restore_position; + struct uv__fd_info_s fd_info; VERIFY_FD(fd, req); + if (uv__fd_hash_get(fd, &fd_info)) { + fs__read_filemap(req, &fd_info); + return; + } + zero_offset.QuadPart = 0; restore_position = 0; handle = uv__get_osfhandle(fd); @@ -690,6 +897,131 @@ void fs__read(uv_fs_t* req) { } +void fs__write_filemap(uv_fs_t* req, HANDLE file, + struct uv__fd_info_s* fd_info) { + int fd = req->file.fd; /* VERIFY_FD done in fs__write */ + int force_append = fd_info->flags & UV_FS_O_APPEND; + int rw_flags = fd_info->flags & + (UV_FS_O_RDONLY | UV_FS_O_WRONLY | UV_FS_O_RDWR); + size_t write_size, done_write; + unsigned int index; + LARGE_INTEGER zero, pos, end_pos; + size_t view_offset; + LARGE_INTEGER view_base; + void* view; + FILETIME ft; + + if (rw_flags == UV_FS_O_RDONLY) { + SET_REQ_WIN32_ERROR(req, ERROR_ACCESS_DENIED); + return; + } + if (fd_info->is_directory) { + SET_REQ_WIN32_ERROR(req, ERROR_INVALID_FUNCTION); + return; + } + + write_size = 0; + for (index = 0; index < req->fs.info.nbufs; ++index) { + write_size += req->fs.info.bufs[index].len; + } + + if (write_size == 0) { + SET_REQ_RESULT(req, 0); + return; + } + + zero.QuadPart = 0; + if (force_append) { + pos = fd_info->size; + } else if (req->fs.info.offset == -1) { + pos = fd_info->current_pos; + } else { + pos.QuadPart = req->fs.info.offset; + } + + end_pos.QuadPart = pos.QuadPart + write_size; + + /* Recreate the mapping to enlarge the file if needed */ + if (end_pos.QuadPart > fd_info->size.QuadPart) { + if (fd_info->mapping != INVALID_HANDLE_VALUE) { + CloseHandle(fd_info->mapping); + } + + fd_info->mapping = CreateFileMapping(file, + NULL, + PAGE_READWRITE, + end_pos.HighPart, + end_pos.LowPart, + NULL); + if (fd_info->mapping == NULL) { + SET_REQ_WIN32_ERROR(req, GetLastError()); + CloseHandle(file); + fd_info->mapping = INVALID_HANDLE_VALUE; + fd_info->size.QuadPart = 0; + fd_info->current_pos.QuadPart = 0; + uv__fd_hash_add(fd, fd_info); + return; + } + + fd_info->size = end_pos; + uv__fd_hash_add(fd, fd_info); + } + + view_offset = pos.QuadPart % uv__allocation_granularity; + view_base.QuadPart = pos.QuadPart - view_offset; + view = MapViewOfFile(fd_info->mapping, + FILE_MAP_WRITE, + view_base.HighPart, + view_base.LowPart, + view_offset + write_size); + if (view == NULL) { + SET_REQ_WIN32_ERROR(req, GetLastError()); + return; + } + + done_write = 0; + for (index = 0; index < req->fs.info.nbufs; ++index) { + int err = 0; +#ifdef _MSC_VER + __try { +#endif + memcpy((char*)view + view_offset + done_write, + req->fs.info.bufs[index].base, + req->fs.info.bufs[index].len); +#ifdef _MSC_VER + } + __except (fs__filemap_ex_filter(GetExceptionCode(), + GetExceptionInformation(), &err)) { + SET_REQ_WIN32_ERROR(req, err); + UnmapViewOfFile(view); + return; + } +#endif + done_write += req->fs.info.bufs[index].len; + } + assert(done_write == write_size); + + if (!FlushViewOfFile(view, 0)) { + SET_REQ_WIN32_ERROR(req, GetLastError()); + UnmapViewOfFile(view); + return; + } + if (!UnmapViewOfFile(view)) { + SET_REQ_WIN32_ERROR(req, GetLastError()); + return; + } + + if (req->fs.info.offset == -1) { + fd_info->current_pos = end_pos; + uv__fd_hash_add(fd, fd_info); + } + + GetSystemTimeAsFileTime(&ft); + SetFileTime(file, NULL, NULL, &ft); + + SET_REQ_RESULT(req, done_write); +} + void fs__write(uv_fs_t* req) { int fd = req->file.fd; int64_t offset = req->fs.info.offset; @@ -702,6 +1034,7 @@ void fs__write(uv_fs_t* req) { LARGE_INTEGER original_position; LARGE_INTEGER zero_offset; int restore_position; + struct uv__fd_info_s fd_info; VERIFY_FD(fd, req); @@ -713,6 +1046,11 @@ void fs__write(uv_fs_t* req) { return; } + if (uv__fd_hash_get(fd, &fd_info)) { + fs__write_filemap(req, handle, &fd_info); + return; + } + if (offset != -1) { memset(&overlapped, 0, sizeof overlapped); overlapped_ptr = &overlapped; @@ -850,8 +1188,13 @@ void fs__unlink(uv_fs_t* req) { void fs__mkdir(uv_fs_t* req) { /* TODO: use req->mode. */ - int result = _wmkdir(req->file.pathw); - SET_REQ_RESULT(req, result); + req->result = _wmkdir(req->file.pathw); + if (req->result == -1) { + req->sys_errno_ = _doserrno; + req->result = req->sys_errno_ == ERROR_INVALID_NAME + ? UV_EINVAL + : uv_translate_sys_error(req->sys_errno_); + } } @@ -1536,6 +1879,7 @@ static void fs__fdatasync(uv_fs_t* req) { static void fs__ftruncate(uv_fs_t* req) { int fd = req->file.fd; HANDLE handle; + struct uv__fd_info_s fd_info = { 0 }; NTSTATUS status; IO_STATUS_BLOCK io_status; FILE_END_OF_FILE_INFORMATION eof_info; @@ -1544,6 +1888,17 @@ static void fs__ftruncate(uv_fs_t* req) { handle = uv__get_osfhandle(fd); + if (uv__fd_hash_get(fd, &fd_info)) { + if (fd_info.is_directory) { + SET_REQ_WIN32_ERROR(req, ERROR_ACCESS_DENIED); + return; + } + + if (fd_info.mapping != INVALID_HANDLE_VALUE) { + CloseHandle(fd_info.mapping); + } + } + eof_info.EndOfFile.QuadPart = req->fs.info.offset; status = pNtSetInformationFile(handle, @@ -1556,6 +1911,43 @@ static void fs__ftruncate(uv_fs_t* req) { SET_REQ_RESULT(req, 0); } else { SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status)); + + if (fd_info.flags) { + CloseHandle(handle); + fd_info.mapping = INVALID_HANDLE_VALUE; + fd_info.size.QuadPart = 0; + fd_info.current_pos.QuadPart = 0; + uv__fd_hash_add(fd, &fd_info); + return; + } + } + + if (fd_info.flags) { + fd_info.size = eof_info.EndOfFile; + + if (fd_info.size.QuadPart == 0) { + fd_info.mapping = INVALID_HANDLE_VALUE; + } else { + DWORD flProtect = (fd_info.flags & (UV_FS_O_RDONLY | UV_FS_O_WRONLY | + UV_FS_O_RDWR)) == UV_FS_O_RDONLY ? PAGE_READONLY : PAGE_READWRITE; + fd_info.mapping = CreateFileMapping(handle, + NULL, + flProtect, + fd_info.size.HighPart, + fd_info.size.LowPart, + NULL); + if (fd_info.mapping == NULL) { + SET_REQ_WIN32_ERROR(req, GetLastError()); + CloseHandle(handle); + fd_info.mapping = INVALID_HANDLE_VALUE; + fd_info.size.QuadPart = 0; + fd_info.current_pos.QuadPart = 0; + uv__fd_hash_add(fd, &fd_info); + return; + } + } + + uv__fd_hash_add(fd, &fd_info); } } @@ -1563,7 +1955,6 @@ static void fs__ftruncate(uv_fs_t* req) { static void fs__copyfile(uv_fs_t* req) { int flags; int overwrite; - DWORD error; uv_stat_t statbuf; uv_stat_t new_statbuf; @@ -2165,6 +2556,41 @@ static void fs__lchown(uv_fs_t* req) { req->result = 0; } + +static void fs__statfs(uv_fs_t* req) { + uv_statfs_t* stat_fs; + DWORD sectors_per_cluster; + DWORD bytes_per_sector; + DWORD free_clusters; + DWORD total_clusters; + + if (0 == GetDiskFreeSpaceW(req->file.pathw, + §ors_per_cluster, + &bytes_per_sector, + &free_clusters, + &total_clusters)) { + SET_REQ_WIN32_ERROR(req, GetLastError()); + return; + } + + stat_fs = uv__malloc(sizeof(*stat_fs)); + if (stat_fs == NULL) { + SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY); + return; + } + + stat_fs->f_type = 0; + stat_fs->f_bsize = bytes_per_sector * sectors_per_cluster; + stat_fs->f_blocks = total_clusters; + stat_fs->f_bfree = free_clusters; + stat_fs->f_bavail = free_clusters; + stat_fs->f_files = 0; + stat_fs->f_ffree = 0; + req->ptr = stat_fs; + SET_REQ_RESULT(req, 0); +} + + static void uv__fs_work(struct uv__work* w) { uv_fs_t* req; @@ -2204,8 +2630,9 @@ static void uv__fs_work(struct uv__work* w) { XX(READLINK, readlink) XX(REALPATH, realpath) XX(CHOWN, chown) - XX(FCHOWN, fchown); - XX(LCHOWN, lchown); + XX(FCHOWN, fchown) + XX(LCHOWN, lchown) + XX(STATFS, statfs) default: assert(!"bad uv_fs_type"); } @@ -2717,3 +3144,18 @@ int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file fd, double atime, req->fs.time.mtime = mtime; POST; } + + +int uv_fs_statfs(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + uv_fs_cb cb) { + int err; + + INIT(UV_FS_STATFS); + err = fs__capture_path(req, path, NULL, cb != NULL); + if (err) + return uv_translate_sys_error(err); + + POST; +} diff --git a/deps/uv/src/win/process.c b/deps/uv/src/win/process.c index f9c53de0af00..9b7fdc1dc1b4 100644 --- a/deps/uv/src/win/process.c +++ b/deps/uv/src/win/process.c @@ -714,7 +714,7 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) { /* second pass: copy to UTF-16 environment block */ dst_copy = (WCHAR*)uv__malloc(env_len * sizeof(WCHAR)); - if (!dst_copy) { + if (dst_copy == NULL && env_len > 0) { return ERROR_OUTOFMEMORY; } env_copy = alloca(env_block_count * sizeof(WCHAR*)); @@ -739,7 +739,7 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) { } } *ptr_copy = NULL; - assert(env_len == (size_t) (ptr - dst_copy)); + assert(env_len == 0 || env_len == (size_t) (ptr - dst_copy)); /* sort our (UTF-16) copy */ qsort(env_copy, env_block_count-1, sizeof(wchar_t*), qsort_wcscmp); diff --git a/deps/uv/src/win/tty.c b/deps/uv/src/win/tty.c index a98fe26335e4..07436dc804f0 100644 --- a/deps/uv/src/win/tty.c +++ b/deps/uv/src/win/tty.c @@ -2280,6 +2280,8 @@ static void uv__determine_vterm_state(HANDLE handle) { static DWORD WINAPI uv__tty_console_resize_message_loop_thread(void* param) { CONSOLE_SCREEN_BUFFER_INFO sb_info; + NTSTATUS status; + ULONG_PTR conhost_pid; MSG msg; if (!GetConsoleScreenBufferInfo(uv__tty_console_handle, &sb_info)) @@ -2288,14 +2290,29 @@ static DWORD WINAPI uv__tty_console_resize_message_loop_thread(void* param) { uv__tty_console_width = sb_info.dwSize.X; uv__tty_console_height = sb_info.srWindow.Bottom - sb_info.srWindow.Top + 1; - if (pSetWinEventHook == NULL) + if (pSetWinEventHook == NULL || pNtQueryInformationProcess == NULL) return 0; + status = pNtQueryInformationProcess(GetCurrentProcess(), + ProcessConsoleHostProcess, + &conhost_pid, + sizeof(conhost_pid), + NULL); + + if (!NT_SUCCESS(status)) + /* We couldn't retrieve our console host process, probably because this + * is a 32-bit process running on 64-bit Windows. Fall back to receiving + * console events from all processes. */ + conhost_pid = 0; + + /* Ensure the PID is a multiple of 4, which is required by SetWinEventHook */ + conhost_pid &= ~(ULONG_PTR)0x3; + if (!pSetWinEventHook(EVENT_CONSOLE_LAYOUT, EVENT_CONSOLE_LAYOUT, NULL, uv__tty_console_resize_event, - 0, + (DWORD)conhost_pid, 0, WINEVENT_OUTOFCONTEXT)) return 0; diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c index 7ca83213a67c..359a16aed4bb 100644 --- a/deps/uv/src/win/util.c +++ b/deps/uv/src/win/util.c @@ -1171,18 +1171,18 @@ int uv_os_homedir(char* buffer, size_t* size) { int uv_os_tmpdir(char* buffer, size_t* size) { - wchar_t path[MAX_PATH + 1]; + wchar_t path[MAX_PATH + 2]; DWORD bufsize; size_t len; if (buffer == NULL || size == NULL || *size == 0) return UV_EINVAL; - len = GetTempPathW(MAX_PATH + 1, path); + len = GetTempPathW(ARRAY_SIZE(path), path); if (len == 0) { return uv_translate_sys_error(GetLastError()); - } else if (len > MAX_PATH + 1) { + } else if (len > ARRAY_SIZE(path)) { /* This should not be possible */ return UV_EIO; } @@ -1397,6 +1397,75 @@ int uv_os_get_passwd(uv_passwd_t* pwd) { } +int uv_os_environ(uv_env_item_t** envitems, int* count) { + wchar_t* env; + wchar_t* penv; + int i, cnt; + uv_env_item_t* envitem; + + *envitems = NULL; + *count = 0; + + env = GetEnvironmentStringsW(); + if (env == NULL) + return 0; + + for (penv = env, i = 0; *penv != L'\0'; penv += wcslen(penv) + 1, i++); + + *envitems = uv__calloc(i, sizeof(**envitems)); + if (envitems == NULL) { + FreeEnvironmentStringsW(env); + return UV_ENOMEM; + } + + penv = env; + cnt = 0; + + while (*penv != L'\0' && cnt < i) { + char* buf; + char* ptr; + + if (uv__convert_utf16_to_utf8(penv, -1, &buf) != 0) + goto fail; + + ptr = strchr(buf, '='); + if (ptr == NULL) { + uv__free(buf); + goto do_continue; + } + + *ptr = '\0'; + + envitem = &(*envitems)[cnt]; + envitem->name = buf; + envitem->value = ptr + 1; + + cnt++; + + do_continue: + penv += wcslen(penv) + 1; + } + + FreeEnvironmentStringsW(env); + + *count = cnt; + return 0; + +fail: + FreeEnvironmentStringsW(env); + + for (i = 0; i < cnt; i++) { + envitem = &(*envitems)[cnt]; + uv__free(envitem->name); + } + uv__free(*envitems); + + *envitems = NULL; + *count = 0; + return UV_ENOMEM; +} + + int uv_os_getenv(const char* name, char* buffer, size_t* size) { wchar_t var[MAX_ENV_VAR_LENGTH]; wchar_t* name_w; diff --git a/deps/uv/src/win/winapi.c b/deps/uv/src/win/winapi.c index fbbbceed95eb..19e4377faf55 100644 --- a/deps/uv/src/win/winapi.c +++ b/deps/uv/src/win/winapi.c @@ -34,6 +34,7 @@ sNtSetInformationFile pNtSetInformationFile; sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile; sNtQueryDirectoryFile pNtQueryDirectoryFile; sNtQuerySystemInformation pNtQuerySystemInformation; +sNtQueryInformationProcess pNtQueryInformationProcess; /* Kernel32 function pointers */ sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx; @@ -106,6 +107,13 @@ void uv_winapi_init(void) { uv_fatal_error(GetLastError(), "GetProcAddress"); } + pNtQueryInformationProcess = (sNtQueryInformationProcess) GetProcAddress( + ntdll_module, + "NtQueryInformationProcess"); + if (pNtQueryInformationProcess == NULL) { + uv_fatal_error(GetLastError(), "GetProcAddress"); + } + kernel32_module = GetModuleHandleA("kernel32.dll"); if (kernel32_module == NULL) { uv_fatal_error(GetLastError(), "GetModuleHandleA"); diff --git a/deps/uv/src/win/winapi.h b/deps/uv/src/win/winapi.h index 82c5ed46711d..203393c2e3af 100644 --- a/deps/uv/src/win/winapi.h +++ b/deps/uv/src/win/winapi.h @@ -4436,6 +4436,10 @@ typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION { # define SystemProcessorPerformanceInformation 8 #endif +#ifndef ProcessConsoleHostProcess +# define ProcessConsoleHostProcess 49 +#endif + #ifndef FILE_DEVICE_FILE_SYSTEM # define FILE_DEVICE_FILE_SYSTEM 0x00000009 #endif @@ -4578,6 +4582,13 @@ typedef NTSTATUS (NTAPI *sNtQueryDirectoryFile) BOOLEAN RestartScan ); +typedef NTSTATUS (NTAPI *sNtQueryInformationProcess) + (HANDLE ProcessHandle, + UINT ProcessInformationClass, + PVOID ProcessInformation, + ULONG Length, + PULONG ReturnLength); + /* * Kernel32 headers */ @@ -4718,6 +4729,7 @@ extern sNtSetInformationFile pNtSetInformationFile; extern sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile; extern sNtQueryDirectoryFile pNtQueryDirectoryFile; extern sNtQuerySystemInformation pNtQuerySystemInformation; +extern sNtQueryInformationProcess pNtQueryInformationProcess; /* Kernel32 function pointers */ extern sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx; diff --git a/deps/uv/test/runner-win.c b/deps/uv/test/runner-win.c index f60c23df3ebf..6bb41a5d0629 100644 --- a/deps/uv/test/runner-win.c +++ b/deps/uv/test/runner-win.c @@ -56,6 +56,12 @@ int platform_init(int argc, char **argv) { _setmode(1, _O_BINARY); _setmode(2, _O_BINARY); +#ifdef _MSC_VER + _set_fmode(_O_BINARY); +#else + _fmode = _O_BINARY; +#endif + /* Disable stdio output buffering. */ setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0); diff --git a/deps/uv/test/task.h b/deps/uv/test/task.h index 8462e0ddbd0a..e763f89f09dc 100644 --- a/deps/uv/test/task.h +++ b/deps/uv/test/task.h @@ -44,6 +44,10 @@ # pragma clang diagnostic ignored "-Wc99-extensions" #endif +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wvariadic-macros" +#endif + #define TEST_PORT 9123 #define TEST_PORT_2 9124 diff --git a/deps/uv/test/test-env-vars.c b/deps/uv/test/test-env-vars.c index 641050e675ff..d7abb4249561 100644 --- a/deps/uv/test/test-env-vars.c +++ b/deps/uv/test/test-env-vars.c @@ -27,9 +27,11 @@ TEST_IMPL(env_vars) { const char* name = "UV_TEST_FOO"; + const char* name2 = "UV_TEST_FOO2"; char buf[BUF_SIZE]; size_t size; - int r; + int i, r, envcount, found; + uv_env_item_t* envitems; /* Reject invalid inputs when setting an environment variable */ r = uv_os_setenv(NULL, "foo"); @@ -86,5 +88,38 @@ TEST_IMPL(env_vars) { r = uv_os_unsetenv(name); ASSERT(r == 0); + /* Check getting all env variables. */ + r = uv_os_setenv(name, "123456789"); + ASSERT(r == 0); + r = uv_os_setenv(name2, ""); + ASSERT(r == 0); + + r = uv_os_environ(&envitems, &envcount); + ASSERT(r == 0); + ASSERT(envcount > 0); + + found = 0; + + for (i = 0; i < envcount; i++) { + /* printf("Env: %s = %s\n", envitems[i].name, envitems[i].value); */ + if (strcmp(envitems[i].name, name) == 0) { + found++; + ASSERT(strcmp(envitems[i].value, "123456789") == 0); + } else if (strcmp(envitems[i].name, name2) == 0) { + found++; + ASSERT(strlen(envitems[i].value) == 0); + } + } + + ASSERT(found == 2); + + uv_os_free_environ(envitems, envcount); + + r = uv_os_unsetenv(name); + ASSERT(r == 0); + + r = uv_os_unsetenv(name2); + ASSERT(r == 0); + return 0; } diff --git a/deps/uv/test/test-fs-fd-hash.c b/deps/uv/test/test-fs-fd-hash.c new file mode 100644 index 000000000000..8b4bc0351b33 --- /dev/null +++ b/deps/uv/test/test-fs-fd-hash.c @@ -0,0 +1,133 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#if defined(_WIN32) && !defined(USING_UV_SHARED) + +#include "uv.h" +#include "task.h" + +#include "../src/win/fs-fd-hash-inl.h" + + +#define HASH_MAX 1000000000 +#define HASH_INC (1000 * UV__FD_HASH_SIZE + 2) +#define BUCKET_MAX (UV__FD_HASH_SIZE * UV__FD_HASH_GROUP_SIZE * 10) +#define BUCKET_INC UV__FD_HASH_SIZE +#define FD_DIFF 9 + + +void assert_nonexistent(int fd) { + struct uv__fd_info_s info = { 0 }; + ASSERT(!uv__fd_hash_get(fd, &info)); + ASSERT(!uv__fd_hash_remove(fd, &info)); +} + +void assert_existent(int fd) { + struct uv__fd_info_s info = { 0 }; + ASSERT(uv__fd_hash_get(fd, &info)); + ASSERT(info.flags == fd + FD_DIFF); +} + +void assert_insertion(int fd) { + struct uv__fd_info_s info = { 0 }; + assert_nonexistent(fd); + info.flags = fd + FD_DIFF; + uv__fd_hash_add(fd, &info); + assert_existent(fd); +} + +void assert_removal(int fd) { + struct uv__fd_info_s info = { 0 }; + assert_existent(fd); + uv__fd_hash_remove(fd, &info); + ASSERT(info.flags == fd + FD_DIFF); + assert_nonexistent(fd); +} + + +/* Run a function for a set of values up to a very high number */ +#define RUN_HASH(function) \ + do { \ + for (fd = 0; fd < HASH_MAX; fd += HASH_INC) { \ + function(fd); \ + } \ + } while (0) + +/* Run a function for a set of values that will cause many collisions */ +#define RUN_COLLISIONS(function) \ + do { \ + for (fd = 1; fd < BUCKET_MAX; fd += BUCKET_INC) { \ + function(fd); \ + } \ + } while (0) + + +TEST_IMPL(fs_fd_hash) { + int fd; + + uv__fd_hash_init(); + + /* Empty table */ + RUN_HASH(assert_nonexistent); + RUN_COLLISIONS(assert_nonexistent); + + /* Fill up */ + RUN_HASH(assert_insertion); + RUN_COLLISIONS(assert_insertion); + + /* Full */ + RUN_HASH(assert_existent); + RUN_COLLISIONS(assert_existent); + + /* Update */ + { + struct uv__fd_info_s info = { 0 }; + info.flags = FD_DIFF + FD_DIFF; + uv__fd_hash_add(0, &info); + } + { + struct uv__fd_info_s info = { 0 }; + ASSERT(uv__fd_hash_get(0, &info)); + ASSERT(info.flags == FD_DIFF + FD_DIFF); + } + { + /* Leave as it was, will be again tested below */ + struct uv__fd_info_s info = { 0 }; + info.flags = FD_DIFF; + uv__fd_hash_add(0, &info); + } + + /* Remove all */ + RUN_HASH(assert_removal); + RUN_COLLISIONS(assert_removal); + + /* Empty table */ + RUN_HASH(assert_nonexistent); + RUN_COLLISIONS(assert_nonexistent); + + return 0; +} + +#else + +typedef int file_has_no_tests; /* ISO C forbids an empty translation unit. */ + +#endif /* ifndef _WIN32 */ diff --git a/deps/uv/test/test-fs-open-flags.c b/deps/uv/test/test-fs-open-flags.c new file mode 100644 index 000000000000..fcef2fb0819f --- /dev/null +++ b/deps/uv/test/test-fs-open-flags.c @@ -0,0 +1,435 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifdef _WIN32 + +#include "uv.h" +#include "task.h" + +#if defined(__unix__) || defined(__POSIX__) || \ + defined(__APPLE__) || defined(__sun) || \ + defined(_AIX) || defined(__MVS__) || \ + defined(__HAIKU__) +# include /* unlink, rmdir */ +#else +# include +# define rmdir _rmdir +# define unlink _unlink +#endif + +static int flags; + +static uv_fs_t close_req; +static uv_fs_t mkdir_req; +static uv_fs_t open_req; +static uv_fs_t read_req; +static uv_fs_t rmdir_req; +static uv_fs_t unlink_req; +static uv_fs_t write_req; + +static char buf[32]; +static uv_buf_t iov; + +/* Opening the same file multiple times quickly can cause uv_fs_open to fail + * with EBUSY, so append an identifier to the file name for each operation */ +static int sid = 0; + +#define FILE_NAME_SIZE 128 +static char absent_file[FILE_NAME_SIZE]; +static char empty_file[FILE_NAME_SIZE]; +static char dummy_file[FILE_NAME_SIZE]; +static char empty_dir[] = "empty_dir"; + +static void setup() { + int r; + + /* empty_dir */ + r = uv_fs_rmdir(NULL, &rmdir_req, empty_dir, NULL); + ASSERT(r == 0 || r == UV_ENOENT); + ASSERT(rmdir_req.result == 0 || rmdir_req.result == UV_ENOENT); + uv_fs_req_cleanup(&rmdir_req); + + r = uv_fs_mkdir(NULL, &mkdir_req, empty_dir, 0755, NULL); + ASSERT(r == 0); + ASSERT(mkdir_req.result == 0); + uv_fs_req_cleanup(&mkdir_req); +} + +static void refresh() { + int r; + + /* absent_file */ + sprintf(absent_file, "test_file_%d", sid++); + + r = uv_fs_unlink(NULL, &unlink_req, absent_file, NULL); + ASSERT(r == 0 || r == UV_ENOENT); + ASSERT(unlink_req.result == 0 || unlink_req.result == UV_ENOENT); + uv_fs_req_cleanup(&unlink_req); + + /* empty_file */ + sprintf(empty_file, "test_file_%d", sid++); + + r = uv_fs_open(NULL, &open_req, empty_file, + UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY, S_IWUSR | S_IRUSR, NULL); + ASSERT(r >= 0); + ASSERT(open_req.result >= 0); + uv_fs_req_cleanup(&open_req); + + r = uv_fs_close(NULL, &close_req, open_req.result, NULL); + ASSERT(r == 0); + ASSERT(close_req.result == 0); + uv_fs_req_cleanup(&close_req); + + /* dummy_file */ + sprintf(dummy_file, "test_file_%d", sid++); + + r = uv_fs_open(NULL, &open_req, dummy_file, + UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY, S_IWUSR | S_IRUSR, NULL); + ASSERT(r >= 0); + ASSERT(open_req.result >= 0); + uv_fs_req_cleanup(&open_req); + + iov = uv_buf_init("a", 1); + r = uv_fs_write(NULL, &write_req, open_req.result, &iov, 1, -1, NULL); + ASSERT(r == 1); + ASSERT(write_req.result == 1); + uv_fs_req_cleanup(&write_req); + + r = uv_fs_close(NULL, &close_req, open_req.result, NULL); + ASSERT(r == 0); + ASSERT(close_req.result == 0); + uv_fs_req_cleanup(&close_req); +} + +static void cleanup() { + unlink(absent_file); + unlink(empty_file); + unlink(dummy_file); +} + +static void openFail(char *file, int error) { + int r; + + refresh(); + + r = uv_fs_open(NULL, &open_req, file, flags, S_IWUSR | S_IRUSR, NULL); + ASSERT(r == error); + ASSERT(open_req.result == error); + uv_fs_req_cleanup(&open_req); + + /* Ensure the first call does not create the file */ + r = uv_fs_open(NULL, &open_req, file, flags, S_IWUSR | S_IRUSR, NULL); + ASSERT(r == error); + ASSERT(open_req.result == error); + uv_fs_req_cleanup(&open_req); + + cleanup(); +} + +static void refreshOpen(char *file) { + int r; + + refresh(); + + r = uv_fs_open(NULL, &open_req, file, flags, S_IWUSR | S_IRUSR, NULL); + ASSERT(r >= 0); + ASSERT(open_req.result >= 0); + uv_fs_req_cleanup(&open_req); +} + +static void writeExpect(char *file, char *expected, int size) { + int r; + + refreshOpen(file); + + iov = uv_buf_init("b", 1); + r = uv_fs_write(NULL, &write_req, open_req.result, &iov, 1, -1, NULL); + ASSERT(r == 1); + ASSERT(write_req.result == 1); + uv_fs_req_cleanup(&write_req); + + iov = uv_buf_init("c", 1); + r = uv_fs_write(NULL, &write_req, open_req.result, &iov, 1, -1, NULL); + ASSERT(r == 1); + ASSERT(write_req.result == 1); + uv_fs_req_cleanup(&write_req); + + r = uv_fs_close(NULL, &close_req, open_req.result, NULL); + ASSERT(r == 0); + ASSERT(close_req.result == 0); + uv_fs_req_cleanup(&close_req); + + /* Check contents */ + r = uv_fs_open(NULL, &open_req, file, UV_FS_O_RDONLY, S_IWUSR | S_IRUSR, NULL); + ASSERT(r >= 0); + ASSERT(open_req.result >= 0); + uv_fs_req_cleanup(&open_req); + + iov = uv_buf_init(buf, sizeof(buf)); + r = uv_fs_read(NULL, &read_req, open_req.result, &iov, 1, -1, NULL); + ASSERT(r == size); + ASSERT(read_req.result == size); + ASSERT(strncmp(buf, expected, size) == 0); + uv_fs_req_cleanup(&read_req); + + r = uv_fs_close(NULL, &close_req, open_req.result, NULL); + ASSERT(r == 0); + ASSERT(close_req.result == 0); + uv_fs_req_cleanup(&close_req); + + cleanup(); +} + +static void writeFail(char *file, int error) { + int r; + + refreshOpen(file); + + iov = uv_buf_init("z", 1); + r = uv_fs_write(NULL, &write_req, open_req.result, &iov, 1, -1, NULL); + ASSERT(r == error); + ASSERT(write_req.result == error); + uv_fs_req_cleanup(&write_req); + + iov = uv_buf_init("z", 1); + r = uv_fs_write(NULL, &write_req, open_req.result, &iov, 1, -1, NULL); + ASSERT(r == error); + ASSERT(write_req.result == error); + uv_fs_req_cleanup(&write_req); + + r = uv_fs_close(NULL, &close_req, open_req.result, NULL); + ASSERT(r == 0); + ASSERT(close_req.result == 0); + uv_fs_req_cleanup(&close_req); + + cleanup(); +} + +static void readExpect(char *file, char *expected, int size) { + int r; + + refreshOpen(file); + + iov = uv_buf_init(buf, sizeof(buf)); + r = uv_fs_read(NULL, &read_req, open_req.result, &iov, 1, -1, NULL); + ASSERT(r == size); + ASSERT(read_req.result == size); + ASSERT(strncmp(buf, expected, size) == 0); + uv_fs_req_cleanup(&read_req); + + r = uv_fs_close(NULL, &close_req, open_req.result, NULL); + ASSERT(r == 0); + ASSERT(close_req.result == 0); + uv_fs_req_cleanup(&close_req); + + cleanup(); +} + +static void readFail(char *file, int error) { + int r; + + refreshOpen(file); + + iov = uv_buf_init(buf, sizeof(buf)); + r = uv_fs_read(NULL, &read_req, open_req.result, &iov, 1, -1, NULL); + ASSERT(r == error); + ASSERT(read_req.result == error); + uv_fs_req_cleanup(&read_req); + + iov = uv_buf_init(buf, sizeof(buf)); + r = uv_fs_read(NULL, &read_req, open_req.result, &iov, 1, -1, NULL); + ASSERT(r == error); + ASSERT(read_req.result == error); + uv_fs_req_cleanup(&read_req); + + r = uv_fs_close(NULL, &close_req, open_req.result, NULL); + ASSERT(r == 0); + ASSERT(close_req.result == 0); + uv_fs_req_cleanup(&close_req); + + cleanup(); +} + +static void fs_open_flags(int add_flags) { + /* Follow the order from + * https://github.com/nodejs/node/blob/1a96abe849/lib/internal/fs/utils.js#L329-L354 + */ + + /* r */ + flags = add_flags | UV_FS_O_RDONLY; + openFail(absent_file, UV_ENOENT); + writeFail(empty_file, UV_EPERM); + readExpect(empty_file, "", 0); + writeFail(dummy_file, UV_EPERM); + readExpect(dummy_file, "a", 1); + writeFail(empty_dir, UV_EPERM); + readFail(empty_dir, UV_EISDIR); + + /* rs */ + flags = add_flags | UV_FS_O_RDONLY | UV_FS_O_SYNC; + openFail(absent_file, UV_ENOENT); + writeFail(empty_file, UV_EPERM); + readExpect(empty_file, "", 0); + writeFail(dummy_file, UV_EPERM); + readExpect(dummy_file, "a", 1); + writeFail(empty_dir, UV_EPERM); + readFail(empty_dir, UV_EISDIR); + + /* r+ */ + flags = add_flags | UV_FS_O_RDWR; + openFail(absent_file, UV_ENOENT); + writeExpect(empty_file, "bc", 2); + readExpect(empty_file, "", 0); + writeExpect(dummy_file, "bc", 2); + readExpect(dummy_file, "a", 1); + writeFail(empty_dir, UV_EISDIR); + readFail(empty_dir, UV_EISDIR); + + /* rs+ */ + flags = add_flags | UV_FS_O_RDWR | UV_FS_O_SYNC; + openFail(absent_file, UV_ENOENT); + writeExpect(empty_file, "bc", 2); + readExpect(empty_file, "", 0); + writeExpect(dummy_file, "bc", 2); + readExpect(dummy_file, "a", 1); + writeFail(empty_dir, UV_EISDIR); + readFail(empty_dir, UV_EISDIR); + + /* w */ + flags = add_flags | UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY; + writeExpect(absent_file, "bc", 2); + readFail(absent_file, UV_EPERM); + writeExpect(empty_file, "bc", 2); + readFail(empty_file, UV_EPERM); + writeExpect(dummy_file, "bc", 2); + readFail(dummy_file, UV_EPERM); + openFail(empty_dir, UV_EISDIR); + + /* wx */ + flags = add_flags | UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY | + UV_FS_O_EXCL; + writeExpect(absent_file, "bc", 2); + readFail(absent_file, UV_EPERM); + openFail(empty_file, UV_EEXIST); + openFail(dummy_file, UV_EEXIST); + openFail(empty_dir, UV_EEXIST); + + /* w+ */ + flags = add_flags | UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_RDWR; + writeExpect(absent_file, "bc", 2); + readExpect(absent_file, "", 0); + writeExpect(empty_file, "bc", 2); + readExpect(empty_file, "", 0); + writeExpect(dummy_file, "bc", 2); + readExpect(dummy_file, "", 0); + openFail(empty_dir, UV_EISDIR); + + /* wx+ */ + flags = add_flags | UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_RDWR | + UV_FS_O_EXCL; + writeExpect(absent_file, "bc", 2); + readExpect(absent_file, "", 0); + openFail(empty_file, UV_EEXIST); + openFail(dummy_file, UV_EEXIST); + openFail(empty_dir, UV_EEXIST); + + /* a */ + flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_WRONLY; + writeExpect(absent_file, "bc", 2); + readFail(absent_file, UV_EPERM); + writeExpect(empty_file, "bc", 2); + readFail(empty_file, UV_EPERM); + writeExpect(dummy_file, "abc", 3); + readFail(dummy_file, UV_EPERM); + writeFail(empty_dir, UV_EISDIR); + readFail(empty_dir, UV_EPERM); + + /* ax */ + flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_WRONLY | + UV_FS_O_EXCL; + writeExpect(absent_file, "bc", 2); + readFail(absent_file, UV_EPERM); + openFail(empty_file, UV_EEXIST); + openFail(dummy_file, UV_EEXIST); + openFail(empty_dir, UV_EEXIST); + + /* as */ + flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_WRONLY | + UV_FS_O_SYNC; + writeExpect(absent_file, "bc", 2); + readFail(absent_file, UV_EPERM); + writeExpect(empty_file, "bc", 2); + readFail(empty_file, UV_EPERM); + writeExpect(dummy_file, "abc", 3); + readFail(dummy_file, UV_EPERM); + writeFail(empty_dir, UV_EISDIR); + readFail(empty_dir, UV_EPERM); + + /* a+ */ + flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_RDWR; + writeExpect(absent_file, "bc", 2); + readExpect(absent_file, "", 0); + writeExpect(empty_file, "bc", 2); + readExpect(empty_file, "", 0); + writeExpect(dummy_file, "abc", 3); + readExpect(dummy_file, "a", 1); + writeFail(empty_dir, UV_EISDIR); + readFail(empty_dir, UV_EISDIR); + + /* ax+ */ + flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_RDWR | + UV_FS_O_EXCL; + writeExpect(absent_file, "bc", 2); + readExpect(absent_file, "", 0); + openFail(empty_file, UV_EEXIST); + openFail(dummy_file, UV_EEXIST); + openFail(empty_dir, UV_EEXIST); + + /* as+ */ + flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_RDWR | + UV_FS_O_SYNC; + writeExpect(absent_file, "bc", 2); + readExpect(absent_file, "", 0); + writeExpect(empty_file, "bc", 2); + readExpect(empty_file, "", 0); + writeExpect(dummy_file, "abc", 3); + readExpect(dummy_file, "a", 1); + writeFail(empty_dir, UV_EISDIR); + readFail(empty_dir, UV_EISDIR); +} +TEST_IMPL(fs_open_flags) { + setup(); + + fs_open_flags(0); + fs_open_flags(UV_FS_O_FILEMAP); + + /* Cleanup. */ + rmdir(empty_dir); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + +#else + +typedef int file_has_no_tests; /* ISO C forbids an empty translation unit. */ + +#endif /* ifndef _WIN32 */ diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c index 2cf8f287fe33..0d92b0d3a0d3 100644 --- a/deps/uv/test/test-fs.c +++ b/deps/uv/test/test-fs.c @@ -94,6 +94,7 @@ static int readlink_cb_count; static int realpath_cb_count; static int utime_cb_count; static int futime_cb_count; +static int statfs_cb_count; static uv_loop_t* loop; @@ -330,6 +331,38 @@ static void fstat_cb(uv_fs_t* req) { } +static void statfs_cb(uv_fs_t* req) { + uv_statfs_t* stats; + + ASSERT(req->fs_type == UV_FS_STATFS); + ASSERT(req->result == 0); + ASSERT(req->ptr != NULL); + stats = req->ptr; + +#if defined(_WIN32) || defined(__sun) || defined(_AIX) || defined(__MVS__) + ASSERT(stats->f_type == 0); +#else + ASSERT(stats->f_type > 0); +#endif + + ASSERT(stats->f_bsize > 0); + ASSERT(stats->f_blocks > 0); + ASSERT(stats->f_bfree <= stats->f_blocks); + ASSERT(stats->f_bavail <= stats->f_bfree); + +#ifdef _WIN32 + ASSERT(stats->f_files == 0); + ASSERT(stats->f_ffree == 0); +#else + ASSERT(stats->f_files > 0); + ASSERT(stats->f_ffree <= stats->f_files); +#endif + uv_fs_req_cleanup(req); + ASSERT(req->ptr == NULL); + statfs_cb_count++; +} + + static void close_cb(uv_fs_t* req) { int r; ASSERT(req == &close_req); @@ -847,7 +880,7 @@ TEST_IMPL(fs_file_async) { } -TEST_IMPL(fs_file_sync) { +static void fs_file_sync(int add_flags) { int r; /* Setup. */ @@ -856,8 +889,8 @@ TEST_IMPL(fs_file_sync) { loop = uv_default_loop(); - r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT, - S_IWUSR | S_IRUSR, NULL); + r = uv_fs_open(loop, &open_req1, "test_file", + O_WRONLY | O_CREAT | add_flags, S_IWUSR | S_IRUSR, NULL); ASSERT(r >= 0); ASSERT(open_req1.result >= 0); uv_fs_req_cleanup(&open_req1); @@ -873,7 +906,7 @@ TEST_IMPL(fs_file_sync) { ASSERT(close_req.result == 0); uv_fs_req_cleanup(&close_req); - r = uv_fs_open(NULL, &open_req1, "test_file", O_RDWR, 0, NULL); + r = uv_fs_open(NULL, &open_req1, "test_file", O_RDWR | add_flags, 0, NULL); ASSERT(r >= 0); ASSERT(open_req1.result >= 0); uv_fs_req_cleanup(&open_req1); @@ -900,7 +933,8 @@ TEST_IMPL(fs_file_sync) { ASSERT(rename_req.result == 0); uv_fs_req_cleanup(&rename_req); - r = uv_fs_open(NULL, &open_req1, "test_file2", O_RDONLY, 0, NULL); + r = uv_fs_open(NULL, &open_req1, "test_file2", O_RDONLY | add_flags, 0, + NULL); ASSERT(r >= 0); ASSERT(open_req1.result >= 0); uv_fs_req_cleanup(&open_req1); @@ -926,13 +960,17 @@ TEST_IMPL(fs_file_sync) { /* Cleanup */ unlink("test_file"); unlink("test_file2"); +} +TEST_IMPL(fs_file_sync) { + fs_file_sync(0); + fs_file_sync(UV_FS_O_FILEMAP); MAKE_VALGRIND_HAPPY(); return 0; } -TEST_IMPL(fs_file_write_null_buffer) { +static void fs_file_write_null_buffer(int add_flags) { int r; /* Setup. */ @@ -940,8 +978,8 @@ TEST_IMPL(fs_file_write_null_buffer) { loop = uv_default_loop(); - r = uv_fs_open(NULL, &open_req1, "test_file", O_WRONLY | O_CREAT, - S_IWUSR | S_IRUSR, NULL); + r = uv_fs_open(NULL, &open_req1, "test_file", + O_WRONLY | O_CREAT | add_flags, S_IWUSR | S_IRUSR, NULL); ASSERT(r >= 0); ASSERT(open_req1.result >= 0); uv_fs_req_cleanup(&open_req1); @@ -958,6 +996,10 @@ TEST_IMPL(fs_file_write_null_buffer) { uv_fs_req_cleanup(&close_req); unlink("test_file"); +} +TEST_IMPL(fs_file_write_null_buffer) { + fs_file_write_null_buffer(0); + fs_file_write_null_buffer(UV_FS_O_FILEMAP); MAKE_VALGRIND_HAPPY(); return 0; @@ -1470,7 +1512,7 @@ TEST_IMPL(fs_chmod) { uv_run(loop, UV_RUN_DEFAULT); ASSERT(fchmod_cb_count == 1); - close(file); + uv_fs_close(loop, &req, file, NULL); /* * Run the loop just to check we don't have make any extraneous uv_ref() @@ -1513,7 +1555,7 @@ TEST_IMPL(fs_unlink_readonly) { ASSERT(req.result == sizeof(test_buf)); uv_fs_req_cleanup(&req); - close(file); + uv_fs_close(loop, &req, file, NULL); /* Make the file read-only */ r = uv_fs_chmod(NULL, &req, "test_file", 0400, NULL); @@ -1572,7 +1614,7 @@ TEST_IMPL(fs_unlink_archive_readonly) { ASSERT(req.result == sizeof(test_buf)); uv_fs_req_cleanup(&req); - close(file); + uv_fs_close(loop, &req, file, NULL); /* Make the file read-only and clear archive flag */ r = SetFileAttributes("test_file", FILE_ATTRIBUTE_READONLY); @@ -1722,7 +1764,7 @@ TEST_IMPL(fs_link) { ASSERT(req.result == sizeof(test_buf)); uv_fs_req_cleanup(&req); - close(file); + uv_fs_close(loop, &req, file, NULL); /* sync link */ r = uv_fs_link(NULL, &req, "test_file", "test_file_link", NULL); @@ -1764,7 +1806,7 @@ TEST_IMPL(fs_link) { ASSERT(req.result >= 0); ASSERT(strcmp(buf, test_buf) == 0); - close(link); + uv_fs_close(loop, &req, link, NULL); /* * Run the loop just to check we don't have make any extraneous uv_ref() @@ -1871,7 +1913,7 @@ TEST_IMPL(fs_symlink) { ASSERT(req.result == sizeof(test_buf)); uv_fs_req_cleanup(&req); - close(file); + uv_fs_close(loop, &req, file, NULL); /* sync symlink */ r = uv_fs_symlink(NULL, &req, "test_file", "test_file_symlink", 0, NULL); @@ -1909,7 +1951,7 @@ TEST_IMPL(fs_symlink) { ASSERT(req.result >= 0); ASSERT(strcmp(buf, test_buf) == 0); - close(link); + uv_fs_close(loop, &req, link, NULL); r = uv_fs_symlink(NULL, &req, @@ -1971,7 +2013,7 @@ TEST_IMPL(fs_symlink) { ASSERT(req.result >= 0); ASSERT(strcmp(buf, test_buf) == 0); - close(link); + uv_fs_close(loop, &req, link, NULL); r = uv_fs_symlink(NULL, &req, @@ -2293,7 +2335,7 @@ TEST_IMPL(fs_utime) { ASSERT(r >= 0); ASSERT(req.result >= 0); uv_fs_req_cleanup(&req); - close(r); + uv_fs_close(loop, &req, r, NULL); atime = mtime = 400497753; /* 1982-09-10 11:22:33 */ @@ -2388,7 +2430,7 @@ TEST_IMPL(fs_futime) { ASSERT(r >= 0); ASSERT(req.result >= 0); uv_fs_req_cleanup(&req); - close(r); + uv_fs_close(loop, &req, r, NULL); atime = mtime = 400497753; /* 1982-09-10 11:22:33 */ @@ -2583,7 +2625,7 @@ TEST_IMPL(fs_open_dir) { } -TEST_IMPL(fs_file_open_append) { +static void fs_file_open_append(int add_flags) { int r; /* Setup. */ @@ -2591,8 +2633,8 @@ TEST_IMPL(fs_file_open_append) { loop = uv_default_loop(); - r = uv_fs_open(NULL, &open_req1, "test_file", O_WRONLY | O_CREAT, - S_IWUSR | S_IRUSR, NULL); + r = uv_fs_open(NULL, &open_req1, "test_file", + O_WRONLY | O_CREAT | add_flags, S_IWUSR | S_IRUSR, NULL); ASSERT(r >= 0); ASSERT(open_req1.result >= 0); uv_fs_req_cleanup(&open_req1); @@ -2608,7 +2650,8 @@ TEST_IMPL(fs_file_open_append) { ASSERT(close_req.result == 0); uv_fs_req_cleanup(&close_req); - r = uv_fs_open(NULL, &open_req1, "test_file", O_RDWR | O_APPEND, 0, NULL); + r = uv_fs_open(NULL, &open_req1, "test_file", + O_RDWR | O_APPEND | add_flags, 0, NULL); ASSERT(r >= 0); ASSERT(open_req1.result >= 0); uv_fs_req_cleanup(&open_req1); @@ -2624,7 +2667,8 @@ TEST_IMPL(fs_file_open_append) { ASSERT(close_req.result == 0); uv_fs_req_cleanup(&close_req); - r = uv_fs_open(NULL, &open_req1, "test_file", O_RDONLY, S_IRUSR, NULL); + r = uv_fs_open(NULL, &open_req1, "test_file", O_RDONLY | add_flags, + S_IRUSR, NULL); ASSERT(r >= 0); ASSERT(open_req1.result >= 0); uv_fs_req_cleanup(&open_req1); @@ -2646,6 +2690,10 @@ TEST_IMPL(fs_file_open_append) { /* Cleanup */ unlink("test_file"); +} +TEST_IMPL(fs_file_open_append) { + fs_file_open_append(0); + fs_file_open_append(UV_FS_O_FILEMAP); MAKE_VALGRIND_HAPPY(); return 0; @@ -2721,13 +2769,13 @@ TEST_IMPL(fs_rename_to_existing_file) { } -TEST_IMPL(fs_read_bufs) { +static void fs_read_bufs(int add_flags) { char scratch[768]; uv_buf_t bufs[4]; ASSERT(0 <= uv_fs_open(NULL, &open_req1, "test/fixtures/lorem_ipsum.txt", - O_RDONLY, 0, NULL)); + O_RDONLY | add_flags, 0, NULL)); ASSERT(open_req1.result >= 0); uv_fs_req_cleanup(&open_req1); @@ -2769,13 +2817,17 @@ TEST_IMPL(fs_read_bufs) { ASSERT(0 == uv_fs_close(NULL, &close_req, open_req1.result, NULL)); ASSERT(close_req.result == 0); uv_fs_req_cleanup(&close_req); +} +TEST_IMPL(fs_read_bufs) { + fs_read_bufs(0); + fs_read_bufs(UV_FS_O_FILEMAP); MAKE_VALGRIND_HAPPY(); return 0; } -TEST_IMPL(fs_read_file_eof) { +static void fs_read_file_eof(int add_flags) { #if defined(__CYGWIN__) || defined(__MSYS__) RETURN_SKIP("Cygwin pread at EOF may (incorrectly) return data!"); #endif @@ -2786,8 +2838,8 @@ TEST_IMPL(fs_read_file_eof) { loop = uv_default_loop(); - r = uv_fs_open(NULL, &open_req1, "test_file", O_WRONLY | O_CREAT, - S_IWUSR | S_IRUSR, NULL); + r = uv_fs_open(NULL, &open_req1, "test_file", + O_WRONLY | O_CREAT | add_flags, S_IWUSR | S_IRUSR, NULL); ASSERT(r >= 0); ASSERT(open_req1.result >= 0); uv_fs_req_cleanup(&open_req1); @@ -2803,7 +2855,8 @@ TEST_IMPL(fs_read_file_eof) { ASSERT(close_req.result == 0); uv_fs_req_cleanup(&close_req); - r = uv_fs_open(NULL, &open_req1, "test_file", O_RDONLY, 0, NULL); + r = uv_fs_open(NULL, &open_req1, "test_file", O_RDONLY | add_flags, 0, + NULL); ASSERT(r >= 0); ASSERT(open_req1.result >= 0); uv_fs_req_cleanup(&open_req1); @@ -2830,13 +2883,17 @@ TEST_IMPL(fs_read_file_eof) { /* Cleanup */ unlink("test_file"); +} +TEST_IMPL(fs_read_file_eof) { + fs_read_file_eof(0); + fs_read_file_eof(UV_FS_O_FILEMAP); MAKE_VALGRIND_HAPPY(); return 0; } -TEST_IMPL(fs_write_multiple_bufs) { +static void fs_write_multiple_bufs(int add_flags) { uv_buf_t iovs[2]; int r; @@ -2845,8 +2902,8 @@ TEST_IMPL(fs_write_multiple_bufs) { loop = uv_default_loop(); - r = uv_fs_open(NULL, &open_req1, "test_file", O_WRONLY | O_CREAT, - S_IWUSR | S_IRUSR, NULL); + r = uv_fs_open(NULL, &open_req1, "test_file", + O_WRONLY | O_CREAT | add_flags, S_IWUSR | S_IRUSR, NULL); ASSERT(r >= 0); ASSERT(open_req1.result >= 0); uv_fs_req_cleanup(&open_req1); @@ -2863,7 +2920,8 @@ TEST_IMPL(fs_write_multiple_bufs) { ASSERT(close_req.result == 0); uv_fs_req_cleanup(&close_req); - r = uv_fs_open(NULL, &open_req1, "test_file", O_RDONLY, 0, NULL); + r = uv_fs_open(NULL, &open_req1, "test_file", O_RDONLY | add_flags, 0, + NULL); ASSERT(r >= 0); ASSERT(open_req1.result >= 0); uv_fs_req_cleanup(&open_req1); @@ -2919,13 +2977,17 @@ TEST_IMPL(fs_write_multiple_bufs) { /* Cleanup */ unlink("test_file"); +} +TEST_IMPL(fs_write_multiple_bufs) { + fs_write_multiple_bufs(0); + fs_write_multiple_bufs(UV_FS_O_FILEMAP); MAKE_VALGRIND_HAPPY(); return 0; } -TEST_IMPL(fs_write_alotof_bufs) { +static void fs_write_alotof_bufs(int add_flags) { size_t iovcount; size_t iovmax; uv_buf_t* iovs; @@ -2947,7 +3009,7 @@ TEST_IMPL(fs_write_alotof_bufs) { r = uv_fs_open(NULL, &open_req1, "test_file", - O_RDWR | O_CREAT, + O_RDWR | O_CREAT | add_flags, S_IWUSR | S_IRUSR, NULL); ASSERT(r >= 0); @@ -2976,7 +3038,17 @@ TEST_IMPL(fs_write_alotof_bufs) { iovs[index] = uv_buf_init(buffer + index * sizeof(test_buf), sizeof(test_buf)); - ASSERT(lseek(open_req1.result, 0, SEEK_SET) == 0); + r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); + ASSERT(r == 0); + ASSERT(close_req.result == 0); + uv_fs_req_cleanup(&close_req); + + r = uv_fs_open(NULL, &open_req1, "test_file", O_RDONLY | add_flags, 0, + NULL); + ASSERT(r >= 0); + ASSERT(open_req1.result >= 0); + uv_fs_req_cleanup(&open_req1); + r = uv_fs_read(NULL, &read_req, open_req1.result, iovs, iovcount, -1, NULL); if (iovcount > iovmax) iovcount = iovmax; @@ -3012,13 +3084,17 @@ TEST_IMPL(fs_write_alotof_bufs) { /* Cleanup */ unlink("test_file"); free(iovs); +} +TEST_IMPL(fs_write_alotof_bufs) { + fs_write_alotof_bufs(0); + fs_write_alotof_bufs(UV_FS_O_FILEMAP); MAKE_VALGRIND_HAPPY(); return 0; } -TEST_IMPL(fs_write_alotof_bufs_with_offset) { +static void fs_write_alotof_bufs_with_offset(int add_flags) { size_t iovcount; size_t iovmax; uv_buf_t* iovs; @@ -3045,7 +3121,7 @@ TEST_IMPL(fs_write_alotof_bufs_with_offset) { r = uv_fs_open(NULL, &open_req1, "test_file", - O_RDWR | O_CREAT, + O_RDWR | O_CREAT | add_flags, S_IWUSR | S_IRUSR, NULL); ASSERT(r >= 0); @@ -3124,6 +3200,10 @@ TEST_IMPL(fs_write_alotof_bufs_with_offset) { /* Cleanup */ unlink("test_file"); free(iovs); +} +TEST_IMPL(fs_write_alotof_bufs_with_offset) { + fs_write_alotof_bufs_with_offset(0); + fs_write_alotof_bufs_with_offset(UV_FS_O_FILEMAP); MAKE_VALGRIND_HAPPY(); return 0; @@ -3539,6 +3619,146 @@ TEST_IMPL(fs_file_pos_after_op_with_offset) { return 0; } +#ifdef _WIN32 +static void fs_file_pos_common() { + int r; + + iov = uv_buf_init("abc", 3); + r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, -1, NULL); + ASSERT(r == 3); + uv_fs_req_cleanup(&write_req); + + /* Read with offset should not change the position */ + iov = uv_buf_init(buf, 1); + r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, 1, NULL); + ASSERT(r == 1); + ASSERT(buf[0] == 'b'); + uv_fs_req_cleanup(&read_req); + + iov = uv_buf_init(buf, sizeof(buf)); + r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL); + ASSERT(r == 0); + uv_fs_req_cleanup(&read_req); + + /* Write without offset should change the position */ + iov = uv_buf_init("d", 1); + r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, -1, NULL); + ASSERT(r == 1); + uv_fs_req_cleanup(&write_req); + + iov = uv_buf_init(buf, sizeof(buf)); + r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL); + ASSERT(r == 0); + uv_fs_req_cleanup(&read_req); +} + +static void fs_file_pos_close_check(const char *contents, int size) { + int r; + + /* Close */ + r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); + ASSERT(r == 0); + uv_fs_req_cleanup(&close_req); + + /* Confirm file contents */ + r = uv_fs_open(NULL, &open_req1, "test_file", O_RDONLY, 0, NULL); + ASSERT(r >= 0); + ASSERT(open_req1.result >= 0); + uv_fs_req_cleanup(&open_req1); + + iov = uv_buf_init(buf, sizeof(buf)); + r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL); + ASSERT(r == size); + ASSERT(strncmp(buf, contents, size) == 0); + uv_fs_req_cleanup(&read_req); + + r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); + ASSERT(r == 0); + uv_fs_req_cleanup(&close_req); + + /* Cleanup */ + unlink("test_file"); +} + +static void fs_file_pos_write(int add_flags) { + int r; + + /* Setup. */ + unlink("test_file"); + + r = uv_fs_open(NULL, + &open_req1, + "test_file", + O_TRUNC | O_CREAT | O_RDWR | add_flags, + S_IWUSR | S_IRUSR, + NULL); + ASSERT(r > 0); + uv_fs_req_cleanup(&open_req1); + + fs_file_pos_common(); + + /* Write with offset should not change the position */ + iov = uv_buf_init("e", 1); + r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, 1, NULL); + ASSERT(r == 1); + uv_fs_req_cleanup(&write_req); + + iov = uv_buf_init(buf, sizeof(buf)); + r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL); + ASSERT(r == 0); + uv_fs_req_cleanup(&read_req); + + fs_file_pos_close_check("aecd", 4); +} +TEST_IMPL(fs_file_pos_write) { + fs_file_pos_write(0); + fs_file_pos_write(UV_FS_O_FILEMAP); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + +static void fs_file_pos_append(int add_flags) { + int r; + + /* Setup. */ + unlink("test_file"); + + r = uv_fs_open(NULL, + &open_req1, + "test_file", + O_APPEND | O_CREAT | O_RDWR | add_flags, + S_IWUSR | S_IRUSR, + NULL); + ASSERT(r > 0); + uv_fs_req_cleanup(&open_req1); + + fs_file_pos_common(); + + /* Write with offset appends (ignoring offset) + * but does not change the position */ + iov = uv_buf_init("e", 1); + r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, 1, NULL); + ASSERT(r == 1); + uv_fs_req_cleanup(&write_req); + + iov = uv_buf_init(buf, sizeof(buf)); + r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL); + ASSERT(r == 1); + ASSERT(buf[0] == 'e'); + uv_fs_req_cleanup(&read_req); + + fs_file_pos_close_check("abcde", 5); +} +TEST_IMPL(fs_file_pos_append) { + fs_file_pos_append(0); + fs_file_pos_append(UV_FS_O_FILEMAP); + + MAKE_VALGRIND_HAPPY(); + return 0; +} +#endif + TEST_IMPL(fs_null_req) { /* Verify that all fs functions return UV_EINVAL when the request is NULL. */ int r; @@ -3630,6 +3850,9 @@ TEST_IMPL(fs_null_req) { r = uv_fs_futime(NULL, NULL, 0, 0.0, 0.0, NULL); ASSERT(r == UV_EINVAL); + r = uv_fs_statfs(NULL, NULL, NULL, NULL); + ASSERT(r == UV_EINVAL); + /* This should be a no-op. */ uv_fs_req_cleanup(NULL); @@ -3873,4 +4096,37 @@ TEST_IMPL(fs_fchmod_archive_readonly) { return 0; } + +TEST_IMPL(fs_invalid_mkdir_name) { + uv_loop_t* loop; + uv_fs_t req; + int r; + + loop = uv_default_loop(); + r = uv_fs_mkdir(loop, &req, "invalid>", 0, NULL); + ASSERT(r == UV_EINVAL); + + return 0; +} #endif + +TEST_IMPL(fs_statfs) { + uv_fs_t req; + int r; + + loop = uv_default_loop(); + + /* Test the synchronous version. */ + r = uv_fs_statfs(NULL, &req, ".", NULL); + ASSERT(r == 0); + statfs_cb(&req); + ASSERT(statfs_cb_count == 1); + + /* Test the asynchronous version. */ + r = uv_fs_statfs(loop, &req, ".", statfs_cb); + ASSERT(r == 0); + uv_run(loop, UV_RUN_DEFAULT); + ASSERT(statfs_cb_count == 2); + + return 0; +} diff --git a/deps/uv/test/test-ipc.c b/deps/uv/test/test-ipc.c index 24c067e0a4b9..8579a470292d 100644 --- a/deps/uv/test/test-ipc.c +++ b/deps/uv/test/test-ipc.c @@ -838,10 +838,10 @@ static unsigned int write_until_data_queued() { closed_handle_large_write_cb); ASSERT(r == 0); i++; - } while (((uv_stream_t*)&channel)->write_queue_size == 0 && + } while (channel.write_queue_size == 0 && i < ARRAY_SIZE(write_reqs)); - return ((uv_stream_t*)&channel)->write_queue_size; + return channel.write_queue_size; } static void send_handle_and_close() { diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index a48f6f380680..6eb8ecadc787 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -264,6 +264,7 @@ TEST_DECLARE (spawn_fails) #ifndef _WIN32 TEST_DECLARE (spawn_fails_check_for_waitpid_cleanup) #endif +TEST_DECLARE (spawn_empty_env) TEST_DECLARE (spawn_exit_code) TEST_DECLARE (spawn_stdout) TEST_DECLARE (spawn_stdin) @@ -321,10 +322,15 @@ TEST_DECLARE (fs_symlink_dir) #ifdef _WIN32 TEST_DECLARE (fs_symlink_junction) TEST_DECLARE (fs_non_symlink_reparse_point) +TEST_DECLARE (fs_open_flags) +#endif +#if defined(_WIN32) && !defined(USING_UV_SHARED) +TEST_DECLARE (fs_fd_hash) #endif TEST_DECLARE (fs_utime) TEST_DECLARE (fs_futime) TEST_DECLARE (fs_file_open_append) +TEST_DECLARE (fs_statfs) TEST_DECLARE (fs_stat_missing_path) TEST_DECLARE (fs_read_bufs) TEST_DECLARE (fs_read_file_eof) @@ -370,10 +376,13 @@ TEST_DECLARE (fs_file_pos_after_op_with_offset) TEST_DECLARE (fs_null_req) TEST_DECLARE (fs_read_dir) #ifdef _WIN32 +TEST_DECLARE (fs_file_pos_write) +TEST_DECLARE (fs_file_pos_append) TEST_DECLARE (fs_exclusive_sharing_mode) TEST_DECLARE (fs_file_flag_no_buffering) TEST_DECLARE (fs_open_readonly_acl) TEST_DECLARE (fs_fchmod_archive_readonly) +TEST_DECLARE (fs_invalid_mkdir_name) #endif TEST_DECLARE (strscpy) TEST_DECLARE (threadpool_queue_work_simple) @@ -821,6 +830,7 @@ TASK_LIST_START #ifndef _WIN32 TEST_ENTRY (spawn_fails_check_for_waitpid_cleanup) #endif + TEST_ENTRY (spawn_empty_env) TEST_ENTRY (spawn_exit_code) TEST_ENTRY (spawn_stdout) TEST_ENTRY (spawn_stdin) @@ -912,7 +922,12 @@ TASK_LIST_START #ifdef _WIN32 TEST_ENTRY (fs_symlink_junction) TEST_ENTRY (fs_non_symlink_reparse_point) + TEST_ENTRY (fs_open_flags) +#endif +#if defined(_WIN32) && !defined(USING_UV_SHARED) + TEST_ENTRY (fs_fd_hash) #endif + TEST_ENTRY (fs_statfs) TEST_ENTRY (fs_stat_missing_path) TEST_ENTRY (fs_read_bufs) TEST_ENTRY (fs_read_file_eof) @@ -957,10 +972,13 @@ TASK_LIST_START TEST_ENTRY (fs_null_req) TEST_ENTRY (fs_read_dir) #ifdef _WIN32 + TEST_ENTRY (fs_file_pos_write) + TEST_ENTRY (fs_file_pos_append) TEST_ENTRY (fs_exclusive_sharing_mode) TEST_ENTRY (fs_file_flag_no_buffering) TEST_ENTRY (fs_open_readonly_acl) TEST_ENTRY (fs_fchmod_archive_readonly) + TEST_ENTRY (fs_invalid_mkdir_name) #endif TEST_ENTRY (get_osfhandle_valid_handle) TEST_ENTRY (open_osfhandle_valid_handle) diff --git a/deps/uv/test/test-pipe-getsockname.c b/deps/uv/test/test-pipe-getsockname.c index d1628a67d5d0..48ee400e74cf 100644 --- a/deps/uv/test/test-pipe-getsockname.c +++ b/deps/uv/test/test-pipe-getsockname.c @@ -171,7 +171,7 @@ TEST_IMPL(pipe_getsockname_abstract) { socklen_t sun_len; char abstract_pipe[] = "\0test-pipe"; - sock = socket(AF_LOCAL, SOCK_STREAM, 0); + sock = socket(AF_UNIX, SOCK_STREAM, 0); ASSERT(sock != -1); sun_len = sizeof sun; diff --git a/deps/uv/test/test-process-title-threadsafe.c b/deps/uv/test/test-process-title-threadsafe.c index 19098eda0c40..5b30f17f44d5 100644 --- a/deps/uv/test/test-process-title-threadsafe.c +++ b/deps/uv/test/test-process-title-threadsafe.c @@ -25,7 +25,11 @@ #include -#define NUM_ITERATIONS 50 +#ifdef __APPLE__ +# define NUM_ITERATIONS 10 +#else +# define NUM_ITERATIONS 50 +#endif static const char* titles[] = { "8L2NY0Kdj0XyNFZnmUZigIOfcWjyNr0SkMmUhKw99VLUsZFrvCQQC3XIRfNR8pjyMjXObllled", diff --git a/deps/uv/test/test-queue-foreach-delete.c b/deps/uv/test/test-queue-foreach-delete.c index 45da225381f5..049ea776e343 100644 --- a/deps/uv/test/test-queue-foreach-delete.c +++ b/deps/uv/test/test-queue-foreach-delete.c @@ -65,11 +65,11 @@ static const unsigned first_handle_number_fs_event = 0; #endif -#define DEFINE_GLOBALS_AND_CBS(name) \ +#define DEFINE_GLOBALS_AND_CBS(name, ...) \ static uv_##name##_t (name)[3]; \ static unsigned name##_cb_calls[3]; \ \ - static void name##2_cb(uv_##name##_t* handle) { \ + static void name##2_cb(__VA_ARGS__) { \ ASSERT(handle == &(name)[2]); \ if (first_handle_number_##name == 2) { \ uv_close((uv_handle_t*)&(name)[2], NULL); \ @@ -78,12 +78,12 @@ static const unsigned first_handle_number_fs_event = 0; name##_cb_calls[2]++; \ } \ \ - static void name##1_cb(uv_##name##_t* handle) { \ + static void name##1_cb(__VA_ARGS__) { \ ASSERT(handle == &(name)[1]); \ ASSERT(0 && "Shouldn't be called" && (&name[0])); \ } \ \ - static void name##0_cb(uv_##name##_t* handle) { \ + static void name##0_cb(__VA_ARGS__) { \ ASSERT(handle == &(name)[0]); \ if (first_handle_number_##name == 0) { \ uv_close((uv_handle_t*)&(name)[0], NULL); \ @@ -93,9 +93,9 @@ static const unsigned first_handle_number_fs_event = 0; } \ \ static const uv_##name##_cb name##_cbs[] = { \ - (uv_##name##_cb)name##0_cb, \ - (uv_##name##_cb)name##1_cb, \ - (uv_##name##_cb)name##2_cb, \ + name##0_cb, \ + name##1_cb, \ + name##2_cb, \ }; #define INIT_AND_START(name, loop) \ @@ -118,12 +118,16 @@ static const unsigned first_handle_number_fs_event = 0; ASSERT(name##_cb_calls[2] == 1); \ } while (0) -DEFINE_GLOBALS_AND_CBS(idle) -DEFINE_GLOBALS_AND_CBS(prepare) -DEFINE_GLOBALS_AND_CBS(check) +DEFINE_GLOBALS_AND_CBS(idle, uv_idle_t* handle) +DEFINE_GLOBALS_AND_CBS(prepare, uv_prepare_t* handle) +DEFINE_GLOBALS_AND_CBS(check, uv_check_t* handle) #ifdef __linux__ -DEFINE_GLOBALS_AND_CBS(fs_event) +DEFINE_GLOBALS_AND_CBS(fs_event, + uv_fs_event_t* handle, + const char* filename, + int events, + int status) static const char watched_dir[] = "."; static uv_timer_t timer; diff --git a/deps/uv/test/test-spawn.c b/deps/uv/test/test-spawn.c index fea1165d89e0..fec610bfdef9 100644 --- a/deps/uv/test/test-spawn.c +++ b/deps/uv/test/test-spawn.c @@ -232,6 +232,34 @@ TEST_IMPL(spawn_fails_check_for_waitpid_cleanup) { #endif +TEST_IMPL(spawn_empty_env) { + char* env[1]; + + /* The autotools dynamic library build requires the presence of + * DYLD_LIBARY_PATH (macOS) or LD_LIBRARY_PATH (other Unices) + * in the environment, but of course that doesn't work with + * the empty environment that we're testing here. + */ + if (NULL != getenv("DYLD_LIBARY_PATH") || + NULL != getenv("LD_LIBRARY_PATH")) { + RETURN_SKIP("doesn't work with DYLD_LIBRARY_PATH/LD_LIBRARY_PATH"); + } + + init_process_options("spawn_helper1", exit_cb); + options.env = env; + env[0] = NULL; + + ASSERT(0 == uv_spawn(uv_default_loop(), &process, &options)); + ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); + + ASSERT(exit_cb_called == 1); + ASSERT(close_cb_called == 1); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + TEST_IMPL(spawn_exit_code) { int r; diff --git a/deps/uv/test/test-tmpdir.c b/deps/uv/test/test-tmpdir.c index 29e8055f1d5d..dac488d05804 100644 --- a/deps/uv/test/test-tmpdir.c +++ b/deps/uv/test/test-tmpdir.c @@ -67,5 +67,16 @@ TEST_IMPL(tmpdir) { r = uv_os_tmpdir(tmpdir, &len); ASSERT(r == UV_EINVAL); +#ifdef _WIN32 + const char *name = "TMP"; + char tmpdir_win[] = "C:\\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; + r = uv_os_setenv(name, tmpdir_win); + ASSERT(r == 0); + char tmpdirx[PATHMAX]; + size_t lenx = sizeof tmpdirx; + r = uv_os_tmpdir(tmpdirx, &lenx); + ASSERT(r == 0); +#endif + return 0; } diff --git a/deps/uv/test/test.gyp b/deps/uv/test/test.gyp index a4083e917834..6158a2b8b660 100644 --- a/deps/uv/test/test.gyp +++ b/deps/uv/test/test.gyp @@ -35,6 +35,8 @@ 'test-fs-readdir.c', 'test-fs-copyfile.c', 'test-fs-event.c', + 'test-fs-fd-hash.c', + 'test-fs-open-flags.c', 'test-fs-poll.c', 'test-getters-setters.c', 'test-get-currentexe.c', From 2035c679a92f13c9eee0674cf38c3f4784afcbc8 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Mon, 9 Sep 2019 13:08:37 -0400 Subject: [PATCH 5/9] deps: upgrade to libuv 1.32.0 Notable changes: - `uv_tcp_close_reset()` has been added. - `uv_udp_set_source_membership()` has been added. - A double free in `uv_free_cpu_info()` on OpenBSD has been fixed. - Defined, but empty environment variables can now be read on Windows. - Several improvements to the cmake build process. - The `EILSEQ` error code is now mapped by libuv. PR-URL: https://github.com/nodejs/node/pull/29508 Reviewed-By: Trivikram Kamat Reviewed-By: Jiawen Geng Reviewed-By: Ben Noordhuis Reviewed-By: David Carlier Reviewed-By: Anna Henningsen Reviewed-By: Beth Griggs Reviewed-By: James M Snell --- deps/uv/AUTHORS | 7 + deps/uv/CMakeLists.txt | 19 +- deps/uv/ChangeLog | 75 +++++ deps/uv/Makefile.am | 3 + deps/uv/README.md | 2 + deps/uv/configure.ac | 2 +- deps/uv/docs/src/handle.rst | 5 +- deps/uv/docs/src/signal.rst | 11 + deps/uv/docs/src/stream.rst | 4 +- deps/uv/docs/src/tcp.rst | 10 + deps/uv/docs/src/udp.rst | 30 +- deps/uv/include/uv.h | 11 + deps/uv/include/uv/errno.h | 5 + deps/uv/include/uv/unix.h | 16 +- deps/uv/include/uv/version.h | 2 +- deps/uv/src/timer.c | 2 +- deps/uv/src/unix/aix-common.c | 10 - deps/uv/src/unix/atomic-ops.h | 4 - deps/uv/src/unix/core.c | 45 ++- deps/uv/src/unix/cygwin.c | 5 - deps/uv/src/unix/darwin.c | 11 - deps/uv/src/unix/freebsd.c | 11 - deps/uv/src/unix/fs.c | 17 +- deps/uv/src/unix/haiku.c | 9 - deps/uv/src/unix/linux-core.c | 10 - deps/uv/src/unix/netbsd.c | 11 - deps/uv/src/unix/openbsd.c | 29 +- deps/uv/src/unix/os390.c | 7 - deps/uv/src/unix/signal.c | 11 +- deps/uv/src/unix/stream.c | 8 +- deps/uv/src/unix/sunos.c | 10 - deps/uv/src/unix/tcp.c | 17 ++ deps/uv/src/unix/udp.c | 137 +++++++++ deps/uv/src/uv-common.c | 10 + deps/uv/src/win/error.c | 1 + deps/uv/src/win/stream.c | 7 +- deps/uv/src/win/tcp.c | 15 + deps/uv/src/win/tty.c | 44 ++- deps/uv/src/win/udp.c | 150 ++++++++++ deps/uv/src/win/util.c | 21 +- deps/uv/src/win/winapi.h | 2 +- deps/uv/test/test-env-vars.c | 9 + deps/uv/test/test-fs.c | 2 +- deps/uv/test/test-list.h | 12 + deps/uv/test/test-signal-pending-on-close.c | 94 +++++++ deps/uv/test/test-spawn.c | 2 +- deps/uv/test/test-tcp-bind-error.c | 4 - deps/uv/test/test-tcp-close-reset.c | 290 ++++++++++++++++++++ deps/uv/test/test-timer.c | 13 + deps/uv/test/test-udp-multicast-join.c | 74 +++-- deps/uv/test/test-udp-multicast-join6.c | 118 +++++--- deps/uv/test/test.gyp | 2 + deps/uv/uv.gyp | 1 + 53 files changed, 1176 insertions(+), 251 deletions(-) create mode 100644 deps/uv/test/test-signal-pending-on-close.c create mode 100644 deps/uv/test/test-tcp-close-reset.c diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS index 5d5866d3ff24..8c3d342d33e6 100644 --- a/deps/uv/AUTHORS +++ b/deps/uv/AUTHORS @@ -396,3 +396,10 @@ Nan Xiao Ben Davies Nhan Khong Crunkle +Tomas Krizek +Konstantin Podsvirov +seny +Vladimir Karnushin +MaYuming +Eneas U de Queiroz +Daniel Hahler diff --git a/deps/uv/CMakeLists.txt b/deps/uv/CMakeLists.txt index bf7990f745fe..6f18f3397d01 100644 --- a/deps/uv/CMakeLists.txt +++ b/deps/uv/CMakeLists.txt @@ -1,5 +1,5 @@ # TODO: determine CMAKE_SYSTEM_NAME on OS/390. Currently assumes "OS/390". -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 2.8.12) project(libuv) if(MSVC) @@ -116,6 +116,7 @@ set(uv_test_sources test/test-shutdown-eof.c test/test-shutdown-twice.c test/test-signal-multiple-loops.c + test/test-signal-pending-on-close.c test/test-signal.c test/test-socket-buffer-size.c test/test-spawn.c @@ -127,6 +128,7 @@ set(uv_test_sources test/test-tcp-close-accept.c test/test-tcp-close-while-connecting.c test/test-tcp-close.c + test/test-tcp-close-reset.c test/test-tcp-connect-error-after-write.c test/test-tcp-connect-error.c test/test-tcp-connect-timeout.c @@ -317,6 +319,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "OS/390") list(APPEND uv_defines _OPEN_MSGQ_EXT) list(APPEND uv_defines _OPEN_SYS_FILE_EXT) list(APPEND uv_defines _OPEN_SYS_IF_EXT) + list(APPEND uv_defines _OPEN_SYS_SOCK_EXT3) list(APPEND uv_defines _OPEN_SYS_SOCK_IPV6) list(APPEND uv_defines _UNIX03_SOURCE) list(APPEND uv_defines _UNIX03_THREADS) @@ -340,15 +343,17 @@ if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD|Linux|NetBSD|OpenBSD") endif() add_library(uv SHARED ${uv_sources}) -target_compile_definitions(uv PRIVATE ${uv_defines} BUILDING_UV_SHARED=1) +target_compile_definitions(uv + INTERFACE USING_UV_SHARED=1 + PRIVATE ${uv_defines} BUILDING_UV_SHARED=1) target_compile_options(uv PRIVATE ${uv_cflags}) -target_include_directories(uv PRIVATE include src) +target_include_directories(uv PUBLIC include PRIVATE src) target_link_libraries(uv ${uv_libraries}) add_library(uv_a STATIC ${uv_sources}) target_compile_definitions(uv_a PRIVATE ${uv_defines}) target_compile_options(uv_a PRIVATE ${uv_cflags}) -target_include_directories(uv_a PRIVATE include src) +target_include_directories(uv_a PUBLIC include PRIVATE src) target_link_libraries(uv_a ${uv_libraries}) option(libuv_buildtests "Build the unit tests when BUILD_TESTING is enabled." ON) @@ -360,7 +365,6 @@ if(BUILD_TESTING AND libuv_buildtests) target_compile_definitions(uv_run_tests PRIVATE ${uv_defines} USING_UV_SHARED=1) target_compile_options(uv_run_tests PRIVATE ${uv_cflags}) - target_include_directories(uv_run_tests PRIVATE include) target_link_libraries(uv_run_tests uv ${uv_test_libraries}) add_test(NAME uv_test COMMAND uv_run_tests @@ -368,7 +372,6 @@ if(BUILD_TESTING AND libuv_buildtests) add_executable(uv_run_tests_a ${uv_test_sources}) target_compile_definitions(uv_run_tests_a PRIVATE ${uv_defines}) target_compile_options(uv_run_tests_a PRIVATE ${uv_cflags}) - target_include_directories(uv_run_tests_a PRIVATE include) target_link_libraries(uv_run_tests_a uv_a ${uv_test_libraries}) add_test(NAME uv_test_a COMMAND uv_run_tests_a @@ -383,6 +386,10 @@ if(UNIX) endforeach(x) file(STRINGS configure.ac configure_ac REGEX ^AC_INIT) string(REGEX MATCH [0-9]+[.][0-9]+[.][0-9]+ PACKAGE_VERSION "${configure_ac}") + string(REGEX MATCH ^[0-9]+ UV_VERSION_MAJOR "${PACKAGE_VERSION}") + # The version in the filename is mirroring the behaviour of autotools. + set_target_properties(uv PROPERTIES VERSION ${UV_VERSION_MAJOR}.0.0 + SOVERSION ${UV_VERSION_MAJOR}) set(includedir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}) set(libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}) set(prefix ${CMAKE_INSTALL_PREFIX}) diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index d440b5507719..093579de8e49 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,3 +1,78 @@ +2019.09.10, Version 1.32.0 (Stable), 697bea87b3a0b0e9b4e5ff86b39d1dedb70ee46d + +Changes since version 1.31.0: + +* misc: enable stalebot (Saúl Ibarra Corretgé) + +* win: map ERROR_ENVVAR_NOT_FOUND to UV_ENOENT (cjihrig) + +* win: use L'\0' as UTF-16 null terminator (cjihrig) + +* win: support retrieving empty env variables (cjihrig) + +* unix,stream: fix returned error codes (Santiago Gimeno) + +* test: fix typo in DYLD_LIBRARY_PATH (Ben Noordhuis) + +* unix,signal: keep handle active if pending signal (Santiago Gimeno) + +* openbsd: fix uv_cpu_info (Santiago Gimeno) + +* src: move uv_free_cpu_info to uv-common.c (Santiago Gimeno) + +* tcp: add uv_tcp_close_reset method (Santiago Gimeno) + +* test: fix udp-multicast-join tests (Santiago Gimeno) + +* test: remove assertion in fs_statfs test (cjihrig) + +* doc: clarify uv_buf_t usage in uv_alloc_cb (Tomas Krizek) + +* win: fix typo in preprocessor expression (Konstantin Podsvirov) + +* timer: fix uv_timer_start on closing timer (seny) + +* udp: add source-specific multicast support (Vladimir Karnushin) + +* udp: fix error return values (Santiago Gimeno) + +* udp: drop IPV6_SSM_SUPPORT macro (Santiago Gimeno) + +* udp: fix uv__udp_set_source_membership6 (Santiago Gimeno) + +* udp: use sockaddr_storage instead of union (Santiago Gimeno) + +* build,zos: add _OPEN_SYS_SOCK_EXT3 flag (Santiago Gimeno) + +* test: add specific source multicast tests (Santiago Gimeno) + +* include: map EILSEQ error code (cjihrig) + +* win, tty: improve SIGWINCH performance (Bartosz Sosnowski) + +* build: fix ios build error (MaYuming) + +* aix: replace ECONNRESET with EOF if already closed (Milad Farazmand) + +* build: add cmake library VERSION, SOVERSION (Eneas U de Queiroz) + +* build: make include/ public in CMakeLists.txt (Ben Noordhuis) + +* build: export USING_UV_SHARED=1 to cmake deps (Ben Noordhuis) + +* build: cmake_minimum_required(VERSION 2.8.12) (Daniel Hahler) + +* aix: Fix broken cmpxchgi() XL C++ specialization. (Andrew Paprocki) + +* test: fix -Wsign-compare warning (Ben Noordhuis) + +* unix: simplify open(O_CLOEXEC) feature detection (Ben Noordhuis) + +* unix: fix UV_FS_O_DIRECT definition on Linux (Joran Dirk Greef) + +* doc: uv_handle_t documentation suggestion (Daniel Bevenius) + + 2019.08.10, Version 1.31.0 (Stable), 0a6771cee4c15184c924bfe9d397bdd0c3b206ba Changes since version 1.30.1: diff --git a/deps/uv/Makefile.am b/deps/uv/Makefile.am index 6b11c9349ce9..099b0efb0843 100644 --- a/deps/uv/Makefile.am +++ b/deps/uv/Makefile.am @@ -248,6 +248,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/test-shutdown-eof.c \ test/test-shutdown-twice.c \ test/test-signal-multiple-loops.c \ + test/test-signal-pending-on-close.c \ test/test-signal.c \ test/test-socket-buffer-size.c \ test/test-spawn.c \ @@ -259,6 +260,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/test-tcp-close-accept.c \ test/test-tcp-close-while-connecting.c \ test/test-tcp-close.c \ + test/test-tcp-close-reset.c \ test/test-tcp-create-socket-early.c \ test/test-tcp-connect-error-after-write.c \ test/test-tcp-connect-error.c \ @@ -517,6 +519,7 @@ libuv_la_CFLAGS += -D_UNIX03_THREADS \ -D_XOPEN_SOURCE_EXTENDED \ -D_ALL_SOURCE \ -D_LARGE_TIME_API \ + -D_OPEN_SYS_SOCK_EXT3 \ -D_OPEN_SYS_SOCK_IPV6 \ -D_OPEN_SYS_FILE_EXT \ -DUV_PLATFORM_SEM_T=int \ diff --git a/deps/uv/README.md b/deps/uv/README.md index b55c3a9238a1..f9daaa1cea15 100644 --- a/deps/uv/README.md +++ b/deps/uv/README.md @@ -401,6 +401,8 @@ Check the [SUPPORTED_PLATFORMS file](SUPPORTED_PLATFORMS.md). ### AIX Notes +AIX compilation using IBM XL C/C++ requires version 12.1 or greater. + AIX support for filesystem events requires the non-default IBM `bos.ahafs` package to be installed. This package provides the AIX Event Infrastructure that is detected by `autoconf`. diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac index c5e29fef849e..b503e538298d 100644 --- a/deps/uv/configure.ac +++ b/deps/uv/configure.ac @@ -13,7 +13,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. AC_PREREQ(2.57) -AC_INIT([libuv], [1.31.0], [https://github.com/libuv/libuv/issues]) +AC_INIT([libuv], [1.32.0], [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]) diff --git a/deps/uv/docs/src/handle.rst b/deps/uv/docs/src/handle.rst index 544794db06c9..0a25bfa8b27d 100644 --- a/deps/uv/docs/src/handle.rst +++ b/deps/uv/docs/src/handle.rst @@ -60,6 +60,9 @@ Data types a ``UV_ENOBUFS`` error will be triggered in the :c:type:`uv_udp_recv_cb` or the :c:type:`uv_read_cb` callback. + Each buffer is used only once and the user is responsible for freeing it in the + :c:type:`uv_udp_recv_cb` or the :c:type:`uv_read_cb` callback. + A suggested size (65536 at the moment in most cases) is provided, but it's just an indication, not related in any way to the pending data to be read. The user is free to allocate the amount of memory they decide. @@ -87,7 +90,7 @@ Public members .. c:member:: uv_loop_t* uv_handle_t.loop - Pointer to the :c:type:`uv_loop_t` where the handle is running on. Readonly. + Pointer to the :c:type:`uv_loop_t` the handle is running on. Readonly. .. c:member:: uv_handle_type uv_handle_t.type diff --git a/deps/uv/docs/src/signal.rst b/deps/uv/docs/src/signal.rst index f5a809ab0bb7..eeadb95b0a47 100644 --- a/deps/uv/docs/src/signal.rst +++ b/deps/uv/docs/src/signal.rst @@ -20,6 +20,15 @@ Reception of some signals is emulated: program is given approximately 10 seconds to perform cleanup. After that Windows will unconditionally terminate it. +* SIGWINCH is raised whenever libuv detects that the console has been + resized. When a libuv app is running under a console emulator, or when a + 32-bit libuv app is running on 64-bit system, SIGWINCH will be emulated. In + such cases SIGWINCH signals may not always be delivered in a timely manner. + For a writable :c:type:`uv_tty_t` handle libuv will only detect size changes + when the cursor is moved. When a readable :c:type:`uv_tty_t` handle is used, + resizing of the console buffer will be detected only if the handle is in raw + mode and is being read. + * Watchers for other signals can be successfully created, but these signals are never received. These signals are: `SIGILL`, `SIGABRT`, `SIGFPE`, `SIGSEGV`, `SIGTERM` and `SIGKILL.` @@ -28,6 +37,8 @@ Reception of some signals is emulated: not detected by libuv; these will not trigger a signal watcher. .. versionchanged:: 1.15.0 SIGWINCH support on Windows was improved. +.. versionchanged:: 1.31.0 32-bit libuv SIGWINCH support on 64-bit Windows was + rolled back to old implementation. Unix notes ---------- diff --git a/deps/uv/docs/src/stream.rst b/deps/uv/docs/src/stream.rst index 6a704367b1b3..2ccb59b51cb4 100644 --- a/deps/uv/docs/src/stream.rst +++ b/deps/uv/docs/src/stream.rst @@ -50,8 +50,8 @@ Data types from the stream again is undefined. The callee is responsible for freeing the buffer, libuv does not reuse it. - The buffer may be a null buffer (where buf->base=NULL and buf->len=0) on - error. + The buffer may be a null buffer (where `buf->base` == NULL and `buf->len` == 0) + on error. .. c:type:: void (*uv_write_cb)(uv_write_t* req, int status) diff --git a/deps/uv/docs/src/tcp.rst b/deps/uv/docs/src/tcp.rst index d20a6362af94..bcb163ea0f03 100644 --- a/deps/uv/docs/src/tcp.rst +++ b/deps/uv/docs/src/tcp.rst @@ -113,3 +113,13 @@ API mapping .. seealso:: The :c:type:`uv_stream_t` API functions also apply. + +.. c:function:: int uv_tcp_close_reset(uv_tcp_t* handle, uv_close_cb close_cb) + + Resets a TCP connection by sending a RST packet. This is accomplished by + setting the `SO_LINGER` socket option with a linger interval of zero and + then calling :c:func:`uv_close`. + Due to some platform inconsistencies, mixing of :c:func:`uv_shutdown` and + :c:func:`uv_tcp_close_reset` calls is not allowed. + + .. versionadded:: 1.32.0 diff --git a/deps/uv/docs/src/udp.rst b/deps/uv/docs/src/udp.rst index f3de53fbab05..53b1fea4933a 100644 --- a/deps/uv/docs/src/udp.rst +++ b/deps/uv/docs/src/udp.rst @@ -56,16 +56,19 @@ Data types * `handle`: UDP handle * `nread`: Number of bytes that have been received. - 0 if there is no more data to read. You may discard or repurpose - the read buffer. Note that 0 may also mean that an empty datagram - was received (in this case `addr` is not NULL). < 0 if a transmission - error was detected. + 0 if there is no more data to read. Note that 0 may also mean that an + empty datagram was received (in this case `addr` is not NULL). < 0 if + a transmission error was detected. * `buf`: :c:type:`uv_buf_t` with the received data. * `addr`: ``struct sockaddr*`` containing the address of the sender. Can be NULL. Valid for the duration of the callback only. * `flags`: One or more or'ed UV_UDP_* constants. Right now only ``UV_UDP_PARTIAL`` is used. + The callee is responsible for freeing the buffer, libuv does not reuse it. + The buffer may be a null buffer (where `buf->base` == NULL and `buf->len` == 0) + on error. + .. note:: The receive callback will be called with `nread` == 0 and `addr` == NULL when there is nothing to read, and with `nread` == 0 and `addr` != NULL when an empty UDP packet is @@ -219,6 +222,25 @@ API :returns: 0 on success, or an error code < 0 on failure. +.. c:function:: int uv_udp_set_source_membership(uv_udp_t* handle, const char* multicast_addr, const char* interface_addr, const char* source_addr, uv_membership membership) + + Set membership for a source-specific multicast group. + + :param handle: UDP handle. Should have been initialized with + :c:func:`uv_udp_init`. + + :param multicast_addr: Multicast address to set membership for. + + :param interface_addr: Interface address. + + :param source_addr: Source address. + + :param membership: Should be ``UV_JOIN_GROUP`` or ``UV_LEAVE_GROUP``. + + :returns: 0 on success, or an error code < 0 on failure. + + .. versionadded:: 1.32.0 + .. c:function:: int uv_udp_set_multicast_loop(uv_udp_t* handle, int on) Set IP multicast loop flag. Makes multicast packets loop back to diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index f71767b6e9fa..ee45bcaefce1 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -27,6 +27,10 @@ extern "C" { #endif +#if defined(BUILDING_UV_SHARED) && defined(USING_UV_SHARED) +#error "Define either BUILDING_UV_SHARED or USING_UV_SHARED, not both." +#endif + #ifdef _WIN32 /* Windows - set up dll import/export decorators. */ # if defined(BUILDING_UV_SHARED) @@ -143,6 +147,7 @@ extern "C" { XX(EREMOTEIO, "remote I/O error") \ XX(ENOTTY, "inappropriate ioctl for device") \ XX(EFTYPE, "inappropriate file type or format") \ + XX(EILSEQ, "illegal byte sequence") \ #define UV_HANDLE_TYPE_MAP(XX) \ XX(ASYNC, async) \ @@ -559,6 +564,7 @@ UV_EXTERN int uv_tcp_getsockname(const uv_tcp_t* handle, UV_EXTERN int uv_tcp_getpeername(const uv_tcp_t* handle, struct sockaddr* name, int* namelen); +UV_EXTERN int uv_tcp_close_reset(uv_tcp_t* handle, uv_close_cb close_cb); UV_EXTERN int uv_tcp_connect(uv_connect_t* req, uv_tcp_t* handle, const struct sockaddr* addr, @@ -645,6 +651,11 @@ UV_EXTERN int uv_udp_set_membership(uv_udp_t* handle, const char* multicast_addr, const char* interface_addr, uv_membership membership); +UV_EXTERN int uv_udp_set_source_membership(uv_udp_t* handle, + const char* multicast_addr, + const char* interface_addr, + const char* source_addr, + uv_membership membership); UV_EXTERN int uv_udp_set_multicast_loop(uv_udp_t* handle, int on); UV_EXTERN int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl); UV_EXTERN int uv_udp_set_multicast_interface(uv_udp_t* handle, diff --git a/deps/uv/include/uv/errno.h b/deps/uv/include/uv/errno.h index 8eeb95de31b0..165fd11c376a 100644 --- a/deps/uv/include/uv/errno.h +++ b/deps/uv/include/uv/errno.h @@ -439,5 +439,10 @@ # define UV__EFTYPE (-4028) #endif +#if defined(EILSEQ) && !defined(_WIN32) +# define UV__EILSEQ UV__ERR(EILSEQ) +#else +# define UV__EILSEQ (-4027) +#endif #endif /* UV_ERRNO_H_ */ diff --git a/deps/uv/include/uv/unix.h b/deps/uv/include/uv/unix.h index 9080352d31df..3a131638f776 100644 --- a/deps/uv/include/uv/unix.h +++ b/deps/uv/include/uv/unix.h @@ -405,11 +405,25 @@ typedef struct { #else # define UV_FS_O_CREAT 0 #endif -#if defined(O_DIRECT) + +#if defined(__linux__) && defined(__arm__) +# define UV_FS_O_DIRECT 0x10000 +#elif defined(__linux__) && defined(__m68k__) +# define UV_FS_O_DIRECT 0x10000 +#elif defined(__linux__) && defined(__mips__) +# define UV_FS_O_DIRECT 0x08000 +#elif defined(__linux__) && defined(__powerpc__) +# define UV_FS_O_DIRECT 0x20000 +#elif defined(__linux__) && defined(__s390x__) +# define UV_FS_O_DIRECT 0x04000 +#elif defined(__linux__) && defined(__x86_64__) +# define UV_FS_O_DIRECT 0x04000 +#elif defined(O_DIRECT) # define UV_FS_O_DIRECT O_DIRECT #else # define UV_FS_O_DIRECT 0 #endif + #if defined(O_DIRECTORY) # define UV_FS_O_DIRECTORY O_DIRECTORY #else diff --git a/deps/uv/include/uv/version.h b/deps/uv/include/uv/version.h index 37a6a445b8d0..928647b82005 100644 --- a/deps/uv/include/uv/version.h +++ b/deps/uv/include/uv/version.h @@ -31,7 +31,7 @@ */ #define UV_VERSION_MAJOR 1 -#define UV_VERSION_MINOR 31 +#define UV_VERSION_MINOR 32 #define UV_VERSION_PATCH 0 #define UV_VERSION_IS_RELEASE 1 #define UV_VERSION_SUFFIX "" diff --git a/deps/uv/src/timer.c b/deps/uv/src/timer.c index dd78bcbad9a9..8fce7f6472f9 100644 --- a/deps/uv/src/timer.c +++ b/deps/uv/src/timer.c @@ -74,7 +74,7 @@ int uv_timer_start(uv_timer_t* handle, uint64_t repeat) { uint64_t clamped_timeout; - if (cb == NULL) + if (uv__is_closing(handle) || cb == NULL) return UV_EINVAL; if (uv__is_active(handle)) diff --git a/deps/uv/src/unix/aix-common.c b/deps/uv/src/unix/aix-common.c index 63ac16a03431..b9d313c0c5d7 100644 --- a/deps/uv/src/unix/aix-common.c +++ b/deps/uv/src/unix/aix-common.c @@ -155,16 +155,6 @@ int uv_exepath(char* buffer, size_t* size) { } } -void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { - int i; - - for (i = 0; i < count; ++i) { - uv__free(cpu_infos[i].model); - } - - uv__free(cpu_infos); -} - int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { uv_interface_address_t* address; diff --git a/deps/uv/src/unix/atomic-ops.h b/deps/uv/src/unix/atomic-ops.h index 541a6c864882..bc37c0d45d15 100644 --- a/deps/uv/src/unix/atomic-ops.h +++ b/deps/uv/src/unix/atomic-ops.h @@ -36,10 +36,6 @@ UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) { : "r" (newval), "0" (oldval) : "memory"); return out; -#elif defined(_AIX) && defined(__xlC__) - const int out = (*(volatile int*) ptr); - __compare_and_swap(ptr, &oldval, newval); - return out; #elif defined(__MVS__) unsigned int op4; if (__plo_CSST(ptr, (unsigned int*) &oldval, newval, diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index f4b94e30cc00..366c43c2ab08 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include /* O_CLOEXEC */ #include #include #include @@ -49,17 +49,19 @@ # include #endif -#ifdef __APPLE__ +#if defined(__APPLE__) +# include +# endif /* defined(__APPLE__) */ + + +#if defined(__APPLE__) && !TARGET_OS_IPHONE # include # include /* _NSGetExecutablePath */ -# include -# if defined(O_CLOEXEC) -# define UV__O_CLOEXEC O_CLOEXEC -# endif # define environ (*_NSGetEnviron()) -#else +#else /* defined(__APPLE__) && !TARGET_OS_IPHONE */ extern char** environ; -#endif +#endif /* !(defined(__APPLE__) && !TARGET_OS_IPHONE) */ + #if defined(__DragonFly__) || \ defined(__FreeBSD__) || \ @@ -68,7 +70,6 @@ extern char** environ; # include # include # include -# define UV__O_CLOEXEC O_CLOEXEC # if defined(__FreeBSD__) && __FreeBSD__ >= 10 # define uv__accept4 accept4 # endif @@ -1000,24 +1001,17 @@ int uv_getrusage(uv_rusage_t* rusage) { int uv__open_cloexec(const char* path, int flags) { - int err; +#if defined(O_CLOEXEC) int fd; -#if defined(UV__O_CLOEXEC) - static int no_cloexec; - - if (!no_cloexec) { - fd = open(path, flags | UV__O_CLOEXEC); - if (fd != -1) - return fd; - - if (errno != EINVAL) - return UV__ERR(errno); + fd = open(path, flags | O_CLOEXEC); + if (fd == -1) + return UV__ERR(errno); - /* O_CLOEXEC not supported. */ - no_cloexec = 1; - } -#endif + return fd; +#else /* O_CLOEXEC */ + int err; + int fd; fd = open(path, flags); if (fd == -1) @@ -1030,6 +1024,7 @@ int uv__open_cloexec(const char* path, int flags) { } return fd; +#endif /* O_CLOEXEC */ } @@ -1051,7 +1046,7 @@ int uv__dup2_cloexec(int oldfd, int newfd) { static int no_dup3; if (!no_dup3) { do - r = uv__dup3(oldfd, newfd, UV__O_CLOEXEC); + r = uv__dup3(oldfd, newfd, O_CLOEXEC); while (r == -1 && errno == EBUSY); if (r != -1) return r; diff --git a/deps/uv/src/unix/cygwin.c b/deps/uv/src/unix/cygwin.c index 6b5cfb7ba5b8..169958d55f2e 100644 --- a/deps/uv/src/unix/cygwin.c +++ b/deps/uv/src/unix/cygwin.c @@ -48,11 +48,6 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { return UV_ENOSYS; } -void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { - (void)cpu_infos; - (void)count; -} - uint64_t uv_get_constrained_memory(void) { return 0; /* Memory constraints are unknown. */ } diff --git a/deps/uv/src/unix/darwin.c b/deps/uv/src/unix/darwin.c index e4cd8ff7e0cf..5cf03aea0b40 100644 --- a/deps/uv/src/unix/darwin.c +++ b/deps/uv/src/unix/darwin.c @@ -223,14 +223,3 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { return 0; } - - -void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { - int i; - - for (i = 0; i < count; i++) { - uv__free(cpu_infos[i].model); - } - - uv__free(cpu_infos); -} diff --git a/deps/uv/src/unix/freebsd.c b/deps/uv/src/unix/freebsd.c index 7de88d6a52fa..d0b7d8e9d11f 100644 --- a/deps/uv/src/unix/freebsd.c +++ b/deps/uv/src/unix/freebsd.c @@ -288,14 +288,3 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { uv__free(cp_times); return 0; } - - -void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { - int i; - - for (i = 0; i < count; i++) { - uv__free(cpu_infos[i].model); - } - - uv__free(cpu_infos); -} diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c index fc80d00d5c56..fd3dd4c287e9 100644 --- a/deps/uv/src/unix/fs.c +++ b/deps/uv/src/unix/fs.c @@ -255,20 +255,10 @@ static ssize_t uv__fs_mkdtemp(uv_fs_t* req) { static ssize_t uv__fs_open(uv_fs_t* req) { - static int no_cloexec_support; - int r; - - /* Try O_CLOEXEC before entering locks */ - if (no_cloexec_support == 0) { #ifdef O_CLOEXEC - r = open(req->path, req->flags | O_CLOEXEC, req->mode); - if (r >= 0) - return r; - if (errno != EINVAL) - return r; - no_cloexec_support = 1; -#endif /* O_CLOEXEC */ - } + return open(req->path, req->flags | O_CLOEXEC, req->mode); +#else /* O_CLOEXEC */ + int r; if (req->cb != NULL) uv_rwlock_rdlock(&req->loop->cloexec_lock); @@ -289,6 +279,7 @@ static ssize_t uv__fs_open(uv_fs_t* req) { uv_rwlock_rdunlock(&req->loop->cloexec_lock); return r; +#endif /* O_CLOEXEC */ } diff --git a/deps/uv/src/unix/haiku.c b/deps/uv/src/unix/haiku.c index 7708851c2a5f..cf17d836b4c7 100644 --- a/deps/uv/src/unix/haiku.c +++ b/deps/uv/src/unix/haiku.c @@ -165,12 +165,3 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { return 0; } - -void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { - int i; - - for (i = 0; i < count; i++) - uv__free(cpu_infos[i].model); - - uv__free(cpu_infos); -} diff --git a/deps/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c index b539beb86ae5..433e201fe19d 100644 --- a/deps/uv/src/unix/linux-core.c +++ b/deps/uv/src/unix/linux-core.c @@ -812,16 +812,6 @@ static uint64_t read_cpufreq(unsigned int cpunum) { } -void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { - int i; - - for (i = 0; i < count; i++) { - uv__free(cpu_infos[i].model); - } - - uv__free(cpu_infos); -} - static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) { if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) return 1; diff --git a/deps/uv/src/unix/netbsd.c b/deps/uv/src/unix/netbsd.c index c649bb375f32..cfe2c6a49dc3 100644 --- a/deps/uv/src/unix/netbsd.c +++ b/deps/uv/src/unix/netbsd.c @@ -234,14 +234,3 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { uv__free(cp_times); return 0; } - - -void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { - int i; - - for (i = 0; i < count; i++) { - uv__free(cpu_infos[i].model); - } - - uv__free(cpu_infos); -} diff --git a/deps/uv/src/unix/openbsd.c b/deps/uv/src/unix/openbsd.c index b5cdc80c3e92..1f5228dc13fd 100644 --- a/deps/uv/src/unix/openbsd.c +++ b/deps/uv/src/unix/openbsd.c @@ -202,14 +202,13 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { if (!(*cpu_infos)) return UV_ENOMEM; + i = 0; *count = numcpus; which[1] = HW_CPUSPEED; size = sizeof(cpuspeed); - if (sysctl(which, 2, &cpuspeed, &size, NULL, 0)) { - uv__free(*cpu_infos); - return UV__ERR(errno); - } + if (sysctl(which, 2, &cpuspeed, &size, NULL, 0)) + goto error; size = sizeof(info); which[0] = CTL_KERN; @@ -217,10 +216,8 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { for (i = 0; i < numcpus; i++) { which[2] = i; size = sizeof(info); - if (sysctl(which, 3, &info, &size, NULL, 0)) { - uv__free(*cpu_infos); - return UV__ERR(errno); - } + if (sysctl(which, 3, &info, &size, NULL, 0)) + goto error; cpu_info = &(*cpu_infos)[i]; @@ -235,15 +232,13 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { } return 0; -} +error: + *count = 0; + for (j = 0; j < i; j++) + uv__free((*cpu_infos)[j].model); -void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { - int i; - - for (i = 0; i < count; i++) { - uv__free(cpu_infos[i].model); - } - - uv__free(cpu_infos); + uv__free(*cpu_infos); + *cpu_infos = NULL; + return UV__ERR(errno); } diff --git a/deps/uv/src/unix/os390.c b/deps/uv/src/unix/os390.c index 273ded7ca5e8..a7305006c175 100644 --- a/deps/uv/src/unix/os390.c +++ b/deps/uv/src/unix/os390.c @@ -433,13 +433,6 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { } -void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { - for (int i = 0; i < count; ++i) - uv__free(cpu_infos[i].model); - uv__free(cpu_infos); -} - - static int uv__interface_addresses_v6(uv_interface_address_t** addresses, int* count) { uv_interface_address_t* address; diff --git a/deps/uv/src/unix/signal.c b/deps/uv/src/unix/signal.c index 5e89ded2d842..3a257f04b578 100644 --- a/deps/uv/src/unix/signal.c +++ b/deps/uv/src/unix/signal.c @@ -477,9 +477,11 @@ static void uv__signal_event(uv_loop_t* loop, * yet dispatched, the uv__finish_close was deferred. Make close pending * now if this has happened. */ - if ((handle->flags & UV_HANDLE_CLOSING) && - (handle->caught_signals == handle->dispatched_signals)) { - uv__make_close_pending((uv_handle_t*) handle); + if (handle->caught_signals == handle->dispatched_signals) { + if (handle->signum == 0) + uv__handle_stop(handle); + if (handle->flags & UV_HANDLE_CLOSING) + uv__make_close_pending((uv_handle_t*) handle); } } @@ -569,5 +571,6 @@ static void uv__signal_stop(uv_signal_t* handle) { uv__signal_unlock_and_unblock(&saved_sigmask); handle->signum = 0; - uv__handle_stop(handle); + if (handle->caught_signals == handle->dispatched_signals) + uv__handle_stop(handle); } diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c index 9de01e3c7840..78ce8e84870e 100644 --- a/deps/uv/src/unix/stream.c +++ b/deps/uv/src/unix/stream.c @@ -1180,6 +1180,10 @@ static void uv__read(uv_stream_t* stream) { } else if (errno == ECONNRESET && stream->type == UV_NAMED_PIPE) { uv__stream_eof(stream, &buf); return; +#elif defined(_AIX) + } else if (errno == ECONNRESET && (stream->flags & UV_DISCONNECT)) { + uv__stream_eof(stream, &buf); + return; #endif } else { /* Error. User should call uv_close(). */ @@ -1403,7 +1407,7 @@ int uv_write2(uv_write_t* req, return UV_EBADF; if (!(stream->flags & UV_HANDLE_WRITABLE)) - return -EPIPE; + return UV_EPIPE; if (send_handle) { if (stream->type != UV_NAMED_PIPE || !((uv_pipe_t*)stream)->ipc) @@ -1557,7 +1561,7 @@ int uv_read_start(uv_stream_t* stream, return UV_EINVAL; if (!(stream->flags & UV_HANDLE_READABLE)) - return -ENOTCONN; + return UV_ENOTCONN; /* The UV_HANDLE_READING flag is irrelevant of the state of the tcp - it just * expresses the desired state of the user. diff --git a/deps/uv/src/unix/sunos.c b/deps/uv/src/unix/sunos.c index f323d1defdef..180cc84651db 100644 --- a/deps/uv/src/unix/sunos.c +++ b/deps/uv/src/unix/sunos.c @@ -696,16 +696,6 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { } -void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { - int i; - - for (i = 0; i < count; i++) { - uv__free(cpu_infos[i].model); - } - - uv__free(cpu_infos); -} - #ifdef SUNOS_NO_IFADDRS int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { *count = 0; diff --git a/deps/uv/src/unix/tcp.c b/deps/uv/src/unix/tcp.c index 8cedcd6027be..fa660f138131 100644 --- a/deps/uv/src/unix/tcp.c +++ b/deps/uv/src/unix/tcp.c @@ -308,6 +308,23 @@ int uv_tcp_getpeername(const uv_tcp_t* handle, } +int uv_tcp_close_reset(uv_tcp_t* handle, uv_close_cb close_cb) { + int fd; + struct linger l = { 1, 0 }; + + /* Disallow setting SO_LINGER to zero due to some platform inconsistencies */ + if (handle->flags & UV_HANDLE_SHUTTING) + return UV_EINVAL; + + fd = uv__stream_fd(handle); + if (0 != setsockopt(fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l))) + return UV__ERR(errno); + + uv_close((uv_handle_t*) handle, close_cb); + return 0; +} + + int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) { static int single_accept = -1; unsigned long flags; diff --git a/deps/uv/src/unix/udp.c b/deps/uv/src/unix/udp.c index b578e7bc1037..dba8eff8382e 100644 --- a/deps/uv/src/unix/udp.c +++ b/deps/uv/src/unix/udp.c @@ -659,6 +659,98 @@ static int uv__udp_set_membership6(uv_udp_t* handle, } +static int uv__udp_set_source_membership4(uv_udp_t* handle, + const struct sockaddr_in* multicast_addr, + const char* interface_addr, + const struct sockaddr_in* source_addr, + uv_membership membership) { + struct ip_mreq_source mreq; + int optname; + int err; + + err = uv__udp_maybe_deferred_bind(handle, AF_INET, UV_UDP_REUSEADDR); + if (err) + return err; + + memset(&mreq, 0, sizeof(mreq)); + + if (interface_addr != NULL) { + err = uv_inet_pton(AF_INET, interface_addr, &mreq.imr_interface.s_addr); + if (err) + return err; + } else { + mreq.imr_interface.s_addr = htonl(INADDR_ANY); + } + + mreq.imr_multiaddr.s_addr = multicast_addr->sin_addr.s_addr; + mreq.imr_sourceaddr.s_addr = source_addr->sin_addr.s_addr; + + if (membership == UV_JOIN_GROUP) + optname = IP_ADD_SOURCE_MEMBERSHIP; + else if (membership == UV_LEAVE_GROUP) + optname = IP_DROP_SOURCE_MEMBERSHIP; + else + return UV_EINVAL; + + if (setsockopt(handle->io_watcher.fd, + IPPROTO_IP, + optname, + &mreq, + sizeof(mreq))) { + return UV__ERR(errno); + } + + return 0; +} + + +static int uv__udp_set_source_membership6(uv_udp_t* handle, + const struct sockaddr_in6* multicast_addr, + const char* interface_addr, + const struct sockaddr_in6* source_addr, + uv_membership membership) { + struct group_source_req mreq; + struct sockaddr_in6 addr6; + int optname; + int err; + + err = uv__udp_maybe_deferred_bind(handle, AF_INET6, UV_UDP_REUSEADDR); + if (err) + return err; + + memset(&mreq, 0, sizeof(mreq)); + + if (interface_addr != NULL) { + err = uv_ip6_addr(interface_addr, 0, &addr6); + if (err) + return err; + mreq.gsr_interface = addr6.sin6_scope_id; + } else { + mreq.gsr_interface = 0; + } + + memcpy(&mreq.gsr_group, multicast_addr, sizeof(mreq.gsr_group)); + memcpy(&mreq.gsr_source, source_addr, sizeof(mreq.gsr_source)); + + if (membership == UV_JOIN_GROUP) + optname = MCAST_JOIN_SOURCE_GROUP; + else if (membership == UV_LEAVE_GROUP) + optname = MCAST_LEAVE_SOURCE_GROUP; + else + return UV_EINVAL; + + if (setsockopt(handle->io_watcher.fd, + IPPROTO_IPV6, + optname, + &mreq, + sizeof(mreq))) { + return UV__ERR(errno); + } + + return 0; +} + + int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) { int domain; int err; @@ -748,6 +840,51 @@ int uv_udp_set_membership(uv_udp_t* handle, } } + +int uv_udp_set_source_membership(uv_udp_t* handle, + const char* multicast_addr, + const char* interface_addr, + const char* source_addr, + uv_membership membership) { + int err; + struct sockaddr_storage mcast_addr; + struct sockaddr_in* mcast_addr4; + struct sockaddr_in6* mcast_addr6; + struct sockaddr_storage src_addr; + struct sockaddr_in* src_addr4; + struct sockaddr_in6* src_addr6; + + mcast_addr4 = (struct sockaddr_in*)&mcast_addr; + mcast_addr6 = (struct sockaddr_in6*)&mcast_addr; + src_addr4 = (struct sockaddr_in*)&src_addr; + src_addr6 = (struct sockaddr_in6*)&src_addr; + + err = uv_ip4_addr(multicast_addr, 0, mcast_addr4); + if (err) { + err = uv_ip6_addr(multicast_addr, 0, mcast_addr6); + if (err) + return err; + err = uv_ip6_addr(source_addr, 0, src_addr6); + if (err) + return err; + return uv__udp_set_source_membership6(handle, + mcast_addr6, + interface_addr, + src_addr6, + membership); + } + + err = uv_ip4_addr(source_addr, 0, src_addr4); + if (err) + return err; + return uv__udp_set_source_membership4(handle, + mcast_addr4, + interface_addr, + src_addr4, + membership); +} + + static int uv__setsockopt(uv_udp_t* handle, int option4, int option6, diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c index d1a5e2fbe6b7..70db53ab04da 100644 --- a/deps/uv/src/uv-common.c +++ b/deps/uv/src/uv-common.c @@ -797,3 +797,13 @@ void uv_os_free_environ(uv_env_item_t* envitems, int count) { uv__free(envitems); } + + +void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { + int i; + + for (i = 0; i < count; i++) + uv__free(cpu_infos[i].model); + + uv__free(cpu_infos); +} diff --git a/deps/uv/src/win/error.c b/deps/uv/src/win/error.c index 24924ba81ef3..32ac5e596fea 100644 --- a/deps/uv/src/win/error.c +++ b/deps/uv/src/win/error.c @@ -132,6 +132,7 @@ int uv_translate_sys_error(int sys_errno) { case WSAENOBUFS: return UV_ENOBUFS; case ERROR_BAD_PATHNAME: return UV_ENOENT; case ERROR_DIRECTORY: return UV_ENOENT; + case ERROR_ENVVAR_NOT_FOUND: return UV_ENOENT; case ERROR_FILE_NOT_FOUND: return UV_ENOENT; case ERROR_INVALID_NAME: return UV_ENOENT; case ERROR_INVALID_DRIVE: return UV_ENOENT; diff --git a/deps/uv/src/win/stream.c b/deps/uv/src/win/stream.c index 7656627e902d..46a0709a38e3 100644 --- a/deps/uv/src/win/stream.c +++ b/deps/uv/src/win/stream.c @@ -198,8 +198,10 @@ int uv_try_write(uv_stream_t* stream, int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) { uv_loop_t* loop = handle->loop; - if (!(handle->flags & UV_HANDLE_WRITABLE)) { - return UV_EPIPE; + if (!(handle->flags & UV_HANDLE_WRITABLE) || + handle->flags & UV_HANDLE_SHUTTING || + uv__is_closing(handle)) { + return UV_ENOTCONN; } UV_REQ_INIT(req, UV_SHUTDOWN); @@ -207,6 +209,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) { req->cb = cb; handle->flags &= ~UV_HANDLE_WRITABLE; + handle->flags |= UV_HANDLE_SHUTTING; handle->stream.conn.shutdown_req = req; handle->reqs_pending++; REGISTER_HANDLE_REQ(loop, handle, req); diff --git a/deps/uv/src/win/tcp.c b/deps/uv/src/win/tcp.c index f2cb5271b8d7..81e48136a3b9 100644 --- a/deps/uv/src/win/tcp.c +++ b/deps/uv/src/win/tcp.c @@ -549,6 +549,21 @@ static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) { } +int uv_tcp_close_reset(uv_tcp_t* handle, uv_close_cb close_cb) { + struct linger l = { 1, 0 }; + + /* Disallow setting SO_LINGER to zero due to some platform inconsistencies */ + if (handle->flags & UV_HANDLE_SHUTTING) + return UV_EINVAL; + + if (0 != setsockopt(handle->socket, SOL_SOCKET, SO_LINGER, &l, sizeof(l))) + return uv_translate_sys_error(WSAGetLastError()); + + uv_close((uv_handle_t*) handle, close_cb); + return 0; +} + + int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { unsigned int i, simultaneous_accepts; uv_tcp_accept_t* req; diff --git a/deps/uv/src/win/tty.c b/deps/uv/src/win/tty.c index 07436dc804f0..8f84bcd0e455 100644 --- a/deps/uv/src/win/tty.c +++ b/deps/uv/src/win/tty.c @@ -120,6 +120,8 @@ static int uv_tty_virtual_width = -1; static HANDLE uv__tty_console_handle = INVALID_HANDLE_VALUE; static int uv__tty_console_height = -1; static int uv__tty_console_width = -1; +static HANDLE uv__tty_console_resized = INVALID_HANDLE_VALUE; +static uv_mutex_t uv__tty_console_resize_mutex; static DWORD WINAPI uv__tty_console_resize_message_loop_thread(void* param); static void CALLBACK uv__tty_console_resize_event(HWINEVENTHOOK hWinEventHook, @@ -129,6 +131,8 @@ static void CALLBACK uv__tty_console_resize_event(HWINEVENTHOOK hWinEventHook, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime); +static DWORD WINAPI uv__tty_console_resize_watcher_thread(void* param); +static void uv__tty_console_signal_resize(void); /* We use a semaphore rather than a mutex or critical section because in some cases (uv__cancel_read_console) we need take the lock in the main thread and @@ -168,6 +172,7 @@ void uv_console_init(void) { QueueUserWorkItem(uv__tty_console_resize_message_loop_thread, NULL, WT_EXECUTELONGFUNCTION); + uv_mutex_init(&uv__tty_console_resize_mutex); } } @@ -728,6 +733,12 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle, } records_left--; + /* We might be not subscribed to EVENT_CONSOLE_LAYOUT or we might be + * running under some TTY emulator that does not send those events. */ + if (handle->tty.rd.last_input_record.EventType == WINDOW_BUFFER_SIZE_EVENT) { + uv__tty_console_signal_resize(); + } + /* Ignore other events that are not key events. */ if (handle->tty.rd.last_input_record.EventType != KEY_EVENT) { continue; @@ -2299,15 +2310,24 @@ static DWORD WINAPI uv__tty_console_resize_message_loop_thread(void* param) { sizeof(conhost_pid), NULL); - if (!NT_SUCCESS(status)) + if (!NT_SUCCESS(status)) { /* We couldn't retrieve our console host process, probably because this * is a 32-bit process running on 64-bit Windows. Fall back to receiving - * console events from all processes. */ - conhost_pid = 0; + * console events from the input stream only. */ + return 0; + } /* Ensure the PID is a multiple of 4, which is required by SetWinEventHook */ conhost_pid &= ~(ULONG_PTR)0x3; + uv__tty_console_resized = CreateEvent(NULL, TRUE, FALSE, NULL); + if (uv__tty_console_resized == NULL) + return 0; + if (QueueUserWorkItem(uv__tty_console_resize_watcher_thread, + NULL, + WT_EXECUTELONGFUNCTION) == 0) + return 0; + if (!pSetWinEventHook(EVENT_CONSOLE_LAYOUT, EVENT_CONSOLE_LAYOUT, NULL, @@ -2331,6 +2351,20 @@ static void CALLBACK uv__tty_console_resize_event(HWINEVENTHOOK hWinEventHook, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime) { + SetEvent(uv__tty_console_resized); +} + +static DWORD WINAPI uv__tty_console_resize_watcher_thread(void* param) { + for (;;) { + /* Make sure to not overwhelm the system with resize events */ + Sleep(33); + WaitForSingleObject(uv__tty_console_resized, INFINITE); + uv__tty_console_signal_resize(); + ResetEvent(uv__tty_console_resized); + } +} + +static void uv__tty_console_signal_resize(void) { CONSOLE_SCREEN_BUFFER_INFO sb_info; int width, height; @@ -2340,9 +2374,13 @@ static void CALLBACK uv__tty_console_resize_event(HWINEVENTHOOK hWinEventHook, width = sb_info.dwSize.X; height = sb_info.srWindow.Bottom - sb_info.srWindow.Top + 1; + uv_mutex_lock(&uv__tty_console_resize_mutex); if (width != uv__tty_console_width || height != uv__tty_console_height) { uv__tty_console_width = width; uv__tty_console_height = height; + uv_mutex_unlock(&uv__tty_console_resize_mutex); uv__signal_dispatch(SIGWINCH); + } else { + uv_mutex_unlock(&uv__tty_console_resize_mutex); } } diff --git a/deps/uv/src/win/udp.c b/deps/uv/src/win/udp.c index 8aeeab3b4628..39fc34d3bfcd 100644 --- a/deps/uv/src/win/udp.c +++ b/deps/uv/src/win/udp.c @@ -702,6 +702,112 @@ int uv__udp_set_membership6(uv_udp_t* handle, } +static int uv__udp_set_source_membership4(uv_udp_t* handle, + const struct sockaddr_in* multicast_addr, + const char* interface_addr, + const struct sockaddr_in* source_addr, + uv_membership membership) { + struct ip_mreq_source mreq; + int optname; + int err; + + if (handle->flags & UV_HANDLE_IPV6) + return UV_EINVAL; + + /* If the socket is unbound, bind to inaddr_any. */ + err = uv_udp_maybe_bind(handle, + (const struct sockaddr*) &uv_addr_ip4_any_, + sizeof(uv_addr_ip4_any_), + UV_UDP_REUSEADDR); + if (err) + return uv_translate_sys_error(err); + + memset(&mreq, 0, sizeof(mreq)); + + if (interface_addr != NULL) { + err = uv_inet_pton(AF_INET, interface_addr, &mreq.imr_interface.s_addr); + if (err) + return err; + } else { + mreq.imr_interface.s_addr = htonl(INADDR_ANY); + } + + mreq.imr_multiaddr.s_addr = multicast_addr->sin_addr.s_addr; + mreq.imr_sourceaddr.s_addr = source_addr->sin_addr.s_addr; + + if (membership == UV_JOIN_GROUP) + optname = IP_ADD_SOURCE_MEMBERSHIP; + else if (membership == UV_LEAVE_GROUP) + optname = IP_DROP_SOURCE_MEMBERSHIP; + else + return UV_EINVAL; + + if (setsockopt(handle->socket, + IPPROTO_IP, + optname, + (char*) &mreq, + sizeof(mreq)) == SOCKET_ERROR) { + return uv_translate_sys_error(WSAGetLastError()); + } + + return 0; +} + + +int uv__udp_set_source_membership6(uv_udp_t* handle, + const struct sockaddr_in6* multicast_addr, + const char* interface_addr, + const struct sockaddr_in6* source_addr, + uv_membership membership) { + struct group_source_req mreq; + struct sockaddr_in6 addr6; + int optname; + int err; + + if ((handle->flags & UV_HANDLE_BOUND) && !(handle->flags & UV_HANDLE_IPV6)) + return UV_EINVAL; + + err = uv_udp_maybe_bind(handle, + (const struct sockaddr*) &uv_addr_ip6_any_, + sizeof(uv_addr_ip6_any_), + UV_UDP_REUSEADDR); + + if (err) + return uv_translate_sys_error(err); + + memset(&mreq, 0, sizeof(mreq)); + + if (interface_addr != NULL) { + err = uv_ip6_addr(interface_addr, 0, &addr6); + if (err) + return err; + mreq.gsr_interface = addr6.sin6_scope_id; + } else { + mreq.gsr_interface = 0; + } + + memcpy(&mreq.gsr_group, multicast_addr, sizeof(mreq.gsr_group)); + memcpy(&mreq.gsr_source, source_addr, sizeof(mreq.gsr_source)); + + if (membership == UV_JOIN_GROUP) + optname = MCAST_JOIN_SOURCE_GROUP; + else if (membership == UV_LEAVE_GROUP) + optname = MCAST_LEAVE_SOURCE_GROUP; + else + return UV_EINVAL; + + if (setsockopt(handle->socket, + IPPROTO_IPV6, + optname, + (char*) &mreq, + sizeof(mreq)) == SOCKET_ERROR) { + return uv_translate_sys_error(WSAGetLastError()); + } + + return 0; +} + + int uv_udp_set_membership(uv_udp_t* handle, const char* multicast_addr, const char* interface_addr, @@ -718,6 +824,50 @@ int uv_udp_set_membership(uv_udp_t* handle, } +int uv_udp_set_source_membership(uv_udp_t* handle, + const char* multicast_addr, + const char* interface_addr, + const char* source_addr, + uv_membership membership) { + int err; + struct sockaddr_storage mcast_addr; + struct sockaddr_in* mcast_addr4; + struct sockaddr_in6* mcast_addr6; + struct sockaddr_storage src_addr; + struct sockaddr_in* src_addr4; + struct sockaddr_in6* src_addr6; + + mcast_addr4 = (struct sockaddr_in*)&mcast_addr; + mcast_addr6 = (struct sockaddr_in6*)&mcast_addr; + src_addr4 = (struct sockaddr_in*)&src_addr; + src_addr6 = (struct sockaddr_in6*)&src_addr; + + err = uv_ip4_addr(multicast_addr, 0, mcast_addr4); + if (err) { + err = uv_ip6_addr(multicast_addr, 0, mcast_addr6); + if (err) + return err; + err = uv_ip6_addr(source_addr, 0, src_addr6); + if (err) + return err; + return uv__udp_set_source_membership6(handle, + mcast_addr6, + interface_addr, + src_addr6, + membership); + } + + err = uv_ip4_addr(source_addr, 0, src_addr4); + if (err) + return err; + return uv__udp_set_source_membership4(handle, + mcast_addr4, + interface_addr, + src_addr4, + membership); +} + + int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) { struct sockaddr_storage addr_st; struct sockaddr_in* addr4; diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c index 359a16aed4bb..8849d041bf02 100644 --- a/deps/uv/src/win/util.c +++ b/deps/uv/src/win/util.c @@ -721,17 +721,6 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos_ptr, int* cpu_count_ptr) { } -void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { - int i; - - for (i = 0; i < count; i++) { - uv__free(cpu_infos[i].model); - } - - uv__free(cpu_infos); -} - - static int is_windows_version_or_greater(DWORD os_major, DWORD os_minor, WORD service_pack_major, @@ -1325,7 +1314,7 @@ int uv__convert_utf8_to_utf16(const char* utf8, int utf8len, WCHAR** utf16) { return uv_translate_sys_error(GetLastError()); } - (*utf16)[bufsize] = '\0'; + (*utf16)[bufsize] = L'\0'; return 0; } @@ -1481,17 +1470,15 @@ int uv_os_getenv(const char* name, char* buffer, size_t* size) { if (r != 0) return r; + SetLastError(ERROR_SUCCESS); len = GetEnvironmentVariableW(name_w, var, MAX_ENV_VAR_LENGTH); uv__free(name_w); assert(len < MAX_ENV_VAR_LENGTH); /* len does not include the null */ if (len == 0) { r = GetLastError(); - - if (r == ERROR_ENVVAR_NOT_FOUND) - return UV_ENOENT; - - return uv_translate_sys_error(r); + if (r != ERROR_SUCCESS) + return uv_translate_sys_error(r); } /* Check how much space we need */ diff --git a/deps/uv/src/win/winapi.h b/deps/uv/src/win/winapi.h index 203393c2e3af..322a212dd73c 100644 --- a/deps/uv/src/win/winapi.h +++ b/deps/uv/src/win/winapi.h @@ -4109,7 +4109,7 @@ #endif /* from winternl.h */ -#if !defined(__UNICODE_STRING_DEFINED) && defined(__MINGW32_) +#if !defined(__UNICODE_STRING_DEFINED) && defined(__MINGW32__) #define __UNICODE_STRING_DEFINED #endif typedef struct _UNICODE_STRING { diff --git a/deps/uv/test/test-env-vars.c b/deps/uv/test/test-env-vars.c index d7abb4249561..3814699356db 100644 --- a/deps/uv/test/test-env-vars.c +++ b/deps/uv/test/test-env-vars.c @@ -88,6 +88,15 @@ TEST_IMPL(env_vars) { r = uv_os_unsetenv(name); ASSERT(r == 0); + /* Setting an environment variable to the empty string does not delete it. */ + r = uv_os_setenv(name, ""); + ASSERT(r == 0); + size = BUF_SIZE; + r = uv_os_getenv(name, buf, &size); + ASSERT(r == 0); + ASSERT(size == 0); + ASSERT(strlen(buf) == 0); + /* Check getting all env variables. */ r = uv_os_setenv(name, "123456789"); ASSERT(r == 0); diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c index 0d92b0d3a0d3..9326c6bc2753 100644 --- a/deps/uv/test/test-fs.c +++ b/deps/uv/test/test-fs.c @@ -354,7 +354,7 @@ static void statfs_cb(uv_fs_t* req) { ASSERT(stats->f_files == 0); ASSERT(stats->f_ffree == 0); #else - ASSERT(stats->f_files > 0); + /* There is no assertion for stats->f_files that makes sense, so ignore it. */ ASSERT(stats->f_ffree <= stats->f_files); #endif uv_fs_req_cleanup(req); diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index 6eb8ecadc787..b6066f27276d 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -112,6 +112,10 @@ TEST_DECLARE (tcp_connect_error_fault) TEST_DECLARE (tcp_connect_timeout) TEST_DECLARE (tcp_close_while_connecting) TEST_DECLARE (tcp_close) +TEST_DECLARE (tcp_close_reset_accepted) +TEST_DECLARE (tcp_close_reset_accepted_after_shutdown) +TEST_DECLARE (tcp_close_reset_client) +TEST_DECLARE (tcp_close_reset_client_after_shutdown) TEST_DECLARE (tcp_create_early) TEST_DECLARE (tcp_create_early_bad_bind) TEST_DECLARE (tcp_create_early_bad_domain) @@ -193,6 +197,7 @@ TEST_DECLARE (timer_huge_timeout) TEST_DECLARE (timer_huge_repeat) TEST_DECLARE (timer_run_once) TEST_DECLARE (timer_from_check) +TEST_DECLARE (timer_is_closing) TEST_DECLARE (timer_null_callback) TEST_DECLARE (timer_early_check) TEST_DECLARE (idle_starvation) @@ -445,6 +450,7 @@ TEST_DECLARE (we_get_signals) TEST_DECLARE (we_get_signal_one_shot) TEST_DECLARE (we_get_signals_mixed) TEST_DECLARE (signal_multiple_loops) +TEST_DECLARE (signal_pending_on_close) TEST_DECLARE (closed_fd_events) #endif #ifdef __APPLE__ @@ -623,6 +629,10 @@ TASK_LIST_START TEST_ENTRY (tcp_connect_timeout) TEST_ENTRY (tcp_close_while_connecting) TEST_ENTRY (tcp_close) + TEST_ENTRY (tcp_close_reset_accepted) + TEST_ENTRY (tcp_close_reset_accepted_after_shutdown) + TEST_ENTRY (tcp_close_reset_client) + TEST_ENTRY (tcp_close_reset_client_after_shutdown) TEST_ENTRY (tcp_create_early) TEST_ENTRY (tcp_create_early_bad_bind) TEST_ENTRY (tcp_create_early_bad_domain) @@ -720,6 +730,7 @@ TASK_LIST_START TEST_ENTRY (timer_huge_repeat) TEST_ENTRY (timer_run_once) TEST_ENTRY (timer_from_check) + TEST_ENTRY (timer_is_closing) TEST_ENTRY (timer_null_callback) TEST_ENTRY (timer_early_check) @@ -886,6 +897,7 @@ TASK_LIST_START TEST_ENTRY (we_get_signal_one_shot) TEST_ENTRY (we_get_signals_mixed) TEST_ENTRY (signal_multiple_loops) + TEST_ENTRY (signal_pending_on_close) TEST_ENTRY (closed_fd_events) #endif diff --git a/deps/uv/test/test-signal-pending-on-close.c b/deps/uv/test/test-signal-pending-on-close.c new file mode 100644 index 000000000000..bf8d2793d51f --- /dev/null +++ b/deps/uv/test/test-signal-pending-on-close.c @@ -0,0 +1,94 @@ +/* Copyright libuv project contributors. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to +* deal in the Software without restriction, including without limitation the +* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +* sell copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +* IN THE SOFTWARE. +*/ +#ifndef _WIN32 + +#include "uv.h" +#include "task.h" + +#include +#include + +static uv_loop_t loop; +static uv_signal_t signal_hdl; +static uv_pipe_t pipe_hdl; +static uv_write_t write_req; +static char* buf; +static int close_cb_called; + + +static void signal_cb(uv_signal_t* signal, int signum) { + ASSERT(0); +} + +static void close_cb(uv_handle_t *handle) { + close_cb_called++; +} + + +static void write_cb(uv_write_t* req, int status) { + ASSERT(req != NULL); + ASSERT(status == UV_EPIPE); + free(buf); + uv_close((uv_handle_t *) &pipe_hdl, close_cb); + uv_close((uv_handle_t *) &signal_hdl, close_cb); +} + + +TEST_IMPL(signal_pending_on_close) { + int pipefds[2]; + uv_buf_t buffer; + int r; + + ASSERT(0 == uv_loop_init(&loop)); + + ASSERT(0 == uv_signal_init(&loop, &signal_hdl)); + + ASSERT(0 == uv_signal_start(&signal_hdl, signal_cb, SIGPIPE)); + + ASSERT(0 == pipe(pipefds)); + + ASSERT(0 == uv_pipe_init(&loop, &pipe_hdl, 0)); + + ASSERT(0 == uv_pipe_open(&pipe_hdl, pipefds[1])); + + /* Write data large enough so it needs loop iteration */ + buf = malloc(1<<24); + ASSERT(buf != NULL); + memset(buf, '.', 1<<24); + buffer = uv_buf_init(buf, 1<<24); + + r = uv_write(&write_req, (uv_stream_t *) &pipe_hdl, &buffer, 1, write_cb); + ASSERT(0 == r); + + /* cause a SIGPIPE on write in next iteration */ + close(pipefds[0]); + + ASSERT(0 == uv_run(&loop, UV_RUN_DEFAULT)); + + ASSERT(0 == uv_loop_close(&loop)); + + ASSERT(2 == close_cb_called); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + +#endif \ No newline at end of file diff --git a/deps/uv/test/test-spawn.c b/deps/uv/test/test-spawn.c index fec610bfdef9..be9e2539aa65 100644 --- a/deps/uv/test/test-spawn.c +++ b/deps/uv/test/test-spawn.c @@ -240,7 +240,7 @@ TEST_IMPL(spawn_empty_env) { * in the environment, but of course that doesn't work with * the empty environment that we're testing here. */ - if (NULL != getenv("DYLD_LIBARY_PATH") || + if (NULL != getenv("DYLD_LIBRARY_PATH") || NULL != getenv("LD_LIBRARY_PATH")) { RETURN_SKIP("doesn't work with DYLD_LIBRARY_PATH/LD_LIBRARY_PATH"); } diff --git a/deps/uv/test/test-tcp-bind-error.c b/deps/uv/test/test-tcp-bind-error.c index 1456d081ae63..f95efd9f0c89 100644 --- a/deps/uv/test/test-tcp-bind-error.c +++ b/deps/uv/test/test-tcp-bind-error.c @@ -239,11 +239,7 @@ TEST_IMPL(tcp_bind_writable_flags) { r = uv_write(&write_req, (uv_stream_t*) &server, &buf, 1, NULL); ASSERT(r == UV_EPIPE); r = uv_shutdown(&shutdown_req, (uv_stream_t*) &server, NULL); -#ifdef _WIN32 - ASSERT(r == UV_EPIPE); -#else ASSERT(r == UV_ENOTCONN); -#endif r = uv_read_start((uv_stream_t*) &server, NULL, NULL); ASSERT(r == UV_ENOTCONN); diff --git a/deps/uv/test/test-tcp-close-reset.c b/deps/uv/test/test-tcp-close-reset.c new file mode 100644 index 000000000000..7ca55c4c7f98 --- /dev/null +++ b/deps/uv/test/test-tcp-close-reset.c @@ -0,0 +1,290 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "task.h" + +#include +#include /* memset */ + +static uv_loop_t* loop; +static uv_tcp_t tcp_server; +static uv_tcp_t tcp_client; +static uv_tcp_t tcp_accepted; +static uv_connect_t connect_req; +static uv_shutdown_t shutdown_req; +static uv_write_t write_reqs[4]; + +static int client_close; +static int shutdown_before_close; + +static int write_cb_called; +static int close_cb_called; +static int shutdown_cb_called; + +static void connect_cb(uv_connect_t* req, int status); +static void write_cb(uv_write_t* req, int status); +static void close_cb(uv_handle_t* handle); +static void shutdown_cb(uv_shutdown_t* req, int status); + +static int read_size; + + +static void do_write(uv_tcp_t* handle) { + uv_buf_t buf; + unsigned i; + int r; + + buf = uv_buf_init("PING", 4); + for (i = 0; i < ARRAY_SIZE(write_reqs); i++) { + r = uv_write(&write_reqs[i], (uv_stream_t*) handle, &buf, 1, write_cb); + ASSERT(r == 0); + } +} + + +static void do_close(uv_tcp_t* handle) { + if (shutdown_before_close == 1) { + ASSERT(0 == uv_shutdown(&shutdown_req, (uv_stream_t*) handle, shutdown_cb)); + ASSERT(UV_EINVAL == uv_tcp_close_reset(handle, close_cb)); + } else { + ASSERT(0 == uv_tcp_close_reset(handle, close_cb)); + ASSERT(UV_ENOTCONN == uv_shutdown(&shutdown_req, (uv_stream_t*) handle, shutdown_cb)); + } + + uv_close((uv_handle_t*) &tcp_server, NULL); +} + +static void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) { + static char slab[1024]; + buf->base = slab; + buf->len = sizeof(slab); +} + +static void read_cb2(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { + ASSERT((uv_tcp_t*)stream == &tcp_client); + if (nread == UV_EOF) + uv_close((uv_handle_t*) stream, NULL); +} + + +static void connect_cb(uv_connect_t* conn_req, int status) { + ASSERT(conn_req == &connect_req); + uv_read_start((uv_stream_t*) &tcp_client, alloc_cb, read_cb2); + do_write(&tcp_client); + if (client_close) + do_close(&tcp_client); +} + + +static void write_cb(uv_write_t* req, int status) { + /* write callbacks should run before the close callback */ + ASSERT(close_cb_called == 0); + ASSERT(req->handle == (uv_stream_t*)&tcp_client); + write_cb_called++; +} + + +static void close_cb(uv_handle_t* handle) { + if (client_close) + ASSERT(handle == (uv_handle_t*) &tcp_client); + else + ASSERT(handle == (uv_handle_t*) &tcp_accepted); + + close_cb_called++; +} + +static void shutdown_cb(uv_shutdown_t* req, int status) { + if (client_close) + ASSERT(req->handle == (uv_stream_t*) &tcp_client); + else + ASSERT(req->handle == (uv_stream_t*) &tcp_accepted); + + shutdown_cb_called++; +} + + +static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { + ASSERT((uv_tcp_t*)stream == &tcp_accepted); + if (nread < 0) { + uv_close((uv_handle_t*) stream, NULL); + } else { + read_size += nread; + if (read_size == 16 && client_close == 0) + do_close(&tcp_accepted); + } +} + + +static void connection_cb(uv_stream_t* server, int status) { + ASSERT(status == 0); + + ASSERT(0 == uv_tcp_init(loop, &tcp_accepted)); + ASSERT(0 == uv_accept(server, (uv_stream_t*) &tcp_accepted)); + + uv_read_start((uv_stream_t*) &tcp_accepted, alloc_cb, read_cb); +} + + +static void start_server(uv_loop_t* loop, uv_tcp_t* handle) { + struct sockaddr_in addr; + int r; + + ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); + + r = uv_tcp_init(loop, handle); + ASSERT(r == 0); + + r = uv_tcp_bind(handle, (const struct sockaddr*) &addr, 0); + ASSERT(r == 0); + + r = uv_listen((uv_stream_t*)handle, 128, connection_cb); + ASSERT(r == 0); +} + + +static void do_connect(uv_loop_t* loop, uv_tcp_t* tcp_client) { + struct sockaddr_in addr; + int r; + + ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); + + r = uv_tcp_init(loop, tcp_client); + ASSERT(r == 0); + + r = uv_tcp_connect(&connect_req, + tcp_client, + (const struct sockaddr*) &addr, + connect_cb); + ASSERT(r == 0); +} + + +/* Check that pending write requests have their callbacks + * invoked when the handle is closed. + */ +TEST_IMPL(tcp_close_reset_client) { + int r; + + loop = uv_default_loop(); + + start_server(loop, &tcp_server); + + client_close = 1; + shutdown_before_close = 0; + + do_connect(loop, &tcp_client); + + ASSERT(write_cb_called == 0); + ASSERT(close_cb_called == 0); + ASSERT(shutdown_cb_called == 0); + + r = uv_run(loop, UV_RUN_DEFAULT); + ASSERT(r == 0); + + ASSERT(write_cb_called == 4); + ASSERT(close_cb_called == 1); + ASSERT(shutdown_cb_called == 0); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + +TEST_IMPL(tcp_close_reset_client_after_shutdown) { + int r; + + loop = uv_default_loop(); + + start_server(loop, &tcp_server); + + client_close = 1; + shutdown_before_close = 1; + + do_connect(loop, &tcp_client); + + ASSERT(write_cb_called == 0); + ASSERT(close_cb_called == 0); + ASSERT(shutdown_cb_called == 0); + + r = uv_run(loop, UV_RUN_DEFAULT); + ASSERT(r == 0); + + ASSERT(write_cb_called == 4); + ASSERT(close_cb_called == 0); + ASSERT(shutdown_cb_called == 1); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + +TEST_IMPL(tcp_close_reset_accepted) { + int r; + + loop = uv_default_loop(); + + start_server(loop, &tcp_server); + + client_close = 0; + shutdown_before_close = 0; + + do_connect(loop, &tcp_client); + + ASSERT(write_cb_called == 0); + ASSERT(close_cb_called == 0); + ASSERT(shutdown_cb_called == 0); + + r = uv_run(loop, UV_RUN_DEFAULT); + ASSERT(r == 0); + + ASSERT(write_cb_called == 4); + ASSERT(close_cb_called == 1); + ASSERT(shutdown_cb_called == 0); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + +TEST_IMPL(tcp_close_reset_accepted_after_shutdown) { + int r; + + loop = uv_default_loop(); + + start_server(loop, &tcp_server); + + client_close = 0; + shutdown_before_close = 1; + + do_connect(loop, &tcp_client); + + ASSERT(write_cb_called == 0); + ASSERT(close_cb_called == 0); + ASSERT(shutdown_cb_called == 0); + + r = uv_run(loop, UV_RUN_DEFAULT); + ASSERT(r == 0); + + ASSERT(write_cb_called == 4); + ASSERT(close_cb_called == 0); + ASSERT(shutdown_cb_called == 1); + + MAKE_VALGRIND_HAPPY(); + return 0; +} diff --git a/deps/uv/test/test-timer.c b/deps/uv/test/test-timer.c index 080a73005ee3..c667da00ec3a 100644 --- a/deps/uv/test/test-timer.c +++ b/deps/uv/test/test-timer.c @@ -292,6 +292,19 @@ TEST_IMPL(timer_run_once) { } +TEST_IMPL(timer_is_closing) { + uv_timer_t handle; + + ASSERT(0 == uv_timer_init(uv_default_loop(), &handle)); + uv_close((uv_handle_t *)&handle, NULL); + + ASSERT(UV_EINVAL == uv_timer_start(&handle, never_cb, 100, 100)); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + TEST_IMPL(timer_null_callback) { uv_timer_t handle; diff --git a/deps/uv/test/test-udp-multicast-join.c b/deps/uv/test/test-udp-multicast-join.c index 053d2f791498..9ee80e44e7c2 100644 --- a/deps/uv/test/test-udp-multicast-join.c +++ b/deps/uv/test/test-udp-multicast-join.c @@ -29,8 +29,12 @@ #define CHECK_HANDLE(handle) \ ASSERT((uv_udp_t*)(handle) == &server || (uv_udp_t*)(handle) == &client) +#define MULTICAST_ADDR "239.255.0.1" + static uv_udp_t server; static uv_udp_t client; +static uv_udp_send_t req; +static uv_udp_send_t req_ss; static int cl_recv_cb_called; @@ -62,7 +66,26 @@ static void sv_send_cb(uv_udp_send_t* req, int status) { sv_send_cb_called++; - uv_close((uv_handle_t*) req->handle, close_cb); + if (sv_send_cb_called == 2) + uv_close((uv_handle_t*) req->handle, close_cb); +} + + +static int do_send(uv_udp_send_t* send_req) { + uv_buf_t buf; + struct sockaddr_in addr; + + buf = uv_buf_init("PING", 4); + + ASSERT(0 == uv_ip4_addr(MULTICAST_ADDR, TEST_PORT, &addr)); + + /* client sends "PING" */ + return uv_udp_send(send_req, + &client, + &buf, + 1, + (const struct sockaddr*) &addr, + sv_send_cb); } @@ -74,8 +97,6 @@ static void cl_recv_cb(uv_udp_t* handle, CHECK_HANDLE(handle); ASSERT(flags == 0); - cl_recv_cb_called++; - if (nread < 0) { ASSERT(0 && "unexpected error"); } @@ -90,18 +111,35 @@ static void cl_recv_cb(uv_udp_t* handle, ASSERT(nread == 4); ASSERT(!memcmp("PING", buf->base, nread)); - /* we are done with the client handle, we can close it */ - uv_close((uv_handle_t*) &client, close_cb); + cl_recv_cb_called++; + + if (cl_recv_cb_called == 2) { + /* we are done with the server handle, we can close it */ + uv_close((uv_handle_t*) &server, close_cb); + } else { + int r; + char source_addr[64]; + + r = uv_ip4_name((const struct sockaddr_in*)addr, source_addr, sizeof(source_addr)); + ASSERT(r == 0); + + r = uv_udp_set_membership(&server, MULTICAST_ADDR, NULL, UV_LEAVE_GROUP); + ASSERT(r == 0); + + r = uv_udp_set_source_membership(&server, MULTICAST_ADDR, NULL, source_addr, UV_JOIN_GROUP); + ASSERT(r == 0); + + r = do_send(&req_ss); + ASSERT(r == 0); + } } TEST_IMPL(udp_multicast_join) { int r; - uv_udp_send_t req; - uv_buf_t buf; struct sockaddr_in addr; - ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); + ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); r = uv_udp_init(uv_default_loop(), &server); ASSERT(r == 0); @@ -110,27 +148,19 @@ TEST_IMPL(udp_multicast_join) { ASSERT(r == 0); /* bind to the desired port */ - r = uv_udp_bind(&client, (const struct sockaddr*) &addr, 0); + r = uv_udp_bind(&server, (const struct sockaddr*) &addr, 0); ASSERT(r == 0); /* join the multicast channel */ - r = uv_udp_set_membership(&client, "239.255.0.1", NULL, UV_JOIN_GROUP); + r = uv_udp_set_membership(&server, MULTICAST_ADDR, NULL, UV_JOIN_GROUP); if (r == UV_ENODEV) RETURN_SKIP("No multicast support."); ASSERT(r == 0); - r = uv_udp_recv_start(&client, alloc_cb, cl_recv_cb); + r = uv_udp_recv_start(&server, alloc_cb, cl_recv_cb); ASSERT(r == 0); - buf = uv_buf_init("PING", 4); - - /* server sends "PING" */ - r = uv_udp_send(&req, - &server, - &buf, - 1, - (const struct sockaddr*) &addr, - sv_send_cb); + r = do_send(&req); ASSERT(r == 0); ASSERT(close_cb_called == 0); @@ -140,8 +170,8 @@ TEST_IMPL(udp_multicast_join) { /* run the loop till all events are processed */ uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(cl_recv_cb_called == 1); - ASSERT(sv_send_cb_called == 1); + ASSERT(cl_recv_cb_called == 2); + ASSERT(sv_send_cb_called == 2); ASSERT(close_cb_called == 2); MAKE_VALGRIND_HAPPY(); diff --git a/deps/uv/test/test-udp-multicast-join6.c b/deps/uv/test/test-udp-multicast-join6.c index bda5e20ea704..edcd371b2c22 100644 --- a/deps/uv/test/test-udp-multicast-join6.c +++ b/deps/uv/test/test-udp-multicast-join6.c @@ -30,8 +30,23 @@ #define CHECK_HANDLE(handle) \ ASSERT((uv_udp_t*)(handle) == &server || (uv_udp_t*)(handle) == &client) +#if defined(__APPLE__) || \ + defined(_AIX) || \ + defined(__MVS__) || \ + defined(__FreeBSD_kernel__) || \ + defined(__NetBSD__) || \ + defined(__OpenBSD__) + #define MULTICAST_ADDR "ff02::1%lo0" + #define INTERFACE_ADDR "::1%lo0" +#else + #define MULTICAST_ADDR "ff02::1" + #define INTERFACE_ADDR NULL +#endif + static uv_udp_t server; static uv_udp_t client; +static uv_udp_send_t req; +static uv_udp_send_t req_ss; static int cl_recv_cb_called; @@ -63,7 +78,26 @@ static void sv_send_cb(uv_udp_send_t* req, int status) { sv_send_cb_called++; - uv_close((uv_handle_t*) req->handle, close_cb); + if (sv_send_cb_called == 2) + uv_close((uv_handle_t*) req->handle, close_cb); +} + + +static int do_send(uv_udp_send_t* send_req) { + uv_buf_t buf; + struct sockaddr_in6 addr; + + buf = uv_buf_init("PING", 4); + + ASSERT(0 == uv_ip6_addr(MULTICAST_ADDR, TEST_PORT, &addr)); + + /* client sends "PING" */ + return uv_udp_send(send_req, + &client, + &buf, + 1, + (const struct sockaddr*) &addr, + sv_send_cb); } @@ -75,8 +109,6 @@ static void cl_recv_cb(uv_udp_t* handle, CHECK_HANDLE(handle); ASSERT(flags == 0); - cl_recv_cb_called++; - if (nread < 0) { ASSERT(0 && "unexpected error"); } @@ -91,21 +123,57 @@ static void cl_recv_cb(uv_udp_t* handle, ASSERT(nread == 4); ASSERT(!memcmp("PING", buf->base, nread)); - /* we are done with the client handle, we can close it */ - uv_close((uv_handle_t*) &client, close_cb); + cl_recv_cb_called++; + + if (cl_recv_cb_called == 2) { + /* we are done with the server handle, we can close it */ + uv_close((uv_handle_t*) &server, close_cb); + } else { + int r; + char source_addr[64]; + + r = uv_ip6_name((const struct sockaddr_in6*)addr, source_addr, sizeof(source_addr)); + ASSERT(r == 0); + + r = uv_udp_set_membership(&server, MULTICAST_ADDR, INTERFACE_ADDR, UV_LEAVE_GROUP); + ASSERT(r == 0); + + r = uv_udp_set_source_membership(&server, MULTICAST_ADDR, INTERFACE_ADDR, source_addr, UV_JOIN_GROUP); + ASSERT(r == 0); + + r = do_send(&req_ss); + ASSERT(r == 0); + } +} + + +static int can_ipv6_external(void) { + uv_interface_address_t* addr; + int supported; + int count; + int i; + + if (uv_interface_addresses(&addr, &count)) + return 0; /* Assume no IPv6 support on failure. */ + + supported = 0; + for (i = 0; supported == 0 && i < count; i += 1) + supported = (AF_INET6 == addr[i].address.address6.sin6_family && + !addr[i].is_internal); + + uv_free_interface_addresses(addr, count); + return supported; } TEST_IMPL(udp_multicast_join6) { int r; - uv_udp_send_t req; - uv_buf_t buf; struct sockaddr_in6 addr; - if (!can_ipv6()) - RETURN_SKIP("IPv6 not supported"); + if (!can_ipv6_external()) + RETURN_SKIP("No external IPv6 interface available"); - ASSERT(0 == uv_ip6_addr("::1", TEST_PORT, &addr)); + ASSERT(0 == uv_ip6_addr("::", TEST_PORT, &addr)); r = uv_udp_init(uv_default_loop(), &server); ASSERT(r == 0); @@ -114,20 +182,10 @@ TEST_IMPL(udp_multicast_join6) { ASSERT(r == 0); /* bind to the desired port */ - r = uv_udp_bind(&client, (const struct sockaddr*) &addr, 0); + r = uv_udp_bind(&server, (const struct sockaddr*) &addr, 0); ASSERT(r == 0); - /* join the multicast channel */ -#if defined(__APPLE__) || \ - defined(_AIX) || \ - defined(__MVS__) || \ - defined(__FreeBSD_kernel__) || \ - defined(__NetBSD__) || \ - defined(__OpenBSD__) - r = uv_udp_set_membership(&client, "ff02::1", "::1%lo0", UV_JOIN_GROUP); -#else - r = uv_udp_set_membership(&client, "ff02::1", NULL, UV_JOIN_GROUP); -#endif + r = uv_udp_set_membership(&server, MULTICAST_ADDR, INTERFACE_ADDR, UV_JOIN_GROUP); if (r == UV_ENODEV) { MAKE_VALGRIND_HAPPY(); RETURN_SKIP("No ipv6 multicast route"); @@ -135,18 +193,10 @@ TEST_IMPL(udp_multicast_join6) { ASSERT(r == 0); - r = uv_udp_recv_start(&client, alloc_cb, cl_recv_cb); + r = uv_udp_recv_start(&server, alloc_cb, cl_recv_cb); ASSERT(r == 0); - buf = uv_buf_init("PING", 4); - - /* server sends "PING" */ - r = uv_udp_send(&req, - &server, - &buf, - 1, - (const struct sockaddr*) &addr, - sv_send_cb); + r = do_send(&req); ASSERT(r == 0); ASSERT(close_cb_called == 0); @@ -156,8 +206,8 @@ TEST_IMPL(udp_multicast_join6) { /* run the loop till all events are processed */ uv_run(uv_default_loop(), UV_RUN_DEFAULT); - ASSERT(cl_recv_cb_called == 1); - ASSERT(sv_send_cb_called == 1); + ASSERT(cl_recv_cb_called == 2); + ASSERT(sv_send_cb_called == 2); ASSERT(close_cb_called == 2); MAKE_VALGRIND_HAPPY(); diff --git a/deps/uv/test/test.gyp b/deps/uv/test/test.gyp index 6158a2b8b660..60792ad6ebbb 100644 --- a/deps/uv/test/test.gyp +++ b/deps/uv/test/test.gyp @@ -99,6 +99,7 @@ 'test-shutdown-twice.c', 'test-signal.c', 'test-signal-multiple-loops.c', + 'test-signal-pending-on-close.c', 'test-socket-buffer-size.c', 'test-spawn.c', 'test-strscpy.c', @@ -108,6 +109,7 @@ 'test-tcp-bind6-error.c', 'test-tcp-close.c', 'test-tcp-close-accept.c', + 'test-tcp-close-reset.c', 'test-tcp-close-while-connecting.c', 'test-tcp-create-socket-early.c', 'test-tcp-connect-error-after-write.c', diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index 78a83587ba90..810c1004cd93 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -20,6 +20,7 @@ '_UNIX03_SOURCE', '_UNIX03_WITHDRAWN', '_OPEN_SYS_IF_EXT', + '_OPEN_SYS_SOCK_EXT3', '_OPEN_SYS_SOCK_IPV6', '_OPEN_MSGQ_EXT', '_XOPEN_SOURCE_EXTENDED', From 3d098e3503f4b6453e3032890e0df831bb5c13ed Mon Sep 17 00:00:00 2001 From: cjihrig Date: Sat, 19 Oct 2019 16:46:32 -0500 Subject: [PATCH 6/9] deps: upgrade to libuv 1.33.1 Notable changes: - uv_random() has been added. - More work to read those pesky Windows environment variables. - Several build fixes for Tier 3 platforms (Android, NetBSD, OpenBSD, Haiku). - Stop using fsevents to watch files (using kqueue again). PR-URL: https://github.com/nodejs/node/pull/29996 Reviewed-By: Richard Lau Reviewed-By: Anna Henningsen Reviewed-By: David Carlier Reviewed-By: Trivikram Kamat Reviewed-By: Jiawen Geng Reviewed-By: James M Snell Reviewed-By: Gireesh Punathil --- deps/uv/AUTHORS | 8 ++ deps/uv/CMakeLists.txt | 42 ++++-- deps/uv/ChangeLog | 80 +++++++++++ deps/uv/Makefile.am | 18 ++- deps/uv/SUPPORTED_PLATFORMS.md | 7 +- deps/uv/configure.ac | 4 +- deps/uv/docs/src/fs.rst | 14 +- deps/uv/docs/src/handle.rst | 14 +- deps/uv/docs/src/misc.rst | 45 ++++++ deps/uv/docs/src/tty.rst | 39 ++++++ deps/uv/include/uv.h | 41 ++++++ deps/uv/include/uv/version.h | 4 +- deps/uv/src/random.c | 121 ++++++++++++++++ deps/uv/src/threadpool.c | 4 + deps/uv/src/unix/android-ifaddrs.c | 2 + deps/uv/src/unix/bsd-ifaddrs.c | 2 + deps/uv/src/unix/core.c | 6 +- deps/uv/src/unix/darwin-proctitle.c | 139 +++++++++---------- deps/uv/src/unix/fs.c | 30 ++-- deps/uv/src/unix/fsevents.c | 6 +- deps/uv/src/unix/internal.h | 6 + deps/uv/src/unix/kqueue.c | 44 +++--- deps/uv/src/unix/linux-core.c | 53 +++++-- deps/uv/src/unix/linux-syscalls.c | 25 ++++ deps/uv/src/unix/linux-syscalls.h | 1 + deps/uv/src/unix/openbsd.c | 2 +- deps/uv/src/unix/pipe.c | 2 +- deps/uv/src/unix/proctitle.c | 4 + deps/uv/src/unix/random-devurandom.c | 93 +++++++++++++ deps/uv/src/unix/random-getentropy.c | 57 ++++++++ deps/uv/src/unix/random-getrandom.c | 88 ++++++++++++ deps/uv/src/unix/random-sysctl.c | 100 +++++++++++++ deps/uv/src/unix/tty.c | 7 + deps/uv/src/unix/udp.c | 22 +-- deps/uv/src/uv-common.c | 3 + deps/uv/src/win/fs.c | 17 +-- deps/uv/src/win/internal.h | 2 + deps/uv/src/win/tcp.c | 2 +- deps/uv/src/win/tty.c | 44 +++--- deps/uv/src/win/udp.c | 2 +- deps/uv/src/win/util.c | 17 ++- deps/uv/src/win/winapi.c | 11 ++ deps/uv/src/win/winapi.h | 8 ++ deps/uv/src/win/winsock.h | 8 ++ deps/uv/test/test-env-vars.c | 8 +- deps/uv/test/test-fs-copyfile.c | 2 +- deps/uv/test/test-fs-event.c | 72 +++++++--- deps/uv/test/test-fs-readdir.c | 2 +- deps/uv/test/test-ip4-addr.c | 4 + deps/uv/test/test-ip6-addr.c | 9 ++ deps/uv/test/test-list.h | 8 ++ deps/uv/test/test-process-title-threadsafe.c | 6 +- deps/uv/test/test-random.c | 94 +++++++++++++ deps/uv/test/test-threadpool-cancel.c | 41 ++++++ deps/uv/test/test-udp-multicast-join.c | 2 +- deps/uv/test/test-udp-multicast-join6.c | 4 +- deps/uv/test/test.gyp | 4 +- deps/uv/uv.gyp | 15 +- 58 files changed, 1282 insertions(+), 233 deletions(-) create mode 100644 deps/uv/src/random.c create mode 100644 deps/uv/src/unix/random-devurandom.c create mode 100644 deps/uv/src/unix/random-getentropy.c create mode 100644 deps/uv/src/unix/random-getrandom.c create mode 100644 deps/uv/src/unix/random-sysctl.c create mode 100644 deps/uv/test/test-random.c diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS index 8c3d342d33e6..408cfd6541a3 100644 --- a/deps/uv/AUTHORS +++ b/deps/uv/AUTHORS @@ -403,3 +403,11 @@ Vladimir Karnushin MaYuming Eneas U de Queiroz Daniel Hahler +Yang Yu +David Carlier +Calvin Hill +Isabella Muerte <63051+slurps-mad-rips@users.noreply.github.com> +Ouyang Yadong +ZYSzys +Carl Lei +Stefan Bender diff --git a/deps/uv/CMakeLists.txt b/deps/uv/CMakeLists.txt index 6f18f3397d01..7da5e688166c 100644 --- a/deps/uv/CMakeLists.txt +++ b/deps/uv/CMakeLists.txt @@ -1,6 +1,15 @@ # TODO: determine CMAKE_SYSTEM_NAME on OS/390. Currently assumes "OS/390". -cmake_minimum_required(VERSION 2.8.12) -project(libuv) +cmake_minimum_required(VERSION 3.4) +project(libuv LANGUAGES C) + +include(CMakePackageConfigHelpers) +include(CMakeDependentOption) +include(GNUInstallDirs) +include(CTest) + +cmake_dependent_option(LIBUV_BUILD_TESTS + "Build the unit tests when BUILD_TESTING is enabled and we are the root project" ON + "BUILD_TESTING;CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF) if(MSVC) list(APPEND uv_cflags /W4) @@ -14,6 +23,7 @@ set(uv_sources src/fs-poll.c src/idna.c src/inet.c + src/random.c src/strscpy.c src/threadpool.c src/timer.c @@ -72,7 +82,6 @@ set(uv_test_sources test/test-idna.c test/test-ip4-addr.c test/test-ip6-addr.c - test/test-ip6-addr.c test/test-ipc-heavy-traffic-deadlock-bug.c test/test-ipc-send-recv.c test/test-ipc.c @@ -108,6 +117,7 @@ set(uv_test_sources test/test-process-title-threadsafe.c test/test-process-title.c test/test-queue-foreach-delete.c + test/test-random.c test/test-ref.c test/test-run-nowait.c test/test-run-once.c @@ -236,6 +246,7 @@ else() src/unix/pipe.c src/unix/poll.c src/unix/process.c + src/unix/random-devurandom.c src/unix/signal.c src/unix/stream.c src/unix/tcp.c @@ -284,6 +295,14 @@ if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD|NetBSD|OpenBSD") list(APPEND uv_sources src/unix/bsd-ifaddrs.c src/unix/kqueue.c) endif() +if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + list(APPEND uv_sources src/unix/random-getrandom.c) +endif() + +if(APPLE OR CMAKE_SYSTEM_NAME STREQUAL "OpenBSD") + list(APPEND uv_sources src/unix/random-getentropy.c) +endif() + if(APPLE) list(APPEND uv_defines _DARWIN_UNLIMITED_SELECT=1 _DARWIN_USE_64_BIT_INODE=1) list(APPEND uv_sources @@ -300,6 +319,8 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux") src/unix/linux-inotify.c src/unix/linux-syscalls.c src/unix/procfs-exepath.c + src/unix/random-getrandom.c + src/unix/random-sysctl.c src/unix/sysinfo-loadavg.c) endif() @@ -356,11 +377,7 @@ target_compile_options(uv_a PRIVATE ${uv_cflags}) target_include_directories(uv_a PUBLIC include PRIVATE src) target_link_libraries(uv_a ${uv_libraries}) -option(libuv_buildtests "Build the unit tests when BUILD_TESTING is enabled." ON) - -include(CTest) -if(BUILD_TESTING AND libuv_buildtests) - enable_testing() +if(LIBUV_BUILD_TESTS) add_executable(uv_run_tests ${uv_test_sources}) target_compile_definitions(uv_run_tests PRIVATE ${uv_defines} USING_UV_SHARED=1) @@ -380,7 +397,6 @@ endif() if(UNIX) # Now for some gibbering horrors from beyond the stars... - include(GNUInstallDirs) foreach(x ${uv_libraries}) set(LIBS "${LIBS} -l${x}") endforeach(x) @@ -402,3 +418,11 @@ if(UNIX) install(TARGETS uv LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) install(TARGETS uv_a ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif() + +if(WIN32) + install(DIRECTORY include/ DESTINATION include) + install(FILES LICENSE DESTINATION .) + install(TARGETS uv uv_a + RUNTIME DESTINATION lib/$ + ARCHIVE DESTINATION lib/$) +endif() diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index 093579de8e49..cd4451ae69c0 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,3 +1,83 @@ +2019.10.20, Version 1.33.1 (Stable), 07ad32138f4d2285ba2226b5e20462b27b091a59 + +Changes since version 1.33.0: + +* linux: fix arm64 SYS__sysctl build breakage (Ben Noordhuis) + + +2019.10.17, Version 1.33.0 (Stable), e56e42e9310e4437e1886dbd6771792c14c0a5f3 + +Changes since version 1.32.0: + +* Revert "linux: drop code path for epoll_pwait-less kernels" (Yang Yu) + +* build: fix build error with __ANDROID_API__ < 21 (Yang Yu) + +* win: fix reading hidden env vars (Anna Henningsen) + +* unix,win: add uv_random() (Ben Noordhuis) + +* win: simplify mkdtemp (Saúl Ibarra Corretgé) + +* docs: fix literal-includes in User Guide (Nhan Khong) + +* win, tty: fix problem of receiving unexpected SIGWINCH (erw7) + +* unix: fix {Net,Open}BSD build (David Carlier) + +* win,mingw: Fix undefined MCAST_* constants (Crunkle) + +* build: Add link for test/fixtures/lorem_ipsum.txt (Andrew Paprocki) + +* fs: use statvfs in uv__fs_statfs() for Haiku (Calvin Hill) + +* fsevents: stop using fsevents to watch files (Jameson Nash) + +* fsevents: regression in watching / (Jameson Nash) + +* build,cmake: don't try to detect a C++ compiler (Isabella Muerte) + +* build: fix build warning on cygwin (MaYuming) + +* unix: set sin_len and sin6_len (Ouyang Yadong) + +* test: fix order of operations in test (cjihrig) + +* doc: improve uv_fs_readdir() cleanup docs (cjihrig) + +* build: remove duplicated test in build files (ZYSzys) + +* android: enable getentropy on Android >= 28 (David Carlier) + +* android: fix build (David Carlier) + +* darwin: speed up uv_set_process_title() (Ben Noordhuis) + +* darwin: assume pthread_setname_np() is available (Ben Noordhuis) + +* unix,udp: ensure addr is non-null (Jameson Nash) + +* win,tty: add uv_tty_{get,set}_vterm_state (erw7) + +* win: fix uv_statfs_t leak in uv_fs_statfs() (Ryan Liptak) + +* build: install files on windows via cmake (Carl Lei) + +* darwin,test: include AvailabilityMacros.h (Saúl Ibarra Corretgé) + +* darwin,test: update loop time after sleeping (Saúl Ibarra Corretgé) + +* doc: remove old FreeBSD 9 related note (Saúl Ibarra Corretgé) + +* doc: improve uv_{send,recv}_buffer_size() docs (Ryan Liptak) + +* build: move -Wno-long-long check to configure time (Ben Noordhuis) + +* unix: update uv_fs_copyfile() fallback logic (Stefan Bender) + +* win: cast setsockopt struct to const char* (Shelley Vohr) + + 2019.09.10, Version 1.32.0 (Stable), 697bea87b3a0b0e9b4e5ff86b39d1dedb70ee46d Changes since version 1.31.0: diff --git a/deps/uv/Makefile.am b/deps/uv/Makefile.am index 099b0efb0843..ce4ca274b217 100644 --- a/deps/uv/Makefile.am +++ b/deps/uv/Makefile.am @@ -35,6 +35,7 @@ libuv_la_SOURCES = src/fs-poll.c \ src/idna.h \ src/inet.c \ src/queue.h \ + src/random.c \ src/strscpy.c \ src/strscpy.h \ src/threadpool.c \ @@ -105,6 +106,7 @@ libuv_la_SOURCES += src/unix/async.c \ src/unix/pipe.c \ src/unix/poll.c \ src/unix/process.c \ + src/unix/random-devurandom.c \ src/unix/signal.c \ src/unix/spinlock.h \ src/unix/stream.c \ @@ -138,11 +140,7 @@ EXTRA_DIST = test/fixtures/empty_file \ TESTS = test/run-tests check_PROGRAMS = test/run-tests -if OS390 test_run_tests_CFLAGS = -else -test_run_tests_CFLAGS = -Wno-long-long -endif if SUNOS # Can't be turned into a CC_CHECK_CFLAGS in configure.ac, it makes compilers @@ -240,6 +238,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/test-process-title.c \ test/test-process-title-threadsafe.c \ test/test-queue-foreach-delete.c \ + test/test-random.c \ test/test-ref.c \ test/test-run-nowait.c \ test/test-run-once.c \ @@ -414,7 +413,8 @@ libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \ src/unix/darwin-proctitle.c \ src/unix/fsevents.c \ src/unix/kqueue.c \ - src/unix/proctitle.c + src/unix/proctitle.c \ + src/unix/random-getentropy.c test_run_tests_LDFLAGS += -lutil endif @@ -434,7 +434,8 @@ libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \ src/unix/bsd-proctitle.c \ src/unix/freebsd.c \ src/unix/kqueue.c \ - src/unix/posix-hrtime.c + src/unix/posix-hrtime.c \ + src/unix/random-getrandom.c test_run_tests_LDFLAGS += -lutil endif @@ -465,6 +466,8 @@ libuv_la_SOURCES += src/unix/linux-core.c \ src/unix/linux-syscalls.h \ src/unix/procfs-exepath.c \ src/unix/proctitle.c \ + src/unix/random-getrandom.c \ + src/unix/random-sysctl.c \ src/unix/sysinfo-loadavg.c test_run_tests_LDFLAGS += -lutil endif @@ -498,7 +501,8 @@ libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \ src/unix/bsd-proctitle.c \ src/unix/kqueue.c \ src/unix/openbsd.c \ - src/unix/posix-hrtime.c + src/unix/posix-hrtime.c \ + src/unix/random-getentropy.c test_run_tests_LDFLAGS += -lutil endif diff --git a/deps/uv/SUPPORTED_PLATFORMS.md b/deps/uv/SUPPORTED_PLATFORMS.md index 077191086ce5..29e4844ff323 100644 --- a/deps/uv/SUPPORTED_PLATFORMS.md +++ b/deps/uv/SUPPORTED_PLATFORMS.md @@ -5,7 +5,7 @@ | GNU/Linux | Tier 1 | Linux >= 2.6.32 with glibc >= 2.12 | | | macOS | Tier 1 | macOS >= 10.7 | | | Windows | Tier 1 | >= Windows 7 | MSVC 2008 and later are supported | -| FreeBSD | Tier 1 | >= 9 (see note) | | +| FreeBSD | Tier 1 | >= 10 | | | AIX | Tier 2 | >= 6 | Maintainers: @libuv/aix | | z/OS | Tier 2 | >= V2R2 | Maintainers: @libuv/zos | | Linux with musl | Tier 2 | musl >= 1.0 | | @@ -16,11 +16,6 @@ | SunOS | Tier 3 | Solaris 121 and later | | | Other | Tier 3 | N/A | | -#### Note on FreeBSD 9 - -While FreeBSD is supported as Tier 1, FreeBSD 9 will get Tier 2 support until -it reaches end of life, in December 2016. - ## Support types * **Tier 1**: Officially supported and tested with CI. Any contributed patch diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac index b503e538298d..07ad0cde81a6 100644 --- a/deps/uv/configure.ac +++ b/deps/uv/configure.ac @@ -13,7 +13,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. AC_PREREQ(2.57) -AC_INIT([libuv], [1.32.0], [https://github.com/libuv/libuv/issues]) +AC_INIT([libuv], [1.33.1], [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]) @@ -32,6 +32,7 @@ CC_CHECK_CFLAGS_APPEND([-g]) CC_CHECK_CFLAGS_APPEND([-std=gnu89]) CC_CHECK_CFLAGS_APPEND([-Wall]) CC_CHECK_CFLAGS_APPEND([-Wextra]) +CC_CHECK_CFLAGS_APPEND([-Wno-long-long]) CC_CHECK_CFLAGS_APPEND([-Wno-unused-parameter]) CC_CHECK_CFLAGS_APPEND([-Wstrict-prototypes]) # AM_PROG_AR is not available in automake v0.11 but it's essential in v0.12. @@ -80,4 +81,5 @@ AC_CHECK_HEADERS([sys/ahafs_evProds.h]) AC_CONFIG_FILES([Makefile libuv.pc]) AC_CONFIG_LINKS([test/fixtures/empty_file:test/fixtures/empty_file]) AC_CONFIG_LINKS([test/fixtures/load_error.node:test/fixtures/load_error.node]) +AC_CONFIG_LINKS([test/fixtures/lorem_ipsum.txt:test/fixtures/lorem_ipsum.txt]) AC_OUTPUT diff --git a/deps/uv/docs/src/fs.rst b/deps/uv/docs/src/fs.rst index aabe49b3f3a9..dc16ff08e65a 100644 --- a/deps/uv/docs/src/fs.rst +++ b/deps/uv/docs/src/fs.rst @@ -295,7 +295,8 @@ API .. note:: On success this function allocates memory that must be freed using - `uv_fs_req_cleanup()`. + `uv_fs_req_cleanup()`. `uv_fs_req_cleanup()` must be called before + closing the directory with `uv_fs_closedir()`. .. c:function:: int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, uv_fs_cb cb) .. c:function:: int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) @@ -358,10 +359,13 @@ API is to overwrite the destination if it exists. - `UV_FS_COPYFILE_FICLONE`: If present, `uv_fs_copyfile()` will attempt to create a copy-on-write reflink. If the underlying platform does not - support copy-on-write, then a fallback copy mechanism is used. + support copy-on-write, or an error occurs while attempting to use + copy-on-write, a fallback copy mechanism based on + :c:func:`uv_fs_sendfile()` is used. - `UV_FS_COPYFILE_FICLONE_FORCE`: If present, `uv_fs_copyfile()` will attempt to create a copy-on-write reflink. If the underlying platform does - not support copy-on-write, then an error is returned. + not support copy-on-write, or an error occurs while attempting to use + copy-on-write, then an error is returned. .. warning:: If the destination path is created, but an error occurs while copying @@ -374,6 +378,10 @@ API .. versionchanged:: 1.20.0 `UV_FS_COPYFILE_FICLONE` and `UV_FS_COPYFILE_FICLONE_FORCE` are supported. + .. versionchanged:: 1.33.0 If an error occurs while using + `UV_FS_COPYFILE_FICLONE_FORCE`, that error is returned. Previously, + all errors were mapped to `UV_ENOTSUP`. + .. c:function:: int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file out_fd, uv_file in_fd, int64_t in_offset, size_t length, uv_fs_cb cb) Limited equivalent to :man:`sendfile(2)`. diff --git a/deps/uv/docs/src/handle.rst b/deps/uv/docs/src/handle.rst index 0a25bfa8b27d..943c51d94ba6 100644 --- a/deps/uv/docs/src/handle.rst +++ b/deps/uv/docs/src/handle.rst @@ -190,8 +190,11 @@ just for some handle types. Gets or sets the size of the send buffer that the operating system uses for the socket. - If `*value` == 0, it will return the current send buffer size, - otherwise it will use `*value` to set the new send buffer size. + If `*value` == 0, then it will set `*value` to the current send buffer size. + If `*value` > 0 then it will use `*value` to set the new send buffer size. + + On success, zero is returned. On error, a negative result is + returned. This function works for TCP, pipe and UDP handles on Unix and for TCP and UDP handles on Windows. @@ -204,8 +207,11 @@ just for some handle types. Gets or sets the size of the receive buffer that the operating system uses for the socket. - If `*value` == 0, it will return the current receive buffer size, - otherwise it will use `*value` to set the new receive buffer size. + If `*value` == 0, then it will set `*value` to the current receive buffer size. + If `*value` > 0 then it will use `*value` to set the new receive buffer size. + + On success, zero is returned. On error, a negative result is + returned. This function works for TCP, pipe and UDP handles on Unix and for TCP and UDP handles on Windows. diff --git a/deps/uv/docs/src/misc.rst b/deps/uv/docs/src/misc.rst index 3ecfce486c4d..8e167e3ec4ec 100644 --- a/deps/uv/docs/src/misc.rst +++ b/deps/uv/docs/src/misc.rst @@ -46,6 +46,12 @@ Data types Replacement function for :man:`free(3)`. See :c:func:`uv_replace_allocator`. +.. c:type:: void (*uv_random_cb)(uv_random_t* req, int status, void* buf, size_t buflen) + + Callback passed to :c:func:`uv_random`. `status` is non-zero in case of + error. The `buf` pointer is the same pointer that was passed to + :c:func:`uv_random`. + .. c:type:: uv_file Cross platform representation of a file handle. @@ -191,6 +197,9 @@ Data types char* value; } uv_env_item_t; +.. c:type:: uv_random_t + + Random data request type. API --- @@ -648,3 +657,39 @@ API argument to `gettimeofday()` is not supported, as it is considered obsolete. .. versionadded:: 1.28.0 + +.. c:function:: int uv_random(uv_loop_t* loop, uv_random_t* req, void* buf, size_t buflen, unsigned int flags, uv_random_cb cb) + + Fill `buf` with exactly `buflen` cryptographically strong random bytes + acquired from the system CSPRNG. `flags` is reserved for future extension + and must currently be 0. + + Short reads are not possible. When less than `buflen` random bytes are + available, a non-zero error value is returned or passed to the callback. + + The synchronous version may block indefinitely when not enough entropy + is available. The asynchronous version may not ever finish when the system + is low on entropy. + + Sources of entropy: + + - Windows: `RtlGenRandom _`. + - Linux, Android: :man:`getrandom(2)` if available, or :man:`urandom(4)` + after reading from `/dev/random` once, or the `KERN_RANDOM` + :man:`sysctl(2)`. + - FreeBSD: `getrandom(2) _`, + or `/dev/urandom` after reading from `/dev/random` once. + - macOS, OpenBSD: `getentropy(2) _` + if available, or `/dev/urandom` after reading from `/dev/random` once. + - AIX: `/dev/random`. + - IBM i: `/dev/urandom`. + - Other UNIX: `/dev/urandom` after reading from `/dev/random` once. + + :returns: 0 on success, or an error code < 0 on failure. The contents of + `buf` is undefined after an error. + + .. note:: + When using the synchronous version, both `loop` and `req` parameters + are not used and can be set to `NULL`. + + .. versionadded:: 1.33.0 diff --git a/deps/uv/docs/src/tty.rst b/deps/uv/docs/src/tty.rst index 9889a0a0b646..ad379dab0dd0 100644 --- a/deps/uv/docs/src/tty.rst +++ b/deps/uv/docs/src/tty.rst @@ -33,6 +33,23 @@ Data types UV_TTY_MODE_IO } uv_tty_mode_t; +.. c:type:: uv_tty_vtermstate_t + Console virtual terminal mode type: + + :: + + typedef enum { + /* + * The console supports handling of virtual terminal sequences + * (Windows10 new console, ConEmu) + */ + UV_TTY_SUPPORTED, + /* The console cannot process virtual terminal sequences. (Legacy + * console) + */ + UV_TTY_UNSUPPORTED + } uv_tty_vtermstate_t + Public members @@ -98,3 +115,25 @@ API Gets the current Window size. On success it returns 0. .. seealso:: The :c:type:`uv_stream_t` API functions also apply. + +.. c:function:: void uv_tty_set_vterm_state(uv_tty_vtermstate_t state) + + Controls whether console virtual terminal sequences are processed by libuv + or console. + Useful in particular for enabling ConEmu support of ANSI X3.64 and Xterm + 256 colors. Otherwise Windows10 consoles are usually detected automatically. + + This function is only meaningful on Windows systems. On Unix it is silently + ignored. + + .. versionadded:: 1.33.0 + +.. c:function:: int uv_tty_get_vterm_state(uv_tty_vtermstate_t* state) + + Get the current state of whether console virtual terminal sequences are + handled by libuv or the console. + + This function is not implemented on Unix, where it returns ``UV_ENOTSUP``. + + .. versionadded:: 1.33.0 + diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index ee45bcaefce1..0e8132e4384b 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -177,6 +177,7 @@ extern "C" { XX(WORK, work) \ XX(GETADDRINFO, getaddrinfo) \ XX(GETNAMEINFO, getnameinfo) \ + XX(RANDOM, random) \ typedef enum { #define XX(code, _) UV_ ## code = UV__ ## code, @@ -234,6 +235,7 @@ typedef struct uv_connect_s uv_connect_t; typedef struct uv_udp_send_s uv_udp_send_t; typedef struct uv_fs_s uv_fs_t; typedef struct uv_work_s uv_work_t; +typedef struct uv_random_s uv_random_t; /* None of the above. */ typedef struct uv_env_item_s uv_env_item_t; @@ -330,6 +332,10 @@ typedef void (*uv_getnameinfo_cb)(uv_getnameinfo_t* req, int status, const char* hostname, const char* service); +typedef void (*uv_random_cb)(uv_random_t* req, + int status, + void* buf, + size_t buflen); typedef struct { long tv_sec; @@ -700,10 +706,25 @@ typedef enum { UV_TTY_MODE_IO } uv_tty_mode_t; +typedef enum { + /* + * The console supports handling of virtual terminal sequences + * (Windows10 new console, ConEmu) + */ + UV_TTY_SUPPORTED, + /* The console cannot process the virtual terminal sequence. (Legacy + * console) + */ + UV_TTY_UNSUPPORTED +} uv_tty_vtermstate_t; + + UV_EXTERN int uv_tty_init(uv_loop_t*, uv_tty_t*, uv_file fd, int readable); UV_EXTERN int uv_tty_set_mode(uv_tty_t*, uv_tty_mode_t mode); UV_EXTERN int uv_tty_reset_mode(void); UV_EXTERN int uv_tty_get_winsize(uv_tty_t*, int* width, int* height); +UV_EXTERN void uv_tty_set_vterm_state(uv_tty_vtermstate_t state); +UV_EXTERN int uv_tty_get_vterm_state(uv_tty_vtermstate_t* state); #ifdef __cplusplus extern "C++" { @@ -1574,6 +1595,26 @@ UV_EXTERN int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size UV_EXTERN int uv_inet_ntop(int af, const void* src, char* dst, size_t size); UV_EXTERN int uv_inet_pton(int af, const char* src, void* dst); + +struct uv_random_s { + UV_REQ_FIELDS + /* read-only */ + uv_loop_t* loop; + /* private */ + int status; + void* buf; + size_t buflen; + uv_random_cb cb; + struct uv__work work_req; +}; + +UV_EXTERN int uv_random(uv_loop_t* loop, + uv_random_t* req, + void *buf, + size_t buflen, + unsigned flags, /* For future extension; must be 0. */ + uv_random_cb cb); + #if defined(IF_NAMESIZE) # define UV_IF_NAMESIZE (IF_NAMESIZE + 1) #elif defined(IFNAMSIZ) diff --git a/deps/uv/include/uv/version.h b/deps/uv/include/uv/version.h index 928647b82005..ca94be6dd4fb 100644 --- a/deps/uv/include/uv/version.h +++ b/deps/uv/include/uv/version.h @@ -31,8 +31,8 @@ */ #define UV_VERSION_MAJOR 1 -#define UV_VERSION_MINOR 32 -#define UV_VERSION_PATCH 0 +#define UV_VERSION_MINOR 33 +#define UV_VERSION_PATCH 1 #define UV_VERSION_IS_RELEASE 1 #define UV_VERSION_SUFFIX "" diff --git a/deps/uv/src/random.c b/deps/uv/src/random.c new file mode 100644 index 000000000000..8c4fe32013dc --- /dev/null +++ b/deps/uv/src/random.c @@ -0,0 +1,121 @@ +/* Copyright libuv contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "uv-common.h" + +#ifdef _WIN32 +# include "win/internal.h" +#else +# include "unix/internal.h" +#endif + +static int uv__random(void* buf, size_t buflen) { + int rc; + +#if defined(__PASE__) + rc = uv__random_readpath("/dev/urandom", buf, buflen); +#elif defined(_AIX) + rc = uv__random_readpath("/dev/random", buf, buflen); +#elif defined(__APPLE__) || defined(__OpenBSD__) || \ + (defined(__ANDROID_API__) && __ANDROID_API__ >= 28) + rc = uv__random_getentropy(buf, buflen); + if (rc == UV_ENOSYS) + rc = uv__random_devurandom(buf, buflen); +#elif defined(__FreeBSD__) || defined(__linux__) + rc = uv__random_getrandom(buf, buflen); + if (rc == UV_ENOSYS) + rc = uv__random_devurandom(buf, buflen); +# if defined(__linux__) + switch (rc) { + case UV_EACCES: + case UV_EIO: + case UV_ELOOP: + case UV_EMFILE: + case UV_ENFILE: + case UV_ENOENT: + case UV_EPERM: + rc = uv__random_sysctl(buf, buflen); + break; + } +# endif +#elif defined(_WIN32) + uv__once_init(); + rc = uv__random_rtlgenrandom(buf, buflen); +#else + rc = uv__random_devurandom(buf, buflen); +#endif + + return rc; +} + + +static void uv__random_work(struct uv__work* w) { + uv_random_t* req; + + req = container_of(w, uv_random_t, work_req); + req->status = uv__random(req->buf, req->buflen); +} + + +static void uv__random_done(struct uv__work* w, int status) { + uv_random_t* req; + + req = container_of(w, uv_random_t, work_req); + uv__req_unregister(req->loop, req); + + if (status == 0) + status = req->status; + + req->cb(req, status, req->buf, req->buflen); +} + + +int uv_random(uv_loop_t* loop, + uv_random_t* req, + void *buf, + size_t buflen, + unsigned flags, + uv_random_cb cb) { + if (buflen > 0x7FFFFFFFu) + return UV_E2BIG; + + if (flags != 0) + return UV_EINVAL; + + if (cb == NULL) + return uv__random(buf, buflen); + + uv__req_init(loop, req, UV_RANDOM); + req->loop = loop; + req->status = 0; + req->cb = cb; + req->buf = buf; + req->buflen = buflen; + + uv__work_submit(loop, + &req->work_req, + UV__WORK_CPU, + uv__random_work, + uv__random_done); + + return 0; +} diff --git a/deps/uv/src/threadpool.c b/deps/uv/src/threadpool.c index 7aa575508fa8..a8f433f05108 100644 --- a/deps/uv/src/threadpool.c +++ b/deps/uv/src/threadpool.c @@ -372,6 +372,10 @@ int uv_cancel(uv_req_t* req) { loop = ((uv_getnameinfo_t*) req)->loop; wreq = &((uv_getnameinfo_t*) req)->work_req; break; + case UV_RANDOM: + loop = ((uv_random_t*) req)->loop; + wreq = &((uv_random_t*) req)->work_req; + break; case UV_WORK: loop = ((uv_work_t*) req)->loop; wreq = &((uv_work_t*) req)->work_req; diff --git a/deps/uv/src/unix/android-ifaddrs.c b/deps/uv/src/unix/android-ifaddrs.c index 99fb25a43b42..7d48c6af57ca 100644 --- a/deps/uv/src/unix/android-ifaddrs.c +++ b/deps/uv/src/unix/android-ifaddrs.c @@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include typedef struct NetlinkList { @@ -475,6 +476,7 @@ static int interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_resultList, l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize)); l_addedNetmask = 1; } + break; case IFA_BROADCAST: l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize)); break; diff --git a/deps/uv/src/unix/bsd-ifaddrs.c b/deps/uv/src/unix/bsd-ifaddrs.c index 0d7bbe662a5c..a3385af17c88 100644 --- a/deps/uv/src/unix/bsd-ifaddrs.c +++ b/deps/uv/src/unix/bsd-ifaddrs.c @@ -69,7 +69,9 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { struct ifaddrs* addrs; struct ifaddrs* ent; uv_interface_address_t* address; +#if !(defined(__CYGWIN__) || defined(__MSYS__)) int i; +#endif *count = 0; *addresses = NULL; diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index 366c43c2ab08..ffce948c9574 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -66,7 +66,8 @@ extern char** environ; #if defined(__DragonFly__) || \ defined(__FreeBSD__) || \ defined(__FreeBSD_kernel__) || \ - defined(__NetBSD__) + defined(__NetBSD__) || \ + defined(__OpenBSD__) # include # include # include @@ -76,7 +77,8 @@ extern char** environ; # if defined(__NetBSD__) # define uv__accept4(a, b, c, d) paccept((a), (b), (c), NULL, (d)) # endif -# if (defined(__FreeBSD__) && __FreeBSD__ >= 10) || defined(__NetBSD__) +# if (defined(__FreeBSD__) && __FreeBSD__ >= 10) || \ + defined(__NetBSD__) || defined(__OpenBSD__) # define UV__SOCK_NONBLOCK SOCK_NONBLOCK # define UV__SOCK_CLOEXEC SOCK_CLOEXEC # endif diff --git a/deps/uv/src/unix/darwin-proctitle.c b/deps/uv/src/unix/darwin-proctitle.c index dabde2239cca..eced23c2da7c 100644 --- a/deps/uv/src/unix/darwin-proctitle.c +++ b/deps/uv/src/unix/darwin-proctitle.c @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -33,61 +34,52 @@ # include #endif +#define S(s) pCFStringCreateWithCString(NULL, (s), kCFStringEncodingUTF8) -static int uv__pthread_setname_np(const char* name) { - int (*dynamic_pthread_setname_np)(const char* name); - char namebuf[64]; /* MAXTHREADNAMESIZE */ - int err; - - /* pthread_setname_np() first appeared in OS X 10.6 and iOS 3.2. */ - *(void **)(&dynamic_pthread_setname_np) = - dlsym(RTLD_DEFAULT, "pthread_setname_np"); - - if (dynamic_pthread_setname_np == NULL) - return UV_ENOSYS; - - strncpy(namebuf, name, sizeof(namebuf) - 1); - namebuf[sizeof(namebuf) - 1] = '\0'; - err = dynamic_pthread_setname_np(namebuf); - if (err) - return UV__ERR(err); +#if !TARGET_OS_IPHONE +static CFStringRef (*pCFStringCreateWithCString)(CFAllocatorRef, + const char*, + CFStringEncoding); +static CFBundleRef (*pCFBundleGetBundleWithIdentifier)(CFStringRef); +static void *(*pCFBundleGetDataPointerForName)(CFBundleRef, CFStringRef); +static void *(*pCFBundleGetFunctionPointerForName)(CFBundleRef, CFStringRef); +static CFTypeRef (*pLSGetCurrentApplicationASN)(void); +static OSStatus (*pLSSetApplicationInformationItem)(int, + CFTypeRef, + CFStringRef, + CFStringRef, + CFDictionaryRef*); +static void* application_services_handle; +static void* core_foundation_handle; +static CFBundleRef launch_services_bundle; +static CFStringRef* display_name_key; +static CFDictionaryRef (*pCFBundleGetInfoDictionary)(CFBundleRef); +static CFBundleRef (*pCFBundleGetMainBundle)(void); +static CFBundleRef hi_services_bundle; +static CFDictionaryRef (*pLSApplicationCheckIn)(int, CFDictionaryRef); +static void (*pLSSetApplicationLaunchServicesServerConnectionStatus)(uint64_t, + void*); + + +UV_DESTRUCTOR(static void uv__set_process_title_platform_fini(void)) { + if (core_foundation_handle != NULL) { + dlclose(core_foundation_handle); + core_foundation_handle = NULL; + } - return 0; + if (application_services_handle != NULL) { + dlclose(application_services_handle); + application_services_handle = NULL; + } } +#endif /* !TARGET_OS_IPHONE */ -int uv__set_process_title(const char* title) { -#if TARGET_OS_IPHONE - return uv__pthread_setname_np(title); -#else - CFStringRef (*pCFStringCreateWithCString)(CFAllocatorRef, - const char*, - CFStringEncoding); - CFBundleRef (*pCFBundleGetBundleWithIdentifier)(CFStringRef); - void *(*pCFBundleGetDataPointerForName)(CFBundleRef, CFStringRef); - void *(*pCFBundleGetFunctionPointerForName)(CFBundleRef, CFStringRef); - CFTypeRef (*pLSGetCurrentApplicationASN)(void); - OSStatus (*pLSSetApplicationInformationItem)(int, - CFTypeRef, - CFStringRef, - CFStringRef, - CFDictionaryRef*); - void* application_services_handle; - void* core_foundation_handle; - CFBundleRef launch_services_bundle; - CFStringRef* display_name_key; - CFDictionaryRef (*pCFBundleGetInfoDictionary)(CFBundleRef); - CFBundleRef (*pCFBundleGetMainBundle)(void); - CFBundleRef hi_services_bundle; +void uv__set_process_title_platform_init(void) { +#if !TARGET_OS_IPHONE OSStatus (*pSetApplicationIsDaemon)(int); - CFDictionaryRef (*pLSApplicationCheckIn)(int, CFDictionaryRef); - void (*pLSSetApplicationLaunchServicesServerConnectionStatus)(uint64_t, - void*); - CFTypeRef asn; - int err; - err = UV_ENOENT; application_services_handle = dlopen("/System/Library/Frameworks/" "ApplicationServices.framework/" "Versions/A/ApplicationServices", @@ -116,8 +108,6 @@ int uv__set_process_title(const char* title) { goto out; } -#define S(s) pCFStringCreateWithCString(NULL, (s), kCFStringEncodingUTF8) - launch_services_bundle = pCFBundleGetBundleWithIdentifier(S("com.apple.LaunchServices")); @@ -148,13 +138,14 @@ int uv__set_process_title(const char* title) { "CFBundleGetInfoDictionary"); *(void **)(&pCFBundleGetMainBundle) = dlsym(core_foundation_handle, "CFBundleGetMainBundle"); + if (pCFBundleGetInfoDictionary == NULL || pCFBundleGetMainBundle == NULL) goto out; /* Black 10.9 magic, to remove (Not responding) mark in Activity Monitor */ hi_services_bundle = pCFBundleGetBundleWithIdentifier(S("com.apple.HIServices")); - err = UV_ENOENT; + if (hi_services_bundle == NULL) goto out; @@ -168,42 +159,38 @@ int uv__set_process_title(const char* title) { pCFBundleGetFunctionPointerForName( launch_services_bundle, S("_LSSetApplicationLaunchServicesServerConnectionStatus")); + if (pSetApplicationIsDaemon == NULL || pLSApplicationCheckIn == NULL || pLSSetApplicationLaunchServicesServerConnectionStatus == NULL) { goto out; } - if (pSetApplicationIsDaemon(1) != noErr) - goto out; + /* Prevent crash when LaunchServices cannot be connected to. */ + pSetApplicationIsDaemon(1); + return; - pLSSetApplicationLaunchServicesServerConnectionStatus(0, NULL); +out: + uv__set_process_title_platform_fini(); +#endif /* !TARGET_OS_IPHONE */ +} - /* Check into process manager?! */ - pLSApplicationCheckIn(-2, - pCFBundleGetInfoDictionary(pCFBundleGetMainBundle())); - asn = pLSGetCurrentApplicationASN(); +void uv__set_process_title(const char* title) { + char namebuf[64 /* MAXTHREADNAMESIZE */]; - err = UV_EINVAL; - if (pLSSetApplicationInformationItem(-2, /* Magic value. */ - asn, - *display_name_key, - S(title), - NULL) != noErr) { - goto out; +#if !TARGET_OS_IPHONE + if (core_foundation_handle != NULL) { + CFTypeRef asn; + pLSSetApplicationLaunchServicesServerConnectionStatus(0, NULL); + pLSApplicationCheckIn(/* Magic value */ -2, + pCFBundleGetInfoDictionary(pCFBundleGetMainBundle())); + asn = pLSGetCurrentApplicationASN(); + pLSSetApplicationInformationItem(/* Magic value */ -2, asn, + *display_name_key, S(title), NULL); } - - uv__pthread_setname_np(title); /* Don't care if it fails. */ - err = 0; - -out: - if (core_foundation_handle != NULL) - dlclose(core_foundation_handle); - - if (application_services_handle != NULL) - dlclose(application_services_handle); - - return err; #endif /* !TARGET_OS_IPHONE */ + + uv__strscpy(namebuf, title, sizeof(namebuf)); + pthread_setname_np(namebuf); } diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c index fd3dd4c287e9..b37cfbbc7a04 100644 --- a/deps/uv/src/unix/fs.c +++ b/deps/uv/src/unix/fs.c @@ -78,7 +78,7 @@ defined(__NetBSD__) # include # include -#elif defined(__sun) || defined(__MVS__) +#elif defined(__sun) || defined(__MVS__) || defined(__NetBSD__) || defined(__HAIKU__) # include #else # include @@ -216,7 +216,11 @@ static ssize_t uv__fs_futime(uv_fs_t* req) { ts[0].tv_nsec = (uint64_t)(req->atime * 1000000) % 1000000 * 1000; ts[1].tv_sec = req->mtime; ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000; +#if defined(__ANDROID_API__) && __ANDROID_API__ < 21 + return utimensat(req->file, NULL, ts, 0); +#else return futimens(req->file, ts); +#endif #elif defined(__APPLE__) \ || defined(__DragonFly__) \ || defined(__FreeBSD__) \ @@ -528,7 +532,7 @@ static int uv__fs_closedir(uv_fs_t* req) { static int uv__fs_statfs(uv_fs_t* req) { uv_statfs_t* stat_fs; -#if defined(__sun) || defined(__MVS__) +#if defined(__sun) || defined(__MVS__) || defined(__NetBSD__) || defined(__HAIKU__) struct statvfs buf; if (0 != statvfs(req->path, &buf)) @@ -545,7 +549,7 @@ static int uv__fs_statfs(uv_fs_t* req) { return -1; } -#if defined(__sun) || defined(__MVS__) +#if defined(__sun) || defined(__MVS__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__HAIKU__) stat_fs->f_type = 0; /* f_type is not supported. */ #else stat_fs->f_type = buf.f_type; @@ -1051,18 +1055,14 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) { #ifdef FICLONE if (req->flags & UV_FS_COPYFILE_FICLONE || req->flags & UV_FS_COPYFILE_FICLONE_FORCE) { - if (ioctl(dstfd, FICLONE, srcfd) == -1) { - /* If an error occurred that the sendfile fallback also won't handle, or - this is a force clone then exit. Otherwise, fall through to try using - sendfile(). */ - if (errno != ENOTTY && errno != EOPNOTSUPP && errno != EXDEV) { - err = UV__ERR(errno); - goto out; - } else if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) { - err = UV_ENOTSUP; - goto out; - } - } else { + if (ioctl(dstfd, FICLONE, srcfd) == 0) { + /* ioctl() with FICLONE succeeded. */ + goto out; + } + /* If an error occurred and force was set, return the error to the caller; + * fall back to sendfile() when force was not set. */ + if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) { + err = UV__ERR(errno); goto out; } } diff --git a/deps/uv/src/unix/fsevents.c b/deps/uv/src/unix/fsevents.c index ddacda31fef8..deeaa63d4730 100644 --- a/deps/uv/src/unix/fsevents.c +++ b/deps/uv/src/unix/fsevents.c @@ -263,10 +263,12 @@ static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef, if (len < handle->realpath_len) continue; + /* Make sure that realpath actually named a directory, + * (unless watching root, which alone keeps a trailing slash on the realpath) + * or that we matched the whole string */ if (handle->realpath_len != len && + handle->realpath_len > 1 && path[handle->realpath_len] != '/') - /* Make sure that realpath actually named a directory, - * or that we matched the whole string */ continue; if (memcmp(path, handle->realpath, handle->realpath_len) != 0) diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h index 260616474ec1..47f220000dcd 100644 --- a/deps/uv/src/unix/internal.h +++ b/deps/uv/src/unix/internal.h @@ -270,6 +270,12 @@ uv_handle_type uv__handle_type(int fd); FILE* uv__open_file(const char* path); int uv__getpwuid_r(uv_passwd_t* pwd); +/* random */ +int uv__random_devurandom(void* buf, size_t buflen); +int uv__random_getrandom(void* buf, size_t buflen); +int uv__random_getentropy(void* buf, size_t buflen); +int uv__random_readpath(const char* path, void* buf, size_t buflen); +int uv__random_sysctl(void* buf, size_t buflen); #if defined(__APPLE__) int uv___stream_fd(const uv_stream_t* handle); diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c index c04e7a485cf9..ad09f4031318 100644 --- a/deps/uv/src/unix/kqueue.c +++ b/deps/uv/src/unix/kqueue.c @@ -454,10 +454,26 @@ int uv_fs_event_start(uv_fs_event_t* handle, const char* path, unsigned int flags) { int fd; +#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 + struct stat statbuf; +#endif if (uv__is_active(handle)) return UV_EINVAL; + handle->cb = cb; + handle->path = uv__strdup(path); + if (handle->path == NULL) + return UV_ENOMEM; + + /* TODO open asynchronously - but how do we report back errors? */ + fd = open(handle->path, O_RDONLY); + if (fd == -1) { + uv__free(handle->path); + handle->path = NULL; + return UV__ERR(errno); + } + #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 /* Nullify field to perform checks later */ handle->cf_cb = NULL; @@ -465,14 +481,17 @@ int uv_fs_event_start(uv_fs_event_t* handle, handle->realpath_len = 0; handle->cf_flags = flags; + if (fstat(fd, &statbuf)) + goto fallback; + /* FSEvents works only with directories */ + if (!(statbuf.st_mode & S_IFDIR)) + goto fallback; + if (!uv__has_forked_with_cfrunloop) { int r; - /* The fallback fd is not used */ + /* The fallback fd is no longer needed */ + uv__close_nocheckstdio(fd); handle->event_watcher.fd = -1; - handle->path = uv__strdup(path); - if (handle->path == NULL) - return UV_ENOMEM; - handle->cb = cb; r = uv__fsevents_init(handle); if (r == 0) { uv__handle_start(handle); @@ -482,20 +501,9 @@ int uv_fs_event_start(uv_fs_event_t* handle, } return r; } +fallback: #endif /* #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */ - /* TODO open asynchronously - but how do we report back errors? */ - fd = open(path, O_RDONLY); - if (fd == -1) - return UV__ERR(errno); - - handle->path = uv__strdup(path); - if (handle->path == NULL) { - uv__close_nocheckstdio(fd); - return UV_ENOMEM; - } - - handle->cb = cb; uv__handle_start(handle); uv__io_init(&handle->event_watcher, uv__fs_event, fd); uv__io_start(handle->loop, &handle->event_watcher, POLLIN); @@ -514,7 +522,7 @@ int uv_fs_event_stop(uv_fs_event_t* handle) { uv__handle_stop(handle); #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 - if (!uv__has_forked_with_cfrunloop) + if (!uv__has_forked_with_cfrunloop && handle->cf_cb != NULL) r = uv__fsevents_close(handle); #endif diff --git a/deps/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c index 433e201fe19d..a155a374e76c 100644 --- a/deps/uv/src/unix/linux-core.c +++ b/deps/uv/src/unix/linux-core.c @@ -90,7 +90,12 @@ int uv__platform_loop_init(uv_loop_t* loop) { * a.k.a. Lollipop. Since EPOLL_CLOEXEC is an alias for O_CLOEXEC on all * architectures, we just use that instead. */ +#if defined(__ANDROID_API__) && __ANDROID_API__ < 21 + fd = -1; + errno = ENOSYS; +#else fd = epoll_create1(O_CLOEXEC); +#endif /* epoll_create1() can fail either because it's not implemented (old kernel) * or because it doesn't understand the O_CLOEXEC flag. @@ -203,6 +208,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { * that being the largest value I have seen in the wild (and only once.) */ static const int max_safe_timeout = 1789569; + static int no_epoll_pwait; + static int no_epoll_wait; struct epoll_event events[1024]; struct epoll_event* pe; struct epoll_event e; @@ -210,7 +217,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { QUEUE* q; uv__io_t* w; sigset_t sigset; - sigset_t* psigset; + uint64_t sigmask; uint64_t base; int have_signals; int nevents; @@ -262,11 +269,11 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { w->events = w->pevents; } - psigset = NULL; + sigmask = 0; if (loop->flags & UV_LOOP_BLOCK_SIGPROF) { sigemptyset(&sigset); sigaddset(&sigset, SIGPROF); - psigset = &sigset; + sigmask |= 1 << (SIGPROF - 1); } assert(timeout >= -1); @@ -281,11 +288,35 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout) timeout = max_safe_timeout; - nfds = epoll_pwait(loop->backend_fd, - events, - ARRAY_SIZE(events), - timeout, - psigset); + if (sigmask != 0 && no_epoll_pwait != 0) + if (pthread_sigmask(SIG_BLOCK, &sigset, NULL)) + abort(); + + if (no_epoll_wait != 0 || (sigmask != 0 && no_epoll_pwait == 0)) { +#if defined(__ANDROID_API__) && __ANDROID_API__ < 21 + nfds = -1; + errno = ENOSYS; +#else + nfds = epoll_pwait(loop->backend_fd, + events, + ARRAY_SIZE(events), + timeout, + &sigset); +#endif + if (nfds == -1 && errno == ENOSYS) + no_epoll_pwait = 1; + } else { + nfds = epoll_wait(loop->backend_fd, + events, + ARRAY_SIZE(events), + timeout); + if (nfds == -1 && errno == ENOSYS) + no_epoll_wait = 1; + } + + if (sigmask != 0 && no_epoll_pwait != 0) + if (pthread_sigmask(SIG_UNBLOCK, &sigset, NULL)) + abort(); /* Update loop->time unconditionally. It's tempting to skip the update when * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the @@ -306,6 +337,12 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { } if (nfds == -1) { + if (errno == ENOSYS) { + /* epoll_wait() or epoll_pwait() failed, try the other system call. */ + assert(no_epoll_wait == 0 || no_epoll_pwait == 0); + continue; + } + if (errno != EINTR) abort(); diff --git a/deps/uv/src/unix/linux-syscalls.c b/deps/uv/src/unix/linux-syscalls.c index 5637cf98a7b3..950387860f04 100644 --- a/deps/uv/src/unix/linux-syscalls.c +++ b/deps/uv/src/unix/linux-syscalls.c @@ -203,6 +203,22 @@ # endif #endif /* __NR_statx */ +#ifndef __NR_getrandom +# if defined(__x86_64__) +# define __NR_getrandom 318 +# elif defined(__i386__) +# define __NR_getrandom 355 +# elif defined(__aarch64__) +# define __NR_getrandom 384 +# elif defined(__arm__) +# define __NR_getrandom (UV_SYSCALL_BASE + 384) +# elif defined(__ppc__) +# define __NR_getrandom 359 +# elif defined(__s390__) +# define __NR_getrandom 349 +# endif +#endif /* __NR_getrandom */ + int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags) { #if defined(__i386__) unsigned long args[4]; @@ -367,3 +383,12 @@ int uv__statx(int dirfd, return errno = ENOSYS, -1; #endif } + + +ssize_t uv__getrandom(void* buf, size_t buflen, unsigned flags) { +#if defined(__NR_getrandom) + return syscall(__NR_getrandom, buf, buflen, flags); +#else + return errno = ENOSYS, -1; +#endif +} diff --git a/deps/uv/src/unix/linux-syscalls.h b/deps/uv/src/unix/linux-syscalls.h index 7e58bfa21896..b7729b82aea9 100644 --- a/deps/uv/src/unix/linux-syscalls.h +++ b/deps/uv/src/unix/linux-syscalls.h @@ -148,5 +148,6 @@ int uv__statx(int dirfd, int flags, unsigned int mask, struct uv__statx* statxbuf); +ssize_t uv__getrandom(void* buf, size_t buflen, unsigned flags); #endif /* UV_LINUX_SYSCALL_H_ */ diff --git a/deps/uv/src/unix/openbsd.c b/deps/uv/src/unix/openbsd.c index 1f5228dc13fd..199a34658a79 100644 --- a/deps/uv/src/unix/openbsd.c +++ b/deps/uv/src/unix/openbsd.c @@ -186,7 +186,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { int numcpus = 1; int which[] = {CTL_HW,HW_MODEL,0}; size_t size; - int i; + int i, j; uv_cpu_info_t* cpu_info; size = sizeof(model); diff --git a/deps/uv/src/unix/pipe.c b/deps/uv/src/unix/pipe.c index 834766863220..cdf24fa9763c 100644 --- a/deps/uv/src/unix/pipe.c +++ b/deps/uv/src/unix/pipe.c @@ -261,7 +261,7 @@ static int uv__pipe_getsockpeername(const uv_pipe_t* handle, addrlen = strlen(sa.sun_path); - if (addrlen >= *size) { + if ((size_t)addrlen >= *size) { *size = addrlen + 1; return UV_ENOBUFS; } diff --git a/deps/uv/src/unix/proctitle.c b/deps/uv/src/unix/proctitle.c index 1a8c7a7090e8..a5ce2030c55b 100644 --- a/deps/uv/src/unix/proctitle.c +++ b/deps/uv/src/unix/proctitle.c @@ -24,6 +24,7 @@ #include #include +extern void uv__set_process_title_platform_init(void); extern void uv__set_process_title(const char* title); static uv_mutex_t process_title_mutex; @@ -38,6 +39,9 @@ static struct { static void init_process_title_mutex_once(void) { uv_mutex_init(&process_title_mutex); +#ifdef __APPLE__ + uv__set_process_title_platform_init(); +#endif } diff --git a/deps/uv/src/unix/random-devurandom.c b/deps/uv/src/unix/random-devurandom.c new file mode 100644 index 000000000000..bfc40d20f88c --- /dev/null +++ b/deps/uv/src/unix/random-devurandom.c @@ -0,0 +1,93 @@ +/* Copyright libuv contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "internal.h" + +#include +#include + +static uv_once_t once = UV_ONCE_INIT; +static int status; + + +int uv__random_readpath(const char* path, void* buf, size_t buflen) { + struct stat s; + size_t pos; + ssize_t n; + int fd; + + fd = uv__open_cloexec(path, O_RDONLY); + + if (fd == -1) + return UV__ERR(errno); + + if (fstat(fd, &s)) { + uv__close(fd); + return UV__ERR(errno); + } + + if (!S_ISCHR(s.st_mode)) { + uv__close(fd); + return UV_EIO; + } + + for (pos = 0; pos != buflen; pos += n) { + do + n = read(fd, (char*) buf + pos, buflen - pos); + while (n == -1 && errno == EINTR); + + if (n == -1) { + uv__close(fd); + return UV__ERR(errno); + } + + if (n == 0) { + uv__close(fd); + return UV_EIO; + } + } + + uv__close(fd); + return 0; +} + + +static void uv__random_devurandom_init(void) { + char c; + + /* Linux's and NetBSD's random(4) man page suggests applications should read + * at least once from /dev/random before switching to /dev/urandom in order + * to seed the system RNG. Reads from /dev/random can of course block + * indefinitely until entropy is available but that's the point. + */ + status = uv__random_readpath("/dev/random", &c, 1); +} + + +int uv__random_devurandom(void* buf, size_t buflen) { + uv_once(&once, uv__random_devurandom_init); + + if (status != 0) + return status; + + return uv__random_readpath("/dev/urandom", buf, buflen); +} diff --git a/deps/uv/src/unix/random-getentropy.c b/deps/uv/src/unix/random-getentropy.c new file mode 100644 index 000000000000..c45d9fd4a2b7 --- /dev/null +++ b/deps/uv/src/unix/random-getentropy.c @@ -0,0 +1,57 @@ +/* Copyright libuv contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "internal.h" + +#include +#include + +typedef int (*uv__getentropy_cb)(void *, size_t); + +static uv__getentropy_cb uv__getentropy; +static uv_once_t once = UV_ONCE_INIT; + + +static void uv__random_getentropy_init(void) { + uv__getentropy = (uv__getentropy_cb) dlsym(RTLD_DEFAULT, "getentropy"); +} + + +int uv__random_getentropy(void* buf, size_t buflen) { + size_t pos; + size_t stride; + + uv_once(&once, uv__random_getentropy_init); + + if (uv__getentropy == NULL) + return UV_ENOSYS; + + /* getentropy() returns an error for requests > 256 bytes. */ + for (pos = 0, stride = 256; pos + stride < buflen; pos += stride) + if (uv__getentropy((char *) buf + pos, stride)) + return UV__ERR(errno); + + if (uv__getentropy((char *) buf + pos, buflen - pos)) + return UV__ERR(errno); + + return 0; +} diff --git a/deps/uv/src/unix/random-getrandom.c b/deps/uv/src/unix/random-getrandom.c new file mode 100644 index 000000000000..bcc94089bcb6 --- /dev/null +++ b/deps/uv/src/unix/random-getrandom.c @@ -0,0 +1,88 @@ +/* Copyright libuv contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "internal.h" + +#ifdef __linux__ + +#include "linux-syscalls.h" + +#define uv__random_getrandom_init() 0 + +#else /* !__linux__ */ + +#include +#include + +typedef ssize_t (*uv__getrandom_cb)(void *, size_t, unsigned); + +static uv__getrandom_cb uv__getrandom; +static uv_once_t once = UV_ONCE_INIT; + +static void uv__random_getrandom_init_once(void) { + uv__getrandom = (uv__getrandom_cb) dlsym(RTLD_DEFAULT, "getrandom"); +} + +static int uv__random_getrandom_init(void) { + uv_once(&once, uv__random_getrandom_init_once); + + if (uv__getrandom == NULL) + return UV_ENOSYS; + + return 0; +} + +#endif /* !__linux__ */ + +int uv__random_getrandom(void* buf, size_t buflen) { + ssize_t n; + size_t pos; + int rc; + + rc = uv__random_getrandom_init(); + if (rc != 0) + return rc; + + for (pos = 0; pos != buflen; pos += n) { + do { + n = buflen - pos; + + /* Most getrandom() implementations promise that reads <= 256 bytes + * will always succeed and won't be interrupted by signals. + * It's therefore useful to split it up in smaller reads because + * one big read may, in theory, continuously fail with EINTR. + */ + if (n > 256) + n = 256; + + n = uv__getrandom((char *) buf + pos, n, 0); + } while (n == -1 && errno == EINTR); + + if (n == -1) + return UV__ERR(errno); + + if (n == 0) + return UV_EIO; + } + + return 0; +} diff --git a/deps/uv/src/unix/random-sysctl.c b/deps/uv/src/unix/random-sysctl.c new file mode 100644 index 000000000000..fb182ded0929 --- /dev/null +++ b/deps/uv/src/unix/random-sysctl.c @@ -0,0 +1,100 @@ +/* Copyright libuv contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "internal.h" + +#include +#include + +#include +#include + + +struct uv__sysctl_args { + int* name; + int nlen; + void* oldval; + size_t* oldlenp; + void* newval; + size_t newlen; + unsigned long unused[4]; +}; + + +/* TODO(bnoordhuis) Use {CTL_KERN, KERN_ARND} on FreeBSD (and NetBSD?) */ +int uv__random_sysctl(void* buf, size_t buflen) { + static int name[] = {1 /*CTL_KERN*/, 40 /*KERN_RANDOM*/, 6 /*RANDOM_UUID*/}; + struct uv__sysctl_args args; + char uuid[16]; + char* p; + char* pe; + size_t n; + + p = buf; + pe = p + buflen; + + while (p < pe) { + memset(&args, 0, sizeof(args)); + + args.name = name; + args.nlen = ARRAY_SIZE(name); + args.oldval = uuid; + args.oldlenp = &n; + n = sizeof(uuid); + + /* Emits a deprecation warning with some kernels but that seems like + * an okay trade-off for the fallback of the fallback: this function is + * only called when neither getrandom(2) nor /dev/urandom are available. + * Fails with ENOSYS on kernels configured without CONFIG_SYSCTL_SYSCALL. + * At least arm64 never had a _sysctl system call and therefore doesn't + * have a SYS__sysctl define either. + */ +#ifdef SYS__sysctl + if (syscall(SYS__sysctl, &args) == -1) + return UV__ERR(errno); +#else + { + (void) &args; + return UV_ENOSYS; + } +#endif + + if (n != sizeof(uuid)) + return UV_EIO; /* Can't happen. */ + + /* uuid[] is now a type 4 UUID. Bytes 6 and 8 (counting from zero) contain + * 4 and 5 bits of entropy, respectively. For ease of use, we skip those + * and only use 14 of the 16 bytes. + */ + uuid[6] = uuid[14]; + uuid[8] = uuid[15]; + + n = pe - p; + if (n > 14) + n = 14; + + memcpy(p, uuid, n); + p += n; + } + + return 0; +} diff --git a/deps/uv/src/unix/tty.c b/deps/uv/src/unix/tty.c index 74d3d75d7615..e7c520f77402 100644 --- a/deps/uv/src/unix/tty.c +++ b/deps/uv/src/unix/tty.c @@ -365,3 +365,10 @@ int uv_tty_reset_mode(void) { return err; } + +void uv_tty_set_vterm_state(uv_tty_vtermstate_t state) { +} + +int uv_tty_get_vterm_state(uv_tty_vtermstate_t* state) { + return UV_ENOTSUP; +} diff --git a/deps/uv/src/unix/udp.c b/deps/uv/src/unix/udp.c index dba8eff8382e..98215f7e1d21 100644 --- a/deps/uv/src/unix/udp.c +++ b/deps/uv/src/unix/udp.c @@ -165,9 +165,6 @@ static void uv__udp_recvmsg(uv_udp_t* handle) { */ count = 32; - memset(&h, 0, sizeof(h)); - h.msg_name = &peer; - do { buf = uv_buf_init(NULL, 0); handle->alloc_cb((uv_handle_t*) handle, 64 * 1024, &buf); @@ -177,6 +174,9 @@ static void uv__udp_recvmsg(uv_udp_t* handle) { } assert(buf.base != NULL); + memset(&h, 0, sizeof(h)); + memset(&peer, 0, sizeof(peer)); + h.msg_name = &peer; h.msg_namelen = sizeof(peer); h.msg_iov = (void*) &buf; h.msg_iovlen = 1; @@ -193,17 +193,11 @@ static void uv__udp_recvmsg(uv_udp_t* handle) { handle->recv_cb(handle, UV__ERR(errno), &buf, NULL, 0); } else { - const struct sockaddr *addr; - if (h.msg_namelen == 0) - addr = NULL; - else - addr = (const struct sockaddr*) &peer; - flags = 0; if (h.msg_flags & MSG_TRUNC) flags |= UV_UDP_PARTIAL; - handle->recv_cb(handle, nread, &buf, addr, flags); + handle->recv_cb(handle, nread, &buf, (const struct sockaddr*) &peer, flags); } } /* recv_cb callback may decide to pause or close the handle */ @@ -659,6 +653,7 @@ static int uv__udp_set_membership6(uv_udp_t* handle, } +#if !defined(__OpenBSD__) && !defined(__NetBSD__) static int uv__udp_set_source_membership4(uv_udp_t* handle, const struct sockaddr_in* multicast_addr, const char* interface_addr, @@ -749,6 +744,7 @@ static int uv__udp_set_source_membership6(uv_udp_t* handle, return 0; } +#endif int uv_udp_init_ex(uv_loop_t* loop, uv_udp_t* handle, unsigned int flags) { @@ -846,6 +842,7 @@ int uv_udp_set_source_membership(uv_udp_t* handle, const char* interface_addr, const char* source_addr, uv_membership membership) { +#if !defined(__OpenBSD__) && !defined(__NetBSD__) int err; struct sockaddr_storage mcast_addr; struct sockaddr_in* mcast_addr4; @@ -873,7 +870,7 @@ int uv_udp_set_source_membership(uv_udp_t* handle, src_addr6, membership); } - + err = uv_ip4_addr(source_addr, 0, src_addr4); if (err) return err; @@ -882,6 +879,9 @@ int uv_udp_set_source_membership(uv_udp_t* handle, interface_addr, src_addr4, membership); +#else + return UV_ENOSYS; +#endif } diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c index 70db53ab04da..cec4ac6281b9 100644 --- a/deps/uv/src/uv-common.c +++ b/deps/uv/src/uv-common.c @@ -211,6 +211,9 @@ int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr) { memset(addr, 0, sizeof(*addr)); addr->sin_family = AF_INET; addr->sin_port = htons(port); +#ifdef SIN6_LEN + addr->sin_len = sizeof(*addr); +#endif return uv_inet_pton(AF_INET, ip, &(addr->sin_addr.s_addr)); } diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c index 5dccca77999d..3ab486080cdf 100644 --- a/deps/uv/src/win/fs.c +++ b/deps/uv/src/win/fs.c @@ -36,8 +36,6 @@ #include "handle-inl.h" #include "fs-fd-hash-inl.h" -#include - #define UV_FS_FREE_PATHS 0x0002 #define UV_FS_FREE_PTR 0x0008 @@ -1207,9 +1205,7 @@ void fs__mkdtemp(uv_fs_t* req) { WCHAR *cp, *ep; unsigned int tries, i; size_t len; - HCRYPTPROV h_crypt_prov; uint64_t v; - BOOL released; len = wcslen(req->file.pathw); ep = req->file.pathw + len; @@ -1218,16 +1214,10 @@ void fs__mkdtemp(uv_fs_t* req) { return; } - if (!CryptAcquireContext(&h_crypt_prov, NULL, NULL, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT)) { - SET_REQ_WIN32_ERROR(req, GetLastError()); - return; - } - tries = TMP_MAX; do { - if (!CryptGenRandom(h_crypt_prov, sizeof(v), (BYTE*) &v)) { - SET_REQ_WIN32_ERROR(req, GetLastError()); + if (uv__random_rtlgenrandom((void *)&v, sizeof(v)) < 0) { + SET_REQ_UV_ERROR(req, UV_EIO, ERROR_IO_DEVICE); break; } @@ -1248,8 +1238,6 @@ void fs__mkdtemp(uv_fs_t* req) { } } while (--tries); - released = CryptReleaseContext(h_crypt_prov, 0); - assert(released); if (tries == 0) { SET_REQ_RESULT(req, -1); } @@ -2587,6 +2575,7 @@ static void fs__statfs(uv_fs_t* req) { stat_fs->f_files = 0; stat_fs->f_ffree = 0; req->ptr = stat_fs; + req->flags |= UV_FS_FREE_PTR; SET_REQ_RESULT(req, 0); } diff --git a/deps/uv/src/win/internal.h b/deps/uv/src/win/internal.h index 70ddaa533244..058ddb8edc6d 100644 --- a/deps/uv/src/win/internal.h +++ b/deps/uv/src/win/internal.h @@ -280,6 +280,8 @@ int uv__getsockpeername(const uv_handle_t* handle, int* namelen, int delayed_error); +int uv__random_rtlgenrandom(void* buf, size_t buflen); + /* * Process stdio handles. diff --git a/deps/uv/src/win/tcp.c b/deps/uv/src/win/tcp.c index 81e48136a3b9..fd34c623d8c5 100644 --- a/deps/uv/src/win/tcp.c +++ b/deps/uv/src/win/tcp.c @@ -556,7 +556,7 @@ int uv_tcp_close_reset(uv_tcp_t* handle, uv_close_cb close_cb) { if (handle->flags & UV_HANDLE_SHUTTING) return UV_EINVAL; - if (0 != setsockopt(handle->socket, SOL_SOCKET, SO_LINGER, &l, sizeof(l))) + if (0 != setsockopt(handle->socket, SOL_SOCKET, SO_LINGER, (const char*)&l, sizeof(l))) return uv_translate_sys_error(WSAGetLastError()); uv_close((uv_handle_t*) handle, close_cb); diff --git a/deps/uv/src/win/tty.c b/deps/uv/src/win/tty.c index 8f84bcd0e455..5d5b92d0d2d6 100644 --- a/deps/uv/src/win/tty.c +++ b/deps/uv/src/win/tty.c @@ -149,13 +149,9 @@ static char uv_tty_default_fg_bright = 0; static char uv_tty_default_bg_bright = 0; static char uv_tty_default_inverse = 0; -typedef enum { - UV_SUPPORTED, - UV_UNCHECKED, - UV_UNSUPPORTED -} uv_vtermstate_t; /* Determine whether or not ANSI support is enabled. */ -static uv_vtermstate_t uv__vterm_state = UV_UNCHECKED; +static BOOL uv__need_check_vterm_state = TRUE; +static uv_tty_vtermstate_t uv__vterm_state = UV_TTY_UNSUPPORTED; static void uv__determine_vterm_state(HANDLE handle); void uv_console_init(void) { @@ -169,10 +165,15 @@ void uv_console_init(void) { 0, 0); if (uv__tty_console_handle != INVALID_HANDLE_VALUE) { + CONSOLE_SCREEN_BUFFER_INFO sb_info; QueueUserWorkItem(uv__tty_console_resize_message_loop_thread, NULL, WT_EXECUTELONGFUNCTION); uv_mutex_init(&uv__tty_console_resize_mutex); + if (GetConsoleScreenBufferInfo(uv__tty_console_handle, &sb_info)) { + uv__tty_console_width = sb_info.dwSize.X; + uv__tty_console_height = sb_info.srWindow.Bottom - sb_info.srWindow.Top + 1; + } } } @@ -218,7 +219,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int unused) { * between all uv_tty_t handles. */ uv_sem_wait(&uv_tty_output_lock); - if (uv__vterm_state == UV_UNCHECKED) + if (uv__need_check_vterm_state) uv__determine_vterm_state(handle); /* Remember the original console text attributes. */ @@ -1670,7 +1671,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle, uv_buf_t buf = bufs[i]; unsigned int j; - if (uv__vterm_state == UV_SUPPORTED && buf.len > 0) { + if (uv__vterm_state == UV_TTY_SUPPORTED && buf.len > 0) { utf16_buf_used = MultiByteToWideChar(CP_UTF8, 0, buf.base, @@ -2275,32 +2276,24 @@ int uv_tty_reset_mode(void) { static void uv__determine_vterm_state(HANDLE handle) { DWORD dwMode = 0; + uv__need_check_vterm_state = FALSE; if (!GetConsoleMode(handle, &dwMode)) { - uv__vterm_state = UV_UNSUPPORTED; return; } dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; if (!SetConsoleMode(handle, dwMode)) { - uv__vterm_state = UV_UNSUPPORTED; return; } - uv__vterm_state = UV_SUPPORTED; + uv__vterm_state = UV_TTY_SUPPORTED; } static DWORD WINAPI uv__tty_console_resize_message_loop_thread(void* param) { - CONSOLE_SCREEN_BUFFER_INFO sb_info; NTSTATUS status; ULONG_PTR conhost_pid; MSG msg; - if (!GetConsoleScreenBufferInfo(uv__tty_console_handle, &sb_info)) - return 0; - - uv__tty_console_width = sb_info.dwSize.X; - uv__tty_console_height = sb_info.srWindow.Bottom - sb_info.srWindow.Top + 1; - if (pSetWinEventHook == NULL || pNtQueryInformationProcess == NULL) return 0; @@ -2375,6 +2368,7 @@ static void uv__tty_console_signal_resize(void) { height = sb_info.srWindow.Bottom - sb_info.srWindow.Top + 1; uv_mutex_lock(&uv__tty_console_resize_mutex); + assert(uv__tty_console_width != -1 && uv__tty_console_height != -1); if (width != uv__tty_console_width || height != uv__tty_console_height) { uv__tty_console_width = width; uv__tty_console_height = height; @@ -2384,3 +2378,17 @@ static void uv__tty_console_signal_resize(void) { uv_mutex_unlock(&uv__tty_console_resize_mutex); } } + +void uv_tty_set_vterm_state(uv_tty_vtermstate_t state) { + uv_sem_wait(&uv_tty_output_lock); + uv__need_check_vterm_state = FALSE; + uv__vterm_state = state; + uv_sem_post(&uv_tty_output_lock); +} + +int uv_tty_get_vterm_state(uv_tty_vtermstate_t* state) { + uv_sem_wait(&uv_tty_output_lock); + *state = uv__vterm_state; + uv_sem_post(&uv_tty_output_lock); + return 0; +} diff --git a/deps/uv/src/win/udp.c b/deps/uv/src/win/udp.c index 39fc34d3bfcd..3daa55f62db0 100644 --- a/deps/uv/src/win/udp.c +++ b/deps/uv/src/win/udp.c @@ -856,7 +856,7 @@ int uv_udp_set_source_membership(uv_udp_t* handle, src_addr6, membership); } - + err = uv_ip4_addr(source_addr, 0, src_addr4); if (err) return err; diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c index 8849d041bf02..4bbeb3154123 100644 --- a/deps/uv/src/win/util.c +++ b/deps/uv/src/win/util.c @@ -1417,7 +1417,9 @@ int uv_os_environ(uv_env_item_t** envitems, int* count) { if (uv__convert_utf16_to_utf8(penv, -1, &buf) != 0) goto fail; - ptr = strchr(buf, '='); + /* Using buf + 1 here because we know that `buf` has length at least 1, + * and some special environment variables on Windows start with a = sign. */ + ptr = strchr(buf + 1, '='); if (ptr == NULL) { uv__free(buf); goto do_continue; @@ -1858,3 +1860,16 @@ int uv_gettimeofday(uv_timeval64_t* tv) { tv->tv_usec = (int32_t) (((ularge.QuadPart - epoch) % 10000000L) / 10); return 0; } + +int uv__random_rtlgenrandom(void* buf, size_t buflen) { + if (pRtlGenRandom == NULL) + return UV_ENOSYS; + + if (buflen == 0) + return 0; + + if (pRtlGenRandom(buf, buflen) == FALSE) + return UV_EIO; + + return 0; +} diff --git a/deps/uv/src/win/winapi.c b/deps/uv/src/win/winapi.c index 19e4377faf55..85a9de8a2295 100644 --- a/deps/uv/src/win/winapi.c +++ b/deps/uv/src/win/winapi.c @@ -36,6 +36,9 @@ sNtQueryDirectoryFile pNtQueryDirectoryFile; sNtQuerySystemInformation pNtQuerySystemInformation; sNtQueryInformationProcess pNtQueryInformationProcess; +/* Advapi32 function pointers */ +sRtlGenRandom pRtlGenRandom; + /* Kernel32 function pointers */ sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx; @@ -51,6 +54,7 @@ void uv_winapi_init(void) { HMODULE powrprof_module; HMODULE user32_module; HMODULE kernel32_module; + HMODULE advapi32_module; ntdll_module = GetModuleHandleA("ntdll.dll"); if (ntdll_module == NULL) { @@ -135,4 +139,11 @@ void uv_winapi_init(void) { GetProcAddress(user32_module, "SetWinEventHook"); } + advapi32_module = GetModuleHandleA("advapi32.dll"); + if (advapi32_module == NULL) { + uv_fatal_error(GetLastError(), "GetModuleHandleA"); + } + + pRtlGenRandom = + (sRtlGenRandom) GetProcAddress(advapi32_module, "SystemFunction036"); } diff --git a/deps/uv/src/win/winapi.h b/deps/uv/src/win/winapi.h index 322a212dd73c..fcc70652a9ae 100644 --- a/deps/uv/src/win/winapi.h +++ b/deps/uv/src/win/winapi.h @@ -4589,6 +4589,11 @@ typedef NTSTATUS (NTAPI *sNtQueryInformationProcess) ULONG Length, PULONG ReturnLength); +/* + * Advapi32 headers + */ +typedef BOOLEAN (WINAPI *sRtlGenRandom)(PVOID Buffer, ULONG BufferLength); + /* * Kernel32 headers */ @@ -4731,6 +4736,9 @@ extern sNtQueryDirectoryFile pNtQueryDirectoryFile; extern sNtQuerySystemInformation pNtQuerySystemInformation; extern sNtQueryInformationProcess pNtQueryInformationProcess; +/* Advapi32 function pointers */ +extern sRtlGenRandom pRtlGenRandom; + /* Kernel32 function pointers */ extern sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx; diff --git a/deps/uv/src/win/winsock.h b/deps/uv/src/win/winsock.h index 7ecb755bfb06..2af958870a7d 100644 --- a/deps/uv/src/win/winsock.h +++ b/deps/uv/src/win/winsock.h @@ -54,6 +54,14 @@ # define SIO_BASE_HANDLE 0x48000022 #endif +#ifndef MCAST_JOIN_SOURCE_GROUP +# define MCAST_JOIN_SOURCE_GROUP 45 +#endif + +#ifndef MCAST_LEAVE_SOURCE_GROUP +# define MCAST_LEAVE_SOURCE_GROUP 46 +#endif + /* * TDI defines that are only in the DDK. * We only need receive flags so far. diff --git a/deps/uv/test/test-env-vars.c b/deps/uv/test/test-env-vars.c index 3814699356db..3c9de95b102a 100644 --- a/deps/uv/test/test-env-vars.c +++ b/deps/uv/test/test-env-vars.c @@ -30,7 +30,7 @@ TEST_IMPL(env_vars) { const char* name2 = "UV_TEST_FOO2"; char buf[BUF_SIZE]; size_t size; - int i, r, envcount, found; + int i, r, envcount, found, found_win_special; uv_env_item_t* envitems; /* Reject invalid inputs when setting an environment variable */ @@ -108,6 +108,7 @@ TEST_IMPL(env_vars) { ASSERT(envcount > 0); found = 0; + found_win_special = 0; for (i = 0; i < envcount; i++) { /* printf("Env: %s = %s\n", envitems[i].name, envitems[i].value); */ @@ -117,10 +118,15 @@ TEST_IMPL(env_vars) { } else if (strcmp(envitems[i].name, name2) == 0) { found++; ASSERT(strlen(envitems[i].value) == 0); + } else if (envitems[i].name[0] == '=') { + found_win_special++; } } ASSERT(found == 2); +#ifdef _WIN32 + ASSERT(found_win_special > 0); +#endif uv_os_free_environ(envitems, envcount); diff --git a/deps/uv/test/test-fs-copyfile.c b/deps/uv/test/test-fs-copyfile.c index def3d967e74f..c3e698e5852c 100644 --- a/deps/uv/test/test-fs-copyfile.c +++ b/deps/uv/test/test-fs-copyfile.c @@ -188,7 +188,7 @@ TEST_IMPL(fs_copyfile) { unlink(dst); r = uv_fs_copyfile(NULL, &req, fixture, dst, UV_FS_COPYFILE_FICLONE_FORCE, NULL); - ASSERT(r == 0 || r == UV_ENOSYS || r == UV_ENOTSUP); + ASSERT(r <= 0); if (r == 0) handle_result(&req); diff --git a/deps/uv/test/test-fs-event.c b/deps/uv/test/test-fs-event.c index ea34bd63a706..e694d258ea93 100644 --- a/deps/uv/test/test-fs-event.c +++ b/deps/uv/test/test-fs-event.c @@ -25,6 +25,10 @@ #include #include +#if defined(__APPLE__) && !TARGET_OS_IPHONE +# include +#endif + #ifndef HAVE_KQUEUE # if defined(__APPLE__) || \ defined(__DragonFly__) || \ @@ -47,6 +51,7 @@ static const char file_prefix[] = "fsevent-"; static const int fs_event_file_count = 16; #if defined(__APPLE__) || defined(_WIN32) static const char file_prefix_in_subdir[] = "subdir"; +static int fs_multievent_cb_called; #endif static uv_timer_t timer; static int timer_cb_called; @@ -280,7 +285,7 @@ static void fs_event_cb_dir_multi_file_in_subdir(uv_fs_event_t* handle, if (filename && strcmp(filename, file_prefix_in_subdir) == 0) return; #endif - fs_event_cb_called++; + fs_multievent_cb_called++; ASSERT(handle == &fs_event); ASSERT(status == 0); ASSERT(events == UV_CHANGE || events == UV_RENAME); @@ -298,7 +303,7 @@ static void fs_event_cb_dir_multi_file_in_subdir(uv_fs_event_t* handle, if (fs_event_created + fs_event_removed == fs_event_file_count) { /* Once we've processed all create events, delete all files */ ASSERT(0 == uv_timer_start(&timer, fs_event_unlink_files_in_subdir, 1, 0)); - } else if (fs_event_cb_called == 2 * fs_event_file_count) { + } else if (fs_multievent_cb_called == 2 * fs_event_file_count) { /* Once we've processed all create and delete events, stop watching */ uv_close((uv_handle_t*) &timer, close_cb); uv_close((uv_handle_t*) handle, close_cb); @@ -393,6 +398,21 @@ static void timer_cb_watch_twice(uv_timer_t* handle) { uv_close((uv_handle_t*) handle, NULL); } +static void fs_event_cb_close(uv_fs_event_t* handle, + const char* filename, + int events, + int status) { + ASSERT(status == 0); + + ASSERT(fs_event_cb_called < 3); + ++fs_event_cb_called; + + if (fs_event_cb_called == 3) { + uv_close((uv_handle_t*) handle, close_cb); + } +} + + TEST_IMPL(fs_event_watch_dir) { #if defined(NO_FS_EVENTS) RETURN_SKIP(NO_FS_EVENTS); @@ -434,10 +454,12 @@ TEST_IMPL(fs_event_watch_dir) { return 0; } + TEST_IMPL(fs_event_watch_dir_recursive) { #if defined(__APPLE__) || defined(_WIN32) uv_loop_t* loop; int r; + uv_fs_event_t fs_event_root; /* Setup */ loop = uv_default_loop(); @@ -451,17 +473,37 @@ TEST_IMPL(fs_event_watch_dir_recursive) { r = uv_fs_event_init(loop, &fs_event); ASSERT(r == 0); - r = uv_fs_event_start(&fs_event, fs_event_cb_dir_multi_file_in_subdir, "watch_dir", UV_FS_EVENT_RECURSIVE); + r = uv_fs_event_start(&fs_event, + fs_event_cb_dir_multi_file_in_subdir, + "watch_dir", + UV_FS_EVENT_RECURSIVE); ASSERT(r == 0); r = uv_timer_init(loop, &timer); ASSERT(r == 0); r = uv_timer_start(&timer, fs_event_create_files_in_subdir, 100, 0); ASSERT(r == 0); +#ifndef _WIN32 + /* Also try to watch the root directory. + * This will be noisier, so we're just checking for any couple events to happen. */ + r = uv_fs_event_init(loop, &fs_event_root); + ASSERT(r == 0); + r = uv_fs_event_start(&fs_event_root, + fs_event_cb_close, + "/", + UV_FS_EVENT_RECURSIVE); + ASSERT(r == 0); +#else + fs_event_cb_called += 3; + close_cb_called += 1; + (void)fs_event_root; +#endif + uv_run(loop, UV_RUN_DEFAULT); - ASSERT(fs_event_cb_called == fs_event_created + fs_event_removed); - ASSERT(close_cb_called == 2); + ASSERT(fs_multievent_cb_called == fs_event_created + fs_event_removed); + ASSERT(fs_event_cb_called == 3); + ASSERT(close_cb_called == 3); /* Cleanup */ fs_event_unlink_files_in_subdir(NULL); @@ -596,6 +638,7 @@ TEST_IMPL(fs_event_watch_file_exact_path) { * versions. Give a long delay here to let the system settle before running * the test. */ uv_sleep(1100); + uv_update_time(loop); #endif r = uv_fs_event_init(loop, &fs_event); @@ -656,6 +699,13 @@ TEST_IMPL(fs_event_watch_file_current_dir) { /* Setup */ remove("watch_file"); create_file("watch_file"); +#if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_12) + /* Empirically, kevent seems to (sometimes) report the preceeding + * create_file events prior to macOS 10.11.6 in the subsequent fs_event_start + * So let the system settle before running the test. */ + uv_sleep(1100); + uv_update_time(loop); +#endif r = uv_fs_event_init(loop, &fs_event); ASSERT(r == 0); @@ -864,18 +914,6 @@ TEST_IMPL(fs_event_close_with_pending_event) { return 0; } -static void fs_event_cb_close(uv_fs_event_t* handle, const char* filename, - int events, int status) { - ASSERT(status == 0); - - ASSERT(fs_event_cb_called < 3); - ++fs_event_cb_called; - - if (fs_event_cb_called == 3) { - uv_close((uv_handle_t*) handle, close_cb); - } -} - TEST_IMPL(fs_event_close_in_callback) { #if defined(NO_FS_EVENTS) RETURN_SKIP(NO_FS_EVENTS); diff --git a/deps/uv/test/test-fs-readdir.c b/deps/uv/test/test-fs-readdir.c index a767f1fb885d..5efc853cc67f 100644 --- a/deps/uv/test/test-fs-readdir.c +++ b/deps/uv/test/test-fs-readdir.c @@ -62,12 +62,12 @@ static void empty_readdir_cb(uv_fs_t* req) { ASSERT(req->fs_type == UV_FS_READDIR); ASSERT(req->result == 0); dir = req->ptr; + uv_fs_req_cleanup(req); r = uv_fs_closedir(uv_default_loop(), &closedir_req, dir, empty_closedir_cb); ASSERT(r == 0); - uv_fs_req_cleanup(req); } static void empty_opendir_cb(uv_fs_t* req) { diff --git a/deps/uv/test/test-ip4-addr.c b/deps/uv/test/test-ip4-addr.c index c72f36a69445..dfefb0f914a6 100644 --- a/deps/uv/test/test-ip4-addr.c +++ b/deps/uv/test/test-ip4-addr.c @@ -42,6 +42,10 @@ TEST_IMPL(ip4_addr) { ASSERT(UV_EINVAL == uv_ip4_addr("2555.0.0.0", TEST_PORT, &addr)); ASSERT(UV_EINVAL == uv_ip4_addr("255", TEST_PORT, &addr)); +#ifdef SIN6_LEN + ASSERT(addr.sin_len == sizeof(addr)); +#endif + /* for broken address family */ ASSERT(UV_EAFNOSUPPORT == uv_inet_pton(42, "127.0.0.1", &addr.sin_addr.s_addr)); diff --git a/deps/uv/test/test-ip6-addr.c b/deps/uv/test/test-ip6-addr.c index bbf33a4854ed..39d570659daa 100644 --- a/deps/uv/test/test-ip6-addr.c +++ b/deps/uv/test/test-ip6-addr.c @@ -160,3 +160,12 @@ TEST_IMPL(ip6_pton) { #undef GOOD_ADDR_LIST #undef BAD_ADDR_LIST + +#ifdef SIN6_LEN +TEST_IMPL(ip6_sin6_len) { + struct sockaddr_in6 s; + ASSERT(uv_ip6_addr("::", 0, &s) < 0); + ASSERT(s.sin6_len == sizeof(s)); + return 0; +} +#endif diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index b6066f27276d..ad94c52d0c58 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -395,6 +395,7 @@ TEST_DECLARE (threadpool_queue_work_einval) TEST_DECLARE (threadpool_multiple_event_loops) TEST_DECLARE (threadpool_cancel_getaddrinfo) TEST_DECLARE (threadpool_cancel_getnameinfo) +TEST_DECLARE (threadpool_cancel_random) TEST_DECLARE (threadpool_cancel_work) TEST_DECLARE (threadpool_cancel_fs) TEST_DECLARE (threadpool_cancel_single) @@ -464,6 +465,9 @@ HELPER_DECLARE (pipe_echo_server) TEST_DECLARE (queue_foreach_delete) +TEST_DECLARE (random_async) +TEST_DECLARE (random_sync) + TEST_DECLARE (handle_type_name) TEST_DECLARE (req_type_name) TEST_DECLARE (getters_setters) @@ -1000,6 +1004,7 @@ TASK_LIST_START TEST_ENTRY_CUSTOM (threadpool_multiple_event_loops, 0, 0, 60000) TEST_ENTRY (threadpool_cancel_getaddrinfo) TEST_ENTRY (threadpool_cancel_getnameinfo) + TEST_ENTRY (threadpool_cancel_random) TEST_ENTRY (threadpool_cancel_work) TEST_ENTRY (threadpool_cancel_fs) TEST_ENTRY (threadpool_cancel_single) @@ -1018,6 +1023,9 @@ TASK_LIST_START TEST_ENTRY (queue_foreach_delete) + TEST_ENTRY (random_async) + TEST_ENTRY (random_sync) + TEST_ENTRY (handle_type_name) TEST_ENTRY (req_type_name) TEST_ENTRY (getters_setters) diff --git a/deps/uv/test/test-process-title-threadsafe.c b/deps/uv/test/test-process-title-threadsafe.c index 5b30f17f44d5..19098eda0c40 100644 --- a/deps/uv/test/test-process-title-threadsafe.c +++ b/deps/uv/test/test-process-title-threadsafe.c @@ -25,11 +25,7 @@ #include -#ifdef __APPLE__ -# define NUM_ITERATIONS 10 -#else -# define NUM_ITERATIONS 50 -#endif +#define NUM_ITERATIONS 50 static const char* titles[] = { "8L2NY0Kdj0XyNFZnmUZigIOfcWjyNr0SkMmUhKw99VLUsZFrvCQQC3XIRfNR8pjyMjXObllled", diff --git a/deps/uv/test/test-random.c b/deps/uv/test/test-random.c new file mode 100644 index 000000000000..2e3ce4424d29 --- /dev/null +++ b/deps/uv/test/test-random.c @@ -0,0 +1,94 @@ +/* Copyright libuv contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "task.h" + +#include + +static char scratch[256]; +static int random_cb_called; + + +static void random_cb(uv_random_t* req, int status, void* buf, size_t buflen) { + char zero[sizeof(scratch)]; + + memset(zero, 0, sizeof(zero)); + + ASSERT(0 == status); + ASSERT(buf == (void*) scratch); + + if (random_cb_called == 0) { + ASSERT(buflen == 0); + ASSERT(0 == memcmp(scratch, zero, sizeof(zero))); + } else { + ASSERT(buflen == sizeof(scratch)); + /* Buy a lottery ticket if you manage to trip this assertion. */ + ASSERT(0 != memcmp(scratch, zero, sizeof(zero))); + } + + random_cb_called++; +} + + +TEST_IMPL(random_async) { + uv_random_t req; + uv_loop_t* loop; + + loop = uv_default_loop(); + ASSERT(UV_EINVAL == uv_random(loop, &req, scratch, sizeof(scratch), -1, + random_cb)); + ASSERT(UV_E2BIG == uv_random(loop, &req, scratch, -1, -1, random_cb)); + + ASSERT(0 == uv_random(loop, &req, scratch, 0, 0, random_cb)); + ASSERT(0 == random_cb_called); + + ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); + ASSERT(1 == random_cb_called); + + ASSERT(0 == uv_random(loop, &req, scratch, sizeof(scratch), 0, random_cb)); + ASSERT(1 == random_cb_called); + + ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); + ASSERT(2 == random_cb_called); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + +TEST_IMPL(random_sync) { + char zero[256]; + char buf[256]; + + ASSERT(UV_EINVAL == uv_random(NULL, NULL, buf, sizeof(buf), -1, NULL)); + ASSERT(UV_E2BIG == uv_random(NULL, NULL, buf, -1, -1, NULL)); + + memset(buf, 0, sizeof(buf)); + ASSERT(0 == uv_random(NULL, NULL, buf, sizeof(buf), 0, NULL)); + + /* Buy a lottery ticket if you manage to trip this assertion. */ + memset(zero, 0, sizeof(zero)); + ASSERT(0 != memcmp(buf, zero, sizeof(zero))); + + MAKE_VALGRIND_HAPPY(); + return 0; +} diff --git a/deps/uv/test/test-threadpool-cancel.c b/deps/uv/test/test-threadpool-cancel.c index dd13d8ae4bf1..be252c6f7234 100644 --- a/deps/uv/test/test-threadpool-cancel.c +++ b/deps/uv/test/test-threadpool-cancel.c @@ -37,6 +37,11 @@ struct cancel_info { uv_timer_t timer_handle; }; +struct random_info { + uv_random_t random_req; + char buf[1]; +}; + static unsigned fs_cb_called; static unsigned done_cb_called; static unsigned done2_cb_called; @@ -143,6 +148,19 @@ static void nop_done_cb(uv_work_t* req, int status) { } +static void nop_random_cb(uv_random_t* req, int status, void* buf, size_t len) { + struct random_info* ri; + + ri = container_of(req, struct random_info, random_req); + + ASSERT(status == UV_ECANCELED); + ASSERT(buf == (void*) ri->buf); + ASSERT(len == sizeof(ri->buf)); + + done_cb_called++; +} + + TEST_IMPL(threadpool_cancel_getaddrinfo) { uv_getaddrinfo_t reqs[4]; struct cancel_info ci; @@ -212,6 +230,29 @@ TEST_IMPL(threadpool_cancel_getnameinfo) { } +TEST_IMPL(threadpool_cancel_random) { + struct random_info req; + uv_loop_t* loop; + + saturate_threadpool(); + loop = uv_default_loop(); + ASSERT(0 == uv_random(loop, + &req.random_req, + &req.buf, + sizeof(req.buf), + 0, + nop_random_cb)); + ASSERT(0 == uv_cancel((uv_req_t*) &req)); + ASSERT(0 == done_cb_called); + unblock_threadpool(); + ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); + ASSERT(1 == done_cb_called); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + TEST_IMPL(threadpool_cancel_work) { struct cancel_info ci; uv_work_t reqs[16]; diff --git a/deps/uv/test/test-udp-multicast-join.c b/deps/uv/test/test-udp-multicast-join.c index 9ee80e44e7c2..6bac072db096 100644 --- a/deps/uv/test/test-udp-multicast-join.c +++ b/deps/uv/test/test-udp-multicast-join.c @@ -74,7 +74,7 @@ static void sv_send_cb(uv_udp_send_t* req, int status) { static int do_send(uv_udp_send_t* send_req) { uv_buf_t buf; struct sockaddr_in addr; - + buf = uv_buf_init("PING", 4); ASSERT(0 == uv_ip4_addr(MULTICAST_ADDR, TEST_PORT, &addr)); diff --git a/deps/uv/test/test-udp-multicast-join6.c b/deps/uv/test/test-udp-multicast-join6.c index edcd371b2c22..5de27a7fb292 100644 --- a/deps/uv/test/test-udp-multicast-join6.c +++ b/deps/uv/test/test-udp-multicast-join6.c @@ -86,7 +86,7 @@ static void sv_send_cb(uv_udp_send_t* req, int status) { static int do_send(uv_udp_send_t* send_req) { uv_buf_t buf; struct sockaddr_in6 addr; - + buf = uv_buf_init("PING", 4); ASSERT(0 == uv_ip6_addr(MULTICAST_ADDR, TEST_PORT, &addr)); @@ -195,7 +195,7 @@ TEST_IMPL(udp_multicast_join6) { r = uv_udp_recv_start(&server, alloc_cb, cl_recv_cb); ASSERT(r == 0); - + r = do_send(&req); ASSERT(r == 0); diff --git a/deps/uv/test/test.gyp b/deps/uv/test/test.gyp index 60792ad6ebbb..73ff42c56e43 100644 --- a/deps/uv/test/test.gyp +++ b/deps/uv/test/test.gyp @@ -52,6 +52,7 @@ 'test-hrtime.c', 'test-idle.c', 'test-idna.c', + 'test-ip4-addr.c', 'test-ip6-addr.c', 'test-ipc-heavy-traffic-deadlock-bug.c', 'test-ipc-send-recv.c', @@ -90,6 +91,7 @@ 'test-process-title.c', 'test-process-title-threadsafe.c', 'test-queue-foreach-delete.c', + 'test-random.c', 'test-ref.c', 'test-run-nowait.c', 'test-run-once.c', @@ -158,8 +160,6 @@ 'test-udp-multicast-join6.c', 'test-dlerror.c', 'test-udp-multicast-ttl.c', - 'test-ip4-addr.c', - 'test-ip6-addr.c', 'test-udp-multicast-interface.c', 'test-udp-multicast-interface6.c', 'test-udp-try-send.c', diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index 810c1004cd93..6a24b7b1706e 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -75,6 +75,7 @@ 'src/idna.h', 'src/inet.c', 'src/queue.h', + 'src/random.c', 'src/strscpy.c', 'src/strscpy.h', 'src/threadpool.c', @@ -167,6 +168,7 @@ 'src/unix/pipe.c', 'src/unix/poll.c', 'src/unix/process.c', + 'src/unix/random-devurandom.c', 'src/unix/signal.c', 'src/unix/spinlock.h', 'src/unix/stream.c', @@ -226,7 +228,8 @@ 'sources': [ 'src/unix/darwin.c', 'src/unix/fsevents.c', - 'src/unix/darwin-proctitle.c' + 'src/unix/darwin-proctitle.c', + 'src/unix/random-getentropy.c', ], 'defines': [ '_DARWIN_USE_64_BIT_INODE=1', @@ -241,6 +244,8 @@ 'src/unix/linux-syscalls.c', 'src/unix/linux-syscalls.h', 'src/unix/procfs-exepath.c', + 'src/unix/random-getrandom.c', + 'src/unix/random-sysctl.c', 'src/unix/sysinfo-loadavg.c', ], 'link_settings': { @@ -320,8 +325,14 @@ [ 'OS=="freebsd" or OS=="dragonflybsd"', { 'sources': [ 'src/unix/freebsd.c' ], }], + [ 'OS=="freebsd"', { + 'sources': [ 'src/unix/random-getrandom.c' ], + }], [ 'OS=="openbsd"', { - 'sources': [ 'src/unix/openbsd.c' ], + 'sources': [ + 'src/unix/openbsd.c', + 'src/unix/random-getentropy.c', + ], }], [ 'OS=="netbsd"', { 'link_settings': { From 111b69761ade6b02e805d8b3ebf147b0f8a9473f Mon Sep 17 00:00:00 2001 From: cjihrig Date: Tue, 3 Dec 2019 22:19:16 -0500 Subject: [PATCH 7/9] deps: upgrade to libuv 1.34.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Notable changes: - Fix handling of large files in uv_fs_copyfile(). Fixes: https://github.com/nodejs/node/issues/30085 - Fix Android build errors. - uv_sleep() has been added. - uv_interface_addresses() IPv6 netmask support has been fixed. Fixes: https://github.com/nodejs/node/issues/30504 - uv_fs_mkstemp() has been added. PR-URL: https://github.com/nodejs/node/pull/30783 Fixes: https://github.com/nodejs/node/issues/30085 Fixes: https://github.com/nodejs/node/issues/30504 Reviewed-By: Tobias Nießen Reviewed-By: Daniel Bevenius Reviewed-By: Richard Lau Reviewed-By: Santiago Gimeno Reviewed-By: Jiawen Geng Reviewed-By: Rich Trott Reviewed-By: Trivikram Kamat Reviewed-By: Michael Dawson Reviewed-By: Ben Noordhuis --- deps/uv/AUTHORS | 1 + deps/uv/CMakeLists.txt | 4 +- deps/uv/ChangeLog | 37 +++++ deps/uv/MAINTAINERS.md | 2 + deps/uv/Makefile.am | 11 +- deps/uv/configure.ac | 2 +- deps/uv/docs/src/fs.rst | 13 +- deps/uv/docs/src/misc.rst | 7 + deps/uv/include/uv.h | 8 +- deps/uv/include/uv/version.h | 4 +- deps/uv/src/random.c | 2 + deps/uv/src/unix/aix-common.c | 114 +++++++++++----- deps/uv/src/unix/core.c | 14 ++ deps/uv/src/unix/fs.c | 129 ++++++++++++++++-- deps/uv/src/unix/netbsd.c | 23 ++++ deps/uv/src/unix/os390-syscalls.c | 23 ++-- deps/uv/src/unix/random-devurandom.c | 8 +- ...{random-sysctl.c => random-sysctl-linux.c} | 1 - deps/uv/src/win/fs.c | 108 +++++++++++++-- deps/uv/src/win/util.c | 4 + deps/uv/test/runner-unix.c | 14 -- deps/uv/test/runner-win.c | 6 - deps/uv/test/task.h | 3 - deps/uv/test/test-fs.c | 96 +++++++++++++ deps/uv/test/test-list.h | 2 + deps/uv/uv.gyp | 5 +- 26 files changed, 535 insertions(+), 106 deletions(-) rename deps/uv/src/unix/{random-sysctl.c => random-sysctl-linux.c} (97%) diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS index 408cfd6541a3..dcc36e8c17f9 100644 --- a/deps/uv/AUTHORS +++ b/deps/uv/AUTHORS @@ -411,3 +411,4 @@ Ouyang Yadong ZYSzys Carl Lei Stefan Bender +nia diff --git a/deps/uv/CMakeLists.txt b/deps/uv/CMakeLists.txt index 7da5e688166c..2ab6d17edddd 100644 --- a/deps/uv/CMakeLists.txt +++ b/deps/uv/CMakeLists.txt @@ -275,6 +275,8 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Android") src/unix/linux-syscalls.c src/unix/procfs-exepath.c src/unix/pthread-fixes.c + src/unix/random-getrandom.c + src/unix/random-sysctl-linux.c src/unix/sysinfo-loadavg.c) endif() @@ -320,7 +322,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux") src/unix/linux-syscalls.c src/unix/procfs-exepath.c src/unix/random-getrandom.c - src/unix/random-sysctl.c + src/unix/random-sysctl-linux.c src/unix/sysinfo-loadavg.c) endif() diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index cd4451ae69c0..a0509e6e153f 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,3 +1,40 @@ +2019.12.05, Version 1.34.0 (Stable), 15ae750151ac9341e5945eb38f8982d59fb99201 + +Changes since version 1.33.1: + +* unix: move random-sysctl to random-sysctl-linux (nia) + +* netbsd: use KERN_ARND sysctl to get entropy (nia) + +* unix: refactor uv__fs_copyfile() logic (cjihrig) + +* build: fix android build, add missing sources (Ben Noordhuis) + +* build: fix android build, fix symbol redefinition (Ben Noordhuis) + +* build: fix android autotools build (Ben Noordhuis) + +* fs: handle non-functional statx system call (Milad Farazmand) + +* unix,win: add uv_sleep() (cjihrig) + +* doc: add richardlau to maintainers (Richard Lau) + +* aix: fix netmask for IPv6 (Richard Lau) + +* aix: clean up after errors in uv_interface_addresses() (Richard Lau) + +* aix: fix setting of physical addresses (Richard Lau) + +* fs: add uv_fs_mkstemp (Saúl Ibarra Corretgé) + +* unix: switch uv_sleep() to nanosleep() (Ben Noordhuis) + +* unix: retry on EINTR in uv_sleep() (Ben Noordhuis) + +* zos: fix nanosleep() emulation (Ben Noordhuis) + + 2019.10.20, Version 1.33.1 (Stable), 07ad32138f4d2285ba2226b5e20462b27b091a59 Changes since version 1.33.0: diff --git a/deps/uv/MAINTAINERS.md b/deps/uv/MAINTAINERS.md index a5a11c8dfff1..0870b88eb689 100644 --- a/deps/uv/MAINTAINERS.md +++ b/deps/uv/MAINTAINERS.md @@ -17,6 +17,8 @@ libuv is currently managed by the following individuals: - GPG key: 9DFE AA5F 481B BF77 2D90 03CE D592 4925 2F8E C41A (pubkey-iwuzhere) * **Jameson Nash** ([@vtjnash](https://github.com/vtjnash)) * **John Barboza** ([@jbarz](https://github.com/jbarz)) +* **Richard Lau** ([@richardlau](https://github.com/richardlau)) + - GPG key: C82F A3AE 1CBE DC6B E46B 9360 C43C EC45 C17A B93C (pubkey-richardlau) * **Santiago Gimeno** ([@santigimeno](https://github.com/santigimeno)) - GPG key: 612F 0EAD 9401 6223 79DF 4402 F28C 3C8D A33C 03BE (pubkey-santigimeno) * **Saúl Ibarra Corretgé** ([@saghul](https://github.com/saghul)) diff --git a/deps/uv/Makefile.am b/deps/uv/Makefile.am index ce4ca274b217..088b4bbd76f3 100644 --- a/deps/uv/Makefile.am +++ b/deps/uv/Makefile.am @@ -387,7 +387,14 @@ endif if ANDROID uvinclude_HEADERS += include/uv/android-ifaddrs.h libuv_la_SOURCES += src/unix/android-ifaddrs.c \ - src/unix/pthread-fixes.c + src/unix/linux-core.c \ + src/unix/linux-inotify.c \ + src/unix/linux-syscalls.c \ + src/unix/procfs-exepath.c \ + src/unix/pthread-fixes.c \ + src/unix/random-getrandom.c \ + src/unix/random-sysctl-linux.c \ + src/unix/sysinfo-loadavg.c endif if CYGWIN @@ -467,7 +474,7 @@ libuv_la_SOURCES += src/unix/linux-core.c \ src/unix/procfs-exepath.c \ src/unix/proctitle.c \ src/unix/random-getrandom.c \ - src/unix/random-sysctl.c \ + src/unix/random-sysctl-linux.c \ src/unix/sysinfo-loadavg.c test_run_tests_LDFLAGS += -lutil endif diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac index 07ad0cde81a6..6ea6b6a06cd1 100644 --- a/deps/uv/configure.ac +++ b/deps/uv/configure.ac @@ -13,7 +13,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. AC_PREREQ(2.57) -AC_INIT([libuv], [1.33.1], [https://github.com/libuv/libuv/issues]) +AC_INIT([libuv], [1.34.0], [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]) diff --git a/deps/uv/docs/src/fs.rst b/deps/uv/docs/src/fs.rst index dc16ff08e65a..28356c2d442e 100644 --- a/deps/uv/docs/src/fs.rst +++ b/deps/uv/docs/src/fs.rst @@ -99,7 +99,8 @@ Data types UV_FS_LCHOWN, UV_FS_OPENDIR, UV_FS_READDIR, - UV_FS_CLOSEDIR + UV_FS_CLOSEDIR, + UV_FS_MKSTEMP } uv_fs_type; .. c:type:: uv_statfs_t @@ -245,10 +246,14 @@ API .. c:function:: int uv_fs_mkdtemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl, uv_fs_cb cb) - Equivalent to :man:`mkdtemp(3)`. + Equivalent to :man:`mkdtemp(3)`. The result can be found as a null terminated string at `req->path`. - .. note:: - The result can be found as a null terminated string at `req->path`. +.. c:function:: int uv_fs_mkstemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl, uv_fs_cb cb) + + Equivalent to :man:`mkstemp(3)`. The created file path can be found as a null terminated string at `req->path`. + The file descriptor can be found as an integer at `req->result`. + + .. versionadded:: 1.34.0 .. c:function:: int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) diff --git a/deps/uv/docs/src/misc.rst b/deps/uv/docs/src/misc.rst index 8e167e3ec4ec..3264973bcce1 100644 --- a/deps/uv/docs/src/misc.rst +++ b/deps/uv/docs/src/misc.rst @@ -679,6 +679,7 @@ API :man:`sysctl(2)`. - FreeBSD: `getrandom(2) _`, or `/dev/urandom` after reading from `/dev/random` once. + - NetBSD: `KERN_ARND` `sysctl(3) _` - macOS, OpenBSD: `getentropy(2) _` if available, or `/dev/urandom` after reading from `/dev/random` once. - AIX: `/dev/random`. @@ -693,3 +694,9 @@ API are not used and can be set to `NULL`. .. versionadded:: 1.33.0 + +.. c:function:: void uv_sleep(unsigned int msec) + + Causes the calling thread to sleep for `msec` milliseconds. + + .. versionadded:: 1.34.0 diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index 0e8132e4384b..626cebabd8c9 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -1258,7 +1258,8 @@ typedef enum { UV_FS_OPENDIR, UV_FS_READDIR, UV_FS_CLOSEDIR, - UV_FS_STATFS + UV_FS_STATFS, + UV_FS_MKSTEMP } uv_fs_type; struct uv_dir_s { @@ -1349,6 +1350,10 @@ UV_EXTERN int uv_fs_mkdtemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl, uv_fs_cb cb); +UV_EXTERN int uv_fs_mkstemp(uv_loop_t* loop, + uv_fs_t* req, + const char* tpl, + uv_fs_cb cb); UV_EXTERN int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, @@ -1641,6 +1646,7 @@ UV_EXTERN uint64_t uv_get_total_memory(void); UV_EXTERN uint64_t uv_get_constrained_memory(void); UV_EXTERN uint64_t uv_hrtime(void); +UV_EXTERN void uv_sleep(unsigned int msec); UV_EXTERN void uv_disable_stdio_inheritance(void); diff --git a/deps/uv/include/uv/version.h b/deps/uv/include/uv/version.h index ca94be6dd4fb..8017302600d9 100644 --- a/deps/uv/include/uv/version.h +++ b/deps/uv/include/uv/version.h @@ -31,8 +31,8 @@ */ #define UV_VERSION_MAJOR 1 -#define UV_VERSION_MINOR 33 -#define UV_VERSION_PATCH 1 +#define UV_VERSION_MINOR 34 +#define UV_VERSION_PATCH 0 #define UV_VERSION_IS_RELEASE 1 #define UV_VERSION_SUFFIX "" diff --git a/deps/uv/src/random.c b/deps/uv/src/random.c index 8c4fe32013dc..491bf7033099 100644 --- a/deps/uv/src/random.c +++ b/deps/uv/src/random.c @@ -40,6 +40,8 @@ static int uv__random(void* buf, size_t buflen) { rc = uv__random_getentropy(buf, buflen); if (rc == UV_ENOSYS) rc = uv__random_devurandom(buf, buflen); +#elif defined(__NetBSD__) + rc = uv__random_sysctl(buf, buflen); #elif defined(__FreeBSD__) || defined(__linux__) rc = uv__random_getrandom(buf, buflen); if (rc == UV_ENOSYS) diff --git a/deps/uv/src/unix/aix-common.c b/deps/uv/src/unix/aix-common.c index b9d313c0c5d7..e96e34c46373 100644 --- a/deps/uv/src/unix/aix-common.c +++ b/deps/uv/src/unix/aix-common.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -158,28 +159,42 @@ int uv_exepath(char* buffer, size_t* size) { int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { uv_interface_address_t* address; - int sockfd, inet6, size = 1; + int sockfd, sock6fd, inet6, i, r, size = 1; struct ifconf ifc; struct ifreq *ifr, *p, flg; + struct in6_ifreq if6; struct sockaddr_dl* sa_addr; + ifc.ifc_req = NULL; + sock6fd = -1; + r = 0; *count = 0; *addresses = NULL; if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) { - return UV__ERR(errno); + r = UV__ERR(errno); + goto cleanup; + } + + if (0 > (sock6fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP))) { + r = UV__ERR(errno); + goto cleanup; } if (ioctl(sockfd, SIOCGSIZIFCONF, &size) == -1) { - uv__close(sockfd); - return UV__ERR(errno); + r = UV__ERR(errno); + goto cleanup; } ifc.ifc_req = (struct ifreq*)uv__malloc(size); + if (ifc.ifc_req == NULL) { + r = UV_ENOMEM; + goto cleanup; + } ifc.ifc_len = size; if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) { - uv__close(sockfd); - return UV__ERR(errno); + r = UV__ERR(errno); + goto cleanup; } #define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p)) @@ -197,8 +212,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { - uv__close(sockfd); - return UV__ERR(errno); + r = UV__ERR(errno); + goto cleanup; } if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING)) @@ -207,16 +222,14 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { (*count)++; } - if (*count == 0) { - uv__close(sockfd); - return 0; - } + if (*count == 0) + goto cleanup; /* Alloc the return interface structs */ - *addresses = uv__malloc(*count * sizeof(uv_interface_address_t)); + *addresses = uv__calloc(*count, sizeof(**addresses)); if (!(*addresses)) { - uv__close(sockfd); - return UV_ENOMEM; + r = UV_ENOMEM; + goto cleanup; } address = *addresses; @@ -233,10 +246,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { inet6 = (p->ifr_addr.sa_family == AF_INET6); memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); - if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { - uv__close(sockfd); - return UV_ENOSYS; - } + if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) + goto syserror; if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING)) continue; @@ -250,28 +261,67 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { else address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr); - sa_addr = (struct sockaddr_dl*) &p->ifr_addr; - memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); - - if (ioctl(sockfd, SIOCGIFNETMASK, p) == -1) { - uv__close(sockfd); - return UV_ENOSYS; - } - - if (inet6) - address->netmask.netmask6 = *((struct sockaddr_in6*) &p->ifr_addr); - else + if (inet6) { + memset(&if6, 0, sizeof(if6)); + r = uv__strscpy(if6.ifr_name, p->ifr_name, sizeof(if6.ifr_name)); + if (r == UV_E2BIG) + goto cleanup; + r = 0; + memcpy(&if6.ifr_Addr, &p->ifr_addr, sizeof(if6.ifr_Addr)); + if (ioctl(sock6fd, SIOCGIFNETMASK6, &if6) == -1) + goto syserror; + address->netmask.netmask6 = *((struct sockaddr_in6*) &if6.ifr_Addr); + /* Explicitly set family as the ioctl call appears to return it as 0. */ + address->netmask.netmask6.sin6_family = AF_INET6; + } else { + if (ioctl(sockfd, SIOCGIFNETMASK, p) == -1) + goto syserror; address->netmask.netmask4 = *((struct sockaddr_in*) &p->ifr_addr); + /* Explicitly set family as the ioctl call appears to return it as 0. */ + address->netmask.netmask4.sin_family = AF_INET; + } address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0; address++; } + /* Fill in physical addresses. */ + ifr = ifc.ifc_req; + while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { + p = ifr; + ifr = (struct ifreq*) + ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); + + if (p->ifr_addr.sa_family != AF_LINK) + continue; + + address = *addresses; + for (i = 0; i < *count; i++) { + if (strcmp(address->name, p->ifr_name) == 0) { + sa_addr = (struct sockaddr_dl*) &p->ifr_addr; + memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); + } + address++; + } + } + #undef ADDR_SIZE + goto cleanup; - uv__close(sockfd); - return 0; +syserror: + uv_free_interface_addresses(*addresses, *count); + *addresses = NULL; + *count = 0; + r = UV_ENOSYS; + +cleanup: + if (sockfd != -1) + uv__close(sockfd); + if (sock6fd != -1) + uv__close(sock6fd); + uv__free(ifc.ifc_req); + return r; } diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index ffce948c9574..04999dce36d1 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -1555,3 +1555,17 @@ int uv_gettimeofday(uv_timeval64_t* tv) { tv->tv_usec = (int32_t) time.tv_usec; return 0; } + +void uv_sleep(unsigned int msec) { + struct timespec timeout; + int rc; + + timeout.tv_sec = msec / 1000; + timeout.tv_nsec = (msec % 1000) * 1000 * 1000; + + do + rc = nanosleep(&timeout, &timeout); + while (rc == -1 && errno == EINTR); + + assert(rc == 0); +} diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c index b37cfbbc7a04..be256bfca6c5 100644 --- a/deps/uv/src/unix/fs.c +++ b/deps/uv/src/unix/fs.c @@ -30,6 +30,7 @@ #include "internal.h" #include +#include #include #include #include @@ -258,6 +259,80 @@ static ssize_t uv__fs_mkdtemp(uv_fs_t* req) { } +static int uv__fs_mkstemp(uv_fs_t* req) { + int r; +#ifdef O_CLOEXEC + int (*mkostemp_function)(char*, int); + static int no_cloexec_support; +#endif + static const char pattern[] = "XXXXXX"; + static const size_t pattern_size = sizeof(pattern) - 1; + char* path; + size_t path_length; + + path = (char*) req->path; + path_length = strlen(path); + + /* EINVAL can be returned for 2 reasons: + 1. The template's last 6 characters were not XXXXXX + 2. open() didn't support O_CLOEXEC + We want to avoid going to the fallback path in case + of 1, so it's manually checked before. */ + if (path_length < pattern_size || + strcmp(path + path_length - pattern_size, pattern)) { + errno = EINVAL; + return -1; + } + +#ifdef O_CLOEXEC + if (no_cloexec_support == 0) { + *(int**)(&mkostemp_function) = dlsym(RTLD_DEFAULT, "mkostemp"); + + /* We don't care about errors, but we do want to clean them up. + If there has been no error, then dlerror() will just return + NULL. */ + dlerror(); + + if (mkostemp_function != NULL) { + r = mkostemp_function(path, O_CLOEXEC); + + if (r >= 0) + return r; + + /* If mkostemp() returns EINVAL, it means the kernel doesn't + support O_CLOEXEC, so we just fallback to mkstemp() below. */ + if (errno != EINVAL) + return r; + + /* We set the static variable so that next calls don't even + try to use mkostemp. */ + no_cloexec_support = 1; + } + } +#endif /* O_CLOEXEC */ + + if (req->cb != NULL) + uv_rwlock_rdlock(&req->loop->cloexec_lock); + + r = mkstemp(path); + + /* In case of failure `uv__cloexec` will leave error in `errno`, + * so it is enough to just set `r` to `-1`. + */ + if (r >= 0 && uv__cloexec(r, 1) != 0) { + r = uv__close(r); + if (r != 0) + abort(); + r = -1; + } + + if (req->cb != NULL) + uv_rwlock_rdunlock(&req->loop->cloexec_lock); + + return r; +} + + static ssize_t uv__fs_open(uv_fs_t* req) { #ifdef O_CLOEXEC return open(req->path, req->flags | O_CLOEXEC, req->mode); @@ -999,6 +1074,7 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) { int err; size_t bytes_to_send; int64_t in_offset; + ssize_t bytes_written; dstfd = -1; err = 0; @@ -1076,18 +1152,17 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) { bytes_to_send = src_statsbuf.st_size; in_offset = 0; while (bytes_to_send != 0) { - err = uv_fs_sendfile(NULL, - &fs_req, - dstfd, - srcfd, - in_offset, - bytes_to_send, - NULL); + uv_fs_sendfile(NULL, &fs_req, dstfd, srcfd, in_offset, bytes_to_send, NULL); + bytes_written = fs_req.result; uv_fs_req_cleanup(&fs_req); - if (err < 0) + + if (bytes_written < 0) { + err = bytes_written; break; - bytes_to_send -= fs_req.result; - in_offset += fs_req.result; + } + + bytes_to_send -= bytes_written; + in_offset += bytes_written; } out: @@ -1234,13 +1309,22 @@ static int uv__fs_statx(int fd, rc = uv__statx(dirfd, path, flags, mode, &statxbuf); - if (rc == -1) { + switch (rc) { + case 0: + break; + case -1: /* EPERM happens when a seccomp filter rejects the system call. * Has been observed with libseccomp < 2.3.3 and docker < 18.04. */ if (errno != EINVAL && errno != EPERM && errno != ENOSYS) return -1; - + /* Fall through. */ + default: + /* Normally on success, zero is returned and On error, -1 is returned. + * Observed on S390 RHEL running in a docker container with statx not + * implemented, rc might return 1 with 0 set as the error code in which + * case we return ENOSYS. + */ no_statx = 1; return UV_ENOSYS; } @@ -1415,6 +1499,7 @@ static void uv__fs_work(struct uv__work* w) { X(LINK, link(req->path, req->new_path)); X(MKDIR, mkdir(req->path, req->mode)); X(MKDTEMP, uv__fs_mkdtemp(req)); + X(MKSTEMP, uv__fs_mkstemp(req)); X(OPEN, uv__fs_open(req)); X(READ, uv__fs_read(req)); X(SCANDIR, uv__fs_scandir(req)); @@ -1639,6 +1724,18 @@ int uv_fs_mkdtemp(uv_loop_t* loop, } +int uv_fs_mkstemp(uv_loop_t* loop, + uv_fs_t* req, + const char* tpl, + uv_fs_cb cb) { + INIT(MKSTEMP); + req->path = uv__strdup(tpl); + if (req->path == NULL) + return UV_ENOMEM; + POST; +} + + int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, @@ -1857,10 +1954,12 @@ void uv_fs_req_cleanup(uv_fs_t* req) { /* Only necessary for asychronous requests, i.e., requests with a callback. * Synchronous ones don't copy their arguments and have req->path and - * req->new_path pointing to user-owned memory. UV_FS_MKDTEMP is the - * exception to the rule, it always allocates memory. + * req->new_path pointing to user-owned memory. UV_FS_MKDTEMP and + * UV_FS_MKSTEMP are the exception to the rule, they always allocate memory. */ - if (req->path != NULL && (req->cb != NULL || req->fs_type == UV_FS_MKDTEMP)) + if (req->path != NULL && + (req->cb != NULL || + req->fs_type == UV_FS_MKDTEMP || req->fs_type == UV_FS_MKSTEMP)) uv__free((void*) req->path); /* Memory is shared with req->new_path. */ req->path = NULL; diff --git a/deps/uv/src/unix/netbsd.c b/deps/uv/src/unix/netbsd.c index cfe2c6a49dc3..690bd79ef91a 100644 --- a/deps/uv/src/unix/netbsd.c +++ b/deps/uv/src/unix/netbsd.c @@ -234,3 +234,26 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { uv__free(cp_times); return 0; } + +int uv__random_sysctl(void* buf, size_t len) { + static int name[] = {CTL_KERN, KERN_ARND}; + size_t count, req; + unsigned char* p; + + p = buf; + while (len) { + req = len < 32 ? len : 32; + count = req; + + if (sysctl(name, ARRAY_SIZE(name), p, &count, NULL, 0) == -1) + return UV__ERR(errno); + + if (count != req) + return UV_EIO; /* Can't happen. */ + + p += count; + len -= count; + } + + return 0; +} diff --git a/deps/uv/src/unix/os390-syscalls.c b/deps/uv/src/unix/os390-syscalls.c index 1040d66979da..d9abdebaeeda 100644 --- a/deps/uv/src/unix/os390-syscalls.c +++ b/deps/uv/src/unix/os390-syscalls.c @@ -23,11 +23,11 @@ #include "os390-syscalls.h" #include #include -#include #include #include #include +#define CW_INTRPT 1 #define CW_CONDVAR 32 #pragma linkage(BPX4CTW, OS) @@ -350,27 +350,34 @@ int nanosleep(const struct timespec* req, struct timespec* rem) { unsigned secrem; unsigned nanorem; int rv; - int rc; + int err; int rsn; nano = (int)req->tv_nsec; seconds = req->tv_sec; - events = CW_CONDVAR; + events = CW_CONDVAR | CW_INTRPT; + secrem = 0; + nanorem = 0; #if defined(_LP64) - BPX4CTW(&seconds, &nano, &events, &secrem, &nanorem, &rv, &rc, &rsn); + BPX4CTW(&seconds, &nano, &events, &secrem, &nanorem, &rv, &err, &rsn); #else - BPX1CTW(&seconds, &nano, &events, &secrem, &nanorem, &rv, &rc, &rsn); + BPX1CTW(&seconds, &nano, &events, &secrem, &nanorem, &rv, &err, &rsn); #endif - assert(rv == -1 && errno == EAGAIN); + /* Don't clobber errno unless BPX1CTW/BPX4CTW errored. + * Don't leak EAGAIN, that just means the timeout expired. + */ + if (rv == -1) + if (err != EAGAIN) + errno = err; - if(rem != NULL) { + if (rem != NULL && (rv == 0 || err == EINTR || err == EAGAIN)) { rem->tv_nsec = nanorem; rem->tv_sec = secrem; } - return 0; + return rv; } diff --git a/deps/uv/src/unix/random-devurandom.c b/deps/uv/src/unix/random-devurandom.c index bfc40d20f88c..9aa762e372ea 100644 --- a/deps/uv/src/unix/random-devurandom.c +++ b/deps/uv/src/unix/random-devurandom.c @@ -74,10 +74,10 @@ int uv__random_readpath(const char* path, void* buf, size_t buflen) { static void uv__random_devurandom_init(void) { char c; - /* Linux's and NetBSD's random(4) man page suggests applications should read - * at least once from /dev/random before switching to /dev/urandom in order - * to seed the system RNG. Reads from /dev/random can of course block - * indefinitely until entropy is available but that's the point. + /* Linux's random(4) man page suggests applications should read at least + * once from /dev/random before switching to /dev/urandom in order to seed + * the system RNG. Reads from /dev/random can of course block indefinitely + * until entropy is available but that's the point. */ status = uv__random_readpath("/dev/random", &c, 1); } diff --git a/deps/uv/src/unix/random-sysctl.c b/deps/uv/src/unix/random-sysctl-linux.c similarity index 97% rename from deps/uv/src/unix/random-sysctl.c rename to deps/uv/src/unix/random-sysctl-linux.c index fb182ded0929..66ba8d74ec22 100644 --- a/deps/uv/src/unix/random-sysctl.c +++ b/deps/uv/src/unix/random-sysctl-linux.c @@ -40,7 +40,6 @@ struct uv__sysctl_args { }; -/* TODO(bnoordhuis) Use {CTL_KERN, KERN_ARND} on FreeBSD (and NetBSD?) */ int uv__random_sysctl(void* buf, size_t buflen) { static int name[] = {1 /*CTL_KERN*/, 40 /*KERN_RANDOM*/, 6 /*RANDOM_UUID*/}; struct uv__sysctl_args args; diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c index 3ab486080cdf..8502b072021a 100644 --- a/deps/uv/src/win/fs.c +++ b/deps/uv/src/win/fs.c @@ -1195,9 +1195,10 @@ void fs__mkdir(uv_fs_t* req) { } } +typedef int (*uv__fs_mktemp_func)(uv_fs_t* req); /* OpenBSD original: lib/libc/stdio/mktemp.c */ -void fs__mkdtemp(uv_fs_t* req) { +void fs__mktemp(uv_fs_t* req, uv__fs_mktemp_func func) { static const WCHAR *tempchars = L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; static const size_t num_chars = 62; @@ -1227,13 +1228,11 @@ void fs__mkdtemp(uv_fs_t* req) { v /= num_chars; } - if (_wmkdir(req->file.pathw) == 0) { - len = strlen(req->path); - wcstombs((char*) req->path + len - num_x, ep - num_x, num_x); - SET_REQ_RESULT(req, 0); - break; - } else if (errno != EEXIST) { - SET_REQ_RESULT(req, -1); + if (func(req)) { + if (req->result >= 0) { + len = strlen(req->path); + wcstombs((char*) req->path + len - num_x, ep - num_x, num_x); + } break; } } while (--tries); @@ -1244,6 +1243,77 @@ void fs__mkdtemp(uv_fs_t* req) { } +static int fs__mkdtemp_func(uv_fs_t* req) { + if (_wmkdir(req->file.pathw) == 0) { + SET_REQ_RESULT(req, 0); + return 1; + } else if (errno != EEXIST) { + SET_REQ_RESULT(req, -1); + return 1; + } + + return 0; +} + + +void fs__mkdtemp(uv_fs_t* req) { + fs__mktemp(req, fs__mkdtemp_func); +} + + +static int fs__mkstemp_func(uv_fs_t* req) { + HANDLE file; + int fd; + + file = CreateFileW(req->file.pathw, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + CREATE_NEW, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (file == INVALID_HANDLE_VALUE) { + DWORD error; + error = GetLastError(); + + /* If the file exists, the main fs__mktemp() function + will retry. If it's another error, we want to stop. */ + if (error != ERROR_FILE_EXISTS) { + SET_REQ_WIN32_ERROR(req, error); + return 1; + } + + return 0; + } + + fd = _open_osfhandle((intptr_t) file, 0); + if (fd < 0) { + /* The only known failure mode for _open_osfhandle() is EMFILE, in which + * case GetLastError() will return zero. However we'll try to handle other + * errors as well, should they ever occur. + */ + if (errno == EMFILE) + SET_REQ_UV_ERROR(req, UV_EMFILE, ERROR_TOO_MANY_OPEN_FILES); + else if (GetLastError() != ERROR_SUCCESS) + SET_REQ_WIN32_ERROR(req, GetLastError()); + else + SET_REQ_WIN32_ERROR(req, UV_UNKNOWN); + CloseHandle(file); + return 1; + } + + SET_REQ_RESULT(req, fd); + + return 1; +} + + +void fs__mkstemp(uv_fs_t* req) { + fs__mktemp(req, fs__mkstemp_func); +} + + void fs__scandir(uv_fs_t* req) { static const size_t dirents_initial_size = 32; @@ -2609,6 +2679,7 @@ static void uv__fs_work(struct uv__work* w) { XX(RMDIR, rmdir) XX(MKDIR, mkdir) XX(MKDTEMP, mkdtemp) + XX(MKSTEMP, mkstemp) XX(RENAME, rename) XX(SCANDIR, scandir) XX(READDIR, readdir) @@ -2785,8 +2856,10 @@ int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, } -int uv_fs_mkdtemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl, - uv_fs_cb cb) { +int uv_fs_mkdtemp(uv_loop_t* loop, + uv_fs_t* req, + const char* tpl, + uv_fs_cb cb) { int err; INIT(UV_FS_MKDTEMP); @@ -2798,6 +2871,21 @@ int uv_fs_mkdtemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl, } +int uv_fs_mkstemp(uv_loop_t* loop, + uv_fs_t* req, + const char* tpl, + uv_fs_cb cb) { + int err; + + INIT(UV_FS_MKSTEMP); + err = fs__capture_path(req, tpl, NULL, TRUE); + if (err) + return uv_translate_sys_error(err); + + POST; +} + + int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { int err; diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c index 4bbeb3154123..4de638f5971c 100644 --- a/deps/uv/src/win/util.c +++ b/deps/uv/src/win/util.c @@ -1873,3 +1873,7 @@ int uv__random_rtlgenrandom(void* buf, size_t buflen) { return 0; } + +void uv_sleep(unsigned int msec) { + Sleep(msec); +} diff --git a/deps/uv/test/runner-unix.c b/deps/uv/test/runner-unix.c index 432cf33d482c..716c15ff088f 100644 --- a/deps/uv/test/runner-unix.c +++ b/deps/uv/test/runner-unix.c @@ -448,17 +448,3 @@ void rewind_cursor(void) { fprintf(stderr, "\033[2K\r"); #endif } - - -/* Pause the calling thread for a number of milliseconds. */ -void uv_sleep(int msec) { - int sec; - int usec; - - sec = msec / 1000; - usec = (msec % 1000) * 1000; - if (sec > 0) - sleep(sec); - if (usec > 0) - usleep(usec); -} diff --git a/deps/uv/test/runner-win.c b/deps/uv/test/runner-win.c index 6bb41a5d0629..4167a386921e 100644 --- a/deps/uv/test/runner-win.c +++ b/deps/uv/test/runner-win.c @@ -355,9 +355,3 @@ void rewind_cursor() { fprintf(stderr, "\n"); } } - - -/* Pause the calling thread for a number of milliseconds. */ -void uv_sleep(int msec) { - Sleep(msec); -} diff --git a/deps/uv/test/task.h b/deps/uv/test/task.h index e763f89f09dc..bc7b53369b53 100644 --- a/deps/uv/test/task.h +++ b/deps/uv/test/task.h @@ -131,9 +131,6 @@ typedef enum { int run_helper_##name(void); \ int run_helper_##name(void) -/* Pause the calling thread for a number of milliseconds. */ -void uv_sleep(int msec); - /* Format big numbers nicely. WARNING: leaks memory. */ const char* fmt(double d); diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c index 9326c6bc2753..ded1eec8dc63 100644 --- a/deps/uv/test/test-fs.c +++ b/deps/uv/test/test-fs.c @@ -73,6 +73,7 @@ static int write_cb_count; static int unlink_cb_count; static int mkdir_cb_count; static int mkdtemp_cb_count; +static int mkstemp_cb_count; static int rmdir_cb_count; static int scandir_cb_count; static int stat_cb_count; @@ -107,6 +108,9 @@ static uv_fs_t close_req; static uv_fs_t mkdir_req; static uv_fs_t mkdtemp_req1; static uv_fs_t mkdtemp_req2; +static uv_fs_t mkstemp_req1; +static uv_fs_t mkstemp_req2; +static uv_fs_t mkstemp_req3; static uv_fs_t rmdir_req; static uv_fs_t scandir_req; static uv_fs_t stat_req; @@ -538,6 +542,32 @@ static void mkdtemp_cb(uv_fs_t* req) { } +static void check_mkstemp_result(uv_fs_t* req) { + int r; + + ASSERT(req->fs_type == UV_FS_MKSTEMP); + ASSERT(req->result >= 0); + ASSERT(req->path); + ASSERT(strlen(req->path) == 16); + ASSERT(memcmp(req->path, "test_file_", 10) == 0); + ASSERT(memcmp(req->path + 10, "XXXXXX", 6) != 0); + check_permission(req->path, 0600); + + /* Check if req->path is actually a file */ + r = uv_fs_stat(NULL, &stat_req, req->path, NULL); + ASSERT(r == 0); + ASSERT(stat_req.statbuf.st_mode & S_IFREG); + uv_fs_req_cleanup(&stat_req); +} + + +static void mkstemp_cb(uv_fs_t* req) { + ASSERT(req == &mkstemp_req1); + check_mkstemp_result(req); + mkstemp_cb_count++; +} + + static void rmdir_cb(uv_fs_t* req) { ASSERT(req == &rmdir_req); ASSERT(req->fs_type == UV_FS_RMDIR); @@ -1208,6 +1238,69 @@ TEST_IMPL(fs_mkdtemp) { } +TEST_IMPL(fs_mkstemp) { + int r; + int fd; + const char path_template[] = "test_file_XXXXXX"; + uv_fs_t req; + + loop = uv_default_loop(); + + r = uv_fs_mkstemp(loop, &mkstemp_req1, path_template, mkstemp_cb); + ASSERT(r == 0); + + uv_run(loop, UV_RUN_DEFAULT); + ASSERT(mkstemp_cb_count == 1); + + /* sync mkstemp */ + r = uv_fs_mkstemp(NULL, &mkstemp_req2, path_template, NULL); + ASSERT(r >= 0); + check_mkstemp_result(&mkstemp_req2); + + /* mkstemp return different values on subsequent calls */ + ASSERT(strcmp(mkstemp_req1.path, mkstemp_req2.path) != 0); + + /* invalid template returns EINVAL */ + ASSERT(uv_fs_mkstemp(NULL, &mkstemp_req3, "test_file", NULL) == UV_EINVAL); + + /* We can write to the opened file */ + iov = uv_buf_init(test_buf, sizeof(test_buf)); + r = uv_fs_write(NULL, &req, mkstemp_req1.result, &iov, 1, -1, NULL); + ASSERT(r == sizeof(test_buf)); + ASSERT(req.result == sizeof(test_buf)); + uv_fs_req_cleanup(&req); + + /* Cleanup */ + uv_fs_close(NULL, &req, mkstemp_req1.result, NULL); + uv_fs_req_cleanup(&req); + uv_fs_close(NULL, &req, mkstemp_req2.result, NULL); + uv_fs_req_cleanup(&req); + + fd = uv_fs_open(NULL, &req, mkstemp_req1.path , O_RDONLY, 0, NULL); + ASSERT(fd >= 0); + uv_fs_req_cleanup(&req); + + memset(buf, 0, sizeof(buf)); + iov = uv_buf_init(buf, sizeof(buf)); + r = uv_fs_read(NULL, &req, fd, &iov, 1, -1, NULL); + ASSERT(r >= 0); + ASSERT(req.result >= 0); + ASSERT(strcmp(buf, test_buf) == 0); + uv_fs_req_cleanup(&req); + + uv_fs_close(NULL, &req, fd, NULL); + uv_fs_req_cleanup(&req); + + unlink(mkstemp_req1.path); + unlink(mkstemp_req2.path); + uv_fs_req_cleanup(&mkstemp_req1); + uv_fs_req_cleanup(&mkstemp_req2); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + + TEST_IMPL(fs_fstat) { int r; uv_fs_t req; @@ -3784,6 +3877,9 @@ TEST_IMPL(fs_null_req) { r = uv_fs_mkdtemp(NULL, NULL, NULL, NULL); ASSERT(r == UV_EINVAL); + r = uv_fs_mkstemp(NULL, NULL, NULL, NULL); + ASSERT(r == UV_EINVAL); + r = uv_fs_rmdir(NULL, NULL, NULL, NULL); ASSERT(r == UV_EINVAL); diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index ad94c52d0c58..a6cfc6bb9284 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -310,6 +310,7 @@ TEST_DECLARE (fs_async_dir) TEST_DECLARE (fs_async_sendfile) TEST_DECLARE (fs_async_sendfile_nodata) TEST_DECLARE (fs_mkdtemp) +TEST_DECLARE (fs_mkstemp) TEST_DECLARE (fs_fstat) TEST_DECLARE (fs_access) TEST_DECLARE (fs_chmod) @@ -920,6 +921,7 @@ TASK_LIST_START TEST_ENTRY (fs_async_sendfile) TEST_ENTRY (fs_async_sendfile_nodata) TEST_ENTRY (fs_mkdtemp) + TEST_ENTRY (fs_mkstemp) TEST_ENTRY (fs_fstat) TEST_ENTRY (fs_access) TEST_ENTRY (fs_chmod) diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index 6a24b7b1706e..bbeda104b47a 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -245,7 +245,7 @@ 'src/unix/linux-syscalls.h', 'src/unix/procfs-exepath.c', 'src/unix/random-getrandom.c', - 'src/unix/random-sysctl.c', + 'src/unix/random-sysctl-linux.c', 'src/unix/sysinfo-loadavg.c', ], 'link_settings': { @@ -261,8 +261,9 @@ 'src/unix/pthread-fixes.c', 'src/unix/android-ifaddrs.c', 'src/unix/procfs-exepath.c', + 'src/unix/random-getrandom.c', + 'src/unix/random-sysctl-linux.c', 'src/unix/sysinfo-loadavg.c', - 'src/unix/sysinfo-memory.c', ], 'link_settings': { 'libraries': [ '-ldl' ], From c23e499d3c363459a3afb25e50f10976f9046f90 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Sun, 12 Jan 2020 18:41:48 -0500 Subject: [PATCH 8/9] deps: upgrade to libuv 1.34.1 Notable changes: - uv_fs_copyfile() now supports CIFS share destinations. - isatty() now works on IBMi - TTYs are opened with the O_NOCTTY flag. Fixes: https://github.com/nodejs/node/issues/31170 PR-URL: https://github.com/nodejs/node/pull/31332 Reviewed-By: Jiawen Geng Reviewed-By: Richard Lau Reviewed-By: Ruben Bridgewater Reviewed-By: David Carlier Reviewed-By: Ben Noordhuis Reviewed-By: Rich Trott Reviewed-By: Trivikram Kamat --- deps/uv/AUTHORS | 1 + deps/uv/ChangeLog | 67 ++ deps/uv/Makefile.am | 1 - deps/uv/README.md | 3 - deps/uv/common.gypi | 5 +- deps/uv/configure.ac | 5 +- deps/uv/docs/src/design.rst | 2 +- deps/uv/docs/src/fs.rst | 22 +- deps/uv/docs/src/fs_event.rst | 2 +- deps/uv/docs/src/index.rst | 8 +- deps/uv/docs/src/misc.rst | 14 +- deps/uv/docs/src/pipe.rst | 7 +- deps/uv/docs/src/sphinx-plugins/manpage.py | 2 +- deps/uv/docs/src/version.rst | 2 +- deps/uv/include/uv/version.h | 2 +- deps/uv/samples/.gitignore | 22 - deps/uv/samples/socks5-proxy/.gitignore | 21 - deps/uv/samples/socks5-proxy/LICENSE | 53 -- deps/uv/samples/socks5-proxy/build.gyp | 46 -- deps/uv/samples/socks5-proxy/client.c | 736 ------------------ deps/uv/samples/socks5-proxy/defs.h | 139 ---- deps/uv/samples/socks5-proxy/getopt.c | 131 ---- deps/uv/samples/socks5-proxy/main.c | 99 --- deps/uv/samples/socks5-proxy/s5.c | 271 ------- deps/uv/samples/socks5-proxy/s5.h | 94 --- deps/uv/samples/socks5-proxy/server.c | 241 ------ deps/uv/samples/socks5-proxy/util.c | 72 -- deps/uv/src/unix/darwin-proctitle.c | 130 ++-- deps/uv/src/unix/darwin.c | 6 +- deps/uv/src/unix/freebsd.c | 8 +- deps/uv/src/unix/fs.c | 75 +- deps/uv/src/unix/linux-core.c | 16 +- deps/uv/src/unix/netbsd.c | 8 +- deps/uv/src/unix/openbsd.c | 30 +- deps/uv/src/unix/proctitle.c | 4 - deps/uv/src/unix/signal.c | 1 + deps/uv/src/unix/stream.c | 7 +- deps/uv/src/unix/tty.c | 9 +- deps/uv/src/win/core.c | 9 +- deps/uv/src/win/tty.c | 70 +- deps/uv/src/win/winsock.c | 47 +- deps/uv/test/run-tests.c | 7 + deps/uv/test/task.h | 2 +- deps/uv/test/test-dlerror.c | 4 + deps/uv/test/test-fs.c | 40 +- deps/uv/test/test-platform-output.c | 4 + .../test-poll-close-doesnt-corrupt-stack.c | 6 +- deps/uv/test/test-poll-closesocket.c | 5 +- deps/uv/test/test-process-title-threadsafe.c | 8 +- deps/uv/test/test-process-title.c | 3 +- deps/uv/test/test-thread.c | 1 + deps/uv/test/test-udp-multicast-join.c | 2 + deps/uv/uv.gyp | 3 +- 53 files changed, 369 insertions(+), 2204 deletions(-) delete mode 100644 deps/uv/samples/.gitignore delete mode 100644 deps/uv/samples/socks5-proxy/.gitignore delete mode 100644 deps/uv/samples/socks5-proxy/LICENSE delete mode 100644 deps/uv/samples/socks5-proxy/build.gyp delete mode 100644 deps/uv/samples/socks5-proxy/client.c delete mode 100644 deps/uv/samples/socks5-proxy/defs.h delete mode 100644 deps/uv/samples/socks5-proxy/getopt.c delete mode 100644 deps/uv/samples/socks5-proxy/main.c delete mode 100644 deps/uv/samples/socks5-proxy/s5.c delete mode 100644 deps/uv/samples/socks5-proxy/s5.h delete mode 100644 deps/uv/samples/socks5-proxy/server.c delete mode 100644 deps/uv/samples/socks5-proxy/util.c diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS index dcc36e8c17f9..f829778a21c1 100644 --- a/deps/uv/AUTHORS +++ b/deps/uv/AUTHORS @@ -412,3 +412,4 @@ ZYSzys Carl Lei Stefan Bender nia +virtualyw diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index a0509e6e153f..b57ff4716a82 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,3 +1,70 @@ +2020.01.13, Version 1.34.1 (Stable), 8aa5636ec72990bb2856f81e14c95813024a5c2b + +Changes since version 1.34.0: + +* unix: fix -Wstrict-aliasing compiler warning (Ben Noordhuis) + +* unix: cache address of dlsym("mkostemp") (Ben Noordhuis) + +* build: remove -pedantic from compiler flags (Ben Noordhuis) + +* Revert "darwin: assume pthread_setname_np() is available" (Ben Noordhuis) + +* Revert "darwin: speed up uv_set_process_title()" (Ben Noordhuis) + +* darwin: assume pthread_setname_np() is available (Ben Noordhuis) + +* ibmi: fix the false isatty() issue on IBMi (Xu Meng) + +* test: fix test failure under NetBSD and OpenBSD (David Carlier) + +* test: skip some test cases on IBMi (Xu Meng) + +* test: skip uv_(get|set)_process_title on IBMi (Xu Meng) + +* doc: remove binaries for Windows from README (Richard Lau) + +* unix: fix -Wunused-but-set-variable warning (George Zhao) + +* unix: pass sysctl size arg using ARRAY_SIZE macro (David Carlier) + +* test: disallow running the test suite as root (cjihrig) + +* unix: suppress -Waddress-of-packed-member warning (Ben Noordhuis) + +* misc: make more tags "not-stale" (Jameson Nash) + +* test: fix pthread memory leak (Trevor Norris) + +* docs: delete socks5-proxy sample (Jameson Nash) + +* ibmi: fix the CMSG length issue (Xu Meng) + +* docs: fix formatting (Jameson Nash) + +* unix: squelch fchmod() EPERM on CIFS share (Ben Noordhuis) + +* docs: fix linkcheck (Jameson Nash) + +* docs: switch from linux.die.net to man7.org (Jameson Nash) + +* win: remove abort when non-IFS LSP detection fails (virtualyw) + +* docs: clarify that uv_pipe_t is a pipe (Jameson Nash) + +* win,tty: avoid regressions in utf-8 handling (Jameson Nash) + +* win: remove bad assert in uv_loop_close (Jameson Nash) + +* test: fix -fno-common build errors (Ben Noordhuis) + +* build: turn on -fno-common to catch regressions (Ben Noordhuis) + +* test: fix fs birth time test failure (Ben Noordhuis) + +* tty,unix: avoid affecting controlling TTY (Jameson Nash) + + 2019.12.05, Version 1.34.0 (Stable), 15ae750151ac9341e5945eb38f8982d59fb99201 Changes since version 1.33.1: diff --git a/deps/uv/Makefile.am b/deps/uv/Makefile.am index 088b4bbd76f3..9a06b9ce4a73 100644 --- a/deps/uv/Makefile.am +++ b/deps/uv/Makefile.am @@ -123,7 +123,6 @@ EXTRA_DIST = test/fixtures/empty_file \ include \ docs \ img \ - samples \ android-configure-arm \ android-configure-arm64 \ android-configure-x86 \ diff --git a/deps/uv/README.md b/deps/uv/README.md index f9daaa1cea15..c040b4c18c89 100644 --- a/deps/uv/README.md +++ b/deps/uv/README.md @@ -116,9 +116,6 @@ libuv can be downloaded either from the [GitHub repository](https://github.com/libuv/libuv) or from the [downloads site](http://dist.libuv.org/dist/). -Starting with libuv 1.7.0, binaries for Windows are also provided. This is to -be considered EXPERIMENTAL. - Before verifying the git tags or signature files, importing the relevant keys is necessary. Key IDs are listed in the [MAINTAINERS](https://github.com/libuv/libuv/blob/master/MAINTAINERS.md) diff --git a/deps/uv/common.gypi b/deps/uv/common.gypi index 2297bdf0fb0c..8e2aa7160bb0 100644 --- a/deps/uv/common.gypi +++ b/deps/uv/common.gypi @@ -35,7 +35,7 @@ }, 'conditions': [ ['OS != "zos"', { - 'cflags': [ '-O0', '-fwrapv' ] + 'cflags': [ '-O0', '-fno-common', '-fwrapv' ] }], ['OS == "android"', { 'cflags': [ '-fPIE' ], @@ -80,9 +80,10 @@ 'conditions': [ ['OS != "zos"', { 'cflags': [ - '-fomit-frame-pointer', '-fdata-sections', '-ffunction-sections', + '-fno-common', + '-fomit-frame-pointer', ], }], ] diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac index 6ea6b6a06cd1..ea7fea90125f 100644 --- a/deps/uv/configure.ac +++ b/deps/uv/configure.ac @@ -13,7 +13,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. AC_PREREQ(2.57) -AC_INIT([libuv], [1.34.0], [https://github.com/libuv/libuv/issues]) +AC_INIT([libuv], [1.34.1], [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]) @@ -24,9 +24,6 @@ AC_ENABLE_SHARED AC_ENABLE_STATIC AC_PROG_CC AM_PROG_CC_C_O -AS_IF([AS_CASE([$host_os],[openedition*], [false], [true])], [ - CC_CHECK_CFLAGS_APPEND([-pedantic]) -]) CC_FLAG_VISIBILITY #[-fvisibility=hidden] CC_CHECK_CFLAGS_APPEND([-g]) CC_CHECK_CFLAGS_APPEND([-std=gnu89]) diff --git a/deps/uv/docs/src/design.rst b/deps/uv/docs/src/design.rst index 9594bd1a77ed..a23e33a214a1 100644 --- a/deps/uv/docs/src/design.rst +++ b/deps/uv/docs/src/design.rst @@ -126,7 +126,7 @@ Unlike network I/O, there are no platform-specific file I/O primitives libuv cou so the current approach is to run blocking file I/O operations in a thread pool. For a thorough explanation of the cross-platform file I/O landscape, checkout -`this post `_. +`this post `_. libuv currently uses a global thread pool on which all loops can queue work. 3 types of operations are currently run on this pool: diff --git a/deps/uv/docs/src/fs.rst b/deps/uv/docs/src/fs.rst index 28356c2d442e..2943ead330cc 100644 --- a/deps/uv/docs/src/fs.rst +++ b/deps/uv/docs/src/fs.rst @@ -403,7 +403,7 @@ API .. c:function:: int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb) .. c:function:: int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime, double mtime, uv_fs_cb cb) - Equivalent to :man:`utime(2)` and :man:`futime(2)` respectively. + Equivalent to :man:`utime(2)` and :man:`futimes(3)` respectively. .. note:: AIX: This function only works for AIX 7.1 and newer. It can still be called on older @@ -435,7 +435,7 @@ API .. c:function:: int uv_fs_realpath(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) - Equivalent to :man:`realpath(3)` on Unix. Windows uses `GetFinalPathNameByHandle `_. + Equivalent to :man:`realpath(3)` on Unix. Windows uses `GetFinalPathNameByHandle `_. The resulting string is stored in `req->ptr`. .. warning:: @@ -512,7 +512,7 @@ Helper functions .. c:function:: uv_os_fd_t uv_get_osfhandle(int fd) For a file descriptor in the C runtime, get the OS-dependent handle. - On UNIX, returns the ``fd`` intact. On Windows, this calls `_get_osfhandle `_. + On UNIX, returns the ``fd`` intact. On Windows, this calls `_get_osfhandle `_. Note that the return value is still owned by the C runtime, any attempts to close it or to use it after closing the fd may lead to malfunction. @@ -521,7 +521,7 @@ Helper functions .. c:function:: int uv_open_osfhandle(uv_os_fd_t os_fd) For a OS-dependent handle, get the file descriptor in the C runtime. - On UNIX, returns the ``os_fd`` intact. On Windows, this calls `_open_osfhandle `_. + On UNIX, returns the ``os_fd`` intact. On Windows, this calls `_open_osfhandle `_. Note that the return value is still owned by the CRT, any attempts to close it or to use it after closing the handle may lead to malfunction. @@ -547,7 +547,7 @@ File open constants .. note:: `UV_FS_O_DIRECT` is supported on Linux, and on Windows via - `FILE_FLAG_NO_BUFFERING `_. + `FILE_FLAG_NO_BUFFERING `_. `UV_FS_O_DIRECT` is not supported on macOS. .. c:macro:: UV_FS_O_DIRECTORY @@ -564,7 +564,7 @@ File open constants .. note:: `UV_FS_O_DSYNC` is supported on Windows via - `FILE_FLAG_WRITE_THROUGH `_. + `FILE_FLAG_WRITE_THROUGH `_. .. c:macro:: UV_FS_O_EXCL @@ -631,7 +631,7 @@ File open constants .. note:: `UV_FS_O_RANDOM` is only supported on Windows via - `FILE_FLAG_RANDOM_ACCESS `_. + `FILE_FLAG_RANDOM_ACCESS `_. .. c:macro:: UV_FS_O_RDONLY @@ -648,7 +648,7 @@ File open constants .. note:: `UV_FS_O_SEQUENTIAL` is only supported on Windows via - `FILE_FLAG_SEQUENTIAL_SCAN `_. + `FILE_FLAG_SEQUENTIAL_SCAN `_. .. c:macro:: UV_FS_O_SHORT_LIVED @@ -656,7 +656,7 @@ File open constants .. note:: `UV_FS_O_SHORT_LIVED` is only supported on Windows via - `FILE_ATTRIBUTE_TEMPORARY `_. + `FILE_ATTRIBUTE_TEMPORARY `_. .. c:macro:: UV_FS_O_SYMLINK @@ -669,7 +669,7 @@ File open constants .. note:: `UV_FS_O_SYNC` is supported on Windows via - `FILE_FLAG_WRITE_THROUGH `_. + `FILE_FLAG_WRITE_THROUGH `_. .. c:macro:: UV_FS_O_TEMPORARY @@ -677,7 +677,7 @@ File open constants .. note:: `UV_FS_O_TEMPORARY` is only supported on Windows via - `FILE_ATTRIBUTE_TEMPORARY `_. + `FILE_ATTRIBUTE_TEMPORARY `_. .. c:macro:: UV_FS_O_TRUNC diff --git a/deps/uv/docs/src/fs_event.rst b/deps/uv/docs/src/fs_event.rst index bd076aaeb404..e28ec625ed6b 100644 --- a/deps/uv/docs/src/fs_event.rst +++ b/deps/uv/docs/src/fs_event.rst @@ -23,7 +23,7 @@ the best backend for the job on each platform. creation/deletion within a directory that is being monitored. See the `IBM Knowledge centre`_ for more details. - .. _documentation: http://www.ibm.com/developerworks/aix/library/au-aix_event_infrastructure/ + .. _documentation: https://developer.ibm.com/articles/au-aix_event_infrastructure/ .. _`IBM Knowledge centre`: https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.2.0/com.ibm.zos.v2r1.bpxb100/ioc.htm diff --git a/deps/uv/docs/src/index.rst b/deps/uv/docs/src/index.rst index 5ec2beb511cb..f696dc16279b 100644 --- a/deps/uv/docs/src/index.rst +++ b/deps/uv/docs/src/index.rst @@ -13,9 +13,9 @@ was primarily developed for use by `Node.js`_, but it's also used by `Luvit`_, In case you find errors in this documentation you can help by sending `pull requests `_! -.. _Node.js: http://nodejs.org -.. _Luvit: http://luvit.io -.. _Julia: http://julialang.org +.. _Node.js: https://nodejs.org +.. _Luvit: https://luvit.io +.. _Julia: https://julialang.org .. _pyuv: https://github.com/saghul/pyuv .. _others: https://github.com/libuv/libuv/wiki/Projects-that-use-libuv @@ -52,7 +52,7 @@ Documentation Downloads --------- -libuv can be downloaded from `here `_. +libuv can be downloaded from `here `_. Installation diff --git a/deps/uv/docs/src/misc.rst b/deps/uv/docs/src/misc.rst index 3264973bcce1..7cfac85f571b 100644 --- a/deps/uv/docs/src/misc.rst +++ b/deps/uv/docs/src/misc.rst @@ -192,10 +192,10 @@ Data types :: - typedef struct uv_env_item_s { - char* name; - char* value; - } uv_env_item_t; + typedef struct uv_env_item_s { + char* name; + char* value; + } uv_env_item_t; .. c:type:: uv_random_t @@ -314,7 +314,7 @@ API .. c:function:: void uv_loadavg(double avg[3]) - Gets the load average. See: ``_ + Gets the load average. See: ``_ .. note:: Returns [0,0,0] on Windows (i.e., it's not implemented). @@ -646,7 +646,7 @@ API Retrieves system information in `buffer`. The populated data includes the operating system name, release, version, and machine. On non-Windows - systems, `uv_os_uname()` is a thin wrapper around :man:`uname(3)`. Returns + systems, `uv_os_uname()` is a thin wrapper around :man:`uname(2)`. Returns zero on success, and a non-zero error value otherwise. .. versionadded:: 1.25.0 @@ -687,7 +687,7 @@ API - Other UNIX: `/dev/urandom` after reading from `/dev/random` once. :returns: 0 on success, or an error code < 0 on failure. The contents of - `buf` is undefined after an error. + `buf` is undefined after an error. .. note:: When using the synchronous version, both `loop` and `req` parameters diff --git a/deps/uv/docs/src/pipe.rst b/deps/uv/docs/src/pipe.rst index 376d6117bbea..5eac1b6df48e 100644 --- a/deps/uv/docs/src/pipe.rst +++ b/deps/uv/docs/src/pipe.rst @@ -4,8 +4,8 @@ :c:type:`uv_pipe_t` --- Pipe handle =================================== -Pipe handles provide an abstraction over local domain sockets on Unix and named -pipes on Windows. +Pipe handles provide an abstraction over streaming files on Unix (including +local domain sockets, pipes, and FIFOs) and named pipes on Windows. :c:type:`uv_pipe_t` is a 'subclass' of :c:type:`uv_stream_t`. @@ -34,7 +34,8 @@ API .. c:function:: int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) Initialize a pipe handle. The `ipc` argument is a boolean to indicate if - this pipe will be used for handle passing between processes. + this pipe will be used for handle passing between processes (which may + change the bytes on the wire). .. c:function:: int uv_pipe_open(uv_pipe_t* handle, uv_file file) diff --git a/deps/uv/docs/src/sphinx-plugins/manpage.py b/deps/uv/docs/src/sphinx-plugins/manpage.py index bb597e280111..672b0020bddb 100644 --- a/deps/uv/docs/src/sphinx-plugins/manpage.py +++ b/deps/uv/docs/src/sphinx-plugins/manpage.py @@ -18,7 +18,7 @@ def make_link_node(rawtext, app, name, manpage_num, options): ref = app.config.man_url_regex if not ref: - ref = "http://linux.die.net/man/%s/%s" % (manpage_num, name) + ref = "http://man7.org/linux/man-pages/man%s/%s.%s.html" %(manpage_num, name, manpage_num) else: s = Template(ref) ref = s.substitute(num=manpage_num, topic=name) diff --git a/deps/uv/docs/src/version.rst b/deps/uv/docs/src/version.rst index e1715b2d3c53..13b094008da9 100644 --- a/deps/uv/docs/src/version.rst +++ b/deps/uv/docs/src/version.rst @@ -10,7 +10,7 @@ a major release. In this section you'll find all macros and functions that will allow you to write or compile code conditionally, in order to work with multiple libuv versions. -.. _semantic versioning: http://semver.org +.. _semantic versioning: https://semver.org Macros diff --git a/deps/uv/include/uv/version.h b/deps/uv/include/uv/version.h index 8017302600d9..cfa321148039 100644 --- a/deps/uv/include/uv/version.h +++ b/deps/uv/include/uv/version.h @@ -32,7 +32,7 @@ #define UV_VERSION_MAJOR 1 #define UV_VERSION_MINOR 34 -#define UV_VERSION_PATCH 0 +#define UV_VERSION_PATCH 1 #define UV_VERSION_IS_RELEASE 1 #define UV_VERSION_SUFFIX "" diff --git a/deps/uv/samples/.gitignore b/deps/uv/samples/.gitignore deleted file mode 100644 index f868091ba327..000000000000 --- a/deps/uv/samples/.gitignore +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright StrongLoop, Inc. All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -*.mk -*.Makefile diff --git a/deps/uv/samples/socks5-proxy/.gitignore b/deps/uv/samples/socks5-proxy/.gitignore deleted file mode 100644 index c177f3745107..000000000000 --- a/deps/uv/samples/socks5-proxy/.gitignore +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright StrongLoop, Inc. All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -/build/ diff --git a/deps/uv/samples/socks5-proxy/LICENSE b/deps/uv/samples/socks5-proxy/LICENSE deleted file mode 100644 index 63c1447fc55e..000000000000 --- a/deps/uv/samples/socks5-proxy/LICENSE +++ /dev/null @@ -1,53 +0,0 @@ -Files: * -======== - -Copyright StrongLoop, Inc. All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. - - -Files: getopt.c -=============== - -Copyright (c) 1987, 1993, 1994 -The Regents of the University of California. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. Neither the name of the University nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -SUCH DAMAGE. diff --git a/deps/uv/samples/socks5-proxy/build.gyp b/deps/uv/samples/socks5-proxy/build.gyp deleted file mode 100644 index 771a1e146db4..000000000000 --- a/deps/uv/samples/socks5-proxy/build.gyp +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright StrongLoop, Inc. All rights reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -{ - 'targets': [ - { - 'dependencies': ['../../uv.gyp:libuv'], - 'target_name': 's5-proxy', - 'type': 'executable', - 'sources': [ - 'client.c', - 'defs.h', - 'main.c', - 's5.c', - 's5.h', - 'server.c', - 'util.c', - ], - 'conditions': [ - ['OS=="win"', { - 'defines': ['HAVE_UNISTD_H=0'], - 'sources': ['getopt.c'] - }, { - 'defines': ['HAVE_UNISTD_H=1'] - }] - ] - } - ] -} diff --git a/deps/uv/samples/socks5-proxy/client.c b/deps/uv/samples/socks5-proxy/client.c deleted file mode 100644 index aa2a91c9a12e..000000000000 --- a/deps/uv/samples/socks5-proxy/client.c +++ /dev/null @@ -1,736 +0,0 @@ -/* Copyright StrongLoop, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "defs.h" -#include -#include -#include - -/* A connection is modeled as an abstraction on top of two simple state - * machines, one for reading and one for writing. Either state machine - * is, when active, in one of three states: busy, done or stop; the fourth - * and final state, dead, is an end state and only relevant when shutting - * down the connection. A short overview: - * - * busy done stop - * ----------|---------------------------|--------------------|------| - * readable | waiting for incoming data | have incoming data | idle | - * writable | busy writing out data | completed write | idle | - * - * We could remove the done state from the writable state machine. For our - * purposes, it's functionally equivalent to the stop state. - * - * When the connection with upstream has been established, the client_ctx - * moves into a state where incoming data from the client is sent upstream - * and vice versa, incoming data from upstream is sent to the client. In - * other words, we're just piping data back and forth. See conn_cycle() - * for details. - * - * An interesting deviation from libuv's I/O model is that reads are discrete - * rather than continuous events. In layman's terms, when a read operation - * completes, the connection stops reading until further notice. - * - * The rationale for this approach is that we have to wait until the data - * has been sent out again before we can reuse the read buffer. - * - * It also pleasingly unifies with the request model that libuv uses for - * writes and everything else; libuv may switch to a request model for - * reads in the future. - */ -enum conn_state { - c_busy, /* Busy; waiting for incoming data or for a write to complete. */ - c_done, /* Done; read incoming data or write finished. */ - c_stop, /* Stopped. */ - c_dead -}; - -/* Session states. */ -enum sess_state { - s_handshake, /* Wait for client handshake. */ - s_handshake_auth, /* Wait for client authentication data. */ - s_req_start, /* Start waiting for request data. */ - s_req_parse, /* Wait for request data. */ - s_req_lookup, /* Wait for upstream hostname DNS lookup to complete. */ - s_req_connect, /* Wait for uv_tcp_connect() to complete. */ - s_proxy_start, /* Connected. Start piping data. */ - s_proxy, /* Connected. Pipe data back and forth. */ - s_kill, /* Tear down session. */ - s_almost_dead_0, /* Waiting for finalizers to complete. */ - s_almost_dead_1, /* Waiting for finalizers to complete. */ - s_almost_dead_2, /* Waiting for finalizers to complete. */ - s_almost_dead_3, /* Waiting for finalizers to complete. */ - s_almost_dead_4, /* Waiting for finalizers to complete. */ - s_dead /* Dead. Safe to free now. */ -}; - -static void do_next(client_ctx *cx); -static int do_handshake(client_ctx *cx); -static int do_handshake_auth(client_ctx *cx); -static int do_req_start(client_ctx *cx); -static int do_req_parse(client_ctx *cx); -static int do_req_lookup(client_ctx *cx); -static int do_req_connect_start(client_ctx *cx); -static int do_req_connect(client_ctx *cx); -static int do_proxy_start(client_ctx *cx); -static int do_proxy(client_ctx *cx); -static int do_kill(client_ctx *cx); -static int do_almost_dead(client_ctx *cx); -static int conn_cycle(const char *who, conn *a, conn *b); -static void conn_timer_reset(conn *c); -static void conn_timer_expire(uv_timer_t *handle); -static void conn_getaddrinfo(conn *c, const char *hostname); -static void conn_getaddrinfo_done(uv_getaddrinfo_t *req, - int status, - struct addrinfo *ai); -static int conn_connect(conn *c); -static void conn_connect_done(uv_connect_t *req, int status); -static void conn_read(conn *c); -static void conn_read_done(uv_stream_t *handle, - ssize_t nread, - const uv_buf_t *buf); -static void conn_alloc(uv_handle_t *handle, size_t size, uv_buf_t *buf); -static void conn_write(conn *c, const void *data, unsigned int len); -static void conn_write_done(uv_write_t *req, int status); -static void conn_close(conn *c); -static void conn_close_done(uv_handle_t *handle); - -/* |incoming| has been initialized by server.c when this is called. */ -void client_finish_init(server_ctx *sx, client_ctx *cx) { - conn *incoming; - conn *outgoing; - - cx->sx = sx; - cx->state = s_handshake; - s5_init(&cx->parser); - - incoming = &cx->incoming; - incoming->client = cx; - incoming->result = 0; - incoming->rdstate = c_stop; - incoming->wrstate = c_stop; - incoming->idle_timeout = sx->idle_timeout; - CHECK(0 == uv_timer_init(sx->loop, &incoming->timer_handle)); - - outgoing = &cx->outgoing; - outgoing->client = cx; - outgoing->result = 0; - outgoing->rdstate = c_stop; - outgoing->wrstate = c_stop; - outgoing->idle_timeout = sx->idle_timeout; - CHECK(0 == uv_tcp_init(cx->sx->loop, &outgoing->handle.tcp)); - CHECK(0 == uv_timer_init(cx->sx->loop, &outgoing->timer_handle)); - - /* Wait for the initial packet. */ - conn_read(incoming); -} - -/* This is the core state machine that drives the client <-> upstream proxy. - * We move through the initial handshake and authentication steps first and - * end up (if all goes well) in the proxy state where we're just proxying - * data between the client and upstream. - */ -static void do_next(client_ctx *cx) { - int new_state; - - ASSERT(cx->state != s_dead); - switch (cx->state) { - case s_handshake: - new_state = do_handshake(cx); - break; - case s_handshake_auth: - new_state = do_handshake_auth(cx); - break; - case s_req_start: - new_state = do_req_start(cx); - break; - case s_req_parse: - new_state = do_req_parse(cx); - break; - case s_req_lookup: - new_state = do_req_lookup(cx); - break; - case s_req_connect: - new_state = do_req_connect(cx); - break; - case s_proxy_start: - new_state = do_proxy_start(cx); - break; - case s_proxy: - new_state = do_proxy(cx); - break; - case s_kill: - new_state = do_kill(cx); - break; - case s_almost_dead_0: - case s_almost_dead_1: - case s_almost_dead_2: - case s_almost_dead_3: - case s_almost_dead_4: - new_state = do_almost_dead(cx); - break; - default: - UNREACHABLE(); - } - cx->state = new_state; - - if (cx->state == s_dead) { - if (DEBUG_CHECKS) { - memset(cx, -1, sizeof(*cx)); - } - free(cx); - } -} - -static int do_handshake(client_ctx *cx) { - unsigned int methods; - conn *incoming; - s5_ctx *parser; - uint8_t *data; - size_t size; - int err; - - parser = &cx->parser; - incoming = &cx->incoming; - ASSERT(incoming->rdstate == c_done); - ASSERT(incoming->wrstate == c_stop); - incoming->rdstate = c_stop; - - if (incoming->result < 0) { - pr_err("read error: %s", uv_strerror(incoming->result)); - return do_kill(cx); - } - - data = (uint8_t *) incoming->t.buf; - size = (size_t) incoming->result; - err = s5_parse(parser, &data, &size); - if (err == s5_ok) { - conn_read(incoming); - return s_handshake; /* Need more data. */ - } - - if (size != 0) { - /* Could allow a round-trip saving shortcut here if the requested auth - * method is S5_AUTH_NONE (provided unauthenticated traffic is allowed.) - * Requires client support however. - */ - pr_err("junk in handshake"); - return do_kill(cx); - } - - if (err != s5_auth_select) { - pr_err("handshake error: %s", s5_strerror(err)); - return do_kill(cx); - } - - methods = s5_auth_methods(parser); - if ((methods & S5_AUTH_NONE) && can_auth_none(cx->sx, cx)) { - s5_select_auth(parser, S5_AUTH_NONE); - conn_write(incoming, "\5\0", 2); /* No auth required. */ - return s_req_start; - } - - if ((methods & S5_AUTH_PASSWD) && can_auth_passwd(cx->sx, cx)) { - /* TODO(bnoordhuis) Implement username/password auth. */ - } - - conn_write(incoming, "\5\377", 2); /* No acceptable auth. */ - return s_kill; -} - -/* TODO(bnoordhuis) Implement username/password auth. */ -static int do_handshake_auth(client_ctx *cx) { - UNREACHABLE(); - return do_kill(cx); -} - -static int do_req_start(client_ctx *cx) { - conn *incoming; - - incoming = &cx->incoming; - ASSERT(incoming->rdstate == c_stop); - ASSERT(incoming->wrstate == c_done); - incoming->wrstate = c_stop; - - if (incoming->result < 0) { - pr_err("write error: %s", uv_strerror(incoming->result)); - return do_kill(cx); - } - - conn_read(incoming); - return s_req_parse; -} - -static int do_req_parse(client_ctx *cx) { - conn *incoming; - conn *outgoing; - s5_ctx *parser; - uint8_t *data; - size_t size; - int err; - - parser = &cx->parser; - incoming = &cx->incoming; - outgoing = &cx->outgoing; - ASSERT(incoming->rdstate == c_done); - ASSERT(incoming->wrstate == c_stop); - ASSERT(outgoing->rdstate == c_stop); - ASSERT(outgoing->wrstate == c_stop); - incoming->rdstate = c_stop; - - if (incoming->result < 0) { - pr_err("read error: %s", uv_strerror(incoming->result)); - return do_kill(cx); - } - - data = (uint8_t *) incoming->t.buf; - size = (size_t) incoming->result; - err = s5_parse(parser, &data, &size); - if (err == s5_ok) { - conn_read(incoming); - return s_req_parse; /* Need more data. */ - } - - if (size != 0) { - pr_err("junk in request %u", (unsigned) size); - return do_kill(cx); - } - - if (err != s5_exec_cmd) { - pr_err("request error: %s", s5_strerror(err)); - return do_kill(cx); - } - - if (parser->cmd == s5_cmd_tcp_bind) { - /* Not supported but relatively straightforward to implement. */ - pr_warn("BIND requests are not supported."); - return do_kill(cx); - } - - if (parser->cmd == s5_cmd_udp_assoc) { - /* Not supported. Might be hard to implement because libuv has no - * functionality for detecting the MTU size which the RFC mandates. - */ - pr_warn("UDP ASSOC requests are not supported."); - return do_kill(cx); - } - ASSERT(parser->cmd == s5_cmd_tcp_connect); - - if (parser->atyp == s5_atyp_host) { - conn_getaddrinfo(outgoing, (const char *) parser->daddr); - return s_req_lookup; - } - - if (parser->atyp == s5_atyp_ipv4) { - memset(&outgoing->t.addr4, 0, sizeof(outgoing->t.addr4)); - outgoing->t.addr4.sin_family = AF_INET; - outgoing->t.addr4.sin_port = htons(parser->dport); - memcpy(&outgoing->t.addr4.sin_addr, - parser->daddr, - sizeof(outgoing->t.addr4.sin_addr)); - } else if (parser->atyp == s5_atyp_ipv6) { - memset(&outgoing->t.addr6, 0, sizeof(outgoing->t.addr6)); - outgoing->t.addr6.sin6_family = AF_INET6; - outgoing->t.addr6.sin6_port = htons(parser->dport); - memcpy(&outgoing->t.addr6.sin6_addr, - parser->daddr, - sizeof(outgoing->t.addr6.sin6_addr)); - } else { - UNREACHABLE(); - } - - return do_req_connect_start(cx); -} - -static int do_req_lookup(client_ctx *cx) { - s5_ctx *parser; - conn *incoming; - conn *outgoing; - - parser = &cx->parser; - incoming = &cx->incoming; - outgoing = &cx->outgoing; - ASSERT(incoming->rdstate == c_stop); - ASSERT(incoming->wrstate == c_stop); - ASSERT(outgoing->rdstate == c_stop); - ASSERT(outgoing->wrstate == c_stop); - - if (outgoing->result < 0) { - /* TODO(bnoordhuis) Escape control characters in parser->daddr. */ - pr_err("lookup error for \"%s\": %s", - parser->daddr, - uv_strerror(outgoing->result)); - /* Send back a 'Host unreachable' reply. */ - conn_write(incoming, "\5\4\0\1\0\0\0\0\0\0", 10); - return s_kill; - } - - /* Don't make assumptions about the offset of sin_port/sin6_port. */ - switch (outgoing->t.addr.sa_family) { - case AF_INET: - outgoing->t.addr4.sin_port = htons(parser->dport); - break; - case AF_INET6: - outgoing->t.addr6.sin6_port = htons(parser->dport); - break; - default: - UNREACHABLE(); - } - - return do_req_connect_start(cx); -} - -/* Assumes that cx->outgoing.t.sa contains a valid AF_INET/AF_INET6 address. */ -static int do_req_connect_start(client_ctx *cx) { - conn *incoming; - conn *outgoing; - int err; - - incoming = &cx->incoming; - outgoing = &cx->outgoing; - ASSERT(incoming->rdstate == c_stop); - ASSERT(incoming->wrstate == c_stop); - ASSERT(outgoing->rdstate == c_stop); - ASSERT(outgoing->wrstate == c_stop); - - if (!can_access(cx->sx, cx, &outgoing->t.addr)) { - pr_warn("connection not allowed by ruleset"); - /* Send a 'Connection not allowed by ruleset' reply. */ - conn_write(incoming, "\5\2\0\1\0\0\0\0\0\0", 10); - return s_kill; - } - - err = conn_connect(outgoing); - if (err != 0) { - pr_err("connect error: %s\n", uv_strerror(err)); - return do_kill(cx); - } - - return s_req_connect; -} - -static int do_req_connect(client_ctx *cx) { - const struct sockaddr_in6 *in6; - const struct sockaddr_in *in; - char addr_storage[sizeof(*in6)]; - conn *incoming; - conn *outgoing; - uint8_t *buf; - int addrlen; - - incoming = &cx->incoming; - outgoing = &cx->outgoing; - ASSERT(incoming->rdstate == c_stop); - ASSERT(incoming->wrstate == c_stop); - ASSERT(outgoing->rdstate == c_stop); - ASSERT(outgoing->wrstate == c_stop); - - /* Build and send the reply. Not very pretty but gets the job done. */ - buf = (uint8_t *) incoming->t.buf; - if (outgoing->result == 0) { - /* The RFC mandates that the SOCKS server must include the local port - * and address in the reply. So that's what we do. - */ - addrlen = sizeof(addr_storage); - CHECK(0 == uv_tcp_getsockname(&outgoing->handle.tcp, - (struct sockaddr *) addr_storage, - &addrlen)); - buf[0] = 5; /* Version. */ - buf[1] = 0; /* Success. */ - buf[2] = 0; /* Reserved. */ - if (addrlen == sizeof(*in)) { - buf[3] = 1; /* IPv4. */ - in = (const struct sockaddr_in *) &addr_storage; - memcpy(buf + 4, &in->sin_addr, 4); - memcpy(buf + 8, &in->sin_port, 2); - conn_write(incoming, buf, 10); - } else if (addrlen == sizeof(*in6)) { - buf[3] = 4; /* IPv6. */ - in6 = (const struct sockaddr_in6 *) &addr_storage; - memcpy(buf + 4, &in6->sin6_addr, 16); - memcpy(buf + 20, &in6->sin6_port, 2); - conn_write(incoming, buf, 22); - } else { - UNREACHABLE(); - } - return s_proxy_start; - } else { - pr_err("upstream connection error: %s\n", uv_strerror(outgoing->result)); - /* Send a 'Connection refused' reply. */ - conn_write(incoming, "\5\5\0\1\0\0\0\0\0\0", 10); - return s_kill; - } - - UNREACHABLE(); - return s_kill; -} - -static int do_proxy_start(client_ctx *cx) { - conn *incoming; - conn *outgoing; - - incoming = &cx->incoming; - outgoing = &cx->outgoing; - ASSERT(incoming->rdstate == c_stop); - ASSERT(incoming->wrstate == c_done); - ASSERT(outgoing->rdstate == c_stop); - ASSERT(outgoing->wrstate == c_stop); - incoming->wrstate = c_stop; - - if (incoming->result < 0) { - pr_err("write error: %s", uv_strerror(incoming->result)); - return do_kill(cx); - } - - conn_read(incoming); - conn_read(outgoing); - return s_proxy; -} - -/* Proxy incoming data back and forth. */ -static int do_proxy(client_ctx *cx) { - if (conn_cycle("client", &cx->incoming, &cx->outgoing)) { - return do_kill(cx); - } - - if (conn_cycle("upstream", &cx->outgoing, &cx->incoming)) { - return do_kill(cx); - } - - return s_proxy; -} - -static int do_kill(client_ctx *cx) { - int new_state; - - if (cx->state >= s_almost_dead_0) { - return cx->state; - } - - /* Try to cancel the request. The callback still runs but if the - * cancellation succeeded, it gets called with status=UV_ECANCELED. - */ - new_state = s_almost_dead_1; - if (cx->state == s_req_lookup) { - new_state = s_almost_dead_0; - uv_cancel(&cx->outgoing.t.req); - } - - conn_close(&cx->incoming); - conn_close(&cx->outgoing); - return new_state; -} - -static int do_almost_dead(client_ctx *cx) { - ASSERT(cx->state >= s_almost_dead_0); - return cx->state + 1; /* Another finalizer completed. */ -} - -static int conn_cycle(const char *who, conn *a, conn *b) { - if (a->result < 0) { - if (a->result != UV_EOF) { - pr_err("%s error: %s", who, uv_strerror(a->result)); - } - return -1; - } - - if (b->result < 0) { - return -1; - } - - if (a->wrstate == c_done) { - a->wrstate = c_stop; - } - - /* The logic is as follows: read when we don't write and write when we don't - * read. That gives us back-pressure handling for free because if the peer - * sends data faster than we consume it, TCP congestion control kicks in. - */ - if (a->wrstate == c_stop) { - if (b->rdstate == c_stop) { - conn_read(b); - } else if (b->rdstate == c_done) { - conn_write(a, b->t.buf, b->result); - b->rdstate = c_stop; /* Triggers the call to conn_read() above. */ - } - } - - return 0; -} - -static void conn_timer_reset(conn *c) { - CHECK(0 == uv_timer_start(&c->timer_handle, - conn_timer_expire, - c->idle_timeout, - 0)); -} - -static void conn_timer_expire(uv_timer_t *handle) { - conn *c; - - c = CONTAINER_OF(handle, conn, timer_handle); - c->result = UV_ETIMEDOUT; - do_next(c->client); -} - -static void conn_getaddrinfo(conn *c, const char *hostname) { - struct addrinfo hints; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - CHECK(0 == uv_getaddrinfo(c->client->sx->loop, - &c->t.addrinfo_req, - conn_getaddrinfo_done, - hostname, - NULL, - &hints)); - conn_timer_reset(c); -} - -static void conn_getaddrinfo_done(uv_getaddrinfo_t *req, - int status, - struct addrinfo *ai) { - conn *c; - - c = CONTAINER_OF(req, conn, t.addrinfo_req); - c->result = status; - - if (status == 0) { - /* FIXME(bnoordhuis) Should try all addresses. */ - if (ai->ai_family == AF_INET) { - c->t.addr4 = *(const struct sockaddr_in *) ai->ai_addr; - } else if (ai->ai_family == AF_INET6) { - c->t.addr6 = *(const struct sockaddr_in6 *) ai->ai_addr; - } else { - UNREACHABLE(); - } - } - - uv_freeaddrinfo(ai); - do_next(c->client); -} - -/* Assumes that c->t.sa contains a valid AF_INET or AF_INET6 address. */ -static int conn_connect(conn *c) { - ASSERT(c->t.addr.sa_family == AF_INET || - c->t.addr.sa_family == AF_INET6); - conn_timer_reset(c); - return uv_tcp_connect(&c->t.connect_req, - &c->handle.tcp, - &c->t.addr, - conn_connect_done); -} - -static void conn_connect_done(uv_connect_t *req, int status) { - conn *c; - - if (status == UV_ECANCELED) { - return; /* Handle has been closed. */ - } - - c = CONTAINER_OF(req, conn, t.connect_req); - c->result = status; - do_next(c->client); -} - -static void conn_read(conn *c) { - ASSERT(c->rdstate == c_stop); - CHECK(0 == uv_read_start(&c->handle.stream, conn_alloc, conn_read_done)); - c->rdstate = c_busy; - conn_timer_reset(c); -} - -static void conn_read_done(uv_stream_t *handle, - ssize_t nread, - const uv_buf_t *buf) { - conn *c; - - c = CONTAINER_OF(handle, conn, handle); - ASSERT(c->t.buf == buf->base); - ASSERT(c->rdstate == c_busy); - c->rdstate = c_done; - c->result = nread; - - uv_read_stop(&c->handle.stream); - do_next(c->client); -} - -static void conn_alloc(uv_handle_t *handle, size_t size, uv_buf_t *buf) { - conn *c; - - c = CONTAINER_OF(handle, conn, handle); - ASSERT(c->rdstate == c_busy); - buf->base = c->t.buf; - buf->len = sizeof(c->t.buf); -} - -static void conn_write(conn *c, const void *data, unsigned int len) { - uv_buf_t buf; - - ASSERT(c->wrstate == c_stop || c->wrstate == c_done); - c->wrstate = c_busy; - - /* It's okay to cast away constness here, uv_write() won't modify the - * memory. - */ - buf.base = (char *) data; - buf.len = len; - - CHECK(0 == uv_write(&c->write_req, - &c->handle.stream, - &buf, - 1, - conn_write_done)); - conn_timer_reset(c); -} - -static void conn_write_done(uv_write_t *req, int status) { - conn *c; - - if (status == UV_ECANCELED) { - return; /* Handle has been closed. */ - } - - c = CONTAINER_OF(req, conn, write_req); - ASSERT(c->wrstate == c_busy); - c->wrstate = c_done; - c->result = status; - do_next(c->client); -} - -static void conn_close(conn *c) { - ASSERT(c->rdstate != c_dead); - ASSERT(c->wrstate != c_dead); - c->rdstate = c_dead; - c->wrstate = c_dead; - c->timer_handle.data = c; - c->handle.handle.data = c; - uv_close(&c->handle.handle, conn_close_done); - uv_close((uv_handle_t *) &c->timer_handle, conn_close_done); -} - -static void conn_close_done(uv_handle_t *handle) { - conn *c; - - c = handle->data; - do_next(c->client); -} diff --git a/deps/uv/samples/socks5-proxy/defs.h b/deps/uv/samples/socks5-proxy/defs.h deleted file mode 100644 index 99ee8160c8a3..000000000000 --- a/deps/uv/samples/socks5-proxy/defs.h +++ /dev/null @@ -1,139 +0,0 @@ -/* Copyright StrongLoop, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef DEFS_H_ -#define DEFS_H_ - -#include "s5.h" -#include "uv.h" - -#include -#include /* sockaddr_in, sockaddr_in6 */ -#include /* size_t, ssize_t */ -#include -#include /* sockaddr */ - -struct client_ctx; - -typedef struct { - const char *bind_host; - unsigned short bind_port; - unsigned int idle_timeout; -} server_config; - -typedef struct { - unsigned int idle_timeout; /* Connection idle timeout in ms. */ - uv_tcp_t tcp_handle; - uv_loop_t *loop; -} server_ctx; - -typedef struct { - unsigned char rdstate; - unsigned char wrstate; - unsigned int idle_timeout; - struct client_ctx *client; /* Backlink to owning client context. */ - ssize_t result; - union { - uv_handle_t handle; - uv_stream_t stream; - uv_tcp_t tcp; - uv_udp_t udp; - } handle; - uv_timer_t timer_handle; /* For detecting timeouts. */ - uv_write_t write_req; - /* We only need one of these at a time so make them share memory. */ - union { - uv_getaddrinfo_t addrinfo_req; - uv_connect_t connect_req; - uv_req_t req; - struct sockaddr_in6 addr6; - struct sockaddr_in addr4; - struct sockaddr addr; - char buf[2048]; /* Scratch space. Used to read data into. */ - } t; -} conn; - -typedef struct client_ctx { - unsigned int state; - server_ctx *sx; /* Backlink to owning server context. */ - s5_ctx parser; /* The SOCKS protocol parser. */ - conn incoming; /* Connection with the SOCKS client. */ - conn outgoing; /* Connection with upstream. */ -} client_ctx; - -/* server.c */ -int server_run(const server_config *cf, uv_loop_t *loop); -int can_auth_none(const server_ctx *sx, const client_ctx *cx); -int can_auth_passwd(const server_ctx *sx, const client_ctx *cx); -int can_access(const server_ctx *sx, - const client_ctx *cx, - const struct sockaddr *addr); - -/* client.c */ -void client_finish_init(server_ctx *sx, client_ctx *cx); - -/* util.c */ -#if defined(__GNUC__) -# define ATTRIBUTE_FORMAT_PRINTF(a, b) __attribute__((format(printf, a, b))) -#else -# define ATTRIBUTE_FORMAT_PRINTF(a, b) -#endif -void pr_info(const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(1, 2); -void pr_warn(const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(1, 2); -void pr_err(const char *fmt, ...) ATTRIBUTE_FORMAT_PRINTF(1, 2); -void *xmalloc(size_t size); - -/* main.c */ -const char *_getprogname(void); - -/* getopt.c */ -#if !HAVE_UNISTD_H -extern char *optarg; -int getopt(int argc, char **argv, const char *options); -#endif - -/* ASSERT() is for debug checks, CHECK() for run-time sanity checks. - * DEBUG_CHECKS is for expensive debug checks that we only want to - * enable in debug builds but still want type-checked by the compiler - * in release builds. - */ -#if defined(NDEBUG) -# define ASSERT(exp) -# define CHECK(exp) do { if (!(exp)) abort(); } while (0) -# define DEBUG_CHECKS (0) -#else -# define ASSERT(exp) assert(exp) -# define CHECK(exp) assert(exp) -# define DEBUG_CHECKS (1) -#endif - -#define UNREACHABLE() CHECK(!"Unreachable code reached.") - -/* This macro looks complicated but it's not: it calculates the address - * of the embedding struct through the address of the embedded struct. - * In other words, if struct A embeds struct B, then we can obtain - * the address of A by taking the address of B and subtracting the - * field offset of B in A. - */ -#define CONTAINER_OF(ptr, type, field) \ - ((type *) ((char *) (ptr) - ((char *) &((type *) 0)->field))) - -#endif /* DEFS_H_ */ diff --git a/deps/uv/samples/socks5-proxy/getopt.c b/deps/uv/samples/socks5-proxy/getopt.c deleted file mode 100644 index 8481b2264f2f..000000000000 --- a/deps/uv/samples/socks5-proxy/getopt.c +++ /dev/null @@ -1,131 +0,0 @@ -/* $NetBSD: getopt.c,v 1.26 2003/08/07 16:43:40 agc Exp $ */ - -/* - * Copyright (c) 1987, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)getopt.c 8.3 (Berkeley) 4/27/95"; -#endif /* LIBC_SCCS and not lint */ - -#include -#include -#include -#include - -extern const char *_getprogname(void); - -int opterr = 1, /* if error message should be printed */ - optind = 1, /* index into parent argv vector */ - optopt, /* character checked for validity */ - optreset; /* reset getopt */ -char *optarg; /* argument associated with option */ - -#define BADCH (int)'?' -#define BADARG (int)':' -#define EMSG "" - -/* - * getopt -- - * Parse argc/argv argument vector. - */ -int -getopt(nargc, nargv, ostr) - int nargc; - char * const nargv[]; - const char *ostr; -{ - static char *place = EMSG; /* option letter processing */ - char *oli; /* option letter list index */ - - if (optreset || *place == 0) { /* update scanning pointer */ - optreset = 0; - place = nargv[optind]; - if (optind >= nargc || *place++ != '-') { - /* Argument is absent or is not an option */ - place = EMSG; - return (-1); - } - optopt = *place++; - if (optopt == '-' && *place == 0) { - /* "--" => end of options */ - ++optind; - place = EMSG; - return (-1); - } - if (optopt == 0) { - /* Solitary '-', treat as a '-' option - if the program (eg su) is looking for it. */ - place = EMSG; - if (strchr(ostr, '-') == NULL) - return (-1); - optopt = '-'; - } - } else - optopt = *place++; - - /* See if option letter is one the caller wanted... */ - if (optopt == ':' || (oli = strchr(ostr, optopt)) == NULL) { - if (*place == 0) - ++optind; - if (opterr && *ostr != ':') - (void)fprintf(stderr, - "%s: illegal option -- %c\n", _getprogname(), - optopt); - return (BADCH); - } - - /* Does this option need an argument? */ - if (oli[1] != ':') { - /* don't need argument */ - optarg = NULL; - if (*place == 0) - ++optind; - } else { - /* Option-argument is either the rest of this argument or the - entire next argument. */ - if (*place) - optarg = place; - else if (nargc > ++optind) - optarg = nargv[optind]; - else { - /* option-argument absent */ - place = EMSG; - if (*ostr == ':') - return (BADARG); - if (opterr) - (void)fprintf(stderr, - "%s: option requires an argument -- %c\n", - _getprogname(), optopt); - return (BADCH); - } - place = EMSG; - ++optind; - } - return (optopt); /* return option letter */ -} diff --git a/deps/uv/samples/socks5-proxy/main.c b/deps/uv/samples/socks5-proxy/main.c deleted file mode 100644 index e77c7c69078d..000000000000 --- a/deps/uv/samples/socks5-proxy/main.c +++ /dev/null @@ -1,99 +0,0 @@ -/* Copyright StrongLoop, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "defs.h" -#include -#include -#include - -#if HAVE_UNISTD_H -#include /* getopt */ -#endif - -#define DEFAULT_BIND_HOST "127.0.0.1" -#define DEFAULT_BIND_PORT 1080 -#define DEFAULT_IDLE_TIMEOUT (60 * 1000) - -static void parse_opts(server_config *cf, int argc, char **argv); -static void usage(void); - -static const char *progname = __FILE__; /* Reset in main(). */ - -int main(int argc, char **argv) { - server_config config; - int err; - - progname = argv[0]; - memset(&config, 0, sizeof(config)); - config.bind_host = DEFAULT_BIND_HOST; - config.bind_port = DEFAULT_BIND_PORT; - config.idle_timeout = DEFAULT_IDLE_TIMEOUT; - parse_opts(&config, argc, argv); - - err = server_run(&config, uv_default_loop()); - if (err) { - exit(1); - } - - return 0; -} - -const char *_getprogname(void) { - return progname; -} - -static void parse_opts(server_config *cf, int argc, char **argv) { - int opt; - - while (-1 != (opt = getopt(argc, argv, "b:hp:"))) { - switch (opt) { - case 'b': - cf->bind_host = optarg; - break; - - case 'p': - if (1 != sscanf(optarg, "%hu", &cf->bind_port)) { - pr_err("bad port number: %s", optarg); - usage(); - } - break; - - default: - usage(); - } - } -} - -static void usage(void) { - printf("Usage:\n" - "\n" - " %s [-b
] [-h] [-p ]\n" - "\n" - "Options:\n" - "\n" - " -b Bind to this address or hostname.\n" - " Default: \"127.0.0.1\"\n" - " -h Show this help message.\n" - " -p Bind to this port number. Default: 1080\n" - "", - progname); - exit(1); -} diff --git a/deps/uv/samples/socks5-proxy/s5.c b/deps/uv/samples/socks5-proxy/s5.c deleted file mode 100644 index 4f08e345247b..000000000000 --- a/deps/uv/samples/socks5-proxy/s5.c +++ /dev/null @@ -1,271 +0,0 @@ -/* Copyright StrongLoop, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "s5.h" -#include -#include -#include /* abort() */ -#include /* memset() */ - -enum { - s5_version, - s5_nmethods, - s5_methods, - s5_auth_pw_version, - s5_auth_pw_userlen, - s5_auth_pw_username, - s5_auth_pw_passlen, - s5_auth_pw_password, - s5_req_version, - s5_req_cmd, - s5_req_reserved, - s5_req_atyp, - s5_req_atyp_host, - s5_req_daddr, - s5_req_dport0, - s5_req_dport1, - s5_dead -}; - -void s5_init(s5_ctx *cx) { - memset(cx, 0, sizeof(*cx)); - cx->state = s5_version; -} - -s5_err s5_parse(s5_ctx *cx, uint8_t **data, size_t *size) { - s5_err err; - uint8_t *p; - uint8_t c; - size_t i; - size_t n; - - p = *data; - n = *size; - i = 0; - - while (i < n) { - c = p[i]; - i += 1; - switch (cx->state) { - case s5_version: - if (c != 5) { - err = s5_bad_version; - goto out; - } - cx->state = s5_nmethods; - break; - - case s5_nmethods: - cx->arg0 = 0; - cx->arg1 = c; /* Number of bytes to read. */ - cx->state = s5_methods; - break; - - case s5_methods: - if (cx->arg0 < cx->arg1) { - switch (c) { - case 0: - cx->methods |= S5_AUTH_NONE; - break; - case 1: - cx->methods |= S5_AUTH_GSSAPI; - break; - case 2: - cx->methods |= S5_AUTH_PASSWD; - break; - /* Ignore everything we don't understand. */ - } - cx->arg0 += 1; - } - if (cx->arg0 == cx->arg1) { - err = s5_auth_select; - goto out; - } - break; - - case s5_auth_pw_version: - if (c != 1) { - err = s5_bad_version; - goto out; - } - cx->state = s5_auth_pw_userlen; - break; - - case s5_auth_pw_userlen: - cx->arg0 = 0; - cx->userlen = c; - cx->state = s5_auth_pw_username; - break; - - case s5_auth_pw_username: - if (cx->arg0 < cx->userlen) { - cx->username[cx->arg0] = c; - cx->arg0 += 1; - } - if (cx->arg0 == cx->userlen) { - cx->username[cx->userlen] = '\0'; - cx->state = s5_auth_pw_passlen; - } - break; - - case s5_auth_pw_passlen: - cx->arg0 = 0; - cx->passlen = c; - cx->state = s5_auth_pw_password; - break; - - case s5_auth_pw_password: - if (cx->arg0 < cx->passlen) { - cx->password[cx->arg0] = c; - cx->arg0 += 1; - } - if (cx->arg0 == cx->passlen) { - cx->password[cx->passlen] = '\0'; - cx->state = s5_req_version; - err = s5_auth_verify; - goto out; - } - break; - - case s5_req_version: - if (c != 5) { - err = s5_bad_version; - goto out; - } - cx->state = s5_req_cmd; - break; - - case s5_req_cmd: - switch (c) { - case 1: /* TCP connect */ - cx->cmd = s5_cmd_tcp_connect; - break; - case 3: /* UDP associate */ - cx->cmd = s5_cmd_udp_assoc; - break; - default: - err = s5_bad_cmd; - goto out; - } - cx->state = s5_req_reserved; - break; - - case s5_req_reserved: - cx->state = s5_req_atyp; - break; - - case s5_req_atyp: - cx->arg0 = 0; - switch (c) { - case 1: /* IPv4, four octets. */ - cx->state = s5_req_daddr; - cx->atyp = s5_atyp_ipv4; - cx->arg1 = 4; - break; - case 3: /* Hostname. First byte is length. */ - cx->state = s5_req_atyp_host; - cx->atyp = s5_atyp_host; - cx->arg1 = 0; - break; - case 4: /* IPv6, sixteen octets. */ - cx->state = s5_req_daddr; - cx->atyp = s5_atyp_ipv6; - cx->arg1 = 16; - break; - default: - err = s5_bad_atyp; - goto out; - } - break; - - case s5_req_atyp_host: - cx->arg1 = c; - cx->state = s5_req_daddr; - break; - - case s5_req_daddr: - if (cx->arg0 < cx->arg1) { - cx->daddr[cx->arg0] = c; - cx->arg0 += 1; - } - if (cx->arg0 == cx->arg1) { - cx->daddr[cx->arg1] = '\0'; - cx->state = s5_req_dport0; - } - break; - - case s5_req_dport0: - cx->dport = c << 8; - cx->state = s5_req_dport1; - break; - - case s5_req_dport1: - cx->dport |= c; - cx->state = s5_dead; - err = s5_exec_cmd; - goto out; - - case s5_dead: - break; - - default: - abort(); - } - } - err = s5_ok; - -out: - *data = p + i; - *size = n - i; - return err; -} - -unsigned int s5_auth_methods(const s5_ctx *cx) { - return cx->methods; -} - -int s5_select_auth(s5_ctx *cx, s5_auth_method method) { - int err; - - err = 0; - switch (method) { - case S5_AUTH_NONE: - cx->state = s5_req_version; - break; - case S5_AUTH_PASSWD: - cx->state = s5_auth_pw_version; - break; - default: - err = -EINVAL; - } - - return err; -} - -const char *s5_strerror(s5_err err) { -#define S5_ERR_GEN(_, name, errmsg) case s5_ ## name: return errmsg; - switch (err) { - S5_ERR_MAP(S5_ERR_GEN) - default: ; /* Silence s5_max_errors -Wswitch warning. */ - } -#undef S5_ERR_GEN - return "Unknown error."; -} diff --git a/deps/uv/samples/socks5-proxy/s5.h b/deps/uv/samples/socks5-proxy/s5.h deleted file mode 100644 index 715f322287dd..000000000000 --- a/deps/uv/samples/socks5-proxy/s5.h +++ /dev/null @@ -1,94 +0,0 @@ -/* Copyright StrongLoop, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef S5_H_ -#define S5_H_ - -#include -#include - -#define S5_ERR_MAP(V) \ - V(-1, bad_version, "Bad protocol version.") \ - V(-2, bad_cmd, "Bad protocol command.") \ - V(-3, bad_atyp, "Bad address type.") \ - V(0, ok, "No error.") \ - V(1, auth_select, "Select authentication method.") \ - V(2, auth_verify, "Verify authentication.") \ - V(3, exec_cmd, "Execute command.") \ - -typedef enum { -#define S5_ERR_GEN(code, name, _) s5_ ## name = code, - S5_ERR_MAP(S5_ERR_GEN) -#undef S5_ERR_GEN - s5_max_errors -} s5_err; - -typedef enum { - S5_AUTH_NONE = 1 << 0, - S5_AUTH_GSSAPI = 1 << 1, - S5_AUTH_PASSWD = 1 << 2 -} s5_auth_method; - -typedef enum { - s5_auth_allow, - s5_auth_deny -} s5_auth_result; - -typedef enum { - s5_atyp_ipv4, - s5_atyp_ipv6, - s5_atyp_host -} s5_atyp; - -typedef enum { - s5_cmd_tcp_connect, - s5_cmd_tcp_bind, - s5_cmd_udp_assoc -} s5_cmd; - -typedef struct { - uint32_t arg0; /* Scratch space for the state machine. */ - uint32_t arg1; /* Scratch space for the state machine. */ - uint8_t state; - uint8_t methods; - uint8_t cmd; - uint8_t atyp; - uint8_t userlen; - uint8_t passlen; - uint16_t dport; - uint8_t username[257]; - uint8_t password[257]; - uint8_t daddr[257]; /* TODO(bnoordhuis) Merge with username/password. */ -} s5_ctx; - -void s5_init(s5_ctx *ctx); - -s5_err s5_parse(s5_ctx *cx, uint8_t **data, size_t *size); - -/* Only call after s5_parse() has returned s5_want_auth_method. */ -unsigned int s5_auth_methods(const s5_ctx *cx); - -/* Call after s5_parse() has returned s5_want_auth_method. */ -int s5_select_auth(s5_ctx *cx, s5_auth_method method); - -const char *s5_strerror(s5_err err); - -#endif /* S5_H_ */ diff --git a/deps/uv/samples/socks5-proxy/server.c b/deps/uv/samples/socks5-proxy/server.c deleted file mode 100644 index 3f1ba42c9e11..000000000000 --- a/deps/uv/samples/socks5-proxy/server.c +++ /dev/null @@ -1,241 +0,0 @@ -/* Copyright StrongLoop, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "defs.h" -#include /* INET6_ADDRSTRLEN */ -#include -#include - -#ifndef INET6_ADDRSTRLEN -# define INET6_ADDRSTRLEN 63 -#endif - -typedef struct { - uv_getaddrinfo_t getaddrinfo_req; - server_config config; - server_ctx *servers; - uv_loop_t *loop; -} server_state; - -static void do_bind(uv_getaddrinfo_t *req, int status, struct addrinfo *ai); -static void on_connection(uv_stream_t *server, int status); - -int server_run(const server_config *cf, uv_loop_t *loop) { - struct addrinfo hints; - server_state state; - int err; - - memset(&state, 0, sizeof(state)); - state.servers = NULL; - state.config = *cf; - state.loop = loop; - - /* Resolve the address of the interface that we should bind to. - * The getaddrinfo callback starts the server and everything else. - */ - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - - err = uv_getaddrinfo(loop, - &state.getaddrinfo_req, - do_bind, - cf->bind_host, - NULL, - &hints); - if (err != 0) { - pr_err("getaddrinfo: %s", uv_strerror(err)); - return err; - } - - /* Start the event loop. Control continues in do_bind(). */ - if (uv_run(loop, UV_RUN_DEFAULT)) { - abort(); - } - - /* Please Valgrind. */ - uv_loop_delete(loop); - free(state.servers); - return 0; -} - -/* Bind a server to each address that getaddrinfo() reported. */ -static void do_bind(uv_getaddrinfo_t *req, int status, struct addrinfo *addrs) { - char addrbuf[INET6_ADDRSTRLEN + 1]; - unsigned int ipv4_naddrs; - unsigned int ipv6_naddrs; - server_state *state; - server_config *cf; - struct addrinfo *ai; - const void *addrv; - const char *what; - uv_loop_t *loop; - server_ctx *sx; - unsigned int n; - int err; - union { - struct sockaddr addr; - struct sockaddr_in addr4; - struct sockaddr_in6 addr6; - } s; - - state = CONTAINER_OF(req, server_state, getaddrinfo_req); - loop = state->loop; - cf = &state->config; - - if (status < 0) { - pr_err("getaddrinfo(\"%s\"): %s", cf->bind_host, uv_strerror(status)); - uv_freeaddrinfo(addrs); - return; - } - - ipv4_naddrs = 0; - ipv6_naddrs = 0; - for (ai = addrs; ai != NULL; ai = ai->ai_next) { - if (ai->ai_family == AF_INET) { - ipv4_naddrs += 1; - } else if (ai->ai_family == AF_INET6) { - ipv6_naddrs += 1; - } - } - - if (ipv4_naddrs == 0 && ipv6_naddrs == 0) { - pr_err("%s has no IPv4/6 addresses", cf->bind_host); - uv_freeaddrinfo(addrs); - return; - } - - state->servers = - xmalloc((ipv4_naddrs + ipv6_naddrs) * sizeof(state->servers[0])); - - n = 0; - for (ai = addrs; ai != NULL; ai = ai->ai_next) { - if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) { - continue; - } - - if (ai->ai_family == AF_INET) { - s.addr4 = *(const struct sockaddr_in *) ai->ai_addr; - s.addr4.sin_port = htons(cf->bind_port); - addrv = &s.addr4.sin_addr; - } else if (ai->ai_family == AF_INET6) { - s.addr6 = *(const struct sockaddr_in6 *) ai->ai_addr; - s.addr6.sin6_port = htons(cf->bind_port); - addrv = &s.addr6.sin6_addr; - } else { - UNREACHABLE(); - } - - if (uv_inet_ntop(s.addr.sa_family, addrv, addrbuf, sizeof(addrbuf))) { - UNREACHABLE(); - } - - sx = state->servers + n; - sx->loop = loop; - sx->idle_timeout = state->config.idle_timeout; - CHECK(0 == uv_tcp_init(loop, &sx->tcp_handle)); - - what = "uv_tcp_bind"; - err = uv_tcp_bind(&sx->tcp_handle, &s.addr, 0); - if (err == 0) { - what = "uv_listen"; - err = uv_listen((uv_stream_t *) &sx->tcp_handle, 128, on_connection); - } - - if (err != 0) { - pr_err("%s(\"%s:%hu\"): %s", - what, - addrbuf, - cf->bind_port, - uv_strerror(err)); - while (n > 0) { - n -= 1; - uv_close((uv_handle_t *) (state->servers + n), NULL); - } - break; - } - - pr_info("listening on %s:%hu", addrbuf, cf->bind_port); - n += 1; - } - - uv_freeaddrinfo(addrs); -} - -static void on_connection(uv_stream_t *server, int status) { - server_ctx *sx; - client_ctx *cx; - - CHECK(status == 0); - sx = CONTAINER_OF(server, server_ctx, tcp_handle); - cx = xmalloc(sizeof(*cx)); - CHECK(0 == uv_tcp_init(sx->loop, &cx->incoming.handle.tcp)); - CHECK(0 == uv_accept(server, &cx->incoming.handle.stream)); - client_finish_init(sx, cx); -} - -int can_auth_none(const server_ctx *sx, const client_ctx *cx) { - return 1; -} - -int can_auth_passwd(const server_ctx *sx, const client_ctx *cx) { - return 0; -} - -int can_access(const server_ctx *sx, - const client_ctx *cx, - const struct sockaddr *addr) { - const struct sockaddr_in6 *addr6; - const struct sockaddr_in *addr4; - const uint32_t *p; - uint32_t a; - uint32_t b; - uint32_t c; - uint32_t d; - - /* TODO(bnoordhuis) Implement proper access checks. For now, just reject - * traffic to localhost. - */ - if (addr->sa_family == AF_INET) { - addr4 = (const struct sockaddr_in *) addr; - d = ntohl(addr4->sin_addr.s_addr); - return (d >> 24) != 0x7F; - } - - if (addr->sa_family == AF_INET6) { - addr6 = (const struct sockaddr_in6 *) addr; - p = (const uint32_t *) &addr6->sin6_addr.s6_addr; - a = ntohl(p[0]); - b = ntohl(p[1]); - c = ntohl(p[2]); - d = ntohl(p[3]); - if (a == 0 && b == 0 && c == 0 && d == 1) { - return 0; /* "::1" style address. */ - } - if (a == 0 && b == 0 && c == 0xFFFF && (d >> 24) == 0x7F) { - return 0; /* "::ffff:127.x.x.x" style address. */ - } - return 1; - } - - return 0; -} diff --git a/deps/uv/samples/socks5-proxy/util.c b/deps/uv/samples/socks5-proxy/util.c deleted file mode 100644 index af34f0559365..000000000000 --- a/deps/uv/samples/socks5-proxy/util.c +++ /dev/null @@ -1,72 +0,0 @@ -/* Copyright StrongLoop, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "defs.h" -#include -#include -#include - -static void pr_do(FILE *stream, - const char *label, - const char *fmt, - va_list ap); - -void *xmalloc(size_t size) { - void *ptr; - - ptr = malloc(size); - if (ptr == NULL) { - pr_err("out of memory, need %lu bytes", (unsigned long) size); - exit(1); - } - - return ptr; -} - -void pr_info(const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - pr_do(stdout, "info", fmt, ap); - va_end(ap); -} - -void pr_warn(const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - pr_do(stderr, "warn", fmt, ap); - va_end(ap); -} - -void pr_err(const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - pr_do(stderr, "error", fmt, ap); - va_end(ap); -} - -static void pr_do(FILE *stream, - const char *label, - const char *fmt, - va_list ap) { - char fmtbuf[1024]; - vsnprintf(fmtbuf, sizeof(fmtbuf), fmt, ap); - fprintf(stream, "%s:%s: %s\n", _getprogname(), label, fmtbuf); -} diff --git a/deps/uv/src/unix/darwin-proctitle.c b/deps/uv/src/unix/darwin-proctitle.c index eced23c2da7c..97eaa05391be 100644 --- a/deps/uv/src/unix/darwin-proctitle.c +++ b/deps/uv/src/unix/darwin-proctitle.c @@ -34,52 +34,53 @@ # include #endif -#define S(s) pCFStringCreateWithCString(NULL, (s), kCFStringEncodingUTF8) +static int uv__pthread_setname_np(const char* name) { + char namebuf[64]; /* MAXTHREADNAMESIZE */ + int err; -#if !TARGET_OS_IPHONE -static CFStringRef (*pCFStringCreateWithCString)(CFAllocatorRef, - const char*, - CFStringEncoding); -static CFBundleRef (*pCFBundleGetBundleWithIdentifier)(CFStringRef); -static void *(*pCFBundleGetDataPointerForName)(CFBundleRef, CFStringRef); -static void *(*pCFBundleGetFunctionPointerForName)(CFBundleRef, CFStringRef); -static CFTypeRef (*pLSGetCurrentApplicationASN)(void); -static OSStatus (*pLSSetApplicationInformationItem)(int, - CFTypeRef, - CFStringRef, - CFStringRef, - CFDictionaryRef*); -static void* application_services_handle; -static void* core_foundation_handle; -static CFBundleRef launch_services_bundle; -static CFStringRef* display_name_key; -static CFDictionaryRef (*pCFBundleGetInfoDictionary)(CFBundleRef); -static CFBundleRef (*pCFBundleGetMainBundle)(void); -static CFBundleRef hi_services_bundle; -static CFDictionaryRef (*pLSApplicationCheckIn)(int, CFDictionaryRef); -static void (*pLSSetApplicationLaunchServicesServerConnectionStatus)(uint64_t, - void*); - - -UV_DESTRUCTOR(static void uv__set_process_title_platform_fini(void)) { - if (core_foundation_handle != NULL) { - dlclose(core_foundation_handle); - core_foundation_handle = NULL; - } + strncpy(namebuf, name, sizeof(namebuf) - 1); + namebuf[sizeof(namebuf) - 1] = '\0'; - if (application_services_handle != NULL) { - dlclose(application_services_handle); - application_services_handle = NULL; - } + err = pthread_setname_np(namebuf); + if (err) + return UV__ERR(err); + + return 0; } -#endif /* !TARGET_OS_IPHONE */ -void uv__set_process_title_platform_init(void) { -#if !TARGET_OS_IPHONE +int uv__set_process_title(const char* title) { +#if TARGET_OS_IPHONE + return uv__pthread_setname_np(title); +#else + CFStringRef (*pCFStringCreateWithCString)(CFAllocatorRef, + const char*, + CFStringEncoding); + CFBundleRef (*pCFBundleGetBundleWithIdentifier)(CFStringRef); + void *(*pCFBundleGetDataPointerForName)(CFBundleRef, CFStringRef); + void *(*pCFBundleGetFunctionPointerForName)(CFBundleRef, CFStringRef); + CFTypeRef (*pLSGetCurrentApplicationASN)(void); + OSStatus (*pLSSetApplicationInformationItem)(int, + CFTypeRef, + CFStringRef, + CFStringRef, + CFDictionaryRef*); + void* application_services_handle; + void* core_foundation_handle; + CFBundleRef launch_services_bundle; + CFStringRef* display_name_key; + CFDictionaryRef (*pCFBundleGetInfoDictionary)(CFBundleRef); + CFBundleRef (*pCFBundleGetMainBundle)(void); + CFBundleRef hi_services_bundle; OSStatus (*pSetApplicationIsDaemon)(int); + CFDictionaryRef (*pLSApplicationCheckIn)(int, CFDictionaryRef); + void (*pLSSetApplicationLaunchServicesServerConnectionStatus)(uint64_t, + void*); + CFTypeRef asn; + int err; + err = UV_ENOENT; application_services_handle = dlopen("/System/Library/Frameworks/" "ApplicationServices.framework/" "Versions/A/ApplicationServices", @@ -108,6 +109,8 @@ void uv__set_process_title_platform_init(void) { goto out; } +#define S(s) pCFStringCreateWithCString(NULL, (s), kCFStringEncodingUTF8) + launch_services_bundle = pCFBundleGetBundleWithIdentifier(S("com.apple.LaunchServices")); @@ -138,14 +141,13 @@ void uv__set_process_title_platform_init(void) { "CFBundleGetInfoDictionary"); *(void **)(&pCFBundleGetMainBundle) = dlsym(core_foundation_handle, "CFBundleGetMainBundle"); - if (pCFBundleGetInfoDictionary == NULL || pCFBundleGetMainBundle == NULL) goto out; /* Black 10.9 magic, to remove (Not responding) mark in Activity Monitor */ hi_services_bundle = pCFBundleGetBundleWithIdentifier(S("com.apple.HIServices")); - + err = UV_ENOENT; if (hi_services_bundle == NULL) goto out; @@ -159,38 +161,42 @@ void uv__set_process_title_platform_init(void) { pCFBundleGetFunctionPointerForName( launch_services_bundle, S("_LSSetApplicationLaunchServicesServerConnectionStatus")); - if (pSetApplicationIsDaemon == NULL || pLSApplicationCheckIn == NULL || pLSSetApplicationLaunchServicesServerConnectionStatus == NULL) { goto out; } - /* Prevent crash when LaunchServices cannot be connected to. */ - pSetApplicationIsDaemon(1); - return; + if (pSetApplicationIsDaemon(1) != noErr) + goto out; -out: - uv__set_process_title_platform_fini(); -#endif /* !TARGET_OS_IPHONE */ -} + pLSSetApplicationLaunchServicesServerConnectionStatus(0, NULL); + /* Check into process manager?! */ + pLSApplicationCheckIn(-2, + pCFBundleGetInfoDictionary(pCFBundleGetMainBundle())); -void uv__set_process_title(const char* title) { - char namebuf[64 /* MAXTHREADNAMESIZE */]; + asn = pLSGetCurrentApplicationASN(); -#if !TARGET_OS_IPHONE - if (core_foundation_handle != NULL) { - CFTypeRef asn; - pLSSetApplicationLaunchServicesServerConnectionStatus(0, NULL); - pLSApplicationCheckIn(/* Magic value */ -2, - pCFBundleGetInfoDictionary(pCFBundleGetMainBundle())); - asn = pLSGetCurrentApplicationASN(); - pLSSetApplicationInformationItem(/* Magic value */ -2, asn, - *display_name_key, S(title), NULL); + err = UV_EINVAL; + if (pLSSetApplicationInformationItem(-2, /* Magic value. */ + asn, + *display_name_key, + S(title), + NULL) != noErr) { + goto out; } -#endif /* !TARGET_OS_IPHONE */ - uv__strscpy(namebuf, title, sizeof(namebuf)); - pthread_setname_np(namebuf); + uv__pthread_setname_np(title); /* Don't care if it fails. */ + err = 0; + +out: + if (core_foundation_handle != NULL) + dlclose(core_foundation_handle); + + if (application_services_handle != NULL) + dlclose(application_services_handle); + + return err; +#endif /* !TARGET_OS_IPHONE */ } diff --git a/deps/uv/src/unix/darwin.c b/deps/uv/src/unix/darwin.c index 5cf03aea0b40..654aba26b1f9 100644 --- a/deps/uv/src/unix/darwin.c +++ b/deps/uv/src/unix/darwin.c @@ -110,7 +110,7 @@ uint64_t uv_get_total_memory(void) { int which[] = {CTL_HW, HW_MEMSIZE}; size_t size = sizeof(info); - if (sysctl(which, 2, &info, &size, NULL, 0)) + if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0)) return UV__ERR(errno); return (uint64_t) info; @@ -127,7 +127,7 @@ void uv_loadavg(double avg[3]) { size_t size = sizeof(info); int which[] = {CTL_VM, VM_LOADAVG}; - if (sysctl(which, 2, &info, &size, NULL, 0) < 0) return; + if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0) < 0) return; avg[0] = (double) info.ldavg[0] / info.fscale; avg[1] = (double) info.ldavg[1] / info.fscale; @@ -162,7 +162,7 @@ int uv_uptime(double* uptime) { size_t size = sizeof(info); static int which[] = {CTL_KERN, KERN_BOOTTIME}; - if (sysctl(which, 2, &info, &size, NULL, 0)) + if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0)) return UV__ERR(errno); now = time(NULL); diff --git a/deps/uv/src/unix/freebsd.c b/deps/uv/src/unix/freebsd.c index d0b7d8e9d11f..57bd04e24093 100644 --- a/deps/uv/src/unix/freebsd.c +++ b/deps/uv/src/unix/freebsd.c @@ -95,7 +95,7 @@ int uv_exepath(char* buffer, size_t* size) { mib[3] = -1; abspath_size = sizeof abspath; - if (sysctl(mib, 4, abspath, &abspath_size, NULL, 0)) + if (sysctl(mib, ARRAY_SIZE(mib), abspath, &abspath_size, NULL, 0)) return UV__ERR(errno); assert(abspath_size > 0); @@ -130,7 +130,7 @@ uint64_t uv_get_total_memory(void) { size_t size = sizeof(info); - if (sysctl(which, 2, &info, &size, NULL, 0)) + if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0)) return UV__ERR(errno); return (uint64_t) info; @@ -147,7 +147,7 @@ void uv_loadavg(double avg[3]) { size_t size = sizeof(info); int which[] = {CTL_VM, VM_LOADAVG}; - if (sysctl(which, 2, &info, &size, NULL, 0) < 0) return; + if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0) < 0) return; avg[0] = (double) info.ldavg[0] / info.fscale; avg[1] = (double) info.ldavg[1] / info.fscale; @@ -168,7 +168,7 @@ int uv_resident_set_memory(size_t* rss) { kinfo_size = sizeof(kinfo); - if (sysctl(mib, 4, &kinfo, &kinfo_size, NULL, 0)) + if (sysctl(mib, ARRAY_SIZE(mib), &kinfo, &kinfo_size, NULL, 0)) return UV__ERR(errno); page_size = getpagesize(); diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c index be256bfca6c5..d5017ebbc8c6 100644 --- a/deps/uv/src/unix/fs.c +++ b/deps/uv/src/unix/fs.c @@ -259,10 +259,29 @@ static ssize_t uv__fs_mkdtemp(uv_fs_t* req) { } +static int (*uv__mkostemp)(char*, int); + + +static void uv__mkostemp_initonce(void) { + /* z/os doesn't have RTLD_DEFAULT but that's okay + * because it doesn't have mkostemp(O_CLOEXEC) either. + */ +#ifdef RTLD_DEFAULT + uv__mkostemp = (int (*)(char*, int)) dlsym(RTLD_DEFAULT, "mkostemp"); + + /* We don't care about errors, but we do want to clean them up. + * If there has been no error, then dlerror() will just return + * NULL. + */ + dlerror(); +#endif /* RTLD_DEFAULT */ +} + + static int uv__fs_mkstemp(uv_fs_t* req) { + static uv_once_t once = UV_ONCE_INIT; int r; #ifdef O_CLOEXEC - int (*mkostemp_function)(char*, int); static int no_cloexec_support; #endif static const char pattern[] = "XXXXXX"; @@ -284,30 +303,23 @@ static int uv__fs_mkstemp(uv_fs_t* req) { return -1; } -#ifdef O_CLOEXEC - if (no_cloexec_support == 0) { - *(int**)(&mkostemp_function) = dlsym(RTLD_DEFAULT, "mkostemp"); - - /* We don't care about errors, but we do want to clean them up. - If there has been no error, then dlerror() will just return - NULL. */ - dlerror(); + uv_once(&once, uv__mkostemp_initonce); - if (mkostemp_function != NULL) { - r = mkostemp_function(path, O_CLOEXEC); +#ifdef O_CLOEXEC + if (no_cloexec_support == 0 && uv__mkostemp != NULL) { + r = uv__mkostemp(path, O_CLOEXEC); - if (r >= 0) - return r; + if (r >= 0) + return r; - /* If mkostemp() returns EINVAL, it means the kernel doesn't - support O_CLOEXEC, so we just fallback to mkstemp() below. */ - if (errno != EINVAL) - return r; + /* If mkostemp() returns EINVAL, it means the kernel doesn't + support O_CLOEXEC, so we just fallback to mkstemp() below. */ + if (errno != EINVAL) + return r; - /* We set the static variable so that next calls don't even - try to use mkostemp. */ - no_cloexec_support = 1; - } + /* We set the static variable so that next calls don't even + try to use mkostemp. */ + no_cloexec_support = 1; } #endif /* O_CLOEXEC */ @@ -1125,7 +1137,28 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) { if (fchmod(dstfd, src_statsbuf.st_mode) == -1) { err = UV__ERR(errno); +#ifdef __linux__ + if (err != UV_EPERM) + goto out; + + { + struct statfs s; + + /* fchmod() on CIFS shares always fails with EPERM unless the share is + * mounted with "noperm". As fchmod() is a meaningless operation on such + * shares anyway, detect that condition and squelch the error. + */ + if (fstatfs(dstfd, &s) == -1) + goto out; + + if (s.f_type != /* CIFS */ 0xFF534D42u) + goto out; + } + + err = 0; +#else /* !__linux__ */ goto out; +#endif /* !__linux__ */ } #ifdef FICLONE diff --git a/deps/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c index a155a374e76c..740e422d46ed 100644 --- a/deps/uv/src/unix/linux-core.c +++ b/deps/uv/src/unix/linux-core.c @@ -359,9 +359,19 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { have_signals = 0; nevents = 0; - assert(loop->watchers != NULL); - loop->watchers[loop->nwatchers] = (void*) events; - loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds; + { + /* Squelch a -Waddress-of-packed-member warning with gcc >= 9. */ + union { + struct epoll_event* events; + uv__io_t* watchers; + } x; + + x.events = events; + assert(loop->watchers != NULL); + loop->watchers[loop->nwatchers] = x.watchers; + loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds; + } + for (i = 0; i < nfds; i++) { pe = events + i; fd = pe->data.fd; diff --git a/deps/uv/src/unix/netbsd.c b/deps/uv/src/unix/netbsd.c index 690bd79ef91a..c66333f522c5 100644 --- a/deps/uv/src/unix/netbsd.c +++ b/deps/uv/src/unix/netbsd.c @@ -55,7 +55,7 @@ void uv_loadavg(double avg[3]) { size_t size = sizeof(info); int which[] = {CTL_VM, VM_LOADAVG}; - if (sysctl(which, 2, &info, &size, NULL, 0) == -1) return; + if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0) == -1) return; avg[0] = (double) info.ldavg[0] / info.fscale; avg[1] = (double) info.ldavg[1] / info.fscale; @@ -102,7 +102,7 @@ uint64_t uv_get_free_memory(void) { size_t size = sizeof(info); int which[] = {CTL_VM, VM_UVMEXP}; - if (sysctl(which, 2, &info, &size, NULL, 0)) + if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0)) return UV__ERR(errno); return (uint64_t) info.free * sysconf(_SC_PAGESIZE); @@ -119,7 +119,7 @@ uint64_t uv_get_total_memory(void) { #endif size_t size = sizeof(info); - if (sysctl(which, 2, &info, &size, NULL, 0)) + if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0)) return UV__ERR(errno); return (uint64_t) info; @@ -167,7 +167,7 @@ int uv_uptime(double* uptime) { size_t size = sizeof(info); static int which[] = {CTL_KERN, KERN_BOOTTIME}; - if (sysctl(which, 2, &info, &size, NULL, 0)) + if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0)) return UV__ERR(errno); now = time(NULL); diff --git a/deps/uv/src/unix/openbsd.c b/deps/uv/src/unix/openbsd.c index 199a34658a79..5ba0db022e4a 100644 --- a/deps/uv/src/unix/openbsd.c +++ b/deps/uv/src/unix/openbsd.c @@ -50,7 +50,7 @@ void uv_loadavg(double avg[3]) { size_t size = sizeof(info); int which[] = {CTL_VM, VM_LOADAVG}; - if (sysctl(which, 2, &info, &size, NULL, 0) < 0) return; + if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0) < 0) return; avg[0] = (double) info.ldavg[0] / info.fscale; avg[1] = (double) info.ldavg[1] / info.fscale; @@ -81,7 +81,7 @@ int uv_exepath(char* buffer, size_t* size) { mib[1] = KERN_PROC_ARGS; mib[2] = mypid; mib[3] = KERN_PROC_ARGV; - if (sysctl(mib, 4, argsbuf, &argsbuf_size, NULL, 0) == 0) { + if (sysctl(mib, ARRAY_SIZE(mib), argsbuf, &argsbuf_size, NULL, 0) == 0) { break; } if (errno != ENOMEM) { @@ -117,7 +117,7 @@ uint64_t uv_get_free_memory(void) { size_t size = sizeof(info); int which[] = {CTL_VM, VM_UVMEXP}; - if (sysctl(which, 2, &info, &size, NULL, 0)) + if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0)) return UV__ERR(errno); return (uint64_t) info.free * sysconf(_SC_PAGESIZE); @@ -129,7 +129,7 @@ uint64_t uv_get_total_memory(void) { int which[] = {CTL_HW, HW_PHYSMEM64}; size_t size = sizeof(info); - if (sysctl(which, 2, &info, &size, NULL, 0)) + if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0)) return UV__ERR(errno); return (uint64_t) info; @@ -154,7 +154,7 @@ int uv_resident_set_memory(size_t* rss) { mib[4] = sizeof(struct kinfo_proc); mib[5] = 1; - if (sysctl(mib, 6, &kinfo, &size, NULL, 0) < 0) + if (sysctl(mib, ARRAY_SIZE(mib), &kinfo, &size, NULL, 0) < 0) return UV__ERR(errno); *rss = kinfo.p_vm_rssize * page_size; @@ -168,7 +168,7 @@ int uv_uptime(double* uptime) { size_t size = sizeof(info); static int which[] = {CTL_KERN, KERN_BOOTTIME}; - if (sysctl(which, 2, &info, &size, NULL, 0)) + if (sysctl(which, ARRAY_SIZE(which), &info, &size, NULL, 0)) return UV__ERR(errno); now = time(NULL); @@ -184,18 +184,19 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { uint64_t info[CPUSTATES]; char model[512]; int numcpus = 1; - int which[] = {CTL_HW,HW_MODEL,0}; + int which[] = {CTL_HW,HW_MODEL}; + int percpu[] = {CTL_HW,HW_CPUSPEED,0}; size_t size; int i, j; uv_cpu_info_t* cpu_info; size = sizeof(model); - if (sysctl(which, 2, &model, &size, NULL, 0)) + if (sysctl(which, ARRAY_SIZE(which), &model, &size, NULL, 0)) return UV__ERR(errno); which[1] = HW_NCPUONLINE; size = sizeof(numcpus); - if (sysctl(which, 2, &numcpus, &size, NULL, 0)) + if (sysctl(which, ARRAY_SIZE(which), &numcpus, &size, NULL, 0)) return UV__ERR(errno); *cpu_infos = uv__malloc(numcpus * sizeof(**cpu_infos)); @@ -205,18 +206,17 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { i = 0; *count = numcpus; - which[1] = HW_CPUSPEED; size = sizeof(cpuspeed); - if (sysctl(which, 2, &cpuspeed, &size, NULL, 0)) + if (sysctl(which, ARRAY_SIZE(percpu), &cpuspeed, &size, NULL, 0)) goto error; size = sizeof(info); - which[0] = CTL_KERN; - which[1] = KERN_CPTIME2; + percpu[0] = CTL_KERN; + percpu[1] = KERN_CPTIME2; for (i = 0; i < numcpus; i++) { - which[2] = i; + percpu[2] = i; size = sizeof(info); - if (sysctl(which, 3, &info, &size, NULL, 0)) + if (sysctl(which, ARRAY_SIZE(percpu), &info, &size, NULL, 0)) goto error; cpu_info = &(*cpu_infos)[i]; diff --git a/deps/uv/src/unix/proctitle.c b/deps/uv/src/unix/proctitle.c index a5ce2030c55b..1a8c7a7090e8 100644 --- a/deps/uv/src/unix/proctitle.c +++ b/deps/uv/src/unix/proctitle.c @@ -24,7 +24,6 @@ #include #include -extern void uv__set_process_title_platform_init(void); extern void uv__set_process_title(const char* title); static uv_mutex_t process_title_mutex; @@ -39,9 +38,6 @@ static struct { static void init_process_title_mutex_once(void) { uv_mutex_init(&process_title_mutex); -#ifdef __APPLE__ - uv__set_process_title_platform_init(); -#endif } diff --git a/deps/uv/src/unix/signal.c b/deps/uv/src/unix/signal.c index 3a257f04b578..ba8fcc204f80 100644 --- a/deps/uv/src/unix/signal.c +++ b/deps/uv/src/unix/signal.c @@ -565,6 +565,7 @@ static void uv__signal_stop(uv_signal_t* handle) { if (first_oneshot && !rem_oneshot) { ret = uv__signal_register_handler(handle->signum, 1); assert(ret == 0); + (void)ret; } } diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c index 78ce8e84870e..8c1329306d70 100644 --- a/deps/uv/src/unix/stream.c +++ b/deps/uv/src/unix/stream.c @@ -1048,7 +1048,12 @@ static int uv__stream_queue_fd(uv_stream_t* stream, int fd) { } -#define UV__CMSG_FD_COUNT 64 +#if defined(__PASE__) +/* on IBMi PASE the control message length can not exceed 256. */ +# define UV__CMSG_FD_COUNT 60 +#else +# define UV__CMSG_FD_COUNT 64 +#endif #define UV__CMSG_FD_SIZE (UV__CMSG_FD_COUNT * sizeof(int)) diff --git a/deps/uv/src/unix/tty.c b/deps/uv/src/unix/tty.c index e7c520f77402..ff7d3b17f930 100644 --- a/deps/uv/src/unix/tty.c +++ b/deps/uv/src/unix/tty.c @@ -139,7 +139,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int unused) { * slave device. */ if (uv__tty_is_slave(fd) && ttyname_r(fd, path, sizeof(path)) == 0) - r = uv__open_cloexec(path, mode); + r = uv__open_cloexec(path, mode | O_NOCTTY); else r = -1; @@ -293,7 +293,14 @@ uv_handle_type uv_guess_handle(uv_file file) { if (file < 0) return UV_UNKNOWN_HANDLE; +#if defined(__PASE__) + /* On IBMi PASE isatty() always returns true for stdin, stdout and stderr. + * Use ioctl() instead to identify whether it's actually a TTY. + */ + if (!ioctl(file, TXISATTY + 0x81, NULL) || errno != ENOTTY) +#else if (isatty(file)) +#endif return UV_TTY; if (fstat(file, &s)) diff --git a/deps/uv/src/win/core.c b/deps/uv/src/win/core.c index e9d0a581537d..6ded90cdcc7f 100644 --- a/deps/uv/src/win/core.c +++ b/deps/uv/src/win/core.c @@ -321,8 +321,13 @@ void uv__loop_close(uv_loop_t* loop) { uv__loops_remove(loop); - /* close the async handle without needing an extra loop iteration */ - assert(!loop->wq_async.async_sent); + /* Close the async handle without needing an extra loop iteration. + * We might have a pending message, but we're just going to destroy the IOCP + * soon, so we can just discard it now without the usual risk of a getting + * another notification from GetQueuedCompletionStatusEx after calling the + * close_cb (which we also skip defining). We'll assert later that queue was + * actually empty and all reqs handled. */ + loop->wq_async.async_sent = 0; loop->wq_async.close_cb = NULL; uv__handle_closing(&loop->wq_async); uv__handle_close(&loop->wq_async); diff --git a/deps/uv/src/win/tty.c b/deps/uv/src/win/tty.c index 5d5b92d0d2d6..517aa4af79f6 100644 --- a/deps/uv/src/win/tty.c +++ b/deps/uv/src/win/tty.c @@ -1625,28 +1625,16 @@ static int uv_tty_write_bufs(uv_tty_t* handle, /* We can only write 8k characters at a time. Windows can't handle much more * characters in a single console write anyway. */ WCHAR utf16_buf[MAX_CONSOLE_CHAR]; - WCHAR* utf16_buffer; DWORD utf16_buf_used = 0; - unsigned int i, len, max_len, pos; - int allocate = 0; - -#define FLUSH_TEXT() \ - do { \ - pos = 0; \ - do { \ - len = utf16_buf_used - pos; \ - if (len > MAX_CONSOLE_CHAR) \ - len = MAX_CONSOLE_CHAR; \ - uv_tty_emit_text(handle, &utf16_buffer[pos], len, error); \ - pos += len; \ - } while (pos < utf16_buf_used); \ - if (allocate) { \ - uv__free(utf16_buffer); \ - allocate = 0; \ - utf16_buffer = utf16_buf; \ - } \ - utf16_buf_used = 0; \ - } while (0) + unsigned int i; + +#define FLUSH_TEXT() \ + do { \ + if (utf16_buf_used > 0) { \ + uv_tty_emit_text(handle, utf16_buf, utf16_buf_used, error); \ + utf16_buf_used = 0; \ + } \ + } while (0) #define ENSURE_BUFFER_SPACE(wchars_needed) \ if (wchars_needed > ARRAY_SIZE(utf16_buf) - utf16_buf_used) { \ @@ -1663,48 +1651,12 @@ static int uv_tty_write_bufs(uv_tty_t* handle, * keep parsing the buffer so we leave the parser in a consistent state. */ *error = ERROR_SUCCESS; - utf16_buffer = utf16_buf; - uv_sem_wait(&uv_tty_output_lock); for (i = 0; i < nbufs; i++) { uv_buf_t buf = bufs[i]; unsigned int j; - if (uv__vterm_state == UV_TTY_SUPPORTED && buf.len > 0) { - utf16_buf_used = MultiByteToWideChar(CP_UTF8, - 0, - buf.base, - buf.len, - NULL, - 0); - - if (utf16_buf_used == 0) { - *error = GetLastError(); - break; - } - - max_len = (utf16_buf_used + 1) * sizeof(WCHAR); - allocate = max_len > MAX_CONSOLE_CHAR; - if (allocate) - utf16_buffer = uv__malloc(max_len); - if (!MultiByteToWideChar(CP_UTF8, - 0, - buf.base, - buf.len, - utf16_buffer, - utf16_buf_used)) { - if (allocate) - uv__free(utf16_buffer); - *error = GetLastError(); - break; - } - - FLUSH_TEXT(); - - continue; - } - for (j = 0; j < buf.len; j++) { unsigned char c = buf.base[j]; @@ -1761,7 +1713,9 @@ static int uv_tty_write_bufs(uv_tty_t* handle, } /* Parse vt100/ansi escape codes */ - if (ansi_parser_state == ANSI_NORMAL) { + if (uv__vterm_state == UV_TTY_SUPPORTED) { + /* Pass through escape codes if conhost supports them. */ + } else if (ansi_parser_state == ANSI_NORMAL) { switch (utf8_codepoint) { case '\033': ansi_parser_state = ANSI_ESCAPE_SEEN; diff --git a/deps/uv/src/win/winsock.c b/deps/uv/src/win/winsock.c index 5820ba9c66da..4cf6e6b042c5 100644 --- a/deps/uv/src/win/winsock.c +++ b/deps/uv/src/win/winsock.c @@ -74,11 +74,6 @@ BOOL uv_get_connectex_function(SOCKET socket, LPFN_CONNECTEX* target) { } -static int error_means_no_support(DWORD error) { - return error == WSAEPROTONOSUPPORT || error == WSAESOCKTNOSUPPORT || - error == WSAEPFNOSUPPORT || error == WSAEAFNOSUPPORT; -} - void uv_winsock_init(void) { WSADATA wsa_data; @@ -105,50 +100,36 @@ void uv_winsock_init(void) { uv_fatal_error(errorno, "WSAStartup"); } - /* Detect non-IFS LSPs */ + /* Try to detect non-IFS LSPs */ + uv_tcp_non_ifs_lsp_ipv4 = 1; dummy = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); - if (dummy != INVALID_SOCKET) { opt_len = (int) sizeof protocol_info; if (getsockopt(dummy, SOL_SOCKET, SO_PROTOCOL_INFOW, (char*) &protocol_info, - &opt_len) == SOCKET_ERROR) - uv_fatal_error(WSAGetLastError(), "getsockopt"); - - if (!(protocol_info.dwServiceFlags1 & XP1_IFS_HANDLES)) - uv_tcp_non_ifs_lsp_ipv4 = 1; - - if (closesocket(dummy) == SOCKET_ERROR) - uv_fatal_error(WSAGetLastError(), "closesocket"); - - } else if (!error_means_no_support(WSAGetLastError())) { - /* Any error other than "socket type not supported" is fatal. */ - uv_fatal_error(WSAGetLastError(), "socket"); + &opt_len) == 0) { + if (protocol_info.dwServiceFlags1 & XP1_IFS_HANDLES) + uv_tcp_non_ifs_lsp_ipv4 = 0; + } + closesocket(dummy); } - /* Detect IPV6 support and non-IFS LSPs */ + /* Try to detect IPV6 support and non-IFS LSPs */ + uv_tcp_non_ifs_lsp_ipv6 = 1; dummy = socket(AF_INET6, SOCK_STREAM, IPPROTO_IP); - if (dummy != INVALID_SOCKET) { opt_len = (int) sizeof protocol_info; if (getsockopt(dummy, SOL_SOCKET, SO_PROTOCOL_INFOW, (char*) &protocol_info, - &opt_len) == SOCKET_ERROR) - uv_fatal_error(WSAGetLastError(), "getsockopt"); - - if (!(protocol_info.dwServiceFlags1 & XP1_IFS_HANDLES)) - uv_tcp_non_ifs_lsp_ipv6 = 1; - - if (closesocket(dummy) == SOCKET_ERROR) - uv_fatal_error(WSAGetLastError(), "closesocket"); - - } else if (!error_means_no_support(WSAGetLastError())) { - /* Any error other than "socket type not supported" is fatal. */ - uv_fatal_error(WSAGetLastError(), "socket"); + &opt_len) == 0) { + if (protocol_info.dwServiceFlags1 & XP1_IFS_HANDLES) + uv_tcp_non_ifs_lsp_ipv6 = 0; + } + closesocket(dummy); } } diff --git a/deps/uv/test/run-tests.c b/deps/uv/test/run-tests.c index 55cf412827d5..2aad6a522ff5 100644 --- a/deps/uv/test/run-tests.c +++ b/deps/uv/test/run-tests.c @@ -51,6 +51,13 @@ static int maybe_run_test(int argc, char **argv); int main(int argc, char **argv) { +#ifndef _WIN32 + if (0 == geteuid() && NULL == getenv("UV_RUN_AS_ROOT")) { + fprintf(stderr, "The libuv test suite cannot be run as root.\n"); + return EXIT_FAILURE; + } +#endif + if (platform_init(argc, argv)) return EXIT_FAILURE; diff --git a/deps/uv/test/task.h b/deps/uv/test/task.h index bc7b53369b53..13105d0bd94a 100644 --- a/deps/uv/test/task.h +++ b/deps/uv/test/task.h @@ -215,7 +215,7 @@ UNUSED static int can_ipv6(void) { return supported; } -#if defined(__CYGWIN__) || defined(__MSYS__) +#if defined(__CYGWIN__) || defined(__MSYS__) || defined(__PASE__) # define NO_FS_EVENTS "Filesystem watching not supported on this platform." #endif diff --git a/deps/uv/test/test-dlerror.c b/deps/uv/test/test-dlerror.c index 8f7697b59412..70cc9bfa8842 100644 --- a/deps/uv/test/test-dlerror.c +++ b/deps/uv/test/test-dlerror.c @@ -42,13 +42,17 @@ TEST_IMPL(dlerror) { msg = uv_dlerror(&lib); ASSERT(msg != NULL); +#ifndef __OpenBSD__ ASSERT(strstr(msg, path) != NULL); +#endif ASSERT(strstr(msg, dlerror_no_error) == NULL); /* Should return the same error twice in a row. */ msg = uv_dlerror(&lib); ASSERT(msg != NULL); +#ifndef __OpenBSD__ ASSERT(strstr(msg, path) != NULL); +#endif ASSERT(strstr(msg, dlerror_no_error) == NULL); uv_dlclose(&lib); diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c index ded1eec8dc63..75cefe32d87e 100644 --- a/deps/uv/test/test-fs.c +++ b/deps/uv/test/test-fs.c @@ -343,7 +343,8 @@ static void statfs_cb(uv_fs_t* req) { ASSERT(req->ptr != NULL); stats = req->ptr; -#if defined(_WIN32) || defined(__sun) || defined(_AIX) || defined(__MVS__) +#if defined(_WIN32) || defined(__sun) || defined(_AIX) || defined(__MVS__) || \ + defined(__OpenBSD__) || defined(__NetBSD__) ASSERT(stats->f_type == 0); #else ASSERT(stats->f_type > 0); @@ -1322,6 +1323,25 @@ TEST_IMPL(fs_fstat) { file = req.result; uv_fs_req_cleanup(&req); +#ifndef _WIN32 + ASSERT(0 == fstat(file, &t)); + ASSERT(0 == uv_fs_fstat(NULL, &req, file, NULL)); + ASSERT(req.result == 0); + s = req.ptr; +# if defined(__APPLE__) + ASSERT(s->st_birthtim.tv_sec == t.st_birthtimespec.tv_sec); + ASSERT(s->st_birthtim.tv_nsec == t.st_birthtimespec.tv_nsec); +# elif defined(__linux__) + /* If statx() is supported, the birth time should be equal to the change time + * because we just created the file. On older kernels, it's set to zero. + */ + ASSERT(s->st_birthtim.tv_sec == 0 || + s->st_birthtim.tv_sec == t.st_ctim.tv_sec); + ASSERT(s->st_birthtim.tv_nsec == 0 || + s->st_birthtim.tv_nsec == t.st_ctim.tv_nsec); +# endif +#endif + iov = uv_buf_init(test_buf, sizeof(test_buf)); r = uv_fs_write(NULL, &req, file, &iov, 1, -1, NULL); ASSERT(r == sizeof(test_buf)); @@ -1356,10 +1376,6 @@ TEST_IMPL(fs_fstat) { ASSERT(s->st_mtim.tv_nsec == t.st_mtimespec.tv_nsec); ASSERT(s->st_ctim.tv_sec == t.st_ctimespec.tv_sec); ASSERT(s->st_ctim.tv_nsec == t.st_ctimespec.tv_nsec); - ASSERT(s->st_birthtim.tv_sec == t.st_birthtimespec.tv_sec); - ASSERT(s->st_birthtim.tv_nsec == t.st_birthtimespec.tv_nsec); - ASSERT(s->st_flags == t.st_flags); - ASSERT(s->st_gen == t.st_gen); #elif defined(_AIX) ASSERT(s->st_atim.tv_sec == t.st_atime); ASSERT(s->st_atim.tv_nsec == 0); @@ -1394,8 +1410,6 @@ TEST_IMPL(fs_fstat) { defined(__NetBSD__) ASSERT(s->st_birthtim.tv_sec == t.st_birthtim.tv_sec); ASSERT(s->st_birthtim.tv_nsec == t.st_birthtim.tv_nsec); - ASSERT(s->st_flags == t.st_flags); - ASSERT(s->st_gen == t.st_gen); # endif #else ASSERT(s->st_atim.tv_sec == t.st_atime); @@ -1407,14 +1421,10 @@ TEST_IMPL(fs_fstat) { #endif #endif -#if defined(__linux__) - /* If statx() is supported, the birth time should be equal to the change time - * because we just created the file. On older kernels, it's set to zero. - */ - ASSERT(s->st_birthtim.tv_sec == 0 || - s->st_birthtim.tv_sec == t.st_ctim.tv_sec); - ASSERT(s->st_birthtim.tv_nsec == 0 || - s->st_birthtim.tv_nsec == t.st_ctim.tv_nsec); +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) + ASSERT(s->st_flags == t.st_flags); + ASSERT(s->st_gen == t.st_gen); +#else ASSERT(s->st_flags == 0); ASSERT(s->st_gen == 0); #endif diff --git a/deps/uv/test/test-platform-output.c b/deps/uv/test/test-platform-output.c index e651e5c58295..65cfa1b3dcd4 100644 --- a/deps/uv/test/test-platform-output.c +++ b/deps/uv/test/test-platform-output.c @@ -58,9 +58,13 @@ TEST_IMPL(platform_output) { #endif err = uv_uptime(&uptime); +#if defined(__PASE__) + ASSERT(err == UV_ENOSYS); +#else ASSERT(err == 0); ASSERT(uptime > 0); printf("uv_uptime: %f\n", uptime); +#endif err = uv_getrusage(&rusage); ASSERT(err == 0); diff --git a/deps/uv/test/test-poll-close-doesnt-corrupt-stack.c b/deps/uv/test/test-poll-close-doesnt-corrupt-stack.c index 3393820fc40d..1d7e84f60398 100644 --- a/deps/uv/test/test-poll-close-doesnt-corrupt-stack.c +++ b/deps/uv/test/test-poll-close-doesnt-corrupt-stack.c @@ -31,11 +31,9 @@ # define NO_INLINE __attribute__ ((noinline)) #endif - -uv_os_sock_t sock; -uv_poll_t handle; - #ifdef _WIN32 +static uv_os_sock_t sock; +static uv_poll_t handle; static int close_cb_called = 0; diff --git a/deps/uv/test/test-poll-closesocket.c b/deps/uv/test/test-poll-closesocket.c index ecaa9e54a223..1a1c364112a1 100644 --- a/deps/uv/test/test-poll-closesocket.c +++ b/deps/uv/test/test-poll-closesocket.c @@ -25,10 +25,9 @@ #include "uv.h" #include "task.h" -uv_os_sock_t sock; -uv_poll_t handle; - #ifdef _WIN32 +static uv_os_sock_t sock; +static uv_poll_t handle; static int close_cb_called = 0; diff --git a/deps/uv/test/test-process-title-threadsafe.c b/deps/uv/test/test-process-title-threadsafe.c index 19098eda0c40..2f12b74e14f9 100644 --- a/deps/uv/test/test-process-title-threadsafe.c +++ b/deps/uv/test/test-process-title-threadsafe.c @@ -25,7 +25,11 @@ #include -#define NUM_ITERATIONS 50 +#ifdef __APPLE__ +# define NUM_ITERATIONS 5 +#else +# define NUM_ITERATIONS 50 +#endif static const char* titles[] = { "8L2NY0Kdj0XyNFZnmUZigIOfcWjyNr0SkMmUhKw99VLUsZFrvCQQC3XIRfNR8pjyMjXObllled", @@ -68,7 +72,7 @@ TEST_IMPL(process_title_threadsafe) { int i; #if defined(__sun) || defined(__CYGWIN__) || defined(__MSYS__) || \ - defined(__MVS__) + defined(__MVS__) || defined(__PASE__) RETURN_SKIP("uv_(get|set)_process_title is not implemented."); #endif diff --git a/deps/uv/test/test-process-title.c b/deps/uv/test/test-process-title.c index efd48142b707..b49f3bc42644 100644 --- a/deps/uv/test/test-process-title.c +++ b/deps/uv/test/test-process-title.c @@ -60,7 +60,8 @@ static void uv_get_process_title_edge_cases(void) { TEST_IMPL(process_title) { -#if defined(__sun) || defined(__CYGWIN__) || defined(__MSYS__) +#if defined(__sun) || defined(__CYGWIN__) || defined(__MSYS__) || \ + defined(__PASE__) RETURN_SKIP("uv_(get|set)_process_title is not implemented."); #endif diff --git a/deps/uv/test/test-thread.c b/deps/uv/test/test-thread.c index be72d5e8b399..ffb392ceebc7 100644 --- a/deps/uv/test/test-thread.c +++ b/deps/uv/test/test-thread.c @@ -232,6 +232,7 @@ static void thread_check_stack(void* arg) { if (expected == 0) expected = (size_t)lim.rlim_cur; ASSERT(stack_size >= expected); + ASSERT(0 == pthread_attr_destroy(&attr)); #endif } diff --git a/deps/uv/test/test-udp-multicast-join.c b/deps/uv/test/test-udp-multicast-join.c index 6bac072db096..cb3ff871eb91 100644 --- a/deps/uv/test/test-udp-multicast-join.c +++ b/deps/uv/test/test-udp-multicast-join.c @@ -126,8 +126,10 @@ static void cl_recv_cb(uv_udp_t* handle, r = uv_udp_set_membership(&server, MULTICAST_ADDR, NULL, UV_LEAVE_GROUP); ASSERT(r == 0); +#if !defined(__OpenBSD__) && !defined(__NetBSD__) r = uv_udp_set_source_membership(&server, MULTICAST_ADDR, NULL, source_addr, UV_JOIN_GROUP); ASSERT(r == 0); +#endif r = do_send(&req_ss); ASSERT(r == 0); diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index bbeda104b47a..99fb3cfb7302 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -93,7 +93,7 @@ '-Wno-unused-parameter', '-Wstrict-prototypes', ], - 'OTHER_CFLAGS': [ '-g', '--std=gnu89', '-pedantic' ], + 'OTHER_CFLAGS': [ '-g', '--std=gnu89' ], }, 'conditions': [ [ 'OS=="win"', { @@ -217,7 +217,6 @@ '-fvisibility=hidden', '-g', '--std=gnu89', - '-pedantic', '-Wall', '-Wextra', '-Wno-unused-parameter', From e1e0206dd4cb931fa3432c6738b86d3a35f1dc75 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Thu, 23 Jan 2020 09:31:45 -0500 Subject: [PATCH 9/9] deps: upgrade to libuv 1.34.2 Notable changes: - SetApplicationDaemon() is no longer called on macOS. - uv_interface_addresses() is implemented on IBMi. - The return value of uv__open_cloexec() is now handled properly. - A race condition in fsevents has been fixed. Fixes: https://github.com/nodejs/node/issues/31328 Fixes: https://github.com/nodejs/help/issues/2099 PR-URL: https://github.com/nodejs/node/pull/31477 Reviewed-By: Richard Lau Reviewed-By: Anna Henningsen Reviewed-By: David Carlier Reviewed-By: Trivikram Kamat Reviewed-By: Ben Noordhuis Reviewed-By: Rich Trott --- deps/uv/ChangeLog | 23 +++ deps/uv/configure.ac | 2 +- deps/uv/include/uv/version.h | 2 +- deps/uv/src/unix/aix-common.c | 180 ------------------- deps/uv/src/unix/aix.c | 180 +++++++++++++++++++ deps/uv/src/unix/darwin-proctitle.c | 27 +-- deps/uv/src/unix/fsevents.c | 5 +- deps/uv/src/unix/ibmi.c | 259 +++++++++++++++++++++++++-- deps/uv/src/unix/linux-core.c | 2 +- deps/uv/src/unix/random-devurandom.c | 4 +- deps/uv/src/unix/stream.c | 4 - deps/uv/test/runner-unix.c | 7 +- deps/uv/test/runner-win.c | 17 +- deps/uv/test/runner.c | 11 +- deps/uv/test/test-env-vars.c | 6 + deps/uv/test/test-get-memory.c | 5 + 16 files changed, 491 insertions(+), 243 deletions(-) diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index b57ff4716a82..9c2146dab9da 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,3 +1,26 @@ +2020.01.24, Version 1.34.2 (Stable), f868c9ab0c307525a16fff99fd21e32a6ebc3837 + +Changes since version 1.34.1: + +* misc: adjust stalebot deadlines (Jameson Nash) + +* test: fix env-vars flakiness (cjihrig) + +* test: avoid truncating output lines (Jameson Nash) + +* darwin: stop calling SetApplicationIsDaemon() (Ben Noordhuis) + +* ibmi: implement uv_interface_addresses() (Xu Meng) + +* osx,fsevent: fix race during uv_loop_close (Jameson Nash) + +* osx,fsevent: clear pointer when deleting it [NFCI] (Jameson Nash) + +* Revert "aix: replace ECONNRESET with EOF if already closed" (Jameson Nash) + +* unix: handle uv__open_cloexec return value correctly (Anna Henningsen) + + 2020.01.13, Version 1.34.1 (Stable), 8aa5636ec72990bb2856f81e14c95813024a5c2b Changes since version 1.34.0: diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac index ea7fea90125f..fba960b6b337 100644 --- a/deps/uv/configure.ac +++ b/deps/uv/configure.ac @@ -13,7 +13,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. AC_PREREQ(2.57) -AC_INIT([libuv], [1.34.1], [https://github.com/libuv/libuv/issues]) +AC_INIT([libuv], [1.34.2], [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]) diff --git a/deps/uv/include/uv/version.h b/deps/uv/include/uv/version.h index cfa321148039..623ca3ef2cba 100644 --- a/deps/uv/include/uv/version.h +++ b/deps/uv/include/uv/version.h @@ -32,7 +32,7 @@ #define UV_VERSION_MAJOR 1 #define UV_VERSION_MINOR 34 -#define UV_VERSION_PATCH 1 +#define UV_VERSION_PATCH 2 #define UV_VERSION_IS_RELEASE 1 #define UV_VERSION_SUFFIX "" diff --git a/deps/uv/src/unix/aix-common.c b/deps/uv/src/unix/aix-common.c index e96e34c46373..c18a5298cec6 100644 --- a/deps/uv/src/unix/aix-common.c +++ b/deps/uv/src/unix/aix-common.c @@ -155,183 +155,3 @@ int uv_exepath(char* buffer, size_t* size) { return UV_EINVAL; } } - - -int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { - uv_interface_address_t* address; - int sockfd, sock6fd, inet6, i, r, size = 1; - struct ifconf ifc; - struct ifreq *ifr, *p, flg; - struct in6_ifreq if6; - struct sockaddr_dl* sa_addr; - - ifc.ifc_req = NULL; - sock6fd = -1; - r = 0; - *count = 0; - *addresses = NULL; - - if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) { - r = UV__ERR(errno); - goto cleanup; - } - - if (0 > (sock6fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP))) { - r = UV__ERR(errno); - goto cleanup; - } - - if (ioctl(sockfd, SIOCGSIZIFCONF, &size) == -1) { - r = UV__ERR(errno); - goto cleanup; - } - - ifc.ifc_req = (struct ifreq*)uv__malloc(size); - if (ifc.ifc_req == NULL) { - r = UV_ENOMEM; - goto cleanup; - } - ifc.ifc_len = size; - if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) { - r = UV__ERR(errno); - goto cleanup; - } - -#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p)) - - /* Count all up and running ipv4/ipv6 addresses */ - ifr = ifc.ifc_req; - while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { - p = ifr; - ifr = (struct ifreq*) - ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); - - if (!(p->ifr_addr.sa_family == AF_INET6 || - p->ifr_addr.sa_family == AF_INET)) - continue; - - memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); - if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { - r = UV__ERR(errno); - goto cleanup; - } - - if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING)) - continue; - - (*count)++; - } - - if (*count == 0) - goto cleanup; - - /* Alloc the return interface structs */ - *addresses = uv__calloc(*count, sizeof(**addresses)); - if (!(*addresses)) { - r = UV_ENOMEM; - goto cleanup; - } - address = *addresses; - - ifr = ifc.ifc_req; - while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { - p = ifr; - ifr = (struct ifreq*) - ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); - - if (!(p->ifr_addr.sa_family == AF_INET6 || - p->ifr_addr.sa_family == AF_INET)) - continue; - - inet6 = (p->ifr_addr.sa_family == AF_INET6); - - memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); - if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) - goto syserror; - - if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING)) - continue; - - /* All conditions above must match count loop */ - - address->name = uv__strdup(p->ifr_name); - - if (inet6) - address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr); - else - address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr); - - if (inet6) { - memset(&if6, 0, sizeof(if6)); - r = uv__strscpy(if6.ifr_name, p->ifr_name, sizeof(if6.ifr_name)); - if (r == UV_E2BIG) - goto cleanup; - r = 0; - memcpy(&if6.ifr_Addr, &p->ifr_addr, sizeof(if6.ifr_Addr)); - if (ioctl(sock6fd, SIOCGIFNETMASK6, &if6) == -1) - goto syserror; - address->netmask.netmask6 = *((struct sockaddr_in6*) &if6.ifr_Addr); - /* Explicitly set family as the ioctl call appears to return it as 0. */ - address->netmask.netmask6.sin6_family = AF_INET6; - } else { - if (ioctl(sockfd, SIOCGIFNETMASK, p) == -1) - goto syserror; - address->netmask.netmask4 = *((struct sockaddr_in*) &p->ifr_addr); - /* Explicitly set family as the ioctl call appears to return it as 0. */ - address->netmask.netmask4.sin_family = AF_INET; - } - - address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0; - - address++; - } - - /* Fill in physical addresses. */ - ifr = ifc.ifc_req; - while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { - p = ifr; - ifr = (struct ifreq*) - ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); - - if (p->ifr_addr.sa_family != AF_LINK) - continue; - - address = *addresses; - for (i = 0; i < *count; i++) { - if (strcmp(address->name, p->ifr_name) == 0) { - sa_addr = (struct sockaddr_dl*) &p->ifr_addr; - memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); - } - address++; - } - } - -#undef ADDR_SIZE - goto cleanup; - -syserror: - uv_free_interface_addresses(*addresses, *count); - *addresses = NULL; - *count = 0; - r = UV_ENOSYS; - -cleanup: - if (sockfd != -1) - uv__close(sockfd); - if (sock6fd != -1) - uv__close(sock6fd); - uv__free(ifc.ifc_req); - return r; -} - - -void uv_free_interface_addresses(uv_interface_address_t* addresses, - int count) { - int i; - - for (i = 0; i < count; ++i) { - uv__free(addresses[i].name); - } - - uv__free(addresses); -} diff --git a/deps/uv/src/unix/aix.c b/deps/uv/src/unix/aix.c index 1f36926c02e2..417ee5512fa2 100644 --- a/deps/uv/src/unix/aix.c +++ b/deps/uv/src/unix/aix.c @@ -1039,6 +1039,186 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { } +int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { + uv_interface_address_t* address; + int sockfd, sock6fd, inet6, i, r, size = 1; + struct ifconf ifc; + struct ifreq *ifr, *p, flg; + struct in6_ifreq if6; + struct sockaddr_dl* sa_addr; + + ifc.ifc_req = NULL; + sock6fd = -1; + r = 0; + *count = 0; + *addresses = NULL; + + if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) { + r = UV__ERR(errno); + goto cleanup; + } + + if (0 > (sock6fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP))) { + r = UV__ERR(errno); + goto cleanup; + } + + if (ioctl(sockfd, SIOCGSIZIFCONF, &size) == -1) { + r = UV__ERR(errno); + goto cleanup; + } + + ifc.ifc_req = (struct ifreq*)uv__malloc(size); + if (ifc.ifc_req == NULL) { + r = UV_ENOMEM; + goto cleanup; + } + ifc.ifc_len = size; + if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) { + r = UV__ERR(errno); + goto cleanup; + } + +#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p)) + + /* Count all up and running ipv4/ipv6 addresses */ + ifr = ifc.ifc_req; + while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { + p = ifr; + ifr = (struct ifreq*) + ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); + + if (!(p->ifr_addr.sa_family == AF_INET6 || + p->ifr_addr.sa_family == AF_INET)) + continue; + + memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); + if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { + r = UV__ERR(errno); + goto cleanup; + } + + if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING)) + continue; + + (*count)++; + } + + if (*count == 0) + goto cleanup; + + /* Alloc the return interface structs */ + *addresses = uv__calloc(*count, sizeof(**addresses)); + if (!(*addresses)) { + r = UV_ENOMEM; + goto cleanup; + } + address = *addresses; + + ifr = ifc.ifc_req; + while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { + p = ifr; + ifr = (struct ifreq*) + ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); + + if (!(p->ifr_addr.sa_family == AF_INET6 || + p->ifr_addr.sa_family == AF_INET)) + continue; + + inet6 = (p->ifr_addr.sa_family == AF_INET6); + + memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); + if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) + goto syserror; + + if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING)) + continue; + + /* All conditions above must match count loop */ + + address->name = uv__strdup(p->ifr_name); + + if (inet6) + address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr); + else + address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr); + + if (inet6) { + memset(&if6, 0, sizeof(if6)); + r = uv__strscpy(if6.ifr_name, p->ifr_name, sizeof(if6.ifr_name)); + if (r == UV_E2BIG) + goto cleanup; + r = 0; + memcpy(&if6.ifr_Addr, &p->ifr_addr, sizeof(if6.ifr_Addr)); + if (ioctl(sock6fd, SIOCGIFNETMASK6, &if6) == -1) + goto syserror; + address->netmask.netmask6 = *((struct sockaddr_in6*) &if6.ifr_Addr); + /* Explicitly set family as the ioctl call appears to return it as 0. */ + address->netmask.netmask6.sin6_family = AF_INET6; + } else { + if (ioctl(sockfd, SIOCGIFNETMASK, p) == -1) + goto syserror; + address->netmask.netmask4 = *((struct sockaddr_in*) &p->ifr_addr); + /* Explicitly set family as the ioctl call appears to return it as 0. */ + address->netmask.netmask4.sin_family = AF_INET; + } + + address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0; + + address++; + } + + /* Fill in physical addresses. */ + ifr = ifc.ifc_req; + while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { + p = ifr; + ifr = (struct ifreq*) + ((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr)); + + if (p->ifr_addr.sa_family != AF_LINK) + continue; + + address = *addresses; + for (i = 0; i < *count; i++) { + if (strcmp(address->name, p->ifr_name) == 0) { + sa_addr = (struct sockaddr_dl*) &p->ifr_addr; + memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); + } + address++; + } + } + +#undef ADDR_SIZE + goto cleanup; + +syserror: + uv_free_interface_addresses(*addresses, *count); + *addresses = NULL; + *count = 0; + r = UV_ENOSYS; + +cleanup: + if (sockfd != -1) + uv__close(sockfd); + if (sock6fd != -1) + uv__close(sock6fd); + uv__free(ifc.ifc_req); + return r; +} + + +void uv_free_interface_addresses(uv_interface_address_t* addresses, + int count) { + int i; + + for (i = 0; i < count; ++i) { + uv__free(addresses[i].name); + } + + uv__free(addresses); +} + + void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { struct pollfd* events; uintptr_t i; diff --git a/deps/uv/src/unix/darwin-proctitle.c b/deps/uv/src/unix/darwin-proctitle.c index 97eaa05391be..2daf3e3474ac 100644 --- a/deps/uv/src/unix/darwin-proctitle.c +++ b/deps/uv/src/unix/darwin-proctitle.c @@ -72,8 +72,6 @@ int uv__set_process_title(const char* title) { CFStringRef* display_name_key; CFDictionaryRef (*pCFBundleGetInfoDictionary)(CFBundleRef); CFBundleRef (*pCFBundleGetMainBundle)(void); - CFBundleRef hi_services_bundle; - OSStatus (*pSetApplicationIsDaemon)(int); CFDictionaryRef (*pLSApplicationCheckIn)(int, CFDictionaryRef); void (*pLSSetApplicationLaunchServicesServerConnectionStatus)(uint64_t, void*); @@ -144,30 +142,19 @@ int uv__set_process_title(const char* title) { if (pCFBundleGetInfoDictionary == NULL || pCFBundleGetMainBundle == NULL) goto out; - /* Black 10.9 magic, to remove (Not responding) mark in Activity Monitor */ - hi_services_bundle = - pCFBundleGetBundleWithIdentifier(S("com.apple.HIServices")); - err = UV_ENOENT; - if (hi_services_bundle == NULL) - goto out; - - *(void **)(&pSetApplicationIsDaemon) = pCFBundleGetFunctionPointerForName( - hi_services_bundle, - S("SetApplicationIsDaemon")); *(void **)(&pLSApplicationCheckIn) = pCFBundleGetFunctionPointerForName( launch_services_bundle, S("_LSApplicationCheckIn")); + + if (pLSApplicationCheckIn == NULL) + goto out; + *(void **)(&pLSSetApplicationLaunchServicesServerConnectionStatus) = pCFBundleGetFunctionPointerForName( launch_services_bundle, S("_LSSetApplicationLaunchServicesServerConnectionStatus")); - if (pSetApplicationIsDaemon == NULL || - pLSApplicationCheckIn == NULL || - pLSSetApplicationLaunchServicesServerConnectionStatus == NULL) { - goto out; - } - if (pSetApplicationIsDaemon(1) != noErr) + if (pLSSetApplicationLaunchServicesServerConnectionStatus == NULL) goto out; pLSSetApplicationLaunchServicesServerConnectionStatus(0, NULL); @@ -178,6 +165,10 @@ int uv__set_process_title(const char* title) { asn = pLSGetCurrentApplicationASN(); + err = UV_EBUSY; + if (asn == NULL) + goto out; + err = UV_EINVAL; if (pLSSetApplicationInformationItem(-2, /* Magic value. */ asn, diff --git a/deps/uv/src/unix/fsevents.c b/deps/uv/src/unix/fsevents.c index deeaa63d4730..448921f813d7 100644 --- a/deps/uv/src/unix/fsevents.c +++ b/deps/uv/src/unix/fsevents.c @@ -747,6 +747,8 @@ static void* uv__cf_loop_runner(void* arg) { state->signal_source, *pkCFRunLoopDefaultMode); + state->loop = NULL; + return NULL; } @@ -799,13 +801,14 @@ int uv__cf_loop_signal(uv_loop_t* loop, uv_mutex_lock(&loop->cf_mutex); QUEUE_INSERT_TAIL(&loop->cf_signals, &item->member); - uv_mutex_unlock(&loop->cf_mutex); state = loop->cf_state; assert(state != NULL); pCFRunLoopSourceSignal(state->signal_source); pCFRunLoopWakeUp(state->loop); + uv_mutex_unlock(&loop->cf_mutex); + return 0; } diff --git a/deps/uv/src/unix/ibmi.c b/deps/uv/src/unix/ibmi.c index 8b355033e29c..4dd8bb6e3758 100644 --- a/deps/uv/src/unix/ibmi.c +++ b/deps/uv/src/unix/ibmi.c @@ -56,6 +56,7 @@ #include #include +#include typedef struct { @@ -98,24 +99,91 @@ typedef struct { } SSTS0200; +typedef struct { + char header[208]; + unsigned char loca_adapter_address[12]; +} LIND0500; + + +typedef struct { + int bytes_provided; + int bytes_available; + char msgid[7]; +} errcode_s; + + +static const unsigned char e2a[256] = { + 0, 1, 2, 3, 156, 9, 134, 127, 151, 141, 142, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 157, 133, 8, 135, 24, 25, 146, 143, 28, 29, 30, 31, + 128, 129, 130, 131, 132, 10, 23, 27, 136, 137, 138, 139, 140, 5, 6, 7, + 144, 145, 22, 147, 148, 149, 150, 4, 152, 153, 154, 155, 20, 21, 158, 26, + 32, 160, 161, 162, 163, 164, 165, 166, 167, 168, 91, 46, 60, 40, 43, 33, + 38, 169, 170, 171, 172, 173, 174, 175, 176, 177, 93, 36, 42, 41, 59, 94, + 45, 47, 178, 179, 180, 181, 182, 183, 184, 185, 124, 44, 37, 95, 62, 63, + 186, 187, 188, 189, 190, 191, 192, 193, 194, 96, 58, 35, 64, 39, 61, 34, + 195, 97, 98, 99, 100, 101, 102, 103, 104, 105, 196, 197, 198, 199, 200, 201, + 202, 106, 107, 108, 109, 110, 111, 112, 113, 114, 203, 204, 205, 206, 207, 208, + 209, 126, 115, 116, 117, 118, 119, 120, 121, 122, 210, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, + 123, 65, 66, 67, 68, 69, 70, 71, 72, 73, 232, 233, 234, 235, 236, 237, + 125, 74, 75, 76, 77, 78, 79, 80, 81, 82, 238, 239, 240, 241, 242, 243, + 92, 159, 83, 84, 85, 86, 87, 88, 89, 90, 244, 245, 246, 247, 248, 249, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 250, 251, 252, 253, 254, 255}; + + +static const unsigned char a2e[256] = { + 0, 1, 2, 3, 55, 45, 46, 47, 22, 5, 37, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 60, 61, 50, 38, 24, 25, 63, 39, 28, 29, 30, 31, + 64, 79, 127, 123, 91, 108, 80, 125, 77, 93, 92, 78, 107, 96, 75, 97, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 122, 94, 76, 126, 110, 111, + 124, 193, 194, 195, 196, 197, 198, 199, 200, 201, 209, 210, 211, 212, 213, 214, + 215, 216, 217, 226, 227, 228, 229, 230, 231, 232, 233, 74, 224, 90, 95, 109, + 121, 129, 130, 131, 132, 133, 134, 135, 136, 137, 145, 146, 147, 148, 149, 150, + 151, 152, 153, 162, 163, 164, 165, 166, 167, 168, 169, 192, 106, 208, 161, 7, + 32, 33, 34, 35, 36, 21, 6, 23, 40, 41, 42, 43, 44, 9, 10, 27, + 48, 49, 26, 51, 52, 53, 54, 8, 56, 57, 58, 59, 4, 20, 62, 225, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 98, 99, 100, 101, 102, 103, 104, 105, 112, 113, 114, 115, 116, 117, + 118, 119, 120, 128, 138, 139, 140, 141, 142, 143, 144, 154, 155, 156, 157, 158, + 159, 160, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 190, 191, 202, 203, 204, 205, 206, 207, 218, 219, + 220, 221, 222, 223, 234, 235, 236, 237, 238, 239, 250, 251, 252, 253, 254, 255}; + + +static void iconv_e2a(unsigned char src[], unsigned char dst[], size_t length) { + size_t i; + for (i = 0; i < length; i++) + dst[i] = e2a[src[i]]; +} + + +static void iconv_a2e(const char* src, unsigned char dst[], size_t length) { + size_t srclen; + size_t i; + + srclen = strlen(src); + if (srclen > length) + abort(); + for (i = 0; i < srclen; i++) + dst[i] = a2e[src[i]]; + /* padding the remaining part with spaces */ + for (; i < length; i++) + dst[i] = a2e[' ']; +} + + static int get_ibmi_system_status(SSTS0200* rcvr) { /* rcvrlen is input parameter 2 to QWCRSSTS */ unsigned int rcvrlen = sizeof(*rcvr); + unsigned char format[8], reset_status[10]; - /* format is input parameter 3 to QWCRSSTS ("SSTS0200" in EBCDIC) */ - unsigned char format[] = {0xE2, 0xE2, 0xE3, 0xE2, 0xF0, 0xF2, 0xF0, 0xF0}; - - /* reset_status is input parameter 4 to QWCRSSTS ("*NO " in EBCDIC) */ - unsigned char reset_status[] = { - 0x5C, 0xD5, 0xD6, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 - }; + /* format is input parameter 3 to QWCRSSTS */ + iconv_a2e("SSTS0200", format, sizeof(format)); + /* reset_status is input parameter 4 */ + iconv_a2e("*NO", reset_status, sizeof(reset_status)); /* errcode is input parameter 5 to QWCRSSTS */ - struct _errcode { - int bytes_provided; - int bytes_available; - char msgid[7]; - } errcode; + errcode_s errcode; /* qwcrssts_pointer is the 16-byte tagged system pointer to QWCRSSTS */ ILEpointer __attribute__((aligned(16))) qwcrssts_pointer; @@ -145,7 +213,7 @@ static int get_ibmi_system_status(SSTS0200* rcvr) { qwcrssts_argv[5] = NULL; /* Call the IBM i QWCRSSTS API from PASE */ - rc = _PGMCALL(&qwcrssts_pointer, (void**)&qwcrssts_argv, 0); + rc = _PGMCALL(&qwcrssts_pointer, qwcrssts_argv, 0); return rc; } @@ -166,10 +234,13 @@ uint64_t uv_get_free_memory(void) { uint64_t current_unprotected_storage_used = rcvr.current_unprotected_storage_used * 1024ULL; - uint64_t free_storage_size = - (main_storage_size - current_unprotected_storage_used) * 1024ULL; + /* Current unprotected storage includes the storage used for memory + * and disks so it is possible to exceed the amount of main storage. + */ + if (main_storage_size <= current_unprotected_storage_used) + return 0ULL; - return free_storage_size < 0 ? 0 : free_storage_size; + return (main_storage_size - current_unprotected_storage_used) * 1024ULL; } @@ -247,3 +318,159 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { return 0; } + + +static int get_ibmi_physical_address(const char* line, char (*phys_addr)[6]) { + LIND0500 rcvr; + /* rcvrlen is input parameter 2 to QDCRLIND */ + unsigned int rcvrlen = sizeof(rcvr); + unsigned char format[8], line_name[10]; + unsigned char mac_addr[sizeof(rcvr.loca_adapter_address)]; + int c[6]; + + /* format is input parameter 3 to QDCRLIND */ + iconv_a2e("LIND0500", format, sizeof(format)); + + /* line_name is input parameter 4 to QDCRLIND */ + iconv_a2e(line, line_name, sizeof(line_name)); + + /* err is input parameter 5 to QDCRLIND */ + errcode_s err; + + /* qwcrssts_pointer is the 16-byte tagged system pointer to QDCRLIND */ + ILEpointer __attribute__((aligned(16))) qdcrlind_pointer; + + /* qwcrssts_argv is the array of argument pointers to QDCRLIND */ + void* qdcrlind_argv[6]; + + /* Set the IBM i pointer to the QSYS/QDCRLIND *PGM object */ + int rc = _RSLOBJ2(&qdcrlind_pointer, RSLOBJ_TS_PGM, "QDCRLIND", "QSYS"); + + if (rc != 0) + return rc; + + /* initialize the QDCRLIND returned info structure */ + memset(&rcvr, 0, sizeof(rcvr)); + + /* initialize the QDCRLIND error code structure */ + memset(&err, 0, sizeof(err)); + err.bytes_provided = sizeof(err); + + /* initialize the array of argument pointers for the QDCRLIND API */ + qdcrlind_argv[0] = &rcvr; + qdcrlind_argv[1] = &rcvrlen; + qdcrlind_argv[2] = &format; + qdcrlind_argv[3] = &line_name; + qdcrlind_argv[4] = &err; + qdcrlind_argv[5] = NULL; + + /* Call the IBM i QDCRLIND API from PASE */ + rc = _PGMCALL(&qdcrlind_pointer, qdcrlind_argv, 0); + if (rc != 0) + return rc; + + /* convert ebcdic loca_adapter_address to ascii first */ + iconv_e2a(rcvr.loca_adapter_address, mac_addr, + sizeof(rcvr.loca_adapter_address)); + + /* convert loca_adapter_address(char[12]) to phys_addr(char[6]) */ + int r = sscanf(mac_addr, "%02x%02x%02x%02x%02x%02x", + &c[0], &c[1], &c[2], &c[3], &c[4], &c[5]); + + if (r == ARRAY_SIZE(c)) { + (*phys_addr)[0] = c[0]; + (*phys_addr)[1] = c[1]; + (*phys_addr)[2] = c[2]; + (*phys_addr)[3] = c[3]; + (*phys_addr)[4] = c[4]; + (*phys_addr)[5] = c[5]; + } else { + memset(*phys_addr, 0, sizeof(*phys_addr)); + rc = -1; + } + return rc; +} + + +int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { + uv_interface_address_t* address; + struct ifaddrs_pase *ifap = NULL, *cur; + int inet6, r = 0; + + *count = 0; + *addresses = NULL; + + if (Qp2getifaddrs(&ifap)) + return UV_ENOSYS; + + /* The first loop to get the size of the array to be allocated */ + for (cur = ifap; cur; cur = cur->ifa_next) { + if (!(cur->ifa_addr->sa_family == AF_INET6 || + cur->ifa_addr->sa_family == AF_INET)) + continue; + + if (!(cur->ifa_flags & IFF_UP && cur->ifa_flags & IFF_RUNNING)) + continue; + + (*count)++; + } + + if (*count == 0) { + Qp2freeifaddrs(ifap); + return 0; + } + + /* Alloc the return interface structs */ + *addresses = uv__calloc(*count, sizeof(**addresses)); + if (*addresses == NULL) { + Qp2freeifaddrs(ifap); + return UV_ENOMEM; + } + address = *addresses; + + /* The second loop to fill in the array */ + for (cur = ifap; cur; cur = cur->ifa_next) { + if (!(cur->ifa_addr->sa_family == AF_INET6 || + cur->ifa_addr->sa_family == AF_INET)) + continue; + + if (!(cur->ifa_flags & IFF_UP && cur->ifa_flags & IFF_RUNNING)) + continue; + + address->name = uv__strdup(cur->ifa_name); + + inet6 = (cur->ifa_addr->sa_family == AF_INET6); + + if (inet6) { + address->address.address6 = *((struct sockaddr_in6*)cur->ifa_addr); + address->netmask.netmask6 = *((struct sockaddr_in6*)cur->ifa_netmask); + address->netmask.netmask6.sin6_family = AF_INET6; + } else { + address->address.address4 = *((struct sockaddr_in*)cur->ifa_addr); + address->netmask.netmask4 = *((struct sockaddr_in*)cur->ifa_netmask); + address->netmask.netmask4.sin_family = AF_INET; + } + address->is_internal = cur->ifa_flags & IFF_LOOPBACK ? 1 : 0; + if (!address->is_internal) { + int rc = get_ibmi_physical_address(address->name, &address->phys_addr); + if (rc != 0) + r = rc; + } + + address++; + } + + Qp2freeifaddrs(ifap); + return r; +} + + +void uv_free_interface_addresses(uv_interface_address_t* addresses, int count) { + int i; + + for (i = 0; i < count; ++i) { + uv__free(addresses[i].name); + } + + uv__free(addresses); +} diff --git a/deps/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c index 740e422d46ed..f8d9ff5868ab 100644 --- a/deps/uv/src/unix/linux-core.c +++ b/deps/uv/src/unix/linux-core.c @@ -990,7 +990,7 @@ static uint64_t uv__read_proc_meminfo(const char* what) { rc = 0; fd = uv__open_cloexec("/proc/meminfo", O_RDONLY); - if (fd == -1) + if (fd < 0) return 0; n = read(fd, buf, sizeof(buf) - 1); diff --git a/deps/uv/src/unix/random-devurandom.c b/deps/uv/src/unix/random-devurandom.c index 9aa762e372ea..05e52a56a364 100644 --- a/deps/uv/src/unix/random-devurandom.c +++ b/deps/uv/src/unix/random-devurandom.c @@ -37,8 +37,8 @@ int uv__random_readpath(const char* path, void* buf, size_t buflen) { fd = uv__open_cloexec(path, O_RDONLY); - if (fd == -1) - return UV__ERR(errno); + if (fd < 0) + return fd; if (fstat(fd, &s)) { uv__close(fd); diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c index 8c1329306d70..8327f9ccfcea 100644 --- a/deps/uv/src/unix/stream.c +++ b/deps/uv/src/unix/stream.c @@ -1185,10 +1185,6 @@ static void uv__read(uv_stream_t* stream) { } else if (errno == ECONNRESET && stream->type == UV_NAMED_PIPE) { uv__stream_eof(stream, &buf); return; -#elif defined(_AIX) - } else if (errno == ECONNRESET && (stream->flags & UV_DISCONNECT)) { - uv__stream_eof(stream, &buf); - return; #endif } else { /* Error. User should call uv_close(). */ diff --git a/deps/uv/test/runner-unix.c b/deps/uv/test/runner-unix.c index 716c15ff088f..dbb33bfa3edf 100644 --- a/deps/uv/test/runner-unix.c +++ b/deps/uv/test/runner-unix.c @@ -371,8 +371,8 @@ int process_copy_output(process_info_t* p, FILE* stream) { } /* TODO: what if the line is longer than buf */ - while (fgets(buf, sizeof(buf), p->stdout_file) != NULL) - print_lines(buf, strlen(buf), stream); + while ((r = fread(buf, 1, sizeof(buf), p->stdout_file)) != 0) + print_lines(buf, r, stream); if (ferror(p->stdout_file)) { perror("read"); @@ -398,7 +398,8 @@ int process_read_last_line(process_info_t *p, buffer[0] = '\0'; while (fgets(buffer, buffer_len, p->stdout_file) != NULL) { - for (ptr = buffer; *ptr && *ptr != '\r' && *ptr != '\n'; ptr++); + for (ptr = buffer; *ptr && *ptr != '\r' && *ptr != '\n'; ptr++) + ; *ptr = '\0'; } diff --git a/deps/uv/test/runner-win.c b/deps/uv/test/runner-win.c index 4167a386921e..e69b7447dcee 100644 --- a/deps/uv/test/runner-win.c +++ b/deps/uv/test/runner-win.c @@ -222,28 +222,19 @@ long int process_output_size(process_info_t *p) { int process_copy_output(process_info_t* p, FILE* stream) { char buf[1024]; int fd, r; - FILE* f; fd = _open_osfhandle((intptr_t)p->stdio_out, _O_RDONLY | _O_TEXT); if (fd == -1) return -1; - f = _fdopen(fd, "rt"); - if (f == NULL) { - _close(fd); - return -1; - } - r = fseek(f, 0, SEEK_SET); + r = _lseek(fd, 0, SEEK_SET); if (r < 0) return -1; - while (fgets(buf, sizeof(buf), f) != NULL) - print_lines(buf, strlen(buf), stream); - - if (ferror(f)) - return -1; + while ((r = _read(fd, buf, sizeof(buf))) != 0) + print_lines(buf, r, stream); - fclose(f); + _close(fd); return 0; } diff --git a/deps/uv/test/runner.c b/deps/uv/test/runner.c index aec560a59dbc..a0f5df8947ba 100644 --- a/deps/uv/test/runner.c +++ b/deps/uv/test/runner.c @@ -419,13 +419,18 @@ void print_lines(const char* buffer, size_t size, FILE* stream) { start = buffer; while ((end = memchr(start, '\n', &buffer[size] - start))) { - fprintf(stream, "# %.*s\n", (int) (end - start), start); + fputs("# ", stream); + fwrite(start, 1, (int)(end - start), stream); + fputs("\n", stream); fflush(stream); start = end + 1; } - if (start < &buffer[size]) { - fprintf(stream, "# %s\n", start); + end = &buffer[size]; + if (start < end) { + fputs("# ", stream); + fwrite(start, 1, (int)(end - start), stream); + fputs("\n", stream); fflush(stream); } } diff --git a/deps/uv/test/test-env-vars.c b/deps/uv/test/test-env-vars.c index 3c9de95b102a..f61c1c6c115c 100644 --- a/deps/uv/test/test-env-vars.c +++ b/deps/uv/test/test-env-vars.c @@ -102,6 +102,12 @@ TEST_IMPL(env_vars) { ASSERT(r == 0); r = uv_os_setenv(name2, ""); ASSERT(r == 0); +#ifdef _WIN32 + /* Create a special environment variable on Windows in case there are no + naturally occurring ones. */ + r = uv_os_setenv("=Z:", "\\"); + ASSERT(r == 0); +#endif r = uv_os_environ(&envitems, &envcount); ASSERT(r == 0); diff --git a/deps/uv/test/test-get-memory.c b/deps/uv/test/test-get-memory.c index 0e0864038b32..6a9a46dc81dc 100644 --- a/deps/uv/test/test-get-memory.c +++ b/deps/uv/test/test-get-memory.c @@ -32,7 +32,12 @@ TEST_IMPL(get_memory) { (unsigned long long) total_mem, (unsigned long long) constrained_mem); + /* On IBMi PASE, the amount of memory in use includes storage used for + * memory and disks so it is possible to exceed the amount of main storage. + */ +#ifndef __PASE__ ASSERT(free_mem > 0); +#endif ASSERT(total_mem > 0); ASSERT(total_mem > free_mem);