Browse Source

deps: update uv to v1.0.0-rc2

PR-URL: https://github.com/joyent/node/pull/8566
Reviewed-by: Fedor Indutny <fedor@indutny.com>
Reviewed-by: Trevor Norris <trev.norris@gmail.com>
v0.11.15-release
Saúl Ibarra Corretgé 11 years ago
committed by Trevor Norris
parent
commit
ce112c27c6
  1. 9
      deps/uv/AUTHORS
  2. 6
      deps/uv/CONTRIBUTING.md
  3. 42
      deps/uv/ChangeLog
  4. 9
      deps/uv/Makefile.am
  5. 4
      deps/uv/README.md
  6. 21
      deps/uv/configure.ac
  7. 30
      deps/uv/docs/src/fs.rst
  8. 4
      deps/uv/docs/src/fs_poll.rst
  9. 9
      deps/uv/docs/src/handle.rst
  10. 11
      deps/uv/docs/src/index.rst
  11. 4
      deps/uv/docs/src/loop.rst
  12. 244
      deps/uv/docs/src/migration_010_100.rst
  13. 10
      deps/uv/docs/src/process.rst
  14. 28
      deps/uv/docs/src/stream.rst
  15. 1
      deps/uv/docs/src/threading.rst
  16. 2
      deps/uv/include/uv-version.h
  17. 12
      deps/uv/include/uv-win.h
  18. 15
      deps/uv/include/uv.h
  19. 2
      deps/uv/src/unix/core.c
  20. 32
      deps/uv/src/unix/fs.c
  21. 5
      deps/uv/src/unix/thread.c
  22. 10
      deps/uv/src/uv-common.c
  23. 2
      deps/uv/src/uv-common.h
  24. 68
      deps/uv/src/win/fs.c
  25. 2
      deps/uv/src/win/poll.c
  26. 5
      deps/uv/src/win/thread.c
  27. 185
      deps/uv/src/win/util.c
  28. 237
      deps/uv/test/test-fs.c
  29. 14
      deps/uv/test/test-list.h
  30. 45
      deps/uv/test/test-thread-equal.c
  31. 2
      deps/uv/test/test-threadpool-cancel.c
  32. 1
      deps/uv/uv.gyp

9
deps/uv/AUTHORS

@ -157,3 +157,12 @@ John Firebaugh <john.firebaugh@gmail.com>
lilohuang <lilohuang@hotmail.com> lilohuang <lilohuang@hotmail.com>
Paul Goldsmith <paul.goldsmith@aplink.net> Paul Goldsmith <paul.goldsmith@aplink.net>
Julien Gilli <julien.gilli@joyent.com> Julien Gilli <julien.gilli@joyent.com>
Michael Hudson-Doyle <michael.hudson@linaro.org>
Recep ASLANTAS <m@recp.me>
Rob Adams <readams@readams.net>
Zachary Newman <znewman01@gmail.com>
Robin Hahling <robin.hahling@gw-computing.net>
Jeff Widman <jeff@jeffwidman.com>
cjihrig <cjihrig@gmail.com>
Tomasz Kołodziejski <tkolodziejski@mozilla.com>
Unknown W. Brackets <checkins@unknownbrackets.org>

6
deps/uv/CONTRIBUTING.md

@ -37,10 +37,10 @@ Okay, so you have decided on the proper branch. Create a feature branch
and start hacking: and start hacking:
``` ```
$ git checkout -b my-feature-branch -t origin/v0.10 $ git checkout -b my-feature-branch -t origin/v1.x
``` ```
(Where v0.10 is the latest stable branch as of this writing.) (Where v1.x is the latest stable branch as of this writing.)
### CODE ### CODE
@ -131,7 +131,7 @@ Use `git rebase` (not `git merge`) to sync your work from time to time.
``` ```
$ git fetch upstream $ git fetch upstream
$ git rebase upstream/v0.10 # or upstream/master $ git rebase upstream/v1.x # or upstream/master
``` ```

42
deps/uv/ChangeLog

@ -1,5 +1,47 @@
2014.10.21, Version 1.0.0-rc2 (Pre-release)
Changes since version 1.0.0-rc1:
* build: add missing fixtures to distribution tarball (Rob Adams)
* doc: update references to current stable branch (Zachary Newman)
* fs: fix readdir on empty directory (Fedor Indutny)
* fs: rename uv_fs_readdir to uv_fs_scandir (Saúl Ibarra Corretgé)
* doc: document uv_alloc_cb (Saúl Ibarra Corretgé)
* doc: add migration guide from version 0.10 (Saúl Ibarra Corretgé)
* build: add DragonFly BSD support in autotools (Robin Hahling)
* doc: document missing stream related structures (Saúl Ibarra Corretgé)
* doc: clarify uv_loop_t.data field lifetime (Saúl Ibarra Corretgé)
* doc: add documentation for missing functions and structures (Saúl Ibarra
Corretgé)
* doc: fix punctuation and grammar in README (Jeff Widman)
* windows: return libuv error codes in uv_poll_init() (cjihrig)
* unix, windows: add uv_fs_access() (cjihrig)
* windows: fix netmask detection (Alexis Campailla)
* unix, windows: don't include null byte in uv_cwd size (Saúl Ibarra Corretgé)
* unix, windows: add uv_thread_equal (Tomasz Kołodziejski)
* windows: fix fs_write with nbufs > 1 and offset (Unknown W. Brackets)
2014.09.18, Version 1.0.0-rc1 (Unstable), 0c28bbf7b42882853d1799ab96ff68b07f7f8d49 2014.09.18, Version 1.0.0-rc1 (Unstable), 0c28bbf7b42882853d1799ab96ff68b07f7f8d49
Changes since version 0.11.29:
* windows: improve timer precision (Alexis Campailla) * windows: improve timer precision (Alexis Campailla)
* build, gyp: set xcode flags (Recep ASLANTAS) * build, gyp: set xcode flags (Recep ASLANTAS)

9
deps/uv/Makefile.am

@ -106,6 +106,9 @@ libuv_la_SOURCES += src/unix/async.c \
endif # WINNT endif # WINNT
EXTRA_DIST = test/fixtures/empty_file \
test/fixtures/load_error.node
TESTS = test/run-tests TESTS = test/run-tests
check_PROGRAMS = test/run-tests check_PROGRAMS = test/run-tests
test_run_tests_CFLAGS = test_run_tests_CFLAGS =
@ -203,6 +206,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-tcp-writealot.c \ test/test-tcp-writealot.c \
test/test-tcp-try-write.c \ test/test-tcp-try-write.c \
test/test-tcp-write-queue-order.c \ test/test-tcp-write-queue-order.c \
test/test-thread-equal.c \
test/test-thread.c \ test/test-thread.c \
test/test-threadpool-cancel.c \ test/test-threadpool-cancel.c \
test/test-threadpool.c \ test/test-threadpool.c \
@ -268,6 +272,11 @@ libuv_la_SOURCES += src/unix/darwin.c \
src/unix/proctitle.c src/unix/proctitle.c
endif endif
if DRAGONFLY
include_HEADERS += include/uv-bsd.h
libuv_la_SOURCES += src/unix/kqueue.c src/unix/freebsd.c
endif
if FREEBSD if FREEBSD
include_HEADERS += include/uv-bsd.h include_HEADERS += include/uv-bsd.h
libuv_la_SOURCES += src/unix/freebsd.c src/unix/kqueue.c libuv_la_SOURCES += src/unix/freebsd.c src/unix/kqueue.c

4
deps/uv/README.md

