From b81c82af8178b97d47ea2c99e0a9dc90a3567c1e Mon Sep 17 00:00:00 2001 From: cjihrig Date: Sun, 31 Mar 2019 01:35:59 -0400 Subject: [PATCH 1/4] test: fix error code typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/27024 Reviewed-By: Richard Lau Reviewed-By: Rich Trott Reviewed-By: Anatoli Papirovski Reviewed-By: Yongsheng Zhang Reviewed-By: Michaƫl Zasso Reviewed-By: Ruben Bridgewater Reviewed-By: Luigi Pinca --- test/known_issues/test-fs-copyfile-respect-permissions.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/known_issues/test-fs-copyfile-respect-permissions.js b/test/known_issues/test-fs-copyfile-respect-permissions.js index 0ebc5fbfc1dbed..34697eea6c0bef 100644 --- a/test/known_issues/test-fs-copyfile-respect-permissions.js +++ b/test/known_issues/test-fs-copyfile-respect-permissions.js @@ -23,8 +23,9 @@ function beforeEach() { fs.chmodSync(dest, '444'); const check = (err) => { - assert.strictEqual(err.code, 'EACCESS'); + assert.strictEqual(err.code, 'EACCES'); assert.strictEqual(fs.readFileSync(dest, 'utf8'), 'dest'); + return true; }; return { source, dest, check }; @@ -39,8 +40,9 @@ function beforeEach() { // Test promises API. { const { source, dest, check } = beforeEach(); - assert.throws(async () => { await fs.promises.copyFile(source, dest); }, - check); + (async () => { + await assert.rejects(fs.promises.copyFile(source, dest), check); + })(); } // Test callback API. From 934d0cb1d13faf5c4812792411e7df3c14fbb073 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Mon, 15 Apr 2019 11:28:16 -0400 Subject: [PATCH 2/4] deps: upgrade to libuv 1.28.0 Notable changes: - uv_gettimeofday() has been added. - Streaming readdir() via the uv_fs_{open,read,close}dir() methods. - A macOS copyfile() permissions bug has been fixed. - A bug in uv_interface_addresses() on machines with multiple interfaces has been fixed. Fixes: https://github.com/nodejs/node/issues/27273 PR-URL: https://github.com/nodejs/node/pull/27241 Reviewed-By: Richard Lau Reviewed-By: Ruben Bridgewater Reviewed-By: James M Snell Reviewed-By: Rich Trott Reviewed-By: Anna Henningsen Reviewed-By: Ben Noordhuis --- deps/uv/AUTHORS | 5 + deps/uv/CMakeLists.txt | 10 +- deps/uv/ChangeLog | 35 +++ deps/uv/Makefile.am | 11 +- deps/uv/configure.ac | 21 +- deps/uv/docs/src/fs.rst | 58 ++++ deps/uv/docs/src/misc.rst | 29 ++ deps/uv/include/uv.h | 32 ++- deps/uv/include/uv/unix.h | 3 + deps/uv/include/uv/version.h | 2 +- deps/uv/include/uv/win.h | 5 + deps/uv/src/unix/atomic-ops.h | 37 --- deps/uv/src/unix/bsd-ifaddrs.c | 11 +- deps/uv/src/unix/core.c | 15 + deps/uv/src/unix/fs.c | 180 +++++++++--- deps/uv/src/unix/linux-core.c | 5 +- deps/uv/src/unix/thread.c | 2 + deps/uv/src/unix/udp.c | 33 ++- deps/uv/src/uv-common.c | 54 +++- deps/uv/src/uv-common.h | 2 + deps/uv/src/win/fs.c | 175 ++++++++++++ deps/uv/src/win/util.c | 17 ++ deps/uv/test/test-fs-copyfile.c | 11 + deps/uv/test/test-fs-readdir.c | 462 +++++++++++++++++++++++++++++++ deps/uv/test/test-gettimeofday.c | 39 +++ deps/uv/test/test-list.h | 17 ++ deps/uv/test/test-udp-open.c | 52 ++++ deps/uv/test/test.gyp | 2 + 28 files changed, 1192 insertions(+), 133 deletions(-) create mode 100644 deps/uv/test/test-fs-readdir.c create mode 100644 deps/uv/test/test-gettimeofday.c diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS index 2c1d8ae68568d3..890e6b0d1a46be 100644 --- a/deps/uv/AUTHORS +++ b/deps/uv/AUTHORS @@ -371,3 +371,8 @@ yeyuanfeng erw7 Thomas Karl Pietrowski evgley +Andreas Rohner +Rich Trott +Milad Farazmand +zlargon +Yury Selivanov diff --git a/deps/uv/CMakeLists.txt b/deps/uv/CMakeLists.txt index 01a7c47e578452..7b25511939e62e 100644 --- a/deps/uv/CMakeLists.txt +++ b/deps/uv/CMakeLists.txt @@ -53,6 +53,7 @@ set(uv_test_sources test/test-fs-event.c test/test-fs-poll.c test/test-fs.c + test/test-fs-readdir.c test/test-get-currentexe.c test/test-get-loadavg.c test/test-get-memory.c @@ -62,6 +63,7 @@ set(uv_test_sources test/test-getnameinfo.c test/test-getsockname.c test/test-getters-setters.c + test/test-gettimeofday.c test/test-handle-fileno.c test/test-homedir.c test/test-hrtime.c @@ -262,7 +264,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Android") src/unix/sysinfo-memory.c) endif() -if(CMAKE_SYSTEM_NAME MATCHES "Android|Darwin|Linux|OS/390") +if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "Android|Linux|OS/390") list(APPEND uv_sources src/unix/proctitle.c) endif() @@ -275,11 +277,11 @@ if(CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD|NetBSD|OpenBSD") list(APPEND uv_libraries kvm) endif() -if(CMAKE_SYSTEM_NAME MATCHES "Darwin|DragonFly|FreeBSD|NetBSD|OpenBSD") +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 STREQUAL "Darwin") +if(APPLE) list(APPEND uv_defines _DARWIN_UNLIMITED_SELECT=1 _DARWIN_USE_64_BIT_INODE=1) list(APPEND uv_sources src/unix/darwin-proctitle.c @@ -333,7 +335,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "SunOS") list(APPEND uv_sources src/unix/no-proctitle.c src/unix/sunos.c) endif() -if(CMAKE_SYSTEM_NAME MATCHES "Darwin|DragonFly|FreeBSD|Linux|NetBSD|OpenBSD") +if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD|Linux|NetBSD|OpenBSD") list(APPEND uv_test_libraries util) endif() diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index 62d6073d7d4340..3095f9fc1029a2 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,3 +1,38 @@ +2019.04.16, Version 1.28.0 (Stable), 7bf8fabfa934660ee0fe889f78e151198a1165fc + +Changes since version 1.27.0: + +* unix,win: add uv_gettimeofday() (cjihrig) + +* unix,win: add uv_fs_{open,read,close}dir() (cjihrig) + +* unix: fix uv_interface_addresses() (Andreas Rohner) + +* fs: remove macOS-specific copyfile(3) (Rich Trott) + +* fs: add test for copyfile() respecting permissions (Rich Trott) + +* build: partially revert 5234b1c43a (Ben Noordhuis) + +* zos: fix setsockopt error when using AF_UNIX (Milad Farazmand) + +* unix: suppress EINTR/EINPROGRESS in uv_fs_close() (Ben Noordhuis) + +* build: use cmake APPLE variable to detect platform (zlargon) + +* distcheck: remove duplicate test/ entry (Jameson Nash) + +* unix: remove unused cmpxchgl() function (Ben Noordhuis) + +* unix: support sockaddr_un in uv_udp_send() (Yury Selivanov) + +* unix: guard use of PTHREAD_STACK_MIN (Kamil Rytarowski) + +* unix,win: introduce uv_timeval64_t (cjihrig) + +* doc: document uv_timeval_t and uv_timeval64_t (cjihrig) + + 2019.03.17, Version 1.27.0 (Stable), a4fc9a66cc35256dbc4dcd67c910174f05b6daa6 Changes since version 1.26.0: diff --git a/deps/uv/Makefile.am b/deps/uv/Makefile.am index 595a5aea03913d..22069625e328c4 100644 --- a/deps/uv/Makefile.am +++ b/deps/uv/Makefile.am @@ -45,12 +45,10 @@ libuv_la_SOURCES = src/fs-poll.c \ src/version.c if SUNOS -if GCC # Can't be turned into a CC_CHECK_CFLAGS in configure.ac, it makes compilers # on other platforms complain that the argument is unused during compilation. libuv_la_CFLAGS += -pthreads endif -endif if WINNT @@ -120,7 +118,6 @@ endif # WINNT EXTRA_DIST = test/fixtures/empty_file \ test/fixtures/load_error.node \ include \ - test \ docs \ img \ samples \ @@ -143,20 +140,14 @@ check_PROGRAMS = test/run-tests if OS390 test_run_tests_CFLAGS = else -if GCC test_run_tests_CFLAGS = -Wno-long-long -else -test_run_tests_CFLAGS = -endif endif if SUNOS -if GCC # Can't be turned into a CC_CHECK_CFLAGS in configure.ac, it makes compilers # on other platforms complain that the argument is unused during compilation. test_run_tests_CFLAGS += -pthreads endif -endif test_run_tests_LDFLAGS = test_run_tests_SOURCES = test/blackhole-server.c \ @@ -191,6 +182,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/test-fs-event.c \ test/test-fs-poll.c \ test/test-fs.c \ + test/test-fs-readdir.c \ test/test-fork.c \ test/test-getters-setters.c \ test/test-get-currentexe.c \ @@ -201,6 +193,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/test-gethostname.c \ test/test-getnameinfo.c \ test/test-getsockname.c \ + test/test-gettimeofday.c \ test/test-handle-fileno.c \ test/test-homedir.c \ test/test-hrtime.c \ diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac index 336e55b15f92d6..75275aa8785f43 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.27.0], [https://github.com/libuv/libuv/issues]) +AC_INIT([libuv], [1.28.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]) @@ -24,18 +24,16 @@ 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]) -AS_IF([test "x$GCC" = xyes], [ - AS_IF([AS_CASE([$host_os], [openedition*], [false], [true])], [ - CC_CHECK_CFLAGS_APPEND([-pedantic]) - ]) - CC_CHECK_CFLAGS_APPEND([-std=gnu89]) - CC_CHECK_CFLAGS_APPEND([-Wall]) - CC_CHECK_CFLAGS_APPEND([-Wextra]) - CC_CHECK_CFLAGS_APPEND([-Wno-unused-parameter]) - CC_CHECK_CFLAGS_APPEND([-Wstrict-prototypes]) -]) +CC_CHECK_CFLAGS_APPEND([-std=gnu89]) +CC_CHECK_CFLAGS_APPEND([-Wall]) +CC_CHECK_CFLAGS_APPEND([-Wextra]) +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. m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) # autoconf complains if AC_PROG_LIBTOOL precedes AM_PROG_AR. @@ -52,7 +50,6 @@ AC_CHECK_LIB([rt], [clock_gettime]) AC_CHECK_LIB([sendfile], [sendfile]) AC_CHECK_LIB([socket], [socket]) AC_SYS_LARGEFILE -AM_CONDITIONAL([GCC], [AS_IF([test "x$GCC" = xyes], [true], [false])]) AM_CONDITIONAL([AIX], [AS_CASE([$host_os],[aix*], [true], [false])]) AM_CONDITIONAL([ANDROID], [AS_CASE([$host_os],[linux-android*],[true], [false])]) AM_CONDITIONAL([CYGWIN], [AS_CASE([$host_os],[cygwin*], [true], [false])]) diff --git a/deps/uv/docs/src/fs.rst b/deps/uv/docs/src/fs.rst index af97ec3a648882..177db5708426dc 100644 --- a/deps/uv/docs/src/fs.rst +++ b/deps/uv/docs/src/fs.rst @@ -122,6 +122,21 @@ Data types uv_dirent_type_t type; } uv_dirent_t; +.. c:type:: uv_dir_t + + Data type used for streaming directory iteration. + Used by :c:func:`uv_fs_opendir()`, :c:func:`uv_fs_readdir()`, and + :c:func:`uv_fs_closedir()`. `dirents` represents a user provided array of + `uv_dirent_t`s used to hold results. `nentries` is the user provided maximum + array size of `dirents`. + + :: + + typedef struct uv_dir_s { + uv_dirent_t* dirents; + size_t nentries; + } uv_dir_t; + Public members ^^^^^^^^^^^^^^ @@ -208,6 +223,49 @@ API Equivalent to :man:`rmdir(2)`. +.. c:function:: int uv_fs_opendir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) + + Opens `path` as a directory stream. On success, a `uv_dir_t` is allocated + and returned via `req->ptr`. This memory is not freed by + `uv_fs_req_cleanup()`, although `req->ptr` is set to `NULL`. The allocated + memory must be freed by calling `uv_fs_closedir()`. On failure, no memory + is allocated. + + The contents of the directory can be iterated over by passing the resulting + `uv_dir_t` to `uv_fs_readdir()`. + + .. versionadded:: 1.28.0 + +.. c:function:: int uv_fs_closedir(uv_loop_t* loop, uv_fs_t* req, uv_dir_t* dir, uv_fs_cb cb) + + Closes the directory stream represented by `dir` and frees the memory + allocated by `uv_fs_opendir()`. + + .. versionadded:: 1.28.0 + +.. c:function:: int uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, uv_dir_t* dir, uv_fs_cb cb) + + Iterates over the directory stream, `dir`, returned by a successful + `uv_fs_opendir()` call. Prior to invoking `uv_fs_readdir()`, the caller + must set `dir->dirents` and `dir->nentries`, representing the array of + :c:type:`uv_dirent_t` elements used to hold the read directory entries and + its size. + + On success, the result is an integer >= 0 representing the number of entries + read from the stream. + + .. versionadded:: 1.28.0 + + .. warning:: + `uv_fs_readdir()` is not thread safe. + + .. note:: + This function does not return the "." and ".." entries. + + .. note:: + On success this function allocates memory that must be freed using + `uv_fs_req_cleanup()`. + .. 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) diff --git a/deps/uv/docs/src/misc.rst b/deps/uv/docs/src/misc.rst index 14e9acce9abb2b..4ad4e40af9f7be 100644 --- a/deps/uv/docs/src/misc.rst +++ b/deps/uv/docs/src/misc.rst @@ -65,6 +65,28 @@ Data types .. versionadded:: 1.16.0 +.. c:type:: uv_timeval_t + + Data type for storing times. + + :: + + typedef struct { + long tv_sec; + long tv_usec; + } uv_timeval_t; + +.. c:type:: uv_timeval64_t + + Alternative data type for storing times. + + :: + + typedef struct { + int64_t tv_sec; + int32_t tv_usec; + } uv_timeval64_t; + .. c:type:: uv_rusage_t Data type for resource usage results. @@ -578,3 +600,10 @@ API zero on success, and a non-zero error value otherwise. .. versionadded:: 1.25.0 + +.. c:function:: int uv_gettimeofday(uv_timeval64_t* tv) + + Cross-platform implementation of :man:`gettimeofday(2)`. The timezone + argument to `gettimeofday()` is not supported, as it is considered obsolete. + + .. versionadded:: 1.28.0 diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index 43895ac80dd670..df15b836789070 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -202,6 +202,7 @@ typedef enum { /* Handle types. */ typedef struct uv_loop_s uv_loop_t; typedef struct uv_handle_s uv_handle_t; +typedef struct uv_dir_s uv_dir_t; typedef struct uv_stream_s uv_stream_t; typedef struct uv_tcp_s uv_tcp_t; typedef struct uv_udp_s uv_udp_t; @@ -1098,6 +1099,11 @@ typedef struct { long tv_usec; } uv_timeval_t; +typedef struct { + int64_t tv_sec; + int32_t tv_usec; +} uv_timeval64_t; + typedef struct { uv_timeval_t ru_utime; /* user CPU time used */ uv_timeval_t ru_stime; /* system CPU time used */ @@ -1196,9 +1202,19 @@ typedef enum { 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; +struct uv_dir_s { + uv_dirent_t* dirents; + size_t nentries; + void* reserved[4]; + UV_DIR_PRIVATE_FIELDS +}; + /* uv_fs_t is a subclass of uv_req_t. */ struct uv_fs_s { UV_REQ_FIELDS @@ -1291,6 +1307,18 @@ UV_EXTERN int uv_fs_scandir(uv_loop_t* loop, uv_fs_cb cb); UV_EXTERN int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent); +UV_EXTERN int uv_fs_opendir(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + uv_fs_cb cb); +UV_EXTERN int uv_fs_readdir(uv_loop_t* loop, + uv_fs_t* req, + uv_dir_t* dir, + uv_fs_cb cb); +UV_EXTERN int uv_fs_closedir(uv_loop_t* loop, + uv_fs_t* req, + uv_dir_t* dir, + uv_fs_cb cb); UV_EXTERN int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, @@ -1586,6 +1614,8 @@ UV_EXTERN void uv_key_delete(uv_key_t* key); UV_EXTERN void* uv_key_get(uv_key_t* key); UV_EXTERN void uv_key_set(uv_key_t* key, void* value); +UV_EXTERN int uv_gettimeofday(uv_timeval64_t* tv); + typedef void (*uv_thread_cb)(void* arg); UV_EXTERN int uv_thread_create(uv_thread_t* tid, uv_thread_cb entry, void* arg); diff --git a/deps/uv/include/uv/unix.h b/deps/uv/include/uv/unix.h index 2363701b414728..26df0ec17a3069 100644 --- a/deps/uv/include/uv/unix.h +++ b/deps/uv/include/uv/unix.h @@ -166,6 +166,9 @@ typedef uid_t uv_uid_t; typedef struct dirent uv__dirent_t; +#define UV_DIR_PRIVATE_FIELDS \ + DIR* dir; + #if defined(DT_UNKNOWN) # define HAVE_DIRENT_TYPES # if defined(DT_REG) diff --git a/deps/uv/include/uv/version.h b/deps/uv/include/uv/version.h index 4f653983075150..fcb813b3121815 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 27 +#define UV_VERSION_MINOR 28 #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 edd2cc6eb9cd3f..acbd958be4cd47 100644 --- a/deps/uv/include/uv/win.h +++ b/deps/uv/include/uv/win.h @@ -301,6 +301,11 @@ typedef struct uv__dirent_s { char d_name[1]; } uv__dirent_t; +#define UV_DIR_PRIVATE_FIELDS \ + HANDLE dir_handle; \ + WIN32_FIND_DATAW find_data; \ + BOOL need_find_call; + #define HAVE_DIRENT_TYPES #define UV__DT_DIR UV_DIRENT_DIR #define UV__DT_FILE UV_DIRENT_FILE diff --git a/deps/uv/src/unix/atomic-ops.h b/deps/uv/src/unix/atomic-ops.h index fb46978859813d..541a6c864882a0 100644 --- a/deps/uv/src/unix/atomic-ops.h +++ b/deps/uv/src/unix/atomic-ops.h @@ -23,7 +23,6 @@ #endif UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)); -UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)); UV_UNUSED(static void cpu_relax(void)); /* Prefer hand-rolled assembly over the gcc builtins because the latter also @@ -55,42 +54,6 @@ UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) { #endif } -UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)) { -#if defined(__i386__) || defined(__x86_64__) - long out; - __asm__ __volatile__ ("lock; cmpxchg %2, %1;" - : "=a" (out), "+m" (*(volatile long*) ptr) - : "r" (newval), "0" (oldval) - : "memory"); - return out; -#elif defined(_AIX) && defined(__xlC__) - const long out = (*(volatile int*) ptr); -# if defined(__64BIT__) - __compare_and_swaplp(ptr, &oldval, newval); -# else - __compare_and_swap(ptr, &oldval, newval); -# endif /* if defined(__64BIT__) */ - return out; -#elif defined (__MVS__) -#ifdef _LP64 - unsigned long long op4; - if (__plo_CSSTGR(ptr, (unsigned long long*) &oldval, newval, - (unsigned long long*) ptr, *ptr, &op4)) -#else - unsigned long op4; - if (__plo_CSST(ptr, (unsigned int*) &oldval, newval, - (unsigned int*) ptr, *ptr, &op4)) -#endif - return oldval; - else - return op4; -#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) - return atomic_cas_ulong((ulong_t *)ptr, (ulong_t)oldval, (ulong_t)newval); -#else - return __sync_val_compare_and_swap(ptr, oldval, newval); -#endif -} - UV_UNUSED(static void cpu_relax(void)) { #if defined(__i386__) || defined(__x86_64__) __asm__ __volatile__ ("rep; nop"); /* a.k.a. PAUSE */ diff --git a/deps/uv/src/unix/bsd-ifaddrs.c b/deps/uv/src/unix/bsd-ifaddrs.c index 3c2253f0c9c952..a4c6bf9d11c7f4 100644 --- a/deps/uv/src/unix/bsd-ifaddrs.c +++ b/deps/uv/src/unix/bsd-ifaddrs.c @@ -84,7 +84,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { return 0; } - *addresses = uv__malloc(*count * sizeof(**addresses)); + /* Make sure the memory is initiallized to zero using calloc() */ + *addresses = uv__calloc(*count, sizeof(**addresses)); if (*addresses == NULL) { freeifaddrs(addrs); @@ -116,6 +117,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { address++; } +#if !(defined(__CYGWIN__) || defined(__MSYS__)) /* Fill in physical addresses for each interface */ for (ent = addrs; ent != NULL; ent = ent->ifa_next) { if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFPHYS)) @@ -124,20 +126,15 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { address = *addresses; for (i = 0; i < *count; i++) { -#if defined(__CYGWIN__) || defined(__MSYS__) - memset(address->phys_addr, 0, sizeof(address->phys_addr)); -#else if (strcmp(address->name, ent->ifa_name) == 0) { struct sockaddr_dl* sa_addr; sa_addr = (struct sockaddr_dl*)(ent->ifa_addr); memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); - } else { - memset(address->phys_addr, 0, sizeof(address->phys_addr)); } -#endif address++; } } +#endif freeifaddrs(addrs); diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index ca0e345da05bc1..e7e9f4b8c10a72 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -41,6 +41,7 @@ #include /* getrusage */ #include #include +#include #ifdef __sun # include @@ -1429,3 +1430,17 @@ int uv__getsockpeername(const uv_handle_t* handle, *namelen = (int) socklen; return 0; } + +int uv_gettimeofday(uv_timeval64_t* tv) { + struct timeval time; + + if (tv == NULL) + return UV_EINVAL; + + if (gettimeofday(&time, NULL) != 0) + return UV__ERR(errno); + + tv->tv_sec = (int64_t) time.tv_sec; + tv->tv_usec = (int32_t) time.tv_usec; + return 0; +} diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c index f4b4280ca0c420..c6d2259adc4080 100644 --- a/deps/uv/src/unix/fs.c +++ b/deps/uv/src/unix/fs.c @@ -60,7 +60,6 @@ #endif #if defined(__APPLE__) -# include # include #elif defined(__linux__) && !defined(FICLONE) # include @@ -143,6 +142,18 @@ extern char *mkdtemp(char *template); /* See issue #740 on AIX < 7 */ while (0) +static int uv__fs_close(int fd) { + int rc; + + rc = close(fd); + if (rc == -1) + if (errno == EINTR || errno == EINPROGRESS) + rc = 0; /* The close is in progress, not an error. */ + + return rc; +} + + static ssize_t uv__fs_fsync(uv_fs_t* req) { #if defined(__APPLE__) /* Apple's fdatasync and fsync explicitly do NOT flush the drive write cache @@ -351,7 +362,7 @@ static int uv__fs_scandir_sort(UV_CONST_DIRENT** a, UV_CONST_DIRENT** b) { static ssize_t uv__fs_scandir(uv_fs_t* req) { - uv__dirent_t **dents; + uv__dirent_t** dents; int n; dents = NULL; @@ -375,6 +386,87 @@ static ssize_t uv__fs_scandir(uv_fs_t* req) { return n; } +static int uv__fs_opendir(uv_fs_t* req) { + uv_dir_t* dir; + + dir = uv__malloc(sizeof(*dir)); + if (dir == NULL) + goto error; + + dir->dir = opendir(req->path); + if (dir->dir == NULL) + goto error; + + req->ptr = dir; + return 0; + +error: + uv__free(dir); + req->ptr = NULL; + return -1; +} + +static int uv__fs_readdir(uv_fs_t* req) { + uv_dir_t* dir; + uv_dirent_t* dirent; + struct dirent* res; + unsigned int dirent_idx; + unsigned int i; + + dir = req->ptr; + dirent_idx = 0; + + while (dirent_idx < dir->nentries) { + /* readdir() returns NULL on end of directory, as well as on error. errno + is used to differentiate between the two conditions. */ + errno = 0; + res = readdir(dir->dir); + + if (res == NULL) { + if (errno != 0) + goto error; + break; + } + + if (strcmp(res->d_name, ".") == 0 || strcmp(res->d_name, "..") == 0) + continue; + + dirent = &dir->dirents[dirent_idx]; + dirent->name = uv__strdup(res->d_name); + + if (dirent->name == NULL) + goto error; + + dirent->type = uv__fs_get_dirent_type(res); + ++dirent_idx; + } + + return dirent_idx; + +error: + for (i = 0; i < dirent_idx; ++i) { + uv__free((char*) dir->dirents[i].name); + dir->dirents[i].name = NULL; + } + + return -1; +} + +static int uv__fs_closedir(uv_fs_t* req) { + uv_dir_t* dir; + + dir = req->ptr; + + if (dir->dir != NULL) { + closedir(dir->dir); + dir->dir = NULL; + } + + uv__free(req->ptr); + req->ptr = NULL; + return 0; +} + #if defined(_POSIX_PATH_MAX) # define UV__FS_PATH_MAX _POSIX_PATH_MAX #elif defined(PATH_MAX) @@ -808,45 +900,6 @@ static ssize_t uv__fs_write(uv_fs_t* req) { } static ssize_t uv__fs_copyfile(uv_fs_t* req) { -#if defined(__APPLE__) && !TARGET_OS_IPHONE - /* On macOS, use the native copyfile(3). */ - static int can_clone; - copyfile_flags_t flags; - char buf[64]; - size_t len; - int major; - - flags = COPYFILE_ALL; - - if (req->flags & UV_FS_COPYFILE_EXCL) - flags |= COPYFILE_EXCL; - - /* Check OS version. Cloning is only supported on macOS >= 10.12. */ - if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) { - if (can_clone == 0) { - len = sizeof(buf); - if (sysctlbyname("kern.osrelease", buf, &len, NULL, 0)) - return UV__ERR(errno); - - if (1 != sscanf(buf, "%d", &major)) - abort(); - - can_clone = -1 + 2 * (major >= 16); /* macOS >= 10.12 */ - } - - if (can_clone < 0) - return UV_ENOSYS; - } - - /* copyfile() simply ignores COPYFILE_CLONE if it's not supported. */ - if (req->flags & UV_FS_COPYFILE_FICLONE) - flags |= 1 << 24; /* COPYFILE_CLONE */ - - if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) - flags |= 1 << 25; /* COPYFILE_CLONE_FORCE */ - - return copyfile(req->path, req->new_path, NULL, flags); -#else uv_fs_t fs_req; uv_file srcfd; uv_file dstfd; @@ -973,7 +1026,6 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) { errno = UV__ERR(result); return -1; -#endif } static void uv__to_stat(struct stat* src, uv_stat_t* dst) { @@ -1249,7 +1301,7 @@ static void uv__fs_work(struct uv__work* w) { X(ACCESS, access(req->path, req->flags)); X(CHMOD, chmod(req->path, req->mode)); X(CHOWN, chown(req->path, req->uid, req->gid)); - X(CLOSE, close(req->file)); + X(CLOSE, uv__fs_close(req->file)); X(COPYFILE, uv__fs_copyfile(req)); X(FCHMOD, fchmod(req->file, req->mode)); X(FCHOWN, fchown(req->file, req->uid, req->gid)); @@ -1266,6 +1318,9 @@ static void uv__fs_work(struct uv__work* w) { X(OPEN, uv__fs_open(req)); X(READ, uv__fs_read(req)); X(SCANDIR, uv__fs_scandir(req)); + X(OPENDIR, uv__fs_opendir(req)); + X(READDIR, uv__fs_readdir(req)); + X(CLOSEDIR, uv__fs_closedir(req)); X(READLINK, uv__fs_readlink(req)); X(REALPATH, uv__fs_realpath(req)); X(RENAME, rename(req->path, req->new_path)); @@ -1536,6 +1591,40 @@ int uv_fs_scandir(uv_loop_t* loop, POST; } +int uv_fs_opendir(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + uv_fs_cb cb) { + INIT(OPENDIR); + PATH; + POST; +} + +int uv_fs_readdir(uv_loop_t* loop, + uv_fs_t* req, + uv_dir_t* dir, + uv_fs_cb cb) { + INIT(READDIR); + + if (dir == NULL || dir->dir == NULL || dir->dirents == NULL) + return UV_EINVAL; + + req->ptr = dir; + POST; +} + +int uv_fs_closedir(uv_loop_t* loop, + uv_fs_t* req, + uv_dir_t* dir, + uv_fs_cb cb) { + INIT(CLOSEDIR); + + if (dir == NULL) + return UV_EINVAL; + + req->ptr = dir; + POST; +} int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, @@ -1676,6 +1765,9 @@ void uv_fs_req_cleanup(uv_fs_t* req) { req->path = NULL; req->new_path = NULL; + if (req->fs_type == UV_FS_READDIR && req->ptr != NULL) + uv__fs_readdir_cleanup(req); + if (req->fs_type == UV_FS_SCANDIR && req->ptr != NULL) uv__fs_scandir_cleanup(req); @@ -1683,7 +1775,7 @@ void uv_fs_req_cleanup(uv_fs_t* req) { uv__free(req->bufs); req->bufs = NULL; - if (req->ptr != &req->statbuf) + if (req->fs_type != UV_FS_OPENDIR && req->ptr != &req->statbuf) uv__free(req->ptr); req->ptr = NULL; } diff --git a/deps/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c index 7165fe2fb4dd1b..f8973bb36be7ae 100644 --- a/deps/uv/src/unix/linux-core.c +++ b/deps/uv/src/unix/linux-core.c @@ -860,7 +860,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { return 0; } - *addresses = uv__malloc(*count * sizeof(**addresses)); + /* Make sure the memory is initiallized to zero using calloc() */ + *addresses = uv__calloc(*count, sizeof(**addresses)); if (!(*addresses)) { freeifaddrs(addrs); return UV_ENOMEM; @@ -902,8 +903,6 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { if (strcmp(address->name, ent->ifa_name) == 0) { sll = (struct sockaddr_ll*)ent->ifa_addr; memcpy(address->phys_addr, sll->sll_addr, sizeof(address->phys_addr)); - } else { - memset(address->phys_addr, 0, sizeof(address->phys_addr)); } address++; } diff --git a/deps/uv/src/unix/thread.c b/deps/uv/src/unix/thread.c index 6088c77f712a95..9a50448e62ce58 100644 --- a/deps/uv/src/unix/thread.c +++ b/deps/uv/src/unix/thread.c @@ -219,8 +219,10 @@ int uv_thread_create_ex(uv_thread_t* tid, pagesize = (size_t)getpagesize(); /* Round up to the nearest page boundary. */ stack_size = (stack_size + pagesize - 1) &~ (pagesize - 1); +#ifdef PTHREAD_STACK_MIN if (stack_size < PTHREAD_STACK_MIN) stack_size = PTHREAD_STACK_MIN; +#endif } if (stack_size > 0) { diff --git a/deps/uv/src/unix/udp.c b/deps/uv/src/unix/udp.c index 15fa5937b3e712..b578e7bc1037ef 100644 --- a/deps/uv/src/unix/udp.c +++ b/deps/uv/src/unix/udp.c @@ -30,6 +30,7 @@ #if defined(__MVS__) #include #endif +#include #if defined(IPV6_JOIN_GROUP) && !defined(IPV6_ADD_MEMBERSHIP) # define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP @@ -232,8 +233,16 @@ static void uv__udp_sendmsg(uv_udp_t* handle) { h.msg_namelen = 0; } else { h.msg_name = &req->addr; - h.msg_namelen = req->addr.ss_family == AF_INET6 ? - sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in); + if (req->addr.ss_family == AF_INET6) + h.msg_namelen = sizeof(struct sockaddr_in6); + else if (req->addr.ss_family == AF_INET) + h.msg_namelen = sizeof(struct sockaddr_in); + else if (req->addr.ss_family == AF_UNIX) + h.msg_namelen = sizeof(struct sockaddr_un); + else { + assert(0 && "unsupported address family"); + abort(); + } } h.msg_iov = (struct iovec*) req->bufs; h.msg_iovlen = req->nbufs; @@ -268,16 +277,30 @@ static void uv__udp_sendmsg(uv_udp_t* handle) { * are different from the BSDs: it _shares_ the port rather than steal it * from the current listener. While useful, it's not something we can emulate * on other platforms so we don't enable it. + * + * zOS does not support getsockname with SO_REUSEPORT option when using + * AF_UNIX. */ static int uv__set_reuse(int fd) { int yes; - -#if defined(SO_REUSEPORT) && !defined(__linux__) yes = 1; + +#if defined(SO_REUSEPORT) && defined(__MVS__) + struct sockaddr_in sockfd; + unsigned int sockfd_len = sizeof(sockfd); + if (getsockname(fd, (struct sockaddr*) &sockfd, &sockfd_len) == -1) + return UV__ERR(errno); + if (sockfd.sin_family == AF_UNIX) { + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes))) + return UV__ERR(errno); + } else { + if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes))) + return UV__ERR(errno); + } +#elif defined(SO_REUSEPORT) && !defined(__linux__) if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes))) return UV__ERR(errno); #else - yes = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes))) return UV__ERR(errno); #endif diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c index 94dd59fb071ca0..066eb31d03892d 100644 --- a/deps/uv/src/uv-common.c +++ b/deps/uv/src/uv-common.c @@ -34,6 +34,7 @@ # include /* malloc */ #else # include /* if_nametoindex */ +# include /* AF_UNIX, sockaddr_un */ #endif @@ -376,6 +377,10 @@ int uv__udp_check_before_send(uv_udp_t* handle, const struct sockaddr* addr) { addrlen = sizeof(struct sockaddr_in); else if (addr->sa_family == AF_INET6) addrlen = sizeof(struct sockaddr_in6); +#if defined(AF_UNIX) && !defined(_WIN32) + else if (addr->sa_family == AF_UNIX) + addrlen = sizeof(struct sockaddr_un); +#endif else return UV_EINVAL; } else { @@ -631,37 +636,66 @@ int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) { dent = dents[(*nbufs)++]; ent->name = dent->d_name; + ent->type = uv__fs_get_dirent_type(dent); + + return 0; +} + +uv_dirent_type_t uv__fs_get_dirent_type(uv__dirent_t* dent) { + uv_dirent_type_t type; + #ifdef HAVE_DIRENT_TYPES switch (dent->d_type) { case UV__DT_DIR: - ent->type = UV_DIRENT_DIR; + type = UV_DIRENT_DIR; break; case UV__DT_FILE: - ent->type = UV_DIRENT_FILE; + type = UV_DIRENT_FILE; break; case UV__DT_LINK: - ent->type = UV_DIRENT_LINK; + type = UV_DIRENT_LINK; break; case UV__DT_FIFO: - ent->type = UV_DIRENT_FIFO; + type = UV_DIRENT_FIFO; break; case UV__DT_SOCKET: - ent->type = UV_DIRENT_SOCKET; + type = UV_DIRENT_SOCKET; break; case UV__DT_CHAR: - ent->type = UV_DIRENT_CHAR; + type = UV_DIRENT_CHAR; break; case UV__DT_BLOCK: - ent->type = UV_DIRENT_BLOCK; + type = UV_DIRENT_BLOCK; break; default: - ent->type = UV_DIRENT_UNKNOWN; + type = UV_DIRENT_UNKNOWN; } #else - ent->type = UV_DIRENT_UNKNOWN; + type = UV_DIRENT_UNKNOWN; #endif - return 0; + return type; +} + +void uv__fs_readdir_cleanup(uv_fs_t* req) { + uv_dir_t* dir; + uv_dirent_t* dirents; + int i; + + if (req->ptr == NULL) + return; + + dir = req->ptr; + dirents = dir->dirents; + req->ptr = NULL; + + if (dirents == NULL) + return; + + for (i = 0; i < req->result; ++i) { + uv__free((char*) dirents[i].name); + dirents[i].name = NULL; + } } diff --git a/deps/uv/src/uv-common.h b/deps/uv/src/uv-common.h index e09a57b2c24b41..f788161c3955ed 100644 --- a/deps/uv/src/uv-common.h +++ b/deps/uv/src/uv-common.h @@ -193,6 +193,8 @@ size_t uv__count_bufs(const uv_buf_t bufs[], unsigned int nbufs); int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value); void uv__fs_scandir_cleanup(uv_fs_t* req); +void uv__fs_readdir_cleanup(uv_fs_t* req); +uv_dirent_type_t uv__fs_get_dirent_type(uv__dirent_t* dent); int uv__next_timeout(const uv_loop_t* loop); void uv__run_timers(uv_loop_t* loop); diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c index 65d936bf08f555..9e2f084c8d0e9c 100644 --- a/deps/uv/src/win/fs.c +++ b/deps/uv/src/win/fs.c @@ -1125,6 +1125,137 @@ void fs__scandir(uv_fs_t* req) { uv__free(dirents); } +void fs__opendir(uv_fs_t* req) { + WCHAR* pathw; + size_t len; + const WCHAR* fmt; + WCHAR* find_path; + uv_dir_t* dir; + + pathw = req->file.pathw; + dir = NULL; + find_path = NULL; + + /* Figure out whether path is a file or a directory. */ + if (!(GetFileAttributesW(pathw) & FILE_ATTRIBUTE_DIRECTORY)) { + SET_REQ_UV_ERROR(req, UV_ENOTDIR, ERROR_DIRECTORY); + goto error; + } + + dir = uv__malloc(sizeof(*dir)); + if (dir == NULL) { + SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY); + goto error; + } + + len = wcslen(pathw); + + if (len == 0) + fmt = L"./*"; + else if (IS_SLASH(pathw[len - 1])) + fmt = L"%s*"; + else + fmt = L"%s\\*"; + + find_path = uv__malloc(sizeof(WCHAR) * (len + 4)); + if (find_path == NULL) { + SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY); + goto error; + } + + _snwprintf(find_path, len + 3, fmt, pathw); + dir->dir_handle = FindFirstFileW(find_path, &dir->find_data); + uv__free(find_path); + find_path = NULL; + if (dir->dir_handle == INVALID_HANDLE_VALUE && + GetLastError() != ERROR_FILE_NOT_FOUND) { + SET_REQ_WIN32_ERROR(req, GetLastError()); + goto error; + } + + dir->need_find_call = FALSE; + req->ptr = dir; + SET_REQ_RESULT(req, 0); + return; + +error: + uv__free(dir); + uv__free(find_path); + req->ptr = NULL; +} + +void fs__readdir(uv_fs_t* req) { + uv_dir_t* dir; + uv_dirent_t* dirents; + uv__dirent_t dent; + unsigned int dirent_idx; + PWIN32_FIND_DATAW find_data; + unsigned int i; + int r; + + req->flags |= UV_FS_FREE_PTR; + dir = req->ptr; + dirents = dir->dirents; + memset(dirents, 0, dir->nentries * sizeof(*dir->dirents)); + find_data = &dir->find_data; + dirent_idx = 0; + + while (dirent_idx < dir->nentries) { + if (dir->need_find_call && FindNextFileW(dir->dir_handle, find_data) == 0) { + if (GetLastError() == ERROR_NO_MORE_FILES) + break; + goto error; + } + + /* Skip "." and ".." entries. */ + if (find_data->cFileName[0] == L'.' && + (find_data->cFileName[1] == L'\0' || + (find_data->cFileName[1] == L'.' && + find_data->cFileName[2] == L'\0'))) { + dir->need_find_call = TRUE; + continue; + } + + r = uv__convert_utf16_to_utf8((const WCHAR*) &find_data->cFileName, + -1, + (char**) &dirents[dirent_idx].name); + if (r != 0) + goto error; + + /* Copy file type. */ + if ((find_data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) + dent.d_type = UV__DT_DIR; + else if ((find_data->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) + dent.d_type = UV__DT_LINK; + else if ((find_data->dwFileAttributes & FILE_ATTRIBUTE_DEVICE) != 0) + dent.d_type = UV__DT_CHAR; + else + dent.d_type = UV__DT_FILE; + + dirents[dirent_idx].type = uv__fs_get_dirent_type(&dent); + dir->need_find_call = TRUE; + ++dirent_idx; + } + + SET_REQ_RESULT(req, dirent_idx); + return; + +error: + SET_REQ_WIN32_ERROR(req, GetLastError()); + for (i = 0; i < dirent_idx; ++i) { + uv__free((char*) dirents[i].name); + dirents[i].name = NULL; + } +} + +void fs__closedir(uv_fs_t* req) { + uv_dir_t* dir; + + dir = req->ptr; + FindClose(dir->dir_handle); + uv__free(req->ptr); + SET_REQ_RESULT(req, 0); +} INLINE static int fs__stat_handle(HANDLE handle, uv_stat_t* statbuf, int do_lstat) { @@ -2039,6 +2170,9 @@ static void uv__fs_work(struct uv__work* w) { XX(MKDTEMP, mkdtemp) XX(RENAME, rename) XX(SCANDIR, scandir) + XX(READDIR, readdir) + XX(OPENDIR, opendir) + XX(CLOSEDIR, closedir) XX(LINK, link) XX(SYMLINK, symlink) XX(READLINK, readlink) @@ -2080,6 +2214,8 @@ void uv_fs_req_cleanup(uv_fs_t* req) { if (req->flags & UV_FS_FREE_PTR) { if (req->fs_type == UV_FS_SCANDIR && req->ptr != NULL) uv__fs_scandir_cleanup(req); + else if (req->fs_type == UV_FS_READDIR) + uv__fs_readdir_cleanup(req); else uv__free(req->ptr); } @@ -2247,6 +2383,45 @@ int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, POST; } +int uv_fs_opendir(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + uv_fs_cb cb) { + int err; + + INIT(UV_FS_OPENDIR); + err = fs__capture_path(req, path, NULL, cb != NULL); + if (err) + return uv_translate_sys_error(err); + POST; +} + +int uv_fs_readdir(uv_loop_t* loop, + uv_fs_t* req, + uv_dir_t* dir, + uv_fs_cb cb) { + INIT(UV_FS_READDIR); + + if (dir == NULL || + dir->dirents == NULL || + dir->dir_handle == INVALID_HANDLE_VALUE) { + return UV_EINVAL; + } + + req->ptr = dir; + POST; +} + +int uv_fs_closedir(uv_loop_t* loop, + uv_fs_t* req, + uv_dir_t* dir, + uv_fs_cb cb) { + INIT(UV_FS_CLOSEDIR); + if (dir == NULL) + return UV_EINVAL; + req->ptr = dir; + POST; +} int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb) { diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c index 395d958c036958..2c10728427b64d 100644 --- a/deps/uv/src/win/util.c +++ b/deps/uv/src/win/util.c @@ -1778,3 +1778,20 @@ int uv_os_uname(uv_utsname_t* buffer) { buffer->machine[0] = '\0'; return r; } + +int uv_gettimeofday(uv_timeval64_t* tv) { + /* Based on https://doxygen.postgresql.org/gettimeofday_8c_source.html */ + const uint64_t epoch = (uint64_t) 116444736000000000ULL; + FILETIME file_time; + ULARGE_INTEGER ularge; + + if (tv == NULL) + return UV_EINVAL; + + GetSystemTimeAsFileTime(&file_time); + ularge.LowPart = file_time.dwLowDateTime; + ularge.HighPart = file_time.dwHighDateTime; + tv->tv_sec = (int64_t) ((ularge.QuadPart - epoch) / 10000000L); + tv->tv_usec = (int32_t) (((ularge.QuadPart - epoch) % 10000000L) / 10); + return 0; +} diff --git a/deps/uv/test/test-fs-copyfile.c b/deps/uv/test/test-fs-copyfile.c index 7b6511c93c9787..cd8a2ea7c07b08 100644 --- a/deps/uv/test/test-fs-copyfile.c +++ b/deps/uv/test/test-fs-copyfile.c @@ -185,6 +185,17 @@ TEST_IMPL(fs_copyfile) { if (r == 0) handle_result(&req); +#ifndef _WIN32 + /* Copying respects permissions/mode. */ + unlink(dst); + touch_file(dst, 0); + chmod(dst, S_IRUSR|S_IRGRP|S_IROTH); /* Sets file mode to 444 (read-only). */ + r = uv_fs_copyfile(NULL, &req, fixture, dst, 0, NULL); + ASSERT(req.result == UV_EACCES); + ASSERT(r == UV_EACCES); + uv_fs_req_cleanup(&req); +#endif + unlink(dst); /* Cleanup */ return 0; } diff --git a/deps/uv/test/test-fs-readdir.c b/deps/uv/test/test-fs-readdir.c new file mode 100644 index 00000000000000..a767f1fb885dcd --- /dev/null +++ b/deps/uv/test/test-fs-readdir.c @@ -0,0 +1,462 @@ +/* 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 + +static uv_fs_t opendir_req; +static uv_fs_t readdir_req; +static uv_fs_t closedir_req; + +static uv_dirent_t dirents[1]; + +static int empty_opendir_cb_count; +static int empty_closedir_cb_count; + +static void cleanup_test_files(void) { + uv_fs_t req; + + uv_fs_unlink(NULL, &req, "test_dir/file1", NULL); + uv_fs_req_cleanup(&req); + uv_fs_unlink(NULL, &req, "test_dir/file2", NULL); + uv_fs_req_cleanup(&req); + uv_fs_rmdir(NULL, &req, "test_dir/test_subdir", NULL); + uv_fs_req_cleanup(&req); + uv_fs_rmdir(NULL, &req, "test_dir", NULL); + uv_fs_req_cleanup(&req); +} + +static void empty_closedir_cb(uv_fs_t* req) { + ASSERT(req == &closedir_req); + ASSERT(req->fs_type == UV_FS_CLOSEDIR); + ASSERT(req->result == 0); + ++empty_closedir_cb_count; + uv_fs_req_cleanup(req); +} + +static void empty_readdir_cb(uv_fs_t* req) { + uv_dir_t* dir; + int r; + + ASSERT(req == &readdir_req); + ASSERT(req->fs_type == UV_FS_READDIR); + ASSERT(req->result == 0); + dir = req->ptr; + 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) { + uv_dir_t* dir; + int r; + + ASSERT(req == &opendir_req); + ASSERT(req->fs_type == UV_FS_OPENDIR); + ASSERT(req->result == 0); + ASSERT(req->ptr != NULL); + dir = req->ptr; + dir->dirents = dirents; + dir->nentries = ARRAY_SIZE(dirents); + r = uv_fs_readdir(uv_default_loop(), + &readdir_req, + dir, + empty_readdir_cb); + ASSERT(r == 0); + uv_fs_req_cleanup(req); + ++empty_opendir_cb_count; +} + +/* + * This test makes sure that both synchronous and asynchronous flavors + * of the uv_fs_opendir() -> uv_fs_readdir() -> uv_fs_closedir() sequence work + * as expected when processing an empty directory. + */ +TEST_IMPL(fs_readdir_empty_dir) { + const char* path; + uv_fs_t mkdir_req; + uv_fs_t rmdir_req; + int r; + int nb_entries_read; + uv_dir_t* dir; + + path = "./empty_dir/"; + uv_fs_mkdir(uv_default_loop(), &mkdir_req, path, 0777, NULL); + uv_fs_req_cleanup(&mkdir_req); + + /* Fill the req to ensure that required fields are cleaned up. */ + memset(&opendir_req, 0xdb, sizeof(opendir_req)); + + /* Testing the synchronous flavor. */ + r = uv_fs_opendir(uv_default_loop(), + &opendir_req, + path, + NULL); + ASSERT(r == 0); + ASSERT(opendir_req.fs_type == UV_FS_OPENDIR); + ASSERT(opendir_req.result == 0); + ASSERT(opendir_req.ptr != NULL); + dir = opendir_req.ptr; + uv_fs_req_cleanup(&opendir_req); + + /* Fill the req to ensure that required fields are cleaned up. */ + memset(&readdir_req, 0xdb, sizeof(readdir_req)); + dir->dirents = dirents; + dir->nentries = ARRAY_SIZE(dirents); + nb_entries_read = uv_fs_readdir(uv_default_loop(), + &readdir_req, + dir, + NULL); + ASSERT(nb_entries_read == 0); + uv_fs_req_cleanup(&readdir_req); + + /* Fill the req to ensure that required fields are cleaned up. */ + memset(&closedir_req, 0xdb, sizeof(closedir_req)); + uv_fs_closedir(uv_default_loop(), &closedir_req, dir, NULL); + ASSERT(closedir_req.result == 0); + uv_fs_req_cleanup(&closedir_req); + + /* Testing the asynchronous flavor. */ + + /* Fill the req to ensure that required fields are cleaned up. */ + memset(&opendir_req, 0xdb, sizeof(opendir_req)); + memset(&readdir_req, 0xdb, sizeof(readdir_req)); + memset(&closedir_req, 0xdb, sizeof(closedir_req)); + + r = uv_fs_opendir(uv_default_loop(), &opendir_req, path, empty_opendir_cb); + ASSERT(r == 0); + ASSERT(empty_opendir_cb_count == 0); + ASSERT(empty_closedir_cb_count == 0); + r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); + ASSERT(r == 0); + ASSERT(empty_opendir_cb_count == 1); + ASSERT(empty_closedir_cb_count == 1); + uv_fs_rmdir(uv_default_loop(), &rmdir_req, path, NULL); + uv_fs_req_cleanup(&rmdir_req); + MAKE_VALGRIND_HAPPY(); + return 0; +} + +/* + * This test makes sure that reading a non-existing directory with + * uv_fs_{open,read}_dir() returns proper error codes. + */ + +static int non_existing_opendir_cb_count; + +static void non_existing_opendir_cb(uv_fs_t* req) { + ASSERT(req == &opendir_req); + ASSERT(req->fs_type == UV_FS_OPENDIR); + ASSERT(req->result == UV_ENOENT); + ASSERT(req->ptr == NULL); + + uv_fs_req_cleanup(req); + ++non_existing_opendir_cb_count; +} + +TEST_IMPL(fs_readdir_non_existing_dir) { + const char* path; + int r; + + path = "./non-existing-dir/"; + + /* Fill the req to ensure that required fields are cleaned up. */ + memset(&opendir_req, 0xdb, sizeof(opendir_req)); + + /* Testing the synchronous flavor. */ + r = uv_fs_opendir(uv_default_loop(), &opendir_req, path, NULL); + ASSERT(r == UV_ENOENT); + ASSERT(opendir_req.fs_type == UV_FS_OPENDIR); + ASSERT(opendir_req.result == UV_ENOENT); + ASSERT(opendir_req.ptr == NULL); + uv_fs_req_cleanup(&opendir_req); + + /* Fill the req to ensure that required fields are cleaned up. */ + memset(&opendir_req, 0xdb, sizeof(opendir_req)); + + /* Testing the async flavor. */ + r = uv_fs_opendir(uv_default_loop(), + &opendir_req, + path, + non_existing_opendir_cb); + ASSERT(r == 0); + ASSERT(non_existing_opendir_cb_count == 0); + r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); + ASSERT(r == 0); + ASSERT(non_existing_opendir_cb_count == 1); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + +/* + * This test makes sure that reading a file as a directory reports correct + * error codes. + */ + +static int file_opendir_cb_count; + +static void file_opendir_cb(uv_fs_t* req) { + ASSERT(req == &opendir_req); + ASSERT(req->fs_type == UV_FS_OPENDIR); + ASSERT(req->result == UV_ENOTDIR); + ASSERT(req->ptr == NULL); + + uv_fs_req_cleanup(req); + ++file_opendir_cb_count; +} + +TEST_IMPL(fs_readdir_file) { + const char* path; + int r; + + path = "test/fixtures/empty_file"; + + /* Fill the req to ensure that required fields are cleaned up. */ + memset(&opendir_req, 0xdb, sizeof(opendir_req)); + + /* Testing the synchronous flavor. */ + r = uv_fs_opendir(uv_default_loop(), &opendir_req, path, NULL); + + ASSERT(r == UV_ENOTDIR); + ASSERT(opendir_req.fs_type == UV_FS_OPENDIR); + ASSERT(opendir_req.result == UV_ENOTDIR); + ASSERT(opendir_req.ptr == NULL); + + uv_fs_req_cleanup(&opendir_req); + + /* Fill the req to ensure that required fields are cleaned up. */ + memset(&opendir_req, 0xdb, sizeof(opendir_req)); + + /* Testing the async flavor. */ + r = uv_fs_opendir(uv_default_loop(), &opendir_req, path, file_opendir_cb); + ASSERT(r == 0); + ASSERT(file_opendir_cb_count == 0); + r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); + ASSERT(r == 0); + ASSERT(file_opendir_cb_count == 1); + MAKE_VALGRIND_HAPPY(); + return 0; +} + +/* + * This test makes sure that reading a non-empty directory with + * uv_fs_{open,read}_dir() returns proper directory entries, including the + * correct entry types. + */ + +static int non_empty_opendir_cb_count; +static int non_empty_readdir_cb_count; +static int non_empty_closedir_cb_count; + +static void non_empty_closedir_cb(uv_fs_t* req) { + ASSERT(req == &closedir_req); + ASSERT(req->result == 0); + uv_fs_req_cleanup(req); + ++non_empty_closedir_cb_count; +} + +static void non_empty_readdir_cb(uv_fs_t* req) { + uv_dir_t* dir; + + ASSERT(req == &readdir_req); + ASSERT(req->fs_type == UV_FS_READDIR); + dir = req->ptr; + + if (req->result == 0) { + uv_fs_req_cleanup(req); + ASSERT(non_empty_readdir_cb_count == 3); + uv_fs_closedir(uv_default_loop(), + &closedir_req, + dir, + non_empty_closedir_cb); + } else { + ASSERT(req->result == 1); + ASSERT(dir->dirents == dirents); + ASSERT(strcmp(dirents[0].name, "file1") == 0 || + strcmp(dirents[0].name, "file2") == 0 || + strcmp(dirents[0].name, "test_subdir") == 0); +#ifdef HAVE_DIRENT_TYPES + if (!strcmp(dirents[0].name, "test_subdir")) + ASSERT(dirents[0].type == UV_DIRENT_DIR); + else + ASSERT(dirents[0].type == UV_DIRENT_FILE); +#else + ASSERT(dirents[0].type == UV_DIRENT_UNKNOWN); +#endif /* HAVE_DIRENT_TYPES */ + + ++non_empty_readdir_cb_count; + uv_fs_req_cleanup(req); + dir->dirents = dirents; + dir->nentries = ARRAY_SIZE(dirents); + uv_fs_readdir(uv_default_loop(), + &readdir_req, + dir, + non_empty_readdir_cb); + } +} + +static void non_empty_opendir_cb(uv_fs_t* req) { + uv_dir_t* dir; + int r; + + ASSERT(req == &opendir_req); + ASSERT(req->fs_type == UV_FS_OPENDIR); + ASSERT(req->result == 0); + ASSERT(req->ptr != NULL); + + dir = req->ptr; + dir->dirents = dirents; + dir->nentries = ARRAY_SIZE(dirents); + + r = uv_fs_readdir(uv_default_loop(), + &readdir_req, + dir, + non_empty_readdir_cb); + ASSERT(r == 0); + uv_fs_req_cleanup(req); + ++non_empty_opendir_cb_count; +} + +TEST_IMPL(fs_readdir_non_empty_dir) { + size_t entries_count; + uv_fs_t mkdir_req; + uv_fs_t rmdir_req; + uv_fs_t create_req; + uv_fs_t close_req; + uv_dir_t* dir; + int r; + + cleanup_test_files(); + + r = uv_fs_mkdir(uv_default_loop(), &mkdir_req, "test_dir", 0755, NULL); + ASSERT(r == 0); + + /* Create two files synchronously. */ + r = uv_fs_open(uv_default_loop(), + &create_req, + "test_dir/file1", + O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR, + NULL); + ASSERT(r >= 0); + uv_fs_req_cleanup(&create_req); + r = uv_fs_close(uv_default_loop(), + &close_req, + create_req.result, + NULL); + ASSERT(r == 0); + uv_fs_req_cleanup(&close_req); + + r = uv_fs_open(uv_default_loop(), + &create_req, + "test_dir/file2", + O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR, + NULL); + ASSERT(r >= 0); + uv_fs_req_cleanup(&create_req); + r = uv_fs_close(uv_default_loop(), + &close_req, + create_req.result, + NULL); + ASSERT(r == 0); + uv_fs_req_cleanup(&close_req); + + r = uv_fs_mkdir(uv_default_loop(), + &mkdir_req, + "test_dir/test_subdir", + 0755, + NULL); + ASSERT(r == 0); + uv_fs_req_cleanup(&mkdir_req); + + /* Fill the req to ensure that required fields are cleaned up. */ + memset(&opendir_req, 0xdb, sizeof(opendir_req)); + + /* Testing the synchronous flavor. */ + r = uv_fs_opendir(uv_default_loop(), &opendir_req, "test_dir", NULL); + ASSERT(r == 0); + ASSERT(opendir_req.fs_type == UV_FS_OPENDIR); + ASSERT(opendir_req.result == 0); + ASSERT(opendir_req.ptr != NULL); + + entries_count = 0; + dir = opendir_req.ptr; + dir->dirents = dirents; + dir->nentries = ARRAY_SIZE(dirents); + uv_fs_req_cleanup(&opendir_req); + + while (uv_fs_readdir(uv_default_loop(), + &readdir_req, + dir, + NULL) != 0) { + ASSERT(strcmp(dirents[0].name, "file1") == 0 || + strcmp(dirents[0].name, "file2") == 0 || + strcmp(dirents[0].name, "test_subdir") == 0); +#ifdef HAVE_DIRENT_TYPES + if (!strcmp(dirents[0].name, "test_subdir")) + ASSERT(dirents[0].type == UV_DIRENT_DIR); + else + ASSERT(dirents[0].type == UV_DIRENT_FILE); +#else + ASSERT(dirents[0].type == UV_DIRENT_UNKNOWN); +#endif /* HAVE_DIRENT_TYPES */ + uv_fs_req_cleanup(&readdir_req); + ++entries_count; + } + + ASSERT(entries_count == 3); + uv_fs_req_cleanup(&readdir_req); + + /* Fill the req to ensure that required fields are cleaned up. */ + memset(&closedir_req, 0xdb, sizeof(closedir_req)); + uv_fs_closedir(uv_default_loop(), &closedir_req, dir, NULL); + ASSERT(closedir_req.result == 0); + uv_fs_req_cleanup(&closedir_req); + + /* Testing the asynchronous flavor. */ + + /* Fill the req to ensure that required fields are cleaned up. */ + memset(&opendir_req, 0xdb, sizeof(opendir_req)); + + r = uv_fs_opendir(uv_default_loop(), + &opendir_req, + "test_dir", + non_empty_opendir_cb); + ASSERT(r == 0); + ASSERT(non_empty_opendir_cb_count == 0); + ASSERT(non_empty_closedir_cb_count == 0); + r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); + ASSERT(r == 0); + ASSERT(non_empty_opendir_cb_count == 1); + ASSERT(non_empty_closedir_cb_count == 1); + + uv_fs_rmdir(uv_default_loop(), &rmdir_req, "test_subdir", NULL); + uv_fs_req_cleanup(&rmdir_req); + + cleanup_test_files(); + MAKE_VALGRIND_HAPPY(); + return 0; + } diff --git a/deps/uv/test/test-gettimeofday.c b/deps/uv/test/test-gettimeofday.c new file mode 100644 index 00000000000000..4ebc11f93ed321 --- /dev/null +++ b/deps/uv/test/test-gettimeofday.c @@ -0,0 +1,39 @@ +/* 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" + +TEST_IMPL(gettimeofday) { + uv_timeval64_t tv; + int r; + + tv.tv_sec = 0; + r = uv_gettimeofday(&tv); + ASSERT(r == 0); + ASSERT(tv.tv_sec != 0); + + /* Test invalid input. */ + r = uv_gettimeofday(NULL); + ASSERT(r == UV_EINVAL); + + return 0; +} diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index f498c7dc81f1e5..ace501c9796f00 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -155,6 +155,9 @@ TEST_DECLARE (udp_open) TEST_DECLARE (udp_open_twice) TEST_DECLARE (udp_open_bound) TEST_DECLARE (udp_open_connect) +#ifndef _WIN32 +TEST_DECLARE (udp_send_unix) +#endif TEST_DECLARE (udp_try_send) TEST_DECLARE (pipe_bind_error_addrinuse) TEST_DECLARE (pipe_bind_error_addrnotavail) @@ -252,6 +255,7 @@ TEST_DECLARE (getnameinfo_basic_ip4_sync) TEST_DECLARE (getnameinfo_basic_ip6) TEST_DECLARE (getsockname_tcp) TEST_DECLARE (getsockname_udp) +TEST_DECLARE (gettimeofday) TEST_DECLARE (fail_always) TEST_DECLARE (pass_always) TEST_DECLARE (socket_buffer_size) @@ -345,6 +349,10 @@ TEST_DECLARE (fs_scandir_empty_dir) TEST_DECLARE (fs_scandir_non_existent_dir) TEST_DECLARE (fs_scandir_file) TEST_DECLARE (fs_open_dir) +TEST_DECLARE (fs_readdir_empty_dir) +TEST_DECLARE (fs_readdir_file) +TEST_DECLARE (fs_readdir_non_empty_dir) +TEST_DECLARE (fs_readdir_non_existing_dir) TEST_DECLARE (fs_rename_to_existing_file) TEST_DECLARE (fs_write_multiple_bufs) TEST_DECLARE (fs_read_write_null_arguments) @@ -652,6 +660,9 @@ TASK_LIST_START TEST_ENTRY (udp_open_bound) TEST_ENTRY (udp_open_connect) TEST_HELPER (udp_open_connect, udp4_echo_server) +#ifndef _WIN32 + TEST_ENTRY (udp_send_unix) +#endif TEST_ENTRY (pipe_bind_error_addrinuse) TEST_ENTRY (pipe_bind_error_addrnotavail) @@ -781,6 +792,8 @@ TASK_LIST_START TEST_ENTRY (getsockname_tcp) TEST_ENTRY (getsockname_udp) + TEST_ENTRY (gettimeofday) + TEST_ENTRY (poll_duplex) TEST_ENTRY (poll_unidirectional) TEST_ENTRY (poll_close) @@ -921,6 +934,10 @@ TASK_LIST_START TEST_ENTRY (fs_scandir_non_existent_dir) TEST_ENTRY (fs_scandir_file) TEST_ENTRY (fs_open_dir) + TEST_ENTRY (fs_readdir_empty_dir) + TEST_ENTRY (fs_readdir_file) + TEST_ENTRY (fs_readdir_non_empty_dir) + TEST_ENTRY (fs_readdir_non_existing_dir) TEST_ENTRY (fs_rename_to_existing_file) TEST_ENTRY (fs_write_multiple_bufs) TEST_ENTRY (fs_write_alotof_bufs) diff --git a/deps/uv/test/test-udp-open.c b/deps/uv/test/test-udp-open.c index 0390bae2e5d282..dee408baa5c09e 100644 --- a/deps/uv/test/test-udp-open.c +++ b/deps/uv/test/test-udp-open.c @@ -27,6 +27,8 @@ #ifndef _WIN32 # include +# include +# include #endif static int send_cb_called = 0; @@ -296,3 +298,53 @@ TEST_IMPL(udp_open_connect) { MAKE_VALGRIND_HAPPY(); return 0; } + +#ifndef _WIN32 +TEST_IMPL(udp_send_unix) { + /* Test that "uv_udp_send()" supports sending over + a "sockaddr_un" address. */ + struct sockaddr_un addr; + uv_udp_t handle; + uv_udp_send_t req; + uv_loop_t* loop; + uv_buf_t buf = uv_buf_init("PING", 4); + int fd; + int r; + + loop = uv_default_loop(); + + memset(&addr, 0, sizeof addr); + addr.sun_family = AF_UNIX; + ASSERT(strlen(TEST_PIPENAME) < sizeof(addr.sun_path)); + memcpy(addr.sun_path, TEST_PIPENAME, strlen(TEST_PIPENAME)); + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + ASSERT(fd >= 0); + + unlink(TEST_PIPENAME); + ASSERT(0 == bind(fd, (const struct sockaddr*)&addr, sizeof addr)); + ASSERT(0 == listen(fd, 1)); + + r = uv_udp_init(loop, &handle); + ASSERT(r == 0); + r = uv_udp_open(&handle, fd); + ASSERT(r == 0); + uv_run(loop, UV_RUN_DEFAULT); + + r = uv_udp_send(&req, + &handle, + &buf, + 1, + (const struct sockaddr*) &addr, + NULL); + ASSERT(r == 0); + + uv_close((uv_handle_t*)&handle, NULL); + uv_run(loop, UV_RUN_DEFAULT); + close(fd); + unlink(TEST_PIPENAME); + + MAKE_VALGRIND_HAPPY(); + return 0; +} +#endif diff --git a/deps/uv/test/test.gyp b/deps/uv/test/test.gyp index 9c13e25dde0ef0..ff64ef0be8d4b4 100644 --- a/deps/uv/test/test.gyp +++ b/deps/uv/test/test.gyp @@ -32,6 +32,7 @@ 'test-fail-always.c', 'test-fork.c', 'test-fs.c', + 'test-fs-readdir.c', 'test-fs-copyfile.c', 'test-fs-event.c', 'test-fs-poll.c', @@ -43,6 +44,7 @@ 'test-gethostname.c', 'test-getnameinfo.c', 'test-getsockname.c', + 'test-gettimeofday.c', 'test-handle-fileno.c', 'test-homedir.c', 'test-hrtime.c', From 50d2ecc8867557c21cc30f452eef4907679990bb Mon Sep 17 00:00:00 2001 From: cjihrig Date: Mon, 15 Apr 2019 11:43:56 -0400 Subject: [PATCH 3/4] test: move known issue test to parallel As of libuv 1.28.0, this bug is fixed, and the test can be moved to parallel. This commit also updates an error code check to work on Windows. PR-URL: https://github.com/nodejs/node/pull/27241 Reviewed-By: Richard Lau Reviewed-By: Ruben Bridgewater Reviewed-By: James M Snell Reviewed-By: Rich Trott Reviewed-By: Anna Henningsen Reviewed-By: Ben Noordhuis --- .../test-fs-copyfile-respect-permissions.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) rename test/{known_issues => parallel}/test-fs-copyfile-respect-permissions.js (90%) diff --git a/test/known_issues/test-fs-copyfile-respect-permissions.js b/test/parallel/test-fs-copyfile-respect-permissions.js similarity index 90% rename from test/known_issues/test-fs-copyfile-respect-permissions.js rename to test/parallel/test-fs-copyfile-respect-permissions.js index 34697eea6c0bef..2021e9ba63155d 100644 --- a/test/known_issues/test-fs-copyfile-respect-permissions.js +++ b/test/parallel/test-fs-copyfile-respect-permissions.js @@ -23,7 +23,8 @@ function beforeEach() { fs.chmodSync(dest, '444'); const check = (err) => { - assert.strictEqual(err.code, 'EACCES'); + const expected = ['EACCES', 'EPERM']; + assert(expected.includes(err.code), `${err.code} not in ${expected}`); assert.strictEqual(fs.readFileSync(dest, 'utf8'), 'dest'); return true; }; From 0397aaae4bbe41f46e99dbd30eacface3a696ce8 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Mon, 22 Apr 2019 10:53:04 -0400 Subject: [PATCH 4/4] test: unskip copyfile permission test This is no longer a flakey test, and should run everywhere. PR-URL: https://github.com/nodejs/node/pull/27241 Reviewed-By: Richard Lau Reviewed-By: Ruben Bridgewater Reviewed-By: James M Snell Reviewed-By: Rich Trott Reviewed-By: Anna Henningsen Reviewed-By: Ben Noordhuis --- test/known_issues/known_issues.status | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/known_issues/known_issues.status b/test/known_issues/known_issues.status index d437ed56cb425c..4da2df28457e9e 100644 --- a/test/known_issues/known_issues.status +++ b/test/known_issues/known_issues.status @@ -7,25 +7,19 @@ prefix known_issues [true] # This section applies to all platforms [$system==win32] -test-fs-copyfile-respect-permissions: SKIP [$system==linux] test-vm-timeout-escape-nexttick: PASS,FLAKY test-vm-timeout-escape-promise: PASS,FLAKY -test-fs-copyfile-respect-permissions: SKIP [$system==macos] [$system==solaris] -test-fs-copyfile-respect-permissions: SKIP [$system==freebsd] -test-fs-copyfile-respect-permissions: SKIP [$system==aix] -test-fs-copyfile-respect-permissions: SKIP [$arch==arm] # https://github.com/nodejs/node/issues/24120 test-vm-timeout-escape-nexttick: PASS,FLAKY -test-fs-copyfile-respect-permissions: SKIP