summaryrefslogtreecommitdiff
path: root/deps/uv
diff options
context:
space:
mode:
authorcjihrig <cjihrig@gmail.com>2019-08-09 11:03:55 -0400
committercjihrig <cjihrig@gmail.com>2019-08-11 11:22:01 -0400
commitce7f3ed13ca15ae4c166d922e7ee39ad2ef41abb (patch)
treef25ca8d612ee2bdfb78f2bac31439633dfb2bb3d /deps/uv
parent8ef68e66d0465441a79a5dae22e480bf0d83ed25 (diff)
downloadandroid-node-v8-ce7f3ed13ca15ae4c166d922e7ee39ad2ef41abb.tar.gz
android-node-v8-ce7f3ed13ca15ae4c166d922e7ee39ad2ef41abb.tar.bz2
android-node-v8-ce7f3ed13ca15ae4c166d922e7ee39ad2ef41abb.zip
deps: upgrade to libuv 1.31.0
Notable changes: - UV_FS_O_FILEMAP has been added for faster access to memory mapped files on Windows. - uv_fs_mkdir() now returns UV_EINVAL for invalid filenames on Windows. It previously returned UV_ENOENT. - The uv_fs_statfs() API has been added. - The uv_os_environ() and uv_os_free_environ() APIs have been added. Fixes: https://github.com/nodejs/node/issues/28599 Fixes: https://github.com/nodejs/node/issues/28945 Fixes: https://github.com/nodejs/node/issues/29008 PR-URL: https://github.com/nodejs/node/pull/29070 Reviewed-By: Richard Lau <riclau@uk.ibm.com> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Jiawen Geng <technicalcute@gmail.com>
Diffstat (limited to 'deps/uv')
-rw-r--r--deps/uv/.gitignore1
-rw-r--r--deps/uv/.mailmap1
-rw-r--r--deps/uv/AUTHORS7
-rw-r--r--deps/uv/CMakeLists.txt2
-rw-r--r--deps/uv/ChangeLog49
-rw-r--r--deps/uv/Makefile.am21
-rw-r--r--deps/uv/README.md2
-rw-r--r--deps/uv/configure.ac3
-rw-r--r--deps/uv/docs/src/fs.rst47
-rw-r--r--deps/uv/docs/src/misc.rst28
-rw-r--r--deps/uv/include/uv.h27
-rw-r--r--deps/uv/include/uv/unix.h6
-rw-r--r--deps/uv/include/uv/version.h4
-rw-r--r--deps/uv/include/uv/win.h1
-rw-r--r--deps/uv/src/unix/core.c60
-rw-r--r--deps/uv/src/unix/darwin-proctitle.c147
-rw-r--r--deps/uv/src/unix/fs.c61
-rw-r--r--deps/uv/src/unix/openbsd.c2
-rw-r--r--deps/uv/src/unix/proctitle.c4
-rw-r--r--deps/uv/src/unix/stream.c2
-rw-r--r--deps/uv/src/uv-common.c11
-rw-r--r--deps/uv/src/win/fs-fd-hash-inl.h178
-rw-r--r--deps/uv/src/win/fs.c458
-rw-r--r--deps/uv/src/win/process.c4
-rw-r--r--deps/uv/src/win/tty.c21
-rw-r--r--deps/uv/src/win/util.c75
-rw-r--r--deps/uv/src/win/winapi.c8
-rw-r--r--deps/uv/src/win/winapi.h12
-rw-r--r--deps/uv/test/runner-win.c6
-rw-r--r--deps/uv/test/task.h4
-rw-r--r--deps/uv/test/test-env-vars.c37
-rw-r--r--deps/uv/test/test-fs-fd-hash.c133
-rw-r--r--deps/uv/test/test-fs-open-flags.c435
-rw-r--r--deps/uv/test/test-fs.c332
-rw-r--r--deps/uv/test/test-ipc.c4
-rw-r--r--deps/uv/test/test-list.h18
-rw-r--r--deps/uv/test/test-pipe-getsockname.c2
-rw-r--r--deps/uv/test/test-process-title-threadsafe.c6
-rw-r--r--deps/uv/test/test-queue-foreach-delete.c26
-rw-r--r--deps/uv/test/test-spawn.c28
-rw-r--r--deps/uv/test/test-tmpdir.c11
-rw-r--r--deps/uv/test/test.gyp2
42 files changed, 2136 insertions, 150 deletions
diff --git a/deps/uv/.gitignore b/deps/uv/.gitignore
index c132987917..b6abc2ab46 100644
--- a/deps/uv/.gitignore
+++ b/deps/uv/.gitignore
@@ -51,6 +51,7 @@ Makefile.in
/test/run-benchmarks
/test/run-benchmarks.exe
/test/run-benchmarks.dSYM
+test_file_*
*.sln
*.sln.cache
diff --git a/deps/uv/.mailmap b/deps/uv/.mailmap
index 3d95997e4f..87d63bed0b 100644
--- a/deps/uv/.mailmap
+++ b/deps/uv/.mailmap
@@ -38,6 +38,7 @@ Sam Roberts <vieuxtech@gmail.com> <sam@strongloop.com>
San-Tai Hsu <vanilla@fatpipi.com>
Santiago Gimeno <santiago.gimeno@quantion.es> <santiago.gimeno@gmail.com>
Saúl Ibarra Corretgé <saghul@gmail.com>
+Saúl Ibarra Corretgé <saghul@gmail.com> <s@saghul.net>
Shigeki Ohtsu <ohtsu@iij.ad.jp> <ohtsu@ohtsu.org>
Timothy J. Fontaine <tjfontaine@gmail.com>
Yasuhiro Matsumoto <mattn.jp@gmail.com>
diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS
index 4db18540d4..5d5866d3ff 100644
--- a/deps/uv/AUTHORS
+++ b/deps/uv/AUTHORS
@@ -389,3 +389,10 @@ Jenil Christo <jenilchristo5@gmail.com>
Evgeny Ermakov <evgeny.v.ermakov@gmail.com>
gengjiawen <technicalcute@gmail.com>
Leo Chung <gewalalb@gmail.com>
+Javier Blazquez <jblazquez@riotgames.com>
+Mustafa M <mus-m@outlook.com>
+Zach Bjornson <zbbjornson@gmail.com>
+Nan Xiao <nan@chinadtrace.org>
+Ben Davies <kaiepi@outlook.com>
+Nhan Khong <knhana7@gmail.com>
+Crunkle <justcrunkle@hotmail.co.uk>
diff --git a/deps/uv/CMakeLists.txt b/deps/uv/CMakeLists.txt
index a34e5a1b80..bf7990f745 100644
--- a/deps/uv/CMakeLists.txt
+++ b/deps/uv/CMakeLists.txt
@@ -53,6 +53,8 @@ set(uv_test_sources
test/test-fs-poll.c
test/test-fs.c
test/test-fs-readdir.c
+ test/test-fs-fd-hash.c
+ test/test-fs-open-flags.c
test/test-get-currentexe.c
test/test-get-loadavg.c
test/test-get-memory.c
diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog
index a6e2786b0e..d440b55077 100644
--- a/deps/uv/ChangeLog
+++ b/deps/uv/ChangeLog
@@ -1,3 +1,52 @@
+2019.08.10, Version 1.31.0 (Stable), 0a6771cee4c15184c924bfe9d397bdd0c3b206ba
+
+Changes since version 1.30.1:
+
+* win,fs: don't modify global file translation mode (Javier Blazquez)
+
+* win: fix uv_os_tmpdir when env var is 260 chars (Mustafa M)
+
+* win: prevent tty event explosion machine hang (Javier Blazquez)
+
+* win: add UV_FS_O_FILEMAP (João Reis)
+
+* win, fs: mkdir return UV_EINVAL for invalid names (Bartosz Sosnowski)
+
+* github: add root warning to template (cjihrig)
+
+* win: misc fs cleanup (cjihrig)
+
+* unix,win: add uv_fs_statfs() (cjihrig)
+
+* test: avoid AF_LOCAL (Carlo Marcelo Arenas Belón)
+
+* unix,win: add ability to retrieve all env variables (Saúl Ibarra Corretgé)
+
+* Revert "darwin: speed up uv_set_process_title()" (Ben Noordhuis)
+
+* doc: add %p to valgrind log-file arg (Zach Bjornson)
+
+* doc: fix typo in basics.rst (Nan Xiao)
+
+* ibmi: support Makefile build for IBM i (Xu Meng)
+
+* OpenBSD: only get active CPU core count (Ben Davies)
+
+* test: fix gcc 8 warnings for tests (Nhan Khong)
+
+* ibmi: use correct header files (Xu Meng)
+
+* unix: clear UV_HANDLE_READING flag before callback (zyxwvu Shi)
+
+* unix: fix unused-function warning on BSD (Nhan Khong)
+
+* test: fix test runner on MinGW (Crunkle)
+
+* win: remove try-except outside MSVC (Crunkle)
+
+* win: fix uv_spawn() ENOMEM on empty env (Ben Noordhuis)
+
+
2019.07.03, Version 1.30.1 (Stable), 1551969c84c2f546a429dac169c7fdac3e38115e
Changes since version 1.30.0:
diff --git a/deps/uv/Makefile.am b/deps/uv/Makefile.am
index d213d8f4fa..6b11c9349c 100644
--- a/deps/uv/Makefile.am
+++ b/deps/uv/Makefile.am
@@ -184,6 +184,8 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-fs-poll.c \
test/test-fs.c \
test/test-fs-readdir.c \
+ test/test-fs-fd-hash.c \
+ test/test-fs-open-flags.c \
test/test-fork.c \
test/test-getters-setters.c \
test/test-get-currentexe.c \
@@ -322,6 +324,12 @@ test_run_tests_CFLAGS += -D_ALL_SOURCE \
-D_LINUX_SOURCE_COMPAT
endif
+if OS400
+test_run_tests_CFLAGS += -D_ALL_SOURCE \
+ -D_XOPEN_SOURCE=500 \
+ -D_LINUX_SOURCE_COMPAT
+endif
+
if HAIKU
test_run_tests_CFLAGS += -D_BSD_SOURCE
endif
@@ -362,6 +370,19 @@ uvinclude_HEADERS += include/uv/aix.h
libuv_la_SOURCES += src/unix/aix.c src/unix/aix-common.c
endif
+if OS400
+libuv_la_CFLAGS += -D_ALL_SOURCE \
+ -D_XOPEN_SOURCE=500 \
+ -D_LINUX_SOURCE_COMPAT \
+ -D_THREAD_SAFE
+uvinclude_HEADERS += include/uv/posix.h
+libuv_la_SOURCES += src/unix/aix-common.c \
+ src/unix/ibmi.c \
+ src/unix/posix-poll.c \
+ src/unix/no-fsevents.c \
+ src/unix/no-proctitle.c
+endif
+
if ANDROID
uvinclude_HEADERS += include/uv/android-ifaddrs.h
libuv_la_SOURCES += src/unix/android-ifaddrs.c \
diff --git a/deps/uv/README.md b/deps/uv/README.md
index 11874cdb28..b55c3a9238 100644
--- a/deps/uv/README.md
+++ b/deps/uv/README.md
@@ -387,7 +387,7 @@ $ gdb --args out/Debug/run-tests TEST_NAME
Use the `--trace-children=yes` parameter:
```bash
-$ valgrind --trace-children=yes -v --tool=memcheck --leak-check=full --track-origins=yes --leak-resolution=high --show-reachable=yes --log-file=memcheck.log out/Debug/run-tests TEST_NAME
+$ valgrind --trace-children=yes -v --tool=memcheck --leak-check=full --track-origins=yes --leak-resolution=high --show-reachable=yes --log-file=memcheck-%p.log out/Debug/run-tests TEST_NAME
```
### Running benchmarks
diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac
index 52aaddcfc1..c5e29fef84 100644
--- a/deps/uv/configure.ac
+++ b/deps/uv/configure.ac
@@ -13,7 +13,7 @@
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
AC_PREREQ(2.57)
-AC_INIT([libuv], [1.30.1], [https://github.com/libuv/libuv/issues])
+AC_INIT([libuv], [1.31.0], [https://github.com/libuv/libuv/issues])
AC_CONFIG_MACRO_DIR([m4])
m4_include([m4/libuv-extra-automake-flags.m4])
m4_include([m4/as_case.m4])
@@ -63,6 +63,7 @@ AM_CONDITIONAL([MSYS], [AS_CASE([$host_os],[msys*], [true], [false])
AM_CONDITIONAL([NETBSD], [AS_CASE([$host_os],[netbsd*], [true], [false])])
AM_CONDITIONAL([OPENBSD], [AS_CASE([$host_os],[openbsd*], [true], [false])])
AM_CONDITIONAL([OS390], [AS_CASE([$host_os],[openedition*], [true], [false])])
+AM_CONDITIONAL([OS400], [AS_CASE([$host_os],[os400], [true], [false])])
AM_CONDITIONAL([SUNOS], [AS_CASE([$host_os],[solaris*], [true], [false])])
AM_CONDITIONAL([WINNT], [AS_CASE([$host_os],[mingw*], [true], [false])])
AS_CASE([$host_os],[mingw*], [
diff --git a/deps/uv/docs/src/fs.rst b/deps/uv/docs/src/fs.rst
index 996624b695..aabe49b3f3 100644
--- a/deps/uv/docs/src/fs.rst
+++ b/deps/uv/docs/src/fs.rst
@@ -102,6 +102,24 @@ Data types
UV_FS_CLOSEDIR
} uv_fs_type;
+.. c:type:: uv_statfs_t
+
+ Reduced cross platform equivalent of ``struct statfs``.
+ Used in :c:func:`uv_fs_statfs`.
+
+ ::
+
+ typedef struct uv_statfs_s {
+ uint64_t f_type;
+ uint64_t f_bsize;
+ uint64_t f_blocks;
+ uint64_t f_bfree;
+ uint64_t f_bavail;
+ uint64_t f_files;
+ uint64_t f_ffree;
+ uint64_t f_spare[4];
+ } uv_statfs_t;
+
.. c:type:: uv_dirent_t
Cross platform (reduced) equivalent of ``struct dirent``.
@@ -200,6 +218,11 @@ API
Equivalent to :man:`preadv(2)`.
+ .. warning::
+ On Windows, under non-MSVC environments (e.g. when GCC or Clang is used
+ to build libuv), files opened using ``UV_FS_O_FILEMAP`` may cause a fatal
+ crash if the memory mapped read operation fails.
+
.. c:function:: int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb)
Equivalent to :man:`unlink(2)`.
@@ -208,6 +231,11 @@ API
Equivalent to :man:`pwritev(2)`.
+ .. warning::
+ On Windows, under non-MSVC environments (e.g. when GCC or Clang is used
+ to build libuv), files opened using ``UV_FS_O_FILEMAP`` may cause a fatal
+ crash if the memory mapped write operation fails.
+
.. c:function:: int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb)
Equivalent to :man:`mkdir(2)`.
@@ -290,6 +318,17 @@ API
Equivalent to :man:`stat(2)`, :man:`fstat(2)` and :man:`lstat(2)` respectively.
+.. c:function:: int uv_fs_statfs(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb)
+
+ Equivalent to :man:`statfs(2)`. On success, a `uv_statfs_t` is allocated
+ and returned via `req->ptr`. This memory is freed by `uv_fs_req_cleanup()`.
+
+ .. note::
+ Any fields in the resulting `uv_statfs_t` that are not supported by the
+ underlying operating system are set to zero.
+
+ .. versionadded:: 1.31.0
+
.. c:function:: int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb)
Equivalent to :man:`rename(2)`.
@@ -534,6 +573,14 @@ File open constants
.. versionchanged:: 1.17.0 support is added for Windows.
+.. c:macro:: UV_FS_O_FILEMAP
+
+ Use a memory file mapping to access the file. When using this flag, the
+ file cannot be open multiple times concurrently.
+
+ .. note::
+ `UV_FS_O_FILEMAP` is only supported on Windows.
+
.. c:macro:: UV_FS_O_NOATIME
Do not update the file access time when the file is read.
diff --git a/deps/uv/docs/src/misc.rst b/deps/uv/docs/src/misc.rst
index ef70e14bff..3ecfce486c 100644
--- a/deps/uv/docs/src/misc.rst
+++ b/deps/uv/docs/src/misc.rst
@@ -180,6 +180,17 @@ Data types
char machine[256];
} uv_utsname_t;
+.. c:type:: uv_env_item_t
+
+ Data type for environment variable storage.
+
+ ::
+
+ typedef struct uv_env_item_s {
+ char* name;
+ char* value;
+ } uv_env_item_t;
+
API
---
@@ -523,6 +534,23 @@ API
.. versionadded:: 1.8.0
+.. c:function:: int uv_os_environ(uv_env_item_t** envitems, int* count)
+
+ Retrieves all environment variables. This function will allocate memory
+ which must be freed by calling :c:func:`uv_os_free_environ`.
+
+ .. warning::
+ This function is not thread safe.
+
+ .. versionadded:: 1.31.0
+
+.. c:function:: void uv_os_free_environ(uv_env_item_t* envitems, int count);
+
+ Frees the memory allocated for the environment variables by
+ :c:func:`uv_os_environ`.
+
+ .. versionadded:: 1.31.0
+
.. c:function:: int uv_os_getenv(const char* name, char* buffer, size_t* size)
Retrieves the environment variable specified by `name`, copies its value
diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h
index f97801cec2..f71767b6e9 100644
--- a/deps/uv/include/uv.h
+++ b/deps/uv/include/uv.h
@@ -231,11 +231,13 @@ typedef struct uv_fs_s uv_fs_t;
typedef struct uv_work_s uv_work_t;
/* None of the above. */
+typedef struct uv_env_item_s uv_env_item_t;
typedef struct uv_cpu_info_s uv_cpu_info_t;
typedef struct uv_interface_address_s uv_interface_address_t;
typedef struct uv_dirent_s uv_dirent_t;
typedef struct uv_passwd_s uv_passwd_t;
typedef struct uv_utsname_s uv_utsname_t;
+typedef struct uv_statfs_s uv_statfs_t;
typedef enum {
UV_LOOP_BLOCK_SIGNAL
@@ -1070,6 +1072,17 @@ struct uv_utsname_s {
to as meaningless in the docs. */
};
+struct uv_statfs_s {
+ uint64_t f_type;
+ uint64_t f_bsize;
+ uint64_t f_blocks;
+ uint64_t f_bfree;
+ uint64_t f_bavail;
+ uint64_t f_files;
+ uint64_t f_ffree;
+ uint64_t f_spare[4];
+};
+
typedef enum {
UV_DIRENT_UNKNOWN,
UV_DIRENT_FILE,
@@ -1150,6 +1163,13 @@ UV_EXTERN int uv_interface_addresses(uv_interface_address_t** addresses,
UV_EXTERN void uv_free_interface_addresses(uv_interface_address_t* addresses,
int count);
+struct uv_env_item_s {
+ char* name;
+ char* value;
+};
+
+UV_EXTERN int uv_os_environ(uv_env_item_t** envitems, int* count);
+UV_EXTERN void uv_os_free_environ(uv_env_item_t* envitems, int count);
UV_EXTERN int uv_os_getenv(const char* name, char* buffer, size_t* size);
UV_EXTERN int uv_os_setenv(const char* name, const char* value);
UV_EXTERN int uv_os_unsetenv(const char* name);
@@ -1205,7 +1225,8 @@ typedef enum {
UV_FS_LCHOWN,
UV_FS_OPENDIR,
UV_FS_READDIR,
- UV_FS_CLOSEDIR
+ UV_FS_CLOSEDIR,
+ UV_FS_STATFS
} uv_fs_type;
struct uv_dir_s {
@@ -1433,6 +1454,10 @@ UV_EXTERN int uv_fs_lchown(uv_loop_t* loop,
uv_uid_t uid,
uv_gid_t gid,
uv_fs_cb cb);
+UV_EXTERN int uv_fs_statfs(uv_loop_t* loop,
+ uv_fs_t* req,
+ const char* path,
+ uv_fs_cb cb);
enum uv_fs_event {
diff --git a/deps/uv/include/uv/unix.h b/deps/uv/include/uv/unix.h
index 6c93ee97de..9080352d31 100644
--- a/deps/uv/include/uv/unix.h
+++ b/deps/uv/include/uv/unix.h
@@ -49,6 +49,8 @@
# include "uv/linux.h"
#elif defined (__MVS__)
# include "uv/os390.h"
+#elif defined(__PASE__) /* __PASE__ and _AIX are both defined on IBM i */
+# include "uv/posix.h" /* IBM i needs uv/posix.h, not uv/aix.h */
#elif defined(_AIX)
# include "uv/aix.h"
#elif defined(__sun)
@@ -61,8 +63,7 @@
defined(__OpenBSD__) || \
defined(__NetBSD__)
# include "uv/bsd.h"
-#elif defined(__PASE__) || \
- defined(__CYGWIN__) || \
+#elif defined(__CYGWIN__) || \
defined(__MSYS__) || \
defined(__GNU__)
# include "uv/posix.h"
@@ -481,6 +482,7 @@ typedef struct {
#endif
/* fs open() flags supported on other platforms: */
+#define UV_FS_O_FILEMAP 0
#define UV_FS_O_RANDOM 0
#define UV_FS_O_SHORT_LIVED 0
#define UV_FS_O_SEQUENTIAL 0
diff --git a/deps/uv/include/uv/version.h b/deps/uv/include/uv/version.h
index bf992d2d0e..37a6a445b8 100644
--- a/deps/uv/include/uv/version.h
+++ b/deps/uv/include/uv/version.h
@@ -31,8 +31,8 @@
*/
#define UV_VERSION_MAJOR 1
-#define UV_VERSION_MINOR 30
-#define UV_VERSION_PATCH 1
+#define UV_VERSION_MINOR 31
+#define UV_VERSION_PATCH 0
#define UV_VERSION_IS_RELEASE 1
#define UV_VERSION_SUFFIX ""
diff --git a/deps/uv/include/uv/win.h b/deps/uv/include/uv/win.h
index acbd958be4..9793eee3e1 100644
--- a/deps/uv/include/uv/win.h
+++ b/deps/uv/include/uv/win.h
@@ -668,6 +668,7 @@ typedef struct {
#define UV_FS_O_APPEND _O_APPEND
#define UV_FS_O_CREAT _O_CREAT
#define UV_FS_O_EXCL _O_EXCL
+#define UV_FS_O_FILEMAP 0x20000000
#define UV_FS_O_RANDOM _O_RANDOM
#define UV_FS_O_RDONLY _O_RDONLY
#define UV_FS_O_RDWR _O_RDWR
diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c
index 202c75bbb5..f4b94e30cc 100644
--- a/deps/uv/src/unix/core.c
+++ b/deps/uv/src/unix/core.c
@@ -50,11 +50,15 @@
#endif
#ifdef __APPLE__
+# include <crt_externs.h>
# include <mach-o/dyld.h> /* _NSGetExecutablePath */
# include <sys/filio.h>
# if defined(O_CLOEXEC)
# define UV__O_CLOEXEC O_CLOEXEC
# endif
+# define environ (*_NSGetEnviron())
+#else
+extern char** environ;
#endif
#if defined(__DragonFly__) || \
@@ -1284,6 +1288,62 @@ int uv_translate_sys_error(int sys_errno) {
}
+int uv_os_environ(uv_env_item_t** envitems, int* count) {
+ int i, j, cnt;
+ uv_env_item_t* envitem;
+
+ *envitems = NULL;
+ *count = 0;
+
+ for (i = 0; environ[i] != NULL; i++);
+
+ *envitems = uv__calloc(i, sizeof(**envitems));
+
+ if (envitems == NULL)
+ return UV_ENOMEM;
+
+ for (j = 0, cnt = 0; j < i; j++) {
+ char* buf;
+ char* ptr;
+
+ if (environ[j] == NULL)
+ break;
+
+ buf = uv__strdup(environ[j]);
+ if (buf == NULL)
+ goto fail;
+
+ ptr = strchr(buf, '=');
+ if (ptr == NULL) {
+ uv__free(buf);
+ continue;
+ }
+
+ *ptr = '\0';
+
+ envitem = &(*envitems)[cnt];
+ envitem->name = buf;
+ envitem->value = ptr + 1;
+
+ cnt++;
+ }
+
+ *count = cnt;
+ return 0;
+
+fail:
+ for (i = 0; i < cnt; i++) {
+ envitem = &(*envitems)[cnt];
+ uv__free(envitem->name);
+ }
+ uv__free(*envitems);
+
+ *envitems = NULL;
+ *count = 0;
+ return UV_ENOMEM;
+}
+
+
int uv_os_getenv(const char* name, char* buffer, size_t* size) {
char* var;
size_t len;
diff --git a/deps/uv/src/unix/darwin-proctitle.c b/deps/uv/src/unix/darwin-proctitle.c
index e505bdd23f..dabde2239c 100644
--- a/deps/uv/src/unix/darwin-proctitle.c
+++ b/deps/uv/src/unix/darwin-proctitle.c
@@ -33,56 +33,61 @@
# include <ApplicationServices/ApplicationServices.h>
#endif
-#define S(s) pCFStringCreateWithCString(NULL, (s), kCFStringEncodingUTF8)
-
-
-static int (*dynamic_pthread_setname_np)(const char* name);
-#if !TARGET_OS_IPHONE
-static CFStringRef (*pCFStringCreateWithCString)(CFAllocatorRef,
- const char*,
- CFStringEncoding);
-static CFBundleRef (*pCFBundleGetBundleWithIdentifier)(CFStringRef);
-static void *(*pCFBundleGetDataPointerForName)(CFBundleRef, CFStringRef);
-static void *(*pCFBundleGetFunctionPointerForName)(CFBundleRef, CFStringRef);
-static CFTypeRef (*pLSGetCurrentApplicationASN)(void);
-static OSStatus (*pLSSetApplicationInformationItem)(int,
- CFTypeRef,
- CFStringRef,
- CFStringRef,
- CFDictionaryRef*);
-static void* application_services_handle;
-static void* core_foundation_handle;
-static CFBundleRef launch_services_bundle;
-static CFStringRef* display_name_key;
-static CFDictionaryRef (*pCFBundleGetInfoDictionary)(CFBundleRef);
-static CFBundleRef (*pCFBundleGetMainBundle)(void);
-static CFBundleRef hi_services_bundle;
-static OSStatus (*pSetApplicationIsDaemon)(int);
-static CFDictionaryRef (*pLSApplicationCheckIn)(int, CFDictionaryRef);
-static void (*pLSSetApplicationLaunchServicesServerConnectionStatus)(uint64_t,
- void*);
-
-
-UV_DESTRUCTOR(static void uv__set_process_title_platform_fini(void)) {
- if (core_foundation_handle != NULL) {
- dlclose(core_foundation_handle);
- core_foundation_handle = NULL;
- }
-
- if (application_services_handle != NULL) {
- dlclose(application_services_handle);
- application_services_handle = NULL;
- }
-}
-#endif /* !TARGET_OS_IPHONE */
+static int uv__pthread_setname_np(const char* name) {
+ int (*dynamic_pthread_setname_np)(const char* name);
+ char namebuf[64]; /* MAXTHREADNAMESIZE */
+ int err;
-void uv__set_process_title_platform_init(void) {
/* pthread_setname_np() first appeared in OS X 10.6 and iOS 3.2. */
*(void **)(&dynamic_pthread_setname_np) =
dlsym(RTLD_DEFAULT, "pthread_setname_np");
-#if !TARGET_OS_IPHONE
+ if (dynamic_pthread_setname_np == NULL)
+ return UV_ENOSYS;
+
+ strncpy(namebuf, name, sizeof(namebuf) - 1);
+ namebuf[sizeof(namebuf) - 1] = '\0';
+
+ err = dynamic_pthread_setname_np(namebuf);
+ if (err)
+ return UV__ERR(err);
+
+ return 0;
+}
+
+
+int uv__set_process_title(const char* title) {
+#if TARGET_OS_IPHONE
+ return uv__pthread_setname_np(title);
+#else
+ CFStringRef (*pCFStringCreateWithCString)(CFAllocatorRef,
+ const char*,
+ CFStringEncoding);
+ CFBundleRef (*pCFBundleGetBundleWithIdentifier)(CFStringRef);
+ void *(*pCFBundleGetDataPointerForName)(CFBundleRef, CFStringRef);
+ void *(*pCFBundleGetFunctionPointerForName)(CFBundleRef, CFStringRef);
+ CFTypeRef (*pLSGetCurrentApplicationASN)(void);
+ OSStatus (*pLSSetApplicationInformationItem)(int,
+ CFTypeRef,
+ CFStringRef,
+ CFStringRef,
+ CFDictionaryRef*);
+ void* application_services_handle;
+ void* core_foundation_handle;
+ CFBundleRef launch_services_bundle;
+ CFStringRef* display_name_key;
+ CFDictionaryRef (*pCFBundleGetInfoDictionary)(CFBundleRef);
+ CFBundleRef (*pCFBundleGetMainBundle)(void);
+ CFBundleRef hi_services_bundle;
+ OSStatus (*pSetApplicationIsDaemon)(int);
+ CFDictionaryRef (*pLSApplicationCheckIn)(int, CFDictionaryRef);
+ void (*pLSSetApplicationLaunchServicesServerConnectionStatus)(uint64_t,
+ void*);
+ CFTypeRef asn;
+ int err;
+
+ err = UV_ENOENT;
application_services_handle = dlopen("/System/Library/Frameworks/"
"ApplicationServices.framework/"
"Versions/A/ApplicationServices",
@@ -111,6 +116,8 @@ void uv__set_process_title_platform_init(void) {
goto out;
}
+#define S(s) pCFStringCreateWithCString(NULL, (s), kCFStringEncodingUTF8)
+
launch_services_bundle =
pCFBundleGetBundleWithIdentifier(S("com.apple.LaunchServices"));
@@ -141,14 +148,13 @@ void uv__set_process_title_platform_init(void) {
"CFBundleGetInfoDictionary");
*(void **)(&pCFBundleGetMainBundle) = dlsym(core_foundation_handle,
"CFBundleGetMainBundle");
-
if (pCFBundleGetInfoDictionary == NULL || pCFBundleGetMainBundle == NULL)
goto out;
/* Black 10.9 magic, to remove (Not responding) mark in Activity Monitor */
hi_services_bundle =
pCFBundleGetBundleWithIdentifier(S("com.apple.HIServices"));
-
+ err = UV_ENOENT;
if (hi_services_bundle == NULL)
goto out;
@@ -162,37 +168,42 @@ void uv__set_process_title_platform_init(void) {
pCFBundleGetFunctionPointerForName(
launch_services_bundle,
S("_LSSetApplicationLaunchServicesServerConnectionStatus"));
-
if (pSetApplicationIsDaemon == NULL ||
pLSApplicationCheckIn == NULL ||
pLSSetApplicationLaunchServicesServerConnectionStatus == NULL) {
goto out;
}
- return;
+ if (pSetApplicationIsDaemon(1) != noErr)
+ goto out;
-out:
- uv__set_process_title_platform_fini();
-#endif /* !TARGET_OS_IPHONE */
-}
+ pLSSetApplicationLaunchServicesServerConnectionStatus(0, NULL);
+ /* Check into process manager?! */
+ pLSApplicationCheckIn(-2,
+ pCFBundleGetInfoDictionary(pCFBundleGetMainBundle()));
-void uv__set_process_title(const char* title) {
-#if !TARGET_OS_IPHONE
- if (core_foundation_handle != NULL && pSetApplicationIsDaemon(1) != noErr) {
- CFTypeRef asn;
- pLSSetApplicationLaunchServicesServerConnectionStatus(0, NULL);
- pLSApplicationCheckIn(/* Magic value */ -2,
- pCFBundleGetInfoDictionary(pCFBundleGetMainBundle()));
- asn = pLSGetCurrentApplicationASN();
- pLSSetApplicationInformationItem(/* Magic value */ -2, asn,
- *display_name_key, S(title), NULL);
- }
-#endif /* !TARGET_OS_IPHONE */
+ asn = pLSGetCurrentApplicationASN();
- if (dynamic_pthread_setname_np != NULL) {
- char namebuf[64]; /* MAXTHREADNAMESIZE */
- uv__strscpy(namebuf, title, sizeof(namebuf));
- dynamic_pthread_setname_np(namebuf);
+ err = UV_EINVAL;
+ if (pLSSetApplicationInformationItem(-2, /* Magic value. */
+ asn,
+ *display_name_key,
+ S(title),
+ NULL) != noErr) {
+ goto out;
}
+
+ uv__pthread_setname_np(title); /* Don't care if it fails. */
+ err = 0;
+
+out:
+ if (core_foundation_handle != NULL)
+ dlclose(core_foundation_handle);
+
+ if (application_services_handle != NULL)
+ dlclose(application_services_handle);
+
+ return err;
+#endif /* !TARGET_OS_IPHONE */
}
diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c
index 5138c619b0..fc80d00d5c 100644
--- a/deps/uv/src/unix/fs.c
+++ b/deps/uv/src/unix/fs.c
@@ -70,6 +70,20 @@
# include <utime.h>
#endif
+#if defined(__APPLE__) || \
+ defined(__DragonFly__) || \
+ defined(__FreeBSD__) || \
+ defined(__FreeBSD_kernel__) || \
+ defined(__OpenBSD__) || \
+ defined(__NetBSD__)
+# include <sys/param.h>
+# include <sys/mount.h>
+#elif defined(__sun) || defined(__MVS__)
+# include <sys/statvfs.h>
+#else
+# include <sys/statfs.h>
+#endif
+
#if defined(_AIX) && _XOPEN_SOURCE <= 600
extern char *mkdtemp(char *template); /* See issue #740 on AIX < 7 */
#endif
@@ -278,6 +292,7 @@ static ssize_t uv__fs_open(uv_fs_t* req) {
}
+#if !HAVE_PREADV
static ssize_t uv__fs_preadv(uv_file fd,
uv_buf_t* bufs,
unsigned int nbufs,
@@ -324,6 +339,7 @@ static ssize_t uv__fs_preadv(uv_file fd,
return result;
}
+#endif
static ssize_t uv__fs_read(uv_fs_t* req) {
@@ -519,6 +535,40 @@ static int uv__fs_closedir(uv_fs_t* req) {
return 0;
}
+static int uv__fs_statfs(uv_fs_t* req) {
+ uv_statfs_t* stat_fs;
+#if defined(__sun) || defined(__MVS__)
+ struct statvfs buf;
+
+ if (0 != statvfs(req->path, &buf))
+#else
+ struct statfs buf;
+
+ if (0 != statfs(req->path, &buf))
+#endif /* defined(__sun) */
+ return -1;
+
+ stat_fs = uv__malloc(sizeof(*stat_fs));
+ if (stat_fs == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+#if defined(__sun) || defined(__MVS__)
+ stat_fs->f_type = 0; /* f_type is not supported. */
+#else
+ stat_fs->f_type = buf.f_type;
+#endif
+ stat_fs->f_bsize = buf.f_bsize;
+ stat_fs->f_blocks = buf.f_blocks;
+ stat_fs->f_bfree = buf.f_bfree;
+ stat_fs->f_bavail = buf.f_bavail;
+ stat_fs->f_files = buf.f_files;
+ stat_fs->f_ffree = buf.f_ffree;
+ req->ptr = stat_fs;
+ return 0;
+}
+
static ssize_t uv__fs_pathmax_size(const char* path) {
ssize_t pathmax;
@@ -1386,6 +1436,7 @@ static void uv__fs_work(struct uv__work* w) {
X(RMDIR, rmdir(req->path));
X(SENDFILE, uv__fs_sendfile(req));
X(STAT, uv__fs_stat(req->path, &req->statbuf));
+ X(STATFS, uv__fs_statfs(req));
X(SYMLINK, symlink(req->path, req->new_path));
X(UNLINK, unlink(req->path));
X(UTIME, uv__fs_utime(req));
@@ -1858,3 +1909,13 @@ int uv_fs_copyfile(uv_loop_t* loop,
req->flags = flags;
POST;
}
+
+
+int uv_fs_statfs(uv_loop_t* loop,
+ uv_fs_t* req,
+ const char* path,
+ uv_fs_cb cb) {
+ INIT(STATFS);
+ PATH;
+ POST;
+}
diff --git a/deps/uv/src/unix/openbsd.c b/deps/uv/src/unix/openbsd.c
index ffae7683d8..b5cdc80c3e 100644
--- a/deps/uv/src/unix/openbsd.c
+++ b/deps/uv/src/unix/openbsd.c
@@ -193,7 +193,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
if (sysctl(which, 2, &model, &size, NULL, 0))
return UV__ERR(errno);
- which[1] = HW_NCPU;
+ which[1] = HW_NCPUONLINE;
size = sizeof(numcpus);
if (sysctl(which, 2, &numcpus, &size, NULL, 0))
return UV__ERR(errno);
diff --git a/deps/uv/src/unix/proctitle.c b/deps/uv/src/unix/proctitle.c
index a5ce2030c5..1a8c7a7090 100644
--- a/deps/uv/src/unix/proctitle.c
+++ b/deps/uv/src/unix/proctitle.c
@@ -24,7 +24,6 @@
#include <stdlib.h>
#include <string.h>
-extern void uv__set_process_title_platform_init(void);
extern void uv__set_process_title(const char* title);
static uv_mutex_t process_title_mutex;
@@ -39,9 +38,6 @@ static struct {
static void init_process_title_mutex_once(void) {
uv_mutex_init(&process_title_mutex);
-#ifdef __APPLE__
- uv__set_process_title_platform_init();
-#endif
}
diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c
index 17b06a39a7..9de01e3c78 100644
--- a/deps/uv/src/unix/stream.c
+++ b/deps/uv/src/unix/stream.c
@@ -1000,12 +1000,12 @@ uv_handle_type uv__handle_type(int fd) {
static void uv__stream_eof(uv_stream_t* stream, const uv_buf_t* buf) {
stream->flags |= UV_HANDLE_READ_EOF;
+ stream->flags &= ~UV_HANDLE_READING;
uv__io_stop(stream->loop, &stream->io_watcher, POLLIN);
if (!uv__io_active(&stream->io_watcher, POLLOUT))
uv__handle_stop(stream);
uv__stream_osx_interrupt_select(stream);
stream->read_cb(stream, UV_EOF, buf);
- stream->flags &= ~UV_HANDLE_READING;
}
diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c
index 066eb31d03..d1a5e2fbe6 100644
--- a/deps/uv/src/uv-common.c
+++ b/deps/uv/src/uv-common.c
@@ -786,3 +786,14 @@ void uv_loop_delete(uv_loop_t* loop) {
if (loop != default_loop)
uv__free(loop);
}
+
+
+void uv_os_free_environ(uv_env_item_t* envitems, int count) {
+ int i;
+
+ for (i = 0; i < count; i++) {
+ uv__free(envitems[i].name);
+ }
+
+ uv__free(envitems);
+}
diff --git a/deps/uv/src/win/fs-fd-hash-inl.h b/deps/uv/src/win/fs-fd-hash-inl.h
new file mode 100644
index 0000000000..7a203d232d
--- /dev/null
+++ b/deps/uv/src/win/fs-fd-hash-inl.h
@@ -0,0 +1,178 @@
+#ifndef UV_WIN_FS_FD_HASH_INL_H_
+#define UV_WIN_FS_FD_HASH_INL_H_
+
+#include "uv.h"
+#include "internal.h"
+
+/* Files are only inserted in uv__fd_hash when the UV_FS_O_FILEMAP flag is
+ * specified. Thus, when uv__fd_hash_get returns true, the file mapping in the
+ * info structure should be used for read/write operations.
+ *
+ * If the file is empty, the mapping field will be set to
+ * INVALID_HANDLE_VALUE. This is not an issue since the file mapping needs to
+ * be created anyway when the file size changes.
+ *
+ * Since file descriptors are sequential integers, the modulo operator is used
+ * as hashing function. For each bucket, a single linked list of arrays is
+ * kept to minimize allocations. A statically allocated memory buffer is kept
+ * for the first array in each bucket. */
+
+
+#define UV__FD_HASH_SIZE 256
+#define UV__FD_HASH_GROUP_SIZE 16
+
+struct uv__fd_info_s {
+ int flags;
+ BOOLEAN is_directory;
+ HANDLE mapping;
+ LARGE_INTEGER size;
+ LARGE_INTEGER current_pos;
+};
+
+struct uv__fd_hash_entry_s {
+ uv_file fd;
+ struct uv__fd_info_s info;
+};
+
+struct uv__fd_hash_entry_group_s {
+ struct uv__fd_hash_entry_s entries[UV__FD_HASH_GROUP_SIZE];
+ struct uv__fd_hash_entry_group_s* next;
+};
+
+struct uv__fd_hash_bucket_s {
+ size_t size;
+ struct uv__fd_hash_entry_group_s* data;
+};
+
+
+static uv_mutex_t uv__fd_hash_mutex;
+
+static struct uv__fd_hash_entry_group_s
+ uv__fd_hash_entry_initial[UV__FD_HASH_SIZE * UV__FD_HASH_GROUP_SIZE];
+static struct uv__fd_hash_bucket_s uv__fd_hash[UV__FD_HASH_SIZE];
+
+
+INLINE static void uv__fd_hash_init(void) {
+ int i, err;
+
+ err = uv_mutex_init(&uv__fd_hash_mutex);
+ if (err) {
+ uv_fatal_error(err, "uv_mutex_init");
+ }
+
+ for (i = 0; i < ARRAY_SIZE(uv__fd_hash); ++i) {
+ uv__fd_hash[i].size = 0;
+ uv__fd_hash[i].data =
+ uv__fd_hash_entry_initial + i * UV__FD_HASH_GROUP_SIZE;
+ }
+}
+
+#define FIND_COMMON_VARIABLES \
+ unsigned i; \
+ unsigned bucket = fd % ARRAY_SIZE(uv__fd_hash); \
+ struct uv__fd_hash_entry_s* entry_ptr = NULL; \
+ struct uv__fd_hash_entry_group_s* group_ptr; \
+ struct uv__fd_hash_bucket_s* bucket_ptr = &uv__fd_hash[bucket];
+
+#define FIND_IN_GROUP_PTR(group_size) \
+ do { \
+ for (i = 0; i < group_size; ++i) { \
+ if (group_ptr->entries[i].fd == fd) { \
+ entry_ptr = &group_ptr->entries[i]; \
+ break; \
+ } \
+ } \
+ } while (0)
+
+#define FIND_IN_BUCKET_PTR() \
+ do { \
+ size_t first_group_size = bucket_ptr->size % UV__FD_HASH_GROUP_SIZE; \
+ if (bucket_ptr->size != 0 && first_group_size == 0) \
+ first_group_size = UV__FD_HASH_GROUP_SIZE; \
+ group_ptr = bucket_ptr->data; \
+ FIND_IN_GROUP_PTR(first_group_size); \
+ for (group_ptr = group_ptr->next; \
+ group_ptr != NULL && entry_ptr == NULL; \
+ group_ptr = group_ptr->next) \
+ FIND_IN_GROUP_PTR(UV__FD_HASH_GROUP_SIZE); \
+ } while (0)
+
+INLINE static int uv__fd_hash_get(int fd, struct uv__fd_info_s* info) {
+ FIND_COMMON_VARIABLES
+
+ uv_mutex_lock(&uv__fd_hash_mutex);
+
+ FIND_IN_BUCKET_PTR();
+
+ if (entry_ptr != NULL) {
+ *info = entry_ptr->info;
+ }
+
+ uv_mutex_unlock(&uv__fd_hash_mutex);
+ return entry_ptr != NULL;
+}
+
+INLINE static void uv__fd_hash_add(int fd, struct uv__fd_info_s* info) {
+ FIND_COMMON_VARIABLES
+
+ uv_mutex_lock(&uv__fd_hash_mutex);
+
+ FIND_IN_BUCKET_PTR();
+
+ if (entry_ptr == NULL) {
+ i = bucket_ptr->size % UV__FD_HASH_GROUP_SIZE;
+
+ if (bucket_ptr->size != 0 && i == 0) {
+ struct uv__fd_hash_entry_group_s* new_group_ptr =
+ uv__malloc(sizeof(*new_group_ptr));
+ if (new_group_ptr == NULL) {
+ uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
+ }
+ new_group_ptr->next = bucket_ptr->data;
+ bucket_ptr->data = new_group_ptr;
+ }
+
+ bucket_ptr->size += 1;
+ entry_ptr = &bucket_ptr->data->entries[i];
+ entry_ptr->fd = fd;
+ }
+
+ entry_ptr->info = *info;
+
+ uv_mutex_unlock(&uv__fd_hash_mutex);
+}
+
+INLINE static int uv__fd_hash_remove(int fd, struct uv__fd_info_s* info) {
+ FIND_COMMON_VARIABLES
+
+ uv_mutex_lock(&uv__fd_hash_mutex);
+
+ FIND_IN_BUCKET_PTR();
+
+ if (entry_ptr != NULL) {
+ *info = entry_ptr->info;
+
+ bucket_ptr->size -= 1;
+
+ i = bucket_ptr->size % UV__FD_HASH_GROUP_SIZE;
+ if (entry_ptr != &bucket_ptr->data->entries[i]) {
+ *entry_ptr = bucket_ptr->data->entries[i];
+ }
+
+ if (bucket_ptr->size != 0 &&
+ bucket_ptr->size % UV__FD_HASH_GROUP_SIZE == 0) {
+ struct uv__fd_hash_entry_group_s* old_group_ptr = bucket_ptr->data;
+ bucket_ptr->data = old_group_ptr->next;
+ uv__free(old_group_ptr);
+ }
+ }
+
+ uv_mutex_unlock(&uv__fd_hash_mutex);
+ return entry_ptr != NULL;
+}
+
+#undef FIND_COMMON_VARIABLES
+#undef FIND_IN_GROUP_PTR
+#undef FIND_IN_BUCKET_PTR
+
+#endif /* UV_WIN_FS_FD_HASH_INL_H_ */
diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c
index 7d78d466c8..5dccca7799 100644
--- a/deps/uv/src/win/fs.c
+++ b/deps/uv/src/win/fs.c
@@ -34,6 +34,7 @@
#include "internal.h"
#include "req-inl.h"
#include "handle-inl.h"
+#include "fs-fd-hash-inl.h"
#include <wincrypt.h>
@@ -126,6 +127,8 @@
#define IS_LETTER(c) (((c) >= L'a' && (c) <= L'z') || \
((c) >= L'A' && (c) <= L'Z'))
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+
const WCHAR JUNCTION_PREFIX[] = L"\\??\\";
const WCHAR JUNCTION_PREFIX_LEN = 4;
@@ -137,8 +140,16 @@ const WCHAR UNC_PATH_PREFIX_LEN = 8;
static int uv__file_symlink_usermode_flag = SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
+static DWORD uv__allocation_granularity;
+
+
void uv_fs_init(void) {
- _fmode = _O_BINARY;
+ SYSTEM_INFO system_info;
+
+ GetSystemInfo(&system_info);
+ uv__allocation_granularity = system_info.dwAllocationGranularity;
+
+ uv__fd_hash_init();
}
@@ -414,6 +425,27 @@ void fs__open(uv_fs_t* req) {
HANDLE file;
int fd, current_umask;
int flags = req->fs.info.file_flags;
+ struct uv__fd_info_s fd_info;
+
+ /* Adjust flags to be compatible with the memory file mapping. Save the
+ * original flags to emulate the correct behavior. */
+ if (flags & UV_FS_O_FILEMAP) {
+ fd_info.flags = flags;
+ fd_info.current_pos.QuadPart = 0;
+
+ if ((flags & (UV_FS_O_RDONLY | UV_FS_O_WRONLY | UV_FS_O_RDWR)) ==
+ UV_FS_O_WRONLY) {
+ /* CreateFileMapping always needs read access */
+ flags = (flags & ~UV_FS_O_WRONLY) | UV_FS_O_RDWR;
+ }
+
+ if (flags & UV_FS_O_APPEND) {
+ /* Clear the append flag and ensure RDRW mode */
+ flags &= ~UV_FS_O_APPEND;
+ flags &= ~(UV_FS_O_RDONLY | UV_FS_O_WRONLY | UV_FS_O_RDWR);
+ flags |= UV_FS_O_RDWR;
+ }
+ }
/* Obtain the active umask. umask() never fails and returns the previous
* umask. */
@@ -444,7 +476,8 @@ void fs__open(uv_fs_t* req) {
* Here is where we deviate significantly from what CRT's _open()
* does. We indiscriminately use all the sharing modes, to match
* UNIX semantics. In particular, this ensures that the file can
- * be deleted even whilst it's open, fixing issue #1449.
+ * be deleted even whilst it's open, fixing issue
+ * https://github.com/nodejs/node-v0.x-archive/issues/1449.
* We still support exclusive sharing mode, since it is necessary
* for opening raw block devices, otherwise Windows will prevent
* any attempt to write past the master boot record.
@@ -583,11 +616,55 @@ void fs__open(uv_fs_t* req) {
else if (GetLastError() != ERROR_SUCCESS)
SET_REQ_WIN32_ERROR(req, GetLastError());
else
- SET_REQ_WIN32_ERROR(req, UV_UNKNOWN);
+ SET_REQ_WIN32_ERROR(req, (DWORD) UV_UNKNOWN);
CloseHandle(file);
return;
}
+ if (flags & UV_FS_O_FILEMAP) {
+ FILE_STANDARD_INFO file_info;
+ if (!GetFileInformationByHandleEx(file,
+ FileStandardInfo,
+ &file_info,
+ sizeof file_info)) {
+ SET_REQ_WIN32_ERROR(req, GetLastError());
+ CloseHandle(file);
+ return;
+ }
+ fd_info.is_directory = file_info.Directory;
+
+ if (fd_info.is_directory) {
+ fd_info.size.QuadPart = 0;
+ fd_info.mapping = INVALID_HANDLE_VALUE;
+ } else {
+ if (!GetFileSizeEx(file, &fd_info.size)) {
+ SET_REQ_WIN32_ERROR(req, GetLastError());
+ CloseHandle(file);
+ return;
+ }
+
+ if (fd_info.size.QuadPart == 0) {
+ fd_info.mapping = INVALID_HANDLE_VALUE;
+ } else {
+ DWORD flProtect = (fd_info.flags & (UV_FS_O_RDONLY | UV_FS_O_WRONLY |
+ UV_FS_O_RDWR)) == UV_FS_O_RDONLY ? PAGE_READONLY : PAGE_READWRITE;
+ fd_info.mapping = CreateFileMapping(file,
+ NULL,
+ flProtect,
+ fd_info.size.HighPart,
+ fd_info.size.LowPart,
+ NULL);
+ if (fd_info.mapping == NULL) {
+ SET_REQ_WIN32_ERROR(req, GetLastError());
+ CloseHandle(file);
+ return;
+ }
+ }
+ }
+
+ uv__fd_hash_add(fd, &fd_info);
+ }
+
SET_REQ_RESULT(req, fd);
return;
@@ -598,9 +675,16 @@ void fs__open(uv_fs_t* req) {
void fs__close(uv_fs_t* req) {
int fd = req->file.fd;
int result;
+ struct uv__fd_info_s fd_info;
VERIFY_FD(fd, req);
+ if (uv__fd_hash_remove(fd, &fd_info)) {
+ if (fd_info.mapping != INVALID_HANDLE_VALUE) {
+ CloseHandle(fd_info.mapping);
+ }
+ }
+
if (fd > 2)
result = _close(fd);
else
@@ -618,6 +702,123 @@ void fs__close(uv_fs_t* req) {
}
+LONG fs__filemap_ex_filter(LONG excode, PEXCEPTION_POINTERS pep,
+ int* perror) {
+ if (excode != EXCEPTION_IN_PAGE_ERROR) {
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+
+ assert(perror != NULL);
+ if (pep != NULL && pep->ExceptionRecord != NULL &&
+ pep->ExceptionRecord->NumberParameters >= 3) {
+ NTSTATUS status = (NTSTATUS)pep->ExceptionRecord->ExceptionInformation[3];
+ *perror = pRtlNtStatusToDosError(status);
+ if (*perror != ERROR_SUCCESS) {
+ return EXCEPTION_EXECUTE_HANDLER;
+ }
+ }
+ *perror = UV_UNKNOWN;
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+
+void fs__read_filemap(uv_fs_t* req, struct uv__fd_info_s* fd_info) {
+ int fd = req->file.fd; /* VERIFY_FD done in fs__read */
+ int rw_flags = fd_info->flags &
+ (UV_FS_O_RDONLY | UV_FS_O_WRONLY | UV_FS_O_RDWR);
+ size_t read_size, done_read;
+ unsigned int index;
+ LARGE_INTEGER pos, end_pos;
+ size_t view_offset;
+ LARGE_INTEGER view_base;
+ void* view;
+
+ if (rw_flags == UV_FS_O_WRONLY) {
+ SET_REQ_WIN32_ERROR(req, ERROR_ACCESS_DENIED);
+ return;
+ }
+ if (fd_info->is_directory) {
+ SET_REQ_WIN32_ERROR(req, ERROR_INVALID_FUNCTION);
+ return;
+ }
+
+ if (req->fs.info.offset == -1) {
+ pos = fd_info->current_pos;
+ } else {
+ pos.QuadPart = req->fs.info.offset;
+ }
+
+ /* Make sure we wont read past EOF. */
+ if (pos.QuadPart >= fd_info->size.QuadPart) {
+ SET_REQ_RESULT(req, 0);
+ return;
+ }
+
+ read_size = 0;
+ for (index = 0; index < req->fs.info.nbufs; ++index) {
+ read_size += req->fs.info.bufs[index].len;
+ }
+ read_size = (size_t) MIN((LONGLONG) read_size,
+ fd_info->size.QuadPart - pos.QuadPart);
+ if (read_size == 0) {
+ SET_REQ_RESULT(req, 0);
+ return;
+ }
+
+ end_pos.QuadPart = pos.QuadPart + read_size;
+
+ view_offset = pos.QuadPart % uv__allocation_granularity;
+ view_base.QuadPart = pos.QuadPart - view_offset;
+ view = MapViewOfFile(fd_info->mapping,
+ FILE_MAP_READ,
+ view_base.HighPart,
+ view_base.LowPart,
+ view_offset + read_size);
+ if (view == NULL) {
+ SET_REQ_WIN32_ERROR(req, GetLastError());
+ return;
+ }
+
+ done_read = 0;
+ for (index = 0;
+ index < req->fs.info.nbufs && done_read < read_size;
+ ++index) {
+ int err = 0;
+ size_t this_read_size = MIN(req->fs.info.bufs[index].len,
+ read_size - done_read);
+#ifdef _MSC_VER
+ __try {
+#endif
+ memcpy(req->fs.info.bufs[index].base,
+ (char*)view + view_offset + done_read,
+ this_read_size);
+#ifdef _MSC_VER
+ }
+ __except (fs__filemap_ex_filter(GetExceptionCode(),
+ GetExceptionInformation(), &err)) {
+ SET_REQ_WIN32_ERROR(req, err);
+ UnmapViewOfFile(view);
+ return;
+ }
+#endif
+ done_read += this_read_size;
+ }
+ assert(done_read == read_size);
+
+ if (!UnmapViewOfFile(view)) {
+ SET_REQ_WIN32_ERROR(req, GetLastError());
+ return;
+ }
+
+ if (req->fs.info.offset == -1) {
+ fd_info->current_pos = end_pos;
+ uv__fd_hash_add(fd, fd_info);
+ }
+
+ SET_REQ_RESULT(req, read_size);
+ return;
+}
+
void fs__read(uv_fs_t* req) {
int fd = req->file.fd;
int64_t offset = req->fs.info.offset;
@@ -631,9 +832,15 @@ void fs__read(uv_fs_t* req) {
LARGE_INTEGER original_position;
LARGE_INTEGER zero_offset;
int restore_position;
+ struct uv__fd_info_s fd_info;
VERIFY_FD(fd, req);
+ if (uv__fd_hash_get(fd, &fd_info)) {
+ fs__read_filemap(req, &fd_info);
+ return;
+ }
+
zero_offset.QuadPart = 0;
restore_position = 0;
handle = uv__get_osfhandle(fd);
@@ -690,6 +897,131 @@ void fs__read(uv_fs_t* req) {
}
+void fs__write_filemap(uv_fs_t* req, HANDLE file,
+ struct uv__fd_info_s* fd_info) {
+ int fd = req->file.fd; /* VERIFY_FD done in fs__write */
+ int force_append = fd_info->flags & UV_FS_O_APPEND;
+ int rw_flags = fd_info->flags &
+ (UV_FS_O_RDONLY | UV_FS_O_WRONLY | UV_FS_O_RDWR);
+ size_t write_size, done_write;
+ unsigned int index;
+ LARGE_INTEGER zero, pos, end_pos;
+ size_t view_offset;
+ LARGE_INTEGER view_base;
+ void* view;
+ FILETIME ft;
+
+ if (rw_flags == UV_FS_O_RDONLY) {
+ SET_REQ_WIN32_ERROR(req, ERROR_ACCESS_DENIED);
+ return;
+ }
+ if (fd_info->is_directory) {
+ SET_REQ_WIN32_ERROR(req, ERROR_INVALID_FUNCTION);
+ return;
+ }
+
+ write_size = 0;
+ for (index = 0; index < req->fs.info.nbufs; ++index) {
+ write_size += req->fs.info.bufs[index].len;
+ }
+
+ if (write_size == 0) {
+ SET_REQ_RESULT(req, 0);
+ return;
+ }
+
+ zero.QuadPart = 0;
+ if (force_append) {
+ pos = fd_info->size;
+ } else if (req->fs.info.offset == -1) {
+ pos = fd_info->current_pos;
+ } else {
+ pos.QuadPart = req->fs.info.offset;
+ }
+
+ end_pos.QuadPart = pos.QuadPart + write_size;
+
+ /* Recreate the mapping to enlarge the file if needed */
+ if (end_pos.QuadPart > fd_info->size.QuadPart) {
+ if (fd_info->mapping != INVALID_HANDLE_VALUE) {
+ CloseHandle(fd_info->mapping);
+ }
+
+ fd_info->mapping = CreateFileMapping(file,
+ NULL,
+ PAGE_READWRITE,
+ end_pos.HighPart,
+ end_pos.LowPart,
+ NULL);
+ if (fd_info->mapping == NULL) {
+ SET_REQ_WIN32_ERROR(req, GetLastError());
+ CloseHandle(file);
+ fd_info->mapping = INVALID_HANDLE_VALUE;
+ fd_info->size.QuadPart = 0;
+ fd_info->current_pos.QuadPart = 0;
+ uv__fd_hash_add(fd, fd_info);
+ return;
+ }
+
+ fd_info->size = end_pos;
+ uv__fd_hash_add(fd, fd_info);
+ }
+
+ view_offset = pos.QuadPart % uv__allocation_granularity;
+ view_base.QuadPart = pos.QuadPart - view_offset;
+ view = MapViewOfFile(fd_info->mapping,
+ FILE_MAP_WRITE,
+ view_base.HighPart,
+ view_base.LowPart,
+ view_offset + write_size);
+ if (view == NULL) {
+ SET_REQ_WIN32_ERROR(req, GetLastError());
+ return;
+ }
+
+ done_write = 0;
+ for (index = 0; index < req->fs.info.nbufs; ++index) {
+ int err = 0;
+#ifdef _MSC_VER
+ __try {
+#endif
+ memcpy((char*)view + view_offset + done_write,
+ req->fs.info.bufs[index].base,
+ req->fs.info.bufs[index].len);
+#ifdef _MSC_VER
+ }
+ __except (fs__filemap_ex_filter(GetExceptionCode(),
+ GetExceptionInformation(), &err)) {
+ SET_REQ_WIN32_ERROR(req, err);
+ UnmapViewOfFile(view);
+ return;
+ }
+#endif
+ done_write += req->fs.info.bufs[index].len;
+ }
+ assert(done_write == write_size);
+
+ if (!FlushViewOfFile(view, 0)) {
+ SET_REQ_WIN32_ERROR(req, GetLastError());
+ UnmapViewOfFile(view);
+ return;
+ }
+ if (!UnmapViewOfFile(view)) {
+ SET_REQ_WIN32_ERROR(req, GetLastError());
+ return;
+ }
+
+ if (req->fs.info.offset == -1) {
+ fd_info->current_pos = end_pos;
+ uv__fd_hash_add(fd, fd_info);
+ }
+
+ GetSystemTimeAsFileTime(&ft);
+ SetFileTime(file, NULL, NULL, &ft);
+
+ SET_REQ_RESULT(req, done_write);
+}
+
void fs__write(uv_fs_t* req) {
int fd = req->file.fd;
int64_t offset = req->fs.info.offset;
@@ -702,6 +1034,7 @@ void fs__write(uv_fs_t* req) {
LARGE_INTEGER original_position;
LARGE_INTEGER zero_offset;
int restore_position;
+ struct uv__fd_info_s fd_info;
VERIFY_FD(fd, req);
@@ -713,6 +1046,11 @@ void fs__write(uv_fs_t* req) {
return;
}
+ if (uv__fd_hash_get(fd, &fd_info)) {
+ fs__write_filemap(req, handle, &fd_info);
+ return;
+ }
+
if (offset != -1) {
memset(&overlapped, 0, sizeof overlapped);
overlapped_ptr = &overlapped;
@@ -850,8 +1188,13 @@ void fs__unlink(uv_fs_t* req) {
void fs__mkdir(uv_fs_t* req) {
/* TODO: use req->mode. */
- int result = _wmkdir(req->file.pathw);
- SET_REQ_RESULT(req, result);
+ req->result = _wmkdir(req->file.pathw);
+ if (req->result == -1) {
+ req->sys_errno_ = _doserrno;
+ req->result = req->sys_errno_ == ERROR_INVALID_NAME
+ ? UV_EINVAL
+ : uv_translate_sys_error(req->sys_errno_);
+ }
}
@@ -1536,6 +1879,7 @@ static void fs__fdatasync(uv_fs_t* req) {
static void fs__ftruncate(uv_fs_t* req) {
int fd = req->file.fd;
HANDLE handle;
+ struct uv__fd_info_s fd_info = { 0 };
NTSTATUS status;
IO_STATUS_BLOCK io_status;
FILE_END_OF_FILE_INFORMATION eof_info;
@@ -1544,6 +1888,17 @@ static void fs__ftruncate(uv_fs_t* req) {
handle = uv__get_osfhandle(fd);
+ if (uv__fd_hash_get(fd, &fd_info)) {
+ if (fd_info.is_directory) {
+ SET_REQ_WIN32_ERROR(req, ERROR_ACCESS_DENIED);
+ return;
+ }
+
+ if (fd_info.mapping != INVALID_HANDLE_VALUE) {
+ CloseHandle(fd_info.mapping);
+ }
+ }
+
eof_info.EndOfFile.QuadPart = req->fs.info.offset;
status = pNtSetInformationFile(handle,
@@ -1556,6 +1911,43 @@ static void fs__ftruncate(uv_fs_t* req) {
SET_REQ_RESULT(req, 0);
} else {
SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(status));
+
+ if (fd_info.flags) {
+ CloseHandle(handle);
+ fd_info.mapping = INVALID_HANDLE_VALUE;
+ fd_info.size.QuadPart = 0;
+ fd_info.current_pos.QuadPart = 0;
+ uv__fd_hash_add(fd, &fd_info);
+ return;
+ }
+ }
+
+ if (fd_info.flags) {
+ fd_info.size = eof_info.EndOfFile;
+
+ if (fd_info.size.QuadPart == 0) {
+ fd_info.mapping = INVALID_HANDLE_VALUE;
+ } else {
+ DWORD flProtect = (fd_info.flags & (UV_FS_O_RDONLY | UV_FS_O_WRONLY |
+ UV_FS_O_RDWR)) == UV_FS_O_RDONLY ? PAGE_READONLY : PAGE_READWRITE;
+ fd_info.mapping = CreateFileMapping(handle,
+ NULL,
+ flProtect,
+ fd_info.size.HighPart,
+ fd_info.size.LowPart,
+ NULL);
+ if (fd_info.mapping == NULL) {
+ SET_REQ_WIN32_ERROR(req, GetLastError());
+ CloseHandle(handle);
+ fd_info.mapping = INVALID_HANDLE_VALUE;
+ fd_info.size.QuadPart = 0;
+ fd_info.current_pos.QuadPart = 0;
+ uv__fd_hash_add(fd, &fd_info);
+ return;
+ }
+ }
+
+ uv__fd_hash_add(fd, &fd_info);
}
}
@@ -1563,7 +1955,6 @@ static void fs__ftruncate(uv_fs_t* req) {
static void fs__copyfile(uv_fs_t* req) {
int flags;
int overwrite;
- DWORD error;
uv_stat_t statbuf;
uv_stat_t new_statbuf;
@@ -2165,6 +2556,41 @@ static void fs__lchown(uv_fs_t* req) {
req->result = 0;
}
+
+static void fs__statfs(uv_fs_t* req) {
+ uv_statfs_t* stat_fs;
+ DWORD sectors_per_cluster;
+ DWORD bytes_per_sector;
+ DWORD free_clusters;
+ DWORD total_clusters;
+
+ if (0 == GetDiskFreeSpaceW(req->file.pathw,
+ &sectors_per_cluster,
+ &bytes_per_sector,
+ &free_clusters,
+ &total_clusters)) {
+ SET_REQ_WIN32_ERROR(req, GetLastError());
+ return;
+ }
+
+ stat_fs = uv__malloc(sizeof(*stat_fs));
+ if (stat_fs == NULL) {
+ SET_REQ_UV_ERROR(req, UV_ENOMEM, ERROR_OUTOFMEMORY);
+ return;
+ }
+
+ stat_fs->f_type = 0;
+ stat_fs->f_bsize = bytes_per_sector * sectors_per_cluster;
+ stat_fs->f_blocks = total_clusters;
+ stat_fs->f_bfree = free_clusters;
+ stat_fs->f_bavail = free_clusters;
+ stat_fs->f_files = 0;
+ stat_fs->f_ffree = 0;
+ req->ptr = stat_fs;
+ SET_REQ_RESULT(req, 0);
+}
+
+
static void uv__fs_work(struct uv__work* w) {
uv_fs_t* req;
@@ -2204,8 +2630,9 @@ static void uv__fs_work(struct uv__work* w) {
XX(READLINK, readlink)
XX(REALPATH, realpath)
XX(CHOWN, chown)
- XX(FCHOWN, fchown);
- XX(LCHOWN, lchown);
+ XX(FCHOWN, fchown)
+ XX(LCHOWN, lchown)
+ XX(STATFS, statfs)
default:
assert(!"bad uv_fs_type");
}
@@ -2717,3 +3144,18 @@ int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file fd, double atime,
req->fs.time.mtime = mtime;
POST;
}
+
+
+int uv_fs_statfs(uv_loop_t* loop,
+ uv_fs_t* req,
+ const char* path,
+ uv_fs_cb cb) {
+ int err;
+
+ INIT(UV_FS_STATFS);
+ err = fs__capture_path(req, path, NULL, cb != NULL);
+ if (err)
+ return uv_translate_sys_error(err);
+
+ POST;
+}
diff --git a/deps/uv/src/win/process.c b/deps/uv/src/win/process.c
index f9c53de0af..9b7fdc1dc1 100644
--- a/deps/uv/src/win/process.c
+++ b/deps/uv/src/win/process.c
@@ -714,7 +714,7 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) {
/* second pass: copy to UTF-16 environment block */
dst_copy = (WCHAR*)uv__malloc(env_len * sizeof(WCHAR));
- if (!dst_copy) {
+ if (dst_copy == NULL && env_len > 0) {
return ERROR_OUTOFMEMORY;
}
env_copy = alloca(env_block_count * sizeof(WCHAR*));
@@ -739,7 +739,7 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) {
}
}
*ptr_copy = NULL;
- assert(env_len == (size_t) (ptr - dst_copy));
+ assert(env_len == 0 || env_len == (size_t) (ptr - dst_copy));
/* sort our (UTF-16) copy */
qsort(env_copy, env_block_count-1, sizeof(wchar_t*), qsort_wcscmp);
diff --git a/deps/uv/src/win/tty.c b/deps/uv/src/win/tty.c
index a98fe26335..07436dc804 100644
--- a/deps/uv/src/win/tty.c
+++ b/deps/uv/src/win/tty.c
@@ -2280,6 +2280,8 @@ static void uv__determine_vterm_state(HANDLE handle) {
static DWORD WINAPI uv__tty_console_resize_message_loop_thread(void* param) {
CONSOLE_SCREEN_BUFFER_INFO sb_info;
+ NTSTATUS status;
+ ULONG_PTR conhost_pid;
MSG msg;
if (!GetConsoleScreenBufferInfo(uv__tty_console_handle, &sb_info))
@@ -2288,14 +2290,29 @@ static DWORD WINAPI uv__tty_console_resize_message_loop_thread(void* param) {
uv__tty_console_width = sb_info.dwSize.X;
uv__tty_console_height = sb_info.srWindow.Bottom - sb_info.srWindow.Top + 1;
- if (pSetWinEventHook == NULL)
+ if (pSetWinEventHook == NULL || pNtQueryInformationProcess == NULL)
return 0;
+ status = pNtQueryInformationProcess(GetCurrentProcess(),
+ ProcessConsoleHostProcess,
+ &conhost_pid,
+ sizeof(conhost_pid),
+ NULL);
+
+ if (!NT_SUCCESS(status))
+ /* We couldn't retrieve our console host process, probably because this
+ * is a 32-bit process running on 64-bit Windows. Fall back to receiving
+ * console events from all processes. */
+ conhost_pid = 0;
+
+ /* Ensure the PID is a multiple of 4, which is required by SetWinEventHook */
+ conhost_pid &= ~(ULONG_PTR)0x3;
+
if (!pSetWinEventHook(EVENT_CONSOLE_LAYOUT,
EVENT_CONSOLE_LAYOUT,
NULL,
uv__tty_console_resize_event,
- 0,
+ (DWORD)conhost_pid,
0,
WINEVENT_OUTOFCONTEXT))
return 0;
diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c
index 7ca83213a6..359a16aed4 100644
--- a/deps/uv/src/win/util.c
+++ b/deps/uv/src/win/util.c
@@ -1171,18 +1171,18 @@ int uv_os_homedir(char* buffer, size_t* size) {
int uv_os_tmpdir(char* buffer, size_t* size) {
- wchar_t path[MAX_PATH + 1];
+ wchar_t path[MAX_PATH + 2];
DWORD bufsize;
size_t len;
if (buffer == NULL || size == NULL || *size == 0)
return UV_EINVAL;
- len = GetTempPathW(MAX_PATH + 1, path);
+ len = GetTempPathW(ARRAY_SIZE(path), path);
if (len == 0) {
return uv_translate_sys_error(GetLastError());
- } else if (len > MAX_PATH + 1) {
+ } else if (len > ARRAY_SIZE(path)) {
/* This should not be possible */
return UV_EIO;
}
@@ -1397,6 +1397,75 @@ int uv_os_get_passwd(uv_passwd_t* pwd) {
}
+int uv_os_environ(uv_env_item_t** envitems, int* count) {
+ wchar_t* env;
+ wchar_t* penv;
+ int i, cnt;
+ uv_env_item_t* envitem;
+
+ *envitems = NULL;
+ *count = 0;
+
+ env = GetEnvironmentStringsW();
+ if (env == NULL)
+ return 0;
+
+ for (penv = env, i = 0; *penv != L'\0'; penv += wcslen(penv) + 1, i++);
+
+ *envitems = uv__calloc(i, sizeof(**envitems));
+ if (envitems == NULL) {
+ FreeEnvironmentStringsW(env);
+ return UV_ENOMEM;
+ }
+
+ penv = env;
+ cnt = 0;
+
+ while (*penv != L'\0' && cnt < i) {
+ char* buf;
+ char* ptr;
+
+ if (uv__convert_utf16_to_utf8(penv, -1, &buf) != 0)
+ goto fail;
+
+ ptr = strchr(buf, '=');
+ if (ptr == NULL) {
+ uv__free(buf);
+ goto do_continue;
+ }
+
+ *ptr = '\0';
+
+ envitem = &(*envitems)[cnt];
+ envitem->name = buf;
+ envitem->value = ptr + 1;
+
+ cnt++;
+
+ do_continue:
+ penv += wcslen(penv) + 1;
+ }
+
+ FreeEnvironmentStringsW(env);
+
+ *count = cnt;
+ return 0;
+
+fail:
+ FreeEnvironmentStringsW(env);
+
+ for (i = 0; i < cnt; i++) {
+ envitem = &(*envitems)[cnt];
+ uv__free(envitem->name);
+ }
+ uv__free(*envitems);
+
+ *envitems = NULL;
+ *count = 0;
+ return UV_ENOMEM;
+}
+
+
int uv_os_getenv(const char* name, char* buffer, size_t* size) {
wchar_t var[MAX_ENV_VAR_LENGTH];
wchar_t* name_w;
diff --git a/deps/uv/src/win/winapi.c b/deps/uv/src/win/winapi.c
index fbbbceed95..19e4377faf 100644
--- a/deps/uv/src/win/winapi.c
+++ b/deps/uv/src/win/winapi.c
@@ -34,6 +34,7 @@ sNtSetInformationFile pNtSetInformationFile;
sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile;
sNtQueryDirectoryFile pNtQueryDirectoryFile;
sNtQuerySystemInformation pNtQuerySystemInformation;
+sNtQueryInformationProcess pNtQueryInformationProcess;
/* Kernel32 function pointers */
sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
@@ -106,6 +107,13 @@ void uv_winapi_init(void) {
uv_fatal_error(GetLastError(), "GetProcAddress");
}
+ pNtQueryInformationProcess = (sNtQueryInformationProcess) GetProcAddress(
+ ntdll_module,
+ "NtQueryInformationProcess");
+ if (pNtQueryInformationProcess == NULL) {
+ uv_fatal_error(GetLastError(), "GetProcAddress");
+ }
+
kernel32_module = GetModuleHandleA("kernel32.dll");
if (kernel32_module == NULL) {
uv_fatal_error(GetLastError(), "GetModuleHandleA");
diff --git a/deps/uv/src/win/winapi.h b/deps/uv/src/win/winapi.h
index 82c5ed4671..203393c2e3 100644
--- a/deps/uv/src/win/winapi.h
+++ b/deps/uv/src/win/winapi.h
@@ -4436,6 +4436,10 @@ typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION {
# define SystemProcessorPerformanceInformation 8
#endif
+#ifndef ProcessConsoleHostProcess
+# define ProcessConsoleHostProcess 49
+#endif
+
#ifndef FILE_DEVICE_FILE_SYSTEM
# define FILE_DEVICE_FILE_SYSTEM 0x00000009
#endif
@@ -4578,6 +4582,13 @@ typedef NTSTATUS (NTAPI *sNtQueryDirectoryFile)
BOOLEAN RestartScan
);
+typedef NTSTATUS (NTAPI *sNtQueryInformationProcess)
+ (HANDLE ProcessHandle,
+ UINT ProcessInformationClass,
+ PVOID ProcessInformation,
+ ULONG Length,
+ PULONG ReturnLength);
+
/*
* Kernel32 headers
*/
@@ -4718,6 +4729,7 @@ extern sNtSetInformationFile pNtSetInformationFile;
extern sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile;
extern sNtQueryDirectoryFile pNtQueryDirectoryFile;
extern sNtQuerySystemInformation pNtQuerySystemInformation;
+extern sNtQueryInformationProcess pNtQueryInformationProcess;
/* Kernel32 function pointers */
extern sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx;
diff --git a/deps/uv/test/runner-win.c b/deps/uv/test/runner-win.c
index f60c23df3e..6bb41a5d06 100644
--- a/deps/uv/test/runner-win.c
+++ b/deps/uv/test/runner-win.c
@@ -56,6 +56,12 @@ int platform_init(int argc, char **argv) {
_setmode(1, _O_BINARY);
_setmode(2, _O_BINARY);
+#ifdef _MSC_VER
+ _set_fmode(_O_BINARY);
+#else
+ _fmode = _O_BINARY;
+#endif
+
/* Disable stdio output buffering. */
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
diff --git a/deps/uv/test/task.h b/deps/uv/test/task.h
index 8462e0ddbd..e763f89f09 100644
--- a/deps/uv/test/task.h
+++ b/deps/uv/test/task.h
@@ -44,6 +44,10 @@
# pragma clang diagnostic ignored "-Wc99-extensions"
#endif
+#ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wvariadic-macros"
+#endif
+
#define TEST_PORT 9123
#define TEST_PORT_2 9124
diff --git a/deps/uv/test/test-env-vars.c b/deps/uv/test/test-env-vars.c
index 641050e675..d7abb42495 100644
--- a/deps/uv/test/test-env-vars.c
+++ b/deps/uv/test/test-env-vars.c
@@ -27,9 +27,11 @@
TEST_IMPL(env_vars) {
const char* name = "UV_TEST_FOO";
+ const char* name2 = "UV_TEST_FOO2";
char buf[BUF_SIZE];
size_t size;
- int r;
+ int i, r, envcount, found;
+ uv_env_item_t* envitems;
/* Reject invalid inputs when setting an environment variable */
r = uv_os_setenv(NULL, "foo");
@@ -86,5 +88,38 @@ TEST_IMPL(env_vars) {
r = uv_os_unsetenv(name);
ASSERT(r == 0);
+ /* Check getting all env variables. */
+ r = uv_os_setenv(name, "123456789");
+ ASSERT(r == 0);
+ r = uv_os_setenv(name2, "");
+ ASSERT(r == 0);
+
+ r = uv_os_environ(&envitems, &envcount);
+ ASSERT(r == 0);
+ ASSERT(envcount > 0);
+
+ found = 0;
+
+ for (i = 0; i < envcount; i++) {
+ /* printf("Env: %s = %s\n", envitems[i].name, envitems[i].value); */
+ if (strcmp(envitems[i].name, name) == 0) {
+ found++;
+ ASSERT(strcmp(envitems[i].value, "123456789") == 0);
+ } else if (strcmp(envitems[i].name, name2) == 0) {
+ found++;
+ ASSERT(strlen(envitems[i].value) == 0);
+ }
+ }
+
+ ASSERT(found == 2);
+
+ uv_os_free_environ(envitems, envcount);
+
+ r = uv_os_unsetenv(name);
+ ASSERT(r == 0);
+
+ r = uv_os_unsetenv(name2);
+ ASSERT(r == 0);
+
return 0;
}
diff --git a/deps/uv/test/test-fs-fd-hash.c b/deps/uv/test/test-fs-fd-hash.c
new file mode 100644
index 0000000000..8b4bc0351b
--- /dev/null
+++ b/deps/uv/test/test-fs-fd-hash.c
@@ -0,0 +1,133 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#if defined(_WIN32) && !defined(USING_UV_SHARED)
+
+#include "uv.h"
+#include "task.h"
+
+#include "../src/win/fs-fd-hash-inl.h"
+
+
+#define HASH_MAX 1000000000
+#define HASH_INC (1000 * UV__FD_HASH_SIZE + 2)
+#define BUCKET_MAX (UV__FD_HASH_SIZE * UV__FD_HASH_GROUP_SIZE * 10)
+#define BUCKET_INC UV__FD_HASH_SIZE
+#define FD_DIFF 9
+
+
+void assert_nonexistent(int fd) {
+ struct uv__fd_info_s info = { 0 };
+ ASSERT(!uv__fd_hash_get(fd, &info));
+ ASSERT(!uv__fd_hash_remove(fd, &info));
+}
+
+void assert_existent(int fd) {
+ struct uv__fd_info_s info = { 0 };
+ ASSERT(uv__fd_hash_get(fd, &info));
+ ASSERT(info.flags == fd + FD_DIFF);
+}
+
+void assert_insertion(int fd) {
+ struct uv__fd_info_s info = { 0 };
+ assert_nonexistent(fd);
+ info.flags = fd + FD_DIFF;
+ uv__fd_hash_add(fd, &info);
+ assert_existent(fd);
+}
+
+void assert_removal(int fd) {
+ struct uv__fd_info_s info = { 0 };
+ assert_existent(fd);
+ uv__fd_hash_remove(fd, &info);
+ ASSERT(info.flags == fd + FD_DIFF);
+ assert_nonexistent(fd);
+}
+
+
+/* Run a function for a set of values up to a very high number */
+#define RUN_HASH(function) \
+ do { \
+ for (fd = 0; fd < HASH_MAX; fd += HASH_INC) { \
+ function(fd); \
+ } \
+ } while (0)
+
+/* Run a function for a set of values that will cause many collisions */
+#define RUN_COLLISIONS(function) \
+ do { \
+ for (fd = 1; fd < BUCKET_MAX; fd += BUCKET_INC) { \
+ function(fd); \
+ } \
+ } while (0)
+
+
+TEST_IMPL(fs_fd_hash) {
+ int fd;
+
+ uv__fd_hash_init();
+
+ /* Empty table */
+ RUN_HASH(assert_nonexistent);
+ RUN_COLLISIONS(assert_nonexistent);
+
+ /* Fill up */
+ RUN_HASH(assert_insertion);
+ RUN_COLLISIONS(assert_insertion);
+
+ /* Full */
+ RUN_HASH(assert_existent);
+ RUN_COLLISIONS(assert_existent);
+
+ /* Update */
+ {
+ struct uv__fd_info_s info = { 0 };
+ info.flags = FD_DIFF + FD_DIFF;
+ uv__fd_hash_add(0, &info);
+ }
+ {
+ struct uv__fd_info_s info = { 0 };
+ ASSERT(uv__fd_hash_get(0, &info));
+ ASSERT(info.flags == FD_DIFF + FD_DIFF);
+ }
+ {
+ /* Leave as it was, will be again tested below */
+ struct uv__fd_info_s info = { 0 };
+ info.flags = FD_DIFF;
+ uv__fd_hash_add(0, &info);
+ }
+
+ /* Remove all */
+ RUN_HASH(assert_removal);
+ RUN_COLLISIONS(assert_removal);
+
+ /* Empty table */
+ RUN_HASH(assert_nonexistent);
+ RUN_COLLISIONS(assert_nonexistent);
+
+ return 0;
+}
+
+#else
+
+typedef int file_has_no_tests; /* ISO C forbids an empty translation unit. */
+
+#endif /* ifndef _WIN32 */
diff --git a/deps/uv/test/test-fs-open-flags.c b/deps/uv/test/test-fs-open-flags.c
new file mode 100644
index 0000000000..fcef2fb081
--- /dev/null
+++ b/deps/uv/test/test-fs-open-flags.c
@@ -0,0 +1,435 @@
+/* Copyright libuv project contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifdef _WIN32
+
+#include "uv.h"
+#include "task.h"
+
+#if defined(__unix__) || defined(__POSIX__) || \
+ defined(__APPLE__) || defined(__sun) || \
+ defined(_AIX) || defined(__MVS__) || \
+ defined(__HAIKU__)
+# include <unistd.h> /* unlink, rmdir */
+#else
+# include <direct.h>
+# define rmdir _rmdir
+# define unlink _unlink
+#endif
+
+static int flags;
+
+static uv_fs_t close_req;
+static uv_fs_t mkdir_req;
+static uv_fs_t open_req;
+static uv_fs_t read_req;
+static uv_fs_t rmdir_req;
+static uv_fs_t unlink_req;
+static uv_fs_t write_req;
+
+static char buf[32];
+static uv_buf_t iov;
+
+/* Opening the same file multiple times quickly can cause uv_fs_open to fail
+ * with EBUSY, so append an identifier to the file name for each operation */
+static int sid = 0;
+
+#define FILE_NAME_SIZE 128
+static char absent_file[FILE_NAME_SIZE];
+static char empty_file[FILE_NAME_SIZE];
+static char dummy_file[FILE_NAME_SIZE];
+static char empty_dir[] = "empty_dir";
+
+static void setup() {
+ int r;
+
+ /* empty_dir */
+ r = uv_fs_rmdir(NULL, &rmdir_req, empty_dir, NULL);
+ ASSERT(r == 0 || r == UV_ENOENT);
+ ASSERT(rmdir_req.result == 0 || rmdir_req.result == UV_ENOENT);
+ uv_fs_req_cleanup(&rmdir_req);
+
+ r = uv_fs_mkdir(NULL, &mkdir_req, empty_dir, 0755, NULL);
+ ASSERT(r == 0);
+ ASSERT(mkdir_req.result == 0);
+ uv_fs_req_cleanup(&mkdir_req);
+}
+
+static void refresh() {
+ int r;
+
+ /* absent_file */
+ sprintf(absent_file, "test_file_%d", sid++);
+
+ r = uv_fs_unlink(NULL, &unlink_req, absent_file, NULL);
+ ASSERT(r == 0 || r == UV_ENOENT);
+ ASSERT(unlink_req.result == 0 || unlink_req.result == UV_ENOENT);
+ uv_fs_req_cleanup(&unlink_req);
+
+ /* empty_file */
+ sprintf(empty_file, "test_file_%d", sid++);
+
+ r = uv_fs_open(NULL, &open_req, empty_file,
+ UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY, S_IWUSR | S_IRUSR, NULL);
+ ASSERT(r >= 0);
+ ASSERT(open_req.result >= 0);
+ uv_fs_req_cleanup(&open_req);
+
+ r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
+ ASSERT(r == 0);
+ ASSERT(close_req.result == 0);
+ uv_fs_req_cleanup(&close_req);
+
+ /* dummy_file */
+ sprintf(dummy_file, "test_file_%d", sid++);
+
+ r = uv_fs_open(NULL, &open_req, dummy_file,
+ UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY, S_IWUSR | S_IRUSR, NULL);
+ ASSERT(r >= 0);
+ ASSERT(open_req.result >= 0);
+ uv_fs_req_cleanup(&open_req);
+
+ iov = uv_buf_init("a", 1);
+ r = uv_fs_write(NULL, &write_req, open_req.result, &iov, 1, -1, NULL);
+ ASSERT(r == 1);
+ ASSERT(write_req.result == 1);
+ uv_fs_req_cleanup(&write_req);
+
+ r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
+ ASSERT(r == 0);
+ ASSERT(close_req.result == 0);
+ uv_fs_req_cleanup(&close_req);
+}
+
+static void cleanup() {
+ unlink(absent_file);
+ unlink(empty_file);
+ unlink(dummy_file);
+}
+
+static void openFail(char *file, int error) {
+ int r;
+
+ refresh();
+
+ r = uv_fs_open(NULL, &open_req, file, flags, S_IWUSR | S_IRUSR, NULL);
+ ASSERT(r == error);
+ ASSERT(open_req.result == error);
+ uv_fs_req_cleanup(&open_req);
+
+ /* Ensure the first call does not create the file */
+ r = uv_fs_open(NULL, &open_req, file, flags, S_IWUSR | S_IRUSR, NULL);
+ ASSERT(r == error);
+ ASSERT(open_req.result == error);
+ uv_fs_req_cleanup(&open_req);
+
+ cleanup();
+}
+
+static void refreshOpen(char *file) {
+ int r;
+
+ refresh();
+
+ r = uv_fs_open(NULL, &open_req, file, flags, S_IWUSR | S_IRUSR, NULL);
+ ASSERT(r >= 0);
+ ASSERT(open_req.result >= 0);
+ uv_fs_req_cleanup(&open_req);
+}
+
+static void writeExpect(char *file, char *expected, int size) {
+ int r;
+
+ refreshOpen(file);
+
+ iov = uv_buf_init("b", 1);
+ r = uv_fs_write(NULL, &write_req, open_req.result, &iov, 1, -1, NULL);
+ ASSERT(r == 1);
+ ASSERT(write_req.result == 1);
+ uv_fs_req_cleanup(&write_req);
+
+ iov = uv_buf_init("c", 1);
+ r = uv_fs_write(NULL, &write_req, open_req.result, &iov, 1, -1, NULL);
+ ASSERT(r == 1);
+ ASSERT(write_req.result == 1);
+ uv_fs_req_cleanup(&write_req);
+
+ r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
+ ASSERT(r == 0);
+ ASSERT(close_req.result == 0);
+ uv_fs_req_cleanup(&close_req);
+
+ /* Check contents */
+ r = uv_fs_open(NULL, &open_req, file, UV_FS_O_RDONLY, S_IWUSR | S_IRUSR, NULL);
+ ASSERT(r >= 0);
+ ASSERT(open_req.result >= 0);
+ uv_fs_req_cleanup(&open_req);
+
+ iov = uv_buf_init(buf, sizeof(buf));
+ r = uv_fs_read(NULL, &read_req, open_req.result, &iov, 1, -1, NULL);
+ ASSERT(r == size);
+ ASSERT(read_req.result == size);
+ ASSERT(strncmp(buf, expected, size) == 0);
+ uv_fs_req_cleanup(&read_req);
+
+ r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
+ ASSERT(r == 0);
+ ASSERT(close_req.result == 0);
+ uv_fs_req_cleanup(&close_req);
+
+ cleanup();
+}
+
+static void writeFail(char *file, int error) {
+ int r;
+
+ refreshOpen(file);
+
+ iov = uv_buf_init("z", 1);
+ r = uv_fs_write(NULL, &write_req, open_req.result, &iov, 1, -1, NULL);
+ ASSERT(r == error);
+ ASSERT(write_req.result == error);
+ uv_fs_req_cleanup(&write_req);
+
+ iov = uv_buf_init("z", 1);
+ r = uv_fs_write(NULL, &write_req, open_req.result, &iov, 1, -1, NULL);
+ ASSERT(r == error);
+ ASSERT(write_req.result == error);
+ uv_fs_req_cleanup(&write_req);
+
+ r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
+ ASSERT(r == 0);
+ ASSERT(close_req.result == 0);
+ uv_fs_req_cleanup(&close_req);
+
+ cleanup();
+}
+
+static void readExpect(char *file, char *expected, int size) {
+ int r;
+
+ refreshOpen(file);
+
+ iov = uv_buf_init(buf, sizeof(buf));
+ r = uv_fs_read(NULL, &read_req, open_req.result, &iov, 1, -1, NULL);
+ ASSERT(r == size);
+ ASSERT(read_req.result == size);
+ ASSERT(strncmp(buf, expected, size) == 0);
+ uv_fs_req_cleanup(&read_req);
+
+ r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
+ ASSERT(r == 0);
+ ASSERT(close_req.result == 0);
+ uv_fs_req_cleanup(&close_req);
+
+ cleanup();
+}
+
+static void readFail(char *file, int error) {
+ int r;
+
+ refreshOpen(file);
+
+ iov = uv_buf_init(buf, sizeof(buf));
+ r = uv_fs_read(NULL, &read_req, open_req.result, &iov, 1, -1, NULL);
+ ASSERT(r == error);
+ ASSERT(read_req.result == error);
+ uv_fs_req_cleanup(&read_req);
+
+ iov = uv_buf_init(buf, sizeof(buf));
+ r = uv_fs_read(NULL, &read_req, open_req.result, &iov, 1, -1, NULL);
+ ASSERT(r == error);
+ ASSERT(read_req.result == error);
+ uv_fs_req_cleanup(&read_req);
+
+ r = uv_fs_close(NULL, &close_req, open_req.result, NULL);
+ ASSERT(r == 0);
+ ASSERT(close_req.result == 0);
+ uv_fs_req_cleanup(&close_req);
+
+ cleanup();
+}
+
+static void fs_open_flags(int add_flags) {
+ /* Follow the order from
+ * https://github.com/nodejs/node/blob/1a96abe849/lib/internal/fs/utils.js#L329-L354
+ */
+
+ /* r */
+ flags = add_flags | UV_FS_O_RDONLY;
+ openFail(absent_file, UV_ENOENT);
+ writeFail(empty_file, UV_EPERM);
+ readExpect(empty_file, "", 0);
+ writeFail(dummy_file, UV_EPERM);
+ readExpect(dummy_file, "a", 1);
+ writeFail(empty_dir, UV_EPERM);
+ readFail(empty_dir, UV_EISDIR);
+
+ /* rs */
+ flags = add_flags | UV_FS_O_RDONLY | UV_FS_O_SYNC;
+ openFail(absent_file, UV_ENOENT);
+ writeFail(empty_file, UV_EPERM);
+ readExpect(empty_file, "", 0);
+ writeFail(dummy_file, UV_EPERM);
+ readExpect(dummy_file, "a", 1);
+ writeFail(empty_dir, UV_EPERM);
+ readFail(empty_dir, UV_EISDIR);
+
+ /* r+ */
+ flags = add_flags | UV_FS_O_RDWR;
+ openFail(absent_file, UV_ENOENT);
+ writeExpect(empty_file, "bc", 2);
+ readExpect(empty_file, "", 0);
+ writeExpect(dummy_file, "bc", 2);
+ readExpect(dummy_file, "a", 1);
+ writeFail(empty_dir, UV_EISDIR);
+ readFail(empty_dir, UV_EISDIR);
+
+ /* rs+ */
+ flags = add_flags | UV_FS_O_RDWR | UV_FS_O_SYNC;
+ openFail(absent_file, UV_ENOENT);
+ writeExpect(empty_file, "bc", 2);
+ readExpect(empty_file, "", 0);
+ writeExpect(dummy_file, "bc", 2);
+ readExpect(dummy_file, "a", 1);
+ writeFail(empty_dir, UV_EISDIR);
+ readFail(empty_dir, UV_EISDIR);
+
+ /* w */
+ flags = add_flags | UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY;
+ writeExpect(absent_file, "bc", 2);
+ readFail(absent_file, UV_EPERM);
+ writeExpect(empty_file, "bc", 2);
+ readFail(empty_file, UV_EPERM);
+ writeExpect(dummy_file, "bc", 2);
+ readFail(dummy_file, UV_EPERM);
+ openFail(empty_dir, UV_EISDIR);
+
+ /* wx */
+ flags = add_flags | UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY |
+ UV_FS_O_EXCL;
+ writeExpect(absent_file, "bc", 2);
+ readFail(absent_file, UV_EPERM);
+ openFail(empty_file, UV_EEXIST);
+ openFail(dummy_file, UV_EEXIST);
+ openFail(empty_dir, UV_EEXIST);
+
+ /* w+ */
+ flags = add_flags | UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_RDWR;
+ writeExpect(absent_file, "bc", 2);
+ readExpect(absent_file, "", 0);
+ writeExpect(empty_file, "bc", 2);
+ readExpect(empty_file, "", 0);
+ writeExpect(dummy_file, "bc", 2);
+ readExpect(dummy_file, "", 0);
+ openFail(empty_dir, UV_EISDIR);
+
+ /* wx+ */
+ flags = add_flags | UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_RDWR |
+ UV_FS_O_EXCL;
+ writeExpect(absent_file, "bc", 2);
+ readExpect(absent_file, "", 0);
+ openFail(empty_file, UV_EEXIST);
+ openFail(dummy_file, UV_EEXIST);
+ openFail(empty_dir, UV_EEXIST);
+
+ /* a */
+ flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_WRONLY;
+ writeExpect(absent_file, "bc", 2);
+ readFail(absent_file, UV_EPERM);
+ writeExpect(empty_file, "bc", 2);
+ readFail(empty_file, UV_EPERM);
+ writeExpect(dummy_file, "abc", 3);
+ readFail(dummy_file, UV_EPERM);
+ writeFail(empty_dir, UV_EISDIR);
+ readFail(empty_dir, UV_EPERM);
+
+ /* ax */
+ flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_WRONLY |
+ UV_FS_O_EXCL;
+ writeExpect(absent_file, "bc", 2);
+ readFail(absent_file, UV_EPERM);
+ openFail(empty_file, UV_EEXIST);
+ openFail(dummy_file, UV_EEXIST);
+ openFail(empty_dir, UV_EEXIST);
+
+ /* as */
+ flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_WRONLY |
+ UV_FS_O_SYNC;
+ writeExpect(absent_file, "bc", 2);
+ readFail(absent_file, UV_EPERM);
+ writeExpect(empty_file, "bc", 2);
+ readFail(empty_file, UV_EPERM);
+ writeExpect(dummy_file, "abc", 3);
+ readFail(dummy_file, UV_EPERM);
+ writeFail(empty_dir, UV_EISDIR);
+ readFail(empty_dir, UV_EPERM);
+
+ /* a+ */
+ flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_RDWR;
+ writeExpect(absent_file, "bc", 2);
+ readExpect(absent_file, "", 0);
+ writeExpect(empty_file, "bc", 2);
+ readExpect(empty_file, "", 0);
+ writeExpect(dummy_file, "abc", 3);
+ readExpect(dummy_file, "a", 1);
+ writeFail(empty_dir, UV_EISDIR);
+ readFail(empty_dir, UV_EISDIR);
+
+ /* ax+ */
+ flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_RDWR |
+ UV_FS_O_EXCL;
+ writeExpect(absent_file, "bc", 2);
+ readExpect(absent_file, "", 0);
+ openFail(empty_file, UV_EEXIST);
+ openFail(dummy_file, UV_EEXIST);
+ openFail(empty_dir, UV_EEXIST);
+
+ /* as+ */
+ flags = add_flags | UV_FS_O_APPEND | UV_FS_O_CREAT | UV_FS_O_RDWR |
+ UV_FS_O_SYNC;
+ writeExpect(absent_file, "bc", 2);
+ readExpect(absent_file, "", 0);
+ writeExpect(empty_file, "bc", 2);
+ readExpect(empty_file, "", 0);
+ writeExpect(dummy_file, "abc", 3);
+ readExpect(dummy_file, "a", 1);
+ writeFail(empty_dir, UV_EISDIR);
+ readFail(empty_dir, UV_EISDIR);
+}
+TEST_IMPL(fs_open_flags) {
+ setup();
+
+ fs_open_flags(0);
+ fs_open_flags(UV_FS_O_FILEMAP);
+
+ /* Cleanup. */
+ rmdir(empty_dir);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+#else
+
+typedef int file_has_no_tests; /* ISO C forbids an empty translation unit. */
+
+#endif /* ifndef _WIN32 */
diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c
index 2cf8f287fe..0d92b0d3a0 100644
--- a/deps/uv/test/test-fs.c
+++ b/deps/uv/test/test-fs.c
@@ -94,6 +94,7 @@ static int readlink_cb_count;
static int realpath_cb_count;
static int utime_cb_count;
static int futime_cb_count;
+static int statfs_cb_count;
static uv_loop_t* loop;
@@ -330,6 +331,38 @@ static void fstat_cb(uv_fs_t* req) {
}
+static void statfs_cb(uv_fs_t* req) {
+ uv_statfs_t* stats;
+
+ ASSERT(req->fs_type == UV_FS_STATFS);
+ ASSERT(req->result == 0);
+ ASSERT(req->ptr != NULL);
+ stats = req->ptr;
+
+#if defined(_WIN32) || defined(__sun) || defined(_AIX) || defined(__MVS__)
+ ASSERT(stats->f_type == 0);
+#else
+ ASSERT(stats->f_type > 0);
+#endif
+
+ ASSERT(stats->f_bsize > 0);
+ ASSERT(stats->f_blocks > 0);
+ ASSERT(stats->f_bfree <= stats->f_blocks);
+ ASSERT(stats->f_bavail <= stats->f_bfree);
+
+#ifdef _WIN32
+ ASSERT(stats->f_files == 0);
+ ASSERT(stats->f_ffree == 0);
+#else
+ ASSERT(stats->f_files > 0);
+ ASSERT(stats->f_ffree <= stats->f_files);
+#endif
+ uv_fs_req_cleanup(req);
+ ASSERT(req->ptr == NULL);
+ statfs_cb_count++;
+}
+
+
static void close_cb(uv_fs_t* req) {
int r;
ASSERT(req == &close_req);
@@ -847,7 +880,7 @@ TEST_IMPL(fs_file_async) {
}
-TEST_IMPL(fs_file_sync) {
+static void fs_file_sync(int add_flags) {
int r;
/* Setup. */
@@ -856,8 +889,8 @@ TEST_IMPL(fs_file_sync) {
loop = uv_default_loop();
- r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT,
- S_IWUSR | S_IRUSR, NULL);
+ r = uv_fs_open(loop, &open_req1, "test_file",
+ O_WRONLY | O_CREAT | add_flags, S_IWUSR | S_IRUSR, NULL);
ASSERT(r >= 0);
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
@@ -873,7 +906,7 @@ TEST_IMPL(fs_file_sync) {
ASSERT(close_req.result == 0);
uv_fs_req_cleanup(&close_req);
- r = uv_fs_open(NULL, &open_req1, "test_file", O_RDWR, 0, NULL);
+ r = uv_fs_open(NULL, &open_req1, "test_file", O_RDWR | add_flags, 0, NULL);
ASSERT(r >= 0);
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
@@ -900,7 +933,8 @@ TEST_IMPL(fs_file_sync) {
ASSERT(rename_req.result == 0);
uv_fs_req_cleanup(&rename_req);
- r = uv_fs_open(NULL, &open_req1, "test_file2", O_RDONLY, 0, NULL);
+ r = uv_fs_open(NULL, &open_req1, "test_file2", O_RDONLY | add_flags, 0,
+ NULL);
ASSERT(r >= 0);
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
@@ -926,13 +960,17 @@ TEST_IMPL(fs_file_sync) {
/* Cleanup */
unlink("test_file");
unlink("test_file2");
+}
+TEST_IMPL(fs_file_sync) {
+ fs_file_sync(0);
+ fs_file_sync(UV_FS_O_FILEMAP);
MAKE_VALGRIND_HAPPY();
return 0;
}
-TEST_IMPL(fs_file_write_null_buffer) {
+static void fs_file_write_null_buffer(int add_flags) {
int r;
/* Setup. */
@@ -940,8 +978,8 @@ TEST_IMPL(fs_file_write_null_buffer) {
loop = uv_default_loop();
- r = uv_fs_open(NULL, &open_req1, "test_file", O_WRONLY | O_CREAT,
- S_IWUSR | S_IRUSR, NULL);
+ r = uv_fs_open(NULL, &open_req1, "test_file",
+ O_WRONLY | O_CREAT | add_flags, S_IWUSR | S_IRUSR, NULL);
ASSERT(r >= 0);
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
@@ -958,6 +996,10 @@ TEST_IMPL(fs_file_write_null_buffer) {
uv_fs_req_cleanup(&close_req);
unlink("test_file");
+}
+TEST_IMPL(fs_file_write_null_buffer) {
+ fs_file_write_null_buffer(0);
+ fs_file_write_null_buffer(UV_FS_O_FILEMAP);
MAKE_VALGRIND_HAPPY();
return 0;
@@ -1470,7 +1512,7 @@ TEST_IMPL(fs_chmod) {
uv_run(loop, UV_RUN_DEFAULT);
ASSERT(fchmod_cb_count == 1);
- close(file);
+ uv_fs_close(loop, &req, file, NULL);
/*
* Run the loop just to check we don't have make any extraneous uv_ref()
@@ -1513,7 +1555,7 @@ TEST_IMPL(fs_unlink_readonly) {
ASSERT(req.result == sizeof(test_buf));
uv_fs_req_cleanup(&req);
- close(file);
+ uv_fs_close(loop, &req, file, NULL);
/* Make the file read-only */
r = uv_fs_chmod(NULL, &req, "test_file", 0400, NULL);
@@ -1572,7 +1614,7 @@ TEST_IMPL(fs_unlink_archive_readonly) {
ASSERT(req.result == sizeof(test_buf));
uv_fs_req_cleanup(&req);
- close(file);
+ uv_fs_close(loop, &req, file, NULL);
/* Make the file read-only and clear archive flag */
r = SetFileAttributes("test_file", FILE_ATTRIBUTE_READONLY);
@@ -1722,7 +1764,7 @@ TEST_IMPL(fs_link) {
ASSERT(req.result == sizeof(test_buf));
uv_fs_req_cleanup(&req);
- close(file);
+ uv_fs_close(loop, &req, file, NULL);
/* sync link */
r = uv_fs_link(NULL, &req, "test_file", "test_file_link", NULL);
@@ -1764,7 +1806,7 @@ TEST_IMPL(fs_link) {
ASSERT(req.result >= 0);
ASSERT(strcmp(buf, test_buf) == 0);
- close(link);
+ uv_fs_close(loop, &req, link, NULL);
/*
* Run the loop just to check we don't have make any extraneous uv_ref()
@@ -1871,7 +1913,7 @@ TEST_IMPL(fs_symlink) {
ASSERT(req.result == sizeof(test_buf));
uv_fs_req_cleanup(&req);
- close(file);
+ uv_fs_close(loop, &req, file, NULL);
/* sync symlink */
r = uv_fs_symlink(NULL, &req, "test_file", "test_file_symlink", 0, NULL);
@@ -1909,7 +1951,7 @@ TEST_IMPL(fs_symlink) {
ASSERT(req.result >= 0);
ASSERT(strcmp(buf, test_buf) == 0);
- close(link);
+ uv_fs_close(loop, &req, link, NULL);
r = uv_fs_symlink(NULL,
&req,
@@ -1971,7 +2013,7 @@ TEST_IMPL(fs_symlink) {
ASSERT(req.result >= 0);
ASSERT(strcmp(buf, test_buf) == 0);
- close(link);
+ uv_fs_close(loop, &req, link, NULL);
r = uv_fs_symlink(NULL,
&req,
@@ -2293,7 +2335,7 @@ TEST_IMPL(fs_utime) {
ASSERT(r >= 0);
ASSERT(req.result >= 0);
uv_fs_req_cleanup(&req);
- close(r);
+ uv_fs_close(loop, &req, r, NULL);
atime = mtime = 400497753; /* 1982-09-10 11:22:33 */
@@ -2388,7 +2430,7 @@ TEST_IMPL(fs_futime) {
ASSERT(r >= 0);
ASSERT(req.result >= 0);
uv_fs_req_cleanup(&req);
- close(r);
+ uv_fs_close(loop, &req, r, NULL);
atime = mtime = 400497753; /* 1982-09-10 11:22:33 */
@@ -2583,7 +2625,7 @@ TEST_IMPL(fs_open_dir) {
}
-TEST_IMPL(fs_file_open_append) {
+static void fs_file_open_append(int add_flags) {
int r;
/* Setup. */
@@ -2591,8 +2633,8 @@ TEST_IMPL(fs_file_open_append) {
loop = uv_default_loop();
- r = uv_fs_open(NULL, &open_req1, "test_file", O_WRONLY | O_CREAT,
- S_IWUSR | S_IRUSR, NULL);
+ r = uv_fs_open(NULL, &open_req1, "test_file",
+ O_WRONLY | O_CREAT | add_flags, S_IWUSR | S_IRUSR, NULL);
ASSERT(r >= 0);
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
@@ -2608,7 +2650,8 @@ TEST_IMPL(fs_file_open_append) {
ASSERT(close_req.result == 0);
uv_fs_req_cleanup(&close_req);
- r = uv_fs_open(NULL, &open_req1, "test_file", O_RDWR | O_APPEND, 0, NULL);
+ r = uv_fs_open(NULL, &open_req1, "test_file",
+ O_RDWR | O_APPEND | add_flags, 0, NULL);
ASSERT(r >= 0);
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
@@ -2624,7 +2667,8 @@ TEST_IMPL(fs_file_open_append) {
ASSERT(close_req.result == 0);
uv_fs_req_cleanup(&close_req);
- r = uv_fs_open(NULL, &open_req1, "test_file", O_RDONLY, S_IRUSR, NULL);
+ r = uv_fs_open(NULL, &open_req1, "test_file", O_RDONLY | add_flags,
+ S_IRUSR, NULL);
ASSERT(r >= 0);
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
@@ -2646,6 +2690,10 @@ TEST_IMPL(fs_file_open_append) {
/* Cleanup */
unlink("test_file");
+}
+TEST_IMPL(fs_file_open_append) {
+ fs_file_open_append(0);
+ fs_file_open_append(UV_FS_O_FILEMAP);
MAKE_VALGRIND_HAPPY();
return 0;
@@ -2721,13 +2769,13 @@ TEST_IMPL(fs_rename_to_existing_file) {
}
-TEST_IMPL(fs_read_bufs) {
+static void fs_read_bufs(int add_flags) {
char scratch[768];
uv_buf_t bufs[4];
ASSERT(0 <= uv_fs_open(NULL, &open_req1,
"test/fixtures/lorem_ipsum.txt",
- O_RDONLY, 0, NULL));
+ O_RDONLY | add_flags, 0, NULL));
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
@@ -2769,13 +2817,17 @@ TEST_IMPL(fs_read_bufs) {
ASSERT(0 == uv_fs_close(NULL, &close_req, open_req1.result, NULL));
ASSERT(close_req.result == 0);
uv_fs_req_cleanup(&close_req);
+}
+TEST_IMPL(fs_read_bufs) {
+ fs_read_bufs(0);
+ fs_read_bufs(UV_FS_O_FILEMAP);
MAKE_VALGRIND_HAPPY();
return 0;
}
-TEST_IMPL(fs_read_file_eof) {
+static void fs_read_file_eof(int add_flags) {
#if defined(__CYGWIN__) || defined(__MSYS__)
RETURN_SKIP("Cygwin pread at EOF may (incorrectly) return data!");
#endif
@@ -2786,8 +2838,8 @@ TEST_IMPL(fs_read_file_eof) {
loop = uv_default_loop();
- r = uv_fs_open(NULL, &open_req1, "test_file", O_WRONLY | O_CREAT,
- S_IWUSR | S_IRUSR, NULL);
+ r = uv_fs_open(NULL, &open_req1, "test_file",
+ O_WRONLY | O_CREAT | add_flags, S_IWUSR | S_IRUSR, NULL);
ASSERT(r >= 0);
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
@@ -2803,7 +2855,8 @@ TEST_IMPL(fs_read_file_eof) {
ASSERT(close_req.result == 0);
uv_fs_req_cleanup(&close_req);
- r = uv_fs_open(NULL, &open_req1, "test_file", O_RDONLY, 0, NULL);
+ r = uv_fs_open(NULL, &open_req1, "test_file", O_RDONLY | add_flags, 0,
+ NULL);
ASSERT(r >= 0);
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
@@ -2830,13 +2883,17 @@ TEST_IMPL(fs_read_file_eof) {
/* Cleanup */
unlink("test_file");
+}
+TEST_IMPL(fs_read_file_eof) {
+ fs_read_file_eof(0);
+ fs_read_file_eof(UV_FS_O_FILEMAP);
MAKE_VALGRIND_HAPPY();
return 0;
}
-TEST_IMPL(fs_write_multiple_bufs) {
+static void fs_write_multiple_bufs(int add_flags) {
uv_buf_t iovs[2];
int r;
@@ -2845,8 +2902,8 @@ TEST_IMPL(fs_write_multiple_bufs) {
loop = uv_default_loop();
- r = uv_fs_open(NULL, &open_req1, "test_file", O_WRONLY | O_CREAT,
- S_IWUSR | S_IRUSR, NULL);
+ r = uv_fs_open(NULL, &open_req1, "test_file",
+ O_WRONLY | O_CREAT | add_flags, S_IWUSR | S_IRUSR, NULL);
ASSERT(r >= 0);
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
@@ -2863,7 +2920,8 @@ TEST_IMPL(fs_write_multiple_bufs) {
ASSERT(close_req.result == 0);
uv_fs_req_cleanup(&close_req);
- r = uv_fs_open(NULL, &open_req1, "test_file", O_RDONLY, 0, NULL);
+ r = uv_fs_open(NULL, &open_req1, "test_file", O_RDONLY | add_flags, 0,
+ NULL);
ASSERT(r >= 0);
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
@@ -2919,13 +2977,17 @@ TEST_IMPL(fs_write_multiple_bufs) {
/* Cleanup */
unlink("test_file");
+}
+TEST_IMPL(fs_write_multiple_bufs) {
+ fs_write_multiple_bufs(0);
+ fs_write_multiple_bufs(UV_FS_O_FILEMAP);
MAKE_VALGRIND_HAPPY();
return 0;
}
-TEST_IMPL(fs_write_alotof_bufs) {
+static void fs_write_alotof_bufs(int add_flags) {
size_t iovcount;
size_t iovmax;
uv_buf_t* iovs;
@@ -2947,7 +3009,7 @@ TEST_IMPL(fs_write_alotof_bufs) {
r = uv_fs_open(NULL,
&open_req1,
"test_file",
- O_RDWR | O_CREAT,
+ O_RDWR | O_CREAT | add_flags,
S_IWUSR | S_IRUSR,
NULL);
ASSERT(r >= 0);
@@ -2976,7 +3038,17 @@ TEST_IMPL(fs_write_alotof_bufs) {
iovs[index] = uv_buf_init(buffer + index * sizeof(test_buf),
sizeof(test_buf));
- ASSERT(lseek(open_req1.result, 0, SEEK_SET) == 0);
+ r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
+ ASSERT(r == 0);
+ ASSERT(close_req.result == 0);
+ uv_fs_req_cleanup(&close_req);
+
+ r = uv_fs_open(NULL, &open_req1, "test_file", O_RDONLY | add_flags, 0,
+ NULL);
+ ASSERT(r >= 0);
+ ASSERT(open_req1.result >= 0);
+ uv_fs_req_cleanup(&open_req1);
+
r = uv_fs_read(NULL, &read_req, open_req1.result, iovs, iovcount, -1, NULL);
if (iovcount > iovmax)
iovcount = iovmax;
@@ -3012,13 +3084,17 @@ TEST_IMPL(fs_write_alotof_bufs) {
/* Cleanup */
unlink("test_file");
free(iovs);
+}
+TEST_IMPL(fs_write_alotof_bufs) {
+ fs_write_alotof_bufs(0);
+ fs_write_alotof_bufs(UV_FS_O_FILEMAP);
MAKE_VALGRIND_HAPPY();
return 0;
}
-TEST_IMPL(fs_write_alotof_bufs_with_offset) {
+static void fs_write_alotof_bufs_with_offset(int add_flags) {
size_t iovcount;
size_t iovmax;
uv_buf_t* iovs;
@@ -3045,7 +3121,7 @@ TEST_IMPL(fs_write_alotof_bufs_with_offset) {
r = uv_fs_open(NULL,
&open_req1,
"test_file",
- O_RDWR | O_CREAT,
+ O_RDWR | O_CREAT | add_flags,
S_IWUSR | S_IRUSR,
NULL);
ASSERT(r >= 0);
@@ -3124,6 +3200,10 @@ TEST_IMPL(fs_write_alotof_bufs_with_offset) {
/* Cleanup */
unlink("test_file");
free(iovs);
+}
+TEST_IMPL(fs_write_alotof_bufs_with_offset) {
+ fs_write_alotof_bufs_with_offset(0);
+ fs_write_alotof_bufs_with_offset(UV_FS_O_FILEMAP);
MAKE_VALGRIND_HAPPY();
return 0;
@@ -3539,6 +3619,146 @@ TEST_IMPL(fs_file_pos_after_op_with_offset) {
return 0;
}
+#ifdef _WIN32
+static void fs_file_pos_common() {
+ int r;
+
+ iov = uv_buf_init("abc", 3);
+ r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, -1, NULL);
+ ASSERT(r == 3);
+ uv_fs_req_cleanup(&write_req);
+
+ /* Read with offset should not change the position */
+ iov = uv_buf_init(buf, 1);
+ r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, 1, NULL);
+ ASSERT(r == 1);
+ ASSERT(buf[0] == 'b');
+ uv_fs_req_cleanup(&read_req);
+
+ iov = uv_buf_init(buf, sizeof(buf));
+ r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL);
+ ASSERT(r == 0);
+ uv_fs_req_cleanup(&read_req);
+
+ /* Write without offset should change the position */
+ iov = uv_buf_init("d", 1);
+ r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, -1, NULL);
+ ASSERT(r == 1);
+ uv_fs_req_cleanup(&write_req);
+
+ iov = uv_buf_init(buf, sizeof(buf));
+ r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL);
+ ASSERT(r == 0);
+ uv_fs_req_cleanup(&read_req);
+}
+
+static void fs_file_pos_close_check(const char *contents, int size) {
+ int r;
+
+ /* Close */
+ r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
+ ASSERT(r == 0);
+ uv_fs_req_cleanup(&close_req);
+
+ /* Confirm file contents */
+ r = uv_fs_open(NULL, &open_req1, "test_file", O_RDONLY, 0, NULL);
+ ASSERT(r >= 0);
+ ASSERT(open_req1.result >= 0);
+ uv_fs_req_cleanup(&open_req1);
+
+ iov = uv_buf_init(buf, sizeof(buf));
+ r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL);
+ ASSERT(r == size);
+ ASSERT(strncmp(buf, contents, size) == 0);
+ uv_fs_req_cleanup(&read_req);
+
+ r = uv_fs_close(NULL, &close_req, open_req1.result, NULL);
+ ASSERT(r == 0);
+ uv_fs_req_cleanup(&close_req);
+
+ /* Cleanup */
+ unlink("test_file");
+}
+
+static void fs_file_pos_write(int add_flags) {
+ int r;
+
+ /* Setup. */
+ unlink("test_file");
+
+ r = uv_fs_open(NULL,
+ &open_req1,
+ "test_file",
+ O_TRUNC | O_CREAT | O_RDWR | add_flags,
+ S_IWUSR | S_IRUSR,
+ NULL);
+ ASSERT(r > 0);
+ uv_fs_req_cleanup(&open_req1);
+
+ fs_file_pos_common();
+
+ /* Write with offset should not change the position */
+ iov = uv_buf_init("e", 1);
+ r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, 1, NULL);
+ ASSERT(r == 1);
+ uv_fs_req_cleanup(&write_req);
+
+ iov = uv_buf_init(buf, sizeof(buf));
+ r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL);
+ ASSERT(r == 0);
+ uv_fs_req_cleanup(&read_req);
+
+ fs_file_pos_close_check("aecd", 4);
+}
+TEST_IMPL(fs_file_pos_write) {
+ fs_file_pos_write(0);
+ fs_file_pos_write(UV_FS_O_FILEMAP);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+static void fs_file_pos_append(int add_flags) {
+ int r;
+
+ /* Setup. */
+ unlink("test_file");
+
+ r = uv_fs_open(NULL,
+ &open_req1,
+ "test_file",
+ O_APPEND | O_CREAT | O_RDWR | add_flags,
+ S_IWUSR | S_IRUSR,
+ NULL);
+ ASSERT(r > 0);
+ uv_fs_req_cleanup(&open_req1);
+
+ fs_file_pos_common();
+
+ /* Write with offset appends (ignoring offset)
+ * but does not change the position */
+ iov = uv_buf_init("e", 1);
+ r = uv_fs_write(NULL, &write_req, open_req1.result, &iov, 1, 1, NULL);
+ ASSERT(r == 1);
+ uv_fs_req_cleanup(&write_req);
+
+ iov = uv_buf_init(buf, sizeof(buf));
+ r = uv_fs_read(NULL, &read_req, open_req1.result, &iov, 1, -1, NULL);
+ ASSERT(r == 1);
+ ASSERT(buf[0] == 'e');
+ uv_fs_req_cleanup(&read_req);
+
+ fs_file_pos_close_check("abcde", 5);
+}
+TEST_IMPL(fs_file_pos_append) {
+ fs_file_pos_append(0);
+ fs_file_pos_append(UV_FS_O_FILEMAP);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+#endif
+
TEST_IMPL(fs_null_req) {
/* Verify that all fs functions return UV_EINVAL when the request is NULL. */
int r;
@@ -3630,6 +3850,9 @@ TEST_IMPL(fs_null_req) {
r = uv_fs_futime(NULL, NULL, 0, 0.0, 0.0, NULL);
ASSERT(r == UV_EINVAL);
+ r = uv_fs_statfs(NULL, NULL, NULL, NULL);
+ ASSERT(r == UV_EINVAL);
+
/* This should be a no-op. */
uv_fs_req_cleanup(NULL);
@@ -3873,4 +4096,37 @@ TEST_IMPL(fs_fchmod_archive_readonly) {
return 0;
}
+
+TEST_IMPL(fs_invalid_mkdir_name) {
+ uv_loop_t* loop;
+ uv_fs_t req;
+ int r;
+
+ loop = uv_default_loop();
+ r = uv_fs_mkdir(loop, &req, "invalid>", 0, NULL);
+ ASSERT(r == UV_EINVAL);
+
+ return 0;
+}
#endif
+
+TEST_IMPL(fs_statfs) {
+ uv_fs_t req;
+ int r;
+
+ loop = uv_default_loop();
+
+ /* Test the synchronous version. */
+ r = uv_fs_statfs(NULL, &req, ".", NULL);
+ ASSERT(r == 0);
+ statfs_cb(&req);
+ ASSERT(statfs_cb_count == 1);
+
+ /* Test the asynchronous version. */
+ r = uv_fs_statfs(loop, &req, ".", statfs_cb);
+ ASSERT(r == 0);
+ uv_run(loop, UV_RUN_DEFAULT);
+ ASSERT(statfs_cb_count == 2);
+
+ return 0;
+}
diff --git a/deps/uv/test/test-ipc.c b/deps/uv/test/test-ipc.c
index 24c067e0a4..8579a47029 100644
--- a/deps/uv/test/test-ipc.c
+++ b/deps/uv/test/test-ipc.c
@@ -838,10 +838,10 @@ static unsigned int write_until_data_queued() {
closed_handle_large_write_cb);
ASSERT(r == 0);
i++;
- } while (((uv_stream_t*)&channel)->write_queue_size == 0 &&
+ } while (channel.write_queue_size == 0 &&
i < ARRAY_SIZE(write_reqs));
- return ((uv_stream_t*)&channel)->write_queue_size;
+ return channel.write_queue_size;
}
static void send_handle_and_close() {
diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h
index a48f6f3806..6eb8ecadc7 100644
--- a/deps/uv/test/test-list.h
+++ b/deps/uv/test/test-list.h
@@ -264,6 +264,7 @@ TEST_DECLARE (spawn_fails)
#ifndef _WIN32
TEST_DECLARE (spawn_fails_check_for_waitpid_cleanup)
#endif
+TEST_DECLARE (spawn_empty_env)
TEST_DECLARE (spawn_exit_code)
TEST_DECLARE (spawn_stdout)
TEST_DECLARE (spawn_stdin)
@@ -321,10 +322,15 @@ TEST_DECLARE (fs_symlink_dir)
#ifdef _WIN32
TEST_DECLARE (fs_symlink_junction)
TEST_DECLARE (fs_non_symlink_reparse_point)
+TEST_DECLARE (fs_open_flags)
+#endif
+#if defined(_WIN32) && !defined(USING_UV_SHARED)
+TEST_DECLARE (fs_fd_hash)
#endif
TEST_DECLARE (fs_utime)
TEST_DECLARE (fs_futime)
TEST_DECLARE (fs_file_open_append)
+TEST_DECLARE (fs_statfs)
TEST_DECLARE (fs_stat_missing_path)
TEST_DECLARE (fs_read_bufs)
TEST_DECLARE (fs_read_file_eof)
@@ -370,10 +376,13 @@ TEST_DECLARE (fs_file_pos_after_op_with_offset)
TEST_DECLARE (fs_null_req)
TEST_DECLARE (fs_read_dir)
#ifdef _WIN32
+TEST_DECLARE (fs_file_pos_write)
+TEST_DECLARE (fs_file_pos_append)
TEST_DECLARE (fs_exclusive_sharing_mode)
TEST_DECLARE (fs_file_flag_no_buffering)
TEST_DECLARE (fs_open_readonly_acl)
TEST_DECLARE (fs_fchmod_archive_readonly)
+TEST_DECLARE (fs_invalid_mkdir_name)
#endif
TEST_DECLARE (strscpy)
TEST_DECLARE (threadpool_queue_work_simple)
@@ -821,6 +830,7 @@ TASK_LIST_START
#ifndef _WIN32
TEST_ENTRY (spawn_fails_check_for_waitpid_cleanup)
#endif
+ TEST_ENTRY (spawn_empty_env)
TEST_ENTRY (spawn_exit_code)
TEST_ENTRY (spawn_stdout)
TEST_ENTRY (spawn_stdin)
@@ -912,7 +922,12 @@ TASK_LIST_START
#ifdef _WIN32
TEST_ENTRY (fs_symlink_junction)
TEST_ENTRY (fs_non_symlink_reparse_point)
+ TEST_ENTRY (fs_open_flags)
+#endif
+#if defined(_WIN32) && !defined(USING_UV_SHARED)
+ TEST_ENTRY (fs_fd_hash)
#endif
+ TEST_ENTRY (fs_statfs)
TEST_ENTRY (fs_stat_missing_path)
TEST_ENTRY (fs_read_bufs)
TEST_ENTRY (fs_read_file_eof)
@@ -957,10 +972,13 @@ TASK_LIST_START
TEST_ENTRY (fs_null_req)
TEST_ENTRY (fs_read_dir)
#ifdef _WIN32
+ TEST_ENTRY (fs_file_pos_write)
+ TEST_ENTRY (fs_file_pos_append)
TEST_ENTRY (fs_exclusive_sharing_mode)
TEST_ENTRY (fs_file_flag_no_buffering)
TEST_ENTRY (fs_open_readonly_acl)
TEST_ENTRY (fs_fchmod_archive_readonly)
+ TEST_ENTRY (fs_invalid_mkdir_name)
#endif
TEST_ENTRY (get_osfhandle_valid_handle)
TEST_ENTRY (open_osfhandle_valid_handle)
diff --git a/deps/uv/test/test-pipe-getsockname.c b/deps/uv/test/test-pipe-getsockname.c
index d1628a67d5..48ee400e74 100644
--- a/deps/uv/test/test-pipe-getsockname.c
+++ b/deps/uv/test/test-pipe-getsockname.c
@@ -171,7 +171,7 @@ TEST_IMPL(pipe_getsockname_abstract) {
socklen_t sun_len;
char abstract_pipe[] = "\0test-pipe";
- sock = socket(AF_LOCAL, SOCK_STREAM, 0);
+ sock = socket(AF_UNIX, SOCK_STREAM, 0);
ASSERT(sock != -1);
sun_len = sizeof sun;
diff --git a/deps/uv/test/test-process-title-threadsafe.c b/deps/uv/test/test-process-title-threadsafe.c
index 19098eda0c..5b30f17f44 100644
--- a/deps/uv/test/test-process-title-threadsafe.c
+++ b/deps/uv/test/test-process-title-threadsafe.c
@@ -25,7 +25,11 @@
#include <string.h>
-#define NUM_ITERATIONS 50
+#ifdef __APPLE__
+# define NUM_ITERATIONS 10
+#else
+# define NUM_ITERATIONS 50
+#endif
static const char* titles[] = {
"8L2NY0Kdj0XyNFZnmUZigIOfcWjyNr0SkMmUhKw99VLUsZFrvCQQC3XIRfNR8pjyMjXObllled",
diff --git a/deps/uv/test/test-queue-foreach-delete.c b/deps/uv/test/test-queue-foreach-delete.c
index 45da225381..049ea776e3 100644
--- a/deps/uv/test/test-queue-foreach-delete.c
+++ b/deps/uv/test/test-queue-foreach-delete.c
@@ -65,11 +65,11 @@ static const unsigned first_handle_number_fs_event = 0;
#endif
-#define DEFINE_GLOBALS_AND_CBS(name) \
+#define DEFINE_GLOBALS_AND_CBS(name, ...) \
static uv_##name##_t (name)[3]; \
static unsigned name##_cb_calls[3]; \
\
- static void name##2_cb(uv_##name##_t* handle) { \
+ static void name##2_cb(__VA_ARGS__) { \
ASSERT(handle == &(name)[2]); \
if (first_handle_number_##name == 2) { \
uv_close((uv_handle_t*)&(name)[2], NULL); \
@@ -78,12 +78,12 @@ static const unsigned first_handle_number_fs_event = 0;
name##_cb_calls[2]++; \
} \
\
- static void name##1_cb(uv_##name##_t* handle) { \
+ static void name##1_cb(__VA_ARGS__) { \
ASSERT(handle == &(name)[1]); \
ASSERT(0 && "Shouldn't be called" && (&name[0])); \
} \
\
- static void name##0_cb(uv_##name##_t* handle) { \
+ static void name##0_cb(__VA_ARGS__) { \
ASSERT(handle == &(name)[0]); \
if (first_handle_number_##name == 0) { \
uv_close((uv_handle_t*)&(name)[0], NULL); \
@@ -93,9 +93,9 @@ static const unsigned first_handle_number_fs_event = 0;
} \
\
static const uv_##name##_cb name##_cbs[] = { \
- (uv_##name##_cb)name##0_cb, \
- (uv_##name##_cb)name##1_cb, \
- (uv_##name##_cb)name##2_cb, \
+ name##0_cb, \
+ name##1_cb, \
+ name##2_cb, \
};
#define INIT_AND_START(name, loop) \
@@ -118,12 +118,16 @@ static const unsigned first_handle_number_fs_event = 0;
ASSERT(name##_cb_calls[2] == 1); \
} while (0)
-DEFINE_GLOBALS_AND_CBS(idle)
-DEFINE_GLOBALS_AND_CBS(prepare)
-DEFINE_GLOBALS_AND_CBS(check)
+DEFINE_GLOBALS_AND_CBS(idle, uv_idle_t* handle)
+DEFINE_GLOBALS_AND_CBS(prepare, uv_prepare_t* handle)
+DEFINE_GLOBALS_AND_CBS(check, uv_check_t* handle)
#ifdef __linux__
-DEFINE_GLOBALS_AND_CBS(fs_event)
+DEFINE_GLOBALS_AND_CBS(fs_event,
+ uv_fs_event_t* handle,
+ const char* filename,
+ int events,
+ int status)
static const char watched_dir[] = ".";
static uv_timer_t timer;
diff --git a/deps/uv/test/test-spawn.c b/deps/uv/test/test-spawn.c
index fea1165d89..fec610bfde 100644
--- a/deps/uv/test/test-spawn.c
+++ b/deps/uv/test/test-spawn.c
@@ -232,6 +232,34 @@ TEST_IMPL(spawn_fails_check_for_waitpid_cleanup) {
#endif
+TEST_IMPL(spawn_empty_env) {
+ char* env[1];
+
+ /* The autotools dynamic library build requires the presence of
+ * DYLD_LIBARY_PATH (macOS) or LD_LIBRARY_PATH (other Unices)
+ * in the environment, but of course that doesn't work with
+ * the empty environment that we're testing here.
+ */
+ if (NULL != getenv("DYLD_LIBARY_PATH") ||
+ NULL != getenv("LD_LIBRARY_PATH")) {
+ RETURN_SKIP("doesn't work with DYLD_LIBRARY_PATH/LD_LIBRARY_PATH");
+ }
+
+ init_process_options("spawn_helper1", exit_cb);
+ options.env = env;
+ env[0] = NULL;
+
+ ASSERT(0 == uv_spawn(uv_default_loop(), &process, &options));
+ ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
+
+ ASSERT(exit_cb_called == 1);
+ ASSERT(close_cb_called == 1);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+
TEST_IMPL(spawn_exit_code) {
int r;
diff --git a/deps/uv/test/test-tmpdir.c b/deps/uv/test/test-tmpdir.c
index 29e8055f1d..dac488d058 100644
--- a/deps/uv/test/test-tmpdir.c
+++ b/deps/uv/test/test-tmpdir.c
@@ -67,5 +67,16 @@ TEST_IMPL(tmpdir) {
r = uv_os_tmpdir(tmpdir, &len);
ASSERT(r == UV_EINVAL);
+#ifdef _WIN32
+ const char *name = "TMP";
+ char tmpdir_win[] = "C:\\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
+ r = uv_os_setenv(name, tmpdir_win);
+ ASSERT(r == 0);
+ char tmpdirx[PATHMAX];
+ size_t lenx = sizeof tmpdirx;
+ r = uv_os_tmpdir(tmpdirx, &lenx);
+ ASSERT(r == 0);
+#endif
+
return 0;
}
diff --git a/deps/uv/test/test.gyp b/deps/uv/test/test.gyp
index a4083e9178..6158a2b8b6 100644
--- a/deps/uv/test/test.gyp
+++ b/deps/uv/test/test.gyp
@@ -35,6 +35,8 @@
'test-fs-readdir.c',
'test-fs-copyfile.c',
'test-fs-event.c',
+ 'test-fs-fd-hash.c',
+ 'test-fs-open-flags.c',
'test-fs-poll.c',
'test-getters-setters.c',
'test-get-currentexe.c',