@ -85,7 +85,7 @@ Documentation can be browsed online [here](http://docs.libuv.org).
## Build Instructions ## Build Instructions
For GCC there are two methods building: via autotools or via [GYP][]. For GCC there are two build methods: via autotools or via [GYP][].
GYP is a meta-build system which can generate MSVS, Makefile, and XCode GYP is a meta-build system which can generate MSVS, Makefile, and XCode
backends. It is best used for integration into other projects. backends. It is best used for integration into other projects.
@ -100,7 +100,7 @@ To build with autotools:
### Windows ### Windows
First, [Python][] 2.6 or 2.7 must be installed as it is required by [GYP][]. First, [Python][] 2.6 or 2.7 must be installed as it is required by [GYP][].
If python is not in your path set the environment variable `PYTHON` to its If python is not in your path, set the environment variable `PYTHON` to its
location. For example: `set PYTHON=C:\Python27\python.exe` location. For example: `set PYTHON=C:\Python27\python.exe`
To build with Visual Studio, launch a git shell (e.g. Cmd or PowerShell) To build with Visual Studio, launch a git shell (e.g. Cmd or PowerShell)

21
deps/uv/configure.ac

@ -13,7 +13,7 @@
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
AC_PREREQ(2.57) AC_PREREQ(2.57)
AC_INIT([libuv], [1.0.0], [https://github.com/joyent/libuv/issues]) AC_INIT([libuv], [1.0.0-rc2], [https://github.com/joyent/libuv/issues])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])
m4_include([m4/libuv-extra-automake-flags.m4]) m4_include([m4/libuv-extra-automake-flags.m4])
m4_include([m4/as_case.m4]) m4_include([m4/as_case.m4])
@ -40,15 +40,16 @@ AC_CHECK_LIB([rt], [clock_gettime])
AC_CHECK_LIB([sendfile], [sendfile]) AC_CHECK_LIB([sendfile], [sendfile])
AC_CHECK_LIB([socket], [socket]) AC_CHECK_LIB([socket], [socket])
AC_SYS_LARGEFILE AC_SYS_LARGEFILE
AM_CONDITIONAL([AIX], [AS_CASE([$host_os],[aix*], [true], [false])]) AM_CONDITIONAL([AIX], [AS_CASE([$host_os],[aix*], [true], [false])])
AM_CONDITIONAL([ANDROID],[AS_CASE([$host_os],[linux-android*],[true], [false])]) AM_CONDITIONAL([ANDROID], [AS_CASE([$host_os],[linux-android*],[true], [false])])
AM_CONDITIONAL([DARWIN], [AS_CASE([$host_os],[darwin*], [true], [false])]) AM_CONDITIONAL([DARWIN], [AS_CASE([$host_os],[darwin*], [true], [false])])
AM_CONDITIONAL([FREEBSD],[AS_CASE([$host_os],[freebsd*], [true], [false])]) AM_CONDITIONAL([DRAGONFLY],[AS_CASE([$host_os],[dragonfly*], [true], [false])])
AM_CONDITIONAL([LINUX], [AS_CASE([$host_os],[linux*], [true], [false])]) AM_CONDITIONAL([FREEBSD], [AS_CASE([$host_os],[freebsd*], [true], [false])])
AM_CONDITIONAL([NETBSD], [AS_CASE([$host_os],[netbsd*], [true], [false])]) AM_CONDITIONAL([LINUX], [AS_CASE([$host_os],[linux*], [true], [false])])
AM_CONDITIONAL([OPENBSD],[AS_CASE([$host_os],[openbsd*], [true], [false])]) AM_CONDITIONAL([NETBSD], [AS_CASE([$host_os],[netbsd*], [true], [false])])
AM_CONDITIONAL([SUNOS], [AS_CASE([$host_os],[solaris*], [true], [false])]) AM_CONDITIONAL([OPENBSD], [AS_CASE([$host_os],[openbsd*], [true], [false])])
AM_CONDITIONAL([WINNT], [AS_CASE([$host_os],[mingw*], [true], [false])]) AM_CONDITIONAL([SUNOS], [AS_CASE([$host_os],[solaris*], [true], [false])])
AM_CONDITIONAL([WINNT], [AS_CASE([$host_os],[mingw*], [true], [false])])
PANDORA_ENABLE_DTRACE PANDORA_ENABLE_DTRACE
AC_CHECK_PROG(PKG_CONFIG, pkg-config, yes) AC_CHECK_PROG(PKG_CONFIG, pkg-config, yes)
AM_CONDITIONAL([HAVE_PKG_CONFIG], [test "x$PKG_CONFIG" != "x"]) AM_CONDITIONAL([HAVE_PKG_CONFIG], [test "x$PKG_CONFIG" != "x"])

30
deps/uv/docs/src/fs.rst

@ -20,9 +20,20 @@ Data types
Filesystem request type. Filesystem request type.
.. c:type:: uv_timespec_t
Portable equivalent of ``struct timespec``.
::
typedef struct {
long tv_sec;
long tv_nsec;
} uv_timespec_t;
.. c:type:: uv_stat_t .. c:type:: uv_stat_t
Portable equivalent of `struct stat`. Portable equivalent of ``struct stat``.
:: ::
@ -65,6 +76,7 @@ Data types
UV_FS_FTRUNCATE, UV_FS_FTRUNCATE,
UV_FS_UTIME, UV_FS_UTIME,
UV_FS_FUTIME, UV_FS_FUTIME,
UV_FS_ACCESS,
UV_FS_CHMOD, UV_FS_CHMOD,
UV_FS_FCHMOD, UV_FS_FCHMOD,
UV_FS_FSYNC, UV_FS_FSYNC,
@ -74,7 +86,7 @@ Data types
UV_FS_MKDIR, UV_FS_MKDIR,
UV_FS_MKDTEMP, UV_FS_MKDTEMP,
UV_FS_RENAME, UV_FS_RENAME,
UV_FS_READDIR, UV_FS_SCANDIR,
UV_FS_LINK, UV_FS_LINK,
UV_FS_SYMLINK, UV_FS_SYMLINK,
UV_FS_READLINK, UV_FS_READLINK,
@ -85,7 +97,7 @@ Data types
.. c:type:: uv_dirent_t .. c:type:: uv_dirent_t
Cross platform (reduced) equivalent of ``struct dirent``. Cross platform (reduced) equivalent of ``struct dirent``.
Used in :c:func:`uv_fs_readdir_next`. Used in :c:func:`uv_fs_scandir_next`.
:: ::
@ -183,11 +195,11 @@ API
Equivalent to ``rmdir(2)``. Equivalent to ``rmdir(2)``.
.. c:function:: int uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, uv_fs_cb cb) .. c:function:: int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, uv_fs_cb cb)
.. c:function:: int uv_fs_readdir_next(uv_fs_t* req, uv_dirent_t* ent) .. c:function:: int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent)
Equivalent to ``readdir(2)``, with a slightly different API. Once the callback Equivalent to ``scandir(3)``, with a slightly different API. Once the callback
for the request is called, the user can use :c:func:`uv_fs_readdir_next` to for the request is called, the user can use :c:func:`uv_fs_scandir_next` to
get `ent` populated with the next directory entry data. When there are no get `ent` populated with the next directory entry data. When there are no
more entries ``UV_EOF`` will be returned. more entries ``UV_EOF`` will be returned.
@ -217,6 +229,10 @@ API
Limited equivalent to ``sendfile(2)``. Limited equivalent to ``sendfile(2)``.
.. c:function:: int uv_fs_access(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, uv_fs_cb cb)
Equivalent to ``access(2)`` on Unix. Windows uses ``GetFileAttributesW()``.
.. c:function:: int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb) .. c:function:: int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb)
.. c:function:: int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file file, int mode, uv_fs_cb cb) .. c:function:: int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file file, int mode, uv_fs_cb cb)

4
deps/uv/docs/src/fs_poll.rst

@ -42,6 +42,10 @@ N/A
API API
--- ---
.. c:function:: int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle)
Initialize the handle.
.. c:function:: int uv_fs_poll_start(uv_fs_poll_t* handle, uv_fs_poll_cb poll_cb, const char* path, unsigned int interval) .. c:function:: int uv_fs_poll_start(uv_fs_poll_t* handle, uv_fs_poll_cb poll_cb, const char* path, unsigned int interval)
Check the file at `path` for changes every `interval` milliseconds. Check the file at `path` for changes every `interval` milliseconds.

9
deps/uv/docs/src/handle.rst

@ -21,6 +21,15 @@ Data types
Union of all handle types. Union of all handle types.
.. c:type:: void (*uv_alloc_cb)(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf)
Type definition for callback passed to :c:func:`uv_read_start` and
:c:func:`uv_udp_recv_start`. The user must fill the supplied :c:type:`uv_buf_t`
structure with whatever size, as long as it's > 0. A suggested size (65536 at the moment)
is provided, but it doesn't need to be honored. Setting the buffer's length to 0
will trigger a ``UV_ENOBUFS`` error in the :c:type:`uv_udp_recv_cb` or
:c:type:`uv_read_cb` callback.
.. c:type:: void (*uv_close_cb)(uv_handle_t* handle) .. c:type:: void (*uv_close_cb)(uv_handle_t* handle)
Type definition for callback passed to :c:func:`uv_close`. Type definition for callback passed to :c:func:`uv_close`.

11
deps/uv/docs/src/index.rst

@ -50,6 +50,17 @@ Installation
Installation instructions can be found on `the README <https://github.com/joyent/libuv/blob/master/README.md>`_. Installation instructions can be found on `the README <https://github.com/joyent/libuv/blob/master/README.md>`_.
Upgrading
---------
Migration guides for different libuv versions, starting with 1.0.
.. toctree::
:maxdepth: 1
migration_010_100
Documentation Documentation
------------- -------------

4
deps/uv/docs/src/loop.rst

@ -38,7 +38,9 @@ Public members
.. c:member:: void* uv_loop_t.data .. c:member:: void* uv_loop_t.data
Space for user-defined arbitrary data. libuv does not use this field. Space for user-defined arbitrary data. libuv does not use this field. libuv does, however,
initialize it to NULL in :c:func:`uv_loop_init`, and it poisons the value (on debug builds)
on :c:func:`uv_loop_close`.
API API

244
deps/uv/docs/src/migration_010_100.rst

