summaryrefslogtreecommitdiff
path: root/deps/uv
diff options
context:
space:
mode:
authorcjihrig <cjihrig@gmail.com>2019-04-15 11:28:16 -0400
committercjihrig <cjihrig@gmail.com>2019-04-22 12:04:35 -0400
commitaec2ce4ee11c766d4c7fcc532f794a758404a6c7 (patch)
tree9426e0d8e92a314c6f23290a2939cd45c418cf3b /deps/uv
parent2161690024862fbfc23c4e01d98199acb832f76b (diff)
downloadandroid-node-v8-aec2ce4ee11c766d4c7fcc532f794a758404a6c7.tar.gz
android-node-v8-aec2ce4ee11c766d4c7fcc532f794a758404a6c7.tar.bz2
android-node-v8-aec2ce4ee11c766d4c7fcc532f794a758404a6c7.zip
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 <riclau@uk.ibm.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'deps/uv')
-rw-r--r--deps/uv/AUTHORS5
-rw-r--r--deps/uv/CMakeLists.txt10
-rw-r--r--deps/uv/ChangeLog35
-rw-r--r--deps/uv/Makefile.am11
-rw-r--r--deps/uv/configure.ac21
-rw-r--r--deps/uv/docs/src/fs.rst58
-rw-r--r--deps/uv/docs/src/misc.rst29
-rw-r--r--deps/uv/include/uv.h32
-rw-r--r--deps/uv/include/uv/unix.h3
-rw-r--r--deps/uv/include/uv/version.h2
-rw-r--r--deps/uv/include/uv/win.h5
-rw-r--r--deps/uv/src/unix/atomic-ops.h37
-rw-r--r--deps/uv/src/unix/bsd-ifaddrs.c11
-rw-r--r--deps/uv/src/unix/core.c15
-rw-r--r--deps/uv/src/unix/fs.c180
-rw-r--r--deps/uv/src/unix/linux-core.c5
-rw-r--r--deps/uv/src/unix/thread.c2
-rw-r--r--deps/uv/src/unix/udp.c33
-rw-r--r--deps/uv/src/uv-common.c54
-rw-r--r--deps/uv/src/uv-common.h2
-rw-r--r--deps/uv/src/win/fs.c175
-rw-r--r--deps/uv/src/win/util.c17
-rw-r--r--deps/uv/test/test-fs-copyfile.c11
-rw-r--r--deps/uv/test/test-fs-readdir.c462
-rw-r--r--deps/uv/test/test-gettimeofday.c39
-rw-r--r--deps/uv/test/test-list.h17
-rw-r--r--deps/uv/test/test-udp-open.c52
-rw-r--r--deps/uv/test/test.gyp2
28 files changed, 1192 insertions, 133 deletions
diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS
index 2c1d8ae685..890e6b0d1a 100644
--- a/deps/uv/AUTHORS
+++ b/deps/uv/AUTHORS
@@ -371,3 +371,8 @@ yeyuanfeng <yeyuanfeng@bytedance.com>
erw7 <erw7.github@gmail.com>
Thomas Karl Pietrowski <thopiekar@gmail.com>
evgley <evgley@gmail.com>
+Andreas Rohner <andreas.rohner@gmx.net>
+Rich Trott <rtrott@gmail.com>
+Milad Farazmand <miladfar@ca.ibm.com>
+zlargon <zlargon1988@gmail.com>
+Yury Selivanov <yury@magic.io>
diff --git a/deps/uv/CMakeLists.txt b/deps/uv/CMakeLists.txt
index 01a7c47e57..7b25511939 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 62d6073d7d..3095f9fc10 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 595a5aea03..22069625e3 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 336e55b15f..75275aa878 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 af97ec3a64..177db57084 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 14e9acce9a..4ad4e40af9 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 43895ac80d..df15b83678 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;
@@ -1099,6 +1100,11 @@ typedef struct {
} 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 */
uint64_t ru_maxrss; /* maximum resident set size */
@@ -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 2363701b41..26df0ec17a 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 4f65398307..fcb813b312 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 edd2cc6eb9..acbd958be4 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 fb46978859..541a6c8648 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 3c2253f0c9..a4c6bf9d11 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 ca0e345da0..e7e9f4b8c1 100644
--- a/deps/uv/src/unix/core.c
+++ b/deps/uv/src/unix/core.c
@@ -41,6 +41,7 @@
#include <sys/resource.h> /* getrusage */
#include <pwd.h>
#include <sys/utsname.h>
+#include <sys/time.h>
#ifdef __sun
# include <sys/filio.h>
@@ -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 f4b4280ca0..c6d2259adc 100644
--- a/deps/uv/src/unix/fs.c
+++ b/deps/uv/src/unix/fs.c
@@ -60,7 +60,6 @@
#endif
#if defined(__APPLE__)
-# include <copyfile.h>
# include <sys/sysctl.h>
#elif defined(__linux__) && !defined(FICLONE)
# include <sys/ioctl.h>
@@ -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 @@ done:
}
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 @@ out:
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 7165fe2fb4..f8973bb36b 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 6088c77f71..9a50448e62 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 15fa5937b3..b578e7bc10 100644
--- a/deps/uv/src/unix/udp.c
+++ b/deps/uv/src/unix/udp.c
@@ -30,6 +30,7 @@
#if defined(__MVS__)
#include <xti.h>
#endif
+#include <sys/un.h>
#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 94dd59fb07..066eb31d03 100644
--- a/deps/uv/src/uv-common.c
+++ b/deps/uv/src/uv-common.c
@@ -34,6 +34,7 @@
# include <malloc.h> /* malloc */
#else
# include <net/if.h> /* if_nametoindex */
+# include <sys/un.h> /* 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 e09a57b2c2..f788161c39 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 65d936bf08..9e2f084c8d 100644
--- a/deps/uv/src/win/fs.c
+++ b/deps/uv/src/win/fs.c
@@ -1125,6 +1125,137 @@ cleanup:
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 395d958c03..2c10728427 100644
--- a/deps/uv/src/win/util.c
+++ b/deps/uv/src/win/util.c
@@ -1778,3 +1778,20 @@ error:
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 7b6511c93c..cd8a2ea7c0 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 0000000000..a767f1fb88
--- /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 <fcntl.h>
+#include <string.h>
+
+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 0000000000..4ebc11f93e
--- /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 f498c7dc81..ace501c979 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 0390bae2e5..dee408baa5 100644
--- a/deps/uv/test/test-udp-open.c
+++ b/deps/uv/test/test-udp-open.c
@@ -27,6 +27,8 @@
#ifndef _WIN32
# include <unistd.h>
+# include <sys/socket.h>
+# include <sys/un.h>
#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 9c13e25dde..ff64ef0be8 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',