@ -0,0 +1,244 @@
.. _migration_010_100:
libuv 0.10 -> 1.0.0 migration guide
===================================
Some APIs changed quite a bit throughout the 1.0.0 development process. Here
is a migration guide for the most significant changes that happened after 0.10
was released.
Loop initialization and closing
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In libuv 0.10 (and previous versions), loops were created with `uv_loop_new`, which
allocated memory for a new loop and initialized it; and destroyed with `uv_loop_delete`,
which destroyed the loop and freed the memory. Starting with 1.0, those are deprecated
and the user is responsible for allocating the memory and then initializing the loop.
libuv 0.10
::
uv_loop_t* loop = uv_loop_new();
...
uv_loop_delete(loop);
libuv 1.0
::
uv_loop_t* loop = malloc(sizeof *loop);
uv_loop_init(loop);
...
uv_loop_close(loop);
free(loop);
.. note::
Error handling was omitted for brevity. Check the documentation for :c:func:`uv_loop_init`
and :c:func:`uv_loop_close`.
Error handling
~~~~~~~~~~~~~~
Error handling had a major overhaul in libuv 1.0. In general, functions and status parameters
would get 0 for success and -1 for failure on libuv 0.10, and the user had to use `uv_last_error`
to fetch the error code, which was a positive number.
In 1.0, functions and status parameters contain the actual error code, which is 0 for success, or
a negative number in case of error.
libuv 0.10
::
... assume 'server' is a TCP server which is already listening
r = uv_listen((uv_stream_t*) server, 511, NULL);
if (r == -1) {
uv_err_t err = uv_last_error(uv_default_loop());
/* err.code contains UV_EADDRINUSE */
}
libuv 1.0
::
... assume 'server' is a TCP server which is already listening
r = uv_listen((uv_stream_t*) server, 511, NULL);
if (r < 0) {
/* r contains UV_EADDRINUSE */
}
Threadpool changes
~~~~~~~~~~~~~~~~~~
In libuv 0.10 Unix used a threadpool which defaulted to 4 threads, while Windows used the
`QueueUserWorkItem` API, which uses a Windows internal threadpool, which defaults to 512
threads per process.
In 1.0, we unified both implementations, so Windows now uses the same implementation Unix
does. The threadppol size can be set by exporting the ``UV_THREADPOOL_SIZE`` environment
variable. See :c:ref:`threadpool`.
Allocation callback API change
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In libuv 0.10 the callback had to return a filled :c:type:`uv_buf_t` by value:
::
uv_buf_t alloc_cb(uv_handle_t* handle, size_t size) {
return uv_buf_init(malloc(size), size);
}
In libuv 1.0 a pointer to a buffer is passed to the callbck, which the user
needs to fill:
::
void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) {
buf->base = malloc(size);
buf->len = size;
}
Unification of IPv4 / IPv6 APIs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
libuv 1.0 unified the IPv4 and IPv6 APIS. There is no longer a `uv_tcp_bind` and `uv_tcp_bind6`
duality, there is only :c:func:`uv_tcp_bind` now.
IPv4 functions took ``struct sockaddr_in`` structures by value, and IPv6 functions took
``struct sockaddr_in6``. Now functions take a ``struct sockaddr*`` (note it's a pointer).
It can be stack allocated.
libuv 0.10
::
struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", 1234);
...
uv_tcp_bind(&server, addr)
libuv 1.0
::
struct sockaddr_in addr;
uv_ip4_addr("0.0.0.0", 1234, &addr)
...
uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0);
The IPv4 and IPv6 struct creating functions (:c:func:`uv_ip4_addr` and :c:func:`uv_ip6_addr`)
have also changed, make sure you check the documentation.
..note::
This change applies to all functions that made a distinction between IPv4 and IPv6
addresses.
Streams / UDP data receive callback API change
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The streams and UDP data receive callbacks now get a pointer to a :c:type:`uv_buf_t` buffer,
not a structure by value.
libuv 0.10
::
void on_read(uv_stream_t* handle,
ssize_t nread,
uv_buf_t buf) {
...
}
void recv_cb(uv_udp_t* handle,
ssize_t nread,
uv_buf_t buf,
struct sockaddr* addr,
unsigned flags) {
...
}
libuv 1.0
::
void on_read(uv_stream_t* handle,
ssize_t nread,
const uv_buf_t* buf) {
...
}
void recv_cb(uv_udp_t* handle,
ssize_t nread,
const uv_buf_t* buf,
const struct sockaddr* addr,
unsigned flags) {
...
}
Receiving handles over pipes API change
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In libuv 0.10 (and earlier versions) the `uv_read2_start` function was used to start reading
data on a pipe, which could also result in the reception of handles over it. The callback
for such function looked like this:
::
void on_read(uv_pipe_t* pipe,
ssize_t nread,
uv_buf_t buf,
uv_handle_type pending) {
...
}
In libuv 1.0, `uv_read2_start` was removed, and the user needs to check if there are penging
handles using :c:func:`uv_pipe_pending_count` and :c:func:`uv_pipe_pending_type` while in
the read callback:
::
void on_read(uv_stream_t* handle,
ssize_t nread,
const uv_buf_t* buf) {
...
while (uv_pipe_pending_count((uv_pipe_t*) handle) != 0) {
pending = uv_pipe_pending_type((uv_pipe_t*) handle);
...
}
...
}
Extracting the file descriptor out of a handle
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
While it wasn't supported by the API, users often accessed the libuv internals in
order to get access to the file descript of a TCP handle, for example.
::
fd = handle->io_watcher.fd;
This is now properly exposed through the :c:func:`uv_fileno` function.
uv_fs_readdir rename and API change
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`uv_fs_readdir` returned a list of strings in the `req->ptr` field upon completion in
libuv 0.10. In 1.0, this function got renamed to :c:func:`uv_fs_scandir`, since it's
actually implemented using ``scandir(3)``.
In addition, instead of allocating a full list strings, the user is able to get one
result at a time by using the :c:func:`uv_fs_scandir_next` function. This function
does not need to make a roundtrip to the threadpool, because libuv will keep the
list of *dents* returned by ``scandir(3)`` around.

10
deps/uv/docs/src/process.rst

@ -212,4 +212,14 @@ API
setgid specified, or not having enough memory to allocate for the new setgid specified, or not having enough memory to allocate for the new
process. process.
.. c:function:: int uv_process_kill(uv_process_t* handle, int signum)
Sends the specified signal to the given process handle. Check the documentation
on :c:ref:`signal` for signal support, specially on Windows.
.. c:function:: int uv_kill(int pid, int signum)
Sends the specified signal to the given PID. Check the documentation
on :c:ref:`signal` for signal support, specially on Windows.
.. seealso:: The :c:type:`uv_handle_t` API functions also apply. .. seealso:: The :c:type:`uv_handle_t` API functions also apply.

28
deps/uv/docs/src/stream.rst

@ -16,6 +16,18 @@ Data types
Stream handle type. Stream handle type.
.. c:type:: uv_connect_t
Connect request type.
.. c:type:: uv_shutdown_t
Shutdown request type.
.. c:type:: uv_write_t
Write request type.
.. c:type:: void (*uv_read_cb)(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) .. c:type:: void (*uv_read_cb)(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf)
Callback called when data was read on a stream. Callback called when data was read on a stream.
@ -60,6 +72,22 @@ Public members
Contains the amount of queued bytes waiting to be sent. Readonly. Contains the amount of queued bytes waiting to be sent. Readonly.
.. c:member:: uv_stream_t* uv_connect_t.handle
Pointer to the stream where this connection request is running.
.. c:member:: uv_stream_t* uv_shutdown_t.handle
Pointer to the stream where this shutdown request is running.
.. c:member:: uv_stream_t* uv_write_t.handle
Pointer to the stream where this write request is running.
.. c:member:: uv_stream_t* uv_write_t.send_handle
Pointer to the stream being sent using this write request..
.. seealso:: The :c:type:`uv_handle_t` members also apply. .. seealso:: The :c:type:`uv_handle_t` members also apply.

1
deps/uv/docs/src/threading.rst

@ -58,6 +58,7 @@ Threads
.. c:function:: int uv_thread_create(uv_thread_t* tid, uv_thread_cb entry, void* arg) .. c:function:: int uv_thread_create(uv_thread_t* tid, uv_thread_cb entry, void* arg)
.. c:function:: unsigned long uv_thread_self(void) .. c:function:: unsigned long uv_thread_self(void)
.. c:function:: int uv_thread_join(uv_thread_t *tid) .. c:function:: int uv_thread_join(uv_thread_t *tid)
.. c:function:: int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2)
Thread-local storage Thread-local storage
^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^

2
deps/uv/include/uv-version.h

@ -34,6 +34,6 @@
#define UV_VERSION_MINOR 0 #define UV_VERSION_MINOR 0
#define UV_VERSION_PATCH 0 #define UV_VERSION_PATCH 0
#define UV_VERSION_IS_RELEASE 1 #define UV_VERSION_IS_RELEASE 1
#define UV_VERSION_SUFFIX "rc1" #define UV_VERSION_SUFFIX "rc2"
#endif /* UV_VERSION_H */ #endif /* UV_VERSION_H */

12
deps/uv/include/uv-win.h

@ -639,3 +639,15 @@ int uv_utf16_to_utf8(const WCHAR* utf16Buffer, size_t utf16Size,
int uv_utf8_to_utf16(const char* utf8Buffer, WCHAR* utf16Buffer, int uv_utf8_to_utf16(const char* utf8Buffer, WCHAR* utf16Buffer,
size_t utf16Size); size_t utf16Size);
#ifndef F_OK
#define F_OK 0
#endif
#ifndef R_OK
#define R_OK 4
#endif
#ifndef W_OK
#define W_OK 2
#endif
#ifndef X_OK
#define X_OK 1
#endif

15
deps/uv/include/uv.h

@ -1022,6 +1022,7 @@ typedef enum {
UV_FS_FTRUNCATE, UV_FS_FTRUNCATE,
UV_FS_UTIME, UV_FS_UTIME,
UV_FS_FUTIME, UV_FS_FUTIME,
UV_FS_ACCESS,
UV_FS_CHMOD, UV_FS_CHMOD,
UV_FS_FCHMOD, UV_FS_FCHMOD,
UV_FS_FSYNC, UV_FS_FSYNC,
@ -1031,7 +1032,7 @@ typedef enum {
UV_FS_MKDIR, UV_FS_MKDIR,
UV_FS_MKDTEMP, UV_FS_MKDTEMP,
UV_FS_RENAME, UV_FS_RENAME,
UV_FS_READDIR, UV_FS_SCANDIR,
UV_FS_LINK, UV_FS_LINK,
UV_FS_SYMLINK, UV_FS_SYMLINK,
UV_FS_READLINK, UV_FS_READLINK,
@ -1094,12 +1095,12 @@ UV_EXTERN int uv_fs_rmdir(uv_loop_t* loop,
uv_fs_t* req, uv_fs_t* req,
const char* path, const char* path,
uv_fs_cb cb); uv_fs_cb cb);
UV_EXTERN int uv_fs_readdir(uv_loop_t* loop, UV_EXTERN int uv_fs_scandir(uv_loop_t* loop,
uv_fs_t* req, uv_fs_t* req,
const char* path, const char* path,
int flags, int flags,
uv_fs_cb cb); uv_fs_cb cb);
UV_EXTERN int uv_fs_readdir_next(uv_fs_t* req, UV_EXTERN int uv_fs_scandir_next(uv_fs_t* req,
uv_dirent_t* ent); uv_dirent_t* ent);
UV_EXTERN int uv_fs_stat(uv_loop_t* loop, UV_EXTERN int uv_fs_stat(uv_loop_t* loop,
uv_fs_t* req, uv_fs_t* req,
@ -1134,6 +1135,11 @@ UV_EXTERN int uv_fs_sendfile(uv_loop_t* loop,
int64_t in_offset, int64_t in_offset,
size_t length, size_t length,
uv_fs_cb cb); uv_fs_cb cb);
UV_EXTERN int uv_fs_access(uv_loop_t* loop,
uv_fs_t* req,
const char* path,
int flags,
uv_fs_cb cb);
UV_EXTERN int uv_fs_chmod(uv_loop_t* loop, UV_EXTERN int uv_fs_chmod(uv_loop_t* loop,
uv_fs_t* req, uv_fs_t* req,
const char* path, const char* path,
@ -1363,8 +1369,9 @@ UV_EXTERN void uv_key_set(uv_key_t* key, void* value);
typedef void (*uv_thread_cb)(void* arg); typedef void (*uv_thread_cb)(void* arg);
UV_EXTERN int uv_thread_create(uv_thread_t* tid, uv_thread_cb entry, void* arg); UV_EXTERN int uv_thread_create(uv_thread_t* tid, uv_thread_cb entry, void* arg);
UV_EXTERN unsigned long uv_thread_self(void); UV_EXTERN uv_thread_t uv_thread_self(void);
UV_EXTERN int uv_thread_join(uv_thread_t *tid); UV_EXTERN int uv_thread_join(uv_thread_t *tid);
UV_EXTERN int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2);
/* The presence of these unions force similar struct layout. */ /* The presence of these unions force similar struct layout. */
#define XX(_, name) uv_ ## name ## _t name; #define XX(_, name) uv_ ## name ## _t name;

2
deps/uv/src/unix/core.c

@ -637,7 +637,7 @@ int uv_cwd(char* buffer, size_t* size) {
if (getcwd(buffer, *size) == NULL) if (getcwd(buffer, *size) == NULL)
return -errno; return -errno;
*size = strlen(buffer) + 1; *size = strlen(buffer);
return 0; return 0;
} }

32
deps/uv/src/unix/fs.c

@ -295,22 +295,21 @@ done:
#if defined(__OpenBSD__) || (defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_8)) #if defined(__OpenBSD__) || (defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_8))
static int uv__fs_readdir_filter(uv__dirent_t* dent) { static int uv__fs_scandir_filter(uv__dirent_t* dent) {
#else #else
static int uv__fs_readdir_filter(const uv__dirent_t* dent) { static int uv__fs_scandir_filter(const uv__dirent_t* dent) {
#endif #endif
return strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0; return strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0;
} }
/* This should have been called uv__fs_scandir(). */ static ssize_t uv__fs_scandir(uv_fs_t* req) {
static ssize_t uv__fs_readdir(uv_fs_t* req) {
uv__dirent_t **dents; uv__dirent_t **dents;
int saved_errno; int saved_errno;
int n; int n;
dents = NULL; dents = NULL;
n = scandir(req->path, &dents, uv__fs_readdir_filter, alphasort); n = scandir(req->path, &dents, uv__fs_scandir_filter, alphasort);
/* NOTE: We will use nbufs as an index field */ /* NOTE: We will use nbufs as an index field */
req->nbufs = 0; req->nbufs = 0;
@ -764,6 +763,7 @@ static void uv__fs_work(struct uv__work* w) {
break; break;
switch (req->fs_type) { switch (req->fs_type) {
X(ACCESS, access(req->path, req->flags));
X(CHMOD, chmod(req->path, req->mode)); X(CHMOD, chmod(req->path, req->mode));
X(CHOWN, chown(req->path, req->uid, req->gid)); X(CHOWN, chown(req->path, req->uid, req->gid));
X(CLOSE, close(req->file)); X(CLOSE, close(req->file));
@ -779,7 +779,7 @@ static void uv__fs_work(struct uv__work* w) {
X(MKDIR, mkdir(req->path, req->mode)); X(MKDIR, mkdir(req->path, req->mode));
X(MKDTEMP, uv__fs_mkdtemp(req)); X(MKDTEMP, uv__fs_mkdtemp(req));
X(READ, uv__fs_read(req)); X(READ, uv__fs_read(req));
X(READDIR, uv__fs_readdir(req)); X(SCANDIR, uv__fs_scandir(req));
X(READLINK, uv__fs_readlink(req)); X(READLINK, uv__fs_readlink(req));
X(RENAME, rename(req->path, req->new_path)); X(RENAME, rename(req->path, req->new_path));
X(RMDIR, rmdir(req->path)); X(RMDIR, rmdir(req->path));
@ -854,6 +854,18 @@ static void uv__fs_done(struct uv__work* w, int status) {
} }
int uv_fs_access(uv_loop_t* loop,
uv_fs_t* req,
const char* path,
int flags,
uv_fs_cb cb) {
INIT(ACCESS);
PATH;
req->flags = flags;
POST;
}
int uv_fs_chmod(uv_loop_t* loop, int uv_fs_chmod(uv_loop_t* loop,
uv_fs_t* req, uv_fs_t* req,
const char* path, const char* path,
@ -1040,12 +1052,12 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req,
} }
int uv_fs_readdir(uv_loop_t* loop, int uv_fs_scandir(uv_loop_t* loop,
uv_fs_t* req, uv_fs_t* req,
const char* path, const char* path,
int flags, int flags,
uv_fs_cb cb) { uv_fs_cb cb) {
INIT(READDIR); INIT(SCANDIR);
PATH; PATH;
req->flags = flags; req->flags = flags;
POST; POST;
@ -1167,8 +1179,8 @@ void uv_fs_req_cleanup(uv_fs_t* req) {
req->path = NULL; req->path = NULL;
req->new_path = NULL; req->new_path = NULL;
if (req->fs_type == UV_FS_READDIR && req->ptr != NULL) if (req->fs_type == UV_FS_SCANDIR && req->ptr != NULL)
uv__fs_readdir_cleanup(req); uv__fs_scandir_cleanup(req);
if (req->ptr != &req->statbuf) if (req->ptr != &req->statbuf)
free(req->ptr); free(req->ptr);

5
deps/uv/src/unix/thread.c

@ -36,6 +36,11 @@ int uv_thread_join(uv_thread_t *tid) {
} }
int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) {
return pthread_equal(*t1, *t2);
}
int uv_mutex_init(uv_mutex_t* mutex) { int uv_mutex_init(uv_mutex_t* mutex) {
#if defined(NDEBUG) || !defined(PTHREAD_MUTEX_ERRORCHECK) #if defined(NDEBUG) || !defined(PTHREAD_MUTEX_ERRORCHECK)
return -pthread_mutex_init(mutex, NULL); return -pthread_mutex_init(mutex, NULL);

10
deps/uv/src/uv-common.c

@ -306,11 +306,11 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
} }
unsigned long uv_thread_self(void) { uv_thread_t uv_thread_self(void) {
#ifdef _WIN32 #ifdef _WIN32
return (unsigned long) GetCurrentThreadId(); return GetCurrentThreadId();
#else #else
return (unsigned long) pthread_self(); return pthread_self();
#endif #endif
} }
@ -437,7 +437,7 @@ int uv_fs_event_getpath(uv_fs_event_t* handle, char* buf, size_t* len) {
} }
void uv__fs_readdir_cleanup(uv_fs_t* req) { void uv__fs_scandir_cleanup(uv_fs_t* req) {
uv__dirent_t** dents; uv__dirent_t** dents;
dents = req->ptr; dents = req->ptr;
@ -448,7 +448,7 @@ void uv__fs_readdir_cleanup(uv_fs_t* req) {
} }
int uv_fs_readdir_next(uv_fs_t* req, uv_dirent_t* ent) { int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) {
uv__dirent_t** dents; uv__dirent_t** dents;
uv__dirent_t* dent; uv__dirent_t* dent;

2
deps/uv/src/uv-common.h

@ -109,7 +109,7 @@ size_t uv__count_bufs(const uv_buf_t bufs[], unsigned int nbufs);
int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value); int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value);
void uv__fs_readdir_cleanup(uv_fs_t* req); void uv__fs_scandir_cleanup(uv_fs_t* req);
#define uv__has_active_reqs(loop) \ #define uv__has_active_reqs(loop) \
(QUEUE_EMPTY(&(loop)->active_reqs) == 0) (QUEUE_EMPTY(&(loop)->active_reqs) == 0)

68
deps/uv/src/win/fs.c

@ -613,11 +613,6 @@ void fs__write(uv_fs_t* req) {
if (offset != -1) { if (offset != -1) {
memset(&overlapped, 0, sizeof overlapped); memset(&overlapped, 0, sizeof overlapped);
offset_.QuadPart = offset;
overlapped.Offset = offset_.LowPart;
overlapped.OffsetHigh = offset_.HighPart;
overlapped_ptr = &overlapped; overlapped_ptr = &overlapped;
} else { } else {
overlapped_ptr = NULL; overlapped_ptr = NULL;
@ -627,6 +622,14 @@ void fs__write(uv_fs_t* req) {
bytes = 0; bytes = 0;
do { do {
DWORD incremental_bytes; DWORD incremental_bytes;
/* WriteFile() does not advance overlapped as ReadFile() does. */
if (offset != -1) {
offset_.QuadPart = offset + bytes;
overlapped.Offset = offset_.LowPart;
overlapped.OffsetHigh = offset_.HighPart;
}
result = WriteFile(handle, result = WriteFile(handle,
req->bufs[index].base, req->bufs[index].base,
req->bufs[index].len, req->bufs[index].len,
@ -783,7 +786,7 @@ void fs__mkdtemp(uv_fs_t* req) {
} }
void fs__readdir(uv_fs_t* req) { void fs__scandir(uv_fs_t* req) {
WCHAR* pathw = req->pathw; WCHAR* pathw = req->pathw;
size_t len = wcslen(pathw); size_t len = wcslen(pathw);
int result; int result;
@ -1220,6 +1223,25 @@ static void fs__sendfile(uv_fs_t* req) {
} }
static void fs__access(uv_fs_t* req) {
DWORD attr = GetFileAttributesW(req->pathw);
if (attr == INVALID_FILE_ATTRIBUTES) {
SET_REQ_WIN32_ERROR(req, GetLastError());
return;
}
if ((req->flags & W_OK) &&
((attr & FILE_ATTRIBUTE_READONLY) ||
(attr & FILE_ATTRIBUTE_DIRECTORY))) {
SET_REQ_WIN32_ERROR(req, UV_EPERM);
return;
}
SET_REQ_RESULT(req, 0);
}
static void fs__chmod(uv_fs_t* req) { static void fs__chmod(uv_fs_t* req) {
int result = _wchmod(req->pathw, req->mode); int result = _wchmod(req->pathw, req->mode);
SET_REQ_RESULT(req, result); SET_REQ_RESULT(req, result);
@ -1595,6 +1617,7 @@ static void uv__fs_work(struct uv__work* w) {
XX(FTRUNCATE, ftruncate) XX(FTRUNCATE, ftruncate)
XX(UTIME, utime) XX(UTIME, utime)
XX(FUTIME, futime) XX(FUTIME, futime)
XX(ACCESS, access)
XX(CHMOD, chmod) XX(CHMOD, chmod)
XX(FCHMOD, fchmod) XX(FCHMOD, fchmod)
XX(FSYNC, fsync) XX(FSYNC, fsync)
@ -1604,7 +1627,7 @@ static void uv__fs_work(struct uv__work* w) {
XX(MKDIR, mkdir) XX(MKDIR, mkdir)
XX(MKDTEMP, mkdtemp) XX(MKDTEMP, mkdtemp)
XX(RENAME, rename) XX(RENAME, rename)
XX(READDIR, readdir) XX(SCANDIR, scandir)
XX(LINK, link) XX(LINK, link)
XX(SYMLINK, symlink) XX(SYMLINK, symlink)
XX(READLINK, readlink) XX(READLINK, readlink)
@ -1839,11 +1862,11 @@ int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
} }
int uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
uv_fs_cb cb) { uv_fs_cb cb) {
int err; int err;
uv_fs_req_init(loop, req, UV_FS_READDIR, cb); uv_fs_req_init(loop, req, UV_FS_SCANDIR, cb);
err = fs__capture_path(loop, req, path, NULL, cb != NULL); err = fs__capture_path(loop, req, path, NULL, cb != NULL);
if (err) { if (err) {
@ -1856,7 +1879,7 @@ int uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags,
QUEUE_FS_TP_JOB(loop, req); QUEUE_FS_TP_JOB(loop, req);
return 0; return 0;
} else { } else {
fs__readdir(req); fs__scandir(req);
return req->result; return req->result;
} }
} }
@ -2102,6 +2125,31 @@ int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file fd_out,
} }
int uv_fs_access(uv_loop_t* loop,
uv_fs_t* req,
const char* path,
int flags,
uv_fs_cb cb) {
int err;
uv_fs_req_init(loop, req, UV_FS_ACCESS, cb);
err = fs__capture_path(loop, req, path, NULL, cb != NULL);
if (err)
return uv_translate_sys_error(err);
req->flags = flags;
if (cb) {
QUEUE_FS_TP_JOB(loop, req);
return 0;
}
fs__access(req);
return req->result;
}
int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode,
uv_fs_cb cb) { uv_fs_cb cb) {
int err; int err;

2
deps/uv/src/win/poll.c

@ -530,7 +530,7 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
SO_PROTOCOL_INFOW, SO_PROTOCOL_INFOW,
(char*) &protocol_info, (char*) &protocol_info,
&len) != 0) { &len) != 0) {
return WSAGetLastError(); return uv_translate_sys_error(WSAGetLastError());
} }
/* Get the peer socket that is needed to enable fast poll. If the returned */ /* Get the peer socket that is needed to enable fast poll. If the returned */

5
deps/uv/src/win/thread.c

@ -129,6 +129,11 @@ int uv_thread_join(uv_thread_t *tid) {
} }
int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) {
return *t1 == *t2;
}
int uv_mutex_init(uv_mutex_t* mutex) { int uv_mutex_init(uv_mutex_t* mutex) {
InitializeCriticalSection(mutex); InitializeCriticalSection(mutex);
return 0; return 0;

185
deps/uv/src/win/util.c

@ -206,7 +206,7 @@ int uv_cwd(char* buffer, size_t* size) {
if (r == 0) { if (r == 0) {
return uv_translate_sys_error(GetLastError()); return uv_translate_sys_error(GetLastError());
} else if (r > (int) *size) { } else if (r > (int) *size) {
*size = r; *size = r -1;
return UV_ENOBUFS; return UV_ENOBUFS;
} }
@ -223,7 +223,7 @@ int uv_cwd(char* buffer, size_t* size) {
return uv_translate_sys_error(GetLastError()); return uv_translate_sys_error(GetLastError());
} }
*size = r; *size = r - 1;
return 0; return 0;
} }
@ -778,11 +778,76 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
} }
static int is_windows_version_or_greater(DWORD os_major,
DWORD os_minor,
WORD service_pack_major,
WORD service_pack_minor) {
OSVERSIONINFOEX osvi;
DWORDLONG condition_mask = 0;
int op = VER_GREATER_EQUAL;
/* Initialize the OSVERSIONINFOEX structure. */
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
osvi.dwMajorVersion = os_major;
osvi.dwMinorVersion = os_minor;
osvi.wServicePackMajor = service_pack_major;
osvi.wServicePackMinor = service_pack_minor;
/* Initialize the condition mask. */
VER_SET_CONDITION(condition_mask, VER_MAJORVERSION, op);
VER_SET_CONDITION(condition_mask, VER_MINORVERSION, op);
VER_SET_CONDITION(condition_mask, VER_SERVICEPACKMAJOR, op);
VER_SET_CONDITION(condition_mask, VER_SERVICEPACKMINOR, op);
/* Perform the test. */
return (int) VerifyVersionInfo(
&osvi,
VER_MAJORVERSION | VER_MINORVERSION |
VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
condition_mask);
}
static int address_prefix_match(int family,
struct sockaddr* address,
struct sockaddr* prefix_address,
int prefix_len) {
uint8_t* address_data;
uint8_t* prefix_address_data;
int i;
assert(address->sa_family == family);
assert(prefix_address->sa_family == family);
if (family == AF_INET6) {
address_data = (uint8_t*) &(((struct sockaddr_in6 *) address)->sin6_addr);
prefix_address_data =
(uint8_t*) &(((struct sockaddr_in6 *) prefix_address)->sin6_addr);
} else {
address_data = (uint8_t*) &(((struct sockaddr_in *) address)->sin_addr);
prefix_address_data =
(uint8_t*) &(((struct sockaddr_in *) prefix_address)->sin_addr);
}
for (i = 0; i < prefix_len >> 3; i++) {
if (address_data[i] != prefix_address_data[i])
return 0;
}
if (prefix_len % 8)
return prefix_address_data[i] ==
(address_data[i] & (0xff << (8 - prefix_len % 8)));
return 1;
}
int uv_interface_addresses(uv_interface_address_t** addresses_ptr, int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
int* count_ptr) { int* count_ptr) {
IP_ADAPTER_ADDRESSES* win_address_buf; IP_ADAPTER_ADDRESSES* win_address_buf;
ULONG win_address_buf_size; ULONG win_address_buf_size;
IP_ADAPTER_ADDRESSES* win_address; IP_ADAPTER_ADDRESSES* adapter;
uv_interface_address_t* uv_address_buf; uv_interface_address_t* uv_address_buf;
char* name_buf; char* name_buf;
@ -791,6 +856,23 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
int count; int count;
int is_vista_or_greater;
ULONG flags;
is_vista_or_greater = is_windows_version_or_greater(6, 0, 0, 0);
if (is_vista_or_greater) {
flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST |
GAA_FLAG_SKIP_DNS_SERVER;
} else {
/* We need at least XP SP1. */
if (!is_windows_version_or_greater(5, 1, 1, 0))
return UV_ENOTSUP;
flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST |
GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_INCLUDE_PREFIX;
}
/* Fetch the size of the adapters reported by windows, and then get the */ /* Fetch the size of the adapters reported by windows, and then get the */
/* list itself. */ /* list itself. */
win_address_buf_size = 0; win_address_buf_size = 0;
@ -803,7 +885,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
/* ERROR_BUFFER_OVERFLOW, and the required buffer size will be stored in */ /* ERROR_BUFFER_OVERFLOW, and the required buffer size will be stored in */
/* win_address_buf_size. */ /* win_address_buf_size. */
r = GetAdaptersAddresses(AF_UNSPEC, r = GetAdaptersAddresses(AF_UNSPEC,
GAA_FLAG_INCLUDE_PREFIX, flags,
NULL, NULL,
win_address_buf, win_address_buf,
&win_address_buf_size); &win_address_buf_size);
@ -862,25 +944,23 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
count = 0; count = 0;
uv_address_buf_size = 0; uv_address_buf_size = 0;
for (win_address = win_address_buf; for (adapter = win_address_buf;
win_address != NULL; adapter != NULL;
win_address = win_address->Next) { adapter = adapter->Next) {
/* Use IP_ADAPTER_UNICAST_ADDRESS_XP to retain backwards compatibility */ IP_ADAPTER_UNICAST_ADDRESS* unicast_address;
/* with Windows XP */
IP_ADAPTER_UNICAST_ADDRESS_XP* unicast_address;
int name_size; int name_size;
/* Interfaces that are not 'up' should not be reported. Also skip */ /* Interfaces that are not 'up' should not be reported. Also skip */
/* interfaces that have no associated unicast address, as to avoid */ /* interfaces that have no associated unicast address, as to avoid */
/* allocating space for the name for this interface. */ /* allocating space for the name for this interface. */
if (win_address->OperStatus != IfOperStatusUp || if (adapter->OperStatus != IfOperStatusUp ||
win_address->FirstUnicastAddress == NULL) adapter->FirstUnicastAddress == NULL)
continue; continue;
/* Compute the size of the interface name. */ /* Compute the size of the interface name. */
name_size = WideCharToMultiByte(CP_UTF8, name_size = WideCharToMultiByte(CP_UTF8,
0, 0,
win_address->FriendlyName, adapter->FriendlyName,
-1, -1,
NULL, NULL,
0, 0,
@ -894,8 +974,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
/* Count the number of addresses associated with this interface, and */ /* Count the number of addresses associated with this interface, and */
/* compute the size. */ /* compute the size. */
for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS_XP*) for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS*)
win_address->FirstUnicastAddress; adapter->FirstUnicastAddress;
unicast_address != NULL; unicast_address != NULL;
unicast_address = unicast_address->Next) { unicast_address = unicast_address->Next) {
count++; count++;
@ -916,16 +996,15 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
name_buf = (char*) (uv_address_buf + count); name_buf = (char*) (uv_address_buf + count);
/* Fill out the output buffer. */ /* Fill out the output buffer. */
for (win_address = win_address_buf; for (adapter = win_address_buf;
win_address != NULL; adapter != NULL;
win_address = win_address->Next) { adapter = adapter->Next) {
IP_ADAPTER_UNICAST_ADDRESS_XP* unicast_address; IP_ADAPTER_UNICAST_ADDRESS* unicast_address;
IP_ADAPTER_PREFIX* prefix;
int name_size; int name_size;
size_t max_name_size; size_t max_name_size;
if (win_address->OperStatus != IfOperStatusUp || if (adapter->OperStatus != IfOperStatusUp ||
win_address->FirstUnicastAddress == NULL) adapter->FirstUnicastAddress == NULL)
continue; continue;
/* Convert the interface name to UTF8. */ /* Convert the interface name to UTF8. */
@ -934,7 +1013,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
max_name_size = INT_MAX; max_name_size = INT_MAX;
name_size = WideCharToMultiByte(CP_UTF8, name_size = WideCharToMultiByte(CP_UTF8,
0, 0,
win_address->FriendlyName, adapter->FriendlyName,
-1, -1,
name_buf, name_buf,
(int) max_name_size, (int) max_name_size,
@ -946,47 +1025,77 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr,
return uv_translate_sys_error(GetLastError()); return uv_translate_sys_error(GetLastError());
} }
prefix = win_address->FirstPrefix;
/* Add an uv_interface_address_t element for every unicast address. */ /* Add an uv_interface_address_t element for every unicast address. */
/* Walk the prefix list in tandem with the address list. */ for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS*)
for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS_XP*) adapter->FirstUnicastAddress;
win_address->FirstUnicastAddress; unicast_address != NULL;
unicast_address != NULL && prefix != NULL; unicast_address = unicast_address->Next) {
unicast_address = unicast_address->Next, prefix = prefix->Next) {
struct sockaddr* sa; struct sockaddr* sa;
ULONG prefix_len; ULONG prefix_len;
sa = unicast_address->Address.lpSockaddr; sa = unicast_address->Address.lpSockaddr;
prefix_len = prefix->PrefixLength;
/* XP has no OnLinkPrefixLength field. */
if (is_vista_or_greater) {
prefix_len = unicast_address->OnLinkPrefixLength;
} else {
/* Prior to Windows Vista the FirstPrefix pointed to the list with
* single prefix for each IP address assigned to the adapter.
* Order of FirstPrefix does not match order of FirstUnicastAddress,
* so we need to find corresponding prefix.
*/
IP_ADAPTER_PREFIX* prefix;
prefix_len = 0;
for (prefix = adapter->FirstPrefix; prefix; prefix = prefix->Next) {
/* We want the longest matching prefix. */
if (prefix->Address.lpSockaddr->sa_family != sa->sa_family ||
prefix->PrefixLength <= prefix_len)
continue;
if (address_prefix_match(sa->sa_family, sa,
prefix->Address.lpSockaddr, prefix->PrefixLength)) {
prefix_len = prefix->PrefixLength;
}
}
/* If there is no matching prefix information, return a single-host
* subnet mask (e.g. 255.255.255.255 for IPv4).
*/
if (!prefix_len)
prefix_len = (sa->sa_family == AF_INET6) ? 128 : 32;
}
memset(uv_address, 0, sizeof *uv_address); memset(uv_address, 0, sizeof *uv_address);
uv_address->name = name_buf; uv_address->name = name_buf;
if (win_address->PhysicalAddressLength == sizeof(uv_address->phys_addr)) { if (adapter->PhysicalAddressLength == sizeof(uv_address->phys_addr)) {
memcpy(uv_address->phys_addr, memcpy(uv_address->phys_addr,
win_address->PhysicalAddress, adapter->PhysicalAddress,
sizeof(uv_address->phys_addr)); sizeof(uv_address->phys_addr));
} }
uv_address->is_internal = uv_address->is_internal =
(win_address->IfType == IF_TYPE_SOFTWARE_LOOPBACK); (adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK);
if (sa->sa_family == AF_INET6) { if (sa->sa_family == AF_INET6) {
uv_address->address.address6 = *((struct sockaddr_in6 *) sa); uv_address->address.address6 = *((struct sockaddr_in6 *) sa);
uv_address->netmask.netmask6.sin6_family = AF_INET6; uv_address->netmask.netmask6.sin6_family = AF_INET6;
memset(uv_address->netmask.netmask6.sin6_addr.s6_addr, 0xff, prefix_len >> 3); memset(uv_address->netmask.netmask6.sin6_addr.s6_addr, 0xff, prefix_len >> 3);
uv_address->netmask.netmask6.sin6_addr.s6_addr[prefix_len >> 3] = /* This check ensures that we don't write past the size of the data. */
0xff << (8 - prefix_len % 8); if (prefix_len % 8) {
uv_address->netmask.netmask6.sin6_addr.s6_addr[prefix_len >> 3] =
0xff << (8 - prefix_len % 8);
}
} else { } else {
uv_address->address.address4 = *((struct sockaddr_in *) sa); uv_address->address.address4 = *((struct sockaddr_in *) sa);
uv_address->netmask.netmask4.sin_family = AF_INET; uv_address->netmask.netmask4.sin_family = AF_INET;
uv_address->netmask.netmask4.sin_addr.s_addr = uv_address->netmask.netmask4.sin_addr.s_addr = (prefix_len > 0) ?
htonl(0xffffffff << (32 - prefix_len)); htonl(0xffffffff << (32 - prefix_len)) : 0;
} }
uv_address++; uv_address++;

237
deps/uv/test/test-fs.c

@ -67,7 +67,7 @@ static int unlink_cb_count;
static int mkdir_cb_count; static int mkdir_cb_count;
static int mkdtemp_cb_count; static int mkdtemp_cb_count;
static int rmdir_cb_count; static int rmdir_cb_count;
static int readdir_cb_count; static int scandir_cb_count;
static int stat_cb_count; static int stat_cb_count;
static int rename_cb_count; static int rename_cb_count;
static int fsync_cb_count; static int fsync_cb_count;
@ -75,6 +75,7 @@ static int fdatasync_cb_count;
static int ftruncate_cb_count; static int ftruncate_cb_count;
static int sendfile_cb_count; static int sendfile_cb_count;
static int fstat_cb_count; static int fstat_cb_count;
static int access_cb_count;
static int chmod_cb_count; static int chmod_cb_count;
static int fchmod_cb_count; static int fchmod_cb_count;
static int chown_cb_count; static int chown_cb_count;
@ -97,7 +98,7 @@ static uv_fs_t mkdir_req;
static uv_fs_t mkdtemp_req1; static uv_fs_t mkdtemp_req1;
static uv_fs_t mkdtemp_req2; static uv_fs_t mkdtemp_req2;
static uv_fs_t rmdir_req; static uv_fs_t rmdir_req;
static uv_fs_t readdir_req; static uv_fs_t scandir_req;
static uv_fs_t stat_req; static uv_fs_t stat_req;
static uv_fs_t rename_req; static uv_fs_t rename_req;
static uv_fs_t fsync_req; static uv_fs_t fsync_req;
@ -109,6 +110,7 @@ static uv_fs_t futime_req;
static char buf[32]; static char buf[32];
static char test_buf[] = "test-buffer\n"; static char test_buf[] = "test-buffer\n";
static char test_buf2[] = "second-buffer\n";
static uv_buf_t iov; static uv_buf_t iov;
static void check_permission(const char* filename, unsigned int mode) { static void check_permission(const char* filename, unsigned int mode) {
@ -164,6 +166,14 @@ static void readlink_cb(uv_fs_t* req) {
uv_fs_req_cleanup(req); uv_fs_req_cleanup(req);
} }
static void access_cb(uv_fs_t* req) {
ASSERT(req->fs_type == UV_FS_ACCESS);
access_cb_count++;
uv_fs_req_cleanup(req);
}
static void fchmod_cb(uv_fs_t* req) { static void fchmod_cb(uv_fs_t* req) {
ASSERT(req->fs_type == UV_FS_FCHMOD); ASSERT(req->fs_type == UV_FS_FCHMOD);
ASSERT(req->result == 0); ASSERT(req->result == 0);
@ -416,18 +426,18 @@ static void rmdir_cb(uv_fs_t* req) {
} }
static void readdir_cb(uv_fs_t* req) { static void scandir_cb(uv_fs_t* req) {
uv_dirent_t dent; uv_dirent_t dent;
ASSERT(req == &readdir_req); ASSERT(req == &scandir_req);
ASSERT(req->fs_type == UV_FS_READDIR); ASSERT(req->fs_type == UV_FS_SCANDIR);
ASSERT(req->result == 2); ASSERT(req->result == 2);
ASSERT(req->ptr); ASSERT(req->ptr);
while (UV_EOF != uv_fs_readdir_next(req, &dent)) { while (UV_EOF != uv_fs_scandir_next(req, &dent)) {
ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0); ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0);
ASSERT(dent.type == UV_DIRENT_FILE || dent.type == UV_DIRENT_UNKNOWN); ASSERT(dent.type == UV_DIRENT_FILE || dent.type == UV_DIRENT_UNKNOWN);
} }
readdir_cb_count++; scandir_cb_count++;
ASSERT(req->path); ASSERT(req->path);
ASSERT(memcmp(req->path, "test_dir\0", 9) == 0); ASSERT(memcmp(req->path, "test_dir\0", 9) == 0);
uv_fs_req_cleanup(req); uv_fs_req_cleanup(req);
@ -435,26 +445,26 @@ static void readdir_cb(uv_fs_t* req) {
} }
static void empty_readdir_cb(uv_fs_t* req) { static void empty_scandir_cb(uv_fs_t* req) {
uv_dirent_t dent; uv_dirent_t dent;
ASSERT(req == &readdir_req); ASSERT(req == &scandir_req);
ASSERT(req->fs_type == UV_FS_READDIR); ASSERT(req->fs_type == UV_FS_SCANDIR);
ASSERT(req->result == 0); ASSERT(req->result == 0);
ASSERT(req->ptr == NULL); ASSERT(req->ptr == NULL);
ASSERT(UV_EOF == uv_fs_readdir_next(req, &dent)); ASSERT(UV_EOF == uv_fs_scandir_next(req, &dent));
uv_fs_req_cleanup(req); uv_fs_req_cleanup(req);
readdir_cb_count++; scandir_cb_count++;
} }
static void file_readdir_cb(uv_fs_t* req) { static void file_scandir_cb(uv_fs_t* req) {
ASSERT(req == &readdir_req); ASSERT(req == &scandir_req);
ASSERT(req->fs_type == UV_FS_READDIR); ASSERT(req->fs_type == UV_FS_SCANDIR);
ASSERT(req->result == UV_ENOTDIR); ASSERT(req->result == UV_ENOTDIR);
ASSERT(req->ptr == NULL); ASSERT(req->ptr == NULL);
uv_fs_req_cleanup(req); uv_fs_req_cleanup(req);
readdir_cb_count++; scandir_cb_count++;
} }
@ -841,23 +851,23 @@ TEST_IMPL(fs_async_dir) {
ASSERT(r == 0); ASSERT(r == 0);
uv_fs_req_cleanup(&close_req); uv_fs_req_cleanup(&close_req);
r = uv_fs_readdir(loop, &readdir_req, "test_dir", 0, readdir_cb); r = uv_fs_scandir(loop, &scandir_req, "test_dir", 0, scandir_cb);
ASSERT(r == 0); ASSERT(r == 0);
uv_run(loop, UV_RUN_DEFAULT); uv_run(loop, UV_RUN_DEFAULT);
ASSERT(readdir_cb_count == 1); ASSERT(scandir_cb_count == 1);
/* sync uv_fs_readdir */ /* sync uv_fs_scandir */
r = uv_fs_readdir(loop, &readdir_req, "test_dir", 0, NULL); r = uv_fs_scandir(loop, &scandir_req, "test_dir", 0, NULL);
ASSERT(r == 2); ASSERT(r == 2);
ASSERT(readdir_req.result == 2); ASSERT(scandir_req.result == 2);
ASSERT(readdir_req.ptr); ASSERT(scandir_req.ptr);
while (UV_EOF != uv_fs_readdir_next(&readdir_req, &dent)) { while (UV_EOF != uv_fs_scandir_next(&scandir_req, &dent)) {
ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0); ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0);
ASSERT(dent.type == UV_DIRENT_FILE || dent.type == UV_DIRENT_UNKNOWN); ASSERT(dent.type == UV_DIRENT_FILE || dent.type == UV_DIRENT_UNKNOWN);
} }
uv_fs_req_cleanup(&readdir_req); uv_fs_req_cleanup(&scandir_req);
ASSERT(!readdir_req.ptr); ASSERT(!scandir_req.ptr);
r = uv_fs_stat(loop, &stat_req, "test_dir", stat_cb); r = uv_fs_stat(loop, &stat_req, "test_dir", stat_cb);
ASSERT(r == 0); ASSERT(r == 0);
@ -1119,6 +1129,70 @@ TEST_IMPL(fs_fstat) {
} }
TEST_IMPL(fs_access) {
int r;
uv_fs_t req;
uv_file file;
/* Setup. */
unlink("test_file");
loop = uv_default_loop();
/* File should not exist */
r = uv_fs_access(loop, &req, "test_file", F_OK, NULL);
ASSERT(r < 0);
ASSERT(req.result < 0);
uv_fs_req_cleanup(&req);
/* File should not exist */
r = uv_fs_access(loop, &req, "test_file", F_OK, access_cb);
ASSERT(r == 0);
uv_run(loop, UV_RUN_DEFAULT);
ASSERT(access_cb_count == 1);
access_cb_count = 0; /* reset for the next test */
/* Create file */
r = uv_fs_open(loop, &req, "test_file", O_RDWR | O_CREAT,
S_IWUSR | S_IRUSR, NULL);
ASSERT(r >= 0);
ASSERT(req.result >= 0);
file = req.result;
uv_fs_req_cleanup(&req);
/* File should exist */
r = uv_fs_access(loop, &req, "test_file", F_OK, NULL);
ASSERT(r == 0);
ASSERT(req.result == 0);
uv_fs_req_cleanup(&req);
/* File should exist */
r = uv_fs_access(loop, &req, "test_file", F_OK, access_cb);
ASSERT(r == 0);
uv_run(loop, UV_RUN_DEFAULT);
ASSERT(access_cb_count == 1);
access_cb_count = 0; /* reset for the next test */
/* Close file */
r = uv_fs_close(loop, &req, file, NULL);
ASSERT(r == 0);
ASSERT(req.result == 0);
uv_fs_req_cleanup(&req);
/*
* Run the loop just to check we don't have make any extraneous uv_ref()
* calls. This should drop out immediately.
*/
uv_run(loop, UV_RUN_DEFAULT);
/* Cleanup. */
unlink("test_file");
MAKE_VALGRIND_HAPPY();
return 0;
}
TEST_IMPL(fs_chmod) { TEST_IMPL(fs_chmod) {
int r; int r;
uv_fs_t req; uv_fs_t req;
@ -1604,36 +1678,36 @@ TEST_IMPL(fs_symlink_dir) {
ASSERT(r == 0); ASSERT(r == 0);
uv_fs_req_cleanup(&close_req); uv_fs_req_cleanup(&close_req);
r = uv_fs_readdir(loop, &readdir_req, "test_dir_symlink", 0, NULL); r = uv_fs_scandir(loop, &scandir_req, "test_dir_symlink", 0, NULL);
ASSERT(r == 2); ASSERT(r == 2);
ASSERT(readdir_req.result == 2); ASSERT(scandir_req.result == 2);
ASSERT(readdir_req.ptr); ASSERT(scandir_req.ptr);
while (UV_EOF != uv_fs_readdir_next(&readdir_req, &dent)) { while (UV_EOF != uv_fs_scandir_next(&scandir_req, &dent)) {
ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0); ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0);
ASSERT(dent.type == UV_DIRENT_FILE || dent.type == UV_DIRENT_UNKNOWN); ASSERT(dent.type == UV_DIRENT_FILE || dent.type == UV_DIRENT_UNKNOWN);
} }
uv_fs_req_cleanup(&readdir_req); uv_fs_req_cleanup(&scandir_req);
ASSERT(!readdir_req.ptr); ASSERT(!scandir_req.ptr);
/* unlink will remove the directory symlink */ /* unlink will remove the directory symlink */
r = uv_fs_unlink(loop, &req, "test_dir_symlink", NULL); r = uv_fs_unlink(loop, &req, "test_dir_symlink", NULL);
ASSERT(r == 0); ASSERT(r == 0);
uv_fs_req_cleanup(&req); uv_fs_req_cleanup(&req);
r = uv_fs_readdir(loop, &readdir_req, "test_dir_symlink", 0, NULL); r = uv_fs_scandir(loop, &scandir_req, "test_dir_symlink", 0, NULL);
ASSERT(r == UV_ENOENT); ASSERT(r == UV_ENOENT);
uv_fs_req_cleanup(&readdir_req); uv_fs_req_cleanup(&scandir_req);
r = uv_fs_readdir(loop, &readdir_req, "test_dir", 0, NULL); r = uv_fs_scandir(loop, &scandir_req, "test_dir", 0, NULL);
ASSERT(r == 2); ASSERT(r == 2);
ASSERT(readdir_req.result == 2); ASSERT(scandir_req.result == 2);
ASSERT(readdir_req.ptr); ASSERT(scandir_req.ptr);
while (UV_EOF != uv_fs_readdir_next(&readdir_req, &dent)) { while (UV_EOF != uv_fs_scandir_next(&scandir_req, &dent)) {
ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0); ASSERT(strcmp(dent.name, "file1") == 0 || strcmp(dent.name, "file2") == 0);
ASSERT(dent.type == UV_DIRENT_FILE || dent.type == UV_DIRENT_UNKNOWN); ASSERT(dent.type == UV_DIRENT_FILE || dent.type == UV_DIRENT_UNKNOWN);
} }
uv_fs_req_cleanup(&readdir_req); uv_fs_req_cleanup(&scandir_req);
ASSERT(!readdir_req.ptr); ASSERT(!scandir_req.ptr);
/* clean-up */ /* clean-up */
unlink("test_dir/file1"); unlink("test_dir/file1");
@ -1805,7 +1879,7 @@ TEST_IMPL(fs_stat_missing_path) {
} }
TEST_IMPL(fs_readdir_empty_dir) { TEST_IMPL(fs_scandir_empty_dir) {
const char* path; const char* path;
uv_fs_t req; uv_fs_t req;
uv_dirent_t dent; uv_dirent_t dent;
@ -1820,19 +1894,19 @@ TEST_IMPL(fs_readdir_empty_dir) {
/* Fill the req to ensure that required fields are cleaned up */ /* Fill the req to ensure that required fields are cleaned up */
memset(&req, 0xdb, sizeof(req)); memset(&req, 0xdb, sizeof(req));
r = uv_fs_readdir(loop, &req, path, 0, NULL); r = uv_fs_scandir(loop, &req, path, 0, NULL);
ASSERT(r == 0); ASSERT(r == 0);
ASSERT(req.result == 0); ASSERT(req.result == 0);
ASSERT(req.ptr == NULL); ASSERT(req.ptr == NULL);
ASSERT(UV_EOF == uv_fs_readdir_next(&req, &dent)); ASSERT(UV_EOF == uv_fs_scandir_next(&req, &dent));
uv_fs_req_cleanup(&req); uv_fs_req_cleanup(&req);
r = uv_fs_readdir(loop, &readdir_req, path, 0, empty_readdir_cb); r = uv_fs_scandir(loop, &scandir_req, path, 0, empty_scandir_cb);
ASSERT(r == 0); ASSERT(r == 0);
ASSERT(readdir_cb_count == 0); ASSERT(scandir_cb_count == 0);
uv_run(loop, UV_RUN_DEFAULT); uv_run(loop, UV_RUN_DEFAULT);
ASSERT(readdir_cb_count == 1); ASSERT(scandir_cb_count == 1);
uv_fs_rmdir(loop, &req, path, NULL); uv_fs_rmdir(loop, &req, path, NULL);
uv_fs_req_cleanup(&req); uv_fs_req_cleanup(&req);
@ -1842,23 +1916,23 @@ TEST_IMPL(fs_readdir_empty_dir) {
} }
TEST_IMPL(fs_readdir_file) { TEST_IMPL(fs_scandir_file) {
const char* path; const char* path;
int r; int r;
path = "test/fixtures/empty_file"; path = "test/fixtures/empty_file";
loop = uv_default_loop(); loop = uv_default_loop();
r = uv_fs_readdir(loop, &readdir_req, path, 0, NULL); r = uv_fs_scandir(loop, &scandir_req, path, 0, NULL);
ASSERT(r == UV_ENOTDIR); ASSERT(r == UV_ENOTDIR);
uv_fs_req_cleanup(&readdir_req); uv_fs_req_cleanup(&scandir_req);
r = uv_fs_readdir(loop, &readdir_req, path, 0, file_readdir_cb); r = uv_fs_scandir(loop, &scandir_req, path, 0, file_scandir_cb);
ASSERT(r == 0); ASSERT(r == 0);
ASSERT(readdir_cb_count == 0); ASSERT(scandir_cb_count == 0);
uv_run(loop, UV_RUN_DEFAULT); uv_run(loop, UV_RUN_DEFAULT);
ASSERT(readdir_cb_count == 1); ASSERT(scandir_cb_count == 1);
MAKE_VALGRIND_HAPPY(); MAKE_VALGRIND_HAPPY();
return 0; return 0;
@ -2091,3 +2165,64 @@ TEST_IMPL(fs_read_file_eof) {
MAKE_VALGRIND_HAPPY(); MAKE_VALGRIND_HAPPY();
return 0; return 0;
} }
TEST_IMPL(fs_write_multiple_bufs) {
uv_buf_t iovs[2];
int r;
/* Setup. */
unlink("test_file");
loop = uv_default_loop();
r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT,
S_IWUSR | S_IRUSR, NULL);
ASSERT(r >= 0);
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
iovs[0] = uv_buf_init(test_buf, sizeof(test_buf));
iovs[1] = uv_buf_init(test_buf2, sizeof(test_buf2));
r = uv_fs_write(loop, &write_req, open_req1.result, iovs, 2, 0, NULL);
ASSERT(r >= 0);
ASSERT(write_req.result >= 0);
uv_fs_req_cleanup(&write_req);
r = uv_fs_close(loop, &close_req, open_req1.result, NULL);
ASSERT(r == 0);
ASSERT(close_req.result == 0);
uv_fs_req_cleanup(&close_req);
r = uv_fs_open(loop, &open_req1, "test_file", O_RDONLY, 0, NULL);
ASSERT(r >= 0);
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
memset(buf, 0, sizeof(buf));
iov = uv_buf_init(buf, sizeof(buf));
r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, -1, NULL);
ASSERT(r >= 0);
ASSERT(read_req.result >= 0);
ASSERT(memcmp(buf, test_buf, sizeof(test_buf)) == 0);
ASSERT(strcmp(buf + sizeof(test_buf), test_buf2) == 0);
uv_fs_req_cleanup(&read_req);
iov = uv_buf_init(buf, sizeof(buf));
r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1,
read_req.result, NULL);
ASSERT(r == 0);
ASSERT(read_req.result == 0);
uv_fs_req_cleanup(&read_req);
r = uv_fs_close(loop, &close_req, open_req1.result, NULL);
ASSERT(r == 0);
ASSERT(close_req.result == 0);
uv_fs_req_cleanup(&close_req);
/* Cleanup */
unlink("test_file");
MAKE_VALGRIND_HAPPY();
return 0;
}

14
deps/uv/test/test-list.h

@ -218,6 +218,7 @@ TEST_DECLARE (fs_async_dir)
TEST_DECLARE (fs_async_sendfile) TEST_DECLARE (fs_async_sendfile)
TEST_DECLARE (fs_mkdtemp) TEST_DECLARE (fs_mkdtemp)
TEST_DECLARE (fs_fstat) TEST_DECLARE (fs_fstat)
TEST_DECLARE (fs_access)
TEST_DECLARE (fs_chmod) TEST_DECLARE (fs_chmod)
TEST_DECLARE (fs_chown) TEST_DECLARE (fs_chown)
TEST_DECLARE (fs_link) TEST_DECLARE (fs_link)
@ -241,10 +242,11 @@ TEST_DECLARE (fs_event_close_in_callback)
TEST_DECLARE (fs_event_start_and_close) TEST_DECLARE (fs_event_start_and_close)
TEST_DECLARE (fs_event_error_reporting) TEST_DECLARE (fs_event_error_reporting)
TEST_DECLARE (fs_event_getpath) TEST_DECLARE (fs_event_getpath)
TEST_DECLARE (fs_readdir_empty_dir) TEST_DECLARE (fs_scandir_empty_dir)
TEST_DECLARE (fs_readdir_file) TEST_DECLARE (fs_scandir_file)
TEST_DECLARE (fs_open_dir) TEST_DECLARE (fs_open_dir)
TEST_DECLARE (fs_rename_to_existing_file) TEST_DECLARE (fs_rename_to_existing_file)
TEST_DECLARE (fs_write_multiple_bufs)
TEST_DECLARE (threadpool_queue_work_simple) TEST_DECLARE (threadpool_queue_work_simple)
TEST_DECLARE (threadpool_queue_work_einval) TEST_DECLARE (threadpool_queue_work_einval)
TEST_DECLARE (threadpool_multiple_event_loops) TEST_DECLARE (threadpool_multiple_event_loops)
@ -257,6 +259,7 @@ TEST_DECLARE (thread_local_storage)
TEST_DECLARE (thread_mutex) TEST_DECLARE (thread_mutex)
TEST_DECLARE (thread_rwlock) TEST_DECLARE (thread_rwlock)
TEST_DECLARE (thread_create) TEST_DECLARE (thread_create)
TEST_DECLARE (thread_equal)
TEST_DECLARE (dlerror) TEST_DECLARE (dlerror)
TEST_DECLARE (poll_duplex) TEST_DECLARE (poll_duplex)
TEST_DECLARE (poll_unidirectional) TEST_DECLARE (poll_unidirectional)
@ -590,6 +593,7 @@ TASK_LIST_START
TEST_ENTRY (fs_async_sendfile) TEST_ENTRY (fs_async_sendfile)
TEST_ENTRY (fs_mkdtemp) TEST_ENTRY (fs_mkdtemp)
TEST_ENTRY (fs_fstat) TEST_ENTRY (fs_fstat)
TEST_ENTRY (fs_access)
TEST_ENTRY (fs_chmod) TEST_ENTRY (fs_chmod)
TEST_ENTRY (fs_chown) TEST_ENTRY (fs_chown)
TEST_ENTRY (fs_utime) TEST_ENTRY (fs_utime)
@ -612,10 +616,11 @@ TASK_LIST_START
TEST_ENTRY (fs_event_start_and_close) TEST_ENTRY (fs_event_start_and_close)
TEST_ENTRY (fs_event_error_reporting) TEST_ENTRY (fs_event_error_reporting)
TEST_ENTRY (fs_event_getpath) TEST_ENTRY (fs_event_getpath)
TEST_ENTRY (fs_readdir_empty_dir) TEST_ENTRY (fs_scandir_empty_dir)
TEST_ENTRY (fs_readdir_file) TEST_ENTRY (fs_scandir_file)
TEST_ENTRY (fs_open_dir) TEST_ENTRY (fs_open_dir)
TEST_ENTRY (fs_rename_to_existing_file) TEST_ENTRY (fs_rename_to_existing_file)
TEST_ENTRY (fs_write_multiple_bufs)
TEST_ENTRY (threadpool_queue_work_simple) TEST_ENTRY (threadpool_queue_work_simple)
TEST_ENTRY (threadpool_queue_work_einval) TEST_ENTRY (threadpool_queue_work_einval)
TEST_ENTRY (threadpool_multiple_event_loops) TEST_ENTRY (threadpool_multiple_event_loops)
@ -628,6 +633,7 @@ TASK_LIST_START
TEST_ENTRY (thread_mutex) TEST_ENTRY (thread_mutex)
TEST_ENTRY (thread_rwlock) TEST_ENTRY (thread_rwlock)
TEST_ENTRY (thread_create) TEST_ENTRY (thread_create)
TEST_ENTRY (thread_equal)
TEST_ENTRY (dlerror) TEST_ENTRY (dlerror)
TEST_ENTRY (ip4_addr) TEST_ENTRY (ip4_addr)
TEST_ENTRY (ip6_addr_link_local) TEST_ENTRY (ip6_addr_link_local)

45
deps/uv/test/test-thread-equal.c

@ -0,0 +1,45 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "uv.h"
#include "task.h"
uv_thread_t main_thread_id;
uv_thread_t subthreads[2];
static void check_thread(void* arg) {
uv_thread_t *thread_id = arg;
uv_thread_t self_id = uv_thread_self();
ASSERT(uv_thread_equal(&main_thread_id, &self_id) == 0);
*thread_id = uv_thread_self();
}
TEST_IMPL(thread_equal) {
uv_thread_t threads[2];
main_thread_id = uv_thread_self();
ASSERT(0 != uv_thread_equal(&main_thread_id, &main_thread_id));
ASSERT(0 == uv_thread_create(threads + 0, check_thread, subthreads + 0));
ASSERT(0 == uv_thread_create(threads + 1, check_thread, subthreads + 1));
ASSERT(0 == uv_thread_join(threads + 0));
ASSERT(0 == uv_thread_join(threads + 1));
ASSERT(0 == uv_thread_equal(subthreads + 0, subthreads + 1));
return 0;
}

2
deps/uv/test/test-threadpool-cancel.c

@ -301,7 +301,7 @@ TEST_IMPL(threadpool_cancel_fs) {
ASSERT(0 == uv_fs_mkdir(loop, reqs + n++, "/", 0, fs_cb)); ASSERT(0 == uv_fs_mkdir(loop, reqs + n++, "/", 0, fs_cb));
ASSERT(0 == uv_fs_open(loop, reqs + n++, "/", 0, 0, fs_cb)); ASSERT(0 == uv_fs_open(loop, reqs + n++, "/", 0, 0, fs_cb));
ASSERT(0 == uv_fs_read(loop, reqs + n++, 0, NULL, 0, 0, fs_cb)); ASSERT(0 == uv_fs_read(loop, reqs + n++, 0, NULL, 0, 0, fs_cb));
ASSERT(0 == uv_fs_readdir(loop, reqs + n++, "/", 0, fs_cb)); ASSERT(0 == uv_fs_scandir(loop, reqs + n++, "/", 0, fs_cb));
ASSERT(0 == uv_fs_readlink(loop, reqs + n++, "/", fs_cb)); ASSERT(0 == uv_fs_readlink(loop, reqs + n++, "/", fs_cb));
ASSERT(0 == uv_fs_rename(loop, reqs + n++, "/", "/", fs_cb)); ASSERT(0 == uv_fs_rename(loop, reqs + n++, "/", "/", fs_cb));
ASSERT(0 == uv_fs_mkdir(loop, reqs + n++, "/", 0, fs_cb)); ASSERT(0 == uv_fs_mkdir(loop, reqs + n++, "/", 0, fs_cb));

1
deps/uv/uv.gyp

@ -410,6 +410,7 @@
'test/test-tcp-write-queue-order.c', 'test/test-tcp-write-queue-order.c',
'test/test-threadpool.c', 'test/test-threadpool.c',
'test/test-threadpool-cancel.c', 'test/test-threadpool-cancel.c',
'test/test-thread-equal.c',
'test/test-mutexes.c', 'test/test-mutexes.c',
'test/test-thread.c', 'test/test-thread.c',
'test/test-barrier.c', 'test/test-barrier.c',

Loading…
Cancel
Save